229 lines
5.8 KiB
C#
229 lines
5.8 KiB
C#
#region Copyright & License Information
|
|
/*
|
|
* Copyright (c) The OpenRA Developers and Contributors
|
|
* 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 System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using OpenRA.Traits;
|
|
|
|
namespace OpenRA.Mods.Common.Traits
|
|
{
|
|
[TraitLocation(SystemActors.Player | SystemActors.EditorPlayer)]
|
|
public class PlayerResourcesInfo : TraitInfo, ILobbyOptions
|
|
{
|
|
[Desc("Descriptive label for the starting cash option in the lobby.")]
|
|
public readonly string DefaultCashDropdownLabel = "Starting Cash";
|
|
|
|
[Desc("Tooltip description for the starting cash option in the lobby.")]
|
|
public readonly string DefaultCashDropdownDescription = "The amount of cash that players start with";
|
|
|
|
[Desc("Starting cash options that are available in the lobby options.")]
|
|
public readonly int[] SelectableCash = { 2500, 5000, 10000, 20000 };
|
|
|
|
[Desc("Default starting cash option: should be one of the SelectableCash options.")]
|
|
public readonly int DefaultCash = 5000;
|
|
|
|
[Desc("Force the DefaultCash option by disabling changes in the lobby.")]
|
|
public readonly bool DefaultCashDropdownLocked = false;
|
|
|
|
[Desc("Whether to display the DefaultCash option in the lobby.")]
|
|
public readonly bool DefaultCashDropdownVisible = true;
|
|
|
|
[Desc("Display order for the DefaultCash option.")]
|
|
public readonly int DefaultCashDropdownDisplayOrder = 0;
|
|
|
|
[NotificationReference("Speech")]
|
|
[Desc("Speech notification to play when the player does not have any funds.")]
|
|
public readonly string InsufficientFundsNotification = null;
|
|
|
|
[FluentReference(optional: true)]
|
|
[Desc("Text notification to display when the player does not have any funds.")]
|
|
public readonly string InsufficientFundsTextNotification = null;
|
|
|
|
[Desc("Delay (in milliseconds) during which warnings will be muted.")]
|
|
public readonly int InsufficientFundsNotificationInterval = 30000;
|
|
|
|
[NotificationReference("Sounds")]
|
|
public readonly string CashTickUpNotification = null;
|
|
|
|
[NotificationReference("Sounds")]
|
|
public readonly string CashTickDownNotification = null;
|
|
|
|
[Desc("Monetary value of each resource type.", "Dictionary of [resource type]: [value per unit].")]
|
|
public readonly Dictionary<string, int> ResourceValues = new();
|
|
|
|
IEnumerable<LobbyOption> ILobbyOptions.LobbyOptions(MapPreview map)
|
|
{
|
|
var startingCash = SelectableCash.ToDictionary(c => c.ToStringInvariant(), c => "$" + c.ToString(NumberFormatInfo.CurrentInfo));
|
|
|
|
if (startingCash.Count > 0)
|
|
yield return new LobbyOption(map, "startingcash",
|
|
DefaultCashDropdownLabel, DefaultCashDropdownDescription, DefaultCashDropdownVisible, DefaultCashDropdownDisplayOrder,
|
|
startingCash, DefaultCash.ToStringInvariant(), DefaultCashDropdownLocked);
|
|
}
|
|
|
|
public override object Create(ActorInitializer init) { return new PlayerResources(init.Self, this); }
|
|
}
|
|
|
|
public class PlayerResources : ISync
|
|
{
|
|
public readonly PlayerResourcesInfo Info;
|
|
readonly Player owner;
|
|
|
|
public PlayerResources(Actor self, PlayerResourcesInfo info)
|
|
{
|
|
Info = info;
|
|
owner = self.Owner;
|
|
|
|
var startingCash = self.World.LobbyInfo.GlobalSettings
|
|
.OptionOrDefault("startingcash", info.DefaultCash.ToStringInvariant());
|
|
|
|
if (!int.TryParse(startingCash, out Cash))
|
|
Cash = info.DefaultCash;
|
|
|
|
lastNotificationTime = -Info.InsufficientFundsNotificationInterval;
|
|
}
|
|
|
|
[Sync]
|
|
public int Cash;
|
|
|
|
[Sync]
|
|
public int Resources;
|
|
|
|
[Sync]
|
|
public int ResourceCapacity;
|
|
|
|
public int Earned;
|
|
public int Spent;
|
|
|
|
long lastNotificationTime;
|
|
|
|
public int ChangeCash(int amount)
|
|
{
|
|
if (amount >= 0)
|
|
GiveCash(amount);
|
|
else
|
|
{
|
|
// Don't put the player into negative funds
|
|
amount = Math.Max(-GetCashAndResources(), amount);
|
|
|
|
TakeCash(-amount);
|
|
}
|
|
|
|
return amount;
|
|
}
|
|
|
|
public bool CanGiveResources(int amount)
|
|
{
|
|
return Resources + amount <= ResourceCapacity;
|
|
}
|
|
|
|
public void GiveResources(int num)
|
|
{
|
|
Resources += num;
|
|
Earned += num;
|
|
|
|
if (Resources > ResourceCapacity)
|
|
{
|
|
Earned -= Resources - ResourceCapacity;
|
|
Resources = ResourceCapacity;
|
|
}
|
|
}
|
|
|
|
public bool TakeResources(int num)
|
|
{
|
|
if (Resources < num) return false;
|
|
Resources -= num;
|
|
Spent += num;
|
|
|
|
return true;
|
|
}
|
|
|
|
public void GiveCash(int num)
|
|
{
|
|
if (Cash < int.MaxValue)
|
|
{
|
|
try
|
|
{
|
|
checked
|
|
{
|
|
Cash += num;
|
|
}
|
|
}
|
|
catch (OverflowException)
|
|
{
|
|
Cash = int.MaxValue;
|
|
}
|
|
}
|
|
|
|
if (Earned < int.MaxValue)
|
|
{
|
|
try
|
|
{
|
|
checked
|
|
{
|
|
Earned += num;
|
|
}
|
|
}
|
|
catch (OverflowException)
|
|
{
|
|
Earned = int.MaxValue;
|
|
}
|
|
}
|
|
}
|
|
|
|
public bool TakeCash(int num, bool notifyLowFunds = false)
|
|
{
|
|
if (GetCashAndResources() < num)
|
|
{
|
|
if (notifyLowFunds && Game.RunTime > lastNotificationTime + Info.InsufficientFundsNotificationInterval)
|
|
{
|
|
lastNotificationTime = Game.RunTime;
|
|
Game.Sound.PlayNotification(owner.World.Map.Rules, owner, "Speech", Info.InsufficientFundsNotification, owner.Faction.InternalName);
|
|
TextNotificationsManager.AddTransientLine(owner, Info.InsufficientFundsTextNotification);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Spend ore before cash
|
|
Resources -= num;
|
|
Spent += num;
|
|
if (Resources < 0)
|
|
{
|
|
Cash += Resources;
|
|
Resources = 0;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public void AddStorageCapacity(int capacity)
|
|
{
|
|
ResourceCapacity += capacity;
|
|
}
|
|
|
|
public void RemoveStorageCapacity(int capacity)
|
|
{
|
|
ResourceCapacity -= capacity;
|
|
|
|
if (Resources > ResourceCapacity)
|
|
Resources = ResourceCapacity;
|
|
}
|
|
|
|
public int GetCashAndResources()
|
|
{
|
|
return Cash + Resources;
|
|
}
|
|
}
|
|
}
|