diff --git a/OpenRA.Game/Traits/Player/PlayerResources.cs b/OpenRA.Game/Traits/Player/PlayerResources.cs
index 64f9f9b059..e6a7f9f698 100644
--- a/OpenRA.Game/Traits/Player/PlayerResources.cs
+++ b/OpenRA.Game/Traits/Player/PlayerResources.cs
@@ -17,7 +17,6 @@ namespace OpenRA.Traits
{
public readonly int[] SelectableCash = { 2500, 5000, 10000, 20000 };
public readonly int DefaultCash = 5000;
- public readonly int AdviceInterval = 250;
public object Create(ActorInitializer init) { return new PlayerResources(init.Self, this); }
}
@@ -27,14 +26,12 @@ namespace OpenRA.Traits
const float DisplayCashFracPerFrame = .07f;
const int DisplayCashDeltaPerFrame = 37;
readonly Player owner;
- int adviceInterval;
public PlayerResources(Actor self, PlayerResourcesInfo info)
{
owner = self.Owner;
Cash = self.World.LobbyInfo.GlobalSettings.StartingCash;
- adviceInterval = info.AdviceInterval;
}
[Sync] public int Cash;
@@ -44,7 +41,6 @@ namespace OpenRA.Traits
public int DisplayCash;
public int DisplayResources;
- public bool AlertSilo;
public int Earned;
public int Spent;
@@ -61,8 +57,6 @@ namespace OpenRA.Traits
if (Resources > ResourceCapacity)
{
- nextSiloAdviceTime = 0;
-
Earned -= Resources - ResourceCapacity;
Resources = ResourceCapacity;
}
@@ -126,7 +120,6 @@ namespace OpenRA.Traits
return true;
}
- int nextSiloAdviceTime = 0;
int nextCashTickTime = 0;
public void Tick(Actor self)
@@ -141,19 +134,6 @@ namespace OpenRA.Traits
if (Resources > ResourceCapacity)
Resources = ResourceCapacity;
- if (--nextSiloAdviceTime <= 0)
- {
- if (Resources > 0.8 * ResourceCapacity)
- {
- Game.Sound.PlayNotification(self.World.Map.Rules, owner, "Speech", "SilosNeeded", owner.Faction.InternalName);
- AlertSilo = true;
- }
- else
- AlertSilo = false;
-
- nextSiloAdviceTime = adviceInterval;
- }
-
var diff = Math.Abs(Cash - DisplayCash);
var move = Math.Min(Math.Max((int)(diff * DisplayCashFracPerFrame), DisplayCashDeltaPerFrame), diff);
diff --git a/OpenRA.Mods.Common/AI/BaseBuilder.cs b/OpenRA.Mods.Common/AI/BaseBuilder.cs
index babe172c87..ae7e359276 100644
--- a/OpenRA.Mods.Common/AI/BaseBuilder.cs
+++ b/OpenRA.Mods.Common/AI/BaseBuilder.cs
@@ -272,7 +272,7 @@ namespace OpenRA.Mods.Common.AI
}
// Create some head room for resource storage if we really need it
- if (playerResources.AlertSilo)
+ if (playerResources.Resources > 0.8 * playerResources.ResourceCapacity)
{
var silo = GetProducibleBuilding("Silo", buildableThings);
if (silo != null && HasSufficientPowerForActor(silo))
diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
index ee5846cd43..b77937ff83 100644
--- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
+++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
@@ -382,6 +382,7 @@
+
diff --git a/OpenRA.Mods.Common/Traits/Player/ResourceStorageWarning.cs b/OpenRA.Mods.Common/Traits/Player/ResourceStorageWarning.cs
new file mode 100644
index 0000000000..4c15151ca1
--- /dev/null
+++ b/OpenRA.Mods.Common/Traits/Player/ResourceStorageWarning.cs
@@ -0,0 +1,56 @@
+#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 OpenRA.Traits;
+
+namespace OpenRA.Mods.Common.Traits
+{
+ [Desc("Provides the player with an audible warning when their storage is nearing full.")]
+ public class ResourceStorageWarningInfo : ITraitInfo, Requires
+ {
+ [Desc("Interval, in seconds, at which to check if more storage is needed.")]
+ public readonly int AdviceInterval = 10;
+
+ [Desc("The percentage threshold above which a warning is played.")]
+ public readonly int Threshold = 80;
+
+ [Desc("The speech to play for the warning.")]
+ public readonly string Notification = "SilosNeeded";
+
+ public object Create(ActorInitializer init) { return new ResourceStorageWarning(init.Self, this); }
+ }
+
+ public class ResourceStorageWarning : ITick
+ {
+ readonly ResourceStorageWarningInfo info;
+ readonly PlayerResources resources;
+
+ int nextSiloAdviceTime = 0;
+
+ public ResourceStorageWarning(Actor self, ResourceStorageWarningInfo info)
+ {
+ this.info = info;
+ resources = self.Trait();
+ }
+
+ public void Tick(Actor self)
+ {
+ if (--nextSiloAdviceTime <= 0)
+ {
+ var owner = self.Owner;
+
+ if (resources.Resources > info.Threshold * resources.ResourceCapacity / 100)
+ Game.Sound.PlayNotification(self.World.Map.Rules, owner, "Speech", info.Notification, owner.Faction.InternalName);
+
+ nextSiloAdviceTime = info.AdviceInterval * 1000 / self.World.Timestep;
+ }
+ }
+ }
+}
diff --git a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs
index 3391274d74..68a1d504ea 100644
--- a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs
+++ b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs
@@ -2764,6 +2764,30 @@ namespace OpenRA.Mods.Common.UtilityCommands
}
}
+ // Refactored the low resources notification to a separate trait
+ if (engineVersion < 20151227 && node.Key == "Player")
+ {
+ var resourcesNode = node.Value.Nodes.FirstOrDefault(x => x.Key == "PlayerResources");
+
+ if (resourcesNode != null)
+ {
+ var intervalNode = resourcesNode.Value.Nodes.FirstOrDefault(x => x.Key == "AdviceInterval");
+ var storageNode = new MiniYamlNode("ResourceStorageWarning", "");
+
+ if (intervalNode != null)
+ {
+ // The time value is now in seconds, not ticks. We
+ // divide by 25 ticks per second at Normal.
+ int oldInterval;
+ if (int.TryParse(intervalNode.Value.Value, out oldInterval))
+ storageNode.Value.Nodes.Add(new MiniYamlNode("AdviceInterval", (oldInterval / 25).ToString()));
+ resourcesNode.Value.Nodes.Remove(intervalNode);
+ }
+
+ node.Value.Nodes.Add(storageNode);
+ }
+ }
+
UpgradeActorRules(engineVersion, ref node.Value.Nodes, node, depth + 1);
}
}
diff --git a/mods/cnc/rules/player.yaml b/mods/cnc/rules/player.yaml
index 972385a259..ac5a01793d 100644
--- a/mods/cnc/rules/player.yaml
+++ b/mods/cnc/rules/player.yaml
@@ -29,4 +29,5 @@ Player:
Name: Unrestricted
Prerequisites: techlevel.low, techlevel.medium, techlevel.high, techlevel.superweapons
GlobalUpgradeManager:
+ ResourceStorageWarning:
diff --git a/mods/d2k/rules/player.yaml b/mods/d2k/rules/player.yaml
index ffec06eb29..436efe1869 100644
--- a/mods/d2k/rules/player.yaml
+++ b/mods/d2k/rules/player.yaml
@@ -61,7 +61,6 @@ Player:
AllyRepair:
PlayerResources:
SelectableCash: 2500, 5000, 7000, 10000, 20000
- AdviceInterval: 650
ActorGroupProxy:
DeveloperMode:
BaseAttackNotifier:
@@ -85,4 +84,6 @@ Player:
EnemyWatcher:
HarvesterInsurance:
GlobalUpgradeManager:
+ ResourceStorageWarning:
+ AdviceInterval: 26
diff --git a/mods/ra/rules/player.yaml b/mods/ra/rules/player.yaml
index 9361dd786e..4968a597e0 100644
--- a/mods/ra/rules/player.yaml
+++ b/mods/ra/rules/player.yaml
@@ -68,4 +68,5 @@ Player:
VeteranProductionIconOverlay:
Image: iconchevrons
Sequence: veteran
+ ResourceStorageWarning:
diff --git a/mods/ts/rules/player.yaml b/mods/ts/rules/player.yaml
index 970e388ca5..71db70ee03 100644
--- a/mods/ts/rules/player.yaml
+++ b/mods/ts/rules/player.yaml
@@ -48,4 +48,5 @@ Player:
HarvesterAttackNotifier:
PlayerStatistics:
PlaceBeacon:
+ ResourceStorageWarning: