401 lines
8.9 KiB
C#
401 lines
8.9 KiB
C#
using DragonLi.Core;
|
|
using DragonLi.Frame;
|
|
using Mirror;
|
|
using System;
|
|
using UnityEngine;
|
|
using UnityEngine.AI;
|
|
|
|
// IAgent
|
|
public class Agent : Entity, IDamagable, IRecordable
|
|
{
|
|
/// <summary>
|
|
/// Default value of spawnable
|
|
/// </summary>
|
|
public class AgentDefault : Default
|
|
{
|
|
/// <summary>
|
|
/// Animator of this entity
|
|
/// </summary>
|
|
public const string kAnimatorKey = "animator";
|
|
|
|
/// <summary>
|
|
/// Speed per second.
|
|
/// </summary>
|
|
public const float kSpeed = 10f;
|
|
|
|
public const string kSpeedKey = "speed";
|
|
|
|
/// <summary>
|
|
/// Acc per second.
|
|
/// </summary>
|
|
public const float kAcc = 30f;
|
|
|
|
public const string kAccKey = "acc";
|
|
|
|
/// <summary>
|
|
/// Health
|
|
/// </summary>
|
|
public const float kHealth = 100f;
|
|
|
|
public const string kHealthKey = "health";
|
|
|
|
/// <summary>
|
|
/// These values are key string in animator controller
|
|
/// We will calculate these values for you
|
|
/// speed: the mag of velocity vector3.
|
|
/// speed_f: the mag of velocity projects on transform.forword
|
|
/// speed_r: the mag of velocity projects on transform.right
|
|
/// </summary>
|
|
public const string kAnimatorKeySpeed = "speed";
|
|
|
|
public const string kAniamtorKeySpeedForword = "speedf";
|
|
|
|
public const string kAniamtorKeySpeedRight = "speedr";
|
|
|
|
public static readonly int AnimtorSpeedKeyHash = Animator.StringToHash("speed");
|
|
|
|
public static readonly int AnimtorSpeedFkeyHash = Animator.StringToHash("speedf");
|
|
|
|
public static readonly int AnimtorSpeedRkeyHash = Animator.StringToHash("speedr");
|
|
}
|
|
|
|
[NonSerialized]
|
|
[SyncVar]
|
|
public float health = 0f;
|
|
|
|
private DragonLiCamera mainCamera;
|
|
|
|
/// <summary>
|
|
/// All DamageParts belong to this agent
|
|
/// </summary>
|
|
protected DragonLiDamagePart[] DamageProxies;
|
|
|
|
private bool updateAniamtorSpeedvalue = false;
|
|
|
|
private bool updateAniamtorSpeedFvalue = false;
|
|
|
|
private bool updateAniamtorSpeedRvalue = false;
|
|
|
|
/// <summary>
|
|
/// Entity type using for world recording
|
|
/// </summary>
|
|
public string EntityType
|
|
{
|
|
get
|
|
{
|
|
return Data["entity_type"].StringValue;
|
|
}
|
|
set
|
|
{
|
|
this.LogEditorOnly("You can't set entity type in runtime.");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Health of this entity
|
|
/// </summary>
|
|
public float Health
|
|
{
|
|
get
|
|
{
|
|
return health;
|
|
}
|
|
set
|
|
{
|
|
health = value;
|
|
health = Mathf.Clamp(health, 0f, Data["health"].FloatValue);
|
|
OnHeathChanged(health);
|
|
}
|
|
}
|
|
|
|
[NonSerialized]
|
|
public float OriginHealth = 0f;
|
|
|
|
/// <summary>
|
|
/// Is agent alive?
|
|
/// </summary>
|
|
public bool IsAlive => Health > 0f;
|
|
|
|
/// <summary>
|
|
/// Is agent full health?
|
|
/// </summary>
|
|
public bool IsHealthy => Health == Data["health"].FloatValue;
|
|
|
|
/// <summary>
|
|
/// Get main camera currently in task system
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public DragonLiCamera MainCamera
|
|
{
|
|
get
|
|
{
|
|
if (mainCamera == null)
|
|
{
|
|
mainCamera = GetMainCamera();
|
|
}
|
|
if (mainCamera == null)
|
|
{
|
|
this.LogEditorOnly("RainCamera you want to get is null.");
|
|
}
|
|
return mainCamera;
|
|
}
|
|
}
|
|
|
|
private NavMeshAgent agent;
|
|
|
|
/// <summary>
|
|
/// NavMesh Agent of this Agent
|
|
/// </summary>
|
|
public NavMeshAgent NavAgent
|
|
{
|
|
get
|
|
{
|
|
if (agent == null)
|
|
{
|
|
agent = GetComponent<NavMeshAgent>();
|
|
}
|
|
return agent;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add damage
|
|
/// </summary>
|
|
/// <param name="value">How much</param>
|
|
/// <param name="info">Some information about this damage you want to tell damage receiver</param>
|
|
/// <param name="_sender">Who take this damage</param>
|
|
[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);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Let this entity die, and tell task system.
|
|
/// </summary>
|
|
public virtual void Die(object info, Transform _sender)
|
|
{
|
|
// MonoSingleton<CoroutineTaskManager>.Instance.WaitFrameEnd(delegate
|
|
// {
|
|
// World.RemoveEntity(EntityType, this);
|
|
// });
|
|
OnDeath(info, _sender);
|
|
}
|
|
|
|
/// <summary>
|
|
/// On entity enable, this will be called when entity was being spawned.
|
|
/// </summary>
|
|
public virtual void OnSpawn()
|
|
{
|
|
Health = Data["health"].FloatValue;
|
|
OriginHealth = Health;
|
|
ResetDamageProxies();
|
|
OnBorn();
|
|
}
|
|
|
|
/// <summary>
|
|
/// On spawn event this entity belonged reset, this function will be called.
|
|
/// </summary>
|
|
public virtual void OnSpawnerReset()
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// On entity die, this will be called, you can write despawn functions here.
|
|
/// </summary>
|
|
public virtual void OnDeath(object info, Transform _sender)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// When agent receives damage this function will be called
|
|
/// If you want to re calculate damage you can do it here.
|
|
/// </summary>
|
|
/// <param name="value">How much</param>
|
|
/// <param name="info">Some information about this damage you want to tell damage receiver</param>
|
|
/// <param name="_sender">Who take this damage</param>
|
|
/// <returns></returns>
|
|
protected virtual float OnReceiveDamage(float value, object info, Transform _sender)
|
|
{
|
|
return value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// When health changed this function will be called
|
|
/// </summary>
|
|
/// <param name="currentHealth">current health</param>
|
|
public virtual void OnHeathChanged(float currentHealth)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// When this entity has been born
|
|
/// </summary>
|
|
protected virtual void OnBorn()
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// On task system boradcast message, this function will be called.
|
|
/// </summary>
|
|
/// <param name="msg">Message</param>
|
|
/// <param name="sender">Message sender</param>
|
|
public virtual void OnReceiveBroadcast(string msg, object sender)
|
|
{
|
|
|
|
}
|
|
|
|
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
|
|
});
|
|
}
|
|
|
|
internal override void Update()
|
|
{
|
|
if (IsAlive && updateSelf && DragonLiEntity.ShouldUpdate)
|
|
{
|
|
if (base.RigidbodyComponent != null)
|
|
{
|
|
UpdateAniamtorValues(base.RigidbodyComponent.velocity);
|
|
}
|
|
base.Update();
|
|
}
|
|
}
|
|
|
|
public override void OnEnable()
|
|
{
|
|
DamageProxies = GetComponentsInChildren<DragonLiDamagePart>();
|
|
base.OnEnable();
|
|
}
|
|
|
|
public override void Awake()
|
|
{
|
|
InitAnimator();
|
|
base.Awake();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Update animator value for you.
|
|
/// </summary>
|
|
/// <param name="vel">Velocity of this entity</param>
|
|
[Server]
|
|
protected void UpdateAniamtorValues(Vector3 vel)
|
|
{
|
|
if (base.AnimatorComponent != null)
|
|
{
|
|
if (updateAniamtorSpeedvalue)
|
|
{
|
|
base.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))));
|
|
base.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))));
|
|
base.AnimatorComponent.SetFloat(AgentDefault.AnimtorSpeedRkeyHash, num2);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Init animator
|
|
/// </summary>
|
|
private void InitAnimator()
|
|
{
|
|
if (base.AnimatorComponent == null)
|
|
{
|
|
return;
|
|
}
|
|
AnimatorControllerParameter[] parameters = base.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 DragonLiCamera GetMainCamera()
|
|
{
|
|
Transform val = World.GetMainCamera();
|
|
if (val == null)
|
|
{
|
|
this.LogEditorOnly("Failed to get main camera.");
|
|
return null;
|
|
}
|
|
DragonLiCamera component = val.GetComponent<DragonLiCamera>();
|
|
if (component == null)
|
|
{
|
|
this.LogEditorOnly("There is no RainCamera on MainCamera.");
|
|
}
|
|
return component;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|