optimization
This commit is contained in:
parent
77d0339354
commit
8bef677eda
@ -141,13 +141,17 @@ function onObjectPickUp(player, object)
|
||||
if showLocationLinks() and isInPlayArea(object) and object.getGMNotes() ~= nil and object.getGMNotes() ~= "" then
|
||||
local pickedUpGuid = object.getGUID()
|
||||
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
|
||||
-- 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.
|
||||
-- Waiting ensures we always do thing in the expected Exit->PickUp order
|
||||
Wait.frames(function()
|
||||
draggingGuids[pickedUpGuid] = metadata
|
||||
if object.is_face_down then
|
||||
draggingGuids[pickedUpGuid] = metadata.locationBack
|
||||
else
|
||||
draggingGuids[pickedUpGuid] = metadata.locationFront
|
||||
end
|
||||
rebuildConnectionList()
|
||||
end, 2)
|
||||
end
|
||||
@ -187,12 +191,20 @@ end
|
||||
function maybeTrackLocation(card)
|
||||
-- Collision checks for any part of the card overlap, but our other tracking is centerpoint
|
||||
-- Ignore any collision where the centerpoint isn't in the area
|
||||
if showLocationLinks() and isInPlayArea(card) then
|
||||
if isInPlayArea(card) then
|
||||
local metadata = JSON.decode(card.getGMNotes()) or { }
|
||||
if metadata.type == "Location" then
|
||||
locations[card.getGUID()] = metadata
|
||||
rebuildConnectionList()
|
||||
drawBaseConnections()
|
||||
if card.is_face_down then
|
||||
locations[card.getGUID()] = metadata.locationBack
|
||||
else
|
||||
locations[card.getGUID()] = metadata.locationFront
|
||||
end
|
||||
|
||||
-- only draw connection lines for not-excluded scenarios
|
||||
if showLocationLinks() then
|
||||
rebuildConnectionList()
|
||||
drawBaseConnections()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -238,20 +250,20 @@ function rebuildConnectionList()
|
||||
|
||||
-- Build a list of cards with each icon as their location ID
|
||||
for cardId, metadata in pairs(draggingGuids) do
|
||||
buildLocListByIcon(cardId, iconCardList)
|
||||
buildLocListByIcon(cardId, iconCardList, metadata)
|
||||
end
|
||||
for cardId, metadata in pairs(locations) do
|
||||
buildLocListByIcon(cardId, iconCardList)
|
||||
buildLocListByIcon(cardId, iconCardList, metadata)
|
||||
end
|
||||
|
||||
-- Pair up all the icons
|
||||
locationConnections = { }
|
||||
for cardId, metadata in pairs(draggingGuids) do
|
||||
buildConnection(cardId, iconCardList)
|
||||
buildConnection(cardId, iconCardList, metadata)
|
||||
end
|
||||
for cardId, metadata in pairs(locations) do
|
||||
if draggingGuids[cardId] == nil then
|
||||
buildConnection(cardId, iconCardList)
|
||||
buildConnection(cardId, iconCardList, metadata)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -259,15 +271,14 @@ end
|
||||
-- Extracts the card's icon string into a list of individual location icons
|
||||
---@param cardID String GUID of the card to pull the icon data from
|
||||
---@param iconCardList Table A table of icon->GUID list. Mutable, will be updated by this method
|
||||
function buildLocListByIcon(cardId, iconCardList)
|
||||
local card = getObjectFromGUID(cardId)
|
||||
local locData = getLocationData(card)
|
||||
---@param locData Table A table containing the metadata for the card (for the correct side)
|
||||
function buildLocListByIcon(cardId, iconCardList, locData)
|
||||
if locData ~= nil and locData.icons ~= nil then
|
||||
for icon in string.gmatch(locData.icons, "%a+") do
|
||||
if iconCardList[icon] == nil then
|
||||
iconCardList[icon] = { }
|
||||
end
|
||||
table.insert(iconCardList[icon], card.getGUID())
|
||||
table.insert(iconCardList[icon], cardId)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -276,25 +287,24 @@ end
|
||||
-- Playarea's locationConnections table.
|
||||
---@param cardId String GUID of the card to build the connections for
|
||||
---@param iconCardList Table A table of icon->GUID List. Used to find matching icons for connections.
|
||||
function buildConnection(cardId, iconCardList)
|
||||
local card = getObjectFromGUID(cardId)
|
||||
local locData = getLocationData(card)
|
||||
---@param locData Table A table containing the metadata for the card (for the correct side)
|
||||
function buildConnection(cardId, iconCardList, locData)
|
||||
if locData ~= nil and locData.connections ~= nil then
|
||||
locationConnections[card.getGUID()] = { }
|
||||
locationConnections[cardId] = { }
|
||||
for icon in string.gmatch(locData.connections, "%a+") do
|
||||
if iconCardList[icon] ~= nil then
|
||||
for _, connectedGuid in ipairs(iconCardList[icon]) do
|
||||
-- If the reciprocal exists, convert it to BiDi, otherwise add as a one-way
|
||||
if locationConnections[connectedGuid] ~= nil
|
||||
and locationConnections[connectedGuid][card.getGUID()] == ONE_WAY then
|
||||
locationConnections[connectedGuid][card.getGUID()] = BIDIRECTIONAL
|
||||
locationConnections[card.getGUID()][connectedGuid] = nil
|
||||
and locationConnections[connectedGuid][cardId] == ONE_WAY then
|
||||
locationConnections[connectedGuid][cardId] = BIDIRECTIONAL
|
||||
locationConnections[cardId][connectedGuid] = nil
|
||||
else
|
||||
if locationConnections[connectedGuid] == nil then
|
||||
locationConnections[connectedGuid] = { }
|
||||
end
|
||||
locationConnections[card.getGUID()][connectedGuid] = ONE_WAY
|
||||
locationConnections[connectedGuid][card.getGUID()] = INCOMING_ONE_WAY
|
||||
locationConnections[cardId][connectedGuid] = ONE_WAY
|
||||
locationConnections[connectedGuid][cardId] = INCOMING_ONE_WAY
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -302,22 +312,6 @@ function buildConnection(cardId, iconCardList)
|
||||
end
|
||||
end
|
||||
|
||||
-- Helper method to extract the location metadata from a card based on whether it's front or back
|
||||
-- is showing.
|
||||
---@param card String Card object to extract data from
|
||||
---@return. Table with either the locationFront or locationBack metadata structure, or nil if the
|
||||
-- metadata doesn't exist
|
||||
function getLocationData(card)
|
||||
if card == nil then
|
||||
return nil
|
||||
end
|
||||
if card.is_face_down then
|
||||
return JSON.decode(card.getGMNotes()).locationBack
|
||||
else
|
||||
return JSON.decode(card.getGMNotes()).locationFront
|
||||
end
|
||||
end
|
||||
|
||||
-- Draws the lines for connections currently in locationConnections but not in draggingGuids.
|
||||
-- Constructed vectors will be set to the playmat
|
||||
function drawBaseConnections()
|
||||
@ -552,6 +546,48 @@ function setLimitSnapsByType(matchTypes)
|
||||
self.setSnapPoints(snaps)
|
||||
end
|
||||
|
||||
-- count victory points on locations in play area
|
||||
---@return. Returns the total amount of VP found in the play area
|
||||
function countVP()
|
||||
local totalVP = 0
|
||||
|
||||
for cardId, metadata in pairs(locations) do
|
||||
if metadata ~= nil then
|
||||
local cardVP = tonumber(metadata.victory) or 0
|
||||
if cardVP ~= 0 and not cardHasClues(cardId) then
|
||||
totalVP = totalVP + cardVP
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return totalVP
|
||||
end
|
||||
|
||||
-- checks if a card has clues on it, returns true if clues are on it
|
||||
---@param cardId String GUID of the card to check for clues
|
||||
function cardHasClues(cardId)
|
||||
local card = getObjectFromGUID(cardId)
|
||||
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()
|
||||
})
|
||||
end
|
||||
|
||||
-- rebuilds local snap points (could be useful in the future again)
|
||||
function buildSnaps()
|
||||
local upperleft = { x = 1.53, z = -1.09}
|
||||
|
@ -55,6 +55,11 @@ do
|
||||
{ container = container, object = object })
|
||||
end
|
||||
|
||||
-- counts the VP on locations in the play area
|
||||
PlayAreaApi.countVP = function()
|
||||
return getObjectFromGUID(PLAY_AREA_GUID).call("countVP")
|
||||
end
|
||||
|
||||
-- Checks if an object is in the play area (returns true or false)
|
||||
PlayAreaApi.isInPlayArea = function(object)
|
||||
return getObjectFromGUID(PLAY_AREA_GUID).call("isInPlayArea", object)
|
||||
|
@ -1,11 +1,8 @@
|
||||
local playAreaApi = require("core/PlayAreaApi")
|
||||
local pendingCall = false
|
||||
local messageSent = {}
|
||||
local victoryPoints = {
|
||||
display = 0,
|
||||
playArea = 0
|
||||
}
|
||||
|
||||
-- button creation when loading the game
|
||||
function onLoad()
|
||||
-- index 0: VP - "Display"
|
||||
local buttonParameters = {}
|
||||
@ -17,7 +14,7 @@ function onLoad()
|
||||
buttonParameters.height = 0
|
||||
buttonParameters.font_size = 600
|
||||
buttonParameters.font_color = { 1, 1, 1 }
|
||||
buttonParameters.position = { x = -0.71, y = 0.06, z = -0.69 }
|
||||
buttonParameters.position = { x = -0.72, y = 0.06, z = -0.69 }
|
||||
self.createButton(buttonParameters)
|
||||
|
||||
-- index 1: VP - "Play Area"
|
||||
@ -25,63 +22,91 @@ function onLoad()
|
||||
self.createButton(buttonParameters)
|
||||
|
||||
-- index 2: VP - "Total"
|
||||
buttonParameters.position.x = 1.685
|
||||
buttonParameters.position.x = 1.69
|
||||
self.createButton(buttonParameters)
|
||||
|
||||
-- update the display label once
|
||||
Wait.time(updateCount, 1)
|
||||
end
|
||||
|
||||
-- automatically update when cards are dropped or removed
|
||||
---------------------------------------------------------
|
||||
-- events with descriptions
|
||||
---------------------------------------------------------
|
||||
|
||||
-- dropping an object on the victory display
|
||||
function onCollisionEnter()
|
||||
updateCount()
|
||||
-- stop if there is already an update call running
|
||||
if pendingCall then return end
|
||||
pendingCall = true
|
||||
Wait.time(updateCount, 0.2)
|
||||
end
|
||||
|
||||
-- removing an object from the victory display
|
||||
function onCollisionExit()
|
||||
updateCount()
|
||||
-- stop if there is already an update call running
|
||||
if pendingCall then return end
|
||||
pendingCall = true
|
||||
Wait.time(updateCount, 0.2)
|
||||
end
|
||||
|
||||
-- picking a clue or location up
|
||||
function onObjectPickUp(_, obj)
|
||||
maybeUpdate(obj)
|
||||
end
|
||||
|
||||
-- dropping a clue or location
|
||||
function onObjectDrop(_, obj)
|
||||
maybeUpdate(obj, 1)
|
||||
end
|
||||
|
||||
-- flipping a clue/doom or location
|
||||
function onObjectRotate(obj, _, flip, _, _, oldFlip)
|
||||
if flip == oldFlip then return end
|
||||
maybeUpdate(obj, 1, true)
|
||||
end
|
||||
|
||||
-- destroying a clue or location
|
||||
function onObjectDestroy(obj)
|
||||
maybeUpdate(obj)
|
||||
end
|
||||
|
||||
---------------------------------------------------------
|
||||
-- main functionality
|
||||
---------------------------------------------------------
|
||||
|
||||
function maybeUpdate(obj, delay, flipped)
|
||||
-- stop if there is already an update call running
|
||||
if pendingCall then return end
|
||||
|
||||
-- stop if obj is nil (by e.g. dropping a clue onto another and making a stack)
|
||||
if obj == nil then return end
|
||||
if obj.memo ~= "clueDoom" then return end
|
||||
if obj.is_face_down == true and flipped ~= true then return end
|
||||
if not playAreaApi.isInPlayArea(obj) then return end
|
||||
delay = tonumber(delay) or 0
|
||||
Wait.time(function() updateCount() end, delay)
|
||||
end
|
||||
|
||||
function isClue(obj)
|
||||
return obj.memo == "clueDoom" and obj.is_face_down == false
|
||||
end
|
||||
|
||||
-- works as a sinkhole for all refresh calls
|
||||
function updateCount()
|
||||
if not pendingCall then
|
||||
pendingCall = true
|
||||
Wait.time(function() updateCountNow() end, 0.2)
|
||||
-- only continue for clues / doom tokens or locations
|
||||
if obj.hasTag("Location") then
|
||||
elseif obj.memo == "clueDoom" then
|
||||
-- only continue if the clue side is up or a doom token is being flipped
|
||||
if obj.is_face_down == true and flipped ~= true then return end
|
||||
else
|
||||
return
|
||||
end
|
||||
|
||||
-- only continue if the obj in in the play area
|
||||
if not playAreaApi.isInPlayArea(obj) then return end
|
||||
|
||||
-- set this flag to limit function calls (will be reset by "updateCount")
|
||||
pendingCall = true
|
||||
|
||||
-- update the count with delay (or 0 if no delay is provided)
|
||||
-- this is needed to let tokens drop on the card
|
||||
delay = tonumber(delay) or 0
|
||||
Wait.time(updateCount, delay + 0.2)
|
||||
end
|
||||
|
||||
function updateCountNow()
|
||||
-- counts the VP in the victory display and request the VP count from the play area
|
||||
function updateCount()
|
||||
local victoryPoints = {}
|
||||
victoryPoints.display = 0
|
||||
victoryPoints.playArea = 0
|
||||
victoryPoints.playArea = playAreaApi.countVP()
|
||||
|
||||
-- count cards in victory display
|
||||
for _, v in ipairs(searchOnObj(self)) do
|
||||
@ -102,29 +127,16 @@ function updateCountNow()
|
||||
end
|
||||
end
|
||||
|
||||
-- count locations in playArea
|
||||
local playArea = getObjectFromGUID("721ba2")
|
||||
for _, v in ipairs(searchOnObj(playArea)) do
|
||||
local obj = v.hit_object
|
||||
local cardVP = 0
|
||||
|
||||
if obj.hasTag("Location") then
|
||||
cardVP = getCardVP(obj.is_face_down, JSON.decode(obj.getGMNotes())) or 0
|
||||
if cardVP ~= 0 and not cardHasClues(obj) then
|
||||
victoryPoints.playArea = victoryPoints.playArea + cardVP
|
||||
end
|
||||
end
|
||||
end
|
||||
pendingCall = false
|
||||
updateVP()
|
||||
end
|
||||
|
||||
function updateVP()
|
||||
-- update the buttons that are used as labels
|
||||
self.editButton({ index = 0, label = victoryPoints.display })
|
||||
self.editButton({ index = 1, label = victoryPoints.playArea })
|
||||
self.editButton({ index = 2, label = victoryPoints.display + victoryPoints.playArea })
|
||||
|
||||
-- allow new update calls
|
||||
pendingCall = false
|
||||
end
|
||||
|
||||
-- sends a message for cards in the victory display that don't have VP
|
||||
function addOrSendMessage(addition, name)
|
||||
if tonumber(addition) ~= nil then
|
||||
return tonumber(addition)
|
||||
@ -135,17 +147,6 @@ function addOrSendMessage(addition, name)
|
||||
return 0
|
||||
end
|
||||
|
||||
-- checks if a card has clues on it
|
||||
function cardHasClues(card)
|
||||
for _, v in ipairs(searchOnObj(card)) do
|
||||
local obj = v.hit_object
|
||||
if isClue(obj) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- gets the VP count from the notes
|
||||
function getCardVP(faceDown, notes)
|
||||
local cardVP
|
||||
@ -155,6 +156,7 @@ function getCardVP(faceDown, notes)
|
||||
|
||||
-- location
|
||||
if not cardVP then
|
||||
-- check the correct side of the location
|
||||
if not faceDown and notes.locationFront ~= nil then
|
||||
cardVP = tonumber(notes.locationFront.victory)
|
||||
elseif notes.locationBack ~= nil then
|
||||
@ -165,6 +167,11 @@ function getCardVP(faceDown, notes)
|
||||
return cardVP
|
||||
end
|
||||
|
||||
---------------------------------------------------------
|
||||
-- utility functions
|
||||
---------------------------------------------------------
|
||||
|
||||
-- searches on an object
|
||||
function searchOnObj(obj)
|
||||
return Physics.cast({
|
||||
direction = { 0, 1, 0 },
|
||||
|
Loading…
Reference in New Issue
Block a user