Add clock overlay to support power beacons.

This commit is contained in:
Paul Chote
2014-05-31 18:17:48 +12:00
parent 91126b9c48
commit e1501d5b7c
9 changed files with 83 additions and 38 deletions

View File

@@ -8,6 +8,7 @@
*/ */
#endregion #endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.Effects; using OpenRA.Effects;
@@ -24,16 +25,18 @@ namespace OpenRA.Mods.RA.Effects
readonly Animation arrow; readonly Animation arrow;
readonly Animation circles; readonly Animation circles;
readonly Animation poster; readonly Animation poster;
readonly Animation clock;
static readonly int maxArrowHeight = 512; static readonly int maxArrowHeight = 512;
int arrowHeight = maxArrowHeight; int arrowHeight = maxArrowHeight;
int arrowSpeed = 50; int arrowSpeed = 50;
public Beacon(Player owner, WPos position, int duration, string palettePrefix, string posterType, string posterPalette) // Player-placed beacons are removed after a delay
public Beacon(Player owner, WPos position, int duration, string palettePrefix)
{ {
this.owner = owner; this.owner = owner;
this.position = position; this.position = position;
this.palettePrefix = palettePrefix; this.palettePrefix = palettePrefix;
this.posterPalette = posterPalette;
arrow = new Animation(owner.World, "beacon"); arrow = new Animation(owner.World, "beacon");
circles = new Animation(owner.World, "beacon"); circles = new Animation(owner.World, "beacon");
@@ -41,14 +44,27 @@ namespace OpenRA.Mods.RA.Effects
arrow.Play("arrow"); arrow.Play("arrow");
circles.Play("circles"); circles.Play("circles");
if (duration > 0)
owner.World.Add(new DelayedAction(duration, () => owner.World.Remove(this)));
}
// Support power beacons are expected to clean themselves up
public Beacon(Player owner, WPos position, string palettePrefix, string posterType, string posterPalette, Func<float> clockFraction)
: this(owner, position, -1, palettePrefix)
{
this.posterPalette = posterPalette;
if (posterType != null) if (posterType != null)
{ {
poster = new Animation(owner.World, "beacon"); poster = new Animation(owner.World, "beacon");
poster.Play(posterType); poster.Play(posterType);
}
if (duration > 0) if (clockFraction != null)
owner.World.Add(new DelayedAction(duration, () => owner.World.Remove(this))); {
clock = new Animation(owner.World, "beacon");
clock.PlayFetchIndex("clock", () => Exts.Clamp((int)(clockFraction() * (clock.CurrentSequence.Length - 1)), 0, clock.CurrentSequence.Length - 1));
}
}
} }
public void Tick(World world) public void Tick(World world)
@@ -63,6 +79,9 @@ namespace OpenRA.Mods.RA.Effects
arrow.Tick(); arrow.Tick();
circles.Tick(); circles.Tick();
if (clock != null)
clock.Tick();
} }
public IEnumerable<IRenderable> Render(WorldRenderer r) public IEnumerable<IRenderable> Render(WorldRenderer r)
@@ -78,8 +97,14 @@ namespace OpenRA.Mods.RA.Effects
yield return a; yield return a;
if (poster != null) if (poster != null)
{
foreach (var a in poster.Render(position, r.Palette(posterPalette))) foreach (var a in poster.Render(position, r.Palette(posterPalette)))
yield return a; yield return a;
if (clock != null)
foreach (var a in clock.Render(position, r.Palette(posterPalette)))
yield return a;
}
} }
} }
} }

View File

@@ -90,5 +90,7 @@ namespace OpenRA.Mods.RA.Effects
{ {
return anim.Render(pos, wr.Palette("effect")); return anim.Render(pos, wr.Palette("effect"));
} }
public float FractionComplete { get { return ticks * 1f / delay; } }
} }
} }

View File

@@ -49,7 +49,7 @@ namespace OpenRA.Mods.RA
if (playerBeacon != null) if (playerBeacon != null)
self.World.Remove(playerBeacon); self.World.Remove(playerBeacon);
playerBeacon = new Beacon(self.Owner, pos, info.Duration, info.PalettePrefix, null, null); playerBeacon = new Beacon(self.Owner, pos, info.Duration, info.PalettePrefix);
self.World.Add(playerBeacon); self.World.Add(playerBeacon);
if (self.Owner.IsAlliedWith(self.World.RenderPlayer)) if (self.Owner.IsAlliedWith(self.World.RenderPlayer))

View File

@@ -43,6 +43,9 @@ namespace OpenRA.Mods.RA
[Desc("Amount of time to keep the camera alive after the aircraft have finished attacking")] [Desc("Amount of time to keep the camera alive after the aircraft have finished attacking")]
public readonly int CameraRemoveDelay = 25; public readonly int CameraRemoveDelay = 25;
[Desc("Weapon range offset to apply during the beacon clock calculation")]
public readonly WRange BeaconDistanceOffset = WRange.FromCells(6);
public override object Create(ActorInitializer init) { return new AirstrikePower(init.self, this); } public override object Create(ActorInitializer init) { return new AirstrikePower(init.self, this); }
} }
@@ -55,20 +58,6 @@ namespace OpenRA.Mods.RA
{ {
base.Activate(self, order, manager); base.Activate(self, order, manager);
Beacon beacon = null;
if (Info.DisplayBeacon)
{
beacon = new Beacon(
order.Player,
order.TargetLocation.CenterPosition,
-1,
Info.BeaconPalettePrefix,
Info.BeaconPoster,
Info.BeaconPosterPalette);
self.World.Add(beacon);
}
var info = Info as AirstrikePowerInfo; var info = Info as AirstrikePowerInfo;
var attackFacing = Util.QuantizeFacing(self.World.SharedRandom.Next(256), info.QuantizedFacings) * (256 / info.QuantizedFacings); var attackFacing = Util.QuantizeFacing(self.World.SharedRandom.Next(256), info.QuantizedFacings) * (256 / info.QuantizedFacings);
var attackRotation = WRot.FromFacing(attackFacing); var attackRotation = WRot.FromFacing(attackFacing);
@@ -81,6 +70,7 @@ namespace OpenRA.Mods.RA
Actor flare = null; Actor flare = null;
Actor camera = null; Actor camera = null;
Beacon beacon = null;
Dictionary<Actor, bool> aircraftInRange = new Dictionary<Actor, bool>(); Dictionary<Actor, bool> aircraftInRange = new Dictionary<Actor, bool>();
Action<Actor> onEnterRange = a => Action<Actor> onEnterRange = a =>
@@ -147,6 +137,7 @@ namespace OpenRA.Mods.RA
var notification = self.Owner.IsAlliedWith(self.World.RenderPlayer) ? Info.LaunchSound : Info.IncomingSound; var notification = self.Owner.IsAlliedWith(self.World.RenderPlayer) ? Info.LaunchSound : Info.IncomingSound;
Sound.Play(notification); Sound.Play(notification);
Actor distanceTestActor = null;
for (var i = -info.SquadSize / 2; i <= info.SquadSize / 2; i++) for (var i = -info.SquadSize / 2; i <= info.SquadSize / 2; i++)
{ {
// Even-sized squads skip the lead plane // Even-sized squads skip the lead plane
@@ -174,6 +165,23 @@ namespace OpenRA.Mods.RA
a.QueueActivity(new Fly(a, Target.FromPos(finishEdge + spawnOffset))); a.QueueActivity(new Fly(a, Target.FromPos(finishEdge + spawnOffset)));
a.QueueActivity(new RemoveSelf()); a.QueueActivity(new RemoveSelf());
aircraftInRange.Add(a, false); aircraftInRange.Add(a, false);
distanceTestActor = a;
}
if (Info.DisplayBeacon)
{
var distance = (target - startEdge).HorizontalLength;
beacon = new Beacon(
order.Player,
order.TargetLocation.CenterPosition,
Info.BeaconPalettePrefix,
Info.BeaconPoster,
Info.BeaconPosterPalette,
() => 1 - ((distanceTestActor.CenterPosition - target).HorizontalLength - info.BeaconDistanceOffset.Range) * 1f / distance
);
w.Add(beacon);
} }
}); });
} }

View File

@@ -68,20 +68,6 @@ namespace OpenRA.Mods.RA
{ {
base.Activate(self, order, manager); base.Activate(self, order, manager);
Beacon beacon = null;
if (Info.DisplayBeacon)
{
beacon = new Beacon(
order.Player,
order.TargetLocation.CenterPosition,
-1,
Info.BeaconPalettePrefix,
Info.BeaconPoster,
Info.BeaconPosterPalette);
self.World.Add(beacon);
}
if (self.Owner.IsAlliedWith(self.World.RenderPlayer)) if (self.Owner.IsAlliedWith(self.World.RenderPlayer))
Sound.Play(Info.LaunchSound); Sound.Play(Info.LaunchSound);
else else
@@ -91,10 +77,12 @@ namespace OpenRA.Mods.RA
var rb = self.Trait<RenderSimple>(); var rb = self.Trait<RenderSimple>();
rb.PlayCustomAnim(self, "active"); rb.PlayCustomAnim(self, "active");
self.World.AddFrameEndTask(w => w.Add(new NukeLaunch(self.Owner, npi.MissileWeapon, var missile = new NukeLaunch(self.Owner, npi.MissileWeapon,
self.CenterPosition + body.LocalToWorld(npi.SpawnOffset), self.CenterPosition + body.LocalToWorld(npi.SpawnOffset),
order.TargetLocation.CenterPosition, order.TargetLocation.CenterPosition,
npi.FlightVelocity, npi.FlightDelay, npi.SkipAscent))); npi.FlightVelocity, npi.FlightDelay, npi.SkipAscent);
self.World.AddFrameEndTask(w => w.Add(missile));
if (npi.CameraActor != null) if (npi.CameraActor != null)
{ {
@@ -111,15 +99,29 @@ namespace OpenRA.Mods.RA
self.World.AddFrameEndTask(w => w.Add(new DelayedAction(npi.FlightDelay - npi.CameraSpawnAdvance, addCamera))); self.World.AddFrameEndTask(w => w.Add(new DelayedAction(npi.FlightDelay - npi.CameraSpawnAdvance, addCamera)));
} }
if (beacon != null) if (Info.DisplayBeacon)
{ {
var beacon = new Beacon(
order.Player,
order.TargetLocation.CenterPosition,
Info.BeaconPalettePrefix,
Info.BeaconPoster,
Info.BeaconPosterPalette,
() => missile.FractionComplete
);
Action removeBeacon = () => self.World.AddFrameEndTask(w => Action removeBeacon = () => self.World.AddFrameEndTask(w =>
{ {
w.Remove(beacon); w.Remove(beacon);
beacon = null; beacon = null;
}); });
self.World.AddFrameEndTask(w => w.Add(new DelayedAction(npi.FlightDelay - npi.BeaconRemoveAdvance, removeBeacon))); self.World.AddFrameEndTask(w =>
{
w.Add(beacon);
w.Add(new DelayedAction(npi.FlightDelay - npi.BeaconRemoveAdvance, removeBeacon));
});
} }
} }
} }

Binary file not shown.

View File

@@ -169,6 +169,10 @@ beacon:
Start: 0 Start: 0
Length: 1 Length: 1
Offset: 0,-42 Offset: 0,-42
clock: beaconclock
Start: 0
Length: *
Offset: 0,-42
select: select:
repair: repair:

Binary file not shown.

View File

@@ -125,6 +125,10 @@ beacon:
Start: 0 Start: 0
Length: * Length: *
Offset: 0,-42 Offset: 0,-42
clock: beaconclock
Start: 0
Length: *
Offset: 0,-42
smoke_m: smoke_m:
idle: idle: