Merge branch 'utility-file' into custom-card-importing
This commit is contained in:
commit
85526429f0
@ -1,3 +1,4 @@
|
||||
local searchLib = require("util/SearchLib")
|
||||
local fontColor
|
||||
local BACKGROUNDS = {
|
||||
{
|
||||
@ -112,25 +113,11 @@ end
|
||||
-- attempt to load image from below card when dropped
|
||||
function onDrop(playerColor)
|
||||
local pos = self.getPosition():setAt("y", 2)
|
||||
local search = Physics.cast({
|
||||
direction = { 0, -1, 0 },
|
||||
max_distance = 2,
|
||||
type = 3,
|
||||
size = { 0.1, 0.1, 0.1 },
|
||||
origin = pos
|
||||
})
|
||||
local searchResult = searchLib.belowPosition(pos, "isCard")
|
||||
if #searchResult == 0 then return end
|
||||
local syncName = searchResult[1].getName()
|
||||
|
||||
local syncName
|
||||
for _, v in ipairs(search) do
|
||||
if v.hit_object.tag == "Card" then
|
||||
syncName = v.hit_object.getName()
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not syncName then return end
|
||||
|
||||
-- remove level information fron syncName
|
||||
-- remove level information from syncName
|
||||
syncName = syncName:gsub("%s%(%d%)", "")
|
||||
|
||||
-- loop through background table
|
||||
@ -170,9 +157,9 @@ end
|
||||
-- only allow cards to enter, split decks and reject other objects
|
||||
function onObjectEnterContainer(container, object)
|
||||
if container ~= self then return end
|
||||
if object.tag == "Deck" then
|
||||
if object.type == "Deck" then
|
||||
takeDeckOut(object.getGUID(), self.getPosition() + Vector(0, 0.1, 0))
|
||||
elseif object.tag ~= "Card" then
|
||||
elseif object.type ~= "Card" then
|
||||
broadcastToAll("The 'Attachment Helper' is meant to be used for cards.", "White")
|
||||
else
|
||||
findCard(object.getGUID(), object.getName(), object.getGMNotes())
|
||||
|
@ -8,6 +8,7 @@ local chaosBagApi = require("chaosbag/ChaosBagApi")
|
||||
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||
local playAreaApi = require("core/PlayAreaApi")
|
||||
local playmatApi = require("playermat/PlaymatApi")
|
||||
local searchLib = require("util/SearchLib")
|
||||
local soundCubeApi = require("core/SoundCubeApi")
|
||||
local tokenSpawnTrackerApi = require("core/token/TokenSpawnTrackerApi")
|
||||
|
||||
@ -284,7 +285,7 @@ function tidyPlayerMatCoroutine()
|
||||
if i < 5 then
|
||||
objList = playmatApi.searchAroundPlaymat(COLORS[i])
|
||||
else
|
||||
objList = searchMythosArea()
|
||||
objList = searchLib.inArea({ -2, 2, 10 }, { 0, 270, 0 }, { 55, 1, 13.5 })
|
||||
end
|
||||
|
||||
for _, obj in ipairs(objList) do
|
||||
@ -321,26 +322,3 @@ function tidyPlayerMatCoroutine()
|
||||
printToAll("Clean up completed!", "Green")
|
||||
return 1
|
||||
end
|
||||
|
||||
---------------------------------------------------------
|
||||
-- helper functions
|
||||
---------------------------------------------------------
|
||||
|
||||
-- find objects in the mythos area
|
||||
function searchMythosArea()
|
||||
local searchResult = Physics.cast({
|
||||
direction = { 0, 1, 0 },
|
||||
max_distance = 1,
|
||||
type = 3,
|
||||
size = { 55, 1, 13.5 },
|
||||
origin = { -2, 2, 10 },
|
||||
orientation = { 0, 270, 0 },
|
||||
debug = false
|
||||
})
|
||||
|
||||
local objList = {}
|
||||
for _, v in ipairs(searchResult) do
|
||||
table.insert(objList, v.hit_object)
|
||||
end
|
||||
return objList
|
||||
end
|
||||
|
@ -1,9 +1,9 @@
|
||||
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||
local objects
|
||||
local playmatApi = require("playermat/PlaymatApi")
|
||||
|
||||
function onClick_hideShow(player, matColor)
|
||||
objects = guidReferenceApi.getObjectsByOwner(matColor)
|
||||
local actionTokens = searchMat(objects.Playermat.positionToWorld({-1.1, 0.05, -0.27}), {4, 1, 1}, isActionToken)
|
||||
local objects = guidReferenceApi.getObjectsByOwner(matColor)
|
||||
local actionTokens = playmatApi.searchAroundPlaymat(matColor, "isActionToken")
|
||||
local pos = objects.Playermat.getPosition()
|
||||
local mod = (pos.y > 0) and -2 or 2
|
||||
|
||||
@ -18,24 +18,3 @@ function onClick_hideShow(player, matColor)
|
||||
obj.setPosition(obj.getPosition() + Vector(0, mod, 0))
|
||||
end
|
||||
end
|
||||
|
||||
function isActionToken(x) return x.getDescription() == 'Action Token' end
|
||||
|
||||
function searchMat(origin, size, filter)
|
||||
local searchResult = Physics.cast({
|
||||
origin = origin,
|
||||
direction = { 0, 1, 0 },
|
||||
orientation = objects.Playermat.getRotation(),
|
||||
type = 3,
|
||||
size = size,
|
||||
max_distance = 0
|
||||
})
|
||||
|
||||
local objList = {}
|
||||
for _, v in ipairs(searchResult) do
|
||||
if not filter or (filter and filter(v.hit_object)) then
|
||||
table.insert(objList, v.hit_object)
|
||||
end
|
||||
end
|
||||
return objList
|
||||
end
|
||||
|
@ -1,3 +1,4 @@
|
||||
local searchLib = require("util/SearchLib")
|
||||
local playmatApi = require("playermat/PlaymatApi")
|
||||
|
||||
-- forward declaration of variables that are used across functions
|
||||
@ -159,17 +160,12 @@ function endSearch(_, _, isRightClick)
|
||||
end
|
||||
|
||||
-- draw set aside cards (from the ground!)
|
||||
for _, v in ipairs(searchArea(setAsidePosition)) do
|
||||
local obj = v.hit_object
|
||||
for _, obj in ipairs(searchLib.atPosition(setAsidePosition), "isCardOrDeck") do
|
||||
if obj.type == "Deck" then
|
||||
Wait.time(function()
|
||||
obj.deal(#obj.getObjects(), handColor)
|
||||
end, 1)
|
||||
break
|
||||
Wait.time(function() obj.deal(#obj.getObjects(), handColor) end, 1)
|
||||
elseif obj.type == "Card" then
|
||||
obj.setPosition(Player[handColor].getHandTransform().position)
|
||||
obj.flip()
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
@ -190,14 +186,3 @@ function endSearch(_, _, isRightClick)
|
||||
Wait.time(function() playmatApi.flipTopCardFromDeck(matColor) end, #handCards * 0.1)
|
||||
end
|
||||
end
|
||||
|
||||
-- utility function
|
||||
function searchArea(position)
|
||||
return Physics.cast({
|
||||
origin = position,
|
||||
direction = { 0, 1, 0 },
|
||||
type = 3,
|
||||
size = { 2, 2, 2 },
|
||||
max_distance = 0
|
||||
})
|
||||
end
|
||||
|
@ -1,3 +1,5 @@
|
||||
local searchLib = require("util/SearchLib")
|
||||
|
||||
local classOrder = {
|
||||
"Guardian",
|
||||
"Seeker",
|
||||
@ -75,17 +77,8 @@ function updateDisplayButtons(_, playerColor)
|
||||
end
|
||||
|
||||
function getNotesFromCardsAndContainers()
|
||||
local search = Physics.cast({
|
||||
direction = { 0, 1, 0 },
|
||||
max_distance = 0,
|
||||
type = 3,
|
||||
size = self.getBounds().size:setAt("y", 1),
|
||||
origin = self.getPosition() + Vector(0, 0.5, 0),
|
||||
})
|
||||
|
||||
local notesList = {}
|
||||
for _, hit in ipairs(search) do
|
||||
local obj = hit.hit_object
|
||||
for _, obj in ipairs(searchLib.onObject(self)) do
|
||||
local notes = {}
|
||||
if obj.type == "Card" then
|
||||
notes = JSON.decode(obj.getGMNotes()) or {}
|
||||
|
@ -1,3 +1,5 @@
|
||||
local searchLib = require("util/SearchLib")
|
||||
|
||||
function onload(saved_data)
|
||||
revealCardPositions = {
|
||||
Vector(3.5, 0.25, 0),
|
||||
@ -176,17 +178,8 @@ function getRevealedCards()
|
||||
local revealedCards = {}
|
||||
|
||||
for _, pos in ipairs(revealCardPositions) do
|
||||
local hitList = Physics.cast({
|
||||
origin = self.positionToWorld(pos) + Vector(0, 0.25, 0),
|
||||
direction = {0,-1,0},
|
||||
type = 1,
|
||||
max_distance = 2
|
||||
})
|
||||
|
||||
for _, hit in ipairs(hitList) do
|
||||
if hit.hit_object != self and hit.hit_object.tag == "Card" then
|
||||
table.insert(revealedCards, hit.hit_object.getGUID())
|
||||
end
|
||||
for _, obj in ipairs(searchLib.atPosition(self.positionToWorld(pos), "isCard")) do
|
||||
table.insert(revealedCards, obj.getGUID())
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
local searchLib = require("util/SearchLib")
|
||||
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||
local playAreaApi = require("core/PlayAreaApi")
|
||||
|
||||
@ -62,13 +63,12 @@ function updateVal(number)
|
||||
broadcastDoom(val)
|
||||
end
|
||||
|
||||
--called by updateVal and addVal to broadcast total doom in play, including doom threshold
|
||||
-- called by updateVal and addVal to broadcast total doom in play, including doom threshold
|
||||
function broadcastDoom(val)
|
||||
|
||||
if val ~= 0 then
|
||||
local doomInPlayCounter = guidReferenceApi.getObjectByOwnerAndType("Mythos", "DoomInPlayCounter")
|
||||
otherDoom = doomInPlayCounter.call("countDoom")
|
||||
totalDoomThreshold = getDoomThreshold()
|
||||
local otherDoom = doomInPlayCounter.call("countDoom")
|
||||
local totalDoomThreshold = getDoomThreshold()
|
||||
|
||||
if totalDoomThreshold ~= nil then
|
||||
broadcastToAll(val .. " doom on the agenda (" .. otherDoom + val .. "/" .. totalDoomThreshold .. " in play)", "White")
|
||||
@ -91,13 +91,10 @@ function startReset()
|
||||
end
|
||||
end
|
||||
|
||||
-- get Doom Threshold from top card of Agenda deck
|
||||
-- get doom threshold from top card of Agenda deck
|
||||
function getDoomThreshold()
|
||||
|
||||
local origin = { -2.72, 1.6, 0.37 } -- this needs to be edited to the actual coordinates of the agenda deck
|
||||
local size = { 0.1, 0.1, 0.1 } -- very slim area, basically a single raycast
|
||||
local searchResult = searchArea(origin, size, isCardOrDeck)
|
||||
|
||||
local agendaPos = { -2.72, 1.6, 0.37 }
|
||||
local searchResult = searchLib.atPosition(agendaPos, "isCardOrDeck")
|
||||
local metadata = {}
|
||||
if #searchResult == 0 then
|
||||
-- handle no agenda found
|
||||
@ -110,32 +107,27 @@ function getDoomThreshold()
|
||||
if metadata == nil then
|
||||
return nil
|
||||
else
|
||||
if(metadata.doomThresholdPerInvestigator) then
|
||||
|
||||
if metadata.doomThresholdPerInvestigator then
|
||||
return metadata.doomThresholdPerInvestigator*playAreaApi.getInvestigatorCount() + metadata.doomThreshold
|
||||
else
|
||||
return metadata.doomThreshold
|
||||
return metadata.doomThreshold
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
-- handle agenda deck
|
||||
|
||||
local cardData = searchResult[1].getData().ContainedObjects
|
||||
local topCardData = cardData[#cardData]
|
||||
metadata = JSON.decode(topCardData.GMNotes)
|
||||
if metadata == nil then
|
||||
return nil
|
||||
else
|
||||
if(metadata.doomThresholdPerInvestigator) then
|
||||
if metadata.doomThresholdPerInvestigator then
|
||||
return metadata.doomThresholdPerInvestigator*playAreaApi.getInvestigatorCount() + metadata.doomThreshold
|
||||
else
|
||||
return metadata.doomThreshold
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
else
|
||||
-- handle multiple cards / decks found
|
||||
return nil
|
||||
@ -157,28 +149,3 @@ function toggleOptions()
|
||||
self.UI.hide("Options")
|
||||
end
|
||||
end
|
||||
|
||||
-- searches an area and optionally filters the result
|
||||
function searchArea(origin, size, filter)
|
||||
local searchResult = Physics.cast({
|
||||
origin = origin,
|
||||
direction = { 0, 1, 0 },
|
||||
orientation = self.getRotation(),
|
||||
type = 3,
|
||||
size = size,
|
||||
max_distance = 0
|
||||
})
|
||||
|
||||
local objList = {}
|
||||
for _, v in ipairs(searchResult) do
|
||||
if not filter or (filter and filter(v.hit_object)) then
|
||||
table.insert(objList, v.hit_object)
|
||||
end
|
||||
end
|
||||
return objList
|
||||
end
|
||||
|
||||
-- filter functions for searchArea()
|
||||
function isCard(x) return x.type == 'Card' end
|
||||
function isDeck(x) return x.type == 'Deck' end
|
||||
function isCardOrDeck(x) return x.type == 'Card' or x.type == 'Deck' end
|
||||
|
@ -2,6 +2,7 @@ local blessCurseManagerApi = require("chaosbag/BlessCurseManagerApi")
|
||||
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||
local optionPanelApi = require("core/OptionPanelApi")
|
||||
local playmatApi = require("playermat/PlaymatApi")
|
||||
local searchLib = require("util/SearchLib")
|
||||
local victoryDisplayApi = require("core/VictoryDisplayApi")
|
||||
|
||||
function onLoad()
|
||||
@ -69,10 +70,8 @@ function discardObject(playerColor, hoveredObject)
|
||||
|
||||
-- discard tokens / tiles on cards / decks
|
||||
if hoveredObject.type ~= "Tile" then
|
||||
for _, v in ipairs(searchOnObj(hoveredObject)) do
|
||||
if v.hit_object.type == "Tile" then
|
||||
table.insert(discardTheseObjects, v.hit_object)
|
||||
end
|
||||
for _, obj in ipairs(searchLib.onObject(hoveredObject), "isTileOrToken") do
|
||||
table.insert(discardTheseObjects, obj)
|
||||
end
|
||||
end
|
||||
|
||||
@ -151,9 +150,8 @@ function removeOneUse(playerColor, hoveredObject)
|
||||
local searchForType = useInfo.type
|
||||
if searchForType then searchForType = searchForType:lower() end
|
||||
|
||||
for _, v in ipairs(searchOnObj(hoveredObject)) do
|
||||
local obj = v.hit_object
|
||||
if obj.type == "Tile" and not obj.locked and obj.memo ~= "resourceCounter" then
|
||||
for _, obj in ipairs(searchLib.onObject(hoveredObject), "isTileOrToken") do
|
||||
if not obj.locked and obj.memo ~= "resourceCounter" then
|
||||
-- check for matching object, otherwise use the first hit
|
||||
if obj.memo == searchForType then
|
||||
targetObject = obj
|
||||
@ -211,18 +209,13 @@ function takeClueFromLocation(playerColor, hoveredObject)
|
||||
return
|
||||
elseif hoveredObject.type == "Card" then
|
||||
cardName = hoveredObject.getName()
|
||||
local searchResult = searchLib.onObject(hoveredObject, "isClue")
|
||||
|
||||
for _, v in ipairs(searchOnObj(hoveredObject)) do
|
||||
local obj = v.hit_object
|
||||
if obj.memo == "clueDoom" and obj.is_face_down == false then
|
||||
clue = obj
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if clue == nil then
|
||||
if #searchResult == 0 then
|
||||
broadcastToColor("This card does not have any clues on it.", playerColor, "Yellow")
|
||||
return
|
||||
else
|
||||
clue = searchResult[1]
|
||||
end
|
||||
elseif hoveredObject.memo == "clueDoom" then
|
||||
if hoveredObject.is_face_down then
|
||||
@ -230,22 +223,10 @@ function takeClueFromLocation(playerColor, hoveredObject)
|
||||
return
|
||||
end
|
||||
|
||||
clue = hoveredObject
|
||||
|
||||
local search = Physics.cast({
|
||||
direction = { 0, -1, 0 },
|
||||
max_distance = 0.1,
|
||||
type = 3,
|
||||
size = { 0.1, 0.1, 0.1 },
|
||||
origin = clue.getPosition()
|
||||
})
|
||||
local searchResult = searchLib.belowPosition(hoveredObject.getPosition(), "isCard")
|
||||
|
||||
for _, v in ipairs(search) do
|
||||
local obj = v.hit_object
|
||||
if obj.type == "Card" then
|
||||
cardName = obj.getName()
|
||||
break
|
||||
end
|
||||
if #searchResult ~= 0 then
|
||||
cardName = searchResult[1].getName()
|
||||
end
|
||||
else
|
||||
broadcastToColor("Hover a clue or card with clues and try again.", playerColor, "Yellow")
|
||||
@ -292,18 +273,6 @@ function addWendysMenu(playerColor, hoveredObject)
|
||||
blessCurseManagerApi.addWendysMenu(playerColor, hoveredObject)
|
||||
end
|
||||
|
||||
-- searches on an object (by using its bounds)
|
||||
---@param obj Object Object to search on
|
||||
function searchOnObj(obj)
|
||||
return Physics.cast({
|
||||
direction = { 0, 1, 0 },
|
||||
max_distance = 0.5,
|
||||
type = 3,
|
||||
size = obj.getBounds().size,
|
||||
origin = obj.getPosition()
|
||||
})
|
||||
end
|
||||
|
||||
-- Simple method to check if the given point is in a specified area
|
||||
---@param point Vector Point to check, only x and z values are relevant
|
||||
---@param bounds Table Defined area to see if the point is within
|
||||
@ -319,4 +288,4 @@ function titleCase(str)
|
||||
local first = str:sub(1, 1)
|
||||
local rest = str:sub(2)
|
||||
return first:upper() .. rest:lower()
|
||||
end
|
||||
end
|
||||
|
@ -4,6 +4,7 @@ local mythosAreaApi = require("core/MythosAreaApi")
|
||||
local navigationOverlayApi = require("core/NavigationOverlayApi")
|
||||
local playAreaApi = require("core/PlayAreaApi")
|
||||
local playmatApi = require("playermat/PlaymatApi")
|
||||
local searchLib = require("util/SearchLib")
|
||||
local soundCubeApi = require("core/SoundCubeApi")
|
||||
local tokenArrangerApi = require("accessories/TokenArrangerApi")
|
||||
local tokenChecker = require("core/token/TokenChecker")
|
||||
@ -1101,15 +1102,10 @@ end
|
||||
-- checks whether something is in the specified position
|
||||
-- returns true if empty
|
||||
function checkPositionForContentSpawn(checkPos)
|
||||
local search = Physics.cast({
|
||||
direction = { 0, 1, 0 },
|
||||
max_distance = 0.1,
|
||||
type = 3,
|
||||
size = { 0.1, 0.1, 0.1 },
|
||||
origin = checkPos
|
||||
})
|
||||
local searchResult = searchLib.atPosition(checkPos)
|
||||
|
||||
-- first hit is the table surface, additional hits means something is there
|
||||
return #search == 1
|
||||
return #searchResult == 1
|
||||
end
|
||||
|
||||
-- downloading of the library file
|
||||
|
@ -1,3 +1,4 @@
|
||||
local searchLib = require("util/SearchLib")
|
||||
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||
local playAreaApi = require("core/PlayAreaApi")
|
||||
local tokenArrangerApi = require("accessories/TokenArrangerApi")
|
||||
@ -129,18 +130,17 @@ end
|
||||
|
||||
-- gets the encounter deck (for internal functions and Api calls)
|
||||
function getEncounterDeck()
|
||||
local search = searchArea(ENCOUNTER_DECK_POS, { 3, 1, 4 }, isCardOrDeck)
|
||||
local searchResult = searchLib.atPosition(ENCOUNTER_DECK_POS, "isCardOrDeck")
|
||||
|
||||
for _, v in ipairs(search) do
|
||||
local obj = v.hit_object
|
||||
for _, obj in ipairs(searchResult) do
|
||||
if obj.type == 'Deck' then
|
||||
return obj
|
||||
end
|
||||
end
|
||||
|
||||
-- if no deck was found, return the first hit (a card)
|
||||
if #search > 0 then
|
||||
return search[1].hit_object
|
||||
if #searchResult > 0 then
|
||||
return searchResult[1]
|
||||
end
|
||||
end
|
||||
|
||||
@ -180,9 +180,9 @@ function reshuffleEncounterDeck(params)
|
||||
isReshuffling = true
|
||||
|
||||
-- shuffle and flip deck, draw card after completion
|
||||
local discarded = searchArea(ENCOUNTER_DISCARD_POSITION, { 3, 1, 4 }, isDeck)
|
||||
if #discarded > 0 then
|
||||
local deck = discarded[1].hit_object
|
||||
local searchResult = searchLib.atPosition(ENCOUNTER_DISCARD_POSITION, "isCardOrDeck")
|
||||
if #searchResult > 0 then
|
||||
local deck = searchResult[1]
|
||||
if not deck.is_face_down then deck.flip() end
|
||||
deck.shuffle()
|
||||
deck.setPositionSmooth(Vector(ENCOUNTER_DECK_POS) + Vector(0, 2, 0), false, true)
|
||||
@ -213,8 +213,7 @@ end
|
||||
|
||||
-- removes tokens from the provided card/deck
|
||||
function removeTokensFromObject(object)
|
||||
for _, v in ipairs(searchArea(object.getPosition(), { 3, 1, 4 })) do
|
||||
local obj = v.hit_object
|
||||
for _, obj in ipairs(searchLib.onObject(object)) do
|
||||
if obj.getGUID() ~= "4ee1f2" and -- table
|
||||
obj ~= self and
|
||||
obj.type ~= "Deck" and
|
||||
@ -226,32 +225,3 @@ function removeTokensFromObject(object)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- searches an area and optionally filters the result
|
||||
function searchArea(origin, size, filter)
|
||||
local objList = Physics.cast({
|
||||
origin = origin,
|
||||
direction = { 0, 1, 0 },
|
||||
orientation = self.getRotation(),
|
||||
type = 3,
|
||||
size = size,
|
||||
max_distance = 1
|
||||
})
|
||||
|
||||
if filter then
|
||||
local filteredList = {}
|
||||
for _, obj in ipairs(objList) do
|
||||
if filter(obj.hit_object) then
|
||||
table.insert(filteredList, obj)
|
||||
end
|
||||
end
|
||||
return filteredList
|
||||
else
|
||||
return objList
|
||||
end
|
||||
end
|
||||
|
||||
-- filter functions for searchArea
|
||||
function isDeck(x) return x.tag == 'Deck' end
|
||||
|
||||
function isCardOrDeck(x) return x.tag == 'Card' or x.tag == 'Deck' end
|
||||
|
@ -260,9 +260,6 @@ function getDynamicViewBounds(objList)
|
||||
}
|
||||
|
||||
for _, obj in pairs(objList) do
|
||||
-- handling for Physics.cast() results
|
||||
if not obj.type then obj = obj.hit_object end
|
||||
|
||||
if not obj.hasTag("CameraZoom_ignore") and not obj.hasTag("CampaignLog") then
|
||||
count = count + 1
|
||||
local bounds = obj.getBounds()
|
||||
|
@ -1,6 +1,6 @@
|
||||
---------------------------------------------------------
|
||||
-- general setup
|
||||
---------------------------------------------------------
|
||||
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||
local searchLib = require("util/SearchLib")
|
||||
local tokenManager = require("core/token/TokenManager")
|
||||
|
||||
-- Location connection directional options
|
||||
local BIDIRECTIONAL = 0
|
||||
@ -25,8 +25,7 @@ local collisionEnabled = false
|
||||
-- used for recreating the link to a custom data helper after image change
|
||||
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 = {
|
||||
left = { x = 0.00, y = 0, z = 7.67 },
|
||||
@ -44,8 +43,6 @@ local LOC_LINK_EXCLUDE_SCENARIOS = {
|
||||
["The Heart of Madness"] = true
|
||||
}
|
||||
|
||||
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||
local tokenManager = require("core/token/TokenManager")
|
||||
local clueData = {}
|
||||
local spawnedLocationGUIDs = {}
|
||||
local locations = {}
|
||||
@ -608,25 +605,8 @@ end
|
||||
-- checks if a card has clues on it, returns true if clues are on it
|
||||
---@param card TTSObject Card to check for clues
|
||||
function cardHasClues(card)
|
||||
for _, v in ipairs(searchOnObj(card)) do
|
||||
local obj = v.hit_object
|
||||
if obj.memo == "clueDoom" and obj.is_face_down == false then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- searches on an object (by using its bounds)
|
||||
---@param obj Object Object to search on
|
||||
function searchOnObj(obj)
|
||||
return Physics.cast({
|
||||
direction = { 0, 1, 0 },
|
||||
max_distance = 0.5,
|
||||
type = 3,
|
||||
size = obj.getBounds().size,
|
||||
origin = obj.getPosition()
|
||||
})
|
||||
local searchResult = searchLib.onObject(card, "isClue")
|
||||
return #searchResult > 0
|
||||
end
|
||||
|
||||
-- highlights all locations in the play area without metadata
|
||||
|
@ -1,12 +1,12 @@
|
||||
local chaosBagApi = require("chaosbag/ChaosBagApi")
|
||||
local searchLib = require("util/SearchLib")
|
||||
local chaosBagApi = require("chaosbag/ChaosBagApi")
|
||||
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||
local playAreaApi = require("core/PlayAreaApi")
|
||||
local tokenChecker = require("core/token/TokenChecker")
|
||||
local playAreaApi = require("core/PlayAreaApi")
|
||||
local tokenChecker = require("core/token/TokenChecker")
|
||||
|
||||
local pendingCall = false
|
||||
local messageSent = {}
|
||||
local missingData = {}
|
||||
local countedVP = {}
|
||||
local pendingCall = false
|
||||
local missingData = {}
|
||||
local countedVP = {}
|
||||
|
||||
local highlightMissing = false
|
||||
local highlightCounted = false
|
||||
@ -35,34 +35,23 @@ function onLoad()
|
||||
self.createButton(buttonParameters)
|
||||
|
||||
-- index 3: highlighting button (missing data)
|
||||
self.createButton({
|
||||
label = "!",
|
||||
click_function = "highlightMissingData",
|
||||
tooltip = "Enable highlighting of cards without metadata (VP on these is not counted).",
|
||||
function_owner = self,
|
||||
scale = { 0.15, 0.15, 0.15 },
|
||||
color = { 1, 0, 0 },
|
||||
width = 700,
|
||||
height = 800,
|
||||
font_size = 700,
|
||||
font_color = { 1, 1, 1 },
|
||||
position = { x = 1.82, y = 0.06, z = -1.32 }
|
||||
})
|
||||
buttonParameters.label = "!"
|
||||
buttonParameters.click_function = "highlightMissingData"
|
||||
buttonParameters.tooltip = "Enable highlighting of cards without metadata (VP on these is not counted)."
|
||||
buttonParameters.color = { 1, 0, 0 }
|
||||
buttonParameters.width = 700
|
||||
buttonParameters.height = 800
|
||||
buttonParameters.font_size = 700
|
||||
buttonParameters.position = { x = 1.82, y = 0.06, z = -1.32 }
|
||||
self.createButton(buttonParameters)
|
||||
|
||||
-- index 4: highlighting button (counted VP)
|
||||
self.createButton({
|
||||
label = "?",
|
||||
click_function = "highlightCountedVP",
|
||||
tooltip = "Enable highlighting of cards with VP.",
|
||||
function_owner = self,
|
||||
scale = { 0.15, 0.15, 0.15 },
|
||||
color = { 0, 1, 0 },
|
||||
width = 700,
|
||||
height = 800,
|
||||
font_size = 700,
|
||||
font_color = { 1, 1, 1 },
|
||||
position = { x = 1.5, y = 0.06, z = -1.32 }
|
||||
})
|
||||
buttonParameters.label = "?"
|
||||
buttonParameters.click_function = "highlightCountedVP"
|
||||
buttonParameters.tooltip = "Enable highlighting of cards with VP."
|
||||
buttonParameters.color = { 0, 1, 0 }
|
||||
buttonParameters.position.x = 1.5
|
||||
self.createButton(buttonParameters)
|
||||
|
||||
-- update the display label once
|
||||
Wait.time(updateCount, 1)
|
||||
@ -147,19 +136,17 @@ function updateCount()
|
||||
victoryPoints.playArea = playAreaApi.countVP()
|
||||
|
||||
-- count cards in victory display
|
||||
for _, v in ipairs(searchOnObj(self)) do
|
||||
local obj = v.hit_object
|
||||
|
||||
for _, obj in ipairs(searchLib.onObject(self), "isCardOrDeck") do
|
||||
-- check metadata for VP
|
||||
if obj.tag == "Card" then
|
||||
if obj.type == "Card" then
|
||||
local VP = getCardVP(obj, JSON.decode(obj.getGMNotes()))
|
||||
victoryPoints.display = victoryPoints.display + VP
|
||||
if VP > 0 then
|
||||
table.insert(countedVP, obj)
|
||||
end
|
||||
|
||||
-- handling for stacked cards
|
||||
elseif obj.tag == "Deck" then
|
||||
-- handling for stacked cards
|
||||
elseif obj.type == "Deck" then
|
||||
local VP = 0
|
||||
for _, deepObj in ipairs(obj.getObjects()) do
|
||||
local deepVP = getCardVP(obj, JSON.decode(deepObj.gm_notes))
|
||||
@ -212,8 +199,7 @@ end
|
||||
function highlightMissingData()
|
||||
self.editButton({
|
||||
index = 3,
|
||||
tooltip = (highlightMissing and "Enable" or "Disable") .. " highlighting of cards without metadata (VP on these is not counted)."
|
||||
})
|
||||
tooltip = (highlightMissing and "Enable" or "Disable") .. " highlighting of cards without metadata (VP on these is not counted)." })
|
||||
for _, obj in pairs(missingData) do
|
||||
if obj ~= nil then
|
||||
if highlightMissing then
|
||||
@ -249,7 +235,7 @@ end
|
||||
-- places the provided card in the first empty spot
|
||||
function placeCard(card)
|
||||
local trash = guidReferenceApi.getObjectByOwnerAndType("Mythos", "Trash")
|
||||
|
||||
|
||||
-- check snap point states
|
||||
local snaps = self.getSnapPoints()
|
||||
table.sort(snaps, function(a, b) return a.position.x > b.position.x end)
|
||||
@ -260,21 +246,15 @@ function placeCard(card)
|
||||
local positions = {}
|
||||
for i, snap in ipairs(snaps) do
|
||||
positions[i] = self.positionToWorld(snap.position)
|
||||
local hits = checkSnapPointState(positions[i])
|
||||
|
||||
-- first hit is self, additional hits must be cards / decks
|
||||
if #hits > 1 then
|
||||
fullSlots[i] = true
|
||||
end
|
||||
local searchResult = searchLib.atPosition(positions[i], "isCardOrDeck")
|
||||
fullSlots[i] = #searchResult > 0
|
||||
end
|
||||
|
||||
-- remove tokens from the card
|
||||
for _, v in ipairs(searchOnObj(card)) do
|
||||
local obj = v.hit_object
|
||||
|
||||
for _, obj in ipairs(searchLib.onObject(card)) do
|
||||
-- don't touch decks / cards
|
||||
if obj.tag == "Deck" or obj.tag == "Card" then
|
||||
-- put chaos tokens back into bag
|
||||
if obj.type == "Deck" or obj.type == "Card" then
|
||||
-- put chaos tokens back into bag
|
||||
elseif tokenChecker.isChaosToken(obj) then
|
||||
local chaosBag = chaosBagApi.findChaosBag()
|
||||
chaosBag.putObject(obj)
|
||||
@ -282,7 +262,7 @@ function placeCard(card)
|
||||
trash.putObject(obj)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- place the card
|
||||
local name = card.getName() or "Unnamed card"
|
||||
for i = 1, 10 do
|
||||
@ -298,28 +278,3 @@ function placeCard(card)
|
||||
broadcastToAll("Victory Display is full! " .. name .. " placed into slot 1.", "Orange")
|
||||
card.setPositionSmooth(positions[1], false, true)
|
||||
end
|
||||
|
||||
---------------------------------------------------------
|
||||
-- utility functions
|
||||
---------------------------------------------------------
|
||||
|
||||
-- searches on an object
|
||||
function searchOnObj(obj)
|
||||
return Physics.cast({
|
||||
direction = { 0, 1, 0 },
|
||||
max_distance = 0.5,
|
||||
type = 3,
|
||||
size = obj.getBounds().size,
|
||||
origin = obj.getPosition()
|
||||
})
|
||||
end
|
||||
|
||||
function checkSnapPointState(pos)
|
||||
return Physics.cast({
|
||||
direction = { 0, 1, 0 },
|
||||
max_distance = 0.1,
|
||||
type = 3,
|
||||
size = { 0.1, 0.1, 0.1 },
|
||||
origin = pos
|
||||
})
|
||||
end
|
||||
|
@ -2,6 +2,7 @@ do
|
||||
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||
local optionPanelApi = require("core/OptionPanelApi")
|
||||
local playAreaApi = require("core/PlayAreaApi")
|
||||
local searchLib = require("util/SearchLib")
|
||||
local tokenSpawnTrackerApi = require("core/token/TokenSpawnTrackerApi")
|
||||
|
||||
local PLAYER_CARD_TOKEN_OFFSETS = {
|
||||
@ -487,12 +488,10 @@ do
|
||||
if mat.positionToLocal(cardPos).x < -1 then return end
|
||||
|
||||
-- get current amount of resource tokens on the card
|
||||
local search = internal.searchOnCard(cardPos, card.getRotation())
|
||||
local clickableResourceCounter = nil
|
||||
local foundTokens = 0
|
||||
|
||||
for _, obj in ipairs(search) do
|
||||
local obj = obj.hit_object
|
||||
for _, obj in ipairs(searchLib.onObject(card), "isTileOrToken") do
|
||||
local memo = obj.getMemo()
|
||||
|
||||
if (stateTable[memo] or 0) > 0 then
|
||||
@ -524,20 +523,5 @@ do
|
||||
end
|
||||
end
|
||||
|
||||
-- searches on a card (standard size) and returns the result
|
||||
---@param position Table Position of the card
|
||||
---@param rotation Table Rotation of the card
|
||||
internal.searchOnCard = function(position, rotation)
|
||||
return Physics.cast({
|
||||
origin = position,
|
||||
direction = {0, 1, 0},
|
||||
orientation = rotation,
|
||||
type = 3,
|
||||
size = { 2.5, 0.5, 3.5 },
|
||||
max_distance = 1,
|
||||
debug = false
|
||||
})
|
||||
end
|
||||
|
||||
return TokenManager
|
||||
end
|
||||
|
@ -1,4 +1,5 @@
|
||||
-- this helper creates buttons to help the user track which hypothesis has been chosen each round (if user forgot to choose one at round start, the old one stays active)
|
||||
-- this helper creates buttons to help the user track which hypothesis has been chosen each round
|
||||
-- (if user forgot to choose one at round start, the old one stays active)
|
||||
local playmatApi = require("playermat/PlaymatApi")
|
||||
local upgradeSheetLibrary = require("playercards/customizable/UpgradeSheetLibrary")
|
||||
|
||||
@ -103,11 +104,10 @@ function createButtons()
|
||||
end
|
||||
|
||||
function findUpgradeSheet()
|
||||
matColor = playmatApi.getMatColorByPosition(self.getPosition())
|
||||
local result = playmatApi.searchAroundPlaymat(matColor, filter)
|
||||
local matColor = playmatApi.getMatColorByPosition(self.getPosition())
|
||||
local result = playmatApi.searchAroundPlaymat(matColor, "isCard")
|
||||
for j, card in ipairs(result) do
|
||||
local metadata = JSON.decode(card.getGMNotes()) or {}
|
||||
|
||||
if metadata.id == "09041-c" then
|
||||
return card
|
||||
end
|
||||
|
@ -1,4 +1,5 @@
|
||||
local playmatApi = require("playermat/PlaymatApi")
|
||||
local searchLib = require("util/SearchLib")
|
||||
local tokenManager = require("core/token/TokenManager")
|
||||
|
||||
local clickableResourceCounter = nil
|
||||
@ -14,8 +15,7 @@ function searchSelf()
|
||||
clickableResourceCounter = nil
|
||||
foundTokens = 0
|
||||
|
||||
for _, obj in ipairs(searchArea(self.getPosition(), { 2.5, 0.5, 3.5 })) do
|
||||
local obj = obj.hit_object
|
||||
for _, obj in ipairs(searchLib.onObject(self), "isTileOrToken") do
|
||||
local image = obj.getCustomObject().image
|
||||
if image == "http://cloud-3.steamusercontent.com/ugc/1758068501357192910/11DDDC7EF621320962FDCF3AE3211D5EDC3D1573/" then
|
||||
foundTokens = foundTokens + math.abs(obj.getQuantity())
|
||||
@ -63,14 +63,3 @@ function loseAll(playerColor)
|
||||
end
|
||||
printToColor("Discarded " .. foundTokens .. " resource(s).", playerColor)
|
||||
end
|
||||
|
||||
function searchArea(origin, size)
|
||||
return Physics.cast({
|
||||
origin = origin,
|
||||
direction = { 0, 1, 0 },
|
||||
orientation = PLAY_ZONE_ROTATION,
|
||||
type = 3,
|
||||
size = size,
|
||||
max_distance = 1
|
||||
})
|
||||
end
|
||||
|
@ -1,12 +1,4 @@
|
||||
-- Table of items which can be counted in this Bowl
|
||||
-- Each entry has 2 things to enter
|
||||
-- a name (what is in the name field of that object)
|
||||
-- a value (how much it is worth)
|
||||
-- a number in the items description will override the number entry in this table
|
||||
local validCountItemList = {
|
||||
["Clue"] = 1,
|
||||
[""] = 1
|
||||
}
|
||||
local searchLib = require("util/SearchLib")
|
||||
exposedValue = 0
|
||||
|
||||
function onLoad()
|
||||
@ -20,49 +12,25 @@ function onLoad()
|
||||
font_color = { 0, 0, 0 },
|
||||
font_size = 2000
|
||||
})
|
||||
loopID = Wait.time(countItems, 1, -1)
|
||||
loopID = Wait.time(countItems, 1.5, -1)
|
||||
end
|
||||
|
||||
-- Activated once per second, counts items in bowls
|
||||
function countItems()
|
||||
local totalValue = 0
|
||||
for _, item in ipairs(findValidItemsInSphere()) do
|
||||
local descValue = tonumber(item.getDescription())
|
||||
local stackMult = math.abs(item.getQuantity())
|
||||
-- Use value in description if available
|
||||
if descValue ~= nil then
|
||||
totalValue = totalValue + descValue * stackMult
|
||||
else
|
||||
-- Otherwise use the value in validCountItemList
|
||||
totalValue = totalValue + validCountItemList[item.getName()] * stackMult
|
||||
end
|
||||
for _, item in ipairs(getClues()) do
|
||||
totalValue = totalValue + math.abs(item.getQuantity())
|
||||
end
|
||||
exposedValue = totalValue
|
||||
self.editButton({ index = 0, label = totalValue })
|
||||
end
|
||||
|
||||
function findValidItemsInSphere()
|
||||
local items = Physics.cast({
|
||||
origin = self.getPosition(),
|
||||
direction = { 0, 1, 0 },
|
||||
type = 2,
|
||||
max_distance = 0,
|
||||
size = { 2, 2, 2 }
|
||||
})
|
||||
|
||||
local validItemList = {}
|
||||
for _, entry in ipairs(items) do
|
||||
if entry.hit_object ~= self then
|
||||
if validCountItemList[entry.hit_object.getName()] ~= nil then
|
||||
table.insert(validItemList, entry.hit_object)
|
||||
end
|
||||
end
|
||||
end
|
||||
return validItemList
|
||||
end
|
||||
|
||||
function removeAllClues(trash)
|
||||
for _, obj in ipairs(findValidItemsInSphere()) do
|
||||
for _, obj in ipairs(getClues()) do
|
||||
trash.putObject(obj)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function getClues()
|
||||
return searchLib.inArea(self.getPosition(), self.getRotation(), { 2, 1, 2 }, "isClue")
|
||||
end
|
||||
|
@ -1,3 +1,4 @@
|
||||
local searchLib = require("util/SearchLib")
|
||||
local chaosBagApi = require("chaosbag/ChaosBagApi")
|
||||
local guidReferenceApi = require("core/GUIDReferenceApi")
|
||||
local mythosAreaApi = require("core/MythosAreaApi")
|
||||
@ -5,9 +6,6 @@ local navigationOverlayApi = require("core/NavigationOverlayApi")
|
||||
local tokenChecker = require("core/token/TokenChecker")
|
||||
local tokenManager = require("core/token/TokenManager")
|
||||
|
||||
-- set true to enable debug logging and show Physics.cast()
|
||||
local DEBUG = false
|
||||
|
||||
-- we use this to turn off collision handling until onLoad() is complete
|
||||
local collisionEnabled = false
|
||||
|
||||
@ -20,7 +18,7 @@ local DISCARD_BUTTON_OFFSETS = {-1.365, -0.91, -0.455, 0, 0.455, 0.91}
|
||||
|
||||
local SEARCH_AROUND_SELF_X_BUFFER = 8
|
||||
|
||||
-- defined areas for "inArea()" and "Physics.cast()"
|
||||
-- defined areas for object searching
|
||||
local MAIN_PLAY_AREA = {
|
||||
upperLeft = {
|
||||
x = 1.98,
|
||||
@ -101,7 +99,7 @@ function onSave()
|
||||
end
|
||||
|
||||
function onLoad(saveState)
|
||||
self.interactable = DEBUG
|
||||
self.interactable = false
|
||||
|
||||
-- get object references to owned objects
|
||||
ownedObjects = guidReferenceApi.getObjectsByOwner(matColor)
|
||||
@ -159,29 +157,9 @@ end
|
||||
|
||||
-- searches an area and optionally filters the result
|
||||
function searchArea(origin, size, filter)
|
||||
local searchResult = Physics.cast({
|
||||
origin = origin,
|
||||
direction = { 0, 1, 0 },
|
||||
orientation = self.getRotation(),
|
||||
type = 3,
|
||||
size = size,
|
||||
max_distance = 0
|
||||
})
|
||||
|
||||
local objList = {}
|
||||
for _, v in ipairs(searchResult) do
|
||||
if not filter or (filter and filter(v.hit_object)) then
|
||||
table.insert(objList, v.hit_object)
|
||||
end
|
||||
end
|
||||
return objList
|
||||
return searchLib.inArea(origin, self.getRotation(), size, filter)
|
||||
end
|
||||
|
||||
-- filter functions for searchArea()
|
||||
function isCard(x) return x.type == 'Card' end
|
||||
function isDeck(x) return x.type == 'Deck' end
|
||||
function isCardOrDeck(x) return x.type == 'Card' or x.type == 'Deck' end
|
||||
|
||||
-- finds all objects on the playmat and associated set aside zone.
|
||||
function searchAroundSelf(filter)
|
||||
local bounds = self.getBoundsNormalized()
|
||||
@ -230,7 +208,7 @@ end
|
||||
---@param objList Table List of objects to discard
|
||||
function discardListOfObjects(objList)
|
||||
for _, obj in ipairs(objList) do
|
||||
if isCardOrDeck(obj) then
|
||||
if obj.type == "Card" or obj.type == "Deck" then
|
||||
if obj.hasTag("PlayerCard") then
|
||||
placeOrMergeIntoDeck(obj, returnGlobalDiscardPosition(), self.getRotation())
|
||||
else
|
||||
@ -255,7 +233,7 @@ function placeOrMergeIntoDeck(obj, pos, rot)
|
||||
local offset = 0.5
|
||||
|
||||
-- search the new position for existing card/deck
|
||||
local searchResult = searchArea(pos, { 1, 1, 1 }, isCardOrDeck)
|
||||
local searchResult = searchArea(pos, { 1, 1, 1 }, "isCardOrDeck")
|
||||
|
||||
-- get new position
|
||||
local newPos
|
||||
@ -320,7 +298,6 @@ function doUpkeepFromHotkey(color)
|
||||
end
|
||||
|
||||
function doUpkeep(_, clickedByColor, isRightClick)
|
||||
-- right-click allow color changing
|
||||
if isRightClick then
|
||||
changeColor(clickedByColor)
|
||||
return
|
||||
@ -480,7 +457,7 @@ end
|
||||
-- get the draw deck and discard pile objects and returns the references
|
||||
function getDeckAreaObjects()
|
||||
local deckAreaObjects = {}
|
||||
for _, object in ipairs(searchDeckAndDiscardArea(isCardOrDeck)) do
|
||||
for _, object in ipairs(searchDeckAndDiscardArea("isCardOrDeck")) do
|
||||
if self.positionToLocal(object.getPosition()).z > 0.5 then
|
||||
deckAreaObjects.discard = object
|
||||
-- Norman Withers handling
|
||||
@ -613,7 +590,7 @@ end
|
||||
-- called when a checkbox is added or removed in-game (which should be rare), and is bounded by the
|
||||
-- number of customizable cards in play.
|
||||
function syncAllCustomizableCards()
|
||||
for _, card in ipairs(searchAroundSelf(isCard)) do
|
||||
for _, card in ipairs(searchAroundSelf("isCard")) do
|
||||
syncCustomizableMetadata(card)
|
||||
end
|
||||
end
|
||||
@ -623,7 +600,7 @@ function syncCustomizableMetadata(card)
|
||||
if cardMetadata == nil or cardMetadata.customizations == nil then
|
||||
return
|
||||
end
|
||||
for _, upgradeSheet in ipairs(searchAroundSelf(isCard)) do
|
||||
for _, upgradeSheet in ipairs(searchAroundSelf("isCard")) do
|
||||
local upgradeSheetMetadata = JSON.decode(upgradeSheet.getGMNotes()) or { }
|
||||
if upgradeSheetMetadata.id == (cardMetadata.id .. "-c") then
|
||||
for i, customization in ipairs(cardMetadata.customizations) do
|
||||
@ -660,7 +637,7 @@ function onCollisionEnter(collisionInfo)
|
||||
if not collisionEnabled then return end
|
||||
|
||||
-- only continue for cards
|
||||
if not isCard(object) then return end
|
||||
if object.type ~= "Card" then return end
|
||||
|
||||
-- detect if "Dream-Enhancing Serum" is placed
|
||||
if object.getName() == "Dream-Enhancing Serum" then isDES = true end
|
||||
@ -715,7 +692,7 @@ function shouldSpawnTokens(card)
|
||||
end
|
||||
|
||||
function onObjectEnterContainer(container, object)
|
||||
if not isCard(object) then return end
|
||||
if object.type ~= "Card" then return end
|
||||
|
||||
local localCardPos = self.positionToLocal(object.getPosition())
|
||||
if inArea(localCardPos, DECK_DISCARD_AREA) then
|
||||
@ -726,7 +703,7 @@ end
|
||||
|
||||
-- removes tokens from the provided card/deck
|
||||
function removeTokensFromObject(object)
|
||||
for _, obj in ipairs(searchArea(object.getPosition(), { 3, 1, 4 })) do
|
||||
for _, obj in ipairs(searchLib.onObject(object)) do
|
||||
if obj.getGUID() ~= "4ee1f2" and -- table
|
||||
obj ~= self and
|
||||
obj.type ~= "Deck" and
|
||||
|
@ -199,7 +199,7 @@ do
|
||||
|
||||
-- finds all objects on the playmat and associated set aside zone and returns a table
|
||||
---@param matColor String Color of the playmat - White, Orange, Green, Red or All
|
||||
---@param filter Function Optional filter function (return true for desired objects)
|
||||
---@param filter String Name of the filte function (see util/SearchLib)
|
||||
PlaymatApi.searchAroundPlaymat = function(matColor, filter)
|
||||
local objList = {}
|
||||
for _, mat in pairs(getMatForColor(matColor)) do
|
||||
|
66
src/util/SearchLib.ttslua
Normal file
66
src/util/SearchLib.ttslua
Normal file
@ -0,0 +1,66 @@
|
||||
do
|
||||
local SearchLib = {}
|
||||
local filterFunctions = {
|
||||
isActionToken = function(x) return x.getDescription() == "Action Token" end,
|
||||
isCard = function(x) return x.type == "Card" end,
|
||||
isDeck = function(x) return x.type == "Deck" end,
|
||||
isCardOrDeck = function(x) return x.type == "Card" or x.type == "Deck" end,
|
||||
isClue = function(x) return x.memo == "clueDoom" and x.is_face_down == false end,
|
||||
isTileOrToken = function(x) return x.type == "Tile" end
|
||||
}
|
||||
|
||||
-- performs the actual search and returns a filtered list of object references
|
||||
---@param pos Table Global position
|
||||
---@param rot Table Global rotation
|
||||
---@param size Table Size
|
||||
---@param filter String Name of the filter function
|
||||
---@param direction Table Direction (positive is up)
|
||||
---@param maxDistance Number Distance for the cast
|
||||
local function returnSearchResult(pos, rot, size, filter, direction, maxDistance)
|
||||
if filter then filter = filterFunctions[filter] end
|
||||
local searchResult = Physics.cast({
|
||||
origin = pos,
|
||||
direction = direction or { 0, 1, 0 },
|
||||
orientation = rot or { 0, 0, 0 },
|
||||
type = 3,
|
||||
size = size,
|
||||
max_distance = maxDistance or 0
|
||||
})
|
||||
|
||||
-- filtering the result
|
||||
local objList = {}
|
||||
for _, v in ipairs(searchResult) do
|
||||
if not filter or filter(v.hit_object) then
|
||||
table.insert(objList, v.hit_object)
|
||||
end
|
||||
end
|
||||
return objList
|
||||
end
|
||||
|
||||
-- searches the specified area
|
||||
SearchLib.inArea = function(pos, rot, size, filter)
|
||||
return returnSearchResult(pos, rot, size, filter)
|
||||
end
|
||||
|
||||
-- searches the area on an object
|
||||
SearchLib.onObject = function(obj, filter)
|
||||
pos = obj.getPosition()
|
||||
size = obj.getBounds().size:setAt("y", 1)
|
||||
return returnSearchResult(pos, _, size, filter)
|
||||
end
|
||||
|
||||
-- searches the specified position (a single point)
|
||||
SearchLib.atPosition = function(pos, filter)
|
||||
size = { 0.1, 2, 0.1 }
|
||||
return returnSearchResult(pos, _, size, filter)
|
||||
end
|
||||
|
||||
-- searches below the specified position (downwards until y = 0)
|
||||
SearchLib.belowPosition = function(pos, filter)
|
||||
direction = { 0, -1, 0 }
|
||||
maxDistance = pos.y
|
||||
return returnSearchResult(pos, _, size, filter, direction, maxDistance)
|
||||
end
|
||||
|
||||
return SearchLib
|
||||
end
|
@ -1,3 +1,4 @@
|
||||
local searchLib = require("util/SearchLib")
|
||||
local tokenManager = require("core/token/TokenManager")
|
||||
local TOKEN_INDEX = {}
|
||||
TOKEN_INDEX[3] = "resourceCounter"
|
||||
@ -31,19 +32,10 @@ function onScriptingButtonDown(index, playerColor)
|
||||
|
||||
-- check for subtype of resource based on card below
|
||||
if tokenType == "resource" then
|
||||
local search = Physics.cast({
|
||||
direction = { 0, -1, 0 },
|
||||
max_distance = 2,
|
||||
type = 3,
|
||||
size = { 0.1, 0.1, 0.1 },
|
||||
origin = position:setAt("y", 2)
|
||||
})
|
||||
|
||||
for _, v in ipairs(search) do
|
||||
if v.hit_object.tag == "Card" and not v.hit_object.is_face_down then
|
||||
local metadata = JSON.decode(v.hit_object.getGMNotes()) or {}
|
||||
for _, obj in ipairs(searchLib.belowPosition(position), "isCard") do
|
||||
if not obj.is_face_down then
|
||||
local metadata = JSON.decode(obj.getGMNotes()) or {}
|
||||
local uses = metadata.uses or {}
|
||||
|
||||
for _, useInfo in ipairs(uses) do
|
||||
if useInfo.token == "resource" then
|
||||
subType = useInfo.type
|
||||
|
Loading…
Reference in New Issue
Block a user