diff --git a/OpenRa.Game/Effects/PowerDownIndicator.cs b/OpenRa.Game/Effects/PowerDownIndicator.cs index 185366a078..55858a6f54 100644 --- a/OpenRa.Game/Effects/PowerDownIndicator.cs +++ b/OpenRa.Game/Effects/PowerDownIndicator.cs @@ -9,7 +9,10 @@ namespace OpenRa.Game.Effects Actor a; Building b; Animation anim = new Animation("powerdown"); - + bool removeNextFrame = false; + bool indicatorState = true; + int stateTicks = 0; + public PowerDownIndicator(Actor a) { this.a = a; @@ -19,8 +22,19 @@ namespace OpenRa.Game.Effects public void Tick() { - if (!b.Disabled || a.IsDead) + if (removeNextFrame == true) Game.world.AddFrameEndTask(w => w.Remove(this)); + + // Fix off-by one frame bug with undisabling causing low-power + if (!b.Disabled || a.IsDead) + removeNextFrame = true; + + // Flash power icon + if (++stateTicks == 15) + { + stateTicks = 0; + indicatorState = !indicatorState; + } } public IEnumerable Render() @@ -28,7 +42,7 @@ namespace OpenRa.Game.Effects foreach (var r in a.Render()) yield return r.WithPalette(PaletteType.Disabled); - if (b.ManuallyDisabled) + if (b.ManuallyDisabled && indicatorState) yield return new Renderable(anim.Image, a.CenterLocation - .5f * anim.Image.size, PaletteType.Chrome); } diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj index b714392a7e..881e1f1d31 100644 --- a/OpenRa.Game/OpenRa.Game.csproj +++ b/OpenRa.Game/OpenRa.Game.csproj @@ -168,7 +168,7 @@ - + @@ -263,7 +263,7 @@ - + diff --git a/OpenRa.Game/Traits/Activities/StealOre.cs b/OpenRa.Game/Traits/Activities/Steal.cs similarity index 55% rename from OpenRa.Game/Traits/Activities/StealOre.cs rename to OpenRa.Game/Traits/Activities/Steal.cs index 9b343e1e30..b0605691c0 100644 --- a/OpenRa.Game/Traits/Activities/StealOre.cs +++ b/OpenRa.Game/Traits/Activities/Steal.cs @@ -5,27 +5,21 @@ using System.Text; namespace OpenRa.Game.Traits.Activities { - class StealOre : IActivity + class Steal : IActivity { Actor target; - public const int CashStolen = 100; //todo: push this out to Rules - - public StealOre(Actor target) { this.target = target; } + + public Steal(Actor target) { this.target = target; } public IActivity NextActivity { get; set; } public IActivity Tick(Actor self) { if (target == null || target.IsDead) return NextActivity; - if (target.Owner == self.Owner) return NextActivity; - - target.Owner.TakeCash(CashStolen); - self.Owner.GiveCash(CashStolen); - - // the thief is sacrificed. - self.Health = 0; - Game.world.AddFrameEndTask(w => w.Remove(self)); + + foreach (var t in target.traits.WithInterface()) + t.OnSteal(target, self); return NextActivity; } diff --git a/OpenRa.Game/Traits/StoresOre.cs b/OpenRa.Game/Traits/StoresOre.cs index 25d16af2d0..bdabfca5d2 100644 --- a/OpenRa.Game/Traits/StoresOre.cs +++ b/OpenRa.Game/Traits/StoresOre.cs @@ -1,9 +1,12 @@ using System.Collections.Generic; - +using System; +using OpenRa.Game.GameRules; namespace OpenRa.Game.Traits { - class StoresOre : IPips + class StoresOre : IPips, IAcceptThief { + public const int MaxStealAmount = 100; //todo: How is cash stolen determined? + readonly Actor self; public StoresOre(Actor self) @@ -11,6 +14,21 @@ namespace OpenRa.Game.Traits this.self = self; } + public void OnSteal(Actor self, Actor thief) + { + // Steal half the ore the building holds + var toSteal = (self.Info as BuildingInfo).Storage/2; + self.Owner.TakeCash(toSteal); + thief.Owner.GiveCash(toSteal); + + if (Game.LocalPlayer == thief.Owner) + Sound.Play("credit1.aud"); + + // the thief is sacrificed. + thief.Health = 0; + Game.world.AddFrameEndTask(w => w.Remove(thief)); + } + public IEnumerable GetPips(Actor self) { for (int i = 0; i < self.Info.OrePips; i++) diff --git a/OpenRa.Game/Traits/ThiefSteal.cs b/OpenRa.Game/Traits/Thief.cs similarity index 65% rename from OpenRa.Game/Traits/ThiefSteal.cs rename to OpenRa.Game/Traits/Thief.cs index 4b3f016c26..362436fae0 100644 --- a/OpenRa.Game/Traits/ThiefSteal.cs +++ b/OpenRa.Game/Traits/Thief.cs @@ -1,19 +1,18 @@ using OpenRa.Game.Traits.Activities; - +using System.Collections.Generic; +using System.Linq; namespace OpenRa.Game.Traits { - class ThiefSteal : IOrder + class Thief : IOrder { - public ThiefSteal(Actor self) { } + public Thief(Actor self) { } public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor) { if (mi.Button != MouseButton.Right) return null; if (underCursor == null) return null; - if (!underCursor.traits.Contains()) return null; - - // todo: other bits - + if (!underCursor.traits.WithInterface().Any()) return null; + return new Order("Steal", self, underCursor, int2.Zero, null); } @@ -23,7 +22,7 @@ namespace OpenRa.Game.Traits { self.CancelActivity(); self.QueueActivity(new Move(order.TargetActor, 1)); - self.QueueActivity(new StealOre(order.TargetActor)); + self.QueueActivity(new Steal(order.TargetActor)); } } } diff --git a/OpenRa.Game/Traits/TraitsInterfaces.cs b/OpenRa.Game/Traits/TraitsInterfaces.cs index 5ee0a485ef..11dc8713ad 100644 --- a/OpenRa.Game/Traits/TraitsInterfaces.cs +++ b/OpenRa.Game/Traits/TraitsInterfaces.cs @@ -17,6 +17,7 @@ namespace OpenRa.Game.Traits interface INotifyDamage { void Damaged(Actor self, AttackInfo e); } interface INotifyBuildComplete { void BuildingComplete (Actor self); } interface INotifyProduction { void UnitProduced(Actor self, Actor other); } + interface IAcceptThief { void OnSteal(Actor self, Actor thief); } interface IOrder { Order IssueOrder( Actor self, int2 xy, MouseInput mi, Actor underCursor ); diff --git a/units.ini b/units.ini index 8d7d1ac456..800d0bcaa6 100644 --- a/units.ini +++ b/units.ini @@ -594,7 +594,7 @@ SelectionSize=12,17,0,-9 [THF] Description=Thief Voice=ThiefVoice -Traits=Unit, Mobile, RenderInfantry, TakeCover, SquishByTank, Passenger +Traits=Unit, Mobile, RenderInfantry, TakeCover, SquishByTank, Passenger, Thief LongDesc=Infiltrates enemy refineries & \nsilos, and steals money stored there.\n Unarmed SelectionSize=12,17,0,-9 [E7]