/// <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> /// <param name="change">The change to make. The result is kept within the -100 to 100 range.</param> internal void ChangeStat(StatInfluencerSO influencer, float change) { StatSO stat = GetOrCreateStat(influencer.statName); stat.value += change; influencer.influenceApplied += change; //Debug.Log(gameObject.name + " changed stat " + influencer.statName + " by " + change); }
private void Start() { controller = GetComponent <Brain>(); health = controller.GetOrCreateStat(healthTemplate, 1); health.onValueChanged.AddListener(OnHealthChanged); deathTriggerID = Animator.StringToHash(deathTriggerName); }
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); }
/// <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].statName); if (stat.goal != DesiredState.Goal.NoAction) { stats.Add(stat); } } return(stats.ToArray()); }
void Update() { if (m_SelectionManager != null && m_SelectionManager.CurrentlySelected != null && (m_SelectedCharacter == null || !GameObject.ReferenceEquals(m_SelectedCharacter.gameObject, m_SelectionManager.CurrentlySelected))) { m_SelectedCharacter = m_SelectionManager.CurrentlySelected.GetComponentInChildren <Brain>(); ClearStatesUI(); } //TODO: don't update every frame if (m_SelectedCharacter != null) { if (m_BehaviourLabel != null && m_SelectedCharacter.ActiveBlockingBehaviour != null) { string duration = Mathf.Clamp(m_SelectedCharacter.ActiveBlockingBehaviour.EndTime - Time.timeSinceLevelLoad, 0, float.MaxValue).ToString("0.0"); m_BehaviourLabel.text = m_SelectedCharacter.DisplayName + " - " + m_SelectedCharacter.ActiveBlockingBehaviour.DisplayName + " Finishes in " + duration; } StateSO[] states = m_SelectedCharacter.DesiredStates; if (states.Length != transform.childCount) { ClearStatesUI(); for (int i = 0; i < states.Length; i++) { if (states[i].statTemplate == null) { continue; } //TODO cache results rather than grabbing stat every cycle StatSO stat = m_SelectedCharacter.GetOrCreateStat(states[i].statTemplate); StatUIPanel stateUI; if (!stateUIObjects.TryGetValue(stat.DisplayName, out stateUI)) { stateUI = Instantiate(statPanelTemplate, transform).GetComponent <StatUIPanel>(); stateUI.stat = stat; stateUI.gameObject.SetActive(true); stateUIObjects.Add(stat.DisplayName, stateUI); } } } } }
/// <summary> /// Add an influencer to this controller. If this controller is not managing the required stat then /// do nothing. If this character has any memory of being influenced by the object within short term /// memory this new influence will be rejected. /// </summary> /// <param name="influencer">The influencer to add.</param> /// <returns>True if the influencer was added, otherwise false.</returns> public bool TryAddInfluencer(StatInfluencerSO influencer) { StatSO stat = GetOrCreateStat(influencer.statName); 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); }
/// <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="statName">Tha name of the stat to Get or Create</param> /// <param name="baseValue">The base value to assign if the stat needs to be created.</param> /// <returns>A StatSO representing the named stat</returns> public StatSO GetOrCreateStat(string statName, float baseValue = 0) { StatSO stat = GetStat(statName); if (stat != null) { return(stat); } stat = ScriptableObject.CreateInstance <StatSO>(); stat.name = statName; stat.value = baseValue; for (int i = 0; i < desiredStates.Length; i++) { if (statName == desiredStates[i].statName) { stat.desiredState = desiredStates[i]; break; } } m_Stats.Add(stat); return(stat); }