diff --git a/OpenRa.Game/Traits/AttackBase.cs b/OpenRa.Game/Traits/AttackBase.cs index 1c7b0c9139..b989b967e4 100644 --- a/OpenRa.Game/Traits/AttackBase.cs +++ b/OpenRa.Game/Traits/AttackBase.cs @@ -16,6 +16,7 @@ namespace OpenRa.Game.Traits public readonly int[] PrimaryOffset = { 0, 0 }; public readonly int[] SecondaryOffset = null; public readonly bool MuzzleFlash = false; + public readonly int FireDelay = 0; public virtual object Create(Actor self) { return new AttackBase(self); } } @@ -37,8 +38,10 @@ namespace OpenRa.Game.Traits public AttackBase(Actor self) { - var primaryWeapon = self.LegacyInfo.Primary != null ? Rules.WeaponInfo[self.LegacyInfo.Primary] : null; - var secondaryWeapon = self.LegacyInfo.Secondary != null ? Rules.WeaponInfo[self.LegacyInfo.Secondary] : null; + var info = self.Info.Traits.WithInterface().First(); + + var primaryWeapon = info.PrimaryWeapon != null ? Rules.WeaponInfo[info.PrimaryWeapon] : null; + var secondaryWeapon = info.SecondaryWeapon != null ? Rules.WeaponInfo[info.SecondaryWeapon] : null; primaryBurst = primaryWeapon != null ? primaryWeapon.Burst : 1; secondaryBurst = secondaryWeapon != null ? secondaryWeapon.Burst : 1; @@ -87,19 +90,20 @@ namespace OpenRa.Game.Traits public void DoAttack(Actor self) { var unit = self.traits.GetOrDefault(); + var info = self.Info.Traits.WithInterface().First(); - if (self.LegacyInfo.Primary != null && CheckFire(self, unit, self.LegacyInfo.Primary, ref primaryFireDelay, - self.LegacyInfo.PrimaryOffset, ref primaryBurst, self.LegacyInfo.PrimaryLocalOffset)) + if (info.PrimaryWeapon != null && CheckFire(self, unit, info.PrimaryWeapon, ref primaryFireDelay, + info.PrimaryOffset, ref primaryBurst, info.PrimaryLocalOffset)) { secondaryFireDelay = Math.Max(4, secondaryFireDelay); primaryRecoil = 1; return; } - if (self.LegacyInfo.Secondary != null && CheckFire(self, unit, self.LegacyInfo.Secondary, ref secondaryFireDelay, - self.LegacyInfo.SecondaryOffset ?? self.LegacyInfo.PrimaryOffset, ref secondaryBurst, self.LegacyInfo.SecondaryLocalOffset)) + if (info.SecondaryWeapon != null && CheckFire(self, unit, info.SecondaryWeapon, ref secondaryFireDelay, + info.SecondaryOffset ?? info.PrimaryOffset, ref secondaryBurst, info.SecondaryLocalOffset)) { - if (self.LegacyInfo.SecondaryOffset != null) secondaryRecoil = 1; + if (info.SecondaryOffset != null) secondaryRecoil = 1; else primaryRecoil = 1; return; } @@ -140,8 +144,9 @@ namespace OpenRa.Game.Traits var firePos = self.CenterLocation.ToInt2() + Util.GetTurretPosition(self, unit, fireOffset, 0f).ToInt2(); var thisTarget = target; // closure. var destUnit = thisTarget.traits.GetOrDefault(); + var info = self.Info.Traits.WithInterface().First(); - ScheduleDelayedAction(self.LegacyInfo.FireDelay, () => + ScheduleDelayedAction(info.FireDelay, () => { var srcAltitude = unit != null ? unit.Altitude : 0; var destAltitude = destUnit != null ? destUnit.Altitude : 0; @@ -175,10 +180,14 @@ namespace OpenRa.Game.Traits { if (mi.Button == MouseButton.Left || underCursor == null) return null; if (self == underCursor) return null; - var isHeal = Rules.WeaponInfo[self.LegacyInfo.Primary].Damage < 0; + + var info = self.Info.Traits.WithInterface().First(); + var isHeal = Rules.WeaponInfo[info.PrimaryWeapon].Damage < 0; if (((underCursor.Owner == self.Owner) ^ isHeal) && !mi.Modifiers.HasModifier( Modifiers.Ctrl )) return null; + if (!Combat.HasAnyValidWeapons(self, underCursor)) return null; + return new Order(isHeal ? "Heal" : "Attack", self, underCursor, int2.Zero, null); } @@ -198,9 +207,10 @@ namespace OpenRa.Game.Traits protected virtual void QueueAttack(Actor self, Order order) { + var info = self.Info.Traits.WithInterface().First(); const int RangeTolerance = 1; /* how far inside our maximum range we should try to sit */ /* todo: choose the appropriate weapon, when only one works against this target */ - var weapon = order.Subject.LegacyInfo.Primary ?? order.Subject.LegacyInfo.Secondary; + var weapon = info.PrimaryWeapon ?? info.SecondaryWeapon; self.QueueActivity(new Activities.Attack(order.TargetActor, Math.Max(0, (int)Rules.WeaponInfo[weapon].Range - RangeTolerance))); diff --git a/RulesConverter/Program.cs b/RulesConverter/Program.cs index 4c51a1fe1d..29c2a8ae03 100644 --- a/RulesConverter/Program.cs +++ b/RulesConverter/Program.cs @@ -138,7 +138,8 @@ namespace RulesConverter { "PrimaryLocalOffset", "PrimaryLocalOffset" }, { "SecondaryLocalOffset", "SecondaryLocalOffset" }, { "MuzzleFlash", "MuzzleFlash" }, // maybe - { "Recoil", "Recoil"} } + { "Recoil", "Recoil"}, + { "FireDelay", "FireDelay" } } }, { "Production", new PL { diff --git a/aftermath.yaml b/aftermath.yaml index 7d422e542f..5eaff6733b 100644 --- a/aftermath.yaml +++ b/aftermath.yaml @@ -129,6 +129,7 @@ MSUB: Speed: 5 AttackBase: PrimaryWeapon: SubSCUD + FireDelay: 2 RenderUnit: Submarine: Chronoshiftable: diff --git a/ra.yaml b/ra.yaml index 36eb9d8fd8..47c9ae40db 100644 --- a/ra.yaml +++ b/ra.yaml @@ -458,6 +458,7 @@ SS: Submarine: AttackBase: PrimaryWeapon: TorpTube + FireDelay: 2 Chronoshiftable: IronCurtainable: @@ -840,6 +841,7 @@ TSLA: RenderBuildingCharge: AttackTurreted: PrimaryWeapon: TeslaZap + FireDelay: 8 AutoTarget: IronCurtainable: @@ -2284,6 +2286,7 @@ E2: AttackBase: PrimaryWeapon: Grenade PrimaryOffset: 0,0,0,-13 + FireDelay: 15 TakeCover: SquishByTank: AutoTarget: @@ -2337,6 +2340,7 @@ E4: AttackBase: PrimaryWeapon: Flamer PrimaryOffset: 0,0,0,-7 + FireDelay: 8 TakeCover: SquishByTank: AutoTarget: