Quest entries order?

Announcements, support questions, and discussion for the Dialogue System.
Post Reply
marafrass
Posts: 40
Joined: Thu Jan 16, 2020 1:32 pm

Quest entries order?

Post by marafrass »

Heya Tony!

Quick question about quest entries (subtasks) in the quest tracker UI. I've noticed that they're automatically arranged by number - is there any way to make them appear in the order which they're marked as active? For example, if I've got these entries in a quest;
1. The guy has asked you for cheese.
2. You gave the guy some cheese.
3. The guy wants blue cheese specifically.

Let's say I speak to the NPC and he asks for cheese, and I agree to the quest. (#1 is added to the tracker) I then ask in a subdialogue what kind of cheese he wants, and he specifies that he wants blue cheese. (#3 is added to the tracker) I finish the quest, and finally, #2 is added. If I check the tracker now, the entries will still be in the order in which I originally created them (1,2,3). Is there an existing way to make the tracker instead show 1,3,2?
User avatar
Tony Li
Posts: 23259
Joined: Thu Jul 18, 2013 1:27 pm

Re: Quest entries order?

Post by Tony Li »

Hi,

You'll either need to switch the order of the entries (so "wants blue cheese" is second) in the Dialogue Editor or do a bit of custom scripting. If it won't work to switch the order of the entries, let me know and I'll describe how to set up the scripting.
marafrass
Posts: 40
Joined: Thu Jan 16, 2020 1:32 pm

Re: Quest entries order?

Post by marafrass »

I've already got tons of dialogues set up with the existing entries, so any advice on how to set up the custom scripting would be really helpful!
User avatar
Tony Li
Posts: 23259
Joined: Thu Jul 18, 2013 1:27 pm

Re: Quest entries order?

Post by Tony Li »

I'll put together an example script tomorrow and post it here.
marafrass
Posts: 40
Joined: Thu Jan 16, 2020 1:32 pm

Re: Quest entries order?

Post by marafrass »

Much appreciated, take your time!
User avatar
Tony Li
Posts: 23259
Joined: Thu Jul 18, 2013 1:27 pm

Re: Quest entries order?

Post by Tony Li »

Hi,

Here's the scripts and an example scene:

DS_QuestEntryOrderExample_2024-11-29.unitypackage

The RecordQuestEntryOrder script goes on the Dialogue Manager and records the order in which quest entries were activated. It stores this in a DS variable that it creates at runtime.

The OrderedQuestTrackerHUD script replaces StandardUIQuestTracker, and OrderedQuestLogWindow replaces StandardUIQuestLogWindow on your UIs. You can replace them in-place.

I'll copy the scripts in the package here, too, for reference:

RecordQuestEntryOrder.cs

Code: Select all

using System.Collections.Generic;
using UnityEngine;

namespace PixelCrushers.DialogueSystem.Examples
{

    // Add this script to the Dialogue Manager.
    public class RecordQuestEntryOrder : MonoBehaviour
    {
        
        // For each quest, we'll store the order to show entries in this variable:
        public static string GetEntryOrderVariableName(string quest)
        {
            return $"EntryOrder.{DialogueLua.StringToTableIndex(quest)}";
        }

        // If a quest entry has become active, add it to the order variable:
        public void OnQuestEntryStateChange(QuestEntryArgs args)
        {
            var entryState = QuestLog.GetQuestEntryState(args.questName, args.entryNumber);
            if (entryState == QuestState.Active)
            {
                var orderVariableName = RecordQuestEntryOrder.GetEntryOrderVariableName(args.questName);
                var orderString = DialogueLua.GetVariable(orderVariableName).asString;
                if (!string.IsNullOrEmpty(orderString))
                {
                    // Make sure the entry isn't already in the order string:
                    var order = new List<string>(orderString.Split(';'));
                    if (order.Contains(args.entryNumber.ToString())) return;
                }
                // Add it to the order string:
                if (!string.IsNullOrEmpty(orderString)) orderString += ";";
                orderString += args.entryNumber;
                DialogueLua.SetVariable(orderVariableName, orderString);
            }
        }

    }

}
OrderedQuestTrackerHUD.cs

Code: Select all

namespace PixelCrushers.DialogueSystem.Examples
{

    // This subclass of StandardUIQuestTracker observes quests' entry order variables.
    public class OrderedQuestTrackerHUD : StandardUIQuestTracker
    {

        protected override void SetupQuestTrackInstance(StandardUIQuestTrackTemplate questTrack, string quest, string heading)
        {
            var orderVariableName = RecordQuestEntryOrder.GetEntryOrderVariableName(quest);
            var orderString = DialogueLua.GetVariable(orderVariableName).asString;

            // If there's no entry order variable, use the base method:
            if (string.IsNullOrEmpty(orderString))
            {
                base.SetupQuestTrackInstance(questTrack, quest, heading);
                return;
            }

            // Otherwise add entries in the order specified in the variable:
            if (questTrack == null) return;
            questTrack.Initialize();
            var questState = QuestLog.GetQuestState(quest);
            questTrack.SetDescription(heading, questState);
            int entryCount = QuestLog.GetQuestEntryCount(quest);
            var order = orderString.Split(';');
            foreach (string entryNumberString in order)
            {
                if (int.TryParse(entryNumberString, out var entryNum))
                {
                    if (!(1 <= entryNum && entryNum <= entryCount)) continue;
                    var entryState = QuestLog.GetQuestEntryState(quest, entryNum);
                    var entryText = FormattedText.Parse(GetQuestEntryText(quest, entryNum, entryState), DialogueManager.masterDatabase.emphasisSettings).text;
                    if (!string.IsNullOrEmpty(entryText))
                    {
                        questTrack.AddEntryDescription(entryText, entryState);
                    }
                }
            }
        }


    }

}
OrderedQuestLogWindow.cs

Code: Select all

namespace PixelCrushers.DialogueSystem.Examples
{

    // This subclass of StandardUIQuestLogWindow observes quests' entry order variables.
    public class OrderedQuestLogWindow : StandardUIQuestLogWindow
    {

        protected override void RepaintSelectedQuest(QuestInfo quest)
        {
            if (quest == null)
            {
                base.RepaintSelectedQuest(quest);
                return;
            }

            var orderVariableName = RecordQuestEntryOrder.GetEntryOrderVariableName(quest.Title);
            var orderString = DialogueLua.GetVariable(orderVariableName).asString;

            // If there's no entry order variable, use base method:
            if (string.IsNullOrEmpty(orderString))
            {
                base.RepaintSelectedQuest(quest);
                return;
            }

            // Otherwise show entries in the order specified in the variable:
            detailsPanelContentManager.Clear();

            // Title:
            var titleInstance = detailsPanelContentManager.Instantiate<StandardUITextTemplate>(questHeadingTextTemplate);
            titleInstance.Assign(quest.Heading.text);
            detailsPanelContentManager.Add(titleInstance, questDetailsContentContainer);

            // Description:
            var descriptionInstance = detailsPanelContentManager.Instantiate<StandardUITextTemplate>(questDescriptionTextTemplate);
            descriptionInstance.Assign(quest.Description.text);
            detailsPanelContentManager.Add(descriptionInstance, questDetailsContentContainer);

            // Entries:
            var order = orderString.Split(';');
            for (int i = 0; i < order.Length; i++)
            {
                if (int.TryParse(order[i], out var entryNum))
                {
                    if (!(1 <= entryNum && entryNum <= quest.Entries.Length)) continue;
                    var entryTemplate = GetEntryTemplate(quest.EntryStates[entryNum - 1]);
                    if (entryTemplate != null)
                    {
                        var entryInstance = detailsPanelContentManager.Instantiate<StandardUITextTemplate>(entryTemplate);
                        entryInstance.Assign(quest.Entries[entryNum - 1].text);
                        detailsPanelContentManager.Add(entryInstance, questDetailsContentContainer);
                    }
                }
            }

            // Abandon button:
            if (isShowingActiveQuests && QuestLog.IsQuestAbandonable(quest.Title))
            {
                var abandonButtonInstance = detailsPanelContentManager.Instantiate<StandardUIButtonTemplate>(abandonButtonTemplate);
                detailsPanelContentManager.Add(abandonButtonInstance, questDetailsContentContainer);
                abandonButtonInstance.button.onClick.AddListener(ClickAbandonQuestButton);
            }
        }

    }

}
marafrass
Posts: 40
Joined: Thu Jan 16, 2020 1:32 pm

Re: Quest entries order?

Post by marafrass »

Just finished implementing everything as you instructed, and it all works perfectly. Amazing stuff man, thank you so much! Going above and beyond as always. Sorry if I took time away from a day off, by the way - didn't realize most people were taking today and yesterday off!

Thanks so much once again, and have a great weekend.
User avatar
Tony Li
Posts: 23259
Joined: Thu Jul 18, 2013 1:27 pm

Re: Quest entries order?

Post by Tony Li »

Glad to help! You have a great weekend, too!
Post Reply