Replace INotifyBuildComplete in render traits with conditions.

This commit is contained in:
Paul Chote
2018-10-05 20:16:36 +00:00
committed by abcdefg30
parent 26b0a06a17
commit 14607f55c5
28 changed files with 152 additions and 407 deletions

View File

@@ -17,38 +17,40 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Cnc.Traits.Render
{
[Desc("Building animation to play when ProductionAirdrop is used to deliver units.")]
public class WithDeliveryAnimationInfo : ITraitInfo, Requires<WithSpriteBodyInfo>
public class WithDeliveryAnimationInfo : ConditionalTraitInfo, Requires<WithSpriteBodyInfo>
{
[SequenceReference] public readonly string ActiveSequence = "active";
[SequenceReference] public readonly string IdleSequence = "idle";
[Desc("Which sprite body to play the animation on.")]
public readonly string Body = "body";
public object Create(ActorInitializer init) { return new WithDeliveryAnimation(init.Self, this); }
public override object Create(ActorInitializer init) { return new WithDeliveryAnimation(init.Self, this); }
}
public class WithDeliveryAnimation : INotifyDelivery
public class WithDeliveryAnimation : ConditionalTrait<WithDeliveryAnimationInfo>, INotifyDelivery
{
readonly WithDeliveryAnimationInfo info;
readonly WithSpriteBody wsb;
public WithDeliveryAnimation(Actor self, WithDeliveryAnimationInfo info)
: base(info)
{
wsb = self.TraitsImplementing<WithSpriteBody>().Single(w => w.Info.Name == info.Body);
this.info = info;
}
public void IncomingDelivery(Actor self)
{
wsb.PlayCustomAnimationRepeating(self, info.ActiveSequence);
if (!IsTraitDisabled)
wsb.PlayCustomAnimationRepeating(self, Info.ActiveSequence);
}
public void Delivered(Actor self)
{
wsb.PlayCustomAnimationRepeating(self, info.IdleSequence);
wsb.CancelCustomAnimation(self);
}
protected override void TraitDisabled(Actor self)
{
wsb.CancelCustomAnimation(self);
}
}
}

View File

@@ -17,7 +17,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Cnc.Traits.Render
{
[Desc("Rendered on the refinery when a voxel harvester is docking and undocking.")]
public class WithDockingOverlayInfo : ITraitInfo, Requires<RenderSpritesInfo>, Requires<BodyOrientationInfo>
public class WithDockingOverlayInfo : PausableConditionalTraitInfo, Requires<RenderSpritesInfo>, Requires<BodyOrientationInfo>
{
[Desc("Sequence name to use")]
[SequenceReference] public readonly string Sequence = "unload-overlay";
@@ -31,29 +31,27 @@ namespace OpenRA.Mods.Cnc.Traits.Render
[Desc("Custom palette is a player palette BaseName")]
public readonly bool IsPlayerPalette = false;
public object Create(ActorInitializer init) { return new WithDockingOverlay(init.Self, this); }
public override object Create(ActorInitializer init) { return new WithDockingOverlay(init.Self, this); }
}
public class WithDockingOverlay
public class WithDockingOverlay : PausableConditionalTrait<WithDockingOverlayInfo>
{
public readonly WithDockingOverlayInfo Info;
public readonly AnimationWithOffset WithOffset;
public bool Visible;
public WithDockingOverlay(Actor self, WithDockingOverlayInfo info)
: base(info)
{
Info = info;
var rs = self.Trait<RenderSprites>();
var body = self.Trait<BodyOrientation>();
var overlay = new Animation(self.World, rs.GetImage(self));
var overlay = new Animation(self.World, rs.GetImage(self), () => IsTraitPaused);
overlay.Play(info.Sequence);
WithOffset = new AnimationWithOffset(overlay,
() => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))),
() => !Visible);
() => !Visible || IsTraitDisabled);
rs.Add(WithOffset, info.Palette, info.IsPlayerPalette);
}

View File

@@ -15,7 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits.Render
{
[Desc("Replaces the building animation when it accepts a cash delivery unit.")]
public class WithAcceptDeliveredCashAnimationInfo : ITraitInfo, Requires<WithSpriteBodyInfo>
public class WithAcceptDeliveredCashAnimationInfo : ConditionalTraitInfo, Requires<WithSpriteBodyInfo>
{
[Desc("Sequence name to use")]
[SequenceReference] public readonly string Sequence = "active";
@@ -23,41 +23,27 @@ namespace OpenRA.Mods.Common.Traits.Render
[Desc("Which sprite body to play the animation on.")]
public readonly string Body = "body";
public object Create(ActorInitializer init) { return new WithAcceptDeliveredCashAnimation(init.Self, this); }
public override object Create(ActorInitializer init) { return new WithAcceptDeliveredCashAnimation(init.Self, this); }
}
public class WithAcceptDeliveredCashAnimation : INotifyCashTransfer, INotifyBuildComplete, INotifySold
public class WithAcceptDeliveredCashAnimation : ConditionalTrait<WithAcceptDeliveredCashAnimationInfo>, INotifyCashTransfer
{
readonly WithAcceptDeliveredCashAnimationInfo info;
readonly WithSpriteBody wsb;
bool buildComplete;
public WithAcceptDeliveredCashAnimation(Actor self, WithAcceptDeliveredCashAnimationInfo info)
: base(info)
{
this.info = info;
wsb = self.TraitsImplementing<WithSpriteBody>().Single(w => w.Info.Name == info.Body);
}
void INotifyBuildComplete.BuildingComplete(Actor self)
{
buildComplete = true;
}
void INotifySold.Selling(Actor self)
{
buildComplete = false;
}
void INotifySold.Sold(Actor self) { }
bool playing;
void INotifyCashTransfer.OnAcceptingCash(Actor self, Actor donor)
{
if (!buildComplete || playing)
if (IsTraitDisabled || playing)
return;
playing = true;
wsb.PlayCustomAnimation(self, info.Sequence, () => playing = false);
wsb.PlayCustomAnimation(self, Info.Sequence, () => playing = false);
}
void INotifyCashTransfer.OnDeliveringCash(Actor self, Actor acceptor) { }

View File

@@ -68,8 +68,10 @@ namespace OpenRA.Mods.Common.Traits.Render
bridgeLayer = init.World.WorldActor.Trait<BridgeLayer>();
}
protected override void OnBuildComplete(Actor self)
protected override void TraitEnabled(Actor self)
{
base.TraitEnabled(self);
if (bridgeInfo.AOffset != CVec.Zero)
UpdateNeighbour(bridgeInfo.AOffset);

View File

@@ -26,41 +26,25 @@ namespace OpenRA.Mods.Common.Traits.Render
public override object Create(ActorInitializer init) { return new WithBuildingPlacedAnimation(init.Self, this); }
}
public class WithBuildingPlacedAnimation : ConditionalTrait<WithBuildingPlacedAnimationInfo>, INotifyBuildingPlaced, INotifyBuildComplete, INotifySold, INotifyTransform
public class WithBuildingPlacedAnimation : ConditionalTrait<WithBuildingPlacedAnimationInfo>, INotifyBuildingPlaced
{
readonly WithSpriteBody wsb;
bool buildComplete;
public WithBuildingPlacedAnimation(Actor self, WithBuildingPlacedAnimationInfo info)
: base(info)
{
wsb = self.TraitsImplementing<WithSpriteBody>().Single(w => w.Info.Name == info.Body);
buildComplete = !self.Info.HasTraitInfo<BuildingInfo>();
}
void INotifyBuildComplete.BuildingComplete(Actor self)
{
buildComplete = true;
}
void INotifySold.Sold(Actor self) { }
void INotifySold.Selling(Actor self)
{
buildComplete = false;
}
void INotifyTransform.BeforeTransform(Actor self)
{
buildComplete = false;
}
void INotifyTransform.OnTransform(Actor self) { }
void INotifyTransform.AfterTransform(Actor self) { }
void INotifyBuildingPlaced.BuildingPlaced(Actor self)
{
if (!IsTraitDisabled && buildComplete)
if (!IsTraitDisabled)
wsb.PlayCustomAnimation(self, Info.Sequence);
}
protected override void TraitDisabled(Actor self)
{
wsb.CancelCustomAnimation(self);
}
}
}

View File

@@ -15,7 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits.Render
{
[Desc("Rendered when the actor constructed a building.")]
public class WithBuildingPlacedOverlayInfo : ITraitInfo, Requires<RenderSpritesInfo>, Requires<BodyOrientationInfo>
public class WithBuildingPlacedOverlayInfo : ConditionalTraitInfo, Requires<RenderSpritesInfo>, Requires<BodyOrientationInfo>
{
[Desc("Sequence name to use")]
[SequenceReference] public readonly string Sequence = "crane-overlay";
@@ -29,52 +29,30 @@ namespace OpenRA.Mods.Common.Traits.Render
[Desc("Custom palette is a player palette BaseName")]
public readonly bool IsPlayerPalette = false;
public object Create(ActorInitializer init) { return new WithBuildingPlacedOverlay(init.Self, this); }
public override object Create(ActorInitializer init) { return new WithBuildingPlacedOverlay(init.Self, this); }
}
public class WithBuildingPlacedOverlay : INotifyBuildComplete, INotifySold, INotifyDamageStateChanged, INotifyBuildingPlaced, INotifyTransform
public class WithBuildingPlacedOverlay : ConditionalTrait<WithBuildingPlacedOverlayInfo>, INotifyDamageStateChanged, INotifyBuildingPlaced
{
readonly Animation overlay;
bool buildComplete;
bool visible;
public WithBuildingPlacedOverlay(Actor self, WithBuildingPlacedOverlayInfo info)
: base(info)
{
var rs = self.Trait<RenderSprites>();
var body = self.Trait<BodyOrientation>();
buildComplete = !self.Info.HasTraitInfo<BuildingInfo>(); // always render instantly for units
overlay = new Animation(self.World, rs.GetImage(self));
var anim = new AnimationWithOffset(overlay,
() => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))),
() => !visible || !buildComplete);
() => !visible || IsTraitDisabled);
overlay.PlayThen(info.Sequence, () => visible = false);
rs.Add(anim, info.Palette, info.IsPlayerPalette);
}
void INotifyBuildComplete.BuildingComplete(Actor self)
{
buildComplete = true;
visible = false;
}
void INotifySold.Sold(Actor self) { }
void INotifySold.Selling(Actor self)
{
buildComplete = false;
}
void INotifyTransform.BeforeTransform(Actor self)
{
buildComplete = false;
}
void INotifyTransform.OnTransform(Actor self) { }
void INotifyTransform.AfterTransform(Actor self) { }
void INotifyDamageStateChanged.DamageStateChanged(Actor self, AttackInfo e)
{
overlay.ReplaceAnim(RenderSprites.NormalizeSequence(overlay, e.DamageState, overlay.CurrentSequence.Name));

View File

@@ -15,7 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits.Render
{
[Desc("Render trait that varies the animation frame based on the AttackCharges trait's charge level.")]
class WithChargeAnimationInfo : ITraitInfo, Requires<WithSpriteBodyInfo>, Requires<AttackChargesInfo>
class WithChargeAnimationInfo : ConditionalTraitInfo, Requires<WithSpriteBodyInfo>, Requires<AttackChargesInfo>
{
[SequenceReference]
[Desc("Sequence to use for the charge levels.")]
@@ -24,26 +24,25 @@ namespace OpenRA.Mods.Common.Traits.Render
[Desc("Which sprite body to play the animation on.")]
public readonly string Body = "body";
public object Create(ActorInitializer init) { return new WithChargeAnimation(init.Self, this); }
public override object Create(ActorInitializer init) { return new WithChargeAnimation(init.Self, this); }
}
class WithChargeAnimation : INotifyBuildComplete
class WithChargeAnimation : ConditionalTrait<WithChargeAnimationInfo>
{
readonly WithChargeAnimationInfo info;
readonly WithSpriteBody wsb;
readonly AttackCharges attackCharges;
public WithChargeAnimation(Actor self, WithChargeAnimationInfo info)
: base(info)
{
this.info = info;
wsb = self.TraitsImplementing<WithSpriteBody>().Single(w => w.Info.Name == info.Body);
attackCharges = self.Trait<AttackCharges>();
}
void INotifyBuildComplete.BuildingComplete(Actor self)
protected override void TraitEnabled(Actor self)
{
var attackChargesInfo = (AttackChargesInfo)attackCharges.Info;
wsb.DefaultAnimation.PlayFetchIndex(wsb.NormalizeSequence(self, info.Sequence),
wsb.DefaultAnimation.PlayFetchIndex(wsb.NormalizeSequence(self, Info.Sequence),
() => int2.Lerp(0, wsb.DefaultAnimation.CurrentSequence.Length, attackCharges.ChargeLevel, attackChargesInfo.ChargeLevel + 1));
}
}

View File

@@ -15,7 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits.Render
{
[Desc("Render overlay that varies the animation frame based on the AttackCharges trait's charge level.")]
class WithChargeOverlayInfo : ITraitInfo, Requires<WithSpriteBodyInfo>, Requires<RenderSpritesInfo>
class WithChargeOverlayInfo : PausableConditionalTraitInfo, Requires<WithSpriteBodyInfo>, Requires<RenderSpritesInfo>
{
[SequenceReference]
[Desc("Sequence to use for the charge levels.")]
@@ -27,46 +27,33 @@ namespace OpenRA.Mods.Common.Traits.Render
[Desc("Custom palette is a player palette BaseName")]
public readonly bool IsPlayerPalette = false;
public object Create(ActorInitializer init) { return new WithChargeOverlay(init.Self, this); }
public override object Create(ActorInitializer init) { return new WithChargeOverlay(init.Self, this); }
}
class WithChargeOverlay : INotifyBuildComplete, INotifySold, INotifyDamageStateChanged
class WithChargeOverlay : PausableConditionalTrait<WithChargeOverlayInfo>, INotifyDamageStateChanged
{
readonly WithChargeOverlayInfo info;
readonly Animation overlay;
readonly RenderSprites rs;
readonly WithSpriteBody wsb;
bool buildComplete;
public WithChargeOverlay(Actor self, WithChargeOverlayInfo info)
: base(info)
{
this.info = info;
rs = self.Trait<RenderSprites>();
wsb = self.Trait<WithSpriteBody>();
var rs = self.Trait<RenderSprites>();
var wsb = self.Trait<WithSpriteBody>();
var attackCharges = self.Trait<AttackCharges>();
var attackChargesInfo = (AttackChargesInfo)attackCharges.Info;
overlay = new Animation(self.World, rs.GetImage(self));
overlay = new Animation(self.World, rs.GetImage(self), () => IsTraitPaused);
overlay.PlayFetchIndex(wsb.NormalizeSequence(self, info.Sequence),
() => int2.Lerp(0, overlay.CurrentSequence.Length, attackCharges.ChargeLevel, attackChargesInfo.ChargeLevel + 1));
rs.Add(new AnimationWithOffset(overlay, null, () => !buildComplete, 1024),
rs.Add(new AnimationWithOffset(overlay, null, () => IsTraitDisabled, 1024),
info.Palette, info.IsPlayerPalette);
}
void INotifyBuildComplete.BuildingComplete(Actor self)
{
buildComplete = true;
}
void INotifyDamageStateChanged.DamageStateChanged(Actor self, AttackInfo e)
{
overlay.ReplaceAnim(RenderSprites.NormalizeSequence(overlay, e.DamageState, info.Sequence));
}
void INotifySold.Selling(Actor self) { buildComplete = false; }
void INotifySold.Sold(Actor self) { }
overlay.ReplaceAnim(RenderSprites.NormalizeSequence(overlay, e.DamageState, Info.Sequence));
}
}
}

View File

@@ -81,8 +81,10 @@ namespace OpenRA.Mods.Common.Traits.Render
return bridgeInfo.RampActors.Contains(neighbour.Info.Name);
}
protected override void OnBuildComplete(Actor self)
protected override void TraitEnabled(Actor self)
{
base.TraitEnabled(self);
self.World.AddFrameEndTask(w =>
{
var aRamp = bridgeInfo.AOffset != CVec.Zero && RampExists(self, bridgeInfo.AOffset);

View File

@@ -16,7 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits.Render
{
[Desc("Rendered when a harvester is docked.")]
public class WithDockedOverlayInfo : ITraitInfo, Requires<RenderSpritesInfo>, Requires<BodyOrientationInfo>
public class WithDockedOverlayInfo : PausableConditionalTraitInfo, Requires<RenderSpritesInfo>, Requires<BodyOrientationInfo>
{
[Desc("Sequence name to use")]
[SequenceReference] public readonly string Sequence = "docking-overlay";
@@ -30,31 +30,26 @@ namespace OpenRA.Mods.Common.Traits.Render
[Desc("Custom palette is a player palette BaseName")]
public readonly bool IsPlayerPalette = false;
public object Create(ActorInitializer init) { return new WithDockedOverlay(init.Self, this); }
public override object Create(ActorInitializer init) { return new WithDockedOverlay(init.Self, this); }
}
public class WithDockedOverlay : INotifyDocking, INotifyBuildComplete, INotifySold
public class WithDockedOverlay : PausableConditionalTrait<WithDockedOverlayInfo>, INotifyDocking
{
readonly WithDockedOverlayInfo info;
readonly AnimationWithOffset anim;
bool buildComplete;
bool docked;
public WithDockedOverlay(Actor self, WithDockedOverlayInfo info)
: base(info)
{
this.info = info;
var rs = self.Trait<RenderSprites>();
var body = self.Trait<BodyOrientation>();
buildComplete = !self.Info.HasTraitInfo<BuildingInfo>(); // always render instantly for units
var overlay = new Animation(self.World, rs.GetImage(self));
var overlay = new Animation(self.World, rs.GetImage(self), () => IsTraitPaused);
overlay.Play(info.Sequence);
anim = new AnimationWithOffset(overlay,
() => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))),
() => !buildComplete || !docked);
() => IsTraitDisabled || !docked);
rs.Add(anim, info.Palette, info.IsPlayerPalette);
}
@@ -62,18 +57,7 @@ namespace OpenRA.Mods.Common.Traits.Render
void PlayDockingOverlay()
{
if (docked)
anim.Animation.PlayThen(info.Sequence, PlayDockingOverlay);
}
void INotifyBuildComplete.BuildingComplete(Actor self)
{
buildComplete = true;
}
void INotifySold.Sold(Actor self) { }
void INotifySold.Selling(Actor self)
{
buildComplete = false;
anim.Animation.PlayThen(Info.Sequence, PlayDockingOverlay);
}
void INotifyDocking.Docked(Actor self, Actor harvester) { docked = true; PlayDockingOverlay(); }

View File

@@ -63,7 +63,7 @@ namespace OpenRA.Mods.Common.Traits.Render
void UpdateState(Actor self)
{
if (renderOpen)
if (renderOpen || IsTraitPaused)
DefaultAnimation.PlayRepeating(NormalizeSequence(self, gateBodyInfo.OpenSequence));
else
DefaultAnimation.PlayFetchIndex(NormalizeSequence(self, Info.Sequence), GetGateFrame);
@@ -91,8 +91,10 @@ namespace OpenRA.Mods.Common.Traits.Render
UpdateState(self);
}
protected override void OnBuildComplete(Actor self)
protected override void TraitEnabled(Actor self)
{
base.TraitEnabled(self);
UpdateState(self);
UpdateNeighbours(self);
}

View File

@@ -28,23 +28,21 @@ namespace OpenRA.Mods.Common.Traits.Render
public override object Create(ActorInitializer init) { return new WithIdleAnimation(init.Self, this); }
}
public class WithIdleAnimation : ConditionalTrait<WithIdleAnimationInfo>, ITick, INotifyBuildComplete, INotifySold
public class WithIdleAnimation : ConditionalTrait<WithIdleAnimationInfo>, ITick
{
readonly WithSpriteBody wsb;
bool buildComplete;
int ticks;
public WithIdleAnimation(Actor self, WithIdleAnimationInfo info)
: base(info)
{
wsb = self.TraitsImplementing<WithSpriteBody>().Single(w => w.Info.Name == Info.Body);
buildComplete = !self.Info.HasTraitInfo<BuildingInfo>(); // always render instantly for units
ticks = info.Interval;
}
void ITick.Tick(Actor self)
{
if (!buildComplete || IsTraitDisabled)
if (IsTraitDisabled)
return;
if (--ticks <= 0)
@@ -54,16 +52,9 @@ namespace OpenRA.Mods.Common.Traits.Render
}
}
void INotifyBuildComplete.BuildingComplete(Actor self)
protected override void TraitDisabled(Actor self)
{
buildComplete = true;
}
void INotifySold.Selling(Actor self)
{
buildComplete = false;
}
void INotifySold.Sold(Actor self) { }
wsb.CancelCustomAnimation(self);
}
}
}

View File

@@ -35,9 +35,6 @@ namespace OpenRA.Mods.Common.Traits.Render
[Desc("Custom palette is a player palette BaseName")]
public readonly bool IsPlayerPalette = false;
// TODO: Remove this when the buildComplete code is replaced with conditions.
public readonly bool RenderBeforeBuildComplete = false;
public override object Create(ActorInitializer init) { return new WithIdleOverlay(init.Self, this); }
public IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
@@ -73,10 +70,9 @@ namespace OpenRA.Mods.Common.Traits.Render
}
}
public class WithIdleOverlay : PausableConditionalTrait<WithIdleOverlayInfo>, INotifyDamageStateChanged, INotifyBuildComplete, INotifySold, INotifyTransform
public class WithIdleOverlay : PausableConditionalTrait<WithIdleOverlayInfo>, INotifyDamageStateChanged
{
readonly Animation overlay;
bool buildComplete;
public WithIdleOverlay(Actor self, WithIdleOverlayInfo info)
: base(info)
@@ -84,8 +80,7 @@ namespace OpenRA.Mods.Common.Traits.Render
var rs = self.Trait<RenderSprites>();
var body = self.Trait<BodyOrientation>();
buildComplete = !self.Info.HasTraitInfo<BuildingInfo>(); // always render instantly for units
overlay = new Animation(self.World, rs.GetImage(self), () => IsTraitPaused || (!info.RenderBeforeBuildComplete && !buildComplete));
overlay = new Animation(self.World, rs.GetImage(self), () => IsTraitPaused);
if (info.StartSequence != null)
overlay.PlayThen(RenderSprites.NormalizeSequence(overlay, self.GetDamageState(), info.StartSequence),
() => overlay.PlayRepeating(RenderSprites.NormalizeSequence(overlay, self.GetDamageState(), info.Sequence)));
@@ -94,31 +89,12 @@ namespace OpenRA.Mods.Common.Traits.Render
var anim = new AnimationWithOffset(overlay,
() => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))),
() => IsTraitDisabled || (!info.RenderBeforeBuildComplete && !buildComplete),
() => IsTraitDisabled,
p => RenderUtils.ZOffsetFromCenter(self, p, 1));
rs.Add(anim, info.Palette, info.IsPlayerPalette);
}
void INotifyBuildComplete.BuildingComplete(Actor self)
{
buildComplete = true;
}
void INotifySold.Sold(Actor self) { }
void INotifySold.Selling(Actor self)
{
buildComplete = false;
}
void INotifyTransform.BeforeTransform(Actor self)
{
buildComplete = false;
}
void INotifyTransform.OnTransform(Actor self) { }
void INotifyTransform.AfterTransform(Actor self) { }
void INotifyDamageStateChanged.DamageStateChanged(Actor self, AttackInfo e)
{
overlay.ReplaceAnim(RenderSprites.NormalizeSequence(overlay, e.DamageState, overlay.CurrentSequence.Name));

View File

@@ -26,33 +26,25 @@ namespace OpenRA.Mods.Common.Traits.Render
public override object Create(ActorInitializer init) { return new WithNukeLaunchAnimation(init.Self, this); }
}
public class WithNukeLaunchAnimation : ConditionalTrait<WithNukeLaunchAnimationInfo>, INotifyNuke, INotifyBuildComplete, INotifySold
public class WithNukeLaunchAnimation : ConditionalTrait<WithNukeLaunchAnimationInfo>, INotifyNuke
{
readonly WithSpriteBody spriteBody;
bool buildComplete;
readonly WithSpriteBody wsb;
public WithNukeLaunchAnimation(Actor self, WithNukeLaunchAnimationInfo info)
: base(info)
{
spriteBody = self.TraitsImplementing<WithSpriteBody>().Single(w => w.Info.Name == Info.Body);
wsb = self.TraitsImplementing<WithSpriteBody>().Single(w => w.Info.Name == Info.Body);
}
void INotifyNuke.Launching(Actor self)
{
if (buildComplete && !IsTraitDisabled)
spriteBody.PlayCustomAnimation(self, Info.Sequence, () => spriteBody.CancelCustomAnimation(self));
if (!IsTraitDisabled)
wsb.PlayCustomAnimation(self, Info.Sequence, () => wsb.CancelCustomAnimation(self));
}
void INotifyBuildComplete.BuildingComplete(Actor self)
protected override void TraitDisabled(Actor self)
{
buildComplete = true;
}
void INotifySold.Selling(Actor self)
{
buildComplete = false;
}
void INotifySold.Sold(Actor self) { }
wsb.CancelCustomAnimation(self);
}
}
}

View File

@@ -33,10 +33,9 @@ namespace OpenRA.Mods.Common.Traits.Render
public override object Create(ActorInitializer init) { return new WithNukeLaunchOverlay(init.Self, this); }
}
public class WithNukeLaunchOverlay : ConditionalTrait<WithNukeLaunchOverlayInfo>, INotifyBuildComplete, INotifySold, INotifyNuke
public class WithNukeLaunchOverlay : ConditionalTrait<WithNukeLaunchOverlayInfo>, INotifyNuke
{
readonly Animation overlay;
bool buildComplete;
bool visible;
public WithNukeLaunchOverlay(Actor self, WithNukeLaunchOverlayInfo info)
@@ -45,29 +44,17 @@ namespace OpenRA.Mods.Common.Traits.Render
var rs = self.Trait<RenderSprites>();
var body = self.Trait<BodyOrientation>();
buildComplete = !self.Info.HasTraitInfo<BuildingInfo>(); // always render instantly for units
overlay = new Animation(self.World, rs.GetImage(self));
overlay.PlayThen(info.Sequence, () => visible = false);
var anim = new AnimationWithOffset(overlay,
() => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))),
() => IsTraitDisabled || !visible || !buildComplete,
() => IsTraitDisabled || !visible,
p => RenderUtils.ZOffsetFromCenter(self, p, 1));
rs.Add(anim, info.Palette, info.IsPlayerPalette);
}
void INotifyBuildComplete.BuildingComplete(Actor self)
{
buildComplete = true;
}
void INotifySold.Sold(Actor self) { }
void INotifySold.Selling(Actor self)
{
buildComplete = false;
}
void INotifyNuke.Launching(Actor self)
{
visible = true;

View File

@@ -18,12 +18,10 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits.Render
{
[Desc("Play an animation when a unit exits or blocks the exit after production finished.")]
class WithProductionDoorOverlayInfo : ITraitInfo, IRenderActorPreviewSpritesInfo, Requires<RenderSpritesInfo>, Requires<BodyOrientationInfo>, Requires<BuildingInfo>
class WithProductionDoorOverlayInfo : ConditionalTraitInfo, IRenderActorPreviewSpritesInfo, Requires<RenderSpritesInfo>, Requires<BodyOrientationInfo>, Requires<BuildingInfo>
{
public readonly string Sequence = "build-door";
public object Create(ActorInitializer init) { return new WithProductionDoorOverlay(init.Self, this); }
public IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
{
var anim = new Animation(init.World, image, () => 0);
@@ -33,18 +31,18 @@ namespace OpenRA.Mods.Common.Traits.Render
var offset = bi.CenterOffset(init.World).Y + 512; // Additional 512 units move from center -> top of cell
yield return new SpriteActorPreview(anim, () => WVec.Zero, () => offset, p, rs.Scale);
}
public override object Create(ActorInitializer init) { return new WithProductionDoorOverlay(init.Self, this); }
}
class WithProductionDoorOverlay : INotifyBuildComplete, ITick, INotifyProduction, INotifySold, INotifyTransform, INotifyDamageStateChanged
class WithProductionDoorOverlay : ConditionalTrait<WithProductionDoorOverlayInfo>, ITick, INotifyProduction, INotifyDamageStateChanged
{
readonly Animation door;
int desiredFrame;
CPos openExit;
bool buildComplete;
public WithProductionDoorOverlay(Actor self, WithProductionDoorOverlayInfo info)
: base(info)
{
var renderSprites = self.Trait<RenderSprites>();
door = new Animation(self.World, renderSprites.GetImage(self));
@@ -54,12 +52,7 @@ namespace OpenRA.Mods.Common.Traits.Render
var buildingInfo = self.Info.TraitInfo<BuildingInfo>();
var offset = buildingInfo.CenterOffset(self.World).Y + 512;
renderSprites.Add(new AnimationWithOffset(door, null, () => !buildComplete, offset));
}
void INotifyBuildComplete.BuildingComplete(Actor self)
{
buildComplete = true;
renderSprites.Add(new AnimationWithOffset(door, null, () => IsTraitDisabled, offset));
}
void ITick.Tick(Actor self)
@@ -79,12 +72,5 @@ namespace OpenRA.Mods.Common.Traits.Render
openExit = exit;
desiredFrame = door.CurrentSequence.Length - 1;
}
void INotifySold.Selling(Actor self) { buildComplete = false; }
void INotifySold.Sold(Actor self) { }
void INotifyTransform.BeforeTransform(Actor self) { buildComplete = false; }
void INotifyTransform.OnTransform(Actor self) { }
void INotifyTransform.AfterTransform(Actor self) { }
}
}

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.Traits.Render
{
[Desc("Renders an animation when the Production trait of the actor is activated.",
"Works both with per player ClassicProductionQueue and per building ProductionQueue, but needs any of these.")]
public class WithProductionOverlayInfo : ITraitInfo, Requires<RenderSpritesInfo>, Requires<BodyOrientationInfo>, Requires<ProductionInfo>
public class WithProductionOverlayInfo : PausableConditionalTraitInfo, Requires<RenderSpritesInfo>, Requires<BodyOrientationInfo>, Requires<ProductionInfo>
{
[Desc("Queues that should be producing for this overlay to render.")]
public readonly HashSet<string> Queues = new HashSet<string>();
@@ -36,16 +36,14 @@ namespace OpenRA.Mods.Common.Traits.Render
[Desc("Custom palette is a player palette BaseName")]
public readonly bool IsPlayerPalette = false;
public object Create(ActorInitializer init) { return new WithProductionOverlay(init.Self, this); }
public override object Create(ActorInitializer init) { return new WithProductionOverlay(init.Self, this); }
}
public class WithProductionOverlay : INotifyDamageStateChanged, INotifyCreated, INotifyBuildComplete, INotifySold, INotifyOwnerChanged
public class WithProductionOverlay : PausableConditionalTrait<WithProductionOverlayInfo>, INotifyDamageStateChanged, INotifyCreated, INotifyOwnerChanged
{
readonly WithProductionOverlayInfo info;
readonly Animation overlay;
readonly ProductionInfo production;
ProductionQueue[] queues;
bool buildComplete;
bool IsProducing
{
@@ -53,21 +51,19 @@ namespace OpenRA.Mods.Common.Traits.Render
}
public WithProductionOverlay(Actor self, WithProductionOverlayInfo info)
: base(info)
{
this.info = info;
var rs = self.Trait<RenderSprites>();
var body = self.Trait<BodyOrientation>();
buildComplete = !self.Info.HasTraitInfo<BuildingInfo>(); // always render instantly for units
production = self.Info.TraitInfo<ProductionInfo>();
overlay = new Animation(self.World, rs.GetImage(self));
overlay = new Animation(self.World, rs.GetImage(self), () => IsTraitPaused);
overlay.PlayRepeating(info.Sequence);
var anim = new AnimationWithOffset(overlay,
() => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))),
() => !IsProducing || !buildComplete);
() => !IsProducing || IsTraitDisabled);
rs.Add(anim, info.Palette, info.IsPlayerPalette);
}
@@ -77,7 +73,7 @@ namespace OpenRA.Mods.Common.Traits.Render
// Per-actor production
queues = self.TraitsImplementing<ProductionQueue>()
.Where(q => production.Produces.Contains(q.Info.Type))
.Where(q => !info.Queues.Any() || info.Queues.Contains(q.Info.Type))
.Where(q => !Info.Queues.Any() || Info.Queues.Contains(q.Info.Type))
.ToArray();
if (!queues.Any())
@@ -85,20 +81,13 @@ namespace OpenRA.Mods.Common.Traits.Render
// Player-wide production
queues = self.Owner.PlayerActor.TraitsImplementing<ProductionQueue>()
.Where(q => production.Produces.Contains(q.Info.Type))
.Where(q => !info.Queues.Any() || info.Queues.Contains(q.Info.Type))
.Where(q => !Info.Queues.Any() || Info.Queues.Contains(q.Info.Type))
.ToArray();
}
}
void INotifyCreated.Created(Actor self)
protected override void TraitEnabled(Actor self)
{
if (buildComplete)
CacheQueues(self);
}
void INotifyBuildComplete.BuildingComplete(Actor self)
{
buildComplete = true;
CacheQueues(self);
}
@@ -107,12 +96,6 @@ namespace OpenRA.Mods.Common.Traits.Render
self.World.AddFrameEndTask(w => CacheQueues(self));
}
void INotifySold.Sold(Actor self) { }
void INotifySold.Selling(Actor self)
{
buildComplete = false;
}
void INotifyDamageStateChanged.DamageStateChanged(Actor self, AttackInfo e)
{
overlay.ReplaceAnim(RenderSprites.NormalizeSequence(overlay, e.DamageState, overlay.CurrentSequence.Name));

View File

@@ -39,10 +39,9 @@ namespace OpenRA.Mods.Common.Traits.Render
public override object Create(ActorInitializer init) { return new WithRepairOverlay(init.Self, this); }
}
public class WithRepairOverlay : PausableConditionalTrait<WithRepairOverlayInfo>, INotifyDamageStateChanged, INotifyBuildComplete, INotifySold, INotifyRepair
public class WithRepairOverlay : PausableConditionalTrait<WithRepairOverlayInfo>, INotifyDamageStateChanged, INotifyRepair
{
readonly Animation overlay;
bool buildComplete;
bool visible;
public WithRepairOverlay(Actor self, WithRepairOverlayInfo info)
@@ -51,29 +50,17 @@ namespace OpenRA.Mods.Common.Traits.Render
var rs = self.Trait<RenderSprites>();
var body = self.Trait<BodyOrientation>();
buildComplete = !self.Info.HasTraitInfo<BuildingInfo>(); // always render instantly for units
overlay = new Animation(self.World, rs.GetImage(self), () => IsTraitPaused);
overlay.PlayThen(info.Sequence, () => visible = false);
var anim = new AnimationWithOffset(overlay,
() => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))),
() => IsTraitDisabled || !visible || !buildComplete,
() => IsTraitDisabled || !visible,
p => RenderUtils.ZOffsetFromCenter(self, p, 1));
rs.Add(anim, info.Palette, info.IsPlayerPalette);
}
void INotifyBuildComplete.BuildingComplete(Actor self)
{
buildComplete = true;
}
void INotifySold.Sold(Actor self) { }
void INotifySold.Selling(Actor self)
{
buildComplete = false;
}
void INotifyDamageStateChanged.DamageStateChanged(Actor self, AttackInfo e)
{
overlay.ReplaceAnim(RenderSprites.NormalizeSequence(overlay, e.DamageState, overlay.CurrentSequence.Name));

View File

@@ -15,27 +15,26 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits.Render
{
[Desc("Displays the fill status of PlayerResources with an extra sprite overlay on the actor.")]
class WithResourcesInfo : ITraitInfo, Requires<WithSpriteBodyInfo>, Requires<RenderSpritesInfo>
class WithResourcesInfo : ConditionalTraitInfo, Requires<WithSpriteBodyInfo>, Requires<RenderSpritesInfo>
{
[Desc("Sequence name to use")]
[SequenceReference] public readonly string Sequence = "resources";
public object Create(ActorInitializer init) { return new WithResources(init.Self, this); }
public override object Create(ActorInitializer init) { return new WithResources(init.Self, this); }
}
class WithResources : INotifyBuildComplete, INotifySold, INotifyOwnerChanged, INotifyDamageStateChanged
// TODO: Rename to WithResourcesOverlay to conform with our naming conventions
class WithResources : ConditionalTrait<WithResourcesInfo>, INotifyOwnerChanged, INotifyDamageStateChanged
{
readonly WithResourcesInfo info;
readonly AnimationWithOffset anim;
readonly RenderSprites rs;
readonly WithSpriteBody wsb;
PlayerResources playerResources;
bool buildComplete;
public WithResources(Actor self, WithResourcesInfo info)
: base(info)
{
this.info = info;
rs = self.Trait<RenderSprites>();
wsb = self.Trait<WithSpriteBody>();
playerResources = self.Owner.PlayerActor.Trait<PlayerResources>();
@@ -46,27 +45,19 @@ namespace OpenRA.Mods.Common.Traits.Render
((10 * a.CurrentSequence.Length - 1) * playerResources.Resources) / (10 * playerResources.ResourceCapacity) :
0);
anim = new AnimationWithOffset(a, null, () => !buildComplete, 1024);
anim = new AnimationWithOffset(a, null, () => IsTraitDisabled, 1024);
rs.Add(anim);
}
void INotifyBuildComplete.BuildingComplete(Actor self)
{
buildComplete = true;
}
void INotifyDamageStateChanged.DamageStateChanged(Actor self, AttackInfo e)
{
if (anim.Animation.CurrentSequence != null)
anim.Animation.ReplaceAnim(wsb.NormalizeSequence(self, info.Sequence));
anim.Animation.ReplaceAnim(wsb.NormalizeSequence(self, Info.Sequence));
}
void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner)
{
playerResources = newOwner.PlayerActor.Trait<PlayerResources>();
}
void INotifySold.Selling(Actor self) { rs.Remove(anim); }
void INotifySold.Sold(Actor self) { }
}
}

View File

@@ -37,10 +37,9 @@ namespace OpenRA.Mods.Common.Traits.Render
public override object Create(ActorInitializer init) { return new WithResupplyAnimation(init.Self, this); }
}
public class WithResupplyAnimation : ConditionalTrait<WithResupplyAnimationInfo>, INotifyRepair, INotifyRearm, INotifyBuildComplete, INotifySold, ITick
public class WithResupplyAnimation : ConditionalTrait<WithResupplyAnimationInfo>, INotifyRepair, INotifyRearm, ITick
{
readonly WithSpriteBody spriteBody;
bool buildComplete;
readonly WithSpriteBody wsb;
bool animPlaying;
bool repairing;
bool rearming;
@@ -48,26 +47,26 @@ namespace OpenRA.Mods.Common.Traits.Render
public WithResupplyAnimation(Actor self, WithResupplyAnimationInfo info)
: base(info)
{
spriteBody = self.TraitsImplementing<WithSpriteBody>().Single(w => w.Info.Name == Info.Body);
wsb = self.TraitsImplementing<WithSpriteBody>().Single(w => w.Info.Name == Info.Body);
}
void ITick.Tick(Actor self)
{
if (!buildComplete || IsTraitDisabled)
if (IsTraitDisabled)
return;
if (!animPlaying
&& ((repairing && Info.PlayAnimationOn.HasFlag(ResupplyType.Repair))
|| (rearming && Info.PlayAnimationOn.HasFlag(ResupplyType.Rearm))))
{
spriteBody.PlayCustomAnimationRepeating(self, Info.Sequence);
wsb.PlayCustomAnimationRepeating(self, Info.Sequence);
animPlaying = true;
}
else if (animPlaying
&& (!repairing || !Info.PlayAnimationOn.HasFlag(ResupplyType.Repair))
&& (!rearming || !Info.PlayAnimationOn.HasFlag(ResupplyType.Rearm)))
{
spriteBody.CancelCustomAnimation(self);
wsb.CancelCustomAnimation(self);
animPlaying = false;
}
}
@@ -96,16 +95,11 @@ namespace OpenRA.Mods.Common.Traits.Render
rearming = false;
}
void INotifyBuildComplete.BuildingComplete(Actor self)
protected override void TraitDisabled(Actor self)
{
buildComplete = true;
}
void INotifySold.Selling(Actor self)
{
buildComplete = false;
}
void INotifySold.Sold(Actor self) { }
// Cancel immediately instead of waiting for the next tick
repairing = rearming = animPlaying = false;
wsb.CancelCustomAnimation(self);
}
}
}

View File

@@ -15,7 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits.Render
{
[Desc("Render trait for buildings that change the sprite according to the remaining resource storage capacity across all depots.")]
class WithSiloAnimationInfo : ITraitInfo, Requires<WithSpriteBodyInfo>, Requires<RenderSpritesInfo>
class WithSiloAnimationInfo : ConditionalTraitInfo, Requires<WithSpriteBodyInfo>, Requires<RenderSpritesInfo>
{
[Desc("Sequence to use for resources-dependent 'stages'."), SequenceReference]
public readonly string Sequence = "stages";
@@ -26,38 +26,35 @@ namespace OpenRA.Mods.Common.Traits.Render
[Desc("Which sprite body to play the animation on.")]
public readonly string Body = "body";
public object Create(ActorInitializer init) { return new WithSiloAnimation(init, this); }
public override object Create(ActorInitializer init) { return new WithSiloAnimation(init, this); }
}
class WithSiloAnimation : INotifyBuildComplete, INotifyOwnerChanged
class WithSiloAnimation : ConditionalTrait<WithSiloAnimationInfo>, INotifyOwnerChanged
{
readonly WithSiloAnimationInfo info;
readonly WithSpriteBody wsb;
PlayerResources playerResources;
public WithSiloAnimation(ActorInitializer init, WithSiloAnimationInfo info)
: base(info)
{
this.info = info;
wsb = init.Self.TraitsImplementing<WithSpriteBody>().Single(w => w.Info.Name == info.Body);
playerResources = init.Self.Owner.PlayerActor.Trait<PlayerResources>();
}
void INotifyBuildComplete.BuildingComplete(Actor self)
void PlayAnimation(Actor self)
{
wsb.DefaultAnimation.PlayFetchIndex(wsb.NormalizeSequence(self, info.Sequence),
wsb.DefaultAnimation.PlayFetchIndex(wsb.NormalizeSequence(self, Info.Sequence),
() => playerResources.ResourceCapacity != 0
? ((info.Stages * wsb.DefaultAnimation.CurrentSequence.Length - 1) * playerResources.Resources) / (info.Stages * playerResources.ResourceCapacity)
? ((Info.Stages * wsb.DefaultAnimation.CurrentSequence.Length - 1) * playerResources.Resources) / (Info.Stages * playerResources.ResourceCapacity)
: 0);
}
void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner)
{
playerResources = newOwner.PlayerActor.Trait<PlayerResources>();
PlayAnimation(self);
}
wsb.DefaultAnimation.PlayFetchIndex(wsb.NormalizeSequence(self, info.Sequence),
() => playerResources.ResourceCapacity != 0
? ((info.Stages * wsb.DefaultAnimation.CurrentSequence.Length - 1) * playerResources.Resources) / (info.Stages * playerResources.ResourceCapacity)
: 0);
}
protected override void TraitEnabled(Actor self) { PlayAnimation(self); }
}
}

View File

@@ -44,7 +44,7 @@ namespace OpenRA.Mods.Common.Traits.Render
}
}
public class WithSpriteBody : PausableConditionalTrait<WithSpriteBodyInfo>, INotifyDamageStateChanged, INotifyBuildComplete, IAutoMouseBounds
public class WithSpriteBody : PausableConditionalTrait<WithSpriteBodyInfo>, INotifyDamageStateChanged, IAutoMouseBounds
{
public readonly Animation DefaultAnimation;
readonly RenderSprites rs;
@@ -80,17 +80,11 @@ namespace OpenRA.Mods.Common.Traits.Render
return RenderSprites.NormalizeSequence(DefaultAnimation, self.GetDamageState(), sequence);
}
protected virtual void OnBuildComplete(Actor self)
protected override void TraitEnabled(Actor self)
{
DefaultAnimation.PlayRepeating(NormalizeSequence(self, Info.Sequence));
}
// TODO: Get rid of INotifyBuildComplete in favor of using the condition system
void INotifyBuildComplete.BuildingComplete(Actor self)
{
OnBuildComplete(self);
}
public void PlayCustomAnimation(Actor self, string name, Action after = null)
{
DefaultAnimation.PlayThen(NormalizeSequence(self, name), () =>

View File

@@ -70,7 +70,7 @@ namespace OpenRA.Mods.Common.Traits.Render
}
}
public class WithSpriteTurret : ConditionalTrait<WithSpriteTurretInfo>, INotifyBuildComplete, INotifySold, INotifyTransform, INotifyDamageStateChanged
public class WithSpriteTurret : ConditionalTrait<WithSpriteTurretInfo>, INotifyDamageStateChanged
{
public readonly Animation DefaultAnimation;
readonly RenderSprites rs;
@@ -78,9 +78,6 @@ namespace OpenRA.Mods.Common.Traits.Render
readonly Turreted t;
readonly Armament[] arms;
// TODO: This should go away once https://github.com/OpenRA/OpenRA/issues/7035 is implemented
bool buildComplete;
public WithSpriteTurret(Actor self, WithSpriteTurretInfo info)
: base(info)
{
@@ -90,13 +87,12 @@ namespace OpenRA.Mods.Common.Traits.Render
.First(tt => tt.Name == info.Turret);
arms = self.TraitsImplementing<Armament>()
.Where(w => w.Info.Turret == info.Turret).ToArray();
buildComplete = !self.Info.HasTraitInfo<BuildingInfo>(); // always render instantly for units
DefaultAnimation = new Animation(self.World, rs.GetImage(self), () => t.TurretFacing);
DefaultAnimation.PlayRepeating(NormalizeSequence(self, info.Sequence));
rs.Add(new AnimationWithOffset(DefaultAnimation,
() => TurretOffset(self),
() => IsTraitDisabled || !buildComplete,
() => IsTraitDisabled,
p => RenderUtils.ZOffsetFromCenter(self, p, 1)), info.Palette, info.IsPlayerPalette);
// Restrict turret facings to match the sprite
@@ -144,12 +140,5 @@ namespace OpenRA.Mods.Common.Traits.Render
{
DefaultAnimation.PlayRepeating(NormalizeSequence(self, Info.Sequence));
}
void INotifyBuildComplete.BuildingComplete(Actor self) { buildComplete = true; }
void INotifySold.Selling(Actor self) { buildComplete = false; }
void INotifySold.Sold(Actor self) { }
void INotifyTransform.BeforeTransform(Actor self) { buildComplete = false; }
void INotifyTransform.OnTransform(Actor self) { }
void INotifyTransform.AfterTransform(Actor toActor) { }
}
}

View File

@@ -63,16 +63,13 @@ namespace OpenRA.Mods.Common.Traits.Render
}
}
public class WithVoxelBarrel : ConditionalTrait<WithVoxelBarrelInfo>, INotifyBuildComplete, INotifySold, INotifyTransform
public class WithVoxelBarrel : ConditionalTrait<WithVoxelBarrelInfo>
{
readonly Actor self;
readonly Armament armament;
readonly Turreted turreted;
readonly BodyOrientation body;
// TODO: This should go away once https://github.com/OpenRA/OpenRA/issues/7035 is implemented
bool buildComplete;
public WithVoxelBarrel(Actor self, WithVoxelBarrelInfo info)
: base(info)
{
@@ -83,12 +80,10 @@ namespace OpenRA.Mods.Common.Traits.Render
turreted = self.TraitsImplementing<Turreted>()
.First(tt => tt.Name == armament.Info.Turret);
buildComplete = !self.Info.HasTraitInfo<BuildingInfo>(); // always render instantly for units
var rv = self.Trait<RenderVoxels>();
rv.Add(new ModelAnimation(self.World.ModelCache.GetModelSequence(rv.Image, Info.Sequence),
BarrelOffset, BarrelRotation,
() => IsTraitDisabled || !buildComplete, () => 0, info.ShowShadow));
() => IsTraitDisabled, () => 0, info.ShowShadow));
}
WVec BarrelOffset()
@@ -110,12 +105,5 @@ namespace OpenRA.Mods.Common.Traits.Render
yield return turreted.WorldOrientation(self) - b + WRot.FromYaw(b.Yaw - qb.Yaw);
yield return qb;
}
void INotifyBuildComplete.BuildingComplete(Actor self) { buildComplete = true; }
void INotifySold.Selling(Actor self) { buildComplete = false; }
void INotifySold.Sold(Actor self) { }
void INotifyTransform.BeforeTransform(Actor self) { buildComplete = false; }
void INotifyTransform.OnTransform(Actor self) { }
void INotifyTransform.AfterTransform(Actor toActor) { }
}
}

View File

@@ -51,15 +51,12 @@ namespace OpenRA.Mods.Common.Traits.Render
}
}
public class WithVoxelTurret : ConditionalTrait<WithVoxelTurretInfo>, INotifyBuildComplete, INotifySold, INotifyTransform
public class WithVoxelTurret : ConditionalTrait<WithVoxelTurretInfo>
{
readonly Actor self;
readonly Turreted turreted;
readonly BodyOrientation body;
// TODO: This should go away once https://github.com/OpenRA/OpenRA/issues/7035 is implemented
bool buildComplete;
public WithVoxelTurret(Actor self, WithVoxelTurretInfo info)
: base(info)
{
@@ -67,12 +64,11 @@ namespace OpenRA.Mods.Common.Traits.Render
body = self.Trait<BodyOrientation>();
turreted = self.TraitsImplementing<Turreted>()
.First(tt => tt.Name == Info.Turret);
buildComplete = !self.Info.HasTraitInfo<BuildingInfo>(); // always render instantly for units
var rv = self.Trait<RenderVoxels>();
rv.Add(new ModelAnimation(self.World.ModelCache.GetModelSequence(rv.Image, Info.Sequence),
() => turreted.Position(self), TurretRotation,
() => IsTraitDisabled || !buildComplete, () => 0, info.ShowShadow));
() => IsTraitDisabled, () => 0, info.ShowShadow));
}
IEnumerable<WRot> TurretRotation()
@@ -82,12 +78,5 @@ namespace OpenRA.Mods.Common.Traits.Render
yield return turreted.WorldOrientation(self) - b + WRot.FromYaw(b.Yaw - qb.Yaw);
yield return qb;
}
void INotifyBuildComplete.BuildingComplete(Actor self) { buildComplete = true; }
void INotifySold.Selling(Actor self) { buildComplete = false; }
void INotifySold.Sold(Actor self) { }
void INotifyTransform.BeforeTransform(Actor self) { buildComplete = false; }
void INotifyTransform.OnTransform(Actor self) { }
void INotifyTransform.AfterTransform(Actor toActor) { }
}
}

View File

@@ -139,8 +139,11 @@ namespace OpenRA.Mods.Common.Traits.Render
dirty = false;
}
protected override void OnBuildComplete(Actor self)
protected override void TraitEnabled(Actor self)
{
base.TraitEnabled(self);
dirty = true;
DefaultAnimation.PlayFetchIndex(NormalizeSequence(self, Info.Sequence), () => adjacent);
UpdateNeighbours(self);
@@ -162,8 +165,6 @@ namespace OpenRA.Mods.Common.Traits.Render
{
UpdateNeighbours(self);
}
protected override void TraitEnabled(Actor self) { dirty = true; }
}
public class RuntimeNeighbourInit : IActorInit<Dictionary<CPos, string[]>>, ISuppressInitExport

View File

@@ -17,7 +17,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.D2k.Traits.Render
{
[Desc("Rendered together with the \"make\" animation.")]
public class WithCrumbleOverlayInfo : ITraitInfo, Requires<RenderSpritesInfo>
public class WithCrumbleOverlayInfo : ConditionalTraitInfo, Requires<RenderSpritesInfo>
{
[Desc("Sequence name to use")]
[SequenceReference] public readonly string Sequence = "crumble-overlay";
@@ -28,14 +28,13 @@ namespace OpenRA.Mods.D2k.Traits.Render
[Desc("Custom palette is a player palette BaseName")]
public readonly bool IsPlayerPalette = false;
public object Create(ActorInitializer init) { return new WithCrumbleOverlay(init, this); }
public override object Create(ActorInitializer init) { return new WithCrumbleOverlay(init, this); }
}
public class WithCrumbleOverlay : INotifyBuildComplete
public class WithCrumbleOverlay : ConditionalTrait<WithCrumbleOverlayInfo>
{
bool buildComplete = false;
public WithCrumbleOverlay(ActorInitializer init, WithCrumbleOverlayInfo info)
: base(info)
{
if (init.Contains<SkipMakeAnimsInit>())
return;
@@ -43,17 +42,12 @@ namespace OpenRA.Mods.D2k.Traits.Render
var rs = init.Self.Trait<RenderSprites>();
var overlay = new Animation(init.World, rs.GetImage(init.Self));
var anim = new AnimationWithOffset(overlay, null, () => !buildComplete);
var anim = new AnimationWithOffset(overlay, null, () => IsTraitDisabled);
// Remove the animation once it is complete
overlay.PlayThen(info.Sequence, () => init.World.AddFrameEndTask(w => rs.Remove(anim)));
rs.Add(anim, info.Palette, info.IsPlayerPalette);
}
void INotifyBuildComplete.BuildingComplete(Actor self)
{
buildComplete = true;
}
}
}

View File

@@ -18,7 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.D2k.Traits.Render
{
[Desc("Rendered when ProductionAirdrop is in progress.")]
public class WithDeliveryOverlayInfo : ITraitInfo, Requires<RenderSpritesInfo>, Requires<BodyOrientationInfo>
public class WithDeliveryOverlayInfo : PausableConditionalTraitInfo, Requires<RenderSpritesInfo>, Requires<BodyOrientationInfo>
{
[Desc("Sequence name to use")]
[SequenceReference] public readonly string Sequence = "active";
@@ -32,28 +32,21 @@ namespace OpenRA.Mods.D2k.Traits.Render
[Desc("Custom palette is a player palette BaseName")]
public readonly bool IsPlayerPalette = false;
public object Create(ActorInitializer init) { return new WithDeliveryOverlay(init.Self, this); }
public override object Create(ActorInitializer init) { return new WithDeliveryOverlay(init.Self, this); }
}
public class WithDeliveryOverlay : INotifyBuildComplete, INotifySold, INotifyDelivery
public class WithDeliveryOverlay : PausableConditionalTrait<WithDeliveryOverlayInfo>, INotifyDelivery
{
readonly WithDeliveryOverlayInfo info;
readonly AnimationWithOffset anim;
bool buildComplete;
bool delivering;
public WithDeliveryOverlay(Actor self, WithDeliveryOverlayInfo info)
: base(info)
{
this.info = info;
var rs = self.Trait<RenderSprites>();
var body = self.Trait<BodyOrientation>();
// always render instantly for units
buildComplete = !self.Info.HasTraitInfo<BuildingInfo>();
var overlay = new Animation(self.World, rs.GetImage(self));
var overlay = new Animation(self.World, rs.GetImage(self), () => IsTraitPaused);
overlay.Play(info.Sequence);
// These translucent overlays should not be included in highlight flashes
@@ -61,7 +54,7 @@ namespace OpenRA.Mods.D2k.Traits.Render
anim = new AnimationWithOffset(overlay,
() => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))),
() => !buildComplete || !delivering);
() => IsTraitDisabled || !delivering);
rs.Add(anim, info.Palette, info.IsPlayerPalette);
}
@@ -69,18 +62,7 @@ namespace OpenRA.Mods.D2k.Traits.Render
void PlayDeliveryOverlay()
{
if (delivering)
anim.Animation.PlayThen(info.Sequence, PlayDeliveryOverlay);
}
void INotifyBuildComplete.BuildingComplete(Actor self)
{
buildComplete = true;
}
void INotifySold.Sold(Actor self) { }
void INotifySold.Selling(Actor self)
{
buildComplete = false;
anim.Animation.PlayThen(Info.Sequence, PlayDeliveryOverlay);
}
void INotifyDelivery.IncomingDelivery(Actor self) { delivering = true; PlayDeliveryOverlay(); }