Invector FSM AI and Quest Machine - pause AI character

Announcements, support questions, and discussion for Quest Machine.
Post Reply
mroshaw
Posts: 96
Joined: Wed Jan 19, 2022 4:10 am

Invector FSM AI and Quest Machine - pause AI character

Post by mroshaw »

Hi! I'm absolutely loving Quest Machine, and the integration you provide for Invector is absolutely brilliant and works perfectly.

One thing I'd like to do is use Quest Giver with my patrolling AIs. This works, but when I launch the dialog via `StartDialogWithPlayer`, while my character pauses (thanks to `QuestMachinePausePlayer`), my NPC continues his patrol.

Happy to code around this, but wondered if there were any components that I could attach to my AIs to pause their movement during quest dialog? I've obviously tried `QuestMachinePausePlayer` with no success).

I have also tried creating a new state in my AI FSM ("Converse"), but need an Event on the Quest Giver that I can call to toggle the decision for that state to be selected. I can't see any public Event that I can hook into.

Any ideas?

Thank you!
mroshaw
Posts: 96
Joined: Wed Jan 19, 2022 4:10 am

Re: Invector FSM AI and Quest Machine - pause AI character

Post by mroshaw »

So, I think I sorta answered my own question! I've taken "Quest Machine Pause Player" and created "Quest Machine Pause Npc". I've replaced all of the code with code that simply toggles a boolean on a custom NPC component, subscribing to the same event messages as player. I have a state in my AI FSM called "Converse", that has no action, and is driven by a simple custom Decision that returns the boolean value to the state machine.

So when I start a conversation, the NPC state goes from "Patrol" to "Converse", and when the conversation ends, the state returns to "Patrol".

All working nicely!

EDIT: Ah, so I'm guessing this will put ALL of my NPCs into the "Converse" state! Back to the drawing board!
User avatar
Tony Li
Posts: 22106
Joined: Thu Jul 18, 2013 1:27 pm

Re: Invector FSM AI and Quest Machine - pause AI character

Post by Tony Li »

Hi,

If you only want to stop the NPC that the player is conversing with, make a subclass of QuestGiver and use it on the NPC. Override StartMostRelevantDialogue() and StopDialogue():

Code: Select all

public class InvectorQuestGiver : QuestGiver
{
    protected override void StartMostRelevantDialogue()
    {
        base.StartMostRelevantDialogue();
        // (Pause NPC here)
    }
    
    protected override void StopDialogue() // [EDIT: See follow-up below. Don't use this method]
    {
        base.StopDialogue();
        // (Unpause NPC here)
    }
}

If you really do want all of your NPCs to pause -- for example, to stop shooting at the player during dialogue -- then see below:
Pause all NPCs
The default Quest Dialogue UI prefab sends the messages "Pause Player" when dialogue starts and "Unpause Player" when dialogue ends. This uses Quest Machine's Message System.

You can add a script to your patrolling AIs that listen for these messages by implementing IMessageHandler. Rough example:

Code: Select all

using UnityEngine;
using PixelCrushers;
public class PauseAIDuringDialogue : MonoBehaviour, IMessageHandler
{
    void OnEnable()
    {
        MessageSystem.AddListener(this, "Pause Player", string.Empty);
        MessageSystem.AddListener(this, "Unpause Player", string.Empty);
    }
    
    void OnDisable()
    {
        MessageSystem.RemoveListener(this);
    }
    
    void OnMessage(MessageArgs messageArgs)
    {
        switch (messageArgs.message)
        {
            case "Pause Player":
                // (Your code here to pause AI)
                break;
            case "Unpause Player":
                // (Your code here to unpause AI)
                break;            
        }
    }
}
mroshaw
Posts: 96
Joined: Wed Jan 19, 2022 4:10 am

Re: Invector FSM AI and Quest Machine - pause AI character

Post by mroshaw »

Wow, what an amazing response! Thanks Tony!
mroshaw
Posts: 96
Joined: Wed Jan 19, 2022 4:10 am

Re: Invector FSM AI and Quest Machine - pause AI character

Post by mroshaw »

This works great with

Code: Select all

StartMostRelevantDialogue
, but

Code: Select all

StopDialogue
doesn't seem to get invoked, whichever way I close the dialog.

I had to tweak your code a little, replacing "protected" for "public", though not sure that's the problem:

Code: Select all

public override void StopDialogue()
{
    _npc.isInConversation = false;
    base.StopDialogue();
}
User avatar
Tony Li
Posts: 22106
Joined: Thu Jul 18, 2013 1:27 pm

Re: Invector FSM AI and Quest Machine - pause AI character

Post by Tony Li »

Sorry about that. StopDialogue() is used to manually interrupt a dialogue before it finishes normally.

Instead, adjust your subclass to do something like this, which uses the message system to listen for the message "Unpause Player" that the dialogue UI sends when closing.

Code: Select all

using PixelCrushers;
using PixelCrushers.QuestMachine;

public class InvectorQuestGiver : QuestGiver
{
    protected override void StartMostRelevantDialogue()
    {
        base.StartMostRelevantDialogue();
        MessageSystem.AddListener(this, "Unpause Player", string.Empty);
        // Pause NPC here
    }

    public override void OnMessage(MessageArgs messageArgs)
    {
        if (messageArgs.message == "Unpause Player")
        {
            // Unpause NPC here
            MessageSystem.RemoveListener(this, "Unpause Player", string.Empty);
        }
        base.OnMessage(messageArgs);
    }

    // Clean up just in case we disable the quest giver before receiving "Unpause Player":
    public override void OnDisable()
    {
        base.OnDisable();
        MessageSystem.RemoveListener(this, "Unpause Player", string.Empty);
    }
}
mroshaw
Posts: 96
Joined: Wed Jan 19, 2022 4:10 am

Re: Invector FSM AI and Quest Machine - pause AI character

Post by mroshaw »

Perfect Tony, that works a treat!
User avatar
Tony Li
Posts: 22106
Joined: Thu Jul 18, 2013 1:27 pm

Re: Invector FSM AI and Quest Machine - pause AI character

Post by Tony Li »

Glad to help!
Lorcan77
Posts: 2
Joined: Sun Jan 14, 2024 4:45 am

Re: Invector FSM AI and Quest Machine - pause AI character

Post by Lorcan77 »

mroshaw wrote: Sat Jan 22, 2022 12:13 pm So, I think I sorta answered my own question! I've taken "Quest Machine Pause Player" and created "Quest Machine Pause Npc". I've replaced all of the code with code that simply toggles a boolean on a custom NPC component, subscribing to the same event messages as player. I have a state in my AI FSM called "Converse", that has no action, and is driven by a simple custom Decision that returns the boolean value to the state machine.

So when I start a conversation, the NPC state goes from "Patrol" to "Converse", and when the conversation ends, the state returns to "Patrol".

All working nicely!

EDIT: Ah, so I'm guessing this will put ALL of my NPCs into the "Converse" state! Back to the drawing board!
It sounds like you've made some progress in customizing NPC behavior for conversations. However, as you've noted, your current approach would indeed affect all NPCs uniformly. Magic 8 Ball
Post Reply