using System; using System.Collections.Generic; using Sirenix.OdinInspector; using Sirenix.Utilities; using UnityEngine; using VOID.Generic.Dict; using VOID.Generic.Objects.Abstract.Events; using VOID.Generic.Triggers; namespace VOID.Generic.Objects.Abstract { [SelectionBase] [DisallowMultipleComponent] [RequireComponent(typeof(Rigidbody))] public abstract class AbstractObject : MonoBehaviour { [Title("=== BasicObject properties ===")] public AbstractObjectData basicData; public AbstractObjectEvents basicEvents; public AbstractObjectStatusManager statusManager; public AbstractObjectState basicState; protected void OnValidate() { gameObject.GetComponent().hideFlags = HideFlags.NotEditable; // Init RigidBody var rb = GetComponent(); rb.mass = 0; rb.linearDamping = 0; rb.angularDamping = 0; rb.automaticCenterOfMass = true; rb.automaticInertiaTensor = true; rb.useGravity = false; rb.isKinematic = true; rb.interpolation = RigidbodyInterpolation.None; rb.constraints = RigidbodyConstraints.FreezeAll; } private void Awake() { GetObjectComponents().ForEach(component => component.SetParent(this)); GetObjectComponents().ForEach(component => component.DoSelfInitialize()); GetObjectComponents().ForEach(component => component.DoEventInitialize()); GetObjectComponents().ForEach(component => component.DoInitialize()); } private void Start() { // Finally when this object is fully initialized then we can basicEvents.onSpawn.Invoke(); } protected void FixedUpdate() { basicEvents.onFixedUpdate.Invoke(); } protected virtual List GetObjectComponents() { return new List { basicData, basicEvents, statusManager, basicState }; } [Button] public void TakeDamage(DamageEvent damageEvent) { if (basicState.isDead) return; if (!basicData.canBeDestroyed) return; basicEvents.onDamagedBefore.Invoke(damageEvent); if (damageEvent.attacker) damageEvent.attacker.unitEvents.onDamageBefore.Invoke(damageEvent); if (damageEvent.prevented) return; var damage = damageEvent.amount; var resistance = 1 - basicData.resistances.Get(damageEvent.damageType); basicData.UseResource(BasicResourceType.Health, damage * resistance, true); basicEvents.onDamagedAfter.Invoke(damageEvent); if (damageEvent.attacker) damageEvent.attacker.unitEvents.onDamageAfter.Invoke(damageEvent); if (basicData.currentResources.health <= 0f) Death(); } [Button] public void Death() { if (basicState.isDead) return; if (!basicData.canBeDestroyed) return; var deathEvent = new DeathEvent { obj = this }; basicEvents.onDeathBefore.Invoke(deathEvent); if (deathEvent.prevented) return; basicEvents.onDeathAfter.Invoke(deathEvent); basicData.currentResources.health = 0f; } [Button] public void Revive() { if (basicState.isDead == false) return; basicData.SetResourcePercentage(BasicResourceType.Health, 0.3f); basicEvents.onRevive.Invoke(new ReviveEvent { obj = this }); } [Button] public void Remove() { var removeEvent = new RemoveEvent { obj = this }; basicEvents.onRemove.Invoke(removeEvent); Destroy(gameObject); } private void OnTriggerEnter(Collider other) { other.GetComponentsInParent().ForEach(triggerArea => { if (basicState.isDead == false) triggerArea.OnObjectEnter(this); basicEvents.onTriggerEnter.Invoke(new TriggerEvent { obj = this, triggerArea = triggerArea }); }); } private void OnTriggerExit(Collider other) { other.GetComponentsInParent().ForEach(triggerArea => { if (basicState.isDead == false) triggerArea.OnObjectExit(this); basicEvents.onTriggerExit.Invoke(new TriggerEvent { obj = this, triggerArea = triggerArea }); }); } } }