SCED/src/core/PlayArea.ttslua

197 lines
5.9 KiB
Plaintext
Raw Normal View History

2022-11-12 05:46:05 -05:00
---------------------------------------------------------
-- general setup
---------------------------------------------------------
-- set true to enable debug logging
DEBUG = false
2022-11-12 05:46:05 -05:00
-- we use this to turn off collision handling until onLoad() is complete
COLLISION_ENABLED = false
local SHIFT_OFFSETS = {
left = { 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 },
down = { x = -6.54, y = 0, z = 0.00 }
}
local SHIFT_EXCLUSION = {
["b7b45b"] = true,
["f182ee"] = true,
["721ba2"] = true
}
local INVESTIGATOR_COUNTER_GUID = "f182ee"
local PLAY_AREA_ZONE_GUID = "a2f932"
2022-11-13 18:29:18 -05:00
local clueData = {}
2022-11-12 19:12:01 -05:00
spawnedLocationGUIDs = {}
local currentScenario
2022-11-12 19:12:01 -05:00
2022-11-12 05:46:05 -05:00
---------------------------------------------------------
-- general code
---------------------------------------------------------
function onSave()
return JSON.encode({
spawnedLocs = spawnedLocationGUIDs,
currentScenario = currentScenario
})
end
function onLoad(saveState)
2022-11-12 05:46:05 -05:00
-- records locations we have spawned clues for
local saveData = JSON.decode(saveState) or {}
spawnedLocationGUIDs = saveData.spawnedLocs or { }
currentScenario = saveData.currentScenario
2022-11-13 18:29:18 -05:00
local TOKEN_DATA = Global.getTable('TOKEN_DATA')
clueData = {
thickness = 0.1,
stackable = true,
type = 2,
image = TOKEN_DATA.clue.image,
image_bottom = TOKEN_DATA.doom.image
}
2022-11-12 05:46:05 -05:00
local dataHelper = getObjectFromGUID('708279')
LOCATIONS = dataHelper.getTable('LOCATIONS_DATA')
2022-11-12 05:46:05 -05:00
self.interactable = DEBUG
Wait.time(function() COLLISION_ENABLED = true end, 1)
end
2022-11-12 05:46:05 -05:00
function log(message)
if DEBUG then print(message) end
end
2022-11-12 05:46:05 -05:00
---------------------------------------------------------
-- clue spawning
---------------------------------------------------------
-- try the compound key then the name alone as default
function getLocation(object)
2022-11-12 05:46:05 -05:00
return LOCATIONS[object.getName() .. '_' .. object.getGUID()] or LOCATIONS[object.getName()]
end
2022-11-12 05:46:05 -05:00
-- Return the number of clues to spawn on this location
function getClueCount(object, isFaceDown, playerCount)
2022-11-12 05:46:05 -05:00
local details = getLocation(object)
if details == nil then
error('attempted to get clue for unexpected object: ' .. object.getName())
end
2022-11-12 05:46:05 -05:00
log(object.getName() .. ' : ' .. details['type'] .. ' : ' .. details['value'] .. ' : ' .. details['clueSide'])
2022-11-12 05:46:05 -05:00
if ((isFaceDown and details['clueSide'] == 'back') or (not isFaceDown and details['clueSide'] == 'front')) then
if details['type'] == 'fixed' then
return details['value']
elseif details['type'] == 'perPlayer' then
return details['value'] * playerCount
end
error('unexpected location type: ' .. details['type'])
end
return 0
end
2022-11-12 05:46:05 -05:00
function spawnCluesAtLocation(clueCount, object)
2022-11-12 19:12:01 -05:00
if spawnedLocationGUIDs[object.getGUID()] ~= nil then
error('tried to spawn clue for already spawned location:' .. object.getName())
end
log('spawning clues for ' .. object.getName() .. '_' .. object.getGUID())
log('player count is ' .. getInvestigatorCount() .. ', clue count is ' .. clueCount)
2022-11-12 05:46:05 -05:00
-- mark this location as spawned, can't happen again
2022-11-12 19:12:01 -05:00
spawnedLocationGUIDs[object.getGUID()] = true
2022-11-12 05:46:05 -05:00
-- spawn clues (starting top right, moving to the next row after 4 clues)
local pos = object.getPosition()
for i = 1, clueCount do
local row = math.floor(1 + (i - 1) / 4)
local column = (i - 1) % 4
2022-11-12 19:12:01 -05:00
spawnClue({ pos.x + 1.5 - 0.55 * row, pos.y, pos.z - 0.825 + 0.55 * column })
end
end
2022-11-12 19:12:01 -05:00
function spawnClue(position)
2022-11-12 05:46:05 -05:00
local token = spawnObject({
position = position,
rotation = { 3.88, -90, 0.24 },
type = 'Custom_Tile'
})
token.setCustomObject(clueData)
token.scale { 0.25, 1, 0.25 }
token.use_snap_points = false
end
function updateLocations(args)
2022-11-12 05:46:05 -05:00
custom_data_helper_guid = args[1]
local custom_data_helper = getObjectFromGUID(args[1])
for k, v in pairs(custom_data_helper.getTable("LOCATIONS_DATA")) do
LOCATIONS[k] = v
end
end
function onCollisionEnter(collision_info)
2022-11-12 05:46:05 -05:00
if not COLLISION_ENABLED then return end
2022-11-12 05:46:05 -05:00
-- check if we should spawn clues here and do so according to playercount
local object = collision_info.collision_object
2022-11-12 19:12:01 -05:00
if getLocation(object) ~= nil and spawnedLocationGUIDs[object.getGUID()] == nil then
local clueCount = getClueCount(object, object.is_face_down, getInvestigatorCount())
2022-11-12 05:46:05 -05:00
if clueCount > 0 then spawnCluesAtLocation(clueCount, object) end
end
end
2022-12-13 05:15:16 -05:00
-- 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
-- 'displacement_excluded'
---@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
function shiftContentsUp(playerColor)
shiftContents(playerColor, "up")
end
function shiftContentsDown(playerColor)
shiftContents(playerColor, "down")
end
function shiftContentsLeft(playerColor)
shiftContents(playerColor, "left")
end
function shiftContentsRight(playerColor)
shiftContents(playerColor, "right")
end
function shiftContents(playerColor, direction)
local zone = getObjectFromGUID(PLAY_AREA_ZONE_GUID)
if not zone then
broadcastToColor("Scripting zone couldn't be found.", playerColor, "Red")
return
end
for _, object in ipairs(zone.getObjects()) do
if not (SHIFT_EXCLUSION[object.getGUID()] or object.hasTag("displacement_excluded")) then
object.translate(SHIFT_OFFSETS[direction])
end
end
end
-- Returns the current value of the investigator counter from the playmat
---@return Integer. Number of investigators currently set on the counter
function getInvestigatorCount()
local investigatorCounter = getObjectFromGUID("f182ee")
return investigatorCounter.getVar("val")
end
-- Reset the play area's tracking of which cards have had tokens spawned.
function resetSpawnedCards()
spawnedLocationGUIDs = {}
end
function onScenarioChanged(scenarioName)
currentScenario = scenarioName
end