diff --git a/OpenRa.Game/Controller.cs b/OpenRa.Game/Controller.cs index ca143b7aff..cbe2d35fa3 100644 --- a/OpenRa.Game/Controller.cs +++ b/OpenRa.Game/Controller.cs @@ -141,63 +141,14 @@ namespace OpenRa.Game public Cursor ChooseCursor() { - var mods = GetModifierKeys(); - - var mi = new MouseInput { - Location = (Game.CellSize * dragEnd - Game.viewport.Location).ToInt2(), - Button = MouseButton.Right, - Modifiers = mods, - IsFake = true, + var mi = new MouseInput + { + Location = (Game.CellSize * MousePosition - Game.viewport.Location).ToInt2(), + Button = MouseButton.Right, + Modifiers = GetModifierKeys(), }; - var c = orderGenerator.Order(dragEnd.ToInt2(), mi) - .Where(o => o.Validate()) - .Select(o => CursorForOrderString(o.OrderString, o.Subject, o.TargetLocation)) - .FirstOrDefault(a => a != null); - - return c ?? - (Game.SelectActorsInBox(Game.CellSize * dragEnd, Game.CellSize * dragEnd).Any() - ? Cursor.Select : Cursor.Default); - } - - Cursor CursorForOrderString( string s, Actor a, int2 location ) - { - var movement = a.traits.WithInterface().FirstOrDefault(); - switch( s ) - { - case "Attack": return Cursor.Attack; - case "Heal": return Cursor.Heal; - case "C4": return Cursor.C4; - case "Move": - if (movement.CanEnterCell(location)) - return Cursor.Move; - else - return Cursor.MoveBlocked; - case "DeployMcv": - var factBuildingInfo = (BuildingInfo)Rules.UnitInfo[ "fact" ]; - if( Game.CanPlaceBuilding( factBuildingInfo, a.Location - new int2( 1, 1 ), a, false ) ) - return Cursor.Deploy; - else - return Cursor.DeployBlocked; - case "Deploy": return Cursor.Deploy; - case "Chronoshift": - if (movement.CanEnterCell(location)) - return Cursor.Chronoshift; - else - return Cursor.MoveBlocked; - case "Enter": return Cursor.Enter; - case "Deliver": return Cursor.Enter; - case "Infiltrate": return Cursor.Enter; - case "Capture": return Cursor.Capture; - case "Harvest": return Cursor.Attack; // TODO: special harvest cursor? - case "PlaceBuilding": return Cursor.Default; - case "Sell": return Cursor.Sell; - case "NoSell": return Cursor.SellBlocked; - case "Repair": return Cursor.Repair; - case "NoRepair": return Cursor.RepairBlocked; - default: - return null; - } + return orderGenerator.GetCursor(MousePosition.ToInt2(), mi); } Cache> controlGroups = new Cache>(_ => new List()); @@ -205,9 +156,11 @@ namespace OpenRa.Game public void DoControlGroup(int group, Modifiers mods) { var uog = orderGenerator as UnitOrderGenerator; + if (uog == null) return; + if (mods.HasModifier(Modifiers.Ctrl)) { - if (uog == null || !uog.selection.Any()) + if (!uog.selection.Any()) return; controlGroups[group].Clear(); @@ -225,7 +178,6 @@ namespace OpenRa.Game return; } - if (uog == null) return; CombineSelection(controlGroups[group], mods.HasModifier(Modifiers.Shift), false); } diff --git a/OpenRa.Game/Cursor.cs b/OpenRa.Game/Cursor.cs index 6a7d341fef..d5ff149cb9 100644 --- a/OpenRa.Game/Cursor.cs +++ b/OpenRa.Game/Cursor.cs @@ -22,7 +22,7 @@ namespace OpenRa.Game public static Cursor Deploy { get { return new Cursor("deploy"); } } public static Cursor Enter { get { return new Cursor("enter"); } } public static Cursor DeployBlocked { get { return new Cursor("deploy-blocked"); } } - public static Cursor Chronoshift { get { return new Cursor("chrono"); } } + public static Cursor Chronoshift { get { return new Cursor("chrono"); } } public static Cursor C4 { get { return new Cursor("c4"); } } public static Cursor Capture { get { return new Cursor("capture"); } } public static Cursor Heal { get { return new Cursor("heal"); } } diff --git a/OpenRa.Game/GameRules/Rules.cs b/OpenRa.Game/GameRules/Rules.cs index 25be1f7693..70a3acdb5e 100755 --- a/OpenRa.Game/GameRules/Rules.cs +++ b/OpenRa.Game/GameRules/Rules.cs @@ -19,7 +19,7 @@ namespace OpenRa.Game public static InfoLoader VoiceInfo; public static InfoLoader SupportPowerInfo; public static GeneralInfo General; - public static AftermathInfo Aftermath; + public static AftermathInfo Aftermath; public static TechTree TechTree; public static Map Map; public static TileSet TileSet; @@ -48,7 +48,7 @@ namespace OpenRa.Game General = new GeneralInfo(); FieldLoader.Load(General, AllRules.GetSection("General")); - Aftermath = new AftermathInfo(); + Aftermath = new AftermathInfo(); if (useAftermath) FieldLoader.Load(Aftermath, AllRules.GetSection("Aftermath")); diff --git a/OpenRa.Game/MainWindow.cs b/OpenRa.Game/MainWindow.cs index d3f8017fa1..8d1d61ce81 100755 --- a/OpenRa.Game/MainWindow.cs +++ b/OpenRa.Game/MainWindow.cs @@ -200,7 +200,6 @@ namespace OpenRa.Game public int2 Location; public MouseButton Button; public Modifiers Modifiers; - public bool IsFake; } enum MouseInputEvent { Down, Move, Up }; diff --git a/OpenRa.Game/Orders/IOrderGenerator.cs b/OpenRa.Game/Orders/IOrderGenerator.cs index 0bdfc382ea..88ac531764 100644 --- a/OpenRa.Game/Orders/IOrderGenerator.cs +++ b/OpenRa.Game/Orders/IOrderGenerator.cs @@ -7,5 +7,6 @@ namespace OpenRa.Game IEnumerable Order( int2 xy, MouseInput mi ); void Tick(); void Render(); + Cursor GetCursor(int2 xy, MouseInput mi); } } diff --git a/OpenRa.Game/Orders/PlaceBuildingOrderGenerator.cs b/OpenRa.Game/Orders/PlaceBuildingOrderGenerator.cs index 43bf7be963..5c9d2b25fc 100644 --- a/OpenRa.Game/Orders/PlaceBuildingOrderGenerator.cs +++ b/OpenRa.Game/Orders/PlaceBuildingOrderGenerator.cs @@ -16,13 +16,14 @@ namespace OpenRa.Game.Orders public IEnumerable Order(int2 xy, MouseInput mi) { - if (mi.IsFake) - { - // this order is never actually issued, but it's used for choosing a cursor - yield return new Order("PlaceBuilding", Producer.Owner.PlayerActor, null, xy, Building.Name); - yield break; - } + if (mi.Button == MouseButton.Right) + Game.controller.CancelInputMode(); + return InnerOrder(xy, mi); + } + + IEnumerable InnerOrder(int2 xy, MouseInput mi) + { if (mi.Button == MouseButton.Left) { if (!Game.CanPlaceBuilding(Building, xy, null, true) @@ -34,8 +35,6 @@ namespace OpenRa.Game.Orders yield return new Order("PlaceBuilding", Producer.Owner.PlayerActor, null, xy, Building.Name); } - else - Game.controller.CancelInputMode(); } public void Tick() @@ -49,5 +48,10 @@ namespace OpenRa.Game.Orders { Game.worldRenderer.uiOverlay.DrawBuildingGrid( Building ); } + + public Cursor GetCursor(int2 xy, MouseInput mi) + { + return Cursor.Default; + } } } diff --git a/OpenRa.Game/Orders/RepairOrderGenerator.cs b/OpenRa.Game/Orders/RepairOrderGenerator.cs index 299c2e65a5..bc79d65ed4 100644 --- a/OpenRa.Game/Orders/RepairOrderGenerator.cs +++ b/OpenRa.Game/Orders/RepairOrderGenerator.cs @@ -11,42 +11,48 @@ namespace OpenRa.Game.Orders { public IEnumerable Order(int2 xy, MouseInput mi) { - if (!mi.IsFake && mi.Button == MouseButton.Right) - { + if (mi.Button == MouseButton.Right) Game.controller.CancelInputMode(); - yield break; - } - var loc = mi.Location + Game.viewport.Location; - var underCursor = Game.FindUnits(loc, loc) - .Where(a => a.Owner == Game.LocalPlayer - && a.traits.Contains() - && a.Info.Selectable).FirstOrDefault(); + return OrderInner(xy, mi); + } - var building = underCursor != null ? underCursor.Info as BuildingInfo : null; - - if (building == null || !building.Repairable || underCursor.Health == building.Strength) + IEnumerable OrderInner(int2 xy, MouseInput mi) + { + if (mi.Button == MouseButton.Left) { - yield return new Order("NoRepair", Game.LocalPlayer.PlayerActor, null, int2.Zero, null); - yield break; - } + var loc = mi.Location + Game.viewport.Location; + var underCursor = Game.FindUnits(loc, loc) + .Where(a => a.Owner == Game.LocalPlayer + && a.traits.Contains() + && a.Info.Selectable).FirstOrDefault(); - yield return new Order("Repair", underCursor, null, int2.Zero, null); + var building = underCursor != null ? underCursor.Info as BuildingInfo : null; + + if (building != null && building.Repairable && underCursor.Health < building.Strength) + yield return new Order("Repair", underCursor, null, int2.Zero, null); + } } public void Tick() { - if (Game.Settings.RepairRequiresConyard) - { - var hasFact = Game.world.Actors - .Any(a => a.Owner == Game.LocalPlayer && a.traits.Contains()); + if (!Game.Settings.RepairRequiresConyard) + return; + + var hasFact = Game.world.Actors + .Any(a => a.Owner == Game.LocalPlayer && a.traits.Contains()); - if (!hasFact) - Game.controller.CancelInputMode(); - } + if (!hasFact) + Game.controller.CancelInputMode(); } - public void Render() {} + + public Cursor GetCursor(int2 xy, MouseInput mi) + { + mi.Button = MouseButton.Left; + return OrderInner(xy, mi).Any() + ? Cursor.Repair : Cursor.RepairBlocked; + } } } diff --git a/OpenRa.Game/Orders/SellOrderGenerator.cs b/OpenRa.Game/Orders/SellOrderGenerator.cs index aac3baf3b5..3576c59d1e 100644 --- a/OpenRa.Game/Orders/SellOrderGenerator.cs +++ b/OpenRa.Game/Orders/SellOrderGenerator.cs @@ -11,30 +11,37 @@ namespace OpenRa.Game.Orders { public IEnumerable Order(int2 xy, MouseInput mi) { - if (!mi.IsFake && mi.Button == MouseButton.Right) - { + if (mi.Button == MouseButton.Right) Game.controller.CancelInputMode(); - yield break; - } - var loc = mi.Location + Game.viewport.Location; - var underCursor = Game.FindUnits(loc, loc) - .Where(a => a.Owner == Game.LocalPlayer - && a.traits.Contains() - && a.Info.Selectable).FirstOrDefault(); + return OrderInner(xy, mi); + } - var building = underCursor != null ? underCursor.Info as BuildingInfo : null; - - if (building == null || building.Unsellable) + IEnumerable OrderInner(int2 xy, MouseInput mi) + { + if (mi.Button == MouseButton.Left) { - yield return new Order("NoSell", Game.LocalPlayer.PlayerActor, null, int2.Zero, null); - yield break; - } + var loc = mi.Location + Game.viewport.Location; + var underCursor = Game.FindUnits(loc, loc) + .Where(a => a.Owner == Game.LocalPlayer + && a.traits.Contains() + && a.Info.Selectable).FirstOrDefault(); - yield return new Order("Sell", underCursor, null, int2.Zero, null); + var building = underCursor != null ? underCursor.Info as BuildingInfo : null; + + if (building != null && !building.Unsellable) + yield return new Order("Sell", underCursor, null, int2.Zero, null); + } } public void Tick() {} public void Render() {} + + public Cursor GetCursor(int2 xy, MouseInput mi) + { + mi.Button = MouseButton.Left; + return OrderInner(xy, mi).Any() + ? Cursor.Sell : Cursor.SellBlocked; + } } } diff --git a/OpenRa.Game/Orders/TeleportOrderGenerator.cs b/OpenRa.Game/Orders/TeleportOrderGenerator.cs index 0c14e694bb..3fca07bc4b 100644 --- a/OpenRa.Game/Orders/TeleportOrderGenerator.cs +++ b/OpenRa.Game/Orders/TeleportOrderGenerator.cs @@ -31,5 +31,10 @@ namespace OpenRa.Game.Orders { Game.worldRenderer.DrawSelectionBox(self, Color.White, true); } + + public Cursor GetCursor(int2 xy, MouseInput mi) + { + return Cursor.Chronoshift; + } } } diff --git a/OpenRa.Game/Orders/UnitOrderGenerator.cs b/OpenRa.Game/Orders/UnitOrderGenerator.cs index 91515eec3a..c50379f4e4 100644 --- a/OpenRa.Game/Orders/UnitOrderGenerator.cs +++ b/OpenRa.Game/Orders/UnitOrderGenerator.cs @@ -1,6 +1,8 @@ using System.Collections.Generic; using System.Drawing; using System.Linq; +using OpenRa.Game.Traits; +using OpenRa.Game.GameRules; namespace OpenRa.Game.Orders { @@ -33,5 +35,59 @@ namespace OpenRa.Game.Orders foreach( var a in selection ) Game.worldRenderer.DrawSelectionBox( a, Color.White, true ); } + + public Cursor GetCursor(int2 xy, MouseInput mi) + { + return ChooseCursor(mi); + } + + Cursor ChooseCursor( MouseInput mi ) + { + var p = Game.controller.MousePosition; + var c = Order(p.ToInt2(), mi) + .Where(o => o.Validate()) + .Select(o => CursorForOrderString(o.OrderString, o.Subject, o.TargetLocation)) + .FirstOrDefault(a => a != null); + + return c ?? + (Game.SelectActorsInBox(Game.CellSize * p, + Game.CellSize * p).Any() + ? Cursor.Select : Cursor.Default); + } + + Cursor CursorForOrderString(string s, Actor a, int2 location) + { + var movement = a.traits.WithInterface().FirstOrDefault(); + switch (s) + { + case "Attack": return Cursor.Attack; + case "Heal": return Cursor.Heal; + case "C4": return Cursor.C4; + case "Move": + if (movement.CanEnterCell(location)) + return Cursor.Move; + else + return Cursor.MoveBlocked; + case "DeployMcv": + var factBuildingInfo = (BuildingInfo)Rules.UnitInfo["fact"]; + if (Game.CanPlaceBuilding(factBuildingInfo, a.Location - new int2(1, 1), a, false)) + return Cursor.Deploy; + else + return Cursor.DeployBlocked; + case "Deploy": return Cursor.Deploy; + case "Chronoshift": + if (movement.CanEnterCell(location)) + return Cursor.Chronoshift; + else + return Cursor.MoveBlocked; + case "Enter": return Cursor.Enter; + case "Deliver": return Cursor.Enter; + case "Infiltrate": return Cursor.Enter; + case "Capture": return Cursor.Capture; + case "Harvest": return Cursor.Attack; // TODO: special harvest cursor? + default: + return null; + } + } } } diff --git a/OpenRa.Game/Traits/Activities/Teleport.cs b/OpenRa.Game/Traits/Activities/Teleport.cs index bb0dc81d7b..f638a60a7b 100644 --- a/OpenRa.Game/Traits/Activities/Teleport.cs +++ b/OpenRa.Game/Traits/Activities/Teleport.cs @@ -6,24 +6,24 @@ using OpenRa.Game.GameRules; namespace OpenRa.Game.Traits.Activities { - class Teleport : IActivity - { - public IActivity NextActivity { get; set; } + class Teleport : IActivity + { + public IActivity NextActivity { get; set; } - int2 destination; + int2 destination; - public Teleport(int2 destination) - { - this.destination = destination; - } + public Teleport(int2 destination) + { + this.destination = destination; + } - public IActivity Tick(Actor self) - { - var mobile = self.traits.Get(); + public IActivity Tick(Actor self) + { + var mobile = self.traits.Get(); mobile.TeleportTo(self, destination); - return NextActivity; - } + return NextActivity; + } public void Cancel(Actor self) { } - } + } } diff --git a/OpenRa.Game/Traits/ChronoshiftDeploy.cs b/OpenRa.Game/Traits/ChronoshiftDeploy.cs index f4bdc69cb2..b2c280cf8e 100644 --- a/OpenRa.Game/Traits/ChronoshiftDeploy.cs +++ b/OpenRa.Game/Traits/ChronoshiftDeploy.cs @@ -6,20 +6,22 @@ using System.Drawing; namespace OpenRa.Game.Traits { class ChronoshiftDeploy : IOrder, ISpeedModifier, ITick, IPips, IPaletteModifier - { - public ChronoshiftDeploy(Actor self) { } - // Recharge logic - int remainingChargeTime = 0; // How long until we can chronoshift again? - int chargeTime = (int)(Rules.Aftermath.ChronoTankDuration * 60 * 25); // How long between shifts? + { + // Recharge logic + int chargeTick = 0; // How long until we can chronoshift again? + int chargeLength = (int)(Rules.Aftermath.ChronoTankDuration * 60 * 25); // How long between shifts? // Screen fade logic int animationTick = 0; int animationLength = 10; bool animationStarted = false; - public void Tick(Actor self) - { - if (remainingChargeTime > 0) - remainingChargeTime--; + + public ChronoshiftDeploy(Actor self) { } + + public void Tick(Actor self) + { + if (chargeTick > 0) + chargeTick--; if (animationStarted) { @@ -32,45 +34,42 @@ namespace OpenRa.Game.Traits { if (animationTick > 0) animationTick--; - //else - // animationForwards = true; } - } + } - public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor) - { - if (mi.Button == MouseButton.Left) return null; - - else if (xy == self.Location && remainingChargeTime <= 0) + 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 null; - } - public void ResolveOrder(Actor self, Order order) - { - if (order.OrderString == "Deploy" && remainingChargeTime <= 0) - { + return null; + } + + public void ResolveOrder(Actor self, Order order) + { + if (order.OrderString == "Deploy") + { Game.controller.orderGenerator = new TeleportOrderGenerator(self); - self.CancelActivity(); - } - + return; + } + var movement = self.traits.WithInterface().FirstOrDefault(); if (order.OrderString == "Chronoshift" && movement.CanEnterCell(order.TargetLocation)) - { + { Game.controller.CancelInputMode(); self.CancelActivity(); - self.QueueActivity(new Activities.Teleport(order.TargetLocation)); - Sound.Play("chrotnk1.aud"); - remainingChargeTime = chargeTime; - animationStarted = true; - } - } - - public float GetSpeedModifier() - { - return (Game.controller.orderGenerator is TeleportOrderGenerator) ? 0f : 1f; - } + self.QueueActivity(new Activities.Teleport(order.TargetLocation)); + Sound.Play("chrotnk1.aud"); + chargeTick = chargeLength; + animationStarted = true; + } + } + + public float GetSpeedModifier() + { + // ARGH! You must not do this, it will desync! + return (Game.controller.orderGenerator is TeleportOrderGenerator) ? 0f : 1f; + } // Display 5 pips indicating the current charge status public IEnumerable GetPips() @@ -78,7 +77,7 @@ namespace OpenRa.Game.Traits const int numPips = 5; for (int i = 0; i < numPips; i++) { - if ((1 - remainingChargeTime * 1.0f / chargeTime) * numPips < i + 1) + if ((1 - chargeTick * 1.0f / chargeLength) * numPips < i + 1) { yield return PipType.Transparent; continue; @@ -146,5 +145,5 @@ namespace OpenRa.Game.Traits bmp.SetPixel(i, j, Color.FromArgb(alpha, (int)(rgb[0] * 255), (int)(rgb[1] * 255), (int)(rgb[2] * 255))); } } - } + } } diff --git a/OpenRa.Game/Traits/Cloak.cs b/OpenRa.Game/Traits/Cloak.cs index 3818f7bff1..491962f89d 100644 --- a/OpenRa.Game/Traits/Cloak.cs +++ b/OpenRa.Game/Traits/Cloak.cs @@ -12,16 +12,16 @@ namespace OpenRa.Game.Traits public void Attacking(Actor self) { - if (remainingUncloakTime <= 0) + if (remainingUncloakTime <= 0) OnCloak(); - remainingUncloakTime = (int)(Rules.General.SubmergeDelay * 60 * 25); + remainingUncloakTime = (int)(Rules.General.SubmergeDelay * 60 * 25); } public IEnumerable ModifyRender(Actor self, IEnumerable rs) { - if (remainingUncloakTime > 0) + if (remainingUncloakTime > 0) return rs; if (self.Owner == Game.LocalPlayer) @@ -32,8 +32,8 @@ namespace OpenRa.Game.Traits public void Tick(Actor self) { - if (remainingUncloakTime > 0) - if (--remainingUncloakTime <= 0) + if (remainingUncloakTime > 0) + if (--remainingUncloakTime <= 0) OnUncloak(); } diff --git a/OpenRa.Game/Traits/Submarine.cs b/OpenRa.Game/Traits/Submarine.cs index 40d943d483..46da5d9a93 100644 --- a/OpenRa.Game/Traits/Submarine.cs +++ b/OpenRa.Game/Traits/Submarine.cs @@ -4,11 +4,11 @@ using OpenRa.Game.Graphics; namespace OpenRa.Game.Traits { - class Submarine : IRenderModifier, INotifyAttack, ITick, INotifyDamage - { - int remainingSurfaceTime = 2; /* setup for initial dive */ + class Submarine : IRenderModifier, INotifyAttack, ITick, INotifyDamage + { + int remainingSurfaceTime = 2; /* setup for initial dive */ - public Submarine(Actor self) { } + public Submarine(Actor self) { } void DoSurface() { @@ -18,36 +18,36 @@ namespace OpenRa.Game.Traits remainingSurfaceTime = (int)(Rules.General.SubmergeDelay * 60 * 25); } - public void Attacking(Actor self) { DoSurface(); } + public void Attacking(Actor self) { DoSurface(); } public void Damaged(Actor self, AttackInfo e) { DoSurface(); } - public IEnumerable - ModifyRender(Actor self, IEnumerable rs) - { - if (remainingSurfaceTime > 0) - return rs; + public IEnumerable + ModifyRender(Actor self, IEnumerable rs) + { + if (remainingSurfaceTime > 0) + return rs; if (self.Owner == Game.LocalPlayer) return rs.Select(a => a.WithPalette(PaletteType.Shadow)); else return new Renderable[] { }; - } + } - public void Tick(Actor self) - { - if (remainingSurfaceTime > 0) - if (--remainingSurfaceTime <= 0) - OnDive(); - } + public void Tick(Actor self) + { + if (remainingSurfaceTime > 0) + if (--remainingSurfaceTime <= 0) + OnDive(); + } - void OnSurface() - { - Sound.Play("subshow1.aud"); - } + void OnSurface() + { + Sound.Play("subshow1.aud"); + } - void OnDive() - { - Sound.Play("subshow1.aud"); /* is this the right sound?? */ - } + void OnDive() + { + Sound.Play("subshow1.aud"); /* is this the right sound?? */ + } } }