diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index d4fbdf7b56..780673dd7f 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -83,6 +83,12 @@ namespace OpenRA.Traits public interface INotifyHarvest { void Harvested(Actor self, ResourceType resource); } public interface INotifyInfiltrated { void Infiltrated(Actor self, Actor infiltrator); } + public interface IUpgradable + { + bool AcceptsUpgrade(string type); + void UpgradeAvailable(Actor self, string type, bool available); + } + public interface ISeedableResource { void Seed(Actor self); } public interface IDemolishableInfo { bool IsValidTarget(ActorInfo actorInfo, Actor saboteur); } diff --git a/OpenRA.Mods.RA/GlobalUpgradable.cs b/OpenRA.Mods.RA/GlobalUpgradable.cs new file mode 100644 index 0000000000..dbfbb36594 --- /dev/null +++ b/OpenRA.Mods.RA/GlobalUpgradable.cs @@ -0,0 +1,62 @@ +#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 System.Linq; +using System.Text; +using OpenRA.Mods.RA; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA +{ + public class GlobalUpgradableInfo : ITraitInfo + { + public readonly string[] Upgrades = { }; + public readonly string[] Prerequisites = { }; + + public object Create(ActorInitializer init) { return new GlobalUpgradable(init.self, this); } + } + + public class GlobalUpgradable : INotifyAddedToWorld + { + readonly GlobalUpgradableInfo info; + readonly GlobalUpgradeManager manager; + + public GlobalUpgradable(Actor actor, GlobalUpgradableInfo info) + { + this.info = info; + manager = actor.Owner.PlayerActor.Trait(); + } + + public void AddedToWorld(Actor self) + { + if (info.Prerequisites.Any()) + manager.Register(self, this, info.Prerequisites); + } + + public void RemovedFromWorld(Actor self) + { + if (info.Prerequisites.Any()) + manager.Unregister(self, this, info.Prerequisites); + } + + public void PrerequisitesUpdated(Actor self, bool available) + { + var upgrades = self.TraitsImplementing(); + foreach (var u in upgrades) + { + foreach (var t in info.Upgrades) + if (u.AcceptsUpgrade(t)) + u.UpgradeAvailable(self, t, available); + } + } + } +} diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index 35c8e104c0..b13a78e143 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -550,6 +550,8 @@ + + diff --git a/OpenRA.Mods.RA/Player/GlobalUpgradeManager.cs b/OpenRA.Mods.RA/Player/GlobalUpgradeManager.cs new file mode 100644 index 0000000000..8e07b259e0 --- /dev/null +++ b/OpenRA.Mods.RA/Player/GlobalUpgradeManager.cs @@ -0,0 +1,94 @@ +#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 System.Linq; +using OpenRA.Graphics; +using OpenRA.Primitives; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA +{ + [Desc("Attach this to the player actor.")] + public class GlobalUpgradeManagerInfo : ITraitInfo, Requires + { + public object Create(ActorInitializer init) { return new GlobalUpgradeManager(init); } + } + + public class GlobalUpgradeManager : ITechTreeElement + { + readonly Actor self; + readonly Dictionary>> upgradables = new Dictionary>>(); + readonly TechTree techTree; + + public GlobalUpgradeManager(ActorInitializer init) + { + self = init.self; + techTree = self.Trait(); + } + + static string MakeKey(string[] prerequisites) + { + return "upgrade_" + string.Join("_", prerequisites.OrderBy(a => a)); + } + + public void Register(Actor actor, GlobalUpgradable u, string[] prerequisites) + { + var key = MakeKey(prerequisites); + if (!upgradables.ContainsKey(key)) + { + upgradables.Add(key, new List>()); + techTree.Add(key, prerequisites, 0, this); + } + + upgradables[key].Add(Pair.New(actor, u)); + + // Notify the current state + u.PrerequisitesUpdated(actor, techTree.HasPrerequisites(prerequisites)); + } + + public void Unregister(Actor actor, GlobalUpgradable u, string[] prerequisites) + { + var key = MakeKey(prerequisites); + var list = upgradables[key]; + + list.RemoveAll(x => x.First == actor && x.Second == u); + if (!list.Any()) + { + upgradables.Remove(key); + techTree.Remove(key); + } + } + + public void PrerequisitesAvailable(string key) + { + List> list; + if (!upgradables.TryGetValue(key, out list)) + return; + + foreach (var u in list) + u.Second.PrerequisitesUpdated(u.First, true); + } + + public void PrerequisitesUnavailable(string key) + { + List> list; + if (!upgradables.TryGetValue(key, out list)) + return; + + foreach (var u in list) + u.Second.PrerequisitesUpdated(u.First, false); + } + + public void PrerequisitesItemHidden(string key) { } + public void PrerequisitesItemVisible(string key) { } + } +}