diff --git a/OpenRA.Game/Selection.cs b/OpenRA.Game/Selection.cs index f7522556bd..528f28ea26 100644 --- a/OpenRA.Game/Selection.cs +++ b/OpenRA.Game/Selection.cs @@ -57,9 +57,10 @@ namespace OpenRA } } - var voicedActor = actors.FirstOrDefault(a => a.Owner == world.LocalPlayer && a.IsInWorld && a.HasVoices()); + var voicedActor = actors.FirstOrDefault(a => a.Owner == world.LocalPlayer && a.IsInWorld && (a.TraitsImplementing() != null)); if (voicedActor != null) - Sound.PlayVoice("Select", voicedActor, voicedActor.Owner.Country.Race); + foreach (var voice in voicedActor.TraitsImplementing()) + voice.PlayVoice("Select", voicedActor, voicedActor.Owner.Country.Race); foreach (var a in newSelection) foreach (var sel in a.TraitsImplementing()) diff --git a/OpenRA.Game/Sound/Sound.cs b/OpenRA.Game/Sound/Sound.cs index 7f171a414a..5af665c5d7 100644 --- a/OpenRA.Game/Sound/Sound.cs +++ b/OpenRA.Game/Sound/Sound.cs @@ -364,32 +364,6 @@ namespace OpenRA return true; } - public static bool PlayVoice(string phrase, Actor voicedActor, string variant) - { - if (voicedActor == null || phrase == null) - return false; - - var mi = voicedActor.TraitOrDefault(); - if (mi == null || mi.VoiceSet == null) - return false; - - var type = mi.VoiceSet.ToLowerInvariant(); - return PlayPredefined(voicedActor.World.Map.Rules, null, voicedActor, type, phrase, variant, true, WPos.Zero, 1f, true); - } - - public static bool PlayVoiceLocal(string phrase, Actor voicedActor, string variant, WPos pos, float volume) - { - if (voicedActor == null || phrase == null) - return false; - - var mi = voicedActor.TraitOrDefault(); - if (mi == null || mi.VoiceSet == null) - return false; - - var type = mi.VoiceSet.ToLowerInvariant(); - return PlayPredefined(voicedActor.World.Map.Rules, null, voicedActor, type, phrase, variant, false, pos, volume, true); - } - public static bool PlayNotification(Ruleset rules, Player player, string type, string notification, string variant) { if (rules == null) diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 9eeaedc662..47e295eb88 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -109,7 +109,15 @@ namespace OpenRA.Traits public interface ISeedableResource { void Seed(Actor self); } - public interface IVoiced { string VoiceSet { get; } } + public interface IVoiced + { + bool PlayVoice(string phrase, Actor voicedActor, string variant); + bool PlayVoiceLocal(string phrase, Actor voicedActor, string variant, WPos pos, float volume); + bool HasVoices(Actor actor); + bool HasVoice(Actor actor, string voice); + string VoiceSet { get; } + } + public interface IDemolishableInfo { bool IsValidTarget(ActorInfo actorInfo, Actor saboteur); } public interface IDemolishable { diff --git a/OpenRA.Game/WorldUtils.cs b/OpenRA.Game/WorldUtils.cs index de62bf0fe0..00549e19c8 100644 --- a/OpenRA.Game/WorldUtils.cs +++ b/OpenRA.Game/WorldUtils.cs @@ -42,28 +42,6 @@ namespace OpenRA } } - public static bool HasVoices(this Actor a) - { - var voice = a.TraitOrDefault(); - return voice != null && voice.VoiceSet != null; - } - - public static bool HasVoice(this Actor a, string voice) - { - var v = GetVoices(a); - return v != null && v.Voices.ContainsKey(voice); - } - - public static SoundInfo GetVoices(this Actor a) - { - var voiced = a.TraitOrDefault(); - if (voiced == null) - return null; - - var v = voiced.VoiceSet; - return (v == null) ? null : a.World.Map.Rules.Voices[v.ToLowerInvariant()]; - } - public static void PlayVoiceForOrders(this World w, Order[] orders) { // Find an actor with a phrase to say @@ -75,13 +53,15 @@ namespace OpenRA if (o.Subject.Destroyed) continue; - if (!o.Subject.HasVoices()) + var hasVoice = o.Subject.TraitsImplementing(); + if (hasVoice == null) continue; foreach (var v in o.Subject.TraitsImplementing()) - if (Sound.PlayVoice(v.VoicePhraseForOrder(o.Subject, o), - o.Subject, o.Subject.Owner.Country.Race)) - return; + foreach (var voice in o.Subject.TraitsImplementing()) + if (voice.PlayVoice(v.VoicePhraseForOrder(o.Subject, o), + o.Subject, o.Subject.Owner.Country.Race)) + return; } } diff --git a/OpenRA.Mods.Common/Traits/Cargo.cs b/OpenRA.Mods.Common/Traits/Cargo.cs index 5c86323984..47696c00bb 100644 --- a/OpenRA.Mods.Common/Traits/Cargo.cs +++ b/OpenRA.Mods.Common/Traits/Cargo.cs @@ -207,7 +207,7 @@ namespace OpenRA.Mods.Common.Traits if (order.OrderString != "Unload" || IsEmpty(self)) return null; - return self.HasVoice("Unload") ? "Unload" : "Move"; + return self.TraitsImplementing().FirstOrDefault().HasVoice(self, "Unload") ? "Unload" : "Move"; } public bool MoveDisabled(Actor self) { return reserves.Any(); } diff --git a/OpenRA.Mods.Common/Traits/Sound/AnnounceOnBuild.cs b/OpenRA.Mods.Common/Traits/Sound/AnnounceOnBuild.cs index 1aee77e138..c45eb28501 100644 --- a/OpenRA.Mods.Common/Traits/Sound/AnnounceOnBuild.cs +++ b/OpenRA.Mods.Common/Traits/Sound/AnnounceOnBuild.cs @@ -19,7 +19,8 @@ namespace OpenRA.Mods.Common.Traits { public void BuildingComplete(Actor self) { - Sound.PlayVoice("Build", self, self.Owner.Country.Race); + foreach (var voiced in self.TraitsImplementing()) + voiced.PlayVoice("Build", self, self.Owner.Country.Race); } } } diff --git a/OpenRA.Mods.Common/Traits/Sound/AnnounceOnKill.cs b/OpenRA.Mods.Common/Traits/Sound/AnnounceOnKill.cs index e5da13aef1..7ad13b8d5a 100644 --- a/OpenRA.Mods.Common/Traits/Sound/AnnounceOnKill.cs +++ b/OpenRA.Mods.Common/Traits/Sound/AnnounceOnKill.cs @@ -39,7 +39,8 @@ namespace OpenRA.Mods.Common.Traits if (e.DamageState == DamageState.Dead && damaged != e.Attacker) { if (self.World.WorldTick - lastAnnounce > info.Interval * 25) - Sound.PlayVoice("Kill", self, self.Owner.Country.Race); + foreach (var voiced in self.TraitsImplementing()) + voiced.PlayVoice("Kill", self, self.Owner.Country.Race); lastAnnounce = self.World.WorldTick; } diff --git a/OpenRA.Mods.Common/Traits/Sound/DeathSounds.cs b/OpenRA.Mods.Common/Traits/Sound/DeathSounds.cs index 0f150d53d3..7d5ca68aca 100644 --- a/OpenRA.Mods.Common/Traits/Sound/DeathSounds.cs +++ b/OpenRA.Mods.Common/Traits/Sound/DeathSounds.cs @@ -42,9 +42,11 @@ namespace OpenRA.Mods.Common.Traits var cp = self.CenterPosition; - if (info.DeathTypes.Contains(e.Warhead.DeathType) || - (!info.DeathTypes.Any() && !self.Info.Traits.WithInterface().Any(dsi => dsi.DeathTypes.Contains(e.Warhead.DeathType)))) - Sound.PlayVoiceLocal(info.DeathSound, self, self.Owner.Country.Race, cp, info.VolumeMultiplier); + foreach (var voiced in self.TraitsImplementing()) + if (info.DeathTypes.Contains(e.Warhead.DeathType) || + (!info.DeathTypes.Any() && !self.Info.Traits.WithInterface() + .Any(dsi => dsi.DeathTypes.Contains(e.Warhead.DeathType)))) + voiced.PlayVoiceLocal(info.DeathSound, self, self.Owner.Country.Race, cp, info.VolumeMultiplier); } } } \ No newline at end of file diff --git a/OpenRA.Mods.Common/Traits/Voiced.cs b/OpenRA.Mods.Common/Traits/Voiced.cs index 6b888fb471..b45354573c 100644 --- a/OpenRA.Mods.Common/Traits/Voiced.cs +++ b/OpenRA.Mods.Common/Traits/Voiced.cs @@ -10,6 +10,7 @@ using System.Collections.Generic; using System.Linq; +using OpenRA.GameRules; using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits @@ -30,6 +31,54 @@ namespace OpenRA.Mods.Common.Traits Info = info; } + public bool PlayVoice(string phrase, Actor voicedActor, string variant) + { + if (voicedActor == null || phrase == null) + return false; + + var mi = voicedActor.TraitOrDefault(); + if (mi == null || mi.VoiceSet == null) + return false; + + var type = mi.VoiceSet.ToLowerInvariant(); + return Sound.PlayPredefined(voicedActor.World.Map.Rules, null, voicedActor, type, phrase, variant, true, WPos.Zero, 1f, true); + } + + public bool PlayVoiceLocal(string phrase, Actor voicedActor, string variant, WPos pos, float volume) + { + if (voicedActor == null || phrase == null) + return false; + + var mi = voicedActor.TraitOrDefault(); + if (mi == null || mi.VoiceSet == null) + return false; + + var type = mi.VoiceSet.ToLowerInvariant(); + return Sound.PlayPredefined(voicedActor.World.Map.Rules, null, voicedActor, type, phrase, variant, false, pos, volume, true); + } + + public bool HasVoices(Actor actor) + { + var voice = actor.TraitsImplementing().FirstOrDefault(); + return voice != null && voice.VoiceSet != null; + } + + public bool HasVoice(Actor actor, string voice) + { + var v = GetVoices(actor); + return v != null && v.Voices.ContainsKey(voice); + } + + public SoundInfo GetVoices(Actor actor) + { + var voice = actor.TraitsImplementing().FirstOrDefault(); + if (voice == null) + return null; + + var v = voice.VoiceSet; + return (v == null) ? null : actor.World.Map.Rules.Voices[v.ToLowerInvariant()]; + } + public string VoiceSet { get { return Info.VoiceSet; } } } }