From 212f07f890184dbac831017bf640c40c9a3667fb Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Thu, 31 Oct 2013 21:29:50 +1300 Subject: [PATCH 1/9] Add a helper for finding the map edge in a given direction. --- OpenRA.Game/WorldUtils.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/OpenRA.Game/WorldUtils.cs b/OpenRA.Game/WorldUtils.cs index eb5490e097..0e0b613690 100755 --- a/OpenRA.Game/WorldUtils.cs +++ b/OpenRA.Game/WorldUtils.cs @@ -124,6 +124,15 @@ namespace OpenRA r.Next(w.Map.Bounds.Top, w.Map.Bounds.Bottom)); } + public static WPos FindMapEdge(this World w, WPos pos, WVec dir) + { + var tl = w.Map.Bounds.TopLeftAsCPos().TopLeft; + var br = w.Map.Bounds.BottomRightAsCPos().BottomRight; + var x = dir.X == 0 ? int.MaxValue : ((dir.X < 0 ? tl.X : br.X) - pos.X) / dir.X; + var y = dir.Y == 0 ? int.MaxValue : ((dir.Y < 0 ? tl.Y : br.Y) - pos.Y) / dir.Y; + return pos + Math.Min(x, y) * dir; + } + public static bool HasVoices(this Actor a) { var selectable = a.Info.Traits.GetOrDefault(); From 4754a8019ad3943c37a50fbaef832773fd7d12ee Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Thu, 31 Oct 2013 21:30:13 +1300 Subject: [PATCH 2/9] Support CenterPositionInit for Aircraft. --- OpenRA.Mods.RA/Air/Aircraft.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/OpenRA.Mods.RA/Air/Aircraft.cs b/OpenRA.Mods.RA/Air/Aircraft.cs index 73bffe7911..e96664438a 100755 --- a/OpenRA.Mods.RA/Air/Aircraft.cs +++ b/OpenRA.Mods.RA/Air/Aircraft.cs @@ -57,13 +57,17 @@ namespace OpenRA.Mods.RA.Air if (init.Contains()) SetPosition(self, init.Get()); - this.Facing = init.Contains() ? init.Get() : info.InitialFacing; if (init.Contains()) { var z = init.Get() * 1024 / Game.CellSize; SetPosition(self, CenterPosition + new WVec(0, 0, z - CenterPosition.Z)); } + + if (init.Contains()) + SetPosition(self, init.Get()); + + this.Facing = init.Contains() ? init.Get() : info.InitialFacing; } public Actor GetActorBelow() From f1f032dbb824e709ee510220e7bcf1ddf2b42554 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Fri, 1 Nov 2013 17:42:48 +1300 Subject: [PATCH 3/9] Don't crash if trying to check targets outside the map. --- OpenRA.Game/GameRules/WeaponInfo.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OpenRA.Game/GameRules/WeaponInfo.cs b/OpenRA.Game/GameRules/WeaponInfo.cs index ae67d887e7..37962ee8f4 100644 --- a/OpenRA.Game/GameRules/WeaponInfo.cs +++ b/OpenRA.Game/GameRules/WeaponInfo.cs @@ -172,6 +172,9 @@ namespace OpenRA.GameRules if (target.Type == TargetType.Terrain) { var cell = target.CenterPosition.ToCPos(); + if (!world.Map.IsInMap(cell)) + return false; + if (ValidTargets.Contains("Ground") && world.GetTerrainType(cell) != "Water") return true; From d7effe71da34f8cfc8cc4e18662b076ba33402af Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Thu, 31 Oct 2013 21:30:57 +1300 Subject: [PATCH 4/9] Add squad and quantisation support to AirstrikePower. --- OpenRA.Game/WorldUtils.cs | 4 +- OpenRA.Mods.RA/CarpetBomb.cs | 1 + .../SupportPowers/AirstrikePower.cs | 83 ++++++++++++------- 3 files changed, 56 insertions(+), 32 deletions(-) diff --git a/OpenRA.Game/WorldUtils.cs b/OpenRA.Game/WorldUtils.cs index 0e0b613690..e52195228f 100755 --- a/OpenRA.Game/WorldUtils.cs +++ b/OpenRA.Game/WorldUtils.cs @@ -124,13 +124,13 @@ namespace OpenRA r.Next(w.Map.Bounds.Top, w.Map.Bounds.Bottom)); } - public static WPos FindMapEdge(this World w, WPos pos, WVec dir) + public static WRange DistanceToMapEdge(this World w, WPos pos, WVec dir) { var tl = w.Map.Bounds.TopLeftAsCPos().TopLeft; var br = w.Map.Bounds.BottomRightAsCPos().BottomRight; var x = dir.X == 0 ? int.MaxValue : ((dir.X < 0 ? tl.X : br.X) - pos.X) / dir.X; var y = dir.Y == 0 ? int.MaxValue : ((dir.Y < 0 ? tl.Y : br.Y) - pos.Y) / dir.Y; - return pos + Math.Min(x, y) * dir; + return new WRange(Math.Min(x, y) * dir.Length); } public static bool HasVoices(this Actor a) diff --git a/OpenRA.Mods.RA/CarpetBomb.cs b/OpenRA.Mods.RA/CarpetBomb.cs index c6c34c5627..c5cdcc6a91 100644 --- a/OpenRA.Mods.RA/CarpetBomb.cs +++ b/OpenRA.Mods.RA/CarpetBomb.cs @@ -41,6 +41,7 @@ namespace OpenRA.Mods.RA } public void SetTarget(CPos targetCell) { target = Target.FromCell(targetCell); } + public void SetTarget(WPos pos) { target = Target.FromPos(pos); } public void Tick(Actor self) { diff --git a/OpenRA.Mods.RA/SupportPowers/AirstrikePower.cs b/OpenRA.Mods.RA/SupportPowers/AirstrikePower.cs index be55c46731..b9faeae598 100755 --- a/OpenRA.Mods.RA/SupportPowers/AirstrikePower.cs +++ b/OpenRA.Mods.RA/SupportPowers/AirstrikePower.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -8,6 +8,7 @@ */ #endregion +using System; using OpenRA.FileFormats; using OpenRA.Mods.RA.Activities; using OpenRA.Mods.RA.Air; @@ -19,59 +20,81 @@ namespace OpenRA.Mods.RA { [ActorReference] public readonly string UnitType = "badr.bomber"; + public readonly int SquadSize = 1; + public readonly WVec SquadOffset = new WVec(-1536, 2048, 0); + + public readonly int QuantizedFacings = 32; + public readonly WRange Cordon = new WRange(5120); + [ActorReference] public readonly string FlareType = null; - - public readonly int FlareTime = 25 * 60 * 2; // 2 minutes + public readonly int FlareTime = 3000; // 2 minutes public override object Create(ActorInitializer init) { return new AirstrikePower(init.self, this); } } class AirstrikePower : SupportPower { - public AirstrikePower(Actor self, AirstrikePowerInfo info) : base(self, info) { } + public AirstrikePower(Actor self, AirstrikePowerInfo info) + : base(self, info) { } public override void Activate(Actor self, Order order) { - var startPos = self.World.ChooseRandomEdgeCell(); + var info = Info as AirstrikePowerInfo; + + var attackFacing = Util.QuantizeFacing(self.World.SharedRandom.Next(256), info.QuantizedFacings) * (256 / info.QuantizedFacings); + var attackRotation = WRot.FromFacing(attackFacing); + var delta = new WVec(0, -1024, 0).Rotate(attackRotation); + + var altitude = Rules.Info[info.UnitType].Traits.Get().CruiseAltitude * 1024 / Game.CellSize; + var target = order.TargetLocation.CenterPosition + new WVec(0, 0, altitude); + var startEdge = target - (self.World.DistanceToMapEdge(target, -delta) + info.Cordon).Range * delta / 1024; + var finishEdge = target + (self.World.DistanceToMapEdge(target, delta) + info.Cordon).Range * delta / 1024; + self.World.AddFrameEndTask(w => { - var info = (Info as AirstrikePowerInfo); + var notification = self.Owner.IsAlliedWith(self.World.RenderPlayer) ? Info.LaunchSound : Info.IncomingSound; + Sound.Play(notification); - if (self.Owner.IsAlliedWith(self.World.RenderPlayer)) - Sound.Play(Info.LaunchSound); - else - Sound.Play(Info.IncomingSound); - - var flare = info.FlareType != null ? w.CreateActor(info.FlareType, new TypeDictionary + Actor flare = null; + if (info.FlareType != null) { - new LocationInit( order.TargetLocation ), - new OwnerInit( self.Owner ), - }) : null; + flare = w.CreateActor(info.FlareType, new TypeDictionary + { + new LocationInit(order.TargetLocation), + new OwnerInit(self.Owner), + }); - if (flare != null) - { flare.QueueActivity(new Wait(info.FlareTime)); flare.QueueActivity(new RemoveSelf()); } - var a = w.CreateActor(info.UnitType, new TypeDictionary + for (var i = -info.SquadSize / 2; i <= info.SquadSize / 2; i++) { - new LocationInit( startPos ), - new OwnerInit( self.Owner ), - new FacingInit( Util.GetFacing(order.TargetLocation - startPos, 0) ), - new AltitudeInit( Rules.Info[info.UnitType].Traits.Get().CruiseAltitude ), - }); - a.Trait().SetTarget(order.TargetLocation); + // Even-sized squads skip the lead plane + if (i == 0 && (info.SquadSize & 1) == 0) + continue; - a.CancelActivity(); - a.QueueActivity(Fly.ToCell(order.TargetLocation)); + // Includes the 90 degree rotation between body and world coordinates + var so = info.SquadOffset; + var spawnOffset = new WVec(i*so.Y, -Math.Abs(i)*so.X, 0).Rotate(attackRotation); + var targetOffset = new WVec(i*so.Y, 0, 0).Rotate(attackRotation); - if (flare != null) - a.QueueActivity(new CallFunc(() => flare.Destroy())); + var a = w.CreateActor(info.UnitType, new TypeDictionary + { + new CenterPositionInit(startEdge + spawnOffset), + new OwnerInit(self.Owner), + new FacingInit(attackFacing), + }); - a.QueueActivity(new FlyOffMap()); - a.QueueActivity(new RemoveSelf()); + a.Trait().SetTarget(target + targetOffset); + + if (flare != null) + a.QueueActivity(new CallFunc(() => flare.Destroy())); + + a.QueueActivity(Fly.ToPos(finishEdge + spawnOffset)); + a.QueueActivity(new RemoveSelf()); + } }); } } From 47209f58482c559481ff0ccde28922f34b2a79d1 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Thu, 31 Oct 2013 22:13:14 +1300 Subject: [PATCH 5/9] CarpetBomb -> AttackBomber. --- OpenRA.Mods.RA/Armament.cs | 5 +- OpenRA.Mods.RA/AttackBomber.cs | 54 +++++++++++++ OpenRA.Mods.RA/CarpetBomb.cs | 78 ------------------- OpenRA.Mods.RA/Missions/MissionUtils.cs | 2 +- OpenRA.Mods.RA/OpenRA.Mods.RA.csproj | 2 +- .../SupportPowers/AirstrikePower.cs | 2 +- mods/cnc/rules/aircraft.yaml | 4 +- mods/cnc/weapons.yaml | 1 + mods/d2k/rules/aircraft.yaml | 4 +- mods/d2k/weapons.yaml | 1 + mods/ra/maps/Fort-Lonestar/map.yaml | 4 +- mods/ra/rules/aircraft.yaml | 4 +- mods/ra/weapons.yaml | 2 +- 13 files changed, 71 insertions(+), 92 deletions(-) create mode 100644 OpenRA.Mods.RA/AttackBomber.cs delete mode 100644 OpenRA.Mods.RA/CarpetBomb.cs diff --git a/OpenRA.Mods.RA/Armament.cs b/OpenRA.Mods.RA/Armament.cs index a4c1914c3a..6a2dcda31a 100644 --- a/OpenRA.Mods.RA/Armament.cs +++ b/OpenRA.Mods.RA/Armament.cs @@ -101,7 +101,8 @@ namespace OpenRA.Mods.RA // The world coordinate model uses Actor.Orientation public void CheckFire(Actor self, AttackBase attack, IFacing facing, Target target) { - if (FireDelay > 0) return; + if (FireDelay > 0) + return; var limitedAmmo = self.TraitOrDefault(); if (limitedAmmo != null && !limitedAmmo.HasAmmo()) @@ -113,7 +114,7 @@ namespace OpenRA.Mods.RA if (!target.IsInRange(self.CenterPosition, range)) return; - if (target.IsInRange(self.CenterPosition, minRange)) + if (minRange != WRange.Zero && target.IsInRange(self.CenterPosition, minRange)) return; if (!Weapon.IsValidAgainst(target, self.World)) diff --git a/OpenRA.Mods.RA/AttackBomber.cs b/OpenRA.Mods.RA/AttackBomber.cs new file mode 100644 index 0000000000..5f43f80dd3 --- /dev/null +++ b/OpenRA.Mods.RA/AttackBomber.cs @@ -0,0 +1,54 @@ +#region Copyright & License Information +/* + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using OpenRA.FileFormats; +using OpenRA.GameRules; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA +{ + class AttackBomberInfo : AttackBaseInfo + { + public override object Create(ActorInitializer init) { return new AttackBomber(init.self); } + } + + class AttackBomber : AttackBase, ISync + { + [Sync] Target target; + + public AttackBomber(Actor self) + : base(self) { } + + public override void Tick(Actor self) + { + base.Tick(self); + + if (!target.IsInRange(self.CenterPosition, GetMaximumRange())) + return; + + var facing = self.TraitOrDefault(); + var cp = self.CenterPosition; + var t = Target.FromPos(cp - new WVec(0, 0, cp.Z)); + foreach (var a in Armaments) + a.CheckFire(self, this, facing, t); + } + + public void SetTarget(WPos pos) { target = Target.FromPos(pos); } + + public override Activity GetAttackActivity(Actor self, Target newTarget, bool allowMove) + { + // TODO: Player controlled units want this too! + throw new NotImplementedException("CarpetBomb requires a scripted target"); + } + } +} diff --git a/OpenRA.Mods.RA/CarpetBomb.cs b/OpenRA.Mods.RA/CarpetBomb.cs deleted file mode 100644 index c5cdcc6a91..0000000000 --- a/OpenRA.Mods.RA/CarpetBomb.cs +++ /dev/null @@ -1,78 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System.Linq; -using OpenRA.GameRules; -using OpenRA.Traits; - -namespace OpenRA.Mods.RA -{ - class CarpetBombInfo : ITraitInfo - { - [WeaponReference] - public readonly string Weapon = null; - public readonly int Range = 3; - - public object Create(ActorInitializer init) { return new CarpetBomb(this); } - } - - // TODO: maybe integrate this better with the normal weapons system? - class CarpetBomb : ITick, ISync - { - CarpetBombInfo info; - Target target; - - [Sync] int dropDelay; - [Sync] WRange range; - - public CarpetBomb(CarpetBombInfo info) - { - this.info = info; - - // TODO: Push this conversion into the yaml - range = WRange.FromCells(info.Range); - } - - public void SetTarget(CPos targetCell) { target = Target.FromCell(targetCell); } - public void SetTarget(WPos pos) { target = Target.FromPos(pos); } - - public void Tick(Actor self) - { - if (!target.IsInRange(self.CenterPosition, range)) - return; - - var limitedAmmo = self.TraitOrDefault(); - if (limitedAmmo != null && !limitedAmmo.HasAmmo()) - return; - - if (--dropDelay <= 0) - { - var weapon = Rules.Weapons[info.Weapon.ToLowerInvariant()]; - dropDelay = weapon.ROF; - - var pos = self.CenterPosition; - var args = new ProjectileArgs - { - Weapon = weapon, - Facing = self.Trait().Facing, - - Source = pos, - SourceActor = self, - PassiveTarget = pos - new WVec(0, 0, pos.Z) - }; - - self.World.Add(args.Weapon.Projectile.Create(args)); - - if (args.Weapon.Report != null && args.Weapon.Report.Any()) - Sound.Play(args.Weapon.Report.Random(self.World.SharedRandom), self.CenterPosition); - } - } - } -} diff --git a/OpenRA.Mods.RA/Missions/MissionUtils.cs b/OpenRA.Mods.RA/Missions/MissionUtils.cs index 75d6ddbfc9..5b8cf38044 100644 --- a/OpenRA.Mods.RA/Missions/MissionUtils.cs +++ b/OpenRA.Mods.RA/Missions/MissionUtils.cs @@ -98,7 +98,7 @@ namespace OpenRA.Mods.RA.Missions new FacingInit(Util.GetFacing(location - entry, 0)), new AltitudeInit(Rules.Info["badr.bomber"].Traits.Get().CruiseAltitude), }); - badger.Trait().SetTarget(location); + badger.Trait().SetTarget(location.CenterPosition); badger.QueueActivity(Fly.ToCell(location)); badger.QueueActivity(new FlyOffMap()); badger.QueueActivity(new RemoveSelf()); diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index 50f6ce7bbb..c627a2aef8 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -179,7 +179,6 @@ - @@ -472,6 +471,7 @@ + diff --git a/OpenRA.Mods.RA/SupportPowers/AirstrikePower.cs b/OpenRA.Mods.RA/SupportPowers/AirstrikePower.cs index b9faeae598..2838bc4ae6 100755 --- a/OpenRA.Mods.RA/SupportPowers/AirstrikePower.cs +++ b/OpenRA.Mods.RA/SupportPowers/AirstrikePower.cs @@ -87,7 +87,7 @@ namespace OpenRA.Mods.RA new FacingInit(attackFacing), }); - a.Trait().SetTarget(target + targetOffset); + a.Trait().SetTarget(target + targetOffset); if (flare != null) a.QueueActivity(new CallFunc(() => flare.Destroy())); diff --git a/mods/cnc/rules/aircraft.yaml b/mods/cnc/rules/aircraft.yaml index 1608909af2..b7ad96b2ae 100644 --- a/mods/cnc/rules/aircraft.yaml +++ b/mods/cnc/rules/aircraft.yaml @@ -187,9 +187,9 @@ A10: WithShadow: LimitedAmmo: Ammo: 10 - CarpetBomb: + AttackBomber: + Armament: Weapon: Napalm - Range: 3 -Selectable: -GainsExperience: FlyAwayOnIdle: diff --git a/mods/cnc/weapons.yaml b/mods/cnc/weapons.yaml index 418253060e..6cc52e3336 100644 --- a/mods/cnc/weapons.yaml +++ b/mods/cnc/weapons.yaml @@ -727,6 +727,7 @@ TowerMissle: Napalm: ROF: 2 + Range: 3 Projectile: GravityBomb Image: BOMBLET Warhead: diff --git a/mods/d2k/rules/aircraft.yaml b/mods/d2k/rules/aircraft.yaml index 132e5ffb12..1072ee9a93 100644 --- a/mods/d2k/rules/aircraft.yaml +++ b/mods/d2k/rules/aircraft.yaml @@ -94,8 +94,8 @@ ORNI: HuskActor: ORNI.Husk ORNI.bomber: - CarpetBomb: - Range: 3 + AttackBomber: + Armament: Weapon: Napalm Inherits: ^Plane Health: diff --git a/mods/d2k/weapons.yaml b/mods/d2k/weapons.yaml index 4c46be0add..268520cb8e 100644 --- a/mods/d2k/weapons.yaml +++ b/mods/d2k/weapons.yaml @@ -482,6 +482,7 @@ ParaBomb: Napalm: ROF: 2 + Range: 3 Projectile: GravityBomb Image: BOMBS Warhead: diff --git a/mods/ra/maps/Fort-Lonestar/map.yaml b/mods/ra/maps/Fort-Lonestar/map.yaml index a90523ad52..288d4ed84c 100644 --- a/mods/ra/maps/Fort-Lonestar/map.yaml +++ b/mods/ra/maps/Fort-Lonestar/map.yaml @@ -1002,8 +1002,8 @@ Rules: Armor: Type: Concrete BADR.Bomber: - CarpetBomb: - Range: 3 + AttackBomber: + Armament: Weapon: ParaBomb Inherits: ^Plane Health: diff --git a/mods/ra/rules/aircraft.yaml b/mods/ra/rules/aircraft.yaml index fa1da4cb27..50b6ecfa78 100644 --- a/mods/ra/rules/aircraft.yaml +++ b/mods/ra/rules/aircraft.yaml @@ -36,8 +36,8 @@ BADR: RejectsOrders: BADR.Bomber: - CarpetBomb: - Range: 3 + AttackBomber: + Armament: Weapon: ParaBomb Inherits: ^Plane Health: diff --git a/mods/ra/weapons.yaml b/mods/ra/weapons.yaml index e6ef429de8..219395caab 100644 --- a/mods/ra/weapons.yaml +++ b/mods/ra/weapons.yaml @@ -898,7 +898,7 @@ DepthCharge: ParaBomb: ROF: 10 - Range: 4.5 + Range: 3 Report: CHUTE1.AUD Projectile: GravityBomb Image: PARABOMB From 911716fb1838271f708313a0c18c908abf6032e6 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Thu, 31 Oct 2013 22:20:43 +1300 Subject: [PATCH 6/9] Fix GravityBomb explosion position. --- OpenRA.Mods.RA/Effects/GravityBomb.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenRA.Mods.RA/Effects/GravityBomb.cs b/OpenRA.Mods.RA/Effects/GravityBomb.cs index edeb784b8e..e021df4a72 100644 --- a/OpenRA.Mods.RA/Effects/GravityBomb.cs +++ b/OpenRA.Mods.RA/Effects/GravityBomb.cs @@ -54,8 +54,9 @@ namespace OpenRA.Mods.RA.Effects if (pos.Z <= args.PassiveTarget.Z) { + pos += new WVec(0, 0, args.PassiveTarget.Z - pos.Z); world.AddFrameEndTask(w => w.Remove(this)); - Combat.DoImpacts(args.PassiveTarget, args.SourceActor, args.Weapon, args.FirepowerModifier); + Combat.DoImpacts(pos, args.SourceActor, args.Weapon, args.FirepowerModifier); } anim.Tick(); From 06fb8bf707aec91a6f83c8e97b92f5b230fe10d4 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Thu, 31 Oct 2013 22:27:14 +1300 Subject: [PATCH 7/9] Change the C&C Airstrike to be more support than sniper. Slight buff to total damage dealt, but no longer 1-shots buildings. --- mods/cnc/rules/aircraft.yaml | 7 +++++++ mods/cnc/rules/structures.yaml | 2 ++ mods/cnc/weapons.yaml | 8 ++++++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/mods/cnc/rules/aircraft.yaml b/mods/cnc/rules/aircraft.yaml index b7ad96b2ae..ad0a4dc1a4 100644 --- a/mods/cnc/rules/aircraft.yaml +++ b/mods/cnc/rules/aircraft.yaml @@ -190,10 +190,17 @@ A10: AttackBomber: Armament: Weapon: Napalm + LocalOffset: 0,-256,-43, 0,256,-43 -Selectable: -GainsExperience: FlyAwayOnIdle: RejectsOrders: + Contrail@1: + Offset: -640,171,0 + TrailLength: 15 + Contrail@2: + Offset: -640,-171,0 + TrailLength: 15 TRAN.Husk: Inherits: ^HelicopterHusk diff --git a/mods/cnc/rules/structures.yaml b/mods/cnc/rules/structures.yaml index 976fe41ef7..aab0d9fb29 100644 --- a/mods/cnc/rules/structures.yaml +++ b/mods/cnc/rules/structures.yaml @@ -375,6 +375,8 @@ HQ: AirstrikePower: Icon: airstrike ChargeTime: 180 + SquadSize: 3 + QuantizedFacings: 8 Description: Air Strike LongDesc: Deploy an aerial napalm strike.\nBurns buildings and infantry along a line. EndChargeSound: airredy1.aud diff --git a/mods/cnc/weapons.yaml b/mods/cnc/weapons.yaml index 6cc52e3336..5b18cf5dd7 100644 --- a/mods/cnc/weapons.yaml +++ b/mods/cnc/weapons.yaml @@ -726,8 +726,11 @@ TowerMissle: Damage: 45 Napalm: - ROF: 2 + ValidTargets: Ground, Water + ROF: 4 Range: 3 + Burst: 2 + BurstDelay: 3 Projectile: GravityBomb Image: BOMBLET Warhead: @@ -739,9 +742,10 @@ Napalm: Heavy: 55% InfDeath: 5 Explosion: med_napalm + WaterExplosion: med_napalm ImpactSound: flamer2.aud SmudgeType: Scorch - Damage: 130 + Damage: 45 Napalm.Crate: Warhead: From 8d07d14e4d2d265331af3552d08a1ba25ea415e9 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Thu, 31 Oct 2013 22:50:50 +1300 Subject: [PATCH 8/9] Add contrails to C17 too. --- mods/cnc/rules/aircraft.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/mods/cnc/rules/aircraft.yaml b/mods/cnc/rules/aircraft.yaml index ad0a4dc1a4..15c7121180 100644 --- a/mods/cnc/rules/aircraft.yaml +++ b/mods/cnc/rules/aircraft.yaml @@ -166,6 +166,18 @@ C17: -GainsExperience: FlyAwayOnIdle: RejectsOrders: + Contrail@1: + Offset: -261,-650,0 + TrailLength: 15 + Contrail@2: + Offset: -85,-384,0 + TrailLength: 16 + Contrail@3: + Offset: -85,384,0 + TrailLength: 16 + Contrail@4: + Offset: -261,650,0 + TrailLength: 15 A10: Inherits: ^Plane From 2f5ff301848bbd4a3550a18c967471d5c4666a7a Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Fri, 1 Nov 2013 17:44:54 +1300 Subject: [PATCH 9/9] Add strafing to C&C airstrike. --- OpenRA.Mods.RA/AttackBomber.cs | 47 +++++++++++++++---- .../SupportPowers/AirstrikePower.cs | 2 +- mods/cnc/rules/aircraft.yaml | 13 +++-- mods/cnc/sequences/aircraft.yaml | 4 ++ mods/cnc/weapons.yaml | 24 ++++++++-- 5 files changed, 75 insertions(+), 15 deletions(-) diff --git a/OpenRA.Mods.RA/AttackBomber.cs b/OpenRA.Mods.RA/AttackBomber.cs index 5f43f80dd3..29b020d0da 100644 --- a/OpenRA.Mods.RA/AttackBomber.cs +++ b/OpenRA.Mods.RA/AttackBomber.cs @@ -19,28 +19,59 @@ namespace OpenRA.Mods.RA { class AttackBomberInfo : AttackBaseInfo { - public override object Create(ActorInitializer init) { return new AttackBomber(init.self); } + [Desc("Armament name")] + public readonly string Bombs = "primary"; + + [Desc("Armament name")] + public readonly string Guns = "secondary"; + public readonly int FacingTolerance = 2; + + public override object Create(ActorInitializer init) { return new AttackBomber(init.self, this); } } class AttackBomber : AttackBase, ISync { + AttackBomberInfo info; [Sync] Target target; - public AttackBomber(Actor self) - : base(self) { } + public AttackBomber(Actor self, AttackBomberInfo info) + : base(self) + { + this.info = info; + } public override void Tick(Actor self) { base.Tick(self); - if (!target.IsInRange(self.CenterPosition, GetMaximumRange())) - return; - var facing = self.TraitOrDefault(); var cp = self.CenterPosition; - var t = Target.FromPos(cp - new WVec(0, 0, cp.Z)); - foreach (var a in Armaments) + var bombTarget = Target.FromPos(cp - new WVec(0, 0, cp.Z)); + + // Bombs drop anywhere in range + foreach (var a in Armaments.Where(a => a.Info.Name == info.Bombs)) + { + var range = new WRange((int)(1024 * a.Weapon.Range)); + if (!target.IsInRange(self.CenterPosition, range)) + continue; + + a.CheckFire(self, this, facing, bombTarget); + } + + // Guns only fire when approaching the target + var facingToTarget = Util.GetFacing(target.CenterPosition - self.CenterPosition, facing.Facing); + if (Math.Abs(facingToTarget - facing.Facing) % 256 > info.FacingTolerance) + return; + + foreach (var a in Armaments.Where(a => a.Info.Name == info.Guns)) + { + var range = new WRange((int)(1024 * a.Weapon.Range)); + if (!target.IsInRange(self.CenterPosition, range)) + continue; + + var t = Target.FromPos(cp - new WVec(0, range.Range / 2, cp.Z).Rotate(WRot.FromFacing(facing.Facing))); a.CheckFire(self, this, facing, t); + } } public void SetTarget(WPos pos) { target = Target.FromPos(pos); } diff --git a/OpenRA.Mods.RA/SupportPowers/AirstrikePower.cs b/OpenRA.Mods.RA/SupportPowers/AirstrikePower.cs index 2838bc4ae6..a04eb7ebf3 100755 --- a/OpenRA.Mods.RA/SupportPowers/AirstrikePower.cs +++ b/OpenRA.Mods.RA/SupportPowers/AirstrikePower.cs @@ -21,7 +21,7 @@ namespace OpenRA.Mods.RA [ActorReference] public readonly string UnitType = "badr.bomber"; public readonly int SquadSize = 1; - public readonly WVec SquadOffset = new WVec(-1536, 2048, 0); + public readonly WVec SquadOffset = new WVec(-1536, 1536, 0); public readonly int QuantizedFacings = 32; public readonly WRange Cordon = new WRange(5120); diff --git a/mods/cnc/rules/aircraft.yaml b/mods/cnc/rules/aircraft.yaml index 15c7121180..1a1e979880 100644 --- a/mods/cnc/rules/aircraft.yaml +++ b/mods/cnc/rules/aircraft.yaml @@ -197,10 +197,17 @@ A10: Range: 12 RenderUnit: WithShadow: - LimitedAmmo: - Ammo: 10 AttackBomber: - Armament: + Guns: gun + Bombs: bombs + Armament@GUNS: + Name: gun + Weapon: Vulcan + LocalOffset: 1024,0,-85 + WithMuzzleFlash@SECONDARY: + Armament: gun + Armament@BOMBS: + Name: bombs Weapon: Napalm LocalOffset: 0,-256,-43, 0,256,-43 -Selectable: diff --git a/mods/cnc/sequences/aircraft.yaml b/mods/cnc/sequences/aircraft.yaml index e85b0ac724..324d9f93e2 100644 --- a/mods/cnc/sequences/aircraft.yaml +++ b/mods/cnc/sequences/aircraft.yaml @@ -60,5 +60,9 @@ a10: idle: Start: 0 Facings: 32 + muzzle: minigun + Start: 0 + Length: 6 + Facings: 8 icon: a10icnh Start: 0 \ No newline at end of file diff --git a/mods/cnc/weapons.yaml b/mods/cnc/weapons.yaml index 5b18cf5dd7..4be159906f 100644 --- a/mods/cnc/weapons.yaml +++ b/mods/cnc/weapons.yaml @@ -725,12 +725,30 @@ TowerMissle: SmudgeType: Crater Damage: 45 +Vulcan: + ValidTargets: Ground, Water + ROF: 2 + Range: 6 + Report: gun5.aud + Projectile: Bullet + Speed: 100 + Warhead: + Damage: 75 + Spread: 10 + Versus: + None: 100% + Wood: 50% + Light: 100% + Heavy: 25% + InfDeath: 2 + Explosion: piffs + Napalm: ValidTargets: Ground, Water ROF: 4 - Range: 3 + Range: 2 Burst: 2 - BurstDelay: 3 + BurstDelay: 2 Projectile: GravityBomb Image: BOMBLET Warhead: @@ -745,7 +763,7 @@ Napalm: WaterExplosion: med_napalm ImpactSound: flamer2.aud SmudgeType: Scorch - Damage: 45 + Damage: 50 Napalm.Crate: Warhead: