Audio 1: the simulation names no sound; delete the dead Wwise path on EquippedItem
Removes EquippedItem's SoundBank, AudioEvents/AudioParameters, every FireAudioEvent/PlaySound/StopSound/SetAudioParameter overload and Update's AudioStats loop, the four audio enums, WwiseMetadata and WwiseSoundBinding, the weapon/reactor/thruster call sites, and the Wwise Sounds counters in FireControlPerWeaponTests (Announced and Starts keep the refused-round pins). Catalog keys 21, 22 and 13-15 stay, unread. Builds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
6b6e7c7c26
commit
2102affb09
11 changed files with 7 additions and 259 deletions
|
|
@ -145,7 +145,6 @@ public class ChargedWeapon : InstantWeapon
|
|||
if (_charging)
|
||||
{
|
||||
_charge += dt / ChargeTime;
|
||||
Item.SetAudioParameter(SpecialAudioParameter.ChargeLevel, saturate(_charge));
|
||||
if (!_charged)
|
||||
{
|
||||
AddHeat(ChargeHeat * (dt / ChargeTime));
|
||||
|
|
@ -162,7 +161,6 @@ public class ChargedWeapon : InstantWeapon
|
|||
_coolingDown = true;
|
||||
_charge = 0;
|
||||
OnFailed?.Invoke();
|
||||
Item.FireAudioEvent(ChargedWeaponAudioEvent.Fail);
|
||||
CauseDamage(_data.FailureDamage);
|
||||
}
|
||||
}
|
||||
|
|
@ -177,7 +175,6 @@ public class ChargedWeapon : InstantWeapon
|
|||
if(!_charging && CanFire && !FireControl.Refuses(this, Entity))
|
||||
{
|
||||
OnStartCharging?.Invoke();
|
||||
Item.FireAudioEvent(ChargedWeaponAudioEvent.Start);
|
||||
_charging = true;
|
||||
_charged = false;
|
||||
}
|
||||
|
|
@ -193,7 +190,6 @@ public class ChargedWeapon : InstantWeapon
|
|||
_charge = 0;
|
||||
}
|
||||
OnStopCharging?.Invoke();
|
||||
Item.FireAudioEvent(ChargedWeaponAudioEvent.Stop);
|
||||
_charging = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -240,7 +240,6 @@ public class InstantWeapon : Weapon, IProgressBehavior, IEventBehavior, IPowerCo
|
|||
}
|
||||
}
|
||||
|
||||
var firedThisFrame = false;
|
||||
_burstTimer += dt;
|
||||
while (_burstRemaining > 0 && _burstTimer > 0)
|
||||
{
|
||||
|
|
@ -280,11 +279,6 @@ public class InstantWeapon : Weapon, IProgressBehavior, IEventBehavior, IPowerCo
|
|||
// Evaluate it into a local first.
|
||||
var shotId = FireControl.Fire(this, Item, Entity);
|
||||
OnFire?.Invoke(shotId);
|
||||
if(!firedThisFrame)
|
||||
{
|
||||
Item.FireAudioEvent(WeaponAudioEvent.Fire);
|
||||
firedThisFrame = true;
|
||||
}
|
||||
CauseWearDamage(1);
|
||||
AddHeat(Heat);
|
||||
Entity.SetSignature(this, SignatureChannel.LaunchFlash, Visibility, Item);
|
||||
|
|
|
|||
|
|
@ -94,8 +94,6 @@ public class Reactor : Behavior
|
|||
Draw = 0;
|
||||
}
|
||||
|
||||
Item.SetAudioParameter(SpecialAudioParameter.Intensity, max(.25f, 1 - 1 / CurrentLoadRatio));
|
||||
|
||||
AddHeat(heat);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,7 +109,6 @@ public class Thruster : Behavior, IPowerConsumer
|
|||
|
||||
public override bool Execute(float dt)
|
||||
{
|
||||
Item.SetAudioParameter(SpecialAudioParameter.Intensity, _input);
|
||||
// Cut 7 (docs/stats-and-power-target.md): "continuous consumers brown out ... through a power supply
|
||||
// curve on their performance stats." Thrust below is a plain Evaluate() read, so once the catalog's own
|
||||
// Thrust stat carries a PowerSupply term, a partial grant already comes back reduced -- this gate no
|
||||
|
|
|
|||
|
|
@ -2149,7 +2149,6 @@ public class EquippedItem : IStatContext
|
|||
|
||||
private bool _thermalOnline;
|
||||
private bool _durabilityOnline;
|
||||
public WwiseMetaSoundBank SoundBank;
|
||||
|
||||
public Behavior[] Behaviors { get; }
|
||||
public Dictionary<int, BehaviorGroup> BehaviorGroups { get; }
|
||||
|
|
@ -2175,10 +2174,6 @@ public class EquippedItem : IStatContext
|
|||
public ReadOnlyReactiveProperty<bool> Active { get; }
|
||||
public ItemManager ItemManager { get; }
|
||||
|
||||
public Subject<uint> AudioEvents { get; } = new Subject<uint>();
|
||||
public Subject<(uint id, float v)> AudioParameters { get; } = new Subject<(uint id, float v)>();
|
||||
public Dictionary<uint, float> AudioParameterValues { get; } = new Dictionary<uint, float>();
|
||||
|
||||
private float oldTemperature;
|
||||
public float Temperature
|
||||
{
|
||||
|
|
@ -2190,77 +2185,6 @@ public class EquippedItem : IStatContext
|
|||
}
|
||||
}
|
||||
|
||||
public void FireAudioEvent(uint eventId, bool skipVerify = false)
|
||||
{
|
||||
if(SoundBank != null && (skipVerify || SoundBank.IncludedEvents.Any(o => o.Id == eventId)))
|
||||
AudioEvents.OnNext(eventId);
|
||||
}
|
||||
|
||||
public void FireAudioEvent(WwiseSoundBinding soundBinding)
|
||||
{
|
||||
FireAudioEvent(soundBinding.PlayEvent);
|
||||
}
|
||||
|
||||
public void PlaySound(WwiseLoopingSoundBinding soundBinding)
|
||||
{
|
||||
FireAudioEvent(soundBinding.PlayEvent);
|
||||
}
|
||||
|
||||
public void StopSound(WwiseLoopingSoundBinding soundBinding)
|
||||
{
|
||||
FireAudioEvent(soundBinding.StopEvent);
|
||||
}
|
||||
|
||||
public void FireAudioEvent(WeaponAudioEvent weaponAudioEvent)
|
||||
{
|
||||
if (SoundBank == null) return;
|
||||
var eventObject = SoundBank.GetEvent(weaponAudioEvent);
|
||||
if (eventObject == null)
|
||||
{
|
||||
ItemManager.Log($"Attempted to trigger {Enum.GetName(typeof(WeaponAudioEvent), weaponAudioEvent)} weapon audio event, but the soundbank doesn't support it!");
|
||||
return;
|
||||
}
|
||||
FireAudioEvent(eventObject.Id, true);
|
||||
}
|
||||
|
||||
public void FireAudioEvent(ChargedWeaponAudioEvent weaponAudioEvent)
|
||||
{
|
||||
if (SoundBank == null) return;
|
||||
var eventObject = SoundBank.GetEvent(weaponAudioEvent);
|
||||
if (eventObject == null)
|
||||
{
|
||||
ItemManager.Log($"Attempted to trigger {Enum.GetName(typeof(ChargedWeaponAudioEvent), weaponAudioEvent)} weapon audio event, but the soundbank doesn't support it!");
|
||||
return;
|
||||
}
|
||||
FireAudioEvent(eventObject.Id, true);
|
||||
}
|
||||
|
||||
public void SetAudioParameter(uint id, float v, bool skipVerify = false)
|
||||
{
|
||||
if (SoundBank != null && (skipVerify || SoundBank.GameParameters.Any(o => o.Id == id)))
|
||||
{
|
||||
AudioParameterValues[id] = v;
|
||||
AudioParameters.OnNext((id, v));
|
||||
}
|
||||
}
|
||||
|
||||
// public void SetAudioParameter(WwiseParameterBinding binding)
|
||||
// {
|
||||
// FireAudioEvent(binding.Parameter);
|
||||
// }
|
||||
|
||||
public void SetAudioParameter(SpecialAudioParameter p, float v)
|
||||
{
|
||||
if (SoundBank == null) return;
|
||||
var metaObject = SoundBank.GetParameter(p);
|
||||
if (metaObject == null)
|
||||
{
|
||||
ItemManager.Log($"Attempted to set {Enum.GetName(typeof(ChargedWeaponAudioEvent), p)} audio parameter, but the soundbank doesn't support it!");
|
||||
return;
|
||||
}
|
||||
SetAudioParameter(metaObject.Id, v, true);
|
||||
}
|
||||
|
||||
public EquippedItem(ItemManager itemManager, EquippableItem item, int2 position, Entity entity, HardpointData hardpoint)
|
||||
{
|
||||
ItemManager = itemManager;
|
||||
|
|
@ -2460,11 +2384,6 @@ public class EquippedItem : IStatContext
|
|||
|
||||
public void Update(float delta)
|
||||
{
|
||||
foreach (var audioStat in Data.AudioStats)
|
||||
{
|
||||
SetAudioParameter(audioStat.Parameter, Evaluate(audioStat.Stat));
|
||||
}
|
||||
|
||||
if (Active.Value)
|
||||
{
|
||||
foreach (var group in BehaviorGroups.Values)
|
||||
|
|
|
|||
|
|
@ -203,34 +203,6 @@ public enum TemperatureUnit
|
|||
Fahrenheit
|
||||
}
|
||||
|
||||
public enum WeaponAudioEvent
|
||||
{
|
||||
Fire,
|
||||
Hit,
|
||||
Miss
|
||||
}
|
||||
|
||||
public enum ChargedWeaponAudioEvent
|
||||
{
|
||||
Start,
|
||||
Stop,
|
||||
Fail
|
||||
}
|
||||
|
||||
public enum SpecialAudioParameter
|
||||
{
|
||||
ShipVelocity,
|
||||
ChargeLevel,
|
||||
TargetLock,
|
||||
Intensity,
|
||||
}
|
||||
|
||||
public enum LoopingAudioEvent
|
||||
{
|
||||
Play,
|
||||
Stop
|
||||
}
|
||||
|
||||
public enum MusicType
|
||||
{
|
||||
Overworld,
|
||||
|
|
|
|||
|
|
@ -1,92 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
[JsonObject]
|
||||
public class WwiseMetadataFile
|
||||
{
|
||||
public WwiseMetaSoundBanksInfo SoundBanksInfo;
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class WwiseMetaSoundBanksInfo
|
||||
{
|
||||
public WwiseMetaSoundBank[] SoundBanks;
|
||||
|
||||
private Dictionary<uint, WwiseMetaSoundBank> _soundBanks;
|
||||
public WwiseMetaSoundBank GetSoundBank(uint id)
|
||||
{
|
||||
if (_soundBanks == null) _soundBanks = SoundBanks.ToDictionary(sb => sb.Id);
|
||||
return _soundBanks[id];
|
||||
}
|
||||
|
||||
private Dictionary<string, WwiseMetaSoundBank> _soundBankNames;
|
||||
public WwiseMetaSoundBank GetSoundBank(string name)
|
||||
{
|
||||
if (_soundBankNames == null) _soundBankNames = SoundBanks.ToDictionary(sb => sb.ShortName);
|
||||
return _soundBankNames[name];
|
||||
}
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class WwiseMetaSoundBank
|
||||
{
|
||||
public uint Id;
|
||||
public string ShortName;
|
||||
public string ObjectPath;
|
||||
public WwiseMetaObject[] IncludedEvents;
|
||||
public WwiseMetaObject[] GameParameters;
|
||||
|
||||
public WwiseMetaObject GetEvent(WeaponAudioEvent weaponAudioEvent)
|
||||
{
|
||||
return weaponAudioEvent switch
|
||||
{
|
||||
WeaponAudioEvent.Fire => IncludedEvents?.FirstOrDefault(e => e.Name.EndsWith("_fire")),
|
||||
WeaponAudioEvent.Hit => IncludedEvents?.FirstOrDefault(e => e.Name.EndsWith("_hit")),
|
||||
WeaponAudioEvent.Miss => IncludedEvents?.FirstOrDefault(e => e.Name.EndsWith("_miss")),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(weaponAudioEvent), weaponAudioEvent, null)
|
||||
};
|
||||
}
|
||||
|
||||
public WwiseMetaObject GetEvent(ChargedWeaponAudioEvent chargedWeaponAudioEvent)
|
||||
{
|
||||
return chargedWeaponAudioEvent switch
|
||||
{
|
||||
ChargedWeaponAudioEvent.Start => IncludedEvents?.FirstOrDefault(e => e.Name.EndsWith("_charge_play")),
|
||||
ChargedWeaponAudioEvent.Stop => IncludedEvents?.FirstOrDefault(e => e.Name.EndsWith("_charge_stop")),
|
||||
ChargedWeaponAudioEvent.Fail => IncludedEvents?.FirstOrDefault(e => e.Name.EndsWith("_fail")),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(chargedWeaponAudioEvent), chargedWeaponAudioEvent, null)
|
||||
};
|
||||
}
|
||||
|
||||
public WwiseMetaObject GetEvent(LoopingAudioEvent loopingAudioEvent)
|
||||
{
|
||||
return loopingAudioEvent switch
|
||||
{
|
||||
LoopingAudioEvent.Play => IncludedEvents?.FirstOrDefault(e => e.Name.EndsWith("_play")),
|
||||
LoopingAudioEvent.Stop => IncludedEvents?.FirstOrDefault(e => e.Name.EndsWith("_stop")),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(loopingAudioEvent), loopingAudioEvent, null)
|
||||
};
|
||||
}
|
||||
|
||||
public WwiseMetaObject GetParameter(SpecialAudioParameter audioParameter)
|
||||
{
|
||||
return audioParameter switch
|
||||
{
|
||||
SpecialAudioParameter.ShipVelocity => GameParameters?.FirstOrDefault(p => p.Name == "ship_velocity"),
|
||||
SpecialAudioParameter.ChargeLevel => GameParameters?.FirstOrDefault(p => p.Name == "charge_level"),
|
||||
SpecialAudioParameter.TargetLock => GameParameters?.FirstOrDefault(p => p.Name == "target_locking"),
|
||||
SpecialAudioParameter.Intensity => GameParameters?.FirstOrDefault(p => p.Name == "sfx_shared_intensity"),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(audioParameter), audioParameter, null)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class WwiseMetaObject
|
||||
{
|
||||
public uint Id;
|
||||
public string Name;
|
||||
public string ObjectPath;
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0a12363ee8ef43b399bf91ca099947a9
|
||||
timeCreated: 1619664281
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
using MessagePack;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
[MessagePackObject, JsonObject(MemberSerialization.OptIn)]
|
||||
public class WwiseSoundBinding
|
||||
{
|
||||
[Key(0), JsonProperty("playEvent")]
|
||||
public uint PlayEvent;
|
||||
}
|
||||
|
||||
[MessagePackObject, JsonObject(MemberSerialization.OptIn)]
|
||||
public class WwiseLoopingSoundBinding : WwiseSoundBinding
|
||||
{
|
||||
[Key(1), JsonProperty("stopEvent")]
|
||||
public uint StopEvent;
|
||||
}
|
||||
|
||||
// public class WwiseParameterBinding
|
||||
// {
|
||||
// [Key(0), JsonProperty("parameter")]
|
||||
// public uint Parameter;
|
||||
// }
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2e128c1cb68f481c9a846344e8283014
|
||||
timeCreated: 1619729875
|
||||
|
|
@ -441,7 +441,6 @@ public sealed class FireControlPerWeaponTests : IDisposable
|
|||
{
|
||||
public int Ammo;
|
||||
public float ChargeSpent;
|
||||
public int Sounds;
|
||||
public int Wears;
|
||||
public float Heat;
|
||||
public bool Visible;
|
||||
|
|
@ -451,7 +450,7 @@ public sealed class FireControlPerWeaponTests : IDisposable
|
|||
}
|
||||
|
||||
// One discrete weapon, triggered once at no target, with every cost observable: a magazine, an energy charge,
|
||||
// a sound bank, wear events, heat and visibility. Range 29.5 refuses (arming 30); Range 40 fires.
|
||||
// wear events, heat and visibility. Range 29.5 refuses (arming 30); Range 40 fires.
|
||||
private Costs Pull(float range, bool single, bool viaTrigger, bool staleRange = false, bool auto = false)
|
||||
{
|
||||
var r = Build(fuse: WeaponFuse.Proximity, blast: 30f, range: range, energy: 50f, heat: 5000f, visibility: 100f, magazine: 5, singleAmmoBurst: single, auto: auto);
|
||||
|
|
@ -459,9 +458,7 @@ public sealed class FireControlPerWeaponTests : IDisposable
|
|||
Aim(r, float2(0, 1));
|
||||
var weapon = (InstantWeapon) r.Gun.Weapon;
|
||||
var capacitor = (InputCapacitor) typeof(InstantWeapon).GetField("_capacitor", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(weapon);
|
||||
r.Gun.Item.SoundBank = new WwiseMetaSoundBank { IncludedEvents = new[] { new WwiseMetaObject { Id = 7, Name = "gun_fire" } } };
|
||||
var costs = new Costs();
|
||||
r.Gun.Item.AudioEvents.Subscribe(_ => costs.Sounds++);
|
||||
r.Zone.ShotCommitted.Subscribe(_ => costs.Shots++); // a fused round with no flight commits and resolves in its own tick
|
||||
r.Shooter.ItemDamage.Subscribe(t => { if (t.Item1 == r.Gun.Item) costs.Wears++; });
|
||||
weapon.OnFire += _ => costs.Announced++;
|
||||
|
|
@ -493,12 +490,12 @@ public sealed class FireControlPerWeaponTests : IDisposable
|
|||
}
|
||||
|
||||
// Control: the same weapon with Range to spare pays every cost, so a free refusal below is not a fixture that
|
||||
// never spends. Then the refusal costs nothing: no ammo, no energy, no sound, no wear, no heat, no
|
||||
// never spends. Then the refusal costs nothing: no ammo, no energy, no announcement, no wear, no heat, no
|
||||
// visibility, no shot. `single` is a weapon that pays once per burst, at its first unrefused round rather than at each;
|
||||
// `viaTrigger` false authorises the burst directly (the way a trigger that passed leaves it) on a weapon whose
|
||||
// Range is short, so the Trigger check cannot be what stops the round and Execute must refuse it itself.
|
||||
// Kills, one per row of the assertions: a spend that precedes the refusal (Execute or Trigger), an
|
||||
// announcement, a sound, wear, heat or visibility left ahead of the `continue`.
|
||||
// announcement (what a presenter hears), wear, heat or visibility left ahead of the `continue`.
|
||||
[Theory]
|
||||
[InlineData(false, true)]
|
||||
[InlineData(true, true)]
|
||||
|
|
@ -509,7 +506,6 @@ public sealed class FireControlPerWeaponTests : IDisposable
|
|||
Assert.True(fired.Shots == 1, $"shots {fired.Shots}");
|
||||
Assert.True(fired.Ammo == 1, $"ammo spent {fired.Ammo}");
|
||||
Assert.True(fired.ChargeSpent > 1f, "a fired round spends its energy");
|
||||
Assert.Equal(1, fired.Sounds);
|
||||
Assert.True(fired.Wears > 0);
|
||||
Assert.True(fired.Heat > 0f);
|
||||
Assert.True(fired.Visible);
|
||||
|
|
@ -519,7 +515,6 @@ public sealed class FireControlPerWeaponTests : IDisposable
|
|||
Assert.Equal(0, refused.Shots);
|
||||
Assert.Equal(0, refused.Ammo);
|
||||
Assert.Equal(0f, refused.ChargeSpent);
|
||||
Assert.Equal(0, refused.Sounds);
|
||||
Assert.Equal(0, refused.Wears);
|
||||
Assert.True(fired.Heat - refused.Heat > 5f, $"a refused round adds no heat ({refused.Heat} vs {fired.Heat})");
|
||||
Assert.False(refused.Visible);
|
||||
|
|
@ -721,26 +716,23 @@ public sealed class FireControlPerWeaponTests : IDisposable
|
|||
Assert.True(refused.CanFire, "a burst that fired nothing leaves no cooldown");
|
||||
}
|
||||
|
||||
// A refused charged weapon never starts charging: no charge heat, no audio, no start event, and it can be
|
||||
// triggered again at once. The control (Range 40) charges, sounds and heats.
|
||||
// A refused charged weapon never starts charging: no charge heat, no start event a presenter could sound, and it can be
|
||||
// triggered again at once. The control (Range 40) charges and heats.
|
||||
// Kills: ChargedWeapon.Activate that does not ask FireControl.
|
||||
private (int Starts, int Sounds, float Heat, bool Charging) Charge(float range)
|
||||
private (int Starts, float Heat, bool Charging) Charge(float range)
|
||||
{
|
||||
var r = Build(charged: true, fuse: WeaponFuse.Proximity, blast: 30f, range: range);
|
||||
r.Shooter.SetTarget(TargetRef.None);
|
||||
Aim(r, float2(0, 1));
|
||||
var weapon = (ChargedWeapon) r.Gun.Weapon;
|
||||
r.Gun.Item.SoundBank = new WwiseMetaSoundBank { IncludedEvents = new[] { new WwiseMetaObject { Id = 7, Name = "gun_charge_play" } } };
|
||||
var starts = 0;
|
||||
var sounds = 0;
|
||||
weapon.OnStartCharging += () => starts++;
|
||||
r.Gun.Item.AudioEvents.Subscribe(_ => sounds++);
|
||||
var heatBefore = r.Gun.Item.Temperature;
|
||||
|
||||
weapon.Activate();
|
||||
for (var i = 0; i < 3; i++) r.Zone.Update(.1f);
|
||||
|
||||
return (starts, sounds, r.Gun.Item.Temperature - heatBefore, weapon.Progress > 0f);
|
||||
return (starts, r.Gun.Item.Temperature - heatBefore, weapon.Progress > 0f);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -748,12 +740,10 @@ public sealed class FireControlPerWeaponTests : IDisposable
|
|||
{
|
||||
var fired = Charge(40f);
|
||||
Assert.Equal(1, fired.Starts);
|
||||
Assert.True(fired.Sounds > 0, "control: charging sounds");
|
||||
Assert.True(fired.Heat > 0f, "control: charging heats");
|
||||
|
||||
var refused = Charge(29.5f);
|
||||
Assert.Equal(0, refused.Starts);
|
||||
Assert.Equal(0, refused.Sounds);
|
||||
Assert.True(fired.Heat - refused.Heat > 5f, $"a refused weapon adds no charge heat ({refused.Heat} vs {fired.Heat})");
|
||||
}
|
||||
// A triggered burst has not started its cooldown, but it is not ready either: pulled again before its first round
|
||||
|
|
|
|||
Loading…
Reference in a new issue