Files
Gen_Hack-and-Slash-Roguelite/Client/Assets/Scripts/EventWorkClass/Event_GrantHediffWorkClass.cs

276 lines
13 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;
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);
}
}
}
}