diff --git a/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj b/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj
index 9b3cc55813..e2a3587abf 100644
--- a/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj
+++ b/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj
@@ -81,7 +81,7 @@
-
+
diff --git a/OpenRA.Mods.Cnc/Traits/Render/RenderGunboat.cs b/OpenRA.Mods.Cnc/Traits/Render/RenderGunboat.cs
deleted file mode 100644
index d0eed55894..0000000000
--- a/OpenRA.Mods.Cnc/Traits/Render/RenderGunboat.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-#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.Linq;
-using OpenRA.Graphics;
-using OpenRA.Mods.Common.Traits;
-using OpenRA.Traits;
-
-namespace OpenRA.Mods.Cnc.Traits
-{
- class RenderGunboatInfo : RenderSpritesInfo, IQuantizeBodyOrientationInfo, Requires
- {
- [Desc("Turreted 'Turret' key to display")]
- public readonly string Turret = "primary";
-
- public readonly string LeftSequence = "left";
- public readonly string RightSequence = "right";
- public readonly string WakeLeftSequence = "wake-left";
- public readonly string WakeRightSequence = "wake-right";
-
- public override object Create(ActorInitializer init) { return new RenderGunboat(init, this); }
-
- public int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string race)
- {
- return 2;
- }
- }
-
- class RenderGunboat : RenderSprites, INotifyDamageStateChanged
- {
- Animation left, right;
-
- public RenderGunboat(ActorInitializer init, RenderGunboatInfo info)
- : base(init, info)
- {
- var name = GetImage(init.Self);
- var facing = init.Self.Trait();
- var turret = init.Self.TraitsImplementing()
- .First(t => t.Name == info.Turret);
-
- left = new Animation(init.World, name, () => turret.TurretFacing);
- left.Play(info.LeftSequence);
- Add(new AnimationWithOffset(left, null, () => facing.Facing > 128, 0));
-
- right = new Animation(init.World, name, () => turret.TurretFacing);
- right.Play(info.RightSequence);
- Add(new AnimationWithOffset(right, null, () => facing.Facing <= 128, 0));
-
- var leftWake = new Animation(init.World, name);
- leftWake.PlayRepeating(info.WakeLeftSequence);
- Add(new AnimationWithOffset(leftWake, null, () => facing.Facing > 128, -87));
-
- var rightWake = new Animation(init.World, name);
- rightWake.PlayRepeating(info.WakeRightSequence);
- Add(new AnimationWithOffset(rightWake, null, () => facing.Facing <= 128, -87));
- }
-
- public void DamageStateChanged(Actor self, AttackInfo e)
- {
- left.ReplaceAnim(NormalizeSequence(left, e.DamageState, left.CurrentSequence.Name));
- right.ReplaceAnim(NormalizeSequence(right, e.DamageState, right.CurrentSequence.Name));
- }
- }
-}
diff --git a/OpenRA.Mods.Cnc/Traits/Render/WithGunboatBody.cs b/OpenRA.Mods.Cnc/Traits/Render/WithGunboatBody.cs
new file mode 100644
index 0000000000..258a8f1d99
--- /dev/null
+++ b/OpenRA.Mods.Cnc/Traits/Render/WithGunboatBody.cs
@@ -0,0 +1,90 @@
+#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;
+using System.Linq;
+using OpenRA.Graphics;
+using OpenRA.Mods.Common.Traits;
+using OpenRA.Traits;
+
+namespace OpenRA.Mods.Cnc.Traits
+{
+ class WithGunboatBodyInfo : WithSpriteBodyInfo, Requires, Requires, Requires
+ {
+ [Desc("Turreted 'Turret' key to display")]
+ public readonly string Turret = "primary";
+
+ [SequenceReference] public readonly string LeftSequence = "left";
+ [SequenceReference] public readonly string RightSequence = "right";
+ [SequenceReference] public readonly string WakeLeftSequence = "wake-left";
+ [SequenceReference] public readonly string WakeRightSequence = "wake-right";
+
+ public override object Create(ActorInitializer init) { return new WithGunboatBody(init, this); }
+
+ public override int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string race)
+ {
+ return 2;
+ }
+ }
+
+ class WithGunboatBody : WithSpriteBody, ITick
+ {
+ readonly WithGunboatBodyInfo info;
+ readonly Animation wake;
+ readonly RenderSprites rs;
+ readonly IFacing facing;
+ readonly Turreted turret;
+
+ static Func MakeTurretFacingFunc(Actor self)
+ {
+ // Turret artwork is baked into the sprite, so only the first turret makes sense.
+ var turreted = self.TraitsImplementing().FirstOrDefault();
+ return () => turreted.TurretFacing;
+ }
+
+ public WithGunboatBody(ActorInitializer init, WithGunboatBodyInfo info)
+ : base(init, info, MakeTurretFacingFunc(init.Self))
+ {
+ this.info = info;
+ rs = init.Self.Trait();
+ facing = init.Self.Trait();
+ var name = rs.GetImage(init.Self);
+ turret = init.Self.TraitsImplementing()
+ .First(t => t.Name == info.Turret);
+ turret.QuantizedFacings = DefaultAnimation.CurrentSequence.Facings;
+
+ wake = new Animation(init.World, name);
+ wake.PlayRepeating(info.WakeLeftSequence);
+ rs.Add(new AnimationWithOffset(wake, null, null, -87));
+ }
+
+ public void Tick(Actor self)
+ {
+ if (facing.Facing <= 128)
+ {
+ var left = NormalizeSequence(self, info.LeftSequence);
+ if (DefaultAnimation.CurrentSequence.Name != left)
+ DefaultAnimation.ReplaceAnim(left);
+
+ if (wake.CurrentSequence.Name != info.WakeLeftSequence)
+ wake.ReplaceAnim(info.WakeLeftSequence);
+ }
+ else
+ {
+ var right = NormalizeSequence(self, info.RightSequence);
+ if (DefaultAnimation.CurrentSequence.Name != right)
+ DefaultAnimation.ReplaceAnim(right);
+
+ if (wake.CurrentSequence.Name != info.WakeRightSequence)
+ wake.ReplaceAnim(info.WakeRightSequence);
+ }
+ }
+ }
+}
diff --git a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs
index 26d17e3c38..e23f86f98e 100644
--- a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs
+++ b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs
@@ -1607,6 +1607,36 @@ namespace OpenRA.Mods.Common.UtilityCommands
}
}
+ if (engineVersion < 20150715)
+ {
+ // Replaced RenderGunboat with RenderSprites + WithGunboatBody.
+ if (depth == 0)
+ {
+ var childKeysGunboat = new[] { "Turret", "LeftSequence", "RightSequence", "WakeLeftSequence", "WakeRightSequence" };
+
+ var rgb = node.Value.Nodes.FirstOrDefault(n => n.Key.StartsWith("RenderGunboat"));
+ if (rgb != null)
+ {
+ rgb.Key = "WithGunboatBody";
+
+ var rsNodes = rgb.Value.Nodes.Where(n => !childKeysGunboat.Contains(n.Key)).ToList();
+ if (rsNodes.Any())
+ node.Value.Nodes.Add(new MiniYamlNode("RenderSprites", new MiniYaml("", rsNodes)));
+ else
+ node.Value.Nodes.Add(new MiniYamlNode("RenderSprites", ""));
+
+ node.Value.Nodes.Add(new MiniYamlNode("AutoSelectionSize", ""));
+
+ rgb.Value.Nodes.RemoveAll(n => rsNodes.Contains(n));
+ rgb.Value.Nodes.Add(new MiniYamlNode("Sequence", "left"));
+ }
+
+ var rrgb = node.Value.Nodes.FirstOrDefault(n => n.Key.StartsWith("-RenderGunboat"));
+ if (rrgb != null)
+ rrgb.Key = "-WithGunboatBody";
+ }
+ }
+
UpgradeActorRules(engineVersion, ref node.Value.Nodes, node, depth + 1);
}
}
diff --git a/mods/cnc/rules/ships.yaml b/mods/cnc/rules/ships.yaml
index bb26dd8d6e..b7a444e399 100644
--- a/mods/cnc/rules/ships.yaml
+++ b/mods/cnc/rules/ships.yaml
@@ -22,7 +22,9 @@ BOAT:
Weapon: BoatMissile
LocalOffset: 85,-85,0, 85,85,0
AttackTurreted:
- RenderGunboat:
+ RenderSprites:
+ WithGunboatBody:
+ Sequence: left # Just a work-around to avoid crash
Selectable:
Bounds: 42,24
AutoTarget: