event OnQuestStatusChanged(string quest, QuestStatus status)?

Announcements, support questions, and discussion for the Dialogue System.
alfonso
Posts: 104
Joined: Mon Jul 13, 2015 6:31 am

event OnQuestStatusChanged(string quest, QuestStatus status)?

Post by alfonso »

Hi Tony!

i have some objects disabled at the start of the scene and need to enable when a quest changed the state. At the start of the scene is not a problem, the problem is how track the quest state changed while the scene is playing and a event like the title will be great :)

exist any event like that?

Thanks
User avatar
Tony Li
Posts: 22104
Joined: Thu Jul 18, 2013 1:27 pm

Re: event OnQuestStatusChanged(string quest, QuestStatus status)?

Post by Tony Li »

Hi Alfonso!

It depends on how you change the quest state.

If you change it with a trigger such as Dialogue System Trigger, you can configure the trigger to show an alert message, send a message to another GameObject, etc.

If you change the quest state during a conversation, you can use the Script field to set Variable["Alert"]. This will show an alert message when the conversation is done. For example:
Script:

Code: Select all

Quest["Escape"].State = "success";
Variable["Alert"] = "You escaped the dungeon!"
You can also use the SetActive() sequencer command to activate GameObjects. For example, say you want to activate a GameObject named "ratSpawner":
Sequence:

Code: Select all

SetActive(ratSpawner)
You can also register one of your C# methods as a Lua function and call it in the Script field:
Script:

Code: Select all

ActivateQuest("Kill 5 Rats", "ratSpawner");
And your C# method:

Code: Select all

void ActivateQuest(string title, string gameObjectToActivate) {
    QuestLog.StartQuest(title);
    Tools.GameObjectHardFind(gameObjectToActivate).SetActive(true);
    DialogueManager.ShowAlert("New Quest: " + title);
}


You can also use a Condition Observer or Quest State Observer. These are polling methods, which means they run on a regular frequency, so they're not necessarily as efficient as the other methods above.

Condition Observer is a component. You can set it to check every 1 second, for example. It can check the quest state. When it changes to a specific value, it can run actions such as showing alert messages, etc.

QuestLog.SetQuestStateObserver() is a method. It registers a C# method that will be called when the quest state changes. But it only checks for quest state changes at specified times: every Update(), every dialogue entry, or only at the end of conversations. For example:

Code: Select all

QuestLog.AddQuestStateObserver("Kill 5 Rats", LuaWatchFrequency.EndOfConversation, OnQuestStateChanged);
 
void OnQuestStateChanged(string title, QuestState newState) {
    if (string.Equals(title, "Kill 5 Rats") && (newState == QuestState.Active)) {
        ratSpawner.SetActive(true);
    }
}
alfonso
Posts: 104
Joined: Mon Jul 13, 2015 6:31 am

Re: event OnQuestStatusChanged(string quest, QuestStatus status)?

Post by alfonso »

woo men this is so long :) thanks i try to explain my idea

my idea was that each object in the scene was "aware" about the quest state he is watching. and if i need to change some behaviour on a object go to the object instead each conversation node looking for where i change it.

for that i made a QuestTrackerObject is the base of each component how need any behaviour on a quest changed.

Code: Select all

public class QuestTrackerObject: MonoBehaviour 
{
	[QuestPopup] public string quest;

	public virtual void Execute(){ }
}
for example i have a tv with an animator, if quets is active show the animation "Alert" and if is success show the animation "Done".
so i can extend this base clase an create QuestTrackerAnimator and attach to the tv.

Code: Select all

[AddComponentMenu("QuestTracker/Animator")]
public class QuestTrackerAnimator : QuestTrackerObject
{
	public AnimatorStringTuple[] objects;

	public override void Execute ()
	{
		foreach(AnimatorStringTuple o in objects)
		{
			if(o.Item1 == QuestLog.GetQuestState(quest))
			{
				this.GetComponent<Animator> ().Play (o.Item2);
			}
		}
	}
	[System.Serializable]
	public class AnimatorStringTuple : Tuple<QuestState, string> {}
other example, and the 90% of the case, is active o disable a gamebject according to the state of a quest. the problem is if the gameobject is disable the sendMenssage dont work so i need a reference of the gameObject to call the SetActive(bool) method.

Code: Select all

[AddComponentMenu("QuestTracker/ GameObject")]
public class QuestTrackerGameObject : QuestTrackerObject {
	public GameObjectBoolTuple[] objects;

	public override void Execute ()
	{
		foreach(GameObjectBoolTuple o in objects)
		{
			if(o.Item1 == QuestLog.GetQuestState(quest))
			{
				this.gameObject.SetActive (o.Item2);
			}
		}
	}
	[System.Serializable]
	public class GameObjectBoolTuple : Tuple<QuestState, bool> {}
}
for now i only need this two ones but if i need another one i can easily extent to the base clase and put the behaviour desired.

then only need someone how tell to all this components that a quest was changed, for that i have a QuestTrackerController

Code: Select all

public class TestQuestObjectController : MonoBehaviour 
{

	QuestTrackerObject[] questObjects;
	//every time we goes to a new scene update behaviour.
	public void OnLevelWasLoaded()
	{
		//cache of all objects at start of each new scene.
		questObjects = Resources.FindObjectsOfTypeAll (typeof(QuestTrackerObject)) as QuestTrackerObject[];
		OnQuestChanged ();
	}
	public void OnQuestChanged()
	{
		for(int i = 0; i<questObjects.Length; i++)
		{
			questObjects[i].Execute ();
		}
	}
}
if i change any quest status and call OnQuestChanged any Object who was watching the quest will update their visibility or their animatior. this is why i wanted the event, but i can create my own script to update the state of a quest and call the OnQuestChanged of QuestTrackerController.

by the way any advice in the code or improve will be great :)
User avatar
Tony Li
Posts: 22104
Joined: Thu Jul 18, 2013 1:27 pm

Re: event OnQuestStatusChanged(string quest, QuestStatus status)?

Post by Tony Li »

That should work fine.

The problem is that quest states are just strings. As you said, you can create your own script to update quest states. For example, you could add this to TestQuestObjectController:

Code: Select all

public void SetQuestState(string questTitle, string state) {
    QuestLog.SetQuestState(questTitle, QuestLog.StringToState(state));
    OnQuestChanged();
}

void Start() {
    // Register the function above with Lua:
    Lua.RegisterFunction("SetQuestState", null, SymbolExtensions.GetMethodInfo(() => SetQuestState(string.Empty, string.Empty)));
}
When you change a quest state in code, use TestQuestObjectController.SetQuestState(). For example:

Code: Select all

FindObjectOfType<TestQuestObjectController>().SetQuestState("Kill 5 Rats", "success");
When you change a quest state in a conversation, use Lua to call SetQuestState() in the dialogue entry's Script field. For example:
  • Script: SetQuestState("Kill 5 Rats", "success");
If you use a trigger component such as Dialogue System Trigger to change the quest state, you can use its Send Message section to send the message "OnQuestChanged" to TestQuestObjectController.
alfonso
Posts: 104
Joined: Mon Jul 13, 2015 6:31 am

Re: event OnQuestStatusChanged(string quest, QuestStatus status)?

Post by alfonso »

yes this will be work so well for me :)

thanks you for the help :)
User avatar
Tony Li
Posts: 22104
Joined: Thu Jul 18, 2013 1:27 pm

Re: event OnQuestStatusChanged(string quest, QuestStatus status)?

Post by Tony Li »

My pleasure!
alfonso
Posts: 104
Joined: Mon Jul 13, 2015 6:31 am

Re: event OnQuestStatusChanged(string quest, QuestStatus status)?

Post by alfonso »

mmmm i am receiving an error, it seem that the target cant go to null in the lua register, whats is the target in this context?

Code: Select all

Dialogue System: Lua code 'SetQuestState("Quest1","active");' threw exception 'Non-static method requires a target.'
UnityEngine.Debug:LogError(Object)
EDIT: i think i fixed passing "this" as target, (/// <param name='target'> Target object containing the registered method. Can be <c>null</c> if a static method.) but if i set the quest state in a script work while the dialogue is open, when i press X and call OnContinue, change the state T_T
User avatar
Tony Li
Posts: 22104
Joined: Thu Jul 18, 2013 1:27 pm

Re: event OnQuestStatusChanged(string quest, QuestStatus status)?

Post by Tony Li »

Sorry, I cut and pasted without testing. I'm glad it wasn't too hard to fix.
alfonso wrote:...but if i set the quest state in a script work while the dialogue is open, when i press X and call OnContinue, change the state T_T
I don't understand. Is it working the way you want it to work?
alfonso
Posts: 104
Joined: Mon Jul 13, 2015 6:31 am

Re: event OnQuestStatusChanged(string quest, QuestStatus status)?

Post by alfonso »

not at all

i start the quest with unnasigned state and i have a npc for test with two options (first change the quest to active and the second to success) if i select any of them the quest change well but when i finish the dialogue the quest goes to unnasigned again.

EDIT: i tried with Quest["Quest1"].State = "success" in the script field of the node and i have same issue, it look like that when i press the OnContinue button and close the dialogue it reset the value to default.

i tried to put to the quest other default start value (active) and when i choose the option to put to success, change fine, but when i close the dialogue goes to unnasigned.
User avatar
Tony Li
Posts: 22104
Joined: Thu Jul 18, 2013 1:27 pm

Re: event OnQuestStatusChanged(string quest, QuestStatus status)?

Post by Tony Li »

That's very strange. Do you have a Set Quest State On Dialogue Event component that's resetting the quest state? Or maybe another script somewhere that's resetting it? Or is another dialogue entry setting it back?

While playing, open the Dialogue Editor. On the Watch tab, add a Lua watch for your quest:

Code: Select all

Quest["Your Quest Name"].State
Tick Auto-Update. Then keep an eye on the quest state while you go through the conversation. Maybe it will help pinpoint when the quest is being reset.
Post Reply