From fa245aaa0875c25781f622ad9fee82dfb077ad6a Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Sat, 31 Jul 2010 22:19:29 +1200 Subject: [PATCH] introduce collection of Turrets on AttackBase, too -- turret sharing w/ recoil works again --- OpenRA.Mods.RA/AttackBase.cs | 67 +++++++++++++-------- OpenRA.Mods.RA/Combat.cs | 13 ++++ OpenRA.Mods.RA/Render/RenderUnitTurreted.cs | 37 ++++++------ 3 files changed, 72 insertions(+), 45 deletions(-) diff --git a/OpenRA.Mods.RA/AttackBase.cs b/OpenRA.Mods.RA/AttackBase.cs index 8f4dc595a9..70a46654e5 100644 --- a/OpenRA.Mods.RA/AttackBase.cs +++ b/OpenRA.Mods.RA/AttackBase.cs @@ -37,22 +37,33 @@ namespace OpenRA.Mods.RA } public class Barrel { public int2 Position; public int Facing; /* relative to turret */ } + public class Turret + { + public float Recoil = 0.0f; // remaining recoil fraction + public int2 UnitSpacePosition; // where, in the unit's local space. + public int2 ScreenSpacePosition; // screen-space hack to make things line up good. + + public Turret(int[] offset) + { + ScreenSpacePosition = offset.AbsOffset().ToInt2(); + UnitSpacePosition = offset.RelOffset().ToInt2(); + } + } public class Weapon { public WeaponInfo Info; public int FireDelay = 0; // time (in frames) until the weapon can fire again public int Burst = 0; // burst counter - public float Recoil = 0.0f; // remaining recoil fraction - public int[] Offset; - public Barrel[] Barrels; + public Barrel[] Barrels; // where projectiles are spawned, in local turret space. + public Turret Turret; // where this weapon is mounted - public Weapon(string weaponName, int[] offset, int[] localOffset) + public Weapon(string weaponName, Turret turret, int[] localOffset) { Info = Rules.Weapons[weaponName.ToLowerInvariant()]; Burst = Info.Burst; - Offset = offset; + Turret = turret; var barrels = new List(); for (var i = 0; i < localOffset.Length / 3; i++) @@ -74,13 +85,26 @@ namespace OpenRA.Mods.RA public void Tick() { if (FireDelay > 0) --FireDelay; - Recoil = Math.Max(0f, Recoil - .2f); + Turret.Recoil = Math.Max(0f, Turret.Recoil - .2f); } public bool IsValidAgainst(Target target) { return Combat.WeaponValidForTarget(Info, target); } + + public void FiredShot() + { + Turret.Recoil = 1; + + if (--Burst > 0) + FireDelay = Info.BurstDelay; + else + { + FireDelay = Info.ROF; + Burst = Info.Burst; + } + } } public class AttackBase : IIssueOrder, IResolveOrder, ITick, IExplodeModifier, IOrderCursor, IOrderVoice @@ -88,18 +112,23 @@ namespace OpenRA.Mods.RA public Target target; public List Weapons = new List(); + public List Turrets = new List(); public AttackBase(Actor self) { var info = self.Info.Traits.Get(); + Turrets.Add(new Turret(info.PrimaryOffset)); + if (info.SecondaryOffset != null) + Turrets.Add(new Turret(info.SecondaryOffset)); + if (info.PrimaryWeapon != null) Weapons.Add(new Weapon(info.PrimaryWeapon, - info.PrimaryOffset, info.PrimaryLocalOffset)); + Turrets[0], info.PrimaryLocalOffset)); if (info.SecondaryWeapon != null) Weapons.Add(new Weapon(info.SecondaryWeapon, - info.SecondaryOffset ?? info.PrimaryOffset, info.SecondaryLocalOffset)); + info.SecondaryOffset != null ? Turrets[1] : Turrets[0], info.SecondaryLocalOffset)); } protected virtual bool CanAttack(Actor self) @@ -149,7 +178,7 @@ namespace OpenRA.Mods.RA foreach (var w in Weapons) if (CheckFire(self, unit, w)) - w.Recoil = 1; + w.FiredShot(); } bool CheckFire(Actor self, Unit unit, Weapon w) @@ -168,18 +197,10 @@ namespace OpenRA.Mods.RA var barrel = w.Barrels[w.Burst % w.Barrels.Length]; var fireOffset = new[] { - w.Offset.ElementAtOrDefault(0) + barrel.Position.X, - w.Offset.ElementAtOrDefault(1) + barrel.Position.Y, - w.Offset.ElementAtOrDefault(2), - w.Offset.ElementAtOrDefault(3) }; - - if (--w.Burst > 0) - w.FireDelay = w.Info.BurstDelay; - else - { - w.FireDelay = w.Info.ROF; - w.Burst = w.Info.Burst; - } + w.Turret.UnitSpacePosition.X + barrel.Position.X, + w.Turret.UnitSpacePosition.Y + barrel.Position.Y, + w.Turret.ScreenSpacePosition.X, + w.Turret.ScreenSpacePosition.Y }; // todo: retardage. var destUnit = target.IsActor ? target.Actor.traits.GetOrDefault() : null; @@ -310,10 +331,6 @@ namespace OpenRA.Mods.RA Math.Max(0, (int)weapon.Info.Range))); } - /* temp hack */ - public float GetPrimaryRecoil() { return Weapons.Count > 0 ? Weapons[0].Recoil : 0; } - public float GetSecondaryRecoil() { return Weapons.Count > 1 ? Weapons[1].Recoil : 0; } - public bool HasAnyValidWeapons(Target t) { return Weapons.Any(w => w.IsValidAgainst(t)); } public float GetMaximumRange() { return Weapons.Max(w => w.Info.Range); } diff --git a/OpenRA.Mods.RA/Combat.cs b/OpenRA.Mods.RA/Combat.cs index 768635b3dd..bceed36e2b 100755 --- a/OpenRA.Mods.RA/Combat.cs +++ b/OpenRA.Mods.RA/Combat.cs @@ -202,5 +202,18 @@ namespace OpenRA.Mods.RA return (Util.RotateVectorByFacing(offset.RelOffset(), quantizedFacing, .7f) + GetRecoil(self, recoil)) + offset.AbsOffset(); } + + public static float2 GetTurretPosition(Actor self, Unit unit, Turret turret) + { + if (unit == null) return turret.ScreenSpacePosition; + + var ru = self.traits.GetOrDefault(); + var numDirs = (ru != null) ? ru.anim.CurrentSequence.Facings : 8; + var bodyFacing = unit.Facing; + var quantizedFacing = Util.QuantizeFacing(bodyFacing, numDirs) * (256 / numDirs); + + return (Util.RotateVectorByFacing(turret.UnitSpacePosition, quantizedFacing, .7f) + GetRecoil(self, turret.Recoil)) + + turret.ScreenSpacePosition; + } } } diff --git a/OpenRA.Mods.RA/Render/RenderUnitTurreted.cs b/OpenRA.Mods.RA/Render/RenderUnitTurreted.cs index 3319440a91..d0b78d0fe0 100755 --- a/OpenRA.Mods.RA/Render/RenderUnitTurreted.cs +++ b/OpenRA.Mods.RA/Render/RenderUnitTurreted.cs @@ -31,27 +31,24 @@ namespace OpenRA.Mods.RA.Render var turretAnim = new Animation(GetImage(self), () => turreted.turretFacing ); turretAnim.Play( "turret" ); - if( attackInfo.PrimaryOffset != null ) - anims.Add("turret_1", new AnimationWithOffset( - turretAnim, - () => Combat.GetTurretPosition(self, unit, attackInfo.PrimaryOffset, attack.GetPrimaryRecoil()), - null) { ZOffset = 1 }); - - if (attackInfo.SecondaryOffset != null) - anims.Add("turret_2", new AnimationWithOffset( - turretAnim, - () => Combat.GetTurretPosition(self, unit, attackInfo.SecondaryOffset, attack.GetSecondaryRecoil()), - null) { ZOffset = 1 }); - - if( attackInfo.MuzzleFlash ) + for( var i = 0; i < attack.Turrets.Count; i++ ) { - var muzzleFlash = new Animation( GetImage(self), () => self.traits.Get().turretFacing ); - muzzleFlash.PlayFetchIndex( "muzzle", - () => (int)(attack.GetPrimaryRecoil() * 5.9f)); /* hack: recoil can be 1.0f, but don't overflow into next anim */ - anims.Add( "muzzle_flash", new AnimationWithOffset( - muzzleFlash, - () => Combat.GetTurretPosition(self, unit, attackInfo.PrimaryOffset, attack.GetPrimaryRecoil()), - () => attack.GetPrimaryRecoil() <= 0)); + var turret = attack.Turrets[i]; + anims.Add( "turret_{0}".F(i), + new AnimationWithOffset( turretAnim, + () => Combat.GetTurretPosition( self, unit, turret ), + null) { ZOffset = 1 }); + + if (attackInfo.MuzzleFlash) + { + var muzzleFlash = new Animation(GetImage(self), () => turreted.turretFacing); + muzzleFlash.PlayFetchIndex("muzzle", + () => (int)(turret.Recoil * 5.9f)); /* hack: dumb crap */ + anims.Add("muzzle_flash_{0}".F(i), + new AnimationWithOffset(muzzleFlash, + () => Combat.GetTurretPosition(self, unit, turret), + () => turret.Recoil <= 0)); + } } } }