142 lines
4 KiB
C#
142 lines
4 KiB
C#
using AcDream.Core.Combat;
|
|
using Xunit;
|
|
|
|
namespace AcDream.Core.Tests.Combat;
|
|
|
|
public sealed class CombatStateTests
|
|
{
|
|
[Fact]
|
|
public void OnUpdateHealth_CachesPercent_AndFiresEvent()
|
|
{
|
|
var state = new CombatState();
|
|
uint seenGuid = 0;
|
|
float seenPct = 0;
|
|
state.HealthChanged += (g, p) => { seenGuid = g; seenPct = p; };
|
|
|
|
state.OnUpdateHealth(0xBEEF, 0.33f);
|
|
|
|
Assert.Equal(0xBEEFu, seenGuid);
|
|
Assert.Equal(0.33f, seenPct, 4);
|
|
Assert.Equal(0.33f, state.GetHealthPercent(0xBEEF), 4);
|
|
}
|
|
|
|
[Fact]
|
|
public void GetHealthPercent_Unknown_ReturnsFullHealth()
|
|
{
|
|
var state = new CombatState();
|
|
Assert.Equal(1f, state.GetHealthPercent(0xDEAD));
|
|
}
|
|
|
|
[Fact]
|
|
public void CombatMode_UsesRetailAceBitValues()
|
|
{
|
|
Assert.Equal(1, (int)CombatMode.NonCombat);
|
|
Assert.Equal(2, (int)CombatMode.Melee);
|
|
Assert.Equal(4, (int)CombatMode.Missile);
|
|
Assert.Equal(8, (int)CombatMode.Magic);
|
|
}
|
|
|
|
[Fact]
|
|
public void AttackType_UsesNamedRetailBitValues()
|
|
{
|
|
Assert.Equal(0x0001u, (uint)AttackType.Punch);
|
|
Assert.Equal(0x0002u, (uint)AttackType.Thrust);
|
|
Assert.Equal(0x0004u, (uint)AttackType.Slash);
|
|
Assert.Equal(0x0008u, (uint)AttackType.Kick);
|
|
Assert.Equal(0x0010u, (uint)AttackType.OffhandPunch);
|
|
Assert.Equal(0x79E0u, (uint)AttackType.MultiStrike);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetCombatMode_TracksCurrentMode_AndFiresEvent()
|
|
{
|
|
var state = new CombatState();
|
|
CombatMode? seen = null;
|
|
state.CombatModeChanged += mode => seen = mode;
|
|
|
|
state.SetCombatMode(CombatMode.Missile);
|
|
|
|
Assert.Equal(CombatMode.Missile, state.CurrentMode);
|
|
Assert.Equal(CombatMode.Missile, seen);
|
|
}
|
|
|
|
[Fact]
|
|
public void OnCombatCommenceAttack_FiresAttackCommenced()
|
|
{
|
|
var state = new CombatState();
|
|
bool seen = false;
|
|
state.AttackCommenced += () => seen = true;
|
|
|
|
state.OnCombatCommenceAttack();
|
|
|
|
Assert.True(seen);
|
|
}
|
|
|
|
[Fact]
|
|
public void OnVictimNotification_FiresDamageTaken()
|
|
{
|
|
var state = new CombatState();
|
|
CombatState.DamageIncoming seen = default;
|
|
state.DamageTaken += d => seen = d;
|
|
|
|
state.OnVictimNotification("Drudge", 0xAA, 1, 42, 3, 1, 8);
|
|
|
|
Assert.Equal("Drudge", seen.AttackerName);
|
|
Assert.Equal(42u, seen.Damage);
|
|
Assert.True(seen.Critical);
|
|
}
|
|
|
|
[Fact]
|
|
public void OnAttackerNotification_FiresDamageDealt()
|
|
{
|
|
var state = new CombatState();
|
|
CombatState.DamageDealt seen = default;
|
|
state.DamageDealtAccepted += d => seen = d;
|
|
|
|
state.OnAttackerNotification("Drudge", 1, 30, 0.15f);
|
|
|
|
Assert.Equal("Drudge", seen.DefenderName);
|
|
Assert.Equal(30u, seen.Damage);
|
|
Assert.Equal(0.15f, seen.DamagePercent, 4);
|
|
}
|
|
|
|
[Fact]
|
|
public void OnEvasionNotification_FiresCorrectEvent()
|
|
{
|
|
var state = new CombatState();
|
|
string? evaded = null, missed = null;
|
|
state.EvadedIncoming += a => evaded = a;
|
|
state.MissedOutgoing += d => missed = d;
|
|
|
|
state.OnEvasionDefenderNotification("Rat"); // you evaded rat
|
|
state.OnEvasionAttackerNotification("Tusker"); // tusker evaded you
|
|
|
|
Assert.Equal("Rat", evaded);
|
|
Assert.Equal("Tusker", missed);
|
|
}
|
|
|
|
[Fact]
|
|
public void OnAttackDone_FiresAttackDone()
|
|
{
|
|
var state = new CombatState();
|
|
uint seenSeq = 0, seenErr = 999;
|
|
state.AttackDone += (s, e) => { seenSeq = s; seenErr = e; };
|
|
|
|
state.OnAttackDone(5, 0);
|
|
Assert.Equal(5u, seenSeq);
|
|
Assert.Equal(0u, seenErr);
|
|
}
|
|
|
|
[Fact]
|
|
public void Clear_ResetsHealthCache()
|
|
{
|
|
var state = new CombatState();
|
|
state.OnUpdateHealth(1, 0.5f);
|
|
state.OnUpdateHealth(2, 0.8f);
|
|
|
|
state.Clear();
|
|
|
|
Assert.Equal(1f, state.GetHealthPercent(1)); // back to default
|
|
Assert.Equal(0, state.TrackedTargetCount);
|
|
}
|
|
}
|