Start Tag System
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using GeometryTD.CustomUtility;
|
||||
|
||||
namespace GeometryTD.Definition
|
||||
{
|
||||
[Serializable]
|
||||
public sealed class AttackPayload
|
||||
{
|
||||
public int BaseDamage { get; set; }
|
||||
public AttackPropertyType AttackPropertyType { get; set; }
|
||||
public TagRuntimeData[] TagRuntimes { get; set; } = Array.Empty<TagRuntimeData>();
|
||||
|
||||
public AttackPayload Clone()
|
||||
{
|
||||
return new AttackPayload
|
||||
{
|
||||
BaseDamage = BaseDamage,
|
||||
AttackPropertyType = AttackPropertyType,
|
||||
TagRuntimes = InventoryCloneUtility.CloneTagRuntimes(TagRuntimes)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4ed2fd20f9feb0f4d9448029b5bf63df
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c26677bee93904e4da19e339c6e3a803
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace GeometryTD.Definition
|
||||
{
|
||||
public enum TagCategory : byte
|
||||
{
|
||||
None = 0,
|
||||
Status = 1,
|
||||
NumericModifier = 2,
|
||||
AttackShape = 3
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8c0d6ea8de936264db4aa2f5df963d2b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace GeometryTD.Definition
|
||||
{
|
||||
public enum TagTriggerPhase : byte
|
||||
{
|
||||
None = 0,
|
||||
OnBeforeHit = 1,
|
||||
OnHit = 2,
|
||||
OnAfterHit = 3,
|
||||
OnKill = 4
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bdfe1f7eba0a78742ae112cd61e9da49
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a2a3c49c622040edbd52d0c66df2377e
|
||||
timeCreated: 1773105664
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1ff28b0dd76d49ecb0f6e615df4f7a62
|
||||
timeCreated: 1773105681
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1909b51822cc4368bc604674fd119123
|
||||
timeCreated: 1773105715
|
||||
@@ -0,0 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace GeometryTD.Definition
|
||||
{
|
||||
public sealed class AbsoluteZeroTagEffect : EnemyStatusTagEffectBase
|
||||
{
|
||||
public override TagType TagType => TagType.AbsoluteZero;
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: deecaa9a38c04725b5abeb5488cbe53f
|
||||
timeCreated: 1773106137
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using GeometryTD.Entity;
|
||||
|
||||
namespace GeometryTD.Definition
|
||||
{
|
||||
public abstract class EnemyStatusTagEffectBase : IEnemyStatusTagEffect
|
||||
{
|
||||
public abstract TagType TagType { get; }
|
||||
|
||||
public virtual void Apply(AttackPayload attackPayload, EnemyTagStatusRuntime runtime,
|
||||
TagRuntimeData runtimeData)
|
||||
{
|
||||
_ = attackPayload;
|
||||
_ = runtime;
|
||||
_ = 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aefaa5745cc94c0aae92109e64d83dc1
|
||||
timeCreated: 1773105755
|
||||
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using GeometryTD.Entity;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GeometryTD.Definition
|
||||
{
|
||||
public sealed class FireTagEffect : EnemyStatusTagEffectBase
|
||||
{
|
||||
public override TagType TagType => TagType.Fire;
|
||||
|
||||
public override void Apply(AttackPayload attackPayload, EnemyTagStatusRuntime runtime,
|
||||
TagRuntimeData runtimeData)
|
||||
{
|
||||
Debug.Assert(TagConfigRegistry.TryGetDefinition(TagType, out TagDefinitionData definition));
|
||||
|
||||
FireTagConfig config = definition.Config as FireTagConfig;
|
||||
Debug.Assert(config != null);
|
||||
if (!config.IsImplemented)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FireTagState state = runtime.GetOrCreateState<FireTagState>(TagType);
|
||||
float burnDamagePerSecond = Mathf.Max(0f,
|
||||
config.BurnDamagePerSecondPerStack * runtimeData.TotalStack);
|
||||
|
||||
if (burnDamagePerSecond <= 0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
state.RemainingDuration = Mathf.Max(state.RemainingDuration, config.BurnDurationSeconds);
|
||||
state.DamagePerSecond = Mathf.Max(state.DamagePerSecond, burnDamagePerSecond);
|
||||
runtime.Activate(TagType);
|
||||
}
|
||||
|
||||
public override bool Tick(EnemyTagStatusRuntime runtime, float deltaTime, Action<int> applyDamage)
|
||||
{
|
||||
FireTagState state = runtime.GetState<FireTagState>(TagType);
|
||||
Debug.Assert(state != null);
|
||||
|
||||
float resolvedDeltaTime = Mathf.Max(0f, deltaTime);
|
||||
if (resolvedDeltaTime <= 0f || state.RemainingDuration <= 0f)
|
||||
{
|
||||
return state.RemainingDuration > 0f;
|
||||
}
|
||||
|
||||
float appliedDuration = Mathf.Min(resolvedDeltaTime, state.RemainingDuration);
|
||||
state.RemainingDuration = Mathf.Max(0f, state.RemainingDuration - appliedDuration);
|
||||
state.PendingDamage += state.DamagePerSecond * appliedDuration;
|
||||
|
||||
int resolvedDamage = Mathf.FloorToInt(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,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6609b360347c4fc9bccbe288efa60ae4
|
||||
timeCreated: 1773105786
|
||||
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using GeometryTD.Entity;
|
||||
|
||||
namespace GeometryTD.Definition
|
||||
{
|
||||
public interface IEnemyStatusTagEffect
|
||||
{
|
||||
TagType TagType { get; }
|
||||
void Apply(AttackPayload attackPayload, EnemyTagStatusRuntime runtime, TagRuntimeData runtimeData);
|
||||
bool Tick(EnemyTagStatusRuntime runtime, float deltaTime, Action<int> applyDamage);
|
||||
float GetMoveSpeedMultiplier(EnemyTagStatusRuntime runtime);
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 07eac037b9274ddaa6352412c9043f62
|
||||
timeCreated: 1773105725
|
||||
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using GeometryTD.Entity;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GeometryTD.Definition
|
||||
{
|
||||
public sealed class IceTagEffect : EnemyStatusTagEffectBase
|
||||
{
|
||||
public override TagType TagType => TagType.Ice;
|
||||
|
||||
public override void Apply(AttackPayload attackPayload, EnemyTagStatusRuntime runtime,
|
||||
TagRuntimeData runtimeData)
|
||||
{
|
||||
_ = attackPayload;
|
||||
Debug.Assert(runtimeData != null);
|
||||
Debug.Assert(runtimeData.TotalStack > 0);
|
||||
Debug.Assert(TagConfigRegistry.TryGetDefinition(TagType, out TagDefinitionData definition));
|
||||
|
||||
IceTagConfig config = definition.Config as IceTagConfig;
|
||||
Debug.Assert(config != null);
|
||||
if (!config.IsImplemented)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IceTagState state = runtime.GetOrCreateState<IceTagState>(TagType);
|
||||
float slowMultiplier = Mathf.Max(config.MinMoveSpeedMultiplier,
|
||||
1f - runtimeData.TotalStack * config.SlowRatioPerStack);
|
||||
state.RemainingDuration = Mathf.Max(state.RemainingDuration, config.SlowDurationSeconds);
|
||||
state.SlowMultiplier = Mathf.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);
|
||||
Debug.Assert(state != null);
|
||||
|
||||
state.RemainingDuration = Mathf.Max(0f, state.RemainingDuration - Mathf.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,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0787cd2263b441ceba5b3ad381827677
|
||||
timeCreated: 1773106119
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace GeometryTD.Definition
|
||||
{
|
||||
public sealed class InfernoTagEffect : EnemyStatusTagEffectBase
|
||||
{
|
||||
public override TagType TagType => TagType.Inferno;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2aa813ec42ea4dddb717ff28da764f15
|
||||
timeCreated: 1773106082
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using GeometryTD.Entity;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GeometryTD.Definition
|
||||
{
|
||||
public static class EnemyStatusTagRegistry
|
||||
{
|
||||
private static readonly Dictionary<TagType, IEnemyStatusTagEffect> EffectsByTag =
|
||||
new Dictionary<TagType, IEnemyStatusTagEffect>
|
||||
{
|
||||
[TagType.Fire] = new FireTagEffect(),
|
||||
[TagType.Inferno] = new InfernoTagEffect(),
|
||||
[TagType.Ice] = new IceTagEffect(),
|
||||
[TagType.AbsoluteZero] = new AbsoluteZeroTagEffect()
|
||||
};
|
||||
|
||||
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,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 49ed835d5a444f199fa74b2cb4d06a51
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c90264b23a9c45c0b21bc627a6109282
|
||||
timeCreated: 1773105821
|
||||
@@ -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; } = 0f;
|
||||
public float BonusSlowRatioPerStack { get; set; } = 0f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a92545f498ff4b8ab974a73d220f2cbc
|
||||
timeCreated: 1773105984
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace GeometryTD.Definition
|
||||
{
|
||||
[Serializable]
|
||||
public sealed class BurnSpreadTagConfig : TagConfigBase
|
||||
{
|
||||
public BurnSpreadTagConfig(bool isImplemented) : base(isImplemented)
|
||||
{
|
||||
}
|
||||
|
||||
public float SpreadRadius { get; set; } = 0f;
|
||||
public float SpreadDamageRate { get; set; } = 0f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 16fa8f668caf4a6a9d384f53c86ef6d8
|
||||
timeCreated: 1773105868
|
||||
@@ -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,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 21c22a1b79d74aa58ef0054fed71b90a
|
||||
timeCreated: 1773106012
|
||||
@@ -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,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 865ffdb6e1df446fabfb2355d06ef60a
|
||||
timeCreated: 1773106044
|
||||
@@ -0,0 +1,15 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3225e9a8d28b4133a6484f576c4662ae
|
||||
timeCreated: 1773105844
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace GeometryTD.Definition
|
||||
{
|
||||
[Serializable]
|
||||
public sealed class FreezeMaskTagConfig : TagConfigBase
|
||||
{
|
||||
public FreezeMaskTagConfig(bool isImplemented) : base(isImplemented)
|
||||
{
|
||||
}
|
||||
|
||||
public float FreezeBuildUpPerStack { get; set; } = 0f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fa016e0d4c76466b8fb665656ee4bc9e
|
||||
timeCreated: 1773105940
|
||||
@@ -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,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 546b506913154d74a9a7cd4b3aa36d12
|
||||
timeCreated: 1773105919
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace GeometryTD.Definition
|
||||
{
|
||||
[Serializable]
|
||||
public sealed class IgniteBurstTagConfig : TagConfigBase
|
||||
{
|
||||
public IgniteBurstTagConfig(bool isImplemented) : base(isImplemented)
|
||||
{
|
||||
}
|
||||
|
||||
public float BurstRadius { get; set; } = 0f;
|
||||
public float BurstDamageRate { get; set; } = 0f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b412ab82145242e3a7ce99991199cc35
|
||||
timeCreated: 1773105884
|
||||
@@ -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; } = 0f;
|
||||
public float BonusBurnDamagePerSecondPerStack { get; set; } = 0f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be707e334ca74a2a8a2a9d7773e70138
|
||||
timeCreated: 1773105897
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace GeometryTD.Definition
|
||||
{
|
||||
[Serializable]
|
||||
public sealed class OverpenetrateTagConfig : TagConfigBase
|
||||
{
|
||||
public OverpenetrateTagConfig(bool isImplemented) : base(isImplemented)
|
||||
{
|
||||
}
|
||||
|
||||
public int ExtraPenetrationCount { get; set; } = 0;
|
||||
public float RemainingDamageRate { get; set; } = 0f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1d017f96198041cc97f2db1cb4f84fcb
|
||||
timeCreated: 1773106028
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace GeometryTD.Definition
|
||||
{
|
||||
[Serializable]
|
||||
public sealed class PierceTagConfig : TagConfigBase
|
||||
{
|
||||
public PierceTagConfig(bool isImplemented) : base(isImplemented)
|
||||
{
|
||||
}
|
||||
|
||||
public int ExtraPierceCount { get; set; } = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3081fa157ac74961a2a4ffb3a6e10851
|
||||
timeCreated: 1773105999
|
||||
@@ -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; } = 0f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d0f84f8e59bd4d0ea620742802223d87
|
||||
timeCreated: 1773105968
|
||||
@@ -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,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c2d0d4db7370b9f4b9d4d2cc4e84e46c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,103 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace GeometryTD.Definition
|
||||
{
|
||||
public static class TagConfigRegistry
|
||||
{
|
||||
private static readonly Dictionary<TagType, TagDefinitionData> DefinitionsByTag =
|
||||
new Dictionary<TagType, TagDefinitionData>
|
||||
{
|
||||
[TagType.Fire] = new TagDefinitionData
|
||||
{
|
||||
TagType = TagType.Fire,
|
||||
Category = TagCategory.Status,
|
||||
TriggerPhase = TagTriggerPhase.OnAfterHit,
|
||||
Config = new FireTagConfig(true)
|
||||
},
|
||||
[TagType.BurnSpread] = new TagDefinitionData
|
||||
{
|
||||
TagType = TagType.BurnSpread,
|
||||
Category = TagCategory.AttackShape,
|
||||
TriggerPhase = TagTriggerPhase.OnKill,
|
||||
Config = new BurnSpreadTagConfig(false)
|
||||
},
|
||||
[TagType.IgniteBurst] = new TagDefinitionData
|
||||
{
|
||||
TagType = TagType.IgniteBurst,
|
||||
Category = TagCategory.AttackShape,
|
||||
TriggerPhase = TagTriggerPhase.OnKill,
|
||||
Config = new IgniteBurstTagConfig(false)
|
||||
},
|
||||
[TagType.Inferno] = new TagDefinitionData
|
||||
{
|
||||
TagType = TagType.Inferno,
|
||||
Category = TagCategory.Status,
|
||||
TriggerPhase = TagTriggerPhase.OnAfterHit,
|
||||
Config = new InfernoTagConfig(false)
|
||||
},
|
||||
[TagType.Ice] = new TagDefinitionData
|
||||
{
|
||||
TagType = TagType.Ice,
|
||||
Category = TagCategory.Status,
|
||||
TriggerPhase = TagTriggerPhase.OnAfterHit,
|
||||
Config = new IceTagConfig(true)
|
||||
},
|
||||
[TagType.FreezeMask] = new TagDefinitionData
|
||||
{
|
||||
TagType = TagType.FreezeMask,
|
||||
Category = TagCategory.AttackShape,
|
||||
TriggerPhase = TagTriggerPhase.OnAfterHit,
|
||||
Config = new FreezeMaskTagConfig(false)
|
||||
},
|
||||
[TagType.Shatter] = new TagDefinitionData
|
||||
{
|
||||
TagType = TagType.Shatter,
|
||||
Category = TagCategory.NumericModifier,
|
||||
TriggerPhase = TagTriggerPhase.OnBeforeHit,
|
||||
Config = new ShatterTagConfig(false)
|
||||
},
|
||||
[TagType.AbsoluteZero] = new TagDefinitionData
|
||||
{
|
||||
TagType = TagType.AbsoluteZero,
|
||||
Category = TagCategory.Status,
|
||||
TriggerPhase = TagTriggerPhase.OnAfterHit,
|
||||
Config = new AbsoluteZeroTagConfig(false)
|
||||
},
|
||||
[TagType.Pierce] = new TagDefinitionData
|
||||
{
|
||||
TagType = TagType.Pierce,
|
||||
Category = TagCategory.AttackShape,
|
||||
TriggerPhase = TagTriggerPhase.OnHit,
|
||||
Config = new PierceTagConfig(false)
|
||||
},
|
||||
[TagType.Crit] = new TagDefinitionData
|
||||
{
|
||||
TagType = TagType.Crit,
|
||||
Category = TagCategory.NumericModifier,
|
||||
TriggerPhase = TagTriggerPhase.OnBeforeHit,
|
||||
Config = new CritTagConfig(true)
|
||||
},
|
||||
[TagType.Overpenetrate] = new TagDefinitionData
|
||||
{
|
||||
TagType = TagType.Overpenetrate,
|
||||
Category = TagCategory.AttackShape,
|
||||
TriggerPhase = TagTriggerPhase.OnHit,
|
||||
Config = new OverpenetrateTagConfig(false)
|
||||
},
|
||||
[TagType.Execution] = new TagDefinitionData
|
||||
{
|
||||
TagType = TagType.Execution,
|
||||
Category = TagCategory.NumericModifier,
|
||||
TriggerPhase = TagTriggerPhase.OnBeforeHit,
|
||||
Config = new ExecutionTagConfig(true)
|
||||
}
|
||||
};
|
||||
|
||||
public static IReadOnlyDictionary<TagType, TagDefinitionData> Definitions => DefinitionsByTag;
|
||||
|
||||
public static bool TryGetDefinition(TagType tagType, out TagDefinitionData definition)
|
||||
{
|
||||
return DefinitionsByTag.TryGetValue(tagType, out definition);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 717bc2031fdf31e45a3de05cf4e2f24f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
|
||||
namespace GeometryTD.Definition
|
||||
{
|
||||
[Serializable]
|
||||
public sealed class TagDefinitionData
|
||||
{
|
||||
public TagType TagType { get; set; }
|
||||
public TagCategory Category { get; set; }
|
||||
public TagTriggerPhase TriggerPhase { get; set; }
|
||||
public TagConfigBase Config { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c0011d6ce1b3dd14a89c6af6524cc732
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6fb08c76711246c2afa02d60769d76ef
|
||||
timeCreated: 1773106291
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
namespace GeometryTD.Definition
|
||||
{
|
||||
public static class AttackShapeTagEffectHandler
|
||||
{
|
||||
public static void Apply(HitContext hitContext, TagTriggerPhase triggerPhase)
|
||||
{
|
||||
if (hitContext?.AttackPayload?.TagRuntimes == null || hitContext.AttackPayload.TagRuntimes.Length <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < hitContext.AttackPayload.TagRuntimes.Length; i++)
|
||||
{
|
||||
TagRuntimeData runtime = hitContext.AttackPayload.TagRuntimes[i];
|
||||
if (runtime == null || runtime.TotalStack <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!TagConfigRegistry.TryGetDefinition(runtime.TagType, out TagDefinitionData definition) ||
|
||||
definition == null ||
|
||||
definition.Category != TagCategory.AttackShape ||
|
||||
definition.TriggerPhase != triggerPhase ||
|
||||
definition.Config == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (runtime.TagType)
|
||||
{
|
||||
case TagType.BurnSpread:
|
||||
case TagType.IgniteBurst:
|
||||
case TagType.FreezeMask:
|
||||
case TagType.Pierce:
|
||||
case TagType.Overpenetrate:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 434d659f0e0963d40a7da7e03b144966
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,107 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace GeometryTD.Definition
|
||||
{
|
||||
public static class NumericTagEffectHandler
|
||||
{
|
||||
public static void ApplyBeforeHit(
|
||||
HitContext hitContext,
|
||||
int targetCurrentHealth,
|
||||
int targetMaxHealth,
|
||||
bool targetHasSlowStatus,
|
||||
float? critRoll = null)
|
||||
{
|
||||
if (hitContext == null || hitContext.AttackPayload == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TagRuntimeData[] tagRuntimes = hitContext.AttackPayload.TagRuntimes;
|
||||
if (tagRuntimes == null || tagRuntimes.Length <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < tagRuntimes.Length; i++)
|
||||
{
|
||||
TagRuntimeData runtime = tagRuntimes[i];
|
||||
if (runtime == null || runtime.TotalStack <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!TagConfigRegistry.TryGetDefinition(runtime.TagType, out TagDefinitionData definition) ||
|
||||
definition == null ||
|
||||
definition.Category != TagCategory.NumericModifier ||
|
||||
definition.TriggerPhase != TagTriggerPhase.OnBeforeHit ||
|
||||
definition.Config == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (runtime.TagType)
|
||||
{
|
||||
case TagType.Crit:
|
||||
ApplyCrit(hitContext, runtime.TotalStack, definition.Config as CritTagConfig, critRoll);
|
||||
break;
|
||||
case TagType.Execution:
|
||||
ApplyExecution(hitContext, runtime.TotalStack, targetCurrentHealth, targetMaxHealth, definition.Config as ExecutionTagConfig);
|
||||
break;
|
||||
case TagType.Shatter:
|
||||
ApplyShatter(hitContext, runtime.TotalStack, targetHasSlowStatus, definition.Config as ShatterTagConfig);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
hitContext.IsKilled = targetCurrentHealth > 0 && hitContext.FinalDamage >= targetCurrentHealth;
|
||||
}
|
||||
|
||||
private static void ApplyCrit(HitContext hitContext, int stack, CritTagConfig config, float? critRoll)
|
||||
{
|
||||
if (config == null || !config.IsImplemented || stack <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float chance = Mathf.Clamp01(stack * config.CritChancePerStack);
|
||||
float resolvedCritRoll = critRoll ?? Random.value;
|
||||
if (resolvedCritRoll > chance)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
hitContext.FinalDamage = Mathf.Max(0, Mathf.RoundToInt(hitContext.FinalDamage * config.CritDamageMultiplier));
|
||||
hitContext.IsCriticalHit = true;
|
||||
}
|
||||
|
||||
private static void ApplyExecution(
|
||||
HitContext hitContext,
|
||||
int stack,
|
||||
int targetCurrentHealth,
|
||||
int targetMaxHealth,
|
||||
ExecutionTagConfig config)
|
||||
{
|
||||
if (config == null || !config.IsImplemented || stack <= 0 || targetMaxHealth <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float healthRatio = Mathf.Clamp01((float)Mathf.Max(0, targetCurrentHealth) / targetMaxHealth);
|
||||
if (healthRatio > config.TargetHealthThreshold)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float multiplier = 1f + stack * config.DamageBonusPerStack;
|
||||
hitContext.FinalDamage = Mathf.Max(0, Mathf.RoundToInt(hitContext.FinalDamage * multiplier));
|
||||
}
|
||||
|
||||
private static void ApplyShatter(HitContext hitContext, int stack, bool targetHasSlowStatus, ShatterTagConfig config)
|
||||
{
|
||||
_ = hitContext;
|
||||
_ = stack;
|
||||
_ = targetHasSlowStatus;
|
||||
_ = config;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eef83fab509bf1b4aaea8504c8a2fc7f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,99 @@
|
||||
using GeometryTD.Entity;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GeometryTD.Definition
|
||||
{
|
||||
public static class TagEffectResolver
|
||||
{
|
||||
public static HitContext ResolveBeforeHit(
|
||||
AttackPayload attackPayload,
|
||||
int targetCurrentHealth,
|
||||
int targetMaxHealth,
|
||||
bool targetHasSlowStatus,
|
||||
float? critRoll = null)
|
||||
{
|
||||
_ = targetHasSlowStatus;
|
||||
AttackPayload resolvedPayload = attackPayload?.Clone() ?? new AttackPayload();
|
||||
HitContext hitContext = new HitContext
|
||||
{
|
||||
AttackPayload = resolvedPayload,
|
||||
FinalDamage = Mathf.Max(0, resolvedPayload.BaseDamage),
|
||||
IsCriticalHit = false,
|
||||
IsKilled = targetCurrentHealth > 0 && resolvedPayload.BaseDamage >= targetCurrentHealth
|
||||
};
|
||||
|
||||
NumericTagEffectHandler.ApplyBeforeHit(
|
||||
hitContext,
|
||||
targetCurrentHealth,
|
||||
targetMaxHealth,
|
||||
targetHasSlowStatus,
|
||||
critRoll);
|
||||
return hitContext;
|
||||
}
|
||||
|
||||
public static void ApplyAfterHit(AttackPayload attackPayload, EnemyTagStatusRuntime targetStatusRuntime)
|
||||
{
|
||||
if (attackPayload != null && targetStatusRuntime != null)
|
||||
{
|
||||
TagRuntimeData[] tagRuntimes = attackPayload.TagRuntimes;
|
||||
if (tagRuntimes != null && tagRuntimes.Length > 0)
|
||||
{
|
||||
foreach (var tag in tagRuntimes)
|
||||
{
|
||||
if (tag == null || tag.TotalStack <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!TagConfigRegistry.TryGetDefinition(tag.TagType, out TagDefinitionData definition) ||
|
||||
definition == null ||
|
||||
definition.Category != TagCategory.Status ||
|
||||
definition.TriggerPhase != TagTriggerPhase.OnAfterHit ||
|
||||
definition.Config == null ||
|
||||
!EnemyStatusTagRegistry.TryGetEffect(tag.TagType, out IEnemyStatusTagEffect effect))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
effect.Apply(attackPayload, targetStatusRuntime, tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AttackShapeTagEffectHandler.Apply(new HitContext
|
||||
{
|
||||
AttackPayload = attackPayload
|
||||
}, TagTriggerPhase.OnAfterHit);
|
||||
}
|
||||
|
||||
public static void ApplyOnHit(HitContext hitContext)
|
||||
{
|
||||
AttackShapeTagEffectHandler.Apply(hitContext, TagTriggerPhase.OnHit);
|
||||
}
|
||||
|
||||
public static void ApplyOnKill(HitContext hitContext)
|
||||
{
|
||||
AttackShapeTagEffectHandler.Apply(hitContext, TagTriggerPhase.OnKill);
|
||||
}
|
||||
|
||||
public static int GetTagStack(TagRuntimeData[] tagRuntimes, TagType tagType)
|
||||
{
|
||||
if (tagRuntimes == null || tagRuntimes.Length <= 0 || tagType == TagType.None)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
foreach (var tag in tagRuntimes)
|
||||
{
|
||||
if (tag == null || tag.TagType != tagType || tag.TotalStack <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return tag.TotalStack;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5e0b2b45c147579459081b36d26d471c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0f2ab8a7e488575498ac933a125360d1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace GeometryTD.Definition
|
||||
{
|
||||
public abstract class EnemyStatusTagStateBase
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 36215e56239c41c5bb196de6927643a8
|
||||
timeCreated: 1773105536
|
||||
@@ -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,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 20ad1b81a1634d06b9c8bbadec37bcd4
|
||||
timeCreated: 1773105566
|
||||
@@ -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,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 43c7eb87fa774e60a894f4cc8e0089a5
|
||||
timeCreated: 1773105599
|
||||
Reference in New Issue
Block a user