Attack Boon Changes
This commit is contained in:
@@ -11,10 +11,13 @@ using System.Collections.Generic;
|
||||
namespace ProjectM.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// Pins the two-channel boon lifecycle: <see cref="BoonApplySystem"/> (a valid pick appends exactly ONE
|
||||
/// boon-band <see cref="StatModifier"/> and clears Pending; out-of-range / not-pending / closed-lifecycle picks
|
||||
/// are rejected; the grace auto-pick deals Option0) and the RunDirector Returning-edge RANGE STRIP (every
|
||||
/// boon-band row dies; class/meta/equip bands survive; offers zeroed) — run boons NEVER persist (DR-037).
|
||||
/// Pins the two-channel boon lifecycle (Phase 1.7 table). <see cref="BoonApplySystem"/>: a valid STAT pick appends
|
||||
/// exactly ONE boon-band <see cref="StatModifier"/> and clears Pending; a MECHANIC-CHANGER pick mutates
|
||||
/// <see cref="BoonEffects"/> (no StatModifier row); out-of-range / not-pending / closed-lifecycle picks are rejected;
|
||||
/// the grace auto-pick deals Option0. The RunDirector Returning-edge strip: every boon-band StatModifier dies,
|
||||
/// BoonEffects is zeroed, the Frenzy timed row is removed from BOTH buffers, and class/meta/equip bands survive.
|
||||
/// New default table ids: 1 Piercing (effect), 4 Detonating (effect), 9 Executioner (Damage +50%),
|
||||
/// 10 Titan (MaxHealth +60), 11 Fleet Foot (MoveSpeed +18%).
|
||||
/// </summary>
|
||||
public class BoonApplyTests
|
||||
{
|
||||
@@ -48,9 +51,11 @@ namespace ProjectM.Tests
|
||||
return (world, group, dir, catalog);
|
||||
}
|
||||
|
||||
static Entity MakePicker(EntityManager em, int netId, byte o0 = 1, byte o1 = 4, byte o2 = 5)
|
||||
// Defaults to STAT ids so an accepted pick appends a StatModifier row (o1 = 11 Fleet Foot).
|
||||
static Entity MakePicker(EntityManager em, int netId, byte o0 = 9, byte o1 = 11, byte o2 = 10)
|
||||
{
|
||||
var e = em.CreateEntity(typeof(PlayerTag), typeof(BoonOffer), typeof(GhostOwner), typeof(RegionTag));
|
||||
var e = em.CreateEntity(typeof(PlayerTag), typeof(BoonOffer), typeof(GhostOwner), typeof(RegionTag),
|
||||
typeof(BoonEffects));
|
||||
em.AddBuffer<StatModifier>(e);
|
||||
em.SetComponentData(e, new GhostOwner { NetworkId = netId });
|
||||
em.SetComponentData(e, new RegionTag { Region = RegionId.Expedition });
|
||||
@@ -78,14 +83,14 @@ namespace ProjectM.Tests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ValidPick_AppendsBoonBandRow_AndClearsPending()
|
||||
public void ValidStatPick_AppendsBoonBandRow_AndClearsPending()
|
||||
{
|
||||
var (world, group, dir, catalog) = MakeWorld(RunLifecycle.RoomReward);
|
||||
using (world)
|
||||
{
|
||||
var em = world.EntityManager;
|
||||
var player = MakePicker(em, 1);
|
||||
SendPick(em, 1, index: 1); // Option1 = id 4 (Fleet Foot, MoveSpeed +12%)
|
||||
SendPick(em, 1, index: 1); // Option1 = id 11 (Fleet Foot, MoveSpeed +18%)
|
||||
|
||||
group.Update();
|
||||
|
||||
@@ -93,12 +98,31 @@ namespace ProjectM.Tests
|
||||
var mods = em.GetBuffer<StatModifier>(player);
|
||||
Assert.AreEqual((byte)StatTarget.MoveSpeed, mods[0].Target, "the picked def's target");
|
||||
Assert.AreEqual((byte)ModOp.PercentAdd, mods[0].Op);
|
||||
Assert.AreEqual(0.12f, mods[0].Value, 1e-4f);
|
||||
Assert.AreEqual(0.18f, mods[0].Value, 1e-4f);
|
||||
Assert.AreEqual(0, em.GetComponentData<BoonOffer>(player).Pending, "pick consumed");
|
||||
Assert.AreEqual(1u, em.GetComponentData<RunRuntime>(dir).BoonPickCounter, "band provenance advanced");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EffectPick_MutatesBoonEffects_AppendsNoStatRow()
|
||||
{
|
||||
var (world, group, dir, catalog) = MakeWorld(RunLifecycle.RoomReward);
|
||||
using (world)
|
||||
{
|
||||
var em = world.EntityManager;
|
||||
var player = MakePicker(em, 1, o0: 1); // Option0 = id 1 (Piercing Shots — a mechanic-changer)
|
||||
SendPick(em, 1, index: 0);
|
||||
|
||||
group.Update();
|
||||
|
||||
Assert.AreEqual(0, BoonRows(em, player), "a mechanic-changer appends NO StatModifier row");
|
||||
Assert.AreEqual(1, em.GetComponentData<BoonEffects>(player).Pierce, "Pierce incremented");
|
||||
Assert.AreEqual(0, em.GetComponentData<BoonOffer>(player).Pending, "pick consumed");
|
||||
Assert.AreEqual(0u, em.GetComponentData<RunRuntime>(dir).BoonPickCounter, "no band row → counter unchanged");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Rejects_NotPending_ClosedLifecycle_KeepsBufferClean()
|
||||
{
|
||||
@@ -106,7 +130,7 @@ namespace ProjectM.Tests
|
||||
var (w1, g1, d1, c1) = MakeWorld(RunLifecycle.RoomReward);
|
||||
_worlds.Add(w1);
|
||||
var p1 = MakePicker(w1.EntityManager, 1);
|
||||
w1.EntityManager.SetComponentData(p1, new BoonOffer { Pending = 0, Option0 = 1 });
|
||||
w1.EntityManager.SetComponentData(p1, new BoonOffer { Pending = 0, Option0 = 9 });
|
||||
SendPick(w1.EntityManager, 1, 0);
|
||||
g1.Update();
|
||||
Assert.AreEqual(0, BoonRows(w1.EntityManager, p1), "not-pending pick rejected");
|
||||
@@ -129,7 +153,7 @@ namespace ProjectM.Tests
|
||||
using (world)
|
||||
{
|
||||
var em = world.EntityManager;
|
||||
var afk = MakePicker(em, 1, o0: 5); // Option0 = id 5 (Iron Constitution, +25 MaxHealth)
|
||||
var afk = MakePicker(em, 1, o0: 10); // Option0 = id 10 (Titan's Vigor, +60 MaxHealth)
|
||||
var run = em.GetComponentData<RunRuntime>(dir);
|
||||
run.RewardGraceTick = T0 - 10; // already elapsed
|
||||
em.SetComponentData(dir, run);
|
||||
@@ -144,9 +168,10 @@ namespace ProjectM.Tests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReturningStrip_KillsBoonBand_SparesClassMetaEquip()
|
||||
public void ReturningStrip_KillsBoonBand_ZeroesEffects_SparesClassMetaEquip()
|
||||
{
|
||||
// Drive the REAL RunDirectorSystem Returning edge over a player carrying all four bands.
|
||||
// Drive the REAL RunDirectorSystem Returning edge over a player carrying all four StatModifier bands
|
||||
// PLUS mechanic-changer BoonEffects + a Frenzy timed row (StatModifier + TimedModifier).
|
||||
var world = new World("BoonStripTest");
|
||||
using (world)
|
||||
{
|
||||
@@ -163,24 +188,29 @@ namespace ProjectM.Tests
|
||||
em.SetComponentData(dir, new RunRuntime { RunSeed = 7u, RunEpoch = 1, RoomsClearedThisRun = 3 });
|
||||
|
||||
var player = em.CreateEntity(typeof(PlayerTag), typeof(PlayerReady), typeof(BoonOffer),
|
||||
typeof(RegionTag), typeof(LocalTransform));
|
||||
typeof(RegionTag), typeof(LocalTransform), typeof(BoonEffects));
|
||||
em.SetComponentData(player, new RegionTag { Region = RegionId.Expedition });
|
||||
em.SetComponentData(player, LocalTransform.Identity);
|
||||
em.SetComponentData(player, new BoonOffer { Pending = 1, Option0 = 1 });
|
||||
em.SetComponentData(player, new BoonEffects { Pierce = 2, Flags = BoonFlag.Frenzy });
|
||||
var mods = em.AddBuffer<StatModifier>(player);
|
||||
mods.Add(new StatModifier { Target = 0, Op = 1, Value = 0.2f, SourceId = Tuning.BoonSourceIdBase }); // boon
|
||||
mods.Add(new StatModifier { Target = 0, Op = 1, Value = 0.5f, SourceId = Tuning.BoonSourceIdBase + 1 }); // boon
|
||||
mods.Add(new StatModifier { Target = 1, Op = 2, Value = -0.3f, SourceId = Tuning.FrenzySourceId }); // Frenzy (boon band top)
|
||||
mods.Add(new StatModifier { Target = 6, Op = 1, Value = 0.1f, SourceId = Tuning.ClassSourceId }); // class
|
||||
mods.Add(new StatModifier { Target = 8, Op = 0, Value = 10f, SourceId = 0x00E7A000u }); // meta (12a band)
|
||||
mods.Add(new StatModifier { Target = 0, Op = 0, Value = 5f, SourceId = Tuning.EquipSourceIdBase }); // equip
|
||||
var timed = em.AddBuffer<TimedModifier>(player);
|
||||
timed.Add(new TimedModifier { SourceId = Tuning.FrenzySourceId, UntilTick = T0 + 100 });
|
||||
|
||||
group.Update(); // Returning: strip + bank + home -> Staging
|
||||
|
||||
var after = em.GetBuffer<StatModifier>(player);
|
||||
Assert.AreEqual(3, after.Length, "both boon rows stripped, all three permanent bands survive");
|
||||
Assert.AreEqual(3, after.Length, "both boon-band rows (incl. Frenzy) stripped, three permanent bands survive");
|
||||
for (int i = 0; i < after.Length; i++)
|
||||
Assert.IsFalse(after[i].SourceId >= Tuning.BoonSourceIdBase
|
||||
&& after[i].SourceId < Tuning.BoonSourceIdBase + Tuning.BoonSourceIdSpan, "no boon-band survivor");
|
||||
Assert.AreEqual(0, em.GetBuffer<TimedModifier>(player).Length, "Frenzy timed row stripped");
|
||||
Assert.AreEqual(default(BoonEffects), em.GetComponentData<BoonEffects>(player), "mechanic-changer effects zeroed");
|
||||
Assert.AreEqual(0, em.GetComponentData<BoonOffer>(player).Pending, "straggler offer zeroed");
|
||||
Assert.AreEqual(RunLifecycle.Staging, em.GetComponentData<RunInfo>(dir).Lifecycle);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user