diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj old mode 100644 new mode 100755 index f9683d6296..4e139c17a4 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -1,4 +1,4 @@ - + Debug @@ -113,6 +113,7 @@ + diff --git a/OpenRA.Game/Traits/Attack/AttackBase.cs b/OpenRA.Game/Traits/Attack/AttackBase.cs old mode 100644 new mode 100755 index cd20b4703d..9b83b6be8a --- a/OpenRA.Game/Traits/Attack/AttackBase.cs +++ b/OpenRA.Game/Traits/Attack/AttackBase.cs @@ -66,9 +66,12 @@ namespace OpenRA.Traits secondaryBurst = secondaryWeapon != null ? secondaryWeapon.Burst : 1; } - protected bool CanAttack(Actor self) + protected virtual bool CanAttack(Actor self) { - return target != null; + if( target == null ) return false; + if( ( primaryFireDelay > 0 ) && ( secondaryFireDelay > 0 ) ) return false; + + return true; } public bool IsReloading() @@ -108,6 +111,8 @@ namespace OpenRA.Traits public void DoAttack(Actor self) { + if( !CanAttack( self ) ) return; + var unit = self.traits.GetOrDefault(); var info = self.Info.Traits.Get(); @@ -165,7 +170,7 @@ namespace OpenRA.Traits var destUnit = thisTarget.traits.GetOrDefault(); var info = self.Info.Traits.Get(); - ScheduleDelayedAction(info.FireDelay, () => + ScheduleDelayedAction( FireDelay( self, info ), () => { var srcAltitude = unit != null ? unit.Altitude : 0; var destAltitude = destUnit != null ? destUnit.Altitude : 0; @@ -202,6 +207,11 @@ namespace OpenRA.Traits return true; } + public virtual int FireDelay( Actor self, AttackBaseInfo info ) + { + return info.FireDelay; + } + public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor) { if (mi.Button == MouseButton.Left || underCursor == null || underCursor.Owner == null) return null; diff --git a/OpenRA.Game/Traits/Attack/AttackOmni.cs b/OpenRA.Game/Traits/Attack/AttackOmni.cs old mode 100644 new mode 100755 index d7d1abfc97..224f075686 --- a/OpenRA.Game/Traits/Attack/AttackOmni.cs +++ b/OpenRA.Game/Traits/Attack/AttackOmni.cs @@ -32,13 +32,15 @@ namespace OpenRA.Traits public AttackOmni(Actor self) : base(self) { } + protected override bool CanAttack( Actor self ) + { + var isBuilding = ( self.traits.Contains() && !buildComplete ); + return base.CanAttack( self ) && !isBuilding; + } + public override void Tick(Actor self) { base.Tick(self); - - if (!CanAttack(self)) return; - if (self.traits.Contains() && !buildComplete) return; - DoAttack(self); } diff --git a/OpenRA.Game/Traits/Attack/AttackTesla.cs b/OpenRA.Game/Traits/Attack/AttackTesla.cs new file mode 100755 index 0000000000..513b9d4c61 --- /dev/null +++ b/OpenRA.Game/Traits/Attack/AttackTesla.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace OpenRA.Traits +{ + class AttackTeslaInfo : AttackOmniInfo + { + public readonly int MaxCharges = 3; + + public override object Create( Actor self ) + { + return new AttackTesla( self ); + } + } + + class AttackTesla : AttackOmni, ITick + { + int charges; + int timeToRecharge; + + public AttackTesla( Actor self ) + : base( self ) + { + charges = self.Info.Traits.Get().MaxCharges; + } + + protected override bool CanAttack( Actor self ) + { + return base.CanAttack( self ) && ( charges > 0 ); + } + + public override void Tick( Actor self ) + { + if( --timeToRecharge <= 0 ) + charges = self.Info.Traits.Get().MaxCharges; + if( charges <= 0 ) + { + primaryFireDelay = Math.Max( primaryFireDelay, timeToRecharge ); + secondaryFireDelay = Math.Max( secondaryFireDelay, timeToRecharge ); + sameTarget = null; + } + base.Tick( self ); + } + + Actor sameTarget; + public override int FireDelay( Actor self, AttackBaseInfo info ) + { + primaryFireDelay = 8; + timeToRecharge = Rules.WeaponInfo[ info.PrimaryWeapon ].ROF; + --charges; + + if( target != sameTarget ) + { + sameTarget = target; + self.traits.Get().PlayCharge( self ); + return base.FireDelay( self, info ); + } + else + return 3; + } + } +} diff --git a/OpenRA.Game/Traits/Attack/AttackTurreted.cs b/OpenRA.Game/Traits/Attack/AttackTurreted.cs old mode 100644 new mode 100755 index 31387e459e..9fb9fe1ece --- a/OpenRA.Game/Traits/Attack/AttackTurreted.cs +++ b/OpenRA.Game/Traits/Attack/AttackTurreted.cs @@ -31,20 +31,22 @@ namespace OpenRA.Traits { public AttackTurreted(Actor self) : base(self) { } - public override void Tick(Actor self) + protected override bool CanAttack( Actor self ) { - base.Tick(self); - - if( !CanAttack( self ) ) return; - - if (self.traits.Contains() && !buildComplete) - return; /* base defenses can't do anything until they finish building !*/ + if( self.traits.Contains() && !buildComplete ) + return false; var turreted = self.traits.Get(); turreted.desiredFacing = Util.GetFacing( target.CenterLocation - self.CenterLocation, turreted.turretFacing ); if( turreted.desiredFacing != turreted.turretFacing ) - return; + return false; + return base.CanAttack( self ); + } + + public override void Tick(Actor self) + { + base.Tick(self); DoAttack( self ); } diff --git a/OpenRA.Game/Traits/Render/RenderBuildingCharge.cs b/OpenRA.Game/Traits/Render/RenderBuildingCharge.cs old mode 100644 new mode 100755 index fe3dc9e817..d347e3a3b7 --- a/OpenRA.Game/Traits/Render/RenderBuildingCharge.cs +++ b/OpenRA.Game/Traits/Render/RenderBuildingCharge.cs @@ -27,14 +27,14 @@ namespace OpenRA.Traits } /* used for tesla */ - class RenderBuildingCharge : RenderBuilding, INotifyAttack + class RenderBuildingCharge : RenderBuilding { public RenderBuildingCharge(Actor self) : base(self) { } - public void Attacking(Actor self) + public void PlayCharge(Actor self) { Sound.Play(self.Info.Traits.Get().ChargeAudio); anim.PlayThen(GetPrefix(self) + "active", diff --git a/mods/ra/rules.yaml b/mods/ra/rules.yaml old mode 100644 new mode 100755 index b8defb75fd..07449e9e05 --- a/mods/ra/rules.yaml +++ b/mods/ra/rules.yaml @@ -570,7 +570,7 @@ TSLA: Crewed: yes Sight: 8 RenderBuildingCharge: - AttackOmni: + AttackTesla: PrimaryWeapon: TeslaZap FireDelay: 8 AutoTarget: