Add hero runtime

This commit is contained in:
2026-04-21 22:54:14 +02:00
parent 67737f3ba8
commit 762c8969ab
29 changed files with 1327 additions and 12 deletions

View File

@@ -0,0 +1,191 @@
#nullable enable
using SideScrollerGame.Content;
using SideScrollerGame.Content.Samples;
using SideScrollerGame.Hero.Rules;
namespace SideScrollerGame.Content.Tests;
public class HeroRuntimeServiceTests
{
[Fact]
public void StartState_UsesDifficultyShieldsAndRetries()
{
HeroRuntimeService service = CreateService("difficulty.normal");
Assert.Equal(HeroLifeState.Alive, service.State.LifeState);
Assert.Equal(3, service.State.ShieldCharges);
Assert.Equal(3, service.State.RetryCount);
Assert.Equal("weapon.primary.basic", service.State.PrimaryWeaponSlots[0]);
Assert.Null(service.State.PrimaryWeaponSlots[1]);
Assert.Equal("weapon.secondary.vertical", service.State.CurrentSecondaryWeaponId);
}
[Fact]
public void ApplyHit_ConsumesShieldsBeforeDeath()
{
HeroRuntimeService service = CreateService();
service.ApplyHit(false);
Assert.Equal(HeroLifeState.Alive, service.State.LifeState);
Assert.Equal(2, service.State.ShieldCharges);
}
[Fact]
public void ApplyHit_WithNoShieldsAndRetries_EntersDeadState()
{
HeroRuntimeService service = CreateService();
service.RemoveShieldCharge(3);
service.ApplyHit(false);
Assert.Equal(HeroLifeState.Dead, service.State.LifeState);
Assert.Equal(3, service.State.RetryCount);
}
[Fact]
public void Rebirth_ConsumesRetryAndRestoresDifficultyShields()
{
HeroRuntimeService service = CreateService();
service.Kill();
HeroRuleResult result = service.Rebirth();
Assert.True(result.Succeeded);
Assert.Equal(HeroLifeState.Alive, service.State.LifeState);
Assert.Equal(2, service.State.RetryCount);
Assert.Equal(3, service.State.ShieldCharges);
}
[Fact]
public void Kill_WithZeroRetries_EntersGameOver()
{
HeroRuntimeService service = CreateService();
service.SetRetryCount(0);
service.Kill();
Assert.Equal(HeroLifeState.GameOver, service.State.LifeState);
Assert.Equal(0, service.State.RetryCount);
}
[Fact]
public void AddPoints_LevelsUpAndAddsShields()
{
HeroRuntimeService service = CreateService();
service.AddPoints(500);
Assert.Equal(2, service.State.Level);
Assert.Equal(500, service.State.Points);
Assert.Equal(4, service.State.ShieldCharges);
}
[Fact]
public void AddPoints_CanCrossMultipleThresholds()
{
HeroRuntimeService service = CreateService();
service.AddPoints(3000);
Assert.Equal(4, service.State.Level);
Assert.Equal(6, service.State.ShieldCharges);
}
[Fact]
public void PrimaryPickup_FillsEmptySlotBeforeReplacingSelectedSlot()
{
HeroRuntimeService service = CreateService();
service.ApplyPrimaryWeaponPickup("weapon.primary.basic");
Assert.Equal("weapon.primary.basic", service.State.PrimaryWeaponSlots[1]);
service.TogglePrimaryWeaponSlot();
service.ApplyPrimaryWeaponPickup("weapon.primary.basic");
Assert.Equal(1, service.State.SelectedPrimaryWeaponSlotIndex);
Assert.Equal("weapon.primary.basic", service.State.PrimaryWeaponSlots[1]);
}
[Fact]
public void TogglePrimaryWeaponSlot_ChangesSelectedSlot()
{
HeroRuntimeService service = CreateService();
service.TogglePrimaryWeaponSlot();
Assert.Equal(1, service.State.SelectedPrimaryWeaponSlotIndex);
}
[Fact]
public void SecondaryPickup_ReplacesCurrentSecondary()
{
HeroRuntimeService service = CreateService();
service.ApplySecondaryWeaponPickup("weapon.secondary.vertical");
Assert.Equal("weapon.secondary.vertical", service.State.CurrentSecondaryWeaponId);
}
[Fact]
public void SpecialAmmo_DoesNotDropBelowZero()
{
HeroRuntimeService service = CreateService();
service.AddSpecialAmmo(-100);
Assert.Equal(0, service.State.SpecialAmmo);
}
[Fact]
public void SquadronMatePickup_ChangesTypeAndCapsCount()
{
HeroRuntimeService service = CreateService();
for (int i = 0; i < 6; i++)
{
service.ApplySquadronMatePickup("squadron.orbit");
}
Assert.Equal("squadron.orbit", service.State.SquadronMateTypeId);
Assert.Equal(4, service.State.SquadronMateCount);
}
[Fact]
public void ClearInventory_ResetsCollectibleDerivedState()
{
HeroRuntimeService service = CreateService();
service.TogglePrimaryWeaponSlot();
service.ApplyPrimaryWeaponPickup("weapon.primary.basic");
service.AddSpecialAmmo(3);
service.ApplySquadronMatePickup("squadron.orbit");
service.ClearInventory();
Assert.Equal(0, service.State.SelectedPrimaryWeaponSlotIndex);
Assert.Equal("weapon.primary.basic", service.State.PrimaryWeaponSlots[0]);
Assert.Null(service.State.PrimaryWeaponSlots[1]);
Assert.Equal("weapon.secondary.vertical", service.State.CurrentSecondaryWeaponId);
Assert.Equal(12, service.State.SpecialAmmo);
Assert.Equal(string.Empty, service.State.SquadronMateTypeId);
Assert.Equal(0, service.State.SquadronMateCount);
}
[Fact]
public void ApplyHit_WithInvulnerability_PreventsDamage()
{
HeroRuntimeService service = CreateService();
service.ApplyHit(true);
Assert.Equal(HeroLifeState.Alive, service.State.LifeState);
Assert.Equal(3, service.State.ShieldCharges);
}
private static HeroRuntimeService CreateService(string difficultyId = "difficulty.normal")
{
ContentRegistry registry = SampleContent.CreateRegistry();
return new HeroRuntimeService(registry, HeroRuleConfig.CreateDefault(), difficultyId);
}
}