From 0e05f4db5cec3a05b61cee6c83cf1da6ffc34e68 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Fri, 8 Jan 2010 00:45:41 +1300 Subject: [PATCH 1/8] Iron Curtain and Powerdown palette effects --- OpenRa.Game/Graphics/HardwarePalette.cs | 15 ++++++++------- OpenRa.Game/OpenRa.Game.csproj | 1 + OpenRa.Game/Traits/Building.cs | 15 +++------------ OpenRa.Game/Traits/IronCurtainable.cs | 2 +- 4 files changed, 13 insertions(+), 20 deletions(-) diff --git a/OpenRa.Game/Graphics/HardwarePalette.cs b/OpenRa.Game/Graphics/HardwarePalette.cs index 09132cc5be..147a639a34 100644 --- a/OpenRa.Game/Graphics/HardwarePalette.cs +++ b/OpenRa.Game/Graphics/HardwarePalette.cs @@ -5,8 +5,8 @@ namespace OpenRa.Game.Graphics { public enum PaletteType { - Gold, Blue, Red, Orange, Teal, Salmon, Green, Gray, - Shadow, Invuln, Chrome, Shroud, Highlight, + Gold, Blue, Red, Orange, Teal, Salmon, Green, Gray, + Shadow, Invuln, Disabled, Highlight, Shroud, Chrome, }; class HardwarePalette : Sheet @@ -23,11 +23,12 @@ namespace OpenRa.Game.Graphics foreach (string remap in new string[] { "blue", "red", "orange", "teal", "salmon", "green", "gray" }) AddPalette(new Palette(pal, new PlayerColorRemap(FileSystem.Open(remap + ".rem")))); - AddPalette(new Palette(pal, new SingleColorRemap(Color.FromArgb(140, 0, 0, 0)))); - AddPalette(pal); // iron curtain. todo: remap! - AddPalette(pal); // chrome (it's like gold, but we're not going to hax it in palettemods) - AddPalette(new Palette(pal, new ShroudPaletteRemap())); - AddPalette(new Palette(pal, new SingleColorRemap(Color.FromArgb(128, 255, 255, 255)))); + AddPalette(new Palette(pal, new SingleColorRemap(Color.FromArgb(140, 0, 0, 0)))); // Shadow + AddPalette(new Palette(pal, new SingleColorRemap(Color.FromArgb(128, 128, 0, 0)))); // Invulnerable (Iron Curtain) + AddPalette(new Palette(pal, new SingleColorRemap(Color.FromArgb(180, 0, 0, 0)))); // Disabled / Low power + AddPalette(new Palette(pal, new SingleColorRemap(Color.FromArgb(128, 255, 255, 255)))); // Highlight + AddPalette(new Palette(pal, new ShroudPaletteRemap())); // Shroud + AddPalette(pal); // Chrome (it's like gold, but we're not going to hax it in palettemods) } int AddPalette(Palette p) diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj index df46a1172b..edc3f28fc9 100644 --- a/OpenRa.Game/OpenRa.Game.csproj +++ b/OpenRa.Game/OpenRa.Game.csproj @@ -84,6 +84,7 @@ + diff --git a/OpenRa.Game/Traits/Building.cs b/OpenRa.Game/Traits/Building.cs index dfb870285c..22bf173a80 100644 --- a/OpenRa.Game/Traits/Building.cs +++ b/OpenRa.Game/Traits/Building.cs @@ -15,6 +15,7 @@ namespace OpenRa.Game.Traits public readonly BuildingInfo unitInfo; bool isRepairing = false; bool isPoweredDown = false; + public bool IsPoweredDown { get { return isPoweredDown; } } public Building(Actor self) { @@ -50,19 +51,8 @@ namespace OpenRa.Game.Traits List nrs = new List(rs); foreach(var r in rs) { - // Need 2 shadows to make it dark enough - nrs.Add(r.WithPalette(PaletteType.Shadow)); - nrs.Add(r.WithPalette(PaletteType.Shadow)); + nrs.Add(r.WithPalette(PaletteType.Disabled)); } - - if (isPoweredDown) - { - iconAnim = new Animation("powerdown"); - iconAnim.PlayRepeating("disabled"); - nrs.Add(new Renderable(iconAnim.Image, self.CenterLocation - 0.5f*iconAnim.Image.size, PaletteType.Chrome)); - } - - return nrs; } @@ -93,6 +83,7 @@ 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"); } } diff --git a/OpenRa.Game/Traits/IronCurtainable.cs b/OpenRa.Game/Traits/IronCurtainable.cs index 91716f6bab..eb15272a02 100644 --- a/OpenRa.Game/Traits/IronCurtainable.cs +++ b/OpenRa.Game/Traits/IronCurtainable.cs @@ -49,7 +49,7 @@ namespace OpenRa.Game.Traits List nrs = new List(rs); foreach(var r in rs) { - nrs.Add(r.WithPalette(PaletteType.Shadow)); + nrs.Add(r.WithPalette(PaletteType.Invuln)); } return nrs; } From 42cfa7ec59af258917b955fabdeb22e03853c3c0 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Fri, 8 Jan 2010 00:52:00 +1300 Subject: [PATCH 2/8] Iron curtain targetting polish --- OpenRa.Game/Chrome.cs | 8 +++++++- OpenRa.Game/Traits/IronCurtainable.cs | 3 ++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/OpenRa.Game/Chrome.cs b/OpenRa.Game/Chrome.cs index 3e7b531932..ea84206eb9 100644 --- a/OpenRa.Game/Chrome.cs +++ b/OpenRa.Game/Chrome.cs @@ -317,7 +317,7 @@ namespace OpenRa.Game else { //repairButton.ReplaceAnim(Game.controller.orderGenerator is RepairOrderGenerator ? "pressed" : "normal"); - AddButton(curtainRect, isLmb => Game.controller.ToggleInputMode()); + AddButton(curtainRect, isLmb => HandleIronCurtainButton()); } buildPaletteRenderer.DrawSprite(repairButton.Image, curtainDrawPos, PaletteType.Chrome); @@ -391,6 +391,12 @@ namespace OpenRa.Game Sound.Play("slcttgt1.aud"); } + void HandleIronCurtainButton() + { + if (Game.controller.ToggleInputMode()) + Sound.Play("slcttgt1.aud"); + } + void DrawChat() { var chatpos = new int2(400, Game.viewport.Height - 20); diff --git a/OpenRa.Game/Traits/IronCurtainable.cs b/OpenRa.Game/Traits/IronCurtainable.cs index eb15272a02..0b01d5fbf7 100644 --- a/OpenRa.Game/Traits/IronCurtainable.cs +++ b/OpenRa.Game/Traits/IronCurtainable.cs @@ -32,10 +32,11 @@ namespace OpenRa.Game.Traits { if (order.OrderString == "IronCurtain") { + Game.controller.CancelInputMode(); RemainingTicks = (int)(Rules.General.IronCurtain * 60 * 25); + Sound.Play("ironcur9.aud"); // Play active anim var ironCurtain = Game.world.Actors.Where(a => a.Owner == order.Subject.Owner && a.traits.Contains()).FirstOrDefault(); - Sound.Play("ironcur9.aud"); if (ironCurtain != null) ironCurtain.traits.Get().PlayCustomAnim(ironCurtain, "active"); } From f3fd108a23d590a949e36c32257a3b27fabd6c12 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Fri, 8 Jan 2010 01:26:30 +1300 Subject: [PATCH 3/8] 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; From b570f3c9a716b352cbce0c6232870be356b53461 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Fri, 8 Jan 2010 01:32:50 +1300 Subject: [PATCH 4/8] Pedantic about wording --- OpenRa.Game/Traits/Building.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/OpenRa.Game/Traits/Building.cs b/OpenRa.Game/Traits/Building.cs index da1b4408a0..bd48fc1c0d 100644 --- a/OpenRa.Game/Traits/Building.cs +++ b/OpenRa.Game/Traits/Building.cs @@ -14,10 +14,10 @@ namespace OpenRa.Game.Traits readonly Actor self; public readonly BuildingInfo unitInfo; bool isRepairing = false; - 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)); } } + bool manuallyDisabled = false; + public bool ManuallyDisabled { get { return manuallyDisabled; } } + public bool Disabled { get { return (manuallyDisabled || (unitInfo.Powered && self.Owner.GetPowerState() != PowerState.Normal)); } } + bool wasDisabled = false; public Building(Actor self) { @@ -29,7 +29,7 @@ namespace OpenRa.Game.Traits public int GetPowerUsage() { - if (isManuallyDisabled) + if (manuallyDisabled) return 0; if (unitInfo.Power > 0) /* todo: is this how real-ra scales it? */ @@ -64,8 +64,8 @@ namespace OpenRa.Game.Traits if (order.OrderString == "PowerDown") { - isManuallyDisabled = !isManuallyDisabled; - Sound.Play((isManuallyDisabled) ? "bleep12.aud" : "bleep11.aud"); + manuallyDisabled = !manuallyDisabled; + Sound.Play((manuallyDisabled) ? "bleep12.aud" : "bleep11.aud"); } } @@ -74,8 +74,8 @@ 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 + if (Disabled ^ wasDisabled + && (wasDisabled = Disabled)) // Yes, I mean assignment Game.world.AddFrameEndTask(w => w.Add(new PowerDownIndicator(self))); if (!isRepairing) return; From 8ed8dad4a9e3287120f66f387e3a33d4744970bb Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Fri, 8 Jan 2010 10:25:37 +1300 Subject: [PATCH 5/8] move initial facing of missile onto AttackBase in prep for fixing 4tnk --- OpenRa.Game/Effects/Missile.cs | 6 ++---- OpenRa.Game/Traits/AttackBase.cs | 5 ++++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/OpenRa.Game/Effects/Missile.cs b/OpenRa.Game/Effects/Missile.cs index ee5d2ce88a..dcf32c7716 100644 --- a/OpenRa.Game/Effects/Missile.cs +++ b/OpenRa.Game/Effects/Missile.cs @@ -21,7 +21,7 @@ namespace OpenRa.Game.Effects int Altitude; public Missile(string weapon, Player owner, Actor firedBy, - int2 src, Actor target, int altitude) + int2 src, Actor target, int altitude, int facing) { Weapon = Rules.WeaponInfo[weapon]; Projectile = Rules.ProjectileInfo[Weapon.Projectile]; @@ -31,9 +31,7 @@ namespace OpenRa.Game.Effects Target = target; Pos = src.ToFloat2(); Altitude = altitude; - - /* todo: initial facing should be turret facing, or unit facing if we're not turreted */ - Facing = Traits.Util.GetFacing( Target.CenterLocation - src.ToFloat2(), 0 ); + Facing = facing; if (Projectile.Image != null && Projectile.Image != "none") { diff --git a/OpenRa.Game/Traits/AttackBase.cs b/OpenRa.Game/Traits/AttackBase.cs index d3b713aa66..d7b0328c58 100644 --- a/OpenRa.Game/Traits/AttackBase.cs +++ b/OpenRa.Game/Traits/AttackBase.cs @@ -118,12 +118,15 @@ namespace OpenRa.Game.Traits var srcAltitude = unit != null ? unit.Altitude : 0; var destAltitude = destUnit != null ? destUnit.Altitude : 0; + var fireFacing = self.traits.Contains() + ? self.traits.Get().turretFacing : unit.Facing; + if( weapon.RenderAsTesla ) Game.world.Add( new TeslaZap( firePos, thisTarget.CenterLocation.ToInt2() ) ); if( Rules.ProjectileInfo[ weapon.Projectile ].ROT != 0 ) Game.world.Add(new Missile(weaponName, self.Owner, self, - firePos, thisTarget, srcAltitude)); + firePos, thisTarget, srcAltitude, fireFacing)); else Game.world.Add(new Bullet(weaponName, self.Owner, self, firePos, thisTarget.CenterLocation.ToInt2(), srcAltitude, destAltitude)); From 39de75047e6452c4d085d1d78341b72da66d6805 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Fri, 8 Jan 2010 11:11:11 +1300 Subject: [PATCH 6/8] turbo boost on missiles --- OpenRa.Game/Effects/Missile.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenRa.Game/Effects/Missile.cs b/OpenRa.Game/Effects/Missile.cs index dcf32c7716..6ea478c153 100644 --- a/OpenRa.Game/Effects/Missile.cs +++ b/OpenRa.Game/Effects/Missile.cs @@ -71,14 +71,14 @@ namespace OpenRa.Game.Effects return; } - var move = (Scale * Weapon.Speed / dist.Length) * dist; + var speed = Weapon.Speed * ((targetAltitude > 0 && Weapon.TurboBoost) ? 1.5f : 1f); + var move = (Scale * speed / dist.Length) * dist; Pos += move; if (Projectile.Animates) Game.world.AddFrameEndTask(w => w.Add(new Smoke((Pos - 1.5f * move - new int2( 0, Altitude )).ToInt2()))); // todo: running out of fuel - // todo: turbo boost vs aircraft } public IEnumerable Render() From 69da6fdd2d2227f93475c490abdf7d48a6cc6d9b Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Fri, 8 Jan 2010 11:58:20 +1300 Subject: [PATCH 7/8] fixed 4tnk --- OpenRa.Game/Effects/Missile.cs | 8 ++++--- OpenRa.Game/GameRules/UnitInfo.cs | 4 ++++ OpenRa.Game/Traits/AttackBase.cs | 30 +++++++++++++++++------- OpenRa.Game/Traits/RenderSimple.cs | 8 +++---- OpenRa.Game/Traits/RenderUnitTurreted.cs | 12 +++++----- units.ini | 3 +++ 6 files changed, 44 insertions(+), 21 deletions(-) diff --git a/OpenRa.Game/Effects/Missile.cs b/OpenRa.Game/Effects/Missile.cs index 6ea478c153..c0247567d1 100644 --- a/OpenRa.Game/Effects/Missile.cs +++ b/OpenRa.Game/Effects/Missile.cs @@ -45,7 +45,7 @@ namespace OpenRa.Game.Effects } const int MissileCloseEnough = 7; - const float Scale = .3f; + const float Scale = .2f; public void Tick() { @@ -71,8 +71,10 @@ namespace OpenRa.Game.Effects return; } - var speed = Weapon.Speed * ((targetAltitude > 0 && Weapon.TurboBoost) ? 1.5f : 1f); - var move = (Scale * speed / dist.Length) * dist; + var speed = Scale * Weapon.Speed * ((targetAltitude > 0 && Weapon.TurboBoost) ? 1.5f : 1f); + + var angle = Facing / 128f * Math.PI; + var move = speed * -float2.FromAngle((float)angle); Pos += move; if (Projectile.Animates) diff --git a/OpenRa.Game/GameRules/UnitInfo.cs b/OpenRa.Game/GameRules/UnitInfo.cs index 63acbe1870..7a29b23bb2 100755 --- a/OpenRa.Game/GameRules/UnitInfo.cs +++ b/OpenRa.Game/GameRules/UnitInfo.cs @@ -59,6 +59,10 @@ namespace OpenRa.Game.GameRules public readonly int UnloadFacing = 0; public readonly UnitMovementType[] PassengerTypes = null; + // weapon origins and firing angles within the turrets. 3 values per position. + public readonly int[] PrimaryLocalOffset = { }; + public readonly int[] SecondaryLocalOffset = { }; + public UnitInfo(string name) { Name = name; } } diff --git a/OpenRa.Game/Traits/AttackBase.cs b/OpenRa.Game/Traits/AttackBase.cs index d7b0328c58..411770437b 100644 --- a/OpenRa.Game/Traits/AttackBase.cs +++ b/OpenRa.Game/Traits/AttackBase.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using IjwFramework.Types; using OpenRa.Game.Effects; @@ -72,7 +73,7 @@ namespace OpenRa.Game.Traits var unit = self.traits.GetOrDefault(); if (self.Info.Primary != null && CheckFire(self, unit, self.Info.Primary, ref primaryFireDelay, - self.Info.PrimaryOffset, ref primaryBurst)) + self.Info.PrimaryOffset, ref primaryBurst, self.Info.PrimaryLocalOffset)) { secondaryFireDelay = Math.Max(4, secondaryFireDelay); primaryRecoil = 1; @@ -80,7 +81,7 @@ namespace OpenRa.Game.Traits } if (self.Info.Secondary != null && CheckFire(self, unit, self.Info.Secondary, ref secondaryFireDelay, - self.Info.SecondaryOffset ?? self.Info.PrimaryOffset, ref secondaryBurst)) + self.Info.SecondaryOffset ?? self.Info.PrimaryOffset, ref secondaryBurst, self.Info.SecondaryLocalOffset)) { if (self.Info.SecondaryOffset != null) secondaryRecoil = 1; else primaryRecoil = 1; @@ -88,7 +89,7 @@ namespace OpenRa.Game.Traits } } - bool CheckFire(Actor self, Unit unit, string weaponName, ref int fireDelay, int[] offset, ref int burst) + bool CheckFire(Actor self, Unit unit, string weaponName, ref int fireDelay, int[] offset, ref int burst, int[] localOffset) { if (fireDelay > 0) return false; @@ -101,6 +102,17 @@ namespace OpenRa.Game.Traits if (!Combat.WeaponValidForTarget(weapon, target)) return false; + var numOffsets = (localOffset.Length + 2) / 3; + if (numOffsets == 0) numOffsets = 1; + var localOffsetForShot = burst % numOffsets; + var thisLocalOffset = localOffset.Skip(3 * localOffsetForShot).Take(3).ToArray(); + + var fireOffset = new[] { + offset.ElementAtOrDefault(0) + thisLocalOffset.ElementAtOrDefault(0), + offset.ElementAtOrDefault(1) + thisLocalOffset.ElementAtOrDefault(1), + offset.ElementAtOrDefault(2), + offset.ElementAtOrDefault(3) }; + if (--burst > 0) fireDelay = 5; else @@ -109,7 +121,7 @@ namespace OpenRa.Game.Traits burst = weapon.Burst; } - var firePos = self.CenterLocation.ToInt2() + Util.GetTurretPosition(self, unit, offset, 0f).ToInt2(); + var firePos = self.CenterLocation.ToInt2() + Util.GetTurretPosition(self, unit, fireOffset, 0f).ToInt2(); var thisTarget = target; // closure. var destUnit = thisTarget.traits.GetOrDefault(); @@ -118,15 +130,17 @@ namespace OpenRa.Game.Traits var srcAltitude = unit != null ? unit.Altitude : 0; var destAltitude = destUnit != null ? destUnit.Altitude : 0; - var fireFacing = self.traits.Contains() - ? self.traits.Get().turretFacing : unit.Facing; - if( weapon.RenderAsTesla ) Game.world.Add( new TeslaZap( firePos, thisTarget.CenterLocation.ToInt2() ) ); - if( Rules.ProjectileInfo[ weapon.Projectile ].ROT != 0 ) + if (Rules.ProjectileInfo[weapon.Projectile].ROT != 0) + { + var fireFacing = thisLocalOffset.ElementAtOrDefault(2) + + (self.traits.Contains() ? self.traits.Get().turretFacing : unit.Facing); + Game.world.Add(new Missile(weaponName, self.Owner, self, firePos, thisTarget, srcAltitude, fireFacing)); + } else Game.world.Add(new Bullet(weaponName, self.Owner, self, firePos, thisTarget.CenterLocation.ToInt2(), srcAltitude, destAltitude)); diff --git a/OpenRa.Game/Traits/RenderSimple.cs b/OpenRa.Game/Traits/RenderSimple.cs index 48f9ec7837..d5db307c09 100644 --- a/OpenRa.Game/Traits/RenderSimple.cs +++ b/OpenRa.Game/Traits/RenderSimple.cs @@ -33,6 +33,7 @@ namespace OpenRa.Game.Traits public Animation Animation; public Func OffsetFunc; public Func DisableFunc; + public int ZOffset; public AnimationWithOffset( Animation a ) : this( a, null, null ) @@ -48,10 +49,9 @@ namespace OpenRa.Game.Traits public Renderable Image( Actor self ) { - if( OffsetFunc != null ) - return Util.Centered( self, Animation.Image, self.CenterLocation + OffsetFunc() ); - else - return Util.Centered( self, Animation.Image, self.CenterLocation ); + var r = Util.Centered( self, Animation.Image, self.CenterLocation + + (OffsetFunc != null ? OffsetFunc() : float2.Zero) ); + return ZOffset != 0 ? r.WithZOffset(ZOffset) : r; } public static implicit operator AnimationWithOffset( Animation a ) diff --git a/OpenRa.Game/Traits/RenderUnitTurreted.cs b/OpenRa.Game/Traits/RenderUnitTurreted.cs index c06614f4bd..f05caa57f4 100644 --- a/OpenRa.Game/Traits/RenderUnitTurreted.cs +++ b/OpenRa.Game/Traits/RenderUnitTurreted.cs @@ -19,16 +19,16 @@ namespace OpenRa.Game.Traits turretAnim.PlayFacing( "turret", () => turreted.turretFacing ); if( self.Info.PrimaryOffset != null ) - anims.Add( "turret_1", new AnimationWithOffset( + anims.Add("turret_1", new AnimationWithOffset( turretAnim, - () => Util.GetTurretPosition( self, unit, self.Info.PrimaryOffset, attack.primaryRecoil ), - null ) ); + () => Util.GetTurretPosition(self, unit, self.Info.PrimaryOffset, attack.primaryRecoil), + null) { ZOffset = 1 }); if( self.Info.SecondaryOffset != null ) - anims.Add( "turret_2", new AnimationWithOffset( + anims.Add("turret_2", new AnimationWithOffset( turretAnim, - () => Util.GetTurretPosition( self, unit, self.Info.SecondaryOffset, attack.secondaryRecoil ), - null ) ); + () => Util.GetTurretPosition(self, unit, self.Info.SecondaryOffset, attack.secondaryRecoil), + null) { ZOffset = 1 }); if( self.Info.MuzzleFlash ) { diff --git a/units.ini b/units.ini index 6ed539a5f0..5c39efaabf 100644 --- a/units.ini +++ b/units.ini @@ -42,6 +42,9 @@ Description=Mammoth Tank Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Repairable, Chronoshiftable, Passenger, IronCurtainable Voice=VehicleVoice LongDesc=Big and slow tank, with anti-air capability.\n Strong vs Tanks, Aircraft\n Weak vs Infantry +PrimaryLocalOffset=-4,-5,0,4,-5,0 +SecondaryLocalOffset=-7,2,25,7,2,-25 +Recoil=4 [ARTY] Description=Artillery Traits=Unit, Mobile, AttackBase, RenderUnit, Explodes, AutoTarget, Repairable, Chronoshiftable, Passenger, IronCurtainable From 49774e022dbdd40d23444e59e19b1c14596ce850 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Fri, 8 Jan 2010 12:18:31 +1300 Subject: [PATCH 8/8] fix warnings; fix small bug in Bullet; fix impossible prereqs --- OpenRa.Game/Chrome.cs | 5 +- OpenRa.Game/Effects/Bullet.cs | 2 + OpenRa.Game/GameRules/AftermathInfo.cs | 14 +- OpenRa.Game/GameRules/GeneralInfo.cs | 199 +++++++++++++------------ OpenRa.Game/GameRules/TechTree.cs | 5 +- OpenRa.Game/GameRules/UnitInfo.cs | 7 +- doc/progress.txt | 2 +- rules.ini | 6 +- 8 files changed, 123 insertions(+), 117 deletions(-) diff --git a/OpenRa.Game/Chrome.cs b/OpenRa.Game/Chrome.cs index 2c5ebb62f9..6e69caf944 100644 --- a/OpenRa.Game/Chrome.cs +++ b/OpenRa.Game/Chrome.cs @@ -703,7 +703,10 @@ namespace OpenRa.Game p += new int2(0, 15); if (!Rules.TechTree.CanBuild(info, Game.LocalPlayer, buildings)) { - var prereqs = info.Prerequisite.Select(a => Rules.UnitInfo[a.ToLowerInvariant()].Description); + var prereqs = info.Prerequisite + .Select(a => Rules.UnitInfo[a.ToLowerInvariant()]) + .Where( u => u.Owner.Any( o => o == Game.LocalPlayer.Race ) ) + .Select( a => a.Description ); renderer.DrawText("Requires {0}".F( string.Join( ", ", prereqs.ToArray() ) ), p.ToInt2(), Color.White); } diff --git a/OpenRa.Game/Effects/Bullet.cs b/OpenRa.Game/Effects/Bullet.cs index f342a2d76d..5104585dd3 100644 --- a/OpenRa.Game/Effects/Bullet.cs +++ b/OpenRa.Game/Effects/Bullet.cs @@ -31,6 +31,8 @@ namespace OpenRa.Game.Effects FiredBy = firedBy; Src = src; Dest = dest; + SrcAltitude = srcAltitude; + DestAltitude = destAltitude; VisualDest = Dest + new int2( Game.CosmeticRandom.Next(-10, 10), Game.CosmeticRandom.Next(-10, 10)); diff --git a/OpenRa.Game/GameRules/AftermathInfo.cs b/OpenRa.Game/GameRules/AftermathInfo.cs index 96c403d00c..60511c4d5c 100644 --- a/OpenRa.Game/GameRules/AftermathInfo.cs +++ b/OpenRa.Game/GameRules/AftermathInfo.cs @@ -3,12 +3,12 @@ namespace OpenRa.Game.GameRules { class AftermathInfo { - public readonly int MTankDistance; - public readonly float QuakeUnitDamage; - public readonly float QuakeBuildingDamage; - public readonly float QuakeInfantryDamage; - public readonly int QuakeDelay; - public readonly int CarrierLaunchDelay; - public readonly int ChronoTankDuration; + public readonly int MTankDistance = 0; + public readonly float QuakeUnitDamage = 0f; + public readonly float QuakeBuildingDamage = 0f; + public readonly float QuakeInfantryDamage = 0f; + public readonly int QuakeDelay = 0; + public readonly int CarrierLaunchDelay = 0; + public readonly int ChronoTankDuration = 0; } } diff --git a/OpenRa.Game/GameRules/GeneralInfo.cs b/OpenRa.Game/GameRules/GeneralInfo.cs index e351a7be66..cbd26f3d6b 100644 --- a/OpenRa.Game/GameRules/GeneralInfo.cs +++ b/OpenRa.Game/GameRules/GeneralInfo.cs @@ -1,126 +1,127 @@  +using System; namespace OpenRa.Game.GameRules { class GeneralInfo { /* Crates */ - public readonly int CrateMinimum; - public readonly int CrateMaximum; - public readonly float CrateRadius; - public readonly float CrateRegen; - public readonly string UnitCrateType; /* =none, if any */ - public readonly float WaterCrateChance; + public readonly int CrateMinimum = 0; + public readonly int CrateMaximum = 0; + public readonly float CrateRadius = 0; + public readonly float CrateRegen = 0; + public readonly string UnitCrateType = null; /* =none, if any */ + public readonly float WaterCrateChance = 0; - public readonly int SoloCrateMoney; - public readonly string SilverCrate; /* solo play crate contents */ - public readonly string WaterCrate; - public readonly string WoodCrate; + public readonly int SoloCrateMoney = 2000; + public readonly string SilverCrate = null; /* solo play crate contents */ + public readonly string WaterCrate = null; + public readonly string WoodCrate = null; /* Special Weapons */ - public readonly int ChronoDuration; - public readonly bool ChronoKillCargo; - public readonly int ChronoTechLevel; - public readonly int GPSTechLevel; - public readonly int GapRadius; - public readonly float GapRegenInterval; - public readonly float IronCurtain; /* minutes */ - public readonly int ParaTech; - public readonly int ParabombTech; - public readonly int RadarJamRadius; - public readonly int SpyPlaneTech; - public readonly int BadgerBombCount; + public readonly int ChronoDuration = 0; + public readonly bool ChronoKillCargo = true; + [Obsolete] public readonly int ChronoTechLevel = -1; + [Obsolete] public readonly int GPSTechLevel = -1; + public readonly int GapRadius = 0; + public readonly float GapRegenInterval =0; + public readonly float IronCurtain = 0; /* minutes */ + [Obsolete] public readonly int ParaTech = -1; + [Obsolete] public readonly int ParabombTech = -1; + public readonly int RadarJamRadius = 1; + [Obsolete] public readonly int SpyPlaneTech = -1; + public readonly int BadgerBombCount = 1; /* Chrono Side Effects */ - public readonly float QuakeChance; - public readonly float QuakeDamage; /* percent */ - public readonly float VortexChance; - public readonly int VortexDamage; - public readonly int VortexRange; - public readonly int VortexSpeed; + public readonly float QuakeChance = 0; + public readonly float QuakeDamage = 0; /* percent */ + public readonly float VortexChance = 0; + public readonly int VortexDamage = 0; + public readonly int VortexRange = 0; + public readonly int VortexSpeed = 0; /* Repair & Refit */ - public readonly float RefundPercent; - public readonly float ReloadRate; - public readonly float RepairPercent; - public readonly float RepairRate; - public readonly int RepairStep; - public readonly float URepairPercent; - public readonly int URepairStep; + public readonly float RefundPercent = 0; + public readonly float ReloadRate = 0; + public readonly float RepairPercent = 0; + public readonly float RepairRate = 0; + public readonly int RepairStep = 0; + public readonly float URepairPercent = 0; + public readonly int URepairStep = 0; /* Combat & Damage */ - public readonly float TurboBoost; - public readonly int APMineDamage; - public readonly int AVMineDamage; - public readonly int AtomDamage; - public readonly float BallisticScatter; - public readonly int BridgeStrength; - public readonly float C4Delay; - public readonly float Crush; - public readonly float ExpSpread; - public readonly int FireSupress; - public readonly float HomingScatter; - public readonly int MaxDamage; - public readonly int MinDamage; - public readonly bool OreExplosive; - public readonly bool PlayerAutoCrush; - public readonly bool PlayerReturnFire; - public readonly bool PlayerScatter; - public readonly float ProneDamage; - public readonly bool TreeTargeting; - public readonly int Incoming; + public readonly float TurboBoost = 1.5f; + public readonly int APMineDamage = 0; + public readonly int AVMineDamage = 0; + public readonly int AtomDamage = 0; + public readonly float BallisticScatter = 0; + public readonly int BridgeStrength = 0; + public readonly float C4Delay = 0; + public readonly float Crush = 0; + public readonly float ExpSpread = 0; + public readonly int FireSupress = 0; + public readonly float HomingScatter = 0; + public readonly int MaxDamage = 0; + public readonly int MinDamage = 0; + public readonly bool OreExplosive = false; + public readonly bool PlayerAutoCrush = false; + public readonly bool PlayerReturnFire = false; + public readonly bool PlayerScatter = false; + public readonly float ProneDamage = 0; + public readonly bool TreeTargeting = false; + public readonly int Incoming = 0; /* Income & Production */ - public readonly int BailCount; - public readonly float BuildSpeed; - public readonly float BuildupTime; - public readonly int GemValue; - public readonly int GoldValue; - public readonly float GrowthRate; - public readonly bool OreGrows; - public readonly bool OreSpreads; - public readonly float OreTruckRate; - public readonly bool SeparateAircraft; - public readonly float SurvivorRate; + public readonly int BailCount = 0; + public readonly float BuildSpeed = 0; + public readonly float BuildupTime = 0; + public readonly int GemValue = 0; + public readonly int GoldValue = 0; + public readonly float GrowthRate = 0; + public readonly bool OreGrows = true; + public readonly bool OreSpreads = true; + public readonly float OreTruckRate = 0; + public readonly bool SeparateAircraft = true; + public readonly float SurvivorRate = 0; /* Audo/Visual Map Controls */ - public readonly bool AllyReveal; - public readonly float ConditionRed; - public readonly float ConditionYellow; - public readonly int DropZoneRadius; - public readonly bool EnemyHealth; - public readonly int Gravity; - public readonly float IdleActionFrequency; - public readonly float MessageDelay; - public readonly float MovieTime; - public readonly bool NamedCivilians; - public readonly float SavourDelay; - public readonly int ShroudRate; - public readonly int SpeakDelay; - public readonly int TimerWarning; - public readonly bool FlashLowPower; + public readonly bool AllyReveal = true; + public readonly float ConditionRed = 0; + public readonly float ConditionYellow = 0; + public readonly int DropZoneRadius = 0; + public readonly bool EnemyHealth = true; + public readonly int Gravity = 0; + public readonly float IdleActionFrequency = 0; + public readonly float MessageDelay = 0; + public readonly float MovieTime = 0; + public readonly bool NamedCivilians = false; + public readonly float SavourDelay = 0; + public readonly int ShroudRate = 0; + public readonly int SpeakDelay = 0; + public readonly int TimerWarning = 0; + public readonly bool FlashLowPower = false; /* Computer & Movement Controls */ - public readonly bool CurleyShuffle; - public readonly float BaseBias; - public readonly float BaseDefenseDelay; - public readonly float CloseEnough; - public readonly int DamageDelay; - public readonly int GameSpeeBias; - public readonly int LZScanRadius; - public readonly bool MineAware; - public readonly float Stray; - public readonly float SubmergeDelay; - public readonly float SuspendDelay; - public readonly int SuspendPriority; - public readonly float TeamDelay; + public readonly bool CurleyShuffle = false; + public readonly float BaseBias = 0; + public readonly float BaseDefenseDelay = 0; + public readonly float CloseEnough = 0; + public readonly int DamageDelay = 0; + public readonly int GameSpeeBias = 0; + public readonly int LZScanRadius = 0; + public readonly bool MineAware = false; + public readonly float Stray = 0; + public readonly float SubmergeDelay = 0; + public readonly float SuspendDelay = 0; + public readonly int SuspendPriority = 0; + public readonly float TeamDelay = 0; /* Misc */ - public readonly bool FineDiffControl; - public readonly bool MCVUndeploy; + [Obsolete] + public readonly bool FineDiffControl = false; + public readonly bool MCVUndeploy = false; /* OpenRA-specific */ - public readonly float OreChance; /* chance of spreading to a - * particular eligible cell */ - public readonly int LowPowerSlowdown; /* build time multiplier */ + public readonly float OreChance = 0; /* chance of spreading to a particular eligible cell */ + public readonly int LowPowerSlowdown = 3; /* build time multiplier */ } } diff --git a/OpenRa.Game/GameRules/TechTree.cs b/OpenRa.Game/GameRules/TechTree.cs index 463934796e..af0fd79ce4 100755 --- a/OpenRa.Game/GameRules/TechTree.cs +++ b/OpenRa.Game/GameRules/TechTree.cs @@ -35,8 +35,9 @@ namespace OpenRa.Game.GameRules return false; foreach( var p in unit.Prerequisite ) - if( playerBuildings[ p ].Count == 0 ) - return false; + if (Rules.UnitInfo[p.ToLowerInvariant()].Owner.Any(x => x == player.Race)) + if( playerBuildings[ p ].Count == 0 ) + return false; if( producesIndex[ Rules.UnitCategory[ unit.Name ] ].All( x => playerBuildings[ x.Name ].Count == 0 ) ) return false; diff --git a/OpenRa.Game/GameRules/UnitInfo.cs b/OpenRa.Game/GameRules/UnitInfo.cs index 7a29b23bb2..6054874fe0 100755 --- a/OpenRa.Game/GameRules/UnitInfo.cs +++ b/OpenRa.Game/GameRules/UnitInfo.cs @@ -1,4 +1,5 @@  +using System; namespace OpenRa.Game.GameRules { public enum ArmorType @@ -19,8 +20,8 @@ namespace OpenRa.Game.GameRules public readonly int Ammo = -1; public readonly ArmorType Armor = ArmorType.none; - public readonly bool DoubleOwned = false; - public readonly bool Cloakable = false; + [Obsolete] public readonly bool DoubleOwned = false; + [Obsolete] public readonly bool Cloakable = false; public readonly int Cost = 0; public readonly bool Crewed = false; public readonly bool Explodes = false; @@ -35,7 +36,7 @@ namespace OpenRa.Game.GameRules public readonly int ROT = 255; public readonly int Reload = 0; public readonly bool SelfHealing = false; - public readonly bool Sensors = false; // no idea what this does + [Obsolete] public readonly bool Sensors = false; // no idea what this does public readonly int Sight = 1; public readonly int Strength = 1; public readonly int TechLevel = -1; diff --git a/doc/progress.txt b/doc/progress.txt index ab2024c607..1d3b8f14f0 100644 --- a/doc/progress.txt +++ b/doc/progress.txt @@ -17,7 +17,7 @@ All tracked vehicles 1TNK Works 2TNK Works 3TNK Works -4TNK Gun, missile origins are wrong +4TNK Works Light vehicles V2RL Works diff --git a/rules.ini b/rules.ini index 8c029a573e..34338ddc33 100644 --- a/rules.ini +++ b/rules.ini @@ -543,10 +543,9 @@ Armor=none TechLevel=2 Sight=4 Speed=3 -Owner=allies +Owner=allies,soviet Cost=300 Points=10 -DoubleOwned=yes ; Flamethrower [E4] @@ -602,7 +601,7 @@ Infiltrate=yes ; Tanya [E7] -Prerequisite=atek +Prerequisite=atek,stek Primary=Colt45 Secondary=Colt45 Strength=100 @@ -615,7 +614,6 @@ Cost=1200 Points=25 Infiltrate=yes C4=yes -DoubleOwned=yes ; field medic [MEDI]