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?
Quest entries order?
Re: Quest entries order?
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.
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.
Re: Quest entries order?
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!
Re: Quest entries order?
I'll put together an example script tomorrow and post it here.
Re: Quest entries order?
Much appreciated, take your time!
Re: Quest entries order?
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
OrderedQuestTrackerHUD.cs
OrderedQuestLogWindow.cs
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);
}
}
}
}
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);
}
}
}
}
}
}
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);
}
}
}
}
Re: Quest entries order?
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.
Thanks so much once again, and have a great weekend.
Re: Quest entries order?
Glad to help! You have a great weekend, too!