using DragonLi.Core; using DragonLi.Frame; using Mirror; using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; // IAgent public class Agent : Entity, IDamagable { /// /// Default value of spawnable /// public class AgentDefault : Default { public static readonly int AnimtorSpeedKeyHash = Animator.StringToHash("speed"); public static readonly int AnimtorSpeedFkeyHash = Animator.StringToHash("speedf"); public static readonly int AnimtorSpeedRkeyHash = Animator.StringToHash("speedr"); } /// /// All DamageParts belong to this agent /// protected DragonLiDamagePart[] DamageProxies; private bool updateAniamtorSpeedvalue = false; private bool updateAniamtorSpeedFvalue = false; private bool updateAniamtorSpeedRvalue = false; #if UNITY_EDITOR [DisplayOnly] #endif [SyncVar] public float health = 0f; /// /// Health of this entity /// /// public float Health { get { return health; } set { health = value; health = Mathf.Clamp(health, 0f, OriginHealth); OnHeathChanged(health); } } [NonSerialized] [SyncVar] public float OriginHealth = 0f; /// /// Is agent alive? /// public bool IsAlive => Health > 0f; /// /// Is agent full health? /// public bool IsHealthy => Health == OriginHealth; private NavMeshAgent agent; /// /// NavMesh Agent of this Agent /// public NavMeshAgent NavAgent { get { if (agent == null) { agent = GetComponent(); } return agent; } } public bool isUserSkill; public bool isUserHpSkill; public int userHpSkillIndex; public float waitSkillTime = 30; public float curWaitSkillTime = 0; public List skillList = new List(); public Transform skillPos; public float skillHpInterval; public int campId; /// /// Add damage /// /// How much /// Some information about this damage you want to tell damage receiver /// Who take this damage [Server] public virtual void ApplyDamage(float value, object info, Transform _sender) { // Debug.Log("造成伤害1" + IsAlive + " " + !Data["partdamage"].BooleanValue + " " + IsProxyDamage(info)); if (IsAlive && (!Data["partdamage"].BooleanValue || IsProxyDamage(info))) { Health -= OnReceiveDamage(value, info, _sender); if (!IsAlive) { Die(info, _sender); } } } /// /// Let this entity die, and tell task system. /// public virtual void Die(object info, Transform _sender) { OnDeath(info, _sender); } [Server] /// /// On entity enable, this will be called when entity was being spawned. /// public virtual void OnSpawn() { ResetDamageProxies(); OnBorn(); } /// /// On entity die, this will be called, you can write despawn functions here. /// public virtual void OnDeath(object info, Transform _sender) { } /// /// When agent receives damage this function will be called /// If you want to re calculate damage you can do it here. /// /// How much /// Some information about this damage you want to tell damage receiver /// Who take this damage /// public virtual float OnReceiveDamage(float value, object info, Transform _sender) { return value; } /// /// When health changed this function will be called /// /// current health [Server] public virtual void OnHeathChanged(float currentHealth) { } /// /// When this entity has been born /// public virtual void OnBorn() { } public override void InitData() { Data.Add("entity_type", new DataRow(SupportDataType.String) { Name = "entity_type" }); Data.Add("speed", new DataRow(SupportDataType.Float) { Name = "speed", FloatValue = 10f }); Data.Add("acc", new DataRow(SupportDataType.Float) { Name = "acc", FloatValue = 30f }); Data.Add("health", new DataRow(SupportDataType.Float) { Name = "health", FloatValue = 100f }); Data.Add("partdamage", new DataRow(SupportDataType.Boolean) { Name = "partdamage", BooleanValue = false }); } public override void Update() { if (isServer && IsAlive) { if (NavAgent != null & NavAgent.enabled) { UpdateAniamtorValues(NavAgent.velocity); } else if (RigidbodyComponent) { UpdateAniamtorValues(RigidbodyComponent.velocity); } OnUpdate(); } } public override void OnEnable() { DamageProxies = GetComponentsInChildren(); base.OnEnable(); } public override void Awake() { base.Awake(); InitAnimator(); } /// /// Update animator value for you. /// /// Velocity of this entity [Server] protected void UpdateAniamtorValues(Vector3 vel) { if (AnimatorComponent != null) { if (updateAniamtorSpeedvalue) { AnimatorComponent.SetFloat(AgentDefault.AnimtorSpeedKeyHash, vel.magnitude); } Vector3 val; if (updateAniamtorSpeedFvalue) { val = Vector3.Project(vel, transform.forward); float num = (val.magnitude / (vel.magnitude * (float)((!(Vector3.Angle(vel, transform.forward) > 90f)) ? 1 : (-1)))); AnimatorComponent.SetFloat(AgentDefault.AnimtorSpeedFkeyHash, num); } if (updateAniamtorSpeedRvalue) { val = Vector3.Project(vel, transform.right); float num2 = (val.magnitude / (vel.magnitude * (float)((!(Vector3.Angle(vel, transform.right) > 90f)) ? 1 : (-1)))); AnimatorComponent.SetFloat(AgentDefault.AnimtorSpeedRkeyHash, num2); } } } /// /// Init animator /// private void InitAnimator() { if (AnimatorComponent == null) { return; } AnimatorControllerParameter[] parameters = AnimatorComponent.parameters; foreach (AnimatorControllerParameter val in parameters) { if ((int)val.type == 1) { switch (val.name) { case "speed": updateAniamtorSpeedvalue = true; break; case "speedr": updateAniamtorSpeedRvalue = true; break; case "speedf": updateAniamtorSpeedFvalue = true; break; } } } } private void ResetDamageProxies() { if (DamageProxies != null) { DragonLiDamagePart[] damageProxies = DamageProxies; foreach (DragonLiDamagePart dragonLiDamagePart in damageProxies) { dragonLiDamagePart.ResetDamagePart(); } } } private bool IsProxyDamage(object info) { DragonLiDamagePart dragonLiDamagePart = info as DragonLiDamagePart; return dragonLiDamagePart == null; } }