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;
}
}