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

282 lines
15 KiB
C#
Raw 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; // 包含 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);
}
}
}
}
}