Moves SupportPowers and related Widgets to Mods.Common

This commit is contained in:
reaperrr
2015-01-11 12:29:19 +01:00
parent f897a9ff01
commit be9d37f30e
20 changed files with 37 additions and 41 deletions

View File

@@ -0,0 +1,182 @@
#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 System.Collections.Generic;
using System.Linq;
using OpenRA.Mods.Common.Activities;
using OpenRA.Mods.Common.Effects;
using OpenRA.Mods.Common.Traits;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
public class AirstrikePowerInfo : SupportPowerInfo
{
[ActorReference]
public readonly string UnitType = "badr.bomber";
public readonly int SquadSize = 1;
public readonly WVec SquadOffset = new WVec(-1536, 1536, 0);
public readonly int QuantizedFacings = 32;
public readonly WRange Cordon = new WRange(5120);
[ActorReference]
[Desc("Actor to spawn when the aircraft start attacking")]
public readonly string CameraActor = null;
[Desc("Amount of time to keep the camera alive after the aircraft have finished attacking")]
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 class AirstrikePower : SupportPower
{
public AirstrikePower(Actor self, AirstrikePowerInfo info)
: base(self, info) { }
public override void Activate(Actor self, Order order, SupportPowerManager manager)
{
base.Activate(self, order, manager);
SendAirstrike(self, self.World.Map.CenterOfCell(order.TargetLocation));
}
public void SendAirstrike(Actor self, WPos target, bool randomize = true, int attackFacing = 0)
{
var info = Info as AirstrikePowerInfo;
if (randomize)
attackFacing = Util.QuantizeFacing(self.World.SharedRandom.Next(256), info.QuantizedFacings) * (256 / info.QuantizedFacings);
var altitude = self.World.Map.Rules.Actors[info.UnitType].Traits.Get<PlaneInfo>().CruiseAltitude.Range;
var attackRotation = WRot.FromFacing(attackFacing);
var delta = new WVec(0, -1024, 0).Rotate(attackRotation);
target = target + new WVec(0, 0, altitude);
var startEdge = target - (self.World.Map.DistanceToEdge(target, -delta) + info.Cordon).Range * delta / 1024;
var finishEdge = target + (self.World.Map.DistanceToEdge(target, delta) + info.Cordon).Range * delta / 1024;
Actor camera = null;
Beacon beacon = null;
var aircraftInRange = new Dictionary<Actor, bool>();
Action<Actor> onEnterRange = a =>
{
// Spawn a camera and remove the beacon when the first plane enters the target area
if (info.CameraActor != null && !aircraftInRange.Any(kv => kv.Value))
{
self.World.AddFrameEndTask(w =>
{
camera = w.CreateActor(info.CameraActor, new TypeDictionary
{
new LocationInit(self.World.Map.CellContaining(target)),
new OwnerInit(self.Owner),
});
});
}
if (beacon != null)
{
self.World.AddFrameEndTask(w =>
{
w.Remove(beacon);
beacon = null;
});
}
aircraftInRange[a] = true;
};
Action<Actor> onExitRange = a =>
{
aircraftInRange[a] = false;
// Remove the camera when the final plane leaves the target area
if (!aircraftInRange.Any(kv => kv.Value))
{
if (camera != null)
{
camera.QueueActivity(new Wait(info.CameraRemoveDelay));
camera.QueueActivity(new RemoveSelf());
}
camera = null;
if (beacon != null)
{
self.World.AddFrameEndTask(w =>
{
w.Remove(beacon);
beacon = null;
});
}
}
};
self.World.AddFrameEndTask(w =>
{
var notification = self.Owner.IsAlliedWith(self.World.RenderPlayer) ? Info.LaunchSound : Info.IncomingSound;
Sound.Play(notification);
Actor distanceTestActor = null;
for (var i = -info.SquadSize / 2; i <= info.SquadSize / 2; i++)
{
// Even-sized squads skip the lead plane
if (i == 0 && (info.SquadSize & 1) == 0)
continue;
// Includes the 90 degree rotation between body and world coordinates
var so = info.SquadOffset;
var spawnOffset = new WVec(i * so.Y, -Math.Abs(i) * so.X, 0).Rotate(attackRotation);
var targetOffset = new WVec(i * so.Y, 0, 0).Rotate(attackRotation);
var a = w.CreateActor(info.UnitType, new TypeDictionary
{
new CenterPositionInit(startEdge + spawnOffset),
new OwnerInit(self.Owner),
new FacingInit(attackFacing),
});
var attack = a.Trait<AttackBomber>();
attack.SetTarget(w, target + targetOffset);
attack.OnEnteredAttackRange += onEnterRange;
attack.OnExitedAttackRange += onExitRange;
attack.OnRemovedFromWorld += onExitRange;
a.QueueActivity(new Fly(a, Target.FromPos(target + spawnOffset)));
a.QueueActivity(new Fly(a, Target.FromPos(finishEdge + spawnOffset)));
a.QueueActivity(new RemoveSelf());
aircraftInRange.Add(a, false);
distanceTestActor = a;
}
if (Info.DisplayBeacon)
{
var distance = (target - startEdge).HorizontalLength;
beacon = new Beacon(
self.Owner,
target,
Info.BeaconPalettePrefix,
Info.BeaconPoster,
Info.BeaconPosterPalette,
() => 1 - ((distanceTestActor.CenterPosition - target).HorizontalLength - info.BeaconDistanceOffset.Range) * 1f / distance);
w.Add(beacon);
}
});
}
}
}

View File

@@ -0,0 +1,148 @@
#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.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
class GrantUpgradePowerInfo : SupportPowerInfo
{
[Desc("The upgrades to apply.")]
public readonly string[] Upgrades = { };
[Desc("Duration of the upgrade (in ticks). Set to 0 for a permanent upgrade.")]
public readonly int Duration = 0;
[Desc("Cells")]
public readonly int Range = 1;
public readonly string GrantUpgradeSound = "ironcur9.aud";
public override object Create(ActorInitializer init) { return new GrantUpgradePower(init.Self, this); }
}
class GrantUpgradePower : SupportPower
{
GrantUpgradePowerInfo info;
public GrantUpgradePower(Actor self, GrantUpgradePowerInfo info)
: base(self, info)
{
this.info = info;
}
public override IOrderGenerator OrderGenerator(string order, SupportPowerManager manager)
{
Sound.PlayToPlayer(manager.Self.Owner, Info.SelectTargetSound);
return new SelectTarget(Self.World, order, manager, this);
}
public override void Activate(Actor self, Order order, SupportPowerManager manager)
{
base.Activate(self, order, manager);
self.Trait<RenderBuilding>().PlayCustomAnim(self, "active");
Sound.Play(info.GrantUpgradeSound, self.World.Map.CenterOfCell(order.TargetLocation));
foreach (var a in UnitsInRange(order.TargetLocation))
{
var um = a.TraitOrDefault<UpgradeManager>();
if (um == null)
continue;
foreach (var u in info.Upgrades)
{
if (!um.AcceptsUpgrade(a, u))
continue;
if (info.Duration > 0)
um.GrantTimedUpgrade(a, u, info.Duration);
else
um.GrantUpgrade(a, u, this);
}
}
}
public IEnumerable<Actor> UnitsInRange(CPos xy)
{
var range = info.Range;
var tiles = Self.World.Map.FindTilesInCircle(xy, range);
var units = new List<Actor>();
foreach (var t in tiles)
units.AddRange(Self.World.ActorMap.GetUnitsAt(t));
return units.Distinct().Where(a =>
{
if (!a.Owner.IsAlliedWith(Self.Owner))
return false;
var um = a.TraitOrDefault<UpgradeManager>();
return um != null && info.Upgrades.Any(u => um.AcceptsUpgrade(a, u));
});
}
class SelectTarget : IOrderGenerator
{
readonly GrantUpgradePower power;
readonly int range;
readonly Sprite tile;
readonly SupportPowerManager manager;
readonly string order;
public SelectTarget(World world, string order, SupportPowerManager manager, GrantUpgradePower power)
{
this.manager = manager;
this.order = order;
this.power = power;
this.range = power.info.Range;
tile = world.Map.SequenceProvider.GetSequence("overlay", "target-select").GetSprite(0);
}
public IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
{
world.CancelInputMode();
if (mi.Button == MouseButton.Left && power.UnitsInRange(xy).Any())
yield return new Order(order, manager.Self, false) { TargetLocation = xy, SuppressVisualFeedback = true };
}
public void Tick(World world)
{
// Cancel the OG if we can't use the power
if (!manager.Powers.ContainsKey(order))
world.CancelInputMode();
}
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world)
{
var xy = wr.Viewport.ViewToWorld(Viewport.LastMousePos);
foreach (var unit in power.UnitsInRange(xy))
yield return new SelectionBoxRenderable(unit, Color.Red);
}
public IEnumerable<IRenderable> Render(WorldRenderer wr, World world)
{
var xy = wr.Viewport.ViewToWorld(Viewport.LastMousePos);
var pal = wr.Palette("terrain");
foreach (var t in world.Map.FindTilesInCircle(xy, range))
yield return new SpriteRenderable(tile, wr.World.Map.CenterOfCell(t), WVec.Zero, -511, pal, 1f, true);
}
public string GetCursor(World world, CPos xy, MouseInput mi)
{
return power.UnitsInRange(xy).Any() ? "ability" : "move-blocked";
}
}
}
}

View File

@@ -0,0 +1,127 @@
#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.Effects;
using OpenRA.Mods.Common.Activities;
using OpenRA.Mods.Common.Effects;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
class NukePowerInfo : SupportPowerInfo, Requires<IBodyOrientationInfo>
{
[WeaponReference]
public readonly string MissileWeapon = "";
public readonly WVec SpawnOffset = WVec.Zero;
[Desc("Travel time - split equally between ascent and descent")]
public readonly int FlightDelay = 400;
[Desc("Visual ascent velocity in WRange / tick")]
public readonly WRange FlightVelocity = new WRange(512);
[Desc("Descend immediately on the target, with half the FlightDelay")]
public readonly bool SkipAscent = false;
[Desc("Amount of time before detonation to remove the beacon")]
public readonly int BeaconRemoveAdvance = 25;
[ActorReference]
[Desc("Actor to spawn before detonation")]
public readonly string CameraActor = null;
[Desc("Amount of time before detonation to spawn the camera")]
public readonly int CameraSpawnAdvance = 25;
[Desc("Amount of time after detonation to remove the camera")]
public readonly int CameraRemoveDelay = 25;
public override object Create(ActorInitializer init) { return new NukePower(init.Self, this); }
}
class NukePower : SupportPower
{
IBodyOrientation body;
public NukePower(Actor self, NukePowerInfo info)
: base(self, info)
{
body = self.Trait<IBodyOrientation>();
}
public override IOrderGenerator OrderGenerator(string order, SupportPowerManager manager)
{
Sound.PlayToPlayer(manager.Self.Owner, Info.SelectTargetSound);
return new SelectGenericPowerTarget(order, manager, "nuke", MouseButton.Left);
}
public override void Activate(Actor self, Order order, SupportPowerManager manager)
{
base.Activate(self, order, manager);
if (self.Owner.IsAlliedWith(self.World.RenderPlayer))
Sound.Play(Info.LaunchSound);
else
Sound.Play(Info.IncomingSound);
var npi = Info as NukePowerInfo;
var rb = self.Trait<RenderSimple>();
rb.PlayCustomAnim(self, "active");
var targetPosition = self.World.Map.CenterOfCell(order.TargetLocation);
var missile = new NukeLaunch(self.Owner, npi.MissileWeapon,
self.CenterPosition + body.LocalToWorld(npi.SpawnOffset),
targetPosition,
npi.FlightVelocity, npi.FlightDelay, npi.SkipAscent);
self.World.AddFrameEndTask(w => w.Add(missile));
if (npi.CameraActor != null)
{
var camera = self.World.CreateActor(false, npi.CameraActor, new TypeDictionary
{
new LocationInit(order.TargetLocation),
new OwnerInit(self.Owner),
});
camera.QueueActivity(new Wait(npi.CameraSpawnAdvance + npi.CameraRemoveDelay));
camera.QueueActivity(new RemoveSelf());
Action addCamera = () => self.World.AddFrameEndTask(w => w.Add(camera));
self.World.AddFrameEndTask(w => w.Add(new DelayedAction(npi.FlightDelay - npi.CameraSpawnAdvance, addCamera)));
}
if (Info.DisplayBeacon)
{
var beacon = new Beacon(
order.Player,
targetPosition,
Info.BeaconPalettePrefix,
Info.BeaconPoster,
Info.BeaconPosterPalette,
() => missile.FractionComplete);
Action removeBeacon = () => self.World.AddFrameEndTask(w =>
{
w.Remove(beacon);
beacon = null;
});
self.World.AddFrameEndTask(w =>
{
w.Add(beacon);
w.Add(new DelayedAction(npi.FlightDelay - npi.BeaconRemoveAdvance, removeBeacon));
});
}
}
}
}

View File

@@ -0,0 +1,67 @@
#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.Effects;
using OpenRA.Mods.Common.Activities;
using OpenRA.Mods.Common.Effects;
using OpenRA.Primitives;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Spawns an actor that stays for a limited amount of time.")]
public class SpawnActorPowerInfo : SupportPowerInfo
{
[Desc("Actor to spawn.")]
public readonly string Actor = null;
[Desc("Amount of time to keep the actor alive in ticks.")]
public readonly int LifeTime = 250;
public readonly string DeploySound = null;
public readonly string EffectSequence = null;
public readonly string EffectPalette = null;
public override object Create(ActorInitializer init) { return new SpawnActorPower(init.Self, this); }
}
public class SpawnActorPower : SupportPower
{
public SpawnActorPower(Actor self, SpawnActorPowerInfo info) : base(self, info) { }
public override void Activate(Actor self, Order order, SupportPowerManager manager)
{
base.Activate(self, order, manager);
var info = Info as SpawnActorPowerInfo;
if (info.Actor != null)
{
self.World.AddFrameEndTask(w =>
{
var location = self.World.Map.CenterOfCell(order.TargetLocation);
Sound.Play(info.DeploySound, location);
if (!string.IsNullOrEmpty(info.EffectSequence) && !string.IsNullOrEmpty(info.EffectPalette))
w.Add(new SpriteEffect(location, w, info.EffectSequence, info.EffectPalette));
var actor = w.CreateActor(info.Actor, new TypeDictionary
{
new LocationInit(order.TargetLocation),
new OwnerInit(self.Owner),
});
actor.QueueActivity(new Wait(info.LifeTime));
actor.QueueActivity(new RemoveSelf());
});
}
}
}
}

View File

@@ -0,0 +1,89 @@
#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 abstract class SupportPowerInfo : ITraitInfo
{
public readonly int ChargeTime = 0;
public readonly string Icon = null;
public readonly string Description = "";
public readonly string LongDesc = "";
public readonly bool AllowMultiple = false;
public readonly bool OneShot = false;
public readonly string[] Prerequisites = { };
public readonly string BeginChargeSound = null;
public readonly string EndChargeSound = null;
public readonly string SelectTargetSound = null;
public readonly string InsufficientPowerSound = null;
public readonly string LaunchSound = null;
public readonly string IncomingSound = null;
public readonly bool DisplayTimer = false;
[Desc("Beacons are only supported on the Airstrike and Nuke powers")]
public readonly bool DisplayBeacon = false;
public readonly string BeaconPalettePrefix = "player";
public readonly string BeaconPoster = null;
public readonly string BeaconPosterPalette = "chrome";
public readonly bool DisplayRadarPing = false;
public readonly int RadarPingDuration = 5 * 25;
public readonly string OrderName;
public abstract object Create(ActorInitializer init);
public SupportPowerInfo() { OrderName = GetType().Name + "Order"; }
}
public class SupportPower
{
public readonly Actor Self;
public readonly SupportPowerInfo Info;
protected RadarPing ping;
public SupportPower(Actor self, SupportPowerInfo info)
{
Info = info;
Self = self;
}
public virtual void Charging(Actor self, string key)
{
Sound.PlayToPlayer(self.Owner, Info.BeginChargeSound);
}
public virtual void Charged(Actor self, string key)
{
Sound.PlayToPlayer(self.Owner, Info.EndChargeSound);
}
public virtual void Activate(Actor self, Order order, SupportPowerManager manager)
{
if (Info.DisplayRadarPing && manager.RadarPings != null)
{
ping = manager.RadarPings.Value.Add(
() => order.Player.IsAlliedWith(self.World.RenderPlayer),
self.World.Map.CenterOfCell(order.TargetLocation),
order.Player.Color.RGB,
Info.RadarPingDuration);
}
}
public virtual IOrderGenerator OrderGenerator(string order, SupportPowerManager manager)
{
Sound.PlayToPlayer(manager.Self.Owner, Info.SelectTargetSound);
return new SelectGenericPowerTarget(order, manager, "ability", MouseButton.Left);
}
}
}

View File

@@ -0,0 +1,266 @@
#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 System.Collections.Generic;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Attach this to the player actor.")]
public class SupportPowerManagerInfo : ITraitInfo, Requires<DeveloperModeInfo>, Requires<TechTreeInfo>
{
public object Create(ActorInitializer init) { return new SupportPowerManager(init); }
}
public class SupportPowerManager : ITick, IResolveOrder, ITechTreeElement
{
public readonly Actor Self;
public readonly Dictionary<string, SupportPowerInstance> Powers = new Dictionary<string, SupportPowerInstance>();
public readonly DeveloperMode DevMode;
public readonly TechTree TechTree;
public readonly Lazy<RadarPings> RadarPings;
public SupportPowerManager(ActorInitializer init)
{
Self = init.Self;
DevMode = Self.Trait<DeveloperMode>();
TechTree = Self.Trait<TechTree>();
RadarPings = Exts.Lazy(() => init.World.WorldActor.TraitOrDefault<RadarPings>());
init.World.ActorAdded += ActorAdded;
init.World.ActorRemoved += ActorRemoved;
}
static string MakeKey(SupportPower sp)
{
return sp.Info.AllowMultiple ? sp.Info.OrderName + "_" + sp.Self.ActorID : sp.Info.OrderName;
}
void ActorAdded(Actor a)
{
if (a.Owner != Self.Owner)
return;
foreach (var t in a.TraitsImplementing<SupportPower>())
{
var key = MakeKey(t);
if (!Powers.ContainsKey(key))
{
Powers.Add(key, new SupportPowerInstance(key, this)
{
Instances = new List<SupportPower>(),
RemainingTime = t.Info.ChargeTime * 25,
TotalTime = t.Info.ChargeTime * 25,
});
if (t.Info.Prerequisites.Any())
{
TechTree.Add(key, t.Info.Prerequisites, 0, this);
TechTree.Update();
}
}
Powers[key].Instances.Add(t);
}
}
void ActorRemoved(Actor a)
{
if (a.Owner != Self.Owner || !a.HasTrait<SupportPower>())
return;
foreach (var t in a.TraitsImplementing<SupportPower>())
{
var key = MakeKey(t);
Powers[key].Instances.Remove(t);
if (Powers[key].Instances.Count == 0 && !Powers[key].Disabled)
{
Powers.Remove(key);
TechTree.Remove(key);
TechTree.Update();
}
}
}
public void Tick(Actor self)
{
foreach (var power in Powers.Values)
power.Tick();
}
public void ResolveOrder(Actor self, Order order)
{
// order.OrderString is the key of the support power
if (Powers.ContainsKey(order.OrderString))
Powers[order.OrderString].Activate(order);
}
// Deprecated. Remove after SupportPowerBinWidget is removed.
public void Target(string key)
{
if (Powers.ContainsKey(key))
Powers[key].Target();
}
static readonly SupportPowerInstance[] NoInstances = { };
public IEnumerable<SupportPowerInstance> GetPowersForActor(Actor a)
{
if (a.Owner != Self.Owner || !a.HasTrait<SupportPower>())
return NoInstances;
return a.TraitsImplementing<SupportPower>()
.Select(t => Powers[MakeKey(t)]);
}
public void PrerequisitesAvailable(string key)
{
SupportPowerInstance sp;
if (!Powers.TryGetValue(key, out sp))
return;
sp.Disabled = false;
}
public void PrerequisitesUnavailable(string key)
{
SupportPowerInstance sp;
if (!Powers.TryGetValue(key, out sp))
return;
sp.Disabled = true;
sp.RemainingTime = sp.TotalTime;
}
public void PrerequisitesItemHidden(string key) { }
public void PrerequisitesItemVisible(string key) { }
}
public class SupportPowerInstance
{
readonly SupportPowerManager manager;
readonly string key;
public List<SupportPower> Instances;
public int RemainingTime;
public int TotalTime;
public bool Active { get; private set; }
public bool Disabled { get; set; }
public SupportPowerInfo Info { get { return Instances.Select(i => i.Info).FirstOrDefault(); } }
public bool Ready { get { return Active && RemainingTime == 0; } }
public SupportPowerInstance(string key, SupportPowerManager manager)
{
this.manager = manager;
this.key = key;
}
static bool InstanceDisabled(SupportPower sp)
{
return sp.Self.TraitsImplementing<IDisable>().Any(d => d.Disabled);
}
bool notifiedCharging;
bool notifiedReady;
public void Tick()
{
Active = !Disabled && Instances.Any(i => !i.Self.IsDisabled());
if (!Active)
return;
if (Active)
{
var power = Instances.First();
if (manager.DevMode.FastCharge && RemainingTime > 25)
RemainingTime = 25;
if (RemainingTime > 0)
--RemainingTime;
if (!notifiedCharging)
{
power.Charging(power.Self, key);
notifiedCharging = true;
}
if (RemainingTime == 0
&& !notifiedReady)
{
power.Charged(power.Self, key);
notifiedReady = true;
}
}
}
public void Target()
{
if (!Ready)
return;
manager.Self.World.OrderGenerator = Instances.First().OrderGenerator(key, manager);
}
public void Activate(Order order)
{
if (!Ready)
return;
var power = Instances.First(i => !InstanceDisabled(i));
// Note: order.Subject is the *player* actor
power.Activate(power.Self, order, manager);
RemainingTime = TotalTime;
notifiedCharging = notifiedReady = false;
if (Info.OneShot)
Disabled = true;
}
}
public class SelectGenericPowerTarget : IOrderGenerator
{
readonly SupportPowerManager manager;
readonly string order;
readonly string cursor;
readonly MouseButton expectedButton;
public SelectGenericPowerTarget(string order, SupportPowerManager manager, string cursor, MouseButton button)
{
this.manager = manager;
this.order = order;
this.cursor = cursor;
expectedButton = button;
}
public IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
{
world.CancelInputMode();
if (mi.Button == expectedButton && world.Map.Contains(xy))
yield return new Order(order, manager.Self, false) { TargetLocation = xy, SuppressVisualFeedback = true };
}
public virtual void Tick(World world)
{
// Cancel the OG if we can't use the power
if (!manager.Powers.ContainsKey(order))
world.CancelInputMode();
}
public IEnumerable<IRenderable> Render(WorldRenderer wr, World world) { yield break; }
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world) { yield break; }
public string GetCursor(World world, CPos xy, MouseInput mi) { return world.Map.Contains(xy) ? cursor : "generic-blocked"; }
}
}