#region Copyright & License Information /* * Copyright 2007-2017 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, either version 3 of * the License, or (at your option) any later version. For more * information, see COPYING. */ #endregion using System.Collections.Generic; using System.Linq; using OpenRA.Effects; using OpenRA.Mods.Cnc.Effects; using OpenRA.Mods.Common.Traits; using OpenRA.Traits; namespace OpenRA.Mods.Cnc.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; } // Whether this watcher has explored the terrain (by becoming Launched, or an ally becoming Launched) [Sync] bool explored; 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.Owner); } public void GpsAdd(Actor atek) { actors.Add(atek); RefreshGps(atek.Owner); } public void ReachedOrbit(Player launcher) { Launched = true; RefreshGps(launcher); } public void RefreshGps(Player launcher) { RefreshGranted(); foreach (var i in launcher.World.ActorsWithTrait()) i.Trait.RefreshGranted(); } void RefreshGranted() { var wasGranted = Granted; var wasGrantedAllies = GrantedAllies; var allyWatchers = owner.World.ActorsWithTrait().Where(kv => kv.Actor.Owner.IsAlliedWith(owner)); Granted = actors.Count > 0 && Launched; GrantedAllies = allyWatchers.Any(w => w.Trait.Granted); var allyLaunched = allyWatchers.Any(w => w.Trait.Launched); if ((Launched || allyLaunched) && !explored) { explored = true; owner.Shroud.ExploreAll(); } 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)); } } }