Cut 12.3, sub-cut A: armour absorbs first down the direct-hit lane
Deletes Entity.DamageSchematic (the even split over the whole hit shape) and Entity.ApplyHit (the 0.5-step penetration march), replacing both with Entity.Absorb (armour then item, per cell) and Entity.DamageHull, moved verbatim from DamageSchematic's own body. FireControl.Apply now builds 2n+1 parallel lanes from the committed Bearing/Lateral (Q12-2 = A), shares damage evenly over the lanes that meet metal, walks each lane in order via the already-verified FireControl.Lane, absorbing cell by cell up to the penetration depth, and sends every lane's own remainder to the hull where it ends (Q12-3 = A). Splash is rewritten onto Absorb/DamageHull (arithmetically identical to before) since DamageSchematic is gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
c7b6e80c70
commit
70c3e0ccdb
3 changed files with 117 additions and 86 deletions
|
|
@ -329,52 +329,55 @@ public abstract class Entity
|
|||
? TargetItem.Value
|
||||
: null;
|
||||
|
||||
// Cut 3 (docs/fire-control-cut.md): the damage rule moved verbatim from EntityInstance.cs's Unity
|
||||
// HullCollider subscription (DamageSchematic) -- same arithmetic, same order, same thresholds. The only
|
||||
// thing that changed is the owner: this entity's own schematic, armor and hull, not a Unity component
|
||||
// reacting to a physics collision.
|
||||
public void DamageSchematic(float damage, Shape hitShape)
|
||||
// Cut 12.3 (docs/fire-control-cut.md): "armour absorbs first" -- moved verbatim from DamageSchematic's own
|
||||
// per-cell body (Cut 3), now called once per lane cell (FireControl.Apply) instead of once per hit-shape
|
||||
// cell with an even split. Armor absorbs up to its own value, then the occupying item once the remainder
|
||||
// exceeds .1f, and whatever is left over is returned to the caller for the hull's own share (or the next
|
||||
// cell down the lane, for a lane that keeps carrying a remainder is not this function's concern -- Apply's
|
||||
// own loop does that). ArmorDamage/ItemDamage fire only for incoming > 0 -- a cell a spent lane still walks
|
||||
// past (rem already 0) takes no event and no recorded hit.
|
||||
public float Absorb(int2 cell, float damage)
|
||||
{
|
||||
var hullData = ItemManager.GetData(Hull) as HullData;
|
||||
foreach (var v in hitShape.Coordinates)
|
||||
hitShape[v] = hitShape[v] && hullData.Shape[v];
|
||||
var d = damage;
|
||||
|
||||
float hullDamage = 0;
|
||||
var damagePerCell = damage / hitShape.Coordinates.Length;
|
||||
foreach (var v in hitShape.Coordinates)
|
||||
if (d > 0f)
|
||||
{
|
||||
var d = damagePerCell;
|
||||
|
||||
// Subtract surface damage from armor, passing on the remainder to the item and then to the hull
|
||||
var prev = Armor[v.x, v.y];
|
||||
Armor[v.x, v.y] = max(prev - d, 0);
|
||||
ArmorDamage.OnNext((v, d));
|
||||
d = max(d - prev, 0);
|
||||
|
||||
if (d > 0.1f)
|
||||
{
|
||||
var item = GearOccupancy[v.x, v.y];
|
||||
if (item != null)
|
||||
{
|
||||
prev = item.EquippableItem.Durability;
|
||||
item.EquippableItem.Durability = max(prev - d, 0);
|
||||
ItemDamage.OnNext((item, d));
|
||||
d = max(d - prev, 0);
|
||||
}
|
||||
}
|
||||
|
||||
hullDamage += d;
|
||||
var prevArmor = Armor[cell.x, cell.y];
|
||||
Armor[cell.x, cell.y] = max(prevArmor - d, 0);
|
||||
ArmorDamage.OnNext((cell, d));
|
||||
d = max(d - prevArmor, 0);
|
||||
}
|
||||
|
||||
if (hullDamage > .1f)
|
||||
if (d > 0.1f)
|
||||
{
|
||||
Hull.Durability -= hullDamage;
|
||||
HullDamage.OnNext(hullDamage);
|
||||
var item = GearOccupancy[cell.x, cell.y];
|
||||
if (item != null)
|
||||
{
|
||||
var prevItem = item.EquippableItem.Durability;
|
||||
item.EquippableItem.Durability = max(prevItem - d, 0);
|
||||
ItemDamage.OnNext((item, d));
|
||||
d = max(d - prevItem, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
// Cut 12.3: moved verbatim from DamageSchematic's own tail (Cut 3) -- the >.1f threshold and the one
|
||||
// HullDamage event are unchanged. FireControl.Apply calls this once per resolved hit, with the summed
|
||||
// remainder every lane's own walk left over (Q12-3 = A: a lane's remainder goes to the hull wherever the
|
||||
// lane ends -- penetration exhausted, a gap, or the far side).
|
||||
public void DamageHull(float damage)
|
||||
{
|
||||
if (damage > .1f)
|
||||
{
|
||||
Hull.Durability -= damage;
|
||||
HullDamage.OnNext(damage);
|
||||
}
|
||||
}
|
||||
|
||||
// Cut 12.1 (docs/fire-control-cut.md): the one schematic-frame owner. Maps a world-planar vector into this
|
||||
// entity's own schematic frame -- x = starboard, y = bow -- so ApplyHit's penetration march and
|
||||
// entity's own schematic frame -- x = starboard, y = bow -- so FireControl.Apply's lane walk and
|
||||
// FireControl.Splash's directional half both read the same transform instead of each carrying their own
|
||||
// copy of forward/right.
|
||||
public float2 ToSchematic(float2 worldPlanar)
|
||||
|
|
@ -384,40 +387,6 @@ public abstract class Entity
|
|||
return float2(dot(worldPlanar, right), dot(worldPlanar, forward));
|
||||
}
|
||||
|
||||
// Cut 3: the shape construction moved from EntityInstance.cs's Unity HullCollider subscription -- the hit
|
||||
// cell is the rolled Cell FireControl already chose, not a UV texture coordinate.
|
||||
// Cut 12.2 (docs/fire-control-cut.md): `bearing` is already in this entity's own schematic frame -- the
|
||||
// committed ShotOutcome.Bearing FireControl.Commit computed once, at the commit tick -- so the ToSchematic
|
||||
// call this used to make internally (12.1) is gone; ApplyHit no longer touches a world direction or this
|
||||
// entity's own Direction at all.
|
||||
public void ApplyHit(Entity source, int2 cell, float spread, float penetration, float damage, float2 bearing)
|
||||
{
|
||||
IncomingHit.OnNext(source);
|
||||
|
||||
var hullData = ItemManager.GetData(Hull) as HullData;
|
||||
var hitShape = new Shape(hullData.Shape.Width, hullData.Shape.Height);
|
||||
hitShape[cell] = true;
|
||||
|
||||
for (var i = 0; i < (int) floor(spread + .5f); i++)
|
||||
hitShape = hitShape.Expand();
|
||||
|
||||
if (penetration > .5f)
|
||||
{
|
||||
var penetrationVector = normalize(bearing);
|
||||
|
||||
var penetrationPoint = (float2) cell + float2(.5f);
|
||||
var penetrationDistance = 0f;
|
||||
while (penetrationDistance < penetration && hullData.Shape[int2(penetrationPoint)])
|
||||
{
|
||||
penetrationDistance += .5f;
|
||||
hitShape[int2(penetrationPoint)] = true;
|
||||
penetrationPoint += penetrationVector * .5f;
|
||||
}
|
||||
}
|
||||
|
||||
DamageSchematic(damage, hitShape);
|
||||
}
|
||||
|
||||
// Another entity's stance toward THIS one, as far as this entity can perceive it: unknown (null)
|
||||
// until this entity detects them, mirroring the existing detection model (VisibleEntities, driven
|
||||
// by EntityInfoGathered crossing TargetDetectionInfoThreshold). Detected but not yet hostility-rated
|
||||
|
|
|
|||
Loading…
Reference in a new issue