Merge branch 'main' into nav-overlay
This commit is contained in:
commit
9dfd3d17cd
10
config.json
10
config.json
@ -19,6 +19,7 @@
|
|||||||
"MusicPlayer_path": "MusicPlayer.json",
|
"MusicPlayer_path": "MusicPlayer.json",
|
||||||
"Note": "",
|
"Note": "",
|
||||||
"ObjectStates_order": [
|
"ObjectStates_order": [
|
||||||
|
"GUIDReferenceHandler.123456",
|
||||||
"HandTrigger.5fe087",
|
"HandTrigger.5fe087",
|
||||||
"HandTrigger.be2f17",
|
"HandTrigger.be2f17",
|
||||||
"HandTrigger.0285cc",
|
"HandTrigger.0285cc",
|
||||||
@ -101,7 +102,7 @@
|
|||||||
"ClueCounter.d86b7c",
|
"ClueCounter.d86b7c",
|
||||||
"MasterClueCounter.4a3aa4",
|
"MasterClueCounter.4a3aa4",
|
||||||
"LegacyAssets.7165a9",
|
"LegacyAssets.7165a9",
|
||||||
"Playarea.721ba2",
|
"PlayArea.721ba2",
|
||||||
"BarkhamHorror.308439",
|
"BarkhamHorror.308439",
|
||||||
"ChaosBagStatTracker.766620",
|
"ChaosBagStatTracker.766620",
|
||||||
"Blesstokens.afa06b",
|
"Blesstokens.afa06b",
|
||||||
@ -131,11 +132,11 @@
|
|||||||
"EdgeoftheEarth.895eaa",
|
"EdgeoftheEarth.895eaa",
|
||||||
"TheDream-Eaters.a16a1a",
|
"TheDream-Eaters.a16a1a",
|
||||||
"ReturntoTheCircleUndone.757324",
|
"ReturntoTheCircleUndone.757324",
|
||||||
"Playermat4Red.0840d5",
|
|
||||||
"Playermat3Green.383d8b",
|
|
||||||
"OtherDoominPlay.652ff3",
|
"OtherDoominPlay.652ff3",
|
||||||
"Playermat1White.8b081b",
|
"Playermat1White.8b081b",
|
||||||
"Playermat2Orange.bd0ff4",
|
"Playermat2Orange.bd0ff4",
|
||||||
|
"Playermat3Green.383d8b",
|
||||||
|
"Playermat4Red.0840d5",
|
||||||
"Neutral.2691e1",
|
"Neutral.2691e1",
|
||||||
"Neutral.748245",
|
"Neutral.748245",
|
||||||
"Neutral.271b17",
|
"Neutral.271b17",
|
||||||
@ -198,6 +199,7 @@
|
|||||||
"TokenArranger.022907",
|
"TokenArranger.022907",
|
||||||
"ChaosBagManager.023240",
|
"ChaosBagManager.023240",
|
||||||
"ArkhamSCE330-1092023-Page1.964222",
|
"ArkhamSCE330-1092023-Page1.964222",
|
||||||
|
"PlaceholderBoxDummy.a93466",
|
||||||
"SoulsofDarkness.a94e6b"
|
"SoulsofDarkness.a94e6b"
|
||||||
],
|
],
|
||||||
"PlayArea": 1,
|
"PlayArea": 1,
|
||||||
@ -218,5 +220,5 @@
|
|||||||
"Tags": [],
|
"Tags": [],
|
||||||
"Turns_path": "Turns.json",
|
"Turns_path": "Turns.json",
|
||||||
"VersionNumber": "v13.2.2",
|
"VersionNumber": "v13.2.2",
|
||||||
"XmlUI": "\u003cInclude src=\"Global.xml\"/\u003e"
|
"XmlUI": "\u003cInclude src=\"Global/Global.xml\"/\u003e"
|
||||||
}
|
}
|
||||||
|
@ -12,10 +12,6 @@
|
|||||||
"displayed": "LinkedPhaseTracker",
|
"displayed": "LinkedPhaseTracker",
|
||||||
"normalized": "linkedphasetracker"
|
"normalized": "linkedphasetracker"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"displayed": "chaosBag",
|
|
||||||
"normalized": "chaosBag"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"displayed": "displacement_excluded",
|
"displayed": "displacement_excluded",
|
||||||
"normalized": "displacement_excluded"
|
"normalized": "displacement_excluded"
|
||||||
@ -60,10 +56,6 @@
|
|||||||
"displayed": "chaosBag",
|
"displayed": "chaosBag",
|
||||||
"normalized": "chaosbag"
|
"normalized": "chaosbag"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"displayed": "arkham_setup_memory_object",
|
|
||||||
"normalized": "arkham_setup_memory_object"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"displayed": "ActionToken",
|
"displayed": "ActionToken",
|
||||||
"normalized": "actiontoken"
|
"normalized": "actiontoken"
|
||||||
@ -72,10 +64,6 @@
|
|||||||
"displayed": "LargeBox",
|
"displayed": "LargeBox",
|
||||||
"normalized": "largebox"
|
"normalized": "largebox"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"displayed": "SoundCube",
|
|
||||||
"normalized": "soundcube"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"displayed": "CampaignBox",
|
"displayed": "CampaignBox",
|
||||||
"normalized": "campaignbox"
|
"normalized": "campaignbox"
|
||||||
@ -83,10 +71,6 @@
|
|||||||
{
|
{
|
||||||
"displayed": "CameraZoom_ignore",
|
"displayed": "CameraZoom_ignore",
|
||||||
"normalized": "camerazoom_ignore"
|
"normalized": "camerazoom_ignore"
|
||||||
},
|
|
||||||
{
|
|
||||||
"displayed": "TokenArranger",
|
|
||||||
"normalized": "tokenarranger"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -218,5 +218,20 @@
|
|||||||
"Name": "FinnIcon",
|
"Name": "FinnIcon",
|
||||||
"Type": 0,
|
"Type": 0,
|
||||||
"URL": "http://cloud-3.steamusercontent.com/ugc/2037357792052848566/5DA900C430E97D3DFF2C9B8A3DB1CB2271791FC7/"
|
"URL": "http://cloud-3.steamusercontent.com/ugc/2037357792052848566/5DA900C430E97D3DFF2C9B8A3DB1CB2271791FC7/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "box-cover-mask-small",
|
||||||
|
"Type": 0,
|
||||||
|
"URL": "http://cloud-3.steamusercontent.com/ugc/2115061298536631564/F29C2ED9DD8431A1D1E21C7FFAFF1FFBC0AF0BF3/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "box-cover-mask-big",
|
||||||
|
"Type": 0,
|
||||||
|
"URL": "http://cloud-3.steamusercontent.com/ugc/2115061298536631429/D075D2EECE6EE091AD3BEA5800DEF9C7B02B745B/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "box-cover-mask-wide",
|
||||||
|
"Type": 0,
|
||||||
|
"URL": "http://cloud-3.steamusercontent.com/ugc/2115061298538827369/A20C2ECB8ECDC1B0AD8B2B38F68CA1C1F5E07D37/"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1557,7 +1557,14 @@
|
|||||||
"StallforTime.7b6ed1",
|
"StallforTime.7b6ed1",
|
||||||
"WrongPlaceRightTime.d5944e",
|
"WrongPlaceRightTime.d5944e",
|
||||||
"SparrowMask.975d79",
|
"SparrowMask.975d79",
|
||||||
"Pitchfork.45a724"
|
"Pitchfork.45a724",
|
||||||
|
"JimsTrumpet.7dfd5f",
|
||||||
|
"JimCulverParallel.72bf31",
|
||||||
|
"JimCulverParallelFront.c5fc80",
|
||||||
|
"VengefulShade.73bc8e",
|
||||||
|
"FinalRhapsody.561775",
|
||||||
|
"JimCulverParallelBack.aba863",
|
||||||
|
"TheBeyond.37ab47"
|
||||||
],
|
],
|
||||||
"ContainedObjects_path": "AllPlayerCards.15bb07",
|
"ContainedObjects_path": "AllPlayerCards.15bb07",
|
||||||
"Description": "",
|
"Description": "",
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"id": "90051",
|
||||||
|
"type": "Treachery",
|
||||||
|
"class": "Neutral",
|
||||||
|
"traits": "Endtimes.",
|
||||||
|
"weakness": true,
|
||||||
|
"cycle": "The Dunwich Legacy"
|
||||||
|
}
|
61
objects/AllPlayerCards.15bb07/FinalRhapsody.561775.json
Normal file
61
objects/AllPlayerCards.15bb07/FinalRhapsody.561775.json
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"AltLookAngle": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"Autoraise": true,
|
||||||
|
"CardID": 847001,
|
||||||
|
"ColorDiffuse": {
|
||||||
|
"b": 0.71324,
|
||||||
|
"g": 0.71324,
|
||||||
|
"r": 0.71324
|
||||||
|
},
|
||||||
|
"CustomDeck": {
|
||||||
|
"8470": {
|
||||||
|
"BackIsHidden": false,
|
||||||
|
"BackURL": "https://i.imgur.com/EcbhVuh.jpg/",
|
||||||
|
"FaceURL": "http://cloud-3.steamusercontent.com/ugc/2149964195986880793/517FBB4FF8F72900B9E123DB865BCAD625F6506C/",
|
||||||
|
"NumHeight": 2,
|
||||||
|
"NumWidth": 2,
|
||||||
|
"Type": 0,
|
||||||
|
"UniqueBack": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Description": "Advanced",
|
||||||
|
"DragSelectable": true,
|
||||||
|
"GMNotes_path": "AllPlayerCards.15bb07/FinalRhapsody.561775.gmnotes",
|
||||||
|
"GUID": "561775",
|
||||||
|
"Grid": true,
|
||||||
|
"GridProjection": false,
|
||||||
|
"Hands": true,
|
||||||
|
"HideWhenFaceDown": true,
|
||||||
|
"IgnoreFoW": false,
|
||||||
|
"LayoutGroupSortIndex": 0,
|
||||||
|
"Locked": false,
|
||||||
|
"LuaScript": "",
|
||||||
|
"LuaScriptState": "",
|
||||||
|
"MeasureMovement": false,
|
||||||
|
"Name": "Card",
|
||||||
|
"Nickname": "Final Rhapsody",
|
||||||
|
"SidewaysCard": false,
|
||||||
|
"Snap": true,
|
||||||
|
"Sticky": true,
|
||||||
|
"Tags": [
|
||||||
|
"PlayerCard"
|
||||||
|
],
|
||||||
|
"Tooltip": true,
|
||||||
|
"Transform": {
|
||||||
|
"posX": 78.419,
|
||||||
|
"posY": 3.193,
|
||||||
|
"posZ": 23.541,
|
||||||
|
"rotX": 0,
|
||||||
|
"rotY": 270,
|
||||||
|
"rotZ": 0,
|
||||||
|
"scaleX": 1,
|
||||||
|
"scaleY": 1,
|
||||||
|
"scaleZ": 1
|
||||||
|
},
|
||||||
|
"Value": 0,
|
||||||
|
"XmlUI": ""
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"id": "02004-p",
|
||||||
|
"type": "Investigator",
|
||||||
|
"class": "Mystic",
|
||||||
|
"traits": "Performer. Cursed.",
|
||||||
|
"willpowerIcons": 4,
|
||||||
|
"intellectIcons": 3,
|
||||||
|
"combatIcons": 3,
|
||||||
|
"agilityIcons": 2,
|
||||||
|
"cycle": "The Dunwich Legacy"
|
||||||
|
}
|
62
objects/AllPlayerCards.15bb07/JimCulverParallel.72bf31.json
Normal file
62
objects/AllPlayerCards.15bb07/JimCulverParallel.72bf31.json
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"AltLookAngle": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"Autoraise": true,
|
||||||
|
"CardID": 846700,
|
||||||
|
"ColorDiffuse": {
|
||||||
|
"b": 0.71324,
|
||||||
|
"g": 0.71324,
|
||||||
|
"r": 0.71324
|
||||||
|
},
|
||||||
|
"CustomDeck": {
|
||||||
|
"8467": {
|
||||||
|
"BackIsHidden": false,
|
||||||
|
"BackURL": "http://cloud-3.steamusercontent.com/ugc/2149964195987018702/54C63785F3AA474F635F58BC506C86A318432BD7/",
|
||||||
|
"FaceURL": "http://cloud-3.steamusercontent.com/ugc/2149964195987018793/0AED4BF62C4FF3206778AD36FDB9C8E482CD3F9E/",
|
||||||
|
"NumHeight": 2,
|
||||||
|
"NumWidth": 4,
|
||||||
|
"Type": 0,
|
||||||
|
"UniqueBack": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Description": "The Musician",
|
||||||
|
"DragSelectable": true,
|
||||||
|
"GMNotes_path": "AllPlayerCards.15bb07/JimCulverParallel.72bf31.gmnotes",
|
||||||
|
"GUID": "72bf31",
|
||||||
|
"Grid": true,
|
||||||
|
"GridProjection": false,
|
||||||
|
"Hands": true,
|
||||||
|
"HideWhenFaceDown": false,
|
||||||
|
"IgnoreFoW": false,
|
||||||
|
"LayoutGroupSortIndex": 0,
|
||||||
|
"Locked": false,
|
||||||
|
"LuaScript": "",
|
||||||
|
"LuaScriptState": "",
|
||||||
|
"MeasureMovement": false,
|
||||||
|
"Name": "Card",
|
||||||
|
"Nickname": "Jim Culver (Parallel)",
|
||||||
|
"SidewaysCard": true,
|
||||||
|
"Snap": true,
|
||||||
|
"Sticky": true,
|
||||||
|
"Tags": [
|
||||||
|
"Investigator",
|
||||||
|
"PlayerCard"
|
||||||
|
],
|
||||||
|
"Tooltip": true,
|
||||||
|
"Transform": {
|
||||||
|
"posX": 82.182,
|
||||||
|
"posY": 3.193,
|
||||||
|
"posZ": 26.386,
|
||||||
|
"rotX": 0,
|
||||||
|
"rotY": 180,
|
||||||
|
"rotZ": 0,
|
||||||
|
"scaleX": 1.15,
|
||||||
|
"scaleY": 1,
|
||||||
|
"scaleZ": 1.15
|
||||||
|
},
|
||||||
|
"Value": 0,
|
||||||
|
"XmlUI": ""
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"id": "02004-pb",
|
||||||
|
"type": "Investigator",
|
||||||
|
"class": "Mystic",
|
||||||
|
"traits": "Performer.",
|
||||||
|
"willpowerIcons": 4,
|
||||||
|
"intellectIcons": 3,
|
||||||
|
"combatIcons": 3,
|
||||||
|
"agilityIcons": 2,
|
||||||
|
"cycle": "The Dunwich Legacy"
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"AltLookAngle": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"Autoraise": true,
|
||||||
|
"CardID": 846805,
|
||||||
|
"ColorDiffuse": {
|
||||||
|
"b": 0.71324,
|
||||||
|
"g": 0.71324,
|
||||||
|
"r": 0.71324
|
||||||
|
},
|
||||||
|
"CustomDeck": {
|
||||||
|
"8468": {
|
||||||
|
"BackIsHidden": false,
|
||||||
|
"BackURL": "http://cloud-3.steamusercontent.com/ugc/2149964195987018702/54C63785F3AA474F635F58BC506C86A318432BD7/",
|
||||||
|
"FaceURL": "http://cloud-3.steamusercontent.com/ugc/1656727981627737050/3CFF9E3825033909543AD1CF843361D9243538EE/",
|
||||||
|
"NumHeight": 2,
|
||||||
|
"NumWidth": 4,
|
||||||
|
"Type": 0,
|
||||||
|
"UniqueBack": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Description": "The Musician",
|
||||||
|
"DragSelectable": true,
|
||||||
|
"GMNotes_path": "AllPlayerCards.15bb07/JimCulverParallelBack.aba863.gmnotes",
|
||||||
|
"GUID": "aba863",
|
||||||
|
"Grid": true,
|
||||||
|
"GridProjection": false,
|
||||||
|
"Hands": true,
|
||||||
|
"HideWhenFaceDown": false,
|
||||||
|
"IgnoreFoW": false,
|
||||||
|
"LayoutGroupSortIndex": 0,
|
||||||
|
"Locked": false,
|
||||||
|
"LuaScript": "",
|
||||||
|
"LuaScriptState": "",
|
||||||
|
"MeasureMovement": false,
|
||||||
|
"Name": "Card",
|
||||||
|
"Nickname": "Jim Culver (Parallel Back)",
|
||||||
|
"SidewaysCard": true,
|
||||||
|
"Snap": true,
|
||||||
|
"Sticky": true,
|
||||||
|
"Tags": [
|
||||||
|
"Investigator",
|
||||||
|
"PlayerCard"
|
||||||
|
],
|
||||||
|
"Tooltip": true,
|
||||||
|
"Transform": {
|
||||||
|
"posX": 82.206,
|
||||||
|
"posY": 3.193,
|
||||||
|
"posZ": 18.459,
|
||||||
|
"rotX": 0,
|
||||||
|
"rotY": 180,
|
||||||
|
"rotZ": 0,
|
||||||
|
"scaleX": 1.15,
|
||||||
|
"scaleY": 1,
|
||||||
|
"scaleZ": 1.15
|
||||||
|
},
|
||||||
|
"Value": 0,
|
||||||
|
"XmlUI": ""
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"id": "02004-pf",
|
||||||
|
"type": "Investigator",
|
||||||
|
"class": "Mystic",
|
||||||
|
"traits": "Performer. Cursed.",
|
||||||
|
"willpowerIcons": 4,
|
||||||
|
"intellectIcons": 3,
|
||||||
|
"combatIcons": 3,
|
||||||
|
"agilityIcons": 2,
|
||||||
|
"cycle": "The Dunwich Legacy"
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"AltLookAngle": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"Autoraise": true,
|
||||||
|
"CardID": 846905,
|
||||||
|
"ColorDiffuse": {
|
||||||
|
"b": 0.71324,
|
||||||
|
"g": 0.71324,
|
||||||
|
"r": 0.71324
|
||||||
|
},
|
||||||
|
"CustomDeck": {
|
||||||
|
"8469": {
|
||||||
|
"BackIsHidden": false,
|
||||||
|
"BackURL": "http://cloud-3.steamusercontent.com/ugc/1656727981627737648/F371339538812F68E38AAC0D520C525250DAC5C0/",
|
||||||
|
"FaceURL": "http://cloud-3.steamusercontent.com/ugc/2149964195987018793/0AED4BF62C4FF3206778AD36FDB9C8E482CD3F9E/",
|
||||||
|
"NumHeight": 2,
|
||||||
|
"NumWidth": 4,
|
||||||
|
"Type": 0,
|
||||||
|
"UniqueBack": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Description": "The Musician",
|
||||||
|
"DragSelectable": true,
|
||||||
|
"GMNotes_path": "AllPlayerCards.15bb07/JimCulverParallelFront.c5fc80.gmnotes",
|
||||||
|
"GUID": "c5fc80",
|
||||||
|
"Grid": true,
|
||||||
|
"GridProjection": false,
|
||||||
|
"Hands": true,
|
||||||
|
"HideWhenFaceDown": false,
|
||||||
|
"IgnoreFoW": false,
|
||||||
|
"LayoutGroupSortIndex": 0,
|
||||||
|
"Locked": false,
|
||||||
|
"LuaScript": "",
|
||||||
|
"LuaScriptState": "",
|
||||||
|
"MeasureMovement": false,
|
||||||
|
"Name": "Card",
|
||||||
|
"Nickname": "Jim Culver (Parallel Front)",
|
||||||
|
"SidewaysCard": true,
|
||||||
|
"Snap": true,
|
||||||
|
"Sticky": true,
|
||||||
|
"Tags": [
|
||||||
|
"Investigator",
|
||||||
|
"PlayerCard"
|
||||||
|
],
|
||||||
|
"Tooltip": true,
|
||||||
|
"Transform": {
|
||||||
|
"posX": 82.087,
|
||||||
|
"posY": 3.193,
|
||||||
|
"posZ": 22.484,
|
||||||
|
"rotX": 0,
|
||||||
|
"rotY": 180,
|
||||||
|
"rotZ": 0,
|
||||||
|
"scaleX": 1.15,
|
||||||
|
"scaleY": 1,
|
||||||
|
"scaleZ": 1.15
|
||||||
|
},
|
||||||
|
"Value": 0,
|
||||||
|
"XmlUI": ""
|
||||||
|
}
|
@ -22,7 +22,7 @@
|
|||||||
"UniqueBack": false
|
"UniqueBack": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Description": "",
|
"Description": "The Dead Listen",
|
||||||
"DragSelectable": true,
|
"DragSelectable": true,
|
||||||
"GMNotes_path": "AllPlayerCards.15bb07/JimsTrumpet.03c6a7.gmnotes",
|
"GMNotes_path": "AllPlayerCards.15bb07/JimsTrumpet.03c6a7.gmnotes",
|
||||||
"GUID": "03c6a7",
|
"GUID": "03c6a7",
|
||||||
|
10
objects/AllPlayerCards.15bb07/JimsTrumpet.7dfd5f.gmnotes
Normal file
10
objects/AllPlayerCards.15bb07/JimsTrumpet.7dfd5f.gmnotes
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"id": "90050",
|
||||||
|
"type": "Asset",
|
||||||
|
"class": "Neutral",
|
||||||
|
"cost": 2,
|
||||||
|
"traits": "Item. Instrument. Relic.",
|
||||||
|
"willpowerIcons": 2,
|
||||||
|
"wildIcons": 2,
|
||||||
|
"cycle": "The Dunwich Legacy"
|
||||||
|
}
|
62
objects/AllPlayerCards.15bb07/JimsTrumpet.7dfd5f.json
Normal file
62
objects/AllPlayerCards.15bb07/JimsTrumpet.7dfd5f.json
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"AltLookAngle": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"Autoraise": true,
|
||||||
|
"CardID": 847000,
|
||||||
|
"ColorDiffuse": {
|
||||||
|
"b": 0.71324,
|
||||||
|
"g": 0.71324,
|
||||||
|
"r": 0.71324
|
||||||
|
},
|
||||||
|
"CustomDeck": {
|
||||||
|
"8470": {
|
||||||
|
"BackIsHidden": false,
|
||||||
|
"BackURL": "https://i.imgur.com/EcbhVuh.jpg/",
|
||||||
|
"FaceURL": "http://cloud-3.steamusercontent.com/ugc/2149964195986880793/517FBB4FF8F72900B9E123DB865BCAD625F6506C/",
|
||||||
|
"NumHeight": 2,
|
||||||
|
"NumWidth": 2,
|
||||||
|
"Type": 0,
|
||||||
|
"UniqueBack": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Description": "The Dead Speak (Advanced)",
|
||||||
|
"DragSelectable": true,
|
||||||
|
"GMNotes_path": "AllPlayerCards.15bb07/JimsTrumpet.7dfd5f.gmnotes",
|
||||||
|
"GUID": "7dfd5f",
|
||||||
|
"Grid": true,
|
||||||
|
"GridProjection": false,
|
||||||
|
"Hands": true,
|
||||||
|
"HideWhenFaceDown": true,
|
||||||
|
"IgnoreFoW": false,
|
||||||
|
"LayoutGroupSortIndex": 0,
|
||||||
|
"Locked": false,
|
||||||
|
"LuaScript": "",
|
||||||
|
"LuaScriptState": "",
|
||||||
|
"MeasureMovement": false,
|
||||||
|
"Name": "Card",
|
||||||
|
"Nickname": "Jim's Trumpet",
|
||||||
|
"SidewaysCard": false,
|
||||||
|
"Snap": true,
|
||||||
|
"Sticky": true,
|
||||||
|
"Tags": [
|
||||||
|
"Asset",
|
||||||
|
"PlayerCard"
|
||||||
|
],
|
||||||
|
"Tooltip": true,
|
||||||
|
"Transform": {
|
||||||
|
"posX": 78.511,
|
||||||
|
"posY": 3.229,
|
||||||
|
"posZ": 27.011,
|
||||||
|
"rotX": 359,
|
||||||
|
"rotY": 270,
|
||||||
|
"rotZ": 0,
|
||||||
|
"scaleX": 1,
|
||||||
|
"scaleY": 1,
|
||||||
|
"scaleZ": 1
|
||||||
|
},
|
||||||
|
"Value": 0,
|
||||||
|
"XmlUI": ""
|
||||||
|
}
|
8
objects/AllPlayerCards.15bb07/TheBeyond.37ab47.gmnotes
Normal file
8
objects/AllPlayerCards.15bb07/TheBeyond.37ab47.gmnotes
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"id": "90052",
|
||||||
|
"type": "Asset",
|
||||||
|
"class": "Neutral",
|
||||||
|
"permanent": true,
|
||||||
|
"startsInPlay": true,
|
||||||
|
"cycle": "Laid to Rest"
|
||||||
|
}
|
62
objects/AllPlayerCards.15bb07/TheBeyond.37ab47.json
Normal file
62
objects/AllPlayerCards.15bb07/TheBeyond.37ab47.json
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"AltLookAngle": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"Autoraise": true,
|
||||||
|
"CardID": 847100,
|
||||||
|
"ColorDiffuse": {
|
||||||
|
"b": 0.71324,
|
||||||
|
"g": 0.71324,
|
||||||
|
"r": 0.71324
|
||||||
|
},
|
||||||
|
"CustomDeck": {
|
||||||
|
"8471": {
|
||||||
|
"BackIsHidden": true,
|
||||||
|
"BackURL": "http://cloud-3.steamusercontent.com/ugc/2149964195986881059/864F6EBBD2900ED6D145B8AF12F2F8C180375C83/",
|
||||||
|
"FaceURL": "http://cloud-3.steamusercontent.com/ugc/2149964195986880989/13172BC914A0D729B4EFD9845FA9FDFCAB6F77F7/",
|
||||||
|
"NumHeight": 1,
|
||||||
|
"NumWidth": 1,
|
||||||
|
"Type": 0,
|
||||||
|
"UniqueBack": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Description": "Bleak Netherworld",
|
||||||
|
"DragSelectable": true,
|
||||||
|
"GMNotes_path": "AllPlayerCards.15bb07/TheBeyond.37ab47.gmnotes",
|
||||||
|
"GUID": "37ab47",
|
||||||
|
"Grid": true,
|
||||||
|
"GridProjection": false,
|
||||||
|
"Hands": true,
|
||||||
|
"HideWhenFaceDown": true,
|
||||||
|
"IgnoreFoW": false,
|
||||||
|
"LayoutGroupSortIndex": 0,
|
||||||
|
"Locked": false,
|
||||||
|
"LuaScript": "",
|
||||||
|
"LuaScriptState": "",
|
||||||
|
"MeasureMovement": false,
|
||||||
|
"Name": "CardCustom",
|
||||||
|
"Nickname": "The Beyond",
|
||||||
|
"SidewaysCard": false,
|
||||||
|
"Snap": true,
|
||||||
|
"Sticky": true,
|
||||||
|
"Tags": [
|
||||||
|
"Asset",
|
||||||
|
"PlayerCard"
|
||||||
|
],
|
||||||
|
"Tooltip": true,
|
||||||
|
"Transform": {
|
||||||
|
"posX": 78.532,
|
||||||
|
"posY": 3.193,
|
||||||
|
"posZ": 17.888,
|
||||||
|
"rotX": 0,
|
||||||
|
"rotY": 270,
|
||||||
|
"rotZ": 0,
|
||||||
|
"scaleX": 1,
|
||||||
|
"scaleY": 1,
|
||||||
|
"scaleZ": 1
|
||||||
|
},
|
||||||
|
"Value": 0,
|
||||||
|
"XmlUI": ""
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"id": "90053",
|
||||||
|
"type": "Enemy",
|
||||||
|
"class": "Neutral",
|
||||||
|
"traits": "Monster. Geist",
|
||||||
|
"weakness": true,
|
||||||
|
"cycle": "Laid to Rest"
|
||||||
|
}
|
61
objects/AllPlayerCards.15bb07/VengefulShade.73bc8e.json
Normal file
61
objects/AllPlayerCards.15bb07/VengefulShade.73bc8e.json
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"AltLookAngle": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"Autoraise": true,
|
||||||
|
"CardID": 847002,
|
||||||
|
"ColorDiffuse": {
|
||||||
|
"b": 0.71324,
|
||||||
|
"g": 0.71324,
|
||||||
|
"r": 0.71324
|
||||||
|
},
|
||||||
|
"CustomDeck": {
|
||||||
|
"8470": {
|
||||||
|
"BackIsHidden": false,
|
||||||
|
"BackURL": "https://i.imgur.com/EcbhVuh.jpg/",
|
||||||
|
"FaceURL": "http://cloud-3.steamusercontent.com/ugc/2149964195986880793/517FBB4FF8F72900B9E123DB865BCAD625F6506C/",
|
||||||
|
"NumHeight": 2,
|
||||||
|
"NumWidth": 2,
|
||||||
|
"Type": 0,
|
||||||
|
"UniqueBack": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Description": "",
|
||||||
|
"DragSelectable": true,
|
||||||
|
"GMNotes_path": "AllPlayerCards.15bb07/VengefulShade.73bc8e.gmnotes",
|
||||||
|
"GUID": "73bc8e",
|
||||||
|
"Grid": true,
|
||||||
|
"GridProjection": false,
|
||||||
|
"Hands": true,
|
||||||
|
"HideWhenFaceDown": true,
|
||||||
|
"IgnoreFoW": false,
|
||||||
|
"LayoutGroupSortIndex": 0,
|
||||||
|
"Locked": false,
|
||||||
|
"LuaScript": "",
|
||||||
|
"LuaScriptState": "",
|
||||||
|
"MeasureMovement": false,
|
||||||
|
"Name": "Card",
|
||||||
|
"Nickname": "Vengeful Shade",
|
||||||
|
"SidewaysCard": false,
|
||||||
|
"Snap": true,
|
||||||
|
"Sticky": true,
|
||||||
|
"Tags": [
|
||||||
|
"PlayerCard"
|
||||||
|
],
|
||||||
|
"Tooltip": true,
|
||||||
|
"Transform": {
|
||||||
|
"posX": 78.455,
|
||||||
|
"posY": 3.193,
|
||||||
|
"posZ": 20.547,
|
||||||
|
"rotX": 0,
|
||||||
|
"rotY": 270,
|
||||||
|
"rotZ": 0,
|
||||||
|
"scaleX": 1,
|
||||||
|
"scaleY": 1,
|
||||||
|
"scaleZ": 1
|
||||||
|
},
|
||||||
|
"Value": 0,
|
||||||
|
"XmlUI": ""
|
||||||
|
}
|
@ -2,7 +2,7 @@
|
|||||||
"id": "01005-p",
|
"id": "01005-p",
|
||||||
"type": "Investigator",
|
"type": "Investigator",
|
||||||
"class": "Survivor",
|
"class": "Survivor",
|
||||||
"traits": "Drifter.",
|
"traits": "Drifter. Blessed. Cursed.",
|
||||||
"willpowerIcons": 4,
|
"willpowerIcons": 4,
|
||||||
"intellectIcons": 3,
|
"intellectIcons": 3,
|
||||||
"combatIcons": 1,
|
"combatIcons": 1,
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"id": "01005-pf",
|
"id": "01005-pf",
|
||||||
"type": "Investigator",
|
"type": "Investigator",
|
||||||
"class": "Survivor",
|
"class": "Survivor",
|
||||||
"traits": "Drifter.",
|
"traits": "Drifter. Blessed. Cursed.",
|
||||||
"willpowerIcons": 4,
|
"willpowerIcons": 4,
|
||||||
"intellectIcons": 3,
|
"intellectIcons": 3,
|
||||||
"combatIcons": 1,
|
"combatIcons": 1,
|
||||||
|
@ -28,9 +28,6 @@
|
|||||||
"Nickname": "Arkham Deck Cutter",
|
"Nickname": "Arkham Deck Cutter",
|
||||||
"Snap": true,
|
"Snap": true,
|
||||||
"Sticky": true,
|
"Sticky": true,
|
||||||
"Tags": [
|
|
||||||
"arkham_setup_memory_object"
|
|
||||||
],
|
|
||||||
"Tooltip": true,
|
"Tooltip": true,
|
||||||
"Transform": {
|
"Transform": {
|
||||||
"posX": 78,
|
"posX": 78,
|
||||||
|
@ -67,6 +67,7 @@
|
|||||||
"Snap": true,
|
"Snap": true,
|
||||||
"Sticky": true,
|
"Sticky": true,
|
||||||
"Tags": [
|
"Tags": [
|
||||||
|
"CleanUpHelper_ignore",
|
||||||
"displacement_excluded"
|
"displacement_excluded"
|
||||||
],
|
],
|
||||||
"Tooltip": true,
|
"Tooltip": true,
|
||||||
|
@ -44,6 +44,9 @@
|
|||||||
"Nickname": "Clue tokens",
|
"Nickname": "Clue tokens",
|
||||||
"Snap": true,
|
"Snap": true,
|
||||||
"Sticky": true,
|
"Sticky": true,
|
||||||
|
"Tags": [
|
||||||
|
"CleanUpHelper_ignore"
|
||||||
|
],
|
||||||
"Tooltip": true,
|
"Tooltip": true,
|
||||||
"Transform": {
|
"Transform": {
|
||||||
"posX": 2.857,
|
"posX": 2.857,
|
||||||
|
@ -83,4 +83,4 @@
|
|||||||
},
|
},
|
||||||
"Value": 0,
|
"Value": 0,
|
||||||
"XmlUI": ""
|
"XmlUI": ""
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,9 @@
|
|||||||
"Nickname": "Cartoon Investigators",
|
"Nickname": "Cartoon Investigators",
|
||||||
"Snap": true,
|
"Snap": true,
|
||||||
"Sticky": true,
|
"Sticky": true,
|
||||||
|
"Tags": [
|
||||||
|
"LargeBox"
|
||||||
|
],
|
||||||
"Tooltip": true,
|
"Tooltip": true,
|
||||||
"Transform": {
|
"Transform": {
|
||||||
"posX": -23.615,
|
"posX": -23.615,
|
||||||
@ -61,9 +64,6 @@
|
|||||||
"scaleY": 0.14,
|
"scaleY": 0.14,
|
||||||
"scaleZ": 1
|
"scaleZ": 1
|
||||||
},
|
},
|
||||||
"Tags": [
|
|
||||||
"LargeBox"
|
|
||||||
],
|
|
||||||
"Value": 0,
|
"Value": 0,
|
||||||
"XmlUI": ""
|
"XmlUI": ""
|
||||||
}
|
}
|
||||||
|
@ -83,4 +83,4 @@
|
|||||||
},
|
},
|
||||||
"Value": 0,
|
"Value": 0,
|
||||||
"XmlUI": ""
|
"XmlUI": ""
|
||||||
}
|
}
|
||||||
|
@ -83,4 +83,4 @@
|
|||||||
},
|
},
|
||||||
"Value": 0,
|
"Value": 0,
|
||||||
"XmlUI": ""
|
"XmlUI": ""
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,9 @@
|
|||||||
"Nickname": "The Ghosts Of Onigawa (Investigator Expansion)",
|
"Nickname": "The Ghosts Of Onigawa (Investigator Expansion)",
|
||||||
"Snap": true,
|
"Snap": true,
|
||||||
"Sticky": true,
|
"Sticky": true,
|
||||||
|
"Tags": [
|
||||||
|
"LargeBox"
|
||||||
|
],
|
||||||
"Tooltip": true,
|
"Tooltip": true,
|
||||||
"Transform": {
|
"Transform": {
|
||||||
"posX": -47.192,
|
"posX": -47.192,
|
||||||
@ -61,9 +64,6 @@
|
|||||||
"scaleY": 0.14,
|
"scaleY": 0.14,
|
||||||
"scaleZ": 1
|
"scaleZ": 1
|
||||||
},
|
},
|
||||||
"Tags": [
|
|
||||||
"LargeBox"
|
|
||||||
],
|
|
||||||
"Value": 0,
|
"Value": 0,
|
||||||
"XmlUI": ""
|
"XmlUI": ""
|
||||||
}
|
}
|
||||||
|
@ -83,4 +83,4 @@
|
|||||||
},
|
},
|
||||||
"Value": 0,
|
"Value": 0,
|
||||||
"XmlUI": ""
|
"XmlUI": ""
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,9 @@
|
|||||||
"Nickname": "The Sands Of Memphis (Investigator Expansion)",
|
"Nickname": "The Sands Of Memphis (Investigator Expansion)",
|
||||||
"Snap": true,
|
"Snap": true,
|
||||||
"Sticky": true,
|
"Sticky": true,
|
||||||
|
"Tags": [
|
||||||
|
"LargeBox"
|
||||||
|
],
|
||||||
"Tooltip": true,
|
"Tooltip": true,
|
||||||
"Transform": {
|
"Transform": {
|
||||||
"posX": -47.192,
|
"posX": -47.192,
|
||||||
@ -61,9 +64,6 @@
|
|||||||
"scaleY": 0.14,
|
"scaleY": 0.14,
|
||||||
"scaleZ": 1
|
"scaleZ": 1
|
||||||
},
|
},
|
||||||
"Tags": [
|
|
||||||
"LargeBox"
|
|
||||||
],
|
|
||||||
"Value": 0,
|
"Value": 0,
|
||||||
"XmlUI": ""
|
"XmlUI": ""
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,9 @@
|
|||||||
"Nickname": "Connection markers",
|
"Nickname": "Connection markers",
|
||||||
"Snap": true,
|
"Snap": true,
|
||||||
"Sticky": true,
|
"Sticky": true,
|
||||||
|
"Tags": [
|
||||||
|
"CleanUpHelper_ignore"
|
||||||
|
],
|
||||||
"Tooltip": true,
|
"Tooltip": true,
|
||||||
"Transform": {
|
"Transform": {
|
||||||
"posX": -51,
|
"posX": -51,
|
||||||
|
@ -67,6 +67,7 @@
|
|||||||
"Snap": true,
|
"Snap": true,
|
||||||
"Sticky": true,
|
"Sticky": true,
|
||||||
"Tags": [
|
"Tags": [
|
||||||
|
"CleanUpHelper_ignore",
|
||||||
"displacement_excluded"
|
"displacement_excluded"
|
||||||
],
|
],
|
||||||
"Tooltip": true,
|
"Tooltip": true,
|
||||||
|
@ -40,6 +40,9 @@
|
|||||||
"Nickname": "Doom Counter",
|
"Nickname": "Doom Counter",
|
||||||
"Snap": true,
|
"Snap": true,
|
||||||
"Sticky": true,
|
"Sticky": true,
|
||||||
|
"Tags": [
|
||||||
|
"CleanUpHelper_ignore"
|
||||||
|
],
|
||||||
"Tooltip": true,
|
"Tooltip": true,
|
||||||
"Transform": {
|
"Transform": {
|
||||||
"posX": -5.3,
|
"posX": -5.3,
|
||||||
|
@ -44,6 +44,9 @@
|
|||||||
"Nickname": "Doom tokens",
|
"Nickname": "Doom tokens",
|
||||||
"Snap": true,
|
"Snap": true,
|
||||||
"Sticky": true,
|
"Sticky": true,
|
||||||
|
"Tags": [
|
||||||
|
"CleanUpHelper_ignore"
|
||||||
|
],
|
||||||
"Tooltip": true,
|
"Tooltip": true,
|
||||||
"Transform": {
|
"Transform": {
|
||||||
"posX": -55.48,
|
"posX": -55.48,
|
||||||
|
@ -44,6 +44,9 @@
|
|||||||
"Nickname": "Doom tokens",
|
"Nickname": "Doom tokens",
|
||||||
"Snap": true,
|
"Snap": true,
|
||||||
"Sticky": true,
|
"Sticky": true,
|
||||||
|
"Tags": [
|
||||||
|
"CleanUpHelper_ignore"
|
||||||
|
],
|
||||||
"Tooltip": true,
|
"Tooltip": true,
|
||||||
"Transform": {
|
"Transform": {
|
||||||
"posX": 2.761,
|
"posX": 2.761,
|
||||||
|
@ -54,4 +54,4 @@
|
|||||||
},
|
},
|
||||||
"Value": 0,
|
"Value": 0,
|
||||||
"XmlUI": ""
|
"XmlUI": ""
|
||||||
}
|
}
|
||||||
|
@ -54,4 +54,4 @@
|
|||||||
},
|
},
|
||||||
"Value": 0,
|
"Value": 0,
|
||||||
"XmlUI": ""
|
"XmlUI": ""
|
||||||
}
|
}
|
||||||
|
@ -73,4 +73,4 @@
|
|||||||
},
|
},
|
||||||
"Value": 0,
|
"Value": 0,
|
||||||
"XmlUI": ""
|
"XmlUI": ""
|
||||||
}
|
}
|
||||||
|
@ -83,4 +83,4 @@
|
|||||||
},
|
},
|
||||||
"Value": 0,
|
"Value": 0,
|
||||||
"XmlUI": ""
|
"XmlUI": ""
|
||||||
}
|
}
|
||||||
|
@ -82,4 +82,4 @@
|
|||||||
},
|
},
|
||||||
"Value": 0,
|
"Value": 0,
|
||||||
"XmlUI": ""
|
"XmlUI": ""
|
||||||
}
|
}
|
||||||
|
@ -66,4 +66,4 @@
|
|||||||
},
|
},
|
||||||
"Value": 0,
|
"Value": 0,
|
||||||
"XmlUI": ""
|
"XmlUI": ""
|
||||||
}
|
}
|
||||||
|
45
objects/GUIDReferenceHandler.123456.json
Normal file
45
objects/GUIDReferenceHandler.123456.json
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"AltLookAngle": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"Autoraise": true,
|
||||||
|
"ColorDiffuse": {
|
||||||
|
"b": 0.116,
|
||||||
|
"g": 0.116,
|
||||||
|
"r": 0.716
|
||||||
|
},
|
||||||
|
"Description": "This object handles GUID references to objects.",
|
||||||
|
"DragSelectable": true,
|
||||||
|
"GMNotes": "",
|
||||||
|
"GUID": "123456",
|
||||||
|
"Grid": true,
|
||||||
|
"GridProjection": false,
|
||||||
|
"Hands": false,
|
||||||
|
"HideWhenFaceDown": false,
|
||||||
|
"IgnoreFoW": false,
|
||||||
|
"LayoutGroupSortIndex": 0,
|
||||||
|
"Locked": true,
|
||||||
|
"LuaScript": "require(\"core/GUIDReferenceHandler\")",
|
||||||
|
"LuaScriptState": "",
|
||||||
|
"MeasureMovement": false,
|
||||||
|
"Name": "go_game_piece_white",
|
||||||
|
"Nickname": "GUID Reference Handler",
|
||||||
|
"Snap": true,
|
||||||
|
"Sticky": true,
|
||||||
|
"Tooltip": true,
|
||||||
|
"Transform": {
|
||||||
|
"posX": 78,
|
||||||
|
"posY": 1.328,
|
||||||
|
"posZ": -8,
|
||||||
|
"rotX": 0,
|
||||||
|
"rotY": 0,
|
||||||
|
"rotZ": 0,
|
||||||
|
"scaleX": 1,
|
||||||
|
"scaleY": 1,
|
||||||
|
"scaleZ": 1
|
||||||
|
},
|
||||||
|
"Value": 0,
|
||||||
|
"XmlUI": ""
|
||||||
|
}
|
@ -19,7 +19,7 @@
|
|||||||
},
|
},
|
||||||
"ImageScalar": 1,
|
"ImageScalar": 1,
|
||||||
"ImageSecondaryURL": "",
|
"ImageSecondaryURL": "",
|
||||||
"ImageURL": "http://cloud-3.steamusercontent.com/ugc/1758068501357164917/1D06F1DC4D6888B6F57124BD2AFE20D0B0DA15A8/",
|
"ImageURL": "http://cloud-3.steamusercontent.com/ugc/784129913444610342/7903BA89870C1656A003FD69C79BFA99BD1AAC24/",
|
||||||
"WidthScale": 0
|
"WidthScale": 0
|
||||||
},
|
},
|
||||||
"Description": "Click to remove all clues from all investigators",
|
"Description": "Click to remove all clues from all investigators",
|
||||||
@ -37,9 +37,12 @@
|
|||||||
"LuaScriptState": "false",
|
"LuaScriptState": "false",
|
||||||
"MeasureMovement": false,
|
"MeasureMovement": false,
|
||||||
"Name": "Custom_Token",
|
"Name": "Custom_Token",
|
||||||
"Nickname": "Master Clue Counter\n",
|
"Nickname": "Master Clue Counter",
|
||||||
"Snap": true,
|
"Snap": true,
|
||||||
"Sticky": true,
|
"Sticky": true,
|
||||||
|
"Tags": [
|
||||||
|
"CleanUpHelper_ignore"
|
||||||
|
],
|
||||||
"Tooltip": true,
|
"Tooltip": true,
|
||||||
"Transform": {
|
"Transform": {
|
||||||
"posX": -5.3,
|
"posX": -5.3,
|
||||||
|
@ -66,6 +66,9 @@
|
|||||||
"Nickname": "Mythos Area",
|
"Nickname": "Mythos Area",
|
||||||
"Snap": true,
|
"Snap": true,
|
||||||
"Sticky": true,
|
"Sticky": true,
|
||||||
|
"Tags": [
|
||||||
|
"CleanUpHelper_ignore"
|
||||||
|
],
|
||||||
"Tooltip": false,
|
"Tooltip": false,
|
||||||
"Transform": {
|
"Transform": {
|
||||||
"posX": -1.309,
|
"posX": -1.309,
|
||||||
|
@ -14,11 +14,12 @@
|
|||||||
"r": 1
|
"r": 1
|
||||||
},
|
},
|
||||||
"ContainedObjects_order": [
|
"ContainedObjects_order": [
|
||||||
"BadBlood.451eaa",
|
|
||||||
"RedTideRising.5302f2",
|
|
||||||
"AllorNothing.72ab92",
|
"AllorNothing.72ab92",
|
||||||
|
"BadBlood.451eaa",
|
||||||
|
"BytheBook.cc7eb3",
|
||||||
|
"LaidtoRest.e2dd57",
|
||||||
"ReadorDie.9e73fa",
|
"ReadorDie.9e73fa",
|
||||||
"BytheBook.cc7eb3"
|
"RedTideRising.5302f2"
|
||||||
],
|
],
|
||||||
"ContainedObjects_path": "ChallengeScenarios.9f6801",
|
"ContainedObjects_path": "ChallengeScenarios.9f6801",
|
||||||
"CustomMesh": {
|
"CustomMesh": {
|
||||||
@ -64,7 +65,7 @@
|
|||||||
"Tooltip": true,
|
"Tooltip": true,
|
||||||
"Transform": {
|
"Transform": {
|
||||||
"posX": -9,
|
"posX": -9,
|
||||||
"posY": 1.481,
|
"posY": 1.482,
|
||||||
"posZ": -76,
|
"posZ": -76,
|
||||||
"rotX": 0,
|
"rotX": 0,
|
||||||
"rotY": 270,
|
"rotY": 270,
|
||||||
|
@ -1 +1 @@
|
|||||||
{"ml":{"451eaa":{"lock":false,"pos":{"x":12.2499580383301,"y":1.46560525894165,"z":3.98636198043823},"rot":{"x":359.920135498047,"y":269.999908447266,"z":0.016873624175787}},"5302f2":{"lock":false,"pos":{"x":12.2504663467407,"y":1.45853757858276,"z":-20.013650894165},"rot":{"x":359.920135498047,"y":270.00146484375,"z":0.0168716721236706}},"72ab92":{"lock":false,"pos":{"x":12.2520532608032,"y":1.4679582118988,"z":11.9863719940186},"rot":{"x":359.920135498047,"y":270,"z":0.0168737415224314}},"9e73fa":{"lock":false,"pos":{"x":12.2500581741333,"y":1.46089386940002,"z":-12.0136384963989},"rot":{"x":359.920135498047,"y":269.999847412109,"z":0.0168744903057814}},"cc7eb3":{"lock":false,"pos":{"x":12.2495565414429,"y":1.46325027942657,"z":-4.01364088058472},"rot":{"x":359.920135498047,"y":269.999908447266,"z":0.0168744102120399}}}}
|
{"ml":{"451eaa":{"lock":false,"pos":{"x":12.252,"y":1.4815,"z":11.986},"rot":{"x":0,"y":269.9999,"z":0}},"5302f2":{"lock":false,"pos":{"x":12.2505,"y":1.4815,"z":-20.0137},"rot":{"x":0,"y":270.0014,"z":0}},"72ab92":{"lock":false,"pos":{"x":12.25,"y":1.4815,"z":19.986},"rot":{"x":0,"y":269.9999,"z":0}},"9e73fa":{"lock":false,"pos":{"x":12.2501,"y":1.4815,"z":-12.0137},"rot":{"x":0,"y":269.9998,"z":0}},"cc7eb3":{"lock":false,"pos":{"x":12.25,"y":1.4815,"z":3.986},"rot":{"x":0,"y":269.9999,"z":0}},"e2dd57":{"lock":false,"pos":{"x":12.25,"y":1.4815,"z":-4.014},"rot":{"x":0,"y":270,"z":0}}}}
|
||||||
|
@ -71,9 +71,9 @@
|
|||||||
"Sticky": true,
|
"Sticky": true,
|
||||||
"Tooltip": true,
|
"Tooltip": true,
|
||||||
"Transform": {
|
"Transform": {
|
||||||
"posX": 12.252,
|
"posX": 12.25,
|
||||||
"posY": 1.468,
|
"posY": 1.481,
|
||||||
"posZ": 11.986,
|
"posZ": 19.986,
|
||||||
"rotX": 0,
|
"rotX": 0,
|
||||||
"rotY": 270,
|
"rotY": 270,
|
||||||
"rotZ": 0,
|
"rotZ": 0,
|
||||||
|
@ -71,9 +71,9 @@
|
|||||||
"Sticky": true,
|
"Sticky": true,
|
||||||
"Tooltip": true,
|
"Tooltip": true,
|
||||||
"Transform": {
|
"Transform": {
|
||||||
"posX": 12.25,
|
"posX": 12.252,
|
||||||
"posY": 1.466,
|
"posY": 1.481,
|
||||||
"posZ": 3.986,
|
"posZ": 11.986,
|
||||||
"rotX": 0,
|
"rotX": 0,
|
||||||
"rotY": 270,
|
"rotY": 270,
|
||||||
"rotZ": 0,
|
"rotZ": 0,
|
||||||
|
@ -72,8 +72,8 @@
|
|||||||
"Tooltip": true,
|
"Tooltip": true,
|
||||||
"Transform": {
|
"Transform": {
|
||||||
"posX": 12.25,
|
"posX": 12.25,
|
||||||
"posY": 1.463,
|
"posY": 1.481,
|
||||||
"posZ": -4.014,
|
"posZ": 3.986,
|
||||||
"rotX": 0,
|
"rotX": 0,
|
||||||
"rotY": 270,
|
"rotY": 270,
|
||||||
"rotZ": 0,
|
"rotZ": 0,
|
||||||
|
@ -0,0 +1,86 @@
|
|||||||
|
{
|
||||||
|
"AltLookAngle": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"AttachedDecals": [
|
||||||
|
{
|
||||||
|
"CustomDecal": {
|
||||||
|
"ImageURL": "http://cloud-3.steamusercontent.com/ugc/959719855119695911/931B9829687A20F4DEADB36DA57B7E6D76792231/",
|
||||||
|
"Name": "dunwich_back",
|
||||||
|
"Size": 7.4
|
||||||
|
},
|
||||||
|
"Transform": {
|
||||||
|
"posX": 0,
|
||||||
|
"posY": 0,
|
||||||
|
"posZ": 0,
|
||||||
|
"rotX": 270,
|
||||||
|
"rotY": 0,
|
||||||
|
"rotZ": 0,
|
||||||
|
"scaleX": 2,
|
||||||
|
"scaleY": 2,
|
||||||
|
"scaleZ": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Autoraise": true,
|
||||||
|
"ColorDiffuse": {
|
||||||
|
"a": 0.27451,
|
||||||
|
"b": 1,
|
||||||
|
"g": 1,
|
||||||
|
"r": 1
|
||||||
|
},
|
||||||
|
"CustomMesh": {
|
||||||
|
"CastShadows": true,
|
||||||
|
"ColliderURL": "",
|
||||||
|
"Convex": true,
|
||||||
|
"CustomShader": {
|
||||||
|
"FresnelStrength": 0,
|
||||||
|
"SpecularColor": {
|
||||||
|
"b": 1,
|
||||||
|
"g": 1,
|
||||||
|
"r": 1
|
||||||
|
},
|
||||||
|
"SpecularIntensity": 0,
|
||||||
|
"SpecularSharpness": 2
|
||||||
|
},
|
||||||
|
"DiffuseURL": "http://cloud-3.steamusercontent.com/ugc/2115061845788468343/B7611EC7DCD2008B87D6518EBEFF0AD36EFE5B54/",
|
||||||
|
"MaterialIndex": 3,
|
||||||
|
"MeshURL": "https://raw.githubusercontent.com/RobMayer/TTSLibrary/master/advboxes/tuckbox_h_MSH.obj",
|
||||||
|
"NormalURL": "",
|
||||||
|
"TypeIndex": 0
|
||||||
|
},
|
||||||
|
"Description": "Challenge Scenario",
|
||||||
|
"DragSelectable": true,
|
||||||
|
"GMNotes": "scenarios/challenge_laid_to_rest.json",
|
||||||
|
"GUID": "e2dd57",
|
||||||
|
"Grid": true,
|
||||||
|
"GridProjection": false,
|
||||||
|
"Hands": true,
|
||||||
|
"HideWhenFaceDown": false,
|
||||||
|
"IgnoreFoW": false,
|
||||||
|
"LayoutGroupSortIndex": 0,
|
||||||
|
"Locked": false,
|
||||||
|
"LuaScript": "require(\"core/DownloadBox\")",
|
||||||
|
"LuaScriptState": "",
|
||||||
|
"MeasureMovement": false,
|
||||||
|
"Name": "Custom_Model",
|
||||||
|
"Nickname": "Laid to Rest",
|
||||||
|
"Snap": true,
|
||||||
|
"Sticky": true,
|
||||||
|
"Tooltip": true,
|
||||||
|
"Transform": {
|
||||||
|
"posX": 12.25,
|
||||||
|
"posY": 1.481,
|
||||||
|
"posZ": -4.014,
|
||||||
|
"rotX": 0,
|
||||||
|
"rotY": 270,
|
||||||
|
"rotZ": 0,
|
||||||
|
"scaleX": 2.21,
|
||||||
|
"scaleY": 0.46,
|
||||||
|
"scaleZ": 2.42
|
||||||
|
},
|
||||||
|
"Value": 0,
|
||||||
|
"XmlUI": ""
|
||||||
|
}
|
@ -72,7 +72,7 @@
|
|||||||
"Tooltip": true,
|
"Tooltip": true,
|
||||||
"Transform": {
|
"Transform": {
|
||||||
"posX": 12.25,
|
"posX": 12.25,
|
||||||
"posY": 1.461,
|
"posY": 1.481,
|
||||||
"posZ": -12.014,
|
"posZ": -12.014,
|
||||||
"rotX": 0,
|
"rotX": 0,
|
||||||
"rotY": 270,
|
"rotY": 270,
|
||||||
|
@ -72,7 +72,7 @@
|
|||||||
"Tooltip": true,
|
"Tooltip": true,
|
||||||
"Transform": {
|
"Transform": {
|
||||||
"posX": 12.25,
|
"posX": 12.25,
|
||||||
"posY": 1.459,
|
"posY": 1.481,
|
||||||
"posZ": -20.014,
|
"posZ": -20.014,
|
||||||
"rotX": 0,
|
"rotX": 0,
|
||||||
"rotY": 270,
|
"rotY": 270,
|
||||||
|
45
objects/PlaceholderBoxDummy.a93466.json
Normal file
45
objects/PlaceholderBoxDummy.a93466.json
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"AltLookAngle": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"Autoraise": true,
|
||||||
|
"ColorDiffuse": {
|
||||||
|
"b": 0.82353,
|
||||||
|
"g": 0.20157,
|
||||||
|
"r": 0
|
||||||
|
},
|
||||||
|
"Description": "This dummy is there to hold the up-to-date script file for placeholder boxes to be available for placeholder box spawning.",
|
||||||
|
"DragSelectable": true,
|
||||||
|
"GMNotes": "",
|
||||||
|
"GUID": "a93466",
|
||||||
|
"Grid": true,
|
||||||
|
"GridProjection": false,
|
||||||
|
"Hands": false,
|
||||||
|
"HideWhenFaceDown": false,
|
||||||
|
"IgnoreFoW": false,
|
||||||
|
"LayoutGroupSortIndex": 0,
|
||||||
|
"Locked": true,
|
||||||
|
"LuaScript": "require(\"core/DownloadBox\")",
|
||||||
|
"LuaScriptState": "",
|
||||||
|
"MeasureMovement": false,
|
||||||
|
"Name": "BlockRectangle",
|
||||||
|
"Nickname": "Placeholder Box Dummy",
|
||||||
|
"Snap": true,
|
||||||
|
"Sticky": true,
|
||||||
|
"Tooltip": true,
|
||||||
|
"Transform": {
|
||||||
|
"posX": 78,
|
||||||
|
"posY": 1.645,
|
||||||
|
"posZ": -33,
|
||||||
|
"rotX": 0,
|
||||||
|
"rotY": 0,
|
||||||
|
"rotZ": 0,
|
||||||
|
"scaleX": 1,
|
||||||
|
"scaleY": 1,
|
||||||
|
"scaleZ": 1
|
||||||
|
},
|
||||||
|
"Value": 0,
|
||||||
|
"XmlUI": ""
|
||||||
|
}
|
@ -974,7 +974,7 @@
|
|||||||
"LuaScriptState": "{\"trackedLocations\":[]}",
|
"LuaScriptState": "{\"trackedLocations\":[]}",
|
||||||
"MeasureMovement": false,
|
"MeasureMovement": false,
|
||||||
"Name": "Custom_Token",
|
"Name": "Custom_Token",
|
||||||
"Nickname": "Playarea",
|
"Nickname": "Play Area",
|
||||||
"Snap": true,
|
"Snap": true,
|
||||||
"Sticky": true,
|
"Sticky": true,
|
||||||
"Tags": [
|
"Tags": [
|
||||||
|
@ -343,9 +343,10 @@
|
|||||||
"IgnoreFoW": false,
|
"IgnoreFoW": false,
|
||||||
"LayoutGroupSortIndex": 0,
|
"LayoutGroupSortIndex": 0,
|
||||||
"Locked": true,
|
"Locked": true,
|
||||||
|
"LuaScript": "require(\"playermat/Playmat\")",
|
||||||
"LuaScriptState_path": "Playermat1White.8b081b.luascriptstate",
|
"LuaScriptState_path": "Playermat1White.8b081b.luascriptstate",
|
||||||
"LuaScript_path": "Playermat1White.8b081b.ttslua",
|
|
||||||
"MeasureMovement": false,
|
"MeasureMovement": false,
|
||||||
|
"Memo": "White",
|
||||||
"Name": "Custom_Tile",
|
"Name": "Custom_Tile",
|
||||||
"Nickname": "Playermat 1: White",
|
"Nickname": "Playermat 1: White",
|
||||||
"Snap": true,
|
"Snap": true,
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
---------------------------------------------------------
|
|
||||||
-- specific setup (different for each playmat)
|
|
||||||
---------------------------------------------------------
|
|
||||||
|
|
||||||
TRASHCAN_GUID = "147e80"
|
|
||||||
STAT_TRACKER_GUID = "e598c2"
|
|
||||||
RESOURCE_COUNTER_GUID = "4406f0"
|
|
||||||
CLUE_COUNTER_GUID = "d86b7c"
|
|
||||||
CLUE_CLICKER_GUID = "db85d6"
|
|
||||||
|
|
||||||
require("playermat/Playmat")
|
|
@ -343,9 +343,10 @@
|
|||||||
"IgnoreFoW": false,
|
"IgnoreFoW": false,
|
||||||
"LayoutGroupSortIndex": 0,
|
"LayoutGroupSortIndex": 0,
|
||||||
"Locked": true,
|
"Locked": true,
|
||||||
|
"LuaScript": "require(\"playermat/Playmat\")",
|
||||||
"LuaScriptState_path": "Playermat2Orange.bd0ff4.luascriptstate",
|
"LuaScriptState_path": "Playermat2Orange.bd0ff4.luascriptstate",
|
||||||
"LuaScript_path": "Playermat2Orange.bd0ff4.ttslua",
|
|
||||||
"MeasureMovement": false,
|
"MeasureMovement": false,
|
||||||
|
"Memo": "Orange",
|
||||||
"Name": "Custom_Tile",
|
"Name": "Custom_Tile",
|
||||||
"Nickname": "Playermat 2: Orange",
|
"Nickname": "Playermat 2: Orange",
|
||||||
"Snap": true,
|
"Snap": true,
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
---------------------------------------------------------
|
|
||||||
-- specific setup (different for each playmat)
|
|
||||||
---------------------------------------------------------
|
|
||||||
|
|
||||||
TRASHCAN_GUID = "f7b6c8"
|
|
||||||
STAT_TRACKER_GUID = "b4a5f7"
|
|
||||||
RESOURCE_COUNTER_GUID = "816d84"
|
|
||||||
CLUE_COUNTER_GUID = "1769ed"
|
|
||||||
CLUE_CLICKER_GUID = "3f22e5"
|
|
||||||
|
|
||||||
require("playermat/Playmat")
|
|
@ -343,9 +343,10 @@
|
|||||||
"IgnoreFoW": false,
|
"IgnoreFoW": false,
|
||||||
"LayoutGroupSortIndex": 0,
|
"LayoutGroupSortIndex": 0,
|
||||||
"Locked": true,
|
"Locked": true,
|
||||||
|
"LuaScript": "require(\"playermat/Playmat\")",
|
||||||
"LuaScriptState_path": "Playermat3Green.383d8b.luascriptstate",
|
"LuaScriptState_path": "Playermat3Green.383d8b.luascriptstate",
|
||||||
"LuaScript_path": "Playermat3Green.383d8b.ttslua",
|
|
||||||
"MeasureMovement": false,
|
"MeasureMovement": false,
|
||||||
|
"Memo": "Green",
|
||||||
"Name": "Custom_Tile",
|
"Name": "Custom_Tile",
|
||||||
"Nickname": "Playermat 3: Green",
|
"Nickname": "Playermat 3: Green",
|
||||||
"Snap": true,
|
"Snap": true,
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
---------------------------------------------------------
|
|
||||||
-- specific setup (different for each playmat)
|
|
||||||
---------------------------------------------------------
|
|
||||||
|
|
||||||
TRASHCAN_GUID = "5f896a"
|
|
||||||
STAT_TRACKER_GUID = "af7ed7"
|
|
||||||
RESOURCE_COUNTER_GUID = "cd15ac"
|
|
||||||
CLUE_COUNTER_GUID = "032300"
|
|
||||||
CLUE_CLICKER_GUID = "891403"
|
|
||||||
|
|
||||||
require("playermat/Playmat")
|
|
@ -343,9 +343,10 @@
|
|||||||
"IgnoreFoW": false,
|
"IgnoreFoW": false,
|
||||||
"LayoutGroupSortIndex": 0,
|
"LayoutGroupSortIndex": 0,
|
||||||
"Locked": true,
|
"Locked": true,
|
||||||
|
"LuaScript": "require(\"playermat/Playmat\")",
|
||||||
"LuaScriptState_path": "Playermat4Red.0840d5.luascriptstate",
|
"LuaScriptState_path": "Playermat4Red.0840d5.luascriptstate",
|
||||||
"LuaScript_path": "Playermat4Red.0840d5.ttslua",
|
|
||||||
"MeasureMovement": false,
|
"MeasureMovement": false,
|
||||||
|
"Memo": "Red",
|
||||||
"Name": "Custom_Tile",
|
"Name": "Custom_Tile",
|
||||||
"Nickname": "Playermat 4: Red",
|
"Nickname": "Playermat 4: Red",
|
||||||
"Snap": true,
|
"Snap": true,
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
---------------------------------------------------------
|
|
||||||
-- specific setup (different for each playmat)
|
|
||||||
---------------------------------------------------------
|
|
||||||
|
|
||||||
TRASHCAN_GUID = "4b8594"
|
|
||||||
STAT_TRACKER_GUID = "e74881"
|
|
||||||
RESOURCE_COUNTER_GUID = "a4b60d"
|
|
||||||
CLUE_COUNTER_GUID = "37be78"
|
|
||||||
CLUE_CLICKER_GUID = "4111de"
|
|
||||||
|
|
||||||
require("playermat/Playmat")
|
|
@ -14,7 +14,7 @@
|
|||||||
"PDFPage": 0,
|
"PDFPage": 0,
|
||||||
"PDFPageOffset": 0,
|
"PDFPageOffset": 0,
|
||||||
"PDFPassword": "",
|
"PDFPassword": "",
|
||||||
"PDFUrl": "https://images-cdn.fantasyflightgames.com/filer_public/c4/b0/c4b0d66c-d79e-411b-bdb5-b5d8c457d4bc/ahc01_rules_reference_web.pdf"
|
"PDFUrl": "http://cloud-3.steamusercontent.com/ugc/2115061845793806189/6FC67F9AF9224452E2D8F25E63B88D702B21B0DC/"
|
||||||
},
|
},
|
||||||
"Description": "",
|
"Description": "",
|
||||||
"DragSelectable": true,
|
"DragSelectable": true,
|
||||||
|
@ -35,9 +35,6 @@
|
|||||||
"Nickname": "SoundCube",
|
"Nickname": "SoundCube",
|
||||||
"Snap": true,
|
"Snap": true,
|
||||||
"Sticky": true,
|
"Sticky": true,
|
||||||
"Tags": [
|
|
||||||
"SoundCube"
|
|
||||||
],
|
|
||||||
"Tooltip": true,
|
"Tooltip": true,
|
||||||
"Transform": {
|
"Transform": {
|
||||||
"posX": 78,
|
"posX": 78,
|
||||||
|
@ -40,9 +40,6 @@
|
|||||||
"Nickname": "Token Arranger",
|
"Nickname": "Token Arranger",
|
||||||
"Snap": true,
|
"Snap": true,
|
||||||
"Sticky": true,
|
"Sticky": true,
|
||||||
"Tags": [
|
|
||||||
"TokenArranger"
|
|
||||||
],
|
|
||||||
"Tooltip": true,
|
"Tooltip": true,
|
||||||
"Transform": {
|
"Transform": {
|
||||||
"posX": -42.3,
|
"posX": -42.3,
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
local blessCurseApi = require("chaosbag/BlessCurseManagerApi")
|
local blessCurseApi = require("chaosbag/BlessCurseManagerApi")
|
||||||
local chaosBagApi = require("chaosbag/ChaosBagApi")
|
local chaosBagApi = require("chaosbag/ChaosBagApi")
|
||||||
local deckImporterApi = require("arkhamdb/DeckImporterApi")
|
local deckImporterApi = require("arkhamdb/DeckImporterApi")
|
||||||
local optionPanelApi = require("core/OptionPanelApi")
|
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||||
local playAreaApi = require("core/PlayAreaApi")
|
local optionPanelApi = require("core/OptionPanelApi")
|
||||||
|
local playAreaApi = require("core/PlayAreaApi")
|
||||||
|
local playmatApi = require("playermat/PlaymatApi")
|
||||||
|
|
||||||
local campaignTokenData = {
|
local campaignTokenData = {
|
||||||
GUID = "51b1c9",
|
|
||||||
Name = "Custom_Model",
|
Name = "Custom_Model",
|
||||||
Transform = {
|
Transform = {
|
||||||
posX = -21.25,
|
posX = -21.25,
|
||||||
@ -18,9 +19,7 @@ local campaignTokenData = {
|
|||||||
scaleY = 2,
|
scaleY = 2,
|
||||||
scaleZ = 2
|
scaleZ = 2
|
||||||
},
|
},
|
||||||
Nickname = "Arkham Coin",
|
|
||||||
Description = "SCED Importer Token",
|
Description = "SCED Importer Token",
|
||||||
GMNotes = "",
|
|
||||||
Tags = {
|
Tags = {
|
||||||
"ImporterToken"
|
"ImporterToken"
|
||||||
},
|
},
|
||||||
@ -33,56 +32,48 @@ local campaignTokenData = {
|
|||||||
MaterialIndex = 2,
|
MaterialIndex = 2,
|
||||||
TypeIndex = 0,
|
TypeIndex = 0,
|
||||||
CustomShader = {
|
CustomShader = {
|
||||||
SpecularColor = {
|
SpecularColor = {
|
||||||
r = 0.7222887,
|
r = 0.7222887,
|
||||||
g = 0.507659256,
|
g = 0.507659256,
|
||||||
b = 0.339915335
|
b = 0.339915335
|
||||||
},
|
},
|
||||||
SpecularIntensity = 0.4,
|
SpecularIntensity = 0.4,
|
||||||
SpecularSharpness = 7.0,
|
SpecularSharpness = 7.0,
|
||||||
FresnelStrength = 0.0
|
FresnelStrength = 0.0
|
||||||
},
|
},
|
||||||
CastShadows = true
|
CastShadows = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
local COLORS = { "White", "Orange", "Green", "Red" }
|
||||||
|
|
||||||
-- counter GUIDS (4x damage and 4x horror)
|
function onLoad()
|
||||||
local DAMAGE_HORROR_GUIDS = {
|
|
||||||
"eb08d6"; "e64eec"; "1f5a0a"; "591a45";
|
|
||||||
"468e88"; "0257d9"; "7b5729"; "beb964";
|
|
||||||
}
|
|
||||||
|
|
||||||
local TOUR_GUID = "0e5aa8"
|
|
||||||
local campaignBoxGUID
|
|
||||||
|
|
||||||
function onLoad(save_state)
|
|
||||||
campaignBoxGUID = ""
|
|
||||||
|
|
||||||
self.createButton({
|
self.createButton({
|
||||||
click_function = "findCampaignFromToken",
|
click_function = "findCampaignFromToken",
|
||||||
function_owner = self,
|
function_owner = self,
|
||||||
label = "Import",
|
label = "Import",
|
||||||
tooltip = "Load in a campaign save from a token!\n\n(Token can be anywhere on the table, but ensure there is only 1!)",
|
tooltip = "Load in a campaign save from a token!\n\n(Token can be anywhere on the table, but ensure there is only 1!)",
|
||||||
position = {x=-1, y=0.2, z=0},
|
position = { x = -1, y = 0.2, z = 0 },
|
||||||
font_size = 400,
|
font_size = 400,
|
||||||
width = 1400,
|
width = 1400,
|
||||||
height = 600,
|
height = 600,
|
||||||
scale = {0.5, 1, 0.5},
|
scale = { 0.5, 1, 0.5 },
|
||||||
})
|
})
|
||||||
self.createButton({
|
self.createButton({
|
||||||
click_function = "createCampaignToken",
|
click_function = "createCampaignToken",
|
||||||
function_owner = self,
|
function_owner = self,
|
||||||
label = "Export",
|
label = "Export",
|
||||||
tooltip = "Create a campaign save token!\n\n(Ensure all chaos tokens have been unsealed!)",
|
tooltip = "Create a campaign save token!\n\n(Ensure all chaos tokens have been unsealed!)",
|
||||||
position = {x=1, y=0.2, z=0},
|
position = { x = 1, y = 0.2, z = 0 },
|
||||||
font_size = 400,
|
font_size = 400,
|
||||||
width = 1400,
|
width = 1400,
|
||||||
height = 600,
|
height = 600,
|
||||||
scale = {0.5, 1, 0.5},
|
scale = { 0.5, 1, 0.5 },
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- The main import functions. Due to timing concerns, has to be split up into several separate methods to allow for Wait conditions
|
---------------------------------------------------------
|
||||||
|
-- main import functions (split up to allow for Wait conditions)
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
-- Identifies import token, determines campaign box and downloads it (if needed)
|
-- Identifies import token, determines campaign box and downloads it (if needed)
|
||||||
function findCampaignFromToken(_, _, _)
|
function findCampaignFromToken(_, _, _)
|
||||||
@ -91,11 +82,13 @@ function findCampaignFromToken(_, _, _)
|
|||||||
if #coinObjects == 0 then
|
if #coinObjects == 0 then
|
||||||
broadcastToAll("Could not find importer token", Color.Red)
|
broadcastToAll("Could not find importer token", Color.Red)
|
||||||
elseif #coinObjects > 1 then
|
elseif #coinObjects > 1 then
|
||||||
broadcastToAll("More than 1 importer token found. Please delete all but 1 importer token", Color.Yellow)
|
broadcastToAll("More than 1 importer token found. Please delete all but 1 importer token", Color.Yellow)
|
||||||
else
|
else
|
||||||
coin = coinObjects[1]
|
coin = coinObjects[1]
|
||||||
|
|
||||||
local importData = JSON.decode(coin.getGMNotes())
|
local importData = JSON.decode(coin.getGMNotes())
|
||||||
campaignBoxGUID = importData["box"]
|
campaignBoxGUID = importData["box"]
|
||||||
|
|
||||||
local campaignBox = getObjectFromGUID(campaignBoxGUID)
|
local campaignBox = getObjectFromGUID(campaignBoxGUID)
|
||||||
if campaignBox.type == "Generic" then
|
if campaignBox.type == "Generic" then
|
||||||
campaignBox.call("buttonClick_download")
|
campaignBox.call("buttonClick_download")
|
||||||
@ -110,24 +103,24 @@ function findCampaignFromToken(_, _, _)
|
|||||||
end,
|
end,
|
||||||
function()
|
function()
|
||||||
local obj = getObjectFromGUID(campaignBoxGUID)
|
local obj = getObjectFromGUID(campaignBoxGUID)
|
||||||
if obj == nil then
|
if obj == nil then
|
||||||
return false
|
return false
|
||||||
else
|
else
|
||||||
return obj.type == "Bag" and obj.getLuaScript() ~= ""
|
return obj.type == "Bag" and obj.getLuaScript() ~= ""
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
2,
|
2,
|
||||||
function() broadcastToAll("Error loading campaign box") end
|
function() broadcastToAll("Error loading campaign box") end
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- After box has been downloaded, places content on table
|
-- After box has been downloaded, places content on table
|
||||||
function placeCampaignFromToken(importData)
|
function placeCampaignFromToken(importData)
|
||||||
getObjectFromGUID(campaignBoxGUID).call("buttonClick_place")
|
getObjectFromGUID(importData["box"]).call("buttonClick_place")
|
||||||
Wait.condition(
|
Wait.condition(
|
||||||
function() createCampaignFromToken(importData) end,
|
function() createCampaignFromToken(importData) end,
|
||||||
function() return findCampaignLog() ~= nil end,
|
function() return findUniqueObjectWithTag("CampaignLog") ~= nil end,
|
||||||
2,
|
2,
|
||||||
function() broadcastToAll("Error placing campaign box") end
|
function() broadcastToAll("Error placing campaign box") end
|
||||||
)
|
)
|
||||||
@ -135,82 +128,86 @@ end
|
|||||||
|
|
||||||
-- After content is placed on table, conducts all the other import operations
|
-- After content is placed on table, conducts all the other import operations
|
||||||
function createCampaignFromToken(importData)
|
function createCampaignFromToken(importData)
|
||||||
findCampaignLog().destruct()
|
-- destroy existing campaign log and load saved campaign log
|
||||||
--create campaign log
|
findUniqueObjectWithTag("CampaignLog").destruct()
|
||||||
spawnObjectData({data = importData["log"]})
|
spawnObjectData({ data = importData["log"] })
|
||||||
--create chaos bag
|
|
||||||
chaosBagApi.setChaosBagState(importData["bag"])
|
chaosBagApi.setChaosBagState(importData["bag"])
|
||||||
--populate trauma values
|
|
||||||
|
-- populate trauma values
|
||||||
if importData["trauma"] then
|
if importData["trauma"] then
|
||||||
updateCounters(importData["trauma"])
|
setTrauma(importData["trauma"])
|
||||||
end
|
end
|
||||||
--populate ArkhamDB deck IDs
|
|
||||||
|
-- populate ArkhamDB deck IDs
|
||||||
if importData["decks"] then
|
if importData["decks"] then
|
||||||
deckImporterApi.setUiState(importData["decks"])
|
deckImporterApi.setUiState(importData["decks"])
|
||||||
end
|
end
|
||||||
--set investigator count
|
|
||||||
playAreaApi.setInvestigatorCount(importData["clueCount"])
|
playAreaApi.setInvestigatorCount(importData["clueCount"])
|
||||||
--set campaign guide page
|
|
||||||
local guide = findCampaignGuide()
|
-- set campaign guide page
|
||||||
|
local guide = findUniqueObjectWithTag("CampaignGuide")
|
||||||
if guide then
|
if guide then
|
||||||
Wait.condition(
|
Wait.condition(
|
||||||
-- Called after the condition function returns true
|
-- Called after the condition function returns true
|
||||||
function()
|
function() log("Campaign Guide import successful!") end,
|
||||||
log("Campaign Guide import successful!")
|
-- Condition function that is called continiously until returs true or timeout is reached
|
||||||
end,
|
function() return guide.Book.setPage(importData["guide"]) end,
|
||||||
-- Condition function that is called continiously until returs true or timeout is reached
|
|
||||||
function()
|
|
||||||
guide.Book.setPage(importData["guide"])
|
|
||||||
return guide.Book.getPage() == importData["guide"]
|
|
||||||
end,
|
|
||||||
-- Amount of time in seconds until the Wait times out
|
-- Amount of time in seconds until the Wait times out
|
||||||
1,
|
1,
|
||||||
-- Called if the Wait times out
|
-- Called if the Wait times out
|
||||||
function()
|
function() log("Campaign Guide import failed!") end
|
||||||
log("Campaign Guide import failed!")
|
|
||||||
end
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
Wait.time(
|
|
||||||
function() optionPanelApi.loadSettings(importData["options"]) end,
|
Wait.time(function() optionPanelApi.loadSettings(importData["options"]) end, 0.5)
|
||||||
0.5
|
|
||||||
)
|
-- destroy Tour Starter token
|
||||||
getObjectFromGUID(TOUR_GUID).destruct()
|
local tourStarter = guidReferenceApi.getObjectByOwnerAndType("Mythos", "TourStarter")
|
||||||
|
tourStarter.destruct()
|
||||||
|
|
||||||
|
-- restore PlayArea image
|
||||||
playAreaApi.updateSurface(importData["playmat"])
|
playAreaApi.updateSurface(importData["playmat"])
|
||||||
|
|
||||||
broadcastToAll("Campaign successfully imported!", Color.Green)
|
broadcastToAll("Campaign successfully imported!", Color.Green)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Creates a campaign token with save data encoded into GM Notes based on the current state of the table
|
-- Creates a campaign token with save data encoded into GM Notes based on the current state of the table
|
||||||
function createCampaignToken(_, playerColor, _)
|
function createCampaignToken(_, playerColor, _)
|
||||||
-- clean up chaos tokens
|
-- clean up chaos tokens
|
||||||
blessCurseApi.removeAll(playerColor)
|
blessCurseApi.removeAll(playerColor)
|
||||||
chaosBagApi.releaseAllSealedTokens(playerColor)
|
chaosBagApi.releaseAllSealedTokens(playerColor)
|
||||||
|
|
||||||
local campaignBoxGUID = ""
|
|
||||||
-- find active campaign
|
-- find active campaign
|
||||||
|
local campaignBox
|
||||||
for _, obj in ipairs(getObjectsWithTag("CampaignBox")) do
|
for _, obj in ipairs(getObjectsWithTag("CampaignBox")) do
|
||||||
if obj.type == "Bag" and #obj.getObjects() == 0 then
|
if obj.type == "Bag" and #obj.getObjects() == 0 then
|
||||||
if campaignBoxGUID ~= "" then
|
if not campaignBox then
|
||||||
|
campaignBox = obj
|
||||||
|
else
|
||||||
broadcastToAll("Multiple empty campaign box detected; delete all but one.", Color.Red)
|
broadcastToAll("Multiple empty campaign box detected; delete all but one.", Color.Red)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
campaignBoxGUID = obj.getGUID()
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if campaignBoxGUID == "" then
|
if not campaignBox then
|
||||||
broadcastToAll("Campaign box with all placed objects not found!", Color.Red)
|
broadcastToAll("Campaign box with all placed objects not found!", Color.Red)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local campaignLog = findCampaignLog()
|
|
||||||
|
local campaignLog = findUniqueObjectWithTag("CampaignLog")
|
||||||
if campaignLog == nil then
|
if campaignLog == nil then
|
||||||
broadcastToAll("Campaign log not found!", Color.Red)
|
broadcastToAll("Campaign log not found!", Color.Red)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local traumaValues = nil
|
|
||||||
|
local traumaValues = {
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0
|
||||||
|
}
|
||||||
local counterData = campaignLog.getVar("ref_buttonData")
|
local counterData = campaignLog.getVar("ref_buttonData")
|
||||||
if counterData ~= nil then
|
if counterData ~= nil then
|
||||||
traumaValues = {}
|
|
||||||
printToAll("Trauma values found in campaign log!", "Green")
|
printToAll("Trauma values found in campaign log!", "Green")
|
||||||
for i = 1, 10, 3 do
|
for i = 1, 10, 3 do
|
||||||
traumaValues[1 + (i - 1) / 3] = counterData.counter[i].value
|
traumaValues[1 + (i - 1) / 3] = counterData.counter[i].value
|
||||||
@ -220,78 +217,49 @@ function createCampaignToken(_, playerColor, _)
|
|||||||
printToAll("Trauma values could not be found in campaign log!", "Yellow")
|
printToAll("Trauma values could not be found in campaign log!", "Yellow")
|
||||||
printToAll("Default values for health and sanity loaded.", "Yellow")
|
printToAll("Default values for health and sanity loaded.", "Yellow")
|
||||||
end
|
end
|
||||||
local campaignGuide = findCampaignGuide()
|
|
||||||
|
local campaignGuide = findUniqueObjectWithTag("CampaignGuide")
|
||||||
if campaignGuide == nil then
|
if campaignGuide == nil then
|
||||||
broadcastToAll("Campaign guide not found!", Color.Red)
|
broadcastToAll("Campaign guide not found!", Color.Red)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local campaignGuidePage = campaignGuide.Book.getPage()
|
|
||||||
local campaignData = {
|
local campaignData = {
|
||||||
box = campaignBoxGUID,
|
box = campaignBox.getGUID(),
|
||||||
log = campaignLog.getData(),
|
log = campaignLog.getData(),
|
||||||
bag = chaosBagApi.getChaosBagState(),
|
bag = chaosBagApi.getChaosBagState(),
|
||||||
trauma = traumaValues,
|
trauma = traumaValues,
|
||||||
decks = deckImporterApi.getUiState(),
|
decks = deckImporterApi.getUiState(),
|
||||||
clueCount = playAreaApi.getInvestigatorCount(),
|
clueCount = playAreaApi.getInvestigatorCount(),
|
||||||
guide = campaignGuidePage,
|
guide = campaignGuide.Book.getPage(),
|
||||||
options = optionPanelApi.getOptions(),
|
options = optionPanelApi.getOptions(),
|
||||||
playmat = playAreaApi.getSurface()
|
playmat = playAreaApi.getSurface()
|
||||||
}
|
}
|
||||||
campaignTokenData.GMNotes = JSON.encode(campaignData)
|
campaignTokenData.GMNotes = JSON.encode(campaignData)
|
||||||
campaignTokenData.Nickname = os.date("%b %d ") .. getObjectFromGUID(campaignBoxGUID).getName() .. " Save"
|
campaignTokenData.Nickname = os.date("%b %d ") .. campaignBox.getName() .. " Save"
|
||||||
spawnObjectData({
|
spawnObjectData({ data = campaignTokenData })
|
||||||
data = campaignTokenData,
|
|
||||||
position = {-21.25, 1.68, 55.59}
|
|
||||||
})
|
|
||||||
broadcastToAll("Campaign successfully exported! Save coin object to import on a fresh save", Color.Green)
|
broadcastToAll("Campaign successfully exported! Save coin object to import on a fresh save", Color.Green)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
-- helper functions
|
-- helper functions
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
function findCampaignLog()
|
function findUniqueObjectWithTag(tag)
|
||||||
local campaignLog = getObjectsWithTag("CampaignLog")
|
local objects = getObjectsWithTag(tag)
|
||||||
if campaignLog then
|
if not objects then return end
|
||||||
if #campaignLog == 1 then
|
|
||||||
return campaignLog[1]
|
if #objects == 1 then
|
||||||
else
|
return objects[1]
|
||||||
broadcastToAll("More than 1 campaign log detected; delete all but one.", Color.Red)
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
|
broadcastToAll("More than 1 " .. tag .. " detected; delete all but one.", Color.Red)
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function findCampaignGuide()
|
function setTrauma(trauma)
|
||||||
local campaignGuide = getObjectsWithTag("CampaignGuide")
|
for i = 1, 4 do
|
||||||
if campaignGuide then
|
playmatApi.updateCounter(COLORS[i], "DamageCounter", trauma[i])
|
||||||
if #campaignGuide == 1 then
|
playmatApi.updateCounter(COLORS[i], "HorrorCounter", trauma[i + 4])
|
||||||
return campaignGuide[1]
|
|
||||||
else
|
|
||||||
broadcastToAll("More than 1 campaign guide detected; delete all but one.", Color.Red)
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
else
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function updateCounters(tableOfNewValues)
|
|
||||||
if tonumber(tableOfNewValues) then
|
|
||||||
local value = tableOfNewValues
|
|
||||||
tableOfNewValues = {}
|
|
||||||
for i = 1, #DAMAGE_HORROR_GUIDS do
|
|
||||||
table.insert(tableOfNewValues, value)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
for i, guid in ipairs(DAMAGE_HORROR_GUIDS) do
|
|
||||||
local TOKEN = getObjectFromGUID(guid)
|
|
||||||
if TOKEN ~= nil then
|
|
||||||
TOKEN.call("updateVal", tableOfNewValues[i])
|
|
||||||
else
|
|
||||||
printToAll(": No. " .. i .. " could not be found.", "Yellow")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -3,79 +3,24 @@
|
|||||||
- puts everything on playmats and hands into respective trashcans
|
- 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 blessCurseManagerApi = require("chaosbag/BlessCurseManagerApi")
|
local blessCurseManagerApi = require("chaosbag/BlessCurseManagerApi")
|
||||||
local chaosBagApi = require("chaosbag/ChaosBagApi")
|
local chaosBagApi = require("chaosbag/ChaosBagApi")
|
||||||
local playAreaApi = require("core/PlayAreaApi")
|
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||||
local playmatApi = require("playermat/PlaymatApi")
|
local playAreaApi = require("core/PlayAreaApi")
|
||||||
local soundCubeApi = require("core/SoundCubeApi")
|
local playmatApi = require("playermat/PlaymatApi")
|
||||||
local tokenSpawnTrackerApi = require("core/token/TokenSpawnTrackerApi")
|
local soundCubeApi = require("core/SoundCubeApi")
|
||||||
|
local tokenSpawnTrackerApi = require("core/token/TokenSpawnTrackerApi")
|
||||||
-- these objects will be ignored
|
|
||||||
local IGNORE_GUIDS = {
|
|
||||||
-- big playmat, change image panel and investigator counter
|
|
||||||
"b7b45b", "f182ee", "721ba2",
|
|
||||||
-- bless/curse manager
|
|
||||||
"afa06b", "bd0253", "5933fb",
|
|
||||||
-- stuff on agenda/act playmat
|
|
||||||
"85c4c6", "4a3aa4", "fea079", "b015d8", "11e0cf", "9f334f", "70b9f6", "0a5a29",
|
|
||||||
-- doom/location token bag
|
|
||||||
"47ffc3", "170f10",
|
|
||||||
-- table
|
|
||||||
"4ee1f2"
|
|
||||||
}
|
|
||||||
|
|
||||||
-- objects with this tag will be ignored
|
-- objects with this tag will be ignored
|
||||||
local IGNORE_TAG = "CleanUpHelper_ignore"
|
local IGNORE_TAG = "CleanUpHelper_ignore"
|
||||||
|
|
||||||
-- colors and order for following tables
|
-- colors and order for following tables
|
||||||
local COLORS = { "White", "Orange", "Green", "Red", "Agenda" }
|
local COLORS = { "White", "Orange", "Green", "Red", "Mythos" }
|
||||||
|
|
||||||
-- counter GUIDS (4x damage and 4x horror)
|
|
||||||
local DAMAGE_HORROR_GUIDS = {
|
|
||||||
"eb08d6", "e64eec", "1f5a0a", "591a45",
|
|
||||||
"468e88", "0257d9", "7b5729", "beb964",
|
|
||||||
}
|
|
||||||
|
|
||||||
local campaignLog
|
local campaignLog
|
||||||
local RESET_VALUES = {}
|
local RESET_VALUES = {}
|
||||||
|
local loadingFailedBefore = false
|
||||||
-- GUIDS of objects (in order of ownership relating to 'COLORS')
|
|
||||||
local PLAYERMAT_GUIDS = { "8b081b", "bd0ff4", "383d8b", "0840d5" }
|
|
||||||
local RESOURCE_GUIDS = { "4406f0", "816d84", "cd15ac", "a4b60d" }
|
|
||||||
local TRACKER_GUIDS = { "e598c2", "b4a5f7", "af7ed7", "e74881" }
|
|
||||||
local CLUE_GUIDS = { "d86b7c", "1769ed", "032300", "37be78" }
|
|
||||||
local CLUE_CLICKER_GUIDS = { "db85d6", "3f22e5", "891403", "4111de" }
|
|
||||||
local TRASHCAN_GUIDS = { "147e80", "f7b6c8", "5f896a", "4b8594", "70b9f6" }
|
|
||||||
|
|
||||||
-- values for physics.cast (4 entries for player zones, 5th entry for agenda/act deck, 6th for campaign log)
|
|
||||||
local PHYSICS_POSITION = {
|
|
||||||
{ -54.5, 2, 21 },
|
|
||||||
{ -54.5, 2, -21 },
|
|
||||||
{ -27.0, 2, 26 },
|
|
||||||
{ -27.0, 2, -26 },
|
|
||||||
{ -02.0, 2, 10 },
|
|
||||||
{ -00.0, 2, -27 }
|
|
||||||
}
|
|
||||||
|
|
||||||
local PHYSICS_ROTATION = {
|
|
||||||
270,
|
|
||||||
270,
|
|
||||||
0,
|
|
||||||
180,
|
|
||||||
270,
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
local PHYSICS_SCALE = {
|
|
||||||
{ 36.6, 1, 14.5 },
|
|
||||||
{ 36.6, 1, 14.5 },
|
|
||||||
{ 34.0, 1, 14.5 },
|
|
||||||
{ 34.0, 1, 14.5 },
|
|
||||||
{ 55.0, 1, 13.5 },
|
|
||||||
{ 05.0, 1, 05.0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
local optionsVisible = false
|
local optionsVisible = false
|
||||||
|
|
||||||
local options = {}
|
local options = {}
|
||||||
options["importTrauma"] = true
|
options["importTrauma"] = true
|
||||||
options["tidyPlayermats"] = true
|
options["tidyPlayermats"] = true
|
||||||
@ -84,7 +29,6 @@ options["removeDrawnLines"] = false
|
|||||||
local buttonParameters = {}
|
local buttonParameters = {}
|
||||||
buttonParameters.function_owner = self
|
buttonParameters.function_owner = self
|
||||||
|
|
||||||
local loadingFailedBefore = false
|
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
-- option loading and GUI setup
|
-- option loading and GUI setup
|
||||||
@ -131,14 +75,6 @@ function onLoad(savedData)
|
|||||||
buttonParameters.position.z = 1.1
|
buttonParameters.position.z = 1.1
|
||||||
buttonParameters.width = 1550
|
buttonParameters.width = 1550
|
||||||
self.createButton(buttonParameters)
|
self.createButton(buttonParameters)
|
||||||
|
|
||||||
-- create single table for ignoring
|
|
||||||
for _, v in ipairs(CLUE_GUIDS) do table.insert(IGNORE_GUIDS, v) end
|
|
||||||
for _, v in ipairs(CLUE_CLICKER_GUIDS) do table.insert(IGNORE_GUIDS, v) end
|
|
||||||
for _, v in ipairs(RESOURCE_GUIDS) do table.insert(IGNORE_GUIDS, v) end
|
|
||||||
for _, v in ipairs(TRASHCAN_GUIDS) do table.insert(IGNORE_GUIDS, v) end
|
|
||||||
for _, v in ipairs(PLAYERMAT_GUIDS) do table.insert(IGNORE_GUIDS, v) end
|
|
||||||
for _, v in ipairs(DAMAGE_HORROR_GUIDS) do table.insert(IGNORE_GUIDS, v) end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
@ -178,13 +114,8 @@ function cleanUp(_, color)
|
|||||||
getTrauma()
|
getTrauma()
|
||||||
|
|
||||||
-- delay to account for potential state change
|
-- delay to account for potential state change
|
||||||
Wait.time(function()
|
Wait.time(updateCounters, 0.2)
|
||||||
updateCounters(RESOURCE_GUIDS, 5, "Resource")
|
|
||||||
updateCounters(CLUE_CLICKER_GUIDS, 0, "Clue clicker")
|
|
||||||
updateCounters(DAMAGE_HORROR_GUIDS, RESET_VALUES, "Damage / Horror")
|
|
||||||
end, 0.2)
|
|
||||||
|
|
||||||
resetSkillTrackers()
|
|
||||||
resetDoomCounter()
|
resetDoomCounter()
|
||||||
blessCurseManagerApi.removeAll(color)
|
blessCurseManagerApi.removeAll(color)
|
||||||
removeLines()
|
removeLines()
|
||||||
@ -201,39 +132,20 @@ end
|
|||||||
-- modular functions, called by other functions
|
-- modular functions, called by other functions
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
function updateCounters(tableOfGUIDs, newValues, info)
|
function updateCounters()
|
||||||
-- instead of a table, this will be used if just a single value is provided
|
playmatApi.updateCounter("All", "ResourceCounter" , 5)
|
||||||
local singleValue = tonumber(newValues)
|
playmatApi.updateCounter("All", "ClickableClueCounter" , 0)
|
||||||
|
playmatApi.resetSkillTracker("All")
|
||||||
|
|
||||||
for i, guid in ipairs(tableOfGUIDs) do
|
for i = 1, 4 do
|
||||||
local TOKEN = getObjectFromGUID(guid)
|
playmatApi.updateCounter(COLORS[i], "DamageCounter", RESET_VALUES.Damage[i])
|
||||||
local newValue = singleValue or newValues[i]
|
playmatApi.updateCounter(COLORS[i], "HorrorCounter", RESET_VALUES.Horror[i])
|
||||||
|
|
||||||
if TOKEN ~= nil then
|
|
||||||
TOKEN.call("updateVal", newValue)
|
|
||||||
else
|
|
||||||
printToAll(info .. ": No. " .. i .. " could not be found.", "Yellow")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- set investigator skill trackers to "1, 1, 1, 1"
|
|
||||||
function resetSkillTrackers()
|
|
||||||
for i, guid in ipairs(TRACKER_GUIDS) do
|
|
||||||
local obj = getObjectFromGUID(guid)
|
|
||||||
|
|
||||||
if obj ~= nil then
|
|
||||||
obj.call("updateStats", { 1, 1, 1, 1 })
|
|
||||||
else
|
|
||||||
printToAll("Skill tracker for " .. COLORS[i] .. " playmat could not be found.", "Yellow")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- reset doom on agenda
|
-- reset doom on agenda
|
||||||
function resetDoomCounter()
|
function resetDoomCounter()
|
||||||
local doomCounter = getObjectFromGUID("85c4c6")
|
local doomCounter = guidReferenceApi.getObjectByOwnerAndType("Mythos", "DoomCounter")
|
||||||
|
|
||||||
if doomCounter ~= nil then
|
if doomCounter ~= nil then
|
||||||
doomCounter.call("updateVal")
|
doomCounter.call("updateVal")
|
||||||
else
|
else
|
||||||
@ -241,19 +153,19 @@ function resetDoomCounter()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- gets the GUID of a custom data helper (if present) and adds it to the ignore list
|
-- adds the ignore tag to the custom data helper
|
||||||
function ignoreCustomDataHelper()
|
function ignoreCustomDataHelper()
|
||||||
local customDataHelper = playAreaApi.getCustomDataHelper()
|
local customDataHelper = playAreaApi.getCustomDataHelper()
|
||||||
if customDataHelper then
|
if customDataHelper then
|
||||||
table.insert(IGNORE_GUIDS, customDataHelper.getGUID())
|
customDataHelper.addTag(IGNORE_TAG)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- read values for trauma from campaign log if enabled
|
-- read values for trauma from campaign log if enabled
|
||||||
function getTrauma()
|
function getTrauma()
|
||||||
RESET_VALUES = {
|
RESET_VALUES = {
|
||||||
0, 0, 0, 0,
|
Damage = { 0, 0, 0, 0 },
|
||||||
0, 0, 0, 0
|
Horror = { 0, 0, 0, 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
-- stop here if trauma import is disabled
|
-- stop here if trauma import is disabled
|
||||||
@ -263,13 +175,12 @@ function getTrauma()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- get campaign log
|
-- get campaign log
|
||||||
campaignLog = findObjects(6)[1]
|
campaignLog = getObjectsWithTag("CampaignLog")[1]
|
||||||
if campaignLog == nil then
|
if campaignLog == nil then
|
||||||
printToAll("Campaign log not found in standard position!", "Yellow")
|
printToAll("Campaign log not found in standard position!", "Yellow")
|
||||||
printToAll("Default values for health and sanity loaded.", "Yellow")
|
printToAll("Default values for health and sanity loaded.", "Yellow")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
campaignLog = campaignLog.hit_object
|
|
||||||
loadTrauma()
|
loadTrauma()
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -280,7 +191,14 @@ function loadTrauma()
|
|||||||
|
|
||||||
if trauma ~= nil then
|
if trauma ~= nil then
|
||||||
printToAll("Trauma values found in campaign log!", "Green")
|
printToAll("Trauma values found in campaign log!", "Green")
|
||||||
RESET_VALUES = campaignLog.call("returnTrauma")
|
trauma = campaignLog.call("returnTrauma")
|
||||||
|
for i = 1, 8 do
|
||||||
|
if i < 5 then
|
||||||
|
RESET_VALUES.Damage[i] = trauma[i]
|
||||||
|
else
|
||||||
|
RESET_VALUES.Horror[i-4] = trauma[i]
|
||||||
|
end
|
||||||
|
end
|
||||||
loadingFailedBefore = false
|
loadingFailedBefore = false
|
||||||
elseif loadingFailedBefore then
|
elseif loadingFailedBefore then
|
||||||
printToAll("Trauma values could not be found in campaign log!", "Yellow")
|
printToAll("Trauma values could not be found in campaign log!", "Yellow")
|
||||||
@ -303,7 +221,7 @@ end
|
|||||||
-- remove drawn lines
|
-- remove drawn lines
|
||||||
function removeLines()
|
function removeLines()
|
||||||
if options["removeDrawnLines"] then
|
if options["removeDrawnLines"] then
|
||||||
printToAll("Removing vector lines...", "White")
|
printToAll("Removing global vector lines...", "White")
|
||||||
Global.setVectorLines({})
|
Global.setVectorLines({})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -312,40 +230,40 @@ end
|
|||||||
function discardHands()
|
function discardHands()
|
||||||
if not options["tidyPlayermats"] then return end
|
if not options["tidyPlayermats"] then return end
|
||||||
for i = 1, 4 do
|
for i = 1, 4 do
|
||||||
local trashcan = getObjectFromGUID(TRASHCAN_GUIDS[i])
|
local trash = guidReferenceApi.getObjectByOwnerAndType(COLORS[i], "Trash")
|
||||||
if trashcan == nil then return end
|
if trash == nil then return end
|
||||||
local hand = Player[playmatApi.getPlayerColor(COLORS[i])].getHandObjects()
|
local hand = Player[playmatApi.getPlayerColor(COLORS[i])].getHandObjects()
|
||||||
for j = #hand, 1, -1 do
|
for j = #hand, 1, -1 do
|
||||||
trashcan.putObject(hand[j])
|
trash.putObject(hand[j])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- clean up for play area
|
-- clean up for play area
|
||||||
function tidyPlayareaCoroutine()
|
function tidyPlayareaCoroutine()
|
||||||
local trashcan = getObjectFromGUID(TRASHCAN_GUIDS[5])
|
local trash = guidReferenceApi.getObjectByOwnerAndType("Mythos", "Trash")
|
||||||
local PLAYMATZONE = getObjectFromGUID("a2f932")
|
local playAreaZone = guidReferenceApi.getObjectByOwnerAndType("Mythos", "PlayAreaZone")
|
||||||
|
|
||||||
if PLAYMATZONE == nil then
|
if playAreaZone == nil then
|
||||||
printToAll("Scripting zone for main play area could not be found!", "Red")
|
printToAll("Scripting zone for main play area could not be found!", "Red")
|
||||||
elseif trashcan == nil then
|
elseif trash == nil then
|
||||||
printToAll("Trashcan for main play area could not be found!", "Red")
|
printToAll("Trashcan for main play area could not be found!", "Red")
|
||||||
else
|
else
|
||||||
for _, obj in ipairs(PLAYMATZONE.getObjects()) do
|
for _, obj in ipairs(playAreaZone.getObjects()) do
|
||||||
-- ignore these elements
|
-- ignore these elements
|
||||||
if not tableContains(IGNORE_GUIDS, obj.getGUID()) and obj.hasTag(IGNORE_TAG) == false then
|
if obj.hasTag(IGNORE_TAG) == false and checkMemo(obj) == false then
|
||||||
coroutine.yield(0)
|
coroutine.yield(0)
|
||||||
trashcan.putObject(obj)
|
trash.putObject(obj)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
printToAll("Tidying playermats and agenda mat...", "White")
|
printToAll("Tidying playermats and mythos area...", "White")
|
||||||
startLuaCoroutine(self, "tidyPlayerMatCoroutine")
|
startLuaCoroutine(self, "tidyPlayerMatCoroutine")
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- clean up for the four playermats and the agenda/act playmat
|
-- clean up for the four playermats and the mythos area
|
||||||
function tidyPlayerMatCoroutine()
|
function tidyPlayerMatCoroutine()
|
||||||
for i = 1, 5 do
|
for i = 1, 5 do
|
||||||
-- only continue for playermat (1-4) if option enabled
|
-- only continue for playermat (1-4) if option enabled
|
||||||
@ -353,32 +271,38 @@ function tidyPlayerMatCoroutine()
|
|||||||
-- delay for animation purpose
|
-- delay for animation purpose
|
||||||
for k = 1, 30 do coroutine.yield(0) end
|
for k = 1, 30 do coroutine.yield(0) end
|
||||||
|
|
||||||
-- get respective trashcan
|
-- get respective trash
|
||||||
local trashcan = getObjectFromGUID(TRASHCAN_GUIDS[i])
|
local trash = guidReferenceApi.getObjectByOwnerAndType(COLORS[i], "Trash")
|
||||||
if trashcan == nil then
|
if trash == nil then
|
||||||
printToAll("Trashcan for " .. COLORS[i] .. " playmat could not be found!", "Red")
|
printToAll("Trashcan for " .. COLORS[i] .. " playmat could not be found!", "Red")
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, entry in ipairs(findObjects(i)) do
|
local objList
|
||||||
local obj = entry.hit_object
|
if i < 5 then
|
||||||
local desc_low = string.lower(obj.getDescription())
|
objList = playmatApi.searchAroundPlaymat(COLORS[i])
|
||||||
|
else
|
||||||
|
objList = searchMythosArea()
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, obj in ipairs(objList) do
|
||||||
-- ignore these elements
|
-- ignore these elements
|
||||||
if not tableContains(IGNORE_GUIDS, obj.getGUID()) and obj.hasTag(IGNORE_TAG) == false and
|
if obj.hasTag(IGNORE_TAG) == false
|
||||||
desc_low ~= "chaos bag" and desc_low ~= "action token" then
|
and obj.hasTag("ActionToken") == false
|
||||||
|
and obj.hasTag("chaosBag") == false
|
||||||
|
and checkMemo(obj) == false then
|
||||||
coroutine.yield(0)
|
coroutine.yield(0)
|
||||||
trashcan.putObject(obj)
|
trash.putObject(obj)
|
||||||
|
|
||||||
-- flip action tokens back to ready
|
-- flip action tokens back to ready
|
||||||
elseif desc_low == "action token" and obj.is_face_down then
|
elseif obj.hasTag("ActionToken") == false and obj.is_face_down then
|
||||||
obj.flip()
|
obj.flip()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- reset "activeInvestigatorId"
|
-- reset "activeInvestigatorId"
|
||||||
if i < 5 then
|
if i < 5 then
|
||||||
local playermat = getObjectFromGUID(PLAYERMAT_GUIDS[i])
|
local playermat = guidReferenceApi.getObjectByOwnerAndType(COLORS[i], "Playermat")
|
||||||
if playermat then
|
if playermat then
|
||||||
playermat.setVar("activeInvestigatorId", "00000")
|
playermat.setVar("activeInvestigatorId", "00000")
|
||||||
end
|
end
|
||||||
@ -386,7 +310,7 @@ function tidyPlayerMatCoroutine()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local datahelper = getObjectFromGUID("708279")
|
local datahelper = guidReferenceApi.getObjectByOwnerAndType("Mythos", "DataHelper")
|
||||||
if datahelper then
|
if datahelper then
|
||||||
datahelper.setTable("SPAWNED_PLAYER_CARD_GUIDS", {})
|
datahelper.setTable("SPAWNED_PLAYER_CARD_GUIDS", {})
|
||||||
end
|
end
|
||||||
@ -399,23 +323,31 @@ end
|
|||||||
-- helper functions
|
-- helper functions
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
-- find objects depending on index (1 to 4 for playermats, 5 for agenda/act playmat, 6 for campaign log)
|
-- find objects in the mythos area
|
||||||
function findObjects(num)
|
function searchMythosArea()
|
||||||
return Physics.cast({
|
local searchResult = Physics.cast({
|
||||||
direction = { 0, 1, 0 },
|
direction = { 0, 1, 0 },
|
||||||
max_distance = 1,
|
max_distance = 1,
|
||||||
type = 3,
|
type = 3,
|
||||||
size = PHYSICS_SCALE[num],
|
size = { 55, 1, 13.5 },
|
||||||
origin = PHYSICS_POSITION[num],
|
origin = { -2, 2, 10 },
|
||||||
orientation = { 0, PHYSICS_ROTATION[num], 0 },
|
orientation = { 0, 270, 0 },
|
||||||
debug = false
|
debug = false
|
||||||
})
|
})
|
||||||
|
|
||||||
|
local objList = {}
|
||||||
|
for _, v in ipairs(searchResult) do
|
||||||
|
table.insert(objList, v.hit_object)
|
||||||
|
end
|
||||||
|
return objList
|
||||||
end
|
end
|
||||||
|
|
||||||
-- search a table for a value, return true if found (else returns false)
|
-- checks if the object is owned by a playermat or the mythos, returns boolean
|
||||||
function tableContains(table, value)
|
function checkMemo(obj)
|
||||||
for _, v in ipairs(table) do
|
local memo = obj.getMemo()
|
||||||
if v == value then
|
if memo then
|
||||||
|
local decoded = JSON.decode(memo) or {}
|
||||||
|
if decoded.matColor then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -312,6 +312,10 @@ function layout(_, _, isRightClick)
|
|||||||
local value = tonumber(objData.Nickname)
|
local value = tonumber(objData.Nickname)
|
||||||
local precedence = tokenPrecedence[objData.Nickname]
|
local precedence = tokenPrecedence[objData.Nickname]
|
||||||
|
|
||||||
|
-- remove GUID to avoid issues for high latency clients
|
||||||
|
objData["GUID"] = nil
|
||||||
|
|
||||||
|
-- store data with value / precendence
|
||||||
data[i] = {
|
data[i] = {
|
||||||
token = objData,
|
token = objData,
|
||||||
value = value or precedence[1]
|
value = value or precedence[1]
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
do
|
do
|
||||||
local TokenArrangerApi = {}
|
local TokenArrangerApi = {}
|
||||||
|
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||||
|
|
||||||
-- local function to call the token arranger, if it is on the table
|
-- local function to call the token arranger, if it is on the table
|
||||||
---@param functionName String Name of the function to cal
|
---@param functionName String Name of the function to cal
|
||||||
---@param argument Variant Parameter to pass
|
---@param argument Variant Parameter to pass
|
||||||
local function callIfExistent(functionName, argument)
|
local function callIfExistent(functionName, argument)
|
||||||
local tokenArranger = getObjectsWithTag("TokenArranger")[1]
|
local tokenArranger = guidReferenceApi.getObjectByOwnerAndType("Mythos", "TokenArranger")
|
||||||
if tokenArranger ~= nil then
|
if tokenArranger ~= nil then
|
||||||
tokenArranger.call(functionName, argument)
|
tokenArranger.call(functionName, argument)
|
||||||
end
|
end
|
||||||
|
@ -198,7 +198,7 @@ do
|
|||||||
local altArt = { front = "normal", back = "normal" }
|
local altArt = { front = "normal", back = "normal" }
|
||||||
|
|
||||||
-- translating front ID
|
-- translating front ID
|
||||||
if altFrontId > 90000 and altFrontId < 90047 then
|
if altFrontId > 90000 and altFrontId < 90050 then
|
||||||
altArt.front = "parallel"
|
altArt.front = "parallel"
|
||||||
elseif altFrontId > 01500 and altFrontId < 01506 then
|
elseif altFrontId > 01500 and altFrontId < 01506 then
|
||||||
altArt.front = "revised"
|
altArt.front = "revised"
|
||||||
@ -207,7 +207,7 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- translating back ID
|
-- translating back ID
|
||||||
if altBackId > 90000 and altBackId < 90047 then
|
if altBackId > 90000 and altBackId < 90050 then
|
||||||
altArt.back = "parallel"
|
altArt.back = "parallel"
|
||||||
elseif altBackId > 01500 and altBackId < 01506 then
|
elseif altBackId > 01500 and altBackId < 01506 then
|
||||||
altArt.back = "revised"
|
altArt.back = "revised"
|
||||||
@ -295,7 +295,12 @@ do
|
|||||||
local card = allCardsBagApi.getCardById(cardId)
|
local card = allCardsBagApi.getCardById(cardId)
|
||||||
if (card ~= nil and card.metadata.bonded ~= nil) then
|
if (card ~= nil and card.metadata.bonded ~= nil) then
|
||||||
for _, bond in ipairs(card.metadata.bonded) do
|
for _, bond in ipairs(card.metadata.bonded) do
|
||||||
bondedCards[bond.id] = bond.count
|
-- add a bonded card for each copy of the parent card (except for Pendant of the Queen)
|
||||||
|
if bond.id == "06022" then
|
||||||
|
bondedCards[bond.id] = bond.count
|
||||||
|
else
|
||||||
|
bondedCards[bond.id] = bond.count * cardCount
|
||||||
|
end
|
||||||
-- We need to know which cards are bonded to determine their position, remember them
|
-- We need to know which cards are bonded to determine their position, remember them
|
||||||
bondedList[bond.id] = true
|
bondedList[bond.id] = true
|
||||||
-- Also adding taboo versions of bonded cards to the list
|
-- Also adding taboo versions of bonded cards to the list
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
do
|
do
|
||||||
local DeckImporterApi = {}
|
local DeckImporterApi = {}
|
||||||
local DECK_IMPORTER_GUID = "a28140"
|
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||||
|
|
||||||
|
local function getDeckImporter()
|
||||||
|
return guidReferenceApi.getObjectByOwnerAndType("Mythos", "DeckImporter")
|
||||||
|
end
|
||||||
|
|
||||||
-- Returns a table with the full state of the UI, including options and deck IDs.
|
-- Returns a table with the full state of the UI, including options and deck IDs.
|
||||||
-- This can be used to persist via onSave(), or provide values for a load operation
|
-- This can be used to persist via onSave(), or provide values for a load operation
|
||||||
-- Table values:
|
-- Table values:
|
||||||
@ -14,7 +18,7 @@ do
|
|||||||
-- investigators: True if investigator cards should be spawned
|
-- investigators: True if investigator cards should be spawned
|
||||||
DeckImporterApi.getUiState = function()
|
DeckImporterApi.getUiState = function()
|
||||||
local passthroughTable = {}
|
local passthroughTable = {}
|
||||||
for k,v in pairs(getObjectFromGUID(DECK_IMPORTER_GUID).call("getUiState")) do
|
for k,v in pairs(getDeckImporter().call("getUiState")) do
|
||||||
passthroughTable[k] = v
|
passthroughTable[k] = v
|
||||||
end
|
end
|
||||||
return passthroughTable
|
return passthroughTable
|
||||||
@ -31,7 +35,7 @@ do
|
|||||||
-- loadNewest: True if the most upgraded version of the deck should be loaded
|
-- loadNewest: True if the most upgraded version of the deck should be loaded
|
||||||
-- investigators: True if investigator cards should be spawned
|
-- investigators: True if investigator cards should be spawned
|
||||||
DeckImporterApi.setUiState = function(uiStateTable)
|
DeckImporterApi.setUiState = function(uiStateTable)
|
||||||
return getObjectFromGUID(DECK_IMPORTER_GUID).call("setUiState", uiStateTable)
|
return getDeckImporter().call("setUiState", uiStateTable)
|
||||||
end
|
end
|
||||||
|
|
||||||
return DeckImporterApi
|
return DeckImporterApi
|
||||||
|
@ -88,6 +88,7 @@ function loadCards(slots, investigatorId, bondedList, customizations, playerColo
|
|||||||
handleAncestralKnowledge(cardsToSpawn)
|
handleAncestralKnowledge(cardsToSpawn)
|
||||||
handleUnderworldMarket(cardsToSpawn, playerColor)
|
handleUnderworldMarket(cardsToSpawn, playerColor)
|
||||||
handleHunchDeck(investigatorId, cardsToSpawn, playerColor)
|
handleHunchDeck(investigatorId, cardsToSpawn, playerColor)
|
||||||
|
handleSpiritDeck(investigatorId, cardsToSpawn, playerColor)
|
||||||
handleCustomizableUpgrades(cardsToSpawn, customizations)
|
handleCustomizableUpgrades(cardsToSpawn, customizations)
|
||||||
handlePeteSignatureAssets(investigatorId, cardsToSpawn)
|
handlePeteSignatureAssets(investigatorId, cardsToSpawn)
|
||||||
|
|
||||||
@ -322,6 +323,48 @@ function handleHunchDeck(investigatorId, cardList, playerColor)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- If the investigator is Parallel Jim Culver, extract all Ally assets to SetAside5 to build the Spirit
|
||||||
|
-- Deck.
|
||||||
|
---@param investigatorId String ID for the deck's investigator card. Passed separately because the
|
||||||
|
--- investigator may not be included in the cardList
|
||||||
|
---@param cardList Table Deck list being created
|
||||||
|
---@param playerColor String Color this deck is being loaded for
|
||||||
|
function handleSpiritDeck(investigatorId, cardList, playerColor)
|
||||||
|
if investigatorId == "02004-p" or investigatorId == "02004-pb" then -- Parallel Jim Culver
|
||||||
|
local spiritList = {}
|
||||||
|
for i, card in ipairs(cardList) do
|
||||||
|
if card.metadata.id == "90053" or (
|
||||||
|
card.metadata.type == "Asset"
|
||||||
|
and card.metadata.traits ~= nil
|
||||||
|
and string.match(card.metadata.traits, "Ally")
|
||||||
|
and card.metadata.level ~= nil
|
||||||
|
and card.metadata.level < 3) then
|
||||||
|
table.insert(spiritList, i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Process allies to move them to the spirit deck. This is done in reverse
|
||||||
|
-- order because the sorting needs to be reversed (deck sorts for face down)
|
||||||
|
-- Performance here may be an issue, as table.remove() is an O(n) operation
|
||||||
|
-- which makes the full shift O(n^2). But keep it simple unless it becomes
|
||||||
|
-- a problem
|
||||||
|
for i = #spiritList, 1, -1 do
|
||||||
|
local moving = cardList[spiritList[i]]
|
||||||
|
moving.zone = "SetAside5"
|
||||||
|
table.remove(cardList, spiritList[i])
|
||||||
|
table.insert(cardList, moving)
|
||||||
|
end
|
||||||
|
if #spiritList < 10 then
|
||||||
|
printToAll("Jim's spirit deck must have 9 Ally assets but the deck only has " .. (#spiritList - 1) ..
|
||||||
|
" Ally assets.", playerColor)
|
||||||
|
elseif #spiritList > 11 then
|
||||||
|
printToAll("Moved all " .. (#spiritList - 1) ..
|
||||||
|
" Ally assets to the spirit deck, reduce it to 10 (including Vengeful Shade).", playerColor)
|
||||||
|
else
|
||||||
|
printToAll("Built Jim's spirit deck", playerColor)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- For any customization upgrade cards in the card list, process the metadata from the deck to
|
-- For any customization upgrade cards in the card list, process the metadata from the deck to
|
||||||
-- set the save state to show the correct checkboxes/text field values
|
-- set the save state to show the correct checkboxes/text field values
|
||||||
---@param cardList Table Deck list being created
|
---@param cardList Table Deck list being created
|
||||||
|
@ -58,36 +58,9 @@ end
|
|||||||
-- loadNewest: True if the most upgraded version of the deck should be loaded
|
-- loadNewest: True if the most upgraded version of the deck should be loaded
|
||||||
-- investigators: True if investigator cards should be spawned
|
-- investigators: True if investigator cards should be spawned
|
||||||
function setUiState(uiStateTable)
|
function setUiState(uiStateTable)
|
||||||
-- Callback functions aren't triggered when editing buttons/inputs so values must be set manually
|
self.clearButtons()
|
||||||
|
self.clearInputs()
|
||||||
if uiStateTable["greenDeck"] then
|
initializeUi(uiStateTable)
|
||||||
greenDeckId = uiStateTable["greenDeck"]
|
|
||||||
self.editInput({index=0, value=greenDeckId})
|
|
||||||
end
|
|
||||||
if uiStateTable["redDeck"] then
|
|
||||||
redDeckId = uiStateTable["redDeck"]
|
|
||||||
self.editInput({index=1, value=redDeckId})
|
|
||||||
end
|
|
||||||
if uiStateTable["whiteDeck"] then
|
|
||||||
whiteDeckId = uiStateTable["whiteDeck"]
|
|
||||||
self.editInput({index=2, value=whiteDeckId})
|
|
||||||
end
|
|
||||||
if uiStateTable["orangeDeck"]then
|
|
||||||
orangeDeckId = uiStateTable["orangeDeck"]
|
|
||||||
self.editInput({index=3, value=orangeDeckId})
|
|
||||||
end
|
|
||||||
if uiStateTable["private"] then
|
|
||||||
privateDeck = uiStateTable["private"]
|
|
||||||
self.editButton { index = 0, label = PRIVATE_TOGGLE_LABELS[privateDeck] }
|
|
||||||
end
|
|
||||||
if uiStateTable["loadNewest"] then
|
|
||||||
loadNewestDeck = uiStateTable["loadNewest"]
|
|
||||||
self.editButton { index = 1, label = UPGRADED_TOGGLE_LABELS[loadNewestDeck] }
|
|
||||||
end
|
|
||||||
if uiStateTable["investigators"] then
|
|
||||||
loadInvestigators = uiStateTable["investigators"]
|
|
||||||
self.editButton { index = 2, label = LOAD_INVESTIGATOR_TOGGLE_LABELS[loadInvestigators] }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Sets up the UI for the deck loader, populating fields from the given save state table decoded from onLoad()
|
-- Sets up the UI for the deck loader, populating fields from the given save state table decoded from onLoad()
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
do
|
do
|
||||||
local BlessCurseManagerApi = {}
|
local BlessCurseManagerApi = {}
|
||||||
local MANAGER_GUID = "5933fb"
|
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||||
|
|
||||||
|
local function getManager()
|
||||||
|
return guidReferenceApi.getObjectByOwnerAndType("Mythos", "BlessCurseManager")
|
||||||
|
end
|
||||||
|
|
||||||
-- removes all taken tokens and resets the counts
|
-- removes all taken tokens and resets the counts
|
||||||
BlessCurseManagerApi.removeTakenTokensAndReset = function()
|
BlessCurseManagerApi.removeTakenTokensAndReset = function()
|
||||||
local BlessCurseManager = getObjectFromGUID(MANAGER_GUID)
|
local BlessCurseManager = getManager()
|
||||||
Wait.time(function() BlessCurseManager.call("removeTakenTokens", "Bless") end, 0.05)
|
Wait.time(function() BlessCurseManager.call("removeTakenTokens", "Bless") end, 0.05)
|
||||||
Wait.time(function() BlessCurseManager.call("removeTakenTokens", "Curse") end, 0.10)
|
Wait.time(function() BlessCurseManager.call("removeTakenTokens", "Curse") end, 0.10)
|
||||||
Wait.time(function() BlessCurseManager.call("doReset", "White") end, 0.15)
|
Wait.time(function() BlessCurseManager.call("doReset", "White") end, 0.15)
|
||||||
@ -12,30 +16,30 @@ do
|
|||||||
|
|
||||||
-- updates the internal count (called by cards that seal bless/curse tokens)
|
-- updates the internal count (called by cards that seal bless/curse tokens)
|
||||||
BlessCurseManagerApi.sealedToken = function(type, guid)
|
BlessCurseManagerApi.sealedToken = function(type, guid)
|
||||||
getObjectFromGUID(MANAGER_GUID).call("sealedToken", { type = type, guid = guid })
|
getManager().call("sealedToken", { type = type, guid = guid })
|
||||||
end
|
end
|
||||||
|
|
||||||
-- updates the internal count (called by cards that seal bless/curse tokens)
|
-- updates the internal count (called by cards that seal bless/curse tokens)
|
||||||
BlessCurseManagerApi.releasedToken = function(type, guid)
|
BlessCurseManagerApi.releasedToken = function(type, guid)
|
||||||
getObjectFromGUID(MANAGER_GUID).call("releasedToken", { type = type, guid = guid })
|
getManager().call("releasedToken", { type = type, guid = guid })
|
||||||
end
|
end
|
||||||
|
|
||||||
-- broadcasts the current status for bless/curse tokens
|
-- broadcasts the current status for bless/curse tokens
|
||||||
---@param playerColor String Color of the player to show the broadcast to
|
---@param playerColor String Color of the player to show the broadcast to
|
||||||
BlessCurseManagerApi.broadcastStatus = function(playerColor)
|
BlessCurseManagerApi.broadcastStatus = function(playerColor)
|
||||||
getObjectFromGUID(MANAGER_GUID).call("broadcastStatus", playerColor)
|
getManager().call("broadcastStatus", playerColor)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- removes all bless / curse tokens from the chaos bag and play
|
-- removes all bless / curse tokens from the chaos bag and play
|
||||||
---@param playerColor String Color of the player to show the broadcast to
|
---@param playerColor String Color of the player to show the broadcast to
|
||||||
BlessCurseManagerApi.removeAll = function(playerColor)
|
BlessCurseManagerApi.removeAll = function(playerColor)
|
||||||
getObjectFromGUID(MANAGER_GUID).call("doRemove", playerColor)
|
getManager().call("doRemove", playerColor)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- adds Wendy's menu to the hovered card (allows sealing of tokens)
|
-- adds Wendy's menu to the hovered card (allows sealing of tokens)
|
||||||
---@param color String Color of the player to show the broadcast to
|
---@param color String Color of the player to show the broadcast to
|
||||||
BlessCurseManagerApi.addWendysMenu = function(playerColor, hoveredObject)
|
BlessCurseManagerApi.addWendysMenu = function(playerColor, hoveredObject)
|
||||||
getObjectFromGUID(MANAGER_GUID).call("addMenuOptions", { playerColor = playerColor, hoveredObject = hoveredObject })
|
getManager().call("addMenuOptions", { playerColor = playerColor, hoveredObject = hoveredObject })
|
||||||
end
|
end
|
||||||
|
|
||||||
return BlessCurseManagerApi
|
return BlessCurseManagerApi
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||||
|
|
||||||
local optionsVisible = false
|
local optionsVisible = false
|
||||||
local options = {
|
local options = {
|
||||||
Agenda = true,
|
Agenda = true,
|
||||||
@ -64,10 +66,9 @@ function startReset()
|
|||||||
if options.Agenda then
|
if options.Agenda then
|
||||||
updateVal(0)
|
updateVal(0)
|
||||||
end
|
end
|
||||||
-- call the "Doom-in-Play"-counter
|
local doomInPlayCounter = guidReferenceApi.getObjectByOwnerAndType("Mythos", "DoomInPlayCounter")
|
||||||
local DoomInPlayCounter = getObjectFromGUID("652ff3")
|
if doomInPlayCounter then
|
||||||
if DoomInPlayCounter then
|
doomInPlayCounter.call("removeDoom", options)
|
||||||
DoomInPlayCounter.call("removeDoom", options)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,25 +1,24 @@
|
|||||||
-- common parameters
|
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||||
local castParameters = {}
|
local playmatApi = require("playermat/PlaymatApi")
|
||||||
castParameters.direction = { 0, 1, 0 }
|
|
||||||
castParameters.type = 3
|
|
||||||
castParameters.max_distance = 0
|
|
||||||
|
|
||||||
local zone
|
local ZONE, TRASH, loopID
|
||||||
local doomURL = "https://i.imgur.com/EoL7yaZ.png"
|
local doomURL = "https://i.imgur.com/EoL7yaZ.png"
|
||||||
local IGNORE_TAG = "DoomCounter_ignore"
|
local IGNORE_TAG = "DoomCounter_ignore"
|
||||||
|
local TOTAL_PLAY_AREA = {
|
||||||
-- playermats 1 to 4
|
upperLeft = {
|
||||||
local originAndSize = {
|
x = -10,
|
||||||
{ origin = { -55, 1.6, 16.5 }, size = { 12, 1, 25 } },
|
z = -35
|
||||||
{ origin = { -55, 1.6, -16.5 }, size = { 12, 1, 25 } },
|
},
|
||||||
{ origin = { -25, 1.6, 27 }, size = { 25, 1, 12 } },
|
lowerRight = {
|
||||||
{ origin = { -25, 1.6, -27 }, size = { 25, 1, 12 } }
|
x = -60,
|
||||||
|
z = 35
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
-- create button, context menu and start loop
|
-- create button, context menu and start loop
|
||||||
function onLoad()
|
function onLoad()
|
||||||
self.createButton({
|
self.createButton({
|
||||||
label = tostring(0),
|
label = "0",
|
||||||
click_function = "none",
|
click_function = "none",
|
||||||
function_owner = self,
|
function_owner = self,
|
||||||
position = { 0, 0.06, 0 },
|
position = { 0, 0.06, 0 },
|
||||||
@ -31,76 +30,65 @@ function onLoad()
|
|||||||
color = { 0, 0, 0, 0 }
|
color = { 0, 0, 0, 0 }
|
||||||
})
|
})
|
||||||
|
|
||||||
zone = getObjectFromGUID("a2f932")
|
TRASH = guidReferenceApi.getObjectByOwnerAndType("Mythos", "Trash")
|
||||||
|
ZONE = guidReferenceApi.getObjectByOwnerAndType("Mythos", "PlayAreaZone")
|
||||||
loopID = Wait.time(countDoom, 2, -1)
|
loopID = Wait.time(countDoom, 2, -1)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- main function
|
-- main function
|
||||||
function countDoom()
|
function countDoom()
|
||||||
local doom = 0
|
local count = 0
|
||||||
for i = 1, 5 do doom = doom + search(i) end
|
|
||||||
self.editButton({ index = 0, label = tostring(doom) })
|
-- get doom in play
|
||||||
|
for _, obj in ipairs(getObjects()) do
|
||||||
|
count = count + getDoomAmount(obj)
|
||||||
|
end
|
||||||
|
|
||||||
|
self.editButton({ index = 0, label = tostring(count) })
|
||||||
end
|
end
|
||||||
|
|
||||||
-- searches playermats (num = 1-4) or the scripting zone (num = 5)
|
-- gets quantity (for stacks) of doom
|
||||||
function search(num)
|
function getDoomAmount(obj)
|
||||||
local val = 0
|
if (obj.is_face_down and obj.getCustomObject().image_bottom == doomURL)
|
||||||
if num == 5 then
|
and not obj.hasTag(IGNORE_TAG)
|
||||||
for _, obj in ipairs(zone.getObjects()) do
|
and inArea(obj.getPosition(), TOTAL_PLAY_AREA) then
|
||||||
val = val + isDoom(obj)
|
return math.abs(obj.getQuantity())
|
||||||
end
|
|
||||||
else
|
else
|
||||||
castParameters.origin = originAndSize[num].origin
|
return 0
|
||||||
castParameters.size = originAndSize[num].size
|
|
||||||
|
|
||||||
for _, obj in ipairs(Physics.cast(castParameters)) do
|
|
||||||
val = val + isDoom(obj.hit_object)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
return val
|
|
||||||
end
|
|
||||||
|
|
||||||
-- checks an object for the doom image and gets quantity (for stacks)
|
|
||||||
function isDoom(obj)
|
|
||||||
if (obj.is_face_down and obj.getCustomObject().image_bottom == doomURL) or
|
|
||||||
(obj.name == "Custom_Token" and obj.getCustomObject().image == doomURL) then
|
|
||||||
if not obj.hasTag(IGNORE_TAG) then
|
|
||||||
return math.abs(obj.getQuantity())
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- removes doom from playermats / playarea
|
-- removes doom from playermats / playarea
|
||||||
function removeDoom(options)
|
function removeDoom(options)
|
||||||
local trashCan = getObjectFromGUID("70b9f6")
|
|
||||||
local count = 0
|
local count = 0
|
||||||
if options.Playermats then
|
|
||||||
for i = 1, 4 do
|
|
||||||
castParameters.origin = originAndSize[i].origin
|
|
||||||
castParameters.size = originAndSize[i].size
|
|
||||||
|
|
||||||
for _, obj in ipairs(Physics.cast(castParameters)) do
|
if options.Playermats then
|
||||||
local obj = obj.hit_object
|
count = removeDoomFromList(playmatApi.searchAroundPlaymat("All"))
|
||||||
local amount = isDoom(obj)
|
|
||||||
if amount > 0 then
|
|
||||||
trashCan.putObject(obj)
|
|
||||||
count = count + amount
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
broadcastToAll(count .. " doom removed from Playermats.", "White")
|
broadcastToAll(count .. " doom removed from Playermats.", "White")
|
||||||
end
|
end
|
||||||
|
|
||||||
local count = 0
|
|
||||||
if options.Playarea then
|
if options.Playarea then
|
||||||
for _, obj in ipairs(zone.getObjects()) do
|
count = removeDoomFromList(ZONE.getObjects())
|
||||||
local amount = isDoom(obj)
|
broadcastToAll(count .. " doom removed from Playerarea.", "White")
|
||||||
if amount > 0 then
|
|
||||||
trashCan.putObject(obj)
|
|
||||||
count = count + amount
|
|
||||||
end
|
|
||||||
end
|
|
||||||
broadcastToAll(count .. " doom removed from Playarea.", "White")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- removes doom from provided object list and returns the removed amount
|
||||||
|
function removeDoomFromList(objList)
|
||||||
|
local count = 0
|
||||||
|
for _, obj in ipairs(objList) do
|
||||||
|
local amount = getDoomAmount(obj)
|
||||||
|
if amount > 0 then
|
||||||
|
TRASH.putObject(obj)
|
||||||
|
count = count + amount
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return count
|
||||||
|
end
|
||||||
|
|
||||||
|
function inArea(point, bounds)
|
||||||
|
return (point.x < bounds.upperLeft.x
|
||||||
|
and point.x > bounds.lowerRight.x
|
||||||
|
and point.z > bounds.upperLeft.z
|
||||||
|
and point.z < bounds.lowerRight.z)
|
||||||
|
end
|
||||||
|
28
src/core/GUIDReferenceApi.ttslua
Normal file
28
src/core/GUIDReferenceApi.ttslua
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
do
|
||||||
|
local GUIDReferenceApi = {}
|
||||||
|
|
||||||
|
local function getGuidHandler()
|
||||||
|
return getObjectFromGUID("123456")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- returns all matching objects as a table with references
|
||||||
|
---@param owner String Parent object for this search
|
||||||
|
---@param type String Type of object to search for
|
||||||
|
GUIDReferenceApi.getObjectByOwnerAndType = function(owner, type)
|
||||||
|
return getGuidHandler().call("getObjectByOwnerAndType", { owner = owner, type = type })
|
||||||
|
end
|
||||||
|
|
||||||
|
-- returns all matching objects as a table with references
|
||||||
|
---@param type String Type of object to search for
|
||||||
|
GUIDReferenceApi.getObjectsByType = function(type)
|
||||||
|
return getGuidHandler().call("getObjectsByType", type)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- returns all matching objects as a table with references
|
||||||
|
---@param owner String Parent object for this search
|
||||||
|
GUIDReferenceApi.getObjectsByOwner = function(owner)
|
||||||
|
return getGuidHandler().call("getObjectsByOwner", owner)
|
||||||
|
end
|
||||||
|
|
||||||
|
return GUIDReferenceApi
|
||||||
|
end
|
101
src/core/GUIDReferenceHandler.ttslua
Normal file
101
src/core/GUIDReferenceHandler.ttslua
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
local GuidReferences = {
|
||||||
|
White = {
|
||||||
|
ClueCounter = "d86b7c",
|
||||||
|
ClickableClueCounter = "db85d6",
|
||||||
|
DamageCounter = "eb08d6",
|
||||||
|
HandZone = "a70eee",
|
||||||
|
HorrorCounter = "468e88",
|
||||||
|
InvestigatorSkillTracker = "e598c2",
|
||||||
|
Playermat = "8b081b",
|
||||||
|
ResourceCounter = "4406f0",
|
||||||
|
Trash = "147e80"
|
||||||
|
},
|
||||||
|
Orange = {
|
||||||
|
ClueCounter = "1769ed",
|
||||||
|
ClickableClueCounter = "3f22e5",
|
||||||
|
DamageCounter = "e64eec",
|
||||||
|
HandZone = "5fe087",
|
||||||
|
HorrorCounter = "0257d9",
|
||||||
|
InvestigatorSkillTracker = "b4a5f7",
|
||||||
|
Playermat = "bd0ff4",
|
||||||
|
ResourceCounter = "816d84",
|
||||||
|
Trash = "f7b6c8"
|
||||||
|
},
|
||||||
|
Green = {
|
||||||
|
ClueCounter = "032300",
|
||||||
|
ClickableClueCounter = "891403",
|
||||||
|
DamageCounter = "1f5a0a",
|
||||||
|
HandZone = "0285cc",
|
||||||
|
HorrorCounter = "7b5729",
|
||||||
|
InvestigatorSkillTracker = "af7ed7",
|
||||||
|
Playermat = "383d8b",
|
||||||
|
ResourceCounter = "cd15ac",
|
||||||
|
Trash = "5f896a"
|
||||||
|
},
|
||||||
|
Red = {
|
||||||
|
ClueCounter = "37be78",
|
||||||
|
ClickableClueCounter = "4111de",
|
||||||
|
DamageCounter = "591a45",
|
||||||
|
HandZone = "be2f17",
|
||||||
|
HorrorCounter = "beb964",
|
||||||
|
InvestigatorSkillTracker = "e74881",
|
||||||
|
Playermat = "0840d5",
|
||||||
|
ResourceCounter = "a4b60d",
|
||||||
|
Trash = "4b8594"
|
||||||
|
},
|
||||||
|
Mythos = {
|
||||||
|
AllCardsBag = "15bb07",
|
||||||
|
BlessCurseManager = "5933fb",
|
||||||
|
CampaignThePathToCarcosa = "aca04c",
|
||||||
|
DataHelper = "708279",
|
||||||
|
DeckImporter = "a28140",
|
||||||
|
DoomCounter = "85c4c6",
|
||||||
|
DoomInPlayCounter = "652ff3",
|
||||||
|
InvestigatorCounter = "f182ee",
|
||||||
|
MasterClueCounter = "4a3aa4",
|
||||||
|
MythosArea = "9f334f",
|
||||||
|
NavigationOverlayHandler = "797ede",
|
||||||
|
OptionPanelSource = "830bd0",
|
||||||
|
PlaceholderBoxDummy = "a93466",
|
||||||
|
PlayArea = "721ba2",
|
||||||
|
PlayAreaZone = "a2f932",
|
||||||
|
PlayerCardPanel = "2d30ee",
|
||||||
|
ResourceTokenBag = "9fadf9",
|
||||||
|
RulesReference = "d99993",
|
||||||
|
SoundCube = "3c988f",
|
||||||
|
TokenArranger = "022907",
|
||||||
|
TokenSource = "124381",
|
||||||
|
TokenSpawnTracker = "e3ffc9",
|
||||||
|
TourStarter = "0e5aa8",
|
||||||
|
Trash = "70b9f6",
|
||||||
|
VictoryDisplay = "6ccd6d"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getObjectByOwnerAndType(params)
|
||||||
|
local owner = params.owner or "Mythos"
|
||||||
|
local type = params.type
|
||||||
|
return getObjectFromGUID(GuidReferences[owner][type])
|
||||||
|
end
|
||||||
|
|
||||||
|
function getObjectsByType(type)
|
||||||
|
local objList = {}
|
||||||
|
for owner, objects in pairs(GuidReferences) do
|
||||||
|
local obj = getObjectFromGUID(objects[type])
|
||||||
|
if obj then
|
||||||
|
objList[owner] = obj
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return objList
|
||||||
|
end
|
||||||
|
|
||||||
|
function getObjectsByOwner(owner)
|
||||||
|
local objList = {}
|
||||||
|
for type, guid in pairs(GuidReferences[owner]) do
|
||||||
|
local obj = getObjectFromGUID(guid)
|
||||||
|
if obj then
|
||||||
|
objList[type] = obj
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return objList
|
||||||
|
end
|
@ -1,4 +1,5 @@
|
|||||||
local blessCurseManagerApi = require("chaosbag/BlessCurseManagerApi")
|
local blessCurseManagerApi = require("chaosbag/BlessCurseManagerApi")
|
||||||
|
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||||
local optionPanelApi = require("core/OptionPanelApi")
|
local optionPanelApi = require("core/OptionPanelApi")
|
||||||
local playmatApi = require("playermat/PlaymatApi")
|
local playmatApi = require("playermat/PlaymatApi")
|
||||||
local victoryDisplayApi = require("core/VictoryDisplayApi")
|
local victoryDisplayApi = require("core/VictoryDisplayApi")
|
||||||
@ -41,7 +42,8 @@ end
|
|||||||
|
|
||||||
-- adds 1 doom to the agenda
|
-- adds 1 doom to the agenda
|
||||||
function addDoomToAgenda()
|
function addDoomToAgenda()
|
||||||
getObjectFromGUID("85c4c6").call("addVal", 1)
|
local doomCounter = guidReferenceApi.getObjectByOwnerAndType("Mythos", "DoomCounter")
|
||||||
|
doomCounter.call("addVal", 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- moves the hovered card to the victory display
|
-- moves the hovered card to the victory display
|
||||||
@ -105,7 +107,7 @@ function takeClueFromLocation(playerColor, hoveredObject)
|
|||||||
local pos = nil
|
local pos = nil
|
||||||
if clickableClues then
|
if clickableClues then
|
||||||
pos = {x = 0.49, y = 2.66, z = 0.00}
|
pos = {x = 0.49, y = 2.66, z = 0.00}
|
||||||
playmatApi.updateClueClicker(playerColor, playmatApi.getClueCount(clickableClues, playerColor) + 1)
|
playmatApi.updateCounter(matColor, "ClickableClueCounter", _, 1)
|
||||||
else
|
else
|
||||||
pos = playmatApi.transformLocalPosition({x = -1.12, y = 0.05, z = 0.7}, matColor)
|
pos = playmatApi.transformLocalPosition({x = -1.12, y = 0.05, z = 0.7}, matColor)
|
||||||
end
|
end
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local blessCurseManagerApi = require("chaosbag/BlessCurseManagerApi")
|
local blessCurseManagerApi = require("chaosbag/BlessCurseManagerApi")
|
||||||
|
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||||
local mythosAreaApi = require("core/MythosAreaApi")
|
local mythosAreaApi = require("core/MythosAreaApi")
|
||||||
local navigationOverlayApi = require("core/NavigationOverlayApi")
|
local navigationOverlayApi = require("core/NavigationOverlayApi")
|
||||||
local playAreaApi = require("core/PlayAreaApi")
|
local playAreaApi = require("core/PlayAreaApi")
|
||||||
@ -12,11 +13,8 @@ local tokenManager = require("core/token/TokenManager")
|
|||||||
-- general setup
|
-- general setup
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
ENCOUNTER_DECK_POS = {-3.93, 1, 5.76}
|
ENCOUNTER_DECK_POS = { -3.93, 1, 5.76 }
|
||||||
ENCOUNTER_DECK_DISCARD_POSITION = {-3.85, 1, 10.38}
|
ENCOUNTER_DECK_DISCARD_POSITION = { -3.85, 1, 10.38 }
|
||||||
|
|
||||||
-- GUID of data helper
|
|
||||||
DATA_HELPER_GUID = "708279"
|
|
||||||
|
|
||||||
-- GUIDs that will not be interactable (e.g. parts of the table)
|
-- GUIDs that will not be interactable (e.g. parts of the table)
|
||||||
local NOT_INTERACTABLE = {
|
local NOT_INTERACTABLE = {
|
||||||
@ -37,14 +35,28 @@ chaosTokens = {}
|
|||||||
local chaosTokensLastMat = nil
|
local chaosTokensLastMat = nil
|
||||||
|
|
||||||
local bagSearchers = {}
|
local bagSearchers = {}
|
||||||
local MAT_COLORS = {"White", "Orange", "Green", "Red"}
|
local MAT_COLORS = { "White", "Orange", "Green", "Red" }
|
||||||
local hideTitleSplashWaitFunctionId = nil
|
local hideTitleSplashWaitFunctionId = nil
|
||||||
|
|
||||||
-- online functionality related variables
|
-- online functionality related variables
|
||||||
local MOD_VERSION = "3.3.0"
|
local MOD_VERSION = "3.3.0"
|
||||||
local SOURCE_REPO = 'https://raw.githubusercontent.com/chr1z93/loadable-objects/main'
|
local SOURCE_REPO = 'https://raw.githubusercontent.com/chr1z93/loadable-objects/main'
|
||||||
local library, requestObj, modMeta, notificationVisible
|
local library, requestObj, modMeta
|
||||||
local acknowledgedUpgradeVersions = {}
|
local acknowledgedUpgradeVersions = {}
|
||||||
|
local contentToShow = "campaigns"
|
||||||
|
local currentListItem = 1
|
||||||
|
local xmlVisibility = {
|
||||||
|
downloadWindow = false,
|
||||||
|
optionPanel = false,
|
||||||
|
updateNotification = false
|
||||||
|
}
|
||||||
|
local tabIdTable = {
|
||||||
|
tab1 = "campaigns",
|
||||||
|
tab2 = "scenarios",
|
||||||
|
tab3 = "fanmadeCampaigns",
|
||||||
|
tab4 = "fanmadeScenarios",
|
||||||
|
tab5 = "fanmadePlayerCards"
|
||||||
|
}
|
||||||
|
|
||||||
-- optionPanel data
|
-- optionPanel data
|
||||||
optionPanel = {}
|
optionPanel = {}
|
||||||
@ -101,14 +113,6 @@ ID_URL_MAP = {
|
|||||||
-- data for chaos token stat tracker
|
-- data for chaos token stat tracker
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
local MAT_GUID_TO_COLOR = {
|
|
||||||
["Overall"] = "Overall",
|
|
||||||
["8b081b"] = "White",
|
|
||||||
["bd0ff4"] = "Orange",
|
|
||||||
["383d8b"] = "Green",
|
|
||||||
["0840d5"] = "Red"
|
|
||||||
}
|
|
||||||
|
|
||||||
local tokenDrawingStats = {
|
local tokenDrawingStats = {
|
||||||
["Overall"] = {},
|
["Overall"] = {},
|
||||||
["8b081b"] = {},
|
["8b081b"] = {},
|
||||||
@ -122,7 +126,12 @@ local tokenDrawingStats = {
|
|||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
-- saving state of optionPanel to restore later
|
-- saving state of optionPanel to restore later
|
||||||
function onSave() return JSON.encode({ optionPanel = optionPanel, acknowledgedUpgradeVersions = acknowledgedUpgradeVersions }) end
|
function onSave()
|
||||||
|
return JSON.encode({
|
||||||
|
optionPanel = optionPanel,
|
||||||
|
acknowledgedUpgradeVersions = acknowledgedUpgradeVersions
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
function onLoad(savedData)
|
function onLoad(savedData)
|
||||||
if savedData then
|
if savedData then
|
||||||
@ -142,6 +151,11 @@ function onLoad(savedData)
|
|||||||
resetChaosTokenStatTracker()
|
resetChaosTokenStatTracker()
|
||||||
getModVersion()
|
getModVersion()
|
||||||
math.randomseed(os.time())
|
math.randomseed(os.time())
|
||||||
|
|
||||||
|
-- initialization of loadable objects library (delay to let Navigation Overlay build)
|
||||||
|
Wait.time(function()
|
||||||
|
WebRequest.get(SOURCE_REPO .. '/library.json', libraryDownloadCallback)
|
||||||
|
end, 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Event hook for any object search. When chaos tokens are manipulated while the chaos bag
|
-- Event hook for any object search. When chaos tokens are manipulated while the chaos bag
|
||||||
@ -289,8 +303,8 @@ function handleStatTrackerClick(_, _, isRightClick)
|
|||||||
if isRightClick then
|
if isRightClick then
|
||||||
resetChaosTokenStatTracker()
|
resetChaosTokenStatTracker()
|
||||||
else
|
else
|
||||||
local squidKing = "Nobody"
|
local squidKing = "Nobody"
|
||||||
local maxSquid = 0
|
local maxSquid = 0
|
||||||
local foundAnyStats = false
|
local foundAnyStats = false
|
||||||
|
|
||||||
for key, personalStats in pairs(tokenDrawingStats) do
|
for key, personalStats in pairs(tokenDrawingStats) do
|
||||||
@ -300,7 +314,9 @@ function handleStatTrackerClick(_, _, isRightClick)
|
|||||||
playerColor = "White"
|
playerColor = "White"
|
||||||
playerName = "Overall"
|
playerName = "Overall"
|
||||||
else
|
else
|
||||||
playerColor = playmatApi.getPlayerColor(MAT_GUID_TO_COLOR[key])
|
-- get mat color
|
||||||
|
local matColor = playmatApi.getMatColorByPosition(getObjectFromGUID(key).getPosition())
|
||||||
|
playerColor = playmatApi.getPlayerColor(matColor)
|
||||||
playerName = Player[playerColor].steam_name or playerColor
|
playerName = Player[playerColor].steam_name or playerColor
|
||||||
|
|
||||||
local playerSquidCount = personalStats["Auto-fail"]
|
local playerSquidCount = personalStats["Auto-fail"]
|
||||||
@ -320,8 +336,8 @@ function handleStatTrackerClick(_, _, isRightClick)
|
|||||||
if totalCount > 0 then
|
if totalCount > 0 then
|
||||||
foundAnyStats = true
|
foundAnyStats = true
|
||||||
printToAll("------------------------------")
|
printToAll("------------------------------")
|
||||||
printToAll(playerName .. " Stats", playerColor)
|
printToAll(playerName .. " Stats", playerColor)
|
||||||
|
|
||||||
for tokenName, value in pairs(personalStats) do
|
for tokenName, value in pairs(personalStats) do
|
||||||
if value ~= 0 then
|
if value ~= 0 then
|
||||||
printToAll(tokenName .. ': ' .. tostring(value))
|
printToAll(tokenName .. ': ' .. tostring(value))
|
||||||
@ -334,7 +350,7 @@ function handleStatTrackerClick(_, _, isRightClick)
|
|||||||
-- detect if any player drew tokens
|
-- detect if any player drew tokens
|
||||||
if foundAnyStats then
|
if foundAnyStats then
|
||||||
printToAll("------------------------------")
|
printToAll("------------------------------")
|
||||||
printToAll(squidKing .. " is an auto-fail magnet.", {255, 0, 0})
|
printToAll(squidKing .. " is an auto-fail magnet.", { 255, 0, 0 })
|
||||||
else
|
else
|
||||||
printToAll("No tokens have been drawn yet.", "Yellow")
|
printToAll("No tokens have been drawn yet.", "Yellow")
|
||||||
end
|
end
|
||||||
@ -363,11 +379,11 @@ function createSetupButtons(args)
|
|||||||
if data ~= nil then
|
if data ~= nil then
|
||||||
local buttonParameters = {}
|
local buttonParameters = {}
|
||||||
buttonParameters.function_owner = args.object
|
buttonParameters.function_owner = args.object
|
||||||
buttonParameters.position = {0, 0.1, -0.15}
|
buttonParameters.position = { 0, 0.1, -0.15 }
|
||||||
buttonParameters.scale = {0.47, 1, 0.47}
|
buttonParameters.scale = { 0.47, 1, 0.47 }
|
||||||
buttonParameters.height = 200
|
buttonParameters.height = 200
|
||||||
buttonParameters.width = 1150
|
buttonParameters.width = 1150
|
||||||
buttonParameters.color = {0.87, 0.8, 0.7}
|
buttonParameters.color = { 0.87, 0.8, 0.7 }
|
||||||
|
|
||||||
if data.easy ~= nil then
|
if data.easy ~= nil then
|
||||||
buttonParameters.label = "Easy"
|
buttonParameters.label = "Easy"
|
||||||
@ -450,7 +466,8 @@ function fillContainer(args)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function getDataValue(storage, key)
|
function getDataValue(storage, key)
|
||||||
local data = getObjectFromGUID(DATA_HELPER_GUID).getTable(storage)
|
local DATA_HELPER = guidReferenceApi.getObjectByOwnerAndType("Mythos", "DataHelper")
|
||||||
|
local data = DATA_HELPER.getTable(storage)
|
||||||
if data ~= nil then
|
if data ~= nil then
|
||||||
local value = data[key]
|
local value = data[key]
|
||||||
if value ~= nil then
|
if value ~= nil then
|
||||||
@ -495,7 +512,6 @@ function getChaosBagState()
|
|||||||
end
|
end
|
||||||
|
|
||||||
return tokens
|
return tokens
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- respawns the chaos bag with a new state of tokens
|
-- respawns the chaos bag with a new state of tokens
|
||||||
@ -524,7 +540,7 @@ function setChaosBagState(tokenList)
|
|||||||
-- overwrite chaos bag content and respawn it
|
-- overwrite chaos bag content and respawn it
|
||||||
chaosbagData.ContainedObjects = containedObjects
|
chaosbagData.ContainedObjects = containedObjects
|
||||||
chaosbag.destruct()
|
chaosbag.destruct()
|
||||||
spawnObjectData({data = chaosbagData})
|
spawnObjectData({ data = chaosbagData })
|
||||||
|
|
||||||
-- remove tokens that are still in play
|
-- remove tokens that are still in play
|
||||||
for _, token in pairs(chaosTokens) do
|
for _, token in pairs(chaosTokens) do
|
||||||
@ -553,7 +569,7 @@ function spawnChaosToken(id)
|
|||||||
type = 'Custom_Tile',
|
type = 'Custom_Tile',
|
||||||
position = { 0.49, 3, 0 },
|
position = { 0.49, 3, 0 },
|
||||||
scale = { 0.81, 1.0, 0.81 },
|
scale = { 0.81, 1.0, 0.81 },
|
||||||
rotation = {0, 270, 0},
|
rotation = { 0, 270, 0 },
|
||||||
callback_function = function(obj)
|
callback_function = function(obj)
|
||||||
obj.setName(ID_URL_MAP[id].name)
|
obj.setName(ID_URL_MAP[id].name)
|
||||||
chaosbag.putObject(obj)
|
chaosbag.putObject(obj)
|
||||||
@ -603,7 +619,7 @@ function emptyChaosBag()
|
|||||||
|
|
||||||
local chaosbag = findChaosBag()
|
local chaosbag = findChaosBag()
|
||||||
for _, object in ipairs(chaosbag.getObjects()) do
|
for _, object in ipairs(chaosbag.getObjects()) do
|
||||||
chaosbag.takeObject({callback_function = function(item) item.destruct() end})
|
chaosbag.takeObject({ callback_function = function(item) item.destruct() end })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -619,176 +635,410 @@ end
|
|||||||
-- Content Importing and XML functions
|
-- Content Importing and XML functions
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
function onClick_refreshList()
|
-- forwards the requested content type to the update function and sets highlight to clicked tab
|
||||||
local request = WebRequest.get(SOURCE_REPO .. '/library.json', completed_list_update)
|
---@param tabId String Id of the clicked tab
|
||||||
requestObj = request
|
function onClick_tab(_, _, tabId)
|
||||||
startLuaCoroutine(Global, 'downloadCoroutine')
|
for listId, listContent in pairs(tabIdTable) do
|
||||||
|
if listId == tabId then
|
||||||
|
UI.setClass(listId, 'downloadTab activeTab')
|
||||||
|
contentToShow = listContent
|
||||||
|
else
|
||||||
|
UI.setClass(listId, 'downloadTab')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
currentListItem = 1
|
||||||
|
updateDownloadItemList()
|
||||||
end
|
end
|
||||||
|
|
||||||
function onClick_select(player, params)
|
-- click function for the items in the download window
|
||||||
params = JSON.decode(urldecode(params))
|
-- updates backgroundcolor for row panel and fontcolor for list item
|
||||||
|
function onClick_select(_, _, identificationKey)
|
||||||
|
UI.setAttribute("panel" .. currentListItem, "color", "clear")
|
||||||
|
UI.setAttribute(contentToShow .. "_" .. currentListItem, "color", "white")
|
||||||
|
|
||||||
|
-- parses the identification key (contentToShow_currentListItem)
|
||||||
|
if identificationKey then
|
||||||
|
contentToShow = nil
|
||||||
|
currentListItem = nil
|
||||||
|
for str in string.gmatch(identificationKey, "([^_]+)") do
|
||||||
|
if not contentToShow then
|
||||||
|
-- grab the first part to know the content type
|
||||||
|
contentToShow = str
|
||||||
|
else
|
||||||
|
-- get the index
|
||||||
|
currentListItem = tonumber(str)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
UI.setAttribute("panel" .. currentListItem, "color", "grey")
|
||||||
|
UI.setAttribute(contentToShow .. "_" .. currentListItem, "color", "black")
|
||||||
|
updatePreviewWindow()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- click function for the download button in the preview window
|
||||||
|
function onClick_download()
|
||||||
|
placeholder_download(library[contentToShow][currentListItem])
|
||||||
|
end
|
||||||
|
|
||||||
|
-- the download button on the placeholder objects calls this to directly initiate a download
|
||||||
|
---@param param Table contains url and guid of replacement object
|
||||||
|
function placeholder_download(params)
|
||||||
local url = SOURCE_REPO .. '/' .. params.url
|
local url = SOURCE_REPO .. '/' .. params.url
|
||||||
local request = WebRequest.get(url, function (request) complete_obj_download(request, params) end )
|
requestObj = WebRequest.get(url, function (request) contentDownloadCallback(request, params) end)
|
||||||
requestObj = request
|
|
||||||
startLuaCoroutine(Global, 'downloadCoroutine')
|
startLuaCoroutine(Global, 'downloadCoroutine')
|
||||||
end
|
end
|
||||||
|
|
||||||
function onClick_load()
|
function downloadCoroutine()
|
||||||
UI.show('progress_display')
|
-- show progress bar
|
||||||
UI.hide('load_button')
|
UI.setAttribute('download_progress', 'active', true)
|
||||||
|
|
||||||
|
-- update progress bar
|
||||||
|
while requestObj do
|
||||||
|
UI.setAttribute('download_progress', 'percentage', requestObj.download_progress * 100)
|
||||||
|
coroutine.yield(0)
|
||||||
|
end
|
||||||
|
UI.setAttribute('download_progress', 'percentage', 100)
|
||||||
|
|
||||||
|
-- wait 30 frames
|
||||||
|
for i = 1, 30 do
|
||||||
|
coroutine.yield(0)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- hide progress bar
|
||||||
|
UI.setAttribute('download_progress', 'active', false)
|
||||||
|
|
||||||
|
-- hide download window
|
||||||
|
if xmlVisibility.downloadWindow then
|
||||||
|
xmlVisibility.downloadWindow = false
|
||||||
|
UI.hide('downloadWindow')
|
||||||
|
end
|
||||||
|
return 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- spawns a bag that contains every object from the library
|
||||||
|
function onClick_downloadAll()
|
||||||
|
broadcastToAll("Download initiated - this will take a few minutes!")
|
||||||
|
|
||||||
|
-- hide download window
|
||||||
|
if xmlVisibility.downloadWindow then
|
||||||
|
xmlVisibility.downloadWindow = false
|
||||||
|
UI.hide('downloadWindow')
|
||||||
|
end
|
||||||
|
|
||||||
|
startLuaCoroutine(Global, "coroutineDownloadAll")
|
||||||
|
end
|
||||||
|
|
||||||
|
function coroutineDownloadAll()
|
||||||
|
local JSON = [[
|
||||||
|
{
|
||||||
|
"Name": "Bag",
|
||||||
|
"Transform": {
|
||||||
|
"posX": -39.5,
|
||||||
|
"posY": 2,
|
||||||
|
"posZ": -87,
|
||||||
|
"rotX": 0,
|
||||||
|
"rotY": 270,
|
||||||
|
"rotZ": 0,
|
||||||
|
"scaleX": 1.0,
|
||||||
|
"scaleY": 1.0,
|
||||||
|
"scaleZ": 1.0
|
||||||
|
},
|
||||||
|
"Nickname": "All Downloadable Content",
|
||||||
|
"Bag": {
|
||||||
|
"Order": 0
|
||||||
|
},
|
||||||
|
"ContainedObjects": [
|
||||||
|
]]
|
||||||
|
|
||||||
|
local contained = ""
|
||||||
|
local downloadedItems = 0
|
||||||
|
local skippedItems = 0
|
||||||
|
|
||||||
|
-- loop through the library to add content
|
||||||
|
for contentType, objectList in pairs(library) do
|
||||||
|
broadcastToAll("Downloading " .. contentType .. "...")
|
||||||
|
for _, params in ipairs(objectList) do
|
||||||
|
local request = WebRequest.get(SOURCE_REPO .. '/' .. params.url)
|
||||||
|
local start = os.time()
|
||||||
|
while true do
|
||||||
|
if request.is_done then
|
||||||
|
contained = contained .. request.text .. ","
|
||||||
|
downloadedItems = downloadedItems + 1
|
||||||
|
break
|
||||||
|
-- time-out if item can't be loaded in 5s
|
||||||
|
elseif request.is_error or (os.time() - start) > 5 then
|
||||||
|
skippedItems = skippedItems + 1
|
||||||
|
break
|
||||||
|
end
|
||||||
|
coroutine.yield(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
JSON = JSON .. contained .. "]}"
|
||||||
|
spawnObjectJSON({json = JSON})
|
||||||
|
|
||||||
|
broadcastToAll(downloadedItems .. " objects downloaded.", "Green")
|
||||||
|
broadcastToAll(skippedItems .. " objects had a time-out / error.", "Orange")
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- spawns a placeholder box for the selected object
|
||||||
|
function onClick_spawnPlaceholder()
|
||||||
|
-- get object references
|
||||||
|
local item = library[contentToShow][currentListItem]
|
||||||
|
local dummy = guidReferenceApi.getObjectByOwnerAndType("Mythos", "PlaceholderBoxDummy")
|
||||||
|
|
||||||
|
-- error handling
|
||||||
|
if not item.boxsize or item.boxsize == "" or not item.boxart or item.boxart == "" then
|
||||||
|
print("Error loading object.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- get data for placeholder
|
||||||
|
local spawnPos = {-39.5, 2, -87}
|
||||||
|
|
||||||
|
local meshTable = {
|
||||||
|
big = "https://raw.githubusercontent.com/RobMayer/TTSLibrary/master/advboxes/core_h_MSH.obj",
|
||||||
|
small = "https://raw.githubusercontent.com/RobMayer/TTSLibrary/master/advboxes/tuckbox_h_MSH.obj",
|
||||||
|
wide = "http://pastebin.com/raw.php?i=uWAmuNZ2"
|
||||||
|
}
|
||||||
|
|
||||||
|
local scaleTable = {
|
||||||
|
big = {1.00, 0.14, 1.00},
|
||||||
|
small = {2.21, 0.46, 2.42},
|
||||||
|
wide = {2.00, 0.11, 1.69}
|
||||||
|
}
|
||||||
|
|
||||||
|
local placeholder = spawnObject({
|
||||||
|
type = "Custom_Model",
|
||||||
|
position = spawnPos,
|
||||||
|
rotation = {0, 270, 0},
|
||||||
|
scale = scaleTable[item.boxsize],
|
||||||
|
})
|
||||||
|
|
||||||
|
placeholder.setCustomObject({
|
||||||
|
mesh = meshTable[item.boxsize],
|
||||||
|
diffuse = item.boxart,
|
||||||
|
material = 3
|
||||||
|
})
|
||||||
|
|
||||||
|
placeholder.setColorTint({1, 1, 1, 71/255})
|
||||||
|
placeholder.setName(item.name)
|
||||||
|
placeholder.setDescription("by " .. (item.author or "Unknown"))
|
||||||
|
placeholder.setGMNotes(item.url)
|
||||||
|
placeholder.setLuaScript(dummy.getLuaScript())
|
||||||
|
Player.getPlayers()[1].pingTable(spawnPos)
|
||||||
|
|
||||||
|
-- hide download window
|
||||||
|
if xmlVisibility.downloadWindow then
|
||||||
|
xmlVisibility.downloadWindow = false
|
||||||
|
UI.hide('downloadWindow')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- toggles the visibility of the respective UI
|
||||||
|
---@param player LuaPlayer Player that triggered this
|
||||||
|
---@param title String Name of the UI to toggle
|
||||||
function onClick_toggleUi(player, title)
|
function onClick_toggleUi(player, title)
|
||||||
if title == "Navigation Overlay" then
|
if title == "Navigation Overlay" then
|
||||||
navigationOverlayApi.cycleVisibility(player.color)
|
navigationOverlayApi.cycleVisibility(player.color)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
UI.hide('optionPanel')
|
if xmlVisibility[title] then
|
||||||
UI.hide('load_ui')
|
-- small delay to allow button click sounds to play
|
||||||
|
Wait.time(function() UI.hide(title) end, 0.1)
|
||||||
-- when same button is clicked or close window button is pressed, don't open UI
|
|
||||||
if UI.getValue('title') ~= title and title ~= 'Hidden' then
|
|
||||||
UI.setValue('title', title)
|
|
||||||
|
|
||||||
if title == "Options" then
|
|
||||||
UI.show('optionPanel')
|
|
||||||
else
|
|
||||||
update_window_content(title)
|
|
||||||
UI.show('load_ui')
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
UI.setValue('title', "Hidden")
|
UI.show(title)
|
||||||
|
end
|
||||||
|
xmlVisibility[title] = not xmlVisibility[title]
|
||||||
|
end
|
||||||
|
|
||||||
|
-- updates the preview window
|
||||||
|
function updatePreviewWindow()
|
||||||
|
local item = library[contentToShow][currentListItem]
|
||||||
|
local tempImage = "http://cloud-3.steamusercontent.com/ugc/2115061845788345842/2CD6ABC551555CCF58F9D0DDB7620197BA398B06/"
|
||||||
|
|
||||||
|
-- set default image if not defined
|
||||||
|
if item.boxsize == nil or item.boxsize == "" or item.boxart == nil or item.boxart == "" then
|
||||||
|
item.boxsize = "big"
|
||||||
|
item.boxart = "http://cloud-3.steamusercontent.com/ugc/762723517667628371/18438B0A0045038A7099648AA3346DFCAA267C66/"
|
||||||
|
end
|
||||||
|
|
||||||
|
UI.setValue("previewTitle", item.name)
|
||||||
|
UI.setValue("previewAuthor", "by " .. (item.author or "- Author not found -"))
|
||||||
|
UI.setValue("previewDescription", item.description or "- Description not found -")
|
||||||
|
|
||||||
|
-- update mask according to size (hardcoded values to align image in mask)
|
||||||
|
local maskData = {}
|
||||||
|
if item.boxsize == "big" then
|
||||||
|
maskData = {
|
||||||
|
image = "box-cover-mask-big",
|
||||||
|
width = "870",
|
||||||
|
height = "435",
|
||||||
|
offsetXY = "154 60"
|
||||||
|
}
|
||||||
|
elseif item.boxsize == "small" then
|
||||||
|
maskData = {
|
||||||
|
image = "box-cover-mask-small",
|
||||||
|
width = "792",
|
||||||
|
height = "594",
|
||||||
|
offsetXY = "135 13"
|
||||||
|
}
|
||||||
|
elseif item.boxsize == "wide" then
|
||||||
|
maskData = {
|
||||||
|
image = "box-cover-mask-wide",
|
||||||
|
width = "756",
|
||||||
|
height = "630",
|
||||||
|
offsetXY = "-190 -70"
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- loading empty image as placeholder until real image is loaded
|
||||||
|
UI.setAttribute("previewArtImage", "image", tempImage)
|
||||||
|
|
||||||
|
-- insert the image itself
|
||||||
|
UI.setAttribute("previewArtImage", "image", item.boxart)
|
||||||
|
UI.setAttributes("previewArtMask", maskData)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- formats the json response from the webrequest into a key-value lua table
|
||||||
|
-- strips the prefix from the community content items
|
||||||
|
function formatLibrary(json_response)
|
||||||
|
library = {}
|
||||||
|
library["campaigns"] = json_response.campaigns
|
||||||
|
library["scenarios"] = json_response.scenarios
|
||||||
|
library["extras"] = json_response.extras
|
||||||
|
library["fanmadeCampaigns"] = {}
|
||||||
|
library["fanmadeScenarios"] = {}
|
||||||
|
library["fanmadePlayerCards"] = {}
|
||||||
|
|
||||||
|
for _, item in ipairs(json_response.community) do
|
||||||
|
local identifier = nil
|
||||||
|
for str in string.gmatch(item.name, "([^:]+)") do
|
||||||
|
if not identifier then
|
||||||
|
-- grab the first part to know the content type
|
||||||
|
identifier = str
|
||||||
|
else
|
||||||
|
-- update the name without the content type
|
||||||
|
item.name = str
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if identifier == "Fan Investigators" then
|
||||||
|
table.insert(library["fanmadePlayerCards"], item)
|
||||||
|
elseif identifier == "Fan Campaign" then
|
||||||
|
table.insert(library["fanmadeCampaigns"], item)
|
||||||
|
elseif identifier == "Fan Scenario" then
|
||||||
|
table.insert(library["fanmadeScenarios"], item)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function downloadCoroutine()
|
-- updates the window content to the requested content
|
||||||
while requestObj do
|
function updateDownloadItemList()
|
||||||
UI.setAttribute('download_progress', 'percentage', requestObj.download_progress * 100)
|
if not library then return end
|
||||||
coroutine.yield(0)
|
|
||||||
end
|
|
||||||
return 1
|
|
||||||
end
|
|
||||||
|
|
||||||
function update_list(objects)
|
-- addition of list items according to library file
|
||||||
local ui = UI.getXmlTable()
|
local globalXml = UI.getXmlTable()
|
||||||
local update_height = find_tag_with_id(ui, 'ui_update_height')
|
local contentList = getXmlTableElementById(globalXml, 'contentList')
|
||||||
local update_children = find_tag_with_id(update_height.children, 'ui_update_point')
|
|
||||||
|
|
||||||
update_children.children = {}
|
contentList.children = {}
|
||||||
|
for i, v in ipairs(library[contentToShow]) do
|
||||||
for _, v in ipairs(objects) do
|
table.insert(contentList.children,
|
||||||
local s = JSON.encode(v);
|
{
|
||||||
table.insert(update_children.children,
|
tag = "Panel",
|
||||||
{ tag = 'Text',
|
attributes = { id = "panel" .. i },
|
||||||
value = v.name,
|
children = {
|
||||||
attributes = { onClick = 'onClick_select(' .. urlencode(JSON.encode(v)) .. ')', alignment = 'MiddleLeft' }
|
tag = 'Text',
|
||||||
|
value = v.name,
|
||||||
|
attributes = {
|
||||||
|
id = contentToShow .. "_" .. i,
|
||||||
|
onClick = 'onClick_select',
|
||||||
|
alignment = 'MiddleLeft'
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
update_height.attributes.height = #(update_children.children) * 24
|
contentList.attributes.height = #contentList.children * 27
|
||||||
UI.setXmlTable(ui)
|
UI.setXmlTable(globalXml)
|
||||||
|
|
||||||
|
-- select the first item
|
||||||
|
Wait.time(onClick_select, 0.2)
|
||||||
end
|
end
|
||||||
|
|
||||||
function update_window_content(new_title)
|
-- called after the webrequest of downloading an item
|
||||||
if not library then return end
|
-- deletes the placeholder and spawns the downloaded item
|
||||||
|
function contentDownloadCallback(request, params)
|
||||||
|
requestObj = nil
|
||||||
|
|
||||||
if new_title == 'Campaigns' then
|
-- error handling
|
||||||
update_list(library.campaigns)
|
|
||||||
elseif new_title == 'Standalone Scenarios' then
|
|
||||||
update_list(library.scenarios)
|
|
||||||
elseif new_title == 'Investigators' then
|
|
||||||
update_list(library.investigators)
|
|
||||||
elseif new_title == 'Community Content' then
|
|
||||||
update_list(library.community)
|
|
||||||
elseif new_title == 'Extras' then
|
|
||||||
update_list(library.extras)
|
|
||||||
else
|
|
||||||
update_list({})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function complete_obj_download(request, params)
|
|
||||||
assert(request.is_done)
|
|
||||||
if request.is_error or request.response_code ~= 200 then
|
if request.is_error or request.response_code ~= 200 then
|
||||||
print('error: ' .. request.error)
|
print('Error: ' .. request.error)
|
||||||
else
|
return
|
||||||
if pcall(function()
|
end
|
||||||
local replaced_object
|
|
||||||
pcall(function()
|
-- initiate content spawning
|
||||||
if params.replace then
|
local spawnTable = { json = request.text }
|
||||||
replaced_object = getObjectFromGUID(params.replace)
|
if params.replace then
|
||||||
end
|
local replacedObject = getObjectFromGUID(params.replace)
|
||||||
end)
|
if replacedObject then
|
||||||
local json = request.text
|
spawnTable.position = replacedObject.getPosition()
|
||||||
if replaced_object then
|
spawnTable.rotation = replacedObject.getRotation()
|
||||||
local pos = replaced_object.getPosition()
|
spawnTable.scale = replacedObject.getScale()
|
||||||
local rot = replaced_object.getRotation()
|
destroyObject(replacedObject)
|
||||||
destroyObject(replaced_object)
|
|
||||||
Wait.frames(function()
|
|
||||||
spawnObjectJSON({json = json, position = pos, rotation = rot})
|
|
||||||
end, 1)
|
|
||||||
else
|
|
||||||
spawnObjectJSON({json = json})
|
|
||||||
end
|
|
||||||
end) then
|
|
||||||
print('Object loaded.')
|
|
||||||
else
|
|
||||||
print('Error loading object.')
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
requestObj = nil
|
-- if spawned from menu, ping the position
|
||||||
UI.setAttribute('download_progress', 'percentage', 100)
|
if params.name then
|
||||||
end
|
spawnTable["callback_function"] = function(obj)
|
||||||
|
Player.getPlayers()[1].pingTable(obj.getPosition())
|
||||||
-- the download button on the placeholder objects calls this to directly initiate a download
|
|
||||||
-- params is a table with url and guid of replacement object, which happens to match what onClick_select wants
|
|
||||||
function placeholder_download(params)
|
|
||||||
onClick_select(nil, JSON.encode(params))
|
|
||||||
end
|
|
||||||
|
|
||||||
function completed_list_update(request)
|
|
||||||
assert(request.is_done)
|
|
||||||
if request.is_error or request.response_code ~= 200 then
|
|
||||||
print('error: ' .. request.error)
|
|
||||||
else
|
|
||||||
local json_response = nil
|
|
||||||
if pcall(function () json_response = JSON.decode(request.text) end) then
|
|
||||||
library = json_response
|
|
||||||
update_window_content(UI.getValue('title'))
|
|
||||||
else
|
|
||||||
print('error parsing downloaded library')
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
requestObj = nil
|
if pcall(function() spawnObjectJSON(spawnTable) end) then
|
||||||
UI.setAttribute('download_progress', 'percentage', 100)
|
print('Object loaded.')
|
||||||
|
else
|
||||||
|
print('Error loading object.')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function find_tag_with_id(ui, id)
|
-- downloading of the library file
|
||||||
|
function libraryDownloadCallback(request)
|
||||||
|
if request.is_error or request.response_code ~= 200 then
|
||||||
|
print('error: ' .. request.error)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local json_response = nil
|
||||||
|
if pcall(function () json_response = JSON.decode(request.text) end) then
|
||||||
|
formatLibrary(json_response)
|
||||||
|
updateDownloadItemList()
|
||||||
|
else
|
||||||
|
print('error parsing downloaded library')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- loops through an XML table and returns the specified object
|
||||||
|
---@param ui Table XmlTable (get this via getXmlTable)
|
||||||
|
---@param id String Id of the object to return
|
||||||
|
function getXmlTableElementById(ui, id)
|
||||||
for _, obj in ipairs(ui) do
|
for _, obj in ipairs(ui) do
|
||||||
if obj.attributes and obj.attributes.id and obj.attributes.id == id then return obj end
|
if obj.attributes and obj.attributes.id and obj.attributes.id == id then return obj end
|
||||||
if obj.children then
|
if obj.children then
|
||||||
local result = find_tag_with_id(obj.children, id)
|
local result = getXmlTableElementById(obj.children, id)
|
||||||
if result then return result end
|
if result then return result end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function urlencode(str)
|
|
||||||
local str = string.gsub(str, "([^A-Za-z0-9-_.~])",
|
|
||||||
function (c) return string.format("%%%02X", string.byte(c)) end)
|
|
||||||
return str
|
|
||||||
end
|
|
||||||
|
|
||||||
function urldecode(str)
|
|
||||||
local str = string.gsub(str, "%%(%x%x)",
|
|
||||||
function (h) return string.char(tonumber(h, 16)) end)
|
|
||||||
return str
|
|
||||||
end
|
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
-- Option Panel related functionality
|
-- Option Panel related functionality
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
@ -875,7 +1125,8 @@ function applyOptionPanelChange(id, state)
|
|||||||
optionPanel[id] = state
|
optionPanel[id] = state
|
||||||
|
|
||||||
-- update master clue counter
|
-- update master clue counter
|
||||||
getObjectFromGUID("4a3aa4").setVar("useClickableCounters", state)
|
local counter = guidReferenceApi.getObjectByOwnerAndType("Mythos", "MasterClueCounter")
|
||||||
|
counter.setVar("useClickableCounters", state)
|
||||||
|
|
||||||
-- option: Play area snap tags
|
-- option: Play area snap tags
|
||||||
elseif id == "playAreaSnapTags" then
|
elseif id == "playAreaSnapTags" then
|
||||||
@ -944,8 +1195,9 @@ end
|
|||||||
-- copies the specified tool (by name) from the option panel source bag
|
-- copies the specified tool (by name) from the option panel source bag
|
||||||
---@param name String Name of the object that should be copied
|
---@param name String Name of the object that should be copied
|
||||||
---@param position Table Desired position of the object
|
---@param position Table Desired position of the object
|
||||||
|
---@param rotation Table Desired rotation of the object (defaults to object's rotation)
|
||||||
function spawnHelperObject(name, position, rotation)
|
function spawnHelperObject(name, position, rotation)
|
||||||
local sourceBag = getObjectFromGUID("830bd0")
|
local sourceBag = guidReferenceApi.getObjectByOwnerAndType("Mythos","OptionPanelSource")
|
||||||
|
|
||||||
-- error handling for missing sourceBag
|
-- error handling for missing sourceBag
|
||||||
if not sourceBag then
|
if not sourceBag then
|
||||||
@ -953,7 +1205,7 @@ function spawnHelperObject(name, position, rotation)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local spawnTable = {position = position}
|
local spawnTable = { position = position }
|
||||||
|
|
||||||
-- only overrride rotation if there is one provided (object's rotation used instead)
|
-- only overrride rotation if there is one provided (object's rotation used instead)
|
||||||
if rotation then
|
if rotation then
|
||||||
@ -1046,7 +1298,6 @@ end
|
|||||||
-- splash scenario title on setup
|
-- splash scenario title on setup
|
||||||
function titleSplash(scenarioName)
|
function titleSplash(scenarioName)
|
||||||
if optionPanel['showTitleSplash'] then
|
if optionPanel['showTitleSplash'] then
|
||||||
|
|
||||||
-- if there's any ongoing title being displayed, hide it and cancel the waiting function
|
-- if there's any ongoing title being displayed, hide it and cancel the waiting function
|
||||||
if hideTitleSplashWaitFunctionId then
|
if hideTitleSplashWaitFunctionId then
|
||||||
Wait.stop(hideTitleSplashWaitFunctionId)
|
Wait.stop(hideTitleSplashWaitFunctionId)
|
||||||
@ -1088,7 +1339,7 @@ function compareVersion(request)
|
|||||||
|
|
||||||
-- stop here if on latest version
|
-- stop here if on latest version
|
||||||
if MOD_VERSION == modMeta["latestVersion"] then return end
|
if MOD_VERSION == modMeta["latestVersion"] then return end
|
||||||
|
|
||||||
-- stop here if "don't show again" was clicked for this version before
|
-- stop here if "don't show again" was clicked for this version before
|
||||||
if acknowledgedUpgradeVersions[modMeta["latestVersion"]] then return end
|
if acknowledgedUpgradeVersions[modMeta["latestVersion"]] then return end
|
||||||
|
|
||||||
@ -1110,25 +1361,14 @@ function updateNotificationLoading()
|
|||||||
highlightText = highlightText .. "\n• " .. entry
|
highlightText = highlightText .. "\n• " .. entry
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- update the XML UI
|
-- update the XML UI
|
||||||
UI.setValue("notificationHeader", "New version available: ".. modMeta["latestVersion"])
|
UI.setValue("notificationHeader", "New version available: " .. modMeta["latestVersion"])
|
||||||
UI.setValue("releaseHighlightText", highlightText)
|
UI.setValue("releaseHighlightText", highlightText)
|
||||||
UI.setAttribute("highlightRow", "preferredHeight", 20*#highlights)
|
UI.setAttribute("highlightRow", "preferredHeight", 20*#highlights)
|
||||||
UI.setAttribute("updateNotification", "height", 20*#highlights + 125)
|
UI.setAttribute("updateNotification", "height", 20*#highlights + 125)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- triggered by clicking on the Finn Icon
|
|
||||||
function onClick_FinnIcon()
|
|
||||||
if notificationVisible then
|
|
||||||
UI.hide("updateNotification")
|
|
||||||
notificationVisible = false
|
|
||||||
else
|
|
||||||
UI.show("updateNotification")
|
|
||||||
notificationVisible = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- close / don't show again buttons on the update notification
|
-- close / don't show again buttons on the update notification
|
||||||
function onClick_notification(_, parameter)
|
function onClick_notification(_, parameter)
|
||||||
if parameter == "dontShowAgain" then
|
if parameter == "dontShowAgain" then
|
||||||
@ -1137,4 +1377,5 @@ function onClick_notification(_, parameter)
|
|||||||
end
|
end
|
||||||
UI.hide("FinnIcon")
|
UI.hide("FinnIcon")
|
||||||
UI.hide("updateNotification")
|
UI.hide("updateNotification")
|
||||||
|
xmlVisibility["updateNotification"] = false
|
||||||
end
|
end
|
||||||
|
@ -20,11 +20,10 @@ function onLoad(savedData)
|
|||||||
width = 900,
|
width = 900,
|
||||||
scale = { 1.5, 1.5, 1.5 },
|
scale = { 1.5, 1.5, 1.5 },
|
||||||
font_size = 650,
|
font_size = 650,
|
||||||
font_color = { 0, 0, 0, 100 },
|
font_color = { 1, 1, 1, 100 },
|
||||||
color = { 0, 0, 0, 0 }
|
color = { 0, 0, 0, 0 }
|
||||||
})
|
})
|
||||||
|
Wait.time(sumClues, 2, -1)
|
||||||
loopID = Wait.time(sumClues, 2, -1)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- removes all player clues by calling the respective function from the counting bowls / clickers
|
-- removes all player clues by calling the respective function from the counting bowls / clickers
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||||
local playAreaApi = require("core/PlayAreaApi")
|
local playAreaApi = require("core/PlayAreaApi")
|
||||||
local tokenArrangerApi = require("accessories/TokenArrangerApi")
|
local tokenArrangerApi = require("accessories/TokenArrangerApi")
|
||||||
local tokenChecker = require("core/token/TokenChecker")
|
local tokenChecker = require("core/token/TokenChecker")
|
||||||
@ -20,11 +21,8 @@ local isReshuffling = false
|
|||||||
-- scenario metadata
|
-- scenario metadata
|
||||||
local currentScenario, useFrontData, tokenData
|
local currentScenario, useFrontData, tokenData
|
||||||
|
|
||||||
-- GUID of data helper
|
-- object references
|
||||||
local DATA_HELPER_GUID = "708279"
|
local TRASH, DATA_HELPER
|
||||||
|
|
||||||
local TRASHCAN
|
|
||||||
local TRASHCAN_GUID = "70b9f6"
|
|
||||||
|
|
||||||
-- we use this to turn off collision handling until onLoad() is complete
|
-- we use this to turn off collision handling until onLoad() is complete
|
||||||
local collisionEnabled = false
|
local collisionEnabled = false
|
||||||
@ -36,7 +34,8 @@ function onLoad(saveState)
|
|||||||
useFrontData = loadedState.useFrontData or true
|
useFrontData = loadedState.useFrontData or true
|
||||||
tokenData = loadedState.tokenData or {}
|
tokenData = loadedState.tokenData or {}
|
||||||
end
|
end
|
||||||
TRASHCAN = getObjectFromGUID(TRASHCAN_GUID)
|
TRASH = guidReferenceApi.getObjectByOwnerAndType("Mythos", "Trash")
|
||||||
|
DATA_HELPER = guidReferenceApi.getObjectByOwnerAndType("Mythos", "DataHelper")
|
||||||
collisionEnabled = true
|
collisionEnabled = true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -153,7 +152,7 @@ function actualEncounterCardDraw(card, params)
|
|||||||
local faceUpRotation = 0
|
local faceUpRotation = 0
|
||||||
if not params.alwaysFaceUp then
|
if not params.alwaysFaceUp then
|
||||||
local metadata = JSON.decode(card.getGMNotes()) or {}
|
local metadata = JSON.decode(card.getGMNotes()) or {}
|
||||||
if metadata.hidden or getObjectFromGUID(DATA_HELPER_GUID).call('checkHiddenCard', card.getName()) then
|
if metadata.hidden or DATA_HELPER.call('checkHiddenCard', card.getName()) then
|
||||||
faceUpRotation = 180
|
faceUpRotation = 180
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -209,7 +208,7 @@ function removeTokensFromObject(object)
|
|||||||
obj.memo ~= nil and
|
obj.memo ~= nil and
|
||||||
obj.getLock() == false and
|
obj.getLock() == false and
|
||||||
not tokenChecker.isChaosToken(obj) then
|
not tokenChecker.isChaosToken(obj) then
|
||||||
TRASHCAN.putObject(obj)
|
TRASH.putObject(obj)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,15 +1,19 @@
|
|||||||
do
|
do
|
||||||
local MythosAreaApi = {}
|
local MythosAreaApi = {}
|
||||||
local MYTHOS_AREA_GUID = "9f334f"
|
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||||
|
|
||||||
|
local function getMythosArea()
|
||||||
|
return guidReferenceApi.getObjectByOwnerAndType("Mythos", "MythosArea")
|
||||||
|
end
|
||||||
|
|
||||||
-- returns the chaos token metadata (if provided through scenario reference card)
|
-- returns the chaos token metadata (if provided through scenario reference card)
|
||||||
MythosAreaApi.returnTokenData = function()
|
MythosAreaApi.returnTokenData = function()
|
||||||
return getObjectFromGUID(MYTHOS_AREA_GUID).call("returnTokenData")
|
return getMythosArea().call("returnTokenData")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- draw an encounter card to the requested position/rotation
|
-- draw an encounter card to the requested position/rotation
|
||||||
MythosAreaApi.drawEncounterCard = function(pos, rotY, alwaysFaceUp)
|
MythosAreaApi.drawEncounterCard = function(pos, rotY, alwaysFaceUp)
|
||||||
getObjectFromGUID(MYTHOS_AREA_GUID).call("drawEncounterCard", {
|
getMythosArea().call("drawEncounterCard", {
|
||||||
pos = pos,
|
pos = pos,
|
||||||
rotY = rotY,
|
rotY = rotY,
|
||||||
alwaysFaceUp = alwaysFaceUp
|
alwaysFaceUp = alwaysFaceUp
|
||||||
|
@ -1,21 +1,25 @@
|
|||||||
do
|
do
|
||||||
local NavigationOverlayApi = {}
|
local NavigationOverlayApi = {}
|
||||||
local HANDLER_GUID = "797ede"
|
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||||
|
|
||||||
|
local function getNOHandler()
|
||||||
|
return guidReferenceApi.getObjectByOwnerAndType("Mythos", "NavigationOverlayHandler")
|
||||||
|
end
|
||||||
|
|
||||||
-- Copies the visibility for the Navigation overlay
|
-- Copies the visibility for the Navigation overlay
|
||||||
---@param startColor String Color of the player to copy from
|
---@param startColor String Color of the player to copy from
|
||||||
---@param targetColor String Color of the targeted player
|
---@param targetColor String Color of the targeted player
|
||||||
NavigationOverlayApi.copyVisibility = function(startColor, targetColor)
|
NavigationOverlayApi.copyVisibility = function(startColor, targetColor)
|
||||||
getObjectFromGUID(HANDLER_GUID).call("copyVisibility", {
|
getNOHandler().call("copyVisibility", {
|
||||||
startColor = startColor,
|
startColor = startColor,
|
||||||
targetColor = targetColor
|
targetColor = targetColor
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Changes the Navigation Overlay view ("Full View" --> "Play Areas" --> "Closed" etc.)
|
-- Changes the Navigation Overlay view ("Full View" --> "Play Areas" --> "Closed" etc.)
|
||||||
---@param playerColor String Color of the player to update the visibility for
|
---@param playerColor String Color of the player to update the visibility for
|
||||||
NavigationOverlayApi.cycleVisibility = function(playerColor)
|
NavigationOverlayApi.cycleVisibility = function(playerColor)
|
||||||
getObjectFromGUID(HANDLER_GUID).call("cycleVisibility", playerColor)
|
getNOHandler().call("cycleVisibility", playerColor)
|
||||||
end
|
end
|
||||||
|
|
||||||
return NavigationOverlayApi
|
return NavigationOverlayApi
|
||||||
|
@ -328,7 +328,7 @@ function loadCamera(player, index)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- search on the playmat for objects
|
-- search on the playmat for objects
|
||||||
local bounds = getDynamicViewBounds(playmatApi.searchPlaymat(matColor))
|
local bounds = getDynamicViewBounds(playmatApi.searchAroundPlaymat(matColor))
|
||||||
|
|
||||||
lookHere = {
|
lookHere = {
|
||||||
position = { bounds.middleX, 0, bounds.middleZ },
|
position = { bounds.middleX, 0, bounds.middleZ },
|
||||||
|
@ -3,60 +3,60 @@
|
|||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
-- Location connection directional options
|
-- Location connection directional options
|
||||||
local BIDIRECTIONAL = 0
|
local BIDIRECTIONAL = 0
|
||||||
local ONE_WAY = 1
|
local ONE_WAY = 1
|
||||||
local INCOMING_ONE_WAY = 2
|
local INCOMING_ONE_WAY = 2
|
||||||
|
|
||||||
-- Connector draw parameters
|
-- Connector draw parameters
|
||||||
local CONNECTION_THICKNESS = 0.015
|
local CONNECTION_THICKNESS = 0.015
|
||||||
local DRAGGING_CONNECTION_THICKNESS = 0.15
|
local DRAGGING_CONNECTION_THICKNESS = 0.15
|
||||||
local DRAGGING_CONNECTION_COLOR = { 0.8, 0.8, 0.8, 1 }
|
local DRAGGING_CONNECTION_COLOR = { 0.8, 0.8, 0.8, 1 }
|
||||||
local CONNECTION_COLOR = { 0.4, 0.4, 0.4, 1 }
|
local CONNECTION_COLOR = { 0.4, 0.4, 0.4, 1 }
|
||||||
local DIRECTIONAL_ARROW_DISTANCE = 3.5
|
local DIRECTIONAL_ARROW_DISTANCE = 3.5
|
||||||
local ARROW_ARM_LENGTH = 0.9
|
local ARROW_ARM_LENGTH = 0.9
|
||||||
local ARROW_ANGLE = 25
|
local ARROW_ANGLE = 25
|
||||||
|
|
||||||
-- Height to draw the connector lines, places them just above the table and always below cards
|
-- Height to draw the connector lines, places them just above the table and always below cards
|
||||||
local CONNECTION_LINE_Y = 1.529
|
local CONNECTION_LINE_Y = 1.529
|
||||||
|
|
||||||
-- we use this to turn off collision handling until onLoad() is complete
|
-- we use this to turn off collision handling until onLoad() is complete
|
||||||
local collisionEnabled = false
|
local collisionEnabled = false
|
||||||
|
|
||||||
-- used for recreating the link to a custom data helper after image change
|
-- used for recreating the link to a custom data helper after image change
|
||||||
customDataHelper = nil
|
customDataHelper = nil
|
||||||
|
|
||||||
local DEFAULT_URL = "http://cloud-3.steamusercontent.com/ugc/998015670465071049/FFAE162920D67CF38045EFBD3B85AD0F916147B2/"
|
local DEFAULT_URL =
|
||||||
|
"http://cloud-3.steamusercontent.com/ugc/998015670465071049/FFAE162920D67CF38045EFBD3B85AD0F916147B2/"
|
||||||
|
|
||||||
local SHIFT_OFFSETS = {
|
local SHIFT_OFFSETS = {
|
||||||
left = { x = 0.00, y = 0, z = 7.67 },
|
left = { x = 0.00, y = 0, z = 7.67 },
|
||||||
right = { x = 0.00, y = 0, z = -7.67 },
|
right = { x = 0.00, y = 0, z = -7.67 },
|
||||||
up = { x = 6.54, y = 0, z = 0.00 },
|
up = { x = 6.54, y = 0, z = 0.00 },
|
||||||
down = { x = -6.54, y = 0, z = 0.00 }
|
down = { x = -6.54, y = 0, z = 0.00 }
|
||||||
}
|
}
|
||||||
local SHIFT_EXCLUSION = {
|
local SHIFT_EXCLUSION = {
|
||||||
["b7b45b"] = true,
|
["b7b45b"] = true,
|
||||||
["f182ee"] = true,
|
["f182ee"] = true,
|
||||||
["721ba2"] = true
|
["721ba2"] = true
|
||||||
}
|
}
|
||||||
local LOC_LINK_EXCLUDE_SCENARIOS = {
|
local LOC_LINK_EXCLUDE_SCENARIOS = {
|
||||||
["The Witching Hour"] = true,
|
["The Witching Hour"] = true,
|
||||||
["The Heart of Madness"] = true
|
["The Heart of Madness"] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
local tokenManager = require("core/token/TokenManager")
|
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||||
local INVESTIGATOR_COUNTER_GUID = "f182ee"
|
local tokenManager = require("core/token/TokenManager")
|
||||||
local PLAY_AREA_ZONE_GUID = "a2f932"
|
|
||||||
|
|
||||||
local clueData = {}
|
local clueData = {}
|
||||||
local spawnedLocationGUIDs = {}
|
local spawnedLocationGUIDs = {}
|
||||||
local locations = {}
|
local locations = {}
|
||||||
local locationConnections = {}
|
local locationConnections = {}
|
||||||
local draggingGuids = {}
|
local draggingGuids = {}
|
||||||
local locationData
|
local locationData
|
||||||
local currentScenario
|
local currentScenario
|
||||||
|
|
||||||
local missingData = {}
|
local missingData = {}
|
||||||
local countedVP = {}
|
local countedVP = {}
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
-- general code
|
-- general code
|
||||||
@ -71,8 +71,8 @@ end
|
|||||||
|
|
||||||
function onLoad(saveState)
|
function onLoad(saveState)
|
||||||
-- records locations we have spawned clues for
|
-- records locations we have spawned clues for
|
||||||
local save = JSON.decode(saveState) or { }
|
local save = JSON.decode(saveState) or {}
|
||||||
locations = save.trackedLocations or { }
|
locations = save.trackedLocations or {}
|
||||||
currentScenario = save.currentScenario
|
currentScenario = save.currentScenario
|
||||||
|
|
||||||
self.interactable = false
|
self.interactable = false
|
||||||
@ -93,13 +93,13 @@ function updateSurface(newURL)
|
|||||||
local customInfo = self.getCustomObject()
|
local customInfo = self.getCustomObject()
|
||||||
|
|
||||||
if newURL ~= "" and newURL ~= nil and newURL ~= DEFAULT_URL then
|
if newURL ~= "" and newURL ~= nil and newURL ~= DEFAULT_URL then
|
||||||
customInfo.image = newURL
|
customInfo.image = newURL
|
||||||
broadcastToAll("New Playmat Image Applied", { 0.2, 0.9, 0.2 })
|
broadcastToAll("New Playmat Image Applied", { 0.2, 0.9, 0.2 })
|
||||||
else
|
else
|
||||||
customInfo.image = DEFAULT_URL
|
customInfo.image = DEFAULT_URL
|
||||||
broadcastToAll("Default Playmat Image Applied", { 0.2, 0.9, 0.2 })
|
broadcastToAll("Default Playmat Image Applied", { 0.2, 0.9, 0.2 })
|
||||||
end
|
end
|
||||||
|
|
||||||
self.setCustomObject(customInfo)
|
self.setCustomObject(customInfo)
|
||||||
|
|
||||||
local guid = nil
|
local guid = nil
|
||||||
@ -108,7 +108,7 @@ function updateSurface(newURL)
|
|||||||
self.reload()
|
self.reload()
|
||||||
|
|
||||||
if guid ~= nil then
|
if guid ~= nil then
|
||||||
Wait.time(function() updateLocations({ guid }) end, 1)
|
Wait.time(function() updateLocations({ guid }) end, 1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -129,12 +129,14 @@ function onCollisionEnter(collisionInfo)
|
|||||||
if shouldSpawnTokens(card) then
|
if shouldSpawnTokens(card) then
|
||||||
tokenManager.spawnForCard(card)
|
tokenManager.spawnForCard(card)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- If this card was being dragged, clear the dragging connections. A multi-drag/drop may send
|
-- If this card was being dragged, clear the dragging connections. A multi-drag/drop may send
|
||||||
-- the dropped card immediately into a deck, so this has to be done here
|
-- the dropped card immediately into a deck, so this has to be done here
|
||||||
if draggingGuids[card.getGUID()] ~= nil then
|
if draggingGuids[card.getGUID()] ~= nil then
|
||||||
card.setVectorLines(nil)
|
card.setVectorLines(nil)
|
||||||
draggingGuids[card.getGUID()] = nil
|
draggingGuids[card.getGUID()] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
maybeTrackLocation(card)
|
maybeTrackLocation(card)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -167,20 +169,20 @@ function onObjectPickUp(player, object)
|
|||||||
-- should be tracking
|
-- should be tracking
|
||||||
if showLocationLinks() and isInPlayArea(object) and object.getGMNotes() ~= nil and object.getGMNotes() ~= "" then
|
if showLocationLinks() and isInPlayArea(object) and object.getGMNotes() ~= nil and object.getGMNotes() ~= "" then
|
||||||
local pickedUpGuid = object.getGUID()
|
local pickedUpGuid = object.getGUID()
|
||||||
local metadata = JSON.decode(object.getGMNotes()) or { }
|
local metadata = JSON.decode(object.getGMNotes()) or {}
|
||||||
if metadata.type == "Location" then
|
if metadata.type == "Location" then
|
||||||
-- onCollisionExit sometimes comes 1 frame after onObjectPickUp (rather than before it or in
|
-- onCollisionExit sometimes comes 1 frame after onObjectPickUp (rather than before it or in
|
||||||
-- the same frame). This causes a mismatch in the data between dragging the on-table, and
|
-- the same frame). This causes a mismatch in the data between dragging the on-table, and
|
||||||
-- that one frame draws connectors on the card which then show up as shadows for snap points.
|
-- that one frame draws connectors on the card which then show up as shadows for snap points.
|
||||||
-- Waiting ensures we always do thing in the expected Exit->PickUp order
|
-- Waiting ensures we always do thing in the expected Exit->PickUp order
|
||||||
Wait.frames(function()
|
Wait.frames(function()
|
||||||
if object.is_face_down then
|
if object.is_face_down then
|
||||||
draggingGuids[pickedUpGuid] = metadata.locationBack
|
draggingGuids[pickedUpGuid] = metadata.locationBack
|
||||||
else
|
else
|
||||||
draggingGuids[pickedUpGuid] = metadata.locationFront
|
draggingGuids[pickedUpGuid] = metadata.locationFront
|
||||||
end
|
end
|
||||||
rebuildConnectionList()
|
rebuildConnectionList()
|
||||||
end, 2)
|
end, 2)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -273,11 +275,11 @@ end
|
|||||||
-- drawBaseConnections()
|
-- drawBaseConnections()
|
||||||
function rebuildConnectionList()
|
function rebuildConnectionList()
|
||||||
if not showLocationLinks() then
|
if not showLocationLinks() then
|
||||||
locationConnections = { }
|
locationConnections = {}
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local iconCardList = { }
|
local iconCardList = {}
|
||||||
|
|
||||||
-- Build a list of cards with each icon as their location ID
|
-- Build a list of cards with each icon as their location ID
|
||||||
for cardId, metadata in pairs(draggingGuids) do
|
for cardId, metadata in pairs(draggingGuids) do
|
||||||
@ -288,7 +290,7 @@ function rebuildConnectionList()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Pair up all the icons
|
-- Pair up all the icons
|
||||||
locationConnections = { }
|
locationConnections = {}
|
||||||
for cardId, metadata in pairs(draggingGuids) do
|
for cardId, metadata in pairs(draggingGuids) do
|
||||||
buildConnection(cardId, iconCardList, metadata)
|
buildConnection(cardId, iconCardList, metadata)
|
||||||
end
|
end
|
||||||
@ -307,7 +309,7 @@ function buildLocListByIcon(cardId, iconCardList, locData)
|
|||||||
if locData ~= nil and locData.icons ~= nil then
|
if locData ~= nil and locData.icons ~= nil then
|
||||||
for icon in string.gmatch(locData.icons, "%a+") do
|
for icon in string.gmatch(locData.icons, "%a+") do
|
||||||
if iconCardList[icon] == nil then
|
if iconCardList[icon] == nil then
|
||||||
iconCardList[icon] = { }
|
iconCardList[icon] = {}
|
||||||
end
|
end
|
||||||
table.insert(iconCardList[icon], cardId)
|
table.insert(iconCardList[icon], cardId)
|
||||||
end
|
end
|
||||||
@ -321,19 +323,19 @@ end
|
|||||||
---@param locData Table A table containing the metadata for the card (for the correct side)
|
---@param locData Table A table containing the metadata for the card (for the correct side)
|
||||||
function buildConnection(cardId, iconCardList, locData)
|
function buildConnection(cardId, iconCardList, locData)
|
||||||
if locData ~= nil and locData.connections ~= nil then
|
if locData ~= nil and locData.connections ~= nil then
|
||||||
locationConnections[cardId] = { }
|
locationConnections[cardId] = {}
|
||||||
for icon in string.gmatch(locData.connections, "%a+") do
|
for icon in string.gmatch(locData.connections, "%a+") do
|
||||||
if iconCardList[icon] ~= nil then
|
if iconCardList[icon] ~= nil then
|
||||||
for _, connectedGuid in ipairs(iconCardList[icon]) do
|
for _, connectedGuid in ipairs(iconCardList[icon]) do
|
||||||
-- If the reciprocal exists, convert it to BiDi, otherwise add as a one-way
|
-- If the reciprocal exists, convert it to BiDi, otherwise add as a one-way
|
||||||
if locationConnections[connectedGuid] ~= nil
|
if locationConnections[connectedGuid] ~= nil
|
||||||
and (locationConnections[connectedGuid][cardId] == ONE_WAY
|
and (locationConnections[connectedGuid][cardId] == ONE_WAY
|
||||||
or locationConnections[connectedGuid][cardId] == BIDIRECTIONAL) then
|
or locationConnections[connectedGuid][cardId] == BIDIRECTIONAL) then
|
||||||
locationConnections[connectedGuid][cardId] = BIDIRECTIONAL
|
locationConnections[connectedGuid][cardId] = BIDIRECTIONAL
|
||||||
locationConnections[cardId][connectedGuid] = nil
|
locationConnections[cardId][connectedGuid] = nil
|
||||||
else
|
else
|
||||||
if locationConnections[connectedGuid] == nil then
|
if locationConnections[connectedGuid] == nil then
|
||||||
locationConnections[connectedGuid] = { }
|
locationConnections[connectedGuid] = {}
|
||||||
end
|
end
|
||||||
locationConnections[cardId][connectedGuid] = ONE_WAY
|
locationConnections[cardId][connectedGuid] = ONE_WAY
|
||||||
locationConnections[connectedGuid][cardId] = INCOMING_ONE_WAY
|
locationConnections[connectedGuid][cardId] = INCOMING_ONE_WAY
|
||||||
@ -348,10 +350,10 @@ end
|
|||||||
-- Constructed vectors will be set to the playmat
|
-- Constructed vectors will be set to the playmat
|
||||||
function drawBaseConnections()
|
function drawBaseConnections()
|
||||||
if not showLocationLinks() then
|
if not showLocationLinks() then
|
||||||
locationConnections = { }
|
locationConnections = {}
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local cardConnectionLines = { }
|
local cardConnectionLines = {}
|
||||||
|
|
||||||
for originGuid, targetGuids in pairs(locationConnections) do
|
for originGuid, targetGuids in pairs(locationConnections) do
|
||||||
-- Objects should reliably exist at this point, but since this can be called during onUpdate the
|
-- Objects should reliably exist at this point, but since this can be called during onUpdate the
|
||||||
@ -380,8 +382,8 @@ function drawDraggingConnections()
|
|||||||
if not showLocationLinks() then
|
if not showLocationLinks() then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local cardConnectionLines = { }
|
local cardConnectionLines = {}
|
||||||
local ownedVectors = { }
|
local ownedVectors = {}
|
||||||
|
|
||||||
for originGuid, _ in pairs(draggingGuids) do
|
for originGuid, _ in pairs(draggingGuids) do
|
||||||
targetGuids = locationConnections[originGuid]
|
targetGuids = locationConnections[originGuid]
|
||||||
@ -389,7 +391,7 @@ function drawDraggingConnections()
|
|||||||
-- object checks are conservative just to make sure.
|
-- object checks are conservative just to make sure.
|
||||||
local origin = getObjectFromGUID(originGuid)
|
local origin = getObjectFromGUID(originGuid)
|
||||||
if draggingGuids[originGuid] and origin ~= nil and targetGuids ~= nil then
|
if draggingGuids[originGuid] and origin ~= nil and targetGuids ~= nil then
|
||||||
ownedVectors[originGuid] = { }
|
ownedVectors[originGuid] = {}
|
||||||
for targetGuid, direction in pairs(targetGuids) do
|
for targetGuid, direction in pairs(targetGuids) do
|
||||||
local target = getObjectFromGUID(targetGuid)
|
local target = getObjectFromGUID(targetGuid)
|
||||||
if target != nil then
|
if target != nil then
|
||||||
@ -427,9 +429,9 @@ function addBidirectionalVector(card1, card2, vectorOwner, lines)
|
|||||||
local pos2 = vectorOwner.positionToLocal(cardPos2)
|
local pos2 = vectorOwner.positionToLocal(cardPos2)
|
||||||
|
|
||||||
table.insert(lines, {
|
table.insert(lines, {
|
||||||
points = { pos1, pos2 },
|
points = { pos1, pos2 },
|
||||||
color = vectorOwner == self and CONNECTION_COLOR or DRAGGING_CONNECTION_COLOR,
|
color = vectorOwner == self and CONNECTION_COLOR or DRAGGING_CONNECTION_COLOR,
|
||||||
thickness = vectorOwner == self and CONNECTION_THICKNESS or DRAGGING_CONNECTION_THICKNESS,
|
thickness = vectorOwner == self and CONNECTION_THICKNESS or DRAGGING_CONNECTION_THICKNESS,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -451,11 +453,13 @@ function addOneWayVector(origin, target, vectorOwner, lines)
|
|||||||
-- Calculate card distance to be closer for horizontal positions than vertical, since cards are
|
-- Calculate card distance to be closer for horizontal positions than vertical, since cards are
|
||||||
-- taller than they are wide
|
-- taller than they are wide
|
||||||
local heading = Vector(originPos):sub(targetPos):heading("y")
|
local heading = Vector(originPos):sub(targetPos):heading("y")
|
||||||
local distanceFromCard = DIRECTIONAL_ARROW_DISTANCE * 0.7 + DIRECTIONAL_ARROW_DISTANCE * 0.3 * math.abs(math.sin(math.rad(heading)))
|
local distanceFromCard = DIRECTIONAL_ARROW_DISTANCE * 0.7 +
|
||||||
|
DIRECTIONAL_ARROW_DISTANCE * 0.3 * math.abs(math.sin(math.rad(heading)))
|
||||||
|
|
||||||
-- Calculate the three possible arrow positions. These are offset by half the arrow length to
|
-- Calculate the three possible arrow positions. These are offset by half the arrow length to
|
||||||
-- make them visually balanced by keeping the arrows centered, not tracking the point
|
-- make them visually balanced by keeping the arrows centered, not tracking the point
|
||||||
local midpoint = Vector(originPos):add(targetPos):scale(Vector(0.5, 0.5, 0.5)):moveTowards(targetPos, ARROW_ARM_LENGTH / 2)
|
local midpoint = Vector(originPos):add(targetPos):scale(Vector(0.5, 0.5, 0.5)):moveTowards(targetPos,
|
||||||
|
ARROW_ARM_LENGTH / 2)
|
||||||
local closeToOrigin = Vector(originPos):moveTowards(targetPos, distanceFromCard + ARROW_ARM_LENGTH / 2)
|
local closeToOrigin = Vector(originPos):moveTowards(targetPos, distanceFromCard + ARROW_ARM_LENGTH / 2)
|
||||||
local closeToTarget = Vector(targetPos):moveTowards(originPos, distanceFromCard - ARROW_ARM_LENGTH / 2)
|
local closeToTarget = Vector(targetPos):moveTowards(originPos, distanceFromCard - ARROW_ARM_LENGTH / 2)
|
||||||
|
|
||||||
@ -474,14 +478,16 @@ end
|
|||||||
--- positioning and scaling, as well as highlighting connections during a drag operation
|
--- positioning and scaling, as well as highlighting connections during a drag operation
|
||||||
---@param lines Table List of vector line elements. Mutable, will be updated to add this arrow
|
---@param lines Table List of vector line elements. Mutable, will be updated to add this arrow
|
||||||
function addArrowLines(arrowheadPos, originPos, vectorOwner, lines)
|
function addArrowLines(arrowheadPos, originPos, vectorOwner, lines)
|
||||||
local arrowArm1 = Vector(arrowheadPos):moveTowards(originPos, ARROW_ARM_LENGTH):sub(arrowheadPos):rotateOver("y", -1 * ARROW_ANGLE):add(arrowheadPos)
|
local arrowArm1 = Vector(arrowheadPos):moveTowards(originPos, ARROW_ARM_LENGTH):sub(arrowheadPos):rotateOver("y",
|
||||||
local arrowArm2 = Vector(arrowheadPos):moveTowards(originPos, ARROW_ARM_LENGTH):sub(arrowheadPos):rotateOver("y", ARROW_ANGLE):add(arrowheadPos)
|
-1 * ARROW_ANGLE):add(arrowheadPos)
|
||||||
|
local arrowArm2 = Vector(arrowheadPos):moveTowards(originPos, ARROW_ARM_LENGTH):sub(arrowheadPos):rotateOver("y",
|
||||||
|
ARROW_ANGLE):add(arrowheadPos)
|
||||||
|
|
||||||
local head = vectorOwner.positionToLocal(arrowheadPos)
|
local head = vectorOwner.positionToLocal(arrowheadPos)
|
||||||
local arm1 = vectorOwner.positionToLocal(arrowArm1)
|
local arm1 = vectorOwner.positionToLocal(arrowArm1)
|
||||||
local arm2 = vectorOwner.positionToLocal(arrowArm2)
|
local arm2 = vectorOwner.positionToLocal(arrowArm2)
|
||||||
table.insert(lines, {
|
table.insert(lines, {
|
||||||
points = { arm1, head, arm2},
|
points = { arm1, head, arm2 },
|
||||||
color = vectorOwner == self and CONNECTION_COLOR or DRAGGING_CONNECTION_COLOR,
|
color = vectorOwner == self and CONNECTION_COLOR or DRAGGING_CONNECTION_COLOR,
|
||||||
thickness = vectorOwner == self and CONNECTION_THICKNESS or DRAGGING_CONNECTION_THICKNESS,
|
thickness = vectorOwner == self and CONNECTION_THICKNESS or DRAGGING_CONNECTION_THICKNESS,
|
||||||
})
|
})
|
||||||
@ -508,7 +514,7 @@ function shiftContentsRight(playerColor)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function shiftContents(playerColor, direction)
|
function shiftContents(playerColor, direction)
|
||||||
local zone = getObjectFromGUID(PLAY_AREA_ZONE_GUID)
|
local zone = guidReferenceApi.getObjectByOwnerAndType("Mythos", "PlayAreaZone")
|
||||||
if not zone then
|
if not zone then
|
||||||
broadcastToColor("Scripting zone couldn't be found.", playerColor, "Red")
|
broadcastToColor("Scripting zone couldn't be found.", playerColor, "Red")
|
||||||
return
|
return
|
||||||
@ -530,8 +536,8 @@ function isInPlayArea(object)
|
|||||||
local bounds = self.getBounds()
|
local bounds = self.getBounds()
|
||||||
local position = object.getPosition()
|
local position = object.getPosition()
|
||||||
-- Corners are arbitrary since it's all global - c1 goes down both axes, c2 goes up
|
-- Corners are arbitrary since it's all global - c1 goes down both axes, c2 goes up
|
||||||
local c1 = { x = bounds.center.x - bounds.size.x / 2, z = bounds.center.z - bounds.size.z / 2}
|
local c1 = { x = bounds.center.x - bounds.size.x / 2, z = bounds.center.z - bounds.size.z / 2 }
|
||||||
local c2 = { x = bounds.center.x + bounds.size.x / 2, z = bounds.center.z + bounds.size.z / 2}
|
local c2 = { x = bounds.center.x + bounds.size.x / 2, z = bounds.center.z + bounds.size.z / 2 }
|
||||||
|
|
||||||
return position.x > c1.x and position.x < c2.x and position.z > c1.z and position.z < c2.z
|
return position.x > c1.x and position.x < c2.x and position.z > c1.z and position.z < c2.z
|
||||||
end
|
end
|
||||||
@ -582,7 +588,7 @@ function countVP()
|
|||||||
local cardVP = tonumber(metadata.victory) or 0
|
local cardVP = tonumber(metadata.victory) or 0
|
||||||
if cardVP ~= 0 and not cardHasClues(cardId) then
|
if cardVP ~= 0 and not cardHasClues(cardId) then
|
||||||
totalVP = totalVP + cardVP
|
totalVP = totalVP + cardVP
|
||||||
if cardVP >0 then
|
if cardVP > 0 then
|
||||||
table.insert(countedVP, getObjectFromGUID(cardId))
|
table.insert(countedVP, getObjectFromGUID(cardId))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -651,8 +657,8 @@ end
|
|||||||
|
|
||||||
-- rebuilds local snap points (could be useful in the future again)
|
-- rebuilds local snap points (could be useful in the future again)
|
||||||
function buildSnaps()
|
function buildSnaps()
|
||||||
local upperleft = { x = 1.53, z = -1.09}
|
local upperleft = { x = 1.53, z = -1.09 }
|
||||||
local lowerright = {x = -1.53, z = 1.55}
|
local lowerright = { x = -1.53, z = 1.55 }
|
||||||
local snaps = {}
|
local snaps = {}
|
||||||
|
|
||||||
-- creates 81 snap points, for uneven rows + columns it makes a rotation snap point
|
-- creates 81 snap points, for uneven rows + columns it makes a rotation snap point
|
||||||
@ -666,7 +672,7 @@ function buildSnaps()
|
|||||||
|
|
||||||
-- enable rotation snaps for uneven rows / columns
|
-- enable rotation snaps for uneven rows / columns
|
||||||
if (i % 2 ~= 0) and (j % 2 ~= 0) then
|
if (i % 2 ~= 0) and (j % 2 ~= 0) then
|
||||||
snap.rotation = {0, 0, 0}
|
snap.rotation = { 0, 0, 0 }
|
||||||
snap.rotation_snap = true
|
snap.rotation_snap = true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -678,6 +684,6 @@ end
|
|||||||
|
|
||||||
-- utility function
|
-- utility function
|
||||||
function round(num, numDecimalPlaces)
|
function round(num, numDecimalPlaces)
|
||||||
local mult = 10^(numDecimalPlaces or 0)
|
local mult = 10 ^ (numDecimalPlaces or 0)
|
||||||
return math.floor(num * mult + 0.5) / mult
|
return math.floor(num * mult + 0.5) / mult
|
||||||
end
|
end
|
||||||
|
@ -1,105 +1,109 @@
|
|||||||
do
|
do
|
||||||
local PlayAreaApi = { }
|
local PlayAreaApi = {}
|
||||||
local PLAY_AREA_GUID = "721ba2"
|
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||||
local INVESTIGATOR_COUNTER_GUID = "f182ee"
|
|
||||||
|
local function getPlayArea()
|
||||||
|
return guidReferenceApi.getObjectByOwnerAndType("Mythos", "PlayArea")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getInvestigatorCounter()
|
||||||
|
return guidReferenceApi.getObjectByOwnerAndType("Mythos", "InvestigatorCounter")
|
||||||
|
end
|
||||||
|
|
||||||
-- Returns the current value of the investigator counter from the playmat
|
-- Returns the current value of the investigator counter from the playmat
|
||||||
---@return Integer. Number of investigators currently set on the counter
|
---@return Integer. Number of investigators currently set on the counter
|
||||||
PlayAreaApi.getInvestigatorCount = function()
|
PlayAreaApi.getInvestigatorCount = function()
|
||||||
return getObjectFromGUID(INVESTIGATOR_COUNTER_GUID).getVar("val")
|
return getInvestigatorCounter().getVar("val")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Updates the current value of the investigator counter from the playmat
|
-- Updates the current value of the investigator counter from the playmat
|
||||||
---@param count Number of investigators to set on the counter
|
---@param count Number of investigators to set on the counter
|
||||||
PlayAreaApi.setInvestigatorCount = function(count)
|
PlayAreaApi.setInvestigatorCount = function(count)
|
||||||
return getObjectFromGUID(INVESTIGATOR_COUNTER_GUID).call("updateVal", count)
|
getInvestigatorCounter().call("updateVal", count)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Move all contents on the play area (cards, tokens, etc) one slot in the given direction. Certain
|
-- Move all contents on the play area (cards, tokens, etc) one slot in the given direction. Certain
|
||||||
-- fixed objects will be ignored, as will anything the player has tagged with
|
-- fixed objects will be ignored, as will anything the player has tagged with 'displacement_excluded'
|
||||||
-- 'displacement_excluded'
|
---@param playerColor Color Color of the player requesting the shift for messages
|
||||||
---@param playerColor Color of the player requesting the shift. Used solely to send an error
|
|
||||||
--- message in the unlikely case that the scripting zone has been deleted
|
|
||||||
PlayAreaApi.shiftContentsUp = function(playerColor)
|
PlayAreaApi.shiftContentsUp = function(playerColor)
|
||||||
return getObjectFromGUID(PLAY_AREA_GUID).call("shiftContentsUp", playerColor)
|
return getPlayArea().call("shiftContentsUp", playerColor)
|
||||||
end
|
end
|
||||||
|
|
||||||
PlayAreaApi.shiftContentsDown = function(playerColor)
|
PlayAreaApi.shiftContentsDown = function(playerColor)
|
||||||
return getObjectFromGUID(PLAY_AREA_GUID).call("shiftContentsDown", playerColor)
|
return getPlayArea().call("shiftContentsDown", playerColor)
|
||||||
end
|
end
|
||||||
|
|
||||||
PlayAreaApi.shiftContentsLeft = function(playerColor)
|
PlayAreaApi.shiftContentsLeft = function(playerColor)
|
||||||
return getObjectFromGUID(PLAY_AREA_GUID).call("shiftContentsLeft", playerColor)
|
return getPlayArea().call("shiftContentsLeft", playerColor)
|
||||||
end
|
end
|
||||||
|
|
||||||
PlayAreaApi.shiftContentsRight = function(playerColor)
|
PlayAreaApi.shiftContentsRight = function(playerColor)
|
||||||
return getObjectFromGUID(PLAY_AREA_GUID).call("shiftContentsRight", playerColor)
|
return getPlayArea().call("shiftContentsRight", playerColor)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Reset the play area's tracking of which cards have had tokens spawned.
|
-- Reset the play area's tracking of which cards have had tokens spawned.
|
||||||
PlayAreaApi.resetSpawnedCards = function()
|
PlayAreaApi.resetSpawnedCards = function()
|
||||||
return getObjectFromGUID(PLAY_AREA_GUID).call("resetSpawnedCards")
|
return getPlayArea().call("resetSpawnedCards")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Event to be called when the current scenario has changed.
|
-- Event to be called when the current scenario has changed.
|
||||||
---@param scenarioName Name of the new scenario
|
---@param scenarioName Name of the new scenario
|
||||||
PlayAreaApi.onScenarioChanged = function(scenarioName)
|
PlayAreaApi.onScenarioChanged = function(scenarioName)
|
||||||
getObjectFromGUID(PLAY_AREA_GUID).call("onScenarioChanged", scenarioName)
|
getPlayArea().call("onScenarioChanged", scenarioName)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Sets this playmat's snap points to limit snapping to locations or not.
|
-- Sets this playmat's snap points to limit snapping to locations or not.
|
||||||
-- If matchTypes is false, snap points will be reset to snap all cards.
|
-- If matchTypes is false, snap points will be reset to snap all cards.
|
||||||
---@param matchTypes Boolean Whether snap points should only snap for the matching card types.
|
---@param matchTypes Boolean Whether snap points should only snap for the matching card types.
|
||||||
PlayAreaApi.setLimitSnapsByType = function(matchCardTypes)
|
PlayAreaApi.setLimitSnapsByType = function(matchCardTypes)
|
||||||
getObjectFromGUID(PLAY_AREA_GUID).call("setLimitSnapsByType", matchCardTypes)
|
getPlayArea().call("setLimitSnapsByType", matchCardTypes)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Receiver for the Global tryObjectEnterContainer event. Used to clear vector lines from dragged
|
-- Receiver for the Global tryObjectEnterContainer event. Used to clear vector lines from dragged
|
||||||
-- cards before they're destroyed by entering the container
|
-- cards before they're destroyed by entering the container
|
||||||
PlayAreaApi.tryObjectEnterContainer = function(container, object)
|
PlayAreaApi.tryObjectEnterContainer = function(container, object)
|
||||||
getObjectFromGUID(PLAY_AREA_GUID).call("tryObjectEnterContainer",
|
getPlayArea().call("tryObjectEnterContainer", { container = container, object = object })
|
||||||
{ container = container, object = object })
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- counts the VP on locations in the play area
|
-- counts the VP on locations in the play area
|
||||||
PlayAreaApi.countVP = function()
|
PlayAreaApi.countVP = function()
|
||||||
return getObjectFromGUID(PLAY_AREA_GUID).call("countVP")
|
return getPlayArea().call("countVP")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- highlights all locations in the play area without metadata
|
-- highlights all locations in the play area without metadata
|
||||||
---@param state Boolean True if highlighting should be enabled
|
---@param state Boolean True if highlighting should be enabled
|
||||||
PlayAreaApi.highlightMissingData = function(state)
|
PlayAreaApi.highlightMissingData = function(state)
|
||||||
return getObjectFromGUID(PLAY_AREA_GUID).call("highlightMissingData", state)
|
return getPlayArea().call("highlightMissingData", state)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- highlights all locations in the play area with VP
|
-- highlights all locations in the play area with VP
|
||||||
---@param state Boolean True if highlighting should be enabled
|
---@param state Boolean True if highlighting should be enabled
|
||||||
PlayAreaApi.highlightCountedVP = function(state)
|
PlayAreaApi.highlightCountedVP = function(state)
|
||||||
return getObjectFromGUID(PLAY_AREA_GUID).call("highlightCountedVP", state)
|
return getPlayArea().call("highlightCountedVP", state)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Checks if an object is in the play area (returns true or false)
|
-- Checks if an object is in the play area (returns true or false)
|
||||||
PlayAreaApi.isInPlayArea = function(object)
|
PlayAreaApi.isInPlayArea = function(object)
|
||||||
return getObjectFromGUID(PLAY_AREA_GUID).call("isInPlayArea", object)
|
return getPlayArea().call("isInPlayArea", object)
|
||||||
end
|
end
|
||||||
|
|
||||||
PlayAreaApi.getSurface = function()
|
PlayAreaApi.getSurface = function()
|
||||||
return getObjectFromGUID(PLAY_AREA_GUID).getCustomObject().image
|
return getPlayArea().getCustomObject().image
|
||||||
end
|
end
|
||||||
|
|
||||||
PlayAreaApi.updateSurface = function(url)
|
PlayAreaApi.updateSurface = function(url)
|
||||||
return getObjectFromGUID(PLAY_AREA_GUID).call("updateSurface", url)
|
return getPlayArea().call("updateSurface", url)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Called by Custom Data Helpers to push their location data into the Data Helper. This adds the
|
-- Called by Custom Data Helpers to push their location data into the Data Helper. This adds the
|
||||||
-- data to the local token manager instance.
|
-- data to the local token manager instance.
|
||||||
---@param args Table Single-value array holding the GUID of the Custom Data Helper making the call
|
---@param args Table Single-value array holding the GUID of the Custom Data Helper making the call
|
||||||
PlayAreaApi.updateLocations = function(args)
|
PlayAreaApi.updateLocations = function(args)
|
||||||
getObjectFromGUID(PLAY_AREA_GUID).call("updateLocations", args)
|
getPlayArea().call("updateLocations", args)
|
||||||
end
|
end
|
||||||
|
|
||||||
PlayAreaApi.getCustomDataHelper = function()
|
PlayAreaApi.getCustomDataHelper = function()
|
||||||
return getObjectFromGUID(PLAY_AREA_GUID).getVar("customDataHelper")
|
return getPlayArea().getVar("customDataHelper")
|
||||||
end
|
end
|
||||||
|
|
||||||
return PlayAreaApi
|
return PlayAreaApi
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
do
|
do
|
||||||
local SoundCubeApi = {}
|
local SoundCubeApi = {}
|
||||||
|
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||||
|
|
||||||
-- this table links the name of a trigger effect to its index
|
-- this table links the name of a trigger effect to its index
|
||||||
local soundIndices = {
|
local soundIndices = {
|
||||||
@ -9,7 +10,8 @@ do
|
|||||||
}
|
}
|
||||||
|
|
||||||
local function playTriggerEffect(index)
|
local function playTriggerEffect(index)
|
||||||
getObjectsWithTag("SoundCube")[1].AssetBundle.playTriggerEffect(index)
|
local SoundCube = guidReferenceApi.getObjectByOwnerAndType("Mythos", "SoundCube")
|
||||||
|
SoundCube.AssetBundle.playTriggerEffect(index)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- plays the by name requested sound
|
-- plays the by name requested sound
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local chaosBagApi = require("chaosbag/ChaosBagApi")
|
local chaosBagApi = require("chaosbag/ChaosBagApi")
|
||||||
|
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||||
local playAreaApi = require("core/PlayAreaApi")
|
local playAreaApi = require("core/PlayAreaApi")
|
||||||
local tokenChecker = require("core/token/TokenChecker")
|
local tokenChecker = require("core/token/TokenChecker")
|
||||||
|
|
||||||
@ -10,13 +11,8 @@ local countedVP = {}
|
|||||||
local highlightMissing = false
|
local highlightMissing = false
|
||||||
local highlightCounted = false
|
local highlightCounted = false
|
||||||
|
|
||||||
local TRASHCAN
|
|
||||||
local TRASHCAN_GUID = "70b9f6"
|
|
||||||
|
|
||||||
-- button creation when loading the game
|
-- button creation when loading the game
|
||||||
function onLoad()
|
function onLoad()
|
||||||
TRASHCAN = getObjectFromGUID(TRASHCAN_GUID)
|
|
||||||
|
|
||||||
-- index 0: VP - "Display"
|
-- index 0: VP - "Display"
|
||||||
local buttonParameters = {}
|
local buttonParameters = {}
|
||||||
buttonParameters.label = "0"
|
buttonParameters.label = "0"
|
||||||
@ -236,8 +232,7 @@ end
|
|||||||
function highlightCountedVP()
|
function highlightCountedVP()
|
||||||
self.editButton({
|
self.editButton({
|
||||||
index = 4,
|
index = 4,
|
||||||
tooltip = (highlightCounted and "Enable" or "Disable") ..
|
tooltip = (highlightCounted and "Enable" or "Disable") .. " highlighting of cards with VP."
|
||||||
" highlighting of cards with VP."
|
|
||||||
})
|
})
|
||||||
for _, obj in pairs(countedVP) do
|
for _, obj in pairs(countedVP) do
|
||||||
if obj ~= nil then
|
if obj ~= nil then
|
||||||
@ -254,6 +249,8 @@ end
|
|||||||
|
|
||||||
-- places the provided card in the first empty spot
|
-- places the provided card in the first empty spot
|
||||||
function placeCard(card)
|
function placeCard(card)
|
||||||
|
local trash = guidReferenceApi.getObjectByOwnerAndType("Mythos", "Trash")
|
||||||
|
|
||||||
-- check snap point states
|
-- check snap point states
|
||||||
local snaps = self.getSnapPoints()
|
local snaps = self.getSnapPoints()
|
||||||
table.sort(snaps, function(a, b) return a.position.x > b.position.x end)
|
table.sort(snaps, function(a, b) return a.position.x > b.position.x end)
|
||||||
@ -283,7 +280,7 @@ function placeCard(card)
|
|||||||
local chaosBag = chaosBagApi.findChaosBag()
|
local chaosBag = chaosBagApi.findChaosBag()
|
||||||
chaosBag.putObject(obj)
|
chaosBag.putObject(obj)
|
||||||
elseif obj.memo ~= nil and obj.getLock() == false then
|
elseif obj.memo ~= nil and obj.getLock() == false then
|
||||||
TRASHCAN.putObject(obj)
|
trash.putObject(obj)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -327,13 +324,3 @@ function checkSnapPointState(pos)
|
|||||||
origin = pos
|
origin = pos
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- search a table for a value, return true if found (else returns false)
|
|
||||||
function tableContains(table, value)
|
|
||||||
for _, v in ipairs(table) do
|
|
||||||
if v == value then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
@ -1,18 +1,22 @@
|
|||||||
do
|
do
|
||||||
local VictoryDisplayApi = {}
|
local VictoryDisplayApi = {}
|
||||||
local VD_GUID = "6ccd6d"
|
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||||
|
|
||||||
|
local function getVictoryDisplay()
|
||||||
|
return guidReferenceApi.getObjectByOwnerAndType("Mythos", "VictoryDisplay")
|
||||||
|
end
|
||||||
|
|
||||||
-- triggers an update of the Victory count
|
-- triggers an update of the Victory count
|
||||||
---@param delay Number Delay in seconds after which the update call is executed
|
---@param delay Number Delay in seconds after which the update call is executed
|
||||||
VictoryDisplayApi.update = function(delay)
|
VictoryDisplayApi.update = function(delay)
|
||||||
getObjectFromGUID(VD_GUID).call("startUpdate", delay)
|
getVictoryDisplay().call("startUpdate", delay)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- moves a card to the victory display (in the first empty spot)
|
-- moves a card to the victory display (in the first empty spot)
|
||||||
---@param object Object Object that should be checked and potentially moved
|
---@param object Object Object that should be checked and potentially moved
|
||||||
VictoryDisplayApi.placeCard = function(object)
|
VictoryDisplayApi.placeCard = function(object)
|
||||||
if object ~= nil and object.tag == "Card" then
|
if object ~= nil and object.tag == "Card" then
|
||||||
getObjectFromGUID(VD_GUID).call("placeCard", object)
|
getVictoryDisplay().call("placeCard", object)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
do
|
do
|
||||||
|
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||||
local optionPanelApi = require("core/OptionPanelApi")
|
local optionPanelApi = require("core/OptionPanelApi")
|
||||||
local playAreaApi = require("core/PlayAreaApi")
|
local playAreaApi = require("core/PlayAreaApi")
|
||||||
local tokenSpawnTrackerApi = require("core/token/TokenSpawnTrackerApi")
|
local tokenSpawnTrackerApi = require("core/token/TokenSpawnTrackerApi")
|
||||||
@ -119,15 +120,10 @@ do
|
|||||||
["supply"] = 7
|
["supply"] = 7
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Source for tokens
|
|
||||||
local TOKEN_SOURCE_GUID = "124381"
|
|
||||||
|
|
||||||
-- Table of data extracted from the token source bag, keyed by the Memo on each token which
|
-- Table of data extracted from the token source bag, keyed by the Memo on each token which
|
||||||
-- should match the token type keys ("resource", "clue", etc)
|
-- should match the token type keys ("resource", "clue", etc)
|
||||||
local tokenTemplates
|
local tokenTemplates
|
||||||
|
|
||||||
local DATA_HELPER_GUID = "708279"
|
|
||||||
|
|
||||||
local playerCardData
|
local playerCardData
|
||||||
local locationData
|
local locationData
|
||||||
|
|
||||||
@ -225,9 +221,11 @@ do
|
|||||||
-- Copy the offsets to make sure we don't change the static values
|
-- Copy the offsets to make sure we don't change the static values
|
||||||
local baseOffsets = offsets
|
local baseOffsets = offsets
|
||||||
offsets = { }
|
offsets = { }
|
||||||
|
|
||||||
|
-- get a vector for the shifting (downwards local to the card)
|
||||||
|
local shiftDownVector = Vector(0, 0, shiftDown):rotateOver("y", card.getRotation().y)
|
||||||
for i, baseOffset in ipairs(baseOffsets) do
|
for i, baseOffset in ipairs(baseOffsets) do
|
||||||
offsets[i] = baseOffset
|
offsets[i] = baseOffset + shiftDownVector
|
||||||
offsets[i][3] = offsets[i][3] + shiftDown
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -340,8 +338,8 @@ do
|
|||||||
if tokenTemplates ~= nil then
|
if tokenTemplates ~= nil then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
tokenTemplates = { }
|
tokenTemplates = {}
|
||||||
local tokenSource = getObjectFromGUID(TOKEN_SOURCE_GUID)
|
local tokenSource = guidReferenceApi.getObjectByOwnerAndType("Mythos", "TokenSource")
|
||||||
for _, tokenTemplate in ipairs(tokenSource.getData().ContainedObjects) do
|
for _, tokenTemplate in ipairs(tokenSource.getData().ContainedObjects) do
|
||||||
local tokenName = tokenTemplate.Memo
|
local tokenName = tokenTemplate.Memo
|
||||||
tokenTemplates[tokenName] = tokenTemplate
|
tokenTemplates[tokenName] = tokenTemplate
|
||||||
@ -353,7 +351,7 @@ do
|
|||||||
if playerCardData ~= nil then
|
if playerCardData ~= nil then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local dataHelper = getObjectFromGUID(DATA_HELPER_GUID)
|
local dataHelper = guidReferenceApi.getObjectByOwnerAndType("Mythos", "DataHelper")
|
||||||
playerCardData = dataHelper.getTable('PLAYER_CARD_DATA')
|
playerCardData = dataHelper.getTable('PLAYER_CARD_DATA')
|
||||||
locationData = dataHelper.getTable('LOCATIONS_DATA')
|
locationData = dataHelper.getTable('LOCATIONS_DATA')
|
||||||
end
|
end
|
||||||
@ -368,18 +366,16 @@ do
|
|||||||
if uses == nil then return end
|
if uses == nil then return end
|
||||||
|
|
||||||
-- go through tokens to spawn
|
-- go through tokens to spawn
|
||||||
local type, token, tokenCount
|
local tokenCount
|
||||||
for i, useInfo in ipairs(uses) do
|
for i, useInfo in ipairs(uses) do
|
||||||
type = useInfo.type
|
tokenCount = (useInfo.count or 0) + (useInfo.countPerInvestigator or 0) * playAreaApi.getInvestigatorCount()
|
||||||
token = useInfo.token
|
if extraUses ~= nil and extraUses[useInfo.type] ~= nil then
|
||||||
tokenCount = (useInfo.count or 0)
|
tokenCount = tokenCount + extraUses[useInfo.type]
|
||||||
+ (useInfo.countPerInvestigator or 0) * playAreaApi.getInvestigatorCount()
|
|
||||||
if extraUses ~= nil and extraUses[type] ~= nil then
|
|
||||||
tokenCount = tokenCount + extraUses[type]
|
|
||||||
end
|
end
|
||||||
-- Shift each spawned group after the first down so they don't pile on each other
|
-- Shift each spawned group after the first down so they don't pile on each other
|
||||||
TokenManager.spawnTokenGroup(card, token, tokenCount, (i - 1) * 0.8, type)
|
TokenManager.spawnTokenGroup(card, useInfo.token, tokenCount, (i - 1) * 0.8, useInfo.type)
|
||||||
end
|
end
|
||||||
|
|
||||||
tokenSpawnTrackerApi.markTokensSpawned(card.getGUID())
|
tokenSpawnTrackerApi.markTokensSpawned(card.getGUID())
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -403,9 +399,8 @@ do
|
|||||||
---@param playerData Table Player card data structure retrieved from the DataHelper. Should be
|
---@param playerData Table Player card data structure retrieved from the DataHelper. Should be
|
||||||
-- the right data for this card.
|
-- the right data for this card.
|
||||||
internal.spawnPlayerCardTokensFromDataHelper = function(card, playerData)
|
internal.spawnPlayerCardTokensFromDataHelper = function(card, playerData)
|
||||||
token = playerData.tokenType
|
local token = playerData.tokenType
|
||||||
tokenCount = playerData.tokenCount
|
local tokenCount = playerData.tokenCount
|
||||||
--log("Spawning data helper tokens for "..card.getName()..'['..card.getDescription()..']: '..tokenCount.."x "..token)
|
|
||||||
TokenManager.spawnTokenGroup(card, token, tokenCount)
|
TokenManager.spawnTokenGroup(card, token, tokenCount)
|
||||||
tokenSpawnTrackerApi.markTokensSpawned(card.getGUID())
|
tokenSpawnTrackerApi.markTokensSpawned(card.getGUID())
|
||||||
end
|
end
|
||||||
@ -438,7 +433,6 @@ do
|
|||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
|
||||||
--log(card.getName() .. ' : ' .. locationData.type .. ' : ' .. locationData.value .. ' : ' .. locationData.clueSide)
|
|
||||||
if ((card.is_face_down and locationData.clueSide == 'back')
|
if ((card.is_face_down and locationData.clueSide == 'back')
|
||||||
or (not card.is_face_down and locationData.clueSide == 'front')) then
|
or (not card.is_face_down and locationData.clueSide == 'front')) then
|
||||||
if locationData.type == 'fixed' then
|
if locationData.type == 'fixed' then
|
||||||
|
@ -1,26 +1,15 @@
|
|||||||
local spawnedCardGuids = { }
|
local spawnedCardGuids = {}
|
||||||
|
|
||||||
local HAND_ZONES = { }
|
function onSave() return JSON.encode({ cards = spawnedCardGuids }) end
|
||||||
HAND_ZONES["a70eee"] = true -- White
|
|
||||||
HAND_ZONES["0285cc"] = true -- Green
|
|
||||||
HAND_ZONES["5fe087"] = true -- Orange
|
|
||||||
HAND_ZONES["be2f17"] = true -- Red
|
|
||||||
|
|
||||||
function onLoad(saveState)
|
function onLoad(saveState)
|
||||||
if saveState ~= nil then
|
if saveState ~= nil then
|
||||||
local saveTable = JSON.decode(saveState) or { }
|
local saveTable = JSON.decode(saveState) or {}
|
||||||
spawnedCardGuids = saveTable.cards or { }
|
spawnedCardGuids = saveTable.cards or {}
|
||||||
end
|
end
|
||||||
|
|
||||||
createResetMenuItems()
|
createResetMenuItems()
|
||||||
end
|
end
|
||||||
|
|
||||||
function onSave()
|
|
||||||
return JSON.encode({
|
|
||||||
cards = spawnedCardGuids
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
function createResetMenuItems()
|
function createResetMenuItems()
|
||||||
self.addContextMenuItem("Reset All", resetAll)
|
self.addContextMenuItem("Reset All", resetAll)
|
||||||
self.addContextMenuItem("Reset Locations", resetAllLocations)
|
self.addContextMenuItem("Reset Locations", resetAllLocations)
|
||||||
@ -39,14 +28,20 @@ function resetTokensSpawned(cardGuid)
|
|||||||
spawnedCardGuids[cardGuid] = nil
|
spawnedCardGuids[cardGuid] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function resetAllAssetAndEvents()
|
function resetAll() spawnedCardGuids = {} end
|
||||||
local resetList = { }
|
|
||||||
|
function resetAllLocations() resetSpecificTypes("Location") end
|
||||||
|
|
||||||
|
function resetAllAssetAndEvents() resetSpecificTypes("Asset", "Event") end
|
||||||
|
|
||||||
|
function resetSpecificTypes(type1, type2)
|
||||||
|
local resetList = {}
|
||||||
for cardGuid, _ in pairs(spawnedCardGuids) do
|
for cardGuid, _ in pairs(spawnedCardGuids) do
|
||||||
local card = getObjectFromGUID(cardGuid)
|
local card = getObjectFromGUID(cardGuid)
|
||||||
if card ~= nil then
|
if card ~= nil then
|
||||||
local cardMetadata = JSON.decode(card.getGMNotes()) or { }
|
local cardMetadata = JSON.decode(card.getGMNotes()) or {}
|
||||||
-- Check this by type rather than the PlayerCard tag so we don't reset weaknesses
|
-- Check this by type rather than the PlayerCard tag so we don't reset weaknesses
|
||||||
if cardMetadata.type == "Asset" or cardMetadata.type == "Event" then
|
if cardMetadata.type == type1 or cardMetadata.type == type2 then
|
||||||
resetList[cardGuid] = true
|
resetList[cardGuid] = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -56,30 +51,9 @@ function resetAllAssetAndEvents()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function resetAllLocations()
|
|
||||||
local resetList = { }
|
|
||||||
for cardGuid, _ in pairs(spawnedCardGuids) do
|
|
||||||
local card = getObjectFromGUID(cardGuid)
|
|
||||||
if card ~= nil then
|
|
||||||
local cardMetadata = JSON.decode(card.getGMNotes()) or { }
|
|
||||||
-- Check this by type rather than the PlayerCard tag so we don't reset weaknesses
|
|
||||||
if cardMetadata.type == "Location" then
|
|
||||||
resetList[cardGuid] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for cardGuid, _ in pairs(resetList) do
|
|
||||||
spawnedCardGuids[cardGuid] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function resetAll()
|
|
||||||
spawnedCardGuids = { }
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Listener to reset card token spawns when they enter a hand.
|
-- Listener to reset card token spawns when they enter a hand.
|
||||||
function onObjectEnterZone(zone, enterObject)
|
function onObjectEnterZone(zone, enterObject)
|
||||||
if HAND_ZONES[zone.getGUID()] then
|
if zone.type == "Hand" and enterObject.type == "Card" then
|
||||||
resetTokensSpawned(enterObject.getGUID())
|
resetTokensSpawned(enterObject.getGUID())
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,29 +1,33 @@
|
|||||||
do
|
do
|
||||||
local TokenSpawnTracker = { }
|
local TokenSpawnTracker = {}
|
||||||
local SPAWN_TRACKER_GUID = "e3ffc9"
|
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||||
|
|
||||||
|
local function getSpawnTracker()
|
||||||
|
return guidReferenceApi.getObjectByOwnerAndType("Mythos", "TokenSpawnTracker")
|
||||||
|
end
|
||||||
|
|
||||||
TokenSpawnTracker.hasSpawnedTokens = function(cardGuid)
|
TokenSpawnTracker.hasSpawnedTokens = function(cardGuid)
|
||||||
return getObjectFromGUID(SPAWN_TRACKER_GUID).call("hasSpawnedTokens", cardGuid)
|
return getSpawnTracker().call("hasSpawnedTokens", cardGuid)
|
||||||
end
|
end
|
||||||
|
|
||||||
TokenSpawnTracker.markTokensSpawned = function(cardGuid)
|
TokenSpawnTracker.markTokensSpawned = function(cardGuid)
|
||||||
return getObjectFromGUID(SPAWN_TRACKER_GUID).call("markTokensSpawned", cardGuid)
|
return getSpawnTracker().call("markTokensSpawned", cardGuid)
|
||||||
end
|
end
|
||||||
|
|
||||||
TokenSpawnTracker.resetTokensSpawned = function(cardGuid)
|
TokenSpawnTracker.resetTokensSpawned = function(cardGuid)
|
||||||
return getObjectFromGUID(SPAWN_TRACKER_GUID).call("resetTokensSpawned", cardGuid)
|
return getSpawnTracker().call("resetTokensSpawned", cardGuid)
|
||||||
end
|
end
|
||||||
|
|
||||||
TokenSpawnTracker.resetAllAssetAndEvents = function()
|
TokenSpawnTracker.resetAllAssetAndEvents = function()
|
||||||
return getObjectFromGUID(SPAWN_TRACKER_GUID).call("resetAllAssetAndEvents")
|
return getSpawnTracker().call("resetAllAssetAndEvents")
|
||||||
end
|
end
|
||||||
|
|
||||||
TokenSpawnTracker.resetAllLocations = function()
|
TokenSpawnTracker.resetAllLocations = function()
|
||||||
return getObjectFromGUID(SPAWN_TRACKER_GUID).call("resetAllLocations")
|
return getSpawnTracker().call("resetAllLocations")
|
||||||
end
|
end
|
||||||
|
|
||||||
TokenSpawnTracker.resetAll = function()
|
TokenSpawnTracker.resetAll = function()
|
||||||
return getObjectFromGUID(SPAWN_TRACKER_GUID).call("resetAll")
|
return getSpawnTracker().call("resetAll")
|
||||||
end
|
end
|
||||||
|
|
||||||
return TokenSpawnTracker
|
return TokenSpawnTracker
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
do
|
do
|
||||||
require("core/tour/TourScript")
|
require("core/tour/TourScript")
|
||||||
require("core/tour/TourCard")
|
require("core/tour/TourCard")
|
||||||
local TourManager = { }
|
local TourManager = {}
|
||||||
local internal = { }
|
local internal = {}
|
||||||
|
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||||
|
|
||||||
-- Base IDs for various tour card UI elements. Actual IDs will have _[playerColor] appended
|
-- Base IDs for various tour card UI elements. Actual IDs will have _[playerColor] appended
|
||||||
local CARD_ID = "tourCard"
|
local CARD_ID = "tourCard"
|
||||||
@ -123,8 +124,9 @@ do
|
|||||||
delay = delay + 0.5
|
delay = delay + 0.5
|
||||||
end
|
end
|
||||||
local lookPos
|
local lookPos
|
||||||
if TOUR_SCRIPT[cardIndex].showObj ~= nil then
|
local objReferenceData = TOUR_SCRIPT[cardIndex].objReferenceData
|
||||||
local lookAtObj = getObjectFromGUID(TOUR_SCRIPT[cardIndex].showObj)
|
if objReferenceData ~= nil then
|
||||||
|
local lookAtObj = guidReferenceApi.getObjectByOwnerAndType(objReferenceData.owner, objReferenceData.type)
|
||||||
lookPos = lookAtObj.getPosition()
|
lookPos = lookAtObj.getPosition()
|
||||||
lookPos.y = TOUR_SCRIPT[cardIndex].distanceFromObj or 0
|
lookPos.y = TOUR_SCRIPT[cardIndex].distanceFromObj or 0
|
||||||
-- Since camera isn't directly above the hook, changing the Y affects the visual position of
|
-- Since camera isn't directly above the hook, changing the Y affects the visual position of
|
||||||
|
@ -15,7 +15,7 @@ TOUR_SCRIPT = {
|
|||||||
{
|
{
|
||||||
narrator = "Daisy",
|
narrator = "Daisy",
|
||||||
text = "If you're new to the game, the library here has everything you'll need. A little research can go a long way, and looking into old newspapers for the weird and unusual can yield some surprisingly helpful information.\n\nI put a few right there that might prove enlightening.",
|
text = "If you're new to the game, the library here has everything you'll need. A little research can go a long way, and looking into old newspapers for the weird and unusual can yield some surprisingly helpful information.\n\nI put a few right there that might prove enlightening.",
|
||||||
showObj = "d99993",
|
objReferenceData = { owner = "Mythos", type = "RulesReference" },
|
||||||
distanceFromObj = 20,
|
distanceFromObj = 20,
|
||||||
position = "west",
|
position = "west",
|
||||||
speakerSide = "right"
|
speakerSide = "right"
|
||||||
@ -23,7 +23,7 @@ TOUR_SCRIPT = {
|
|||||||
{
|
{
|
||||||
narrator = "Mandy",
|
narrator = "Mandy",
|
||||||
text = "To survive what's coming you'll need a deck. If it's safely hidden away on ArkhamDB you can load it here, and even find the newest version after an upgrade without changing the ID.\n\nNo need to publish all your decks, use 'Private' and you can see it. Just make sure to select 'Make your decks public' in ArkhamDB.",
|
text = "To survive what's coming you'll need a deck. If it's safely hidden away on ArkhamDB you can load it here, and even find the newest version after an upgrade without changing the ID.\n\nNo need to publish all your decks, use 'Private' and you can see it. Just make sure to select 'Make your decks public' in ArkhamDB.",
|
||||||
showObj = "a28140",
|
objReferenceData = { owner = "Mythos", type = "DeckImporter" },
|
||||||
distanceFromObj = -5,
|
distanceFromObj = -5,
|
||||||
position = "northwest",
|
position = "northwest",
|
||||||
skipCentering = true,
|
skipCentering = true,
|
||||||
@ -31,7 +31,7 @@ TOUR_SCRIPT = {
|
|||||||
{
|
{
|
||||||
narrator = "Daniela",
|
narrator = "Daniela",
|
||||||
text = "I prefer the hands-on approach to building things, if you do too you can build a deck yourself.\n\nAll the cards you could ever need are here, laid out like a disassembled engine. Place the cards on the table, copy them for your deck, and you'll be ready for anything.",
|
text = "I prefer the hands-on approach to building things, if you do too you can build a deck yourself.\n\nAll the cards you could ever need are here, laid out like a disassembled engine. Place the cards on the table, copy them for your deck, and you'll be ready for anything.",
|
||||||
showObj = "2d30ee",
|
objReferenceData = { owner = "Mythos", type = "PlayerCardPanel" },
|
||||||
distanceFromObj = -7,
|
distanceFromObj = -7,
|
||||||
position = "south",
|
position = "south",
|
||||||
speakerSide = "right"
|
speakerSide = "right"
|
||||||
@ -39,7 +39,7 @@ TOUR_SCRIPT = {
|
|||||||
{
|
{
|
||||||
narrator = "Finn",
|
narrator = "Finn",
|
||||||
text = "Ready to face the unknown? We've smuggled shocking revelations and devious enemies from all over the world. Download the campaign you want to play, then Place it on the table to see the scenarios.\n\nJust remember - if it turns out to be too much for you, I was never here.",
|
text = "Ready to face the unknown? We've smuggled shocking revelations and devious enemies from all over the world. Download the campaign you want to play, then Place it on the table to see the scenarios.\n\nJust remember - if it turns out to be too much for you, I was never here.",
|
||||||
showObj = "aca04c",
|
objReferenceData = { owner = "Mythos", type = "CampaignThePathToCarcosa" },
|
||||||
distanceFromObj = 20,
|
distanceFromObj = 20,
|
||||||
position = "northwest",
|
position = "northwest",
|
||||||
},
|
},
|
||||||
@ -77,7 +77,7 @@ TOUR_SCRIPT = {
|
|||||||
{
|
{
|
||||||
narrator = "Preston",
|
narrator = "Preston",
|
||||||
text = "I can afford to buy what I need, but for those less well-off we've provided an endless pool of tokens to track your game. Simply drag one out of the pools here.\n\nResources are my favorite of course, but damage and horror are as inevitable as taxes. I leave those to my bookkeeper though. Those tokens can work like counters, use the number keys to change the value.",
|
text = "I can afford to buy what I need, but for those less well-off we've provided an endless pool of tokens to track your game. Simply drag one out of the pools here.\n\nResources are my favorite of course, but damage and horror are as inevitable as taxes. I leave those to my bookkeeper though. Those tokens can work like counters, use the number keys to change the value.",
|
||||||
showObj = "9fadf9",
|
objReferenceData = { owner = "Mythos", type = "ResourceTokenBag" },
|
||||||
position = "north",
|
position = "north",
|
||||||
skipCentering = true,
|
skipCentering = true,
|
||||||
speakerSide = "right"
|
speakerSide = "right"
|
||||||
|
@ -1,29 +1,33 @@
|
|||||||
do
|
do
|
||||||
local AllCardsBagApi = {}
|
local AllCardsBagApi = {}
|
||||||
local ALL_CARDS_BAG_GUID = "15bb07"
|
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||||
|
|
||||||
|
local function getAllCardsBag()
|
||||||
|
return guidReferenceApi.getObjectByOwnerAndType("Mythos", "AllCardsBag")
|
||||||
|
end
|
||||||
|
|
||||||
-- Returns a specific card from the bag, based on ArkhamDB ID
|
-- Returns a specific card from the bag, based on ArkhamDB ID
|
||||||
-- @param table:
|
---@param id table String ID of the card to retrieve
|
||||||
-- id: String ID of the card to retrieve
|
---@return table table
|
||||||
-- @return: If the indexes are still being constructed, an empty table is
|
-- If the indexes are still being constructed, an empty table is
|
||||||
-- returned. Otherwise, a single table with the following fields
|
-- returned. Otherwise, a single table with the following fields
|
||||||
-- cardData: TTS object data, suitable for spawning the card
|
-- cardData: TTS object data, suitable for spawning the card
|
||||||
-- cardMetadata: Table of parsed metadata
|
-- cardMetadata: Table of parsed metadata
|
||||||
AllCardsBagApi.getCardById = function(id)
|
AllCardsBagApi.getCardById = function(id)
|
||||||
return getObjectFromGUID(ALL_CARDS_BAG_GUID).call("getCardById", {id = id})
|
return getAllCardsBag().call("getCardById", {id = id})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Gets a random basic weakness from the bag. Once a given ID has been returned
|
-- Gets a random basic weakness from the bag. Once a given ID has been returned
|
||||||
-- it will be removed from the list and cannot be selected again until a reload
|
-- it will be removed from the list and cannot be selected again until a reload
|
||||||
-- occurs or the indexes are rebuilt, which will refresh the list to include all
|
-- occurs or the indexes are rebuilt, which will refresh the list to include all
|
||||||
-- weaknesses.
|
-- weaknesses.
|
||||||
-- @return: String ID of the selected weakness.
|
---@return id String ID of the selected weakness.
|
||||||
AllCardsBagApi.getRandomWeaknessId = function()
|
AllCardsBagApi.getRandomWeaknessId = function()
|
||||||
return getObjectFromGUID(ALL_CARDS_BAG_GUID).call("getRandomWeaknessId")
|
return getAllCardsBag().call("getRandomWeaknessId")
|
||||||
end
|
end
|
||||||
|
|
||||||
AllCardsBagApi.isIndexReady = function()
|
AllCardsBagApi.isIndexReady = function()
|
||||||
return getObjectFromGUID(ALL_CARDS_BAG_GUID).call("isIndexReady")
|
return getAllCardsBag().call("isIndexReady")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Called by Hotfix bags when they load. If we are still loading indexes, then
|
-- Called by Hotfix bags when they load. If we are still loading indexes, then
|
||||||
@ -32,40 +36,38 @@ do
|
|||||||
-- called once indexing is complete it means the hotfix bag has been added
|
-- called once indexing is complete it means the hotfix bag has been added
|
||||||
-- later, and we should rebuild the index to integrate the hotfix bag.
|
-- later, and we should rebuild the index to integrate the hotfix bag.
|
||||||
AllCardsBagApi.rebuildIndexForHotfix = function()
|
AllCardsBagApi.rebuildIndexForHotfix = function()
|
||||||
return getObjectFromGUID(ALL_CARDS_BAG_GUID).call("rebuildIndexForHotfix")
|
return getAllCardsBag().call("rebuildIndexForHotfix")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Searches the bag for cards which match the given name and returns a list. Note that this is
|
-- Searches the bag for cards which match the given name and returns a list. Note that this is
|
||||||
-- an O(n) search without index support. It may be slow.
|
-- an O(n) search without index support. It may be slow.
|
||||||
-- @param
|
---@param name String or string fragment to search for names
|
||||||
-- name String or string fragment to search for names
|
---@param exact Boolean Whether the name match should be exact
|
||||||
-- exact Whether the name match should be exact
|
|
||||||
AllCardsBagApi.getCardsByName = function(name, exact)
|
AllCardsBagApi.getCardsByName = function(name, exact)
|
||||||
return getObjectFromGUID(ALL_CARDS_BAG_GUID).call("getCardsByName", {name = name, exact = exact})
|
return getAllCardsBag().call("getCardsByName", {name = name, exact = exact})
|
||||||
end
|
end
|
||||||
|
|
||||||
AllCardsBagApi.isBagPresent = function()
|
AllCardsBagApi.isBagPresent = function()
|
||||||
return getObjectFromGUID(ALL_CARDS_BAG_GUID) and true
|
return getAllCardsBag() and true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Returns a list of cards from the bag matching a class and level (0 or upgraded)
|
-- Returns a list of cards from the bag matching a class and level (0 or upgraded)
|
||||||
-- @param
|
---@param class String class to retrieve ("Guardian", "Seeker", etc)
|
||||||
-- class: String class to retrieve ("Guardian", "Seeker", etc)
|
---@param upgraded Boolean true for upgraded cards (Level 1-5), false for Level 0
|
||||||
-- upgraded: true for upgraded cards (Level 1-5), false for Level 0
|
---@return: If the indexes are still being constructed, returns an empty table.
|
||||||
-- @return: If the indexes are still being constructed, returns an empty table.
|
|
||||||
-- Otherwise, a list of tables, each with the following fields
|
-- Otherwise, a list of tables, each with the following fields
|
||||||
-- cardData: TTS object data, suitable for spawning the card
|
-- cardData: TTS object data, suitable for spawning the card
|
||||||
-- cardMetadata: Table of parsed metadata
|
-- cardMetadata: Table of parsed metadata
|
||||||
AllCardsBagApi.getCardsByClassAndLevel = function(class, upgraded)
|
AllCardsBagApi.getCardsByClassAndLevel = function(class, upgraded)
|
||||||
return getObjectFromGUID(ALL_CARDS_BAG_GUID).call("getCardsByClassAndLevel", {class = class, upgraded = upgraded})
|
return getAllCardsBag().call("getCardsByClassAndLevel", {class = class, upgraded = upgraded})
|
||||||
end
|
end
|
||||||
|
|
||||||
AllCardsBagApi.getCardsByCycle = function(cycle)
|
AllCardsBagApi.getCardsByCycle = function(cycle)
|
||||||
return getObjectFromGUID(ALL_CARDS_BAG_GUID).call("getCardsByCycle", cycle)
|
return getAllCardsBag().call("getCardsByCycle", cycle)
|
||||||
end
|
end
|
||||||
|
|
||||||
AllCardsBagApi.getUniqueWeaknesses = function()
|
AllCardsBagApi.getUniqueWeaknesses = function()
|
||||||
return getObjectFromGUID(ALL_CARDS_BAG_GUID).call("getUniqueWeaknesses")
|
return getAllCardsBag().call("getUniqueWeaknesses")
|
||||||
end
|
end
|
||||||
|
|
||||||
return AllCardsBagApi
|
return AllCardsBagApi
|
||||||
|
@ -245,9 +245,9 @@ INVESTIGATORS["Jenny Barnes"] = {
|
|||||||
starterDeck = "2624961"
|
starterDeck = "2624961"
|
||||||
}
|
}
|
||||||
INVESTIGATORS["Jim Culver"] = {
|
INVESTIGATORS["Jim Culver"] = {
|
||||||
cards = { "02004" },
|
cards = { "02004", "02004-p", "02004-pf", "02004-pb" },
|
||||||
minicards = { "02004-m" },
|
minicards = { "02004-m" },
|
||||||
signatures = { "02012", "02013" },
|
signatures = { "02012", "02013", "90050", "90051", "90052", "90053" },
|
||||||
starterDeck = "2624965"
|
starterDeck = "2624965"
|
||||||
}
|
}
|
||||||
INVESTIGATORS["\"Ashcan\" Pete"] = {
|
INVESTIGATORS["\"Ashcan\" Pete"] = {
|
||||||
|
@ -16,8 +16,8 @@ function searchSelf()
|
|||||||
|
|
||||||
for _, obj in ipairs(searchArea(self.getPosition(), { 2.5, 0.5, 3.5 })) do
|
for _, obj in ipairs(searchArea(self.getPosition(), { 2.5, 0.5, 3.5 })) do
|
||||||
local obj = obj.hit_object
|
local obj = obj.hit_object
|
||||||
if obj.getCustomObject().image ==
|
local image = obj.getCustomObject().image
|
||||||
"http://cloud-3.steamusercontent.com/ugc/1758068501357192910/11DDDC7EF621320962FDCF3AE3211D5EDC3D1573/" then
|
if image == "http://cloud-3.steamusercontent.com/ugc/1758068501357192910/11DDDC7EF621320962FDCF3AE3211D5EDC3D1573/" then
|
||||||
foundTokens = foundTokens + math.abs(obj.getQuantity())
|
foundTokens = foundTokens + math.abs(obj.getQuantity())
|
||||||
obj.destruct()
|
obj.destruct()
|
||||||
elseif obj.getMemo() == "resourceCounter" then
|
elseif obj.getMemo() == "resourceCounter" then
|
||||||
@ -47,7 +47,7 @@ end
|
|||||||
function takeAll(playerColor)
|
function takeAll(playerColor)
|
||||||
searchSelf()
|
searchSelf()
|
||||||
local matColor = playmatApi.getMatColorByPosition(self.getPosition())
|
local matColor = playmatApi.getMatColorByPosition(self.getPosition())
|
||||||
playmatApi.gainResources(foundTokens, matColor)
|
playmatApi.updateCounter(matColor, "ResourceCounter", foundTokens)
|
||||||
|
|
||||||
if clickableResourceCounter then
|
if clickableResourceCounter then
|
||||||
clickableResourceCounter.call("updateVal", 0)
|
clickableResourceCounter.call("updateVal", 0)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
local playmatAPI = require("playermat/PlaymatApi")
|
local playmatApi = require("playermat/PlaymatApi")
|
||||||
|
|
||||||
function onLoad()
|
function onLoad()
|
||||||
self.addContextMenuItem("Discard 10 cards", shortSupply)
|
self.addContextMenuItem("Discard 10 cards", shortSupply)
|
||||||
@ -6,11 +6,11 @@ end
|
|||||||
|
|
||||||
-- called by context menu entry
|
-- called by context menu entry
|
||||||
function shortSupply(color)
|
function shortSupply(color)
|
||||||
local matColor = playmatAPI.getMatColorByPosition(self.getPosition())
|
local matColor = playmatApi.getMatColorByPosition(self.getPosition())
|
||||||
|
|
||||||
-- get draw deck and discard position
|
-- get draw deck and discard position
|
||||||
local drawDeck = playmatAPI.getDrawDeck(matColor)
|
local drawDeck = playmatApi.getDrawDeck(matColor)
|
||||||
local discardPos = playmatAPI.getDiscardPosition(matColor)
|
local discardPos = playmatApi.getDiscardPosition(matColor)
|
||||||
|
|
||||||
-- error handling
|
-- error handling
|
||||||
if discardPos == nil then
|
if discardPos == nil then
|
||||||
@ -21,7 +21,7 @@ function shortSupply(color)
|
|||||||
if drawDeck == nil then
|
if drawDeck == nil then
|
||||||
broadcastToColor("Deck not found!", color, "Yellow")
|
broadcastToColor("Deck not found!", color, "Yellow")
|
||||||
return
|
return
|
||||||
elseif drawDeck.tag ~= "Deck" then
|
elseif drawDeck.type ~= "Deck" then
|
||||||
broadcastToColor("Deck only contains a single card!", color, "Yellow")
|
broadcastToColor("Deck only contains a single card!", color, "Yellow")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user