S4-07 process 1
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
using Components;
|
||||
using GeometryTD.DataTable;
|
||||
using GeometryTD.Definition;
|
||||
using GeometryTD.Entity;
|
||||
using GeometryTD.Entity.EntityData;
|
||||
using GeometryTD.CustomUtility;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -47,6 +49,47 @@ namespace GeometryTD.Tests.EditMode
|
||||
Assert.That(lowHealthHit.FinalDamage, Is.EqualTo(150));
|
||||
Assert.That(highHealthHit.FinalDamage, Is.EqualTo(100));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ResolveBeforeHit_Shatter_OnlyTriggersOnSlowedTarget()
|
||||
{
|
||||
AttackPayload attackPayload = new AttackPayload
|
||||
{
|
||||
BaseDamage = 100,
|
||||
AttackPropertyType = AttackPropertyType.Physics,
|
||||
TagRuntimes = new[]
|
||||
{
|
||||
new TagRuntimeData { TagType = TagType.Shatter, TotalStack = 2 }
|
||||
}
|
||||
};
|
||||
|
||||
HitContext slowedHit = TagEffectResolver.ResolveBeforeHit(attackPayload, 100, 100, true);
|
||||
HitContext normalHit = TagEffectResolver.ResolveBeforeHit(attackPayload, 100, 100, false);
|
||||
|
||||
Assert.That(slowedHit.FinalDamage, Is.EqualTo(150));
|
||||
Assert.That(normalHit.FinalDamage, Is.EqualTo(100));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ResolveBeforeHit_Shatter_CanStackWithOtherNumericTags()
|
||||
{
|
||||
AttackPayload attackPayload = new AttackPayload
|
||||
{
|
||||
BaseDamage = 100,
|
||||
AttackPropertyType = AttackPropertyType.Physics,
|
||||
TagRuntimes = new[]
|
||||
{
|
||||
new TagRuntimeData { TagType = TagType.Crit, TotalStack = 1 },
|
||||
new TagRuntimeData { TagType = TagType.Execution, TotalStack = 1 },
|
||||
new TagRuntimeData { TagType = TagType.Shatter, TotalStack = 1 }
|
||||
}
|
||||
};
|
||||
|
||||
HitContext hitContext = TagEffectResolver.ResolveBeforeHit(attackPayload, 30, 100, true, 0.05f);
|
||||
|
||||
Assert.That(hitContext.IsCriticalHit, Is.True);
|
||||
Assert.That(hitContext.FinalDamage, Is.EqualTo(281));
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class EnemyTagStatusRuntimeTests
|
||||
@@ -124,6 +167,101 @@ namespace GeometryTD.Tests.EditMode
|
||||
Assert.That(runtime.GetMoveSpeedMultiplier(), Is.EqualTo(1f).Within(0.001f));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ApplyAfterHit_FireWithInferno_IncreasesBurnDamageAndDuration()
|
||||
{
|
||||
EnemyTagStatusRuntime runtime = new EnemyTagStatusRuntime();
|
||||
AttackPayload attackPayload = new AttackPayload
|
||||
{
|
||||
BaseDamage = 100,
|
||||
TagRuntimes = new[]
|
||||
{
|
||||
new TagRuntimeData { TagType = TagType.Fire, TotalStack = 1 },
|
||||
new TagRuntimeData { TagType = TagType.Inferno, TotalStack = 1 }
|
||||
}
|
||||
};
|
||||
int totalDamage = 0;
|
||||
|
||||
TagEffectResolver.ApplyAfterHit(attackPayload, runtime);
|
||||
Assert.That(runtime.HasStatus(TagType.Fire), Is.True);
|
||||
Assert.That(runtime.HasStatus(TagType.Inferno), Is.False);
|
||||
|
||||
runtime.Tick(1f, damage => totalDamage += damage);
|
||||
runtime.Tick(1f, damage => totalDamage += damage);
|
||||
runtime.Tick(1f, damage => totalDamage += damage);
|
||||
runtime.Tick(1f, damage => totalDamage += damage);
|
||||
runtime.Tick(1f, damage => totalDamage += damage);
|
||||
|
||||
Assert.That(totalDamage, Is.EqualTo(200));
|
||||
Assert.That(runtime.HasStatus(TagType.Fire), Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ApplyAfterHit_InfernoWithoutFire_DoesNotCreateStatus()
|
||||
{
|
||||
EnemyTagStatusRuntime runtime = new EnemyTagStatusRuntime();
|
||||
AttackPayload attackPayload = new AttackPayload
|
||||
{
|
||||
BaseDamage = 100,
|
||||
TagRuntimes = new[]
|
||||
{
|
||||
new TagRuntimeData { TagType = TagType.Inferno, TotalStack = 1 }
|
||||
}
|
||||
};
|
||||
|
||||
TagEffectResolver.ApplyAfterHit(attackPayload, runtime);
|
||||
|
||||
Assert.That(runtime.HasStatus(TagType.Fire), Is.False);
|
||||
Assert.That(runtime.HasStatus(TagType.Inferno), Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ApplyAfterHit_IceWithAbsoluteZero_IncreasesSlowStrengthAndDuration()
|
||||
{
|
||||
EnemyTagStatusRuntime runtime = new EnemyTagStatusRuntime();
|
||||
AttackPayload attackPayload = new AttackPayload
|
||||
{
|
||||
BaseDamage = 100,
|
||||
TagRuntimes = new[]
|
||||
{
|
||||
new TagRuntimeData { TagType = TagType.Ice, TotalStack = 2 },
|
||||
new TagRuntimeData { TagType = TagType.AbsoluteZero, TotalStack = 1 }
|
||||
}
|
||||
};
|
||||
|
||||
TagEffectResolver.ApplyAfterHit(attackPayload, runtime);
|
||||
|
||||
Assert.That(runtime.HasStatus(TagType.Ice), Is.True);
|
||||
Assert.That(runtime.HasStatus(TagType.AbsoluteZero), Is.False);
|
||||
Assert.That(runtime.GetMoveSpeedMultiplier(), Is.EqualTo(0.5f).Within(0.001f));
|
||||
|
||||
runtime.Tick(2.5f, null);
|
||||
Assert.That(runtime.HasStatus(TagType.Ice), Is.True);
|
||||
|
||||
runtime.Tick(0.5f, null);
|
||||
Assert.That(runtime.HasStatus(TagType.Ice), Is.False);
|
||||
Assert.That(runtime.GetMoveSpeedMultiplier(), Is.EqualTo(1f).Within(0.001f));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ApplyAfterHit_AbsoluteZeroWithoutIce_DoesNotCreateStatus()
|
||||
{
|
||||
EnemyTagStatusRuntime runtime = new EnemyTagStatusRuntime();
|
||||
AttackPayload attackPayload = new AttackPayload
|
||||
{
|
||||
BaseDamage = 100,
|
||||
TagRuntimes = new[]
|
||||
{
|
||||
new TagRuntimeData { TagType = TagType.AbsoluteZero, TotalStack = 1 }
|
||||
}
|
||||
};
|
||||
|
||||
TagEffectResolver.ApplyAfterHit(attackPayload, runtime);
|
||||
|
||||
Assert.That(runtime.HasStatus(TagType.Ice), Is.False);
|
||||
Assert.That(runtime.HasStatus(TagType.AbsoluteZero), Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Tick_OnlyUpdatesActivatedStatusTags()
|
||||
{
|
||||
@@ -177,21 +315,84 @@ namespace GeometryTD.Tests.EditMode
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Definitions_Keep_Unimplemented_Tags_As_Explicit_NoOpPlaceholders()
|
||||
public void Definitions_Mark_FirstBatch_SevenTags_AsImplemented()
|
||||
{
|
||||
Assert.That(TagConfigRegistry.TryGetDefinition(TagType.Shatter, out TagDefinitionData shatter), Is.True);
|
||||
Assert.That(shatter.Config, Is.TypeOf<ShatterTagConfig>());
|
||||
Assert.That(((ShatterTagConfig)shatter.Config).IsImplemented, Is.False);
|
||||
Assert.That(((ShatterTagConfig)shatter.Config).IsImplemented, Is.True);
|
||||
|
||||
Assert.That(TagConfigRegistry.TryGetDefinition(TagType.Inferno, out TagDefinitionData inferno), Is.True);
|
||||
Assert.That(inferno.Config, Is.TypeOf<InfernoTagConfig>());
|
||||
Assert.That(((InfernoTagConfig)inferno.Config).IsImplemented, Is.False);
|
||||
Assert.That(((InfernoTagConfig)inferno.Config).IsImplemented, Is.True);
|
||||
|
||||
Assert.That(TagConfigRegistry.TryGetDefinition(TagType.AbsoluteZero, out TagDefinitionData absoluteZero), Is.True);
|
||||
Assert.That(absoluteZero.Config, Is.TypeOf<AbsoluteZeroTagConfig>());
|
||||
Assert.That(((AbsoluteZeroTagConfig)absoluteZero.Config).IsImplemented, Is.True);
|
||||
|
||||
Assert.That(TagConfigRegistry.TryGetDefinition(TagType.Pierce, out TagDefinitionData pierce), Is.True);
|
||||
Assert.That(pierce.Config, Is.TypeOf<PierceTagConfig>());
|
||||
Assert.That(((PierceTagConfig)pierce.Config).IsImplemented, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LoadFromRows_Overrides_TriggerPhase_And_ConfigValues()
|
||||
{
|
||||
DRTagConfig fireRow = new DRTagConfig();
|
||||
bool parsed = fireRow.ParseDataRow("\t1\t元素\tFire\tOnAfterHit\t火焰测试描述\t{\"BurnDurationSeconds\":4,\"BurnDamagePerSecondPerStack\":25,\"MaxEffectiveStack\":3}", null);
|
||||
Assert.That(parsed, Is.True);
|
||||
|
||||
TagConfigRegistry.LoadFromRows(new[] { fireRow });
|
||||
|
||||
Assert.That(TagConfigRegistry.TryGetDefinition(TagType.Fire, out TagDefinitionData fire), Is.True);
|
||||
Assert.That(fire.TriggerPhase, Is.EqualTo(TagTriggerPhase.OnAfterHit));
|
||||
Assert.That(fire.Description, Is.EqualTo("火焰测试描述"));
|
||||
Assert.That(fire.Config, Is.TypeOf<FireTagConfig>());
|
||||
|
||||
FireTagConfig config = (FireTagConfig)fire.Config;
|
||||
Assert.That(config.BurnDurationSeconds, Is.EqualTo(4f).Within(0.001f));
|
||||
Assert.That(config.BurnDamagePerSecondPerStack, Is.EqualTo(25f).Within(0.001f));
|
||||
Assert.That(config.MaxEffectiveStack, Is.EqualTo(3));
|
||||
|
||||
TagConfigRegistry.ResetToDefaults();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildTagDescriptionText_Uses_Registry_Descriptions()
|
||||
{
|
||||
DRTagConfig fireRow = new DRTagConfig();
|
||||
DRTagConfig shatterRow = new DRTagConfig();
|
||||
Assert.That(fireRow.ParseDataRow("\t1\t元素\tFire\tOnAfterHit\t持续燃烧\t{\"BurnDurationSeconds\":3,\"BurnDamagePerSecondPerStack\":20,\"MaxEffectiveStack\":5}", null), Is.True);
|
||||
Assert.That(shatterRow.ParseDataRow("\t7\t控制\tShatter\tOnBeforeHit\t对减速目标增伤\t{\"RequiresSlowedTarget\":true,\"DamageBonusPerStack\":0.25}", null), Is.True);
|
||||
|
||||
TagConfigRegistry.LoadFromRows(new[] { fireRow, shatterRow });
|
||||
|
||||
string description = TagDisplayUtility.BuildTagDescriptionText(new[] { TagType.Fire, TagType.Shatter });
|
||||
|
||||
Assert.That(description, Does.Contain("持续燃烧"));
|
||||
Assert.That(description, Does.Contain("对减速目标增伤"));
|
||||
|
||||
TagConfigRegistry.ResetToDefaults();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildTagDescriptionText_FromTagRuntimes_Preserves_StackText()
|
||||
{
|
||||
DRTagConfig iceRow = new DRTagConfig();
|
||||
Assert.That(iceRow.ParseDataRow("\t5\t控制\tIce\tOnAfterHit\t命中附加减速\t{\"SlowDurationSeconds\":2,\"SlowRatioPerStack\":0.2,\"MinMoveSpeedMultiplier\":0.4}", null), Is.True);
|
||||
|
||||
TagConfigRegistry.LoadFromRows(new[] { iceRow });
|
||||
|
||||
string description = TagDisplayUtility.BuildTagDescriptionText(new[]
|
||||
{
|
||||
new TagRuntimeData { TagType = TagType.Ice, TotalStack = 2 }
|
||||
});
|
||||
|
||||
Assert.That(description, Does.Contain("Ice x2"));
|
||||
Assert.That(description, Does.Contain("命中附加减速"));
|
||||
|
||||
TagConfigRegistry.ResetToDefaults();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AttackShape_Placeholders_Are_Routable_Without_Runtime_Effect()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user