using MalbersAnimations.Controller; using MalbersAnimations.Controller.Reactions; using MalbersAnimations.Events; using MalbersAnimations.Scriptables; using UnityEngine; using UnityEngine.Events; #if UNITY_EDITOR using UnityEditor; #endif namespace MalbersAnimations { [DisallowMultipleComponent] /// Damager Receiver [AddComponentMenu("Malbers/Damage/MDamageable")] [HelpURL("https://malbersanimations.gitbook.io/animal-controller/secondary-components/mdamageable")] public class MDamageable : MonoBehaviour, IMDamage { [Tooltip("Animal Reaction to apply when the damage is done")] public Component character; [Tooltip("Animal Reaction to apply when the damage is done")] public MReaction reaction; [Tooltip("Stats component to apply the Damage")] public Stats stats; [Tooltip("Multiplier for the Stat modifier Value")] public FloatReference multiplier = new FloatReference(1); public MDamageable Root; public damagerEvents events; public Vector3 HitDirection { get; set; } public GameObject Damager { get; set; } public GameObject Damagee => gameObject; public DamageData LastDamage; private void Start() { if (character == null) character = stats.GetComponent(reaction.ReactionType()); } public virtual void ReceiveDamage(Vector3 Direction, GameObject Damager, StatModifier modifier, bool isCritical, bool react, MReaction customReaction, bool pureDamage) { if (!enabled) return; //This makes the Animal Immortal. SetDamageable(Direction, Damager); Root?.SetDamageable(Direction, Damager); //Send the Direction and Damager to the Root if (isCritical) { events.OnCriticalDamage.Invoke(); Root?.events.OnCriticalDamage.Invoke(); } if (!pureDamage) modifier.Value *= multiplier; //Apply to the Stat modifier a new Modification events.OnReceivingDamage.Invoke(modifier.Value); Root?.events.OnReceivingDamage.Invoke(modifier.Value); LastDamage = new DamageData(Damager, modifier); if (Root) Root.LastDamage = LastDamage; modifier.ModifyStat(stats.Stat_Get(modifier.ID)); if (customReaction) customReaction.React(character); //Custom reaction else if (react && reaction) { reaction.React(character); //Lets React } } /// Receive Damage from external sources simplified /// What stat will be modified /// value to substact to the stat public virtual void ReceiveDamage(StatID stat, float amount) { var modifier = new StatModifier(){ ID = stat, modify = StatOption.SubstractValue, Value = amount}; ReceiveDamage(Vector3.forward, null, modifier, false, true, null, false); } /// Receive Damage from external sources simplified /// What stat will be modified /// value to substact to the stat public virtual void ReceiveDamage(StatID stat, float amount, StatOption modifyStat = StatOption.SubstractValue) { var modifier = new StatModifier() { ID = stat, modify = modifyStat, Value = amount }; ReceiveDamage(Vector3.forward, null, modifier, false, true, null, false); } /// Receive Damage from external sources simplified /// Where the Damage is coming from /// Who is doing the Damage /// What Stat will be modified /// Type of modification applied to the stat /// is the Damage Critical? /// Does Apply the Default Reaction? /// if is pure Damage, do not apply the default multiplier /// What stat will be modified /// value to substact to the stat public virtual void ReceiveDamage(Vector3 Direction, GameObject Damager, StatID stat, float amount, StatOption modifyStat = StatOption.SubstractValue, bool isCritical = false, bool react = true, MReaction customReaction = null, bool pureDamage = false) { var modifier = new StatModifier() { ID = stat, modify = modifyStat, Value = amount }; ReceiveDamage(Direction, Damager, modifier, isCritical, react, customReaction, pureDamage); } /// Receive Damage from external sources simplified /// Where the Damage is coming from /// Who is doing the Damage /// What Stat will be modified /// is the Damage Critical? /// Does Apply the Default Reaction? /// if is pure Damage, do not apply the default multiplier /// What stat will be modified /// value to substact to the stat public virtual void ReceiveDamage(Vector3 Direction, GameObject Damager, StatID stat, float amount, bool isCritical = false, bool react = true, MReaction customReaction = null, bool pureDamage = false) { var modifier = new StatModifier() { ID = stat, modify = StatOption.SubstractValue, Value = amount }; ReceiveDamage(Direction, Damager, modifier, isCritical, react, customReaction, pureDamage); } internal void SetDamageable(Vector3 Direction, GameObject Damager) { HitDirection = Direction; this.Damager = Damager; } [System.Serializable] public class damagerEvents { // public UnityEvent BeforeReceivingDamage = new UnityEvent(); public FloatEvent OnReceivingDamage = new FloatEvent(); // public UnityEvent AfterReceivingDamage = new UnityEvent(); public UnityEvent OnCriticalDamage = new UnityEvent(); } public struct DamageData { /// Who made the Damage ? public GameObject Damager; /// Final Stat Modifier ? public StatModifier stat; /// Final value who modified the Stat public float Damage => stat.modify != StatOption.None ? stat.Value.Value : 0f; public DamageData(GameObject damager, StatModifier stat) { Damager = damager; this.stat = new StatModifier(stat); } } #if UNITY_EDITOR private void Reset() { reaction = MTools.GetInstance("Damaged"); stats = this.FindComponent(); Root = transform.root.GetComponent(); //Check if there's a Damageable on the Root if (Root == this) Root = null; if (stats == null) { stats = gameObject.AddComponent(); } } #endif } #if UNITY_EDITOR [CustomEditor(typeof(MDamageable))] public class MDamageableEditor : Editor { SerializedProperty reaction, stats, multiplier, events, Root; MDamageable M; private void OnEnable() { M = (MDamageable)target; reaction = serializedObject.FindProperty("reaction"); stats = serializedObject.FindProperty("stats"); multiplier = serializedObject.FindProperty("multiplier"); events = serializedObject.FindProperty("events"); Root = serializedObject.FindProperty("Root"); } public override void OnInspectorGUI() { serializedObject.Update(); MalbersEditor.DrawDescription("Allows the Animal React and Receive damage from external sources"); EditorGUILayout.BeginVertical(MalbersEditor.StyleGray); EditorGUILayout.BeginVertical(EditorStyles.helpBox); if (M.transform.parent != null) EditorGUILayout.PropertyField(Root); EditorGUILayout.PropertyField(reaction); EditorGUILayout.PropertyField(stats); EditorGUILayout.PropertyField(multiplier); EditorGUILayout.EndVertical(); EditorGUILayout.BeginVertical(EditorStyles.helpBox); EditorGUI.indentLevel++; EditorGUILayout.PropertyField(events,true); EditorGUI.indentLevel--; EditorGUILayout.EndVertical(); EditorGUILayout.EndVertical(); serializedObject.ApplyModifiedProperties(); } } #endif }