Publish weapon fire refusals
This commit is contained in:
parent
9d55ab67ff
commit
52b3664adf
3 changed files with 39 additions and 1 deletions
|
|
@ -292,6 +292,7 @@ namespace GameCult.Aetheria.State.Verse
|
|||
var triggerResult = CommitWeaponRound(attacker, weapon);
|
||||
if (triggerResult == WeaponRoundResult.ReloadStarted)
|
||||
AppendWeaponEvent(run, zone, attacker, weapon, frameId, "weapon.reload.started");
|
||||
PublishWeaponRoundResult(run, zone, attacker, weapon, frameId, triggerResult);
|
||||
if (triggerResult != WeaponRoundResult.Fired) continue;
|
||||
}
|
||||
weapon.State.BurstRemaining = weapon.BurstCount;
|
||||
|
|
@ -309,6 +310,7 @@ namespace GameCult.Aetheria.State.Verse
|
|||
var roundResult = CommitWeaponRound(attacker, weapon);
|
||||
if (roundResult == WeaponRoundResult.ReloadStarted)
|
||||
AppendWeaponEvent(run, zone, attacker, weapon, frameId, "weapon.reload.started");
|
||||
PublishWeaponRoundResult(run, zone, attacker, weapon, frameId, roundResult);
|
||||
if (roundResult != WeaponRoundResult.Fired)
|
||||
{
|
||||
weapon.State.BurstRemaining = 0;
|
||||
|
|
@ -379,6 +381,39 @@ namespace GameCult.Aetheria.State.Verse
|
|||
});
|
||||
}
|
||||
|
||||
private static void PublishWeaponRoundResult(
|
||||
AetheriaRuntimeRunCheckpointCommit run,
|
||||
AetheriaRuntimeZoneSnapshotCommit zone,
|
||||
AetheriaRuntimeEntitySnapshotCommit entity,
|
||||
ResolvedWeapon weapon,
|
||||
long frameId,
|
||||
WeaponRoundResult result)
|
||||
{
|
||||
var reason = result == WeaponRoundResult.InsufficientEnergy ? "insufficient-energy" :
|
||||
result == WeaponRoundResult.NoAmmo ? "no-ammunition" : "";
|
||||
if (string.IsNullOrEmpty(reason))
|
||||
{
|
||||
weapon.State.LastRefusalReason = "";
|
||||
return;
|
||||
}
|
||||
if (string.Equals(weapon.State.LastRefusalReason, reason, StringComparison.Ordinal))
|
||||
return;
|
||||
|
||||
weapon.State.LastRefusalReason = reason;
|
||||
AetheriaRuntimeGameEvents.Append(run, new AetheriaRuntimeGameEventCommit
|
||||
{
|
||||
EventId = $"frame:{frameId}:zone:{zone.ZoneIndex}:entity:{entity.EntityIndex}:weapon:{weapon.State.OwnerIndex}:{weapon.State.BehaviorIndex}:refused:{reason}",
|
||||
Kind = "weapon.fire.refused",
|
||||
FrameId = frameId,
|
||||
ZoneIndex = zone.ZoneIndex,
|
||||
SourceEntityIndex = entity.EntityIndex,
|
||||
TargetEntityIndex = entity.TargetEntityIndex,
|
||||
SubjectKey = reason,
|
||||
ItemKey = weapon.ItemKey,
|
||||
ScalarValue = weapon.State.Ammo
|
||||
});
|
||||
}
|
||||
|
||||
private static void UpdateWeaponLock(
|
||||
AetheriaRuntimeEntitySnapshotCommit attacker,
|
||||
AetheriaRuntimeEntitySnapshotCommit target,
|
||||
|
|
|
|||
|
|
@ -1113,6 +1113,9 @@ namespace GameCult.Aetheria.State.Verse
|
|||
|
||||
[Key(18)]
|
||||
public int LockTargetEntityIndex { get; set; } = -1;
|
||||
|
||||
[Key(19)]
|
||||
public string LastRefusalReason { get; set; } = "";
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ validation proves contract shape, not wiring, exclusivity, lowering, or parity.
|
|||
| Minimap/tactical map | `ZoneRenderer`, map cameras | daemon world facts | explicit map projections | Unity and Electron | facts fragmented; generic lowerers absent | same state in both runtimes |
|
||||
| Fields/fog/gravity | zone renderer and shaders | daemon/plugin semantics | Fields plugin documents | EveUnity fields lowerer | owner-exists; basic lowering; composition parity absent | visual parity captures |
|
||||
| HUD/schematic | ARPG HUD and `SchematicDisplay` | Eve composition from daemon facts | semantic status/components | EveUnity UI | reference | source-fact and timing matrix |
|
||||
| Hit/lock/warnings | `ActionGameManager` feedback | daemon event facts | transient feedback stream | VFX/UI/audio | bounded deduplicated game-event ledger and Eve `feedback.stream` wired for pickup outcomes, projectile launch/impact, entity damage, alive-to-dead destruction, and authoritative weapon reload start/completion chronology; reload interval is proven projectile-free | add lock transitions, resource refusals, thermal and docking event families with runtime effect consumption |
|
||||
| Hit/lock/warnings | `ActionGameManager` feedback | daemon event facts | transient feedback stream | VFX/UI/audio | bounded deduplicated game-event ledger and Eve `feedback.stream` wired for pickup outcomes, projectile launch/impact, entity damage, alive-to-dead destruction, authoritative weapon reload chronology, and episode-deduplicated `weapon.fire.refused` facts for insufficient energy or missing ammunition; refusal identity, authored weapon, target, reason, and remaining magazine state are runtime-independent cockpit inputs | add lock transitions, thermal and docking event families, negative transaction fixtures, and runtime effect consumption |
|
||||
| Assets | `Assets/Resources` | Aetheria provider | asset catalog + CultMesh CDN | runtime cache/load | wired; basic lowering; not live-proven remotely | cold/warm remote-only live load and cache proof |
|
||||
| Save/resume | original persistence paths | daemon/CultCache | published current state | clients rehydrate | owner-exists; not parity-proven | mid-loop restart |
|
||||
| Terminus loop | original game composition | daemon/Ymir/Eve | pilot surface | Aetheria.Unity | incomplete; no scenario proof | fly/fire/loot/dock/trade |
|
||||
|
|
|
|||
Loading…
Reference in a new issue