diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index 83e79644b5..e0923b37cc 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -382,6 +382,7 @@ + diff --git a/OpenRA.Mods.Common/Traits/Attack/AttackCharge.cs b/OpenRA.Mods.Common/Traits/Attack/AttackCharge.cs index 756bb26e24..e93cf3e35b 100644 --- a/OpenRA.Mods.Common/Traits/Attack/AttackCharge.cs +++ b/OpenRA.Mods.Common/Traits/Attack/AttackCharge.cs @@ -29,6 +29,9 @@ namespace OpenRA.Mods.Common.Traits [Desc("Delay between charge attacks (in ticks).")] public readonly int ChargeDelay = 3; + [Desc("Sound to play when actor charges.")] + public readonly string ChargeAudio = null; + public override object Create(ActorInitializer init) { return new AttackCharge(init.Self, this); } } @@ -98,7 +101,11 @@ namespace OpenRA.Mods.Common.Traits if (attack.charges == 0) return this; - self.Trait().PlayCharge(self); + foreach (var notify in self.TraitsImplementing()) + notify.Charging(self, target); + + if (!string.IsNullOrEmpty(attack.info.ChargeAudio)) + Sound.Play(attack.info.ChargeAudio, self.CenterPosition); return Util.SequenceActivities(new Wait(attack.info.InitialChargeDelay), new ChargeFire(attack, target), this); } diff --git a/OpenRA.Mods.Common/Traits/Render/RenderBuildingCharge.cs b/OpenRA.Mods.Common/Traits/Render/RenderBuildingCharge.cs index 451bda2e59..932de424fc 100644 --- a/OpenRA.Mods.Common/Traits/Render/RenderBuildingCharge.cs +++ b/OpenRA.Mods.Common/Traits/Render/RenderBuildingCharge.cs @@ -8,19 +8,20 @@ */ #endregion +using OpenRA.Traits; + namespace OpenRA.Mods.Common.Traits { [Desc("Used for tesla coil and obelisk.")] public class RenderBuildingChargeInfo : RenderBuildingInfo { - [Desc("Sound to play when building charges.")] - public readonly string ChargeAudio = null; [Desc("Sequence to use for building charge animation.")] public readonly string ChargeSequence = "active"; + public override object Create(ActorInitializer init) { return new RenderBuildingCharge(init, this); } } - public class RenderBuildingCharge : RenderBuilding + public class RenderBuildingCharge : RenderBuilding, INotifyCharging { RenderBuildingChargeInfo info; @@ -30,9 +31,8 @@ namespace OpenRA.Mods.Common.Traits this.info = info; } - public void PlayCharge(Actor self) + public void Charging(Actor self, Target target) { - Sound.Play(info.ChargeAudio, self.CenterPosition); PlayCustomAnim(self, info.ChargeSequence); } } diff --git a/OpenRA.Mods.Common/Traits/Render/WithChargeOverlay.cs b/OpenRA.Mods.Common/Traits/Render/WithChargeOverlay.cs new file mode 100644 index 0000000000..a06554aebf --- /dev/null +++ b/OpenRA.Mods.Common/Traits/Render/WithChargeOverlay.cs @@ -0,0 +1,68 @@ +#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 OpenRA.Graphics; +using OpenRA.Traits; + +namespace OpenRA.Mods.Common.Traits +{ + [Desc("Rendered together with AttackCharge.")] + public class WithChargeOverlayInfo : ITraitInfo, Requires + { + [Desc("Sequence name to use")] + public readonly string Sequence = "active"; + + [Desc("Custom palette name")] + public readonly string Palette = null; + + [Desc("Custom palette is a player palette BaseName")] + public readonly bool IsPlayerPalette = false; + + public object Create(ActorInitializer init) { return new WithChargeOverlay(init, this); } + } + + public class WithChargeOverlay : INotifyCharging, INotifyDamageStateChanged, INotifySold + { + readonly Animation overlay; + readonly RenderSprites renderSprites; + readonly WithChargeOverlayInfo info; + + bool charging; + + public WithChargeOverlay(ActorInitializer init, WithChargeOverlayInfo info) + { + this.info = info; + + renderSprites = init.Self.Trait(); + + overlay = new Animation(init.World, renderSprites.GetImage(init.Self)); + + renderSprites.Add(new AnimationWithOffset(overlay, null, () => !charging), + info.Palette, info.IsPlayerPalette); + } + + public void Charging(Actor self, Target target) + { + charging = true; + overlay.PlayThen(RenderSprites.NormalizeSequence(overlay, self.GetDamageState(), info.Sequence), () => charging = false); + } + + public void DamageStateChanged(Actor self, AttackInfo e) + { + overlay.ReplaceAnim(RenderSprites.NormalizeSequence(overlay, e.DamageState, info.Sequence)); + } + + public void Sold(Actor self) { } + public void Selling(Actor self) + { + charging = false; + } + } +} \ No newline at end of file diff --git a/OpenRA.Mods.Common/Traits/Sound/DeathSounds.cs b/OpenRA.Mods.Common/Traits/Sound/DeathSounds.cs index 0e51472955..0f150d53d3 100644 --- a/OpenRA.Mods.Common/Traits/Sound/DeathSounds.cs +++ b/OpenRA.Mods.Common/Traits/Sound/DeathSounds.cs @@ -30,7 +30,7 @@ namespace OpenRA.Mods.Common.Traits public class DeathSounds : INotifyKilled { - DeathSoundsInfo info; + readonly DeathSoundsInfo info; public DeathSounds(DeathSoundsInfo info) { this.info = info; } diff --git a/OpenRA.Mods.Common/TraitsInterfaces.cs b/OpenRA.Mods.Common/TraitsInterfaces.cs index 88f2d762d1..3918b7f151 100644 --- a/OpenRA.Mods.Common/TraitsInterfaces.cs +++ b/OpenRA.Mods.Common/TraitsInterfaces.cs @@ -36,6 +36,7 @@ namespace OpenRA.Mods.Common.Traits } public interface INotifyAttack { void Attacking(Actor self, Target target, Armament a, Barrel barrel); } + public interface INotifyCharging { void Charging(Actor self, Target target); } public interface INotifyChat { bool OnChat(string from, string message); } public interface INotifyParachuteLanded { void OnLanded(); } public interface IRenderActorPreviewInfo { IEnumerable RenderPreview(ActorPreviewInitializer init); } diff --git a/mods/cnc/rules/structures.yaml b/mods/cnc/rules/structures.yaml index e55a1b73a7..a5a48706e3 100644 --- a/mods/cnc/rules/structures.yaml +++ b/mods/cnc/rules/structures.yaml @@ -721,12 +721,12 @@ OBLI: Bib: HasMinibib: Yes RenderBuildingCharge: - ChargeAudio: obelpowr.aud Armament: Weapon: Laser LocalOffset: 0,0,725 FireDelay: 0 AttackCharge: + ChargeAudio: obelpowr.aud ReloadTime: 40 InitialChargeDelay: 50 AutoTarget: diff --git a/mods/ra/rules/structures.yaml b/mods/ra/rules/structures.yaml index 4d535f0c69..d2a0fad564 100644 --- a/mods/ra/rules/structures.yaml +++ b/mods/ra/rules/structures.yaml @@ -387,11 +387,11 @@ TSLA: Bib: HasMinibib: Yes RenderBuildingCharge: - ChargeAudio: tslachg2.aud Armament: Weapon: TeslaZap LocalOffset: 0,0,427 AttackCharge: + ChargeAudio: tslachg2.aud MaxCharges: 3 ReloadTime: 120 AutoTarget: diff --git a/mods/ts/rules/nod-support.yaml b/mods/ts/rules/nod-support.yaml index 4fbb8a9613..76198480ec 100644 --- a/mods/ts/rules/nod-support.yaml +++ b/mods/ts/rules/nod-support.yaml @@ -88,16 +88,18 @@ NAOBEL: Type: Heavy RevealsShroud: Range: 8c0 - RenderBuildingCharge: - ChargeAudio: obelpowr.aud Armament: Weapon: LaserFire - LocalOffset: 0,0,725 + LocalOffset: 1400,200,1250 AttackCharge: + ChargeAudio: obelpowr.aud ReloadTime: 50 InitialChargeDelay: 50 + WithChargeOverlay: + Sequence: active + Palette: player + IsPlayerPalette: true AutoTarget: - -RenderBuilding: RenderRangeCircle: RenderDetectionCircle: DetectCloaked: diff --git a/mods/ts/sequences/structures.yaml b/mods/ts/sequences/structures.yaml index f56b460f77..8d54d2e583 100644 --- a/mods/ts/sequences/structures.yaml +++ b/mods/ts/sequences/structures.yaml @@ -582,11 +582,9 @@ naobel: Start: 2 ShadowStart: 5 Tick: 400 - active: naobel #placeholder until Charge supports overlays - ShadowStart: 3 -# active: ntobel_b -# Length: 12 -# Tick: 240 + active: ntobel_b + Length: 12 + Tick: 200 idle-lights: ntobel_a Length: 12 Tick: 80