Files

216 lines
7.1 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Collections.Generic;
using Data;
using UnityEngine;
namespace Entity
{
/// <summary>
/// 表示一个具有生命周期、属性和可受健康状态Hediff影响的实体。
/// </summary>
public class LivingEntity : CombatantEntity
{
/// <summary>
/// 当健康状态Hediff被添加到实体时触发的事件。
/// </summary>
/// <param name="entity">触发事件的实体。</param>
/// <param name="hediff">被添加的Hediff实例。</param>
public delegate void HediffAppliedEventHandler(LivingEntity entity, Hediff hediff);
/// <summary>
/// 当健康状态Hediff从实体移除时触发的事件。
/// </summary>
/// <param name="entity">触发事件的实体。</param>
/// <param name="hediff">被移除的Hediff实例。</param>
public delegate void HediffRemovedEventHandler(LivingEntity entity, Hediff hediff);
public bool getBaseHediff;
private Attributes _cachedBaseAttributes;
// 标记实体属性是否需要重新计算。当Hediff发生变化时此标记会被设置为true。
private bool _needUpdateAttributes = true;
// 存储应用于此实体的所有健康状态Hediff列表。
protected List<Hediff> hediffs = new();
public EntityPathManager pathManager;
// 指示当前是否正在使用路径寻路模式。
private bool _isUsingPathfinding;
// 路径寻路的距离阈值。
private const float PATHFINDING_DISTANCE_THRESHOLD = 10f;
public LivingEntity()
{
pathManager = new EntityPathManager(this);
}
/// <summary>
/// 获取实体的基础属性。来源于实体的定义Def+健康状态。
/// </summary>
public override Attributes BaseAttributes
{
get
{
if (_cachedBaseAttributes == null || _needUpdateAttributes)
{
var defAttributes = DefAttributes;
var hediffOffset = new AttributesOffsetDef();
foreach (var hediff in Hediffs)
{
if (hediff.CurrentStage == null)
continue;
var attributes = hediff.CurrentStage?.attributesOffset;
if (attributes != null) hediffOffset += attributes;
}
_cachedBaseAttributes = defAttributes.GetModifiedAttributes(hediffOffset);
_needUpdateAttributes = false;
AttributesNow = Attributes.Min(AttributesNow, _cachedBaseAttributes);
}
return _cachedBaseAttributes;
}
}
public override bool OnTargetPoint => pathManager.IsPathComplete;
public virtual IReadOnlyList<Hediff> Hediffs => hediffs.AsReadOnly();
/// <summary>
/// Hediff被成功添加到此实体时触发。
/// </summary>
public event HediffAppliedEventHandler OnHediffAdded;
/// <summary>
/// Hediff被从此实体移除时触发。
/// </summary>
public event HediffRemovedEventHandler OnHediffRemoved;
/// <summary>
/// 供内部使用的属性标记方法。当 Hediff 自身状态改变并影响属性时,通过此方法通知 LivingEntity。
/// </summary>
public void SetAttribsDirty()
{
_needUpdateAttributes = true;
}
/// <summary>
/// 每帧调用的更新函数,传入时间增量。
/// </summary>
public override void Tick()
{
base.Tick();
for (var i = hediffs.Count - 1; i >= 0; i--)
{
var hediff = hediffs[i];
hediff.Tick(Time.deltaTime);
if (hediff.ShouldRemove) RemoveHediff(hediff);
}
}
/// <summary>
/// 添加一个新的健康状态到实体上。
/// </summary>
/// <param name="hediff">要添加的 Hediff 实例。</param>
public void AddHediff(Hediff hediff)
{
if (hediff == null)
{
Debug.LogWarning("警告: 尝试向活体实体添加一个空的健康状态Hediff。");
return;
}
hediffs.Add(hediff);
hediff.OnAdded(this);
SetAttribsDirty();
OnHediffAdded?.Invoke(this, hediff);
}
/// <summary>
/// 移除一个特定的健康状态。
/// </summary>
/// <param name="hediff">要移除的 Hediff 实例。</param>
public void RemoveHediff(Hediff hediff)
{
if (hediff == null)
{
Debug.LogWarning("警告: 尝试从活体实体移除一个空的健康状态Hediff。");
return;
}
if (hediffs.Remove(hediff))
{
hediff.OnRemoved(this);
SetAttribsDirty();
OnHediffRemoved?.Invoke(this, hediff);
}
}
/// <summary>
/// 设置实体的目标位置。
/// </summary>
/// <param name="pos">目标位置。</param>
/// <returns>如果目标设置成功则返回 true否则返回 false。</returns>
public override bool SetTarget(Vector3 pos)
{
bool baseSetResult = base.SetTarget(pos);
if (!baseSetResult)
{
_isUsingPathfinding = false;
return false;
}
float distance = (transform.position - pos).sqrMagnitude;
if (distance < PATHFINDING_DISTANCE_THRESHOLD * PATHFINDING_DISTANCE_THRESHOLD)
{
bool pathGenerated = pathManager.GeneratePath(pos);
if (pathGenerated)
{
_isUsingPathfinding = true;
return true;
}
else
{
_isUsingPathfinding = false;
return true;
}
}
else
{
_isUsingPathfinding = false;
return true;
}
}
/// <summary>
/// 尝试移动实体。
/// </summary>
public override void TryMove()
{
if (_isUsingPathfinding)
{
if (pathManager.IsPathComplete)
{
_isUsingPathfinding = false;
return;
}
_walkingTimer = 2;
var targetWorldPos = pathManager.GetNextPosition(transform.position, AttributesNow.moveSpeed);
Direction = targetWorldPos - transform.position;
SetBodyTexture(EntityState.Walking, CurrentOrientation);
transform.position = targetWorldPos;
}
else
{
base.TryMove();
}
}
}
}