Merge pull request #6799 from pchote/additional-sounds

Made use of various additional sound files in Red Alert
This commit is contained in:
Paul Chote
2014-10-20 20:28:17 +13:00
12 changed files with 66 additions and 17 deletions

View File

@@ -15,9 +15,15 @@ namespace OpenRA.Traits
{ {
public class HealthInfo : ITraitInfo, UsesInit<HealthInit> public class HealthInfo : ITraitInfo, UsesInit<HealthInit>
{ {
[Desc("HitPoints")]
public readonly int HP = 0; public readonly int HP = 0;
[Desc("Physical size of the unit used for damage calculations. Impacts within this radius apply full damage")] [Desc("Physical size of the unit used for damage calculations. Impacts within this radius apply full damage")]
public readonly WRange Radius = new WRange(426); public readonly WRange Radius = new WRange(426);
[Desc("Don't trigger interfaces such as AnnounceOnKill.")]
public readonly bool NotifyAppliedDamage = true;
public virtual object Create(ActorInitializer init) { return new Health(init, this); } public virtual object Create(ActorInitializer init) { return new Health(init, this); }
} }
@@ -92,7 +98,7 @@ namespace OpenRA.Traits
foreach (var nd in self.TraitsImplementing<INotifyDamageStateChanged>()) foreach (var nd in self.TraitsImplementing<INotifyDamageStateChanged>())
nd.DamageStateChanged(self, ai); nd.DamageStateChanged(self, ai);
if (repairer != null && repairer.IsInWorld && !repairer.IsDead()) if (Info.NotifyAppliedDamage && repairer != null && repairer.IsInWorld && !repairer.IsDead())
foreach (var nd in repairer.TraitsImplementing<INotifyAppliedDamage>() foreach (var nd in repairer.TraitsImplementing<INotifyAppliedDamage>()
.Concat(repairer.Owner.PlayerActor.TraitsImplementing<INotifyAppliedDamage>())) .Concat(repairer.Owner.PlayerActor.TraitsImplementing<INotifyAppliedDamage>()))
nd.AppliedDamage(repairer, self, ai); nd.AppliedDamage(repairer, self, ai);
@@ -135,7 +141,7 @@ namespace OpenRA.Traits
foreach (var nd in self.TraitsImplementing<INotifyDamageStateChanged>()) foreach (var nd in self.TraitsImplementing<INotifyDamageStateChanged>())
nd.DamageStateChanged(self, ai); nd.DamageStateChanged(self, ai);
if (attacker != null && attacker.IsInWorld && !attacker.IsDead()) if (Info.NotifyAppliedDamage && attacker != null && attacker.IsInWorld && !attacker.IsDead())
foreach (var nd in attacker.TraitsImplementing<INotifyAppliedDamage>() foreach (var nd in attacker.TraitsImplementing<INotifyAppliedDamage>()
.Concat(attacker.Owner.PlayerActor.TraitsImplementing<INotifyAppliedDamage>())) .Concat(attacker.Owner.PlayerActor.TraitsImplementing<INotifyAppliedDamage>()))
nd.AppliedDamage(attacker, self, ai); nd.AppliedDamage(attacker, self, ai);

View File

@@ -26,8 +26,9 @@ namespace OpenRA.Mods.RA.Activities
var limitedAmmo = self.TraitOrDefault<LimitedAmmo>(); var limitedAmmo = self.TraitOrDefault<LimitedAmmo>();
if (!limitedAmmo.HasAmmo()) if (!limitedAmmo.HasAmmo())
{ {
var info = self.Info.Traits.Get<MinelayerInfo>();
// rearm & repair at fix, then back out here to refill the minefield some more // rearm & repair at fix, then back out here to refill the minefield some more
var buildings = self.Info.Traits.Get<MinelayerInfo>().RearmBuildings; var buildings = info.RearmBuildings;
var rearmTarget = self.World.Actors.Where(a => self.Owner.Stances[a.Owner] == Stance.Ally var rearmTarget = self.World.Actors.Where(a => self.Owner.Stances[a.Owner] == Stance.Ally
&& buildings.Contains(a.Info.Name)) && buildings.Contains(a.Info.Name))
.ClosestTo(self); .ClosestTo(self);
@@ -38,26 +39,27 @@ namespace OpenRA.Mods.RA.Activities
return Util.SequenceActivities( return Util.SequenceActivities(
new MoveAdjacentTo(self, Target.FromActor(rearmTarget)), new MoveAdjacentTo(self, Target.FromActor(rearmTarget)),
movement.MoveTo(self.World.Map.CellContaining(rearmTarget.CenterPosition), rearmTarget), movement.MoveTo(self.World.Map.CellContaining(rearmTarget.CenterPosition), rearmTarget),
new Rearm(self), new Rearm(self, info.RearmSound),
new Repair(rearmTarget), new Repair(rearmTarget),
this); this);
} }
var ml = self.Trait<Minelayer>(); var ml = self.Trait<Minelayer>();
if (ml.Minefield.Contains(self.Location) && if (ml.Minefield.Contains(self.Location) && ShouldLayMine(self, self.Location))
ShouldLayMine(self, self.Location))
{ {
LayMine(self); LayMine(self);
return Util.SequenceActivities(new Wait(20), this); // a little wait after placing each mine, for show return Util.SequenceActivities(new Wait(20), this); // a little wait after placing each mine, for show
} }
if (ml.Minefield.Length > 0) if (ml.Minefield.Length > 0)
{
for (var n = 0; n < 20; n++) // dont get stuck forever here for (var n = 0; n < 20; n++) // dont get stuck forever here
{ {
var p = ml.Minefield.Random(self.World.SharedRandom); var p = ml.Minefield.Random(self.World.SharedRandom);
if (ShouldLayMine(self, p)) if (ShouldLayMine(self, p))
return Util.SequenceActivities( movement.MoveTo(p, 0), this ); return Util.SequenceActivities( movement.MoveTo(p, 0), this );
} }
}
// TODO: return somewhere likely to be safe (near fix) so we're not sitting out in the minefield. // TODO: return somewhere likely to be safe (near fix) so we're not sitting out in the minefield.

View File

@@ -19,18 +19,21 @@ namespace OpenRA.Mods.RA.Activities
readonly LimitedAmmo limitedAmmo; readonly LimitedAmmo limitedAmmo;
int ticksPerPip = 25 * 2; int ticksPerPip = 25 * 2;
int remainingTicks = 25 * 2; int remainingTicks = 25 * 2;
string sound = null;
public Rearm(Actor self) public Rearm(Actor self, string sound = null)
{ {
limitedAmmo = self.TraitOrDefault<LimitedAmmo>(); limitedAmmo = self.TraitOrDefault<LimitedAmmo>();
if (limitedAmmo != null) if (limitedAmmo != null)
ticksPerPip = limitedAmmo.ReloadTimePerAmmo(); ticksPerPip = limitedAmmo.ReloadTimePerAmmo();
remainingTicks = ticksPerPip; remainingTicks = ticksPerPip;
this.sound = sound;
} }
public override Activity Tick(Actor self) public override Activity Tick(Actor self)
{ {
if (IsCanceled || limitedAmmo == null) return NextActivity; if (IsCanceled || limitedAmmo == null)
return NextActivity;
if (--remainingTicks == 0) if (--remainingTicks == 0)
{ {
@@ -44,6 +47,8 @@ namespace OpenRA.Mods.RA.Activities
return NextActivity; return NextActivity;
hostBuilding.Trait<RenderBuilding>().PlayCustomAnim(hostBuilding, "active"); hostBuilding.Trait<RenderBuilding>().PlayCustomAnim(hostBuilding, "active");
if (sound != null)
Sound.Play(sound, self.CenterPosition);
remainingTicks = limitedAmmo.ReloadTimePerAmmo(); remainingTicks = limitedAmmo.ReloadTimePerAmmo();
} }

View File

@@ -12,6 +12,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA namespace OpenRA.Mods.RA
{ {
[Desc("Play the Build voice of this actor when trained.")]
public class AnnounceOnBuildInfo : ITraitInfo public class AnnounceOnBuildInfo : ITraitInfo
{ {
public object Create(ActorInitializer init) { return new AnnounceOnBuild(init.self); } public object Create(ActorInitializer init) { return new AnnounceOnBuild(init.self); }

View File

@@ -12,15 +12,36 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA namespace OpenRA.Mods.RA
{ {
public class AnnounceOnKillInfo : TraitInfo<AnnounceOnKill> {} [Desc("Play the Kill voice of this actor when eliminating enemies.")]
public class AnnounceOnKillInfo : ITraitInfo
{
[Desc("Minimum duration (in seconds) between sound events.")]
public readonly int Interval = 5;
public object Create(ActorInitializer init) { return new AnnounceOnKill(init.self, this); }
}
public class AnnounceOnKill : INotifyAppliedDamage public class AnnounceOnKill : INotifyAppliedDamage
{ {
readonly AnnounceOnKillInfo info;
int lastAnnounce;
public AnnounceOnKill(Actor self, AnnounceOnKillInfo info)
{
this.info = info;
lastAnnounce = -info.Interval * 25;
}
public void AppliedDamage(Actor self, Actor damaged, AttackInfo e) public void AppliedDamage(Actor self, Actor damaged, AttackInfo e)
{ {
if (e.DamageState == DamageState.Dead) if (e.DamageState == DamageState.Dead && damaged != e.Attacker) // don't notify suicides
Sound.PlayVoice("Kill", self, self.Owner.Country.Race); {
if (self.World.WorldTick - lastAnnounce > info.Interval * 25)
Sound.PlayVoice("Kill", self, self.Owner.Country.Race);
lastAnnounce = self.World.WorldTick;
}
} }
} }
} }

View File

@@ -30,6 +30,8 @@ namespace OpenRA.Mods.RA
public readonly int FlashInterval = 4; public readonly int FlashInterval = 4;
[Desc("Duration of each flash")] [Desc("Duration of each flash")]
public readonly int FlashDuration = 3; public readonly int FlashDuration = 3;
[Desc("Voice string when planting explosive charges.")]
public readonly string Voice = "Attack";
public object Create(ActorInitializer init) { return new C4Demolition(this); } public object Create(ActorInitializer init) { return new C4Demolition(this); }
} }
@@ -82,7 +84,7 @@ namespace OpenRA.Mods.RA
public string VoicePhraseForOrder(Actor self, Order order) public string VoicePhraseForOrder(Actor self, Order order)
{ {
return order.OrderString == "C4" ? "Attack" : null; return order.OrderString == "C4" ? info.Voice : null;
} }
class C4DemolitionOrderTargeter : UnitOrderTargeter class C4DemolitionOrderTargeter : UnitOrderTargeter

View File

@@ -23,6 +23,8 @@ namespace OpenRA.Mods.RA
[ActorReference] public readonly string Mine = "minv"; [ActorReference] public readonly string Mine = "minv";
[ActorReference] public readonly string[] RearmBuildings = { "fix" }; [ActorReference] public readonly string[] RearmBuildings = { "fix" };
public readonly string RearmSound = "minelay1.aud";
public readonly float MinefieldDepth = 1.5f; public readonly float MinefieldDepth = 1.5f;
public object Create(ActorInitializer init) { return new Minelayer(init.self); } public object Create(ActorInitializer init) { return new Minelayer(init.self); }
@@ -30,7 +32,7 @@ namespace OpenRA.Mods.RA
class Minelayer : IIssueOrder, IResolveOrder, IPostRenderSelection, ISync class Minelayer : IIssueOrder, IResolveOrder, IPostRenderSelection, ISync
{ {
/* [Sync] when sync can cope with arrays! */ /* TODO: [Sync] when sync can cope with arrays! */
public CPos[] Minefield = null; public CPos[] Minefield = null;
[Sync] CPos minefieldStart; [Sync] CPos minefieldStart;
Actor self; Actor self;

View File

@@ -1338,6 +1338,8 @@ Rules:
Percentage: 0 Percentage: 0
InvulnerabilityUpgrade@UNKILLABLE: InvulnerabilityUpgrade@UNKILLABLE:
RequiresUpgrade: unkillable RequiresUpgrade: unkillable
E7:
-Selectable:
Sequences: Sequences:

View File

@@ -250,6 +250,7 @@ E7:
Range: 6c0 Range: 6c0
C4Demolition: C4Demolition:
C4Delay: 45 C4Delay: 45
Voice: Demolish
Passenger: Passenger:
PipType: Red PipType: Red
Armament@PRIMARY: Armament@PRIMARY:
@@ -264,6 +265,8 @@ E7:
TakeCover: TakeCover:
RenderInfantry: RenderInfantry:
IdleAnimations: idle1,idle2 IdleAnimations: idle1,idle2
AnnounceOnBuild:
AnnounceOnKill:
MEDI: MEDI:
Inherits: ^Infantry Inherits: ^Infantry

View File

@@ -7,6 +7,7 @@ MINP:
Weapon: APMine Weapon: APMine
Health: Health:
HP: 100 HP: 100
NotifyAppliedDamage: false
Armor: Armor:
Type: Light Type: Light
RenderSimple: RenderSimple:
@@ -35,6 +36,7 @@ MINV:
Weapon: ATMine Weapon: ATMine
Health: Health:
HP: 100 HP: 100
NotifyAppliedDamage: false
Armor: Armor:
Type: Light Type: Light
RenderSimple: RenderSimple:

View File

@@ -46,11 +46,14 @@ MechanicVoice:
TanyaVoice: TanyaVoice:
Voices: Voices:
Select: yo1,yes1,yeah1 Select: yo1,yes1,yeah1
Move: rokroll1,onit1,cmon1 Move: onit1,cmon1,rokroll1
Attack: tuffguy1,bombit1,gotit1 Attack: tuffguy1,bombit1
Die: tandeth1 Die: tandeth1
Burned: tandeth1 Burned: tandeth1
Zapped: tandeth1 Zapped: tandeth1
Build: laugh1
Kill: gotit1,lefty1
Demolish: keepem1,tuffguy1
DogVoice: DogVoice:
Voices: Voices:

View File

@@ -1093,7 +1093,7 @@ DepthCharge:
SmudgeType: Crater SmudgeType: Crater
Warhead@3Eff: CreateEffect Warhead@3Eff: CreateEffect
Explosion: large_splash Explosion: large_splash
ImpactSound: splash9.aud ImpactSound: h2obomb2.aud
Warhead@4EffHit: CreateEffect Warhead@4EffHit: CreateEffect
Explosion: small_explosion Explosion: small_explosion
ImpactSound: kaboom15.aud ImpactSound: kaboom15.aud