mirror of
http://47.107.252.169:3000/Roguelite-Game-Developing-Team/Gen_Hack-and-Slash-Roguelite.git
synced 2025-11-20 11:27:14 +08:00
(client) feat:健康给予,路径优化,结算界面,商店界面 (#60)
Co-authored-by: m0_75251201 <m0_75251201@noreply.gitcode.com> Reviewed-on: http://47.107.252.169:3000/Roguelite-Game-Developing-Team/Gen_Hack-and-Slash-Roguelite/pulls/60
This commit is contained in:
@@ -1,187 +1,215 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Data;
|
||||
using Managers;
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Entity
|
||||
{
|
||||
// 假设 Entity 基类如下结构
|
||||
// public abstract class Entity
|
||||
// {
|
||||
// public virtual Attributes baseAttributes { get; protected set; } = new Attributes();
|
||||
// public virtual Attributes attributes { get; protected set; } = new Attributes();
|
||||
// public virtual void Tick(float deltaTime) { /* Base entity update logic */ }
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// 表示一个具有生命周期、属性和可受健康状态(Hediff)影响的实体。
|
||||
/// 表示一个具有生命周期、属性和可受健康状态(Hediff)影响的实体。
|
||||
/// </summary>
|
||||
public class LivingEntity : CombatantEntity
|
||||
{
|
||||
// 存储应用于此实体的所有健康状态(Hediff)列表。
|
||||
protected List<Hediff> hediffs = new List<Hediff>();
|
||||
/// <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;
|
||||
private bool _needUpdateAttributes = true;
|
||||
|
||||
// 缓存实体的基础属性,这些属性不受动态Hediff影响,但可能受基类或Def影响。
|
||||
private Attributes _cachedBaseAttributes;
|
||||
/// <summary>
|
||||
/// 获取实体的基础属性。这些属性通常来源于实体的定义(Def),并可能受到常驻的基础健康状态(Base Hediffs)影响。
|
||||
/// </summary>
|
||||
public override Attributes baseAttributes
|
||||
{
|
||||
get
|
||||
{
|
||||
// 仅在 _cachedBaseAttributes 为 null 时计算一次
|
||||
if(_cachedBaseAttributes == null)
|
||||
{
|
||||
var defAttributes = base.baseAttributes;
|
||||
var hediffOffset = new AttributesOffsetDef();
|
||||
|
||||
foreach (var hediff in HediffManager.Instance.BaseHediffs)
|
||||
{
|
||||
hediffOffset += hediff.CurrentTotalAttributesOffset;
|
||||
}
|
||||
_cachedBaseAttributes = defAttributes.GetModifiedAttributes(hediffOffset);
|
||||
}
|
||||
return _cachedBaseAttributes;
|
||||
}
|
||||
}
|
||||
|
||||
// 缓存实体当前的最终属性,该属性是基础属性加上所有健康状态(Hediff)修正后的结果。
|
||||
private Attributes _cachedAttributes;
|
||||
/// <summary>
|
||||
/// 获取实体当前的最终属性,包括所有健康状态(Hediff)的修正。
|
||||
/// </summary>
|
||||
public override Attributes AttributesNow
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_needUpdateAttributes || _cachedAttributes == null)
|
||||
{
|
||||
// 1. 获取旧的属性值(在重新计算之前,也就是当前的缓存值)
|
||||
// 仅用于需要与“当前值”进行比较或钳制的情况,例如最大生命值Buff移除时
|
||||
var oldCachedAttributes = _cachedAttributes;
|
||||
if (oldCachedAttributes == null) // 如果是第一次计算,初始化一个默认值或者使用baseAttributes
|
||||
{
|
||||
oldCachedAttributes = baseAttributes;
|
||||
}
|
||||
|
||||
// 2. 计算完全修正后的“理论”最大属性值(基于 baseAttributes 和所有 Hediff 偏移)
|
||||
var totalModifiedAttributes = baseAttributes;
|
||||
|
||||
var hediffOffset = new AttributesOffsetDef();
|
||||
foreach (var hediff in hediffs)
|
||||
{
|
||||
hediffOffset += hediff.CurrentTotalAttributesOffset;
|
||||
}
|
||||
|
||||
// 应用所有 hediff 的偏移到 totalModifiedAttributes
|
||||
totalModifiedAttributes = totalModifiedAttributes.GetModifiedAttributes(hediffOffset);
|
||||
_cachedAttributes = Attributes.Min(oldCachedAttributes, totalModifiedAttributes);
|
||||
// 标记为已更新
|
||||
_needUpdateAttributes = false;
|
||||
}
|
||||
return _cachedAttributes;
|
||||
}
|
||||
protected set => _cachedAttributes = value;
|
||||
}
|
||||
// 存储应用于此实体的所有健康状态(Hediff)列表。
|
||||
protected List<Hediff> hediffs = new();
|
||||
|
||||
public EntityPathManager pathManager;
|
||||
|
||||
public override bool OnTargetPoint => pathManager.IsPathComplete;
|
||||
|
||||
// 指示当前是否正在使用路径寻路模式。
|
||||
private bool _isUsingPathfinding;
|
||||
// 路径寻路的距离阈值。
|
||||
private const float PATHFINDING_DISTANCE_THRESHOLD = 10f;
|
||||
|
||||
public LivingEntity()
|
||||
{
|
||||
pathManager = new EntityPathManager(this);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 供内部使用的属性标记方法。当 Hediff 自身状态改变并影响属性时,通过此方法通知 LivingEntity。
|
||||
/// 获取实体的基础属性。来源于实体的定义(Def)+健康状态。
|
||||
/// </summary>
|
||||
internal void SetAttribsDirty()
|
||||
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(); // 调用基类的Tick方法
|
||||
base.Tick();
|
||||
|
||||
// 遍历并更新所有健康状态,从后向前循环以安全地移除已完成的Hediff
|
||||
for (var i = hediffs.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var hediff = hediffs[i];
|
||||
hediff.Tick(Time.deltaTime); // 调用单个Hediff的Tick方法
|
||||
hediff.Tick(Time.deltaTime);
|
||||
|
||||
// 检查Hediff是否已达到移除条件
|
||||
if (hediff.ShouldRemove)
|
||||
{
|
||||
RemoveHediff(hediff); // 使用RemoveHediff方法确保OnRemoved被调用并设置_needUpdateAttributes
|
||||
}
|
||||
if (hediff.ShouldRemove) RemoveHediff(hediff);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加一个新的健康状态到实体上。
|
||||
/// 添加一个新的健康状态到实体上。
|
||||
/// </summary>
|
||||
/// <param name="hediff">要添加的 Hediff 实例。</param>
|
||||
public void AddHediff(Hediff hediff)
|
||||
{
|
||||
if (hediff == null)
|
||||
{
|
||||
Debug.LogWarning("尝试向活体实体添加一个空的健康状态(Hediff)。");
|
||||
Debug.LogWarning("警告: 尝试向活体实体添加一个空的健康状态(Hediff)。");
|
||||
return;
|
||||
}
|
||||
|
||||
hediffs.Add(hediff);
|
||||
// 通知Hediff它被添加到一个实体上,进行初始化等操作,并传入自身引用
|
||||
hediff.OnAdded(this);
|
||||
_needUpdateAttributes = true; // 添加新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)。");
|
||||
Debug.LogWarning("警告: 尝试从活体实体移除一个空的健康状态(Hediff)。");
|
||||
return;
|
||||
}
|
||||
|
||||
// 尝试从列表中移除Hediff
|
||||
if (hediffs.Remove(hediff))
|
||||
{
|
||||
// 通知Hediff它被从实体上移除,进行清理等操作,并传入自身引用
|
||||
hediff.OnRemoved(this);
|
||||
_needUpdateAttributes = true; // 移除Hediff,需要更新属性缓存
|
||||
hediff.OnRemoved(this);
|
||||
SetAttribsDirty();
|
||||
OnHediffRemoved?.Invoke(this, hediff);
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetTarget(Vector3 pos)
|
||||
/// <summary>
|
||||
/// 设置实体的目标位置。
|
||||
/// </summary>
|
||||
/// <param name="pos">目标位置。</param>
|
||||
/// <returns>如果目标设置成功则返回 true,否则返回 false。</returns>
|
||||
public override bool SetTarget(Vector3 pos)
|
||||
{
|
||||
base.SetTarget(pos);
|
||||
pathManager.GeneratePath(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 (pathManager.IsPathComplete)
|
||||
return;
|
||||
_walkingTimer = 2;
|
||||
var target= pathManager.GetNextPosition(Position, AttributesNow.moveSpeed);
|
||||
Direction = target - Position;
|
||||
SetBodyTexture(EntityState.Walking, CurrentOrientation);
|
||||
transform.position = target;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user