Custom quest condition not being checked for next quest's node.

Announcements, support questions, and discussion for Quest Machine.
Post Reply
CatStrategist
Posts: 2
Joined: Thu Jul 18, 2024 8:33 am

Custom quest condition not being checked for next quest's node.

Post by CatStrategist »

I have a simple quest with:
1. Start node
2. Condition node
3. Success node

I have applied my custom condition to quest autostart, it works great - starts my quest and transitions to Conditon node.
Now I've applied the same condition to my condition node and it seems to never be checked as if StartChecking() is never run and the quest is stuck in condition node.

My custom condition:

Code: Select all

using System.Collections.Generic;
using PixelCrushers.QuestMachine;
using UnityEngine;

public class ItemCountQuestCondition : QuestCondition {
    public ItemDescription itemType;

    public CounterValueConditionMode comparison = CounterValueConditionMode.AtLeast;

    public QuestNumber requiredValue = new QuestNumber();

    public override string GetEditorName() {
        return "Inventory has " + comparison + " " + requiredValue.GetValue(quest) + " " + itemType;
    }

    public override void StartChecking(System.Action trueAction) {
        base.StartChecking(trueAction);

        if (IsTrue()) {
            SetTrue();
        } else {
            Inventory.ItemAdded += Inventory_OnChange;
            Inventory.ItemRemoved += Inventory_OnChange;
        }
    }

    public override void StopChecking() {
        base.StopChecking();
    }

    private void Inventory_OnChange(Inventory i, InventoryItem item, int quantity) {
        if (IsTrue()) {
            SetTrue();
            Debug.Log("Item count condition is true");
        }
    }

    private bool IsTrue() {
        List<Unit> playersUnits = GameActors.Instance.PlayerActor.units;

        foreach (Unit unit in playersUnits) {
            Inventory inventory = unit.GetInventory();

            if (inventory == null) {
                continue;
            }

            InventoryItem item = inventory.TryGetItem(itemType);

            if (item == null) {
                continue;
            };

            switch (comparison) {
                case CounterValueConditionMode.AtLeast:
                    if (item.quantity >= requiredValue.GetValue(quest)) return true;
                    break;
                case CounterValueConditionMode.AtMost:
                    if (item.quantity <= requiredValue.GetValue(quest)) return true;
                    break;
            }
        }

        return false;
    }
}
Attachments
Unity_h9tGHphScZ.png
Unity_h9tGHphScZ.png (22.4 KiB) Viewed 1147 times
Unity_IHX0VxXj1g.png
Unity_IHX0VxXj1g.png (61.46 KiB) Viewed 1147 times
Unity_6FKhyvT2NQ.png
Unity_6FKhyvT2NQ.png (23.42 KiB) Viewed 1147 times
User avatar
Tony Li
Posts: 22091
Joined: Thu Jul 18, 2013 1:27 pm

Re: Custom quest condition not being checked for next quest's node.

Post by Tony Li »

Hi,

What version of Quest Machine are you using? (Can you back up your project and update to the current version if you're on an older version?)

Are there any errors or warnings in the Console window?

In StopChecking, make sure to unregister from your Inventory.ItemAdded & ItemRemoved events. Otherwise it could cause an error that would prevent subsequently-added handlers (such as your Condition node) from receiving the event.

Consider adding some temporary Debug.Log() lines to your custom condition to log when you hook into and out of Inventory.ItemAdded and ItemRemoved. You can print out quest.id and/or questNode.id with those Debug.Log() lines.
CatStrategist
Posts: 2
Joined: Thu Jul 18, 2024 8:33 am

Re: Custom quest condition not being checked for next quest's node.

Post by CatStrategist »

Edit:
I removed and added again a faulty node, configured it the same way and it seems to be working now.
I reverted changes to broken quest state, I am attaching it just in case you are curious what might be broken, maybe it will help you debug and make a fix :)

Anyway, thanks for help, I am good now.


Hello,
- Quest Machine version: 1.2.47, also using Dialogue System version 2.2.47 with integration installed.
- No errors or warnings (with Quest Machine debug turned on)
- Added unsubscribing events to StopChecking()
- Added Debug.Log()s, they seem to be executed correctly for Autostart condition, but not a single log is called for the second condition, StartChecking() is never called.

Logs are called in following order for autostart condition, never for second node:
1. StopChecking()
2. StartChecking(), initializing listeners
3. Once item is picked up, listener is called, setting condition to true
4. StopChecking() is called twice

First StopChecking() stack trace:

Code: Select all

[Pistol] StopChecking()
UnityEngine.Debug:Log (object)
ItemCountQuestCondition:StopChecking () (at Assets/Modules/Quests/ItemCountQuestCondition.cs:32)
PixelCrushers.QuestMachine.QuestCondition:SetTrue () (at Assets/_Assets/Pixel Crushers/Quest Machine/Scripts/Quest/Quest Subasset/Quest Condition/QuestCondition.cs:74)
ItemCountQuestCondition:Inventory_OnChange (Inventory,InventoryItem,int) (at Assets/Modules/Quests/ItemCountQuestCondition.cs:41)
Inventory:InsertItem (ItemDescription,int) (at Assets/Modules/InventorySystem/Inventory.cs:33)
Inventory:AddItem (ItemDescription,int) (at Assets/Modules/InventorySystem/Inventory.cs:21)
InventoryTradeHandler:OnItemClick (Inventory,InventoryItem) (at Assets/Modules/InventorySystem/InventoryHandlers/InventoryTradeHandler.cs:27)
InventoryTradeHandler:<.ctor>b__1_0 (Inventory,InventoryItem) (at Assets/Modules/InventorySystem/InventoryHandlers/InventoryTradeHandler.cs:12)
InventoryUIController:<RenderInventory>b__8_0 (InventoryItem) (at Assets/Modules/InventorySystem/UI/InventoryUIController.cs:41)
ItemUIController:<Init>b__5_0 () (at Assets/Modules/InventorySystem/UI/ItemUIController.cs:24)
UnityEngine.EventSystems.EventSystem:Update () (at ./Library/PackageCache/com.unity.ugui@2.0.0/Runtime/UGUI/EventSystem/EventSystem.cs:530)
Second StopChecking() stack trace:

Code: Select all

[Pistol] StopChecking()
UnityEngine.Debug:Log (object)
ItemCountQuestCondition:StopChecking () (at Assets/Modules/Quests/ItemCountQuestCondition.cs:32)
PixelCrushers.QuestMachine.QuestConditionSet:StopChecking () (at Assets/_Assets/Pixel Crushers/Quest Machine/Scripts/Quest/Quest Condition Set/QuestConditionSet.cs:145)
PixelCrushers.QuestMachine.Quest:SetStartChecking (bool) (at Assets/_Assets/Pixel Crushers/Quest Machine/Scripts/Quest/Quest.cs:826)
PixelCrushers.QuestMachine.Quest:SetState (PixelCrushers.QuestMachine.QuestState,bool) (at Assets/_Assets/Pixel Crushers/Quest Machine/Scripts/Quest/Quest.cs:933)
PixelCrushers.QuestMachine.Quest:Autostart () (at Assets/_Assets/Pixel Crushers/Quest Machine/Scripts/Quest/Quest.cs:840)
PixelCrushers.QuestMachine.QuestConditionSet:SetTrue () (at Assets/_Assets/Pixel Crushers/Quest Machine/Scripts/Quest/Quest Condition Set/QuestConditionSet.cs:195)
PixelCrushers.QuestMachine.QuestConditionSet:OnTrueCondition () (at Assets/_Assets/Pixel Crushers/Quest Machine/Scripts/Quest/Quest Condition Set/QuestConditionSet.cs:190)
PixelCrushers.QuestMachine.QuestCondition:SetTrue () (at Assets/_Assets/Pixel Crushers/Quest Machine/Scripts/Quest/Quest Subasset/Quest Condition/QuestCondition.cs:75)
ItemCountQuestCondition:Inventory_OnChange (Inventory,InventoryItem,int) (at Assets/Modules/Quests/ItemCountQuestCondition.cs:41)
Inventory:InsertItem (ItemDescription,int) (at Assets/Modules/InventorySystem/Inventory.cs:33)
Inventory:AddItem (ItemDescription,int) (at Assets/Modules/InventorySystem/Inventory.cs:21)
InventoryTradeHandler:OnItemClick (Inventory,InventoryItem) (at Assets/Modules/InventorySystem/InventoryHandlers/InventoryTradeHandler.cs:27)
InventoryTradeHandler:<.ctor>b__1_0 (Inventory,InventoryItem) (at Assets/Modules/InventorySystem/InventoryHandlers/InventoryTradeHandler.cs:12)
InventoryUIController:<RenderInventory>b__8_0 (InventoryItem) (at Assets/Modules/InventorySystem/UI/InventoryUIController.cs:41)
ItemUIController:<Init>b__5_0 () (at Assets/Modules/InventorySystem/UI/ItemUIController.cs:24)
UnityEngine.EventSystems.EventSystem:Update () (at ./Library/PackageCache/com.unity.ugui@2.0.0/Runtime/UGUI/EventSystem/EventSystem.cs:530)
Update condition code:

Code: Select all

using System.Collections.Generic;
using PixelCrushers.QuestMachine;
using UnityEngine;

public class ItemCountQuestCondition : QuestCondition {
    public ItemDescription itemType;

    public CounterValueConditionMode comparison = CounterValueConditionMode.AtLeast;

    public QuestNumber requiredValue = new QuestNumber();

    public override string GetEditorName() {
        return "Inventory has " + comparison + " " + requiredValue.GetValue(quest) + " " + itemType;
    }

    public override void StartChecking(System.Action trueAction) {
        Debug.Log($"[{itemType.itemName}] StartChecking() - Start ");		# <-------- ADDED

        base.StartChecking(trueAction);

        if (IsTrue()) {
            Debug.Log($"[{itemType.itemName}] StartChecking() - True at start.");		# <-------- ADDED
            SetTrue();
        } else {
            Debug.Log($"[{itemType.itemName}] StartChecking() - False at start, subscribing listeners.");
            Inventory.ItemAdded += Inventory_OnChange;
            Inventory.ItemRemoved += Inventory_OnChange;
        }
    }

    public override void StopChecking() {
        Debug.Log($"[{itemType.itemName}] StopChecking()")		# <-------- ADDED
        base.StopChecking();
        Inventory.ItemAdded -= Inventory_OnChange;		# <-------- ADDED
        Inventory.ItemRemoved -= Inventory_OnChange;		# <-------- ADDED
    }

    private void Inventory_OnChange(Inventory i, InventoryItem item, int quantity) {
        if (IsTrue()) {
            Debug.Log($"[{itemType.itemName}] Inventory_OnChange - Condition true.");		# <-------- ADDED
            SetTrue();
            Debug.Log("Item count condition is true");		# <-------- ADDED
        }
    }

    private bool IsTrue() {
        List<Unit> playersUnits = GameActors.Instance.PlayerActor.units;

        foreach (Unit unit in playersUnits) {
            Inventory inventory = unit.GetInventory();

            if (inventory == null) {
                continue;
            }

            InventoryItem item = inventory.TryGetItem(itemType);

            if (item == null) {
                continue;
            };

            switch (comparison) {
                case CounterValueConditionMode.AtLeast:
                    if (item.quantity >= requiredValue.GetValue(quest)) return true;
                    break;
                case CounterValueConditionMode.AtMost:
                    if (item.quantity <= requiredValue.GetValue(quest)) return true;
                    break;
            }
        }

        return false;
    }
}
Attachments
Get Ready.asset.txt
(11.96 KiB) Downloaded 70 times
Get Ready.asset.meta.txt
(189 Bytes) Downloaded 72 times
User avatar
Tony Li
Posts: 22091
Joined: Thu Jul 18, 2013 1:27 pm

Re: Custom quest condition not being checked for next quest's node.

Post by Tony Li »

Hi,

I'm glad you got it all working. If any questions come up, feel free to follow up.
Post Reply