diff --git a/OpenRA.Mods.RA2/Traits/Render/WithSupportPowerChargedOverlay.cs b/OpenRA.Mods.RA2/Traits/Render/WithSupportPowerChargedOverlay.cs new file mode 100644 index 00000000..8152f49d --- /dev/null +++ b/OpenRA.Mods.RA2/Traits/Render/WithSupportPowerChargedOverlay.cs @@ -0,0 +1,85 @@ +#region Copyright & License Information +/* + * Copyright (c) The OpenRA Developers and Contributors + * 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, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using OpenRA.Graphics; +using OpenRA.Mods.Common.Traits; +using OpenRA.Mods.Common.Traits.Render; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA2.Traits.Render +{ + [Desc("Displays an overlay when `" + nameof(SupportPower) + "` is fully charged.")] + public class WithSupportPowerChargedOverlayInfo : ConditionalTraitInfo, Requires, Requires + { + [SequenceReference] + [Desc("Sequence name to use")] + public readonly string ChargeSequence = "charged"; + + [SequenceReference] + [Desc("Sequence name to use")] + public readonly string LoopSequence = "loop"; + + [SequenceReference] + [Desc("Sequence name to use")] + public readonly string EndSequence = "end"; + + [Desc("Position relative to body")] + public readonly WVec Offset = WVec.Zero; + + [PaletteReference(nameof(IsPlayerPalette))] + [Desc("Custom palette name")] + public readonly string Palette = "player"; + + [Desc("Custom palette is a player palette BaseName")] + public readonly bool IsPlayerPalette = true; + + public override object Create(ActorInitializer init) { return new WithSupportPowerChargedOverlay(init.Self, this); } + } + + public class WithSupportPowerChargedOverlay : ConditionalTrait, INotifySupportPower + { + readonly Animation overlay; + readonly WithSupportPowerChargedOverlayInfo info; + bool visible; + + public WithSupportPowerChargedOverlay(Actor self, WithSupportPowerChargedOverlayInfo info) + : base(info) + { + this.info = info; + + var rs = self.Trait(); + var body = self.Trait(); + + overlay = new Animation(self.World, rs.GetImage(self)); + + var anim = new AnimationWithOffset(overlay, + () => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self.Orientation))), + () => IsTraitDisabled || !visible, + p => RenderUtils.ZOffsetFromCenter(self, p, 1)); + + rs.Add(anim, info.Palette, info.IsPlayerPalette); + } + + void INotifySupportPower.Charged(Actor self) + { + visible = true; + overlay.PlayThen(info.ChargeSequence, + () => overlay.PlayRepeating(info.LoopSequence)); + } + + void INotifySupportPower.Activated(Actor self) + { + if (!string.IsNullOrEmpty(info.EndSequence)) + overlay.PlayThen(info.EndSequence, + () => visible = false); + } + } +} diff --git a/mods/ra2/rules/allied-structures.yaml b/mods/ra2/rules/allied-structures.yaml index ad80f875..dddaaeda 100644 --- a/mods/ra2/rules/allied-structures.yaml +++ b/mods/ra2/rules/allied-structures.yaml @@ -978,6 +978,9 @@ gaweat: Description: Play God with deadly weather! IsometricSelectable: Height: 75 + WithIdleOverlay: + Sequence: idle-top + RequiresCondition: !build-incomplete Valued: Cost: 5000 Tooltip: @@ -1020,6 +1023,8 @@ gaweat: PauseOnCondition: lowpower Cursor: weatherstorm PaletteEffectType: LightningStorm + SupportPowerChargeBar: + WithSupportPowerChargedOverlay: SpawnSurvivors: DeathTypes: ExplosionDeath, BulletDeath Actors: e1, e1, e1, e1, e1 @@ -1053,6 +1058,9 @@ gacsph: WithIdleOverlay: Sequence: idle-dome RequiresCondition: !build-incomplete + WithIdleOverlay@FANS: + Sequence: idle-fans + RequiresCondition: !build-incomplete GrantConditionOnPowerState@LOWPOWER: Condition: lowpower ValidPowerStates: Low, Critical @@ -1061,6 +1069,7 @@ gacsph: Types: SpyInfiltrate Targetable: TargetTypes: Ground, C4, DetonateAttack, Structure, SpyInfiltrate + WithSupportPowerChargedOverlay: ChronoshiftPower@chronoshift: OrderName: Chronoshift Icon: chrono diff --git a/mods/ra2/rules/soviet-structures.yaml b/mods/ra2/rules/soviet-structures.yaml index f6d1ef21..08940157 100644 --- a/mods/ra2/rules/soviet-structures.yaml +++ b/mods/ra2/rules/soviet-structures.yaml @@ -857,6 +857,7 @@ nairon: Types: SpyInfiltrate Targetable: TargetTypes: Ground, C4, DetonateAttack, Structure, SpyInfiltrate + WithSupportPowerChargedOverlay: GrantConditionOnPowerState@LOWPOWER: Condition: lowpower ValidPowerStates: Low, Critical @@ -910,7 +911,6 @@ namisl: LaunchSpeechNotification: AtomBombLaunchDetected MissileWeapon: atomic MissilePalette: player - MissileDelay: 35 SpawnOffset: 0,0,-1c0 IsPlayerPalette: true DisplayTimerRelationships: Ally, Neutral, Enemy @@ -928,7 +928,10 @@ namisl: PauseOnCondition: lowpower SelectTargetSpeechNotification: SelectTarget MissileImage: atomic - WithSupportPowerActivationAnimation: + WithSupportPowerChargedOverlay: + WithSupportPowerActivationOverlay: + Sequence: smoke + Palette: effect50alpha SpawnSurvivors: DeathTypes: ExplosionDeath, BulletDeath Actors: e2, e2, e2, e2, e2, e2, e2 diff --git a/mods/ra2/sequences/allied-structures.yaml b/mods/ra2/sequences/allied-structures.yaml index df76bb11..6a33a841 100644 --- a/mods/ra2/sequences/allied-structures.yaml +++ b/mods/ra2/sequences/allied-structures.yaml @@ -413,8 +413,43 @@ gaweat: Defaults: Offset: 0, -45, 45 idle: ggweth + ShadowStart: 3 damaged-idle: ggweth + Start: 1 + ShadowStart: 4 + idle-top: ggweth_e + damaged-idle-top: ggweth_e + Start: 1 + charged: ggweth_f + Length: 12 + ShadowStart: 24 + Tick: 150 + damaged-charged: ggweth_f + Start: 12 + Length: 12 + ShadowStart: 36 + Tick: 150 + loop: ggweth_g + Length: 12 + ShadowStart: 24 + Tick: 150 + damaged-loop: ggweth_g + Start: 12 + Length: 12 + ShadowStart: 36 + Tick: 150 + end: ggweth_h + Length: 12 + ShadowStart: 24 + Tick: 150 + damaged-end: ggweth_h + Start: 12 + Length: 12 + ShadowStart: 36 + Tick: 150 make: guwethmk + Length: 25 + ShadowStart: 25 icon: wethicon gacsph: @@ -424,11 +459,37 @@ gacsph: idle: ggcsph ShadowStart: 3 damaged-idle: ggcsph + idle-fans: ggcsph_a + Length: 6 + damaged-idle-fans: ggcsph_a + Start: 6 + Length: 6 idle-dome: ggcsph_e ShadowStart: 2 damaged-idle-dome: ggcsph_e Start: 1 ShadowStart: 3 + charged: ggcsph_f + Length: 12 + ShadowStart: 24 + damaged-charged: ggcsph_f + Start: 12 + Length: 12 + ShadowStart: 36 + loop: ggcsph_g + Length: 6 + ShadowStart: 12 + damaged-loop: ggcsph_g + Start: 6 + Length: 6 + ShadowStart: 18 + end: ggcsph_h + Length: 15 + ShadowStart: 30 + damaged-end: ggcsph_h + Start: 15 + Length: 15 + ShadowStart: 45 dead: ggcsphdm # SHP broken & unused Length: 25 ShadowStart: 25 diff --git a/mods/ra2/sequences/soviet-structures.yaml b/mods/ra2/sequences/soviet-structures.yaml index ac961291..3c17b834 100644 --- a/mods/ra2/sequences/soviet-structures.yaml +++ b/mods/ra2/sequences/soviet-structures.yaml @@ -348,16 +348,38 @@ namisl: critical-idle: ngmisl_e Start: 1 ShadowStart: 3 - # TODO: ngmisl_f is actually the open sequence - active: ngmisl_f + charged: ngmisl_f Length: 16 ShadowStart: 32 + Tick: 150 + damaged-charged: ngmisl_f + Start: 16 + Length: 16 + ShadowStart: 48 + Tick: 120 + loop: ngmisl_g + ShadowStart: 2 + Tick: 120 + damaged-loop: ngmisl_g + Start: 1 + ShadowStart: 3 Tick: 120 - damaged-active: ngmisl_f - Start: 17 + end: ngmisl_h + Length: 16 + ShadowStart: 32 + Tick: 150 + damaged-end: ngmisl_h + Start: 16 Length: 16 ShadowStart: 48 Tick: 120 + smoke: nuketo + Length: * + Tick: 120 + Offset: 0, 0 + steam: nukestm # TODO: unused + Length: * + Tick: 120 make: ntmislmk UseTilesetCode: true Length: 26 @@ -375,13 +397,37 @@ nairon: Start: 11 Length: 11 ShadowStart: 33 - active: ngiron_h + + charged: ngiron_f + Length: 21 + damaged-charged: ngiron_f + Start: 21 + Length: 21 + loop: ngiron_f + Start: 10 + Length: 10 + damaged-loop: ngiron_f + Start: 31 + Length: 10 + end: ggcsph_h + Length: 12 + damaged-end: ggcsph_h + Start: 15 + Length: 15 + ShadowStart: 45 + end: ngiron_h Length: 12 ShadowStart: 24 - damaged-active: ngiron_h + damaged-end: ngiron_h Start: 12 Length: 12 ShadowStart: 36 + active: ngiron_f + Start: 10 + Length: 10 + damaged-active: ngiron_f + Start: 31 + Length: 10 make: ntironmk icon: ironicon