--These are piles we want to sort so the user does not know the order of the cards local PILES_WITH_SECRET_ORDER = { [TRIBUTE_BOARD_LOCATION_PLAYER_DECK] = true, [TRIBUTE_BOARD_LOCATION_OPPONENT_DECK] = true, [TRIBUTE_BOARD_LOCATION_OPPONENT_HAND] = true, [TRIBUTE_BOARD_LOCATION_DOCKS_DECK] = true, } local function CompareSecretOrderedEntries(left, right) -- Compare patrons if left.patronId == right.patronId then -- If the patron ids are the same, compare the name if left.name == right.name then -- If the names are the same, compare the card id if left.cardId == right.cardId then --If the card ids are the same, compare the card instance ids return left.cardInstanceId < right.cardInstanceId else return left.cardId < right.cardId end else return left.name < right.name end else local leftIsNeutral = IsTributePatronNeutral(left.patronId) local rightIsNeutral = IsTributePatronNeutral(right.patronId) if leftIsNeutral == rightIsNeutral then -- Just group the patrons return left.patronId < right.patronId else -- Neutral cards first return leftIsNeutral end end end -- Tribute Pile Data -- ZO_TributePileData = ZO_InitializingObject:Subclass() function ZO_TributePileData:Initialize(boardLocation, family) self.boardLocation = boardLocation self.family = family self.cardDataList = {} self:MarkDirty() end function ZO_TributePileData:MarkDirty() self.dirty = true end function ZO_TributePileData:GetBoardLocation() return self.boardLocation end function ZO_TributePileData:GetFamilyInfo() return self.family end function ZO_TributePileData:GetNumCards() return #self:GetCardList() end function ZO_TributePileData:GetName() return GetString("SI_TRIBUTEBOARDLOCATION", self.boardLocation) end function ZO_TributePileData:RefreshCardList() ZO_ClearNumericallyIndexedTable(self.cardDataList) local numCards = GetNumTributeCardsAtBoardLocation(self.boardLocation) for index = 1, numCards do local instanceId = GetTributeCardInstanceIdAtBoardLocation(self.boardLocation, index) local cardId, patronId = GetTributeCardInstanceDefIds(instanceId) local data = { index = index, cardId = cardId, patronId = patronId, cardInstanceId = instanceId, name = GetTributeCardName(cardId), } table.insert(self.cardDataList, data) end if PILES_WITH_SECRET_ORDER[self.boardLocation] then table.sort(self.cardDataList, CompareSecretOrderedEntries) end self.dirty = false end function ZO_TributePileData:GetCardList(optionalSortFunction) if self.dirty then self:RefreshCardList() end if optionalSortFunction then local sortedCardDataList = ZO_ShallowTableCopy(self.cardDataList) table.sort(sortedCardDataList, optionalSortFunction) return sortedCardDataList else return self.cardDataList end end function ZO_TributePileData:GetNumCardsPerPatronId() local numPatronIdCards = {} local cardList = self:GetCardList() for _, cardData in ipairs(cardList) do local patronId = cardData.patronId local numCards = numPatronIdCards[patronId] or 0 numPatronIdCards[patronId] = numCards + 1 end return numPatronIdCards end function ZO_TributePileData:GetPatronCardCountList() local numPatronIdCards = self:GetNumCardsPerPatronId() local patronCardCountList = {} for patronId, numCards in pairs(numPatronIdCards) do local patronData = TRIBUTE_DATA_MANAGER:GetTributePatronData(patronId) local patronCardCountData = { patronData = patronData, numCards = numCards, } table.insert(patronCardCountList, patronCardCountData) end table.sort(patronCardCountList, ZO_TributePileData.PatronCardCountListSortFunction) return patronCardCountList end function ZO_TributePileData.PatronCardCountListSortFunction(left, right) return left.patronData:GetName() < right.patronData:GetName() end function ZO_TributePileData:TryTriggerHandAndDocksTutorials() if not GetSetting_Bool(SETTING_TYPE_TUTORIAL, TUTORIAL_ENABLED_SETTING_ID) then return end local cardList = self:GetCardList() local hasContractAgent = false local hasTaunt = false local hasContract = false local hasAgent = false local hasChoice = false local hasTrigger = false local hasConfine = false local hasDonate = false local hasSetback = false -- Loop through the cards in this pile and determine which tutorials we should try to trigger for _, cardData in ipairs(cardList) do local cardDefId = cardData.cardId local isContract = IsTributeCardContract(cardDefId) local isAgent = GetTributeCardType(cardDefId) == TRIBUTE_CARD_TYPE_AGENT -- If the card is a contract or an agent if isContract or isAgent then hasContract = hasContract or isContract hasAgent = hasAgent or isAgent -- If the card is a contract agent if isAgent and isContract then hasContractAgent = true end end -- If the card has taunt if not hasTaunt and DoesTributeCardTaunt(cardDefId) then hasTaunt = true end -- If the card is a choice card if not hasChoice and DoesTributeCardChooseOneMechanic(cardDefId) then hasChoice = true end -- If the card has a trigger mechanic if not hasTrigger and DoesTributeCardHaveTriggerMechanic(cardDefId) then hasTrigger = true end -- If the card has a setback mechanic if not hasSetback and DoesTributeCardHaveSetbackMechanic(cardDefId) then hasSetback = true end -- The confine mechanic is only on agents so we can skip the check if this card isn't an agent if not hasConfine and isAgent and DoesTributeCardHaveMechanicType(cardDefId, TRIBUTE_MECHANIC_CONFINE_CARDS) then hasConfine = true end -- If the card has a donate mechanic if not hasDonate and DoesTributeCardHaveMechanicType(cardDefId, TRIBUTE_MECHANIC_DONATE_CARDS) then hasDonate = true end end -- Trigger the tutorials in the order of the priority we want them to show in if hasContractAgent then TUTORIAL_MANAGER:ShowTutorial(TUTORIAL_TRIGGER_TRIBUTE_CONTRACT_AGENT_CARD_SEEN) end if hasTaunt then TUTORIAL_MANAGER:ShowTutorial(TUTORIAL_TRIGGER_TRIBUTE_TAUNT_AGENT_CARD_SEEN) end if hasContract then TUTORIAL_MANAGER:ShowTutorial(TUTORIAL_TRIGGER_TRIBUTE_CONTRACT_CARD_SEEN) end if hasAgent then TUTORIAL_MANAGER:ShowTutorial(TUTORIAL_TRIGGER_TRIBUTE_AGENT_CARD_SEEN) end if hasChoice then TUTORIAL_MANAGER:ShowTutorial(TUTORIAL_TRIGGER_TRIBUTE_CHOICE_CARD_SEEN) end if hasTrigger then TUTORIAL_MANAGER:ShowTutorial(TUTORIAL_TRIGGER_TRIBUTE_TRIGGER_CARD_SEEN) end if hasConfine then TUTORIAL_MANAGER:ShowTutorial(TUTORIAL_TRIGGER_TRIBUTE_CONFINE_CARD_SEEN) end if hasDonate then TUTORIAL_MANAGER:ShowTutorial(TUTORIAL_TRIGGER_TRIBUTE_DONATE_CARD_SEEN) end if hasSetback then TUTORIAL_MANAGER:ShowTutorial(TUTORIAL_TRIGGER_TRIBUTE_SETBACK_CARD_SEEN) end end function ZO_TributePileData:TryTriggerDeckAndCooldownTutorials() if not GetSetting_Bool(SETTING_TYPE_TUTORIAL, TUTORIAL_ENABLED_SETTING_ID) then return end local cardList = self:GetCardList() local hasCurse = false -- Loop through the cards in this pile and determine which tutorials we should try to trigger for _, cardData in ipairs(cardList) do local cardDefId = cardData.cardId -- If the card is a curse card if IsTributeCardCurse(cardDefId) then hasCurse = true -- This is only doable because hasCurse is the only thing we are checking for right now. -- We should remove this line if we add more tutorial triggers to this function in the future break end end -- Trigger the tutorials in the order of the priority we want them to show in if hasCurse then TUTORIAL_MANAGER:ShowTutorial(TUTORIAL_TRIGGER_TRIBUTE_CURSE_CARD_SEEN) end end -- Combine the contents of multiple piles into one object ZO_TributeCompositePileData = ZO_TributePileData:Subclass() function ZO_TributeCompositePileData:Initialize(boardLocations, family) ZO_TributePileData.Initialize(self, boardLocations[1], family) self.boardLocations = boardLocations end function ZO_TributeCompositePileData:GetBoardLocations() return self.boardLocations end function ZO_TributeCompositePileData:SetOverrideName(overrideName) self.overrideName = overrideName end function ZO_TributeCompositePileData:GetName() return self.overrideName or ZO_TributePileData.GetName(self) end do local function CompareEntries(left, right) if not (left.isSecretOrder and right.isSecretOrder) then -- One has a non-secret order if left.locationSortIndex == right.locationSortIndex then -- If the board locations are the same, maintain the index sort return left.index < right.index else -- If the locations are not the same, sort by locationSortIndex return left.locationSortIndex < right.locationSortIndex end end -- Both have secret order return CompareSecretOrderedEntries(left, right) end function ZO_TributeCompositePileData:RefreshCardList() ZO_ClearNumericallyIndexedTable(self.cardDataList) local anyLocationHasSecretOrder = false for locationSortIndex, boardLocation in ipairs(self.boardLocations) do local numCards = GetNumTributeCardsAtBoardLocation(boardLocation) local isSecretOrder = PILES_WITH_SECRET_ORDER[boardLocation] for index = 1, numCards do local instanceId = GetTributeCardInstanceIdAtBoardLocation(boardLocation, index) local cardId, patronId = GetTributeCardInstanceDefIds(instanceId) local data = { locationSortIndex = locationSortIndex, index = index, cardId = cardId, patronId = patronId, cardInstanceId = instanceId, name = GetTributeCardName(cardId), isSecretOrder = isSecretOrder, } table.insert(self.cardDataList, data) end if numCards > 0 and isSecretOrder then anyLocationHasSecretOrder = true end end if anyLocationHasSecretOrder then table.sort(self.cardDataList, CompareEntries) end self.dirty = false end end