Map Updates
This commit is contained in:
@@ -113,5 +113,117 @@ namespace ProjectM.Tests
|
||||
Assert.IsTrue(em.Exists(proj), "A projectile that hits no node survives (no destroy-on-miss).");
|
||||
}
|
||||
}
|
||||
|
||||
static Entity MakeClutter(EntityManager em, float3 pos, float hitRadius, int remaining, float scrapPerHit)
|
||||
{
|
||||
var e = em.CreateEntity();
|
||||
em.AddComponentData(e, LocalTransform.FromPosition(pos));
|
||||
em.AddComponentData(e, new HitRadius { Value = hitRadius });
|
||||
em.AddComponentData(e, new BlightClutter { Remaining = remaining, Variant = 0, ScrapResourceId = ResourceId.Biomass, ScrapPerHit = scrapPerHit });
|
||||
return e;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Clutter_Hit_Deposits_Scrap_Decrements_And_Consumes_Projectile()
|
||||
{
|
||||
var (world, group, ledger) = MakeWorld("ClutterHit");
|
||||
using (world)
|
||||
{
|
||||
var em = world.EntityManager;
|
||||
var clutter = MakeClutter(em, new float3(10, 1, 10), hitRadius: 1f, remaining: 8, scrapPerHit: 2f);
|
||||
var proj = MakeProjectile(em, new float3(10, 1, 10), new float2(1, 0), lastStep: 5f);
|
||||
|
||||
group.Update();
|
||||
|
||||
Assert.AreEqual(2, LedgerCount(em, ledger, ResourceId.Biomass), "Smashing clutter deposits ScrapPerHit Biomass.");
|
||||
Assert.AreEqual(6, em.GetComponentData<BlightClutter>(clutter).Remaining, "Clutter Remaining decrements by the scrap amount.");
|
||||
Assert.IsTrue(em.Exists(clutter), "Clutter with hit-points left survives.");
|
||||
Assert.IsFalse(em.Exists(proj), "The smashing projectile is consumed.");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Clutter_Two_Projectiles_Shatter_It_At_Most_Once()
|
||||
{
|
||||
var (world, group, ledger) = MakeWorld("ClutterShatter");
|
||||
using (world)
|
||||
{
|
||||
var em = world.EntityManager;
|
||||
var clutter = MakeClutter(em, new float3(10, 1, 10), hitRadius: 1f, remaining: 3, scrapPerHit: 2f);
|
||||
var p1 = MakeProjectile(em, new float3(10, 1, 10), new float2(1, 0), lastStep: 5f);
|
||||
var p2 = MakeProjectile(em, new float3(10, 1, 10), new float2(0, 1), lastStep: 5f);
|
||||
|
||||
group.Update();
|
||||
|
||||
Assert.AreEqual(4, LedgerCount(em, ledger, ResourceId.Biomass), "Both hits deposit scrap, even though the second over-clears.");
|
||||
Assert.IsFalse(em.Exists(clutter), "Shattered clutter is destroyed exactly once (a double destroy would throw at playback).");
|
||||
Assert.IsFalse(em.Exists(p1));
|
||||
Assert.IsFalse(em.Exists(p2));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Overlapping_Node_And_Clutter_Consume_Projectile_Once_Hitting_Nearest()
|
||||
{
|
||||
var (world, group, ledger) = MakeWorld("OverlapNearest");
|
||||
using (world)
|
||||
{
|
||||
var em = world.EntityManager;
|
||||
// Segment runs +X from x=0 (segStart = pos - dir*lastStep) to x=10 (pos). Clutter at x=4 is nearer
|
||||
// along the segment (t=0.4) than the node at x=9 (t=0.9), so the unified best-t sweep hits clutter.
|
||||
var clutter = MakeClutter(em, new float3(4, 1, 0), hitRadius: 1f, remaining: 100, scrapPerHit: 2f);
|
||||
var node = MakeNode(em, new float3(9, 1, 0), hitRadius: 1f, resourceId: ResourceId.Ore, remaining: 100, perHit: 25f);
|
||||
var proj = MakeProjectile(em, new float3(10, 1, 0), new float2(1, 0), lastStep: 10f);
|
||||
|
||||
group.Update();
|
||||
|
||||
Assert.AreEqual(2, LedgerCount(em, ledger, ResourceId.Biomass), "The nearest target (clutter) is harvested.");
|
||||
Assert.AreEqual(0, LedgerCount(em, ledger, ResourceId.Ore), "The farther target (node) is NOT hit — one projectile, one target.");
|
||||
Assert.AreEqual(98, em.GetComponentData<BlightClutter>(clutter).Remaining);
|
||||
Assert.AreEqual(100, em.GetComponentData<ResourceNode>(node).Remaining, "Node untouched.");
|
||||
Assert.IsFalse(em.Exists(proj), "The projectile is consumed exactly once (no double-destroy across the two target types).");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Fractional_ScrapPerHit_Still_Deposits_And_Depletes_Never_Immortal()
|
||||
{
|
||||
var (world, group, ledger) = MakeWorld("FractionalScrap");
|
||||
using (world)
|
||||
{
|
||||
var em = world.EntityManager;
|
||||
// A sub-1.0 per-hit yield must NOT truncate to 0 (that would make the target immortal + eat shots).
|
||||
var clutter = MakeClutter(em, new float3(10, 1, 10), hitRadius: 1f, remaining: 2, scrapPerHit: 0.5f);
|
||||
var proj = MakeProjectile(em, new float3(10, 1, 10), new float2(1, 0), lastStep: 5f);
|
||||
|
||||
group.Update();
|
||||
|
||||
Assert.AreEqual(1, LedgerCount(em, ledger, ResourceId.Biomass), "A positive sub-1.0 yield deposits at least 1 (math.max(1, (int)...)).");
|
||||
Assert.AreEqual(1, em.GetComponentData<BlightClutter>(clutter).Remaining, "Remaining decrements by at least 1, so depletion always progresses.");
|
||||
Assert.IsTrue(em.Exists(clutter), "Still alive after one hit (2 -> 1), not immortal.");
|
||||
Assert.IsFalse(em.Exists(proj), "The projectile is consumed.");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Second_Projectile_On_A_SameTick_Cleared_Target_Is_Consumed_Without_Double_Deposit()
|
||||
{
|
||||
var (world, group, ledger) = MakeWorld("SameTickCleared");
|
||||
using (world)
|
||||
{
|
||||
var em = world.EntityManager;
|
||||
// Both projectiles overlap one clutter that the FIRST hit shatters (remaining == scrapPerHit).
|
||||
var clutter = MakeClutter(em, new float3(10, 1, 10), hitRadius: 1f, remaining: 2, scrapPerHit: 2f);
|
||||
var p1 = MakeProjectile(em, new float3(10, 1, 10), new float2(1, 0), lastStep: 5f);
|
||||
var p2 = MakeProjectile(em, new float3(10, 1, 10), new float2(0, 1), lastStep: 5f);
|
||||
|
||||
group.Update();
|
||||
|
||||
Assert.AreEqual(2, LedgerCount(em, ledger, ResourceId.Biomass), "Only the first hit deposits; the second strikes the already-cleared spot (no double-deposit).");
|
||||
Assert.IsFalse(em.Exists(clutter), "The clutter is shattered exactly once.");
|
||||
Assert.IsFalse(em.Exists(p1), "First projectile consumed (harvested).");
|
||||
Assert.IsFalse(em.Exists(p2), "Second projectile is still consumed — a hit always spends the shot, even on a same-tick-cleared target.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user