Merge pull request #8012 from reaperrr/voiceset

Extracted actor Voices from Selectable into own Voiced trait
This commit is contained in:
Matthias Mailänder
2015-05-23 21:59:34 +02:00
33 changed files with 376 additions and 165 deletions

View File

@@ -179,6 +179,7 @@
<Compile Include="Traits\World\Shroud.cs" />
<Compile Include="World.cs" />
<Compile Include="WorldUtils.cs" />
<Compile Include="VoiceExts.cs" />
<Compile Include="Network\ReplayRecorderConnection.cs" />
<Compile Include="Traits\DebugPauseState.cs" />
<Compile Include="Network\UPnP.cs" />

View File

@@ -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.HasTrait<IVoiced>());
if (voicedActor != null)
voicedActor.PlayVoice("Select");
foreach (var a in newSelection)
foreach (var sel in a.TraitsImplementing<INotifySelected>())

View File

@@ -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,32 +364,6 @@ namespace OpenRA
return true;
}
public static bool PlayVoice(string phrase, Actor voicedUnit, string variant)
{
if (voicedUnit == null || phrase == null)
return false;
var mi = voicedUnit.Info.Traits.GetOrDefault<SelectableInfo>();
if (mi == null || mi.Voice == null)
return false;
var type = mi.Voice.ToLowerInvariant();
return PlayPredefined(voicedUnit.World.Map.Rules, null, voicedUnit, type, phrase, variant, true, WPos.Zero, 1f, true);
}
public static bool PlayVoiceLocal(string phrase, Actor voicedUnit, string variant, WPos pos, float volume)
{
if (voicedUnit == null || phrase == null)
return false;
var mi = voicedUnit.Info.Traits.GetOrDefault<SelectableInfo>();
if (mi == null || mi.Voice == null)
return false;
var type = mi.Voice.ToLowerInvariant();
return PlayPredefined(voicedUnit.World.Map.Rules, null, voicedUnit, type, phrase, variant, false, pos, volume, true);
}
public static bool PlayNotification(Ruleset rules, Player player, string type, string notification, string variant)
{
if (rules == null)

View File

@@ -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); }
}

View File

@@ -109,6 +109,14 @@ namespace OpenRA.Traits
public interface ISeedableResource { void Seed(Actor self); }
public interface IVoiced
{
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); }
public interface IDemolishable
{

75
OpenRA.Game/VoiceExts.cs Normal file
View File

@@ -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<IVoiced>())
{
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<IVoiced>())
{
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<IVoiced>().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<IVoiced>())
foreach (var v in orderSubject.TraitsImplementing<IOrderVoice>())
{
if (voice.PlayVoice(orderSubject, v.VoicePhraseForOrder(orderSubject, o),
orderSubject.Owner.Country.Race))
return;
}
}
}
}
}

View File

@@ -42,44 +42,6 @@ namespace OpenRA
}
}
public static bool HasVoices(this Actor a)
{
var selectable = a.Info.Traits.GetOrDefault<SelectableInfo>();
return selectable != null && selectable.Voice != 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 selectable = a.Info.Traits.GetOrDefault<SelectableInfo>();
if (selectable == null) return null;
var v = selectable.Voice;
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
foreach (var o in orders)
{
if (o == null)
continue;
if (o.Subject.Destroyed)
continue;
foreach (var v in o.Subject.TraitsImplementing<IOrderVoice>())
if (Sound.PlayVoice(v.VoicePhraseForOrder(o.Subject, o),
o.Subject, o.Subject.Owner.Country.Race))
return;
}
}
public static void DoTimed<T>(this IEnumerable<T> e, Action<T> a, string text)
{
// Note - manual enumeration here for performance due to high call volume.

View File

@@ -443,6 +443,7 @@
<Compile Include="Traits\Upgrades\UpgradeActorsNear.cs" />
<Compile Include="Traits\Upgrades\UpgradeManager.cs" />
<Compile Include="Traits\Valued.cs" />
<Compile Include="Traits\Voiced.cs" />
<Compile Include="Traits\Wanders.cs" />
<Compile Include="Traits\World\BridgeLayer.cs" />
<Compile Include="Traits\World\CrateSpawner.cs" />

View File

@@ -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.HasVoice("Unload") ? "Unload" : "Move";
return Info.UnloadVoice;
}
public bool MoveDisabled(Actor self) { return reserves.Any(); }

View File

@@ -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<AnnounceOnBuild> { }
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)
{
Sound.PlayVoice("Build", self, self.Owner.Country.Race);
self.PlayVoice(info.BuildVoice);
}
}
}

View File

@@ -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)
Sound.PlayVoice("Kill", self, self.Owner.Country.Race);
self.PlayVoice(info.KillVoice);
lastAnnounce = self.World.WorldTick;
}

View File

@@ -40,11 +40,9 @@ namespace OpenRA.Mods.Common.Traits
if (e.Warhead == null)
return;
var cp = self.CenterPosition;
if (info.DeathTypes.Contains(e.Warhead.DeathType) ||
(!info.DeathTypes.Any() && !self.Info.Traits.WithInterface<DeathSoundsInfo>().Any(dsi => dsi.DeathTypes.Contains(e.Warhead.DeathType))))
Sound.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<DeathSoundsInfo>().Any(dsi => dsi.DeathTypes.Contains(e.Warhead.DeathType))))
self.PlayVoiceLocal(info.DeathSound, info.VolumeMultiplier);
}
}
}

View File

@@ -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.Linq;
using OpenRA.GameRules;
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); }
}
public class Voiced : IVoiced
{
public readonly VoicedInfo Info;
public Voiced(Actor self, VoicedInfo info)
{
Info = info;
}
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);
}
}
}

View File

@@ -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<string>("Voice", voice.Value.Value) : "";
if (voice != null)
{
node.Value.Nodes.Add(new MiniYamlNode("Voiced", "", new List<MiniYamlNode>
{
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);
}
}

View File

@@ -18,6 +18,7 @@ VehicleVoice:
Voices:
Select: vehic1,yessir1,report1,await1,unit1
Move: ackno,affirm1,movout1
Unload: movout1
CivilianMaleVoice:
Voices:

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -27,6 +27,7 @@ VehicleVoice:
Voices:
Select: vehic1,yessir1,report1,await1
Move: ackno,affirm1
Unload: ackno,affirm1
EngineerVoice:
Voices:

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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:

View File

@@ -207,7 +207,8 @@ SCRIN:
Prerequisites: ~nahpad, natech
Selectable:
Bounds: 30,24
Voice: Scrin
Voiced:
VoiceSet: Scrin
Plane:
MaximumPitch: 90
ROT: 3

View File

@@ -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:

View File

@@ -185,7 +185,8 @@
SelectionDecorations:
Palette: pips
Selectable:
Voice: Infantry
Voiced:
VoiceSet: Infantry
TargetableUnit:
TargetTypes: Ground, Infantry
RenderSprites:
@@ -250,8 +251,9 @@
^CivilianInfantry:
Inherits: ^Infantry
Selectable:
Voice: Civilian
Bounds: 12,17,0,-9
Voiced:
VoiceSet: Civilian
Valued:
Cost: 10
Tooltip:
@@ -281,10 +283,11 @@
Tiberium: 80
BlueTiberium: 80
ROT: 5
Selectable:
SelectionDecorations:
Palette: pips
Selectable:
Voice: Vehicle
Voiced:
VoiceSet: Vehicle
TargetableUnit:
TargetTypes: Ground, Vehicle
Repairable:
@@ -365,10 +368,11 @@
Tiberium: 80
BlueTiberium: 80
ROT: 5
Selectable:
SelectionDecorations:
Palette: pips
Selectable:
Voice: Vehicle
Voiced:
VoiceSet: Vehicle
TargetableUnit:
TargetTypes: Ground, Vehicle
Repairable:
@@ -442,10 +446,11 @@
TargetableAircraft:
TargetTypes: Air
GroundedTargetTypes: Ground
Selectable:
SelectionDecorations:
Palette: pips
Selectable:
Voice: Heli
Voiced:
VoiceSet: Heli
Helicopter:
RepairBuildings: gadept
RearmBuildings:

View File

@@ -44,7 +44,8 @@ MEDIC:
Prerequisites: ~gapile
Selectable:
Bounds: 12,17,0,-6
Voice: Medic
Voiced:
VoiceSet: Medic
Mobile:
Speed: 56
Health:

View File

@@ -106,8 +106,9 @@ SMECH:
Weapon: AssaultCannon
RenderSprites:
WithInfantryBody:
Voiced:
VoiceSet: Mech
Selectable:
Voices: Mech
Bounds: 20, 32, 0, -8
MMCH:

View File

@@ -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:

View File

@@ -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

View File

@@ -49,7 +49,8 @@ ENGINEER:
Prerequisites: ~barracks
Selectable:
Bounds: 12,17,0,-6
Voice: Engineer
Voiced:
VoiceSet: Engineer
Mobile:
Speed: 56
Health: