Prove weapon visibility and wear across firing modes
This commit is contained in:
parent
39a407fa95
commit
dad0770174
3 changed files with 66 additions and 17 deletions
|
|
@ -1018,6 +1018,7 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
new AetheriaRuntimeBehaviorField(2, PerformanceStat(10)),
|
||||
new AetheriaRuntimeBehaviorField(5, PerformanceStat(0)),
|
||||
new AetheriaRuntimeBehaviorField(6, PerformanceStat(200)),
|
||||
new AetheriaRuntimeBehaviorField(11, PerformanceStat(7)),
|
||||
new AetheriaRuntimeBehaviorField(16, PerformanceStat(100)),
|
||||
new AetheriaRuntimeBehaviorField(17, PerformanceStat(1)),
|
||||
new AetheriaRuntimeBehaviorField(19, PerformanceStat(0.1)),
|
||||
|
|
@ -1027,7 +1028,7 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
new AetheriaRuntimeBehaviorField(24, PerformanceStat(1)),
|
||||
new AetheriaRuntimeBehaviorField(25, PerformanceStat(1))
|
||||
]);
|
||||
var weaponItem = CatalogItem("turret-smoke-weapon", weaponPayload);
|
||||
var weaponItem = WearableWeaponCatalogItem("turret-smoke-weapon", weaponPayload);
|
||||
var controllerItem = CatalogItem(
|
||||
"turret-smoke-controller",
|
||||
new AetheriaRuntimeBehaviorPayload(0, "EnergyDraw", 0,
|
||||
|
|
@ -1046,7 +1047,7 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
uncontrolled.Equipment = [new AetheriaRuntimeLoadoutItemSlotCommit
|
||||
{
|
||||
Item = new AetheriaRuntimeLoadoutItemCommit
|
||||
{ ItemKey = weaponItem.ItemKey, Quality = 1, Durability = 1, Enabled = true }
|
||||
{ ItemKey = weaponItem.ItemKey, Quality = 0, Durability = 1, Enabled = true }
|
||||
}];
|
||||
uncontrolled.Contacts = [new AetheriaRuntimeEntityContactCommit
|
||||
{ TargetEntityIndex = 1, InfoGathered = 1, Visible = true, Hostile = true }];
|
||||
|
|
@ -1086,13 +1087,13 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
{
|
||||
Rotation = "None",
|
||||
Item = new AetheriaRuntimeLoadoutItemCommit
|
||||
{ ItemKey = weaponItem.ItemKey, Quality = 1, Durability = 1, Enabled = true }
|
||||
{ ItemKey = weaponItem.ItemKey, Quality = 0, Durability = 1, Enabled = true }
|
||||
},
|
||||
new AetheriaRuntimeLoadoutItemSlotCommit
|
||||
{
|
||||
Rotation = "Half",
|
||||
Item = new AetheriaRuntimeLoadoutItemCommit
|
||||
{ ItemKey = weaponItem.ItemKey, Quality = 1, Durability = 1, Enabled = true }
|
||||
{ ItemKey = weaponItem.ItemKey, Quality = 0, Durability = 1, Enabled = true }
|
||||
},
|
||||
new AetheriaRuntimeLoadoutItemSlotCommit
|
||||
{
|
||||
|
|
@ -1138,6 +1139,12 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
"projectile velocity must enable the fossil first-order intercept aim and persist its controller state");
|
||||
Require(run.ShotReceipts.Count > 0 && run.ShotReceipts.All(receipt => receipt.WeaponOwnerIndex == 1),
|
||||
"turret controller must trigger only the exact in-range aligned weapon behavior, not its group or reversed neighbor");
|
||||
RequireNear(7, turret.StatGrids.Single(grid =>
|
||||
grid.Name == "transient-visibility:weapon:equipment:1:0").Values.Single(), 0.000001,
|
||||
"turret-triggered fire must publish the selected weapon's authored visibility through the shared shot transaction");
|
||||
Require(turret.Equipment[1].Item!.Durability < 1 &&
|
||||
Math.Abs(turret.Equipment[2].Item!.Durability - 1) < 0.000001,
|
||||
"turret-triggered fire must wear only the exact weapon that committed a shot");
|
||||
}
|
||||
|
||||
private static void DockingUsesRealBaysAndFossilUndockRules()
|
||||
|
|
@ -2181,7 +2188,7 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
source.Equipment =
|
||||
[
|
||||
new AetheriaRuntimeLoadoutItemSlotCommit { Item = new AetheriaRuntimeLoadoutItemCommit
|
||||
{ ItemKey = "test-beam", Quality = 1, Durability = 1, Enabled = true } },
|
||||
{ ItemKey = "test-beam", Quality = 0, Durability = 1, Enabled = true } },
|
||||
new AetheriaRuntimeLoadoutItemSlotCommit { Item = new AetheriaRuntimeLoadoutItemCommit
|
||||
{ ItemKey = "test-beam-capacitor", Quality = 1, Durability = 1, Enabled = true } }
|
||||
];
|
||||
|
|
@ -2206,6 +2213,7 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
new AetheriaRuntimeBehaviorField(6, PerformanceStat(150)),
|
||||
new AetheriaRuntimeBehaviorField(9, PerformanceStat(2)),
|
||||
new AetheriaRuntimeBehaviorField(10, PerformanceStat(3)),
|
||||
new AetheriaRuntimeBehaviorField(11, PerformanceStat(6)),
|
||||
new AetheriaRuntimeBehaviorField(12, new AetheriaRuntimeBehaviorValue(
|
||||
"item-key", "", 0, false, "", "beam-ammo", [], [])),
|
||||
new AetheriaRuntimeBehaviorField(13, Number(3)),
|
||||
|
|
@ -2213,7 +2221,7 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
new AetheriaRuntimeBehaviorField(17, Number(0.15))
|
||||
]);
|
||||
var catalog = new AetheriaRuntimeCatalogSnapshot(
|
||||
[CatalogItem("test-beam", payload), CatalogItem("test-beam-capacitor", CapacitorPayload(10, 1))], [], []);
|
||||
[WearableWeaponCatalogItem("test-beam", payload), CatalogItem("test-beam-capacitor", CapacitorPayload(10, 1))], [], []);
|
||||
var press = AetheriaRuntimeDaemonCommandDocument.Create(
|
||||
AetheriaRuntimeDaemonCommandKinds.SetWeaponGroupActive,
|
||||
"pilot",
|
||||
|
|
@ -2248,6 +2256,11 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
"constant weapon reload must consume its reserve cargo through the shared transaction");
|
||||
Require(source.BehaviorStates.Single(value => value.BehaviorKind == "Capacitor").CapacitorCharge < 10,
|
||||
"constant weapon must pay elapsed-time energy through canonical capacitor state");
|
||||
RequireNear(6, source.StatGrids.Single(grid =>
|
||||
grid.Name == "transient-visibility:weapon:equipment:0:0").Values.Single(), 0.000001,
|
||||
"constant fire must refresh its authored weapon visibility while the beam is committed");
|
||||
Require(source.Equipment[0].Item!.Durability < 1,
|
||||
"constant fire must apply elapsed-time wear only while its beam transaction commits");
|
||||
for (var frame = 7; frame < 11; frame++)
|
||||
AetheriaRuntimeDaemonSimulation.Step(run, new AetheriaRuntimeDaemonIntentState(), 0.1,
|
||||
new AetheriaRuntimeDaemonSimulationSettings(),
|
||||
|
|
@ -2305,7 +2318,7 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
source.Equipment = [new AetheriaRuntimeLoadoutItemSlotCommit
|
||||
{
|
||||
Item = new AetheriaRuntimeLoadoutItemCommit
|
||||
{ ItemKey = "test-charged", Quality = 1, Durability = 1, Enabled = true }
|
||||
{ ItemKey = "test-charged", Quality = 0, Durability = 1, Enabled = true }
|
||||
}];
|
||||
var target = Entity(1, 80, "raider");
|
||||
var zone = new AetheriaRuntimeZoneSnapshotCommit { ZoneIndex = 0, Entities = [source, target] };
|
||||
|
|
@ -2318,14 +2331,18 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
[
|
||||
new AetheriaRuntimeBehaviorField(2, PerformanceStat(20)),
|
||||
new AetheriaRuntimeBehaviorField(6, PerformanceStat(150)),
|
||||
new AetheriaRuntimeBehaviorField(11, PerformanceStat(5)),
|
||||
new AetheriaRuntimeBehaviorField(15, PerformanceStat(1000000000)),
|
||||
new AetheriaRuntimeBehaviorField(16, PerformanceStat(200)),
|
||||
new AetheriaRuntimeBehaviorField(17, PerformanceStat(1)),
|
||||
new AetheriaRuntimeBehaviorField(19, PerformanceStat(0.5)),
|
||||
new AetheriaRuntimeBehaviorField(21, PerformanceStat(1)),
|
||||
new AetheriaRuntimeBehaviorField(24, new AetheriaRuntimeBehaviorValue("bool", "", 0, true, "", "", [], [])),
|
||||
new AetheriaRuntimeBehaviorField(27, Number(2))
|
||||
new AetheriaRuntimeBehaviorField(27, Number(2)),
|
||||
new AetheriaRuntimeBehaviorField(30, Number(3))
|
||||
]);
|
||||
var catalog = new AetheriaRuntimeCatalogSnapshot(
|
||||
[WearableWeaponCatalogItem("test-charged", payload)], [], []);
|
||||
var intents = new AetheriaRuntimeDaemonIntentState();
|
||||
intents.WeaponGroups.Add(new AetheriaRuntimeDaemonWeaponGroupIntent
|
||||
{
|
||||
|
|
@ -2334,7 +2351,7 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
AetheriaRuntimeDaemonSimulation.Step(run, intents, 0.1,
|
||||
new AetheriaRuntimeDaemonSimulationSettings(),
|
||||
NewPhysics(),
|
||||
new AetheriaRuntimeCatalogSnapshot([CatalogItem("test-charged", payload)], [], []), 0, 0);
|
||||
catalog, 0, 0);
|
||||
|
||||
Require(zone.PhysicalPayloads.Count == 0 && !run.GameEvents.Any(value => value.Kind == "shot.committed"),
|
||||
"pressing an authored ChargedWeapon must not bypass charging through the instant weapon resolver");
|
||||
|
|
@ -2345,7 +2362,7 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
AetheriaRuntimeDaemonSimulation.Step(run, new AetheriaRuntimeDaemonIntentState(), 0.1,
|
||||
new AetheriaRuntimeDaemonSimulationSettings(),
|
||||
NewPhysics(),
|
||||
new AetheriaRuntimeCatalogSnapshot([CatalogItem("test-charged", payload)], [], []), frame, frame * 0.1);
|
||||
catalog, frame, frame * 0.1);
|
||||
Require(state.Charging && state.Charged && state.Charge >= 1 && state.ChargeHoldSeconds > 0,
|
||||
"one semantic request must precharge without a firing solution and enter persisted hold state");
|
||||
Require(!run.GameEvents.Any(value => value.Kind == "shot.committed"),
|
||||
|
|
@ -2354,11 +2371,16 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
AetheriaRuntimeDaemonSimulation.Step(run, new AetheriaRuntimeDaemonIntentState(), 0.1,
|
||||
new AetheriaRuntimeDaemonSimulationSettings(),
|
||||
NewPhysics(),
|
||||
new AetheriaRuntimeCatalogSnapshot([CatalogItem("test-charged", payload)], [], []), 11, 1.1);
|
||||
catalog, 11, 1.1);
|
||||
Require(run.GameEvents.Count(value => value.Kind == "weapon.charge.committed") == 1 &&
|
||||
run.GameEvents.Any(value => value.Kind == "shot.committed" &&
|
||||
value.ItemKey == "test-charged" && Math.Abs(value.ScalarValue - 40) < 0.000001),
|
||||
"stored full charge must commit automatically when a firing solution becomes available");
|
||||
RequireNear(15, source.StatGrids.Single(grid =>
|
||||
grid.Name == "transient-visibility:weapon:equipment:0:0").Values.Single(), 0.000001,
|
||||
"charged fire must publish base visibility multiplied by its committed charge modifier");
|
||||
Require(source.Equipment[0].Item!.Durability < 1,
|
||||
"charged hold must not suppress wear when the stored shot finally commits");
|
||||
var miss = run.ShotReceipts.Single(value => value.WeaponItemKey == "test-charged");
|
||||
var missDx = miss.EndpointX - target.PositionX;
|
||||
var missDz = miss.EndpointZ - target.PositionZ;
|
||||
|
|
@ -2396,7 +2418,7 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
source.Equipment = [new AetheriaRuntimeLoadoutItemSlotCommit
|
||||
{
|
||||
Item = new AetheriaRuntimeLoadoutItemCommit
|
||||
{ ItemKey = "test-instant", Quality = 1, Durability = 1, Enabled = true }
|
||||
{ ItemKey = "test-instant", Quality = 0, Durability = 1, Enabled = true }
|
||||
}];
|
||||
var target = Entity(1, 80, "raider");
|
||||
var zone = new AetheriaRuntimeZoneSnapshotCommit
|
||||
|
|
@ -2437,7 +2459,7 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
new AetheriaRuntimeBehaviorField(24, PerformanceStat(0)),
|
||||
new AetheriaRuntimeBehaviorField(25, PerformanceStat(1))
|
||||
]);
|
||||
var catalog = new AetheriaRuntimeCatalogSnapshot([CatalogItem("test-instant", payload)], [], []);
|
||||
var catalog = new AetheriaRuntimeCatalogSnapshot([WearableWeaponCatalogItem("test-instant", payload)], [], []);
|
||||
RequireNear(45,
|
||||
AetheriaRuntimeEquippedBehaviorQueries.Find(source, catalog, AetheriaRuntimeBehaviorKinds.InstantWeapon)
|
||||
.Single().EvaluateStat(23),
|
||||
|
|
@ -2472,6 +2494,8 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
grid.Name == "transient-visibility:weapon:equipment:0:0");
|
||||
RequireNear(8, weaponVisibility.Values.Single(), 0.000001,
|
||||
"committed instant shot must publish its authored visibility as a named transient source");
|
||||
Require(source.Equipment[0].Item!.Durability < 1,
|
||||
"committed instant shot must apply one round of thermal wear to its owning equipment");
|
||||
AetheriaRuntimeVisibilitySimulation.BeginTick([source], 1, 0.5);
|
||||
RequireNear(8 * Math.Exp(-0.5), weaponVisibility.Values.Single(), 0.000001,
|
||||
"weapon visibility must use the fossil exponential source decay rather than vanish with the effect");
|
||||
|
|
@ -2628,7 +2652,7 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
source.Equipment = [new AetheriaRuntimeLoadoutItemSlotCommit
|
||||
{
|
||||
Item = new AetheriaRuntimeLoadoutItemCommit
|
||||
{ ItemKey = "test-mine-layer", Quality = 1, Durability = 1, Enabled = true }
|
||||
{ ItemKey = "test-mine-layer", Quality = 0, Durability = 1, Enabled = true }
|
||||
}];
|
||||
var target = Entity(1, 50, "neutral");
|
||||
var zone = new AetheriaRuntimeZoneSnapshotCommit { ZoneIndex = 0, Entities = [source, target] };
|
||||
|
|
@ -2641,6 +2665,7 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
[
|
||||
new AetheriaRuntimeBehaviorField(2, PerformanceStat(35)),
|
||||
new AetheriaRuntimeBehaviorField(6, PerformanceStat(100)),
|
||||
new AetheriaRuntimeBehaviorField(11, PerformanceStat(4)),
|
||||
new AetheriaRuntimeBehaviorField(16, PerformanceStat(10)),
|
||||
new AetheriaRuntimeBehaviorField(17, PerformanceStat(1)),
|
||||
new AetheriaRuntimeBehaviorField(19, PerformanceStat(1)),
|
||||
|
|
@ -2651,7 +2676,7 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
new AetheriaRuntimeBehaviorField(30, PerformanceStat(50))
|
||||
]);
|
||||
var catalog = new AetheriaRuntimeCatalogSnapshot(
|
||||
[CatalogItem("test-mine-layer", payload)], [], []);
|
||||
[WearableWeaponCatalogItem("test-mine-layer", payload)], [], []);
|
||||
var fire = new AetheriaRuntimeDaemonIntentState();
|
||||
fire.WeaponGroups.Add(new AetheriaRuntimeDaemonWeaponGroupIntent
|
||||
{ ActorEntityKey = "zone.0.entity.0", WeaponGroup = 0, Fire = true, Active = true });
|
||||
|
|
@ -2661,6 +2686,11 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
NewPhysics(), catalog, 1, 0.1);
|
||||
RequireEqual(1, zone.PhysicalPayloads.Count, "deployable fire must create one persistent physical payload");
|
||||
Require(!run.ShotReceipts.Any(), "deployable fire must not masquerade as an ordinary shot receipt");
|
||||
RequireNear(4, source.StatGrids.Single(grid =>
|
||||
grid.Name == "transient-visibility:weapon:equipment:0:0").Values.Single(), 0.000001,
|
||||
"successful deployment must publish the launcher's authored weapon visibility");
|
||||
Require(source.Equipment[0].Item!.Durability < 1,
|
||||
"successful deployment must apply one round of thermal wear to its launcher");
|
||||
var mine = zone.PhysicalPayloads.Single();
|
||||
Require(mine.PositionX > 2 && mine.TriggeredAtSeconds < 0,
|
||||
"Ymir must advance the unarmed mine without inventing a trigger");
|
||||
|
|
@ -3888,6 +3918,22 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
0, 1000, Array.Empty<AetheriaRuntimeCurveKey>(), "", 1, 0, 0, 0, false,
|
||||
0, 0, "", Array.Empty<AetheriaRuntimeAudioStat>(), Array.Empty<AetheriaRuntimeCurveKey>(), "", "");
|
||||
|
||||
private static AetheriaRuntimeCatalogItem WearableWeaponCatalogItem(
|
||||
string itemKey, params AetheriaRuntimeBehaviorPayload[] payloads)
|
||||
{
|
||||
var item = CatalogItem(itemKey, payloads);
|
||||
item.Durability = 1;
|
||||
item.ThermalResilience = 1;
|
||||
item.MinimumTemperature = 0;
|
||||
item.MaximumTemperature = 1;
|
||||
item.ThermalPerformanceCurveKeys =
|
||||
[
|
||||
new AetheriaRuntimeCurveKey(0, 0.9, 0, 0),
|
||||
new AetheriaRuntimeCurveKey(1, 0.9, 0, 0)
|
||||
];
|
||||
return item;
|
||||
}
|
||||
|
||||
private static AetheriaRuntimeCatalogItem HullCatalogItem(string itemKey, int width, int height, double armor)
|
||||
{
|
||||
var cells = Enumerable.Range(0, height)
|
||||
|
|
|
|||
|
|
@ -918,7 +918,10 @@ lifecycle state.
|
|||
canonical `EnergyDraw -> TurretController` chain; restored power acquires
|
||||
without firing in the same fossil tick; projectile
|
||||
velocity enables CultMath first-order intercept; and a forward weapon fires
|
||||
while the reversed behavior remains inactive.
|
||||
while the reversed behavior remains inactive. That exact forward weapon alone
|
||||
receives thermal wear and publishes its authored transient visibility. Shared
|
||||
weapon smokes also prove those side effects for instant, constant, charged,
|
||||
and deployable transactions, including the charged visibility multiplier.
|
||||
|
||||
### Daemon Damage Transaction
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ validation proves contract shape, not wiring, exclusivity, lowering, or parity.
|
|||
| Projectile flight | weapon/projectile classes | Eve presentation for ordinary tracers; Ymir for persistent physical payloads | receipt trajectory/effect facts or persistent payload state | native projectile visual | ordinary instant, charged, and constant execution creates no projectile body; each weapon state owns a stable shot sequence and receipts carry origin, endpoint, nominal duration, and effect identity for Eve presentation; `SpawnProjectile` and its alternate writer are deleted; Ymir projectile contacts are feedback-only for explicitly persisted payload rows and cannot write damage; Ymir.Core remains embedded for world integration, radial fields, circle contacts, pickups, and genuinely persistent/interceptable payloads | split/rename the remaining physical-payload interface and remove ordinary projectile terminology from runtime contracts |
|
||||
| Shield/armor/equipment/hull damage | energy-funded shield, schematic armor cells, equipment and scalar hull | daemon canonical damage transaction | aggregate/exact armor grid, entity status, and layer-aware shot/damage receipts | schematic, meters, impacts, damage VFX | owner-exists; wired; exclusive; projected: daemon initializes armor/maximum-armor grids from hull plus hardpoint catalog topology; direct and deployable damage share one `shield -> armor cell -> equipment -> scalar hull` transaction; direct impacts select a cell or complete hardpoint footprint before orthogonal spread and 0.5-cell penetration, while splash payloads select the source-facing hull half; the fossil penetration infinite-loop defect is fixed; damage type is typed/pass-through without resistances because the fossil never applied them; Eve exposes aggregate and exact armor state and receipts identify reached/applied layers; fake Ymir contacts and presentation cannot decide damage | fossil parity fixtures for topology, edge impacts, orthogonal spread, multi-cell penetration, equipment interception, and generic shield/equipment effect lifecycle |
|
||||
| Thermal/energy | cell conduction, capacitor/reactor/radiator network, and cockpit thermal exposure | daemon | ship/equipment power, temperature, medical state, risk and death feedback | schematic/post effects | owner-exists; wired; exclusive; projected; generic timing and native asset delivery lowered: catalog hull and installed-item shapes derive cell mass/conductivity/topology; local temperature derives thermal performance, wear potential and online state; all consumers share capacitor-first/reactor-residual transactions; powered radiators pump before reactor settlement; reactor heat then enters the same cell network before conduction/radiation; cockpit-cell temperature drives the fossil nonlinear heatstroke/hypothermia accumulation, linear recovery, severe-risk crossings, and ordinary exactly-once destruction with a typed cause; Eve exposes cockpit, risk, heatstroke source-weight, phasing and death-transition facts; EveUnity generically resolves the original severe pulse plus live/reconnect-safe cause-specific death crossfade; Aetheria deterministically translates the five legacy profiles into URP profiles, persists every override as a real profile sub-asset, advertises them by semantic role through CultMesh CDN, and binds them in the canonical client through a weight-only native sink; rotated equipment topology, parent/child radiation, schematic composition, legacy SSR/AO/roundness equivalents, and live/reconnect death-fade parity remain incomplete | multi-consumer ordering, multi-radiator visibility, rotated topology, generic schematic meters, renderer-feature parity, and live/reconnect death-fade screenshots |
|
||||
| Weapons | ServerShared behaviors + Unity effects | daemon plus Ymir geometry/kinematics | action capability, weapon state, shot/damage receipts | effects/audio/HUD | instant and constant resource/timing lifecycles are daemon-owned; charged weapons accept one semantic request, spool without requiring a solution, hold at full charge, commit automatically when a solution appears, and perform deterministic once-per-second malfunction hazard checks after the authored safe hold interval with increasing persisted risk; generic Eve `weapon.state` exposes charge hold/risk and feedback exposes readiness, commit, refusal, and malfunction chronology; committed direct damage now enters the shared daemon armor-cell transaction | guided persistent payloads, visibility/wear, remaining impact-distribution parity, and Unity effect reconciliation |
|
||||
| Weapons | ServerShared behaviors + Unity effects | daemon plus Ymir geometry/kinematics | action capability, weapon state, shot/damage receipts | effects/audio/HUD | instant and constant resource/timing lifecycles are daemon-owned; charged weapons accept one semantic request, spool without requiring a solution, hold at full charge, commit automatically when a solution appears, and perform deterministic once-per-second malfunction hazard checks after the authored safe hold interval with increasing persisted risk; successful instant, constant, charged, deployable, and turret-controlled transactions publish authored transient visibility and consume the owning equipment's temperature-derived wear, with charged visibility applying its authored multiplier and turret wear remaining exact-weapon scoped; generic Eve `weapon.state` exposes charge hold/risk and feedback exposes readiness, commit, refusal, and malfunction chronology; committed direct damage now enters the shared daemon armor-cell transaction | guided persistent payloads, remaining impact-distribution parity, and Unity effect reconciliation |
|
||||
| Destruction/drops | hull death, 25% equipment rolls, unconditional cargo drops, 25-unit launch, 30-second pickups | daemon | destruction identity, death/drop events, typed pickups | provider-advertised destruction effect and pickups | owner-exists; wired; exclusive; projected: direct and deployable lethal damage commit one deterministic destruction transaction, clear live references, retain only a non-rendered identity tombstone, and emit exact pickups/events; the reserved client `DestroyEntity` command is rejected; Aetheria advertises its original big explosion as `effect.feedback.entity.destroyed`, lowered generically by EveUnity | equipment-destruction-before-hull parity and multiplayer reconnect chronology |
|
||||
| Tractor/scoop | analog tractor and physical timed pickups | daemon + Ymir | tractor power, pickup body and receipt | pickup world entity plus beam/interaction feedback | fossil 2/s power ramp and authored forward radius/traction/distance feed pickup bodies into the shared Ymir world; ship contact collects exactly once when capacity permits or applies the fossil 25-unit rejection kick; Aetheria maps pickup collision only against ship bodies, so stations and other world bodies cannot become cargo writers; 30s daemon lifetime; instant cargo teleport deleted; current-zone pickups occupy ordinary rows in the shared Eve entity SoA body with stable logical identity and provider-owned assets; `pilot.scoop` advertises a generic `button-hold.v1` scalar contract, the released client sends `1` on press and `0` on release through `SetTractorPower`, both receipts reconcile, and daemon power returns exactly to zero; the provider build removes the fossil's embedded tractor object from ship prefabs, and `beam.presentation` attaches the sole standalone effect to the SoA ship; released warm witnesses prove successful exactly-once Ymir collection and controlled-player `cargo-capacity` rejection with unchanged cargo | polish provider beam shape/attachment |
|
||||
| Dock/undock | wormhole-first interact; first eligible bay; component prerequisites | daemon + Ymir placement | dock commands/context | camera/UI transition | daemon docking now preserves the fossil transaction: stable zone order selects the first entity with a real empty bay inside the fixed 25-unit XZ center radius; undock checks installed Cockpit, Thruster-or-AetherDrive, Reactor, then empty bay cargo in source order; rejection reasons survive committed command facts into generic Eve receipts; success removes parentage without moving, stopping, or rotating the ship. Docking clears held-group and transient weapon state, docked actors reject later fire commands, and combat subtracts docked child identities from both attacker iteration and target lookup, so stale input, forged pulses, and turret controllers cannot fire through a bay. Ymir world entities retain gravity/query bodies but do not invent ship/station rigidbody collision response that would make the 25-unit rule unreachable; ship/pickup Begin contacts remain enabled. The live generic Unity witness also proves advertised actions, bay assignment, dock-parent SoA inclusion and sensor sharing, camera retargeting, controlled-subject hiding, movement suppression, and restoration on undock | reconnect, docked inventory/trade surfaces, and authored dock-camera blend/effect chronology |
|
||||
|
|
|
|||
Loading…
Reference in a new issue