Files
OpenRA/OpenRA.Mods.Cnc/Traits/FrozenUnderFogUpdatedByGps.cs
2017-09-28 13:14:08 +02:00

110 lines
3.4 KiB
C#

#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;
using OpenRA.Mods.Common.Traits;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Mods.Cnc.Traits
{
using FrozenActorAction = Action<FrozenUnderFogUpdatedByGps, FrozenActorLayer, GpsWatcher, FrozenActor>;
[Desc("Updates frozen actors of actors that change owners, are sold or die whilst having an active GPS power.")]
public class FrozenUnderFogUpdatedByGpsInfo : ITraitInfo, Requires<FrozenUnderFogInfo>
{
public object Create(ActorInitializer init) { return new FrozenUnderFogUpdatedByGps(init); }
}
public class FrozenUnderFogUpdatedByGps : INotifyOwnerChanged, INotifyActorDisposing, IOnGpsRefreshed
{
static readonly FrozenActorAction Refresh = (fufubg, fal, gps, fa) =>
{
// Refreshes the visual state of the frozen actor, so ownership changes can be seen.
// This only makes sense if the frozen actor has already been revealed (i.e. has renderables)
if (fa.HasRenderables)
{
fa.RefreshState();
fa.NeedRenderables = true;
}
};
static readonly FrozenActorAction Remove = (fufubg, fal, gps, fa) =>
{
// Removes the frozen actor. Once done, we no longer need to track GPS updates.
fal.Remove(fa);
gps.UnregisterForOnGpsRefreshed(fufubg.self, fufubg);
};
class Traits
{
public readonly FrozenActorLayer FrozenActorLayer;
public readonly GpsWatcher GpsWatcher;
public Traits(Player player, FrozenUnderFogUpdatedByGps frozenUnderFogUpdatedByGps)
{
FrozenActorLayer = player.PlayerActor.TraitOrDefault<FrozenActorLayer>();
GpsWatcher = player.PlayerActor.TraitOrDefault<GpsWatcher>();
GpsWatcher.RegisterForOnGpsRefreshed(frozenUnderFogUpdatedByGps.self, frozenUnderFogUpdatedByGps);
}
}
readonly PlayerDictionary<Traits> traits;
readonly Actor self;
public FrozenUnderFogUpdatedByGps(ActorInitializer init)
{
self = init.Self;
traits = new PlayerDictionary<Traits>(init.World, player => new Traits(player, this));
}
public void OnOwnerChanged(Actor self, Player oldOwner, Player newOwner)
{
ActOnFrozenActorsForAllPlayers(Refresh);
}
void INotifyActorDisposing.Disposing(Actor self)
{
ActOnFrozenActorsForAllPlayers(Remove);
}
public void OnGpsRefresh(Actor self, Player player)
{
if (self.IsDead)
ActOnFrozenActorForPlayer(player, Remove);
else
ActOnFrozenActorForPlayer(player, Refresh);
}
void ActOnFrozenActorsForAllPlayers(FrozenActorAction action)
{
for (var playerIndex = 0; playerIndex < traits.Count; playerIndex++)
ActOnFrozenActorForTraits(traits[playerIndex], action);
}
void ActOnFrozenActorForPlayer(Player player, FrozenActorAction action)
{
ActOnFrozenActorForTraits(traits[player], action);
}
void ActOnFrozenActorForTraits(Traits t, FrozenActorAction action)
{
if (t.FrozenActorLayer == null || t.GpsWatcher == null ||
!t.GpsWatcher.Granted || !t.GpsWatcher.GrantedAllies)
return;
var fa = t.FrozenActorLayer.FromID(self.ActorID);
if (fa == null)
return;
action(this, t.FrozenActorLayer, t.GpsWatcher, fa);
}
}
}