Skip to content

Commit

Permalink
Merge branch 'main' into Eye-of-Ghatanothoa
Browse files Browse the repository at this point in the history
  • Loading branch information
Chr1Z93 committed Jan 8, 2025
2 parents e4b8fe7 + dc5433d commit 50ee45d
Show file tree
Hide file tree
Showing 11 changed files with 140 additions and 41 deletions.
2 changes: 1 addition & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@
0,
0
],
"SaveName": "Arkham SCE - 4.0.3",
"SaveName": "Arkham SCE - 4.1.0",
"Sky": "Sky_Museum",
"SkyURL": "https://i.imgur.com/GkQqaOF.jpg",
"SnapPoints_path": "SnapPoints.json",
Expand Down
6 changes: 3 additions & 3 deletions objects/PatchNotes.f47225.luascriptstate
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
},
"tooltip": "None",
"value": [
"Arkham Horror LCG SCE 4.0.3 - 11/21/2024"
"Arkham Horror LCG SCE 4.1.0 - 01/11/2025"
]
},
{
Expand All @@ -104,7 +104,7 @@
"g": 1,
"r": 1
},
"font": "70",
"font": "115",
"locked": false,
"name": "Details",
"pos": {
Expand All @@ -124,7 +124,7 @@
},
"tooltip": "None",
"value": [
"Changes from 4.0.3\n- added ability for 'number typing' to the chaos token draw button\n- added \"0 uses\" metadata for Charles Ross\n- added \"imprinting\" to Charisma / Relic Hunter (drop them on a playermat!)\n- turned \"randomize\" feature of action / ability tokens into a context menu entry\n- turned upgradesheets into XML and their boxes into crosses\n- fixed Clean Up Helper toggling the \"subtract doom\" feature\n- fixed DES scripting\n- fixed error with Navigation Overlay\n- fixed error with investigator placing on playermats\n- fixed error with Kohaku feedback messages\n- fixed issues with Campaign Importer / Exporter\n- fixed handling for cards with attachments (Deck Importer)\n\nHighlights from 4.0.0\n\nNew Stuff\n- added Parallel Mateo\n- added a global UI for the Bless / Curse manager\n- added a \"shuffle discard into deck\" button to playermats (for example for the mulligan)\n- added XML helper for \"Stella Clark\", \"The Red Clock\" and \"Elle Rubash\"\n- added \"clickability\" to damage / horror tokens and updated the font / image\n- added investigator specific things spawning when placing (e.g. Bounty tokens for Tony)\n- added a right-click function to the left-most \"Discard\" button on playermats\n- added ability for the \"doom in play\" counter to subtract from the total (e.g. Longest Night)\n\nBugfixes\n- fixed hotkey for multi-handed Upkeep\n- fixed wrong visibility of playermat option panels after loading\n- fixed issues with token redrawing\n- fixed issues with scenario reference card detection\n- updated Navigation Overlay to not break with removed playermats\n- Clean Up Helper: 'nil' handling for scenario, mini card detection and action token resetting\n\nThe campaigns were also updated with improved helpers and upgraded campaign logs!\nPreviewed / spoiled cards for the upcoming cycle \"The Drowned City\" can be accessed\nvia the download menu (bottom right corner of your screen).\n"
"New Stuff\r\n- added minicard sync (drop minicard on investigator)\r\n- added search assistant for encounter deck\r\n- added handling for revealed top card of encounter deck\r\n- added already previewed cards from The Drowned City\r\n- added filtering to Search-A-Card (syntax similar to ArkhamDB)\r\n- added proper helper for parallel Mateo\r\n- added token attaching to cards so they don't drop shitty on snap points\r\n- added hotkeys for navigation overlay\r\n\r\nUpdates\r\n- updated \"Encounter Card Bag\" to replace cards inside decks\r\n- updated \"Chef's Selection\" for resource counters to use them for\nauto-replenishing cards\r\n- increased checkbox cross size on Upgradesheets\r\n- rehosted some models to steamcloud for performance\nand regions without access to pastebin\r\n\r\nBugfixes\r\n- fixed color for Token Draw Dummy\n(type a number on the \"Draw Chaos Token\" button)\r\n- fixed handling for Underworld Market Taboo\r\n- ignore Explore / Tekeli-li deck for displacement"
]
}
],
Expand Down
2 changes: 1 addition & 1 deletion objects/Search-A-Card.24051a.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"ImageURL": "https://steamusercontent-a.akamaihd.net/ugc/2342503777976621188/4C119690DEF2B128E6EC309A880984E55D80350C/",
"WidthScale": 0
},
"Description": "Allows searching for card(s) by name or filters. Use the buttons to toggle the spawn / search mode.\n\nThe search partially supports filters in the style of ArkhamDB:\nk - Trait\no - cost\np - level\nf - class\nz - slot\nt - type\n\nTo use a filter, use the abbreviation and then an operator (:, !, < or >) followed by the filter value. Example:\nk:criminal t!investigator",
"Description": "Allows searching for card(s) by name or filters. Use the buttons to toggle the spawn / search mode.\n\nThe search partially supports filters in the style of ArkhamDB:\nk - Trait\no - cost\np - level\nf - class\nz - slot\nt - type\n\nTo use a filter, use the abbreviation and then an operator (:, !, \u003c or \u003e) followed by the filter value. Example:\nk:criminal t!investigator",
"DragSelectable": true,
"GMNotes": "",
"GUID": "24051a",
Expand Down
2 changes: 1 addition & 1 deletion src/core/Constants.ttslua
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ ENCOUNTER_DECK_POS = Vector(-3.93, 1.5, 5.76)
ENCOUNTER_DISCARD_POSITION = Vector(-3.85, 1.5, 10.38)

-- online functionality related variables
MOD_VERSION = "4.0.3"
MOD_VERSION = "4.1.0"
SOURCE_REPO = "https://github.com/Chr1Z93/SCED-downloads/releases/latest/download/"
--SOURCE_REPO = "https://github.com/Chr1Z93/SCED-downloads/releases/download/v1.0.1/"
141 changes: 111 additions & 30 deletions src/core/Global.ttslua
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ local lastDrawnTokens = {}

local bagSearchers = {}
local hideTitleSplashWaitFunctionId = nil
local lastZoneEnterObject = nil

-- online functionality related variables
local library, requestObj, modMeta, searchFilter, authorFilter
Expand Down Expand Up @@ -75,6 +76,7 @@ local blurseVisibility = {}

-- track cards' tokens
local cardTokens = {}
local cardSettings = {}

---------------------------------------------------------
-- data for tokens
Expand Down Expand Up @@ -208,6 +210,8 @@ function tryObjectEnterContainer(container, object)
-- stop mini cards from forming decks
if object.hasTag("Minicard") and container.hasTag("Minicard") then
return false
elseif object.type == "Card" and object.getName() ~= "Atlach-Nacha" then
handleTokenDetaching({ card = object })
end

playAreaApi.tryObjectEnterContainer(container, object)
Expand All @@ -216,16 +220,31 @@ end

-- TTS event for objects that enter zones
function onObjectEnterZone(zone, object)
if lastZoneEnterObject == object then return end
lastZoneEnterObject = object
Wait.frames(function() lastZoneEnterObject = nil end, 3)

-- detect the "token discard zones" beneath the hand zones
if zone.getName() == "TokenDiscardZone" and
not tokenChecker.isChaosToken(object) and
object.type == "Tile" and
object.getMemo() and
not object.getLock() and
object.interactable == true then
local matcolor = playermatApi.getMatColorByPosition(object.getPosition())
local trash = guidReferenceApi.getObjectByOwnerAndType(matcolor, "Trash")
trash.putObject(object)
if zone.getName() == "TokenDiscardZone" then
if object.type == "Card" then
local attachments = object.getAttachments()
if not attachments then return end

local matcolor = playermatApi.getMatColorByPosition(object.getPosition())
local trash = guidReferenceApi.getObjectByOwnerAndType(matcolor, "Trash")

for i = #attachments, 1, -1 do
local deepObj = attachments[i]
if not tokenChecker.isChaosTokenName(deepObj["nickname"]) and deepObj["memo"] ~= nil then
trash.putObject(object.removeAttachment(deepObj["index"]))
end
end
elseif object.type == "Tile" and not tokenChecker.isChaosToken(object) and object.getMemo() and
not object.getLock() and object.interactable == true then
local matcolor = playermatApi.getMatColorByPosition(object.getPosition())
local trash = guidReferenceApi.getObjectByOwnerAndType(matcolor, "Trash")
trash.putObject(object)
end
elseif zone.type == "Hand" and object.type == "Card" then
-- make sure the card is face-up
if object.is_face_down then
Expand Down Expand Up @@ -300,15 +319,22 @@ function onObjectNumberTyped(hoveredObject, playerColor, number)
end
end

-- disable delete action (only applies to promoted players) and discard objects instead
function onPlayerAction(player, action, targets)
if action == Player.Action.Delete and not player.admin then
-- disable delete action (only applies to promoted players) and discard objects instead
for _, target in ipairs(targets) do
local matColor = playermatApi.getMatColorByPosition(target.getPosition())
local trash = guidReferenceApi.getObjectByOwnerAndType(matColor, "Trash")
trash.putObject(target)
end
return false
elseif action == Player.Action.PickUp then
-- attach tokens to each card -> might need to add a limit if performance is an issue
for _, target in ipairs(targets) do
if target.type == "Card" and not target.hasTag("Minicard") then
handleTokenAttaching({ player = player, card = target })
end
end
end
end

Expand Down Expand Up @@ -2333,31 +2359,31 @@ function TokenManager.spawnMultipleTokens(card, tokenType, tokenCount, shiftDown
local activeInvestigatorData = playermatApi.getActiveInvestigatorData(matColor)
callbackName = "updateUniversalActionAbilityToken"
callbackParams = {
class = activeInvestigatorData.class,
class = activeInvestigatorData.class,
symbol = subType,
addTag = temporary and "Temporary" or nil
}
end

for i = 1, tokenCount do
TokenManager.spawnToken({
position = offsets[i],
tokenType = tokenType,
rotation = card.getRotation(),
callbackName = callbackName,
position = offsets[i],
tokenType = tokenType,
rotation = card.getRotation(),
callbackName = callbackName,
callbackParams = callbackParams
})
end
end

-- Spawns a single token at the given global position by copying it from the template bag.
function TokenManager.spawnToken(params)
local position = params.position
local rotation = params.rotation
local tokenType = params.tokenType
local callbackName = params.callbackName
local position = params.position
local rotation = params.rotation
local tokenType = params.tokenType
local callbackName = params.callbackName
local callbackParams = params.callbackParams
local scriptstate = params.scriptstate
local scriptstate = params.scriptstate

-- initialize data table
local spawnData = { position = position }
Expand Down Expand Up @@ -2463,8 +2489,8 @@ end
function TokenManager.initDataHelperData()
if playerCardData ~= nil then return end
local dataHelper = guidReferenceApi.getObjectByOwnerAndType("Mythos", "DataHelper")
playerCardData = dataHelper.getTable('PLAYER_CARD_DATA')
locationData = dataHelper.getTable('LOCATIONS_DATA')
playerCardData = dataHelper.getTable('PLAYER_CARD_DATA')
locationData = dataHelper.getTable('LOCATIONS_DATA')
end

-- Spawn tokens for a card based on the uses metadata. This will consider the face up/down state
Expand Down Expand Up @@ -2888,18 +2914,72 @@ function moveAndRotatePlayermat(params)
playermatApi.moveAndRotate(params.matColor, params.position, params.rotationY)
end

-- check if an element is in a table
function tableContains(thisTable, thisElement)
for _, element in pairs(thisTable) do
if element == thisElement then
return true
function handleTokenAttaching(params)
local card = params.card
if card == nil then return end

local player = params.player
local searchResult = searchLib.onObject(card, "isTileOrToken", 0.9)

if card.is_face_down and next(searchResult) ~= nil then
cardSettings[card] = {
hideFacedown = card.hide_when_face_down,
tooltip = card.tooltip
}
card.hide_when_face_down = false
card.tooltip = false
end

for _, token in ipairs(searchResult) do
if not token.locked then
card.addAttachment(token)
end
end
return false

Wait.condition(
function() handleTokenDetaching({ card = card }) end,
function()
if card ~= nil and player ~= nil and player.seated then
return card.resting and card.held_by_color ~= player.color
else
return true
end
end
)
end

function moveCardWithTokens(params)
function handleTokenDetaching(params)
local card = params.card
if card == nil or next(card.getAttachments()) == nil then return end

-- restore card settings
if cardSettings[card] ~= nil then
card.hide_when_face_down = cardSettings[card]["hideFacedown"]
card.tooltip = cardSettings[card]["tooltip"]
cardSettings[card] = nil
end

-- remove attachments (move tokens below the card on top)
local removedTokens = card.removeAttachments()
for _, token in ipairs(removedTokens) do
if token.getPosition().y < card.getPosition().y then
local posY = card.getPosition().y + 0.05
token.setPosition(token.getPosition():setAt("y", posY))
end
end

-- redraw token xml for cards with sealing
if card.hasTag("CardThatSeals") then
local func = card.getVar("updateStackSize") -- make sure function exists
if func ~= nil then
card.call("updateStackSize")
end
end
return removedTokens
end

function moveCardWithTokens(params)
local card = params.card
local position = params.position
local rotation = params.rotation

Expand All @@ -2925,7 +3005,6 @@ function moveCardWithTokens(params)
updateTokenTransform(card)
return card.resting and not card.isSmoothMoving()
end

return true
end
)
Expand Down Expand Up @@ -2976,6 +3055,8 @@ end
-- removes tokens from the provided card/deck
function removeTokensFromObject(params)
local object = params.object
if object == nil then return end

local trash = guidReferenceApi.getObjectByOwnerAndType(params.owner, "Trash")

if object.hasTag("CardThatSeals") then
Expand Down
6 changes: 6 additions & 0 deletions src/core/GlobalApi.ttslua
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ do
Global.call("moveCardWithTokens", { card = card, position = position, rotation = rotation })
end

-- handles token detaching for cards
---@param card tts__Object Card that should get tokens detached
function GlobalApi.handleTokenDetaching(card)
Global.call("handleTokenDetaching", { card = card })
end

-- loads saved options
---@param options table Set a new state for the option table
function GlobalApi.loadOptionPanelSettings(options)
Expand Down
1 change: 1 addition & 0 deletions src/mythos/MythosArea.ttslua
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ function onCollisionEnter(collisionInfo)
if inArea(localPos, ENCOUNTER_DECK_DISCARD_AREA) then
-- reset spawned tokens and remove tokens from cards in encounter deck / discard area
Wait.frames(function() tokenSpawnTrackerApi.resetTokensSpawned(object) end, 1)
GlobalApi.handleTokenDetaching(object)
GlobalApi.removeTokensFromObject(object, "Mythos")
elseif inArea(localPos, SCENARIO_REFERENCE_AREA) then
-- detect scenario reference card and attempt to load data from it
Expand Down
6 changes: 3 additions & 3 deletions src/playarea/PlayAreaImageData.ttslua
Original file line number Diff line number Diff line change
Expand Up @@ -256,15 +256,15 @@ PLAYAREA_IMAGE_DATA = {
URL = "https://steamusercontent-a.akamaihd.net/ugc/2279446315725449814/30BB7E4F8D9F1571A420372E78ACAF2D7792811F/"
},
{
Name = "VII - The Depths of Yoth 1",
Name = "VII - The Depths of Yoth 1",
URL = "https://steamusercontent-a.akamaihd.net/ugc/2279446315725449962/D69532827DFF2D654F8A606B7917D593F52D7624/"
},
{
Name = "VII - The Depths of Yoth 2",
Name = "VII - The Depths of Yoth 2",
URL = "https://steamusercontent-a.akamaihd.net/ugc/2279446315725450085/479A8A1BDD7BE80B43AE4F2C14DFA811D7B28482/"
},
{
Name = "VII - The Depths of Yoth 3",
Name = "VII - The Depths of Yoth 3",
URL = "https://steamusercontent-a.akamaihd.net/ugc/2279446315725450258/E617F5A78DFBE913652E20BF97D38B91087FACAE/"
},
{
Expand Down
4 changes: 3 additions & 1 deletion src/playermat/Playermat.ttslua
Original file line number Diff line number Diff line change
Expand Up @@ -1106,7 +1106,7 @@ function applyOptionPanelChange(id, state, clickType)
resetSlotSymbols()
elseif currentlyEditingSlots and clickType == "-3" then -- middle-clicked
resetSlotSymbols(true)
else
elseif clickType == "-1" then -- left-clicked
toggleSlotEditing()
end
end
Expand Down Expand Up @@ -1295,6 +1295,8 @@ function onCollisionEnter(collisionInfo)
collisionTable[object] = true
Wait.frames(function() collisionTable[object] = nil end, 1)

GlobalApi.handleTokenDetaching(object)

local md = JSON.decode(object.getGMNotes()) or {}
syncCustomizableMetadata(object, md)

Expand Down
9 changes: 9 additions & 0 deletions src/tokens/TokenChecker.ttslua
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,14 @@ do
end
end

-- returns true if the passed name is a chaos token name
TokenChecker.isChaosTokenName = function(objName)
if CHAOS_TOKEN_NAMES[objName] then
return true
else
return false
end
end

return TokenChecker
end
2 changes: 1 addition & 1 deletion src/util/SearchLib.ttslua
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ do
isClue = function(x) return x.memo == "clueDoom" and x.is_face_down == false end,
isDoom = function(x) return x.memo == "clueDoom" and x.is_face_down == true end,
isInteractable = function(x) return x.interactable end,
isTileOrToken = function(x) return x.type == "Tile" or x.type == "Generic" end,
isTileOrToken = function(x) return not x.Book and (x.type == "Tile" or x.type == "Generic") end,
isUniversalToken = function(x) return x.getMemo() == "universalActionAbility" end,
}

Expand Down

0 comments on commit 50ee45d

Please sign in to comment.