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

282 lines
15 KiB
C#
Raw Permalink Normal View History

using System;
using System.Collections.Generic;
using Data; // 包含 AttributesOffsetDef (API), HediffDef, Define, Attributes
using Entity; // 包含 Entity, LivingEntity
using Managers; // 包含 DefineManager, EntityManager, Program (Program.Instance, Program.Instance.FocusedEntity)
using Newtonsoft.Json;
using UnityEngine;
namespace EventWorkClass
{
/// <summary>
/// 表示添加属性偏移事件的配置数据结构,从 JSON 反序列化而来。
/// 现在直接在配置中定义属性偏移,而不是通过引用 AttributesOffsetDef 的名称。
/// 每个事件实例只执行一个(包含多个属性的)偏移。
/// </summary>
public class GrantAttributeOffsetEventConfig
{
/// <summary>
/// 指示是否将属性偏移额外地应用于事件的触发者 (initiator)。如果为 true 且 initiator 是 LivingEntity它将被添加到目标中。
/// 此选项可以与 TargetType 结合。
/// 默认为 false。
/// </summary>
[JsonProperty("applyToInitiator")]
public bool ApplyToInitiator { get; set; }
/// <summary>
/// 选择额外属性偏移目标的方式。可以与 ApplyToInitiator 结合使用。
/// 默认为 None。
/// </summary>
[JsonProperty("targetType")]
public TargetSelectionType TargetType { get; set; } = TargetSelectionType.None;
/// <summary>
/// 当 TargetType 为 SpecificLocation 时,属性偏移应用的中心位置(世界坐标)。
/// </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>
/// 给予属性偏移的次数。此数量将应用于选定的目标及每种指定的 AttributesOffsetDef。默认为 1。
/// </summary>
[JsonProperty("applyCount")]
public int ApplyCount { get; set; } = 1;
// 以下是直接嵌入的属性偏移字段,直接在此配置中定义
[JsonProperty("attackOffset")] public float attackOffset = 0f;
[JsonProperty("attackPercentOffset")] public float attackPercentOffset = 0f;
[JsonProperty("attackRangeOffset")] public float attackRangeOffset = 0f;
[JsonProperty("attackRangePercentOffset")] public float attackRangePercentOffset = 0f;
[JsonProperty("attackSpeedOffset")] public float attackSpeedOffset = 0f;
[JsonProperty("attackSpeedPercentOffset")] public float attackSpeedPercentOffset = 0f;
[JsonProperty("attackTargetCountOffset")] public float attackTargetCountOffset = 0f;
[JsonProperty("attackTargetCountPercentOffset")] public float attackTargetCountPercentOffset = 0f;
[JsonProperty("damageTakenOffset")] public float damageTakenOffset = 0f;
[JsonProperty("damageTakenPercentOffset")] public float damageTakenPercentOffset = 0f;
[JsonProperty("defenseOffset")] public float defenseOffset = 0f;
[JsonProperty("defensePercentOffset")] public float defensePercentOffset = 0f;
[JsonProperty("effectiveDamageOffset")] public float effectiveDamageOffset = 0f;
[JsonProperty("effectiveDamagePercentOffset")] public float effectiveDamagePercentOffset = 0f;
[JsonProperty("healthOffset")] public float healthOffset = 0f;
[JsonProperty("healthPercentOffset")] public float healthPercentOffset = 0f;
[JsonProperty("moveSpeedOffset")] public float moveSpeedOffset = 0f;
[JsonProperty("moveSpeedPercentOffset")] public float moveSpeedPercentOffset = 0f;
}
/// <summary>
/// 一个继承自 EventWorkClassBase 的类,用于在游戏中给予指定 LivingEntity 运行时属性 (AttributesNow) 偏移。
/// 支持灵活的目标选择,以及直接在 JSON 配置中定义单一(复合)属性偏移。
/// </summary>
public class Event_GrantAttributeOffsetWorkClass : EventWorkClassBase
{
private GrantAttributeOffsetEventConfig _eventConfig;
// _resolvedAttributesOffsetDefs 已被移除,因为不再从 DefineManager 预加载 AttributesOffsetDef
/// <summary>
/// 初始化 GrantAttributeOffset 工作类。通过解析 JSON 字符串来配置要给予的属性偏移及其目标。
/// </summary>
/// <param name="value">包含 GrantAttributeOffset 配置的 JSON 字符串。</param>
/// <exception cref="ArgumentNullException">当 JSON 字符串为空或null时抛出。</exception>
/// <exception cref="JsonSerializationException">当 JSON 字符串格式不正确时抛出。</exception>
/// <exception cref="InvalidOperationException">当 JSON 配置中缺少必要的字段时抛出。</exception>
public override void Init(string value)
{
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentNullException(nameof(value),
"事件_授予属性偏移工作类初始化JSON不能为空。");
try
{
_eventConfig = JsonConvert.DeserializeObject<GrantAttributeOffsetEventConfig>(value);
}
catch (JsonException ex)
{
throw new JsonSerializationException(
"未能反序列化事件_授予属性偏移工作类配置JSON。请检查JSON格式。",
ex
);
}
if (_eventConfig == null)
throw new InvalidOperationException(
"授予属性偏移事件配置无法反序列化。结果对象为空。");
// 移除了对 AttributesOffsetDefNames 列表的验证和预加载逻辑
// 验证 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">当类未初始化时抛出。</exception>
public override void Run(string dimensionID, Entity.Entity initiator = null)
{
// 更新了检查条件,因为 _resolvedAttributesOffsetDefs 字段已移除
if (_eventConfig == null)
throw new InvalidOperationException(
"事件_授予属性偏移工作类尚未初始化。请先调用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_GrantAttributeOffsetWorkClass]</color> ApplyToInitiator为真但触发者('{initiator.entityDef.label}' Def: '{initiator.entityDef.defName}')不是LivingEntity。跳过直接设置触发者。");
}
// 阶段2根据 TargetType 查找其他目标
switch (_eventConfig.TargetType)
{
case TargetSelectionType.AroundInitiator:
if (initiator) // 对于 UnityEngine.Object 派生类型,直接布尔转换检查其有效性
{
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_GrantAttributeOffsetWorkClass]</color> 在触发者偏移位置 {searchCenter2D} 附近半径 {actualRadius} 未找到 LivingEntities。");
}
else
{
Debug.LogWarning(
"<color=Yellow>[Event_GrantAttributeOffsetWorkClass]</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_GrantAttributeOffsetWorkClass]</color> 在指定位置 {searchPosition2D} 附近半径 {actualRadius} 未找到 LivingEntities。");
}
else
{
Debug.LogWarning(
"<color=Yellow>[Event_GrantAttributeOffsetWorkClass]</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_GrantAttributeOffsetWorkClass]</color> 焦点实体('{Program.Instance.FocusedEntity.entityDef.label}' Def: '{Program.Instance.FocusedEntity.entityDef.defName}')不是LivingEntity。跳过焦点实体。");
}
else
{
Debug.LogWarning(
"<color=Yellow>[Event_GrantAttributeOffsetWorkClass]</color> TargetType为FocusedEntity但未找到焦点实体。");
}
break;
case TargetSelectionType.None:
// 这种情况表示除了 ApplyToInitiator 之外没有其他特定的目标选择策略。
break;
}
if (targets.Count == 0)
{
// 更新警告信息
Debug.LogWarning(
$"<color=Yellow>[Event_GrantAttributeOffsetWorkClass]</color> 没有找到有效的LivingEntities来授予属性偏移。");
return;
}
// 阶段3为所有目标创建并应用属性偏移
// 从 _eventConfig 中直接构建一个 AttributesOffsetDef 实例
var generatedOffsetDef = new AttributesOffsetDef
{
attackOffset = _eventConfig.attackOffset,
attackPercentOffset = _eventConfig.attackPercentOffset,
attackRangeOffset = _eventConfig.attackRangeOffset,
attackRangePercentOffset = _eventConfig.attackRangePercentOffset,
attackSpeedOffset = _eventConfig.attackSpeedOffset,
attackSpeedPercentOffset = _eventConfig.attackSpeedPercentOffset,
attackTargetCountOffset = _eventConfig.attackTargetCountOffset,
attackTargetCountPercentOffset = _eventConfig.attackTargetCountPercentOffset,
damageTakenOffset = _eventConfig.damageTakenOffset,
damageTakenPercentOffset = _eventConfig.damageTakenPercentOffset,
defenseOffset = _eventConfig.defenseOffset,
defensePercentOffset = _eventConfig.defensePercentOffset,
effectiveDamageOffset = _eventConfig.effectiveDamageOffset,
effectiveDamagePercentOffset = _eventConfig.effectiveDamagePercentOffset,
healthOffset = _eventConfig.healthOffset,
healthPercentOffset = _eventConfig.healthPercentOffset,
moveSpeedOffset = _eventConfig.moveSpeedOffset,
moveSpeedPercentOffset = _eventConfig.moveSpeedPercentOffset
};
foreach (var target in targets)
{
if (target.AttributesNow == null)
{
Debug.LogWarning(
$"<color=Yellow>[Event_GrantAttributeOffsetWorkClass]</color> 目标实体 '{target.entityDef.label}' (Def: '{target.entityDef.defName}') 的 AttributesNow 为空,无法应用属性偏移。跳过。");
continue; // 跳过此目标,尝试下一个
}
for (var i = 0; i < _eventConfig.ApplyCount; i++)
{
target.OffsetAttribute(generatedOffsetDef);
}
}
}
}
}