From e765fb64398abac2eeda959724740c2ee0b95520 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 1 Apr 2013 15:53:23 +1300 Subject: [PATCH 01/30] Make world-coordinates [Sync]able --- OpenRA.Game/Sync.cs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/OpenRA.Game/Sync.cs b/OpenRA.Game/Sync.cs index 5d29bb85f8..7e41470919 100755 --- a/OpenRA.Game/Sync.cs +++ b/OpenRA.Game/Sync.cs @@ -80,6 +80,31 @@ namespace OpenRA il.EmitCall(OpCodes.Call, ((Func)hash_PSubVec).Method, null); il.Emit(OpCodes.Xor); } + else if (type == typeof(WRange)) + { + il.EmitCall(OpCodes.Call, ((Func)(a => a.GetHashCode())).Method, null); + il.Emit(OpCodes.Xor); + } + else if (type == typeof(WPos)) + { + il.EmitCall(OpCodes.Call, ((Func)(a => a.GetHashCode())).Method, null); + il.Emit(OpCodes.Xor); + } + else if (type == typeof(WVec)) + { + il.EmitCall(OpCodes.Call, ((Func)(a => a.GetHashCode())).Method, null); + il.Emit(OpCodes.Xor); + } + else if (type == typeof(WAngle)) + { + il.EmitCall(OpCodes.Call, ((Func)(a => a.GetHashCode())).Method, null); + il.Emit(OpCodes.Xor); + } + else if (type == typeof(WRot)) + { + il.EmitCall(OpCodes.Call, ((Func)(a => a.GetHashCode())).Method, null); + il.Emit(OpCodes.Xor); + } else if (type == typeof(TypeDictionary)) { il.EmitCall(OpCodes.Call, ((Func)hash_tdict).Method, null); From eec986d93ded6149fbf30361cea2a42e28fe8517 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Jul 2013 19:11:08 +1200 Subject: [PATCH 02/30] Add world coords overload of FindUnitsInCircle. --- OpenRA.Game/WorldUtils.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/OpenRA.Game/WorldUtils.cs b/OpenRA.Game/WorldUtils.cs index 0c43535154..64c47d5af5 100755 --- a/OpenRA.Game/WorldUtils.cs +++ b/OpenRA.Game/WorldUtils.cs @@ -39,6 +39,11 @@ namespace OpenRA return actors.OrderBy( a => (a.CenterLocation - px).LengthSquared ).FirstOrDefault(); } + public static IEnumerable FindUnitsInCircle(this World world, WPos a, WRange r) + { + return world.FindUnitsInCircle(PPos.FromWPos(a), r.Range * Game.CellSize / 1024); + } + public static IEnumerable FindUnitsInCircle(this World world, PPos a, int r) { using (new PerfSample("FindUnitsInCircle")) From 399aac7e0f7f263d0191fef328d7c40decaf72b9 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Jul 2013 15:07:18 +1200 Subject: [PATCH 03/30] Extend Target with world-coordinate range checks. --- OpenRA.Game/Traits/Target.cs | 50 ++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/OpenRA.Game/Traits/Target.cs b/OpenRA.Game/Traits/Target.cs index 33456afd5c..43a8efec68 100644 --- a/OpenRA.Game/Traits/Target.cs +++ b/OpenRA.Game/Traits/Target.cs @@ -8,11 +8,15 @@ */ #endregion +using System; +using System.Collections.Generic; +using System.Linq; + namespace OpenRA.Traits { - public struct Target // a target: either an actor, or a fixed location. + public struct Target { - public static Target[] NoTargets = {}; + public static readonly Target[] NoTargets = {}; Actor actor; PPos pos; @@ -43,6 +47,48 @@ namespace OpenRA.Traits public PPos PxPosition { get { return IsActor ? actor.Trait().PxPosition : pos; } } public PPos CenterLocation { get { return PxPosition; } } + // Representative position - see Positions for the full set of targetable positions. + public WPos CenterPosition + { + get + { + if (!IsValid) + throw new InvalidOperationException("Attempting to query the position of an invalid Target"); + + return actor != null ? actor.CenterPosition : pos.ToWPos(0); + } + } + + // Positions available to target for range checks + static readonly WPos[] NoPositions = {}; + public IEnumerable Positions + { + get + { + if (!IsValid) + return NoPositions; + + if (actor == null) + return new []{pos.ToWPos(0)}; + + var targetable = actor.TraitOrDefault(); + if (targetable == null) + return new []{actor.CenterPosition}; + + return targetable.TargetableCells(actor).Select(c => c.CenterPosition); + } + } + + public bool IsInRange(WPos origin, WRange range) + { + if (!IsValid) + return false; + + // Target ranges are calculated in 2D, so ignore height differences + return Positions.Any(t => (t.X - origin.X)*(t.X - origin.X) + + (t.Y - origin.Y)*(t.Y - origin.Y) <= range.Range*range.Range); + } + public Actor Actor { get { return IsActor ? actor : null; } } public bool IsActor { get { return actor != null && !actor.Destroyed; } } } From 6f67602d5770707e2b3d0142ac6f97ea77a2343f Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Jul 2013 15:25:13 +1200 Subject: [PATCH 04/30] Use Target range checks in attack activities. --- OpenRA.FileFormats/WRange.cs | 1 + OpenRA.Mods.RA/Activities/Attack.cs | 27 ++++++++++--------- OpenRA.Mods.RA/Activities/Heal.cs | 4 +-- OpenRA.Mods.RA/Attack/AttackFrontal.cs | 15 ++++++----- OpenRA.Mods.RA/Attack/AttackLeap.cs | 8 ------ OpenRA.Mods.RA/Attack/AttackMedic.cs | 9 ++++--- OpenRA.Mods.RA/Missions/Allies03Script.cs | 2 +- OpenRA.Mods.RA/Missions/Allies04Script.cs | 4 +-- OpenRA.Mods.RA/Missions/FortLonestarScript.cs | 2 +- OpenRA.Mods.RA/Missions/MissionUtils.cs | 2 +- OpenRA.Mods.RA/Missions/Survival01Script.cs | 2 +- OpenRA.Mods.RA/Missions/Survival02Script.cs | 2 +- 12 files changed, 39 insertions(+), 39 deletions(-) diff --git a/OpenRA.FileFormats/WRange.cs b/OpenRA.FileFormats/WRange.cs index 1f4c45ead2..216f8bd77e 100644 --- a/OpenRA.FileFormats/WRange.cs +++ b/OpenRA.FileFormats/WRange.cs @@ -22,6 +22,7 @@ namespace OpenRA public WRange(int r) { Range = r; } public static readonly WRange Zero = new WRange(0); + public static WRange FromCells(int cells) { return new WRange(1024*cells); } public static WRange operator +(WRange a, WRange b) { return new WRange(a.Range + b.Range); } public static WRange operator -(WRange a, WRange b) { return new WRange(a.Range - b.Range); } diff --git a/OpenRA.Mods.RA/Activities/Attack.cs b/OpenRA.Mods.RA/Activities/Attack.cs index cae2b93656..91b52e241a 100755 --- a/OpenRA.Mods.RA/Activities/Attack.cs +++ b/OpenRA.Mods.RA/Activities/Attack.cs @@ -19,7 +19,7 @@ namespace OpenRA.Mods.RA.Activities { protected Target Target; ITargetable targetable; - int Range; + WRange Range; bool AllowMovement; int nextPathTime; @@ -27,7 +27,10 @@ namespace OpenRA.Mods.RA.Activities const int delayBetweenPathingAttempts = 20; const int delaySpread = 5; - public Attack(Target target, int range, bool allowMovement) + public Attack(Target target, WRange range) + : this(target, range, true) {} + + public Attack(Target target, WRange range, bool allowMovement) { Target = target; if (target.IsActor) @@ -37,20 +40,18 @@ namespace OpenRA.Mods.RA.Activities AllowMovement = allowMovement; } - public Attack(Target target, int range) : this(target, range, true) {} - - public override Activity Tick( Actor self ) + public override Activity Tick(Actor self) { var attack = self.Trait(); - - var ret = InnerTick( self, attack ); - attack.IsAttacking = ( ret == this ); + var ret = InnerTick(self, attack); + attack.IsAttacking = (ret == this); return ret; } - protected virtual Activity InnerTick( Actor self, AttackBase attack ) + protected virtual Activity InnerTick(Actor self, AttackBase attack) { - if (IsCanceled) return NextActivity; + if (IsCanceled) + return NextActivity; if (!Target.IsValid) return NextActivity; @@ -61,7 +62,7 @@ namespace OpenRA.Mods.RA.Activities if (targetable != null && !targetable.TargetableBy(Target.Actor, self)) return NextActivity; - if (!Combat.IsInRange(self.CenterLocation, Range, Target)) + if (!Target.IsInRange(self.CenterPosition, Range)) { if (--nextPathTime > 0) return this; @@ -69,13 +70,13 @@ namespace OpenRA.Mods.RA.Activities nextPathTime = self.World.SharedRandom.Next(delayBetweenPathingAttempts - delaySpread, delayBetweenPathingAttempts + delaySpread); - return (AllowMovement) ? Util.SequenceActivities(self.Trait().MoveWithinRange(Target, Range), this) : NextActivity; + return (AllowMovement) ? Util.SequenceActivities(self.Trait().MoveWithinRange(Target, Range.Range / 1024), this) : NextActivity; } var desiredFacing = Util.GetFacing(Target.CenterLocation - self.CenterLocation, 0); var facing = self.Trait(); if (facing.Facing != desiredFacing) - return Util.SequenceActivities( new Turn( desiredFacing ), this ); + return Util.SequenceActivities(new Turn(desiredFacing), this); attack.DoAttack(self, Target); return this; diff --git a/OpenRA.Mods.RA/Activities/Heal.cs b/OpenRA.Mods.RA/Activities/Heal.cs index 0861e56c54..199f89d041 100755 --- a/OpenRA.Mods.RA/Activities/Heal.cs +++ b/OpenRA.Mods.RA/Activities/Heal.cs @@ -17,10 +17,10 @@ namespace OpenRA.Mods.RA.Activities /* non-turreted attack */ public class Heal : Attack { - public Heal(Target target, int range, bool allowMovement) + public Heal(Target target, WRange range, bool allowMovement) : base(target, range, allowMovement) {} - protected override Activity InnerTick( Actor self, AttackBase attack ) + protected override Activity InnerTick(Actor self, AttackBase attack) { if (Target.IsActor && Target.Actor.GetDamageState() == DamageState.Undamaged) return NextActivity; diff --git a/OpenRA.Mods.RA/Attack/AttackFrontal.cs b/OpenRA.Mods.RA/Attack/AttackFrontal.cs index 2f52e23625..c93cffbd2a 100644 --- a/OpenRA.Mods.RA/Attack/AttackFrontal.cs +++ b/OpenRA.Mods.RA/Attack/AttackFrontal.cs @@ -28,15 +28,15 @@ namespace OpenRA.Mods.RA public AttackFrontal(Actor self, AttackFrontalInfo info) : base( self ) { this.info = info; } - protected override bool CanAttack( Actor self, Target target ) + protected override bool CanAttack(Actor self, Target target) { - if( !base.CanAttack( self, target ) ) + if (!base.CanAttack(self, target)) return false; var facing = self.Trait().Facing; var facingToTarget = Util.GetFacing(target.CenterLocation - self.CenterLocation, facing); - if( Math.Abs( facingToTarget - facing ) % 256 > info.FacingTolerance ) + if (Math.Abs(facingToTarget - facing) % 256 > info.FacingTolerance) return false; return true; @@ -44,10 +44,13 @@ namespace OpenRA.Mods.RA public override Activity GetAttackActivity(Actor self, Target newTarget, bool allowMove) { - var weapon = ChooseArmamentForTarget(newTarget); - if (weapon == null) + var a = ChooseArmamentForTarget(newTarget); + if (a == null) return null; - return new Activities.Attack(newTarget, Math.Max(0, (int)weapon.Weapon.Range), allowMove); + + // TODO: Define weapon ranges as WRange + var range = new WRange(Math.Max(0,(int)(1024*a.Weapon.Range))); + return new Activities.Attack(newTarget, range, allowMove); } } } diff --git a/OpenRA.Mods.RA/Attack/AttackLeap.cs b/OpenRA.Mods.RA/Attack/AttackLeap.cs index b9acc3a097..1021bd7514 100644 --- a/OpenRA.Mods.RA/Attack/AttackLeap.cs +++ b/OpenRA.Mods.RA/Attack/AttackLeap.cs @@ -42,13 +42,5 @@ namespace OpenRA.Mods.RA self.CancelActivity(); self.QueueActivity(new Leap(self, target)); } - - public override Activity GetAttackActivity(Actor self, Target newTarget, bool allowMove) - { - var a = ChooseArmamentForTarget(newTarget); - if (a == null) - return null; - return new Activities.Attack(newTarget, Math.Max(0, (int)a.Weapon.Range), allowMove); - } } } diff --git a/OpenRA.Mods.RA/Attack/AttackMedic.cs b/OpenRA.Mods.RA/Attack/AttackMedic.cs index ec705f25ba..699b2d9cbd 100644 --- a/OpenRA.Mods.RA/Attack/AttackMedic.cs +++ b/OpenRA.Mods.RA/Attack/AttackMedic.cs @@ -29,10 +29,13 @@ namespace OpenRA.Mods.RA public override Activity GetAttackActivity(Actor self, Target newTarget, bool allowMove) { - var weapon = ChooseArmamentForTarget(newTarget); - if (weapon == null) + var a = ChooseArmamentForTarget(newTarget); + if (a == null) return null; - return new Activities.Heal(newTarget, Math.Max(0, (int)weapon.Weapon.Range), allowMove); + + // TODO: Define weapon ranges as WRange + var range = new WRange(Math.Max(0,(int)(1024*a.Weapon.Range))); + return new Activities.Heal(newTarget, range, allowMove); } } } diff --git a/OpenRA.Mods.RA/Missions/Allies03Script.cs b/OpenRA.Mods.RA/Missions/Allies03Script.cs index 28ee1db87a..1adde71cf4 100644 --- a/OpenRA.Mods.RA/Missions/Allies03Script.cs +++ b/OpenRA.Mods.RA/Missions/Allies03Script.cs @@ -297,7 +297,7 @@ namespace OpenRA.Mods.RA.Missions var enemy = FirstUnshroudedOrDefault(enemies.OrderBy(u => (self.CenterLocation - u.CenterLocation).LengthSquared), world, 10); if (enemy != null) - self.QueueActivity(new AttackMove.AttackMoveActivity(self, new Attack(Target.FromActor(enemy), 3))); + self.QueueActivity(new AttackMove.AttackMoveActivity(self, new Attack(Target.FromActor(enemy), WRange.FromCells(3)))); } void ManageSovietUnits() diff --git a/OpenRA.Mods.RA/Missions/Allies04Script.cs b/OpenRA.Mods.RA/Missions/Allies04Script.cs index a9c32e015a..d89c7085e2 100644 --- a/OpenRA.Mods.RA/Missions/Allies04Script.cs +++ b/OpenRA.Mods.RA/Missions/Allies04Script.cs @@ -125,7 +125,7 @@ namespace OpenRA.Mods.RA.Missions if (world.FrameNumber == frameInfiltrated + 1500 * 12 && !bridgeTank.IsDead() && bridgeTank.IsInWorld && !bridge.IsDead()) { - bridgeTank.QueueActivity(new Attack(Target.FromPos(bridge.CenterLocation), 4)); + bridgeTank.QueueActivity(new Attack(Target.FromPos(bridge.CenterLocation), WRange.FromCells(4))); attackingBridge = true; } if (attackingBridge && bridge.IsDead()) @@ -152,7 +152,7 @@ namespace OpenRA.Mods.RA.Missions var enemy = enemies.OrderBy(u => (attacker.CenterLocation - u.CenterLocation).LengthSquared).FirstOrDefault(); if (enemy != null) - attacker.QueueActivity(new AttackMove.AttackMoveActivity(attacker, new Attack(Target.FromActor(enemy), 3))); + attacker.QueueActivity(new AttackMove.AttackMoveActivity(attacker, new Attack(Target.FromActor(enemy), WRange.FromCells(3)))); else { attackingTown = false; diff --git a/OpenRA.Mods.RA/Missions/FortLonestarScript.cs b/OpenRA.Mods.RA/Missions/FortLonestarScript.cs index 9e61f389fc..9aebdad818 100644 --- a/OpenRA.Mods.RA/Missions/FortLonestarScript.cs +++ b/OpenRA.Mods.RA/Missions/FortLonestarScript.cs @@ -82,7 +82,7 @@ namespace OpenRA.Mods.RA.Missions var targetEnemy = enemies.OrderBy(u => (self.CenterLocation - u.CenterLocation).LengthSquared).FirstOrDefault(); if (targetEnemy != null) { - self.QueueActivity(new AttackMove.AttackMoveActivity(self, new Attack(Target.FromActor(targetEnemy), 6))); + self.QueueActivity(new AttackMove.AttackMoveActivity(self, new Attack(Target.FromActor(targetEnemy), WRange.FromCells(6)))); } } diff --git a/OpenRA.Mods.RA/Missions/MissionUtils.cs b/OpenRA.Mods.RA/Missions/MissionUtils.cs index 93d9b943af..2d0537c547 100644 --- a/OpenRA.Mods.RA/Missions/MissionUtils.cs +++ b/OpenRA.Mods.RA/Missions/MissionUtils.cs @@ -213,7 +213,7 @@ namespace OpenRA.Mods.RA.Missions var enemy = enemies.OrderBy(u => (self.CenterLocation - u.CenterLocation).LengthSquared).FirstOrDefault(); if (enemy != null) - self.QueueActivity(queued, new AttackMove.AttackMoveActivity(self, new Attack(Target.FromActor(enemy), 3))); + self.QueueActivity(queued, new AttackMove.AttackMoveActivity(self, new Attack(Target.FromActor(enemy), WRange.FromCells(3)))); } } diff --git a/OpenRA.Mods.RA/Missions/Survival01Script.cs b/OpenRA.Mods.RA/Missions/Survival01Script.cs index 3f976702bf..b5b62aa75b 100644 --- a/OpenRA.Mods.RA/Missions/Survival01Script.cs +++ b/OpenRA.Mods.RA/Missions/Survival01Script.cs @@ -214,7 +214,7 @@ namespace OpenRA.Mods.RA.Missions var targetEnemy = enemies.OrderBy(u => (self.CenterLocation - u.CenterLocation).LengthSquared).FirstOrDefault(); if (targetEnemy != null) { - self.QueueActivity(new AttackMove.AttackMoveActivity(self, new Attack(Target.FromActor(targetEnemy), 3))); + self.QueueActivity(new AttackMove.AttackMoveActivity(self, new Attack(Target.FromActor(targetEnemy), WRange.FromCells(3)))); } } diff --git a/OpenRA.Mods.RA/Missions/Survival02Script.cs b/OpenRA.Mods.RA/Missions/Survival02Script.cs index 9036003048..bfb8861f6e 100644 --- a/OpenRA.Mods.RA/Missions/Survival02Script.cs +++ b/OpenRA.Mods.RA/Missions/Survival02Script.cs @@ -139,7 +139,7 @@ namespace OpenRA.Mods.RA.Missions var enemy = FirstUnshroudedOrDefault(enemies.OrderBy(u => (self.CenterLocation - u.CenterLocation).LengthSquared), world, 20); if (enemy != null) - self.QueueActivity(new AttackMove.AttackMoveActivity(self, new Attack(Target.FromActor(enemy), 3))); + self.QueueActivity(new AttackMove.AttackMoveActivity(self, new Attack(Target.FromActor(enemy), WRange.FromCells(3)))); } void SpawnAndAttack(string[] squad, Player owner, CPos location) From 3a0f6dda08d1c2f049c4507d8c20cc8c74cdff52 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Jul 2013 15:28:19 +1200 Subject: [PATCH 05/30] Use Target range checks in Armament. --- OpenRA.Mods.RA/Armament.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/OpenRA.Mods.RA/Armament.cs b/OpenRA.Mods.RA/Armament.cs index 74809cfce0..fe50383714 100755 --- a/OpenRA.Mods.RA/Armament.cs +++ b/OpenRA.Mods.RA/Armament.cs @@ -107,9 +107,17 @@ namespace OpenRA.Mods.RA if (limitedAmmo != null && !limitedAmmo.HasAmmo()) return; - if (!Combat.IsInRange(self.CenterLocation, Weapon.Range, target)) return; - if (Combat.IsInRange(self.CenterLocation, Weapon.MinRange, target)) return; - if (!IsValidAgainst(self.World, target)) return; + // TODO: Define weapon ranges as WRange + var range = new WRange((int)(1024*Weapon.Range)); + var minRange = new WRange((int)(1024*Weapon.MinRange)); + if (!target.IsInRange(self.CenterPosition, range)) + return; + + if (target.IsInRange(self.CenterPosition, minRange)) + return; + + if (!IsValidAgainst(self.World, target)) + return; var barrel = Barrels[Burst % Barrels.Length]; var destMove = target.IsActor ? target.Actor.TraitOrDefault() : null; From 07f9575bb7d42e39e5759c93663e5c94eea274ee Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Jul 2013 15:30:48 +1200 Subject: [PATCH 06/30] Use Target range checks in AttackLeap. --- OpenRA.Mods.RA/Attack/AttackLeap.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/OpenRA.Mods.RA/Attack/AttackLeap.cs b/OpenRA.Mods.RA/Attack/AttackLeap.cs index 1021bd7514..613d1da196 100644 --- a/OpenRA.Mods.RA/Attack/AttackLeap.cs +++ b/OpenRA.Mods.RA/Attack/AttackLeap.cs @@ -36,7 +36,9 @@ namespace OpenRA.Mods.RA if (a == null) return; - if (!Combat.IsInRange(self.CenterLocation, a.Weapon.Range, target)) + // TODO: Define weapon ranges as WRange + var range = new WRange((int)(1024*a.Weapon.Range)); + if (!target.IsInRange(self.CenterPosition, range)) return; self.CancelActivity(); From 4a471eff8b996d0fcb9d56d0408097ef774dda34 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Jul 2013 15:30:55 +1200 Subject: [PATCH 07/30] Use Target range checks in AttackLoyalty. --- OpenRA.Mods.RA/Attack/AttackLoyalty.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/OpenRA.Mods.RA/Attack/AttackLoyalty.cs b/OpenRA.Mods.RA/Attack/AttackLoyalty.cs index 3559fe52fb..ceb8caab0f 100644 --- a/OpenRA.Mods.RA/Attack/AttackLoyalty.cs +++ b/OpenRA.Mods.RA/Attack/AttackLoyalty.cs @@ -33,7 +33,9 @@ namespace OpenRA.Mods.RA if (arm == null) return; - if (!Combat.IsInRange(self.CenterLocation, arm.Weapon.Range, target)) + // TODO: Define weapon ranges as WRange + var range = new WRange((int)(1024*arm.Weapon.Range)); + if (!target.IsInRange(self.CenterPosition, range)) return; var move = self.TraitOrDefault(); From ec9054ceb1f53c1bce88e85bd0b95688aff0eab7 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Jul 2013 15:45:24 +1200 Subject: [PATCH 08/30] Use Target range checks in AutoTarget and dependencies. --- OpenRA.Mods.RA/Air/HeliAttack.cs | 2 +- OpenRA.Mods.RA/Attack/AttackBase.cs | 2 +- OpenRA.Mods.RA/AutoHeal.cs | 8 ++++---- OpenRA.Mods.RA/AutoTarget.cs | 17 ++++++++--------- OpenRA.Mods.RA/RenderRangeCircle.cs | 4 +++- 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/OpenRA.Mods.RA/Air/HeliAttack.cs b/OpenRA.Mods.RA/Air/HeliAttack.cs index 2bad762b79..38a8b8ae43 100755 --- a/OpenRA.Mods.RA/Air/HeliAttack.cs +++ b/OpenRA.Mods.RA/Air/HeliAttack.cs @@ -43,7 +43,7 @@ namespace OpenRA.Mods.RA.Air var desiredFacing = Util.GetFacing(dist, aircraft.Facing); aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT); - if (!Combat.IsInRange(self.CenterLocation, attack.GetMaximumRange(), target)) + if (!target.IsInRange(self.CenterPosition, attack.GetMaximumRange())) aircraft.TickMove(PSubPos.PerPx * aircraft.MovementSpeed, desiredFacing); attack.DoAttack( self, target ); diff --git a/OpenRA.Mods.RA/Attack/AttackBase.cs b/OpenRA.Mods.RA/Attack/AttackBase.cs index a3bd02a1f9..6f98b5f7e8 100644 --- a/OpenRA.Mods.RA/Attack/AttackBase.cs +++ b/OpenRA.Mods.RA/Attack/AttackBase.cs @@ -140,7 +140,7 @@ namespace OpenRA.Mods.RA public abstract Activity GetAttackActivity(Actor self, Target newTarget, bool allowMove); public bool HasAnyValidWeapons(Target t) { return Armaments.Any(a => a.IsValidAgainst(self.World, t)); } - public float GetMaximumRange() { return Armaments.Select(a => a.Weapon.Range).Aggregate(0f, Math.Max); } + public WRange GetMaximumRange() { return new WRange((int)(1024*Armaments.Max(a => a.Weapon.Range))); } public Armament ChooseArmamentForTarget(Target t) { return Armaments.FirstOrDefault(a => a.IsValidAgainst(self.World, t)); } diff --git a/OpenRA.Mods.RA/AutoHeal.cs b/OpenRA.Mods.RA/AutoHeal.cs index 60b4ca4f40..130f133801 100644 --- a/OpenRA.Mods.RA/AutoHeal.cs +++ b/OpenRA.Mods.RA/AutoHeal.cs @@ -19,10 +19,10 @@ namespace OpenRA.Mods.RA class AutoHeal : INotifyIdle { - public void TickIdle( Actor self ) + public void TickIdle(Actor self) { var attack = self.Trait(); - var inRange = self.World.FindUnitsInCircle(self.CenterLocation, (int)(Game.CellSize * attack.GetMaximumRange())); + var inRange = self.World.FindUnitsInCircle(self.CenterPosition, attack.GetMaximumRange()); var target = inRange .Where(a => a != self && a.AppearsFriendlyTo(self)) @@ -31,8 +31,8 @@ namespace OpenRA.Mods.RA .Where(a => attack.HasAnyValidWeapons(Target.FromActor(a))) .ClosestTo( self.CenterLocation ); - if( target != null ) - self.QueueActivity(attack.GetAttackActivity(self, Target.FromActor( target ), false )); + if (target != null) + self.QueueActivity(attack.GetAttackActivity(self, Target.FromActor(target), false)); } } } diff --git a/OpenRA.Mods.RA/AutoTarget.cs b/OpenRA.Mods.RA/AutoTarget.cs index d53f66fcc3..993ff3f7c3 100644 --- a/OpenRA.Mods.RA/AutoTarget.cs +++ b/OpenRA.Mods.RA/AutoTarget.cs @@ -87,8 +87,9 @@ namespace OpenRA.Mods.RA var target = ScanForTarget(self, null); if (target != null) { - self.SetTargetLine(Target.FromActor(target), Color.Red, false); - attack.AttackTarget(Target.FromActor(target), false, Info.AllowMovement && stance != UnitStance.Defend); + var t = Target.FromActor(target); + self.SetTargetLine(t, Color.Red, false); + attack.AttackTarget(t, false, Info.AllowMovement && stance != UnitStance.Defend); } } @@ -100,10 +101,9 @@ namespace OpenRA.Mods.RA public Actor ScanForTarget(Actor self, Actor currentTarget) { - var range = Info.ScanRadius > 0 ? Info.ScanRadius : attack.GetMaximumRange(); - - if (self.IsIdle || currentTarget == null || !Combat.IsInRange(self.CenterLocation, range, currentTarget)) - if(nextScanTime <= 0) + var range = Info.ScanRadius > 0 ? WRange.FromCells(Info.ScanRadius) : attack.GetMaximumRange(); + if (self.IsIdle || currentTarget == null || !Target.FromActor(currentTarget).IsInRange(self.CenterPosition, range)) + if (nextScanTime <= 0) return ChooseTarget(self, range); return currentTarget; @@ -116,11 +116,10 @@ namespace OpenRA.Mods.RA attack.AttackTarget(Target.FromActor(targetActor), false, Info.AllowMovement && stance != UnitStance.Defend); } - Actor ChooseTarget(Actor self, float range) + Actor ChooseTarget(Actor self, WRange range) { nextScanTime = self.World.SharedRandom.Next(Info.MinimumScanTimeInterval, Info.MaximumScanTimeInterval); - - var inRange = self.World.FindUnitsInCircle(self.CenterLocation, (int)(Game.CellSize * range)); + var inRange = self.World.FindUnitsInCircle(self.CenterPosition, range); if (self.Owner.HasFogVisibility()) { diff --git a/OpenRA.Mods.RA/RenderRangeCircle.cs b/OpenRA.Mods.RA/RenderRangeCircle.cs index e0ca291fe7..c931a1627c 100644 --- a/OpenRA.Mods.RA/RenderRangeCircle.cs +++ b/OpenRA.Mods.RA/RenderRangeCircle.cs @@ -47,9 +47,11 @@ namespace OpenRA.Mods.RA if (self.Owner != self.World.LocalPlayer) return; + // Hack: Convert world coords to cells + var pxRange = self.Trait().GetMaximumRange().Range / 1024f; wr.DrawRangeCircleWithContrast( Color.FromArgb(128, Color.Yellow), - self.CenterLocation.ToFloat2(), self.Trait().GetMaximumRange(), + self.CenterLocation.ToFloat2(), pxRange, Color.FromArgb(96, Color.Black), 1); } From d631f1b06b778b0950deae42ddc8a6047335ad23 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Jul 2013 15:51:52 +1200 Subject: [PATCH 09/30] Use Target range checks in CarpetBomb. --- OpenRA.Mods.RA/CarpetBomb.cs | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/OpenRA.Mods.RA/CarpetBomb.cs b/OpenRA.Mods.RA/CarpetBomb.cs index 7583e27822..03e612d3fe 100644 --- a/OpenRA.Mods.RA/CarpetBomb.cs +++ b/OpenRA.Mods.RA/CarpetBomb.cs @@ -14,25 +14,37 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA { - class CarpetBombInfo : TraitInfo + class CarpetBombInfo : ITraitInfo { [WeaponReference] public readonly string Weapon = null; public readonly int Range = 3; + + public object Create(ActorInitializer init) { return new CarpetBomb(this); } } - class CarpetBomb : ITick, ISync // TODO: maybe integrate this better with the normal weapons system? + // TODO: maybe integrate this better with the normal weapons system? + class CarpetBomb : ITick, ISync { - [Sync] CPos Target; - [Sync] int dropDelay; + CarpetBombInfo info; + Target target; - public void SetTarget(CPos targetCell) { Target = targetCell; } + [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 Tick(Actor self) { - var info = self.Info.Traits.Get(); - - if( !Combat.IsInRange( self.CenterLocation, info.Range, Target.ToPPos() ) ) + if (!target.IsInRange(self.CenterPosition, range)) return; var limitedAmmo = self.TraitOrDefault(); From 39e699d119ac8965e9782e29ffd1f578144593fc Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Jul 2013 16:10:31 +1200 Subject: [PATCH 10/30] Convert BaseProvider range check to world coords. --- OpenRA.Mods.RA/BelowUnits.cs | 2 +- OpenRA.Mods.RA/Buildings/BaseProvider.cs | 2 +- OpenRA.Mods.RA/Buildings/Building.cs | 23 +++++++++---------- OpenRA.Mods.RA/Buildings/FootprintUtils.cs | 3 ++- .../Orders/PlaceBuildingOrderGenerator.cs | 2 +- OpenRA.Mods.RA/Player/PlaceBuilding.cs | 17 ++++---------- .../Render/RenderBuildingWarFactory.cs | 6 +++-- 7 files changed, 25 insertions(+), 30 deletions(-) diff --git a/OpenRA.Mods.RA/BelowUnits.cs b/OpenRA.Mods.RA/BelowUnits.cs index 73c6fe4616..9de8e5b48d 100644 --- a/OpenRA.Mods.RA/BelowUnits.cs +++ b/OpenRA.Mods.RA/BelowUnits.cs @@ -29,7 +29,7 @@ namespace OpenRA.Mods.RA { // Offset effective position to the top of the northernmost occupied cell var bi = self.Info.Traits.GetOrDefault(); - offset = (bi != null) ? -FootprintUtils.CenterOffset(bi).Y : -512; + offset = ((bi != null) ? -FootprintUtils.CenterOffset(bi).Y : 0) - 512; } public IEnumerable ModifyRender(Actor self, WorldRenderer wr, IEnumerable r) diff --git a/OpenRA.Mods.RA/Buildings/BaseProvider.cs b/OpenRA.Mods.RA/Buildings/BaseProvider.cs index 0622f5a441..c3c28e8b61 100755 --- a/OpenRA.Mods.RA/Buildings/BaseProvider.cs +++ b/OpenRA.Mods.RA/Buildings/BaseProvider.cs @@ -17,7 +17,7 @@ namespace OpenRA.Mods.RA.Buildings { public class BaseProviderInfo : ITraitInfo { - public readonly float Range = 10; + public readonly int Range = 10; public readonly int Cooldown = 0; public readonly int InitialDelay = 0; diff --git a/OpenRA.Mods.RA/Buildings/Building.cs b/OpenRA.Mods.RA/Buildings/Building.cs index f4904e8b82..dbe8fda472 100755 --- a/OpenRA.Mods.RA/Buildings/Building.cs +++ b/OpenRA.Mods.RA/Buildings/Building.cs @@ -38,23 +38,20 @@ namespace OpenRA.Mods.RA.Buildings public object Create(ActorInitializer init) { return new Building(init, this); } - public PPos CenterLocation(CPos topLeft) + public Actor FindBaseProvider(World world, Player p, CPos topLeft) { - return (PPos)((2 * topLeft.ToInt2() + Dimensions) * Game.CellSize / 2); - } - - bool HasBaseProvider(World world, Player p, CPos topLeft) - { - var center = CenterLocation(topLeft); + var center = topLeft.CenterPosition + FootprintUtils.CenterOffset(this); foreach (var bp in world.ActorsWithTrait()) { if (bp.Actor.Owner.Stances[p] != Stance.Ally || !bp.Trait.Ready()) continue; - if (Combat.IsInRange(center, bp.Trait.Info.Range, bp.Actor.CenterLocation)) - return true; + // Range is counted from the center of the actor, not from each cell. + var target = Target.FromPos(bp.Actor.CenterLocation); + if (target.IsInRange(center, WRange.FromCells(bp.Trait.Info.Range))) + return bp.Actor; } - return false; + return null; } public bool IsCloseEnoughToBase(World world, Player p, string buildingName, CPos topLeft) @@ -62,7 +59,7 @@ namespace OpenRA.Mods.RA.Buildings if (p.PlayerActor.Trait().BuildAnywhere) return true; - if (RequiresBaseProvider && !HasBaseProvider(world, p, topLeft)) + if (RequiresBaseProvider && FindBaseProvider(world, p, topLeft) == null) return false; var buildingMaxBounds = (CVec)Dimensions; @@ -126,7 +123,9 @@ namespace OpenRA.Mods.RA.Buildings occupiedCells = FootprintUtils.UnpathableTiles( self.Info.Name, Info, TopLeft ) .Select(c => Pair.New(c, SubCell.FullCell)).ToArray(); - pxPosition = Info.CenterLocation(topLeft); + + var position = topLeft.CenterPosition + FootprintUtils.CenterOffset(Info); + pxPosition = PPos.FromWPosHackZ(position); } public int GetPowerUsage() diff --git a/OpenRA.Mods.RA/Buildings/FootprintUtils.cs b/OpenRA.Mods.RA/Buildings/FootprintUtils.cs index cddc6ac7c2..ddddcef376 100755 --- a/OpenRA.Mods.RA/Buildings/FootprintUtils.cs +++ b/OpenRA.Mods.RA/Buildings/FootprintUtils.cs @@ -65,7 +65,8 @@ namespace OpenRA.Mods.RA.Buildings public static WVec CenterOffset(BuildingInfo buildingInfo) { var dim = buildingInfo.Dimensions; - return new CVec(dim.X, dim.Y).ToWVec() / 2; + // Offset is measured relative to the center of the cell, so need to subtract an additional half cell. + return new CVec(dim.X, dim.Y).ToWVec() / 2 - new WVec(512, 512, 0); } } } diff --git a/OpenRA.Mods.RA/Orders/PlaceBuildingOrderGenerator.cs b/OpenRA.Mods.RA/Orders/PlaceBuildingOrderGenerator.cs index b561ca2dfd..602c48b42e 100755 --- a/OpenRA.Mods.RA/Orders/PlaceBuildingOrderGenerator.cs +++ b/OpenRA.Mods.RA/Orders/PlaceBuildingOrderGenerator.cs @@ -98,7 +98,7 @@ namespace OpenRA.Mods.RA.Orders initialized = true; } - var offset = (topLeft - CPos.Zero).ToWVec() + FootprintUtils.CenterOffset(BuildingInfo); + var offset = topLeft.CenterPosition + FootprintUtils.CenterOffset(BuildingInfo) - WPos.Zero; foreach (var r in preview) r.WithPos(r.Pos + offset).Render(wr); diff --git a/OpenRA.Mods.RA/Player/PlaceBuilding.cs b/OpenRA.Mods.RA/Player/PlaceBuilding.cs index 607b8f647f..cfa783579b 100755 --- a/OpenRA.Mods.RA/Player/PlaceBuilding.cs +++ b/OpenRA.Mods.RA/Player/PlaceBuilding.cs @@ -83,18 +83,11 @@ namespace OpenRA.Mods.RA if (buildingInfo.RequiresBaseProvider) { - var center = buildingInfo.CenterLocation(order.TargetLocation); - foreach (var bp in w.ActorsWithTrait()) - { - if (bp.Actor.Owner.Stances[self.Owner] != Stance.Ally || !bp.Trait.Ready()) - continue; - - if (Combat.IsInRange(center, bp.Trait.Info.Range, bp.Actor.CenterLocation)) - { - bp.Trait.BeginCooldown(); - break; - } - } + // May be null if the build anywhere cheat is active + // BuildingInfo.IsCloseEnoughToBase has already verified that this is a valid build location + var producer = buildingInfo.FindBaseProvider(w, self.Owner, order.TargetLocation); + if (producer != null) + producer.Trait().BeginCooldown(); } if (GetNumBuildables(self.Owner) > prevItems) diff --git a/OpenRA.Mods.RA/Render/RenderBuildingWarFactory.cs b/OpenRA.Mods.RA/Render/RenderBuildingWarFactory.cs index a766115f47..23e55b5cde 100755 --- a/OpenRA.Mods.RA/Render/RenderBuildingWarFactory.cs +++ b/OpenRA.Mods.RA/Render/RenderBuildingWarFactory.cs @@ -49,10 +49,12 @@ namespace OpenRA.Mods.RA.Render : base(init, info) { roof = new Animation(GetImage(init.self)); - var bi = init.self.Info.Traits.Get(); + + // Additional 512 units move from center -> top of cell + var offset = FootprintUtils.CenterOffset(bi).Y + 512; anims.Add("roof", new AnimationWithOffset(roof, null, - () => !buildComplete, FootprintUtils.CenterOffset(bi).Y)); + () => !buildComplete, offset)); } public void BuildingComplete( Actor self ) From 34df1ab705064d2ca7967da16a1037f2b565eff4 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Jul 2013 16:13:08 +1200 Subject: [PATCH 11/30] Remove Combat.IsInRange(). Closes #3433. --- OpenRA.Mods.RA/Combat.cs | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/OpenRA.Mods.RA/Combat.cs b/OpenRA.Mods.RA/Combat.cs index 3a3c821639..e912a7cbc4 100755 --- a/OpenRA.Mods.RA/Combat.cs +++ b/OpenRA.Mods.RA/Combat.cs @@ -207,29 +207,5 @@ namespace OpenRA.Mods.RA if (weapon.ValidTargets.Contains("Water") && world.GetTerrainType(location) == "Water") return true; return false; } - - public static bool IsInRange(PPos attackOrigin, float range, Actor target) - { - var rsq = range * range * Game.CellSize * Game.CellSize; - foreach (var cell in target.Trait().TargetableCells(target)) - if ((attackOrigin - Util.CenterOfCell(cell)).LengthSquared <= rsq) - return true; - return false; - } - - public static bool IsInRange(PPos attackOrigin, float range, PPos targetLocation) - { - var rsq = range * range * Game.CellSize * Game.CellSize; - return (attackOrigin - targetLocation).LengthSquared <= rsq; - } - - public static bool IsInRange(PPos attackOrigin, float range, Target target) - { - if (!target.IsValid) return false; - if (target.IsActor) - return IsInRange(attackOrigin, range, target.Actor); - else - return IsInRange(attackOrigin, range, target.CenterLocation); - } } } From 82b7854ed7447ef05e4edae85f625b84d335ff51 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Jul 2013 17:24:46 +1200 Subject: [PATCH 12/30] Make MobileInfo.SubCellOffsets static. --- OpenRA.Mods.RA/Move/Mobile.cs | 6 +++--- OpenRA.Mods.RA/Move/Move.cs | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/OpenRA.Mods.RA/Move/Mobile.cs b/OpenRA.Mods.RA/Move/Mobile.cs index f380906945..ad75f3f9cf 100755 --- a/OpenRA.Mods.RA/Move/Mobile.cs +++ b/OpenRA.Mods.RA/Move/Mobile.cs @@ -81,7 +81,7 @@ namespace OpenRA.Mods.RA.Move return passability.ToBits(); } - public readonly Dictionary SubCellOffsets = new Dictionary() + public static readonly Dictionary SubCellOffsets = new Dictionary() { {SubCell.TopLeft, new PVecInt(-7,-6)}, {SubCell.TopRight, new PVecInt(6,-6)}, @@ -197,7 +197,7 @@ namespace OpenRA.Mods.RA.Move if (init.Contains()) { this.__fromCell = this.__toCell = init.Get(); - this.PxPosition = Util.CenterOfCell(fromCell) + info.SubCellOffsets[fromSubCell]; + this.PxPosition = Util.CenterOfCell(fromCell) + MobileInfo.SubCellOffsets[fromSubCell]; } this.Facing = init.Contains() ? init.Get() : info.InitialFacing; @@ -207,7 +207,7 @@ namespace OpenRA.Mods.RA.Move public void SetPosition(Actor self, CPos cell) { SetLocation(cell,fromSubCell, cell,fromSubCell); - PxPosition = Util.CenterOfCell(fromCell) + Info.SubCellOffsets[fromSubCell]; + PxPosition = Util.CenterOfCell(fromCell) + MobileInfo.SubCellOffsets[fromSubCell]; FinishedMoving(self); } diff --git a/OpenRA.Mods.RA/Move/Move.cs b/OpenRA.Mods.RA/Move/Move.cs index b86f2278cc..6b35e2acf0 100755 --- a/OpenRA.Mods.RA/Move/Move.cs +++ b/OpenRA.Mods.RA/Move/Move.cs @@ -144,8 +144,8 @@ namespace OpenRA.Mods.RA.Move mobile.SetLocation( mobile.fromCell, mobile.fromSubCell, nextCell.Value.First, nextCell.Value.Second ); var move = new MoveFirstHalf( this, - Util.CenterOfCell( mobile.fromCell ) + mobile.Info.SubCellOffsets[mobile.fromSubCell], - Util.BetweenCells( mobile.fromCell, mobile.toCell ) + (mobile.Info.SubCellOffsets[mobile.fromSubCell] + mobile.Info.SubCellOffsets[mobile.toSubCell] ) / 2, + Util.CenterOfCell( mobile.fromCell ) + MobileInfo.SubCellOffsets[mobile.fromSubCell], + Util.BetweenCells( mobile.fromCell, mobile.toCell ) + (MobileInfo.SubCellOffsets[mobile.fromSubCell] + MobileInfo.SubCellOffsets[mobile.toSubCell] ) / 2, mobile.Facing, mobile.Facing, 0 ); @@ -335,15 +335,15 @@ namespace OpenRA.Mods.RA.Move protected override MovePart OnComplete( Actor self, Mobile mobile, Move parent ) { - var fromSubcellOffset = mobile.Info.SubCellOffsets[mobile.fromSubCell]; - var toSubcellOffset = mobile.Info.SubCellOffsets[mobile.toSubCell]; + var fromSubcellOffset = MobileInfo.SubCellOffsets[mobile.fromSubCell]; + var toSubcellOffset = MobileInfo.SubCellOffsets[mobile.toSubCell]; var nextCell = parent.PopPath( self, mobile ); if( nextCell != null ) { if(IsTurn(mobile, nextCell.Value.First)) { - var nextSubcellOffset = mobile.Info.SubCellOffsets[nextCell.Value.Second]; + var nextSubcellOffset = MobileInfo.SubCellOffsets[nextCell.Value.Second]; var ret = new MoveFirstHalf( move, Util.BetweenCells( mobile.fromCell, mobile.toCell ) + (fromSubcellOffset + toSubcellOffset) / 2, From 561cb6cfe0f3b6110038bca756cc959a7564d545 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Jul 2013 17:29:24 +1200 Subject: [PATCH 13/30] Rewrite Leap activity to be more robust. The dog will now always leap to the target subcell (even if the target dies or moves), and will kill whatever happens to be in the target cell when it lands. --- OpenRA.Mods.RA/Activities/Leap.cs | 47 +++++++++++++++++------------ OpenRA.Mods.RA/Attack/AttackLeap.cs | 2 -- OpenRA.Mods.RA/Move/Mobile.cs | 4 ++- 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/OpenRA.Mods.RA/Activities/Leap.cs b/OpenRA.Mods.RA/Activities/Leap.cs index d8f4537386..64898fa68b 100644 --- a/OpenRA.Mods.RA/Activities/Leap.cs +++ b/OpenRA.Mods.RA/Activities/Leap.cs @@ -8,6 +8,7 @@ */ #endregion +using System; using System.Linq; using OpenRA.Mods.RA.Move; using OpenRA.Mods.RA.Render; @@ -17,16 +18,29 @@ namespace OpenRA.Mods.RA.Activities { class Leap : Activity { - Target target; - PPos initialLocation; + Mobile mobile; + + PPos from; + PPos to; int moveFraction; - const int delay = 6; + const int length = 6; public Leap(Actor self, Target target) { - this.target = target; - initialLocation = (PPos) self.Trait().PxPosition; + if (!target.IsActor) + throw new InvalidOperationException("Leap requires a target actor"); + + var targetMobile = target.Actor.TraitOrDefault(); + if (targetMobile == null) + throw new InvalidOperationException("Leap requires a target actor with the Mobile trait"); + + mobile = self.Trait(); + mobile.SetLocation(mobile.fromCell, mobile.fromSubCell, targetMobile.fromCell, targetMobile.fromSubCell); + mobile.IsMoving = true; + + from = self.CenterLocation; + to = Util.CenterOfCell(targetMobile.fromCell) + MobileInfo.SubCellOffsets[targetMobile.fromSubCell]; self.Trait().Attacking(self, target); Sound.Play("dogg5p.aud", self.CenterLocation); @@ -34,23 +48,18 @@ namespace OpenRA.Mods.RA.Activities public override Activity Tick(Actor self) { - if( moveFraction == 0 && IsCanceled ) return NextActivity; - if (!target.IsValid) return NextActivity; + if (moveFraction == 0 && IsCanceled) + return NextActivity; - self.Trait().IsLeaping = true; - var mobile = self.Trait(); - ++moveFraction; - - mobile.PxPosition = PPos.Lerp(initialLocation, target.PxPosition, moveFraction, delay); - - if (moveFraction >= delay) + mobile.AdjustPxPosition(self, PPos.Lerp(from, to, moveFraction++, length - 1)); + if (moveFraction >= length) { - self.TraitsImplementing().FirstOrDefault() - .SetPosition(self, target.CenterLocation.ToCPos()); + mobile.SetLocation(mobile.toCell, mobile.toSubCell, mobile.toCell, mobile.toSubCell); + mobile.FinishedMoving(self); + mobile.IsMoving = false; - if (target.IsActor) - target.Actor.Kill(self); - self.Trait().IsLeaping = false; + // Kill whatever else is in our new cell + self.World.ActorMap.GetUnitsAt(mobile.toCell, mobile.toSubCell).Except(new []{self}).Do(a => a.Kill(self)); return NextActivity; } diff --git a/OpenRA.Mods.RA/Attack/AttackLeap.cs b/OpenRA.Mods.RA/Attack/AttackLeap.cs index 613d1da196..0dbf477093 100644 --- a/OpenRA.Mods.RA/Attack/AttackLeap.cs +++ b/OpenRA.Mods.RA/Attack/AttackLeap.cs @@ -22,8 +22,6 @@ namespace OpenRA.Mods.RA class AttackLeap : AttackFrontal, ISync { - [Sync] internal bool IsLeaping; - public AttackLeap(Actor self, AttackLeapInfo info) : base(self, info) {} diff --git a/OpenRA.Mods.RA/Move/Mobile.cs b/OpenRA.Mods.RA/Move/Mobile.cs index ad75f3f9cf..2fd6c1b279 100755 --- a/OpenRA.Mods.RA/Move/Mobile.cs +++ b/OpenRA.Mods.RA/Move/Mobile.cs @@ -170,7 +170,9 @@ namespace OpenRA.Mods.RA.Move public void SetLocation(CPos from, SubCell fromSub, CPos to, SubCell toSub) { - if (fromCell == from && toCell == to) return; + if (fromCell == from && toCell == to && fromSubCell == fromSub && toSubCell == toSub) + return; + RemoveInfluence(); __fromCell = from; __toCell = to; From f9ec5fd9b7dfa56b7732a0c62a3dc0a215d9fb37 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Jul 2013 18:53:35 +1200 Subject: [PATCH 14/30] Add WPos.ToCPos(). --- OpenRA.Game/CPos.cs | 9 ++++++--- OpenRA.Game/Graphics/ContrailRenderable.cs | 4 ++-- OpenRA.Mods.RA/Effects/Parachute.cs | 2 +- OpenRA.Mods.RA/SmokeTrailWhenDamaged.cs | 2 +- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/OpenRA.Game/CPos.cs b/OpenRA.Game/CPos.cs index 02e117c220..82b17d3d8b 100644 --- a/OpenRA.Game/CPos.cs +++ b/OpenRA.Game/CPos.cs @@ -21,8 +21,6 @@ namespace OpenRA public readonly int X, Y; public CPos(int x, int y) { X = x; Y = y; } - public CPos(WPos a) { X = a.X / 1024; Y = a.Y / 1024; } - public static readonly CPos Zero = new CPos(0, 0); public static explicit operator CPos(int2 a) { return new CPos(a.X, a.Y); } @@ -71,4 +69,9 @@ namespace OpenRA public static CPos TopLeftAsCPos(this Rectangle r) { return new CPos(r.Left, r.Top); } public static CPos BottomRightAsCPos(this Rectangle r) { return new CPos(r.Right, r.Bottom); } } -} + + public static class WPosExtensions + { + public static CPos ToCPos(this WPos a) { return new CPos(a.X / 1024, a.Y / 1024); } + } +} \ No newline at end of file diff --git a/OpenRA.Game/Graphics/ContrailRenderable.cs b/OpenRA.Game/Graphics/ContrailRenderable.cs index 9ef43b1813..a33cedd6b2 100644 --- a/OpenRA.Game/Graphics/ContrailRenderable.cs +++ b/OpenRA.Game/Graphics/ContrailRenderable.cs @@ -60,13 +60,13 @@ namespace OpenRA.Graphics // Start of the first line segment is the tail of the list - don't smooth it. var curPos = trail[idx(next - skip - 1)]; - var curCell = new CPos(curPos); + var curCell = curPos.ToCPos(); var curColor = color; for (var i = 0; i < length - skip - 4; i++) { var j = next - skip - i - 2; var nextPos = WPos.Average(trail[idx(j)], trail[idx(j-1)], trail[idx(j-2)], trail[idx(j-3)]); - var nextCell = new CPos(nextPos); + var nextCell = nextPos.ToCPos(); var nextColor = Exts.ColorLerp(i * 1f / (length - 4), color, Color.Transparent); if (!world.FogObscures(curCell) && !world.FogObscures(nextCell)) diff --git a/OpenRA.Mods.RA/Effects/Parachute.cs b/OpenRA.Mods.RA/Effects/Parachute.cs index 97ac756ce8..bc20073810 100644 --- a/OpenRA.Mods.RA/Effects/Parachute.cs +++ b/OpenRA.Mods.RA/Effects/Parachute.cs @@ -36,7 +36,7 @@ namespace OpenRA.Mods.RA.Effects parachuteOffset = pai.Offset; // Adjust x,y to match the target subcell - cargo.Trait().SetPosition(cargo, new CPos(dropPosition)); + cargo.Trait().SetPosition(cargo, dropPosition.ToCPos()); var cp = cargo.CenterPosition; pos = new WPos(cp.X, cp.Y, dropPosition.Z); } diff --git a/OpenRA.Mods.RA/SmokeTrailWhenDamaged.cs b/OpenRA.Mods.RA/SmokeTrailWhenDamaged.cs index eabdfee99d..4678af3399 100644 --- a/OpenRA.Mods.RA/SmokeTrailWhenDamaged.cs +++ b/OpenRA.Mods.RA/SmokeTrailWhenDamaged.cs @@ -43,7 +43,7 @@ namespace OpenRA.Mods.RA { var position = self.CenterPosition; if (position.Z > 0 && self.GetDamageState() >= info.MinDamage && - !self.World.FogObscures(new CPos(position))) + !self.World.FogObscures(position.ToCPos())) { var offset = info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation)); var pos = position + body.LocalToWorld(offset); From 2a0eff2ed0a643da788f30f87a1e13bc30a60ef1 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Jul 2013 19:18:20 +1200 Subject: [PATCH 15/30] Convert DrawLineToTarget to world coords. --- OpenRA.Game/Traits/DrawLineToTarget.cs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/OpenRA.Game/Traits/DrawLineToTarget.cs b/OpenRA.Game/Traits/DrawLineToTarget.cs index 2c72b9489c..a241af6715 100644 --- a/OpenRA.Game/Traits/DrawLineToTarget.cs +++ b/OpenRA.Game/Traits/DrawLineToTarget.cs @@ -52,8 +52,6 @@ namespace OpenRA.Traits public void RenderAfterWorld(WorldRenderer wr) { - //if (self.IsIdle) return; - var force = Game.GetModifierKeys().HasModifier(Modifiers.Alt); if ((lifetime <= 0 || --lifetime <= 0) && !force) return; @@ -61,9 +59,7 @@ namespace OpenRA.Traits if (targets == null || targets.Count == 0) return; - var move = self.TraitOrDefault(); - var origin = (move != null ? self.CenterLocation - new PVecInt(0, move.Altitude) : self.CenterLocation).ToFloat2(); - + var from = wr.ScreenPxPosition(self.CenterPosition); var wlr = Game.Renderer.WorldLineRenderer; foreach (var target in targets) @@ -71,9 +67,10 @@ namespace OpenRA.Traits if (!target.IsValid) continue; - wlr.DrawLine(origin, target.CenterLocation.ToFloat2(), c, c); - DrawTargetMarker(wlr, target.CenterLocation.ToFloat2()); - DrawTargetMarker(wlr, origin); + var to = wr.ScreenPxPosition(target.CenterPosition); + wlr.DrawLine(from, to, c, c); + DrawTargetMarker(wlr, from); + DrawTargetMarker(wlr, to); } } From e741e83fd403b554c18a4ec3674fffb932acf8a2 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Jul 2013 19:25:34 +1200 Subject: [PATCH 16/30] Convert IonCannon to world coords. --- OpenRA.Mods.Cnc/Effects/IonCannon.cs | 6 ++---- mods/cnc/sequences/misc.yaml | 1 + 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/OpenRA.Mods.Cnc/Effects/IonCannon.cs b/OpenRA.Mods.Cnc/Effects/IonCannon.cs index 697efece23..1fcefdc9b0 100644 --- a/OpenRA.Mods.Cnc/Effects/IonCannon.cs +++ b/OpenRA.Mods.Cnc/Effects/IonCannon.cs @@ -34,12 +34,10 @@ namespace OpenRA.Mods.Cnc.Effects public IEnumerable Render(WorldRenderer wr) { - yield return new SpriteRenderable(anim.Image, - target.CenterLocation.ToFloat2() - new float2(0, 0.5f*anim.Image.size.Y - Game.CellSize), - wr.Palette("effect"), (int)target.CenterLocation.Y); + yield return new SpriteRenderable(anim.Image, target.CenterPosition, 1, wr.Palette("effect"), 1.0f); } - void Finish( World world ) + void Finish(World world) { world.AddFrameEndTask(w => w.Remove(this)); Combat.DoExplosion(firedBy, "IonCannon", target.CenterLocation, 0); diff --git a/mods/cnc/sequences/misc.yaml b/mods/cnc/sequences/misc.yaml index 8556630c36..9f892d6db3 100644 --- a/mods/cnc/sequences/misc.yaml +++ b/mods/cnc/sequences/misc.yaml @@ -223,6 +223,7 @@ ionsfx: idle: Start: 0 Length: * + Offset: 0, -78 bomblet: idle: From 9eaeeffae9ea45808e90f96daa5afb782a17248d Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Jul 2013 19:32:37 +1200 Subject: [PATCH 17/30] CenterLocation.ToCPos() -> CenterPosition.ToCPos(). --- OpenRA.Game/Traits/Util.cs | 2 +- OpenRA.Game/Traits/World/Shroud.cs | 2 +- OpenRA.Mods.RA/AI/HackyAI.cs | 4 ++-- OpenRA.Mods.RA/Activities/Follow.cs | 2 +- OpenRA.Mods.RA/Activities/LayMines.cs | 2 +- OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs | 2 +- OpenRA.Mods.RA/Air/Aircraft.cs | 2 +- OpenRA.Mods.RA/Armament.cs | 2 +- OpenRA.Mods.RA/Attack/AttackBase.cs | 2 +- OpenRA.Mods.RA/Harvester.cs | 2 +- OpenRA.Mods.RA/Minelayer.cs | 2 +- OpenRA.Mods.RA/Move/Mobile.cs | 2 +- OpenRA.Mods.RA/Move/Move.cs | 2 +- OpenRA.Mods.RA/Player/BaseAttackNotifier.cs | 2 +- OpenRA.Mods.RA/Player/HarvesterAttackNotifier.cs | 2 +- OpenRA.Mods.RA/RallyPoint.cs | 2 +- OpenRA.Mods.RA/Repairable.cs | 2 +- OpenRA.Mods.RA/TargetableUnit.cs | 2 +- 18 files changed, 19 insertions(+), 19 deletions(-) diff --git a/OpenRA.Game/Traits/Util.cs b/OpenRA.Game/Traits/Util.cs index 6b605ab4d1..d40af1fa6c 100755 --- a/OpenRA.Game/Traits/Util.cs +++ b/OpenRA.Game/Traits/Util.cs @@ -177,7 +177,7 @@ namespace OpenRA.Traits : new CPos[] {}; if (cells.Length == 0) - cells = new CPos[] { target.CenterLocation.ToCPos() }; + cells = new CPos[] { target.CenterPosition.ToCPos() }; return Util.ExpandFootprint(cells, true); } diff --git a/OpenRA.Game/Traits/World/Shroud.cs b/OpenRA.Game/Traits/World/Shroud.cs index 1e7355b5f7..2b87e4b872 100644 --- a/OpenRA.Game/Traits/World/Shroud.cs +++ b/OpenRA.Game/Traits/World/Shroud.cs @@ -202,7 +202,7 @@ namespace OpenRA.Traits return cells.Select(c => c.First); } - return new[] { a.CenterLocation.ToCPos() }; + return new[] { a.CenterPosition.ToCPos() }; } public void Explore(World world, CPos center, int range) diff --git a/OpenRA.Mods.RA/AI/HackyAI.cs b/OpenRA.Mods.RA/AI/HackyAI.cs index 0e7219789e..b864e199b0 100644 --- a/OpenRA.Mods.RA/AI/HackyAI.cs +++ b/OpenRA.Mods.RA/AI/HackyAI.cs @@ -518,7 +518,7 @@ namespace OpenRA.Mods.RA.AI if (owner.attackOrFleeFuzzy.CanAttack) { foreach(var u in owner.units) - owner.world.IssueOrder(new Order("AttackMove", u, false) { TargetLocation = owner.Target.CenterLocation.ToCPos() }); + owner.world.IssueOrder(new Order("AttackMove", u, false) { TargetLocation = owner.Target.CenterPosition.ToCPos() }); // We have gathered sufficient units. Attack the nearest enemy unit. owner.fsm.ChangeState(new GroundUnitsAttackMoveState(), true); return; @@ -560,7 +560,7 @@ namespace OpenRA.Mods.RA.AI { owner.world.IssueOrder(new Order("Stop", leader, false)); foreach (var unit in owner.units.Where(a => !ownUnits.Contains(a))) - owner.world.IssueOrder(new Order("AttackMove", unit, false) { TargetLocation = leader.CenterLocation.ToCPos() }); + owner.world.IssueOrder(new Order("AttackMove", unit, false) { TargetLocation = leader.CenterPosition.ToCPos() }); } else { diff --git a/OpenRA.Mods.RA/Activities/Follow.cs b/OpenRA.Mods.RA/Activities/Follow.cs index f806851da1..8e5bae7cd7 100644 --- a/OpenRA.Mods.RA/Activities/Follow.cs +++ b/OpenRA.Mods.RA/Activities/Follow.cs @@ -33,7 +33,7 @@ namespace OpenRA.Mods.RA.Activities if (IsCanceled) return NextActivity; if (!Target.IsValid) return NextActivity; - var inRange = ( Target.CenterLocation.ToCPos() - self.Location ).LengthSquared < Range * Range; + var inRange = ( Target.CenterPosition.ToCPos() - self.Location ).LengthSquared < Range * Range; if( inRange ) return this; if (--nextPathTime > 0) return this; diff --git a/OpenRA.Mods.RA/Activities/LayMines.cs b/OpenRA.Mods.RA/Activities/LayMines.cs index 487b500954..8b426786be 100644 --- a/OpenRA.Mods.RA/Activities/LayMines.cs +++ b/OpenRA.Mods.RA/Activities/LayMines.cs @@ -38,7 +38,7 @@ namespace OpenRA.Mods.RA.Activities return Util.SequenceActivities( new MoveAdjacentTo(Target.FromActor(rearmTarget)), - mobile.MoveTo(rearmTarget.CenterLocation.ToCPos(), rearmTarget), + mobile.MoveTo(rearmTarget.CenterPosition.ToCPos(), rearmTarget), new Rearm(self), new Repair(rearmTarget), this ); diff --git a/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs b/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs index 3615d40485..285312b7b0 100755 --- a/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs +++ b/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs @@ -41,7 +41,7 @@ namespace OpenRA.Mods.RA.Activities } ps1.heuristic = PathSearch.DefaultEstimator(mobile.toCell); - var ps2 = PathSearch.FromPoint(self.World, mobile.Info, self, mobile.toCell, target.CenterLocation.ToCPos(), true); + var ps2 = PathSearch.FromPoint(self.World, mobile.Info, self, mobile.toCell, target.CenterPosition.ToCPos(), true); var ret = self.World.WorldActor.Trait().FindBidiPath(ps1, ps2); return Util.SequenceActivities(mobile.MoveTo(() => ret), this); diff --git a/OpenRA.Mods.RA/Air/Aircraft.cs b/OpenRA.Mods.RA/Air/Aircraft.cs index 55958cb82f..0cb4bed6db 100755 --- a/OpenRA.Mods.RA/Air/Aircraft.cs +++ b/OpenRA.Mods.RA/Air/Aircraft.cs @@ -177,7 +177,7 @@ namespace OpenRA.Mods.RA.Air return new Order(order.OrderID, self, queued) { TargetActor = target.Actor }; if (order.OrderID == "Move") - return new Order(order.OrderID, self, queued) { TargetLocation = target.CenterLocation.ToCPos() }; + return new Order(order.OrderID, self, queued) { TargetLocation = target.CenterPosition.ToCPos() }; return null; } diff --git a/OpenRA.Mods.RA/Armament.cs b/OpenRA.Mods.RA/Armament.cs index fe50383714..eae3275e4d 100755 --- a/OpenRA.Mods.RA/Armament.cs +++ b/OpenRA.Mods.RA/Armament.cs @@ -177,7 +177,7 @@ namespace OpenRA.Mods.RA if (target.IsActor) return Combat.WeaponValidForTarget(Weapon, target.Actor); else - return Combat.WeaponValidForTarget(Weapon, world, target.CenterLocation.ToCPos()); + return Combat.WeaponValidForTarget(Weapon, world, target.CenterPosition.ToCPos()); } public bool IsReloading { get { return FireDelay > 0; } } diff --git a/OpenRA.Mods.RA/Attack/AttackBase.cs b/OpenRA.Mods.RA/Attack/AttackBase.cs index 6f98b5f7e8..65641fd8ca 100644 --- a/OpenRA.Mods.RA/Attack/AttackBase.cs +++ b/OpenRA.Mods.RA/Attack/AttackBase.cs @@ -117,7 +117,7 @@ namespace OpenRA.Mods.RA if (target.IsActor) return new Order("Attack", self, queued) { TargetActor = target.Actor }; else - return new Order("Attack", self, queued) { TargetLocation = target.CenterLocation.ToCPos() }; + return new Order("Attack", self, queued) { TargetLocation = target.CenterPosition.ToCPos() }; } return null; } diff --git a/OpenRA.Mods.RA/Harvester.cs b/OpenRA.Mods.RA/Harvester.cs index 7a17785dd2..562364f255 100644 --- a/OpenRA.Mods.RA/Harvester.cs +++ b/OpenRA.Mods.RA/Harvester.cs @@ -250,7 +250,7 @@ namespace OpenRA.Mods.RA return new Order(order.OrderID, self, queued) { TargetActor = target.Actor }; if (order.OrderID == "Harvest") - return new Order(order.OrderID, self, queued) { TargetLocation = target.CenterLocation.ToCPos() }; + return new Order(order.OrderID, self, queued) { TargetLocation = target.CenterPosition.ToCPos() }; return null; } diff --git a/OpenRA.Mods.RA/Minelayer.cs b/OpenRA.Mods.RA/Minelayer.cs index da775f83fc..6d638a0e0e 100644 --- a/OpenRA.Mods.RA/Minelayer.cs +++ b/OpenRA.Mods.RA/Minelayer.cs @@ -46,7 +46,7 @@ namespace OpenRA.Mods.RA { if( order is BeginMinefieldOrderTargeter ) { - var start = target.CenterLocation.ToCPos(); + var start = target.CenterPosition.ToCPos(); self.World.OrderGenerator = new MinefieldOrderGenerator( self, start ); return new Order("BeginMinefield", self, false) { TargetLocation = start }; } diff --git a/OpenRA.Mods.RA/Move/Mobile.cs b/OpenRA.Mods.RA/Move/Mobile.cs index 2fd6c1b279..b1c44e96a1 100755 --- a/OpenRA.Mods.RA/Move/Mobile.cs +++ b/OpenRA.Mods.RA/Move/Mobile.cs @@ -234,7 +234,7 @@ namespace OpenRA.Mods.RA.Move if (order is MoveOrderTargeter) { if (Info.OnRails) return null; - return new Order("Move", self, queued) { TargetLocation = target.CenterLocation.ToCPos() }; + return new Order("Move", self, queued) { TargetLocation = target.CenterPosition.ToCPos() }; } return null; } diff --git a/OpenRA.Mods.RA/Move/Move.cs b/OpenRA.Mods.RA/Move/Move.cs index 6b35e2acf0..097e1ab51f 100755 --- a/OpenRA.Mods.RA/Move/Move.cs +++ b/OpenRA.Mods.RA/Move/Move.cs @@ -61,7 +61,7 @@ namespace OpenRA.Mods.RA.Move public Move(Target target, int range) { this.getPath = (self,mobile) => self.World.WorldActor.Trait().FindUnitPathToRange( - mobile.toCell, target.CenterLocation.ToCPos(), + mobile.toCell, target.CenterPosition.ToCPos(), range, self); this.destination = null; this.nearEnough = range; diff --git a/OpenRA.Mods.RA/Player/BaseAttackNotifier.cs b/OpenRA.Mods.RA/Player/BaseAttackNotifier.cs index a5495f6277..8ce7d9e876 100644 --- a/OpenRA.Mods.RA/Player/BaseAttackNotifier.cs +++ b/OpenRA.Mods.RA/Player/BaseAttackNotifier.cs @@ -44,7 +44,7 @@ namespace OpenRA.Mods.RA if (self.World.FrameNumber - lastAttackTime > info.NotifyInterval * 25) Sound.PlayNotification(self.Owner, "Speech", "BaseAttack", self.Owner.Country.Race); - lastAttackLocation = self.CenterLocation.ToCPos(); + lastAttackLocation = self.CenterPosition.ToCPos(); lastAttackTime = self.World.FrameNumber; } } diff --git a/OpenRA.Mods.RA/Player/HarvesterAttackNotifier.cs b/OpenRA.Mods.RA/Player/HarvesterAttackNotifier.cs index ac4e76df59..f003381ad1 100644 --- a/OpenRA.Mods.RA/Player/HarvesterAttackNotifier.cs +++ b/OpenRA.Mods.RA/Player/HarvesterAttackNotifier.cs @@ -44,7 +44,7 @@ namespace OpenRA.Mods.RA if (self.World.FrameNumber - lastAttackTime > info.NotifyInterval * 25) Sound.PlayNotification(self.Owner, "Speech", "HarvesterAttack", self.Owner.Country.Race); - lastAttackLocation = self.CenterLocation.ToCPos(); + lastAttackLocation = self.CenterPosition.ToCPos(); lastAttackTime = self.World.FrameNumber; } } diff --git a/OpenRA.Mods.RA/RallyPoint.cs b/OpenRA.Mods.RA/RallyPoint.cs index 36a0ff52a3..1db32f3e2b 100755 --- a/OpenRA.Mods.RA/RallyPoint.cs +++ b/OpenRA.Mods.RA/RallyPoint.cs @@ -42,7 +42,7 @@ namespace OpenRA.Mods.RA public Order IssueOrder( Actor self, IOrderTargeter order, Target target, bool queued ) { if( order.OrderID == "SetRallyPoint" ) - return new Order(order.OrderID, self, false) { TargetLocation = target.CenterLocation.ToCPos() }; + return new Order(order.OrderID, self, false) { TargetLocation = target.CenterPosition.ToCPos() }; return null; } diff --git a/OpenRA.Mods.RA/Repairable.cs b/OpenRA.Mods.RA/Repairable.cs index 9137a95360..35b1e8bc9c 100644 --- a/OpenRA.Mods.RA/Repairable.cs +++ b/OpenRA.Mods.RA/Repairable.cs @@ -78,7 +78,7 @@ namespace OpenRA.Mods.RA self.CancelActivity(); self.QueueActivity(new MoveAdjacentTo(target)); - self.QueueActivity(mobile.MoveTo(order.TargetActor.CenterLocation.ToCPos(), order.TargetActor)); + self.QueueActivity(mobile.MoveTo(order.TargetActor.CenterPosition.ToCPos(), order.TargetActor)); self.QueueActivity(new Rearm(self)); self.QueueActivity(new Repair(order.TargetActor)); diff --git a/OpenRA.Mods.RA/TargetableUnit.cs b/OpenRA.Mods.RA/TargetableUnit.cs index 37da70da40..2cda0fa15a 100755 --- a/OpenRA.Mods.RA/TargetableUnit.cs +++ b/OpenRA.Mods.RA/TargetableUnit.cs @@ -54,7 +54,7 @@ namespace OpenRA.Mods.RA public virtual IEnumerable TargetableCells( Actor self ) { - yield return self.CenterLocation.ToCPos(); + yield return self.CenterPosition.ToCPos(); } } } From 7f25573cfaff6a4a64beffbbd1f92d19f09c5e62 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Jul 2013 19:41:28 +1200 Subject: [PATCH 18/30] Convert Selectable to world coords. --- OpenRA.Game/Traits/Selectable.cs | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/OpenRA.Game/Traits/Selectable.cs b/OpenRA.Game/Traits/Selectable.cs index 9fbaf02b4d..b2a4ffe058 100644 --- a/OpenRA.Game/Traits/Selectable.cs +++ b/OpenRA.Game/Traits/Selectable.cs @@ -46,9 +46,9 @@ namespace OpenRA.Traits var Xy = new float2(bounds.Right, bounds.Top); wr.DrawSelectionBox(self, Color.White); - DrawHealthBar(self, xy, Xy); - DrawExtraBars(self, xy, Xy); - DrawUnitPath(self); + DrawHealthBar(wr, self, xy, Xy); + DrawExtraBars(wr, self, xy, Xy); + DrawUnitPath(wr, self); } public void DrawRollover(WorldRenderer wr, Actor self) @@ -61,11 +61,11 @@ namespace OpenRA.Traits var xy = new float2(bounds.Left, bounds.Top); var Xy = new float2(bounds.Right, bounds.Top); - DrawHealthBar(self, xy, Xy); - DrawExtraBars(self, xy, Xy); + DrawHealthBar(wr, self, xy, Xy); + DrawExtraBars(wr, self, xy, Xy); } - void DrawExtraBars(Actor self, float2 xy, float2 Xy) + void DrawExtraBars(WorldRenderer wr, Actor self, float2 xy, float2 Xy) { foreach (var extraBar in self.TraitsImplementing()) { @@ -74,12 +74,12 @@ namespace OpenRA.Traits { xy.Y += 4; Xy.Y += 4; - DrawSelectionBar(self, xy, Xy, extraBar.GetValue(), extraBar.GetColor()); + DrawSelectionBar(wr, self, xy, Xy, extraBar.GetValue(), extraBar.GetColor()); } } } - void DrawSelectionBar(Actor self, float2 xy, float2 Xy, float value, Color barColor) + void DrawSelectionBar(WorldRenderer wr, Actor self, float2 xy, float2 Xy, float value, Color barColor) { if (!self.IsInWorld) return; @@ -102,7 +102,7 @@ namespace OpenRA.Traits wlr.DrawLine(xy + new float2(0, -4), z + new float2(0, -4), barColor2, barColor2); } - void DrawHealthBar(Actor self, float2 xy, float2 Xy) + void DrawHealthBar(WorldRenderer wr, Actor self, float2 xy, float2 Xy) { if (!self.IsInWorld) return; @@ -148,24 +148,21 @@ namespace OpenRA.Traits } } - void DrawUnitPath(Actor self) + void DrawUnitPath(WorldRenderer wr, Actor self) { if (self.World.LocalPlayer == null ||!self.World.LocalPlayer.PlayerActor.Trait().PathDebug) return; var activity = self.GetCurrentActivity(); - var mobile = self.TraitOrDefault(); - if (activity != null && mobile != null) + if (activity != null) { - var alt = new float2(0, -mobile.Altitude); var targets = activity.GetTargets(self); - var start = self.CenterLocation.ToFloat2() + alt; + var start = wr.ScreenPxPosition(self.CenterPosition); var c = Color.Green; var wlr = Game.Renderer.WorldLineRenderer; - foreach (var step in targets.Select(p => p.CenterLocation.ToFloat2())) + foreach (var stp in targets.Select(p => wr.ScreenPxPosition(p.CenterPosition))) { - var stp = step + alt; wlr.DrawLine(stp + new float2(-1, -1), stp + new float2(-1, 1), c, c); wlr.DrawLine(stp + new float2(-1, 1), stp + new float2(1, 1), c, c); wlr.DrawLine(stp + new float2(1, 1), stp + new float2(1, -1), c, c); From 0fdffd7b6abb3487f1c957e7f957e141cce77d04 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Jul 2013 19:55:16 +1200 Subject: [PATCH 19/30] Convert Drag to world coords. --- OpenRA.FileFormats/WPos.cs | 2 ++ OpenRA.Game/Traits/Util.cs | 5 +++++ .../Activities/HarvesterDockSequence.cs | 7 +++---- OpenRA.Mods.RA/Activities/Enter.cs | 6 +++--- OpenRA.Mods.RA/Activities/UnloadCargo.cs | 17 +++++++++-------- OpenRA.Mods.RA/Move/Drag.cs | 18 +++++++++--------- OpenRA.Mods.RA/Move/Mobile.cs | 5 +++++ OpenRA.Mods.RA/Production.cs | 8 ++++---- 8 files changed, 40 insertions(+), 28 deletions(-) diff --git a/OpenRA.FileFormats/WPos.cs b/OpenRA.FileFormats/WPos.cs index 7800ef8508..25f76bef65 100644 --- a/OpenRA.FileFormats/WPos.cs +++ b/OpenRA.FileFormats/WPos.cs @@ -34,6 +34,8 @@ namespace OpenRA public static bool operator ==(WPos me, WPos other) { return (me.X == other.X && me.Y == other.Y && me.Z == other.Z); } public static bool operator !=(WPos me, WPos other) { return !(me == other); } + public static WPos Lerp(WPos a, WPos b, int mul, int div) { return a + (b - a) * mul / div; } + public static WPos Average(params WPos[] list) { if (list == null || list.Length == 0) diff --git a/OpenRA.Game/Traits/Util.cs b/OpenRA.Game/Traits/Util.cs index d40af1fa6c..c68b0d932e 100755 --- a/OpenRA.Game/Traits/Util.cs +++ b/OpenRA.Game/Traits/Util.cs @@ -30,6 +30,11 @@ namespace OpenRA.Traits return ( facing - rot ) & 0xFF; } + public static int GetFacing(WVec d, int currentFacing) + { + return GetFacing(new int2(d.X, d.Y), currentFacing); + } + public static int GetFacing(PVecInt d, int currentFacing) { return GetFacing(d.ToInt2(), currentFacing); diff --git a/OpenRA.Mods.Cnc/Activities/HarvesterDockSequence.cs b/OpenRA.Mods.Cnc/Activities/HarvesterDockSequence.cs index 59999add0e..337438a7fc 100644 --- a/OpenRA.Mods.Cnc/Activities/HarvesterDockSequence.cs +++ b/OpenRA.Mods.Cnc/Activities/HarvesterDockSequence.cs @@ -27,16 +27,15 @@ namespace OpenRA.Mods.Cnc readonly RenderUnit ru; State state; - PPos startDock; - PPos endDock; + WPos startDock, endDock; public HarvesterDockSequence(Actor self, Actor proc) { this.proc = proc; state = State.Turn; harv = self.Trait(); ru = self.Trait(); - startDock = self.Trait().PxPosition; - endDock = proc.Trait().PxPosition + new PVecInt(-15,8); + startDock = self.Trait().PxPosition.ToWPos(0); + endDock = (proc.Trait().PxPosition + new PVecInt(-15,8)).ToWPos(0); } public override Activity Tick(Actor self) diff --git a/OpenRA.Mods.RA/Activities/Enter.cs b/OpenRA.Mods.RA/Activities/Enter.cs index 652e970c63..fbf2243139 100755 --- a/OpenRA.Mods.RA/Activities/Enter.cs +++ b/OpenRA.Mods.RA/Activities/Enter.cs @@ -35,9 +35,9 @@ namespace OpenRA.Mods.RA.Activities // Move to the middle of the target, ignoring impassable tiles var mobile = self.Trait(); - var to = target.CenterLocation; - var from = self.CenterLocation; - var speed = mobile.MovementSpeedForCell(self, self.Location); + var to = target.CenterPosition; + var from = self.CenterPosition; + var speed = mobile.WorldMovementSpeedForCell(self, self.Location); var length = speed > 0 ? (int)((to - from).Length * 3 / speed) : 0; return Util.SequenceActivities( diff --git a/OpenRA.Mods.RA/Activities/UnloadCargo.cs b/OpenRA.Mods.RA/Activities/UnloadCargo.cs index 56968ad59e..e4cba01ee2 100644 --- a/OpenRA.Mods.RA/Activities/UnloadCargo.cs +++ b/OpenRA.Mods.RA/Activities/UnloadCargo.cs @@ -79,23 +79,24 @@ namespace OpenRA.Mods.RA.Activities return this; var actor = cargo.Unload(self); - var exitPx = Util.CenterOfCell(exitTile.Value); - var currentPx = Util.CenterOfCell(self.Location); + var exit = exitTile.Value.CenterPosition; + var current = self.Location.CenterPosition; self.World.AddFrameEndTask(w => { - if (actor.Destroyed) return; + if (actor.Destroyed) + return; var mobile = actor.Trait(); - mobile.Facing = Util.GetFacing( (exitPx - currentPx).ToInt2(), mobile.Facing ); + mobile.Facing = Util.GetFacing(exit - current, mobile.Facing ); mobile.SetPosition(actor, exitTile.Value); - mobile.AdjustPxPosition(actor, currentPx); - var speed = mobile.MovementSpeedForCell(actor, exitTile.Value); - var length = speed > 0 ? ((int)(exitPx - currentPx).Length * 3 / speed) : 0; + mobile.AdjustPxPosition(actor, PPos.FromWPos(current)); + var speed = mobile.WorldMovementSpeedForCell(actor, exitTile.Value); + var length = speed > 0 ? ((int)(exit - current).Length * 3 / speed) : 0; w.Add(actor); actor.CancelActivity(); - actor.QueueActivity(new Drag(currentPx, exitPx, length)); + actor.QueueActivity(new Drag(current, exit, length)); actor.QueueActivity(mobile.MoveTo(exitTile.Value, 0)); var rallyPoint = ChooseRallyPoint(actor).Value; diff --git a/OpenRA.Mods.RA/Move/Drag.cs b/OpenRA.Mods.RA/Move/Drag.cs index 9379d8c936..abfaf89392 100755 --- a/OpenRA.Mods.RA/Move/Drag.cs +++ b/OpenRA.Mods.RA/Move/Drag.cs @@ -15,25 +15,25 @@ namespace OpenRA.Mods.RA.Move { public class Drag : Activity { - PPos endLocation; - PPos startLocation; + WPos start, end; int length; int ticks = 0; - public Drag(PPos start, PPos end, int length) + public Drag(WPos start, WPos end, int length) { - startLocation = start; - endLocation = end; + this.start = start; + this.end = end; this.length = length; } public override Activity Tick( Actor self ) { var mobile = self.Trait(); - mobile.PxPosition = length > 1 - ? PPos.Lerp(startLocation, endLocation, ticks, length - 1) - : endLocation; + var pos = length > 1 + ? WPos.Lerp(start, end, ticks, length - 1) + : end; + mobile.PxPosition = PPos.FromWPos(pos); if (++ticks >= length) { mobile.IsMoving = false; @@ -46,7 +46,7 @@ namespace OpenRA.Mods.RA.Move public override IEnumerable GetTargets( Actor self ) { - yield return Target.FromPos(endLocation); + yield return Target.FromPos(PPos.FromWPos(end)); } // Cannot be cancelled diff --git a/OpenRA.Mods.RA/Move/Mobile.cs b/OpenRA.Mods.RA/Move/Mobile.cs index b1c44e96a1..f109367585 100755 --- a/OpenRA.Mods.RA/Move/Mobile.cs +++ b/OpenRA.Mods.RA/Move/Mobile.cs @@ -420,6 +420,11 @@ namespace OpenRA.Mods.RA.Move return (int)(speed / 100); } + public int WorldMovementSpeedForCell(Actor self, CPos cell) + { + return MovementSpeedForCell(self, cell) * 1024 / Game.CellSize; + } + public void AddInfluence() { if (self.IsInWorld) diff --git a/OpenRA.Mods.RA/Production.cs b/OpenRA.Mods.RA/Production.cs index ffdbcf8fdb..d8718b08f9 100755 --- a/OpenRA.Mods.RA/Production.cs +++ b/OpenRA.Mods.RA/Production.cs @@ -50,8 +50,8 @@ namespace OpenRA.Mods.RA public void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo) { var exit = self.Location + exitinfo.ExitCellVector; - var spawn = self.Trait().PxPosition + exitinfo.SpawnOffsetVector; - var to = Util.CenterOfCell(exit); + var spawn = (self.Trait().PxPosition + exitinfo.SpawnOffsetVector).ToWPos(0); + var to = exit.CenterPosition; var fi = producee.Traits.Get(); var initialFacing = exitinfo.Facing < 0 ? Util.GetFacing(to - spawn, fi.GetInitialFacing()) : exitinfo.Facing; @@ -66,7 +66,7 @@ namespace OpenRA.Mods.RA // TODO: Move this into an *Init // TODO: We should be adjusting the actual position for aircraft, not just visuals. var teleportable = newUnit.Trait(); - teleportable.AdjustPxPosition(newUnit, spawn); + teleportable.AdjustPxPosition(newUnit, PPos.FromWPos(spawn)); // TODO: Generalize this for non-mobile (e.g. aircraft) too // Remember to update the Enter activity too @@ -74,7 +74,7 @@ namespace OpenRA.Mods.RA if (mobile != null) { // Animate the spawn -> exit transition - var speed = mobile.MovementSpeedForCell(newUnit, exit); + var speed = mobile.WorldMovementSpeedForCell(newUnit, exit); var length = speed > 0 ? (int)((to - spawn).Length * 3 / speed) : 0; newUnit.QueueActivity(new Drag(spawn, to, length)); } From 7883b1bd7f0361a25a293853392e0ae9d4c65180 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Jul 2013 20:26:09 +1200 Subject: [PATCH 20/30] Convert Combat.DoExplosion to world coords. --- OpenRA.Mods.Cnc/Effects/IonCannon.cs | 2 +- OpenRA.Mods.RA/Air/FallsToEarth.cs | 2 +- OpenRA.Mods.RA/Combat.cs | 12 +++++++----- OpenRA.Mods.RA/Crates/ExplodeCrateAction.cs | 2 +- OpenRA.Mods.RA/Effects/NukeLaunch.cs | 2 +- OpenRA.Mods.RA/Explodes.cs | 6 +----- OpenRA.Mods.RA/Missions/Soviet01ClassicScript.cs | 2 +- 7 files changed, 13 insertions(+), 15 deletions(-) diff --git a/OpenRA.Mods.Cnc/Effects/IonCannon.cs b/OpenRA.Mods.Cnc/Effects/IonCannon.cs index 1fcefdc9b0..c8e8e18e7d 100644 --- a/OpenRA.Mods.Cnc/Effects/IonCannon.cs +++ b/OpenRA.Mods.Cnc/Effects/IonCannon.cs @@ -40,7 +40,7 @@ namespace OpenRA.Mods.Cnc.Effects void Finish(World world) { world.AddFrameEndTask(w => w.Remove(this)); - Combat.DoExplosion(firedBy, "IonCannon", target.CenterLocation, 0); + Combat.DoExplosion(firedBy, "IonCannon", target.CenterPosition); } } } diff --git a/OpenRA.Mods.RA/Air/FallsToEarth.cs b/OpenRA.Mods.RA/Air/FallsToEarth.cs index 678b367874..9f62efcc01 100755 --- a/OpenRA.Mods.RA/Air/FallsToEarth.cs +++ b/OpenRA.Mods.RA/Air/FallsToEarth.cs @@ -50,7 +50,7 @@ namespace OpenRA.Mods.RA.Air if (aircraft.Altitude <= 0) { if (info.Explosion != null) - Combat.DoExplosion(self, info.Explosion, self.CenterLocation, 0); + Combat.DoExplosion(self, info.Explosion, self.CenterPosition); self.Destroy(); return null; diff --git a/OpenRA.Mods.RA/Combat.cs b/OpenRA.Mods.RA/Combat.cs index e912a7cbc4..82190f8310 100755 --- a/OpenRA.Mods.RA/Combat.cs +++ b/OpenRA.Mods.RA/Combat.cs @@ -139,22 +139,24 @@ namespace OpenRA.Mods.RA } } - public static void DoExplosion(Actor attacker, string weapontype, PPos pos, int altitude) + public static void DoExplosion(Actor attacker, string weapontype, WPos pos) { + var pxPos = PPos.FromWPos(pos); + var altitude = pos.Z * Game.CellSize / 1024; var args = new ProjectileArgs { - src = pos, - dest = pos, + src = pxPos, + dest = pxPos, srcAltitude = altitude, destAltitude = altitude, firedBy = attacker, - target = Target.FromPos(pos), + target = Target.FromPos(pxPos), weapon = Rules.Weapons[weapontype.ToLowerInvariant()], facing = 0 }; if (args.weapon.Report != null && args.weapon.Report.Any()) - Sound.Play(args.weapon.Report.Random(attacker.World.SharedRandom), pos); + Sound.Play(args.weapon.Report.Random(attacker.World.SharedRandom), pxPos); DoImpacts(args); } diff --git a/OpenRA.Mods.RA/Crates/ExplodeCrateAction.cs b/OpenRA.Mods.RA/Crates/ExplodeCrateAction.cs index 6924c85f8c..2826a21eb9 100644 --- a/OpenRA.Mods.RA/Crates/ExplodeCrateAction.cs +++ b/OpenRA.Mods.RA/Crates/ExplodeCrateAction.cs @@ -27,7 +27,7 @@ namespace OpenRA.Mods.RA public override void Activate(Actor collector) { - Combat.DoExplosion(self, (info as ExplodeCrateActionInfo).Weapon, collector.CenterLocation, 0); + Combat.DoExplosion(self, (info as ExplodeCrateActionInfo).Weapon, collector.CenterPosition); base.Activate(collector); } } diff --git a/OpenRA.Mods.RA/Effects/NukeLaunch.cs b/OpenRA.Mods.RA/Effects/NukeLaunch.cs index e0c9657f8f..c228048335 100755 --- a/OpenRA.Mods.RA/Effects/NukeLaunch.cs +++ b/OpenRA.Mods.RA/Effects/NukeLaunch.cs @@ -66,7 +66,7 @@ namespace OpenRA.Mods.RA.Effects void Explode(World world) { world.AddFrameEndTask(w => w.Remove(this)); - Combat.DoExplosion(firedBy.PlayerActor, weapon, PPos.FromWPos(pos), pos.Z * Game.CellSize / 1024); + Combat.DoExplosion(firedBy.PlayerActor, weapon, pos); world.WorldActor.Trait().AddEffect(20, PPos.FromWPos(pos).ToFloat2(), 5); foreach (var a in world.ActorsWithTrait()) diff --git a/OpenRA.Mods.RA/Explodes.cs b/OpenRA.Mods.RA/Explodes.cs index 8d23da8c3f..96b2bd1b0a 100644 --- a/OpenRA.Mods.RA/Explodes.cs +++ b/OpenRA.Mods.RA/Explodes.cs @@ -42,11 +42,7 @@ namespace OpenRA.Mods.RA var weapon = ChooseWeaponForExplosion(self); if (weapon != null) - { - var move = self.TraitOrDefault(); - var altitude = move != null ? move.Altitude : 0; - Combat.DoExplosion(e.Attacker, weapon, self.CenterLocation, altitude); - } + Combat.DoExplosion(e.Attacker, weapon, self.CenterPosition); } string ChooseWeaponForExplosion(Actor self) diff --git a/OpenRA.Mods.RA/Missions/Soviet01ClassicScript.cs b/OpenRA.Mods.RA/Missions/Soviet01ClassicScript.cs index 121aebb274..0d1caddd12 100644 --- a/OpenRA.Mods.RA/Missions/Soviet01ClassicScript.cs +++ b/OpenRA.Mods.RA/Missions/Soviet01ClassicScript.cs @@ -128,7 +128,7 @@ namespace OpenRA.Mods.RA.Missions .Where(a => a.HasTrait() && !a.IsDead()) .OrderBy(a => (startJeep.CenterLocation - a.CenterLocation).LengthSquared) .First(); - Combat.DoExplosion(bridge, "Demolish", bridge.CenterLocation, 0); + Combat.DoExplosion(bridge, "Demolish", bridge.CenterPosition); world.WorldActor.Trait().AddEffect(15, bridge.CenterLocation.ToFloat2(), 6); bridge.Kill(bridge); })); From d0bed067657804f6a18259948f120cbd70050971 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Jul 2013 20:36:49 +1200 Subject: [PATCH 21/30] Use WVec overload of Util.GetFacing where possible. --- OpenRA.Game/Traits/Util.cs | 2 +- OpenRA.Mods.RA/Activities/Attack.cs | 2 +- OpenRA.Mods.RA/Air/Fly.cs | 2 +- OpenRA.Mods.RA/Air/HeliAttack.cs | 2 +- OpenRA.Mods.RA/Air/Land.cs | 4 ++-- OpenRA.Mods.RA/Attack/AttackFrontal.cs | 2 +- OpenRA.Mods.RA/Missions/MonsterTankMadnessScript.cs | 4 ++-- OpenRA.Mods.RA/SupportPowers/SpyPlanePower.cs | 2 +- OpenRA.Mods.RA/Turreted.cs | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/OpenRA.Game/Traits/Util.cs b/OpenRA.Game/Traits/Util.cs index c68b0d932e..dc87b9b473 100755 --- a/OpenRA.Game/Traits/Util.cs +++ b/OpenRA.Game/Traits/Util.cs @@ -45,7 +45,7 @@ namespace OpenRA.Traits return GetFacing(d.ToInt2(), currentFacing); } - public static int GetFacing( int2 d, int currentFacing ) + public static int GetFacing(int2 d, int currentFacing) { if (d == int2.Zero) return currentFacing; diff --git a/OpenRA.Mods.RA/Activities/Attack.cs b/OpenRA.Mods.RA/Activities/Attack.cs index 91b52e241a..28d00a3b68 100755 --- a/OpenRA.Mods.RA/Activities/Attack.cs +++ b/OpenRA.Mods.RA/Activities/Attack.cs @@ -73,7 +73,7 @@ namespace OpenRA.Mods.RA.Activities return (AllowMovement) ? Util.SequenceActivities(self.Trait().MoveWithinRange(Target, Range.Range / 1024), this) : NextActivity; } - var desiredFacing = Util.GetFacing(Target.CenterLocation - self.CenterLocation, 0); + var desiredFacing = Util.GetFacing(Target.CenterPosition - self.CenterPosition, 0); var facing = self.Trait(); if (facing.Facing != desiredFacing) return Util.SequenceActivities(new Turn(desiredFacing), this); diff --git a/OpenRA.Mods.RA/Air/Fly.cs b/OpenRA.Mods.RA/Air/Fly.cs index b5a08d103b..09f2ca2d81 100755 --- a/OpenRA.Mods.RA/Air/Fly.cs +++ b/OpenRA.Mods.RA/Air/Fly.cs @@ -35,7 +35,7 @@ namespace OpenRA.Mods.RA.Air var aircraft = self.Trait(); - var desiredFacing = Util.GetFacing(d.ToInt2(), aircraft.Facing); + var desiredFacing = Util.GetFacing(d, aircraft.Facing); if (aircraft.Altitude == cruiseAltitude) aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT); diff --git a/OpenRA.Mods.RA/Air/HeliAttack.cs b/OpenRA.Mods.RA/Air/HeliAttack.cs index 38a8b8ae43..87e3de5eed 100755 --- a/OpenRA.Mods.RA/Air/HeliAttack.cs +++ b/OpenRA.Mods.RA/Air/HeliAttack.cs @@ -38,7 +38,7 @@ namespace OpenRA.Mods.RA.Air } var attack = self.Trait(); - var dist = target.CenterLocation - self.CenterLocation; + var dist = target.CenterPosition - self.CenterPosition; var desiredFacing = Util.GetFacing(dist, aircraft.Facing); aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT); diff --git a/OpenRA.Mods.RA/Air/Land.cs b/OpenRA.Mods.RA/Air/Land.cs index ad028daa55..eb5d41f398 100755 --- a/OpenRA.Mods.RA/Air/Land.cs +++ b/OpenRA.Mods.RA/Air/Land.cs @@ -27,8 +27,8 @@ namespace OpenRA.Mods.RA.Air if (IsCanceled) return NextActivity; - var d = Target.CenterLocation - self.CenterLocation; - if (d.LengthSquared < 50) /* close enough */ + var d = Target.CenterPosition - self.CenterPosition; + if (d.LengthSquared < 256*256) // close enough (1/4 cell) return NextActivity; var aircraft = self.Trait(); diff --git a/OpenRA.Mods.RA/Attack/AttackFrontal.cs b/OpenRA.Mods.RA/Attack/AttackFrontal.cs index c93cffbd2a..4e5abbb442 100644 --- a/OpenRA.Mods.RA/Attack/AttackFrontal.cs +++ b/OpenRA.Mods.RA/Attack/AttackFrontal.cs @@ -34,7 +34,7 @@ namespace OpenRA.Mods.RA return false; var facing = self.Trait().Facing; - var facingToTarget = Util.GetFacing(target.CenterLocation - self.CenterLocation, facing); + var facingToTarget = Util.GetFacing(target.CenterPosition - self.CenterPosition, facing); if (Math.Abs(facingToTarget - facing) % 256 > info.FacingTolerance) return false; diff --git a/OpenRA.Mods.RA/Missions/MonsterTankMadnessScript.cs b/OpenRA.Mods.RA/Missions/MonsterTankMadnessScript.cs index 58d189afee..622ebae34a 100644 --- a/OpenRA.Mods.RA/Missions/MonsterTankMadnessScript.cs +++ b/OpenRA.Mods.RA/Missions/MonsterTankMadnessScript.cs @@ -258,7 +258,7 @@ namespace OpenRA.Mods.RA.Missions { Sound.Play("reinfor1.aud"); foreach (var unit in units) - world.CreateActor(unit, greece, startEntryPoint.Location, Util.GetFacing(startBridgeEndPoint.CenterLocation - startEntryPoint.CenterLocation, 0)) + world.CreateActor(unit, greece, startEntryPoint.Location, Util.GetFacing(startBridgeEndPoint.CenterPosition - startEntryPoint.CenterPosition, 0)) .QueueActivity(new Move.Move(startMovePoint.Location, 0)); } @@ -266,7 +266,7 @@ namespace OpenRA.Mods.RA.Missions { Sound.Play("reinfor1.aud"); foreach (var unit in units) - world.CreateActor(unit, greece, alliedBaseEntryPoint.Location, Util.GetFacing(alliedBaseMovePoint.CenterLocation - alliedBaseEntryPoint.CenterLocation, 0)) + world.CreateActor(unit, greece, alliedBaseEntryPoint.Location, Util.GetFacing(alliedBaseMovePoint.CenterPosition - alliedBaseEntryPoint.CenterPosition, 0)) .QueueActivity(new Move.Move(alliedBaseMovePoint.Location, 0)); } diff --git a/OpenRA.Mods.RA/SupportPowers/SpyPlanePower.cs b/OpenRA.Mods.RA/SupportPowers/SpyPlanePower.cs index 3320fc1d2c..648f1a571a 100755 --- a/OpenRA.Mods.RA/SupportPowers/SpyPlanePower.cs +++ b/OpenRA.Mods.RA/SupportPowers/SpyPlanePower.cs @@ -33,7 +33,7 @@ namespace OpenRA.Mods.RA { new LocationInit( enterCell ), new OwnerInit( self.Owner ), - new FacingInit( Util.GetFacing((order.TargetLocation - enterCell).ToInt2(), 0) ), + new FacingInit( Util.GetFacing(order.TargetLocation - enterCell, 0) ), new AltitudeInit( Rules.Info["u2"].Traits.Get().CruiseAltitude ), }); diff --git a/OpenRA.Mods.RA/Turreted.cs b/OpenRA.Mods.RA/Turreted.cs index d863bf90af..68dc809d55 100755 --- a/OpenRA.Mods.RA/Turreted.cs +++ b/OpenRA.Mods.RA/Turreted.cs @@ -71,7 +71,7 @@ namespace OpenRA.Mods.RA public bool FaceTarget(Actor self, Target target) { - desiredFacing = Util.GetFacing(target.CenterLocation - self.CenterLocation, turretFacing); + desiredFacing = Util.GetFacing(target.CenterPosition - self.CenterPosition, turretFacing); return turretFacing == desiredFacing; } From 89fd889cf4d9f96017c6493717da13853ed0d183 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 7 Jul 2013 10:30:09 +1200 Subject: [PATCH 22/30] Convert Target positions to world coords. --- OpenRA.Game/Traits/Target.cs | 13 +++++++------ OpenRA.Mods.RA/Buildings/Building.cs | 2 +- OpenRA.Mods.RA/Combat.cs | 2 +- OpenRA.Mods.RA/Missions/Allies04Script.cs | 2 +- OpenRA.Mods.RA/Move/Drag.cs | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/OpenRA.Game/Traits/Target.cs b/OpenRA.Game/Traits/Target.cs index 43a8efec68..fa9424d47f 100644 --- a/OpenRA.Game/Traits/Target.cs +++ b/OpenRA.Game/Traits/Target.cs @@ -19,7 +19,7 @@ namespace OpenRA.Traits public static readonly Target[] NoTargets = {}; Actor actor; - PPos pos; + WPos pos; bool valid; int generation; @@ -32,8 +32,9 @@ namespace OpenRA.Traits generation = a.Generation, }; } - public static Target FromPos(PPos p) { return new Target { pos = p, valid = true }; } - public static Target FromCell(CPos c) { return new Target { pos = Util.CenterOfCell(c), valid = true }; } + public static Target FromPos(WPos p) { return new Target { pos = p, valid = true }; } + public static Target FromPos(PPos p) { return new Target { pos = p.ToWPos(0), valid = true }; } + public static Target FromCell(CPos c) { return new Target { pos = c.CenterPosition, valid = true }; } public static Target FromOrder(Order o) { return o.TargetActor != null @@ -44,7 +45,7 @@ namespace OpenRA.Traits public static readonly Target None = new Target(); public bool IsValid { get { return valid && (actor == null || (actor.IsInWorld && !actor.IsDead() && actor.Generation == generation)); } } - public PPos PxPosition { get { return IsActor ? actor.Trait().PxPosition : pos; } } + public PPos PxPosition { get { return IsActor ? actor.Trait().PxPosition : PPos.FromWPos(pos); } } public PPos CenterLocation { get { return PxPosition; } } // Representative position - see Positions for the full set of targetable positions. @@ -55,7 +56,7 @@ namespace OpenRA.Traits if (!IsValid) throw new InvalidOperationException("Attempting to query the position of an invalid Target"); - return actor != null ? actor.CenterPosition : pos.ToWPos(0); + return actor != null ? actor.CenterPosition : pos; } } @@ -69,7 +70,7 @@ namespace OpenRA.Traits return NoPositions; if (actor == null) - return new []{pos.ToWPos(0)}; + return new []{pos}; var targetable = actor.TraitOrDefault(); if (targetable == null) diff --git a/OpenRA.Mods.RA/Buildings/Building.cs b/OpenRA.Mods.RA/Buildings/Building.cs index dbe8fda472..057523555e 100755 --- a/OpenRA.Mods.RA/Buildings/Building.cs +++ b/OpenRA.Mods.RA/Buildings/Building.cs @@ -47,7 +47,7 @@ namespace OpenRA.Mods.RA.Buildings continue; // Range is counted from the center of the actor, not from each cell. - var target = Target.FromPos(bp.Actor.CenterLocation); + var target = Target.FromPos(bp.Actor.CenterPosition); if (target.IsInRange(center, WRange.FromCells(bp.Trait.Info.Range))) return bp.Actor; } diff --git a/OpenRA.Mods.RA/Combat.cs b/OpenRA.Mods.RA/Combat.cs index 82190f8310..390ab54a65 100755 --- a/OpenRA.Mods.RA/Combat.cs +++ b/OpenRA.Mods.RA/Combat.cs @@ -150,7 +150,7 @@ namespace OpenRA.Mods.RA srcAltitude = altitude, destAltitude = altitude, firedBy = attacker, - target = Target.FromPos(pxPos), + target = Target.FromPos(pos), weapon = Rules.Weapons[weapontype.ToLowerInvariant()], facing = 0 }; diff --git a/OpenRA.Mods.RA/Missions/Allies04Script.cs b/OpenRA.Mods.RA/Missions/Allies04Script.cs index d89c7085e2..ba65084906 100644 --- a/OpenRA.Mods.RA/Missions/Allies04Script.cs +++ b/OpenRA.Mods.RA/Missions/Allies04Script.cs @@ -125,7 +125,7 @@ namespace OpenRA.Mods.RA.Missions if (world.FrameNumber == frameInfiltrated + 1500 * 12 && !bridgeTank.IsDead() && bridgeTank.IsInWorld && !bridge.IsDead()) { - bridgeTank.QueueActivity(new Attack(Target.FromPos(bridge.CenterLocation), WRange.FromCells(4))); + bridgeTank.QueueActivity(new Attack(Target.FromPos(bridge.CenterPosition), WRange.FromCells(4))); attackingBridge = true; } if (attackingBridge && bridge.IsDead()) diff --git a/OpenRA.Mods.RA/Move/Drag.cs b/OpenRA.Mods.RA/Move/Drag.cs index abfaf89392..307f71b5ee 100755 --- a/OpenRA.Mods.RA/Move/Drag.cs +++ b/OpenRA.Mods.RA/Move/Drag.cs @@ -46,7 +46,7 @@ namespace OpenRA.Mods.RA.Move public override IEnumerable GetTargets( Actor self ) { - yield return Target.FromPos(PPos.FromWPos(end)); + yield return Target.FromPos(end); } // Cannot be cancelled From 4b1323ada5585b1663e27631a580f2b351ff228c Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 7 Jul 2013 10:47:56 +1200 Subject: [PATCH 23/30] Target cleanup. --- OpenRA.Game/Traits/Target.cs | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/OpenRA.Game/Traits/Target.cs b/OpenRA.Game/Traits/Target.cs index fa9424d47f..9d0466db0f 100644 --- a/OpenRA.Game/Traits/Target.cs +++ b/OpenRA.Game/Traits/Target.cs @@ -17,21 +17,13 @@ namespace OpenRA.Traits public struct Target { public static readonly Target[] NoTargets = {}; + public static readonly Target None = new Target(); Actor actor; WPos pos; bool valid; int generation; - public static Target FromActor(Actor a) - { - return new Target - { - actor = a, - valid = (a != null), - generation = a.Generation, - }; - } public static Target FromPos(WPos p) { return new Target { pos = p, valid = true }; } public static Target FromPos(PPos p) { return new Target { pos = p.ToWPos(0), valid = true }; } public static Target FromCell(CPos c) { return new Target { pos = c.CenterPosition, valid = true }; } @@ -42,11 +34,23 @@ namespace OpenRA.Traits : Target.FromCell(o.TargetLocation); } - public static readonly Target None = new Target(); + public static Target FromActor(Actor a) + { + return new Target + { + actor = a, + valid = (a != null), + generation = a.Generation, + }; + } public bool IsValid { get { return valid && (actor == null || (actor.IsInWorld && !actor.IsDead() && actor.Generation == generation)); } } public PPos PxPosition { get { return IsActor ? actor.Trait().PxPosition : PPos.FromWPos(pos); } } public PPos CenterLocation { get { return PxPosition; } } + public Actor Actor { get { return IsActor ? actor : null; } } + + // TODO: This should return true even if the actor is destroyed + public bool IsActor { get { return actor != null && !actor.Destroyed; } } // Representative position - see Positions for the full set of targetable positions. public WPos CenterPosition @@ -90,7 +94,5 @@ namespace OpenRA.Traits (t.Y - origin.Y)*(t.Y - origin.Y) <= range.Range*range.Range); } - public Actor Actor { get { return IsActor ? actor : null; } } - public bool IsActor { get { return actor != null && !actor.Destroyed; } } } } From 87361df0433a8cb0b1fa73c3fdb6f18047db61f2 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 7 Jul 2013 10:48:29 +1200 Subject: [PATCH 24/30] Centralize weapon validity check into WeaponInfo. --- OpenRA.Game/GameRules/WeaponInfo.cs | 32 +++++++++++++++++++++++++++++ OpenRA.Mods.RA/Armament.cs | 10 +-------- OpenRA.Mods.RA/Attack/AttackBase.cs | 4 ++-- OpenRA.Mods.RA/Combat.cs | 22 ++------------------ 4 files changed, 37 insertions(+), 31 deletions(-) diff --git a/OpenRA.Game/GameRules/WeaponInfo.cs b/OpenRA.Game/GameRules/WeaponInfo.cs index a6a65ffd75..2c98c65d8c 100644 --- a/OpenRA.Game/GameRules/WeaponInfo.cs +++ b/OpenRA.Game/GameRules/WeaponInfo.cs @@ -137,5 +137,37 @@ namespace OpenRA.GameRules return ret; } + + public bool IsValidAgainst(Actor a) + { + var targetable = a.TraitOrDefault(); + if (targetable == null || !ValidTargets.Intersect(targetable.TargetTypes).Any()) + return false; + + if (Warheads.All(w => w.EffectivenessAgainst(a) <= 0)) + return false; + + return true; + } + + public bool IsValidAgainst(Target target, World world) + { + if (!target.IsValid) + return false; + + if (target.IsActor) + return IsValidAgainst(target.Actor); + else + { + var cell = target.CenterPosition.ToCPos(); + if (ValidTargets.Contains("Ground") && world.GetTerrainType(cell) != "Water") + return true; + + if (ValidTargets.Contains("Water") && world.GetTerrainType(cell) == "Water") + return true; + + return false; + } + } } } diff --git a/OpenRA.Mods.RA/Armament.cs b/OpenRA.Mods.RA/Armament.cs index eae3275e4d..7ec683ac00 100755 --- a/OpenRA.Mods.RA/Armament.cs +++ b/OpenRA.Mods.RA/Armament.cs @@ -116,7 +116,7 @@ namespace OpenRA.Mods.RA if (target.IsInRange(self.CenterPosition, minRange)) return; - if (!IsValidAgainst(self.World, target)) + if (!Weapon.IsValidAgainst(target, self.World)) return; var barrel = Barrels[Burst % Barrels.Length]; @@ -172,14 +172,6 @@ namespace OpenRA.Mods.RA } } - public bool IsValidAgainst(World world, Target target) - { - if (target.IsActor) - return Combat.WeaponValidForTarget(Weapon, target.Actor); - else - return Combat.WeaponValidForTarget(Weapon, world, target.CenterPosition.ToCPos()); - } - public bool IsReloading { get { return FireDelay > 0; } } public WVec MuzzleOffset(Actor self, Barrel b) diff --git a/OpenRA.Mods.RA/Attack/AttackBase.cs b/OpenRA.Mods.RA/Attack/AttackBase.cs index 65641fd8ca..c8263c6dec 100644 --- a/OpenRA.Mods.RA/Attack/AttackBase.cs +++ b/OpenRA.Mods.RA/Attack/AttackBase.cs @@ -139,10 +139,10 @@ namespace OpenRA.Mods.RA public abstract Activity GetAttackActivity(Actor self, Target newTarget, bool allowMove); - public bool HasAnyValidWeapons(Target t) { return Armaments.Any(a => a.IsValidAgainst(self.World, t)); } + public bool HasAnyValidWeapons(Target t) { return Armaments.Any(a => a.Weapon.IsValidAgainst(t, self.World)); } public WRange GetMaximumRange() { return new WRange((int)(1024*Armaments.Max(a => a.Weapon.Range))); } - public Armament ChooseArmamentForTarget(Target t) { return Armaments.FirstOrDefault(a => a.IsValidAgainst(self.World, t)); } + public Armament ChooseArmamentForTarget(Target t) { return Armaments.FirstOrDefault(a => a.Weapon.IsValidAgainst(t, self.World)); } public void AttackTarget(Target target, bool queued, bool allowMove) { diff --git a/OpenRA.Mods.RA/Combat.cs b/OpenRA.Mods.RA/Combat.cs index 390ab54a65..c0d4de1ed0 100755 --- a/OpenRA.Mods.RA/Combat.cs +++ b/OpenRA.Mods.RA/Combat.cs @@ -178,7 +178,8 @@ namespace OpenRA.Mods.RA static float GetDamageToInflict(Actor target, ProjectileArgs args, WarheadInfo warhead, float modifier) { // don't hit air units with splash from ground explosions, etc - if (!WeaponValidForTarget(args.weapon, target)) return 0f; + if (!args.weapon.IsValidAgainst(target)) + return 0f; var health = target.Info.Traits.GetOrDefault(); if( health == null ) return 0f; @@ -190,24 +191,5 @@ namespace OpenRA.Mods.RA return (float)(rawDamage * multiplier); } - - public static bool WeaponValidForTarget(WeaponInfo weapon, Actor target) - { - var targetable = target.TraitOrDefault(); - if (targetable == null || !weapon.ValidTargets.Intersect(targetable.TargetTypes).Any()) - return false; - - if (weapon.Warheads.All( w => w.EffectivenessAgainst(target) <= 0)) - return false; - - return true; - } - - public static bool WeaponValidForTarget(WeaponInfo weapon, World world, CPos location) - { - if (weapon.ValidTargets.Contains("Ground") && world.GetTerrainType(location) != "Water") return true; - if (weapon.ValidTargets.Contains("Water") && world.GetTerrainType(location) == "Water") return true; - return false; - } } } From 8fe0eb73e257b18809e5834439cd47f77542157b Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 7 Jul 2013 11:14:25 +1200 Subject: [PATCH 25/30] Ensure a valid target in move. --- OpenRA.Mods.RA/Move/Move.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/OpenRA.Mods.RA/Move/Move.cs b/OpenRA.Mods.RA/Move/Move.cs index 097e1ab51f..5e5cec526b 100755 --- a/OpenRA.Mods.RA/Move/Move.cs +++ b/OpenRA.Mods.RA/Move/Move.cs @@ -58,11 +58,18 @@ namespace OpenRA.Mods.RA.Move this.ignoreBuilding = ignoreBuilding; } + static readonly List NoPath = new List(); public Move(Target target, int range) { - this.getPath = (self,mobile) => self.World.WorldActor.Trait().FindUnitPathToRange( - mobile.toCell, target.CenterPosition.ToCPos(), - range, self); + this.getPath = (self, mobile) => + { + if (!target.IsValid) + return NoPath; + + return self.World.WorldActor.Trait().FindUnitPathToRange( + mobile.toCell, target.CenterPosition.ToCPos(), range, self); + }; + this.destination = null; this.nearEnough = range; } From 01de84e9fca196216656bb2857f510608795e542 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 7 Jul 2013 11:14:41 +1200 Subject: [PATCH 26/30] Ensure valid targets in Selectable. --- OpenRA.Game/Traits/Selectable.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenRA.Game/Traits/Selectable.cs b/OpenRA.Game/Traits/Selectable.cs index b2a4ffe058..2a8f95f485 100644 --- a/OpenRA.Game/Traits/Selectable.cs +++ b/OpenRA.Game/Traits/Selectable.cs @@ -161,7 +161,7 @@ namespace OpenRA.Traits var c = Color.Green; var wlr = Game.Renderer.WorldLineRenderer; - foreach (var stp in targets.Select(p => wr.ScreenPxPosition(p.CenterPosition))) + foreach (var stp in targets.Where(t => t.IsValid).Select(p => wr.ScreenPxPosition(p.CenterPosition))) { wlr.DrawLine(stp + new float2(-1, -1), stp + new float2(-1, 1), c, c); wlr.DrawLine(stp + new float2(-1, 1), stp + new float2(1, 1), c, c); From 1e7f1ab225dd8fe2dfbfa983603df18fd80253d9 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Jul 2013 21:44:39 +1200 Subject: [PATCH 27/30] Convert Explosion to world coords. --- OpenRA.Mods.RA/Combat.cs | 2 +- OpenRA.Mods.RA/Effects/Explosion.cs | 16 +++++----------- OpenRA.Mods.RA/Render/WithBuildingExplosion.cs | 2 +- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/OpenRA.Mods.RA/Combat.cs b/OpenRA.Mods.RA/Combat.cs index c0d4de1ed0..c65c21837a 100755 --- a/OpenRA.Mods.RA/Combat.cs +++ b/OpenRA.Mods.RA/Combat.cs @@ -45,7 +45,7 @@ namespace OpenRA.Mods.RA if (explosionType != null) world.AddFrameEndTask( - w => w.Add(new Explosion(w, args.dest, explosionType, isWater, args.destAltitude))); + w => w.Add(new Explosion(w, args.dest.ToWPos(args.destAltitude), explosionType))); Sound.Play(GetImpactSound(warhead, isWater), args.dest); diff --git a/OpenRA.Mods.RA/Effects/Explosion.cs b/OpenRA.Mods.RA/Effects/Explosion.cs index 7463e3c2ce..0a8e953e21 100644 --- a/OpenRA.Mods.RA/Effects/Explosion.cs +++ b/OpenRA.Mods.RA/Effects/Explosion.cs @@ -18,26 +18,20 @@ namespace OpenRA.Mods.RA.Effects public class Explosion : IEffect { Animation anim; - PPos pos; - int altitude; + WPos pos; - public Explosion(World world, PPos pixelPos, string style, bool isWater, int altitude) + public Explosion(World world, WPos pos, string style) { - this.pos = pixelPos; - this.altitude = altitude; + this.pos = pos; anim = new Animation("explosion"); - anim.PlayThen(style, - () => world.AddFrameEndTask(w => w.Remove(this))); + anim.PlayThen(style, () => world.AddFrameEndTask(w => w.Remove(this))); } public void Tick( World world ) { anim.Tick(); } public IEnumerable Render(WorldRenderer wr) { - var p = pos.ToInt2() - new int2(0, altitude); - yield return new SpriteRenderable(anim.Image, p, wr.Palette("effect"), p.Y); + yield return new SpriteRenderable(anim.Image, pos, 0, wr.Palette("effect"), 1f); } - - public Player Owner { get { return null; } } } } diff --git a/OpenRA.Mods.RA/Render/WithBuildingExplosion.cs b/OpenRA.Mods.RA/Render/WithBuildingExplosion.cs index 0a2eb2a6a9..2ca9291cac 100755 --- a/OpenRA.Mods.RA/Render/WithBuildingExplosion.cs +++ b/OpenRA.Mods.RA/Render/WithBuildingExplosion.cs @@ -22,7 +22,7 @@ namespace OpenRA.Mods.RA.Render var bi = self.Info.Traits.Get(); FootprintUtils.UnpathableTiles(self.Info.Name, bi, self.Location).Do( t => self.World.AddFrameEndTask( - w => w.Add(new Explosion(w, Traits.Util.CenterOfCell(t), "building", false, 0)))); + w => w.Add(new Explosion(w, t.CenterPosition, "building")))); } } } From 5976913c73c1f371cde4cb4d102ca1389a1fa8ba Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 7 Jul 2013 12:49:43 +1200 Subject: [PATCH 28/30] Add WPos/WVec.LerpQuadratic to simplify ballistic calculations. --- OpenRA.FileFormats/WPos.cs | 14 ++++++++++++++ OpenRA.FileFormats/WVec.cs | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/OpenRA.FileFormats/WPos.cs b/OpenRA.FileFormats/WPos.cs index 25f76bef65..32ec012970 100644 --- a/OpenRA.FileFormats/WPos.cs +++ b/OpenRA.FileFormats/WPos.cs @@ -36,6 +36,20 @@ namespace OpenRA public static WPos Lerp(WPos a, WPos b, int mul, int div) { return a + (b - a) * mul / div; } + public static WPos LerpQuadratic(WPos a, WPos b, WAngle pitch, int mul, int div) + { + // Start with a linear lerp between the points + var ret = Lerp(a, b, mul, div); + + if (pitch.Angle == 0) + return ret; + + // Add an additional quadratic variation to height + // Uses fp to avoid integer overflow + var offset = (int)((float)((float)(b - a).Length*pitch.Tan()*mul*(div - mul)) / (float)(1024*div*div)); + return new WPos(ret.X, ret.Y, ret.Z + offset); + } + public static WPos Average(params WPos[] list) { if (list == null || list.Length == 0) diff --git a/OpenRA.FileFormats/WVec.cs b/OpenRA.FileFormats/WVec.cs index 4eab6e15d1..7b450d9d57 100644 --- a/OpenRA.FileFormats/WVec.cs +++ b/OpenRA.FileFormats/WVec.cs @@ -53,6 +53,20 @@ namespace OpenRA public static WVec Lerp(WVec a, WVec b, int mul, int div) { return a + (b - a) * mul / div; } + public static WVec LerpQuadratic(WVec a, WVec b, WAngle pitch, int mul, int div) + { + // Start with a linear lerp between the points + var ret = Lerp(a, b, mul, div); + + if (pitch.Angle == 0) + return ret; + + // Add an additional quadratic variation to height + // Uses fp to avoid integer overflow + var offset = (int)((float)((float)(b - a).Length*pitch.Tan()*mul*(div - mul)) / (float)(1024*div*div)); + return new WVec(ret.X, ret.Y, ret.Z + offset); + } + public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode() ^ Z.GetHashCode(); } public override bool Equals(object obj) From 4fbed810dcba2538400a46bb0ae7d891a278aa36 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 7 Jul 2013 13:13:36 +1200 Subject: [PATCH 29/30] Redo husk particle physics using LerpQuadratic. --- OpenRA.Mods.RA/ThrowsParticle.cs | 37 +++++++++++++++++--------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/OpenRA.Mods.RA/ThrowsParticle.cs b/OpenRA.Mods.RA/ThrowsParticle.cs index 076000e37f..7f7360d264 100644 --- a/OpenRA.Mods.RA/ThrowsParticle.cs +++ b/OpenRA.Mods.RA/ThrowsParticle.cs @@ -22,14 +22,20 @@ namespace OpenRA.Mods.RA [Desc("Initial position relative to body")] public readonly WVec Offset = WVec.Zero; + [Desc("Minimum distance to throw the particle")] + public readonly WRange MinThrowRange = new WRange(256); + [Desc("Maximum distance to throw the particle")] - public readonly WRange ThrowRange = new WRange(768); + public readonly WRange MaxThrowRange = new WRange(768); - [Desc("Maximum height to throw the particle")] - public readonly WRange ThrowHeight = new WRange(256); + [Desc("Minimum angle to throw the particle")] + public readonly WAngle MinThrowAngle = WAngle.FromDegrees(30); - [Desc("Number of ticks to animate")] - public readonly int Length = 15; + [Desc("Maximum angle to throw the particle")] + public readonly WAngle MaxThrowAngle = WAngle.FromDegrees(60); + + [Desc("Speed to throw the particle (horizontal WPos/tick)")] + public readonly int Velocity = 75; [Desc("Maximum rotation rate")] public readonly float ROT = 15; @@ -39,19 +45,19 @@ namespace OpenRA.Mods.RA class ThrowsParticle : ITick { - ThrowsParticleInfo info; WVec pos; WVec initialPos; WVec finalPos; + WAngle angle; + int tick = 0; + int length; float facing; float rotation; public ThrowsParticle(ActorInitializer init, ThrowsParticleInfo info) { - this.info = info; - var self = init.self; var rs = self.Trait(); var body = self.Trait(); @@ -62,10 +68,12 @@ namespace OpenRA.Mods.RA // Calculate final position var throwRotation = WRot.FromFacing(Game.CosmeticRandom.Next(1024)); - var throwOffset = new WVec((int)(Game.CosmeticRandom.Gauss1D(1)*info.ThrowRange.Range), 0, 0).Rotate(throwRotation); + var throwDistance = Game.CosmeticRandom.Next(info.MinThrowRange.Range, info.MaxThrowRange.Range); initialPos = pos = info.Offset.Rotate(body.QuantizeOrientation(self, WRot.FromFacing(bodyFacing))); - finalPos = initialPos + throwOffset; + finalPos = initialPos + new WVec(throwDistance, 0, 0).Rotate(throwRotation); + angle = new WAngle(Game.CosmeticRandom.Next(info.MinThrowAngle.Angle, info.MaxThrowAngle.Angle)); + length = (finalPos - initialPos).Length / info.Velocity; // Facing rotation rotation = Game.CosmeticRandom.Gauss1D(2) * info.ROT; @@ -77,15 +85,10 @@ namespace OpenRA.Mods.RA public void Tick(Actor self) { - if (tick == info.Length) + if (tick == length) return; - tick++; - // Lerp position horizontally and height along a sinusoid using a cubic ease - var t = (tick*tick*tick / (info.Length*info.Length) - 3*tick*tick / info.Length + 3*tick); - var tp = WVec.Lerp(initialPos, finalPos, t, info.Length); - var th = new WAngle(512*(info.Length - t) / info.Length).Sin()*info.ThrowHeight.Range / 1024; - pos = new WVec(tp.X, tp.Y, th); + pos = WVec.LerpQuadratic(initialPos, finalPos, angle, tick++, length); // Spin the particle facing += rotation; From 2cff2d8bbed827723b804458777543a5bfc3733a Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 8 Jul 2013 22:10:05 +1200 Subject: [PATCH 30/30] Improve Leap behavior: * Configurable jump speed. * Configurable jump angle. * Configurable attack sound (uses weapon report). * Don't accidentally eat tanks. --- OpenRA.Mods.RA/Activities/Leap.cs | 45 +++++++++++++++++------------ OpenRA.Mods.RA/Attack/AttackLeap.cs | 16 ++++++++-- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/OpenRA.Mods.RA/Activities/Leap.cs b/OpenRA.Mods.RA/Activities/Leap.cs index 64898fa68b..289e87e379 100644 --- a/OpenRA.Mods.RA/Activities/Leap.cs +++ b/OpenRA.Mods.RA/Activities/Leap.cs @@ -10,6 +10,7 @@ using System; using System.Linq; +using OpenRA.GameRules; using OpenRA.Mods.RA.Move; using OpenRA.Mods.RA.Render; using OpenRA.Traits; @@ -19,47 +20,53 @@ namespace OpenRA.Mods.RA.Activities class Leap : Activity { Mobile mobile; + WeaponInfo weapon; - PPos from; - PPos to; + WPos from; + WPos to; + int ticks; + int length; + WAngle angle; - int moveFraction; - const int length = 6; - - public Leap(Actor self, Target target) + public Leap(Actor self, Actor target, WeaponInfo weapon, WRange speed, WAngle angle) { - if (!target.IsActor) - throw new InvalidOperationException("Leap requires a target actor"); - - var targetMobile = target.Actor.TraitOrDefault(); + var targetMobile = target.TraitOrDefault(); if (targetMobile == null) throw new InvalidOperationException("Leap requires a target actor with the Mobile trait"); + this.weapon = weapon; + this.angle = angle; mobile = self.Trait(); mobile.SetLocation(mobile.fromCell, mobile.fromSubCell, targetMobile.fromCell, targetMobile.fromSubCell); mobile.IsMoving = true; - from = self.CenterLocation; - to = Util.CenterOfCell(targetMobile.fromCell) + MobileInfo.SubCellOffsets[targetMobile.fromSubCell]; + from = self.CenterPosition; + var offset = MobileInfo.SubCellOffsets[targetMobile.fromSubCell]; + to = targetMobile.fromCell.CenterPosition + new WVec(offset.X * 1024 / Game.CellSize, offset.Y * 1024 / Game.CellSize, 0); + length = Math.Max((to - from).Length / speed.Range, 1); - self.Trait().Attacking(self, target); - Sound.Play("dogg5p.aud", self.CenterLocation); + self.Trait().Attacking(self, Target.FromActor(target)); + + if (weapon.Report != null && weapon.Report.Any()) + Sound.Play(weapon.Report.Random(self.World.SharedRandom), self.CenterLocation); } public override Activity Tick(Actor self) { - if (moveFraction == 0 && IsCanceled) + if (ticks == 0 && IsCanceled) return NextActivity; - mobile.AdjustPxPosition(self, PPos.Lerp(from, to, moveFraction++, length - 1)); - if (moveFraction >= length) + mobile.AdjustPxPosition(self, PPos.FromWPosHackZ(WPos.LerpQuadratic(from, to, angle, ++ticks, length))); + if (ticks >= length) { mobile.SetLocation(mobile.toCell, mobile.toSubCell, mobile.toCell, mobile.toSubCell); mobile.FinishedMoving(self); mobile.IsMoving = false; - // Kill whatever else is in our new cell - self.World.ActorMap.GetUnitsAt(mobile.toCell, mobile.toSubCell).Except(new []{self}).Do(a => a.Kill(self)); + self.World.ActorMap.GetUnitsAt(mobile.toCell, mobile.toSubCell) + .Except(new []{self}).Where(t => weapon.IsValidAgainst(t)) + .Do(t => t.Kill(self)); + return NextActivity; } diff --git a/OpenRA.Mods.RA/Attack/AttackLeap.cs b/OpenRA.Mods.RA/Attack/AttackLeap.cs index 0dbf477093..75683b1673 100644 --- a/OpenRA.Mods.RA/Attack/AttackLeap.cs +++ b/OpenRA.Mods.RA/Attack/AttackLeap.cs @@ -10,6 +10,7 @@ using System; using System.Linq; +using OpenRA.FileFormats; using OpenRA.Mods.RA.Activities; using OpenRA.Traits; @@ -17,17 +18,26 @@ namespace OpenRA.Mods.RA { class AttackLeapInfo : AttackFrontalInfo { + [Desc("Leap speed (in units/tick).")] + public readonly WRange Speed = new WRange(426); + public readonly WAngle Angle = WAngle.FromDegrees(20); + public override object Create(ActorInitializer init) { return new AttackLeap(init.self, this); } } class AttackLeap : AttackFrontal, ISync { + AttackLeapInfo info; + public AttackLeap(Actor self, AttackLeapInfo info) - : base(self, info) {} + : base(self, info) + { + this.info = info; + } public override void DoAttack(Actor self, Target target) { - if (!CanAttack(self, target)) + if (!CanAttack(self, target) || !target.IsActor) return; var a = ChooseArmamentForTarget(target); @@ -40,7 +50,7 @@ namespace OpenRA.Mods.RA return; self.CancelActivity(); - self.QueueActivity(new Leap(self, target)); + self.QueueActivity(new Leap(self, target.Actor, a.Weapon, info.Speed, info.Angle)); } } }