ORK integration

Announcements, support questions, and discussion for Quest Machine.
dlevel
Posts: 197
Joined: Wed Nov 16, 2016 6:17 pm

Re: ORK integration

Post by dlevel »

Made a change on the QuestJournal that chatgpr proposed, this is the new method that seems to work, lmk if its enough or you have another solution:

Code: Select all

protected virtual void VerifyTrueNodeChildrenAreActive()
{
    // Create a copy of the quest list to iterate over safely
    var questListCopy = new List<Quest>(questList);

    foreach (var quest in questListCopy)
    {
        // Only process active quests
        if (quest.GetState() != QuestState.Active) continue;

        var processed = new HashSet<QuestNode>();
        foreach (var node in quest.nodeList)
        {
            if (processed.Contains(node)) continue;
            processed.Add(node);

            // Check for True nodes
            if (node.GetState() == QuestNodeState.True)
            {
                foreach (var child in node.childList)
                {
                    // Activate inactive children
                    if (child.GetState() == QuestNodeState.Inactive)
                    {
                        child.SetState(QuestNodeState.Active);
                    }
                }
            }
        }
    }
}
User avatar
Tony Li
Posts: 23161
Joined: Thu Jul 18, 2013 1:27 pm

Re: ORK integration

Post by Tony Li »

There's some code in there that you probably don't need, but if it works I say leave it be.
dlevel
Posts: 197
Joined: Wed Nov 16, 2016 6:17 pm

Re: ORK integration

Post by dlevel »

Hey, probably you are on holidays but I ll leave some issues here :)

1) There is a core issue with conditions. I use ORK Variables for offering or not the quests from the quest givers, but it seems that if a player finishes a 1 time quest, if he acts fast and presses back on the quest giver dialogue they can select the quest again, even though the success node of the quest changes the variable of the quest (maybe a timing issue).

To recap: 1 Time quests are being given again to players even though conditions are not met (and they are 1 time quests). Attaching couple of quests

2) Due to this issue, players have some duplicate quests (or 3-4plicate), can we handle those as well on the script you send me above? Thanks and happy holidays!

link of quests: https://we.tl/t-veQgGanIlb
User avatar
Tony Li
Posts: 23161
Joined: Thu Jul 18, 2013 1:27 pm

Re: ORK integration

Post by Tony Li »

Hi, and happy holidays!

Does the player do this while in the same dialogue UI window session? In other words, they complete a quest, click the Back button, and the quest appears again in the list of offerable quests?

Or does it appear if the player closes the dialogue UI and immediately interacts with the quest giver again, which reopens the dialogue UI?
dlevel
Posts: 197
Joined: Wed Nov 16, 2016 6:17 pm

Re: ORK integration

Post by dlevel »

Sorry just saw your message, yes it happens while the window is still open, they can press back. If the windows closes then the back button is not there.
User avatar
Tony Li
Posts: 23161
Joined: Thu Jul 18, 2013 1:27 pm

Re: ORK integration

Post by Tony Li »

Would you please remind me which Quest Machine version you're using? You can find the version number in Plugins > Pixel Crushers > Quest Machine / _README.txt.

In the current version (1.2.50) and most previous versions, when the player clicks the Back button it will recheck the offer conditions before showing the list of available quests. In addition, if it's a one-time quest, then the quest giver should remove the quest from its list as soon as the player accepts it the first time.

If you can reproduce the issue in the Unity editor's play mode, keep an inspector view on the Quest Giver component's Quests list. For example, here's the Villager in Quest Machine's Demo scene:
questList1.png
questList1.png (418.63 KiB) Viewed 11380 times

When I accept the quest:
questList2.png
questList2.png (355.84 KiB) Viewed 11380 times

The Quest Giver removes it from its Quests list since it's a one-time quest:
questList3.png
questList3.png (335.17 KiB) Viewed 11380 times
dlevel
Posts: 197
Joined: Wed Nov 16, 2016 6:17 pm

Re: ORK integration

Post by dlevel »

Oh I see, I use 1.2.48 plus the custom changes you made in this thread, avoding too much updating due to custom code we implemented. Will update and get back to you. Also can we add the duplicate quest fix as well, here is the script I use now:

Code: Select all

using System.Collections.Generic;
using UnityEngine;
using ORKFramework;

namespace PixelCrushers.QuestMachine.ORKSupport
{
    public class QuestJournalForORKWithVerify : QuestJournalForORK
    {
        public override void LoadGame(DataObject data)
        {
            // If the saved game doesn't have QuestJournalForORK data,
            // then we know that it's saved through ORKQuestMachineSaveData,
            // and we don't need to do anything.
            if (data == null)
            {
                Debug.Log("QuestJournalForORKWithVerify has no saved data. Exiting.");
                return;
            }

            // Ensure questList is initialized
            if (questList == null)
            {
                Debug.LogError("QuestJournalForORKWithVerify: questList is null.");
                return;
            }

            // First, restore the quests.
            Debug.Log("QuestJournalForORKWithVerify is restoring the quest journal.");
            base.LoadGame(data);

            // Make lists of "bad" and completed quests
            Debug.Log("QuestJournalForORKWithVerify is making a list of bad quests and completed quests.");
            var badQuests = new List<Quest>();
            var completedQuests = new List<Quest>();

            foreach (var quest in questList)
            {
                if (quest == null)
                {
                    Debug.LogWarning("QuestJournalForORKWithVerify: Found a null quest in questList.");
                    continue;
                }

                if (quest.GetState() == QuestState.Successful)
                {
                    Debug.Log($"QuestJournalForORKWithVerify: quest is completed: {quest.id}");
                    completedQuests.Add(quest);
                }
                else if (quest.startNode == null || quest.startNode.GetState() != QuestNodeState.True)
                {
                    Debug.Log($"QuestJournalForORKWithVerify: quest is bad: {quest.id}");
                    badQuests.Add(quest);
                }
            }

            // Remove completed quests
            foreach (var completedQuest in completedQuests)
            {
                Debug.Log($"QuestJournalForORKWithVerify removing completed quest {completedQuest.id}");
                DeleteQuest(completedQuest);
            }

            // Replace the bad quests with fresh copies
            foreach (var badQuest in badQuests)
            {
                if (badQuest.originalAsset == null)
                {
                    Debug.LogWarning($"QuestJournalForORKWithVerify: Quest {badQuest.id} has a null original asset.");
                    continue;
                }

                Debug.Log($"QuestJournalForORKWithVerify adding fresh copy of bad quest {badQuest.id}");
                var questAsset = badQuest.originalAsset;
                DeleteQuest(badQuest);

                var questInstance = questAsset.Clone();
                if (questInstance == null)
                {
                    Debug.LogWarning($"QuestJournalForORKWithVerify: Failed to clone quest asset for quest {badQuest.id}.");
                    continue;
                }

                var questerTextInfo = new QuestParticipantTextInfo(id, displayName, image, null);
                questInstance.AssignQuester(questerTextInfo);
                questInstance.timesAccepted = 1;

                deletedStaticQuests.Remove(StringField.GetStringValue(questInstance.id));
                AddQuest(questInstance);
                questInstance.SetState(QuestState.Active);
            }

            // Refresh the UI to show the updated quest journal
            QuestMachineMessages.RefreshUIs(this);
        }
    }
}
User avatar
Tony Li
Posts: 23161
Joined: Thu Jul 18, 2013 1:27 pm

Re: ORK integration

Post by Tony Li »

Hi,

Try this version:

Code: Select all

using System.Collections.Generic;
using UnityEngine;
using ORKFramework;

namespace PixelCrushers.QuestMachine.ORKSupport
{
    public class QuestJournalForORKWithVerify : QuestJournalForORK
    {
        public override void LoadGame(DataObject data)
        {
            // If the saved game doesn't have QuestJournalForORK data,
            // then we know that it's saved through ORKQuestMachineSaveData,
            // and we don't need to do anything.
            if (data == null)
            {
                Debug.Log("QuestJournalForORKWithVerify has no saved data. Exiting.");
                return;
            }

            // Ensure questList is initialized
            if (questList == null)
            {
                Debug.LogError("QuestJournalForORKWithVerify: questList is null.");
                return;
            }

            // First, restore the quests.
            Debug.Log("QuestJournalForORKWithVerify is restoring the quest journal.");
            base.LoadGame(data);

            // Identify and remove duplicate quests
            var firstQuestInstances = new List<Quest>();
            var duplicateQuestInstances = new List<Quest>();
            foreach (var quest in questList)
            {
                bool alreadyHasQuest = firstQuestInstances.Find(x => StringField.Equals(x.id, quest.id)) != null;
                if (!alreadyHasQuest)
                {
                    firstQuestInstances.Add(quest);
                }
                else
                {
                    duplicateQuestInstances.Add(quest);
                }
            }
            foreach (var quest in duplicateQuestInstances)
            {
                Debug.Log($"QuestJournalForORKWithVerify: removing duplicate quest: {quest.id}");
                DeleteQuest(quest);
            }

            // Make lists of "bad" and completed quests
            Debug.Log("QuestJournalForORKWithVerify is making a list of bad quests and completed quests.");
            var badQuests = new List<Quest>();
            var completedQuests = new List<Quest>();

            foreach (var quest in questList)
            {
                if (quest == null)
                {
                    Debug.LogWarning("QuestJournalForORKWithVerify: Found a null quest in questList.");
                    continue;
                }

                if (quest.GetState() == QuestState.Successful)
                {
                    Debug.Log($"QuestJournalForORKWithVerify: quest is completed: {quest.id}");
                    completedQuests.Add(quest);
                }
                else if (quest.startNode == null || quest.startNode.GetState() != QuestNodeState.True)
                {
                    Debug.Log($"QuestJournalForORKWithVerify: quest is bad: {quest.id}");
                    badQuests.Add(quest);
                }
            }

            // Remove completed quests
            foreach (var completedQuest in completedQuests)
            {
                Debug.Log($"QuestJournalForORKWithVerify removing completed quest {completedQuest.id}");
                DeleteQuest(completedQuest);
            }

            // Replace the bad quests with fresh copies
            foreach (var badQuest in badQuests)
            {
                if (badQuest.originalAsset == null)
                {
                    Debug.LogWarning($"QuestJournalForORKWithVerify: Quest {badQuest.id} has a null original asset.");
                    continue;
                }

                Debug.Log($"QuestJournalForORKWithVerify adding fresh copy of bad quest {badQuest.id}");
                var questAsset = badQuest.originalAsset;
                DeleteQuest(badQuest);

                var questInstance = questAsset.Clone();
                if (questInstance == null)
                {
                    Debug.LogWarning($"QuestJournalForORKWithVerify: Failed to clone quest asset for quest {badQuest.id}.");
                    continue;
                }

                var questerTextInfo = new QuestParticipantTextInfo(id, displayName, image, null);
                questInstance.AssignQuester(questerTextInfo);
                questInstance.timesAccepted = 1;

                deletedStaticQuests.Remove(StringField.GetStringValue(questInstance.id));
                AddQuest(questInstance);
                questInstance.SetState(QuestState.Active);
            }

            // Refresh the UI to show the updated quest journal
            QuestMachineMessages.RefreshUIs(this);
        }
    }
}
dlevel
Posts: 197
Joined: Wed Nov 16, 2016 6:17 pm

Re: ORK integration

Post by dlevel »

So this new script seems to remove duplicates if they haven't been progressed (they are still on first node), others that have been progressed but haven't been delivered (NPC doesnt allow to deliver it after you deliver it once since I m disabling the quest giver to avoid duplicate rewards) are not being removed
User avatar
Tony Li
Posts: 23161
Joined: Thu Jul 18, 2013 1:27 pm

Re: ORK integration

Post by Tony Li »

Hi,

That script should preserve the first instance of the quest that's in the player's journal and delete any other instances.

How should I change the criteria to accomplish what you need?
Post Reply