diff --git a/OpenRa.Game/MainWindow.cs b/OpenRa.Game/MainWindow.cs index 14086e2779..92b4f4067f 100755 --- a/OpenRa.Game/MainWindow.cs +++ b/OpenRa.Game/MainWindow.cs @@ -63,6 +63,7 @@ namespace OpenRa.Game Game.world.Add( new Actor( "mcv", Game.map.Offset + new int2( 9, 5 ), Game.players[ 0 ] ) ); Game.world.Add( new Actor( "jeep", Game.map.Offset + new int2( 9, 14 ), Game.players[ 1 ] ) ); Game.world.Add( new Actor( "3tnk", Game.map.Offset + new int2( 12, 7 ), Game.players[ 1 ] ) ); + Game.world.Add(new Actor("apc", Game.map.Offset + new int2(13, 7), Game.players[1])); Game.world.Add(new Actor("ca", Game.map.Offset + new int2(40, 7), Game.players[1])); Game.world.Add(new Actor("e1", Game.map.Offset + new int2(9, 13), Game.players[1])); Game.world.Add(new Actor("arty", Game.map.Offset + new int2(10, 13), Game.players[1])); diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj index f601117070..5cd94575af 100644 --- a/OpenRa.Game/OpenRa.Game.csproj +++ b/OpenRa.Game/OpenRa.Game.csproj @@ -153,6 +153,7 @@ + diff --git a/OpenRa.Game/Traits/AttackTurreted.cs b/OpenRa.Game/Traits/AttackTurreted.cs index 0dda1090c1..e79f5ddc28 100755 --- a/OpenRa.Game/Traits/AttackTurreted.cs +++ b/OpenRa.Game/Traits/AttackTurreted.cs @@ -13,6 +13,8 @@ namespace OpenRa.Game.Traits protected int primaryFireDelay = 0; protected int secondaryFireDelay = 0; + public float primaryRecoil = 0.0f, secondaryRecoil = 0.0f; + public AttackBase(Actor self) { } protected bool CanAttack( Actor self ) @@ -25,6 +27,9 @@ namespace OpenRa.Game.Traits if (primaryFireDelay > 0) --primaryFireDelay; if (secondaryFireDelay > 0) --secondaryFireDelay; + primaryRecoil = Math.Max(0f, primaryRecoil - .2f); + secondaryRecoil = Math.Max(0f, secondaryRecoil - .2f); + if (target != null && target.IsDead) target = null; /* he's dead, jim. */ } @@ -36,20 +41,15 @@ namespace OpenRa.Game.Traits self.unitInfo.PrimaryOffset ) ) { secondaryFireDelay = Math.Max( 4, secondaryFireDelay ); - if (rut != null) rut.primaryRecoil = 1; + primaryRecoil = 1; return; } if (self.unitInfo.Secondary != null && CheckFire(self, self.unitInfo.Secondary, ref secondaryFireDelay, self.unitInfo.SecondaryOffset ?? self.unitInfo.PrimaryOffset)) { - if (rut != null) - { - if (self.unitInfo.SecondaryOffset != null) - rut.secondaryRecoil = 1; - else - rut.primaryRecoil = 1; - } + if (self.unitInfo.SecondaryOffset != null) secondaryRecoil = 1; + else primaryRecoil = 1; return; } } diff --git a/OpenRa.Game/Traits/RenderUnitMuzzleFlash.cs b/OpenRa.Game/Traits/RenderUnitMuzzleFlash.cs new file mode 100644 index 0000000000..194cc8d2c8 --- /dev/null +++ b/OpenRa.Game/Traits/RenderUnitMuzzleFlash.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using OpenRa.Game.Graphics; + +namespace OpenRa.Game.Traits +{ + class RenderUnitMuzzleFlash : RenderUnit + { + Animation muzzleFlash; + + public RenderUnitMuzzleFlash(Actor self) + : base(self) + { + if (!self.unitInfo.MuzzleFlash) throw new InvalidOperationException("wtf??"); + + muzzleFlash = new Animation(self.unitInfo.Name); + muzzleFlash.PlayFetchIndex("muzzle", + () => + { + var attack = self.traits.WithInterface().First(); + var mobile = self.traits.WithInterface().First(); + return (Util.QuantizeFacing( + mobile.facing, 8)) * 6 + (int)(attack.primaryRecoil * 5.9f); + }); + } + + public override void Tick(Actor self) + { + base.Tick(self); + muzzleFlash.Tick(); + } + + public override IEnumerable> Render(Actor self) + { + var attack = self.traits.WithInterface().First(); + if (attack.primaryRecoil > 0) + return base.Render(self).Concat(new[] {Util.Centered(self, + muzzleFlash.Image, self.CenterLocation + new float2( + self.unitInfo.PrimaryOffset.ElementAtOrDefault(2), + self.unitInfo.PrimaryOffset.ElementAtOrDefault(3)))}); + else + return base.Render(self); + } + } +} diff --git a/OpenRa.Game/Traits/RenderUnitTurreted.cs b/OpenRa.Game/Traits/RenderUnitTurreted.cs index dce1b47a38..bcdac9a98d 100644 --- a/OpenRa.Game/Traits/RenderUnitTurreted.cs +++ b/OpenRa.Game/Traits/RenderUnitTurreted.cs @@ -11,7 +11,6 @@ namespace OpenRa.Game.Traits { public Animation turretAnim; public Animation muzzleFlash; - public float primaryRecoil = 0.0f, secondaryRecoil = 0.0f; public RenderUnitTurreted(Actor self) : base(self) @@ -21,9 +20,11 @@ namespace OpenRa.Game.Traits { if (self.unitInfo.MuzzleFlash) { + var attack = self.traits.WithInterface().First(); muzzleFlash = new Animation(self.unitInfo.Name); muzzleFlash.PlayFetchIndex("muzzle", - () => (Util.QuantizeFacing(self.traits.Get().turretFacing,8)) * 6 + (int)(primaryRecoil * 6)); + () => (Util.QuantizeFacing(self.traits.Get().turretFacing,8)) * 6 + (int)(attack.primaryRecoil * 5.9f)); + /* hack: recoil can be 1.0f, but don't overflow into next anim */ } turretAnim.PlayFetchIndex("turret", @@ -36,25 +37,24 @@ namespace OpenRa.Game.Traits public override IEnumerable> Render(Actor self) { var mobile = self.traits.Get(); + var attack = self.traits.WithInterface().FirstOrDefault(); yield return Util.Centered(self, anim.Image, self.CenterLocation); yield return Util.Centered(self, turretAnim.Image, self.CenterLocation - + Util.GetTurretPosition(self, self.unitInfo.PrimaryOffset, primaryRecoil)); + + Util.GetTurretPosition(self, self.unitInfo.PrimaryOffset, attack.primaryRecoil)); if (self.unitInfo.SecondaryOffset != null) yield return Util.Centered(self, turretAnim.Image, self.CenterLocation - + Util.GetTurretPosition(self, self.unitInfo.SecondaryOffset, secondaryRecoil)); + + Util.GetTurretPosition(self, self.unitInfo.SecondaryOffset, attack.secondaryRecoil)); - if (muzzleFlash != null && primaryRecoil > 0) + if (muzzleFlash != null && attack.primaryRecoil > 0) yield return Util.Centered(self, muzzleFlash.Image, self.CenterLocation - + Util.GetTurretPosition(self, self.unitInfo.PrimaryOffset, primaryRecoil)); + + Util.GetTurretPosition(self, self.unitInfo.PrimaryOffset, attack.primaryRecoil)); } public override void Tick(Actor self) { base.Tick(self); turretAnim.Tick(); - primaryRecoil = Math.Max(0f, primaryRecoil - .2f); - secondaryRecoil = Math.Max(0f, secondaryRecoil - .2f); if (muzzleFlash != null) muzzleFlash.Tick(); } diff --git a/sequences.xml b/sequences.xml index e3b88530a2..cc38b910b7 100644 --- a/sequences.xml +++ b/sequences.xml @@ -275,6 +275,7 @@ + diff --git a/units.ini b/units.ini index 02addd386d..5fd9cd1c0a 100755 --- a/units.ini +++ b/units.ini @@ -55,7 +55,9 @@ PrimaryOffset=0,0,0,-2 MuzzleFlash=yes [APC] Description=Armored Personnel Carrier -Traits=Mobile, RenderUnit, AttackBase +Traits=Mobile, AttackBase, RenderUnitMuzzleFlash +PrimaryOffset=0,0,0,-4 +MuzzleFlash=yes [MNLY] Description=Minelayer Traits=Mobile, RenderUnit