Page 27 of 29

Re: ORK integration

Posted: Sun Nov 24, 2024 12:25 am
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);
                    }
                }
            }
        }
    }
}

Re: ORK integration

Posted: Sun Nov 24, 2024 5:04 am
by Tony Li
There's some code in there that you probably don't need, but if it works I say leave it be.

Re: ORK integration

Posted: Tue Dec 24, 2024 2:15 am
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

Re: ORK integration

Posted: Tue Dec 24, 2024 10:23 am
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?

Re: ORK integration

Posted: Fri Dec 27, 2024 1:36 pm
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.

Re: ORK integration

Posted: Fri Dec 27, 2024 3:19 pm
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 11345 times

When I accept the quest:
questList2.png
questList2.png (355.84 KiB) Viewed 11345 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 11345 times

Re: ORK integration

Posted: Sat Dec 28, 2024 2:31 am
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);
        }
    }
}

Re: ORK integration

Posted: Sat Dec 28, 2024 10:19 am
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);
        }
    }
}

Re: ORK integration

Posted: Mon Dec 30, 2024 1:43 am
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

Re: ORK integration

Posted: Mon Dec 30, 2024 8:31 am
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?