From f3fd108a23d590a949e36c32257a3b27fabd6c12 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Fri, 8 Jan 2010 01:26:30 +1300 Subject: [PATCH] Refactor building power-down and Invulnerable effect. Introduces render bugs on state change (effects appearing/dissapearing a frame too late) --- OpenRa.Game/Effects/InvulnEffect.cs | 30 ++++++++++++++++ OpenRa.Game/Effects/PowerDownIndicator.cs | 36 +++++++++++++++++++ OpenRa.Game/OpenRa.Game.csproj | 1 + OpenRa.Game/Traits/AttackTurreted.cs | 2 +- OpenRa.Game/Traits/Building.cs | 42 ++++++++--------------- OpenRa.Game/Traits/IronCurtainable.cs | 17 ++------- OpenRa.Game/Traits/ProductionQueue.cs | 2 +- OpenRa.Game/Traits/ProvidesRadar.cs | 2 +- 8 files changed, 87 insertions(+), 45 deletions(-) create mode 100644 OpenRa.Game/Effects/InvulnEffect.cs create mode 100644 OpenRa.Game/Effects/PowerDownIndicator.cs diff --git a/OpenRa.Game/Effects/InvulnEffect.cs b/OpenRa.Game/Effects/InvulnEffect.cs new file mode 100644 index 0000000000..b7f28a0a49 --- /dev/null +++ b/OpenRa.Game/Effects/InvulnEffect.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; +using OpenRa.Game.Graphics; +using OpenRa.Game.Traits; + +namespace OpenRa.Game.Effects +{ + class InvulnEffect : IEffect + { + Actor a; + IronCurtainable b; + + public InvulnEffect(Actor a) + { + this.a = a; + this.b = a.traits.Get(); + } + + public void Tick() + { + if (a.IsDead || b.GetDamageModifier() > 0) + Game.world.AddFrameEndTask(w => w.Remove(this)); + } + + public IEnumerable Render() + { + foreach (var r in a.Render()) + yield return r.WithPalette(PaletteType.Invuln); + } + } +} diff --git a/OpenRa.Game/Effects/PowerDownIndicator.cs b/OpenRa.Game/Effects/PowerDownIndicator.cs new file mode 100644 index 0000000000..185366a078 --- /dev/null +++ b/OpenRa.Game/Effects/PowerDownIndicator.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using OpenRa.Game.Graphics; +using OpenRa.Game.Traits; + +namespace OpenRa.Game.Effects +{ + class PowerDownIndicator : IEffect + { + Actor a; + Building b; + Animation anim = new Animation("powerdown"); + + public PowerDownIndicator(Actor a) + { + this.a = a; + this.b = a.traits.Get(); + anim.PlayRepeating("disabled"); + } + + public void Tick() + { + if (!b.Disabled || a.IsDead) + Game.world.AddFrameEndTask(w => w.Remove(this)); + } + + public IEnumerable Render() + { + foreach (var r in a.Render()) + yield return r.WithPalette(PaletteType.Disabled); + + if (b.ManuallyDisabled) + 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 edc3f28fc9..80e5bc199f 100644 --- a/OpenRa.Game/OpenRa.Game.csproj +++ b/OpenRa.Game/OpenRa.Game.csproj @@ -83,6 +83,7 @@ + diff --git a/OpenRa.Game/Traits/AttackTurreted.cs b/OpenRa.Game/Traits/AttackTurreted.cs index 20941b5886..9c0f513251 100755 --- a/OpenRa.Game/Traits/AttackTurreted.cs +++ b/OpenRa.Game/Traits/AttackTurreted.cs @@ -26,7 +26,7 @@ namespace OpenRa.Game.Traits protected override void QueueAttack( Actor self, Order order ) { - if (self.traits.Contains() && self.traits.Get().InsuffientPower()) + if (self.traits.Contains() && self.traits.Get().Disabled) return; const int RangeTolerance = 1; /* how far inside our maximum range we should try to sit */ diff --git a/OpenRa.Game/Traits/Building.cs b/OpenRa.Game/Traits/Building.cs index 22bf173a80..da1b4408a0 100644 --- a/OpenRa.Game/Traits/Building.cs +++ b/OpenRa.Game/Traits/Building.cs @@ -9,14 +9,16 @@ using OpenRa.Game.Graphics; namespace OpenRa.Game.Traits { - class Building : INotifyDamage, IOrder, ITick, IRenderModifier + class Building : INotifyDamage, IOrder, ITick { readonly Actor self; public readonly BuildingInfo unitInfo; bool isRepairing = false; - bool isPoweredDown = false; - public bool IsPoweredDown { get { return isPoweredDown; } } - + bool isManuallyDisabled = false; + bool wasManuallyDisabled = false; + public bool ManuallyDisabled { get { return isManuallyDisabled; } } + public bool Disabled { get { return (isManuallyDisabled || (unitInfo.Powered && self.Owner.GetPowerState() != PowerState.Normal)); } } + public Building(Actor self) { this.self = self; @@ -25,14 +27,9 @@ namespace OpenRa.Game.Traits * ((float2)self.Location + .5f * (float2)unitInfo.Dimensions); } - public bool InsuffientPower() - { - return (isPoweredDown || (unitInfo.Powered && self.Owner.GetPowerState() != PowerState.Normal)); - } - public int GetPowerUsage() { - if (isPoweredDown) + if (isManuallyDisabled) return 0; if (unitInfo.Power > 0) /* todo: is this how real-ra scales it? */ @@ -41,21 +38,6 @@ namespace OpenRa.Game.Traits return unitInfo.Power; } - public Animation iconAnim; - public IEnumerable - ModifyRender(Actor self, IEnumerable rs) - { - if (!InsuffientPower()) - return rs; - - List nrs = new List(rs); - foreach(var r in rs) - { - nrs.Add(r.WithPalette(PaletteType.Disabled)); - } - return nrs; - } - public void Damaged(Actor self, AttackInfo e) { if (e.DamageState == DamageState.Dead) @@ -82,9 +64,8 @@ namespace OpenRa.Game.Traits if (order.OrderString == "PowerDown") { - isPoweredDown = !isPoweredDown; - if (isPoweredDown) Game.world.AddFrameEndTask(w => w.Add(new PowerDownIndicator(self))); - Sound.Play((isPoweredDown) ? "bleep12.aud" : "bleep11.aud"); + isManuallyDisabled = !isManuallyDisabled; + Sound.Play((isManuallyDisabled) ? "bleep12.aud" : "bleep11.aud"); } } @@ -92,6 +73,11 @@ namespace OpenRa.Game.Traits public void Tick(Actor self) { + // If the disabled state has changed since the last frame + if (Disabled ^ wasManuallyDisabled + && (wasManuallyDisabled = Disabled)) // Yes, I mean assignment + Game.world.AddFrameEndTask(w => w.Add(new PowerDownIndicator(self))); + if (!isRepairing) return; if (remainingTicks == 0) diff --git a/OpenRa.Game/Traits/IronCurtainable.cs b/OpenRa.Game/Traits/IronCurtainable.cs index 0b01d5fbf7..685075273f 100644 --- a/OpenRa.Game/Traits/IronCurtainable.cs +++ b/OpenRa.Game/Traits/IronCurtainable.cs @@ -8,7 +8,7 @@ using OpenRa.Game.Graphics; namespace OpenRa.Game.Traits { - class IronCurtainable: IOrder, IDamageModifier, ITick, IRenderModifier + class IronCurtainable: IOrder, IDamageModifier, ITick { int RemainingTicks = 0; @@ -23,6 +23,7 @@ namespace OpenRa.Game.Traits { return (RemainingTicks > 0) ? 0.0f : 1.0f; } + public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor) { return null; // Chronoshift order is issued through Chrome. @@ -33,6 +34,7 @@ namespace OpenRa.Game.Traits if (order.OrderString == "IronCurtain") { Game.controller.CancelInputMode(); + Game.world.AddFrameEndTask(w => w.Add(new InvulnEffect(self))); RemainingTicks = (int)(Rules.General.IronCurtain * 60 * 25); Sound.Play("ironcur9.aud"); // Play active anim @@ -41,18 +43,5 @@ namespace OpenRa.Game.Traits ironCurtain.traits.Get().PlayCustomAnim(ironCurtain, "active"); } } - - public IEnumerable ModifyRender(Actor self, IEnumerable rs) - { - if (RemainingTicks <= 0) - return rs; - - List nrs = new List(rs); - foreach(var r in rs) - { - nrs.Add(r.WithPalette(PaletteType.Invuln)); - } - return nrs; - } } } diff --git a/OpenRa.Game/Traits/ProductionQueue.cs b/OpenRa.Game/Traits/ProductionQueue.cs index 0e58800572..824229b64d 100755 --- a/OpenRa.Game/Traits/ProductionQueue.cs +++ b/OpenRa.Game/Traits/ProductionQueue.cs @@ -140,7 +140,7 @@ namespace OpenRa.Game.Traits foreach (var p in primaryProducers) { // Ignore buildings that are disabled - if (p.traits.Contains() && p.traits.Get().InsuffientPower()) + if (p.traits.Contains() && p.traits.Get().Disabled) continue; producer = p; break; diff --git a/OpenRa.Game/Traits/ProvidesRadar.cs b/OpenRa.Game/Traits/ProvidesRadar.cs index 41c3ced78c..7a4ba5e0c6 100644 --- a/OpenRa.Game/Traits/ProvidesRadar.cs +++ b/OpenRa.Game/Traits/ProvidesRadar.cs @@ -19,7 +19,7 @@ namespace OpenRa.Game.Traits // Check if powered var b = self.traits.Get(); - if (b != null && b.InsuffientPower()) + if (b != null && b.Disabled) return false; return true;