Files
OpenRA/OpenRA.Mods.RA/Traits/FrozenUnderFogUpdatedByGps.cs
RoosterDragon 3c930c3ef9 Introduce FrozenUnderFogUpdatedByGps and IOnGpsRefreshed.
This trait uses the new interface to register with the GpsWatcher to get notified when the GPS state changes. It needs to register as if the actor is destroyed, the GpsWatcher can no longer query actors in the world to get the trait. This is no good as the trait needs to perform actions after the death of its parent actor.

When the GPS is enabled, the trait will track ownership changes and update the frozen actor (just like if there was only a GPS dot, it would change colour) and it will also remove frozen actors if the real actor dies or is sold.
2016-01-17 00:13:06 +00:00

106 lines
3.2 KiB
C#

#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;
using OpenRA.Mods.Common.Traits;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.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.
fa.RefreshState();
if (fa.HasRenderables)
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);
}
public void 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);
}
}
}