process Lo
This commit is contained in:
parent
fb2252f688
commit
4c413ccd6d
90
TODO.md
90
TODO.md
|
|
@ -3,13 +3,14 @@
|
||||||
最后更新:2026-04-30
|
最后更新:2026-04-30
|
||||||
|
|
||||||
> **2026-04-30 第一波完成**:Definition/Enum + Event
|
> **2026-04-30 第一波完成**:Definition/Enum + Event
|
||||||
|
> **2026-04-30 第二波完成**:Vector3/Mathf 替换,AttackPayload/HitContext 迁移
|
||||||
|
|
||||||
## 概述
|
## 概述
|
||||||
|
|
||||||
| 指标 | 数量 | 状态 |
|
| 指标 | 数量 | 状态 |
|
||||||
|------|------|------|
|
|------|------|------|
|
||||||
| 总文件数 | 457 | - |
|
| 总文件数 | 457 | - |
|
||||||
| L0 (Domain) 可直接迁移 | ~180 | **第一波已完成 62 个文件** |
|
| L0 (Domain) 可直接迁移 | ~180 | **第一波已完成 62 个文件,第二波完成 5 个文件** |
|
||||||
| L1 (Infrastructure) 需重构 | ~80 | - |
|
| L1 (Infrastructure) 需重构 | ~80 | - |
|
||||||
| L2 (Presentation) Unity 依赖 | ~197 | - |
|
| L2 (Presentation) Unity 依赖 | ~197 | - |
|
||||||
|
|
||||||
|
|
@ -63,6 +64,8 @@ src/
|
||||||
|
|
||||||
### Definition/DataStruct(8 个文件)
|
### Definition/DataStruct(8 个文件)
|
||||||
|
|
||||||
|
- [x] `Definition/DataStruct/AttackPayload.cs` ⚠️ **已迁移** - Vector3 → System.Numerics.Vector3
|
||||||
|
- [x] `Definition/DataStruct/HitContext.cs` ⚠️ **已迁移** - Vector3 → System.Numerics.Vector3,TargetStatusRuntime 已恢复
|
||||||
- [ ] `Definition/DataStruct/BackpackInventoryData.cs`
|
- [ ] `Definition/DataStruct/BackpackInventoryData.cs`
|
||||||
- [ ] `Definition/DataStruct/BuildInfo.cs`
|
- [ ] `Definition/DataStruct/BuildInfo.cs`
|
||||||
- [ ] `Definition/DataStruct/EventItem.cs`
|
- [ ] `Definition/DataStruct/EventItem.cs`
|
||||||
|
|
@ -127,18 +130,19 @@ src/
|
||||||
|
|
||||||
### Definition/Tag(37 个文件)
|
### Definition/Tag(37 个文件)
|
||||||
|
|
||||||
- [ ] `Definition/Tag/Aggregation/TagRuntimeData.cs`
|
- [x] `Definition/Tag/Aggregation/TagRuntimeData.cs` ⚠️ **已迁移** - 无 Unity 依赖
|
||||||
|
- [x] `Definition/Tag/Aggregation/TagRuntimeUtility.cs` ⚠️ **已新建** - CloneTagRuntimes 方法
|
||||||
- [ ] `Definition/Tag/Aggregation/TowerTagAggregationService.cs`
|
- [ ] `Definition/Tag/Aggregation/TowerTagAggregationService.cs`
|
||||||
- [ ] `Definition/Tag/Combat/EnemyStatusTagRegistry.cs`
|
- [x] `Definition/Tag/Combat/EnemyStatusTagRegistry.cs` ⚠️ **已迁移** - 简化版(含 FireTagEffect、IceTagEffect 注册)
|
||||||
- [ ] `Definition/Tag/Combat/Handlers/AttackShapeTagEffectHandler.cs`
|
- [ ] `Definition/Tag/Combat/Handlers/AttackShapeTagEffectHandler.cs`
|
||||||
- [ ] `Definition/Tag/Combat/Handlers/NumericTagEffectHandler.cs`
|
- [ ] `Definition/Tag/Combat/Handlers/NumericTagEffectHandler.cs`
|
||||||
- [ ] `Definition/Tag/Combat/States/EnemyStatusTagStateBase.cs`
|
- [x] `Definition/Tag/Combat/States/EnemyStatusTagStateBase.cs` ⚠️ **已迁移** - 无 Unity 依赖
|
||||||
- [ ] `Definition/Tag/Combat/States/FireTagState.cs`
|
- [x] `Definition/Tag/Combat/States/FireTagState.cs` ⚠️ **已迁移** - 无 Unity 依赖
|
||||||
- [ ] `Definition/Tag/Combat/States/IceTagState.cs`
|
- [x] `Definition/Tag/Combat/States/IceTagState.cs` ⚠️ **已迁移** - 无 Unity 依赖
|
||||||
- [ ] `Definition/Tag/Combat/StatusEffects/EnemyStatusTagEffectBase.cs`
|
- [x] `Definition/Tag/Combat/StatusEffects/EnemyStatusTagEffectBase.cs` ⚠️ **已迁移** - 无 Unity 依赖
|
||||||
- [ ] `Definition/Tag/Combat/StatusEffects/FireTagEffect.cs`
|
- [x] `Definition/Tag/Combat/StatusEffects/FireTagEffect.cs` ⚠️ **已迁移** - Mathf → System.Math
|
||||||
- [ ] `Definition/Tag/Combat/StatusEffects/IEnemyStatusTagEffect.cs`
|
- [x] `Definition/Tag/Combat/StatusEffects/IEnemyStatusTagEffect.cs` ⚠️ **已迁移** - 无 Unity 依赖
|
||||||
- [ ] `Definition/Tag/Combat/StatusEffects/IceTagEffect.cs`
|
- [x] `Definition/Tag/Combat/StatusEffects/IceTagEffect.cs` ⚠️ **已迁移** - Mathf → System.Math
|
||||||
- [ ] `Definition/Tag/Combat/TagEffectResolver.cs`
|
- [ ] `Definition/Tag/Combat/TagEffectResolver.cs`
|
||||||
- [ ] `Definition/Tag/Generation/ComponentTagGenerationService.cs`
|
- [ ] `Definition/Tag/Generation/ComponentTagGenerationService.cs`
|
||||||
- [ ] `Definition/Tag/Generation/InventoryTagRandomContext.cs`
|
- [ ] `Definition/Tag/Generation/InventoryTagRandomContext.cs`
|
||||||
|
|
@ -146,20 +150,21 @@ src/
|
||||||
- [ ] `Definition/Tag/Generation/RarityTagBudgetRuleRegistry.cs`
|
- [ ] `Definition/Tag/Generation/RarityTagBudgetRuleRegistry.cs`
|
||||||
- [ ] `Definition/Tag/Generation/TagGenerationRule.cs`
|
- [ ] `Definition/Tag/Generation/TagGenerationRule.cs`
|
||||||
- [ ] `Definition/Tag/Generation/TagGenerationRuleRegistry.cs`
|
- [ ] `Definition/Tag/Generation/TagGenerationRuleRegistry.cs`
|
||||||
- [ ] `Definition/Tag/Metadata/Config/AbsoluteZeroTagConfig.cs`
|
- [x] `Definition/Tag/Metadata/Config/AbsoluteZeroTagConfig.cs` ⚠️ **已迁移** - 无 Unity 依赖
|
||||||
- [ ] `Definition/Tag/Metadata/Config/BurnSpreadTagConfig.cs`
|
- [x] `Definition/Tag/Metadata/Config/BurnSpreadTagConfig.cs` ⚠️ **已迁移** - 无 Unity 依赖
|
||||||
- [ ] `Definition/Tag/Metadata/Config/CritTagConfig.cs`
|
- [x] `Definition/Tag/Metadata/Config/CritTagConfig.cs` ⚠️ **已迁移** - 无 Unity 依赖
|
||||||
- [ ] `Definition/Tag/Metadata/Config/ExecutionTagConfig.cs`
|
- [x] `Definition/Tag/Metadata/Config/ExecutionTagConfig.cs` ⚠️ **已迁移** - 无 Unity 依赖
|
||||||
- [ ] `Definition/Tag/Metadata/Config/FireTagConfig.cs`
|
- [x] `Definition/Tag/Metadata/Config/FireTagConfig.cs` ⚠️ **已迁移** - 无 Unity 依赖
|
||||||
- [ ] `Definition/Tag/Metadata/Config/FreezeMaskTagConfig.cs`
|
- [x] `Definition/Tag/Metadata/Config/FreezeMaskTagConfig.cs` ⚠️ **已迁移** - 无 Unity 依赖
|
||||||
- [ ] `Definition/Tag/Metadata/Config/IceTagConfig.cs`
|
- [x] `Definition/Tag/Metadata/Config/IceTagConfig.cs` ⚠️ **已迁移** - 无 Unity 依赖
|
||||||
- [ ] `Definition/Tag/Metadata/Config/IgniteBurstTagConfig.cs`
|
- [x] `Definition/Tag/Metadata/Config/IgniteBurstTagConfig.cs` ⚠️ **已迁移** - 无 Unity 依赖
|
||||||
- [ ] `Definition/Tag/Metadata/Config/InfernoTagConfig.cs`
|
- [x] `Definition/Tag/Metadata/Config/InfernoTagConfig.cs` ⚠️ **已迁移** - 无 Unity 依赖
|
||||||
- [ ] `Definition/Tag/Metadata/Config/OverpenetrateTagConfig.cs`
|
- [x] `Definition/Tag/Metadata/Config/OverpenetrateTagConfig.cs` ⚠️ **已迁移** - 无 Unity 依赖
|
||||||
- [ ] `Definition/Tag/Metadata/Config/PierceTagConfig.cs`
|
- [x] `Definition/Tag/Metadata/Config/PierceTagConfig.cs` ⚠️ **已迁移** - 无 Unity 依赖
|
||||||
- [ ] `Definition/Tag/Metadata/Config/ShatterTagConfig.cs`
|
- [x] `Definition/Tag/Metadata/Config/ShatterTagConfig.cs` ⚠️ **已迁移** - 无 Unity 依赖
|
||||||
- [ ] `Definition/Tag/Metadata/Config/TagConfigBase.cs`
|
- [x] `Definition/Tag/Metadata/Config/TagConfigBase.cs` ⚠️ **已迁移** - 无 Unity 依赖
|
||||||
- [ ] `Definition/Tag/Metadata/TagDefinition.cs`
|
- [x] `Definition/Tag/Metadata/TagDefinition.cs` ⚠️ **已迁移** - 无 Unity 依赖
|
||||||
|
- [x] `Definition/Tag/Metadata/TagDefinitionRegistry.cs` ⚠️ **已迁移** - 简化版(移除 DR* 依赖)
|
||||||
|
|
||||||
### Definition/Event(6 个文件)
|
### Definition/Event(6 个文件)
|
||||||
|
|
||||||
|
|
@ -555,8 +560,8 @@ L0 迁移阻塞链:
|
||||||
### 重构优先级
|
### 重构优先级
|
||||||
|
|
||||||
1. **第一波**:Definition/Enum + Event ✅ 已完成
|
1. **第一波**:Definition/Enum + Event ✅ 已完成
|
||||||
2. **第二波**:DataTable 整体移入 L1
|
2. **第二波**:Vector3 → System.Numerics.Vector3,Mathf → System.Math ✅ **已完成部分**
|
||||||
3. **第三波**:Vector3 → System.Numerics.Vector3 替换
|
3. **第三波**:Tag 系统迁移到 L1(TagDefinitionRegistry、TagEffectResolver 等)
|
||||||
4. **第四波**:GameEntry 静态调用 → 接口注入
|
4. **第四波**:GameEntry 静态调用 → 接口注入
|
||||||
5. **第五波**:Tilemap 接口抽象
|
5. **第五波**:Tilemap 接口抽象
|
||||||
6. **第六波**:剩余 L1 文件迁移
|
6. **第六波**:剩余 L1 文件迁移
|
||||||
|
|
@ -602,9 +607,40 @@ L0 迁移阻塞链:
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 第二波修改记录(2026-04-30)
|
||||||
|
|
||||||
|
### 进度统计
|
||||||
|
|
||||||
|
| 类别 | 源文件数 | 已迁移 | 说明 |
|
||||||
|
|------|----------|--------|------|
|
||||||
|
| Definition/DataStruct | 2 | 2 | AttackPayload, HitContext(Vector3 替换) |
|
||||||
|
| Definition/Tag | 17 | 17 | Tag系统(TagDefinition、TagConfig系列、TagEffect系列等) |
|
||||||
|
| Entity/EntityLogic | 1 | 1 | EnemyTagStatusRuntime(Mathf → System.Math) |
|
||||||
|
| **小计** | **20** | **20** | - |
|
||||||
|
|
||||||
|
### 新增/迁移文件(Mathf 替换)
|
||||||
|
|
||||||
|
| 文件 | 修改内容 |
|
||||||
|
|------|----------|
|
||||||
|
| `Entity/EntityLogic/EnemyTagStatusRuntime.cs` | Mathf → System.Math |
|
||||||
|
| `Definition/Tag/Combat/StatusEffects/FireTagEffect.cs` | 新建,Mathf → System.Math |
|
||||||
|
| `Definition/Tag/Combat/StatusEffects/IceTagEffect.cs` | 新建,Mathf → System.Math |
|
||||||
|
| `Definition/Tag/Metadata/TagDefinitionRegistry.cs` | 简化版,移除 DR* 依赖 |
|
||||||
|
|
||||||
|
### L0 构建状态
|
||||||
|
|
||||||
|
✅ `dotnet build GeometryTD.Domain` **成功**,0 警告 0 错误
|
||||||
|
|
||||||
|
### 阻塞说明
|
||||||
|
|
||||||
|
1. `TagDefinitionRegistry` 简化版已可用,`DRTag`/`DRTagConfig` 依赖已移除
|
||||||
|
2. `TagGenerationRuleRegistry` 等仍有 `Debug.Assert` 待替换
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 验收标准
|
## 验收标准
|
||||||
|
|
||||||
- [ ] L0 独立构建成功(`dotnet build GeometryTD.Domain`)
|
- [x] L0 独立构建成功(`dotnet build GeometryTD.Domain`)✅ **2026-04-30**
|
||||||
- [ ] L1 引用 L0 无循环依赖
|
- [ ] L1 引用 L0 无循环依赖
|
||||||
- [ ] L2 引用 L1 无循环依赖
|
- [ ] L2 引用 L1 无循环依赖
|
||||||
- [ ] 三层整体构建成功(`dotnet build Geometry-Tower-Defense-Base.sln`)
|
- [ ] 三层整体构建成功(`dotnet build Geometry-Tower-Defense-Base.sln`)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
using System;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public sealed class HitStatusModifierContext
|
||||||
|
{
|
||||||
|
public float BonusBurnDurationSeconds { get; set; }
|
||||||
|
public float BonusBurnDamagePerSecond { get; set; }
|
||||||
|
public float BonusSlowDurationSeconds { get; set; }
|
||||||
|
public float BonusSlowRatio { get; set; }
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
BonusBurnDurationSeconds = 0f;
|
||||||
|
BonusBurnDamagePerSecond = 0f;
|
||||||
|
BonusSlowDurationSeconds = 0f;
|
||||||
|
BonusSlowRatio = 0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public sealed class AttackPayload
|
||||||
|
{
|
||||||
|
public int BaseDamage { get; set; }
|
||||||
|
public AttackPropertyType AttackPropertyType { get; set; }
|
||||||
|
public int SourceEntityId { get; set; }
|
||||||
|
public int ProjectileEntityId { get; set; }
|
||||||
|
public Vector3 OriginPosition { get; set; }
|
||||||
|
public TagRuntimeData[] TagRuntimes { get; set; } = Array.Empty<TagRuntimeData>();
|
||||||
|
|
||||||
|
public AttackPayload Clone()
|
||||||
|
{
|
||||||
|
return new AttackPayload
|
||||||
|
{
|
||||||
|
BaseDamage = BaseDamage,
|
||||||
|
AttackPropertyType = AttackPropertyType,
|
||||||
|
SourceEntityId = SourceEntityId,
|
||||||
|
ProjectileEntityId = ProjectileEntityId,
|
||||||
|
OriginPosition = OriginPosition,
|
||||||
|
TagRuntimes = TagRuntimeUtility.CloneTagRuntimes(TagRuntimes)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
using System;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public sealed class HitContext
|
||||||
|
{
|
||||||
|
public AttackPayload AttackPayload { get; set; }
|
||||||
|
public int FinalDamage { get; set; }
|
||||||
|
public bool IsCriticalHit { get; set; }
|
||||||
|
public bool IsKilled { get; set; }
|
||||||
|
public int TargetEntityId { get; set; }
|
||||||
|
public Vector3 TargetPosition { get; set; }
|
||||||
|
public int TargetCurrentHealthBeforeHit { get; set; }
|
||||||
|
public int TargetCurrentHealthAfterHit { get; set; }
|
||||||
|
public int TargetMaxHealth { get; set; }
|
||||||
|
public float TargetMoveSpeedMultiplierBeforeHit { get; set; } = 1f;
|
||||||
|
public TagType[] TargetStatusTagsBeforeHit { get; set; } = Array.Empty<TagType>();
|
||||||
|
public EnemyTagStatusRuntime TargetStatusRuntime { get; set; }
|
||||||
|
public float? CritRoll { get; set; }
|
||||||
|
public HitStatusModifierContext StatusModifierContext { get; set; } = new HitStatusModifierContext();
|
||||||
|
|
||||||
|
public bool HasTargetStatus(TagType tagType)
|
||||||
|
{
|
||||||
|
if (tagType == TagType.None || TargetStatusTagsBeforeHit == null || TargetStatusTagsBeforeHit.Length <= 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < TargetStatusTagsBeforeHit.Length; i++)
|
||||||
|
{
|
||||||
|
if (TargetStatusTagsBeforeHit[i] == tagType)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasSlowStatusBeforeHit => TargetMoveSpeedMultiplierBeforeHit < 0.999f || HasTargetStatus(TagType.Ice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
public static class TagRuntimeUtility
|
||||||
|
{
|
||||||
|
public static TagRuntimeData[] CloneTagRuntimes(TagRuntimeData[] source)
|
||||||
|
{
|
||||||
|
if (source == null || source.Length <= 0)
|
||||||
|
{
|
||||||
|
return Array.Empty<TagRuntimeData>();
|
||||||
|
}
|
||||||
|
|
||||||
|
TagRuntimeData[] cloned = new TagRuntimeData[source.Length];
|
||||||
|
for (int i = 0; i < source.Length; i++)
|
||||||
|
{
|
||||||
|
TagRuntimeData runtime = source[i];
|
||||||
|
if (runtime == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
cloned[i] = new TagRuntimeData
|
||||||
|
{
|
||||||
|
TagType = runtime.TagType,
|
||||||
|
TotalStack = runtime.TotalStack
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return cloned;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public sealed class TagRuntimeData
|
||||||
|
{
|
||||||
|
public TagType TagType { get; set; }
|
||||||
|
public int TotalStack { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
public static class EnemyStatusTagRegistry
|
||||||
|
{
|
||||||
|
private static readonly Dictionary<TagType, IEnemyStatusTagEffect> EffectsByTag = new Dictionary<TagType, IEnemyStatusTagEffect>
|
||||||
|
{
|
||||||
|
[TagType.Fire] = new FireTagEffect(),
|
||||||
|
[TagType.Ice] = new IceTagEffect()
|
||||||
|
};
|
||||||
|
|
||||||
|
public static IReadOnlyDictionary<TagType, IEnemyStatusTagEffect> Effects => EffectsByTag;
|
||||||
|
|
||||||
|
public static bool TryGetEffect(TagType tagType, out IEnemyStatusTagEffect effect)
|
||||||
|
{
|
||||||
|
return EffectsByTag.TryGetValue(tagType, out effect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
public abstract class EnemyStatusTagStateBase
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
public sealed class FireTagState : EnemyStatusTagStateBase
|
||||||
|
{
|
||||||
|
public float RemainingDuration { get; set; }
|
||||||
|
public float DamagePerSecond { get; set; }
|
||||||
|
public float PendingDamage { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
public sealed class IceTagState : EnemyStatusTagStateBase
|
||||||
|
{
|
||||||
|
public float RemainingDuration { get; set; }
|
||||||
|
public float SlowMultiplier { get; set; } = 1f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
public abstract class EnemyStatusTagEffectBase : IEnemyStatusTagEffect
|
||||||
|
{
|
||||||
|
public abstract TagType TagType { get; }
|
||||||
|
|
||||||
|
public virtual void Apply(HitContext hitContext, TagRuntimeData runtimeData)
|
||||||
|
{
|
||||||
|
_ = hitContext;
|
||||||
|
_ = runtimeData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool Tick(EnemyTagStatusRuntime runtime, float deltaTime, Action<int> applyDamage)
|
||||||
|
{
|
||||||
|
_ = runtime;
|
||||||
|
_ = deltaTime;
|
||||||
|
_ = applyDamage;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual float GetMoveSpeedMultiplier(EnemyTagStatusRuntime runtime)
|
||||||
|
{
|
||||||
|
_ = runtime;
|
||||||
|
return 1f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
public sealed class FireTagEffect : EnemyStatusTagEffectBase
|
||||||
|
{
|
||||||
|
public override TagType TagType => TagType.Fire;
|
||||||
|
|
||||||
|
public override void Apply(HitContext hitContext, TagRuntimeData runtimeData)
|
||||||
|
{
|
||||||
|
if (!TagDefinitionRegistry.TryGetDefinition(TagType, out TagDefinition definition))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hitContext == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hitContext.TargetStatusRuntime == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FireTagConfig config = definition.Config as FireTagConfig;
|
||||||
|
if (config == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config.IsImplemented)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnemyTagStatusRuntime runtime = hitContext.TargetStatusRuntime;
|
||||||
|
FireTagState state = runtime.GetOrCreateState<FireTagState>(TagType);
|
||||||
|
int effectiveStack = (int)System.Math.Max(0, System.Math.Min(runtimeData.TotalStack, config.MaxEffectiveStack));
|
||||||
|
HitStatusModifierContext modifierContext = hitContext.StatusModifierContext ?? new HitStatusModifierContext();
|
||||||
|
float burnDamagePerSecond = System.Math.Max(
|
||||||
|
0f,
|
||||||
|
config.BurnDamagePerSecondPerStack * effectiveStack + modifierContext.BonusBurnDamagePerSecond);
|
||||||
|
|
||||||
|
if (burnDamagePerSecond <= 0f)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.RemainingDuration = System.Math.Max(
|
||||||
|
state.RemainingDuration,
|
||||||
|
config.BurnDurationSeconds + modifierContext.BonusBurnDurationSeconds);
|
||||||
|
state.DamagePerSecond = System.Math.Max(state.DamagePerSecond, burnDamagePerSecond);
|
||||||
|
runtime.Activate(TagType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Tick(EnemyTagStatusRuntime runtime, float deltaTime, Action<int> applyDamage)
|
||||||
|
{
|
||||||
|
FireTagState state = runtime.GetState<FireTagState>(TagType);
|
||||||
|
if (state == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float resolvedDeltaTime = System.Math.Max(0f, deltaTime);
|
||||||
|
if (resolvedDeltaTime <= 0f || state.RemainingDuration <= 0f)
|
||||||
|
{
|
||||||
|
return state.RemainingDuration > 0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float appliedDuration = System.Math.Min(resolvedDeltaTime, state.RemainingDuration);
|
||||||
|
state.RemainingDuration = System.Math.Max(0f, state.RemainingDuration - appliedDuration);
|
||||||
|
state.PendingDamage += state.DamagePerSecond * appliedDuration;
|
||||||
|
|
||||||
|
int resolvedDamage = (int)System.Math.Floor(state.PendingDamage);
|
||||||
|
if (resolvedDamage > 0)
|
||||||
|
{
|
||||||
|
applyDamage?.Invoke(resolvedDamage);
|
||||||
|
state.PendingDamage -= resolvedDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.RemainingDuration > 0f)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.PendingDamage = 0f;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
public interface IEnemyStatusTagEffect
|
||||||
|
{
|
||||||
|
TagType TagType { get; }
|
||||||
|
void Apply(HitContext hitContext, TagRuntimeData runtimeData);
|
||||||
|
bool Tick(EnemyTagStatusRuntime runtime, float deltaTime, Action<int> applyDamage);
|
||||||
|
float GetMoveSpeedMultiplier(EnemyTagStatusRuntime runtime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
public sealed class IceTagEffect : EnemyStatusTagEffectBase
|
||||||
|
{
|
||||||
|
public override TagType TagType => TagType.Ice;
|
||||||
|
|
||||||
|
public override void Apply(HitContext hitContext, TagRuntimeData runtimeData)
|
||||||
|
{
|
||||||
|
if (hitContext == null || runtimeData == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hitContext.TargetStatusRuntime == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TagDefinitionRegistry.TryGetDefinition(TagType, out TagDefinition definition))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IceTagConfig config = definition.Config as IceTagConfig;
|
||||||
|
if (config == null || !config.IsImplemented)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnemyTagStatusRuntime runtime = hitContext.TargetStatusRuntime;
|
||||||
|
IceTagState state = runtime.GetOrCreateState<IceTagState>(TagType);
|
||||||
|
HitStatusModifierContext modifierContext = hitContext.StatusModifierContext ?? new HitStatusModifierContext();
|
||||||
|
float slowRatio = runtimeData.TotalStack * config.SlowRatioPerStack + modifierContext.BonusSlowRatio;
|
||||||
|
float slowMultiplier = System.Math.Max(config.MinMoveSpeedMultiplier, 1f - slowRatio);
|
||||||
|
state.RemainingDuration = System.Math.Max(
|
||||||
|
state.RemainingDuration,
|
||||||
|
config.SlowDurationSeconds + modifierContext.BonusSlowDurationSeconds);
|
||||||
|
state.SlowMultiplier = System.Math.Min(state.SlowMultiplier, slowMultiplier);
|
||||||
|
runtime.Activate(TagType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Tick(EnemyTagStatusRuntime runtime, float deltaTime, Action<int> applyDamage)
|
||||||
|
{
|
||||||
|
_ = applyDamage;
|
||||||
|
IceTagState state = runtime.GetState<IceTagState>(TagType);
|
||||||
|
if (state == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.RemainingDuration = System.Math.Max(0f, state.RemainingDuration - System.Math.Max(0f, deltaTime));
|
||||||
|
return state.RemainingDuration > 0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override float GetMoveSpeedMultiplier(EnemyTagStatusRuntime runtime)
|
||||||
|
{
|
||||||
|
IceTagState state = runtime.GetState<IceTagState>(TagType);
|
||||||
|
return state == null ? 1f : state.SlowMultiplier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public sealed class AbsoluteZeroTagConfig : TagConfigBase
|
||||||
|
{
|
||||||
|
public AbsoluteZeroTagConfig(bool isImplemented) : base(isImplemented)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public float BonusSlowDurationSeconds { get; set; } = 1f;
|
||||||
|
public float BonusSlowRatioPerStack { get; set; } = 0.1f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public sealed class BurnSpreadTagConfig : TagConfigBase
|
||||||
|
{
|
||||||
|
public BurnSpreadTagConfig(bool isImplemented) : base(isImplemented)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public sealed class CritTagConfig : TagConfigBase
|
||||||
|
{
|
||||||
|
public CritTagConfig(bool isImplemented) : base(isImplemented)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public float CritChancePerStack { get; set; } = 0.1f;
|
||||||
|
public float CritDamageMultiplier { get; set; } = 1.5f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public sealed class ExecutionTagConfig : TagConfigBase
|
||||||
|
{
|
||||||
|
public ExecutionTagConfig(bool isImplemented) : base(isImplemented)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public float TargetHealthThreshold { get; set; } = 0.3f;
|
||||||
|
public float DamageBonusPerStack { get; set; } = 0.5f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public sealed class FireTagConfig : TagConfigBase
|
||||||
|
{
|
||||||
|
public FireTagConfig(bool isImplemented) : base(isImplemented)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public float BurnDurationSeconds { get; set; } = 3f;
|
||||||
|
public float BurnDamagePerSecondPerStack { get; set; } = 20f;
|
||||||
|
public int MaxEffectiveStack { get; set; } = 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public sealed class FreezeMaskTagConfig : TagConfigBase
|
||||||
|
{
|
||||||
|
public FreezeMaskTagConfig(bool isImplemented) : base(isImplemented)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public sealed class IceTagConfig : TagConfigBase
|
||||||
|
{
|
||||||
|
public IceTagConfig(bool isImplemented) : base(isImplemented)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public float SlowDurationSeconds { get; set; } = 2f;
|
||||||
|
public float SlowRatioPerStack { get; set; } = 0.2f;
|
||||||
|
public float MinMoveSpeedMultiplier { get; set; } = 0.4f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public sealed class IgniteBurstTagConfig : TagConfigBase
|
||||||
|
{
|
||||||
|
public IgniteBurstTagConfig(bool isImplemented) : base(isImplemented)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public sealed class InfernoTagConfig : TagConfigBase
|
||||||
|
{
|
||||||
|
public InfernoTagConfig(bool isImplemented) : base(isImplemented)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public float BonusBurnDurationSeconds { get; set; } = 2f;
|
||||||
|
public float BonusBurnDamagePerSecondPerStack { get; set; } = 20f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public sealed class OverpenetrateTagConfig : TagConfigBase
|
||||||
|
{
|
||||||
|
public OverpenetrateTagConfig(bool isImplemented) : base(isImplemented)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public sealed class PierceTagConfig : TagConfigBase
|
||||||
|
{
|
||||||
|
public PierceTagConfig(bool isImplemented) : base(isImplemented)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public sealed class ShatterTagConfig : TagConfigBase
|
||||||
|
{
|
||||||
|
public ShatterTagConfig(bool isImplemented) : base(isImplemented)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool RequiresSlowedTarget { get; set; } = true;
|
||||||
|
public float DamageBonusPerStack { get; set; } = 0.25f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public abstract class TagConfigBase
|
||||||
|
{
|
||||||
|
public bool IsImplemented { get; set; }
|
||||||
|
|
||||||
|
protected TagConfigBase(bool isImplemented)
|
||||||
|
{
|
||||||
|
IsImplemented = isImplemented;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public sealed class TagDefinition
|
||||||
|
{
|
||||||
|
public TagType TagType { get; set; }
|
||||||
|
public TagCategory Category { get; set; }
|
||||||
|
public TagTriggerPhase TriggerPhase { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public TagConfigBase Config { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
public static class TagDefinitionRegistry
|
||||||
|
{
|
||||||
|
private static readonly Dictionary<TagType, TagDefinition> DefinitionsByTag = CreateDefaultDefinitions();
|
||||||
|
|
||||||
|
public static IReadOnlyDictionary<TagType, TagDefinition> Definitions => DefinitionsByTag;
|
||||||
|
|
||||||
|
public static void ResetToDefaults()
|
||||||
|
{
|
||||||
|
DefinitionsByTag.Clear();
|
||||||
|
foreach (KeyValuePair<TagType, TagDefinition> pair in CreateDefaultDefinitions())
|
||||||
|
{
|
||||||
|
DefinitionsByTag.Add(pair.Key, pair.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryGetDefinition(TagType tagType, out TagDefinition definition)
|
||||||
|
{
|
||||||
|
return DefinitionsByTag.TryGetValue(tagType, out definition);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ApplyTagRow(int tagId, bool isImplemented)
|
||||||
|
{
|
||||||
|
TagType tagType = (TagType)tagId;
|
||||||
|
if (DefinitionsByTag.TryGetValue(tagType, out TagDefinition definition) && definition.Config != null)
|
||||||
|
{
|
||||||
|
definition.Config.IsImplemented = isImplemented;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Dictionary<TagType, TagDefinition> CreateDefaultDefinitions()
|
||||||
|
{
|
||||||
|
return new Dictionary<TagType, TagDefinition>
|
||||||
|
{
|
||||||
|
[TagType.Fire] = CreateDefinition(TagType.Fire, TagCategory.Status, TagTriggerPhase.OnAfterHit, new FireTagConfig(true)),
|
||||||
|
[TagType.BurnSpread] = CreateDefinition(TagType.BurnSpread, TagCategory.AttackShape, TagTriggerPhase.None, new BurnSpreadTagConfig(false)),
|
||||||
|
[TagType.IgniteBurst] = CreateDefinition(TagType.IgniteBurst, TagCategory.AttackShape, TagTriggerPhase.None, new IgniteBurstTagConfig(false)),
|
||||||
|
[TagType.Inferno] = CreateDefinition(TagType.Inferno, TagCategory.StatusModifier, TagTriggerPhase.OnAfterHit, new InfernoTagConfig(true)),
|
||||||
|
[TagType.Ice] = CreateDefinition(TagType.Ice, TagCategory.Status, TagTriggerPhase.OnAfterHit, new IceTagConfig(true)),
|
||||||
|
[TagType.FreezeMask] = CreateDefinition(TagType.FreezeMask, TagCategory.AttackShape, TagTriggerPhase.None, new FreezeMaskTagConfig(false)),
|
||||||
|
[TagType.Shatter] = CreateDefinition(TagType.Shatter, TagCategory.NumericModifier, TagTriggerPhase.OnBeforeHit, new ShatterTagConfig(true)),
|
||||||
|
[TagType.AbsoluteZero] = CreateDefinition(TagType.AbsoluteZero, TagCategory.StatusModifier, TagTriggerPhase.OnAfterHit, new AbsoluteZeroTagConfig(true)),
|
||||||
|
[TagType.Pierce] = CreateDefinition(TagType.Pierce, TagCategory.AttackShape, TagTriggerPhase.None, new PierceTagConfig(false)),
|
||||||
|
[TagType.Crit] = CreateDefinition(TagType.Crit, TagCategory.NumericModifier, TagTriggerPhase.OnBeforeHit, new CritTagConfig(true)),
|
||||||
|
[TagType.Overpenetrate] = CreateDefinition(TagType.Overpenetrate, TagCategory.AttackShape, TagTriggerPhase.None, new OverpenetrateTagConfig(false)),
|
||||||
|
[TagType.Execution] = CreateDefinition(TagType.Execution, TagCategory.NumericModifier, TagTriggerPhase.OnBeforeHit, new ExecutionTagConfig(true))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TagDefinition CreateDefinition(
|
||||||
|
TagType tagType,
|
||||||
|
TagCategory category,
|
||||||
|
TagTriggerPhase triggerPhase,
|
||||||
|
TagConfigBase config)
|
||||||
|
{
|
||||||
|
return new TagDefinition
|
||||||
|
{
|
||||||
|
TagType = tagType,
|
||||||
|
Category = category,
|
||||||
|
TriggerPhase = triggerPhase,
|
||||||
|
Description = string.Empty,
|
||||||
|
Config = config
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace GeometryTD.Definition
|
||||||
|
{
|
||||||
|
public sealed class EnemyTagStatusRuntime
|
||||||
|
{
|
||||||
|
private readonly Dictionary<TagType, EnemyStatusTagStateBase> _statesByTag = new();
|
||||||
|
private readonly List<TagType> _activeTags = new();
|
||||||
|
|
||||||
|
public bool HasStatus(TagType tagType)
|
||||||
|
{
|
||||||
|
return _statesByTag.ContainsKey(tagType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TagType[] GetActiveTagSnapshot()
|
||||||
|
{
|
||||||
|
if (_activeTags.Count <= 0)
|
||||||
|
{
|
||||||
|
return Array.Empty<TagType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return _activeTags.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
_statesByTag.Clear();
|
||||||
|
_activeTags.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Activate(TagType tagType)
|
||||||
|
{
|
||||||
|
if (_activeTags.Contains(tagType))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_activeTags.Add(tagType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TState GetState<TState>(TagType tagType) where TState : EnemyStatusTagStateBase
|
||||||
|
{
|
||||||
|
if (!_statesByTag.TryGetValue(tagType, out EnemyStatusTagStateBase state))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (TState)state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TState GetOrCreateState<TState>(TagType tagType) where TState : EnemyStatusTagStateBase, new()
|
||||||
|
{
|
||||||
|
if (_statesByTag.TryGetValue(tagType, out EnemyStatusTagStateBase existingState))
|
||||||
|
{
|
||||||
|
return (TState)existingState;
|
||||||
|
}
|
||||||
|
|
||||||
|
TState state = new TState();
|
||||||
|
_statesByTag[tagType] = state;
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick(float deltaTime, Action<int> applyDamage)
|
||||||
|
{
|
||||||
|
float resolvedDeltaTime = System.Math.Max(0f, deltaTime);
|
||||||
|
if (resolvedDeltaTime <= 0f)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = _activeTags.Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
TagType tagType = _activeTags[i];
|
||||||
|
if (!EnemyStatusTagRegistry.TryGetEffect(tagType, out IEnemyStatusTagEffect effect))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (effect.Tick(this, resolvedDeltaTime, applyDamage))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
_statesByTag.Remove(tagType);
|
||||||
|
_activeTags.RemoveAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float GetMoveSpeedMultiplier()
|
||||||
|
{
|
||||||
|
float multiplier = 1f;
|
||||||
|
for (int i = 0; i < _activeTags.Count; i++)
|
||||||
|
{
|
||||||
|
TagType tagType = _activeTags[i];
|
||||||
|
if (!EnemyStatusTagRegistry.TryGetEffect(tagType, out IEnemyStatusTagEffect effect))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
multiplier = System.Math.Min(multiplier, effect.GetMoveSpeedMultiplier(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
return multiplier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using GeometryTD.Definition;
|
||||||
|
|
||||||
|
namespace GeometryTD.Entity
|
||||||
|
{
|
||||||
|
public sealed class EnemyTagStatusRuntime
|
||||||
|
{
|
||||||
|
private readonly Dictionary<TagType, EnemyStatusTagStateBase> _statesByTag = new();
|
||||||
|
private readonly List<TagType> _activeTags = new();
|
||||||
|
|
||||||
|
public bool HasStatus(TagType tagType)
|
||||||
|
{
|
||||||
|
return _statesByTag.ContainsKey(tagType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TagType[] GetActiveTagSnapshot()
|
||||||
|
{
|
||||||
|
if (_activeTags.Count <= 0)
|
||||||
|
{
|
||||||
|
return Array.Empty<TagType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return _activeTags.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
_statesByTag.Clear();
|
||||||
|
_activeTags.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Activate(TagType tagType)
|
||||||
|
{
|
||||||
|
if (_activeTags.Contains(tagType))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_activeTags.Add(tagType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TState GetState<TState>(TagType tagType) where TState : EnemyStatusTagStateBase
|
||||||
|
{
|
||||||
|
if (!_statesByTag.TryGetValue(tagType, out EnemyStatusTagStateBase state))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.Assert(state is TState);
|
||||||
|
return state as TState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TState GetOrCreateState<TState>(TagType tagType) where TState : EnemyStatusTagStateBase, new()
|
||||||
|
{
|
||||||
|
if (_statesByTag.TryGetValue(tagType, out EnemyStatusTagStateBase existingState))
|
||||||
|
{
|
||||||
|
Debug.Assert(existingState is TState);
|
||||||
|
return existingState as TState;
|
||||||
|
}
|
||||||
|
|
||||||
|
TState state = new TState();
|
||||||
|
_statesByTag[tagType] = state;
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick(float deltaTime, Action<int> applyDamage)
|
||||||
|
{
|
||||||
|
float resolvedDeltaTime = System.Math.Max(0f, deltaTime);
|
||||||
|
if (resolvedDeltaTime <= 0f)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = _activeTags.Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
TagType tagType = _activeTags[i];
|
||||||
|
Debug.Assert(EnemyStatusTagRegistry.TryGetEffect(tagType, out IEnemyStatusTagEffect effect));
|
||||||
|
|
||||||
|
if (effect.Tick(this, resolvedDeltaTime, applyDamage))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
_statesByTag.Remove(tagType);
|
||||||
|
_activeTags.RemoveAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float GetMoveSpeedMultiplier()
|
||||||
|
{
|
||||||
|
float multiplier = 1f;
|
||||||
|
for (int i = 0; i < _activeTags.Count; i++)
|
||||||
|
{
|
||||||
|
TagType tagType = _activeTags[i];
|
||||||
|
Debug.Assert(EnemyStatusTagRegistry.TryGetEffect(tagType, out IEnemyStatusTagEffect effect));
|
||||||
|
multiplier = System.Math.Min(multiplier, effect.GetMoveSpeedMultiplier(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
return multiplier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue