diff --git a/OpenRA.Mods.Common/Activities/Attack.cs b/OpenRA.Mods.Common/Activities/Attack.cs index 5090a2cdc0..ea062da4a0 100644 --- a/OpenRA.Mods.Common/Activities/Attack.cs +++ b/OpenRA.Mods.Common/Activities/Attack.cs @@ -255,7 +255,7 @@ namespace OpenRA.Mods.Common.Activities { if (!attack.IsTraitPaused) foreach (var a in armaments) - a.CheckFire(self, facing, target); + a.CheckFire(self, facing, target, false); } void IActivityNotifyStanceChanged.StanceChanged(Actor self, AutoTarget autoTarget, UnitStance oldStance, UnitStance newStance) diff --git a/OpenRA.Mods.Common/Traits/Air/AttackBomber.cs b/OpenRA.Mods.Common/Traits/Air/AttackBomber.cs index b22236a42b..4f02953b9b 100644 --- a/OpenRA.Mods.Common/Traits/Air/AttackBomber.cs +++ b/OpenRA.Mods.Common/Traits/Air/AttackBomber.cs @@ -65,7 +65,7 @@ namespace OpenRA.Mods.Common.Traits continue; inAttackRange = true; - a.CheckFire(self, facing, target); + a.CheckFire(self, facing, target, false); } // Actors without armaments may want to trigger an action when it passes the target diff --git a/OpenRA.Mods.Common/Traits/Armament.cs b/OpenRA.Mods.Common/Traits/Armament.cs index e402375c50..b8c7496d7c 100644 --- a/OpenRA.Mods.Common/Traits/Armament.cs +++ b/OpenRA.Mods.Common/Traits/Armament.cs @@ -101,6 +101,9 @@ namespace OpenRA.Mods.Common.Traits if (WeaponInfo.Burst > 1 && WeaponInfo.BurstDelays.Length > 1 && (WeaponInfo.BurstDelays.Length != WeaponInfo.Burst - 1)) throw new YamlException($"Weapon '{weaponToLower}' has an invalid number of BurstDelays, must be single entry or Burst - 1."); + if (WeaponInfo.ReloadDelay <= 0) + throw new YamlException($"Weapon '{weaponToLower}' ReloadDelay value must not be equal to or lower than 0"); + base.RulesetLoaded(rules, ai); } } @@ -251,26 +254,32 @@ namespace OpenRA.Mods.Common.Traits // Note: facing is only used by the legacy positioning code // The world coordinate model uses Actor.Orientation - public virtual Barrel CheckFire(Actor self, IFacing facing, in Target target) + public virtual bool CheckFire(Actor self, IFacing facing, in Target target, bool notifyAttacking) { if (!CanFire(self, target)) - return null; + return false; if (ticksSinceLastShot >= Weapon.ReloadDelay) Burst = Weapon.Burst; ticksSinceLastShot = 0; + do + { + // If Weapon.Burst == 1, cycle through all LocalOffsets, otherwise use the offset corresponding to current Burst + currentBarrel %= barrelCount; + var barrel = Weapon.Burst == 1 ? Barrels[currentBarrel] : Barrels[Burst % Barrels.Length]; + currentBarrel++; - // If Weapon.Burst == 1, cycle through all LocalOffsets, otherwise use the offset corresponding to current Burst - currentBarrel %= barrelCount; - var barrel = Weapon.Burst == 1 ? Barrels[currentBarrel] : Barrels[Burst % Barrels.Length]; - currentBarrel++; + FireBarrel(self, facing, target, barrel); + UpdateBurst(self, target); - FireBarrel(self, facing, target, barrel); + if (notifyAttacking) + foreach (var notify in notifyAttacks) + notify.Attacking(self, target, this, barrel); + } + while (FireDelay == 0 && CanFire(self, target)); - UpdateBurst(self, target); - - return barrel; + return true; } protected virtual void FireBarrel(Actor self, IFacing facing, in Target target, Barrel barrel) diff --git a/OpenRA.Mods.Common/Traits/Attack/AttackBase.cs b/OpenRA.Mods.Common/Traits/Attack/AttackBase.cs index a96473eaf9..ed75f2997a 100644 --- a/OpenRA.Mods.Common/Traits/Attack/AttackBase.cs +++ b/OpenRA.Mods.Common/Traits/Attack/AttackBase.cs @@ -166,7 +166,7 @@ namespace OpenRA.Mods.Common.Traits return; foreach (var a in Armaments) - a.CheckFire(self, facing, target); + a.CheckFire(self, facing, target, false); } IEnumerable IIssueOrder.Orders diff --git a/OpenRA.Mods.Common/Traits/Attack/AttackGarrisoned.cs b/OpenRA.Mods.Common/Traits/Attack/AttackGarrisoned.cs index c30549f309..5a82a3a1db 100644 --- a/OpenRA.Mods.Common/Traits/Attack/AttackGarrisoned.cs +++ b/OpenRA.Mods.Common/Traits/Attack/AttackGarrisoned.cs @@ -78,7 +78,6 @@ namespace OpenRA.Mods.Common.Traits public class AttackGarrisoned : AttackFollow, INotifyPassengerEntered, INotifyPassengerExited, IRender { public new readonly AttackGarrisonedInfo Info; - INotifyAttack[] notifyAttacks; readonly Lazy coords; readonly List armaments; readonly List muzzles; @@ -98,12 +97,6 @@ namespace OpenRA.Mods.Common.Traits paxRender = new Dictionary(); } - protected override void Created(Actor self) - { - notifyAttacks = self.TraitsImplementing().ToArray(); - base.Created(self); - } - protected override Func> InitializeGetArmaments(Actor self) { return () => armaments; @@ -171,8 +164,7 @@ namespace OpenRA.Mods.Common.Traits paxFacing[a.Actor].Facing = targetYaw; paxPos[a.Actor].SetCenterPosition(a.Actor, pos + PortOffset(self, port)); - var barrel = a.CheckFire(a.Actor, facing, target); - if (barrel == null) + if (!a.CheckFire(a.Actor, facing, target, true)) continue; if (a.Info.MuzzleSequence != null) @@ -188,9 +180,6 @@ namespace OpenRA.Mods.Common.Traits muzzles.Add(muzzleFlash); muzzleAnim.PlayThen(sequence, () => muzzles.Remove(muzzleFlash)); } - - foreach (var npa in notifyAttacks) - npa.Attacking(self, target, a, barrel); } } diff --git a/OpenRA.Mods.D2k/Activities/SwallowActor.cs b/OpenRA.Mods.D2k/Activities/SwallowActor.cs index 87923ab355..e0980a2bf2 100644 --- a/OpenRA.Mods.D2k/Activities/SwallowActor.cs +++ b/OpenRA.Mods.D2k/Activities/SwallowActor.cs @@ -85,15 +85,7 @@ namespace OpenRA.Mods.D2k.Activities if (affectedPlayers.Contains(self.World.LocalPlayer)) TextNotificationsManager.AddTransientLine(self.World.LocalPlayer, swallow.Info.WormAttackTextNotification); - var barrel = armament.CheckFire(self, facing, target); - if (barrel == null) - return false; - - // armament.CheckFire already calls INotifyAttack.PreparingAttack - foreach (var notify in self.TraitsImplementing()) - notify.Attacking(self, target, armament, barrel); - - return true; + return armament.CheckFire(self, facing, target, true); } public override bool Tick(Actor self)