Merge pull request #8553 from reaperrr/rem-renderunit

Removed RenderHarvester, RenderLandingCraft and RenderUnit
This commit is contained in:
Pavel Penev
2015-07-04 23:23:06 +03:00
24 changed files with 382 additions and 239 deletions

View File

@@ -15,25 +15,37 @@ namespace OpenRA.Mods.Common.Activities
{
public class SpriteHarvesterDockSequence : HarvesterDockSequence
{
readonly RenderUnit ru;
readonly WithSpriteBody wsb;
readonly WithDockingAnimation wda;
public SpriteHarvesterDockSequence(Actor self, Actor refinery, int dockAngle, bool isDragRequired, WVec dragOffset, int dragLength)
: base(self, refinery, dockAngle, isDragRequired, dragOffset, dragLength)
{
ru = self.Trait<RenderUnit>();
wsb = self.Trait<WithSpriteBody>();
wda = self.Trait<WithDockingAnimation>();
}
public override Activity OnStateDock(Actor self)
{
ru.PlayCustomAnimation(self, "dock", () => ru.PlayCustomAnimationRepeating(self, "dock-loop"));
foreach (var trait in self.TraitsImplementing<INotifyHarvesterAction>())
trait.Docked();
wsb.PlayCustomAnimation(self, wda.Info.DockSequence, () => wsb.PlayCustomAnimationRepeating(self, wda.Info.DockLoopSequence));
dockingState = State.Loop;
return this;
}
public override Activity OnStateUndock(Actor self)
{
ru.PlayCustomAnimationBackwards(self, "dock", () => dockingState = State.Complete);
wsb.PlayCustomAnimationBackwards(self, wda.Info.DockSequence,
() =>
{
dockingState = State.Complete;
foreach (var trait in self.TraitsImplementing<INotifyHarvesterAction>())
trait.Undocked();
});
dockingState = State.Wait;
return this;
}
}

View File

@@ -397,11 +397,9 @@
<Compile Include="Traits\Render\RenderBuildingCharge.cs" />
<Compile Include="Traits\Render\RenderBuildingTurreted.cs" />
<Compile Include="Traits\Render\RenderEditorOnly.cs" />
<Compile Include="Traits\Render\RenderHarvester.cs" />
<Compile Include="Traits\Render\RenderNameTag.cs" />
<Compile Include="Traits\Render\RenderSimple.cs" />
<Compile Include="Traits\Render\RenderSprites.cs" />
<Compile Include="Traits\Render\RenderUnit.cs" />
<Compile Include="Traits\Render\RenderBuildingSilo.cs" />
<Compile Include="Traits\Render\RenderBuildingWall.cs" />
<Compile Include="Traits\Render\RenderDetectionCircle.cs" />
@@ -421,8 +419,10 @@
<Compile Include="Traits\Render\WithCrateBody.cs" />
<Compile Include="Traits\Render\WithDeathAnimation.cs" />
<Compile Include="Traits\Render\WithDecoration.cs" />
<Compile Include="Traits\Render\WithDockingAnimation.cs" />
<Compile Include="Traits\Render\WithDockingOverlay.cs" />
<Compile Include="Traits\Render\WithHarvestAnimation.cs" />
<Compile Include="Traits\Render\WithHarvestOverlay.cs" />
<Compile Include="Traits\Render\WithIdleOverlay.cs" />
<Compile Include="Traits\Render\WithMuzzleFlash.cs" />
<Compile Include="Traits\Render\WithRangeCircle.cs" />

View File

@@ -1,63 +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 OpenRA.Activities;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
class RenderHarvesterInfo : RenderUnitInfo, Requires<HarvesterInfo>
{
public readonly string[] ImagesByFullness = { "harv" };
[SequenceReference("ImagesByFullness")] public readonly string HarvestSequence = "harvest";
public override object Create(ActorInitializer init) { return new RenderHarvester(init, this); }
}
class RenderHarvester : RenderUnit, INotifyHarvesterAction
{
Harvester harv;
RenderHarvesterInfo info;
public RenderHarvester(ActorInitializer init, RenderHarvesterInfo info)
: base(init, info)
{
this.info = info;
harv = init.Self.Trait<Harvester>();
// HACK: Force images to be loaded up-front
foreach (var image in info.ImagesByFullness)
new Animation(init.World, image);
}
public override void Tick(Actor self)
{
var desiredState = harv.Fullness * (info.ImagesByFullness.Length - 1) / 100;
var desiredImage = info.ImagesByFullness[desiredState];
if (DefaultAnimation.Name != desiredImage)
DefaultAnimation.ChangeImage(desiredImage, info.Sequence);
base.Tick(self);
}
public void Harvested(Actor self, ResourceType resource)
{
if (DefaultAnimation.CurrentSequence.Name != info.HarvestSequence)
PlayCustomAnim(self, info.HarvestSequence);
}
public void MovingToResources(Actor self, CPos targetCell, Activity next) { }
public void MovingToRefinery(Actor self, CPos targetCell, Activity next) { }
public void MovementCancelled(Actor self) { }
}
}

View File

@@ -1,50 +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;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Render trait for non-animated actors that have sprites facing into each direction.",
"Deprecated. This will soon be removed, use RenderSprites + WithFacingSpriteBody instead.")]
public class RenderUnitInfo : RenderSimpleInfo, Requires<IFacingInfo>
{
public override object Create(ActorInitializer init) { return new RenderUnit(init, this); }
}
public class RenderUnit : RenderSimple, ISpriteBody
{
readonly RenderUnitInfo info;
public RenderUnit(ActorInitializer init, RenderUnitInfo info)
: base(init, info)
{
this.info = info;
}
public void PlayCustomAnimation(Actor self, string newAnimation, Action after)
{
DefaultAnimation.PlayThen(newAnimation, () => { DefaultAnimation.Play(info.Sequence); if (after != null) after(); });
}
public void PlayCustomAnimationRepeating(Actor self, string name)
{
DefaultAnimation.PlayThen(name,
() => PlayCustomAnimationRepeating(self, name));
}
public void PlayCustomAnimationBackwards(Actor self, string name, Action after)
{
DefaultAnimation.PlayBackwardsThen(name,
() => { DefaultAnimation.PlayRepeating(info.Sequence); if (after != null) after(); });
}
}
}

View File

@@ -9,10 +9,9 @@
#endregion
using System.Linq;
using OpenRA.Mods.Common.Traits;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Traits
namespace OpenRA.Mods.Common.Traits
{
public class WithAttackAnimationInfo : ITraitInfo, Requires<WithFacingSpriteBodyInfo>, Requires<ArmamentInfo>, Requires<AttackBaseInfo>
{

View File

@@ -0,0 +1,35 @@
#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.Traits;
namespace OpenRA.Mods.Common.Traits
{
public class WithDockingAnimationInfo : ITraitInfo, Requires<WithSpriteBodyInfo>, Requires<HarvesterInfo>
{
[Desc("Displayed when docking to refinery.")]
[SequenceReference] public readonly string DockSequence = "dock";
[Desc("Looped while unloading at refinery.")]
[SequenceReference] public readonly string DockLoopSequence = "dock-loop";
public object Create(ActorInitializer init) { return new WithDockingAnimation(init, this); }
}
public class WithDockingAnimation
{
public readonly WithDockingAnimationInfo Info;
public WithDockingAnimation(ActorInitializer init, WithDockingAnimationInfo info)
{
Info = info;
}
}
}

View File

@@ -9,64 +9,79 @@
#endregion
using OpenRA.Activities;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Displays an overlay whenever resources are harvested by the actor.")]
class WithHarvestAnimationInfo : ITraitInfo, Requires<RenderSpritesInfo>, Requires<IBodyOrientationInfo>
public class WithHarvestAnimationInfo : ITraitInfo, Requires<WithSpriteBodyInfo>, Requires<HarvesterInfo>
{
[Desc("Sequence name to use")]
[SequenceReference] public readonly string Sequence = "harvest";
[Desc("Prefix added to idle and harvest sequences depending on fullness of harvester.")]
[SequenceReference(null, true)] public readonly string[] PrefixByFullness = { "" };
[Desc("Position relative to body")]
public readonly WVec Offset = WVec.Zero;
[Desc("Displayed while harvesting.")]
[SequenceReference] public readonly string HarvestSequence = "harvest";
public readonly string Palette = "effect";
public object Create(ActorInitializer init) { return new WithHarvestAnimation(init.Self, this); }
public object Create(ActorInitializer init) { return new WithHarvestAnimation(init, this); }
}
class WithHarvestAnimation : INotifyHarvesterAction
public class WithHarvestAnimation : ITick, INotifyHarvesterAction
{
WithHarvestAnimationInfo info;
Animation anim;
bool visible;
public readonly WithHarvestAnimationInfo Info;
readonly WithSpriteBody wsb;
readonly Harvester harv;
public WithHarvestAnimation(Actor self, WithHarvestAnimationInfo info)
public bool IsModifying;
public WithHarvestAnimation(ActorInitializer init, WithHarvestAnimationInfo info)
{
this.info = info;
var rs = self.Trait<RenderSprites>();
var body = self.Trait<IBodyOrientation>();
Info = info;
harv = init.Self.Trait<Harvester>();
wsb = init.Self.Trait<WithSpriteBody>();
}
anim = new Animation(self.World, rs.GetImage(self), RenderSprites.MakeFacingFunc(self));
anim.IsDecoration = true;
anim.Play(info.Sequence);
rs.Add(new AnimationWithOffset(anim,
() => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))),
() => !visible,
() => false,
p => ZOffsetFromCenter(self, p, 0)), info.Palette);
protected virtual string NormalizeHarvesterSequence(Actor self, string baseSequence)
{
var desiredState = harv.Fullness * (Info.PrefixByFullness.Length - 1) / 100;
var desiredPrefix = Info.PrefixByFullness[desiredState];
if (wsb.DefaultAnimation.HasSequence(desiredPrefix + baseSequence))
return desiredPrefix + baseSequence;
else
return baseSequence;
}
public void Tick(Actor self)
{
if (!IsModifying && !string.IsNullOrEmpty(wsb.Info.Sequence) && wsb.DefaultAnimation.HasSequence(NormalizeHarvesterSequence(self, wsb.Info.Sequence)))
{
if (wsb.DefaultAnimation.CurrentSequence.Name != NormalizeHarvesterSequence(self, wsb.Info.Sequence))
wsb.DefaultAnimation.ReplaceAnim(NormalizeHarvesterSequence(self, wsb.Info.Sequence));
}
}
public void Harvested(Actor self, ResourceType resource)
{
if (visible)
return;
if (!IsModifying && !string.IsNullOrEmpty(Info.HarvestSequence) && wsb.DefaultAnimation.HasSequence(NormalizeHarvesterSequence(self, Info.HarvestSequence)))
{
IsModifying = true;
wsb.PlayCustomAnimation(self, NormalizeHarvesterSequence(self, Info.HarvestSequence), () => IsModifying = false);
}
}
visible = true;
anim.PlayThen(info.Sequence, () => visible = false);
// If IsModifying isn't set to true, the docking animation
// will be overridden by the WithHarvestAnimation fullness modifier.
public void Docked()
{
IsModifying = true;
}
public void Undocked()
{
IsModifying = false;
}
public void MovingToResources(Actor self, CPos targetCell, Activity next) { }
public void MovingToRefinery(Actor self, CPos targetCell, Activity next) { }
public void MovementCancelled(Actor self) { }
public static int ZOffsetFromCenter(Actor self, WPos pos, int offset)
{
var delta = self.CenterPosition - pos;
return delta.Y + delta.Z + offset;
}
}
}

View File

@@ -0,0 +1,74 @@
#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.Activities;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Displays an overlay whenever resources are harvested by the actor.")]
class WithHarvestOverlayInfo : ITraitInfo, Requires<RenderSpritesInfo>, Requires<IBodyOrientationInfo>
{
[Desc("Sequence name to use")]
[SequenceReference] public readonly string Sequence = "harvest";
[Desc("Position relative to body")]
public readonly WVec Offset = WVec.Zero;
public readonly string Palette = "effect";
public object Create(ActorInitializer init) { return new WithHarvestOverlay(init.Self, this); }
}
class WithHarvestOverlay : INotifyHarvesterAction
{
WithHarvestOverlayInfo info;
Animation anim;
bool visible;
public WithHarvestOverlay(Actor self, WithHarvestOverlayInfo info)
{
this.info = info;
var rs = self.Trait<RenderSprites>();
var body = self.Trait<IBodyOrientation>();
anim = new Animation(self.World, rs.GetImage(self), RenderSprites.MakeFacingFunc(self));
anim.IsDecoration = true;
anim.Play(info.Sequence);
rs.Add(new AnimationWithOffset(anim,
() => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))),
() => !visible,
() => false,
p => ZOffsetFromCenter(self, p, 0)), info.Palette);
}
public void Harvested(Actor self, ResourceType resource)
{
if (visible)
return;
visible = true;
anim.PlayThen(info.Sequence, () => visible = false);
}
public void MovingToResources(Actor self, CPos targetCell, Activity next) { }
public void MovingToRefinery(Actor self, CPos targetCell, Activity next) { }
public void MovementCancelled(Actor self) { }
public void Docked() { }
public void Undocked() { }
public static int ZOffsetFromCenter(Actor self, WPos pos, int offset)
{
var delta = self.CenterPosition - pos;
return delta.Y + delta.Z + offset;
}
}
}

View File

@@ -58,6 +58,8 @@ namespace OpenRA.Mods.Common.Traits
void MovingToRefinery(Actor self, CPos targetCell, Activity next);
void MovementCancelled(Actor self);
void Harvested(Actor self, ResourceType resource);
void Docked();
void Undocked();
}
public interface ITechTreePrerequisite

View File

@@ -1221,6 +1221,136 @@ namespace OpenRA.Mods.Common.UtilityCommands
}
}
// Removed RenderUnit
if (engineVersion < 20150704)
{
// Renamed WithHarvestAnimation to WithHarvestOverlay
if (node.Key == "WithHarvestAnimation")
node.Key = "WithHarvestOverlay";
// Replaced RenderLandingCraft with WithFacingSpriteBody + WithLandingCraftAnimation.
// Note: These rules are set up to do approximately the right thing for maps, but
// mods might need additional manual tweaks. This is the best we can do without having
// much smarter rules parsing, because we currently can't reason about inherited traits.
if (depth == 0)
{
var childKeySequence = new[] { "Sequence" };
var childKeysExcludeFromRS = new[] { "Sequence", "OpenTerrainTypes", "OpenSequence", "UnloadSequence" };
var rlc = node.Value.Nodes.FirstOrDefault(n => n.Key.StartsWith("RenderLandingCraft"));
if (rlc != null)
{
rlc.Key = "WithLandingCraftAnimation";
var rsNodes = rlc.Value.Nodes.Where(n => !childKeysExcludeFromRS.Contains(n.Key)).ToList();
var wfsbNodes = rlc.Value.Nodes.Where(n => childKeySequence.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", ""));
// Note: For the RA landing craft WithSpriteBody would be sufficient since it has no facings,
// but WithFacingSpriteBody works as well and covers the potential case where a third-party mod
// might have given their landing craft multiple facings.
if (wfsbNodes.Any())
node.Value.Nodes.Add(new MiniYamlNode("WithFacingSpriteBody", new MiniYaml("", wfsbNodes)));
else
node.Value.Nodes.Add(new MiniYamlNode("WithFacingSpriteBody", ""));
node.Value.Nodes.Add(new MiniYamlNode("AutoSelectionSize", ""));
rlc.Value.Nodes.RemoveAll(n => rsNodes.Contains(n));
rlc.Value.Nodes.RemoveAll(n => wfsbNodes.Contains(n));
}
var rrlc = node.Value.Nodes.FirstOrDefault(n => n.Key.StartsWith("-RenderLandingCraft"));
if (rrlc != null)
rrlc.Key = "-WithLandingCraftAnimation";
}
// Replaced RenderHarvester with WithFacingSpriteBody + WithHarvestAnimation + WithDockingAnimation.
// Note: These rules are set up to do approximately the right thing for maps, but
// mods might need additional manual tweaks. This is the best we can do without having
// much smarter rules parsing, because we currently can't reason about inherited traits.
if (depth == 0)
{
var childKeySequence = new[] { "Sequence" };
var childKeyIBF = new[] { "ImagesByFullness" };
var childKeysExcludeFromRS = new[] { "Sequence", "ImagesByFullness", "HarvestSequence" };
var rh = node.Value.Nodes.FirstOrDefault(n => n.Key.StartsWith("RenderHarvester"));
if (rh != null)
{
rh.Key = "WithHarvestAnimation";
var rsNodes = rh.Value.Nodes.Where(n => !childKeysExcludeFromRS.Contains(n.Key)).ToList();
var wfsbNodes = rh.Value.Nodes.Where(n => childKeySequence.Contains(n.Key)).ToList();
var ibfNode = rh.Value.Nodes.Where(n => childKeyIBF.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", ""));
if (wfsbNodes.Any())
node.Value.Nodes.Add(new MiniYamlNode("WithFacingSpriteBody", new MiniYaml("", wfsbNodes)));
else
node.Value.Nodes.Add(new MiniYamlNode("WithFacingSpriteBody", ""));
node.Value.Nodes.Add(new MiniYamlNode("AutoSelectionSize", ""));
node.Value.Nodes.Add(new MiniYamlNode("WithDockingAnimation", ""));
rh.Value.Nodes.RemoveAll(n => rsNodes.Contains(n));
rh.Value.Nodes.RemoveAll(n => wfsbNodes.Contains(n));
if (ibfNode.Any())
rh.Value.Nodes.RemoveAll(n => ibfNode.Contains(n));
Console.WriteLine("The 'ImagesByFullness' property from the removed RenderHarvester trait has been");
Console.WriteLine("replaced with a 'PrefixByFullness' property on the new WithHarvestAnimation trait.");
Console.WriteLine("This cannot be reliably upgraded, as the actor sequences need to be adapted as well.");
Console.WriteLine("Therefore, WithHarvestAnimation will use the default (no prefix) after upgrading.");
Console.WriteLine("See RA's harvester for reference on how to re-implement this feature using the new trait.");
}
var rrh = node.Value.Nodes.FirstOrDefault(n => n.Key.StartsWith("-RenderHarvester"));
if (rrh != null)
rrh.Key = "-WithHarvestAnimation";
}
// Replace RenderUnit with RenderSprites + WithFacingSpriteBody + AutoSelectionSize.
// Normally this should have been removed by previous upgrade rules, but let's run this again
// to make sure to get rid of potential left-over cases like D2k sandworms and harvesters.
if (depth == 0)
{
var childKeys = new[] { "Sequence" };
var ru = node.Value.Nodes.FirstOrDefault(n => n.Key.StartsWith("RenderUnit"));
if (ru != null)
{
ru.Key = "WithFacingSpriteBody";
var rsNodes = ru.Value.Nodes.Where(n => !childKeys.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", ""));
ru.Value.Nodes.RemoveAll(n => rsNodes.Contains(n));
Console.WriteLine("RenderUnit has now been removed from code.");
Console.WriteLine("Use RenderSprites + WithFacingSpriteBody (+ AutoSelectionSize, if necessary) instead.");
}
var rru = node.Value.Nodes.FirstOrDefault(n => n.Key.StartsWith("-RenderUnit"));
if (rru != null)
rru.Key = "-WithFacingSpriteBody";
}
}
UpgradeActorRules(engineVersion, ref node.Value.Nodes, node, depth + 1);
}
}

View File

@@ -29,7 +29,7 @@ namespace OpenRA.Mods.D2k.Activities
readonly Target target;
readonly Sandworm sandworm;
readonly WeaponInfo weapon;
readonly RenderUnit renderUnit;
readonly WithSpriteBody withSpriteBody;
readonly RadarPings radarPings;
readonly AttackSwallow swallow;
readonly IPositionable positionable;
@@ -44,11 +44,11 @@ namespace OpenRA.Mods.D2k.Activities
sandworm = self.Trait<Sandworm>();
positionable = self.Trait<Mobile>();
swallow = self.Trait<AttackSwallow>();
renderUnit = self.Trait<RenderUnit>();
withSpriteBody = self.Trait<WithSpriteBody>();
radarPings = self.World.WorldActor.TraitOrDefault<RadarPings>();
countdown = swallow.Info.AttackTime;
renderUnit.DefaultAnimation.ReplaceAnim("burrowed");
withSpriteBody.DefaultAnimation.ReplaceAnim(sandworm.Info.BurrowedSequence);
stance = AttackState.Burrowed;
location = target.Actor.Location;
}
@@ -104,7 +104,7 @@ namespace OpenRA.Mods.D2k.Activities
// List because IEnumerable gets evaluated too late.
void PlayAttack(Actor self, WPos attackPosition, List<Player> affectedPlayers)
{
renderUnit.PlayCustomAnim(self, "mouth");
withSpriteBody.PlayCustomAnimation(self, sandworm.Info.MouthSequence);
Sound.Play(swallow.Info.WormAttackSound, self.CenterPosition);
Game.RunAfterDelay(1000, () =>
@@ -142,7 +142,7 @@ namespace OpenRA.Mods.D2k.Activities
self.World.AddFrameEndTask(w => self.Kill(self));
}
else
renderUnit.DefaultAnimation.ReplaceAnim("idle");
withSpriteBody.DefaultAnimation.ReplaceAnim(sandworm.Info.IdleSequence);
return NextActivity;
}
@@ -156,7 +156,7 @@ namespace OpenRA.Mods.D2k.Activities
if (!WormAttack(self))
{
renderUnit.DefaultAnimation.ReplaceAnim("idle");
withSpriteBody.DefaultAnimation.ReplaceAnim(sandworm.Info.IdleSequence);
return NextActivity;
}

View File

@@ -93,6 +93,8 @@ namespace OpenRA.Mods.D2k.Traits
// We do not handle Harvested notification
public void Harvested(Actor self, ResourceType resource) { }
public void Docked() { }
public void Undocked() { }
public Actor GetClosestIdleCarrier()
{

View File

@@ -15,7 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.D2k.Traits
{
class SandwormInfo : WandersInfo, Requires<MobileInfo>, Requires<RenderUnitInfo>, Requires<AttackBaseInfo>
class SandwormInfo : WandersInfo, Requires<MobileInfo>, Requires<WithSpriteBodyInfo>, Requires<AttackBaseInfo>
{
[Desc("Time between rescanning for targets (in ticks).")]
public readonly int TargetRescanInterval = 32;
@@ -30,7 +30,13 @@ namespace OpenRA.Mods.D2k.Traits
public readonly int ChanceToDisappear = 80;
[Desc("Name of the sequence that is used when the actor is idle or moving (not attacking).")]
public readonly string IdleSequence = "idle";
[SequenceReference] public readonly string IdleSequence = "idle";
[Desc("Name of the sequence that is used when the actor is attacking.")]
[SequenceReference] public readonly string MouthSequence = "mouth";
[Desc("Name of the sequence that is used when the actor is burrowed.")]
[SequenceReference] public readonly string BurrowedSequence = "burrowed";
public override object Create(ActorInitializer init) { return new Sandworm(init.Self, this); }
}
@@ -41,7 +47,7 @@ namespace OpenRA.Mods.D2k.Traits
readonly WormManager manager;
readonly Lazy<Mobile> mobile;
readonly Lazy<RenderUnit> renderUnit;
readonly Lazy<WithSpriteBody> withSpriteBody;
readonly Lazy<AttackBase> attackTrait;
public bool IsMovingTowardTarget { get; private set; }
@@ -55,15 +61,15 @@ namespace OpenRA.Mods.D2k.Traits
{
Info = info;
mobile = Exts.Lazy(self.Trait<Mobile>);
renderUnit = Exts.Lazy(self.Trait<RenderUnit>);
withSpriteBody = Exts.Lazy(self.Trait<WithSpriteBody>);
attackTrait = Exts.Lazy(self.Trait<AttackBase>);
manager = self.World.WorldActor.Trait<WormManager>();
}
public override void OnBecomingIdle(Actor self)
{
if (renderUnit.Value.DefaultAnimation.CurrentSequence.Name != Info.IdleSequence)
renderUnit.Value.DefaultAnimation.PlayRepeating("idle");
if (withSpriteBody.Value.DefaultAnimation.CurrentSequence.Name != Info.IdleSequence)
withSpriteBody.Value.DefaultAnimation.PlayRepeating(Info.IdleSequence);
base.OnBecomingIdle(self);
}

View File

@@ -104,7 +104,7 @@
<Compile Include="Traits\PaletteEffects\ChronoshiftPaletteEffect.cs" />
<Compile Include="Traits\PortableChrono.cs" />
<Compile Include="Traits\Render\RenderJammerCircle.cs" />
<Compile Include="Traits\Render\RenderLandingCraft.cs" />
<Compile Include="Traits\Render\WithLandingCraftAnimation.cs" />
<Compile Include="Traits\Render\RenderShroudCircle.cs" />
<Compile Include="Traits\SupportPowers\ChronoshiftPower.cs" />
<Compile Include="Traits\SupportPowers\GpsPower.cs" />

View File

@@ -14,30 +14,31 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA.Traits
{
public class RenderLandingCraftInfo : RenderUnitInfo, Requires<IMoveInfo>, Requires<CargoInfo>
public class WithLandingCraftAnimationInfo : ITraitInfo, Requires<IMoveInfo>, Requires<WithSpriteBodyInfo>, Requires<CargoInfo>
{
public readonly string[] OpenTerrainTypes = { "Clear" };
[SequenceReference] public readonly string OpenAnim = "open";
[SequenceReference] public readonly string UnloadAnim = "unload";
[SequenceReference] public readonly string OpenSequence = "open";
[SequenceReference] public readonly string UnloadSequence = "unload";
public override object Create(ActorInitializer init) { return new RenderLandingCraft(init, this); }
public object Create(ActorInitializer init) { return new WithLandingCraftAnimation(init, this); }
}
public class RenderLandingCraft : RenderUnit
public class WithLandingCraftAnimation : ITick
{
readonly RenderLandingCraftInfo info;
readonly WithLandingCraftAnimationInfo info;
readonly Actor self;
readonly Cargo cargo;
readonly IMove move;
readonly WithSpriteBody wsb;
bool open;
public RenderLandingCraft(ActorInitializer init, RenderLandingCraftInfo info)
: base(init, info)
public WithLandingCraftAnimation(ActorInitializer init, WithLandingCraftAnimationInfo info)
{
this.info = info;
self = init.Self;
cargo = self.Trait<Cargo>();
move = self.Trait<IMove>();
wsb = init.Self.Trait<WithSpriteBody>();
}
public bool ShouldBeOpen()
@@ -51,34 +52,32 @@ namespace OpenRA.Mods.RA.Traits
void Open()
{
if (open || !DefaultAnimation.HasSequence(info.OpenAnim))
if (open || !wsb.DefaultAnimation.HasSequence(info.OpenSequence))
return;
open = true;
PlayCustomAnimation(self, info.OpenAnim, () =>
wsb.PlayCustomAnimation(self, info.OpenSequence, () =>
{
if (DefaultAnimation.HasSequence(info.UnloadAnim))
PlayCustomAnimationRepeating(self, info.UnloadAnim);
if (wsb.DefaultAnimation.HasSequence(info.UnloadSequence))
wsb.PlayCustomAnimationRepeating(self, info.UnloadSequence);
});
}
void Close()
{
if (!open || !DefaultAnimation.HasSequence(info.OpenAnim))
if (!open || !wsb.DefaultAnimation.HasSequence(info.OpenSequence))
return;
open = false;
PlayCustomAnimationBackwards(self, info.OpenAnim, null);
wsb.PlayCustomAnimationBackwards(self, info.OpenSequence, null);
}
public override void Tick(Actor self)
public void Tick(Actor self)
{
if (ShouldBeOpen())
Open();
else
Close();
base.Tick(self);
}
}
}

View File

@@ -70,10 +70,8 @@ HARV:
LeavesHusk:
HuskActor: HARV.Husk
-GainsExperience:
-RenderSprites:
-WithFacingSpriteBody:
-AutoSelectionSize:
RenderHarvester:
WithHarvestAnimation:
WithDockingAnimation:
Explodes:
Weapon: TiberiumExplosion
SelectionDecorations:

View File

@@ -33,7 +33,7 @@ sandworm:
Spice: 100
TargetableUnit:
TargetTypes: Ground
RenderUnit:
WithFacingSpriteBody:
WithAttackOverlay:
Sequence: sand
BodyOrientation:
@@ -51,6 +51,8 @@ sandworm:
AnnounceOnSeen:
Notification: WormSign
PingRadar: True
RenderSprites:
AutoSelectionSize:
sietch:
Inherits: ^Building

View File

@@ -14,7 +14,7 @@ harvester.starport:
Queue: Starport
Valued:
Cost: 1500
RenderUnit:
RenderSprites:
Image: harvester
trike.starport:

View File

@@ -77,12 +77,9 @@ harvester:
EmptyWeapon: UnitExplodeScale
LeavesHusk:
HuskActor: Harvester.Husk
RenderUnit:
-RenderSprites:
-WithFacingSpriteBody:
-AutoSelectionSize:
WithHarvestAnimation:
WithHarvestOverlay:
Palette: effect50alpha
WithDockingAnimation:
AttractsWorms:
Intensity: 700
SelectionDecorations:

View File

@@ -1658,7 +1658,7 @@ Rules:
ShowOwnerRow: false
LST.IN:
Inherits: LST
RenderLandingCraft:
RenderSprites:
Image: LST
Cargo:
Types: disabled

View File

@@ -218,10 +218,7 @@ LST:
Range: 6c0
SelectionDecorations:
VisualBounds: 36,36
-AutoSelectionSize:
-RenderSprites:
-WithFacingSpriteBody:
RenderLandingCraft:
WithLandingCraftAnimation:
OpenTerrainTypes: Clear, Rough, Road, Ore, Gems, Beach
Cargo:
Types: Infantry, Vehicle

View File

@@ -265,11 +265,9 @@ HARV:
Crushes: wall, mine, crate, infantry
RevealsShroud:
Range: 4c0
-WithFacingSpriteBody:
-AutoSelectionSize:
-RenderSprites:
RenderHarvester:
ImagesByFullness: harvempty, harvhalf, harv
WithHarvestAnimation:
PrefixByFullness: empty-, half-, full-
WithDockingAnimation:
GpsDot:
String: Harvester
LeavesHusk:

View File

@@ -14,9 +14,27 @@ truk:
icon: trukicon
harv:
idle:
idle: harvempty
Facings: 32
harvest:
harvest: harvempty
Start: 32
Length: 8
Facings: 8
empty-idle: harvempty
Facings: 32
empty-harvest: harvempty
Start: 32
Length: 8
Facings: 8
half-idle: harvhalf
Facings: 32
half-harvest: harvhalf
Start: 32
Length: 8
Facings: 8
full-idle:
Facings: 32
full-harvest:
Start: 32
Length: 8
Facings: 8
@@ -29,34 +47,6 @@ harv:
icon: harvicon
Start: 0
harvhalf:
idle:
Facings: 32
harvest:
Start: 32
Length: 8
Facings: 8
dock: harv
Start: 96
Length: 8
dock-loop: harv
Start: 104
Length: 7
harvempty:
idle:
Facings: 32
harvest:
Start: 32
Length: 8
Facings: 8
dock: harv
Start: 96
Length: 8
dock-loop: harv
Start: 104
Length: 7
hhusk:
idle:
Facings: 32

View File

@@ -82,7 +82,7 @@ HARV:
WithVoxelUnloadBody:
Explodes:
Weapon: TiberiumExplosion
WithHarvestAnimation:
WithHarvestOverlay:
Offset: 384,0,0
Palette: effect
SelectionDecorations: