diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index c617cbea48..49d839cb9a 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -405,6 +405,7 @@ + diff --git a/OpenRA.Mods.Common/Traits/Render/WithProductionDoorOverlay.cs b/OpenRA.Mods.Common/Traits/Render/WithProductionDoorOverlay.cs new file mode 100644 index 0000000000..85f95d526c --- /dev/null +++ b/OpenRA.Mods.Common/Traits/Render/WithProductionDoorOverlay.cs @@ -0,0 +1,91 @@ +#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.Graphics; +using OpenRA.Mods.Common.Graphics; +using OpenRA.Mods.Common.Traits; +using OpenRA.Traits; + +namespace OpenRA.Mods.TS.Traits +{ + [Desc("Play an animation when a unit exits or blocks the exit after production finished.")] + class WithProductionDoorOverlayInfo : ITraitInfo, IRenderActorPreviewSpritesInfo, Requires, Requires, Requires + { + public readonly string Sequence = "idle-door"; + public readonly string BuildSequence = "build-door"; + + public object Create(ActorInitializer init) { return new WithProductionDoorOverlay(init.Self, this); } + + public IEnumerable RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p) + { + var anim = new Animation(init.World, image, () => 0); + anim.PlayRepeating(Sequence); + + var bi = init.Actor.Traits.Get(); + var offset = FootprintUtils.CenterOffset(init.World, bi).Y + 512; // Additional 512 units move from center -> top of cell + yield return new SpriteActorPreview(anim, WVec.Zero, offset, p, rs.Scale); + } + } + + class WithProductionDoorOverlay : INotifyBuildComplete, ITick, INotifyProduction, INotifySold, INotifyDamageStateChanged + { + readonly WithProductionDoorOverlayInfo info; + readonly RenderSprites renderSprites; + readonly Animation door; + + bool isOpen; + CPos openExit; + bool buildComplete; + + public WithProductionDoorOverlay(Actor self, WithProductionDoorOverlayInfo info) + { + this.info = info; + renderSprites = self.Trait(); + door = new Animation(self.World, renderSprites.GetImage(self)); + door.Play(RenderSprites.NormalizeSequence(door, self.GetDamageState(), info.Sequence)); + + var buildingInfo = self.Info.Traits.Get(); + + var offset = FootprintUtils.CenterOffset(self.World, buildingInfo).Y + 512; + renderSprites.Add("door_overlay_{0}".F(info.Sequence), new AnimationWithOffset(door, null, () => !buildComplete, offset)); + } + + public void BuildingComplete(Actor self) + { + buildComplete = true; + } + + public void Tick(Actor self) + { + if (isOpen && !self.World.ActorMap.GetUnitsAt(openExit).Any(a => a != self)) + { + isOpen = false; + door.PlayBackwardsThen(RenderSprites.NormalizeSequence(door, self.GetDamageState(), info.BuildSequence), + () => door.Play(RenderSprites.NormalizeSequence(door, self.GetDamageState(), info.Sequence))); + } + } + + public void DamageStateChanged(Actor self, AttackInfo e) + { + if (door.CurrentSequence != null) + door.ReplaceAnim(RenderSprites.NormalizeSequence(door, e.DamageState, door.CurrentSequence.Name)); + } + + public void UnitProduced(Actor self, Actor other, CPos exit) + { + door.PlayThen(RenderSprites.NormalizeSequence(door, self.GetDamageState(), info.BuildSequence), () => { isOpen = true; openExit = exit; }); + } + + public void Selling(Actor self) { buildComplete = false; } + public void Sold(Actor self) { } + } +} diff --git a/mods/ts/rules/gdi-structures.yaml b/mods/ts/rules/gdi-structures.yaml index 6ecf481663..a3138fcf3e 100644 --- a/mods/ts/rules/gdi-structures.yaml +++ b/mods/ts/rules/gdi-structures.yaml @@ -123,8 +123,6 @@ GAWEAP: HP: 1000 RevealsShroud: Range: 4c0 - -RenderBuilding: - RenderBuildingWarFactory: RallyPoint: RallyPoint: 6,1 Exit@1: @@ -134,6 +132,9 @@ GAWEAP: Produces: Vehicle PrimaryBuilding: ProductionBar: + WithIdleOverlay@ROOF: + Sequence: idle-roof + WithProductionDoorOverlay@DOOR: WithProductionOverlay@WHITELIGHTS: Sequence: production-lights-white WithProductionOverlay@REDLIGHTS: diff --git a/mods/ts/rules/nod-structures.yaml b/mods/ts/rules/nod-structures.yaml index 15118349d8..71aa3ad2e4 100644 --- a/mods/ts/rules/nod-structures.yaml +++ b/mods/ts/rules/nod-structures.yaml @@ -130,8 +130,6 @@ NAWEAP: HP: 1000 RevealsShroud: Range: 4c0 - -RenderBuilding: - RenderBuildingWarFactory: RallyPoint: RallyPoint: 6,1 Exit@1: @@ -141,6 +139,9 @@ NAWEAP: Produces: Vehicle PrimaryBuilding: ProductionBar: + WithIdleOverlay@ROOF: + Sequence: idle-roof + WithProductionDoorOverlay@DOOR: WithProductionOverlay@LIGHTS: Sequence: production-lights WithIdleOverlay@BIB: diff --git a/mods/ts/sequences/structures.yaml b/mods/ts/sequences/structures.yaml index 7deb008378..0ba1da08d2 100644 --- a/mods/ts/sequences/structures.yaml +++ b/mods/ts/sequences/structures.yaml @@ -136,12 +136,17 @@ gaweap: Defaults: Offset: -12, -42 UseTilesetCode: true - idle: - ShadowStart: 3 - damaged-idle: + idle: gtweap_1 + ShadowStart: 2 + damaged-idle: gtweap_1 Start: 1 - ShadowStart: 4 - dead: + ShadowStart: 3 + idle-roof: gtweap_2 + ShadowStart: 2 + damaged-idle-roof: gtweap_2 + Start: 1 + ShadowStart: 3 + dead: gtweap Start: 2 ShadowStart: 5 Tick: 400 @@ -171,14 +176,14 @@ gaweap: Length: 4 Tick: 80 ZOffset: 2048 - build-top: gtweap_d + build-door: gtweap_d Length: 9 ShadowStart: 9 - damaged-build-top: gtweap_d + damaged-build-door: gtweap_d Length: 9 ShadowStart: 9 - idle-top: gtweap_2 - damaged-idle-top: gtweap_2 + idle-door: gtweap_d + damaged-idle-door: gtweap_d Start: 1 make: gtweapmk Length: 20 @@ -195,7 +200,6 @@ gaweap: icon: weapicon Offset: 0, 0 UseTilesetCode: false -# TODO: gtweap_1 & gtweap_a & gtweap_b & gtweap_c are unused napowr: Defaults: @@ -289,12 +293,17 @@ naweap: Defaults: Offset: -12, -42 UseTilesetCode: true - idle: - ShadowStart: 3 - damaged-idle: + idle: ntweap_1 + ShadowStart: 2 + damaged-idle: ntweap_1 Start: 1 - ShadowStart: 4 - dead: + ShadowStart: 3 + idle-roof: ntweap_2 + ShadowStart: 2 + damaged-idle-roof: ntweap_2 + Start: 1 + ShadowStart: 3 + dead: ntweap Start: 2 ShadowStart: 5 Tick: 400 @@ -307,15 +316,15 @@ naweap: Length: 16 Tick: 100 ZOffset: 2048 - build-top: ntweap_b + build-door: ntweap_b Length: 10 ShadowStart: 10 - damaged-build-top: ntweap_b + damaged-build-door: ntweap_b Start: 10 Length: 10 ShadowStart: 20 - idle-top: ntweap_2 - damaged-idle-top: ntweap_2 + idle-door: ntweap_b + damaged-idle-door: ntweap_b Start: 1 make: ntweapmk Length: 22 @@ -329,7 +338,6 @@ naweap: icon: nwepicon Offset: 0, 0 UseTilesetCode: false -# TODO: ntweap_1 & ntweap_b & ntweap_c are unused naradr: Defaults: