From 0d05fdefbbc874d785ebda57e6e4e89615d3488b Mon Sep 17 00:00:00 2001 From: reaperrr Date: Mon, 20 Apr 2015 22:24:53 +0200 Subject: [PATCH 1/8] Extract actor voice set into Voiced trait --- OpenRA.Game/Selection.cs | 6 +-- OpenRA.Game/Sound/Sound.cs | 32 +++++++-------- OpenRA.Game/Traits/Selectable.cs | 1 - OpenRA.Game/Traits/TraitsInterfaces.cs | 1 + OpenRA.Game/WorldUtils.cs | 15 ++++--- OpenRA.Mods.Common/OpenRA.Mods.Common.csproj | 1 + OpenRA.Mods.Common/Traits/Voiced.cs | 35 ++++++++++++++++ mods/cnc/rules/civilian.yaml | 21 ++++++---- mods/cnc/rules/defaults.yaml | 24 +++++++---- mods/cnc/rules/infantry.yaml | 3 +- mods/d2k/rules/defaults.yaml | 12 ++++-- mods/d2k/rules/infantry.yaml | 15 ++++--- mods/ra/rules/civilian.yaml | 15 ++++--- mods/ra/rules/defaults.yaml | 18 ++++++--- mods/ra/rules/infantry.yaml | 42 +++++++++++++------- mods/ts/rules/aircraft.yaml | 3 +- mods/ts/rules/civilian-infantry.yaml | 39 +++++++++++------- mods/ts/rules/defaults.yaml | 21 ++++++---- mods/ts/rules/gdi-infantry.yaml | 3 +- mods/ts/rules/gdi-vehicles.yaml | 3 +- mods/ts/rules/nod-infantry.yaml | 12 ++++-- mods/ts/rules/nod-support.yaml | 6 ++- mods/ts/rules/shared-infantry.yaml | 3 +- 23 files changed, 223 insertions(+), 108 deletions(-) create mode 100644 OpenRA.Mods.Common/Traits/Voiced.cs diff --git a/OpenRA.Game/Selection.cs b/OpenRA.Game/Selection.cs index 7e86b519f0..f7522556bd 100644 --- a/OpenRA.Game/Selection.cs +++ b/OpenRA.Game/Selection.cs @@ -57,9 +57,9 @@ namespace OpenRA } } - var voicedUnit = actors.FirstOrDefault(a => a.Owner == world.LocalPlayer && a.IsInWorld && a.HasVoices()); - if (voicedUnit != null) - Sound.PlayVoice("Select", voicedUnit, voicedUnit.Owner.Country.Race); + var voicedActor = actors.FirstOrDefault(a => a.Owner == world.LocalPlayer && a.IsInWorld && a.HasVoices()); + if (voicedActor != null) + Sound.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 8654ee2334..7f171a414a 100644 --- a/OpenRA.Game/Sound/Sound.cs +++ b/OpenRA.Game/Sound/Sound.cs @@ -300,7 +300,7 @@ namespace OpenRA } // Returns true if played successfully - public static bool PlayPredefined(Ruleset ruleset, Player p, Actor voicedUnit, string type, string definition, string variant, + public static bool PlayPredefined(Ruleset ruleset, Player p, Actor voicedActor, string type, string definition, string variant, bool relative, WPos pos, float volumeModifier, bool attenuateVolume) { if (ruleset == null) @@ -312,17 +312,17 @@ namespace OpenRA if (ruleset.Voices == null || ruleset.Notifications == null) return false; - var rules = (voicedUnit != null) ? ruleset.Voices[type] : ruleset.Notifications[type]; + var rules = (voicedActor != null) ? ruleset.Voices[type] : ruleset.Notifications[type]; if (rules == null) return false; - var id = voicedUnit != null ? voicedUnit.ActorID : 0; + var id = voicedActor != null ? voicedActor.ActorID : 0; string clip; var suffix = rules.DefaultVariant; var prefix = rules.DefaultPrefix; - if (voicedUnit != null) + if (voicedActor != null) { if (!rules.VoicePools.Value.ContainsKey("Attack")) rules.VoicePools.Value.Add("Attack", rules.VoicePools.Value["Move"]); @@ -364,30 +364,30 @@ namespace OpenRA return true; } - public static bool PlayVoice(string phrase, Actor voicedUnit, string variant) + public static bool PlayVoice(string phrase, Actor voicedActor, string variant) { - if (voicedUnit == null || phrase == null) + if (voicedActor == null || phrase == null) return false; - var mi = voicedUnit.Info.Traits.GetOrDefault(); - if (mi == null || mi.Voice == null) + var mi = voicedActor.TraitOrDefault(); + if (mi == null || mi.VoiceSet == null) return false; - var type = mi.Voice.ToLowerInvariant(); - return PlayPredefined(voicedUnit.World.Map.Rules, null, voicedUnit, type, phrase, variant, true, WPos.Zero, 1f, true); + 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 voicedUnit, string variant, WPos pos, float volume) + public static bool PlayVoiceLocal(string phrase, Actor voicedActor, string variant, WPos pos, float volume) { - if (voicedUnit == null || phrase == null) + if (voicedActor == null || phrase == null) return false; - var mi = voicedUnit.Info.Traits.GetOrDefault(); - if (mi == null || mi.Voice == null) + var mi = voicedActor.TraitOrDefault(); + if (mi == null || mi.VoiceSet == null) return false; - var type = mi.Voice.ToLowerInvariant(); - return PlayPredefined(voicedUnit.World.Map.Rules, null, voicedUnit, type, phrase, variant, false, pos, volume, true); + 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) diff --git a/OpenRA.Game/Traits/Selectable.cs b/OpenRA.Game/Traits/Selectable.cs index 1c05250734..5e23b4cab6 100644 --- a/OpenRA.Game/Traits/Selectable.cs +++ b/OpenRA.Game/Traits/Selectable.cs @@ -20,7 +20,6 @@ namespace OpenRA.Traits public readonly bool Selectable = true; public readonly int Priority = 10; public readonly int[] Bounds = null; - [VoiceReference] public readonly string Voice = null; public object Create(ActorInitializer init) { return new Selectable(init.Self, this); } } diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 301d162542..9eeaedc662 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -109,6 +109,7 @@ namespace OpenRA.Traits public interface ISeedableResource { void Seed(Actor self); } + public interface IVoiced { 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 868273632d..de62bf0fe0 100644 --- a/OpenRA.Game/WorldUtils.cs +++ b/OpenRA.Game/WorldUtils.cs @@ -44,8 +44,8 @@ namespace OpenRA public static bool HasVoices(this Actor a) { - var selectable = a.Info.Traits.GetOrDefault(); - return selectable != null && selectable.Voice != null; + var voice = a.TraitOrDefault(); + return voice != null && voice.VoiceSet != null; } public static bool HasVoice(this Actor a, string voice) @@ -56,9 +56,11 @@ namespace OpenRA public static SoundInfo GetVoices(this Actor a) { - var selectable = a.Info.Traits.GetOrDefault(); - if (selectable == null) return null; - var v = selectable.Voice; + var voiced = a.TraitOrDefault(); + if (voiced == null) + return null; + + var v = voiced.VoiceSet; return (v == null) ? null : a.World.Map.Rules.Voices[v.ToLowerInvariant()]; } @@ -73,6 +75,9 @@ namespace OpenRA if (o.Subject.Destroyed) continue; + if (!o.Subject.HasVoices()) + continue; + foreach (var v in o.Subject.TraitsImplementing()) if (Sound.PlayVoice(v.VoicePhraseForOrder(o.Subject, o), o.Subject, o.Subject.Owner.Country.Race)) diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index cc1b29a043..ed5dce8e10 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -443,6 +443,7 @@ + diff --git a/OpenRA.Mods.Common/Traits/Voiced.cs b/OpenRA.Mods.Common/Traits/Voiced.cs new file mode 100644 index 0000000000..6b888fb471 --- /dev/null +++ b/OpenRA.Mods.Common/Traits/Voiced.cs @@ -0,0 +1,35 @@ +#region Copyright & License Information +/* + * Copyright 2007-2015 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using System.Collections.Generic; +using System.Linq; +using OpenRA.Traits; + +namespace OpenRA.Mods.Common.Traits +{ + public class VoicedInfo : ITraitInfo + { + [VoiceReference] public readonly string VoiceSet = null; + + public object Create(ActorInitializer init) { return new Voiced(init.Self, this); } + } + + public class Voiced : IVoiced + { + public readonly VoicedInfo Info; + + public Voiced(Actor self, VoicedInfo info) + { + Info = info; + } + + public string VoiceSet { get { return Info.VoiceSet; } } + } +} diff --git a/mods/cnc/rules/civilian.yaml b/mods/cnc/rules/civilian.yaml index 0167e02dab..4cb3b82688 100644 --- a/mods/cnc/rules/civilian.yaml +++ b/mods/cnc/rules/civilian.yaml @@ -381,12 +381,14 @@ BRIDGEHUT: C1: Inherits: ^CivInfantry Selectable: - Voice: CivilianMaleVoice + Voiced: + VoiceSet: CivilianMaleVoice C2: Inherits: ^CivInfantry Selectable: - Voice: CivilianFemaleVoice + Voiced: + VoiceSet: CivilianFemaleVoice C3: Inherits: ^CivInfantry @@ -394,7 +396,8 @@ C3: C4: Inherits: ^CivInfantry Selectable: - Voice: CivilianFemaleVoice + Voiced: + VoiceSet: CivilianFemaleVoice C5: Inherits: ^CivInfantry @@ -402,7 +405,8 @@ C5: C6: Inherits: ^CivInfantry Selectable: - Voice: CivilianFemaleVoice + Voiced: + VoiceSet: CivilianFemaleVoice C7: Inherits: ^CivInfantry @@ -410,7 +414,8 @@ C7: C8: Inherits: ^CivInfantry Selectable: - Voice: CivilianFemaleVoice + Voiced: + VoiceSet: CivilianFemaleVoice C9: Inherits: ^CivInfantry @@ -418,7 +423,8 @@ C9: C10: Inherits: ^CivInfantry Selectable: - Voice: CivilianFemaleVoice + Voiced: + VoiceSet: CivilianFemaleVoice VICE: AppearsOnRadar: @@ -439,7 +445,6 @@ VICE: BlueTiberium: 100 Beach: 60 Selectable: - Voice: DinoVoice TargetableUnit: TargetTypes: Ground AutoTarget: @@ -472,4 +477,6 @@ VICE: QuantizedFacings: 8 PoisonedByTiberium: Weapon: Heal + Voiced: + VoiceSet: DinoVoice diff --git a/mods/cnc/rules/defaults.yaml b/mods/cnc/rules/defaults.yaml index 1c34d44183..656c3c6a2f 100644 --- a/mods/cnc/rules/defaults.yaml +++ b/mods/cnc/rules/defaults.yaml @@ -12,7 +12,6 @@ ROT: 5 SelectionDecorations: Selectable: - Voice: VehicleVoice TargetableUnit: TargetTypes: Ground, Vehicle Repairable: @@ -51,6 +50,8 @@ UpgradeMinEnabledLevel: 1 UpgradeManager: MustBeDestroyed: + Voiced: + VoiceSet: VehicleVoice ^Tank: AppearsOnRadar: @@ -66,7 +67,6 @@ ROT: 5 SelectionDecorations: Selectable: - Voice: VehicleVoice TargetableUnit: TargetTypes: Ground, Vehicle Repairable: @@ -108,6 +108,8 @@ UpgradeMinEnabledLevel: 1 UpgradeManager: MustBeDestroyed: + Voiced: + VoiceSet: VehicleVoice ^Helicopter: AppearsOnRadar: @@ -117,7 +119,6 @@ GroundedTargetTypes: Ground SelectionDecorations: Selectable: - Voice: VehicleVoice Helicopter: RepairBuildings: hpad RearmBuildings: @@ -152,6 +153,8 @@ WithShadow: Hovers: MustBeDestroyed: + Voiced: + VoiceSet: VehicleVoice ^Infantry: AppearsOnRadar: @@ -177,7 +180,6 @@ Beach: 80 SelectionDecorations: Selectable: - Voice: GenericVoice TargetableUnit: TargetTypes: Ground, Infantry TakeCover: @@ -241,6 +243,8 @@ UpgradeMinEnabledLevel: 1 UpgradeManager: MustBeDestroyed: + Voiced: + VoiceSet: GenericVoice ^CivInfantry: Inherits: ^Infantry @@ -249,7 +253,6 @@ AppearsOnRadar: SelectionDecorations: Selectable: - Voice: CivilianMaleVoice Bounds: 12,17,0,-9 Valued: Cost: 70 @@ -271,6 +274,8 @@ ScaredyCat: Crushable: CrushSound: squish2.aud + Voiced: + VoiceSet: CivilianMaleVoice ^DINO: AppearsOnRadar: @@ -299,7 +304,6 @@ BlueTiberium: 70 Beach: 80 Selectable: - Voice: DinoVoice TargetableUnit: TargetTypes: Ground, Infantry HiddenUnderFog: @@ -321,13 +325,14 @@ DeathSounds: RenderSprites: Palette: terrain + Voiced: + VoiceSet: DinoVoice ^Plane: AppearsOnRadar: UseLocation: yes SelectionDecorations: Selectable: - Voice: GenericVoice TargetableUnit: TargetTypes: Air HiddenUnderFog: @@ -350,6 +355,8 @@ UpgradeMinEnabledLevel: 1 UpgradeManager: WithShadow: + Voiced: + VoiceSet: GenericVoice ^Ship: AppearsOnRadar: @@ -359,7 +366,6 @@ Water: 100 SelectionDecorations: Selectable: - Voice: VehicleVoice TargetableUnit: TargetTypes: Ground, Water HiddenUnderFog: @@ -384,6 +390,8 @@ UpgradeTypes: selfheal UpgradeMinEnabledLevel: 1 UpgradeManager: + Voiced: + VoiceSet: VehicleVoice ^Building: AppearsOnRadar: diff --git a/mods/cnc/rules/infantry.yaml b/mods/cnc/rules/infantry.yaml index 5d7920fc7f..15558fed49 100644 --- a/mods/cnc/rules/infantry.yaml +++ b/mods/cnc/rules/infantry.yaml @@ -185,7 +185,6 @@ RMBO: Queue: Infantry.GDI Selectable: Bounds: 12,17,0,-6 - Voice: CommandoVoice Mobile: Speed: 71 Health: @@ -206,6 +205,8 @@ RMBO: StandSequences: stand, stand2 AnnounceOnBuild: AnnounceOnKill: + Voiced: + VoiceSet: CommandoVoice PVICE: Inherits: VICE diff --git a/mods/d2k/rules/defaults.yaml b/mods/d2k/rules/defaults.yaml index 13394e55f1..d4cdf27675 100644 --- a/mods/d2k/rules/defaults.yaml +++ b/mods/d2k/rules/defaults.yaml @@ -13,7 +13,6 @@ ROT: 5 SelectionDecorations: Selectable: - Voice: VehicleVoice TargetableUnit: TargetTypes: Ground, C4 Passenger: @@ -52,6 +51,8 @@ MustBeDestroyed: AnnounceOnSeen: Notification: EnemyUnitsDetected + Voiced: + VoiceSet: VehicleVoice ^Tank: AppearsOnRadar: @@ -68,7 +69,6 @@ ROT: 5 SelectionDecorations: Selectable: - Voice: VehicleVoice TargetableUnit: TargetTypes: Ground, C4 Passenger: @@ -107,6 +107,8 @@ MustBeDestroyed: AnnounceOnSeen: Notification: EnemyUnitsDetected + Voiced: + VoiceSet: VehicleVoice ^Husk: Health: @@ -190,7 +192,6 @@ Rough: 70 SelectionDecorations: Selectable: - Voice: InfantryVoice TargetableUnit: TargetTypes: Ground RenderSprites: @@ -241,13 +242,14 @@ TerrainModifiesDamage: TerrainModifier: Rough: 80 + Voiced: + VoiceSet: InfantryVoice ^Plane: AppearsOnRadar: UseLocation: yes SelectionDecorations: Selectable: - Voice: GenericVoice TargetableAircraft: TargetTypes: Air GroundedTargetTypes: Ground @@ -277,6 +279,8 @@ AnnounceOnSeen: Notification: EnemyUnitsDetected RenderUnit: + Voiced: + VoiceSet: GenericVoice ^Helicopter: Inherits: ^Plane diff --git a/mods/d2k/rules/infantry.yaml b/mods/d2k/rules/infantry.yaml index 5999966ab8..88bf58ba66 100644 --- a/mods/d2k/rules/infantry.yaml +++ b/mods/d2k/rules/infantry.yaml @@ -37,7 +37,6 @@ engineer: Description: Infiltrates and captures enemy structures\n Strong vs Buildings\n Weak vs Everything Selectable: Bounds: 12,17,0,0 - Voice: EngineerVoice Health: HP: 25 Mobile: @@ -52,6 +51,8 @@ engineer: -AutoTarget: AttractsWorms: Intensity: 180 + Voiced: + VoiceSet: EngineerVoice bazooka: Inherits: ^Infantry @@ -94,7 +95,6 @@ medic: Description: Heals nearby infantry\n Strong vs Nothing\n Weak vs Everything Selectable: Bounds: 12,17,0,0 - Voice: EngineerVoice Health: HP: 60 Mobile: @@ -112,6 +112,8 @@ medic: -AutoTarget: AttractsWorms: Intensity: 180 + Voiced: + VoiceSet: EngineerVoice fremen: Inherits: ^Infantry @@ -126,7 +128,6 @@ fremen: Prerequisites: ~barracks.atreides, palace, ~techlevel.high Selectable: Bounds: 12,17,0,0 - Voice: FremenVoice Mobile: Speed: 53 Health: @@ -151,6 +152,8 @@ fremen: CloakSound: STEALTH1.WAV UncloakSound: STEALTH2.WAV -MustBeDestroyed: + Voiced: + VoiceSet: FremenVoice grenadier: Inherits: ^Infantry @@ -199,7 +202,6 @@ sardaukar: Description: Elite asssault infantry\n Strong vs Infantry, Vehicles\n Weak vs Artillery Selectable: Bounds: 12,17,0,0 - Voice: GenericVoice Health: HP: 100 Mobile: @@ -217,6 +219,8 @@ sardaukar: AttackFrontal: AttractsWorms: Intensity: 180 + Voiced: + VoiceSet: GenericVoice saboteur: Inherits: ^Infantry @@ -230,7 +234,6 @@ saboteur: Name: Saboteur Description: Sneaky infantry, armed with explosives\n Strong vs Buildings\n Weak vs Everything\n Special Ability: destroy buildings Selectable: - Voice: SaboteurVoice Bounds: 12,17,0,0 Health: HP: 100 @@ -243,4 +246,6 @@ saboteur: -AutoTarget: AttractsWorms: Intensity: 120 + Voiced: + VoiceSet: SaboteurVoice diff --git a/mods/ra/rules/civilian.yaml b/mods/ra/rules/civilian.yaml index ff1d5b5f6d..ac6688191c 100644 --- a/mods/ra/rules/civilian.yaml +++ b/mods/ra/rules/civilian.yaml @@ -4,7 +4,8 @@ C1: C2: Inherits: ^CivInfantry Selectable: - Voice: CivilianFemaleVoice + Voiced: + VoiceSet: CivilianFemaleVoice C3: Inherits: ^CivInfantry @@ -12,10 +13,11 @@ C3: C4: Inherits: ^CivInfantry Selectable: - Voice: CivilianFemaleVoice WithInfantryBody: RenderSprites: Image: C2 + Voiced: + VoiceSet: CivilianFemaleVoice C5: Inherits: ^CivInfantry @@ -26,10 +28,11 @@ C5: C6: Inherits: ^CivInfantry Selectable: - Voice: CivilianFemaleVoice WithInfantryBody: RenderSprites: Image: C2 + Voiced: + VoiceSet: CivilianFemaleVoice C7: Inherits: ^CivInfantry @@ -40,10 +43,11 @@ C7: C8: Inherits: ^CivInfantry Selectable: - Voice: CivilianFemaleVoice WithInfantryBody: RenderSprites: Image: C2 + Voiced: + VoiceSet: CivilianFemaleVoice C9: Inherits: ^CivInfantry @@ -54,10 +58,11 @@ C9: C10: Inherits: ^CivInfantry Selectable: - Voice: CivilianFemaleVoice WithInfantryBody: RenderSprites: Image: C2 + Voiced: + VoiceSet: CivilianFemaleVoice FCOM: Inherits: ^TechBuilding diff --git a/mods/ra/rules/defaults.yaml b/mods/ra/rules/defaults.yaml index ffdb85f4a8..0ce6f96534 100644 --- a/mods/ra/rules/defaults.yaml +++ b/mods/ra/rules/defaults.yaml @@ -48,7 +48,6 @@ ROT: 5 SelectionDecorations: Selectable: - Voice: VehicleVoice TargetableUnit: TargetTypes: Ground, Repair, Vehicle Repairable: @@ -83,6 +82,8 @@ MustBeDestroyed: AnnounceOnSeen: Notification: EnemyDetected + Voiced: + VoiceSet: VehicleVoice ^Tank: Inherits@1: ^ExistsInWorld @@ -101,7 +102,6 @@ ROT: 5 SelectionDecorations: Selectable: - Voice: VehicleVoice TargetableUnit: TargetTypes: Ground, C4, Repair, Tank Repairable: @@ -145,6 +145,8 @@ WaterCorpsePalette: AnnounceOnSeen: Notification: EnemyDetected + Voiced: + VoiceSet: VehicleVoice ^Infantry: Inherits@1: ^ExistsInWorld @@ -168,7 +170,6 @@ Beach: 80 SelectionDecorations: Selectable: - Voice: GenericVoice TargetableUnit: TargetTypes: Ground, Infantry, Disguise RenderSprites: @@ -221,6 +222,8 @@ MustBeDestroyed: AnnounceOnSeen: Notification: EnemyDetected + Voiced: + VoiceSet: GenericVoice ^Ship: Inherits@1: ^ExistsInWorld @@ -232,7 +235,6 @@ Water: 100 SelectionDecorations: Selectable: - Voice: VehicleVoice TargetableUnit: TargetTypes: Ground, Water, Repair HiddenUnderFog: @@ -254,6 +256,8 @@ Notification: EnemyDetected EditorTilesetFilter: ExcludeTilesets: INTERIOR + Voiced: + VoiceSet: VehicleVoice ^Plane: Inherits@1: ^ExistsInWorld @@ -263,7 +267,6 @@ UseLocation: true SelectionDecorations: Selectable: - Voice: GenericVoice TargetableAircraft: TargetTypes: Air GroundedTargetTypes: Ground, Repair @@ -290,6 +293,8 @@ MustBeDestroyed: AnnounceOnSeen: Notification: EnemyDetected + Voiced: + VoiceSet: GenericVoice ^Helicopter: Inherits: ^Plane @@ -446,7 +451,6 @@ ^CivInfantry: Inherits: ^Infantry Selectable: - Voice: CivilianMaleVoice Bounds: 12,17,0,-9 Valued: Cost: 70 @@ -466,6 +470,8 @@ Types: CivilianInfantry WithInfantryBody: ScaredyCat: + Voiced: + VoiceSet: CivilianMaleVoice ^CivBuilding: Inherits: ^TechBuilding diff --git a/mods/ra/rules/infantry.yaml b/mods/ra/rules/infantry.yaml index 22f82ec472..d5315b335b 100644 --- a/mods/ra/rules/infantry.yaml +++ b/mods/ra/rules/infantry.yaml @@ -11,7 +11,6 @@ DOG: Name: Attack Dog Description: Anti-infantry unit.\nCan detect cloaked units and spies.\n Strong vs Infantry\n Weak vs Vehicles Selectable: - Voice: DogVoice Bounds: 12,17,-1,-4 Health: HP: 12 @@ -29,6 +28,8 @@ DOG: IgnoresDisguise: DetectCloaked: Range: 5 + Voiced: + VoiceSet: DogVoice E1: Inherits: ^Infantry @@ -184,7 +185,6 @@ E6: Name: Engineer Description: Infiltrates and captures enemy structures.\n Strong vs Nothing\n Weak vs Everything Selectable: - Voice: EngineerVoice Bounds: 12,17,0,-9 Health: HP: 25 @@ -204,6 +204,8 @@ E6: WithInfantryBody: IdleSequences: idle1,idle2 StandSequences: stand,stand2 + Voiced: + VoiceSet: EngineerVoice SPY: Inherits: ^Infantry @@ -220,7 +222,6 @@ SPY: GenericName: Soldier Description: Infiltrates enemy structures for intel or\nsabotage. Exact effect depends on the\nbuilding infiltrated.\n Strong vs Nothing\n Weak vs Everything\n Special Ability: Disguised Selectable: - Voice: SpyVoice Bounds: 12,17,0,-9 Health: HP: 25 @@ -245,6 +246,8 @@ SPY: Armament: Weapon: SilencedPPK AttackFrontal: + Voiced: + VoiceSet: SpyVoice SPY.England: Inherits: SPY @@ -272,7 +275,6 @@ E7: Name: Tanya Description: Elite commando infantry. Armed with\ndual pistols and C4.\n Strong vs Infantry, Buildings\n Weak vs Vehicles\n Special Ability: Destroy Building with C4\n\nMaximum 1 can be trained Selectable: - Voice: TanyaVoice Bounds: 12,17,0,-9 Health: HP: 100 @@ -302,6 +304,8 @@ E7: IdleSequences: idle1,idle2 AnnounceOnBuild: AnnounceOnKill: + Voiced: + VoiceSet: TanyaVoice MEDI: Inherits: ^Infantry @@ -316,7 +320,6 @@ MEDI: Name: Medic Description: Heals nearby infantry.\n Strong vs Nothing\n Weak vs Everything Selectable: - Voice: MedicVoice Bounds: 12,17,0,-9 Health: HP: 80 @@ -340,6 +343,8 @@ MEDI: WithInfantryBody: IdleSequences: idle1,idle2 AttackSequence: heal + Voiced: + VoiceSet: MedicVoice MECH: Inherits: ^Infantry @@ -354,7 +359,6 @@ MECH: Name: Mechanic Description: Repairs nearby vehicles and restores\nhusks to working condition.\n Strong vs Nothing\n Weak vs Everything Selectable: - Voice: MechanicVoice Bounds: 12,17,0,-9 Health: HP: 80 @@ -380,11 +384,12 @@ MECH: WithInfantryBody: IdleSequences: idle1,idle2 AttackSequence: heal + Voiced: + VoiceSet: MechanicVoice EINSTEIN: Inherits: ^Infantry Selectable: - Voice: EinsteinVoice Bounds: 12,17,0,-9 Valued: Cost: 10 @@ -401,11 +406,12 @@ EINSTEIN: Types: CivilianInfantry WithInfantryBody: ScaredyCat: + Voiced: + VoiceSet: EinsteinVoice DELPHI: Inherits: ^Infantry Selectable: - Voice: CivilianMaleVoice Bounds: 12,17,0,-9 Valued: Cost: 10 @@ -422,6 +428,8 @@ DELPHI: Types: CivilianInfantry WithInfantryBody: ScaredyCat: + Voiced: + VoiceSet: CivilianMaleVoice CHAN: Inherits: ^CivInfantry @@ -433,7 +441,8 @@ GNRL: Tooltip: Name: General Selectable: - Voice: StavrosVoice + Voiced: + VoiceSet: StavrosVoice THF: Inherits: ^Infantry @@ -443,7 +452,6 @@ THF: Name: Thief Description: Steals enemy credits.\n Strong vs Nothing\n Weak vs Everything\n Selectable: - Voice: ThiefVoice Bounds: 12,17,0,-9 Health: HP: 25 @@ -460,6 +468,8 @@ THF: Prone50Percent: 50 DamageTriggers: TriggerProne -AutoTarget: + Voiced: + VoiceSet: ThiefVoice HIJACKER: Inherits: ^Infantry @@ -474,7 +484,6 @@ HIJACKER: Name: Hijacker Description: Hijacks enemy vehicles. Unarmed\n Strong vs Tanks\n Weak vs Infantry, Aircraft Selectable: - Voice: ThiefVoice Bounds: 12,17,0,-9 Health: HP: 50 @@ -487,6 +496,8 @@ HIJACKER: Captures: CaptureTypes: vehicle -AutoTarget: + Voiced: + VoiceSet: ThiefVoice SHOK: Inherits: ^Infantry @@ -501,7 +512,6 @@ SHOK: Name: Shock Trooper Description: Elite infantry with portable tesla coils.\n Strong vs Infantry\n Weak vs Aircraft Selectable: - Voice: ShokVoice Bounds: 12,17,0,-9 Health: HP: 100 @@ -523,6 +533,8 @@ SHOK: WithInfantryBody: IdleSequences: idle1,idle2 StandSequences: stand,stand2 + Voiced: + VoiceSet: ShokVoice SNIPER: Inherits: ^Infantry @@ -584,7 +596,6 @@ Zombie: BuildPaletteOrder: 200 Prerequisites: ~bio Selectable: - Voice: AntVoice Bounds: 12,17,0,-9 Health: HP: 250 @@ -595,6 +606,8 @@ Zombie: AttackFrontal: Armament: Weapon: claw + Voiced: + VoiceSet: AntVoice Ant: Inherits: ^Infantry @@ -608,7 +621,6 @@ Ant: BuildPaletteOrder: 1954 Prerequisites: ~bio Selectable: - Voice: AntVoice Bounds: 30,30,0,-2 Health: HP: 750 @@ -626,4 +638,6 @@ Ant: TargetTypes: Ground, Infantry WithDeathAnimation: UseDeathTypeSuffix: false + Voiced: + VoiceSet: AntVoice diff --git a/mods/ts/rules/aircraft.yaml b/mods/ts/rules/aircraft.yaml index ca8e02ce40..bf1f5dd041 100644 --- a/mods/ts/rules/aircraft.yaml +++ b/mods/ts/rules/aircraft.yaml @@ -207,7 +207,8 @@ SCRIN: Prerequisites: ~nahpad, natech Selectable: Bounds: 30,24 - Voice: Scrin + Voiced: + VoiceSet: Scrin Plane: MaximumPitch: 90 ROT: 3 diff --git a/mods/ts/rules/civilian-infantry.yaml b/mods/ts/rules/civilian-infantry.yaml index 998e22f6f8..85e1de3850 100644 --- a/mods/ts/rules/civilian-infantry.yaml +++ b/mods/ts/rules/civilian-infantry.yaml @@ -6,7 +6,8 @@ WEEDGUY: Name: Chem Spray Infantry Selectable: Bounds: 12,17,0,-6 - Voice: Weed + Voiced: + VoiceSet: Weed Mobile: Speed: 42 Health: @@ -35,7 +36,8 @@ UMAGON: Name: Umagon Selectable: Bounds: 12,17,0,-6 - Voice: Umagon + Voiced: + VoiceSet: Umagon Mobile: Speed: 71 Health: @@ -65,8 +67,9 @@ CHAMSPY: Cost: 700 DisguiseToolTip: Name: Chameleon Spy + Voiced: + VoiceSet: Spy Selectable: - Voice: Spy Bounds: 12,17,0,-9 Health: HP: 120 @@ -99,7 +102,8 @@ MUTANT: Name: Mutant Selectable: Bounds: 12,17,0,-9 - Voice: Mutant + Voiced: + VoiceSet: Mutant Health: HP: 50 PoisonedByTiberium: @@ -130,7 +134,8 @@ MWMN: Name: Mutant Soldier Selectable: Bounds: 12,17,0,-9 - Voice: CivilianFemale + Voiced: + VoiceSet: CivilianFemale Health: HP: 50 PoisonedByTiberium: @@ -161,7 +166,8 @@ MUTANT3: Name: Mutant Sergeant Selectable: Bounds: 12,17,0,-9 - Voice: Mutant + Voiced: + VoiceSet: Mutant Health: HP: 50 PoisonedByTiberium: @@ -192,7 +198,8 @@ TRATOS: Name: Tratos Selectable: Bounds: 12,17,0,-9 - Voice: Tratos + Voiced: + VoiceSet: Tratos Health: HP: 200 PoisonedByTiberium: @@ -221,7 +228,8 @@ OXANNA: Name: Oxanna Selectable: Bounds: 12,17,0,-9 - Voice: Oxanna + Voiced: + VoiceSet: Oxanna Health: HP: 50 Mobile: @@ -248,7 +256,8 @@ SLAV: Name: Slavick Selectable: Bounds: 12,17,0,-9 - Voice: Slavick + Voiced: + VoiceSet: Slavick Health: HP: 300 Mobile: @@ -284,8 +293,8 @@ DOGGIE: Range: 4c0 Mobile: Speed: 113 - Selectable: - Voice: Fiend + Voiced: + VoiceSet: Fiend TargetableUnit: TargetTypes: Ground Armament: @@ -314,8 +323,8 @@ VISSML: Speed: 113 ROT: 16 -Crushable: - Selectable: - Voice: Fiend + Voiced: + VoiceSet: Fiend TargetableUnit: TargetTypes: Ground -AutoTarget: @@ -342,8 +351,8 @@ VISLRG: Speed: 113 ROT: 16 -Crushable: - Selectable: - Voice: Fiend + Voiced: + VoiceSet: Fiend TargetableUnit: TargetTypes: Ground Armament: diff --git a/mods/ts/rules/defaults.yaml b/mods/ts/rules/defaults.yaml index e6835d98ae..426ca64fe5 100644 --- a/mods/ts/rules/defaults.yaml +++ b/mods/ts/rules/defaults.yaml @@ -188,7 +188,8 @@ SelectionDecorations: Palette: pips Selectable: - Voice: Infantry + Voiced: + VoiceSet: Infantry TargetableUnit: TargetTypes: Ground, Infantry RenderSprites: @@ -253,8 +254,9 @@ ^CivilianInfantry: Inherits: ^Infantry Selectable: - Voice: Civilian Bounds: 12,17,0,-9 + Voiced: + VoiceSet: Civilian Valued: Cost: 10 Tooltip: @@ -284,10 +286,11 @@ Tiberium: 80 BlueTiberium: 80 ROT: 5 + Selectable: SelectionDecorations: Palette: pips - Selectable: - Voice: Vehicle + Voiced: + VoiceSet: Vehicle TargetableUnit: TargetTypes: Ground, Vehicle Repairable: @@ -368,10 +371,11 @@ Tiberium: 80 BlueTiberium: 80 ROT: 5 + Selectable: SelectionDecorations: Palette: pips - Selectable: - Voice: Vehicle + Voiced: + VoiceSet: Vehicle TargetableUnit: TargetTypes: Ground, Vehicle Repairable: @@ -445,10 +449,11 @@ TargetableAircraft: TargetTypes: Air GroundedTargetTypes: Ground + Selectable: SelectionDecorations: Palette: pips - Selectable: - Voice: Heli + Voiced: + VoiceSet: Heli Helicopter: RepairBuildings: gadept RearmBuildings: diff --git a/mods/ts/rules/gdi-infantry.yaml b/mods/ts/rules/gdi-infantry.yaml index 50808a8910..df4542e4f4 100644 --- a/mods/ts/rules/gdi-infantry.yaml +++ b/mods/ts/rules/gdi-infantry.yaml @@ -44,7 +44,8 @@ MEDIC: Prerequisites: ~gapile Selectable: Bounds: 12,17,0,-6 - Voice: Medic + Voiced: + VoiceSet: Medic Mobile: Speed: 56 Health: diff --git a/mods/ts/rules/gdi-vehicles.yaml b/mods/ts/rules/gdi-vehicles.yaml index bad3e0193a..b6b18e0ad8 100644 --- a/mods/ts/rules/gdi-vehicles.yaml +++ b/mods/ts/rules/gdi-vehicles.yaml @@ -106,8 +106,9 @@ SMECH: Weapon: AssaultCannon RenderSprites: WithInfantryBody: + Voiced: + VoiceSet: Mech Selectable: - Voices: Mech Bounds: 20, 32, 0, -8 MMCH: diff --git a/mods/ts/rules/nod-infantry.yaml b/mods/ts/rules/nod-infantry.yaml index 5312403718..a14c303faf 100644 --- a/mods/ts/rules/nod-infantry.yaml +++ b/mods/ts/rules/nod-infantry.yaml @@ -11,7 +11,8 @@ E3: Description: Anti-tank infantry.\n Strong vs Vehicles, Aircraft, Buildings\n Weak vs Infantry Selectable: Bounds: 12,17,0,-9 - Voice: Rocket + Voiced: + VoiceSet: Rocket Health: HP: 100 Mobile: @@ -47,7 +48,8 @@ CYBORG: -Crushable: Selectable: Bounds: 14,30,0,-7 - Voice: Cyborg + Voiced: + VoiceSet: Cyborg Mobile: Speed: 56 Health: @@ -88,7 +90,8 @@ CYC2: -Crushable: Selectable: Bounds: 14,30,0,-7 - Voice: CyborgCommando + Voiced: + VoiceSet: CyborgCommando Mobile: Speed: 56 Health: @@ -126,7 +129,8 @@ MHIJACK: Description: Hijacks enemy vehicles.\n Unarmed Selectable: Bounds: 12,17,0,-9 - Voice: Hijacker + Voiced: + VoiceSet: Hijacker Health: HP: 300 PoisonedByTiberium: diff --git a/mods/ts/rules/nod-support.yaml b/mods/ts/rules/nod-support.yaml index 76198480ec..93445c9d71 100644 --- a/mods/ts/rules/nod-support.yaml +++ b/mods/ts/rules/nod-support.yaml @@ -165,6 +165,8 @@ GATICK: Type: Concrete RevealsShroud: Range: 5c0 + Voiced: + VoiceSet: Vehicle Turreted: ROT: 6 InitialFacing: 128 @@ -215,8 +217,8 @@ GAARTY: Type: Light RevealsShroud: Range: 9c0 - Selectable: - Voice: Vehicle + Voiced: + VoiceSet: Vehicle Turreted: ROT: 5 InitialFacing: 128 diff --git a/mods/ts/rules/shared-infantry.yaml b/mods/ts/rules/shared-infantry.yaml index 47c235b37a..0ea97851f4 100644 --- a/mods/ts/rules/shared-infantry.yaml +++ b/mods/ts/rules/shared-infantry.yaml @@ -49,7 +49,8 @@ ENGINEER: Prerequisites: ~barracks Selectable: Bounds: 12,17,0,-6 - Voice: Engineer + Voiced: + VoiceSet: Engineer Mobile: Speed: 56 Health: From 037bd6794c85899818b1aaded8b4eb556dc31382 Mon Sep 17 00:00:00 2001 From: reaperrr Date: Sat, 9 May 2015 18:21:57 +0200 Subject: [PATCH 2/8] Upgrade rules for moving Voice to Voiced trait --- .../UtilityCommands/UpgradeRules.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs index 38ddd21285..1133847829 100644 --- a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs +++ b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs @@ -943,6 +943,28 @@ namespace OpenRA.Mods.Common.UtilityCommands node.Key = node.Key.Replace("ProvidesCustomPrerequisite", "ProvidesPrerequisite"); } + if (engineVersion < 20150509) + { + if (depth == 0 && node.Value.Nodes.Exists(n => n.Key == "Selectable")) + { + var selectable = node.Value.Nodes.FirstOrDefault(n => n.Key == "Selectable"); + var selectableNodes = selectable.Value.Nodes; + var voice = selectableNodes.FirstOrDefault(n => n.Key == "Voice"); + var selectableVoice = voice != null ? FieldLoader.GetValue("Voice", voice.Value.Value) : ""; + + if (voice != null) + { + node.Value.Nodes.Add(new MiniYamlNode("Voiced", "", new List + { + new MiniYamlNode("VoiceSet", selectableVoice), + })); + } + } + + if (node.Key.StartsWith("Selectable")) + node.Value.Nodes.RemoveAll(p => p.Key == "Voice"); + } + UpgradeActorRules(engineVersion, ref node.Value.Nodes, node, depth + 1); } } From 251d3e686498fda9ddf45e399f78f8a3b2995b60 Mon Sep 17 00:00:00 2001 From: reaperrr Date: Tue, 12 May 2015 16:35:31 +0200 Subject: [PATCH 3/8] Move PlayVoice and PlayVoiceLocal from Sound to Voiced. Move HasVoice, HasVoices and GetVoices from WorldUtils to Voiced. --- OpenRA.Game/Selection.cs | 5 +- OpenRA.Game/Sound/Sound.cs | 26 ---------- OpenRA.Game/Traits/TraitsInterfaces.cs | 10 +++- OpenRA.Game/WorldUtils.cs | 32 +++--------- OpenRA.Mods.Common/Traits/Cargo.cs | 2 +- .../Traits/Sound/AnnounceOnBuild.cs | 3 +- .../Traits/Sound/AnnounceOnKill.cs | 3 +- .../Traits/Sound/DeathSounds.cs | 8 +-- OpenRA.Mods.Common/Traits/Voiced.cs | 49 +++++++++++++++++++ 9 files changed, 77 insertions(+), 61 deletions(-) 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; } } } } From 5f6851607034d33577d0cba899292c85ff473ab6 Mon Sep 17 00:00:00 2001 From: reaperrr Date: Thu, 14 May 2015 17:48:35 +0200 Subject: [PATCH 4/8] Cleaned up IVoiced-related code. Added Volume control and descriptions to Voiced. Streamline voice checks in WorldUtils and DeathSounds. --- OpenRA.Game/Selection.cs | 4 +- OpenRA.Game/Traits/TraitsInterfaces.cs | 7 +- OpenRA.Game/WorldUtils.cs | 15 ++-- OpenRA.Mods.Common/Traits/Cargo.cs | 2 +- .../Traits/Sound/AnnounceOnBuild.cs | 2 +- .../Traits/Sound/AnnounceOnKill.cs | 2 +- .../Traits/Sound/DeathSounds.cs | 11 +-- OpenRA.Mods.Common/Traits/Voiced.cs | 87 +++++++++---------- 8 files changed, 57 insertions(+), 73 deletions(-) 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); + } } } From 5e2c781c8a6dbe420a93a0ba97564e02f0c970fd Mon Sep 17 00:00:00 2001 From: reaperrr Date: Thu, 21 May 2015 05:35:08 +0200 Subject: [PATCH 5/8] Adds PlayVoice, PlayVoiceLocal and HasVoice to ActorExts. Makes Cargo unload voice customisable. --- OpenRA.Mods.Common/ActorExts.cs | 33 +++++++++++++++++++ OpenRA.Mods.Common/Traits/Cargo.cs | 7 ++-- .../Traits/Sound/AnnounceOnBuild.cs | 3 +- .../Traits/Sound/AnnounceOnKill.cs | 3 +- .../Traits/Sound/DeathSounds.cs | 3 +- 5 files changed, 41 insertions(+), 8 deletions(-) diff --git a/OpenRA.Mods.Common/ActorExts.cs b/OpenRA.Mods.Common/ActorExts.cs index 4cbe893c74..57f19ca1be 100644 --- a/OpenRA.Mods.Common/ActorExts.cs +++ b/OpenRA.Mods.Common/ActorExts.cs @@ -80,6 +80,39 @@ namespace OpenRA.Mods.Common return Target.Invalid; } + public static void PlayVoice(this Actor self, Actor actor, string phrase, string variant) + { + foreach (var voiced in self.TraitsImplementing()) + { + if (phrase == null) + return; + + if (string.IsNullOrEmpty(voiced.VoiceSet)) + return; + + voiced.PlayVoice(self, phrase, variant); + } + } + + public static void PlayVoiceLocal(this Actor self, Actor actor, string phrase, string variant, float volume) + { + foreach (var voiced in self.TraitsImplementing()) + { + if (phrase == null) + return; + + if (string.IsNullOrEmpty(voiced.VoiceSet)) + return; + + voiced.PlayVoiceLocal(self, phrase, variant, volume); + } + } + + public static bool HasVoice(this Actor self, string voice) + { + return self.TraitsImplementing().Any(x => x.HasVoice(self, voice)); + } + public static void NotifyBlocker(this Actor self, IEnumerable blockers) { foreach (var blocker in blockers) diff --git a/OpenRA.Mods.Common/Traits/Cargo.cs b/OpenRA.Mods.Common/Traits/Cargo.cs index db87aed3f0..e501df1acf 100644 --- a/OpenRA.Mods.Common/Traits/Cargo.cs +++ b/OpenRA.Mods.Common/Traits/Cargo.cs @@ -39,6 +39,9 @@ namespace OpenRA.Mods.Common.Traits [Desc("Terrain types that this actor is allowed to eject actors onto. Leave empty for all terrain types.")] public readonly string[] UnloadTerrainTypes = { }; + [Desc("Voice to play when ordered to unload the passengers.")] + public readonly string UnloadVoice = "Unload"; + [Desc("Which direction the passenger will face (relative to the transport) when unloading.")] public readonly int PassengerFacing = 128; @@ -204,10 +207,10 @@ namespace OpenRA.Mods.Common.Traits public string VoicePhraseForOrder(Actor self, Order order) { - if (order.OrderString != "Unload" || IsEmpty(self)) + if (order.OrderString != "Unload" || IsEmpty(self) || !self.HasVoice(Info.UnloadVoice)) return null; - return self.TraitsImplementing().Any(x => x.HasVoice(self, "Unload")) ? "Unload" : "Move"; + return Info.UnloadVoice; } 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 b60ae2f1b8..e3ceb5fc64 100644 --- a/OpenRA.Mods.Common/Traits/Sound/AnnounceOnBuild.cs +++ b/OpenRA.Mods.Common/Traits/Sound/AnnounceOnBuild.cs @@ -19,8 +19,7 @@ namespace OpenRA.Mods.Common.Traits { public void BuildingComplete(Actor self) { - foreach (var voiced in self.TraitsImplementing()) - voiced.PlayVoice(self, "Build", self.Owner.Country.Race); + self.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 2f46199cb7..43e1a1e4f7 100644 --- a/OpenRA.Mods.Common/Traits/Sound/AnnounceOnKill.cs +++ b/OpenRA.Mods.Common/Traits/Sound/AnnounceOnKill.cs @@ -39,8 +39,7 @@ namespace OpenRA.Mods.Common.Traits if (e.DamageState == DamageState.Dead && damaged != e.Attacker) { if (self.World.WorldTick - lastAnnounce > info.Interval * 25) - foreach (var voiced in self.TraitsImplementing()) - voiced.PlayVoice(self, "Kill", self.Owner.Country.Race); + self.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 69ccbe1d2c..92b0068a1b 100644 --- a/OpenRA.Mods.Common/Traits/Sound/DeathSounds.cs +++ b/OpenRA.Mods.Common/Traits/Sound/DeathSounds.cs @@ -42,8 +42,7 @@ namespace OpenRA.Mods.Common.Traits 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); + self.PlayVoiceLocal(self, info.DeathSound, self.Owner.Country.Race, info.VolumeMultiplier); } } } \ No newline at end of file From b9e8406aeb65f08a01937aaf964fe797f834d2fd Mon Sep 17 00:00:00 2001 From: reaperrr Date: Thu, 21 May 2015 05:53:49 +0200 Subject: [PATCH 6/8] Fix Unload definition in voice sets. --- mods/cnc/audio/voices.yaml | 1 + mods/ra/audio/voices.yaml | 1 + mods/ts/audio/voices.yaml | 1 + 3 files changed, 3 insertions(+) diff --git a/mods/cnc/audio/voices.yaml b/mods/cnc/audio/voices.yaml index b0045e5624..c69770bf45 100644 --- a/mods/cnc/audio/voices.yaml +++ b/mods/cnc/audio/voices.yaml @@ -18,6 +18,7 @@ VehicleVoice: Voices: Select: vehic1,yessir1,report1,await1,unit1 Move: ackno,affirm1,movout1 + Unload: movout1 CivilianMaleVoice: Voices: diff --git a/mods/ra/audio/voices.yaml b/mods/ra/audio/voices.yaml index cd628a67d7..1d828bea0f 100644 --- a/mods/ra/audio/voices.yaml +++ b/mods/ra/audio/voices.yaml @@ -27,6 +27,7 @@ VehicleVoice: Voices: Select: vehic1,yessir1,report1,await1 Move: ackno,affirm1 + Unload: ackno,affirm1 EngineerVoice: Voices: diff --git a/mods/ts/audio/voices.yaml b/mods/ts/audio/voices.yaml index 0f83f7b9c8..a1cc798eba 100644 --- a/mods/ts/audio/voices.yaml +++ b/mods/ts/audio/voices.yaml @@ -161,6 +161,7 @@ Vehicle: Select: 25-I000, 25-I002, 25-I004, 25-I006 Move: 25-I012, 25-I014, 25-I016, 25-I018, 25-I022 Attack: 25-I014, 25-I022, 25-I024, 25-I026 + Unload: 25-I018 Mech: Voices: From 3777a8bca9e10fa98da693ee9caae80a94c8709f Mon Sep 17 00:00:00 2001 From: reaperrr Date: Thu, 21 May 2015 15:48:30 +0200 Subject: [PATCH 7/8] Moved Voice-related extensions to VoiceExts. Note: This is a work-around until Selectable can be moved to Mods.Common, which is when the voice extensions should be moved back to ActorExts. Pulled phrase check before foreach in PlayVoice ActorExts. Removed superflous actor parameter from PlayVoice/PlayVoiceLocal. Simplified PlayVoice extensions. variant is no longer customisable, as all current usages use self.Owner.Country.Race anyway. --- OpenRA.Game/OpenRA.Game.csproj | 1 + OpenRA.Game/Selection.cs | 3 +- OpenRA.Game/VoiceExts.cs | 75 +++++++++++++++++++ OpenRA.Game/WorldUtils.cs | 20 ----- OpenRA.Mods.Common/ActorExts.cs | 33 -------- .../Traits/Sound/AnnounceOnBuild.cs | 2 +- .../Traits/Sound/AnnounceOnKill.cs | 2 +- .../Traits/Sound/DeathSounds.cs | 2 +- 8 files changed, 80 insertions(+), 58 deletions(-) create mode 100644 OpenRA.Game/VoiceExts.cs diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index a1e1d691a3..b211f9c12c 100644 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -179,6 +179,7 @@ + diff --git a/OpenRA.Game/Selection.cs b/OpenRA.Game/Selection.cs index 38bc05cbd6..2700aee20a 100644 --- a/OpenRA.Game/Selection.cs +++ b/OpenRA.Game/Selection.cs @@ -59,8 +59,7 @@ namespace OpenRA var voicedActor = actors.FirstOrDefault(a => a.Owner == world.LocalPlayer && a.IsInWorld && a.HasTrait()); if (voicedActor != null) - foreach (var voice in voicedActor.TraitsImplementing()) - voice.PlayVoice(voicedActor, "Select", voicedActor.Owner.Country.Race); + voicedActor.PlayVoice("Select"); foreach (var a in newSelection) foreach (var sel in a.TraitsImplementing()) diff --git a/OpenRA.Game/VoiceExts.cs b/OpenRA.Game/VoiceExts.cs new file mode 100644 index 0000000000..c63d7a4d69 --- /dev/null +++ b/OpenRA.Game/VoiceExts.cs @@ -0,0 +1,75 @@ +#region Copyright & License Information +/* + * Copyright 2007-2015 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using OpenRA.Traits; + +namespace OpenRA +{ + public static class VoiceExts + { + public static void PlayVoice(this Actor self, string phrase) + { + if (phrase == null) + return; + + foreach (var voiced in self.TraitsImplementing()) + { + if (string.IsNullOrEmpty(voiced.VoiceSet)) + return; + + voiced.PlayVoice(self, phrase, self.Owner.Country.Race); + } + } + + public static void PlayVoiceLocal(this Actor self, string phrase, float volume) + { + if (phrase == null) + return; + + foreach (var voiced in self.TraitsImplementing()) + { + if (string.IsNullOrEmpty(voiced.VoiceSet)) + return; + + voiced.PlayVoiceLocal(self, phrase, self.Owner.Country.Race, volume); + } + } + + public static bool HasVoice(this Actor self, string voice) + { + return self.TraitsImplementing().Any(x => x.HasVoice(self, voice)); + } + + public static void PlayVoiceForOrders(this World w, Order[] orders) + { + // Find an actor with a phrase to say + foreach (var o in orders) + { + if (o == null) + continue; + + var orderSubject = o.Subject; + if (orderSubject.Destroyed) + continue; + + 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.Game/WorldUtils.cs b/OpenRA.Game/WorldUtils.cs index ae342a3f9c..d3cd04cda8 100644 --- a/OpenRA.Game/WorldUtils.cs +++ b/OpenRA.Game/WorldUtils.cs @@ -42,26 +42,6 @@ namespace OpenRA } } - public static void PlayVoiceForOrders(this World w, Order[] orders) - { - // Find an actor with a phrase to say - foreach (var o in orders) - { - if (o == null) - continue; - - var orderSubject = o.Subject; - if (orderSubject.Destroyed) - continue; - - 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; - } - } - public static void DoTimed(this IEnumerable e, Action a, string text) { // Note - manual enumeration here for performance due to high call volume. diff --git a/OpenRA.Mods.Common/ActorExts.cs b/OpenRA.Mods.Common/ActorExts.cs index 57f19ca1be..4cbe893c74 100644 --- a/OpenRA.Mods.Common/ActorExts.cs +++ b/OpenRA.Mods.Common/ActorExts.cs @@ -80,39 +80,6 @@ namespace OpenRA.Mods.Common return Target.Invalid; } - public static void PlayVoice(this Actor self, Actor actor, string phrase, string variant) - { - foreach (var voiced in self.TraitsImplementing()) - { - if (phrase == null) - return; - - if (string.IsNullOrEmpty(voiced.VoiceSet)) - return; - - voiced.PlayVoice(self, phrase, variant); - } - } - - public static void PlayVoiceLocal(this Actor self, Actor actor, string phrase, string variant, float volume) - { - foreach (var voiced in self.TraitsImplementing()) - { - if (phrase == null) - return; - - if (string.IsNullOrEmpty(voiced.VoiceSet)) - return; - - voiced.PlayVoiceLocal(self, phrase, variant, volume); - } - } - - public static bool HasVoice(this Actor self, string voice) - { - return self.TraitsImplementing().Any(x => x.HasVoice(self, voice)); - } - public static void NotifyBlocker(this Actor self, IEnumerable blockers) { foreach (var blocker in blockers) diff --git a/OpenRA.Mods.Common/Traits/Sound/AnnounceOnBuild.cs b/OpenRA.Mods.Common/Traits/Sound/AnnounceOnBuild.cs index e3ceb5fc64..f2b4188cc9 100644 --- a/OpenRA.Mods.Common/Traits/Sound/AnnounceOnBuild.cs +++ b/OpenRA.Mods.Common/Traits/Sound/AnnounceOnBuild.cs @@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.Traits { public void BuildingComplete(Actor self) { - self.PlayVoice(self, "Build", self.Owner.Country.Race); + self.PlayVoice("Build"); } } } diff --git a/OpenRA.Mods.Common/Traits/Sound/AnnounceOnKill.cs b/OpenRA.Mods.Common/Traits/Sound/AnnounceOnKill.cs index 43e1a1e4f7..e5d552d2fc 100644 --- a/OpenRA.Mods.Common/Traits/Sound/AnnounceOnKill.cs +++ b/OpenRA.Mods.Common/Traits/Sound/AnnounceOnKill.cs @@ -39,7 +39,7 @@ namespace OpenRA.Mods.Common.Traits if (e.DamageState == DamageState.Dead && damaged != e.Attacker) { if (self.World.WorldTick - lastAnnounce > info.Interval * 25) - self.PlayVoice(self, "Kill", self.Owner.Country.Race); + self.PlayVoice("Kill"); lastAnnounce = self.World.WorldTick; } diff --git a/OpenRA.Mods.Common/Traits/Sound/DeathSounds.cs b/OpenRA.Mods.Common/Traits/Sound/DeathSounds.cs index 92b0068a1b..1f590806ed 100644 --- a/OpenRA.Mods.Common/Traits/Sound/DeathSounds.cs +++ b/OpenRA.Mods.Common/Traits/Sound/DeathSounds.cs @@ -42,7 +42,7 @@ namespace OpenRA.Mods.Common.Traits if (info.DeathTypes.Contains(e.Warhead.DeathType) || (!info.DeathTypes.Any() && !self.Info.Traits.WithInterface().Any(dsi => dsi.DeathTypes.Contains(e.Warhead.DeathType)))) - self.PlayVoiceLocal(self, info.DeathSound, self.Owner.Country.Race, info.VolumeMultiplier); + self.PlayVoiceLocal(info.DeathSound, info.VolumeMultiplier); } } } \ No newline at end of file From a99f69035c51d2465a6999a8c466d6c50c0a7c44 Mon Sep 17 00:00:00 2001 From: reaperrr Date: Sat, 23 May 2015 13:04:45 +0200 Subject: [PATCH 8/8] Made AnnounceOnKill and AnnounceOnBuild voices customisable. --- .../Traits/Sound/AnnounceOnBuild.cs | 17 +++++++++++++++-- .../Traits/Sound/AnnounceOnKill.cs | 5 ++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/OpenRA.Mods.Common/Traits/Sound/AnnounceOnBuild.cs b/OpenRA.Mods.Common/Traits/Sound/AnnounceOnBuild.cs index f2b4188cc9..f2fb745b6f 100644 --- a/OpenRA.Mods.Common/Traits/Sound/AnnounceOnBuild.cs +++ b/OpenRA.Mods.Common/Traits/Sound/AnnounceOnBuild.cs @@ -13,13 +13,26 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { [Desc("Play the Build voice of this actor when trained.")] - public class AnnounceOnBuildInfo : TraitInfo { } + public class AnnounceOnBuildInfo : ITraitInfo + { + [Desc("Voice to use when built/trained.")] + public readonly string BuildVoice = "Build"; + + public object Create(ActorInitializer init) { return new AnnounceOnBuild(init.Self, this); } + } public class AnnounceOnBuild : INotifyBuildComplete { + readonly AnnounceOnBuildInfo info; + + public AnnounceOnBuild(Actor self, AnnounceOnBuildInfo info) + { + this.info = info; + } + public void BuildingComplete(Actor self) { - self.PlayVoice("Build"); + self.PlayVoice(info.BuildVoice); } } } diff --git a/OpenRA.Mods.Common/Traits/Sound/AnnounceOnKill.cs b/OpenRA.Mods.Common/Traits/Sound/AnnounceOnKill.cs index e5d552d2fc..64713a8b82 100644 --- a/OpenRA.Mods.Common/Traits/Sound/AnnounceOnKill.cs +++ b/OpenRA.Mods.Common/Traits/Sound/AnnounceOnKill.cs @@ -18,6 +18,9 @@ namespace OpenRA.Mods.Common.Traits [Desc("Minimum duration (in seconds) between sound events.")] public readonly int Interval = 5; + [Desc("Voice to use when killing something.")] + public readonly string KillVoice = "Kill"; + public object Create(ActorInitializer init) { return new AnnounceOnKill(init.Self, this); } } @@ -39,7 +42,7 @@ namespace OpenRA.Mods.Common.Traits if (e.DamageState == DamageState.Dead && damaged != e.Attacker) { if (self.World.WorldTick - lastAnnounce > info.Interval * 25) - self.PlayVoice("Kill"); + self.PlayVoice(info.KillVoice); lastAnnounce = self.World.WorldTick; }