283 lines
10 KiB (Stored with Git LFS)
C#
283 lines
10 KiB (Stored with Git LFS)
C#
// Copyright (c) Pixel Crushers. All rights reserved.
|
|
|
|
using UnityEngine;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
|
|
namespace PixelCrushers.DialogueSystem
|
|
{
|
|
|
|
/// <summary>
|
|
/// When you attach this script to the Dialogue Manager object (or a child),
|
|
/// it will display tracked quests using the new Unity UI. It updates when the player
|
|
/// toggles tracking in the quest log window and at the end of conversations. If you
|
|
/// change the state of a quest elsewhere, you must manually call UpdateTracker().
|
|
/// </summary>
|
|
[AddComponentMenu("")] // Use wrapper.
|
|
public class UnityUIQuestTracker : MonoBehaviour
|
|
{
|
|
|
|
[Tooltip("Record the quest tracker display toggle in this PlayerPrefs key.")]
|
|
public string playerPrefsToggleKey = "QuestTracker";
|
|
|
|
/// <summary>
|
|
/// The UI control that will hold quest track info (instantiated copies of the
|
|
/// quest track template). This is typically a Vertical Layout Group.
|
|
/// </summary>
|
|
[Tooltip("UI container that will hold instances of quest track template.")]
|
|
public Transform container;
|
|
|
|
/// <summary>
|
|
/// Tick to show the container even if there's nothing to track.
|
|
/// </summary>
|
|
[Tooltip("Show Container even if there's nothing to track.")]
|
|
public bool showContainerIfEmpty = true;
|
|
|
|
/// <summary>
|
|
/// The quest track template.
|
|
/// </summary>
|
|
[Tooltip("Template to instantiate for each tracked quest.")]
|
|
public UnityUIQuestTrackTemplate questTrackTemplate;
|
|
|
|
/// <summary>
|
|
/// Tick to show active quests in the tracker.
|
|
/// </summary>
|
|
[Tooltip("Show active quests.")]
|
|
public bool showActiveQuests = true;
|
|
|
|
/// <summary>
|
|
/// Tick to show successful and failed quests in the tracker.
|
|
/// </summary>
|
|
[Tooltip("Show successful and failed quests.")]
|
|
public bool showCompletedQuests = false;
|
|
|
|
/// <summary>
|
|
/// Tick to look up "Entry n Success" or "Entry n Failure" if the
|
|
/// quest entry is in the success or failure state.
|
|
/// </summary>
|
|
[Tooltip("Show Entry n Success or Entry n Failure text if quest entry is in success/failure state.")]
|
|
public bool showCompletedEntryText = false;
|
|
|
|
public enum QuestDescriptionSource { Title, Description }
|
|
|
|
[Tooltip("Source for the quest tracker text.")]
|
|
public QuestDescriptionSource questDescriptionSource = QuestDescriptionSource.Title;
|
|
|
|
public bool visibleOnStart = true;
|
|
|
|
protected List<UnityUIQuestTrackTemplate> instantiatedItems = new List<UnityUIQuestTrackTemplate>();
|
|
|
|
protected List<UnityUIQuestTrackTemplate> unusedInstances = new List<UnityUIQuestTrackTemplate>();
|
|
|
|
protected int siblingIndexCounter = 0;
|
|
|
|
protected bool isVisible = true;
|
|
|
|
protected Coroutine refreshCoroutine = null;
|
|
|
|
/// <summary>
|
|
/// Wait 0.5s to update the tracker in case other start
|
|
/// methods change the state of quests.
|
|
/// </summary>
|
|
public virtual void Start()
|
|
{
|
|
isVisible = PlayerPrefs.GetInt(playerPrefsToggleKey, visibleOnStart ? 1 : 0) == 1;
|
|
if (container == null) Debug.LogWarning(string.Format("{0}: {1} Container is unassigned", new object[] { DialogueDebug.Prefix, name }));
|
|
if (questTrackTemplate == null)
|
|
{
|
|
Debug.LogWarning(string.Format("{0}: {1} Quest Track Template is unassigned", new object[] { DialogueDebug.Prefix, name }));
|
|
}
|
|
else
|
|
{
|
|
questTrackTemplate.gameObject.SetActive(false);
|
|
}
|
|
if (isVisible)
|
|
{
|
|
Invoke("UpdateTracker", 0.5f);
|
|
}
|
|
else
|
|
{
|
|
HideTracker();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Shows the quest tracker HUD.
|
|
/// </summary>
|
|
public virtual void ShowTracker()
|
|
{
|
|
isVisible = true;
|
|
PlayerPrefs.SetInt(playerPrefsToggleKey, 1);
|
|
if (container != null) container.gameObject.SetActive(true);
|
|
UpdateTracker();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Hides the quest tracker HUD entirely.
|
|
/// </summary>
|
|
public virtual void HideTracker()
|
|
{
|
|
isVisible = false;
|
|
PlayerPrefs.SetInt(playerPrefsToggleKey, 0);
|
|
if (container != null) container.gameObject.SetActive(false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Toggles the quest tracker HUD visibility.
|
|
/// </summary>
|
|
public virtual void ToggleTracker()
|
|
{
|
|
if (isVisible) HideTracker(); else ShowTracker();
|
|
}
|
|
|
|
/// <summary>
|
|
/// The quest log window sends this message when the player toggles tracking.
|
|
/// </summary>
|
|
/// <param name="quest">Quest.</param>
|
|
public virtual void OnQuestTrackingEnabled(string quest)
|
|
{
|
|
UpdateTracker();
|
|
}
|
|
|
|
/// <summary>
|
|
/// The quest log window sends this message when the player toggles tracking.
|
|
/// </summary>
|
|
/// <param name="quest">Quest.</param>
|
|
public virtual void OnQuestTrackingDisabled(string quest)
|
|
{
|
|
UpdateTracker();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Quests are often completed in conversations. This handles changes in quest states
|
|
/// after conversations.
|
|
/// </summary>
|
|
/// <param name="actor">Actor.</param>
|
|
public void OnConversationEnd(Transform actor)
|
|
{
|
|
UpdateTracker();
|
|
}
|
|
|
|
public virtual void UpdateTracker()
|
|
{
|
|
if (!isVisible) return;
|
|
if (refreshCoroutine == null)
|
|
{
|
|
refreshCoroutine = StartCoroutine(RefreshAtEndOfFrame());
|
|
}
|
|
}
|
|
|
|
protected virtual IEnumerator RefreshAtEndOfFrame()
|
|
{
|
|
yield return CoroutineUtility.endOfFrame;
|
|
|
|
// 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);
|
|
foreach (string quest in QuestLog.GetAllQuests(flags))
|
|
{
|
|
if (QuestLog.IsQuestTrackingEnabled(quest))
|
|
{
|
|
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;
|
|
}
|
|
|
|
protected virtual void AddQuestTrack(string quest)
|
|
{
|
|
if (container == null || questTrackTemplate == null) return;
|
|
|
|
var questDescription = (questDescriptionSource == QuestDescriptionSource.Title)
|
|
? QuestLog.GetQuestTitle(quest)
|
|
: QuestLog.GetQuestDescription(quest);
|
|
var heading = FormattedText.Parse(questDescription, DialogueManager.masterDatabase.emphasisSettings).text;
|
|
|
|
GameObject go;
|
|
if (unusedInstances.Count > 0)
|
|
{
|
|
// Try to use an unused instance:
|
|
go = unusedInstances[0].gameObject;
|
|
unusedInstances.RemoveAt(0);
|
|
}
|
|
else
|
|
{
|
|
// Otherwise instantiate one:
|
|
go = Instantiate(questTrackTemplate.gameObject) as GameObject;
|
|
if (go == null)
|
|
{
|
|
Debug.LogError(string.Format("{0}: {1} couldn't instantiate quest track template", new object[] { DialogueDebug.Prefix, name }));
|
|
return;
|
|
}
|
|
}
|
|
|
|
go.name = heading;
|
|
go.transform.SetParent(container.transform, false);
|
|
go.SetActive(true);
|
|
var questTrack = go.GetComponent<UnityUIQuestTrackTemplate>();
|
|
instantiatedItems.Add(questTrack);
|
|
if (questTrack != null)
|
|
{
|
|
questTrack.Initialize();
|
|
var questState = QuestLog.GetQuestState(quest);
|
|
questTrack.SetDescription(heading, questState);
|
|
int entryCount = QuestLog.GetQuestEntryCount(quest);
|
|
for (int i = 1; i <= entryCount; i++)
|
|
{
|
|
var entryState = QuestLog.GetQuestEntryState(quest, i);
|
|
var entryText = FormattedText.Parse(GetQuestEntryText(quest, i, entryState), DialogueManager.masterDatabase.emphasisSettings).text;
|
|
if (!string.IsNullOrEmpty(entryText))
|
|
{
|
|
questTrack.AddEntryDescription(entryText, entryState);
|
|
}
|
|
}
|
|
|
|
questTrack.transform.SetSiblingIndex(siblingIndexCounter++);
|
|
}
|
|
}
|
|
|
|
protected virtual 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)
|
|
{
|
|
var text = DialogueLua.GetQuestField(quest, "Entry " + entryNum + " Success").asString;
|
|
if (!string.IsNullOrEmpty(text)) return text;
|
|
}
|
|
else if (entryState == QuestState.Failure)
|
|
{
|
|
var text = DialogueLua.GetQuestField(quest, "Entry " + entryNum + " Failure").asString;
|
|
if (!string.IsNullOrEmpty(text)) return text;
|
|
}
|
|
return QuestLog.GetQuestEntry(quest, entryNum);
|
|
}
|
|
|
|
}
|
|
|
|
}
|