Added WithHarvestAnimation + WithDockingAnimation

Removed RenderHarvester.
This commit is contained in:
reaperrr
2015-06-23 20:17:08 +02:00
parent de72db83db
commit 76aaafe37c
13 changed files with 221 additions and 107 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,7 +397,6 @@
<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" />
@@ -421,7 +420,9 @@
<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" />

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

@@ -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

@@ -0,0 +1,87 @@
#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.Traits;
namespace OpenRA.Mods.Common.Traits
{
public class WithHarvestAnimationInfo : ITraitInfo, Requires<WithSpriteBodyInfo>, Requires<HarvesterInfo>
{
[Desc("Prefix added to idle and harvest sequences depending on fullness of harvester.")]
[SequenceReference(null, true)] public readonly string[] PrefixByFullness = { "" };
[Desc("Displayed while harvesting.")]
[SequenceReference] public readonly string HarvestSequence = "harvest";
public object Create(ActorInitializer init) { return new WithHarvestAnimation(init, this); }
}
public class WithHarvestAnimation : ITick, INotifyHarvesterAction
{
public readonly WithHarvestAnimationInfo Info;
readonly WithSpriteBody wsb;
readonly Harvester harv;
public bool IsModifying;
public WithHarvestAnimation(ActorInitializer init, WithHarvestAnimationInfo info)
{
Info = info;
harv = init.Self.Trait<Harvester>();
wsb = init.Self.Trait<WithSpriteBody>();
}
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 (!IsModifying && !string.IsNullOrEmpty(Info.HarvestSequence) && wsb.DefaultAnimation.HasSequence(NormalizeHarvesterSequence(self, Info.HarvestSequence)))
{
IsModifying = true;
wsb.PlayCustomAnimation(self, NormalizeHarvesterSequence(self, Info.HarvestSequence), () => IsModifying = 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) { }
}
}

View File

@@ -62,6 +62,8 @@ namespace OpenRA.Mods.Common.Traits
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)
{

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

@@ -1268,6 +1268,55 @@ namespace OpenRA.Mods.Common.UtilityCommands
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";
}
}
UpgradeActorRules(engineVersion, ref node.Value.Nodes, node, depth + 1);

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

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

View File

@@ -83,6 +83,7 @@ harvester:
-AutoSelectionSize:
WithHarvestOverlay:
Palette: effect50alpha
WithDockingAnimation:
AttractsWorms:
Intensity: 700
SelectionDecorations:

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