diff --git a/OpenRA.Game/Traits/Player/PlayerResources.cs b/OpenRA.Game/Traits/Player/PlayerResources.cs index 604c0e2f3a..1b32342a2c 100644 --- a/OpenRA.Game/Traits/Player/PlayerResources.cs +++ b/OpenRA.Game/Traits/Player/PlayerResources.cs @@ -25,6 +25,12 @@ namespace OpenRA.Traits [Desc("Force the DefaultCash option by disabling changes in the lobby.")] public readonly bool DefaultCashLocked = false; + [Desc("Speech notification to play when the player does not have any funds.")] + public readonly string InsufficientFundsNotification = null; + + [Desc("Delay (in ticks) during which warnings will be muted.")] + public readonly int InsufficientFundsNotificationDelay = 750; + public object Create(ActorInitializer init) { return new PlayerResources(init.Self, this); } } @@ -32,10 +38,12 @@ namespace OpenRA.Traits { const float DisplayCashFracPerFrame = .07f; const int DisplayCashDeltaPerFrame = 37; + readonly PlayerResourcesInfo info; readonly Player owner; public PlayerResources(Actor self, PlayerResourcesInfo info) { + this.info = info; owner = self.Owner; Cash = self.World.LobbyInfo.GlobalSettings.StartingCash; @@ -52,6 +60,8 @@ namespace OpenRA.Traits public int Earned; public int Spent; + int lastNotificationTick; + public bool CanGiveResources(int amount) { return Resources + amount <= ResourceCapacity; @@ -111,9 +121,19 @@ namespace OpenRA.Traits } } - public bool TakeCash(int num) + public bool TakeCash(int num, bool notifyLowFunds = false) { - if (Cash + Resources < num) return false; + if (Cash + Resources < num) + { + if (notifyLowFunds && !string.IsNullOrEmpty(info.InsufficientFundsNotification) && + owner.World.WorldTick - lastNotificationTick >= info.InsufficientFundsNotificationDelay) + { + lastNotificationTick = owner.World.WorldTick; + Game.Sound.PlayNotification(owner.World.Map.Rules, owner, "Speech", info.InsufficientFundsNotification, owner.Faction.InternalName); + } + + return false; + } // Spend ore before cash Resources -= num; diff --git a/OpenRA.Mods.Common/Activities/Repair.cs b/OpenRA.Mods.Common/Activities/Repair.cs index 289ba0e5da..1eb37fd904 100644 --- a/OpenRA.Mods.Common/Activities/Repair.cs +++ b/OpenRA.Mods.Common/Activities/Repair.cs @@ -56,7 +56,7 @@ namespace OpenRA.Mods.Common.Activities Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", repairsUnits.StartRepairingNotification, self.Owner.Faction.InternalName); } - if (!self.Owner.PlayerActor.Trait().TakeCash(cost)) + if (!self.Owner.PlayerActor.Trait().TakeCash(cost, true)) { remainingTicks = 1; return this; diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index c004e194d3..dd5c9ba35c 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -298,7 +298,6 @@ - diff --git a/OpenRA.Mods.Common/Traits/Buildings/RepairableBuilding.cs b/OpenRA.Mods.Common/Traits/Buildings/RepairableBuilding.cs index ea89b45ea1..ea2d860345 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/RepairableBuilding.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/RepairableBuilding.cs @@ -115,7 +115,7 @@ namespace OpenRA.Mods.Common.Traits var cost = Math.Max(1, (hpToRepair * Info.RepairPercent * buildingValue) / (health.MaxHP * 100)); // TakeCash will return false if the player can't pay, and will stop him from contributing this Tick - var activePlayers = Repairers.Count(player => player.PlayerActor.Trait().TakeCash(cost)); + var activePlayers = Repairers.Count(player => player.PlayerActor.Trait().TakeCash(cost, true)); RepairActive = activePlayers > 0; diff --git a/OpenRA.Mods.Common/Traits/Player/InsufficientFundsWarning.cs b/OpenRA.Mods.Common/Traits/Player/InsufficientFundsWarning.cs deleted file mode 100644 index b76a5d50c3..0000000000 --- a/OpenRA.Mods.Common/Traits/Player/InsufficientFundsWarning.cs +++ /dev/null @@ -1,54 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2016 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 OpenRA.Traits; - -namespace OpenRA.Mods.Common.Traits -{ - [Desc("Provides the player with an audible warning when they run out of money while producing.")] - public class InsufficientFundsWarningInfo : ITraitInfo, Requires - { - [Desc("The speech to play for the warning.")] - public readonly string Notification = "InsufficientFunds"; - - public object Create(ActorInitializer init) { return new InsufficientFundsWarning(this); } - } - - public class InsufficientFundsWarning : INotifyInsufficientFunds - { - readonly InsufficientFundsWarningInfo info; - - bool played; - - public InsufficientFundsWarning(InsufficientFundsWarningInfo info) - { - this.info = info; - } - - void INotifyInsufficientFunds.InsufficientFunds(Actor self) - { - Game.RunAfterTick(() => - { - if (played) - return; - - played = true; - var owner = self.Owner; - Game.Sound.PlayNotification(self.World.Map.Rules, owner, "Speech", info.Notification, owner.Faction.InternalName); - }); - } - - void INotifyInsufficientFunds.SufficientFunds(Actor self) - { - played = false; - } - } -} diff --git a/OpenRA.Mods.Common/Traits/Player/ProductionQueue.cs b/OpenRA.Mods.Common/Traits/Player/ProductionQueue.cs index b3cb6df09f..594ce5d707 100644 --- a/OpenRA.Mods.Common/Traits/Player/ProductionQueue.cs +++ b/OpenRA.Mods.Common/Traits/Player/ProductionQueue.cs @@ -415,12 +415,8 @@ namespace OpenRA.Mods.Common.Traits public bool Started { get; private set; } public int Slowdown { get; private set; } - readonly INotifyInsufficientFunds[] insufficientFunds; - readonly Player owner; readonly PowerManager pm; - bool insufficientFundsPlayed; - public ProductionItem(ProductionQueue queue, string item, int cost, PowerManager pm, Action onComplete) { Item = item; @@ -429,8 +425,6 @@ namespace OpenRA.Mods.Common.Traits OnComplete = onComplete; Queue = queue; this.pm = pm; - owner = queue.Actor.Owner; - insufficientFunds = owner.PlayerActor.TraitsImplementing().ToArray(); } public void Tick(PlayerResources pr) @@ -441,13 +435,6 @@ namespace OpenRA.Mods.Common.Traits if (time > 0) RemainingTime = TotalTime = time; - // Don't play a QueuedAudio notification when we can't start building (because we don't have the money to) - // Also don't play it when the time to build is actually 0 (i.e. normally dev cheats) - // to prevent overlapping with the ReadyAudio notification - var initialCost = RemainingCost / RemainingTime; - if (time != 0 && initialCost != 0 && pr.Cash + pr.Resources > initialCost) - Game.Sound.PlayNotification(owner.World.Map.Rules, owner, "Speech", Queue.Info.QueuedAudio, owner.Faction.InternalName); - Started = true; } @@ -471,23 +458,8 @@ namespace OpenRA.Mods.Common.Traits } var costThisFrame = RemainingCost / RemainingTime; - if (costThisFrame != 0 && !pr.TakeCash(costThisFrame)) - { - if (!insufficientFundsPlayed) - { - insufficientFundsPlayed = true; - foreach (var funds in insufficientFunds) - funds.InsufficientFunds(owner.PlayerActor); - } - + if (costThisFrame != 0 && !pr.TakeCash(costThisFrame, true)) return; - } - - if (insufficientFundsPlayed) - insufficientFundsPlayed = false; - - foreach (var funds in insufficientFunds) - funds.SufficientFunds(owner.PlayerActor); RemainingCost -= costThisFrame; RemainingTime -= 1; diff --git a/OpenRA.Mods.Common/TraitsInterfaces.cs b/OpenRA.Mods.Common/TraitsInterfaces.cs index 7b355fb53c..a996d6e76a 100644 --- a/OpenRA.Mods.Common/TraitsInterfaces.cs +++ b/OpenRA.Mods.Common/TraitsInterfaces.cs @@ -124,11 +124,4 @@ namespace OpenRA.Mods.Common.Traits bool AdjacentWallCanConnect(Actor self, CPos wallLocation, string wallType, out CVec facing); void SetDirty(); } - - [RequireExplicitImplementation] - interface INotifyInsufficientFunds - { - void InsufficientFunds(Actor self); - void SufficientFunds(Actor self); - } } diff --git a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs index eb4b56edfb..95d193bf23 100644 --- a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs +++ b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs @@ -757,6 +757,19 @@ namespace OpenRA.Mods.Common.UtilityCommands node.Key = "EffectImage"; } + if (engineVersion < 20160408) + { + var traitNode = node.Value.Nodes.FirstOrDefault(n => n.Key == "InsufficientFundsWarning"); + if (traitNode != null) + { + var prNode = node.Value.Nodes.FirstOrDefault(n => n.Key == "PlayerResources"); + if (prNode != null) + prNode.Value.Nodes.Add(new MiniYamlNode("InsufficientFundsNotification", new MiniYaml("InsufficientFunds"))); + + node.Value.Nodes.Remove(traitNode); + } + } + UpgradeActorRules(engineVersion, ref node.Value.Nodes, node, depth + 1); } } diff --git a/OpenRA.Mods.Common/Widgets/ProductionPaletteWidget.cs b/OpenRA.Mods.Common/Widgets/ProductionPaletteWidget.cs index 0801a934b2..0f4661ff84 100644 --- a/OpenRA.Mods.Common/Widgets/ProductionPaletteWidget.cs +++ b/OpenRA.Mods.Common/Widgets/ProductionPaletteWidget.cs @@ -233,6 +233,7 @@ namespace OpenRA.Mods.Common.Widgets { // Queue a new item Game.Sound.Play(TabClick); + Game.Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.QueuedAudio, World.LocalPlayer.Faction.InternalName); World.IssueOrder(Order.StartProduction(CurrentQueue.Actor, icon.Name, handleCount)); return true; } diff --git a/mods/d2k/rules/player.yaml b/mods/d2k/rules/player.yaml index 807fd19362..c31633d836 100644 --- a/mods/d2k/rules/player.yaml +++ b/mods/d2k/rules/player.yaml @@ -61,6 +61,7 @@ Player: AllyRepair: PlayerResources: SelectableCash: 2500, 5000, 7000, 10000, 20000 + InsufficientFundsNotification: InsufficientFunds ActorGroupProxy: DeveloperMode: BaseAttackNotifier: @@ -86,4 +87,3 @@ Player: GlobalUpgradeManager: ResourceStorageWarning: AdviceInterval: 26 - InsufficientFundsWarning: diff --git a/mods/ra/rules/player.yaml b/mods/ra/rules/player.yaml index d442ad4cf5..05d155f158 100644 --- a/mods/ra/rules/player.yaml +++ b/mods/ra/rules/player.yaml @@ -43,6 +43,7 @@ Player: PowerManager: AllyRepair: PlayerResources: + InsufficientFundsNotification: InsufficientFunds ActorGroupProxy: DeveloperMode: GpsWatcher: @@ -72,4 +73,3 @@ Player: Image: iconchevrons Sequence: veteran ResourceStorageWarning: - InsufficientFundsWarning: diff --git a/mods/ts/rules/player.yaml b/mods/ts/rules/player.yaml index 7cffe960e3..4e6b611dad 100644 --- a/mods/ts/rules/player.yaml +++ b/mods/ts/rules/player.yaml @@ -40,6 +40,7 @@ Player: PowerManager: AllyRepair: PlayerResources: + InsufficientFundsNotification: InsufficientFunds ActorGroupProxy: DeveloperMode: Enabled: true @@ -51,4 +52,3 @@ Player: PlayerStatistics: PlaceBeacon: ResourceStorageWarning: - InsufficientFundsWarning: