-- Class card bag implementation. Mimics the behavior of the previous SCED -- card memory bags, but spawns cards from the All Cards Bag instead. -- -- The All Cards Bag handles indexing of the player cards by class and level, as -- well as sorting those lists. See that object for more information. local allCardsBagGuid = "15bb07" -- Lines which define the card layout area. The X threshold is shared, basic -- cards have Z > 47 while upgrades have Z < -46 -- Note that the SCED table is rotated, making X the vertical (up the table) -- axis and Z the side-to-side axis local CARD_AREA_X_THRESHOLD = 22 local CARD_AREA_BASIC_Z_THRESHOLD = 47 local CARD_AREA_UPGRADED_Z_THRESHOLD = -46 local skillCount = 0 local eventCount = 0 local assetCount = 0 -- Coordinates to begin laying out cards to match the reserved areas of the -- table. Cards will lay out horizontally, then create additional rows local startPositions = { upgrades = { skill = Vector(58.09966, 1.36, -47.42), event = Vector(52.94421, 1.36, -47.42), asset = Vector(40.29005, 1.36, -47.42), }, level0 = { skill = Vector(58.38383, 1.36, 92.39036), event = Vector(53.22857, 1.36, 92.44123), asset = Vector(40.9602, 1.36, 92.44869), }, } -- Amount to shift for the next card (zShift) or next row of cards (xShift) -- Note that the table rotation is weird, and the X axis is vertical while the -- Z axis is horizontal local zShift = -2.29998 local xShift = -3.66572 local yRotation = 270 local cardsPerRow = 20 -- Tracks cards which are placed by this "bag" so they can be recalled local placedCardGuids = { } local placedCardsCount = 0 -- In order to mimic the behavior of the previous memory buttons we use a -- a temporary bag when recalling objects. This bag is tiny and transparent, -- and will be placed at the same location as this object. Once all placed -- cards are recalled bag to this bag, it will be destroyed local recallBag = { Name = "Bag", Transform = { scaleX = 0.01, scaleY = 0.01, scaleZ = 0.01, }, ColorDiffuse = { r = 0, g = 0, b = 0, a = 0, }, Locked = true, Grid = true, Snap = false, Tooltip = false, } function onLoad(savedData) createPlaceRecallButtons() placedCardGuids = { } placedCardCount = 0 if (savedData ~= nil) then local saveState = JSON.decode(savedData) if (saveState.placedCards ~= nil) then placedCardGuids = saveState.placedCards end end end function onSave() local saveState = { placedCards = placedCardGuids, } return JSON.encode(saveState) end --Creates recall and place buttons function createPlaceRecallButtons() self.createButton({ label="Place", click_function="buttonClick_place", function_owner=self, position={1,0.1,2.1}, rotation={0,0,0}, height=350, width=800, font_size=250, color={0,0,0}, font_color={1,1,1} }) self.createButton({ label="Recall", click_function="buttonClick_recall", function_owner=self, position={-1,0.1,2.1}, rotation={0,0,0}, height=350, width=800, font_size=250, color={0,0,0}, font_color={1,1,1} }) end -- Spawns the set of cards identified by this objects Name (which should hold -- the class) and description (whether to spawn basic cards or upgraded) function buttonClick_place() -- Cards already on the table, don't spawn more if (placedCardCount > 0) then return end local cardClass = self.getName() local isUpgraded = false if (self.getDescription() == "Upgrades") then isUpgraded = true end skillCount = 0 eventCount = 0 assetCount = 0 local allCardsBag = getObjectFromGUID(allCardsBagGuid) local cardList = allCardsBag.call("getCardsByClassAndLevel", {class = cardClass, upgraded = isUpgraded}) placeCards(cardList) end -- Spawn all cards from the returned index function placeCards(cardIdList) local allCardsBag = getObjectFromGUID(allCardsBagGuid) local indexReady = allCardsBag.call("isIndexReady") if (not indexReady) then broadcastToAll("Still loading player cards, please try again in a few seconds", {0.9, 0.2, 0.2}) return end for _, cardId in ipairs(cardIdList) do local card = allCardsBag.call("getCardById", { id = cardId }) placeCard(card.data, card.metadata) end end function placeCard(cardData, cardMetadata) local destinationPos if (cardMetadata.type == "Skill") then destinationPos = getSkillPosition(cardMetadata.level > 0) elseif (cardMetadata.type == "Event") then destinationPos = getEventPosition(cardMetadata.level > 0) elseif (cardMetadata.type == "Asset") then destinationPos = getAssetPosition(cardMetadata.level > 0) end -- Clear the GUID from the card's data so it will get a new GUID on spawn. -- This solves the issue of duplicate GUIDs being spawned and causing problems -- with recall cardData.GUID = nil local spawnedCard = spawnObjectData({ data = cardData, position = destinationPos, rotation = {0, yRotation, 0}, callback_function = recordPlacedCard}) end -- Returns the table position where the next skill should be placed -- Param isUpgraded: True if it's an upgraded card (right side of the table), -- false for a Level 0 card (left side of table) function getSkillPosition(isUpgraded) local skillPos if (isUpgraded) then skillPos = startPositions.upgrades.skill:copy() else skillPos = startPositions.level0.skill:copy() end local shift = Vector(div(skillCount, cardsPerRow) * xShift, 0, (skillCount % cardsPerRow) * zShift) skillPos:add(shift) skillCount = skillCount + 1 return skillPos end -- Returns the table position where the next event should be placed -- Param isUpgraded: True if it's an upgraded card (right side of the table), -- false for a Level 0 card (left side of table) function getEventPosition(isUpgraded) local eventPos if (isUpgraded) then eventPos = startPositions.upgrades.event:copy() else eventPos = startPositions.level0.event:copy() end local shift = Vector(div(eventCount, cardsPerRow) * xShift, 0, (eventCount % cardsPerRow) * zShift) eventPos:add(shift) eventCount = eventCount + 1 return eventPos end -- Returns the table position where the next asset should be placed -- Param isUpgraded: True if it's an upgraded card (right side of the table), -- false for a Level 0 card (left side of table) function getAssetPosition(isUpgraded) local assetPos if (isUpgraded) then assetPos = startPositions.upgrades.asset:copy() else assetPos = startPositions.level0.asset:copy() end local shift = Vector(div(assetCount, cardsPerRow) * xShift, 0, (assetCount % cardsPerRow) * zShift) assetPos:add(shift) assetCount = assetCount + 1 return assetPos end -- Callback function which adds a spawned card to the tracking list function recordPlacedCard(spawnedCard) if (spawnedCard.getName() == "Protecting the Anirniq (2)") then log("Spawned PtA "..spawnedCard.getGUID()) end placedCardGuids[spawnedCard.getGUID()] = true placedCardCount = placedCardCount + 1 end -- Recalls all spawned cards to the bag, and clears the placedCardGuids list function buttonClick_recall() local trash = spawnObjectData({data = recallBag, position = self.getPosition()}) for cardGuid, _ in pairs(placedCardGuids) do local card = getObjectFromGUID(cardGuid) if (card ~= nil) then trash.putObject(card) placedCardGuids[cardGuid] = nil placedCardCount = placedCardCount - 1 end end if (placedCardCount > 0) then -- Couldn't recall all the cards, check and pull them from decks local decksInArea = { } local allObjects = getAllObjects() for _, object in ipairs(allObjects) do if (object.name == "Deck" and isInArea(object)) then table.insert(decksInArea, object) end end for _, deck in ipairs(decksInArea) do local cardsInDeck = deck.getObjects() for i, card in ipairs(cardsInDeck) do if (placedCardGuids[card.guid]) then trash.putObject(deck.takeObject({ guid = card.guid })) break end end end end trash.destruct() -- We've recalled everything we can, some cards may have been moved out of the -- card area. Just reset at this point. placedCardGuids = { } placedCardCount = 0 end function isInArea(object) if (object == nil) then return false end local position = object.getPosition() return position.x > CARD_AREA_X_THRESHOLD and (position.z > CARD_AREA_BASIC_Z_THRESHOLD or position.z < CARD_AREA_UPGRADED_Z_THRESHOLD) end function div(a,b) return (a - a % b) / b end