diff --git a/OpenRA.Game/Traits/Targetable.cs b/OpenRA.Game/Traits/Targetable.cs index ffd5a533a2..05e0d682bf 100644 --- a/OpenRA.Game/Traits/Targetable.cs +++ b/OpenRA.Game/Traits/Targetable.cs @@ -10,7 +10,8 @@ using System.Drawing; using OpenRA.Graphics; -using System.Linq; +using System.Linq; +using System.Collections.Generic; namespace OpenRA.Traits { @@ -31,6 +32,11 @@ namespace OpenRA.Traits public virtual string[] TargetTypes { get { return Info.TargetTypes;} + } + + public virtual IEnumerable TargetableSquares( Actor self ) + { + yield return self.Location; } } } diff --git a/OpenRA.Mods.RA/Activities/Attack.cs b/OpenRA.Mods.RA/Activities/Attack.cs index 0f16734a72..7650cb40e0 100755 --- a/OpenRA.Mods.RA/Activities/Attack.cs +++ b/OpenRA.Mods.RA/Activities/Attack.cs @@ -45,7 +45,7 @@ namespace OpenRA.Mods.RA.Activities var mobile = self.Trait(); var targetCell = Util.CellContaining(Target.CenterLocation); - if ((targetCell - self.Location).LengthSquared >= Range * Range) + if (!Combat.IsInRange( self.CenterLocation, Range, Util.CenterOfCell(targetCell))) return Util.SequenceActivities( mobile.MoveTo( Target, Range ), this ); var desiredFacing = Util.GetFacing((targetCell - self.Location).ToFloat2(), 0); diff --git a/OpenRA.Mods.RA/AttackLeap.cs b/OpenRA.Mods.RA/AttackLeap.cs index 9d56fb3d67..e54f0d88cb 100644 --- a/OpenRA.Mods.RA/AttackLeap.cs +++ b/OpenRA.Mods.RA/AttackLeap.cs @@ -32,8 +32,7 @@ namespace OpenRA.Mods.RA if (IsLeaping) return; var weapon = self.Trait().Weapons[0].Info; - if (weapon.Range * Game.CellSize * weapon.Range * Game.CellSize - < (target.CenterLocation - self.CenterLocation).LengthSquared) return; + if( !Combat.IsInRange( self.CenterLocation, weapon.Range, target.Actor ) ) return; self.CancelActivity(); self.QueueActivity(new Leap(self, target)); diff --git a/OpenRA.Mods.RA/Combat.cs b/OpenRA.Mods.RA/Combat.cs index 67e4fea214..45be4ac4d5 100755 --- a/OpenRA.Mods.RA/Combat.cs +++ b/OpenRA.Mods.RA/Combat.cs @@ -219,5 +219,20 @@ namespace OpenRA.Mods.RA return Util.RotateVectorByFacing(barrel.Position, turretFacing, .7f); } + + public static bool IsInRange( float2 attackOrigin, float range, Actor target ) + { + var rsq = range * range * Game.CellSize * Game.CellSize; + foreach( var cell in target.Trait().TargetableSquares( target ) ) + if( ( attackOrigin - cell * Game.CellSize ).LengthSquared < rsq ) + return true; + return false; + } + + public static bool IsInRange( float2 attackOrigin, float range, float2 targetLocation ) + { + var rsq = range * range * Game.CellSize * Game.CellSize; + return ( attackOrigin - targetLocation ).LengthSquared < rsq; + } } } diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index 02ac637ec5..a01a1b0406 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -221,6 +221,7 @@ + diff --git a/OpenRA.Mods.RA/TargetableBuilding.cs b/OpenRA.Mods.RA/TargetableBuilding.cs new file mode 100755 index 0000000000..6a946706fe --- /dev/null +++ b/OpenRA.Mods.RA/TargetableBuilding.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA +{ + class TargetableBuildingInfo : TargetableInfo, ITraitPrerequisite + { + public override object Create( ActorInitializer init ) { return new TargetableBuilding( this ); } + } + + class TargetableBuilding : Targetable + { + public TargetableBuilding( TargetableBuildingInfo info ) + : base( info ) + { + } + + public override IEnumerable TargetableSquares( Actor self ) + { + return self.Trait().OccupiedCells(); + } + } +} diff --git a/OpenRA.Mods.RA/Weapon.cs b/OpenRA.Mods.RA/Weapon.cs index fdb9e59207..6b5f758c3c 100644 --- a/OpenRA.Mods.RA/Weapon.cs +++ b/OpenRA.Mods.RA/Weapon.cs @@ -102,8 +102,10 @@ namespace OpenRA.Mods.RA if (limitedAmmo != null && !limitedAmmo.HasAmmo()) return; - if (Info.Range * Info.Range * Game.CellSize * Game.CellSize - < (target.CenterLocation - self.CenterLocation).LengthSquared) return; + if( target.IsActor && !Combat.IsInRange( self.CenterLocation, Info.Range, target.Actor ) ) + return; + else if( !target.IsActor && !Combat.IsInRange( self.CenterLocation, Info.Range, target.CenterLocation ) ) + return; if (Info.MinRange * Info.MinRange * Game.CellSize * Game.CellSize > (target.CenterLocation - self.CenterLocation).LengthSquared) return; diff --git a/mods/ra/rules/defaults.yaml b/mods/ra/rules/defaults.yaml index 94fc8ea07d..03ebab4158 100644 --- a/mods/ra/rules/defaults.yaml +++ b/mods/ra/rules/defaults.yaml @@ -125,7 +125,7 @@ AppearsOnRadar: Selectable: Priority: 3 - Targetable: + TargetableBuilding: TargetTypes: Ground Building: Dimensions: 1,1