mirror of
http://47.107.252.169:3000/Roguelite-Game-Developing-Team/Gen_Hack-and-Slash-Roguelite.git
synced 2025-11-20 05:27:13 +08:00
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
276 lines
13 KiB
C#
276 lines
13 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using Data;
|
||
using Entity;
|
||
using Managers;
|
||
using Newtonsoft.Json;
|
||
using UnityEngine;
|
||
|
||
namespace EventWorkClass
|
||
{
|
||
/// <summary>
|
||
/// 定义 Hediff 目标选择方式。
|
||
/// </summary>
|
||
public enum TargetSelectionType
|
||
{
|
||
/// <summary>
|
||
/// 不指定除发起者之外的任何目标(仅作为默认或后备)。
|
||
/// </summary>
|
||
None,
|
||
|
||
/// <summary>
|
||
/// 在事件触发者 (initiator) 周围的指定半径内查找 LivingEntity。
|
||
/// </summary>
|
||
AroundInitiator,
|
||
|
||
/// <summary>
|
||
/// 根据指定的世界坐标位置和半径查找 LivingEntity。
|
||
/// </summary>
|
||
SpecificLocation,
|
||
|
||
/// <summary>
|
||
/// 针对当前游戏焦点实体(如果它是 LivingEntity)。
|
||
/// </summary>
|
||
FocusedEntity
|
||
}
|
||
|
||
/// <summary>
|
||
/// 表示添加健康状态事件的配置数据结构,从 JSON 反序列化而来。
|
||
/// 已修改以支持同时给予多种健康状态。
|
||
/// </summary>
|
||
public class GrantHediffEventConfig
|
||
{
|
||
/// <summary>
|
||
/// 要添加的 HediffDef 的定义名称列表。这是必填字段。
|
||
/// </summary>
|
||
[JsonProperty("hediffDefNames", Required = Required.Always)]
|
||
public List<string> HediffDefNames { get; set; }
|
||
|
||
/// <summary>
|
||
/// 指示是否将 Hediff 额外地应用于事件的触发者 (initiator)。如果为 true 且 initiator 是 LivingEntity,它将被添加到目标中。
|
||
/// 此选项可以与 TargetType 结合。
|
||
/// 默认为 false。
|
||
/// </summary>
|
||
[JsonProperty("applyToInitiator")]
|
||
public bool ApplyToInitiator { get; set; }
|
||
|
||
/// <summary>
|
||
/// 选择额外 Hediff 目标的方式。可以与 ApplyToInitiator 结合使用。
|
||
/// 默认为 None。
|
||
/// </summary>
|
||
[JsonProperty("targetType")]
|
||
public TargetSelectionType TargetType { get; set; } = TargetSelectionType.None;
|
||
|
||
/// <summary>
|
||
/// 当 TargetType 为 SpecificLocation 时,Hediff 应用的中心位置(世界坐标)。
|
||
/// </summary>
|
||
[JsonProperty("position")]
|
||
public Vector2? Position { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当 TargetType 为 SpecificLocation 或 AroundInitiator 时,查找 LivingEntity 的半径。
|
||
/// 可选,如果未指定则默认为 1.0f。
|
||
/// </summary>
|
||
[JsonProperty("radius")]
|
||
public float? Radius { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当 TargetType 为 AroundInitiator 时,相对于 initiator 位置的偏移(2D 坐标)。
|
||
/// 可选,如果未指定则默认为 Vector2.zero。
|
||
/// </summary>
|
||
[JsonProperty("relativeOffsetToInitiator")]
|
||
public Vector2? RelativeOffsetToInitiator { get; set; }
|
||
|
||
/// <summary>
|
||
/// 给予 Hediff 的数量。此数量将应用于选定的目标及每种指定的 HediffDef。默认为 1。
|
||
/// </summary>
|
||
[JsonProperty("applyCount")]
|
||
public int ApplyCount { get; set; } = 1;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 一个继承自 EventWorkClassBase 的类,用于在游戏中给予指定 LivingEntity 健康状态 (Hediff)。
|
||
/// 支持灵活的目标选择,以及同时给予多种健康状态。
|
||
/// </summary>
|
||
public class Event_GrantHediffWorkClass : EventWorkClassBase
|
||
{
|
||
private GrantHediffEventConfig _eventConfig;
|
||
private List<HediffDef> _resolvedHediffDefs;
|
||
|
||
/// <summary>
|
||
/// 初始化 GrantHediff 工作类。通过解析 JSON 字符串来配置要给予的 Hediff 及其目标。
|
||
/// </summary>
|
||
/// <param name="value">包含 GrantHediff 配置的 JSON 字符串。</param>
|
||
/// <exception cref="ArgumentNullException">当 JSON 字符串为空或null时抛出。</exception>
|
||
/// <exception cref="JsonSerializationException">当 JSON 字符串格式不正确时抛出。</exception>
|
||
/// <exception cref="InvalidOperationException">当 JSON 配置中缺少必要的字段或 HediffDef 未找到时抛出。</exception>
|
||
public override void Init(string value)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(value))
|
||
throw new ArgumentNullException(nameof(value),
|
||
"事件_授予Hediff工作类初始化JSON不能为空。");
|
||
|
||
try
|
||
{
|
||
_eventConfig = JsonConvert.DeserializeObject<GrantHediffEventConfig>(value);
|
||
}
|
||
catch (JsonException ex)
|
||
{
|
||
throw new JsonSerializationException(
|
||
"未能反序列化事件_授予Hediff工作类配置JSON。请检查JSON格式。",
|
||
ex
|
||
);
|
||
}
|
||
|
||
if (_eventConfig == null)
|
||
throw new InvalidOperationException(
|
||
"授予Hediff事件配置无法反序列化。结果对象为空。");
|
||
|
||
// 验证 HediffDefNames 列表
|
||
if (_eventConfig.HediffDefNames == null || _eventConfig.HediffDefNames.Count == 0)
|
||
throw new InvalidOperationException(
|
||
"Hediff事件配置缺少必填字段'hediffDefNames'或其为空。");
|
||
|
||
// 预加载所有 HediffDef
|
||
_resolvedHediffDefs = new List<HediffDef>();
|
||
foreach (var defName in _eventConfig.HediffDefNames)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(defName))
|
||
throw new InvalidOperationException(
|
||
"列表'hediffDefNames'中的HediffDef名称不能为空。");
|
||
|
||
var hediffFound = DefineManager.Instance.FindDefine<HediffDef>(defName);
|
||
if (hediffFound == null)
|
||
throw new InvalidOperationException(
|
||
$"HediffDef '{defName}'在DefineManager中未找到。无法授予未知Hediff。");
|
||
|
||
_resolvedHediffDefs.Add(hediffFound);
|
||
}
|
||
|
||
// 验证 Radius
|
||
var configuredRadius = _eventConfig.Radius.GetValueOrDefault(1f);
|
||
if (configuredRadius < 0f) throw new InvalidOperationException("配置的'radius'不能为负数。");
|
||
|
||
// 验证 SpecificLocation 目标类型所需的字段
|
||
if (_eventConfig.TargetType == TargetSelectionType.SpecificLocation &&
|
||
!_eventConfig.Position.HasValue)
|
||
throw new InvalidOperationException(
|
||
"当TargetType为SpecificLocation时,'position'字段是必需的。");
|
||
|
||
if (_eventConfig.ApplyCount <= 0) throw new InvalidOperationException("ApplyCount必须是正整数。");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行给予健康状态操作。
|
||
/// </summary>
|
||
/// <param name="dimensionID">当前维度ID,此事件通常不直接使用,但作为 EventWorkClassBase 的Run方法签名。</param>
|
||
/// <param name="initiator">触发此事件的实体,可能作为目标。</param>
|
||
/// <exception cref="InvalidOperationException">当类未初始化或 HediffDef 未加载时抛出。</exception>
|
||
public override void Run(string dimensionID, Entity.Entity initiator = null)
|
||
{
|
||
if (_eventConfig == null || _resolvedHediffDefs == null || _resolvedHediffDefs.Count == 0)
|
||
throw new InvalidOperationException(
|
||
"事件_授予Hediff工作类尚未初始化或HediffDefs无法解析。请先调用Init()。");
|
||
|
||
// 使用 HashSet 收集目标,自动处理重复实体
|
||
var targets = new HashSet<LivingEntity>();
|
||
var actualRadius = _eventConfig.Radius.GetValueOrDefault(1f);
|
||
|
||
// 阶段1:如果配置为应用给发起者,则将其添加到目标中
|
||
if (_eventConfig.ApplyToInitiator && initiator != null)
|
||
{
|
||
if (initiator is LivingEntity livingInitiator)
|
||
targets.Add(livingInitiator);
|
||
else
|
||
Debug.LogWarning(
|
||
$"<color=Yellow>[Event_GrantHediffWorkClass]</color> ApplyToInitiator为真,但触发者('{initiator.entityDef.label}' Def: '{initiator.entityDef.defName}')不是LivingEntity。跳过直接设置触发者。");
|
||
}
|
||
|
||
// 阶段2:根据 TargetType 查找其他目标
|
||
switch (_eventConfig.TargetType)
|
||
{
|
||
case TargetSelectionType.AroundInitiator:
|
||
if (initiator)
|
||
{
|
||
var searchCenter2D = (Vector2)initiator.Position +
|
||
_eventConfig.RelativeOffsetToInitiator
|
||
.GetValueOrDefault(Vector2.zero);
|
||
var entitiesAround =
|
||
EntityManager.FindEntity<LivingEntity>(searchCenter2D, actualRadius);
|
||
if (entitiesAround != null && entitiesAround.Length > 0)
|
||
foreach (var entity in entitiesAround)
|
||
targets.Add(entity);
|
||
else
|
||
Debug.LogWarning(
|
||
$"<color=Yellow>[Event_GrantHediffWorkClass]</color> 在触发者偏移位置 {searchCenter2D} 附近半径 {actualRadius} 未找到 LivingEntities。");
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning(
|
||
"<color=Yellow>[Event_GrantHediffWorkClass]</color> TargetType为AroundInitiator,但未提供触发实体。跳过此目标类型。");
|
||
}
|
||
|
||
break;
|
||
|
||
case TargetSelectionType.SpecificLocation:
|
||
if (_eventConfig.Position.HasValue)
|
||
{
|
||
var searchPosition2D = _eventConfig.Position.Value;
|
||
var entitiesInArea =
|
||
EntityManager.FindEntity<LivingEntity>(searchPosition2D, actualRadius);
|
||
if (entitiesInArea != null && entitiesInArea.Length > 0)
|
||
foreach (var entity in entitiesInArea)
|
||
targets.Add(entity);
|
||
else
|
||
Debug.LogWarning(
|
||
$"<color=Yellow>[Event_GrantHediffWorkClass]</color> 在指定位置 {searchPosition2D} 附近半径 {actualRadius} 未找到 LivingEntities。");
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning(
|
||
"<color=Yellow>[Event_GrantHediffWorkClass]</color> TargetType为SpecificLocation,但'position'为空。这应该在Init阶段被捕获。跳过。");
|
||
}
|
||
|
||
break;
|
||
|
||
case TargetSelectionType.FocusedEntity:
|
||
if (Program.Instance.FocusedEntity)
|
||
{
|
||
if (Program.Instance.FocusedEntity is LivingEntity focusedLivingEntity)
|
||
targets.Add(focusedLivingEntity);
|
||
else
|
||
Debug.LogWarning(
|
||
$"<color=Yellow>[Event_GrantHediffWorkClass]</color> 焦点实体('{Program.Instance.FocusedEntity.entityDef.label}' Def: '{Program.Instance.FocusedEntity.entityDef.defName}')不是LivingEntity。跳过焦点实体。");
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning(
|
||
"<color=Yellow>[Event_GrantHediffWorkClass]</color> TargetType为FocusedEntity,但未找到焦点实体。");
|
||
}
|
||
|
||
break;
|
||
|
||
case TargetSelectionType.None:
|
||
// 这种情况表示除了 ApplyToInitiator 之外没有其他特定的目标选择策略。
|
||
break;
|
||
}
|
||
|
||
if (targets.Count == 0)
|
||
{
|
||
Debug.LogWarning(
|
||
$"<color=Yellow>[Event_GrantHediffWorkClass]</color> 没有找到有效的LivingEntities来授予Hediffs '{string.Join(", ", _eventConfig.HediffDefNames)}'。");
|
||
return;
|
||
}
|
||
|
||
// 阶段3:对所有确定的目标应用所有 Hediff
|
||
foreach (var target in targets)
|
||
foreach (var hediffDef in _resolvedHediffDefs)
|
||
for (var i = 0; i < _eventConfig.ApplyCount; i++)
|
||
{
|
||
// 为每个 Hediff 创建一个新实例以确保其独立性
|
||
var newHediff = new Hediff(hediffDef);
|
||
target.AddHediff(newHediff);
|
||
}
|
||
}
|
||
}
|
||
} |