From 8f24f93330ce7f2f2cde7e360ca4e881852a0872 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 3 Aug 2013 16:39:47 +1200 Subject: [PATCH] Add per-armament muzzle flashes. Fixes #3609. --- OpenRA.Mods.RA/Render/WithMuzzleFlash.cs | 71 ++++++++++++++---------- mods/cnc/rules/aircraft.yaml | 5 +- mods/cnc/rules/vehicles.yaml | 6 +- mods/ra/maps/drop-zone-w/map.yaml | 5 +- mods/ra/rules/aircraft.yaml | 10 +++- 5 files changed, 64 insertions(+), 33 deletions(-) diff --git a/OpenRA.Mods.RA/Render/WithMuzzleFlash.cs b/OpenRA.Mods.RA/Render/WithMuzzleFlash.cs index ab2e88da00..91bcc97833 100644 --- a/OpenRA.Mods.RA/Render/WithMuzzleFlash.cs +++ b/OpenRA.Mods.RA/Render/WithMuzzleFlash.cs @@ -11,69 +11,84 @@ using System; using System.Collections.Generic; using System.Linq; +using OpenRA.FileFormats; using OpenRA.Graphics; using OpenRA.Traits; using OpenRA.Mods.RA; namespace OpenRA.Mods.RA.Render { - class WithMuzzleFlashInfo : ITraitInfo, Requires, Requires + class WithMuzzleFlashInfo : ITraitInfo, Requires, Requires, Requires { - public object Create(ActorInitializer init) { return new WithMuzzleFlash(init.self); } + [Desc("Sequence name to use")] + public readonly string Sequence = "muzzle"; + + [Desc("Armament name")] + public readonly string Armament = "primary"; + + public object Create(ActorInitializer init) { return new WithMuzzleFlash(init.self, this); } } class WithMuzzleFlash : INotifyAttack, IRender, ITick { - Dictionary muzzleFlashes = new Dictionary(); - bool isShowing; + readonly WithMuzzleFlashInfo info; + Dictionary visible = new Dictionary(); + Dictionary anims = new Dictionary(); - public WithMuzzleFlash(Actor self) + public WithMuzzleFlash(Actor self, WithMuzzleFlashInfo info) { + this.info = info; var render = self.Trait(); var facing = self.TraitOrDefault(); - var arms = self.TraitsImplementing(); - foreach (var a in arms) - foreach(var b in a.Barrels) - { - var barrel = b; - var turreted = self.TraitsImplementing() - .FirstOrDefault(t => t.Name == a.Info.Turret); - var getFacing = turreted != null ? () => turreted.turretFacing : - facing != null ? (Func)(() => facing.Facing) : () => 0; + var arm = self.TraitsImplementing() + .Single(a => a.Info.Name == info.Armament); - var muzzleFlash = new Animation(render.GetImage(self), getFacing); - muzzleFlash.Play("muzzle"); + foreach (var b in arm.Barrels) + { + var barrel = b; + var turreted = self.TraitsImplementing() + .FirstOrDefault(t => t.Name == arm.Info.Turret); - muzzleFlashes.Add("muzzle{0}".F(muzzleFlashes.Count), - new AnimationWithOffset(muzzleFlash, - () => a.MuzzleOffset(self, barrel), - () => !isShowing)); - } + var getFacing = turreted != null ? () => turreted.turretFacing : + facing != null ? (Func)(() => facing.Facing) : () => 0; + + var muzzleFlash = new Animation(render.GetImage(self), getFacing); + visible.Add(barrel, false); + anims.Add(barrel, + new AnimationWithOffset(muzzleFlash, + () => arm.MuzzleOffset(self, barrel), + () => !visible[barrel])); + } } public void Attacking(Actor self, Target target, Armament a, Barrel barrel) { - isShowing = true; - foreach( var mf in muzzleFlashes.Values ) - mf.Animation.PlayThen("muzzle", () => isShowing = false); + if (a.Info.Name != info.Armament) + return; + + visible[barrel] = true; + anims[barrel].Animation.PlayThen(info.Sequence, () => visible[barrel] = false); } public IEnumerable Render(Actor self, WorldRenderer wr) { - foreach (var a in muzzleFlashes.Values) + foreach (var kv in anims) { - if (a.DisableFunc != null && a.DisableFunc()) + if (!visible[kv.Key]) continue; - foreach (var r in a.Render(self, wr, wr.Palette("effect"), 1f)) + if (kv.Value.DisableFunc != null && kv.Value.DisableFunc()) + continue; + + foreach (var r in kv.Value.Render(self, wr, wr.Palette("effect"), 1f)) yield return r; } } public void Tick(Actor self) { - foreach (var a in muzzleFlashes.Values) + foreach (var a in anims.Values) a.Animation.Tick(); } } diff --git a/mods/cnc/rules/aircraft.yaml b/mods/cnc/rules/aircraft.yaml index b2f3e7c779..49fd8db64c 100644 --- a/mods/cnc/rules/aircraft.yaml +++ b/mods/cnc/rules/aircraft.yaml @@ -69,6 +69,7 @@ HELI: Weapon: HeliAGGun LocalOffset: 128,-213,-85, 128,213,-85 Armament@SECONDARY: + Name: secondary Weapon: HeliAAGun LocalOffset: 128,-213,-85, 128,213,-85 AttackHeli: @@ -82,7 +83,9 @@ HELI: RenderUnit: WithRotor: Offset: 0,0,85 - WithMuzzleFlash: + WithMuzzleFlash@PRIMARY: + WithMuzzleFlash@SECONDARY: + Armament: secondary WithShadow: LeavesHusk: HuskActor: HELI.Husk diff --git a/mods/cnc/rules/vehicles.yaml b/mods/cnc/rules/vehicles.yaml index 82743f763a..da0d043cd9 100644 --- a/mods/cnc/rules/vehicles.yaml +++ b/mods/cnc/rules/vehicles.yaml @@ -106,12 +106,15 @@ APC: RecoilRecovery: 18 LocalOffset: 85,85,299, 85,-85,299 Armament@SECONDARY: + Name: secondary Weapon: APCGun.AA Recoil: 96 RecoilRecovery: 18 LocalOffset: 85,85,299, 85,-85,299 AttackTurreted: - WithMuzzleFlash: + WithMuzzleFlash@PRIMARY: + WithMuzzleFlash@SECONDARY: + Armament: secondary RenderUnit: WithTurret: AutoTarget: @@ -404,6 +407,7 @@ HTNK: Recoil: 170 RecoilRecovery: 42 Armament@SECONDARY: + Name: secondary Weapon: MammothMissiles LocalOffset: -85, 384, 340, -85, -384, 340 LocalYaw: -100, 100 diff --git a/mods/ra/maps/drop-zone-w/map.yaml b/mods/ra/maps/drop-zone-w/map.yaml index 393027a6e5..0aee39dc1d 100644 --- a/mods/ra/maps/drop-zone-w/map.yaml +++ b/mods/ra/maps/drop-zone-w/map.yaml @@ -248,9 +248,12 @@ Rules: Armament@PRIMARY: Weapon:M60mg Armament@SECONDARY: + Name: secondary Weapon:M60mg AttackFrontal: - WithMuzzleFlash: + WithMuzzleFlash@PRIMARY: + WithMuzzleFlash@SECONDARY: + Armament: secondary MustBeDestroyed: -GivesBounty: PT: diff --git a/mods/ra/rules/aircraft.yaml b/mods/ra/rules/aircraft.yaml index 80ecedea64..94e827516d 100644 --- a/mods/ra/rules/aircraft.yaml +++ b/mods/ra/rules/aircraft.yaml @@ -145,6 +145,7 @@ YAK: Weapon: ChainGun.Yak LocalOffset: 256,-213,0 Armament@SECONDARY: + Name: secondary Weapon: ChainGun.Yak LocalOffset: 256,213,0 AttackPlane: @@ -163,7 +164,9 @@ YAK: ReloadTicks: 11 IronCurtainable: ReturnOnIdle: - WithMuzzleFlash: + WithMuzzleFlash@PRIMARY: + WithMuzzleFlash@SECONDARY: + Armament: secondary Contrail: Offset: -853,0,0 LeavesHusk: @@ -294,6 +297,7 @@ HIND: Weapon: ChainGun LocalOffset: 85,-213,-85 Armament@SECONDARY: + Name: secondary Weapon: ChainGun LocalOffset: 85,213,-85 AttackHeli: @@ -314,7 +318,9 @@ HIND: IronCurtainable: Selectable: Bounds: 38,32,0,0 - WithMuzzleFlash: + WithMuzzleFlash@PRIMARY: + WithMuzzleFlash@SECONDARY: + Armament: secondary LeavesHusk: HuskActor: HIND.Husk SmokeTrailWhenDamaged: