Quest Tracker

Announcements, support questions, and discussion for the Dialogue System.
nivlekius
Posts: 105
Joined: Thu Feb 28, 2019 4:39 pm

Quest Tracker

Post by nivlekius »

Hello, I'm just trying to finish up some last things for quests and I'm trying to make the tracker show only a specific entry. For instance 1/10 goblins killed... etc.

I've made a new QuestTracker class like this

Code: Select all


public class CustomQuestTracker : StandardUIQuestTracker
{
    protected override string GetQuestEntryText(string quest, int entryNum, QuestState entryState)
    {
        if (entryState == QuestState.Unassigned || entryState == QuestState.Abandoned)
        {
            return string.Empty;
        }
        else if ((entryState == QuestState.Success || entryState == QuestState.Failure) && !showCompletedEntryText)
        {
            return string.Empty;
        }
        else if (entryState == QuestState.Success)
        {
            return string.Empty;
        }
        else if (entryState == QuestState.Failure)
        {
            return string.Empty;
        }
        else if (entryState == QuestState.Active)
        {
            var text = DialogueLua.GetQuestField(quest, QuestLog.GetQuestEntry(quest, 1)).asString;
            if (!string.IsNullOrEmpty(text)) return text;
        }
        return QuestLog.GetQuestEntry(quest, entryNum);
    }

}

But nothing shows up. Is there something else I need to adjust to make it show an entry only when active?

Thanks.
nivlekius
Posts: 105
Joined: Thu Feb 28, 2019 4:39 pm

Re: Quest Tracker

Post by nivlekius »

What I really need is a way to make new quest states that can work with the log and tracker together. The way it is now they don't cooperate. If I set a custom quest state to say "preempted" and it is really unassigned, then it will trigger the entry state of unassigned but it will leave the tracker window. If I set "preempted" to be active and I set the entry for active then it shows the entry before the objective is done. But in both cases the tracker window still leaves if the quest is in "preempted" and also the entry isn't showing on the tracker... again, I only need entries on the tracker at certain times.
User avatar
Tony Li
Posts: 22055
Joined: Thu Jul 18, 2013 1:27 pm

Re: Quest Tracker

Post by Tony Li »

Hi,

Try changing the method to:

Code: Select all

protected override string GetQuestEntryText(string quest, int entryNum, QuestState entryState)
{
    var questStateString = QuestLog.CurrentQuestState(quest);
    var isPreempted = questStateString == "preempted";
    var isReallyUnassigned = questStateString == "unassigned";
    if (isReallyUnassigned || entryState == QuestState.Abandoned)
    {
        return string.Empty;
    }
    else if ((entryState == QuestState.Success || entryState == QuestState.Failure) && !showCompletedEntryText)
    {
        return string.Empty;
    }
    else if (entryState == QuestState.Success)
    {
        return string.Empty;
    }
    else if (entryState == QuestState.Failure)
    {
        return string.Empty;
    }
    else if (entryState == QuestState.Active || isPreempted)
    {
        var text = DialogueLua.GetQuestField(quest, QuestLog.GetQuestEntry(quest, 1)).asString;
        if (!string.IsNullOrEmpty(text)) return text;
    }
    return QuestLog.GetQuestEntry(quest, entryNum);
}
This allows it to distinguish between the "preempted" and "unassigned" states.

EDIT: Fixed typo in 3rd line. Changed "record.questTitle" to "quest".
nivlekius
Posts: 105
Joined: Thu Feb 28, 2019 4:39 pm

Re: Quest Tracker

Post by nivlekius »

record.questTitle is an error - does not exist
nivlekius
Posts: 105
Joined: Thu Feb 28, 2019 4:39 pm

Re: Quest Tracker

Post by nivlekius »

I'm not sure I was correct but I just used "quest" from parameters instead. Seems to work but I still have the problem of the tracker closing if the state is not 'active' and seeing specific entries with the quest title in the tracker.
nivlekius
Posts: 105
Joined: Thu Feb 28, 2019 4:39 pm

Re: Quest Tracker

Post by nivlekius »

My guess is this is determining whether to show a certain quest state on the tracker:

Code: Select all

int numTracked = 0;
            QuestState flags = (showActiveQuests ? QuestState.Active : 0) |
                (showCompletedQuests ? QuestState.Success | QuestState.Failure : 0);
            foreach (string quest in QuestLog.GetAllQuests(flags))
            {
                if (QuestLog.IsQuestTrackingEnabled(quest))
                {
                    AddQuestTrack(quest);
                    numTracked++;
                }
            }
            if (container != null)
            {
                container.gameObject.SetActive(showContainerIfEmpty || numTracked > 0);
            }
and it looks like I could add | and the quest state but how do I add the quest state that is just text? Or can I?
User avatar
Tony Li
Posts: 22055
Joined: Thu Jul 18, 2013 1:27 pm

Re: Quest Tracker

Post by Tony Li »

Yes, sorry, you're correct to change "record.questTitle" to "quest". I copied it from one of our previous threads and forgot to change it.

Change the "QuestState flags =" line to:

Code: Select all

            QuestState flags = (showActiveQuests ? QuestState.Active : 0) |
                (showCompletedQuests ? QuestState.Success | QuestState.Failure : 0) | 
                QuestState.Unassigned;
Then change this line:

Code: Select all

if (QuestLog.IsQuestTrackingEnabled(quest))
to this:

Code: Select all

if (QuestLog.IsQuestTrackingEnabled(quest) && QuestLog.CurrentQuestState(quest) != "unassigned")
so you only include quests that are preempted and not really unassigned.
nivlekius
Posts: 105
Joined: Thu Feb 28, 2019 4:39 pm

Re: Quest Tracker

Post by nivlekius »

Well, the tracker is staying open now but unfortunately it's not showing the entry. It also makes the quest title go away.
Here is what I have done, just so you can see and perhaps so I don't forget. I've got custom code all over now and it's getting harder to keep track of. Anyway.

So here is my CustomQuestState:

Code: Select all

public class CustomQuestStateCode : MonoBehaviour
{

    public const string QuestStatePreempted = "preempted";
    public const string QuestStateReady = "ready";
    public const string QuestStateComplete = "complete";

    [ObfuscateLiterals]
    private void OnEnable()
    {
        Lua.RegisterFunction("UpdateTracker", null, SymbolExtensions.GetMethodInfo(() => DialogueManager.SendUpdateTracker()));
    }

    [ObfuscateLiterals]
    private void Start()
    {
        QuestLog.StringToState = CustomStringToState;
        QuestLog.StringToState = MakeReadyState;
        QuestLog.StringToState = CustomActiveState;
    }

    [SkipRename]
    [ObfuscateLiterals]
    public static QuestState CustomStringToState(string s)
    {
        if (s == "preempted") return QuestState.Unassigned;
        else return QuestLog.DefaultStringToState(s);
    }
    [SkipRename]
    [ObfuscateLiterals]
    public static QuestState CustomActiveState(string s)
    {
        if (s == "complete") return QuestState.Active;
        else return QuestLog.DefaultStringToState(s);
    }
    [SkipRename]
    [ObfuscateLiterals]
    public static QuestState MakeReadyState(string s)
    {
        if (s == "ready") return QuestState.Unassigned;
        else return QuestLog.DefaultStringToState(s);
    }

    [SkipRename]
    public void OnQuestTrackingEnabled(string questName)
    {
        ManagerSupp.instance.SaveLua();
    }
    [SkipRename]
    public void OnQuestTrackingDisabled(string questName)
    {
        ManagerSupp.instance.SaveLua();
    }

}
complete and ready are only used for the quest indicators.

Next is my custom quest tracker:

Code: Select all

public class CustomQuestTracker : StandardUIQuestTracker
{
    protected override string GetQuestEntryText(string quest, int entryNum, QuestState entryState)
    {
        var questStateString = QuestLog.CurrentQuestState(quest);
        var isPreempted = questStateString == "preempted";
        var isReallyUnassigned = questStateString == "unassigned";

        if (isReallyUnassigned || entryState == QuestState.Abandoned)
        {
            return string.Empty;
        }
        else if ((entryState == QuestState.Success || entryState == QuestState.Failure) && !showCompletedEntryText)
        {
            return string.Empty;
        }
        else if (entryState == QuestState.Success)
        {
            return string.Empty;
        }
        else if (entryState == QuestState.Failure)
        {
            return string.Empty;
        }
        else if (entryState == QuestState.Active)
        {
            var text = DialogueLua.GetQuestField(quest, QuestLog.GetQuestEntry(quest, 1)).asString;
        }
        else if (isPreempted) //entryState == QuestState.Active || isPreempted)
        {
            var text = DialogueLua.GetQuestField(quest, QuestLog.GetQuestEntry(quest, 2)).asString;
            if (!string.IsNullOrEmpty(text)) return text;
        }

        return QuestLog.GetQuestEntry(quest, entryNum);
    }

}
and I did this is the StandardUIQuestTracker as you showed me.

Code: Select all

protected virtual IEnumerator RefreshAtEndOfFrame()
        {
            yield return new WaitForEndOfFrame();

            // Move instances to the unused list:
            unusedInstances.AddRange(instantiatedItems);
            instantiatedItems.Clear();
            siblingIndexCounter = 0;

            // Add quests, drawing from unused list when possible:
            int numTracked = 0;
            QuestState flags = (showActiveQuests ? QuestState.Active : 0) |
                (showCompletedQuests ? QuestState.Success | QuestState.Failure : 0) | QuestState.Unassigned;
            foreach (string quest in QuestLog.GetAllQuests(flags))
            {
                if (QuestLog.IsQuestTrackingEnabled(quest) && QuestLog.CurrentQuestState(quest) != "unassigned")
                {
                    AddQuestTrack(quest);
                    numTracked++;
                }
            }
            if (container != null)
            {
                container.gameObject.SetActive(showContainerIfEmpty || numTracked > 0);
            }

            // Destroy remaining unused instances:
            for (int i = 0; i < unusedInstances.Count; i++)
            {
                Destroy(unusedInstances[i].gameObject);
            }
            unusedInstances.Clear();
            refreshCoroutine = null;
        }
I'm changing the quest state and the entry state when I pick up the item and it triggers UpdateTracker().
Also, I have to set an entry when I start the conversation or I get no tracking at all. It doesn't show whatsoever if I have 1 entry that doesn't get started right away. If I have no entries it works as normal.

SO basically, if I keep it how it is now, what happens is I get the quest and the tracker opens and shows entry 1. The quest is "active" at this time (Hard Active). When I pick up the item UpdateTracker() is called by Lua as it should and the tracker stays but the title disappears and only shows entry1, not entry2 which should say "return to jerkface", etc. the quest is now "preempted" (Soft Unassigned). My quest entries are set to active and unassigned respectively.

Oh, and I also set the QuestEntryState to preempted in my UpdateTracker function.

Thanks for your previous and any future help.
User avatar
Tony Li
Posts: 22055
Joined: Thu Jul 18, 2013 1:27 pm

Re: Quest Tracker

Post by Tony Li »

Thanks for the details reminders. I'll put together a little example to make sure everything I'm saying it correct. I'll post it here later today.
nivlekius
Posts: 105
Joined: Thu Feb 28, 2019 4:39 pm

Re: Quest Tracker

Post by nivlekius »

Awesome, thanks, Tony. You're the best.
Post Reply