Page 1 of 1
Quest entries order?
Posted: Thu Nov 28, 2024 3:08 pm
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?
Re: Quest entries order?
Posted: Thu Nov 28, 2024 3:16 pm
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.
Re: Quest entries order?
Posted: Thu Nov 28, 2024 4:15 pm
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!
Re: Quest entries order?
Posted: Thu Nov 28, 2024 8:51 pm
by Tony Li
I'll put together an example script tomorrow and post it here.
Re: Quest entries order?
Posted: Thu Nov 28, 2024 9:16 pm
by marafrass
Much appreciated, take your time!
Re: Quest entries order?
Posted: Fri Nov 29, 2024 8:33 pm
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);
}
}
}
}
Re: Quest entries order?
Posted: Sat Nov 30, 2024 12:58 am
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.
Re: Quest entries order?
Posted: Sat Nov 30, 2024 6:36 am
by Tony Li
Glad to help! You have a great weekend, too!