Page 1 of 1

Invector with mirror

Posted: Sun May 19, 2024 9:17 pm
by DeidreReay
So we have basically worked out quests working and saving/ reloading with Dialogue/ Quest Machine in Multiplayer using mirror, but just ran into an issue. When in a quest and quest askign for Vitem id >= whatever.. Caliing towards these scripts, where we have some FindComponents and such. Which does not work as other players have those components etc.
Can you think of any way to make some changes with the Quest Machine Invector calls that could work better using Mirror??
Figured might ask if you had looked into or another person had before trying to rewrite things that may break with updates to your stuff.
For example the Invector scripts

Code: Select all

using UnityEngine;
using PixelCrushers.QuestMachine.InvectorSupport;
using Invector.vItemManager;

namespace PixelCrushers.QuestMachine
{

    public class InvectorHasItemsQuestCondition : QuestCondition
    {

        [Tooltip("ID of item to check.")]
        [SerializeField]
        private int m_itemID = 0;

        [Tooltip("How the player's current amount applies to the required amount.")]
        [SerializeField]
        private CounterValueConditionMode m_valueMode = CounterValueConditionMode.AtLeast;

        [Tooltip("Required amount.")]
        [SerializeField]
        private QuestNumber m_requiredAmount = new QuestNumber();

        [Tooltip("If assigned, keep this quest counter updated while waiting for this condition to be true. Inspect the quest's main info to view/edit counters.")]
        [SerializeField]
        private int m_counterIndex;

        public int itemID
        {
            get { return m_itemID; }
            set { m_itemID = value; }
        }

        public CounterValueConditionMode valueMode
        {
            get { return m_valueMode; }
            set { m_valueMode = value; }
        }

        public QuestNumber requiredAmount
        {
            get { return m_requiredAmount; }
            set { m_requiredAmount = value; }
        }

        public int counterIndex
        {
            get { return m_counterIndex; }
            set { m_counterIndex = value; }
        }

        private QuestCounter counter { get; set; }

        public override string GetEditorName()
        {
            return "Invector player has " + valueMode + " " + requiredAmount.GetValue(quest) + " of item ID " + itemID;
        }

#if USE_INVECTOR_INVENTORY

        public override void StartChecking(System.Action trueAction)
        {
            base.StartChecking(trueAction);
            counter = quest.GetCounter(counterIndex);
            var itemManager = QuestMachine_InvectorUtils.GetItemManager();
            if (itemManager != null)
            {
                itemManager.onAddItem.AddListener(OnHandleItem);
                itemManager.onChangeItemAmount.AddListener(OnHandleItem);
                itemManager.onDestroyItem.AddListener(OnChangeItem);
                itemManager.onDropItem.AddListener(OnChangeItem);
                CheckItemCount();
            }
        }

        public override void StopChecking()
        {
            base.StopChecking();
            var itemManager = QuestMachine_InvectorUtils.GetItemManager();
            if (itemManager != null)
            {
                itemManager.onAddItem.RemoveListener(OnHandleItem);
                itemManager.onChangeItemAmount.RemoveListener(OnHandleItem);
                itemManager.onDestroyItem.RemoveListener(OnChangeItem);
                itemManager.onDropItem.RemoveListener(OnChangeItem);
            }
        }

        private void OnHandleItem(vItem item)
        {
            CheckItemCount();
        }

        private void OnChangeItem(vItem item, int amount)
        {
            CheckItemCount();
        }

        public void CheckItemCount()
        {
            var currentAmount = QuestMachine_InvectorUtils.GetItemAmount(itemID);
            if (counter != null) counter.currentValue = currentAmount;
            var actualRequiredAmount = requiredAmount.GetValue(quest);
            bool isRequirementMet = false;
            switch (valueMode)
            {
                default:
                case CounterValueConditionMode.AtLeast:
                    isRequirementMet = currentAmount >= actualRequiredAmount;
                    break;
                case CounterValueConditionMode.AtMost:
                    isRequirementMet = currentAmount <= actualRequiredAmount;
                    break;
            }
            if (isRequirementMet)
            {
                if (QuestMachine.debug) Debug.Log("Quest Machine: InvectorHasItemsQuestCondition player has " + valueMode + " " + requiredAmount.GetValue(quest) + " of item ID " + itemID + " is true.");
                StopChecking();
                SetTrue();
            }
        }

#else

        public override void StartChecking(System.Action trueAction)
        {
            base.StartChecking(trueAction);
            Debug.LogError(GetType().Name + ": You must define the scripting symbol USE_INVECTOR_INVENTORY to use Invector inventory features in Quest Machine.");
        }

#endif

    }
}

Code: Select all

using UnityEngine;

namespace PixelCrushers.QuestMachine.InvectorSupport
{
    public static class QuestMachine_InvectorUtils
    {

        public static Invector.vCharacterController.vThirdPersonController GetController()
        {
            return GameObject.FindObjectOfType<Invector.vCharacterController.vThirdPersonController>();
        }

        public static void AddHealth(int v)
        {
            var controller = GetController();
            if (controller != null) controller.ChangeHealth(v);
        }

        public static void AddMaxHealth(int v)
        {
            var controller = GetController();
            if (controller != null) controller.ChangeMaxHealth(v);
        }


#if USE_INVECTOR_INVENTORY

        public static Invector.vItemManager.vItemManager GetItemManager()
        {
            return GameObject.FindObjectOfType<Invector.vItemManager.vItemManager>();
        }

        public static int GetItemAmount(int itemID)
        {
            var itemManager = GetItemManager();
            if (itemManager)
            {
                int total = 0;
                var allItems = itemManager.GetItems(itemID);
                foreach (var item in allItems)
                {
                    if (item.id == itemID)
                    {
                        total += item.amount;
                    }
                }
                return total;
            }
            return 0;
        }

        public static void AddItem(int itemID, int amount, bool autoEquip)
        {
            var itemManager = GetItemManager();
            if (itemManager == null || amount == 0) return;
            if (amount > 0)
            {
                var reference = new Invector.vItemManager.ItemReference(itemID);
                reference.amount = amount;
                reference.autoEquip = autoEquip;
                reference.addToEquipArea = autoEquip;
                itemManager.AddItem(reference);
            }
            else
            {
                var allItems = itemManager.GetItems();
                for (int i = allItems.Count - 1; i >= 0; i--)
                {
                    var item = allItems[i];
                    if (item.id == itemID)
                    {
                        itemManager.DestroyItem(item, -amount);
                    }
                }
            }
        }

#else

        public static int GetItemAmount(int itemID)
        {
            Debug.LogError("You must define the scripting symbol USE_INVECTOR_INVENTORY to use Invector inventory features in Quest Machine.");
            return 0;
        }

        public static void AddItem(int itemID, int amount, bool autoEquip)
        {
            Debug.LogError("You must define the scripting symbol USE_INVECTOR_INVENTORY to use Invector inventory features in Quest Machine.");
        }

#endif

    }
}

Re: Invector with mirror

Posted: Sun May 19, 2024 9:53 pm
by Tony Li
Hi,

Those integration scripts assume a single Invector player. They could still work in a multiplayer game if the remote players are represented by "ghosts" -- that is, non-Invector GameObjects that just mirror the positions and animations of the actual remote players.

If you're instantiating full Invector player GameObjects for each player -- local and remote -- then you'll have to write your own conditions and actions scripts. Copy the code that's in the integration scripts, but instead of calling QuestMachine_InvectorUtils.GetItemManager() which looks for a single Invector player GameObject, find the instance of the Quest Journal component whose questList contains the condition's or action's "quest" property. This will identify the correct Invector player.

Re: Invector with mirror

Posted: Sun May 19, 2024 10:06 pm
by DeidreReay
Okay that is what I figured, just not sure if there was something already spun up for mirror.
Will dive in and should be easy enough to figure out.
Thank you

Re: Invector with mirror

Posted: Mon May 20, 2024 7:58 am
by Tony Li
Glad to help!