diff --git a/OpenRA.Game/Selection.cs b/OpenRA.Game/Selection.cs index 528f28ea26..38bc05cbd6 100644 --- a/OpenRA.Game/Selection.cs +++ b/OpenRA.Game/Selection.cs @@ -57,10 +57,10 @@ namespace OpenRA } } - var voicedActor = actors.FirstOrDefault(a => a.Owner == world.LocalPlayer && a.IsInWorld && (a.TraitsImplementing() != null)); + var voicedActor = actors.FirstOrDefault(a => a.Owner == world.LocalPlayer && a.IsInWorld && a.HasTrait()); if (voicedActor != null) foreach (var voice in voicedActor.TraitsImplementing()) - voice.PlayVoice("Select", voicedActor, voicedActor.Owner.Country.Race); + voice.PlayVoice(voicedActor, "Select", voicedActor.Owner.Country.Race); foreach (var a in newSelection) foreach (var sel in a.TraitsImplementing()) diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 47e295eb88..e5c7990c1a 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -111,11 +111,10 @@ namespace OpenRA.Traits 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; } + bool PlayVoice(Actor self, string phrase, string variant); + bool PlayVoiceLocal(Actor self, string phrase, string variant, float volume); + bool HasVoice(Actor self, string voice); } public interface IDemolishableInfo { bool IsValidTarget(ActorInfo actorInfo, Actor saboteur); } diff --git a/OpenRA.Game/WorldUtils.cs b/OpenRA.Game/WorldUtils.cs index 00549e19c8..ae342a3f9c 100644 --- a/OpenRA.Game/WorldUtils.cs +++ b/OpenRA.Game/WorldUtils.cs @@ -50,17 +50,14 @@ namespace OpenRA if (o == null) continue; - if (o.Subject.Destroyed) + var orderSubject = o.Subject; + if (orderSubject.Destroyed) continue; - var hasVoice = o.Subject.TraitsImplementing(); - if (hasVoice == null) - continue; - - foreach (var v in o.Subject.TraitsImplementing()) - foreach (var voice in o.Subject.TraitsImplementing()) - if (voice.PlayVoice(v.VoicePhraseForOrder(o.Subject, o), - o.Subject, o.Subject.Owner.Country.Race)) + foreach (var voice in orderSubject.TraitsImplementing()) + foreach (var v in orderSubject.TraitsImplementing()) + if (voice.PlayVoice(orderSubject, v.VoicePhraseForOrder(orderSubject, o), + orderSubject.Owner.Country.Race)) return; } } diff --git a/OpenRA.Mods.Common/Traits/Cargo.cs b/OpenRA.Mods.Common/Traits/Cargo.cs index 47696c00bb..db87aed3f0 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.TraitsImplementing().FirstOrDefault().HasVoice(self, "Unload") ? "Unload" : "Move"; + return self.TraitsImplementing().Any(x => x.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 c45eb28501..b60ae2f1b8 100644 --- a/OpenRA.Mods.Common/Traits/Sound/AnnounceOnBuild.cs +++ b/OpenRA.Mods.Common/Traits/Sound/AnnounceOnBuild.cs @@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.Traits public void BuildingComplete(Actor self) { foreach (var voiced in self.TraitsImplementing()) - voiced.PlayVoice("Build", self, self.Owner.Country.Race); + voiced.PlayVoice(self, "Build", self.Owner.Country.Race); } } } diff --git a/OpenRA.Mods.Common/Traits/Sound/AnnounceOnKill.cs b/OpenRA.Mods.Common/Traits/Sound/AnnounceOnKill.cs index 7ad13b8d5a..2f46199cb7 100644 --- a/OpenRA.Mods.Common/Traits/Sound/AnnounceOnKill.cs +++ b/OpenRA.Mods.Common/Traits/Sound/AnnounceOnKill.cs @@ -40,7 +40,7 @@ namespace OpenRA.Mods.Common.Traits { if (self.World.WorldTick - lastAnnounce > info.Interval * 25) foreach (var voiced in self.TraitsImplementing()) - voiced.PlayVoice("Kill", self, self.Owner.Country.Race); + voiced.PlayVoice(self, "Kill", 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 7d5ca68aca..69ccbe1d2c 100644 --- a/OpenRA.Mods.Common/Traits/Sound/DeathSounds.cs +++ b/OpenRA.Mods.Common/Traits/Sound/DeathSounds.cs @@ -40,13 +40,10 @@ namespace OpenRA.Mods.Common.Traits if (e.Warhead == null) return; - var cp = self.CenterPosition; - - 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); + if (info.DeathTypes.Contains(e.Warhead.DeathType) || (!info.DeathTypes.Any() && + !self.Info.Traits.WithInterface().Any(dsi => dsi.DeathTypes.Contains(e.Warhead.DeathType)))) + foreach (var voiced in self.TraitsImplementing()) + voiced.PlayVoiceLocal(self, info.DeathSound, self.Owner.Country.Race, 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 b45354573c..e6359aabe2 100644 --- a/OpenRA.Mods.Common/Traits/Voiced.cs +++ b/OpenRA.Mods.Common/Traits/Voiced.cs @@ -15,10 +15,15 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + [Desc("This actor has a voice.")] public class VoicedInfo : ITraitInfo { + [Desc("Which voice set to use.")] [VoiceReference] public readonly string VoiceSet = null; + [Desc("Multiply volume with this factor.")] + public readonly float Volume = 1f; + public object Create(ActorInitializer init) { return new Voiced(init.Self, this); } } @@ -31,54 +36,40 @@ 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; } } + + public bool PlayVoice(Actor self, string phrase, string variant) + { + if (phrase == null) + return false; + + if (string.IsNullOrEmpty(Info.VoiceSet)) + return false; + + var type = Info.VoiceSet.ToLowerInvariant(); + var volume = Info.Volume; + return Sound.PlayPredefined(self.World.Map.Rules, null, self, type, phrase, variant, true, WPos.Zero, volume, true); + } + + public bool PlayVoiceLocal(Actor self, string phrase, string variant, float volume) + { + if (phrase == null) + return false; + + if (string.IsNullOrEmpty(Info.VoiceSet)) + return false; + + var type = Info.VoiceSet.ToLowerInvariant(); + return Sound.PlayPredefined(self.World.Map.Rules, null, self, type, phrase, variant, false, self.CenterPosition, volume, true); + } + + public bool HasVoice(Actor self, string voice) + { + if (string.IsNullOrEmpty(Info.VoiceSet)) + return false; + + var voices = self.World.Map.Rules.Voices[Info.VoiceSet.ToLowerInvariant()]; + return voices != null && voices.Voices.ContainsKey(voice); + } } }