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 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) public SpriteHarvesterDockSequence(Actor self, Actor refinery, int dockAngle, bool isDragRequired, WVec dragOffset, int dragLength)
: base(self, refinery, dockAngle, isDragRequired, dragOffset, 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) 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; dockingState = State.Loop;
return this; return this;
} }
public override Activity OnStateUndock(Actor self) 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; dockingState = State.Wait;
return this; return this;
} }
} }

View File

@@ -397,7 +397,6 @@
<Compile Include="Traits\Render\RenderBuildingCharge.cs" /> <Compile Include="Traits\Render\RenderBuildingCharge.cs" />
<Compile Include="Traits\Render\RenderBuildingTurreted.cs" /> <Compile Include="Traits\Render\RenderBuildingTurreted.cs" />
<Compile Include="Traits\Render\RenderEditorOnly.cs" /> <Compile Include="Traits\Render\RenderEditorOnly.cs" />
<Compile Include="Traits\Render\RenderHarvester.cs" />
<Compile Include="Traits\Render\RenderNameTag.cs" /> <Compile Include="Traits\Render\RenderNameTag.cs" />
<Compile Include="Traits\Render\RenderSimple.cs" /> <Compile Include="Traits\Render\RenderSimple.cs" />
<Compile Include="Traits\Render\RenderSprites.cs" /> <Compile Include="Traits\Render\RenderSprites.cs" />
@@ -421,7 +420,9 @@
<Compile Include="Traits\Render\WithCrateBody.cs" /> <Compile Include="Traits\Render\WithCrateBody.cs" />
<Compile Include="Traits\Render\WithDeathAnimation.cs" /> <Compile Include="Traits\Render\WithDeathAnimation.cs" />
<Compile Include="Traits\Render\WithDecoration.cs" /> <Compile Include="Traits\Render\WithDecoration.cs" />
<Compile Include="Traits\Render\WithDockingAnimation.cs" />
<Compile Include="Traits\Render\WithDockingOverlay.cs" /> <Compile Include="Traits\Render\WithDockingOverlay.cs" />
<Compile Include="Traits\Render\WithHarvestAnimation.cs" />
<Compile Include="Traits\Render\WithHarvestOverlay.cs" /> <Compile Include="Traits\Render\WithHarvestOverlay.cs" />
<Compile Include="Traits\Render\WithIdleOverlay.cs" /> <Compile Include="Traits\Render\WithIdleOverlay.cs" />
<Compile Include="Traits\Render\WithMuzzleFlash.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 MovingToResources(Actor self, CPos targetCell, Activity next) { }
public void MovingToRefinery(Actor self, CPos targetCell, Activity next) { } public void MovingToRefinery(Actor self, CPos targetCell, Activity next) { }
public void MovementCancelled(Actor self) { } public void MovementCancelled(Actor self) { }
public void Docked() { }
public void Undocked() { }
public static int ZOffsetFromCenter(Actor self, WPos pos, int offset) 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 MovingToRefinery(Actor self, CPos targetCell, Activity next);
void MovementCancelled(Actor self); void MovementCancelled(Actor self);
void Harvested(Actor self, ResourceType resource); void Harvested(Actor self, ResourceType resource);
void Docked();
void Undocked();
} }
public interface ITechTreePrerequisite public interface ITechTreePrerequisite

View File

@@ -1268,6 +1268,55 @@ namespace OpenRA.Mods.Common.UtilityCommands
if (rrlc != null) if (rrlc != null)
rrlc.Key = "-WithLandingCraftAnimation"; 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); 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 // We do not handle Harvested notification
public void Harvested(Actor self, ResourceType resource) { } public void Harvested(Actor self, ResourceType resource) { }
public void Docked() { }
public void Undocked() { }
public Actor GetClosestIdleCarrier() public Actor GetClosestIdleCarrier()
{ {

View File

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

View File

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

View File

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

View File

@@ -14,9 +14,27 @@ truk:
icon: trukicon icon: trukicon
harv: harv:
idle: idle: harvempty
Facings: 32 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 Start: 32
Length: 8 Length: 8
Facings: 8 Facings: 8
@@ -29,34 +47,6 @@ harv:
icon: harvicon icon: harvicon
Start: 0 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: hhusk:
idle: idle:
Facings: 32 Facings: 32