diff --git a/OpenRa.FileFormats/TypeDictionary.cs b/OpenRa.FileFormats/TypeDictionary.cs index aad834d7bf..e9c5db5cf5 100644 --- a/OpenRa.FileFormats/TypeDictionary.cs +++ b/OpenRa.FileFormats/TypeDictionary.cs @@ -27,15 +27,15 @@ namespace OpenRa.FileFormats public T Get() { - var l = innerInherit[ typeof( T ) ]; - if( l.Count == 1 ) - return (T)l[ 0 ]; - else if( l.Count == 0 ) - throw new InvalidOperationException( string.Format( "TypeDictionary does not contain instance of type `{0}`", typeof( T ) ) ); + var l = innerInherit[typeof(T)]; + if (l.Count == 1) + return (T)l[0]; + else if (l.Count == 0) + throw new InvalidOperationException(string.Format("TypeDictionary does not contain instance of type `{0}`", typeof(T))); else - throw new InvalidOperationException( string.Format( "TypeDictionary contains multiple instance of type `{0}`", typeof( T ) ) ); + throw new InvalidOperationException(string.Format("TypeDictionary contains multiple instance of type `{0}`", typeof(T))); } - + public T GetOrDefault() { var l = innerInherit[ typeof( T ) ]; diff --git a/OpenRa.Game/Chrome.cs b/OpenRa.Game/Chrome.cs index ab0a0bd848..7111bd893f 100644 --- a/OpenRa.Game/Chrome.cs +++ b/OpenRa.Game/Chrome.cs @@ -117,10 +117,10 @@ namespace OpenRa u => u.Name, u => SpriteSheetBuilder.LoadAllSprites(u.Traits.Get().Icon ?? (u.Name + "icon"))[0]); - spsprites = Rules.SupportPowerInfo + spsprites = Rules.Info.Values.SelectMany( u => u.Traits.WithInterface() ) .ToDictionary( - u => u.Key, - u => SpriteSheetBuilder.LoadAllSprites(u.Value.Image)[0]); + u => u.Image, + u => SpriteSheetBuilder.LoadAllSprites(u.Image)[0]); var groups = Rules.Info.Values.Select( x => x.Category ).Distinct().Where( g => g != null ).ToList(); @@ -893,8 +893,8 @@ namespace OpenRa void DrawSupportPowers( World world ) { - var numPowers = world.LocalPlayer.SupportPowers.Values - .Where(a => a.IsAvailable).Count(); + var powers = world.LocalPlayer.PlayerActor.traits.WithInterface(); + var numPowers = powers.Count(p => p.IsAvailable); if (numPowers == 0) return; @@ -907,38 +907,38 @@ namespace OpenRa var y = 24; - string tooltipItem = null; + SupportPower tooltipItem = null; int2 tooltipPos = int2.Zero; - foreach (var sp in world.LocalPlayer.SupportPowers) + foreach (var sp in powers) { - var image = spsprites[sp.Key]; - if (sp.Value.IsAvailable) + var image = spsprites[sp.Info.Image]; + if (sp.IsAvailable) { var drawPos = new float2(5, y); shpRenderer.DrawSprite(image, drawPos, PaletteType.Chrome); clock.PlayFetchIndex("idle", - () => (sp.Value.TotalTime - sp.Value.RemainingTime) - * NumClockFrames / sp.Value.TotalTime); + () => (sp.TotalTime - sp.RemainingTime) + * NumClockFrames / sp.TotalTime); clock.Tick(); shpRenderer.DrawSprite(clock.Image, drawPos, PaletteType.Chrome); var rect = new Rectangle(5, y, 64, 48); - if (sp.Value.IsDone) + if (sp.IsReady) { ready.Play("ready"); shpRenderer.DrawSprite(ready.Image, drawPos + new float2((64 - ready.Image.size.X) / 2, 2), PaletteType.Chrome); - AddButton(rect, HandleSupportPower( sp.Value )); + AddButton(rect, HandleSupportPower( sp )); } if (rect.Contains(lastMousePos.ToPoint())) { - tooltipItem = sp.Key; + tooltipItem = sp; tooltipPos = drawPos.ToInt2() + new int2(72, 0); } @@ -965,25 +965,23 @@ namespace OpenRa return "{0:D2}:{1:D2}".F(minutes, seconds % 60); } - void DrawSupportPowerTooltip(World world, string sp, int2 pos) + void DrawSupportPowerTooltip(World world, SupportPower sp, int2 pos) { var tooltipSprite = ChromeProvider.GetImage(renderer, chromeCollection, "tooltip-bg"); rgbaRenderer.DrawSprite(tooltipSprite, pos, PaletteType.Chrome); rgbaRenderer.Flush(); - var info = Rules.SupportPowerInfo[sp]; - pos += new int2(5, 5); - renderer.DrawText2(info.Description, pos, Color.White); + renderer.DrawText2(sp.Info.Description, pos, Color.White); - var timer = "Charge Time: {0}".F(FormatTime(world.LocalPlayer.SupportPowers[sp].RemainingTime)); + var timer = "Charge Time: {0}".F(FormatTime(sp.RemainingTime)); DrawRightAligned(timer, pos + new int2((int)tooltipSprite.size.X - 10, 0), Color.White); - if (info.LongDesc != null) + if (sp.Info.LongDesc != null) { pos += new int2(0, 25); - renderer.DrawText(info.LongDesc.Replace("\\n", "\n"), pos, Color.White); + renderer.DrawText(sp.Info.LongDesc.Replace("\\n", "\n"), pos, Color.White); } } } diff --git a/OpenRa.Game/Game.cs b/OpenRa.Game/Game.cs index 78f9d3630d..3331e5d171 100644 --- a/OpenRa.Game/Game.cs +++ b/OpenRa.Game/Game.cs @@ -274,7 +274,7 @@ namespace OpenRa if( e.KeyCode == Keys.F8 && !Game.orderManager.GameStarted ) { Game.orderManager.IssueOrder( - new Order( "ToggleReady", Game.world.LocalPlayer.PlayerActor, null, int2.Zero, "" ) { IsImmediate = true } ); + new Order( "ToggleReady", Game.world.LocalPlayer.PlayerActor, "" ) { IsImmediate = true } ); } /* temporary hack: DO NOT LEAVE IN */ diff --git a/OpenRa.Game/GameRules/Rules.cs b/OpenRa.Game/GameRules/Rules.cs index bd4f52c8c1..d755c8b07f 100755 --- a/OpenRa.Game/GameRules/Rules.cs +++ b/OpenRa.Game/GameRules/Rules.cs @@ -15,7 +15,6 @@ namespace OpenRa public static InfoLoader WarheadInfo; public static InfoLoader ProjectileInfo; public static InfoLoader VoiceInfo; - public static InfoLoader SupportPowerInfo; public static GeneralInfo General; public static AftermathInfo Aftermath; public static TechTree TechTree; @@ -40,8 +39,7 @@ namespace OpenRa "Weapon", "Warhead", "Projectile", - "Voice", - "SupportPower"); + "Voice"); WeaponInfo = new InfoLoader( Pair.New>("Weapon", _ => new WeaponInfo())); @@ -51,9 +49,7 @@ namespace OpenRa Pair.New>("Projectile", _ => new ProjectileInfo())); VoiceInfo = new InfoLoader( Pair.New>("Voice", _ => new VoiceInfo())); - SupportPowerInfo = new InfoLoader( - Pair.New>("SupportPower", _ => new SupportPowerInfo())); - + var yamlRules = m.Rules.Reverse().Select(a => MiniYaml.FromFile(a)).Aggregate(MiniYaml.Merge); ActorInfo.LoadModAssemblies(m); diff --git a/OpenRa.Game/GameRules/SupportPowerInfo.cs b/OpenRa.Game/GameRules/SupportPowerInfo.cs deleted file mode 100644 index 08b8f6d190..0000000000 --- a/OpenRa.Game/GameRules/SupportPowerInfo.cs +++ /dev/null @@ -1,17 +0,0 @@ - -namespace OpenRa.GameRules -{ - public class SupportPowerInfo - { - public readonly bool Powered = true; - public readonly bool OneShot = false; - public readonly float ChargeTime = 0; - public readonly string Image; - public readonly string Description = ""; - public readonly string LongDesc = ""; - public readonly string[] Prerequisite = { }; - public readonly int TechLevel = -1; - public readonly bool GivenAuto = true; - public readonly string Impl = null; - } -} diff --git a/OpenRa.Game/Network/Order.cs b/OpenRa.Game/Network/Order.cs index 953f599fb9..9576366d95 100755 --- a/OpenRa.Game/Network/Order.cs +++ b/OpenRa.Game/Network/Order.cs @@ -1,7 +1,6 @@ using System; using System.IO; using System.Linq; -using OpenRa.SupportPowers; namespace OpenRa { @@ -26,6 +25,21 @@ namespace OpenRa this.TargetString = targetString; } + public Order(string orderString, Actor subject) + : this(orderString, subject, null, int2.Zero, null) { } + public Order(string orderString, Actor subject, Actor targetActor) + : this(orderString, subject, targetActor, int2.Zero, null) { } + public Order(string orderString, Actor subject, int2 targetLocation) + : this(orderString, subject, null, targetLocation, null) { } + public Order(string orderString, Actor subject, string targetString) + : this(orderString, subject, null, int2.Zero, targetString) { } + public Order(string orderString, Actor subject, Actor targetActor, int2 targetLocation) + : this(orderString, subject, targetActor, targetLocation, null) { } + public Order(string orderString, Actor subject, Actor targetActor, string targetString) + : this(orderString, subject, targetActor, int2.Zero, targetString) { } + public Order(string orderString, Actor subject, int2 targetLocation, string targetString) + : this(orderString, subject, null, targetLocation, targetString) { } + public byte[] Serialize() { if (IsImmediate) /* chat, whatever */ @@ -99,7 +113,7 @@ namespace OpenRa var name = r.ReadString(); var data = r.ReadString(); - return new Order( name, LookupPlayer( world, playerID ).PlayerActor, null, int2.Zero, data ) { IsImmediate = true }; + return new Order( name, LookupPlayer( world, playerID ).PlayerActor, data ) { IsImmediate = true }; } default: @@ -136,28 +150,22 @@ namespace OpenRa // Now that Orders are resolved by individual Actors, these are weird; you unpack orders manually, but not pack them. public static Order Chat(Player subject, string text) { - return new Order("Chat", subject.PlayerActor, null, int2.Zero, text) - { IsImmediate = true }; + return new Order("Chat", subject.PlayerActor, text) { IsImmediate = true }; } public static Order StartProduction(Player subject, string item) { - return new Order("StartProduction", subject.PlayerActor, null, int2.Zero, item ); + return new Order("StartProduction", subject.PlayerActor, item ); } public static Order PauseProduction(Player subject, string item, bool pause) { - return new Order("PauseProduction", subject.PlayerActor, null, new int2( pause ? 1 : 0, 0 ), item); + return new Order("PauseProduction", subject.PlayerActor, new int2( pause ? 1 : 0, 0 ), item); } public static Order CancelProduction(Player subject, string item) { - return new Order("CancelProduction", subject.PlayerActor, null, int2.Zero, item); - } - - public static Order PlayAnimation(Actor actor, string animationString) - { - return new Order("PlayAnimation", actor, null, int2.Zero, animationString); + return new Order("CancelProduction", subject.PlayerActor, item); } } } diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj index a0424974b7..9d98f7e452 100644 --- a/OpenRa.Game/OpenRa.Game.csproj +++ b/OpenRa.Game/OpenRa.Game.csproj @@ -93,7 +93,6 @@ - @@ -123,12 +122,6 @@ - - - - - - @@ -216,22 +209,24 @@ - + + - + + diff --git a/OpenRa.Game/Orders/ChronoshiftDestinationOrderGenerator.cs b/OpenRa.Game/Orders/ChronoshiftDestinationOrderGenerator.cs index 7ce28e2851..9b5c990fae 100644 --- a/OpenRa.Game/Orders/ChronoshiftDestinationOrderGenerator.cs +++ b/OpenRa.Game/Orders/ChronoshiftDestinationOrderGenerator.cs @@ -3,19 +3,16 @@ using System.Collections.Generic; using System.Linq; using System.Drawing; using OpenRa.Traits; -using OpenRa.SupportPowers; namespace OpenRa.Orders { class ChronoshiftDestinationOrderGenerator : IOrderGenerator { public readonly Actor self; - SupportPower power; - public ChronoshiftDestinationOrderGenerator(Actor self, SupportPower power) + public ChronoshiftDestinationOrderGenerator(Actor self) { this.self = self; - this.power = power; } public IEnumerable Order(World world, int2 xy, MouseInput mi) @@ -25,8 +22,9 @@ namespace OpenRa.Orders Game.controller.CancelInputMode(); yield break; } - yield return new Order("Chronoshift", self, null, xy, - power != null ? power.Name : null); + + yield return new Order("Chronoshift", self, xy); + yield return new Order("ChronosphereFinish", self.Owner.PlayerActor); } public void Tick( World world ) {} diff --git a/OpenRa.Game/Orders/ChronosphereSelectOrderGenerator.cs b/OpenRa.Game/Orders/ChronosphereSelectOrderGenerator.cs index 011c47f345..d09de18bbf 100644 --- a/OpenRa.Game/Orders/ChronosphereSelectOrderGenerator.cs +++ b/OpenRa.Game/Orders/ChronosphereSelectOrderGenerator.cs @@ -3,17 +3,12 @@ using System.Collections.Generic; using System.Linq; using OpenRa.GameRules; using OpenRa.Traits; -using OpenRa.SupportPowers; namespace OpenRa.Orders { class ChronosphereSelectOrderGenerator : IOrderGenerator { - SupportPower power; - public ChronosphereSelectOrderGenerator(SupportPower power) - { - this.power = power; - } + public ChronosphereSelectOrderGenerator() {} public IEnumerable Order(World world, int2 xy, MouseInput mi) { @@ -32,10 +27,12 @@ namespace OpenRa.Orders .Where(a => a.Owner == world.LocalPlayer && a.traits.Contains() && a.traits.Contains()).FirstOrDefault(); - + if (underCursor != null) - yield return new Order("ChronosphereSelect", underCursor, null, int2.Zero, power.Name); + yield return new Order("ChronosphereSelect", world.LocalPlayer.PlayerActor, underCursor); } + + yield break; } public void Tick( World world ) @@ -43,8 +40,9 @@ namespace OpenRa.Orders var hasChronosphere = world.Actors .Any(a => a.Owner == world.LocalPlayer && a.traits.Contains()); - if (!hasChronosphere) - Game.controller.CancelInputMode(); + // HACK: re-enable this + //if (!hasChronosphere) + // Game.controller.CancelInputMode(); } public void Render( World world ) { } diff --git a/OpenRa.Game/Orders/IronCurtainOrderGenerator.cs b/OpenRa.Game/Orders/IronCurtainOrderGenerator.cs index d8bbbd77e5..61ec4433e6 100644 --- a/OpenRa.Game/Orders/IronCurtainOrderGenerator.cs +++ b/OpenRa.Game/Orders/IronCurtainOrderGenerator.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; using OpenRa.GameRules; using OpenRa.Traits; -using OpenRa.SupportPowers; namespace OpenRa.Orders { @@ -34,8 +33,10 @@ namespace OpenRa.Orders && a.traits.Contains()).FirstOrDefault(); if (underCursor != null) - yield return new Order("IronCurtain", underCursor, null, int2.Zero, power.Name); + yield return new Order("IronCurtain", underCursor.Owner.PlayerActor, underCursor); } + + yield break; } public void Tick( World world ) diff --git a/OpenRa.Game/Orders/PlaceBuildingOrderGenerator.cs b/OpenRa.Game/Orders/PlaceBuildingOrderGenerator.cs index 2e586f3489..842175ebaf 100644 --- a/OpenRa.Game/Orders/PlaceBuildingOrderGenerator.cs +++ b/OpenRa.Game/Orders/PlaceBuildingOrderGenerator.cs @@ -36,7 +36,7 @@ namespace OpenRa.Orders yield break; } - yield return new Order("PlaceBuilding", Producer.Owner.PlayerActor, null, topLeft, Building); + yield return new Order("PlaceBuilding", Producer.Owner.PlayerActor, topLeft, Building); } } diff --git a/OpenRa.Game/Orders/PowerDownOrderGenerator.cs b/OpenRa.Game/Orders/PowerDownOrderGenerator.cs index 3ecb702812..b4e7144ff3 100644 --- a/OpenRa.Game/Orders/PowerDownOrderGenerator.cs +++ b/OpenRa.Game/Orders/PowerDownOrderGenerator.cs @@ -28,7 +28,7 @@ namespace OpenRa.Orders && a.traits.Contains()).FirstOrDefault(); if (underCursor != null) - yield return new Order("PowerDown", underCursor, null, int2.Zero, null); + yield return new Order("PowerDown", underCursor); } } diff --git a/OpenRa.Game/Orders/RepairOrderGenerator.cs b/OpenRa.Game/Orders/RepairOrderGenerator.cs index b4e8cf1bb1..bc7144cbb1 100644 --- a/OpenRa.Game/Orders/RepairOrderGenerator.cs +++ b/OpenRa.Game/Orders/RepairOrderGenerator.cs @@ -30,7 +30,7 @@ namespace OpenRa.Orders var building = underCursor != null ? underCursor.Info.Traits.Get() : null; if (building != null && building.Repairable && underCursor.Health < building.HP) - yield return new Order("Repair", underCursor, null, int2.Zero, null); + yield return new Order("Repair", underCursor); } } diff --git a/OpenRa.Game/Orders/SellOrderGenerator.cs b/OpenRa.Game/Orders/SellOrderGenerator.cs index 7c34244dfb..347ac977ad 100644 --- a/OpenRa.Game/Orders/SellOrderGenerator.cs +++ b/OpenRa.Game/Orders/SellOrderGenerator.cs @@ -30,7 +30,7 @@ namespace OpenRa.Orders var building = underCursor != null ? underCursor.Info.Traits.Get() : null; if (building != null && !building.Unsellable) - yield return new Order("Sell", underCursor, null, int2.Zero, null); + yield return new Order("Sell", underCursor); } } diff --git a/OpenRa.Game/PackageDownloader.cs b/OpenRa.Game/PackageDownloader.cs index 4524cd6dc5..5ea68abfa8 100644 --- a/OpenRa.Game/PackageDownloader.cs +++ b/OpenRa.Game/PackageDownloader.cs @@ -68,7 +68,7 @@ namespace OpenRa Game.chat.AddLine(Color.White, "Debug", "Requesting package: {0}".F(currentPackage)); Game.orderManager.IssueOrder( - new Order("RequestFile", Game.world.LocalPlayer.PlayerActor, null, int2.Zero, currentPackage) { IsImmediate = true }); + new Order("RequestFile", Game.world.LocalPlayer.PlayerActor, currentPackage) { IsImmediate = true }); Fraction = 0f; } diff --git a/OpenRa.Game/Player.cs b/OpenRa.Game/Player.cs index 05322d4664..c12f96c5e1 100644 --- a/OpenRa.Game/Player.cs +++ b/OpenRa.Game/Player.cs @@ -29,7 +29,6 @@ namespace OpenRa public World World { get { return PlayerActor.World; } } public Shroud Shroud; - public Dictionary SupportPowers; public Player( World world, int index, Session.Client client ) { @@ -41,10 +40,6 @@ namespace OpenRa this.Palette = client != null ? (PaletteType)client.Palette : (PaletteType)index; this.PlayerName = client != null ? client.Name : "Player {0}".F(index+1); this.Race = client != null ? (Race)client.Race : Race.Allies; - - SupportPowers = Rules.SupportPowerInfo.ToDictionary( - spi => spi.Key, - spi => new SupportPower(spi.Key, spi.Value, this)); } void UpdatePower() @@ -134,9 +129,6 @@ namespace OpenRa UpdateOreCapacity(); Shroud.Tick( World ); - foreach (var sp in SupportPowers.Values) - sp.Tick(); - if (this == World.LocalPlayer) { var totalMoney = Cash + Ore; diff --git a/OpenRa.Game/SupportPower.cs b/OpenRa.Game/SupportPower.cs deleted file mode 100644 index 4544451316..0000000000 --- a/OpenRa.Game/SupportPower.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System; -using System.Linq; -using OpenRa.GameRules; -using OpenRa.SupportPowers; -using OpenRa.Traits; - -namespace OpenRa -{ - // todo: fix this to route Activate through the orders system (otherwise desync in netplay) - - public class SupportPower - { - public readonly SupportPowerInfo Info; - public readonly Player Owner; - public readonly ISupportPowerImpl Impl; - public readonly string Name; - - static ISupportPowerImpl ConstructPowerImpl(string implName) - { - var type = typeof(ISupportPowerImpl).Assembly.GetType( - typeof(ISupportPowerImpl).Namespace + "." + implName, true, false); - var ctor = type.GetConstructor(Type.EmptyTypes); - return (ISupportPowerImpl)ctor.Invoke(new object[] { }); - } - - public SupportPower(string name, SupportPowerInfo info, Player owner) - { - Name = name; - Info = info; - Owner = owner; - RemainingTime = TotalTime = (int)(info.ChargeTime * 60 * 25); - Impl = ConstructPowerImpl(info.Impl); - } - - public bool IsUsed; - public bool IsAvailable { get; private set; } - public bool IsDone { get { return RemainingTime == 0; } } - public int RemainingTime { get; private set; } - public int TotalTime { get; private set; } - bool notifiedReady = false; - bool notifiedCharging = false; - - public void Tick() - { - if (Info.OneShot && IsUsed) - return; - - if (Info.GivenAuto) - { - var buildings = Rules.TechTree.GatherBuildings(Owner); - var effectivePrereq = Info.Prerequisite - .Select( a => a.ToLowerInvariant() ) - .Where( a => Rules.Info[a].Traits.Get().Owner.Contains( Owner.Race )); - - IsAvailable = Info.TechLevel > -1 - && effectivePrereq.Any() - && effectivePrereq.All(a => buildings[a].Count > 0); - } - - if (IsAvailable && (!Info.Powered || Owner.GetPowerState() == PowerState.Normal)) - { - if (RemainingTime > 0) --RemainingTime; - if (!notifiedCharging) - { - Impl.IsChargingNotification(this); - notifiedCharging = true; - } - } - - if (RemainingTime == 0 - && Impl != null - && !notifiedReady) - { - Impl.IsReadyNotification(this); - notifiedReady = true; - } - } - - public void Activate() - { - if (Impl != null) - Impl.Activate(this); - } - - public void FinishActivate() - { - if (Info.OneShot) - { - IsUsed = true; - IsAvailable = false; - } - RemainingTime = TotalTime; - notifiedReady = false; - notifiedCharging = false; - } - - public void Give(bool requireCharge) // called by crate/spy/etc code - { - IsAvailable = true; - IsUsed = false; - RemainingTime = requireCharge ? TotalTime : 0; - } - } -} diff --git a/OpenRa.Game/SupportPowers/ChronospherePower.cs b/OpenRa.Game/SupportPowers/ChronospherePower.cs deleted file mode 100644 index 05aef7d637..0000000000 --- a/OpenRa.Game/SupportPowers/ChronospherePower.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Drawing; -using OpenRa.Orders; -using OpenRa.Traits; - -namespace OpenRa.SupportPowers -{ - class ChronospherePower : ISupportPowerImpl - { - public void IsReadyNotification(SupportPower p) { Sound.Play("chrordy1.aud"); } - public void IsChargingNotification(SupportPower p) { Sound.Play("chrochr1.aud"); } - - public void OnFireNotification(Actor target, int2 xy) - { - p.FinishActivate(); - Game.controller.CancelInputMode(); - - Sound.Play("chrono2.aud"); - - // Play chronosphere active anim - var chronosphere = target.World.Actors.Where(a => a.Owner == p.Owner && a.traits.Contains()).FirstOrDefault(); - if (chronosphere != null) - Game.orderManager.IssueOrder(Order.PlayAnimation(chronosphere, "active")); - - // Trigger screen desaturate effect - foreach (var a in target.World.Actors.Where(a => a.traits.Contains())) - a.traits.Get().DoChronoshift(); - } - SupportPower p; - public void Activate(SupportPower p) - { - this.p = p; - Game.controller.orderGenerator = new ChronosphereSelectOrderGenerator(p); - Sound.Play("slcttgt1.aud"); - } - } -} diff --git a/OpenRa.Game/SupportPowers/GpsSatellite.cs b/OpenRa.Game/SupportPowers/GpsSatellite.cs deleted file mode 100644 index 195d99abab..0000000000 --- a/OpenRa.Game/SupportPowers/GpsSatellite.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Linq; -using OpenRa.Effects; -using OpenRa.Traits; - -namespace OpenRa.SupportPowers -{ - class GpsSatellite : ISupportPowerImpl - { - const int revealDelay = 15 * 25; - - public void OnFireNotification(Actor a, int2 xy) { } - public void IsChargingNotification(SupportPower p) { } - public void IsReadyNotification(SupportPower p) - { - var launchSite = p.Owner.World.Actors - .FirstOrDefault(a => a.Owner == p.Owner && a.traits.Contains()); - - if (launchSite == null) - return; - - p.Owner.World.AddFrameEndTask(w => - { - w.Add(new SatelliteLaunch(launchSite)); - w.Add(new DelayedAction(revealDelay, () => p.Owner.Shroud.HasGPS = true)); - }); - - p.FinishActivate(); - } - - public void Activate(SupportPower p) {} - } -} diff --git a/OpenRa.Game/SupportPowers/ISupportPowerImpl.cs b/OpenRa.Game/SupportPowers/ISupportPowerImpl.cs deleted file mode 100644 index c28694cf95..0000000000 --- a/OpenRa.Game/SupportPowers/ISupportPowerImpl.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace OpenRa.SupportPowers -{ - public interface ISupportPowerImpl - { - void Activate(SupportPower p); - void OnFireNotification(Actor target, int2 xy); - void IsChargingNotification(SupportPower p); - void IsReadyNotification(SupportPower p); - } -} diff --git a/OpenRa.Game/SupportPowers/IronCurtainPower.cs b/OpenRa.Game/SupportPowers/IronCurtainPower.cs deleted file mode 100644 index f22db1a611..0000000000 --- a/OpenRa.Game/SupportPowers/IronCurtainPower.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using OpenRa.Orders; -using OpenRa.Traits; - -namespace OpenRa.SupportPowers -{ - class IronCurtainPower : ISupportPowerImpl - { - public void IsReadyNotification(SupportPower p) - { - Sound.Play("ironrdy1.aud"); - } - - public void IsChargingNotification(SupportPower p) - { - Sound.Play("ironchg1.aud"); - } - - public void OnFireNotification(Actor target, int2 xy) - { - p.FinishActivate(); - Game.controller.CancelInputMode(); - Sound.Play("ironcur9.aud"); - - // Play active anim - var ironCurtain = target.World.Actors - .Where(a => a.Owner == p.Owner && a.traits.Contains()) - .FirstOrDefault(); - if (ironCurtain != null) - Game.orderManager.IssueOrder(Order.PlayAnimation(ironCurtain, "active")); - - } - SupportPower p; - public void Activate(SupportPower p) - { - this.p = p; - // Pick a building to use - Game.controller.orderGenerator = new IronCurtainOrderGenerator(p); - Sound.Play("slcttgt1.aud"); - } - } -} diff --git a/OpenRa.Game/SupportPowers/NullPower.cs b/OpenRa.Game/SupportPowers/NullPower.cs deleted file mode 100644 index caf2c57c15..0000000000 --- a/OpenRa.Game/SupportPowers/NullPower.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace OpenRa.SupportPowers -{ - class NullPower : ISupportPowerImpl - { - public void OnFireNotification(Actor a, int2 xy) { } - public void IsReadyNotification(SupportPower p) { } - public void IsChargingNotification(SupportPower p) { } - public void Activate(SupportPower p) - { - // if this was a real power, i'd do something here! - throw new NotImplementedException(); - } - } -} diff --git a/OpenRa.Game/Traits/AttackBase.cs b/OpenRa.Game/Traits/AttackBase.cs index af9dcfb010..3a43c45748 100644 --- a/OpenRa.Game/Traits/AttackBase.cs +++ b/OpenRa.Game/Traits/AttackBase.cs @@ -195,7 +195,7 @@ namespace OpenRa.Traits if (!Combat.HasAnyValidWeapons(self, underCursor)) return null; - return new Order(isHeal ? "Heal" : "Attack", self, underCursor, int2.Zero, null); + return new Order(isHeal ? "Heal" : "Attack", self, underCursor); } public void ResolveOrder(Actor self, Order order) diff --git a/OpenRa.Game/Traits/AutoHeal.cs b/OpenRa.Game/Traits/AutoHeal.cs index f81564e3b9..7f480550cc 100644 --- a/OpenRa.Game/Traits/AutoHeal.cs +++ b/OpenRa.Game/Traits/AutoHeal.cs @@ -11,7 +11,7 @@ namespace OpenRa.Traits { var attack = self.traits.Get(); if (target != null) - attack.ResolveOrder(self, new Order("Attack", self, target, int2.Zero, null)); + attack.ResolveOrder(self, new Order("Attack", self, target)); else if (self.GetCurrentActivity() is Attack) self.CancelActivity(); diff --git a/OpenRa.Game/Traits/AutoTarget.cs b/OpenRa.Game/Traits/AutoTarget.cs index cef1214bc9..647e6b2c64 100644 --- a/OpenRa.Game/Traits/AutoTarget.cs +++ b/OpenRa.Game/Traits/AutoTarget.cs @@ -10,7 +10,7 @@ namespace OpenRa.Traits { var attack = self.traits.Get(); if (target != null) - attack.ResolveOrder(self, new Order("Attack", self, target, int2.Zero, null)); + attack.ResolveOrder(self, new Order("Attack", self, target)); } public void Tick(Actor self) diff --git a/OpenRa.Game/Traits/Cargo.cs b/OpenRa.Game/Traits/Cargo.cs index f5caacd5b3..4de9cd9099 100644 --- a/OpenRa.Game/Traits/Cargo.cs +++ b/OpenRa.Game/Traits/Cargo.cs @@ -26,7 +26,7 @@ namespace OpenRa.Traits var unit = underCursor.traits.GetOrDefault(); if (unit != null && unit.Altitude > 0) return null; - return new Order("Deploy", self, null, int2.Zero, null); + return new Order("Deploy", self); } return null; diff --git a/OpenRa.Game/Traits/ChronoshiftPower.cs b/OpenRa.Game/Traits/ChronoshiftPower.cs new file mode 100644 index 0000000000..e79ac8b6e9 --- /dev/null +++ b/OpenRa.Game/Traits/ChronoshiftPower.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using OpenRa.Orders; + +namespace OpenRa.Traits +{ + class ChronoshiftPowerInfo : SupportPowerInfo + { + public readonly float Duration = 0f; + public readonly bool KillCargo = true; + public override object Create(Actor self) { return new ChronoshiftPower(self,this); } + } + + class ChronoshiftPower : SupportPower, IResolveOrder + { + public ChronoshiftPower(Actor self, ChronoshiftPowerInfo info) : base(self, info) { } + protected override void OnBeginCharging() { Sound.Play("chrochr1.aud"); } + protected override void OnFinishCharging() { Sound.Play("chrordy1.aud"); } + + protected override void OnActivate() + { + Game.controller.orderGenerator = new ChronosphereSelectOrderGenerator(); + Sound.Play("slcttgt1.aud"); + } + + public void ResolveOrder(Actor self, Order order) + { + if (order.OrderString == "ChronosphereSelect" && self.Owner == self.World.LocalPlayer) + { + Game.controller.orderGenerator = new ChronoshiftDestinationOrderGenerator(order.TargetActor); + Sound.Play("slcttgt1.aud"); + } + + if (order.OrderString == "ChronosphereFinish") + { + Game.controller.CancelInputMode(); + FinishActivate(); + + Sound.Play("chrono2.aud"); + + var chronosphere = self.World.Actors.Where(a => a.Owner == self.Owner + && a.traits.Contains()).FirstOrDefault(); + if (chronosphere != null) + Game.orderManager.IssueOrder(new Order("PlayAnimation", chronosphere, "active")); + + // Trigger screen desaturate effect + foreach (var a in self.World.Actors.Where(a => a.traits.Contains())) + a.traits.Get().DoChronoshift(); + } + } + } + + // tag trait to identify the building + class ChronosphereInfo : StatelessTraitInfo { } + public class Chronosphere { } +} diff --git a/OpenRa.Game/Traits/Chronoshiftable.cs b/OpenRa.Game/Traits/Chronoshiftable.cs index 18498faa93..30306ec3b6 100644 --- a/OpenRa.Game/Traits/Chronoshiftable.cs +++ b/OpenRa.Game/Traits/Chronoshiftable.cs @@ -10,7 +10,7 @@ namespace OpenRa.Traits public object Create(Actor self) { return new Chronoshiftable(self); } } - public class Chronoshiftable : IResolveOrder, ISpeedModifier, ITick + public class Chronoshiftable : IResolveOrder, ITick { // Return-to-sender logic [Sync] @@ -39,12 +39,6 @@ namespace OpenRa.Traits public void ResolveOrder(Actor self, Order order) { - if (order.OrderString == "ChronosphereSelect") - { - var power = self.Owner.SupportPowers[order.TargetString]; - Game.controller.orderGenerator = new ChronoshiftDestinationOrderGenerator(self, power); - } - var movement = self.traits.GetOrDefault(); if (order.OrderString == "Chronoshift" && movement.CanEnterCell(order.TargetLocation)) { @@ -70,16 +64,8 @@ namespace OpenRa.Traits // Set up the teleport self.CancelActivity(); self.QueueActivity(new Activities.Teleport(order.TargetLocation)); - - var power = self.Owner.SupportPowers[order.TargetString].Impl; - power.OnFireNotification(self, self.Location); } } - - public float GetSpeedModifier() - { - // ARGH! You must not do this, it will desync! - return (Game.controller.orderGenerator is ChronoshiftDestinationOrderGenerator) ? 0f : 1f; - } } + } diff --git a/OpenRa.Game/Traits/Chronosphere.cs b/OpenRa.Game/Traits/Chronosphere.cs deleted file mode 100644 index 0951dfc678..0000000000 --- a/OpenRa.Game/Traits/Chronosphere.cs +++ /dev/null @@ -1,18 +0,0 @@ - -namespace OpenRa.Traits -{ - class ChronosphereInfo : StatelessTraitInfo { } - - public class Chronosphere : IResolveOrder - { - public void ResolveOrder(Actor self, Order order) - { - if (order.OrderString == "PlayAnimation") - { - var rb = self.traits.Get(); - if (rb != null) - rb.PlayCustomAnim(self, order.TargetString); - } - } - } -} diff --git a/OpenRa.Game/Traits/ConstructionYard.cs b/OpenRa.Game/Traits/ConstructionYard.cs index 36486265d7..9a8a696880 100644 --- a/OpenRa.Game/Traits/ConstructionYard.cs +++ b/OpenRa.Game/Traits/ConstructionYard.cs @@ -30,7 +30,7 @@ namespace OpenRa.Traits if (!self.World.IsActorCrushableByActor(underCursor, self)) return null; } - return new Order("Move", self, null, xy, null); + return new Order("Move", self, xy); } public void ResolveOrder(Actor self, Order order) diff --git a/OpenRa.Game/Traits/GpsPower.cs b/OpenRa.Game/Traits/GpsPower.cs new file mode 100644 index 0000000000..b3ea8af8c5 --- /dev/null +++ b/OpenRa.Game/Traits/GpsPower.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using OpenRa.Effects; + +namespace OpenRa.Traits +{ + class GpsPowerInfo : SupportPowerInfo + { + public readonly int RevealDelay = 0; + + public override object Create(Actor self) { return new GpsPower(self, this); } + } + + class GpsPower : SupportPower + { + public GpsPower(Actor self, GpsPowerInfo info) : base(self, info) { } + + protected override void OnFinishCharging() + { + var launchSite = Owner.World.Actors + .FirstOrDefault(a => a.Owner == Owner && a.traits.Contains()); + + if (launchSite == null) + return; + + Owner.World.AddFrameEndTask(w => + { + w.Add(new SatelliteLaunch(launchSite)); + w.Add(new DelayedAction((Info as GpsPowerInfo).RevealDelay * 25, + () => Owner.Shroud.HasGPS = true)); + }); + + FinishActivate(); + } + } +} diff --git a/OpenRa.Game/Traits/Harvester.cs b/OpenRa.Game/Traits/Harvester.cs index a6e6acbfb8..073cc8e38e 100644 --- a/OpenRa.Game/Traits/Harvester.cs +++ b/OpenRa.Game/Traits/Harvester.cs @@ -39,10 +39,10 @@ namespace OpenRa.Traits if (underCursor != null && underCursor.Owner == self.Owner && underCursor.traits.Contains() && !IsEmpty) - return new Order("Deliver", self, underCursor, int2.Zero, null); + return new Order("Deliver", self, underCursor); if (underCursor == null && self.World.Map.ContainsResource(xy)) - return new Order("Harvest", self, null, xy, null); + return new Order("Harvest", self, xy); return null; } diff --git a/OpenRa.Game/Traits/Helicopter.cs b/OpenRa.Game/Traits/Helicopter.cs index 53223925a0..908cca6a05 100644 --- a/OpenRa.Game/Traits/Helicopter.cs +++ b/OpenRa.Game/Traits/Helicopter.cs @@ -27,12 +27,12 @@ namespace OpenRa.Traits if (mi.Button == MouseButton.Left) return null; if (underCursor == null) - return new Order("Move", self, null, xy, null); + return new Order("Move", self, xy); if (HeliCanEnter(underCursor) && underCursor.Owner == self.Owner && !Reservable.IsReserved(underCursor)) - return new Order("Enter", self, underCursor, int2.Zero, null); + return new Order("Enter", self, underCursor); return null; } diff --git a/OpenRa.Game/Traits/IronCurtain.cs b/OpenRa.Game/Traits/IronCurtain.cs deleted file mode 100644 index b342683353..0000000000 --- a/OpenRa.Game/Traits/IronCurtain.cs +++ /dev/null @@ -1,18 +0,0 @@ - -namespace OpenRa.Traits -{ - class IronCurtainInfo : StatelessTraitInfo { } - - class IronCurtain : IResolveOrder - { - public void ResolveOrder(Actor self, Order order) - { - if (order.OrderString == "PlayAnimation") - { - var rb = self.traits.Get(); - if (rb != null) - rb.PlayCustomAnim(self, order.TargetString); - } - } - } -} diff --git a/OpenRa.Game/Traits/IronCurtainPower.cs b/OpenRa.Game/Traits/IronCurtainPower.cs new file mode 100644 index 0000000000..61b611b52c --- /dev/null +++ b/OpenRa.Game/Traits/IronCurtainPower.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using OpenRa.Orders; + +namespace OpenRa.Traits +{ + class IronCurtainPowerInfo : SupportPowerInfo + { + public readonly float Duration = 0f; + public override object Create(Actor self) { return new IronCurtainPower(self, this); } + } + + class IronCurtainPower : SupportPower, IResolveOrder + { + public IronCurtainPower(Actor self, IronCurtainPowerInfo info) : base(self, info) { } + + protected override void OnBeginCharging() { Sound.Play("ironchg1.aud"); } + protected override void OnFinishCharging() { Sound.Play("ironrdy1.aud"); } + protected override void OnActivate() + { + Game.controller.orderGenerator = new IronCurtainOrderGenerator(this); + Sound.Play("slcttgt1.aud"); + } + + public void ResolveOrder(Actor self, Order order) + { + if (order.OrderString == "IronCurtain") + { + order.TargetActor.traits.Get().Activate(order.TargetActor, + (int)((Info as IronCurtainPowerInfo).Duration * 25 * 60)); + Game.controller.CancelInputMode(); + FinishActivate(); + } + } + } + + // tag trait for the building + class IronCurtainInfo : StatelessTraitInfo { } + class IronCurtain { } +} diff --git a/OpenRa.Game/Traits/IronCurtainable.cs b/OpenRa.Game/Traits/IronCurtainable.cs index 4d761fc2a7..3447cb0efb 100644 --- a/OpenRa.Game/Traits/IronCurtainable.cs +++ b/OpenRa.Game/Traits/IronCurtainable.cs @@ -8,7 +8,7 @@ namespace OpenRa.Traits public object Create(Actor self) { return new IronCurtainable(); } } - class IronCurtainable : IResolveOrder, IDamageModifier, ITick + class IronCurtainable : IDamageModifier, ITick { [Sync] int RemainingTicks = 0; @@ -18,20 +18,16 @@ namespace OpenRa.Traits if (RemainingTicks > 0) RemainingTicks--; } + public float GetDamageModifier() { return (RemainingTicks > 0) ? 0.0f : 1.0f; } - public void ResolveOrder(Actor self, Order order) + public void Activate(Actor self, int duration) { - if (order.OrderString == "IronCurtain") - { - var power = self.Owner.SupportPowers[order.TargetString].Impl; - power.OnFireNotification(self, self.Location); - self.World.AddFrameEndTask(w => w.Add(new InvulnEffect(self))); - RemainingTicks = (int)(Rules.General.IronCurtain * 60 * 25); - } + self.World.AddFrameEndTask(w => w.Add(new InvulnEffect(self))); + RemainingTicks = duration; } } } diff --git a/OpenRa.Game/Traits/McvDeploy.cs b/OpenRa.Game/Traits/McvDeploy.cs index 72c75ab5a5..5e72aaeeec 100644 --- a/OpenRa.Game/Traits/McvDeploy.cs +++ b/OpenRa.Game/Traits/McvDeploy.cs @@ -15,7 +15,7 @@ namespace OpenRa.Traits public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor) { if (mi.Button == MouseButton.Right && self == underCursor) - return new Order("DeployMcv", self, null, int2.Zero, null); + return new Order("DeployMcv", self); return null; } diff --git a/OpenRa.Game/Traits/Mobile.cs b/OpenRa.Game/Traits/Mobile.cs index 0ccdda4176..0bc226d367 100644 --- a/OpenRa.Game/Traits/Mobile.cs +++ b/OpenRa.Game/Traits/Mobile.cs @@ -67,7 +67,7 @@ namespace OpenRa.Traits if (Util.GetEffectiveSpeed(self) == 0) return null; /* allow disabling move orders from modifiers */ if (xy == toCell) return null; - return new Order("Move", self, null, xy, null); + return new Order("Move", self, xy); } public void ResolveOrder(Actor self, Order order) diff --git a/OpenRa.Game/Traits/Passenger.cs b/OpenRa.Game/Traits/Passenger.cs index e48b0806a2..e8c3c79be4 100644 --- a/OpenRa.Game/Traits/Passenger.cs +++ b/OpenRa.Game/Traits/Passenger.cs @@ -23,7 +23,7 @@ namespace OpenRa.Traits if (!underCursor.Info.Traits.Get().PassengerTypes.Contains(umt)) return null; - return new Order("EnterTransport", self, underCursor, int2.Zero, null); + return new Order("EnterTransport", self, underCursor); } public void ResolveOrder(Actor self, Order order) diff --git a/OpenRa.Game/Traits/Plane.cs b/OpenRa.Game/Traits/Plane.cs index f83a1f3f02..60977b53ef 100644 --- a/OpenRa.Game/Traits/Plane.cs +++ b/OpenRa.Game/Traits/Plane.cs @@ -26,12 +26,12 @@ namespace OpenRa.Traits { if (mi.Button == MouseButton.Left) return null; if (underCursor == null) - return new Order("Move", self, null, xy, null); + return new Order("Move", self, xy); if (PlaneCanEnter(underCursor) && underCursor.Owner == self.Owner && !Reservable.IsReserved(underCursor)) - return new Order("Enter", self, underCursor, int2.Zero, null); + return new Order("Enter", self, underCursor); return null; } diff --git a/OpenRa.Game/Traits/Production.cs b/OpenRa.Game/Traits/Production.cs index a15ebdb240..989f2ae1e3 100755 --- a/OpenRa.Game/Traits/Production.cs +++ b/OpenRa.Game/Traits/Production.cs @@ -65,7 +65,7 @@ namespace OpenRa.Traits public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor) { if (mi.Button == MouseButton.Right && underCursor == self) - return new Order("Deploy", self, null, int2.Zero, null); + return new Order("Deploy", self); return null; } diff --git a/OpenRa.Game/Traits/RallyPoint.cs b/OpenRa.Game/Traits/RallyPoint.cs index 570e346af3..9629c6081a 100644 --- a/OpenRa.Game/Traits/RallyPoint.cs +++ b/OpenRa.Game/Traits/RallyPoint.cs @@ -36,7 +36,7 @@ namespace OpenRa.Traits public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor) { if (mi.Button == MouseButton.Left || underCursor != null) return null; - return new Order("SetRallyPoint", self, null, xy, null); + return new Order("SetRallyPoint", self, xy); } public void ResolveOrder( Actor self, Order order ) diff --git a/OpenRa.Game/Traits/RenderBuilding.cs b/OpenRa.Game/Traits/RenderBuilding.cs index 1e0e41a5e7..0ba2bcc1d4 100644 --- a/OpenRa.Game/Traits/RenderBuilding.cs +++ b/OpenRa.Game/Traits/RenderBuilding.cs @@ -8,7 +8,7 @@ namespace OpenRa.Traits public override object Create(Actor self) { return new RenderBuilding(self); } } - class RenderBuilding : RenderSimple, INotifyDamage, INotifySold + class RenderBuilding : RenderSimple, INotifyDamage, INotifySold, IResolveOrder { const int SmallBibStart = 1; const int LargeBibStart = 5; @@ -99,5 +99,11 @@ namespace OpenRa.Traits } public void Sold(Actor self) { DoBib(self, true); } + + public void ResolveOrder(Actor self, Order order) + { + if (order.OrderString == "PlayAnimation") + PlayCustomAnim(self, order.TargetString); + } } } diff --git a/OpenRa.Game/Traits/Repairable.cs b/OpenRa.Game/Traits/Repairable.cs index e4f0095046..7157a5835a 100644 --- a/OpenRa.Game/Traits/Repairable.cs +++ b/OpenRa.Game/Traits/Repairable.cs @@ -24,7 +24,7 @@ namespace OpenRa.Traits if (underCursor.Info.Name == "fix" && underCursor.Owner == self.Owner && !Reservable.IsReserved(underCursor)) - return new Order("Enter", self, underCursor, int2.Zero, null); + return new Order("Enter", self, underCursor); return null; } diff --git a/OpenRa.Game/Traits/SupportPower.cs b/OpenRa.Game/Traits/SupportPower.cs new file mode 100644 index 0000000000..f31664074e --- /dev/null +++ b/OpenRa.Game/Traits/SupportPower.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace OpenRa.Traits +{ + abstract class SupportPowerInfo : ITraitInfo + { + public readonly bool RequiresPower = true; + public readonly bool OneShot = false; + public readonly float ChargeTime = 0; + public readonly string Image = null; + public readonly string Description = ""; + public readonly string LongDesc = ""; + public readonly string[] Prerequisites = { }; + public readonly int TechLevel = -1; + public readonly bool GivenAuto = true; + + public abstract object Create(Actor self); + } + + class SupportPower : ITick + { + 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 RemainingTime == 0; } } + public readonly Player Owner; + + bool notifiedCharging; + bool notifiedReady; + + public SupportPower(Actor self, SupportPowerInfo info) + { + Info = info; + RemainingTime = TotalTime; + Owner = self.Owner; + } + + public void Tick(Actor self) + { + if (Info.OneShot && IsUsed) + return; + + if (Info.GivenAuto) + { + var buildings = Rules.TechTree.GatherBuildings(self.Owner); + var effectivePrereq = Info.Prerequisites + .Select(a => a.ToLowerInvariant()) + .Where(a => Rules.Info[a].Traits.Get().Owner.Contains(self.Owner.Race)); + + IsAvailable = Info.TechLevel > -1 + && effectivePrereq.Any() + && effectivePrereq.All(a => buildings[a].Count > 0); + } + + if (IsAvailable && (!Info.RequiresPower || self.Owner.GetPowerState() == PowerState.Normal)) + { + if (RemainingTime > 0) --RemainingTime; + if (!notifiedCharging) + { + OnBeginCharging(); + notifiedCharging = true; + } + } + + if (RemainingTime == 0 + && !notifiedReady) + { + 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() { OnActivate(); } // todo: some more hax + } +} diff --git a/OpenRa.Mods.Aftermath/ChronoshiftDeploy.cs b/OpenRa.Mods.Aftermath/ChronoshiftDeploy.cs index 9fb760b74f..db74c1b9a0 100644 --- a/OpenRa.Mods.Aftermath/ChronoshiftDeploy.cs +++ b/OpenRa.Mods.Aftermath/ChronoshiftDeploy.cs @@ -29,7 +29,7 @@ namespace OpenRa.Mods.Aftermath public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor) { if (mi.Button == MouseButton.Right && xy == self.Location && chargeTick <= 0) - return new Order("Deploy", self, null, int2.Zero, null); + return new Order("Deploy", self); return null; } diff --git a/OpenRa.Mods.Aftermath/Orders/SetChronoTankDestination.cs b/OpenRa.Mods.Aftermath/Orders/SetChronoTankDestination.cs index dd69faa23a..6be3b3e0ba 100644 --- a/OpenRa.Mods.Aftermath/Orders/SetChronoTankDestination.cs +++ b/OpenRa.Mods.Aftermath/Orders/SetChronoTankDestination.cs @@ -21,7 +21,7 @@ namespace OpenRa.Mods.Aftermath.Orders yield break; } - yield return new Order("ChronoshiftSelf", self, null, xy, null); + yield return new Order("ChronoshiftSelf", self, xy); } public void Tick( World world ) { } diff --git a/OpenRa.Mods.RA/C4Demolition.cs b/OpenRa.Mods.RA/C4Demolition.cs index 402d899207..1e1bc647d5 100644 --- a/OpenRa.Mods.RA/C4Demolition.cs +++ b/OpenRa.Mods.RA/C4Demolition.cs @@ -15,7 +15,7 @@ namespace OpenRa.Mods.RA if (underCursor.Owner == self.Owner && !mi.Modifiers.HasModifier(Modifiers.Ctrl)) return null; if (!underCursor.traits.Contains()) return null; - return new Order("C4", self, underCursor, int2.Zero, null); + return new Order("C4", self, underCursor); } public void ResolveOrder(Actor self, Order order) diff --git a/OpenRa.Mods.RA/EngineerCapture.cs b/OpenRa.Mods.RA/EngineerCapture.cs index 1d07608b1f..1056b9d9b2 100644 --- a/OpenRa.Mods.RA/EngineerCapture.cs +++ b/OpenRa.Mods.RA/EngineerCapture.cs @@ -20,7 +20,7 @@ namespace OpenRa.Mods.RA if (underCursor.Owner == null) return null; // don't allow capturing of bridges, etc. return new Order(underCursor.Health <= EngineerDamage ? "Capture" : "Infiltrate", - self, underCursor, int2.Zero, null); + self, underCursor); } public void ResolveOrder(Actor self, Order order) diff --git a/OpenRa.Mods.RA/Minelayer.cs b/OpenRa.Mods.RA/Minelayer.cs index 8ae75d9059..825388f6ec 100644 --- a/OpenRa.Mods.RA/Minelayer.cs +++ b/OpenRa.Mods.RA/Minelayer.cs @@ -21,7 +21,7 @@ namespace OpenRa.Mods.RA return null; if (mi.Button == MouseButton.Right && underCursor == self) - return new Order("Deploy", self, null, int2.Zero, null); + return new Order("Deploy", self); return null; } diff --git a/OpenRa.Mods.RA/RepairableNear.cs b/OpenRa.Mods.RA/RepairableNear.cs index 721833d1c5..3d02000a73 100644 --- a/OpenRa.Mods.RA/RepairableNear.cs +++ b/OpenRa.Mods.RA/RepairableNear.cs @@ -15,11 +15,11 @@ namespace OpenRa.Mods.RA { if (mi.Button != MouseButton.Right) return null; if (underCursor == null) return null; - - if (underCursor.Owner == self.Owner && - (underCursor.Info.Name == "spen" || underCursor.Info.Name == "syrd") && + + if (underCursor.Owner == self.Owner && + (underCursor.Info.Name == "spen" || underCursor.Info.Name == "syrd") && self.Health < self.GetMaxHP()) - return new Order("Enter", self, underCursor, int2.Zero, null); + return new Order("Enter", self, underCursor); return null; } diff --git a/OpenRa.Mods.RA/Spy.cs b/OpenRa.Mods.RA/Spy.cs index 8ebb86a3f2..ceaec5eee6 100644 --- a/OpenRa.Mods.RA/Spy.cs +++ b/OpenRa.Mods.RA/Spy.cs @@ -19,7 +19,7 @@ namespace OpenRa.Mods.RA if (underCursor.Owner == self.Owner) return null; if (!underCursor.traits.Contains()) return null; - return new Order("Infiltrate", self, underCursor, int2.Zero, null); + return new Order("Infiltrate", self, underCursor); } public void ResolveOrder(Actor self, Order order) diff --git a/OpenRa.Mods.RA/Thief.cs b/OpenRa.Mods.RA/Thief.cs index 1f3eb5d19e..2161bcec42 100644 --- a/OpenRa.Mods.RA/Thief.cs +++ b/OpenRa.Mods.RA/Thief.cs @@ -13,8 +13,8 @@ namespace OpenRa.Mods.RA if (mi.Button != MouseButton.Right) return null; if (underCursor == null) return null; if (!underCursor.traits.Contains()) return null; - - return new Order("Steal", self, underCursor, int2.Zero, null); + + return new Order("Steal", self, underCursor); } public void ResolveOrder(Actor self, Order order) diff --git a/mods/ra/merge-rules.yaml b/mods/ra/merge-rules.yaml index 3d7631e9fc..18fa29e37f 100644 --- a/mods/ra/merge-rules.yaml +++ b/mods/ra/merge-rules.yaml @@ -1,6 +1,32 @@ Player: ProductionQueue: PlaceBuilding: + GpsPower: + Image: gpssicon + OneShot: yes + ChargeTime: 8 + Description: GPS Satellite + LongDesc: Reveals the entire map + Prerequisites: ATEK + TechLevel: 12 + RevealDelay: 15 + ChronoshiftPower: + Image: warpicon + ChargeTime: 7 + Description: Chronoshift + LongDesc: Temporarily teleports a vehicle across \nthe map. + Prerequisites: PDOX + TechLevel: 12 + Duration: 3 + KillCargo: yes + IronCurtainPower: + Image: infxicon + ChargeTime: 11 + Description: Invulnerability + LongDesc: Makes a single unit invulnerable for a \nshort time. + Prerequisites: IRON + TechLevel: 12 + Duration: .75 World: WaterPaletteRotation: diff --git a/mods/ra/rules.yaml b/mods/ra/rules.yaml index 7da019e819..9a4cf44835 100644 --- a/mods/ra/rules.yaml +++ b/mods/ra/rules.yaml @@ -1,6 +1,32 @@ Player: ProductionQueue: PlaceBuilding: + GpsPower: + Image: gpssicon + OneShot: yes + ChargeTime: 8 + Description: GPS Satellite + LongDesc: Reveals the entire map + Prerequisites: ATEK + TechLevel: 12 + RevealDelay: 15 + ChronoshiftPower: + Image: warpicon + ChargeTime: 7 + Description: Chronoshift + LongDesc: Temporarily teleports a vehicle across \nthe map. + Prerequisites: PDOX + TechLevel: 12 + Duration: 3 + KillCargo: yes + IronCurtainPower: + Image: infxicon + ChargeTime: 11 + Description: Invulnerability + LongDesc: Makes a single unit invulnerable for a \nshort time. + Prerequisites: IRON + TechLevel: 12 + Duration: .75 World: WaterPaletteRotation: diff --git a/mods/ra/units.ini b/mods/ra/units.ini index 9f85cc2f50..11dc2ea24a 100644 --- a/mods/ra/units.ini +++ b/mods/ra/units.ini @@ -849,20 +849,6 @@ Move=girlokay Select=einah1,einok1,einyes1 Move=einah1,einok1,einyes1 - -;; todo: where there are different variants of the same power, -;; split them here. SonarPulse is the obvious one. - -[SupportPowerTypes] -ParadropPower -ParabombPower -SonarPulsePower -ChronoshiftPower -SpyPlanePower -NukePower -GpsSatellitePower -InvulnerabilityPower - [ParadropPower] ; comes free with first AFLD ChargeTime=7 Description=Paratroopers @@ -894,15 +880,6 @@ TechLevel=5 GivenAuto=no Impl=NullPower -[ChronoshiftPower] ; free with Chronosphere... sortof the point. -ChargeTime=7 -Description=Chronoshift -LongDesc=Temporarily teleports a vehicle across \nthe map. -Prerequisite=PDOX -Image=warpicon -TechLevel=12 -Impl=ChronospherePower - [SpyPlanePower] ; free with first AFLD ChargeTime=3 TechLevel=5 @@ -921,21 +898,3 @@ Image=atomicon TechLevel=12 Impl=NullPower -[GpsSatellitePower] ; free with ATEK -ChargeTime=8 -Description=GPS Satellite -LongDesc=Reveals the entire map -OneShot=yes -Prerequisite=ATEK -Image=gpssicon -TechLevel=12 -Impl=GpsSatellite - -[InvulnerabilityPower] ; the point of IRON -ChargeTime=11 -Description=Invulnerability -LongDesc=Makes a single unit invulnerable for a \nshort time. -Image=infxicon -Prerequisite=IRON -TechLevel=12 -Impl=IronCurtainPower