diff --git a/OpenRA.Mods.Cnc/IonCannonPower.cs b/OpenRA.Mods.Cnc/IonCannonPower.cs index 0ec8b9a3a1..cd285fb857 100644 --- a/OpenRA.Mods.Cnc/IonCannonPower.cs +++ b/OpenRA.Mods.Cnc/IonCannonPower.cs @@ -20,10 +20,10 @@ namespace OpenRA.Mods.Cnc public override object Create(ActorInitializer init) { return new IonCannonPower(init.self, this); } } - class IonCannonPower : SupportPower, IResolveOrder + class IonCannonPower : SupportPower { public IonCannonPower(Actor self, IonCannonPowerInfo info) : base(self, info) { } - +/* public void ResolveOrder(Actor self, Order order) { if (!IsReady) return; @@ -45,6 +45,7 @@ namespace OpenRA.Mods.Cnc Self.World.OrderGenerator = new GenericSelectTargetWithBuilding(Owner.PlayerActor, "IonCannon", "ability"); } +*/ } class IonControlInfo : TraitInfo { } diff --git a/OpenRA.Mods.RA/Crates/SupportPowerCrateAction.cs b/OpenRA.Mods.RA/Crates/SupportPowerCrateAction.cs index 53f9f045ac..91bb770559 100644 --- a/OpenRA.Mods.RA/Crates/SupportPowerCrateAction.cs +++ b/OpenRA.Mods.RA/Crates/SupportPowerCrateAction.cs @@ -26,15 +26,16 @@ namespace OpenRA.Mods.RA.Crates public override void Activate(Actor collector) { + throw new System.NotImplementedException(); // shit and broken. if you have a single-use and a multi-use version of the same // support power, this only works by order-coincidence. that's stupid. - var p = collector.Owner.PlayerActor.TraitsImplementing() - .FirstOrDefault(sp => sp.GetType().Name == (info as SupportPowerCrateActionInfo).Power); + //var p = collector.Owner.PlayerActor.TraitsImplementing() + // .FirstOrDefault(sp => sp.GetType().Name == (info as SupportPowerCrateActionInfo).Power); - if (p != null) p.Give(1); + //if (p != null) p.Give(1); - base.Activate(collector); + //base.Activate(collector); } } } diff --git a/OpenRA.Mods.RA/InfiltrateForSupportPower.cs b/OpenRA.Mods.RA/InfiltrateForSupportPower.cs index f5a82cca2a..c41048185b 100644 --- a/OpenRA.Mods.RA/InfiltrateForSupportPower.cs +++ b/OpenRA.Mods.RA/InfiltrateForSupportPower.cs @@ -29,10 +29,11 @@ namespace OpenRA.Mods.RA public void OnInfiltrate(Actor self, Actor spy) { - var p = spy.Owner.PlayerActor.TraitsImplementing() - .FirstOrDefault(sp => sp.GetType().Name == info.Power); - - if (p != null) p.Give(1); + throw new System.NotImplementedException(); + //var p = spy.Owner.PlayerActor.TraitsImplementing() + // .FirstOrDefault(sp => sp.GetType().Name == info.Power); + // + //if (p != null) p.Give(1); } } } diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index e189fd837b..baf58a6d53 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -325,6 +325,7 @@ + @@ -351,4 +352,8 @@ copy "$(TargetPath)" "$(SolutionDir)mods/ra/" cd "$(SolutionDir)" + + + + \ No newline at end of file diff --git a/OpenRA.Mods.RA/SupportPowers/AirstrikePower.cs b/OpenRA.Mods.RA/SupportPowers/AirstrikePower.cs index 29ed417eec..888050276b 100755 --- a/OpenRA.Mods.RA/SupportPowers/AirstrikePower.cs +++ b/OpenRA.Mods.RA/SupportPowers/AirstrikePower.cs @@ -26,53 +26,39 @@ namespace OpenRA.Mods.RA public override object Create(ActorInitializer init) { return new AirstrikePower(init.self, this); } } - class AirstrikePower : SupportPower, IResolveOrder + class AirstrikePower : SupportPower { public AirstrikePower(Actor self, AirstrikePowerInfo info) : base(self, info) { } - - protected override void OnActivate() + public override void Activate(Actor self, Order order) { - Self.World.OrderGenerator = new GenericSelectTarget(Owner.PlayerActor, Info.OrderName, "ability"); - } - - public void ResolveOrder(Actor self, Order order) - { - if (!IsReady) return; - - if (order.OrderString == Info.OrderName) + var startPos = self.World.ChooseRandomEdgeCell(); + self.World.AddFrameEndTask(w => { - var startPos = Owner.World.ChooseRandomEdgeCell(); + var info = (Info as AirstrikePowerInfo); + var flare = info.FlareType != null ? w.CreateActor(info.FlareType, new TypeDictionary + { + new LocationInit( order.TargetLocation ), + new OwnerInit( self.Owner ), + }) : null; + + var a = w.CreateActor(info.UnitType, new TypeDictionary + { + new LocationInit( startPos ), + new OwnerInit( self.Owner ), + new FacingInit( Util.GetFacing(order.TargetLocation - startPos, 0) ), + new AltitudeInit( Rules.Info[info.UnitType].Traits.Get().CruiseAltitude ), + }); + a.Trait().SetTarget(order.TargetLocation); - Owner.World.AddFrameEndTask(w => - { - var info = (Info as AirstrikePowerInfo); - var flare = info.FlareType != null ? w.CreateActor(info.FlareType, new TypeDictionary - { - new LocationInit( order.TargetLocation ), - new OwnerInit( Owner ), - }) : null; - - var a = w.CreateActor(info.UnitType, new TypeDictionary - { - new LocationInit( startPos ), - new OwnerInit( Owner ), - new FacingInit( Util.GetFacing(order.TargetLocation - startPos, 0) ), - new AltitudeInit( Rules.Info[info.UnitType].Traits.Get().CruiseAltitude ), - }); - a.Trait().SetTarget(order.TargetLocation); + a.CancelActivity(); + a.QueueActivity(Fly.ToCell(order.TargetLocation)); - a.CancelActivity(); - a.QueueActivity(Fly.ToCell(order.TargetLocation)); + if (flare != null) + a.QueueActivity(new CallFunc(() => flare.Destroy())); - if (flare != null) - a.QueueActivity(new CallFunc(() => flare.Destroy())); - - a.QueueActivity(new FlyOffMap { Interruptible = false }); - a.QueueActivity(new RemoveSelf()); - }); - - FinishActivate(); - } + a.QueueActivity(new FlyOffMap { Interruptible = false }); + a.QueueActivity(new RemoveSelf()); + }); } } } diff --git a/OpenRA.Mods.RA/SupportPowers/ChronoshiftPower.cs b/OpenRA.Mods.RA/SupportPowers/ChronoshiftPower.cs index 0ba5701fb9..f48c4655f8 100755 --- a/OpenRA.Mods.RA/SupportPowers/ChronoshiftPower.cs +++ b/OpenRA.Mods.RA/SupportPowers/ChronoshiftPower.cs @@ -15,7 +15,7 @@ using OpenRA.Graphics; using OpenRA.Mods.RA.Render; using OpenRA.Traits; using OpenRA.Mods.RA.Effects; - +/* namespace OpenRA.Mods.RA { class ChronoshiftPowerInfo : SupportPowerInfo @@ -255,3 +255,4 @@ namespace OpenRA.Mods.RA class ChronosphereInfo : TraitInfo {} class Chronosphere {} } +*/ \ No newline at end of file diff --git a/OpenRA.Mods.RA/SupportPowers/GpsPower.cs b/OpenRA.Mods.RA/SupportPowers/GpsPower.cs index 0bd0066918..cb93913b59 100755 --- a/OpenRA.Mods.RA/SupportPowers/GpsPower.cs +++ b/OpenRA.Mods.RA/SupportPowers/GpsPower.cs @@ -12,7 +12,7 @@ using System.Linq; using OpenRA.Effects; using OpenRA.Mods.RA.Effects; using OpenRA.Traits; - +/* namespace OpenRA.Mods.RA { class GpsPowerInfo : SupportPowerInfo @@ -51,3 +51,4 @@ namespace OpenRA.Mods.RA class GpsLaunchSiteInfo : TraitInfo { } class GpsLaunchSite { } } +*/ \ No newline at end of file diff --git a/OpenRA.Mods.RA/SupportPowers/IronCurtainPower.cs b/OpenRA.Mods.RA/SupportPowers/IronCurtainPower.cs index 5a9d190a3e..c6c3b02656 100755 --- a/OpenRA.Mods.RA/SupportPowers/IronCurtainPower.cs +++ b/OpenRA.Mods.RA/SupportPowers/IronCurtainPower.cs @@ -16,7 +16,7 @@ using OpenRA.Mods.RA.Effects; using OpenRA.Mods.RA.Render; using OpenRA.Traits; using TUtil = OpenRA.Traits.Util; - +/* namespace OpenRA.Mods.RA { class IronCurtainPowerInfo : SupportPowerInfo @@ -139,3 +139,4 @@ namespace OpenRA.Mods.RA class IronCurtainInfo : TraitInfo { } class IronCurtain { } } +*/ \ No newline at end of file diff --git a/OpenRA.Mods.RA/SupportPowers/NukePower.cs b/OpenRA.Mods.RA/SupportPowers/NukePower.cs index 53b0c10c07..e163024f8e 100755 --- a/OpenRA.Mods.RA/SupportPowers/NukePower.cs +++ b/OpenRA.Mods.RA/SupportPowers/NukePower.cs @@ -20,11 +20,11 @@ namespace OpenRA.Mods.RA { public override object Create(ActorInitializer init) { return new NukePower(init.self, this); } } - - class NukePower : SupportPower, IResolveOrder + + class NukePower : SupportPower { public NukePower(Actor self, NukePowerInfo info) : base(self, info) { } - +/* protected override void OnActivate() { Self.World.OrderGenerator = @@ -52,6 +52,7 @@ namespace OpenRA.Mods.RA FinishActivate(); } } +*/ } // tag trait for the building diff --git a/OpenRA.Mods.RA/SupportPowers/ParatroopersPower.cs b/OpenRA.Mods.RA/SupportPowers/ParatroopersPower.cs index 4fd0a66224..37f36d5c7f 100755 --- a/OpenRA.Mods.RA/SupportPowers/ParatroopersPower.cs +++ b/OpenRA.Mods.RA/SupportPowers/ParatroopersPower.cs @@ -13,7 +13,7 @@ using OpenRA.Orders; using OpenRA.Traits; using OpenRA.FileFormats; using OpenRA.Mods.RA.Air; - +/* namespace OpenRA.Mods.RA { class ParatroopersPowerInfo : SupportPowerInfo @@ -82,3 +82,4 @@ namespace OpenRA.Mods.RA } } } +*/ \ No newline at end of file diff --git a/OpenRA.Mods.RA/SupportPowers/SonarPulsePower.cs b/OpenRA.Mods.RA/SupportPowers/SonarPulsePower.cs index f7ba92c686..0eb3c24b9a 100755 --- a/OpenRA.Mods.RA/SupportPowers/SonarPulsePower.cs +++ b/OpenRA.Mods.RA/SupportPowers/SonarPulsePower.cs @@ -9,7 +9,7 @@ #endregion using OpenRA.Traits; - +/* namespace OpenRA.Mods.RA { public class SonarPulsePowerInfo : SupportPowerInfo @@ -44,3 +44,4 @@ namespace OpenRA.Mods.RA } } } +*/ \ No newline at end of file diff --git a/OpenRA.Mods.RA/SupportPowers/SpyPlanePower.cs b/OpenRA.Mods.RA/SupportPowers/SpyPlanePower.cs index 9ef641dc61..055acf0179 100755 --- a/OpenRA.Mods.RA/SupportPowers/SpyPlanePower.cs +++ b/OpenRA.Mods.RA/SupportPowers/SpyPlanePower.cs @@ -14,7 +14,7 @@ using OpenRA.Traits; using OpenRA.Traits.Activities; using OpenRA.FileFormats; using OpenRA.Mods.RA.Air; - +/* namespace OpenRA.Mods.RA { class SpyPlanePowerInfo : SupportPowerInfo @@ -71,3 +71,4 @@ namespace OpenRA.Mods.RA } } } +*/ \ No newline at end of file diff --git a/OpenRA.Mods.RA/SupportPowers/SupportPower.cs b/OpenRA.Mods.RA/SupportPowers/SupportPower.cs index 0964329801..a7115be329 100755 --- a/OpenRA.Mods.RA/SupportPowers/SupportPower.cs +++ b/OpenRA.Mods.RA/SupportPowers/SupportPower.cs @@ -14,136 +14,40 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA { - public abstract class SupportPowerInfo : ITraitInfo, ITraitPrerequisite, ITraitPrerequisite + public abstract class SupportPowerInfo : ITraitInfo { - public readonly bool RequiresPower = true; - public readonly bool OneShot = false; - public readonly float ChargeTime = 0; + public readonly int ChargeTime = 0; public readonly string Image = null; public readonly string Description = ""; public readonly string LongDesc = ""; - [ActorReference] - public readonly string[] Prerequisites = { }; - public readonly bool GivenAuto = true; public readonly string OrderName; - public readonly string BeginChargeSound = null; public readonly string EndChargeSound = null; public readonly string SelectTargetSound = null; public readonly string LaunchSound = null; - + public readonly bool AllowMultiple = false; public abstract object Create(ActorInitializer init); public SupportPowerInfo() { OrderName = GetType().Name + "Order"; } } - public class SupportPower : ITick, ITechTreeElement + public class SupportPower { + public readonly Actor self; public readonly SupportPowerInfo Info; - public int RemainingTime { get; private set; } - public int TotalTime { get { return (int)(Info.ChargeTime * 60 * 25); } } - public bool IsUsed; - public bool IsAvailable; - public bool IsReady { get { return IsAvailable && RemainingTime == 0; } } - - protected readonly Actor Self; - protected readonly Player Owner; - bool notifiedCharging; - bool notifiedReady; - - readonly PowerManager PlayerPower; public SupportPower(Actor self, SupportPowerInfo info) { Info = info; - RemainingTime = TotalTime; - Self = self; - Owner = self.Owner; - PlayerPower = self.Trait(); - - self.Trait().Add( Info.OrderName, Info.Prerequisites.Select( a => a.ToLowerInvariant() ).ToList(), this ); + this.self = self; } - public void Tick(Actor self) + public virtual void Activate(Actor self, Order order) { } + public virtual IOrderGenerator OrderGenerator(string order, SupportPowerManager manager) { - if (Info.OneShot && IsUsed) - return; - - if (Info.GivenAuto) - IsAvailable = hasPrerequisites; - - if (IsAvailable && (!Info.RequiresPower || PlayerPower.PowerState == PowerState.Normal)) - { - if (self.World.LobbyInfo.GlobalSettings.AllowCheats && self.Trait().FastCharge) RemainingTime = 0; - - if (RemainingTime > 0) --RemainingTime; - if (!notifiedCharging) - { - Sound.PlayToPlayer(Owner, Info.BeginChargeSound); - OnBeginCharging(); - notifiedCharging = true; - } - } - - if (RemainingTime == 0 - && !notifiedReady) - { - Sound.PlayToPlayer(Owner, Info.EndChargeSound); - OnFinishCharging(); - notifiedReady = true; - } - } - - public void FinishActivate() - { - if (Info.OneShot) - { - IsUsed = true; - IsAvailable = false; - } - RemainingTime = TotalTime; - notifiedReady = false; - notifiedCharging = false; - } - - public void Give(float charge) - { - IsAvailable = true; - IsUsed = false; - RemainingTime = (int)(charge * TotalTime); - } - - protected virtual void OnBeginCharging() { } - protected virtual void OnFinishCharging() { } - protected virtual void OnActivate() { } - - public void Activate() - { - if (!IsAvailable || !IsReady) - return; - - if (Info.RequiresPower && PlayerPower.PowerState != PowerState.Normal) - { - var eva = Owner.World.WorldActor.Info.Traits.Get(); - Sound.Play(eva.AbilityInsufficientPower); - return; - } - - Sound.PlayToPlayer(Owner, Info.SelectTargetSound); - OnActivate(); - } - - bool hasPrerequisites; - - public void PrerequisitesAvailable(string key) - { - hasPrerequisites = true; - } - - public void PrerequisitesUnavailable(string key) - { - hasPrerequisites = false; + Sound.PlayToPlayer(manager.self.Owner, Info.SelectTargetSound); + return new SelectGenericPowerTarget(order, manager, "ability", MouseButton.Left); } } } diff --git a/OpenRA.Mods.RA/SupportPowers/SupportPowerManager.cs b/OpenRA.Mods.RA/SupportPowers/SupportPowerManager.cs new file mode 100755 index 0000000000..a91e19b847 --- /dev/null +++ b/OpenRA.Mods.RA/SupportPowers/SupportPowerManager.cs @@ -0,0 +1,194 @@ +#region Copyright & License Information +/* + * Copyright 2007-2010 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 LICENSE. + */ +#endregion + +using System.Linq; +using OpenRA.Mods.RA.Buildings; +using OpenRA.Traits; +using System.Collections.Generic; +using OpenRA.Graphics; + +namespace OpenRA.Mods.RA +{ + public class SupportPowerManagerInfo : ITraitInfo + { + public object Create(ActorInitializer init) { return new SupportPowerManager(init); } + } + + public class SupportPowerManager : ITick, IResolveOrder + { + public readonly Actor self; + public Dictionary Powers = new Dictionary(); + + public SupportPowerManager(ActorInitializer init) + { + self = init.self; + + init.world.ActorAdded += ActorAdded; + init.world.ActorRemoved += ActorRemoved; + } + + void ActorAdded(Actor a) + { + if (a.Owner != self.Owner || !a.HasTrait()) + return; + + foreach (var t in a.TraitsImplementing()) + { + var key = (t.Info.AllowMultiple) ? t.Info.OrderName+"_"+a.ActorID : t.Info.OrderName; + + if (Powers.ContainsKey(key)) + { + Powers[key].Instances.Add(t); + } + else + { + var si = new SupportPowerInstance(this) + { + Instances = new List() { t }, + RemainingTime = t.Info.ChargeTime * 25, + TotalTime = t.Info.ChargeTime * 25, + }; + + Powers.Add(key, si); + } + } + } + + void ActorRemoved(Actor a) + { + if (a.Owner != self.Owner || !a.HasTrait()) + return; + + foreach (var t in a.TraitsImplementing()) + { + var key = (t.Info.AllowMultiple) ? t.Info.OrderName+"_"+a.ActorID : t.Info.OrderName; + Powers[key].Instances.Remove(t); + if (Powers[key].Instances.Count == 0) + Powers.Remove(key); + } + } + + 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); + } + + public void Target(string key) + { + if (Powers.ContainsKey(key)) + Powers[key].Target(key); + } + + public class SupportPowerInstance + { + SupportPowerManager Manager; + public List Instances; + public int RemainingTime; + public int TotalTime; + public bool Active; + + public SupportPowerInfo Info { get { return Instances.First().Info; } } + public bool Ready { get { return Active && RemainingTime == 0; } } + + public SupportPowerInstance(SupportPowerManager manager) + { + Manager = manager; + } + + bool notifiedCharging; + bool notifiedReady; + public void Tick() + { + Active = Instances.Any(i => !i.self.TraitsImplementing().Any(d => d.Disabled)); + + if (Active) + { + if (RemainingTime > 0) --RemainingTime; + if (!notifiedCharging) + { + Sound.PlayToPlayer(Instances.First().self.Owner, Info.BeginChargeSound); + //instance.OnBeginCharging(); + notifiedCharging = true; + } + } + + if (RemainingTime == 0 + && !notifiedReady) + { + Sound.PlayToPlayer(Instances.First().self.Owner, Info.EndChargeSound); + //instance.FinishCharging(); + notifiedReady = true; + } + } + + public void Target(string key) + { + if (!Ready) + return; + + Manager.self.World.OrderGenerator = Instances.First().OrderGenerator(key, Manager); + } + + public void Activate(Order order) + { + if (!Ready) + return; + + var power = Instances.First(); + // Note: order.Subject is the *player* actor + power.Activate(power.self, order); + RemainingTime = TotalTime; + notifiedCharging = notifiedReady = false; + } + } + } + + 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(World world, int2 xy, MouseInput mi) + { + world.CancelInputMode(); + if (mi.Button == expectedButton && world.Map.IsInMap(xy)) + yield return new Order(order, manager.self, false) { TargetLocation = xy }; + } + + public virtual void Tick(World world) + { + // Cancel the OG if we can't use the power + if (!manager.Powers.ContainsKey(order)) + world.CancelInputMode(); + } + + public void RenderBeforeWorld(WorldRenderer wr, World world) { } + public void RenderAfterWorld(WorldRenderer wr, World world) { } + public string GetCursor(World world, int2 xy, MouseInput mi) { return world.Map.IsInMap(xy) ? cursor : "generic-blocked"; } + } +} diff --git a/OpenRA.Mods.RA/Widgets/SpecialPowerBinWidget.cs b/OpenRA.Mods.RA/Widgets/SpecialPowerBinWidget.cs index 5bb8de2277..7305c44d3c 100755 --- a/OpenRA.Mods.RA/Widgets/SpecialPowerBinWidget.cs +++ b/OpenRA.Mods.RA/Widgets/SpecialPowerBinWidget.cs @@ -74,9 +74,10 @@ namespace OpenRA.Mods.RA.Widgets if( world.LocalPlayer == null ) return; - var powers = world.LocalPlayer.PlayerActor.TraitsImplementing(); - var numPowers = powers.Count(p => p.IsAvailable); + var manager = world.LocalPlayer.PlayerActor.Trait(); + var numPowers = manager.Powers.Count; if (numPowers == 0) return; + var rectBounds = RenderBounds; WidgetUtils.DrawRGBA(WidgetUtils.GetChromeImage(world, "specialbin-top"),new float2(rectBounds.X,rectBounds.Y)); for (var i = 1; i < numPowers; i++) @@ -88,74 +89,78 @@ namespace OpenRA.Mods.RA.Widgets rectBounds.Height = 10 + numPowers * 51 + 21; var y = rectBounds.Y + 10; - foreach (var sp in powers) + foreach (var kv in manager.Powers) { + var sp = kv.Value; var image = spsprites[sp.Info.Image]; - if (sp.IsAvailable) + + var drawPos = new float2(rectBounds.X + 5, y); + var rect = new Rectangle(rectBounds.X + 5, y, 64, 48); + + if (rect.Contains(Viewport.LastMousePos.ToPoint())) { - var drawPos = new float2(rectBounds.X + 5, y); - var rect = new Rectangle(rectBounds.X + 5, y, 64, 48); + var pos = drawPos.ToInt2(); + var tl = new int2(pos.X-3,pos.Y-3); + var m = new int2(pos.X+64+3,pos.Y+48+3); + var br = tl + new int2(64+3+20,60); + + if (sp.Info.LongDesc != null) + br += Game.Renderer.RegularFont.Measure(sp.Info.LongDesc.Replace("\\n", "\n")); + else + br += new int2(300,0); - if (rect.Contains(Viewport.LastMousePos.ToPoint())) + var border = WidgetUtils.GetBorderSizes("dialog4"); + + WidgetUtils.DrawPanelPartial("dialog4", Rectangle.FromLTRB(tl.X, tl.Y, m.X + border[3], m.Y), + PanelSides.Left | PanelSides.Top | PanelSides.Bottom); + WidgetUtils.DrawPanelPartial("dialog4", Rectangle.FromLTRB(m.X - border[2], tl.Y, br.X, m.Y + border[1]), + PanelSides.Top | PanelSides.Right); + WidgetUtils.DrawPanelPartial("dialog4", Rectangle.FromLTRB(m.X, m.Y - border[1], br.X, br.Y), + PanelSides.Left | PanelSides.Right | PanelSides.Bottom); + + pos += new int2(77, 5); + Game.Renderer.BoldFont.DrawText(sp.Info.Description, pos, Color.White); + + pos += new int2(0,20); + Game.Renderer.BoldFont.DrawText(WidgetUtils.FormatTime(sp.RemainingTime).ToString(), pos, Color.White); + Game.Renderer.BoldFont.DrawText("/ {0}".F(WidgetUtils.FormatTime(sp.TotalTime)), pos + new int2(45,0), Color.White); + + if (sp.Info.LongDesc != null) { - var pos = drawPos.ToInt2(); - var tl = new int2(pos.X-3,pos.Y-3); - var m = new int2(pos.X+64+3,pos.Y+48+3); - var br = tl + new int2(64+3+20,60); - - if (sp.Info.LongDesc != null) - br += Game.Renderer.RegularFont.Measure(sp.Info.LongDesc.Replace("\\n", "\n")); - else - br += new int2(300,0); - - var border = WidgetUtils.GetBorderSizes("dialog4"); - - WidgetUtils.DrawPanelPartial("dialog4", Rectangle.FromLTRB(tl.X, tl.Y, m.X + border[3], m.Y), - PanelSides.Left | PanelSides.Top | PanelSides.Bottom); - WidgetUtils.DrawPanelPartial("dialog4", Rectangle.FromLTRB(m.X - border[2], tl.Y, br.X, m.Y + border[1]), - PanelSides.Top | PanelSides.Right); - WidgetUtils.DrawPanelPartial("dialog4", Rectangle.FromLTRB(m.X, m.Y - border[1], br.X, br.Y), - PanelSides.Left | PanelSides.Right | PanelSides.Bottom); - - pos += new int2(77, 5); - Game.Renderer.BoldFont.DrawText(sp.Info.Description, pos, Color.White); - - pos += new int2(0,20); - Game.Renderer.BoldFont.DrawText(WidgetUtils.FormatTime(sp.RemainingTime).ToString(), pos, Color.White); - Game.Renderer.BoldFont.DrawText("/ {0}".F(WidgetUtils.FormatTime(sp.TotalTime)), pos + new int2(45,0), Color.White); - - if (sp.Info.LongDesc != null) - { - pos += new int2(0, 20); - Game.Renderer.RegularFont.DrawText(sp.Info.LongDesc.Replace("\\n", "\n"), pos, Color.White); - } + pos += new int2(0, 20); + Game.Renderer.RegularFont.DrawText(sp.Info.LongDesc.Replace("\\n", "\n"), pos, Color.White); } - WidgetUtils.DrawSHP(image, drawPos, wr); - - clock.PlayFetchIndex("idle", - () => (sp.TotalTime - sp.RemainingTime) - * (clock.CurrentSequence.Length - 1) / sp.TotalTime); - clock.Tick(); - - WidgetUtils.DrawSHP(clock.Image, drawPos, wr); - - if (sp.IsReady) - { - ready.Play("ready"); - WidgetUtils.DrawSHP(ready.Image, drawPos + new float2((64 - ready.Image.size.X) / 2, 2), wr); - } - - buttons.Add(Pair.New(rect,HandleSupportPower(sp))); - - y += 51; } + WidgetUtils.DrawSHP(image, drawPos, wr); + + clock.PlayFetchIndex("idle", + () => (sp.TotalTime - sp.RemainingTime) + * (clock.CurrentSequence.Length - 1) / sp.TotalTime); + clock.Tick(); + + WidgetUtils.DrawSHP(clock.Image, drawPos, wr); + + if (sp.Ready) + { + ready.Play("ready"); + WidgetUtils.DrawSHP(ready.Image, drawPos + new float2((64 - ready.Image.size.X) / 2, 2), wr); + } + else if (!sp.Active) + { + ready.Play("hold"); + WidgetUtils.DrawSHP(ready.Image, drawPos + new float2((64 - ready.Image.size.X) / 2, 2), wr); + } + + buttons.Add(Pair.New(rect,HandleSupportPower(kv.Key, manager))); + + y += 51; } } - Action HandleSupportPower(SupportPower sp) + Action HandleSupportPower(string key, SupportPowerManager manager) { - return mi => { if (mi.Button == MouseButton.Left) sp.Activate(); }; + return mi => { if (mi.Button == MouseButton.Left) manager.Target(key); }; } } } \ No newline at end of file diff --git a/mods/cnc/rules/structures.yaml b/mods/cnc/rules/structures.yaml index 2fa11ba924..bfeaae76ae 100644 --- a/mods/cnc/rules/structures.yaml +++ b/mods/cnc/rules/structures.yaml @@ -33,6 +33,15 @@ FACT: BuildSpeed: .4 LowPowerSlowdown: 3 BaseBuilding: + AirstrikePower: + Image: bombicnh + ChargeTime: 10 + Description: Airstrike + LongDesc: Delivers a load of napalm on your target. + EndChargeSound: airredy1.aud + SelectTargetSound: select1.aud + UnitType: a10 +# AllowMultiple: true NUKE: Inherits: ^Building diff --git a/mods/cnc/rules/system.yaml b/mods/cnc/rules/system.yaml index 66ad732eac..8ef0237455 100644 --- a/mods/cnc/rules/system.yaml +++ b/mods/cnc/rules/system.yaml @@ -1,35 +1,36 @@ Player: PlaceBuilding: TechTree: - NukePower: - Image: atomicnh - ChargeTime: 5 - Description: Atom Bomb - LongDesc: Launches a nuclear missile at a target location. - Prerequisites: TMPL - BeginChargeSound: - EndChargeSound: nukavail.aud - SelectTargetSound: select1.aud - LaunchSound: nukemisl.aud - IonCannonPower: - Image: ionicnh - ChargeTime: 3 - Description: Ion Cannon - LongDesc: Discharges the orbital Ion Cannon at your target. - Prerequisites: EYE - BeginChargeSound: ionchrg1.aud - EndChargeSound: ionredy1.aud - LaunchSound: ion1.aud - SelectTargetSound: select1.aud - AirstrikePower: - Image: bombicnh - ChargeTime: 4 - Description: Airstrike - LongDesc: Delivers a load of napalm on your target. - Prerequisites: hq - EndChargeSound: airredy1.aud - SelectTargetSound: select1.aud - UnitType: a10 +# NukePower: +# Image: atomicnh +# ChargeTime: 5 +# Description: Atom Bomb +# LongDesc: Launches a nuclear missile at a target location. +# Prerequisites: TMPL +# BeginChargeSound: +# EndChargeSound: nukavail.aud +# SelectTargetSound: select1.aud +# LaunchSound: nukemisl.aud +# IonCannonPower: +# Image: ionicnh +# ChargeTime: 3 +# Description: Ion Cannon +# LongDesc: Discharges the orbital Ion Cannon at your target. +# Prerequisites: EYE +# BeginChargeSound: ionchrg1.aud +# EndChargeSound: ionredy1.aud +# LaunchSound: ion1.aud +# SelectTargetSound: select1.aud +# AirstrikePower: +# Image: bombicnh +# ChargeTime: 4 +# Description: Airstrike +# LongDesc: Delivers a load of napalm on your target. +# Prerequisites: hq +# EndChargeSound: airredy1.aud +# SelectTargetSound: select1.aud +# UnitType: a10 + SupportPowerManager: ConquestVictoryConditions: PowerManager: PlayerResources: