diff --git a/OpenRA.Mods.RA/Effects/GpsDot.cs b/OpenRA.Mods.RA/Effects/GpsDot.cs index 2b286343d6..55b8d17d97 100644 --- a/OpenRA.Mods.RA/Effects/GpsDot.cs +++ b/OpenRA.Mods.RA/Effects/GpsDot.cs @@ -19,10 +19,16 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA.Effects { + [Desc("Attach this to actors to render pictograms while hidden.")] class GpsDotInfo : ITraitInfo { - public readonly string String = "Infantry"; - public readonly string IndicatorPalettePrefix = "player"; + [Desc("Sprite collection for symbols.")] + public readonly string Image = "gpsdot"; + + [Desc("Sprite used for this actor.")] + [SequenceReference("Image")] public readonly string String = "Infantry"; + + [PaletteReference(true)] public readonly string IndicatorPalettePrefix = "player"; public object Create(ActorInitializer init) { @@ -58,7 +64,7 @@ namespace OpenRA.Mods.RA.Effects { this.self = self; this.info = info; - anim = new Animation(self.World, "gpsdot"); + anim = new Animation(self.World, info.Image); anim.PlayRepeating(info.String); self.World.AddFrameEndTask(w => w.Add(this)); diff --git a/OpenRA.Mods.RA/Effects/GpsSatellite.cs b/OpenRA.Mods.RA/Effects/GpsSatellite.cs index 2d61be7979..40493cdb63 100644 --- a/OpenRA.Mods.RA/Effects/GpsSatellite.cs +++ b/OpenRA.Mods.RA/Effects/GpsSatellite.cs @@ -11,20 +11,23 @@ using System.Collections.Generic; using OpenRA.Effects; using OpenRA.Graphics; +using OpenRA.Mods.RA.Traits; namespace OpenRA.Mods.RA.Effects { class GpsSatellite : IEffect { + readonly GpsPowerInfo info; readonly Animation anim; WPos pos; - public GpsSatellite(World world, WPos pos) + public GpsSatellite(World world, WPos pos, GpsPowerInfo info) { + this.info = info; this.pos = pos; - anim = new Animation(world, "sputnik"); - anim.PlayRepeating("idle"); + anim = new Animation(world, info.SatelliteImage); + anim.PlayRepeating(info.SatelliteSequence); } public void Tick(World world) @@ -38,7 +41,7 @@ namespace OpenRA.Mods.RA.Effects public IEnumerable Render(WorldRenderer wr) { - return anim.Render(pos, wr.Palette("effect")); + return anim.Render(pos, wr.Palette(info.SatellitePalette)); } } } diff --git a/OpenRA.Mods.RA/Effects/SatelliteLaunch.cs b/OpenRA.Mods.RA/Effects/SatelliteLaunch.cs index 47fa08c92d..f908a8345c 100644 --- a/OpenRA.Mods.RA/Effects/SatelliteLaunch.cs +++ b/OpenRA.Mods.RA/Effects/SatelliteLaunch.cs @@ -11,20 +11,23 @@ using System.Collections.Generic; using OpenRA.Effects; using OpenRA.Graphics; +using OpenRA.Mods.RA.Traits; namespace OpenRA.Mods.RA.Effects { class SatelliteLaunch : IEffect { + readonly GpsPowerInfo info; readonly Animation doors; readonly WPos pos; int frame = 0; - public SatelliteLaunch(Actor a) + public SatelliteLaunch(Actor a, GpsPowerInfo info) { - doors = new Animation(a.World, "atek"); + this.info = info; - doors.PlayThen("active", + doors = new Animation(a.World, info.DoorImage); + doors.PlayThen(info.DoorSequence, () => a.World.AddFrameEndTask(w => w.Remove(this))); pos = a.CenterPosition; @@ -35,12 +38,12 @@ namespace OpenRA.Mods.RA.Effects doors.Tick(); if (++frame == 19) - world.AddFrameEndTask(w => w.Add(new GpsSatellite(world, pos))); + world.AddFrameEndTask(w => w.Add(new GpsSatellite(world, pos, info))); } public IEnumerable Render(WorldRenderer wr) { - return doors.Render(pos, wr.Palette("effect")); + return doors.Render(pos, wr.Palette(info.DoorPalette)); } } } diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index 2714c3a97b..ab16686649 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -108,6 +108,7 @@ + diff --git a/OpenRA.Mods.RA/Traits/GpsWatcher.cs b/OpenRA.Mods.RA/Traits/GpsWatcher.cs new file mode 100644 index 0000000000..ebdf294c9b --- /dev/null +++ b/OpenRA.Mods.RA/Traits/GpsWatcher.cs @@ -0,0 +1,117 @@ +#region Copyright & License Information +/* + * Copyright 2007-2015 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using System.Collections.Generic; +using System.Linq; +using OpenRA.Effects; +using OpenRA.Mods.Common.Traits; +using OpenRA.Mods.RA.Effects; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA.Traits +{ + [Desc("Required for `GpsPower`. Attach this to the player actor.")] + class GpsWatcherInfo : ITraitInfo + { + public object Create(ActorInitializer init) { return new GpsWatcher(init.Self.Owner); } + } + + interface IOnGpsRefreshed { void OnGpsRefresh(Actor self, Player player); } + + class GpsWatcher : ISync, IFogVisibilityModifier + { + [Sync] public bool Launched { get; private set; } + [Sync] public bool GrantedAllies { get; private set; } + [Sync] public bool Granted { get; private set; } + + readonly Player owner; + + readonly List actors = new List(); + readonly HashSet> notifyOnRefresh = new HashSet>(); + + public GpsWatcher(Player owner) + { + this.owner = owner; + } + + public void GpsRemove(Actor atek) + { + actors.Remove(atek); + RefreshGps(atek); + } + + public void GpsAdd(Actor atek) + { + actors.Add(atek); + RefreshGps(atek); + } + + public void Launch(Actor atek, GpsPowerInfo info) + { + atek.World.Add(new DelayedAction(info.RevealDelay * 25, + () => + { + Launched = true; + RefreshGps(atek); + })); + } + + public void RefreshGps(Actor atek) + { + RefreshGranted(); + + foreach (var i in atek.World.ActorsWithTrait()) + i.Trait.RefreshGranted(); + + if ((Granted || GrantedAllies) && atek.Owner.IsAlliedWith(owner)) + atek.Owner.Shroud.ExploreAll(atek.World); + } + + void RefreshGranted() + { + var wasGranted = Granted; + var wasGrantedAllies = GrantedAllies; + + Granted = actors.Count > 0 && Launched; + GrantedAllies = owner.World.ActorsHavingTrait(g => g.Granted).Any(p => p.Owner.IsAlliedWith(owner)); + + if (Granted || GrantedAllies) + owner.Shroud.ExploreAll(owner.World); + + if (wasGranted != Granted || wasGrantedAllies != GrantedAllies) + foreach (var tp in notifyOnRefresh.ToList()) + tp.Trait.OnGpsRefresh(tp.Actor, owner); + } + + public bool HasFogVisibility() + { + return Granted || GrantedAllies; + } + + public bool IsVisible(Actor actor) + { + var gpsDot = actor.TraitOrDefault(); + if (gpsDot == null) + return false; + + return gpsDot.IsDotVisible(owner); + } + + public void RegisterForOnGpsRefreshed(Actor actor, IOnGpsRefreshed toBeNotified) + { + notifyOnRefresh.Add(new TraitPair(actor, toBeNotified)); + } + + public void UnregisterForOnGpsRefreshed(Actor actor, IOnGpsRefreshed toBeNotified) + { + notifyOnRefresh.Remove(new TraitPair(actor, toBeNotified)); + } + } +} diff --git a/OpenRA.Mods.RA/Traits/SupportPowers/GpsPower.cs b/OpenRA.Mods.RA/Traits/SupportPowers/GpsPower.cs index 8a5930dd1b..d319185c6f 100644 --- a/OpenRA.Mods.RA/Traits/SupportPowers/GpsPower.cs +++ b/OpenRA.Mods.RA/Traits/SupportPowers/GpsPower.cs @@ -17,114 +17,31 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA.Traits { - [Desc("Required for GpsPower. Attach this to the player actor.")] - class GpsWatcherInfo : ITraitInfo - { - public object Create(ActorInitializer init) { return new GpsWatcher(init.Self.Owner); } - } - - class GpsWatcher : ISync, IFogVisibilityModifier - { - [Sync] public bool Launched { get; private set; } - [Sync] public bool GrantedAllies { get; private set; } - [Sync] public bool Granted { get; private set; } - public readonly Player Owner; - - readonly List actors = new List(); - readonly HashSet> notifyOnRefresh = new HashSet>(); - - public GpsWatcher(Player owner) { Owner = owner; } - - public void GpsRem(Actor atek) - { - actors.Remove(atek); - RefreshGps(atek); - } - - public void GpsAdd(Actor atek) - { - actors.Add(atek); - RefreshGps(atek); - } - - public void Launch(Actor atek, SupportPowerInfo info) - { - atek.World.Add(new DelayedAction(((GpsPowerInfo)info).RevealDelay * 25, - () => - { - Launched = true; - RefreshGps(atek); - })); - } - - public void RefreshGps(Actor atek) - { - RefreshGranted(); - - foreach (var i in atek.World.ActorsWithTrait()) - i.Trait.RefreshGranted(); - - if ((Granted || GrantedAllies) && atek.Owner.IsAlliedWith(Owner)) - atek.Owner.Shroud.ExploreAll(atek.World); - } - - void RefreshGranted() - { - var wasGranted = Granted; - var wasGrantedAllies = GrantedAllies; - - Granted = actors.Count > 0 && Launched; - GrantedAllies = Owner.World.ActorsHavingTrait(g => g.Granted).Any(p => p.Owner.IsAlliedWith(Owner)); - - if (Granted || GrantedAllies) - Owner.Shroud.ExploreAll(Owner.World); - - if (wasGranted != Granted || wasGrantedAllies != GrantedAllies) - foreach (var tp in notifyOnRefresh.ToList()) - tp.Trait.OnGpsRefresh(tp.Actor, Owner); - } - - public bool HasFogVisibility() - { - return Granted || GrantedAllies; - } - - public bool IsVisible(Actor actor) - { - var gpsDot = actor.TraitOrDefault(); - if (gpsDot == null) - return false; - - return gpsDot.IsDotVisible(Owner); - } - - public void RegisterForOnGpsRefreshed(Actor actor, IOnGpsRefreshed toBeNotified) - { - notifyOnRefresh.Add(new TraitPair(actor, toBeNotified)); - } - - public void UnregisterForOnGpsRefreshed(Actor actor, IOnGpsRefreshed toBeNotified) - { - notifyOnRefresh.Remove(new TraitPair(actor, toBeNotified)); - } - } - - interface IOnGpsRefreshed { void OnGpsRefresh(Actor self, Player player); } - + [Desc("Requires `GpsWatcher` on the player actor.")] class GpsPowerInfo : SupportPowerInfo { public readonly int RevealDelay = 0; + public readonly string DoorImage = "atek"; + [SequenceReference("DoorImage")] public readonly string DoorSequence = "active"; + [PaletteReference] public readonly string DoorPalette = "effect"; + + public readonly string SatelliteImage = "sputnik"; + [SequenceReference("SatelliteImage")] public readonly string SatelliteSequence = "idle"; + [PaletteReference] public readonly string SatellitePalette = "effect"; + public override object Create(ActorInitializer init) { return new GpsPower(init.Self, this); } } class GpsPower : SupportPower, INotifyKilled, INotifyStanceChanged, INotifySold, INotifyOwnerChanged { + readonly GpsPowerInfo info; GpsWatcher owner; public GpsPower(Actor self, GpsPowerInfo info) : base(self, info) { + this.info = info; owner = self.Owner.PlayerActor.Trait(); owner.GpsAdd(self); } @@ -142,9 +59,9 @@ namespace OpenRA.Mods.RA.Traits { Game.Sound.PlayToPlayer(self.Owner, Info.LaunchSound); - w.Add(new SatelliteLaunch(self)); + w.Add(new SatelliteLaunch(self, info)); - owner.Launch(self, Info); + owner.Launch(self, info); }); } @@ -156,7 +73,7 @@ namespace OpenRA.Mods.RA.Traits void RemoveGps(Actor self) { // Extra function just in case something needs to be added later - owner.GpsRem(self); + owner.GpsRemove(self); } public void StanceChanged(Actor self, Player a, Player b, Stance oldStance, Stance newStance)