Custom Quest Actions

Announcements, support questions, and discussion for Quest Machine.
GorkaGames
Posts: 178
Joined: Fri Sep 21, 2018 8:38 pm

Re: Custom Quest Actions

Post by GorkaGames »

awesome...
GorkaGames
Posts: 178
Joined: Fri Sep 21, 2018 8:38 pm

Re: Custom Quest Actions

Post by GorkaGames »

Any event I can call to refresh the UI (example HUD) everytime some of the counters I want get updated?
Thanks
User avatar
Tony Li
Posts: 22143
Joined: Thu Jul 18, 2013 1:27 pm

Re: Custom Quest Actions

Post by Tony Li »

Yes, QuestMachineMessages.RefreshUIs().
GorkaGames
Posts: 178
Joined: Fri Sep 21, 2018 8:38 pm

Re: Custom Quest Actions

Post by GorkaGames »

yes sure, but i refer how do we suscribe to the Listener / event?

MessageSystem.AddListener(this, QuestMachineMessages.QuestCounterChangedMessage, questString);

Maybe?

One More thing: Counters do't refresh in real time in the editor Journal (runtime:Active) do they?

And...last one...is it possible to write on the UI from my script with this special tags so the counters got refresh?
{#EnemyFloodedWaves} / {>#EnemyFloodedWaves

I have tried but it shows like that and it doesn't convert.
User avatar
Tony Li
Posts: 22143
Joined: Thu Jul 18, 2013 1:27 pm

Re: Custom Quest Actions

Post by Tony Li »

Hi,
GorkaGames wrote: Tue Feb 19, 2019 6:26 pmyes sure, but i refer how do we suscribe to the Listener / event?

MessageSystem.AddListener(this, QuestMachineMessages.QuestCounterChangedMessage, questString);

Maybe?
Yes. The UIs already subscribe to the event. If you have an additional UI of your own, you can subscribe to it like that. The QuestMachineMessages API page explains what values Quest Machine send with each message.

For QuestCounterChangedMessage, they are:
  • parameter: Quest ID
  • values[0]: Counter name (type: StringField)
  • values[1]: New value (type: int)
GorkaGames wrote: Tue Feb 19, 2019 6:26 pmOne More thing: Counters do't refresh in real time in the editor Journal (runtime:Active) do they?
Yes. They refresh in the Unity editor's Inspector view, and they refresh in the gameplay Quest Journal UI.
GorkaGames wrote: Tue Feb 19, 2019 6:26 pmAnd...last one...is it possible to write on the UI from my script with this special tags so the counters got refresh?
{#EnemyFloodedWaves} / {>#EnemyFloodedWaves

I have tried but it shows like that and it doesn't convert.
If you're writing a new QuestContent type, override the originalText field.

For example, BodyTextQuestContent overrides originalText to map it to its bodyText property.

QuestContent's runtimeText property returns a copy of originalText in which the tags have been replaced by their current values.

If you don't use originalText and runtimeText, you can always manually replace the tags with their values:

Code: Select all

string preparedText = QuestMachineTags.ReplaceTags(text, quest);
Also, make sure your counter tags (such as {#EnemyFloodedWaves}) match counter names in your quest.
GorkaGames
Posts: 178
Joined: Fri Sep 21, 2018 8:38 pm

Re: Custom Quest Actions

Post by GorkaGames »

ok, thanks very much for your awesome support, but for me it's a bit complicated the tag thing :)

I'm calling this from my custom Quest Action that you helped me yesterday to code.

And what I want it, it's to write in the Hud: "Chests: 0 of 7" and that it refresh every time the counter updates.
So now i have:
content1.bodyText = new StringField("Chests: " + quest.GetCounter(CounterName).currentValue + " / " + quest.GetCounter(CounterName).maxValue);

But this only works once as it doesn't refresh (I guess because Execute only executes once by design)

So I may need to change to:
//content.bodyText = new StringField("Chests: " + "{#Flooded2_Chests1} / {>#Flooded2_Chests1}");

But this it doesn't work as it shows the literal tags instead of the value inside the tags.
So how do I need to write this line so it gets on the Hud and refresh automatically?

Thanks! (I leave here the code just in case it's more clear for you)
And I leave you here a screenshot of the HUD and Dialogue:

https://1drv.ms/u/s!AgOs7p5LnVflkMAfksqndaIQpk_1vw



using UnityEngine;
using System;

namespace PixelCrushers.QuestMachine
{
public class ChestQuestAction : QuestAction, PixelCrushers.IMessageHandler
{

public string QuestParameterMessage = "IMPORTANTE: A rellenar, mismo que en el Prefab";
public string CounterName;
private string QuestMessageToActivate = "ActivateChest";
private string QuestMessageOpened = "ChestOpened";
private string QuestMessageToDeativated = "ChestDeativated";
private Quest questActual;
private QuestNode questNodeActual;
private string questString;

public EstadoChest EstadoChestAPoner = EstadoChest.Cerrado;

public bool isVisible => throw new NotImplementedException();

public override void Execute()
{
base.Execute();
// Add your code here. This code will run when the action runs.

switch (EstadoChestAPoner)
{
case EstadoChest.Cerrado:
//Envia mensaje para activar el chest (cerrado)
PixelCrushers.MessageSystem.SendMessage(this, QuestMessageToActivate, QuestParameterMessage);


break;
case EstadoChest.Bloqueado:
//Envia mensaje para desactivar el chest, no se utiliza mucho
PixelCrushers.MessageSystem.SendMessage(this, QuestMessageToDeativated, QuestParameterMessage); //No se utiliza mucho
break;
}

UpdateUI();

// Nos suscribimos a los mensajes de Quest Machine
MessageSystem.AddListener(this, QuestMachineMessages.QuestCounterChangedMessage, questString);
}

private void UpdateUI()
{
//Obtiene la quest donde estamos
questActual = this.quest;
questString = questActual.ToString();
//Obtiene el Nodo donde estamos
questNodeActual = this.questNode;
//Obtiene el estado del Nodo donde estamos
var stateInfo = questNode.GetStateInfo(QuestNodeState.Active);
// get the content list for a specific category
var hudContentList = stateInfo.GetContentList(QuestContentCategory.HUD);
var journalContentList = stateInfo.GetContentList(QuestContentCategory.Journal);
var dialogueContentList = stateInfo.GetContentList(QuestContentCategory.Dialogue);
var alertContentList = stateInfo.GetContentList(QuestContentCategory.Alert);

var content = BodyTextQuestContent.CreateInstance<BodyTextQuestContent>();
var content1 = BodyTextQuestContent.CreateInstance<BodyTextQuestContent>();

content.bodyText = new StringField("Now go find the chest");

if (quest.GetCounter(CounterName) != null)
{
content1.bodyText = new StringField("Chests: " + quest.GetCounter(CounterName).currentValue + " / " + quest.GetCounter(CounterName).maxValue);
//content.bodyText = new StringField("Chests: " + "{#Flooded2_Chests1} / {>#Flooded2_Chests1}");
}

if (hudContentList != null) hudContentList.Add(content);
if (hudContentList != null) hudContentList.Add(content1);

if (journalContentList != null) journalContentList.Add(content);
if (dialogueContentList != null) dialogueContentList.Add(content);
if (alertContentList != null) alertContentList.Add(content);
//Refresca los UIs
QuestMachineMessages.RefreshUIs(this);
//Envia al manager de UI Quest los datos de esta quest para que se pueda suscribir a refrescar el UI cuando cambian los contadores.
//if (QuestUIManager.instance != null) QuestUIManager.instance.RecibeInfoQuestNode(quest, questNode, CounterName);

}

public void OnMessage(MessageArgs messageArgs)
{
if (messageArgs.message == QuestMachineMessages.QuestCounterChangedMessage)
{
Debug.Log("Recibimos mensaje de counter change");
//Refrescamos los UIs (Journal, Hud, Dialogues, etc...)
QuestMachineMessages.RefreshUIs(this);
}
}
}

}
GorkaGames
Posts: 178
Joined: Fri Sep 21, 2018 8:38 pm

Re: Custom Quest Actions

Post by GorkaGames »

Any Feedback on this? (I'm just working right now on this....:)
Thanks!
User avatar
Tony Li
Posts: 22143
Joined: Thu Jul 18, 2013 1:27 pm

Re: Custom Quest Actions

Post by Tony Li »

I've set up a reproduction case, and I'm investigating now.
User avatar
Tony Li
Posts: 22143
Joined: Thu Jul 18, 2013 1:27 pm

Re: Custom Quest Actions

Post by Tony Li »

Add these lines:

Code: Select all

content.SetRuntimeReferences(quest, node);
content1.SetRuntimeReferences(quest, node);
content1.AddTagsToDictionary();
Note: Since Actions run when a node becomes True, I didn't use the action's questNode property. Instead, I used quest.GetNode() to get the next node, like this:

Code: Select all

QuestNode node = quest.GetNode("getChests");
The SetRuntimeReferences() method initializes internal references. Normally the quest does this automatically. But since you're adding new content at runtime, you need to call it manually.

You don't really need AddTagsToDictionary() unless you're using new tags that aren't used anywhere else in the quest.
GorkaGames
Posts: 178
Joined: Fri Sep 21, 2018 8:38 pm

Re: Custom Quest Actions

Post by GorkaGames »

It works! Thanks very much, but even works with: questNodeActual = this.questNode; so I don't have to look for the next node as you mentioned (easier :)

And thanks for your time!
Post Reply