From da592f0a25cae9c4521fb58a5160c004182f4908 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 28 Sep 2014 17:03:48 +1300 Subject: [PATCH] Add UpgradeActorsNear trait for passive upgrades. --- OpenRA.Mods.RA/OpenRA.Mods.RA.csproj | 1 + OpenRA.Mods.RA/UpgradeActorsNear.cs | 117 +++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 OpenRA.Mods.RA/UpgradeActorsNear.cs diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index be236ea26a..ce55cb81f7 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -550,6 +550,7 @@ + diff --git a/OpenRA.Mods.RA/UpgradeActorsNear.cs b/OpenRA.Mods.RA/UpgradeActorsNear.cs new file mode 100644 index 0000000000..070805eb57 --- /dev/null +++ b/OpenRA.Mods.RA/UpgradeActorsNear.cs @@ -0,0 +1,117 @@ +#region Copyright & License Information +/* + * Copyright 2007-2014 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 System.Collections.Generic; +using OpenRA.GameRules; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA +{ + [Desc("Applies an upgrade to actors within a specified range.")] + public class UpgradeActorsNearInfo : ITraitInfo + { + [Desc("The upgrades to grant.")] + public readonly string[] Upgrades = { }; + + [Desc("The range to search for actors to upgrade.")] + public readonly WRange Range = WRange.FromCells(3); + + [Desc("What diplomatic stances are affected.")] + public readonly Stance ValidStances = Stance.Ally; + + [Desc("Grant the upgrades apply to this actor.")] + public readonly bool AffectsParent = false; + + public readonly string EnableSound = null; + public readonly string DisableSound = null; + + public object Create(ActorInitializer init) { return new UpgradeActorsNear(init.self, this); } + } + + public class UpgradeActorsNear : ITick, INotifyAddedToWorld, INotifyRemovedFromWorld + { + readonly UpgradeActorsNearInfo info; + readonly Actor self; + + int proximityTrigger; + WPos cachedPosition; + WRange cachedRange; + WRange desiredRange; + + bool cachedDisabled = true; + + public UpgradeActorsNear(Actor self, UpgradeActorsNearInfo info) + { + this.info = info; + this.self = self; + cachedRange = info.Range; + } + + public void AddedToWorld(Actor self) + { + cachedPosition = self.CenterPosition; + proximityTrigger = self.World.ActorMap.AddProximityTrigger(cachedPosition, cachedRange, ActorEntered, ActorExited); + } + + public void RemovedFromWorld(Actor self) + { + self.World.ActorMap.RemoveProximityTrigger(proximityTrigger); + } + + public void Tick(Actor self) + { + var disabled = self.IsDisabled(); + + if (cachedDisabled != disabled) + { + Sound.Play(disabled ? info.DisableSound : info.EnableSound, self.CenterPosition); + desiredRange = disabled ? WRange.Zero : info.Range; + cachedDisabled = disabled; + } + + if (self.CenterPosition != cachedPosition || desiredRange != cachedRange) + { + cachedPosition = self.CenterPosition; + cachedRange = desiredRange; + self.World.ActorMap.UpdateProximityTrigger(proximityTrigger, cachedPosition, cachedRange); + } + } + + void ActorEntered(Actor a) + { + if (a.Destroyed) + return; + + if (a == self && !info.AffectsParent) + return; + + var stance = self.Owner.Stances[a.Owner]; + if (!info.ValidStances.HasFlag(stance)) + return; + + var um = a.TraitOrDefault(); + if (um != null) + foreach (var u in info.Upgrades) + um.GrantUpgrade(a, u, this); + } + + void ActorExited(Actor a) + { + if (a == self || a.Destroyed) + return; + + var um = a.TraitOrDefault(); + if (um != null) + foreach (var u in info.Upgrades) + um.RevokeUpgrade(a, u, this); + } + } +}