Esempio n. 1
0
        string IDebug.StatusText()
        {
            string msg = DisplayName;

            msg += "\n\nStats";
            for (int i = 0; i < m_Stats.Count; i++)
            {
                msg += "\n" + m_Stats[i].statusDescription;
            }

            msg += GetActiveInfluencersDescription();

            msg += "\n\nUnsatisfied Desired States";
            if (UnsatisfiedDesiredStates.Count == 0)
            {
                msg += "\nNone";
            }
            for (int i = 0; i < UnsatisfiedDesiredStates.Count; i++)
            {
                StatSO stat = GetOrCreateStat(UnsatisfiedDesiredStates[i].statTemplate);
                msg += "\nIs not ";
                msg += UnsatisfiedDesiredStates[i].name + " ";
                msg += " (" + stat.name + " should be " + UnsatisfiedDesiredStates[i].objective + " " + UnsatisfiedDesiredStates[i].normalizedTargetValue + ")";
            }

            return(msg);
        }
Esempio n. 2
0
        string IDebug.StatusText()
        {
            string msg = DisplayName;

            msg += "\n\nStats";
            for (int i = 0; i < m_Stats.Count; i++)
            {
                msg += "\n" + m_Stats[i].statusDescription;
            }

            msg += GetActiveInfluencersDescription();

            msg += "\n\nUnsatisfied Desired States";
            if (UnsatisfiedDesiredStates.Count == 0)
            {
                msg += "\nNone";
            }
            for (int i = 0; i < UnsatisfiedDesiredStates.Count; i++)
            {
                StatSO stat = GetOrCreateStat(UnsatisfiedDesiredStates[i].statTemplate);
                msg += "\nIs not ";
                msg += UnsatisfiedDesiredStates[i].name + " ";
                msg += " (" + stat.name + " should be " + UnsatisfiedDesiredStates[i].objective + " " + UnsatisfiedDesiredStates[i].normalizedTargetValue + ")";
            }

            if (Memory == null)
            {
                msg += "\n\nThis actor has no memory.";
            }
            else
            {
                msg += "\n\nThis actor has a memory.";
                msg += "\nShort term memories: " + Memory.GetShortTermMemories().Length;
                msg += "\nLong term memories: " + Memory.GetLongTermMemories().Length;
            }

            if (ActiveBlockingBehaviour != null)
            {
                float timeLeft = Mathf.Clamp(ActiveBlockingBehaviour.EndTime - Time.timeSinceLevelLoad, 0, float.MaxValue);
                msg += "\n\nCurrent Behaviour";
                msg += "\n" + ActiveBlockingBehaviour + " (time to abort / end " + timeLeft.ToString("0.0") + ")";
                if (TargetInteractable != null)
                {
                    msg += "\nTarget interaction: " + TargetInteractable.InteractionName + " at " + TargetInteractable.name;
                }
                else
                {
                    msg += "\nNo target interaction";
                }
            }
            else
            {
                msg += "\n\nCurrent Behaviour";
                msg += "\nNone";
            }

            return(msg);
        }
Esempio n. 3
0
        /// <summary>
        /// Add an influencer to this controller. If this controller is not managing the required stat then
        /// do nothing.
        /// </summary>
        /// <param name="influencer">The influencer to add.</param>
        /// <returns>True if the influencer was added, otherwise false.</returns>
        public override bool TryAddInfluencer(StatInfluencerSO influencer)
        {
            if (Memory != null && influencer.Trigger != null)
            {
                MemorySO[] memories = Memory.GetAllMemoriesAbout(influencer.Generator);
                for (int i = 0; i < memories.Length; i++)
                {
                    if (memories[i].stat == influencer.stat && memories[i].time + memories[i].cooldown > Time.timeSinceLevelLoad)
                    {
                        return(false);
                    }
                }
            }

            if (Memory != null)
            {
                StatSO         stat   = GetOrCreateStat(influencer.stat);
                List <StateSO> states = GetDesiredStatesFor(stat);
                bool           isGood = true;
                for (int i = 0; i < states.Count; i++)
                {
                    switch (states[i].objective)
                    {
                    case StateSO.Objective.LessThan:
                        if (influencer.maxChange > 0)
                        {
                            isGood = false;
                        }
                        break;

                    case StateSO.Objective.Approximately:
                        float currentDelta    = states[i].normalizedTargetValue - stat.NormalizedValue;
                        float influencedDelta = states[i].normalizedTargetValue - (stat.NormalizedValue + influencer.maxChange);
                        if (currentDelta < influencedDelta)
                        {
                            isGood = false;
                        }
                        break;

                    case StateSO.Objective.GreaterThan:
                        if (influencer.maxChange < 0)
                        {
                            isGood = false;
                        }
                        break;
                    }

                    if (influencer.Generator != null)
                    {
                        Memory.AddMemory(influencer, isGood);
                    }
                }
            }

            return(base.TryAddInfluencer(influencer));
        }
Esempio n. 4
0
        public IEnumerator StatsControllerAddUnknownStat()
        {
            string          statName   = "Test Unkown Stat";
            StatsController controller = new GameObject().AddComponent <StatsController>();

            StatSO stat = controller.GetOrCreateStat(statName, 50);

            Assert.True(stat.name == statName, "Did not create the unknown stat.");

            yield return(null);
        }
Esempio n. 5
0
        /// <summary>
        /// Get the current goal for a given stat. That is do we currently want to
        /// increase, decrease or maintaint his stat.
        /// If there are multiple desired states then an attempt is made to create
        /// a meaningful goal. For example, if there are multiple greater than goals
        /// then the target will be the highest goal.
        ///
        /// If there are conflicting goals,
        /// such as a greater than and a less than then lessThan will take preference
        /// over greaterThan, but approximately will always be given prefernce.
        /// </summary>
        /// <returns>The current goal for the stat.</returns>
        public Goal GetGoalFor(StatSO stat)
        {
            float lessThan    = float.MaxValue;
            float greaterThan = float.MinValue;

            List <StateSO> states = GetDesiredStatesFor(stat);

            for (int i = 0; i < states.Count; i++)
            {
                switch (states[i].objective)
                {
                case Objective.LessThan:
                    if (stat.NormalizedValue >= states[i].normalizedTargetValue && states[i].normalizedTargetValue < lessThan)
                    {
                        lessThan = states[i].normalizedTargetValue;
                    }
                    break;

                case Objective.Approximately:
                    if (Mathf.Approximately(stat.NormalizedValue, states[i].normalizedTargetValue))
                    {
                        if (stat.NormalizedValue > states[i].normalizedTargetValue)
                        {
                            return(StateSO.Goal.Decrease);
                        }
                        else
                        {
                            return(StateSO.Goal.Increase);
                        }
                    }
                    break;

                case Objective.GreaterThan:
                    if (stat.NormalizedValue <= states[i].normalizedTargetValue && states[i].normalizedTargetValue > greaterThan)
                    {
                        greaterThan = states[i].normalizedTargetValue;
                    }
                    break;
                }
            }

            if (lessThan != float.MaxValue)
            {
                return(StateSO.Goal.Decrease);
            }
            if (greaterThan != float.MinValue)
            {
                return(StateSO.Goal.Increase);
            }

            return(StateSO.Goal.NoAction);
        }
Esempio n. 6
0
        /// <summary>
        /// Add an influencer to this controller. If this controller is not managing the required stat then
        /// do nothing.
        /// </summary>
        /// <param name="influencer">The influencer to add.</param>
        /// <returns>True if the influencer was added, otherwise false.</returns>
        public bool TryAddInfluencer(StatInfluencerSO influencer)
        {
            if (m_Memory != null && influencer.generator != null)
            {
                MemorySO[] memories = m_Memory.GetAllMemoriesAbout(influencer.generator);
                for (int i = 0; i < memories.Length; i++)
                {
                    if (memories[i].stat == influencer.stat && memories[i].time + memories[i].cooldown > Time.timeSinceLevelLoad)
                    {
                        return(false);
                    }
                }
            }

            StatSO stat   = GetOrCreateStat(influencer.stat.name);
            bool   isGood = true;

            switch (stat.desiredState.objective)
            {
            case DesiredState.Objective.LessThan:
                if (influencer.maxChange > 0)
                {
                    isGood = false;
                }
                break;

            case DesiredState.Objective.Approximately:
                float currentDelta    = stat.desiredState.targetValue - stat.value;
                float influencedDelta = stat.desiredState.targetValue - (stat.value + influencer.maxChange);
                if (currentDelta < influencedDelta)
                {
                    isGood = false;
                }
                break;

            case DesiredState.Objective.GreaterThan:
                if (influencer.maxChange < 0)
                {
                    isGood = false;
                }
                break;
            }

            if (m_Memory != null)
            {
                m_Memory.AddMemory(influencer, isGood);
            }

            m_StatsInfluencers.Add(influencer);

            return(true);
        }
Esempio n. 7
0
 /// <summary>
 /// Get the Stat of a given type.
 /// </summary>
 /// <param name="name">The name of the stat we want to retrieve</param>
 /// <returns>The stat, if it exists, or null.</returns>
 public StatSO GetStat(StatSO template)
 {
     for (int i = 0; i < m_Stats.Count; i++)
     {
         if (template != null)
         {
             if (m_Stats[i].name == template.name)
             {
                 return(m_Stats[i]);
             }
         }
     }
     return(null);
 }
Esempio n. 8
0
        /// <summary>
        /// Get a list of stats that are currently outside the desired state for that stat.
        /// This can be used, for example. by AI deciding what action to take next.
        /// </summary>
        /// <returns>A list of stats that are not in a desired state.</returns>
        public StatSO[] GetStatsNotInDesiredState()
        {
            List <StatSO> stats = new List <StatSO>();

            for (int i = 0; i < desiredStates.Length; i++)
            {
                StatSO stat = GetOrCreateStat(desiredStates[i].stat.name);
                if (stat.goal != DesiredState.Goal.NoAction)
                {
                    stats.Add(stat);
                }
            }
            return(stats.ToArray());
        }
Esempio n. 9
0
        internal List <StateSO> GetDesiredStatesFor(StatSO stat)
        {
            List <StateSO> states = new List <StateSO>();

            for (int i = 0; i < DesiredStates.Length; i++)
            {
                if (DesiredStates[i].statTemplate != null && stat.name == DesiredStates[i].statTemplate.name)
                {
                    states.Add(DesiredStates[i]);
                    break;
                }
            }

            return(states);
        }
Esempio n. 10
0
        public IEnumerator StatsControllerAddUnknownStat()
        {
            StatSO template = ScriptableObject.CreateInstance <StatSO>();
            string statName = "Test Unkown Stat";

            template.name = statName;

            Brain controller = new GameObject().AddComponent <Brain>();

            StatSO stat = controller.GetOrCreateStat(template, 50);

            Assert.True(stat.name == statName, "Did not create the unknown stat.");

            yield return(null);
        }
Esempio n. 11
0
        /// <summary>
        /// Apply an immediate change to a given Stats, if this controller is tracking that stat.
        /// </summary>
        ///
        /// <param name="influencer">The influencer imparting the change.</param>
        internal void ChangeStat(StatInfluencerSO influencer)
        {
            StatSO stat = GetOrCreateStat(influencer.stat.name);
            float  change;

            if (influencer.duration > 0)
            {
                change = Mathf.Clamp(influencer.changePerSecond * (Time.timeSinceLevelLoad - m_TimeOfLastUpdate), float.MinValue, influencer.maxChange - influencer.influenceApplied);
            }
            else
            {
                change = Mathf.Clamp(influencer.maxChange, influencer.maxChange - influencer.influenceApplied, influencer.maxChange);
            }

            stat.value += change;
            influencer.influenceApplied += change;
            //Debug.Log(gameObject.name + " changed stat " + influencer.statName + " by " + change);
        }
Esempio n. 12
0
        private List <StatSO> GetStatsDesiredForState(StateSO state)
        {
            List <StatSO> stats = new List <StatSO>();

            if (state.statTemplate != null)
            {
                StatSO stat = GetOrCreateStat(state.statTemplate);
                if (GetGoalFor(state.statTemplate) != StateSO.Goal.NoAction)
                {
                    stats.Add(stat);
                }
            }

            for (int idx = 1; idx < state.SubStates.Length; idx++)
            {
                stats.AddRange(GetStatsDesiredForState(state.SubStates[idx]));
            }
            return(stats);
        }
Esempio n. 13
0
        /// <summary>
        /// Get the stat object representing a named stat. If it does not already
        /// exist it will be created with a base value.
        /// </summary>
        /// <param name="name">Tha name of the stat to Get or Create for this controller</param>
        /// <returns>A StatSO representing the named stat</returns>
        public StatSO GetOrCreateStat(StatSO template, float?value = null)
        {
            StatSO stat = GetStat(template);

            if (stat != null)
            {
                return(stat);
            }

            stat      = Instantiate(template);
            stat.name = template.name;
            if (value != null)
            {
                stat.NormalizedValue = (float)value;
            }

            m_Stats.Add(stat);
            return(stat);
        }
Esempio n. 14
0
        /// <summary>
        /// Apply a change from a stat influencer.
        /// </summary>
        ///
        /// <param name="statsTracker">The stats tracker managing the stats to be changed.</param>
        internal void ChangeStat(StatsTracker statsTracker)
        {
            StatSO statToUpdate = statsTracker.GetOrCreateStat(stat);
            float  change;

            if (duration > 0)
            {
                change = Mathf.Clamp(changePerSecond * (Time.timeSinceLevelLoad - m_TimeOfLastUpdate), float.MinValue, Mathf.Abs(maxChange) - Mathf.Abs(influenceApplied));
            }
            else
            {
                change = Mathf.Clamp(maxChange, maxChange - influenceApplied, Mathf.Abs(maxChange));
            }

            statToUpdate.Value += change;
            influenceApplied   += change;

            m_TimeOfLastUpdate = Time.timeSinceLevelLoad;
            //Debug.Log(gameObject.name + " changed stat " + influencer.statName + " by " + change);
        }
Esempio n. 15
0
        public IEnumerator StatInstantInfluencer()
        {
            string          statName   = "Test Immediate Influencer Stat";
            StatsController controller = new GameObject().AddComponent <StatsController>();

            StatInfluencerSO influencer = ScriptableObject.CreateInstance <StatInfluencerSO>();
            StatSO           stat       = controller.GetOrCreateStat(statName);

            influencer.stat      = stat;
            influencer.maxChange = 10;
            influencer.duration  = 0;

            Assert.True(controller.TryAddInfluencer(influencer), "Was not able to add the Stat influencer");

            yield return(null);

            Assert.True(controller.GetOrCreateStat(statName).value > 0, "Seems the influencer has had no effect.");

            yield return(null);
        }
Esempio n. 16
0
        /// <summary>
        /// Get the stat object representing a named stat. If it does not already
        /// exist it will be created with a base value.
        /// </summary>
        /// <param name="name">Tha name of the stat to Get or Create for this controller</param>
        /// <returns>A StatSO representing the named stat</returns>
        public StatSO GetOrCreateStat(string name, float value = 0)
        {
            StatSO stat = GetStat(name);

            if (stat != null)
            {
                return(stat);
            }

            stat       = ScriptableObject.CreateInstance <StatSO>();
            stat.name  = name;
            stat.value = value;
            for (int i = 0; i < desiredStates.Length; i++)
            {
                if (stat.GetType() == desiredStates[i].stat.GetType())
                {
                    stat.desiredState = desiredStates[i];
                    break;
                }
            }

            m_Stats.Add(stat);
            return(stat);
        }
Esempio n. 17
0
        public IEnumerator StatInstantInfluencer()
        {
            StatSO template = ScriptableObject.CreateInstance <StatSO>();
            string statName = "Test Immediate Influencer Stat";

            template.name = statName;

            Brain controller = new GameObject().AddComponent <Brain>();

            StatInfluencerSO influencer = ScriptableObject.CreateInstance <StatInfluencerSO>();
            StatSO           stat       = controller.GetOrCreateStat(template);

            influencer.stat      = stat;
            influencer.maxChange = 10;
            influencer.duration  = 0;

            Assert.True(controller.TryAddInfluencer(influencer), "Was not able to add the Stat influencer");

            yield return(new WaitForSeconds(0.51f)); // ensure the brain has time to apply the influencer

            Assert.True(stat.NormalizedValue > 0, "Seems the influencer has had no effect.");

            yield return(null);
        }
Esempio n. 18
0
 /// <summary>
 /// Test if the stat tracker is currently tracking the stat provided in the template.
 /// </summary>
 /// <param name="statTemplate">The stat to test for</param>
 /// <returns>True if the stat is currently being tracked.</returns>
 internal bool HasStat(StatSO statTemplate)
 {
     return(GetStat(statTemplate) != null);
 }