def makeQuestsFromData(self, avatar=None):
        """Creates new quest instances based on the questData array from the avatar. 
        If not provided an avatar, it will default to the owner of this quest manager. """

        if avatar is None:
            avatar = self.avatar

            if self.avatar is None:
                raise AssertionError(
                    'An avatar must be provided to #makeQuestsFromData() if using an anonymous quest manager.'
                )

        # Make sure to cleanup old quests before we override them.
        for quest in self.quests.values():
            quest.cleanup()

        self.quests = {}

        QuestData.extractDataAsIntegerLists(
            avatar.getQuests(), parseDataFunc=self.makeQuestFromData)
    def removeEntireQuest(self, questId):
        """
        Remove the specified quest from the avatars current quest list.
        This is mainly called when a quest is completed.
        """

        del self.quests[questId]
        questData, _, _ = QuestData.toDataStump(self.quests.values(), self.trackingId)

        # Update the information on the network and database.
        self.avatar.b_setQuests(questData)
    def updateQuestObjective(self, questId, value):
        """Change the objective on the quest specified to the value specified."""
        currentObjectives = []
        
        for quest in self.quests.values():
            if quest.id != questId:
                currentObjectives.append(quest.currentObjectiveIndex)
            else:
                currentObjectives.append(value)
        questData, _, _ = QuestData.toDataStump(self.quests.values(), self.trackingId, currentObjectives = currentObjectives)

        # Update the information on the network and database.
        self.avatar.b_setQuests(questData)
    def addNewQuest(self, questId):
        """Add the specified quest to the avatar's quest history and current quests."""

        questHistory = list(self.avatar.getQuestHistory())
        quest = Quest(questId, self)
        quest.setupCurrentObjectiveFromData(-1, 0, [0])
        
        quests = list(self.quests.values())
        quests.append(quest)
        questData, _, _ = QuestData.toDataStump(quests, self.trackingId)

        # Add this questId to the quest history.
        questHistory.append(questId)

        # Update this stuff on the network and database.
        self.avatar.b_setQuests(questData)
        self.avatar.b_setQuestHistory(questHistory)
    def incrementQuestObjective(self, questId, increment = 1):
        """
        Move to the next objective inside the quest.
        Mainly called when an objective is complete or when switching to the next objective.
        """
        
        currentObjectives = []
        
        for quest in self.quests.values():
            if quest.id != questId:
                currentObjectives.append(quest.currentObjectiveIndex)
            else:
                currentObjectives.append(quest.currentObjectiveIndex + increment)
        questData, _, _ = QuestData.toDataStump(self.quests.values(), self.trackingId, currentObjectives)

        # Update the information on the network and database.
        self.avatar.b_setQuests(questData)
    def updateQuestObjectiveProgress(self, questId, objIndex, value):
        """ Generates the quest data with the current objective progress on the quest specified to the value."""

        progresses = []
        
        for quest in self.quests.values():
            if quest.id != questId:
                progress = []
                for objective in quest.accessibleObjectives:
                    progress.append(objective.progress)
                progresses.append(progress)
            else:
                progress = []
                for i, objective in enumerate(quest.accessibleObjectives):
                    if not i is objIndex:
                        progress.append(objective.progress)
                    else:
                        progress.append(value)
                progresses.append(progress)
        return QuestData.toDataStump(self.quests.values(), self.trackingId, objectiveProgresses = progresses)
    def incrementQuestObjectiveProgress(self, questId, objIndex, increment = 1):
        """Increment the progress on the current objective of the quest specified by the increment."""

        progresses = []
        
        for quest in self.quests.values():
            if quest.id != questId:
                progress = []
                for objective in quest.accessibleObjectives:
                    progress.append(objective.progress)
                progresses.append(progress)
            else:
                progress = []
                
                for i, objective in enumerate(quest.accessibleObjectives):
                    if i != objIndex:
                        progress.append(objective.progress)
                    else:
                        progress.append(objective.progress + increment)
                progresses.append(progress)

        return QuestData.toDataStump(self.quests.values(), self.trackingId, objectiveProgresses = progresses)
    def __handleNewQuestData(self, oldDataStr, newDataStr):
        _, oldData = QuestData.extractDataAsIntegerLists(oldDataStr, None)
        _, newData = QuestData.extractDataAsIntegerLists(newDataStr, None)

        newQuests = {}
        oldQuests = {}

        for newQuestData in newData:
            questId = newQuestData[0]
            quest = Quest(questId, None)
            quest.setupCurrentObjectiveFromData(newQuestData[2],
                                                newQuestData[1],
                                                newQuestData[3])
            newQuests.update({questId: quest})

        for oldQuestData in oldData:
            questId = oldQuestData[0]
            quest = Quest(questId, None)
            quest.setupCurrentObjectiveFromData(oldQuestData[2],
                                                oldQuestData[1],
                                                oldQuestData[3])
            oldQuests.update({questId: quest})

        def acknowledgeLastObjectivesComplete(quest):
            # Let's acknowledge that we finished our last objectives.
            for objective in quest.accessibleObjectives:
                objText = objective.getUpdateBrief()
                if objective.HasProgress:
                    # This is a bit hacky, but it just allows
                    # #getProgressUpdateBrief() to show the correct stuff.
                    objective.progress = objective.goal
                    objText = objective.getProgressUpdateBrief()
                self.addLine(
                    '{0}: {1}'.format(self.OBJECTIVE_COMPLETE, objText),
                    self.GREEN_COLOR)

        if len(oldDataStr) > 0:

            # Let's display the text for completed quests.
            if len(oldData) > len(newData):
                for questId, quest in oldQuests.iteritems():
                    if not questId in newQuests.keys():
                        # Let's acknowledge that we finished our last objective.
                        if len(quest.accessibleObjectives) == 1:
                            objective = quest.accessibleObjectives[0]
                        else:
                            objective = quest.accessibleObjectives[
                                len(quest.accessibleObjectives) - 1]

                        npcId = objective.assigner if not hasattr(
                            objective, 'npcId') else objective.npcId

                        if npcId == 0:
                            objInfo = '{0} to a {1}'.format(
                                RETURN, NPCGlobals.lHQOfficerM)
                        else:
                            locationText = getLocationText(None,
                                                           objective,
                                                           verbose=False)
                            objInfo = '{0} to {1} at {2}'.format(
                                RETURN, NPCGlobals.NPCToonNames[npcId],
                                locationText)
                        self.addLine(
                            '{0}: {1}'.format(self.OBJECTIVE_COMPLETE,
                                              objInfo), self.GREEN_COLOR)

                        # This quest isn't in our new dictionary. It must've been completed!
                        quest = oldQuests.get(questId)
                        self.addLine(
                            '{0}: \"{1}\"'.format(self.QUEST_COMPLETE,
                                                  quest.name),
                            self.GREEN_COLOR)

            for questId, newQuest in newQuests.iteritems():
                oldQuest = oldQuests.get(questId, None)

                if oldQuest:
                    # Let's handle when the quest is complete.
                    if newQuest.isComplete() and not oldQuest.isComplete():
                        objective = newQuest.accessibleObjectives[0]
                        npcId = objective.assigner if not hasattr(
                            objective, 'npcId') else objective.npcId

                        acknowledgeLastObjectivesComplete(oldQuest)

                        if npcId == 0:
                            objInfo = '{0} to a {1}'.format(
                                RETURN, NPCGlobals.lHQOfficerM)
                        else:
                            locationText = getLocationText(None,
                                                           objective,
                                                           verbose=False)
                            objInfo = '{0} to {1} at {2}'.format(
                                RETURN, NPCGlobals.NPCToonNames[npcId],
                                locationText)

                        self.addLine(
                            '{0}: {1}'.format(self.NEW_OBJECTIVE, objInfo),
                            self.ORANGE_COLOR)

                    # Let's handle when the current objective changes.
                    elif newQuest.currentObjectiveIndex > oldQuest.currentObjectiveIndex:
                        objInfo = newQuest.accessibleObjectives[
                            0].getUpdateBrief()
                        color = self.ORANGE_COLOR
                        prefix = self.NEW_OBJECTIVE

                        # Let's acknowledge that we finished our last objectives.
                        acknowledgeLastObjectivesComplete(oldQuest)

                        if newQuest.isComplete() and not oldQuest.isComplete():
                            color = self.GREEN_COLOR
                            prefix = self.QUEST_COMPLETE

                        self.addLine('{0}: {1}'.format(prefix, objInfo), color)

                    elif newQuest.currentObjectiveIndex == oldQuest.currentObjectiveIndex:
                        for objIndex, newObjective in enumerate(
                                newQuest.accessibleObjectives):
                            oldObjective = oldQuest.accessibleObjectives[
                                objIndex]

                            if newObjective.progress > oldObjective.progress:
                                objInfo = newObjective.getProgressUpdateBrief()
                                prefix = self.OBJECTIVE_UPDATE
                                color = self.YELLOW_COLOR

                                if newObjective.isComplete():
                                    color = self.GREEN_COLOR
                                    prefix = self.OBJECTIVE_COMPLETE

                                self.addLine(
                                    '{0}: {1}'.format(prefix, objInfo), color)
                else:
                    newObjective = newQuest.accessibleObjectives[0]
                    objInfo = newObjective.getUpdateBrief()

                    self.addLine(
                        '{0}: \"{1}\"'.format(self.NEW_QUEST, newQuest.name),
                        self.YELLOW_COLOR)
                    self.addLine(
                        '{0}: {1}'.format(self.NEW_OBJECTIVE, objInfo),
                        self.YELLOW_COLOR)

        # Let's cleanup our garbage now.
        for quest in itertools.chain(oldQuests.values(), newQuests.values()):
            quest.cleanup()
        newQuests.clear()
        oldQuests.clear()
 def updateQuestData(self, currentObjectives = [], objectiveProgresses = []):
     questData, _, _ = QuestData.toDataStump(self.quests.values(), self.trackingId, currentObjectives, objectiveProgresses)
     self.avatar.b_setQuests(questData)