(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:
2025-10-10 14:08:23 +08:00
parent 9a797479ff
commit 16b49f3d3a
1900 changed files with 114053 additions and 34157 deletions

View File

@@ -4,15 +4,17 @@ using System.Text;
using Data;
using Parsing;
using UnityEngine;
using Utils;
namespace AI
{
public abstract class CompositeNodeBase:BehaviorTreeBase
public abstract class CompositeNodeBase : BehaviorTreeBase
{
// 组合节点特有的成员:子行为树列表
protected List<BehaviorTreeBase> children = new();
/// <summary>
/// 初始化组合行为树节点及其子节点。
/// 初始化组合行为树节点及其子节点。
/// </summary>
/// <param name="def">行为树定义。</param>
/// <param name="selfEntity">关联的实体。</param>
@@ -22,45 +24,44 @@ namespace AI
if (def.childTree == null) return;
foreach (var childDef in def.childTree)
{
var childNode = Utils.BehaviorTreeUtils.ConvertToAIBase(childDef);
var childNode = BehaviorTreeUtils.ConvertToAIBase(childDef);
if (childNode == null) continue;
children.Add(childNode);
childNode.Init(childDef, selfEntity); // 递归初始化子节点
}
}
/// <summary>
/// 重置组合行为树节点的状态及其所有子节点的状态。
/// 重置组合行为树节点的状态及其所有子节点的状态。
/// </summary>
public override void Reset()
{
base.Reset(); // 调用基类Reset重置自身状态
foreach (var child in children)
{
child?.Reset(); // 确保子节点不为 null 时才调用 Reset
}
foreach (var child in children) child?.Reset(); // 确保子节点不为 null 时才调用 Reset
}
/// <summary>
/// 返回表示当前行为树节点及其子节点层次结构的字符串。
/// 返回表示当前行为树节点及其子节点层次结构的字符串。
/// </summary>
/// <returns>行为树的层次结构字符串。</returns>
public override string ToString()
{
return ToString(0); // 从根节点开始初始缩进为0
}
/// <summary>
/// 返回表示当前行为树节点及其子节点层次结构的字符串,带有指定缩进。
/// 返回表示当前行为树节点及其子节点层次结构的字符串,带有指定缩进。
/// </summary>
/// <param name="indent">当前节点的缩进级别。</param>
/// <returns>行为树的层次结构字符串。</returns>
protected virtual string ToString(int indent)
{
StringBuilder sb = new StringBuilder();
string indentStr = new string(' ', indent * 2); // 每个级别2个空格
sb.AppendLine($"{indentStr}[{this.GetType().Name}] ");
var sb = new StringBuilder();
var indentStr = new string(' ', indent * 2); // 每个级别2个空格
sb.AppendLine($"{indentStr}[{GetType().Name}] ");
foreach (var child in children)
{
// 确保子节点不为 null 且支持 ToString(int) 方法
if (child is CompositeNodeBase compositeChild)
if (child is CompositeNodeBase compositeChild)
{
sb.Append(compositeChild.ToString(indent + 1));
}
@@ -68,21 +69,21 @@ namespace AI
{
// 如果子节点不是复合节点但有自己的ToString实现直接调用其ToString
// 否则打印其类型和ID/名称
string childIndentStr = new string(' ', (indent + 1) * 2);
var childIndentStr = new string(' ', (indent + 1) * 2);
sb.AppendLine($"{childIndentStr}[{child.GetType().Name}] ");
}
}
return sb.ToString();
}
}
public class ThinkNode_Selector : CompositeNodeBase
{
// 用于跟踪正在运行的子节点索引
protected int currentChildIndex = 0;
protected int currentChildIndex;
/// <summary>
/// 执行选择器节点的逻辑。它会按顺序执行子节点,直到一个子节点成功或正在运行。
/// 执行选择器节点的逻辑。它会按顺序执行子节点,直到一个子节点成功或正在运行。
/// </summary>
/// <returns>节点的执行状态。</returns>
public override Status Tick()
@@ -118,7 +119,7 @@ namespace AI
}
/// <summary>
/// 重置选择器节点的状态,包括子节点索引。
/// 重置选择器节点的状态,包括子节点索引。
/// </summary>
public override void Reset()
{
@@ -133,7 +134,7 @@ namespace AI
private Func<Entity.Entity, bool> condition;
/// <summary>
/// 初始化条件节点,创建条件委托。
/// 初始化条件节点,创建条件委托。
/// </summary>
/// <param name="def">行为树定义。</param>
/// <param name="selfEntity">关联的实体。</param>
@@ -141,7 +142,6 @@ namespace AI
{
base.Init(def, selfEntity); // 调用基类的 Init 方法,初始化子节点和 SelfEntity
if (!string.IsNullOrEmpty(def.value))
{
try
{
condition = ConditionDelegateFactory.CreateConditionDelegate(
@@ -154,17 +154,14 @@ namespace AI
{
// 记录错误,并使条件始终不满足
Debug.LogError($"无法为 '{def.value}' 创建条件委托: {ex.Message}");
condition = (e) => false;
condition = e => false;
}
}
else
{
condition = (e) => false; // 如果没有指定条件,则条件始终不满足
}
condition = e => false; // 如果没有指定条件,则条件始终不满足
}
/// <summary>
/// 执行条件节点的逻辑。首先检查条件,如果条件满足则执行其子节点(作为选择器)。
/// 执行条件节点的逻辑。首先检查条件,如果条件满足则执行其子节点(作为选择器)。
/// </summary>
/// <returns>节点的执行状态。</returns>
public override Status Tick()
@@ -185,10 +182,10 @@ namespace AI
public class ThinkNode_Sequence : CompositeNodeBase
{
// 用于跟踪正在运行的子节点索引
private int currentChildIndex = 0;
private int currentChildIndex;
/// <summary>
/// 执行序列器节点的逻辑。它会按顺序执行子节点,直到一个子节点失败或正在运行。
/// 执行序列器节点的逻辑。它会按顺序执行子节点,直到一个子节点失败或正在运行。
/// </summary>
/// <returns>节点的执行状态。</returns>
public override Status Tick()
@@ -231,7 +228,7 @@ namespace AI
}
/// <summary>
/// 重置序列器节点的状态,包括子节点索引。
/// 重置序列器节点的状态,包括子节点索引。
/// </summary>
public override void Reset()
{
@@ -254,10 +251,10 @@ namespace AI
private BranchExecutionPhase _currentPhase = BranchExecutionPhase.None;
// 用于防止日志刷屏
private bool _hasLoggedMisconfigurationWarning = false;
private bool _hasLoggedMisconfigurationWarning;
/// <summary>
/// 初始化分支节点。
/// 初始化分支节点。
/// </summary>
/// <param name="def">行为树定义。</param>
/// <param name="selfEntity">关联的实体。</param>
@@ -269,16 +266,13 @@ namespace AI
}
/// <summary>
/// 执行分支节点的逻辑。它会首先评估条件树,然后根据条件结果执行真分支或假分支。
/// 执行分支节点的逻辑。它会首先评估条件树,然后根据条件结果执行真分支或假分支。
/// </summary>
/// <returns>节点的执行状态。</returns>
public override Status Tick()
{
// 如果之前有警告但现在配置正确了,就重置警告标志
if (_hasLoggedMisconfigurationWarning && children.Count >= 2)
{
_hasLoggedMisconfigurationWarning = false;
}
if (_hasLoggedMisconfigurationWarning && children.Count >= 2) _hasLoggedMisconfigurationWarning = false;
// 确保至少有两个子节点 (条件树和真树)
if (children.Count < 2)
@@ -286,8 +280,8 @@ namespace AI
if (!_hasLoggedMisconfigurationWarning) // 只有在未记录过警告时才记录
{
Debug.LogWarning(
$"分支节点至少需要2个子节点(条件和真分支)。当前实例配置错误。 " +
$"此实例的进一步警告将在重置或更正后才显示。 " +
"分支节点至少需要2个子节点(条件和真分支)。当前实例配置错误。 " +
"此实例的进一步警告将在重置或更正后才显示。 " +
$"实体: {SelfEntity?.name ?? "N/A"}。"); // 增加更多上下文信息
_hasLoggedMisconfigurationWarning = true; // 标记已记录
}
@@ -302,10 +296,7 @@ namespace AI
// 假树是可选的
var falseTree = children.Count > 2 ? children[2] : null;
// 如果是首次 Tick 或者 Reset 后,将阶段设置为评估条件
if (_currentPhase == BranchExecutionPhase.None)
{
_currentPhase = BranchExecutionPhase.EvaluatingCondition;
}
if (_currentPhase == BranchExecutionPhase.None) _currentPhase = BranchExecutionPhase.EvaluatingCondition;
Status result;
switch (_currentPhase)
@@ -321,10 +312,8 @@ namespace AI
result = conditionTree.Tick();
if (result == Status.Running)
{
// 条件正在运行,则整个分支也运行
return Status.Running;
}
if (result == Status.Success)
{
@@ -350,10 +339,8 @@ namespace AI
result = trueTree.Tick();
if (result == Status.Running)
{
// 真树正在运行,则整个分支也运行
return Status.Running;
}
// 真树完成 (成功或失败),分支节点完成,重置状态
Reset();
@@ -364,10 +351,8 @@ namespace AI
{
result = falseTree.Tick();
if (result == Status.Running)
{
// 假树正在运行,则整个分支也运行
return Status.Running;
}
// 假树完成 (成功或失败),分支节点完成,重置状态
Reset();
@@ -387,7 +372,7 @@ namespace AI
}
/// <summary>
/// 重置分支节点的状态,包括内部执行阶段。
/// 重置分支节点的状态,包括内部执行阶段。
/// </summary>
public override void Reset()
{