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 { /// /// 表示添加属性偏移事件的配置数据结构,从 JSON 反序列化而来。 /// 现在直接在配置中定义属性偏移,而不是通过引用 AttributesOffsetDef 的名称。 /// 每个事件实例只执行一个(包含多个属性的)偏移。 /// public class GrantAttributeOffsetEventConfig { /// /// 指示是否将属性偏移额外地应用于事件的触发者 (initiator)。如果为 true 且 initiator 是 LivingEntity,它将被添加到目标中。 /// 此选项可以与 TargetType 结合。 /// 默认为 false。 /// [JsonProperty("applyToInitiator")] public bool ApplyToInitiator { get; set; } /// /// 选择额外属性偏移目标的方式。可以与 ApplyToInitiator 结合使用。 /// 默认为 None。 /// [JsonProperty("targetType")] public TargetSelectionType TargetType { get; set; } = TargetSelectionType.None; /// /// 当 TargetType 为 SpecificLocation 时,属性偏移应用的中心位置(世界坐标)。 /// [JsonProperty("position")] public Vector2? Position { get; set; } /// /// 当 TargetType 为 SpecificLocation 或 AroundInitiator 时,查找 LivingEntity 的半径。 /// 可选,如果未指定则默认为 1.0f。 /// [JsonProperty("radius")] public float? Radius { get; set; } /// /// 当 TargetType 为 AroundInitiator 时,相对于 initiator 位置的偏移(2D 坐标)。 /// 可选,如果未指定则默认为 Vector2.zero。 /// [JsonProperty("relativeOffsetToInitiator")] public Vector2? RelativeOffsetToInitiator { get; set; } /// /// 给予属性偏移的次数。此数量将应用于选定的目标及每种指定的 AttributesOffsetDef。默认为 1。 /// [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; } /// /// 一个继承自 EventWorkClassBase 的类,用于在游戏中给予指定 LivingEntity 运行时属性 (AttributesNow) 偏移。 /// 支持灵活的目标选择,以及直接在 JSON 配置中定义单一(复合)属性偏移。 /// public class Event_GrantAttributeOffsetWorkClass : EventWorkClassBase { private GrantAttributeOffsetEventConfig _eventConfig; // _resolvedAttributesOffsetDefs 已被移除,因为不再从 DefineManager 预加载 AttributesOffsetDef /// /// 初始化 GrantAttributeOffset 工作类。通过解析 JSON 字符串来配置要给予的属性偏移及其目标。 /// /// 包含 GrantAttributeOffset 配置的 JSON 字符串。 /// 当 JSON 字符串为空或null时抛出。 /// 当 JSON 字符串格式不正确时抛出。 /// 当 JSON 配置中缺少必要的字段时抛出。 public override void Init(string value) { if (string.IsNullOrWhiteSpace(value)) throw new ArgumentNullException(nameof(value), "事件_授予属性偏移工作类初始化JSON不能为空。"); try { _eventConfig = JsonConvert.DeserializeObject(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必须是正整数。"); } /// /// 执行给予属性偏移操作。 /// /// 当前维度ID,此事件通常不直接使用,但作为 EventWorkClassBase 的Run方法签名。 /// 触发此事件的实体,可能作为目标。 /// 当类未初始化时抛出。 public override void Run(string dimensionID, Entity.Entity initiator = null) { // 更新了检查条件,因为 _resolvedAttributesOffsetDefs 字段已移除 if (_eventConfig == null) throw new InvalidOperationException( "事件_授予属性偏移工作类尚未初始化。请先调用Init()。"); // 使用 HashSet 收集目标,自动处理重复实体 var targets = new HashSet(); var actualRadius = _eventConfig.Radius.GetValueOrDefault(1f); // 阶段1:如果配置为应用给发起者,则将其添加到目标中 if (_eventConfig.ApplyToInitiator && initiator != null) { if (initiator is LivingEntity livingInitiator) targets.Add(livingInitiator); else Debug.LogWarning( $"[Event_GrantAttributeOffsetWorkClass] 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(searchCenter2D, actualRadius); if (entitiesAround != null && entitiesAround.Length > 0) foreach (var entity in entitiesAround) targets.Add(entity); else Debug.LogWarning( $"[Event_GrantAttributeOffsetWorkClass] 在触发者偏移位置 {searchCenter2D} 附近半径 {actualRadius} 未找到 LivingEntities。"); } else { Debug.LogWarning( "[Event_GrantAttributeOffsetWorkClass] TargetType为AroundInitiator,但未提供触发实体。跳过此目标类型。"); } break; case TargetSelectionType.SpecificLocation: if (_eventConfig.Position.HasValue) { var searchPosition2D = _eventConfig.Position.Value; var entitiesInArea = EntityManager.FindEntity(searchPosition2D, actualRadius); if (entitiesInArea != null && entitiesInArea.Length > 0) foreach (var entity in entitiesInArea) targets.Add(entity); else Debug.LogWarning( $"[Event_GrantAttributeOffsetWorkClass] 在指定位置 {searchPosition2D} 附近半径 {actualRadius} 未找到 LivingEntities。"); } else { Debug.LogWarning( "[Event_GrantAttributeOffsetWorkClass] 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( $"[Event_GrantAttributeOffsetWorkClass] 焦点实体('{Program.Instance.FocusedEntity.entityDef.label}' Def: '{Program.Instance.FocusedEntity.entityDef.defName}')不是LivingEntity。跳过焦点实体。"); } else { Debug.LogWarning( "[Event_GrantAttributeOffsetWorkClass] TargetType为FocusedEntity,但未找到焦点实体。"); } break; case TargetSelectionType.None: // 这种情况表示除了 ApplyToInitiator 之外没有其他特定的目标选择策略。 break; } if (targets.Count == 0) { // 更新警告信息 Debug.LogWarning( $"[Event_GrantAttributeOffsetWorkClass] 没有找到有效的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( $"[Event_GrantAttributeOffsetWorkClass] 目标实体 '{target.entityDef.label}' (Def: '{target.entityDef.defName}') 的 AttributesNow 为空,无法应用属性偏移。跳过。"); continue; // 跳过此目标,尝试下一个 } for (var i = 0; i < _eventConfig.ApplyCount; i++) { target.OffsetAttribute(generatedOffsetDef); } } } } }