diff --git a/OpenRA.Game/GameRules/SoundInfo.cs b/OpenRA.Game/GameRules/SoundInfo.cs index 771cdac0b4..151b1a3fdd 100644 --- a/OpenRA.Game/GameRules/SoundInfo.cs +++ b/OpenRA.Game/GameRules/SoundInfo.cs @@ -33,7 +33,7 @@ namespace OpenRA.GameRules { FieldLoader.Load(this, y); - VoicePools = Exts.Lazy(() => Voices.ToDictionary(a => a.Key, a => new SoundPool(1f, false, a.Value))); + VoicePools = Exts.Lazy(() => Voices.ToDictionary(a => a.Key, a => new SoundPool(1f, SoundPool.DefaultInterruptType, a.Value))); NotificationsPools = Exts.Lazy(() => ParseSoundPool(y, "Notifications")); } @@ -44,17 +44,17 @@ namespace OpenRA.GameRules foreach (var t in classifiction.Value.Nodes) { var volumeModifier = 1f; - var volumeModifierNode = t.Value.Nodes.FirstOrDefault(x => x.Key == "VolumeModifier"); + var volumeModifierNode = t.Value.Nodes.FirstOrDefault(x => x.Key == nameof(SoundPool.VolumeModifier)); if (volumeModifierNode != null) volumeModifier = FieldLoader.GetValue(volumeModifierNode.Key, volumeModifierNode.Value.Value); - var allowInterrupt = false; - var allowInterruptNode = t.Value.Nodes.FirstOrDefault(x => x.Key == "AllowInterrupt"); - if (allowInterruptNode != null) - allowInterrupt = FieldLoader.GetValue(allowInterruptNode.Key, allowInterruptNode.Value.Value); + var interruptType = SoundPool.DefaultInterruptType; + var interruptTypeNode = t.Value.Nodes.FirstOrDefault(x => x.Key == nameof(SoundPool.InterruptType)); + if (interruptTypeNode != null) + interruptType = FieldLoader.GetValue(interruptTypeNode.Key, interruptTypeNode.Value.Value); var names = FieldLoader.GetValue(t.Key, t.Value.Value); - var sp = new SoundPool(volumeModifier, allowInterrupt, names); + var sp = new SoundPool(volumeModifier, interruptType, names); ret.Add(t.Key, sp); } @@ -64,15 +64,17 @@ namespace OpenRA.GameRules public class SoundPool { + public enum InterruptType { DoNotPlay, Interrupt, Overlap } + public const InterruptType DefaultInterruptType = InterruptType.DoNotPlay; public readonly float VolumeModifier; - public readonly bool AllowInterrupt; + public readonly InterruptType Type; readonly string[] clips; readonly List liveclips = new List(); - public SoundPool(float volumeModifier, bool allowInterrupt, params string[] clips) + public SoundPool(float volumeModifier, InterruptType interruptType, params string[] clips) { VolumeModifier = volumeModifier; - AllowInterrupt = allowInterrupt; + Type = interruptType; this.clips = clips; } diff --git a/OpenRA.Game/Sound/Sound.cs b/OpenRA.Game/Sound/Sound.cs index 41d399f6ed..56fe4e6cd3 100644 --- a/OpenRA.Game/Sound/Sound.cs +++ b/OpenRA.Game/Sound/Sound.cs @@ -401,36 +401,49 @@ namespace OpenRA if (!string.IsNullOrEmpty(name) && (p == null || p == p.World.LocalPlayer)) { - if (currentNotifications.TryGetValue(name, out var currentNotification)) + ISound PlaySound() { - if (!currentNotification.Complete) + var volume = InternalSoundVolume * volumeModifier * pool.VolumeModifier; + return soundEngine.Play2D(sounds[name], false, relative, pos, volume, attenuateVolume); + } + + if (pool.Type == SoundPool.InterruptType.Overlap) + { + if (PlaySound() == null) + return false; + } + else if (voicedActor == null) + { + if (currentNotifications.TryGetValue(name, out var currentNotification) && !currentNotification.Complete) { - if (pool.AllowInterrupt) + if (pool.Type == SoundPool.InterruptType.Interrupt) soundEngine.StopSound(currentNotification); - else + else if (pool.Type == SoundPool.InterruptType.DoNotPlay) return false; } - } - else if (currentSounds.TryGetValue(actorId, out var currentSound)) - { - if (!currentSound.Complete) - { - if (pool.AllowInterrupt) - soundEngine.StopSound(currentSound); - else - return false; - } - } - var volume = InternalSoundVolume * volumeModifier * pool.VolumeModifier; - var sound = soundEngine.Play2D(sounds[name], false, relative, pos, volume, attenuateVolume); - if (sound == null) - return false; - - if (voicedActor != null) - currentSounds[actorId] = sound; + var sound = PlaySound(); + if (sound == null) + return false; + else + currentNotifications[name] = sound; + } else - currentNotifications[name] = sound; + { + if (currentSounds.TryGetValue(actorId, out var currentSound) && !currentSound.Complete) + { + if (pool.Type == SoundPool.InterruptType.Interrupt) + soundEngine.StopSound(currentSound); + else if (pool.Type == SoundPool.InterruptType.DoNotPlay) + return false; + } + + var sound = PlaySound(); + if (sound == null) + return false; + else + currentSounds[actorId] = sound; + } } return true; diff --git a/mods/cnc/audio/notifications.yaml b/mods/cnc/audio/notifications.yaml index 1051c63d25..e8978bdd61 100644 --- a/mods/cnc/audio/notifications.yaml +++ b/mods/cnc/audio/notifications.yaml @@ -54,19 +54,21 @@ Sounds: Notifications: Appear: appear1 Beacon: bleep2 - AllowInterrupt: true + InterruptType: Interrupt Beepy2: beepy2 Beepy3: beepy3 Beepy6: beepy6 CashTickDown: tone16 + InterruptType: Overlap CashTickUp: tone15 VolumeModifier: 0.33 + InterruptType: Overlap ChatLine: scold1 - AllowInterrupt: true + InterruptType: Interrupt ClickDisabledSound: scold2 - AllowInterrupt: true + InterruptType: Interrupt ClickSound: button - AllowInterrupt: true + InterruptType: Interrupt Cloak: trans1 Clock: clock1 Construction: constru2 diff --git a/mods/d2k/audio/notifications.yaml b/mods/d2k/audio/notifications.yaml index 4e3b92ee29..7ab6ad4959 100644 --- a/mods/d2k/audio/notifications.yaml +++ b/mods/d2k/audio/notifications.yaml @@ -67,17 +67,19 @@ Sounds: DisablePower: POWRDN1 EnablePower: POWRUP1 CashTickUp: CASHTIK1 + InterruptType: Overlap CashTickDown: CASHTIK1 + InterruptType: Overlap LevelUp: SCORTIK1 ChatLine: CHAT1 - AllowInterrupt: true + InterruptType: Interrupt BuildPaletteOpen: BUTTON1 BuildPaletteClose: BUTTON1 TabClick: SIDEBAR1 - AllowInterrupt: true + InterruptType: Interrupt ClickSound: BUTTON1 - AllowInterrupt: true + InterruptType: Interrupt ClickDisabledSound: ENDLIST1 - AllowInterrupt: true + InterruptType: Interrupt Beacon: CHAT1 - AllowInterrupt: true + InterruptType: Interrupt diff --git a/mods/ra/audio/notifications.yaml b/mods/ra/audio/notifications.yaml index 312451a9e2..2be754fe1a 100644 --- a/mods/ra/audio/notifications.yaml +++ b/mods/ra/audio/notifications.yaml @@ -120,18 +120,20 @@ Sounds: RadarDown: radardn1 CashTickUp: cashup1 VolumeModifier: 0.33 + InterruptType: Overlap CashTickDown: cashdn1 VolumeModifier: 0.33 + InterruptType: Overlap LevelUp: hydrod1 DisablePower: bleep11 EnablePower: bleep12 ChatLine: rabeep1 - AllowInterrupt: true + InterruptType: Interrupt ClickSound: ramenu1 - AllowInterrupt: true + InterruptType: Interrupt ClickDisabledSound: Beacon: beepslct - AllowInterrupt: true + InterruptType: Interrupt AlertBuzzer: buzzy1 AlertBleep: bleep6 BaseSetup: bleep9 diff --git a/mods/ts/audio/sounds-generic.yaml b/mods/ts/audio/sounds-generic.yaml index 7ae0a3c422..4e838f3984 100644 --- a/mods/ts/audio/sounds-generic.yaml +++ b/mods/ts/audio/sounds-generic.yaml @@ -2,7 +2,7 @@ Sounds: Notifications: Bargraph: bargraph Beacon: message1 - AllowInterrupt: true + InterruptType: Interrupt Bestbox: bestbox Blip: blip BuildPaletteClose: emblem @@ -11,14 +11,16 @@ Sounds: CantPushButtonSound: scold8 CashTickDown: creddwn1 VolumeModifier: 0.33 + InterruptType: Overlap CashTickUp: credup1 VolumeModifier: 0.33 + InterruptType: Overlap ChatLine: message1 - AllowInterrupt: true + InterruptType: Interrupt ClickDisabledSound: wrong1 - AllowInterrupt: true + InterruptType: Interrupt ClickSound: clicky1 - AllowInterrupt: true + InterruptType: Interrupt GameForming: gamefrm1 Gdiclose: gdiclose Gdiopen: gdiopen