2020-11-28 11:47:21 -05:00
|
|
|
PLAYAREA = {
|
|
|
|
position = { x=-25, y=4, z=0 },
|
|
|
|
rotation = { x=0, y=90, z=0 },
|
|
|
|
scale = { x=37, y=5, z=43 }
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSEMBLY = {
|
|
|
|
position = { x=68, y=2, z=36 },
|
|
|
|
rotation = { x=0, y=270, z=180 }
|
|
|
|
}
|
|
|
|
|
|
|
|
SET_ASIDE = {
|
|
|
|
position = { x=-2.52, y=2, z=14.87 },
|
|
|
|
rotation = { x=0, y=270, z=180 }
|
|
|
|
}
|
|
|
|
|
|
|
|
EXPLORATION = {
|
|
|
|
position = { x=-6.33, y=2, z=14.87 },
|
|
|
|
rotation = { x=0, y=270, z=180 }
|
|
|
|
}
|
|
|
|
|
|
|
|
START = {
|
|
|
|
position = { x=-30.22, y=2, z=-0.03 },
|
|
|
|
rotation = { x=0, y=270, z=180 }
|
|
|
|
}
|
|
|
|
|
2021-02-13 12:12:29 -05:00
|
|
|
HEART = 1
|
|
|
|
STAR = 2
|
|
|
|
DIAMOND = 3
|
|
|
|
TRIANGLE = 4
|
|
|
|
CIRCLE = 5
|
|
|
|
SQUARE = 6
|
|
|
|
BACKTICK = 7
|
|
|
|
TILDE = 8
|
|
|
|
PARALLEL = 9
|
|
|
|
T = 10
|
|
|
|
HOURGLASS = 11
|
|
|
|
|
2020-11-28 11:47:21 -05:00
|
|
|
LOCATIONS = {
|
2021-02-13 12:12:29 -05:00
|
|
|
{ name="City of the Serpents", symbol=DIAMOND, connections={ PARALLEL, BACKTICK, TRIANGLE, T, SQUARE } },
|
|
|
|
{ name="Bridge over N'kai", symbol=HEART, connections={ PARALLEL, BACKTICK, CIRCLE, TILDE, HOURGLASS } },
|
|
|
|
{ name="Abandoned Site", symbol=SQUARE, connections={ PARALLEL, DIAMOND, TRIANGLE, TILDE, T } },
|
|
|
|
{ name="Caverns of Yoth", symbol=BACKTICK, connections={ CIRCLE, HOURGLASS, HEART, TILDE, DIAMOND } },
|
|
|
|
{ name="Hall of Heresy", symbol=TRIANGLE, connections={ CIRCLE, PARALLEL, T, SQUARE, DIAMOND } },
|
|
|
|
{ name="Bright Canyon", symbol=CIRCLE, connections={ BACKTICK, TILDE, T, HEART, TRIANGLE } },
|
|
|
|
{ name="Forked Path", symbol=T, connections={ CIRCLE, DIAMOND, HOURGLASS, SQUARE, TRIANGLE } },
|
|
|
|
{ name="Crumbling Precipice", symbol=HOURGLASS, connections={ PARALLEL, TILDE, HEART, T, BACKTICK } },
|
|
|
|
{ name="Broken Passage", symbol=TILDE, connections={ CIRCLE, BACKTICK, HOURGLASS, SQUARE, HEART } },
|
|
|
|
{ name="Steps of Yoth", symbol=PARALLEL, connections={ HOURGLASS, SQUARE, TRIANGLE, DIAMOND, HEART } }
|
2020-11-28 11:47:21 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
STEPS = "Steps of Yoth"
|
|
|
|
PERILS = "Perils of Yoth"
|
|
|
|
|
|
|
|
function onLoad()
|
|
|
|
self.createButton({
|
|
|
|
label="Set Up",
|
|
|
|
click_function="setup",
|
|
|
|
function_owner=self,
|
2021-02-13 12:12:29 -05:00
|
|
|
position={0,0.1,-0.6},
|
2020-11-28 11:47:21 -05:00
|
|
|
height=120,
|
2021-02-13 12:12:29 -05:00
|
|
|
width=500,
|
|
|
|
scale={x=1.75, y=1.75, z=1.75},
|
|
|
|
font_size=80
|
|
|
|
})
|
|
|
|
|
|
|
|
self.createButton({
|
|
|
|
label="Update\nConnections",
|
|
|
|
click_function="updateConnections",
|
|
|
|
function_owner=self,
|
|
|
|
position={0,0.1,0.4},
|
|
|
|
height=240,
|
|
|
|
width=500,
|
2020-11-28 11:47:21 -05:00
|
|
|
scale={x=1.75, y=1.75, z=1.75},
|
2021-02-13 12:12:29 -05:00
|
|
|
font_size=80
|
2020-11-28 11:47:21 -05:00
|
|
|
})
|
|
|
|
|
|
|
|
playarea = getObjectFromGUID("721ba2")
|
|
|
|
TOKEN_IMAGES = Global.getTable("tokenplayerone")
|
2021-02-13 12:12:29 -05:00
|
|
|
makeIndexes()
|
2020-11-28 11:47:21 -05:00
|
|
|
math.randomseed(os.time())
|
|
|
|
end
|
|
|
|
|
2021-02-13 12:12:29 -05:00
|
|
|
function makeIndexes()
|
|
|
|
nameMap = {}
|
|
|
|
for i,v in ipairs(LOCATIONS) do
|
|
|
|
nameMap[v.name] = v
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function getPlayAreaObjects()
|
|
|
|
return Physics.cast({
|
2020-11-28 11:47:21 -05:00
|
|
|
origin = PLAYAREA.position,
|
|
|
|
direction = { x=0, y=1, z=0 },
|
|
|
|
type = 3,
|
|
|
|
size = PLAYAREA.scale,
|
|
|
|
orientation = PLAYAREA.rotation
|
|
|
|
})
|
2021-02-13 12:12:29 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
function setup(_obj, _color, _alt_click)
|
|
|
|
local objs = getPlayAreaObjects()
|
|
|
|
clearLines()
|
2020-11-28 11:47:21 -05:00
|
|
|
|
|
|
|
-- make index of all cards in play area and remove all clues and doom
|
|
|
|
local allCards = {}
|
|
|
|
for i,v in ipairs(objs) do
|
|
|
|
local obj = v.hit_object
|
|
|
|
local name = obj.getName()
|
|
|
|
if name ~= nil then
|
|
|
|
if obj.tag == "Card" then
|
|
|
|
allCards[name] = { card = obj, guid = obj.getGUID() }
|
|
|
|
elseif obj.tag == "Deck" then
|
|
|
|
local cards = obj.getObjects()
|
|
|
|
for j,card in ipairs(cards) do
|
|
|
|
if card.guid ~= nil and card.name ~= nil then
|
|
|
|
allCards[card.name] = { deck = obj, guid = card.guid }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
elseif obj.tag == "Tile" then
|
|
|
|
local props = obj.getCustomObject()
|
|
|
|
if (props.image == TOKEN_IMAGES.clue and props.image_bottom == TOKEN_IMAGES.doom)
|
|
|
|
or (props.image == TOKEN_IMAGES.doom and props.image_bottom == TOKEN_IMAGES.clue)
|
|
|
|
then
|
|
|
|
Wait.time(|| Global.destroyObject(obj), 1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- find location cards
|
|
|
|
local locCards = {}
|
|
|
|
local notFound = {}
|
|
|
|
for i,loc in ipairs(LOCATIONS) do
|
2021-02-13 12:12:29 -05:00
|
|
|
local card = allCards[loc.name]
|
2020-11-28 11:47:21 -05:00
|
|
|
if card == nil then
|
2021-02-13 12:12:29 -05:00
|
|
|
table.insert(notFound, loc.name)
|
2020-11-28 11:47:21 -05:00
|
|
|
else
|
|
|
|
table.insert(locCards, card)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if #notFound > 0 then
|
|
|
|
printToColor("The following locations were not found: " ..
|
|
|
|
table.concat(notFound, ", "), _color)
|
|
|
|
printToColor("Place them in the central play area and try again", _color)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Perils of Yoth
|
|
|
|
local peril = allCards[PERILS]
|
|
|
|
if peril ~= nil then
|
|
|
|
if peril.card ~= nil then
|
|
|
|
placeCard(nil, peril.card, ASSEMBLY)
|
|
|
|
else
|
|
|
|
placeCard(peril.deck, peril.guid, ASSEMBLY)
|
|
|
|
if peril.deck.is_face_down and #peril.deck.getObjects() > 0 then
|
|
|
|
peril.deck.shuffle()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- reset clue spawn status and make a deck of all location cards in the
|
|
|
|
-- assembly area
|
|
|
|
local spawnedGuids = playarea.getVar("SPAWNED_LOCATION_GUIDS")
|
|
|
|
for i,loc in ipairs(locCards) do
|
|
|
|
spawnedGuids[loc.guid] = nil
|
|
|
|
if loc.card ~= nil then
|
|
|
|
placeCard(nil, loc.card, ASSEMBLY)
|
|
|
|
elseif loc.deck ~= nil and #loc.deck.getObjects() > 0 then
|
|
|
|
placeCard(loc.deck, loc.guid, ASSEMBLY)
|
|
|
|
else
|
|
|
|
-- all but one card was taken from deck, so it doesn't exist anymore
|
|
|
|
Wait.time(|| placeCard(nil, loc.guid, ASSEMBLY), 1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
playarea.setVar("SPAWNED_LOCATION_GUIDS", spawnedGuids)
|
|
|
|
Wait.time(setup_2, 2)
|
|
|
|
end
|
|
|
|
|
|
|
|
function setup_2()
|
|
|
|
local objs = Physics.cast({
|
|
|
|
origin = ASSEMBLY.position,
|
|
|
|
direction = { x=0, y=1, z=0 },
|
|
|
|
type = 3,
|
|
|
|
size = { x=1, y=1, z=1 },
|
|
|
|
orientation = ASSEMBLY.rotation
|
|
|
|
})
|
|
|
|
|
|
|
|
local deck = nil
|
|
|
|
for i,v in ipairs(objs) do
|
|
|
|
if v.hit_object.tag == "Deck" then
|
|
|
|
deck = v.hit_object
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local locMap = {}
|
|
|
|
for i,card in ipairs(deck.getObjects()) do
|
|
|
|
locMap[card.name] = card.guid
|
|
|
|
end
|
|
|
|
|
|
|
|
-- place Steps of Yoth and Perils of Yoth (if necessary)
|
|
|
|
placeCard(deck, locMap[STEPS], EXPLORATION)
|
|
|
|
if locMap[PERILS] ~= nil then
|
|
|
|
placeCard(deck, locMap[PERILS], EXPLORATION)
|
|
|
|
end
|
|
|
|
|
|
|
|
-- randomly select starting location
|
|
|
|
deck.shuffle()
|
|
|
|
placeCard(deck, nil, START, true)
|
|
|
|
|
|
|
|
-- assemble exploration deck
|
|
|
|
for i=1,4 do
|
|
|
|
placeCard(deck, nil, EXPLORATION)
|
|
|
|
end
|
|
|
|
Wait.time(setup_3, 1)
|
|
|
|
|
|
|
|
-- move remaining cards to set aside area
|
|
|
|
deck.setPosition(SET_ASIDE.position)
|
|
|
|
deck.setName("Set Aside Locations")
|
|
|
|
end
|
|
|
|
|
|
|
|
function setup_3()
|
|
|
|
local objs = Physics.cast({
|
|
|
|
origin = EXPLORATION.position,
|
|
|
|
direction = { x=0, y=1, z=0 },
|
|
|
|
type = 3,
|
|
|
|
size = { x=1, y=1, z=1 },
|
|
|
|
orientation = EXPLORATION.rotation
|
|
|
|
})
|
|
|
|
|
|
|
|
local deck = nil
|
|
|
|
for i,v in ipairs(objs) do
|
|
|
|
if v.hit_object.tag == "Deck" then
|
|
|
|
deck = v.hit_object
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
deck.shuffle()
|
|
|
|
deck.setName("Exploration Deck")
|
|
|
|
end
|
|
|
|
|
|
|
|
function placeCard(deck, card, location, faceup)
|
|
|
|
if deck ~= nil then
|
|
|
|
deck.takeObject({
|
|
|
|
guid = card,
|
|
|
|
position = location.position,
|
|
|
|
rotation = location.rotation,
|
|
|
|
smooth = false,
|
|
|
|
flip = faceup
|
|
|
|
})
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
if type(card) == "string" then
|
|
|
|
card = getObjectFromGUID(card)
|
|
|
|
end
|
|
|
|
card.setRotation(location.rotation)
|
|
|
|
card.setPosition(location.position)
|
|
|
|
if faceup then card.flip() end
|
|
|
|
end
|
2021-02-13 12:12:29 -05:00
|
|
|
|
|
|
|
function updateConnections(obj, color, alt_click)
|
|
|
|
local objs = getPlayAreaObjects()
|
|
|
|
|
|
|
|
local cardObjs = {}
|
|
|
|
local connObjs = {}
|
|
|
|
for i,v in ipairs(objs) do
|
|
|
|
local obj = v.hit_object
|
|
|
|
local guid = obj.getGUID()
|
|
|
|
if guid ~= nil and obj.tag == "Card" and not obj.is_face_down then
|
|
|
|
local name = obj.getName()
|
|
|
|
local loc = nameMap[name]
|
|
|
|
if loc ~= nil then
|
|
|
|
cardObjs[name] = obj
|
|
|
|
connObjs[loc.symbol] = obj
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local lines = {}
|
|
|
|
for name,obj in pairs(cardObjs) do
|
|
|
|
for j,conn in ipairs(nameMap[obj.getName()].connections) do
|
|
|
|
if connObjs[conn] ~= nil then
|
|
|
|
drawConnection(obj, connObjs[conn], lines)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
Global.setVectorLines(lines)
|
|
|
|
end
|
|
|
|
|
|
|
|
function clearLines()
|
|
|
|
Global.setVectorLines({})
|
|
|
|
end
|
|
|
|
|
|
|
|
function drawConnection(origin, target, lines)
|
|
|
|
local originPos = origin.getPosition()
|
|
|
|
local targetPos = target.getPosition()
|
|
|
|
table.insert(lines, { points={ originPos, targetPos } })
|
|
|
|
|
|
|
|
if not connectsTo(target, origin) then
|
|
|
|
-- draw one-way arrow
|
|
|
|
local midpoint = originPos:lerp(targetPos, 0.5)
|
|
|
|
local direction = (targetPos - originPos):normalize()
|
|
|
|
local arrow1 = direction:copy():rotateOver('y', 45)
|
|
|
|
local arrow2 = direction:copy():rotateOver('y', -45)
|
|
|
|
table.insert(lines, { points={ midpoint-arrow1, midpoint, midpoint-arrow2 } })
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function connectsTo(origin, target)
|
|
|
|
local symbol = nameMap[target.getName()].symbol
|
|
|
|
for i,conn in ipairs(nameMap[origin.getName()].connections) do
|
|
|
|
if conn == symbol then return true end
|
|
|
|
end
|
|
|
|
return false
|
|
|
|
end
|