Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
- public class Buffable : MonoBehaviour
- {
- public static List<Buffable> buffables = new List<Buffable>();
- public static List<Buffable> playerBuffables = new List<Buffable>();
- public static List<Buffable> aiBuffables = new List<Buffable>();
- public string name = string.Empty;
- public Character owner; // who caused the buffable
- public Character affected; // afflicted with the buffable
- public int damage = 0;
- [Tooltip("Keywords will be replaced: (STR, DEX, WILL, ABILITY_BASE_DAMAGE, BUFFABLE_BASE_DAMAGE, ITEM_BASE_DAMAGE)")]
- // Put in basic mathematical expressions
- // Use method to calculate string to a final damage value
- public string damageFormula = string.Empty;
- private int _finalDamage = 0;
- public virtual int finalDamage { get { return this._finalDamage; } }
- public BuffDuration buffDuration = BuffDuration.NONE;
- public TargetType targetType = TargetType.NONE;
- public float timedDuration = 0.0f;
- public ElapseType elapseType = ElapseType.NONE;
- public float interval = 0;
- [Header ("Conditions for applying")]
- [Range (0f, 1f)]
- public float applyChance = 1f;
- public bool lessThan;
- public bool equalTo;
- public bool greaterThan;
- public bool checkCurrentHealth;
- public int currentHealth;
- public bool checkPercentageCurrentHealth;
- [Range (0f, 1f)]
- public float percentageCurrentHealth;
- public delegate void OnInitializeEffect();
- public OnInitializeEffect onInitializeEffect;
- public delegate void OnStartEffect(Character target);
- public OnStartEffect onStartEffect;
- public delegate void OnUpdateEffect(Character target);
- public OnStartEffect onUpdateEffect;
- public delegate void OnEndEffect(Character target);
- public OnStartEffect onEndEffect;
- public Ability ability = null; // ability that applied the buffable
- private bool forceQuit = false;
- protected virtual void Awake ()
- {
- buffables.Add(this);
- if (gameObject.tag == "PlayerBuffable")
- playerBuffables.Add(this);
- else if (gameObject.tag == "AIBuffable")
- aiBuffables.Add(this);
- }
- // Update is called once per frame
- protected virtual void Update () {
- }
- public void CalculateFinalDamage()
- {
- /*
- * Keywords will be replaced: (STR, DEX, WILL, ABILITY_BASE_DAMAGE, BUFFABLE_BASE_DAMAGE, ITEM_BASE_DAMAGE)
- * EXCLUDED: (HERO_BASE_PHYSICAL_DAMAGE, HERO_BASE_RANGED_DAMAGE, HERO_BASE_WILL_DAMAGE)
- * Format must be: "STR"
- * Example: "2 * STR + BASE_DAMAGE"
- */
- int amount = 0;
- CombatStats stats = this.owner.GetComponent<CombatStats>();
- if(stats == null)
- {
- Debug.LogErrorFormat("Missing combat stats from {0}", this.owner);
- amount = this.damage;
- }
- else
- {
- if(this.damageFormula == "")
- {
- amount = this.damage;
- }
- else
- {
- try
- {
- string expression = damageFormula;
- expression = expression.Replace("STR", stats.str.ToString());
- expression = expression.Replace("DEX", stats.dex.ToString());
- expression = expression.Replace("WILL", stats.will.ToString());
- expression = expression.Replace("ABILITY_BASE_DAMAGE", this.ability.damage.ToString());
- expression = expression.Replace("BUFFABLE_BASE_DAMAGE", this.damage.ToString());
- expression = expression.Replace("ITEM_BASE_DAMAGE", this.ability.finalItemBaseDamage.ToString());
- // expression = expression.Replace("HERO_BASE_PHYSICAL_DAMAGE", stats.physicalDamage.ToString());
- // expression = expression.Replace("HERO_BASE_RANGED_DAMAGE", stats.rangedDamage.ToString());
- // expression = expression.Replace("HERO_BASE_WILL_DAMAGE", stats.willDamage.ToString());
- amount = (int)MathfExtension.Evaluate(expression);
- }
- catch(System.Exception e)
- {
- Debug.LogError(e);
- amount = this.damage;
- }
- }
- }
- this._finalDamage = amount;
- }
- private bool CheckSuccessfulApplication(Character target)
- {
- float r = Random.value;
- if(r > this.applyChance)
- {
- return false;
- }
- if(this.checkCurrentHealth)
- {
- if(!LogicOperator<int>(target.currentHealth, this.currentHealth))
- {
- return false;
- }
- }
- if(this.checkPercentageCurrentHealth)
- {
- if(!LogicOperator<float>((float)target.currentHealth/(float)target.maxHealth, this.percentageCurrentHealth))
- {
- return false;
- }
- }
- return true;
- }
- private bool LogicOperator<T>(T lhs, T rhs)
- {
- bool v = false;
- if(this.lessThan)
- {
- v = Comparer<T>.Default.Compare(lhs, rhs) < 0;
- }
- else if(this.greaterThan)
- {
- v = Comparer<T>.Default.Compare(lhs, rhs) > 0;
- }
- if(this.equalTo)
- {
- v = v || Comparer<T>.Default.Compare(lhs, rhs) == 0;
- }
- return v;
- }
- public void Initialize(Character affected, Character owner, Ability ability)
- {
- // check if it gets applied
- if(!this.CheckSuccessfulApplication(affected))
- {
- // failed, don't apply buffable
- GameObject.Destroy(this.gameObject);
- return;
- }
- this.affected = affected;
- this.owner = owner;
- this.ability = ability;
- // terminate buff when character is dead
- this.affected.onAIDeath += (string name) => { this.ForceQuit(); };
- this.affected.onPlayerDeath += (string name) => { this.ForceQuit(); };
- this.onInitializeEffect(); // calls BuffStart
- }
- protected virtual void BuffStart()
- {
- Debug.Log(string.Format("Starting buffable: {0}", this.name));
- foreach(Character target in this.afflictedTargets)
- {
- this.onStartEffect(target);
- target.buffables.Add(this);
- }
- // Handle interval buff
- if(elapseType == ElapseType.INTERVAL)
- {
- if(interval == 0)
- {
- Debug.LogWarning("interval is set to 0 while elapseType == ElapseType.INTERVAL");
- }
- StartCoroutine(UpdateDelay(interval));
- }
- else if(elapseType == ElapseType.CONSTANT)
- {
- StartCoroutine(EndDelay(timedDuration));
- }
- }
- private IEnumerator UpdateDelay(float delay)
- {
- float time = 0;
- while(true)
- {
- if(this.forceQuit) break;
- yield return new WaitForSeconds(delay);
- time += delay;
- // check buff duration
- if(buffDuration == BuffDuration.TIMED)
- {
- if(time >= timedDuration)
- {
- break;
- }
- }
- foreach(Character target in this.afflictedTargets)
- {
- this.onUpdateEffect(target);
- }
- }
- BuffEnd();
- }
- private IEnumerator EndDelay(float delay)
- {
- yield return new WaitForSeconds(delay);
- BuffEnd();
- }
- protected virtual void ForceQuit()
- {
- this.forceQuit = true;
- }
- protected virtual void BuffEnd()
- {
- if(buffDuration == BuffDuration.TIMED)
- {
- foreach(Character target in this.afflictedTargets)
- {
- this.onEndEffect(target);
- target.buffables.Remove(this);
- }
- Remove();
- }
- }
- protected virtual void Remove()
- {
- Debug.Log(string.Format("Buffable: {0} has ended", this.name));
- GameObject.Destroy(this.gameObject);
- }
- public List<Character> afflictedTargets
- {
- get
- {
- List<Character> targets = new List<Character>();
- // Decide target
- switch(targetType)
- {
- case TargetType.BOTH:
- targets.Add(owner);
- targets.Add(affected);
- break;
- case TargetType.SELF:
- targets.Add(owner);
- break;
- case TargetType.ENEMY:
- targets.Add(affected);
- break;
- }
- return targets;
- }
- }
- }
- public enum BuffDuration { NONE, PERMANENT, TIMED }
- public enum TargetType { NONE, SELF, ENEMY, BOTH }
- public enum ElapseType { NONE, CONSTANT, INTERVAL }
- /*
- * ElapseType:
- * None - None
- * Constant: Effects will only be active once in the begining and removed at the end
- * Interval: The effects will continue to apply on every internal, set above, then will end
- */
Advertisement
Add Comment
Please, Sign In to add comment