C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
// #define TESTING
#if TESTING
using System.Diagnostics;
#endif
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;
using Facepunch;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Oxide.Core;
using Oxide.Core.Libraries;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Oxide.Plugins.BankSystemExtensionMethods;
using UnityEngine;
using Debug = UnityEngine.Debug;
using Random = UnityEngine.Random;
namespace Oxide.Plugins
{
[Info("Bank System", "Mevent", "1.3.8")]
public class BankSystem : RustPlugin
{
#region Fields
[PluginReference] private Plugin
ImageLibrary = null,
Notify = null,
UINotify = null,
Economics = null,
LangAPI = null;
private const string Layer = "UI.BankSystem";
private static BankSystem _instance;
private readonly Dictionary<ulong, ATMData> _atmByPlayer = new Dictionary<ulong, ATMData>();
private readonly List<VendingMachine> _vendingMachines = new List<VendingMachine>();
private const string VendingMachinePrefab =
"assets/prefabs/deployable/vendingmachine/vendingmachine.deployed.prefab";
private enum Transaction
{
Deposit,
Withdrawal,
Transfer
}
private bool _enabledImageLibrary;
#endregion
#region Config
private static Configuration _config;
private class Configuration
{
[JsonProperty(PropertyName = "Work with LangAPI?")]
public bool UseLangAPI = true;
[JsonProperty(PropertyName = "Work with Notify?")]
public bool UseNotify = true;
[JsonProperty(PropertyName = "Commands", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public string[] Commands = {"bank"};
[JsonProperty(PropertyName = "Permission (example: banksystem.use)")]
public string Permission = string.Empty;
[JsonProperty(PropertyName = "Starting balance")]
public int StartingBalance = 100;
[JsonProperty(PropertyName = "Card Image")]
public string CardImage = "https://i.ibb.co/ZMXtF1d/image.png";
[JsonProperty(PropertyName = "Transit Image")]
public string DepositImage = "https://i.ibb.co/R2NT67x/image.png";
[JsonProperty(PropertyName = "Withdraw Image")]
public string WithdrawImage = "https://i.ibb.co/qp6VLDm/image.png";
[JsonProperty(PropertyName = "Transfer Image")]
public string TransferImage = "https://i.ibb.co/T2ZNvFf/image.png";
[JsonProperty(PropertyName = "Exit Image")]
public string ExitImage = "https://i.ibb.co/BgssZ0p/image.png";
[JsonProperty(PropertyName = "Disable the close button in the ATM header")]
public bool AtmDisableCloser = false;
[JsonProperty(PropertyName = "Currency Settings")]
public CurrencySettings Currency = new CurrencySettings
{
ControlSplit = true,
DisplayName = "RUSTNote",
ShortName = "sticks",
Skin = 2536195910
};
[JsonProperty(PropertyName = "Card auto-creation")]
public bool CardAutoCreation = false;
[JsonProperty(PropertyName = "Use card expiration date?")]
public bool UseCardExpiry = true;
[JsonProperty(PropertyName = "Card expiry date (in days)")]
public int CardExpiryDays = 7;
[JsonProperty(PropertyName = "ATM Settings")]
public ATMSettings Atm = new ATMSettings
{
MinWithdrawal = 1,
MinDeposit = 1,
EnableDepositFee = true,
MinDepositFee = 0,
MaxDepositFee = 10,
StepDepositFee = 0.1f,
MinWithdrawalFee = 0,
MaxWithdrawalFee = 10,
EnableBreakage = true,
StepWithdrawalFee = 0.1f,
DisplayName = "ATM",
Skin = 2551771822,
Repair = new RepairSettings
{
Items = new List<RepairItemConf>
{
new RepairItemConf
{
ShortName = "scrap",
Amount = 2,
Skin = 0,
Title = string.Empty
},
new RepairItemConf
{
ShortName = "metalpipe",
Amount = 1,
Skin = 0,
Title = string.Empty
},
new RepairItemConf
{
ShortName = "metal.fragments",
Amount = 15,
Skin = 0,
Title = string.Empty
}
}
},
DefaultDepositFee = 1,
EnableWithdrawalFee = true,
DefaultWithdrawalFee = 1,
DefaultBreakPercent = 1,
BreakPercent = new Dictionary<string, float>
{
["banksystem.vip"] = 0.7f,
["banksystem.premium"] = 0.5f
},
Spawn = new SpawnSettings
{
ConfAddons = new ATMConf
{
DisplayName = "ATM",
DepositFee = 0,
WithdrawFee = 0
},
Monuments = new Dictionary<string, ATMPosition>
{
["compound"] = new ATMPosition
{
Enabled = true,
DisplayName = "ATM",
Position = new Vector3(-3.5f,
1.15f,
2.7f),
Rotation = -90,
DepositFee = 0,
WithdrawFee = 0
},
["bandit"] = new ATMPosition
{
Enabled = true,
DisplayName = "ATM",
Position = new Vector3(34.2f,
2.35f,
-24.7f),
Rotation = 135,
DepositFee = 0,
WithdrawFee = 0
}
}
},
ShopName = "ATM #{id}",
Commands = new[]
{
"secret.open.atm"
},
PermissionToOpenATMviaCommand = "banksystem.openatm",
NotifyPlayerWhenNoPermissionInCommandATM = false
};
[JsonProperty(PropertyName = "Tracking Settings")]
public TrackingSettings Tracking = new TrackingSettings
{
InHand = false,
CostTable = new Dictionary<string, float>
{
["sulfur.ore"] = 5f,
["metal.ore"] = 5f,
["hq.metal.ore"] = 5f,
["stone.ore"] = 5f,
["crate_elite"] = 10f,
["crate_normal"] = 7f,
["crate_normal_2"] = 4
},
CollectibleCostTable = new Dictionary<string, float>
{
["sulfur.ore"] = 0.5f,
["metal.ore"] = 0.5f,
["hq.metal.ore"] = 0.5f,
["stones"] = 0.5f
}
};
[JsonProperty(PropertyName = "Wipe Settings")]
public WipeSettings Wipe = new WipeSettings
{
Players = false,
Logs = true,
ATMs = true
};
[JsonProperty(PropertyName = "NPC Settings")]
public NPCSettings NPC = new NPCSettings
{
NPCs = new List<string>
{
"1234567",
"7654321",
"4644687478"
}
};
[JsonProperty(PropertyName = "Economy Settings")]
public EconomySettings Economy = new EconomySettings
{
Self = true,
AddHook = "Deposit",
BalanceHook = "Balance",
RemoveHook = "Withdraw",
PluginName = "Economics"
};
[JsonProperty(PropertyName = "Drop Settings", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<DropInfo> Drop = new List<DropInfo>
{
new DropInfo
{
Enabled = true,
PrefabName = "assets/bundled/prefabs/radtown/crate_normal.prefab",
DropChance = 50,
MinAmount = 2,
MaxAmount = 5
},
new DropInfo
{
Enabled = true,
PrefabName = "assets/bundled/prefabs/radtown/loot_barrel_2.prefab",
DropChance = 5,
MinAmount = 2,
MaxAmount = 5
},
new DropInfo
{
Enabled = true,
PrefabName = "assets/bundled/prefabs/radtown/loot_barrel_1.prefab",
DropChance = 5,
MinAmount = 2,
MaxAmount = 5
}
};
[JsonProperty(PropertyName = "Colors")]
public Colors Colors = new Colors
{
Color1 = new IColor("#0E0E10"),
Color2 = new IColor("#161617"),
Color3 = new IColor("#4B68FF"),
Color4 = new IColor("#74884A"),
Color5 = new IColor("#FF6060"),
Color6 = new IColor("#C4C4C4"),
Color7 = new IColor("#CD4632"),
Color8 = new IColor("#595651"),
Color9 = new IColor("#4B68FF", 50),
Color10 = new IColor("#4B68FF", 33),
Color11 = new IColor("#FFFFFF", 20),
Color12 = new IColor("#C4C4C4", 20),
Color13 = new IColor("#FFFFFF"),
Color14 = new IColor("#FFFFFF", 50),
Color15 = new IColor("#FFFFFF", 40),
Color16 = new IColor("#FFFFFF", 70),
Color17 = new IColor("#FFFFFF", 10),
Color18 = new IColor("#FFFFFF", 95),
Color19 = new IColor("#FFFFFF", 30),
};
[JsonProperty(PropertyName = "UI Settings")]
public UserInterface UI = new UserInterface
{
BankWidth = 900f,
BankHeight = 595f,
BankHeaderHeight = 70f,
BankHeaderWidth = 850f,
BankHeaderUpIndent = 65f,
ShowTransactionsHistory = true,
THFieldWidth = 190f,
THButtonMargin = 5f,
THButtonSize = 20f,
ShowGatherHistory = true,
GHFieldWidth = 190f,
GHButtonMargin = 5f,
GHButtonSize = 20f,
ShowCard = true,
CardWidth = 245f,
CardLeftIndent = 25f,
ShowTransfers = true,
Transfers = new LabelSettings
{
AnchorMin = "0 1", AnchorMax = "0 1",
OffsetMin = "25 -345",
OffsetMax = "175 -325",
Align = TextAnchor.MiddleLeft,
Font = "robotocondensed-bold.ttf",
FontSize = 16,
Color = new IColor("#FFFFFF")
},
RecentTransfersTitle = new LabelSettings
{
AnchorMin = "0 1", AnchorMax = "0 1",
OffsetMin = "25 -360",
OffsetMax = "175 -345",
Align = TextAnchor.MiddleLeft,
Font = "robotocondensed-regular.ttf",
FontSize = 10,
Color = new IColor("#FFFFFF", 50)
},
NoTransactions = new LabelSettings
{
AnchorMin = "0 1", AnchorMax = "0 1",
OffsetMin = "25 -490",
OffsetMax = "405 -360",
Align = TextAnchor.MiddleCenter,
Font = "robotocondensed-bold.ttf",
FontSize = 14,
Color = new IColor("#FFFFFF", 10)
},
TransferCard = new LabelSettings
{
AnchorMin = "0 1", AnchorMax = "0 1",
OffsetMin = "25 -515",
OffsetMax = "175 -500",
Align = TextAnchor.MiddleLeft,
Font = "robotocondensed-regular.ttf",
FontSize = 10,
Color = new IColor("#FFFFFF", 50)
},
TransferCardNumber = new LabelSettings
{
AnchorMin = "0 1", AnchorMax = "0 1",
OffsetMin = "25 -550",
OffsetMax = "175 -520",
Align = TextAnchor.MiddleLeft,
Font = "robotocondensed-regular.ttf",
FontSize = 10,
Color = new IColor("#FFFFFF")
},
TransferCardAmount = new LabelSettings
{
AnchorMin = "0 1", AnchorMax = "0 1",
OffsetMin = "185 -550",
OffsetMax = "335 -520",
FontSize = 10,
Font = "robotocondensed-regular.ttf",
Align = TextAnchor.MiddleLeft,
Color = new IColor("#FFFFFF")
},
TransferCardButton = new LabelSettings
{
AnchorMin = "0 1", AnchorMax = "0 1",
OffsetMin = "340 -550",
OffsetMax = "400 -520",
Align = TextAnchor.MiddleCenter,
Font = "robotocondensed-bold.ttf",
FontSize = 11,
Color = new IColor("#FFFFFF")
}
};
[JsonProperty(PropertyName = "Log Settings")]
public LogInfo Logs = new LogInfo
{
CollectGatherLogs = true,
CollectTransfersLogs = true
};
public VersionNumber Version;
}
private class LogInfo
{
[JsonProperty(PropertyName = "Collect Gather logs?")]
public bool CollectGatherLogs;
[JsonProperty(PropertyName = "Collect Transfers logs?")]
public bool CollectTransfersLogs;
}
private class UserInterface
{
[JsonProperty(PropertyName = "Bank | Width")]
public float BankWidth;
[JsonProperty(PropertyName = "Bank | Height")]
public float BankHeight;
[JsonProperty(PropertyName = "Bank Header | Width")]
public float BankHeaderWidth;
[JsonProperty(PropertyName = "Bank Header | Height")]
public float BankHeaderHeight;
[JsonProperty(PropertyName = "Bank Header | Up Indent")]
public float BankHeaderUpIndent;
[JsonProperty(PropertyName = "Show Transactions history?")]
public bool ShowTransactionsHistory;
[JsonProperty(PropertyName = "Transactions history | Field width")]
public float THFieldWidth;
[JsonProperty(PropertyName = "Transactions history | Page button margin")]
public float THButtonMargin;
[JsonProperty(PropertyName = "Transactions history | Page button size")]
public float THButtonSize;
[JsonProperty(PropertyName = "Show Gather history?")]
public bool ShowGatherHistory;
[JsonProperty(PropertyName = "Gather history | Field width")]
public float GHFieldWidth;
[JsonProperty(PropertyName = "Gather history | Page button margin")]
public float GHButtonMargin;
[JsonProperty(PropertyName = "Gather history | Page button size")]
public float GHButtonSize;
[JsonProperty(PropertyName = "Show card?")]
public bool ShowCard;
[JsonProperty(PropertyName = "Card | Width")]
public float CardWidth;
[JsonProperty(PropertyName = "Card | Left indent")]
public float CardLeftIndent;
[JsonProperty(PropertyName = "Show Transfers?")]
public bool ShowTransfers;
[JsonProperty(PropertyName = "Title: Transfers")]
public LabelSettings Transfers;
[JsonProperty(PropertyName = "Title: Recent Transfers")]
public LabelSettings RecentTransfersTitle;
[JsonProperty(PropertyName = "Title: Player has no transactions Title")]
public LabelSettings NoTransactions;
[JsonProperty(PropertyName = "Title: Transfer by card")]
public LabelSettings TransferCard;
[JsonProperty(PropertyName = "Transfer by card | Card number")]
public LabelSettings TransferCardNumber;
[JsonProperty(PropertyName = "Transfer by card | Amount")]
public LabelSettings TransferCardAmount;
[JsonProperty(PropertyName = "Transfer by card | Transfer button")]
public LabelSettings TransferCardButton;
}
private class LabelSettings : InterfacePosition
{
[JsonProperty(PropertyName = "FontSize")]
public int FontSize;
[JsonProperty(PropertyName = "Align")] [JsonConverter(typeof(StringEnumConverter))]
public TextAnchor Align;
[JsonProperty(PropertyName = "Color")] public IColor Color;
[JsonProperty(PropertyName = "Font")] public string Font;
}
private class InterfacePosition
{
public string AnchorMin;
public string AnchorMax;
public string OffsetMin;
public string OffsetMax;
}
private class IColor
{
[JsonProperty(PropertyName = "HEX")] public string Hex;
[JsonProperty(PropertyName = "Opacity (0 - 100)")]
public float Alpha;
[JsonIgnore] private string _color;
[JsonIgnore]
public string Get
{
get
{
if (string.IsNullOrEmpty(_color))
_color = GetColor();
return _color;
}
}
private string GetColor()
{
if (string.IsNullOrEmpty(Hex)) Hex = "#FFFFFF";
var str = Hex.Trim('#');
if (str.Length != 6) throw new Exception(Hex);
var r = byte.Parse(str.Substring(0, 2), NumberStyles.HexNumber);
var g = byte.Parse(str.Substring(2, 2), NumberStyles.HexNumber);
var b = byte.Parse(str.Substring(4, 2), NumberStyles.HexNumber);
return $"{(double) r / 255} {(double) g / 255} {(double) b / 255} {Alpha / 100}";
}
public IColor()
{
}
public IColor(string hex, float alpha = 100)
{
Hex = hex;
Alpha = alpha;
}
}
private class Colors
{
[JsonProperty(PropertyName = "First color")]
public IColor Color1;
[JsonProperty(PropertyName = "Second color")]
public IColor Color2;
[JsonProperty(PropertyName = "Third color")]
public IColor Color3;
[JsonProperty(PropertyName = "Fourth color")]
public IColor Color4;
[JsonProperty(PropertyName = "Fifth color")]
public IColor Color5;
[JsonProperty(PropertyName = "Sixth color")]
public IColor Color6;
[JsonProperty(PropertyName = "Seventh color")]
public IColor Color7;
[JsonProperty(PropertyName = "Eighth color")]
public IColor Color8;
[JsonProperty(PropertyName = "Ninth color")]
public IColor Color9;
[JsonProperty(PropertyName = "Tenth color")]
public IColor Color10;
[JsonProperty(PropertyName = "Eleventh color")]
public IColor Color11;
[JsonProperty(PropertyName = "Twelfth color")]
public IColor Color12;
[JsonProperty(PropertyName = "Thirteenth color")]
public IColor Color13;
[JsonProperty(PropertyName = "Fourteenth color")]
public IColor Color14;
[JsonProperty(PropertyName = "Fifteenth color")]
public IColor Color15;
[JsonProperty(PropertyName = "Sixteenth color")]
public IColor Color16;
[JsonProperty(PropertyName = "Seventeenth color")]
public IColor Color17;
[JsonProperty(PropertyName = "Eighteenth color")]
public IColor Color18;
[JsonProperty(PropertyName = "Nineteenth color")]
public IColor Color19;
}
public class DropInfo
{
[JsonProperty(PropertyName = "Enabled")]
public bool Enabled;
[JsonProperty(PropertyName = "Prefab")]
public string PrefabName;
[JsonProperty(PropertyName = "Chance")]
public int DropChance;
[JsonProperty(PropertyName = "Min Amount")]
public int MinAmount;
[JsonProperty(PropertyName = "Max Amount")]
public int MaxAmount;
}
private class EconomySettings
{
[JsonProperty(PropertyName = "Use own economic system?")]
public bool Self;
[JsonProperty(PropertyName = "Plugin name")]
public string PluginName;
[JsonProperty(PropertyName = "Balance add hook")]
public string AddHook;
[JsonProperty(PropertyName = "Balance remove hook")]
public string RemoveHook;
[JsonProperty(PropertyName = "Balance show hook")]
public string BalanceHook;
public double ShowBalance(BasePlayer player)
{
return ShowBalance(player.UserIDString);
}
public double ShowBalance(ulong player)
{
return ShowBalance(player.ToString());
}
private double ShowBalance(string player)
{
if (Self) return _instance.Balance(player);
var plugin = _instance?.plugins?.Find(PluginName);
if (plugin == null) return 0;
return Convert.ToDouble(Math.Floor(Convert.ToDouble(plugin.Call(BalanceHook, player))).ToString("0.00"));
}
public void AddBalance(BasePlayer player, int amount)
{
AddBalance(player.UserIDString, amount);
}
private void AddBalance(ulong player, int amount)
{
AddBalance(player.ToString(), amount);
}
private void AddBalance(string player, int amount)
{
if (Self)
{
_instance.Deposit(player, amount);
return;
}
var plugin = _instance?.plugins.Find(PluginName);
if (plugin == null) return;
switch (PluginName)
{
case "Economics":
plugin.Call(AddHook, player, (double) amount);
break;
default:
plugin.Call(AddHook, player, amount);
break;
}
}
public bool RemoveBalance(BasePlayer player, int amount)
{
return RemoveBalance(player.UserIDString, amount);
}
private bool RemoveBalance(ulong player, int amount)
{
return RemoveBalance(player.ToString(), amount);
}
private bool RemoveBalance(string player, int amount)
{
if (ShowBalance(player) < amount) return false;
if (Self) return _instance.Withdraw(player, amount);
var plugin = _instance?.plugins.Find(PluginName);
if (plugin == null) return false;
switch (PluginName)
{
case "Economics":
plugin.Call(RemoveHook, player, (double) amount);
break;
default:
plugin.Call(RemoveHook, player, amount);
break;
}
return true;
}
public bool Transfer(ulong member, ulong target, int amount)
{
if (!RemoveBalance(member, amount)) return false;
AddBalance(target, amount);
return true;
}
}
private class NPCSettings
{
[JsonProperty(PropertyName = "NPCs", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<string> NPCs = new List<string>();
}
private class WipeSettings
{
[JsonProperty(PropertyName = "Wipe Players?")]
public bool Players;
[JsonProperty(PropertyName = "Wipe Logs?")]
public bool Logs;
[JsonProperty(PropertyName = "Wipe ATMs?")]
public bool ATMs;
}
private class SpawnSettings
{
[JsonProperty(PropertyName = "Monuments", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, ATMPosition> Monuments;
[JsonProperty(PropertyName = "Settings for ATMs from MonumentAddons")]
public ATMConf ConfAddons;
}
private class ATMConf
{
[JsonProperty(PropertyName = "Display Name")]
public string DisplayName;
[JsonProperty(PropertyName = "Deposit Fee")]
public float DepositFee;
[JsonProperty(PropertyName = "Withdraw Fee")]
public float WithdrawFee;
}
private class ATMPosition : ATMConf
{
[JsonProperty(PropertyName = "Enabled")]
public bool Enabled;
[JsonProperty(PropertyName = "Position")]
public Vector3 Position;
[JsonProperty(PropertyName = "Rotation")]
public float Rotation;
}
private class TrackingSettings
{
[JsonProperty(PropertyName = "Handing out an award?")]
public bool InHand;
[JsonProperty(PropertyName = "Cost Table (shortname - cost)",
ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, float> CostTable;
[JsonProperty(PropertyName = "Collectible Items Cost Table (shortname - cost)",
ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, float> CollectibleCostTable;
}
private class CurrencySettings
{
[JsonProperty(PropertyName =
"Enable item split control? (if there are errors with stack plugins - it is worth turning off)")]
public bool ControlSplit;
[JsonProperty(PropertyName = "Display Name")]
public string DisplayName;
[JsonProperty(PropertyName = "Short Name")]
public string ShortName;
[JsonProperty(PropertyName = "Skin")] public ulong Skin;
public Item ToItem(int amount = 1)
{
var item = ItemManager.CreateByName(ShortName, amount, Skin);
if (item == null)
{
Debug.LogError($"Error creating item with ShortName: '{ShortName}'");
return null;
}
if (!string.IsNullOrEmpty(DisplayName)) item.name = DisplayName;
return item;
}
}
private class ATMSettings
{
#region Fields
[JsonProperty(PropertyName = "Minimum deposit (amount)")]
public float MinDeposit;
[JsonProperty(PropertyName = "Minimum withdrawal (amount)")]
public float MinWithdrawal;
[JsonProperty(PropertyName = "Enable Deposit fee?")]
public bool EnableDepositFee;
[JsonProperty(PropertyName = "Minimum deposit fee")]
public float MinDepositFee;
[JsonProperty(PropertyName = "Maximum deposit fee")]
public float MaxDepositFee;
[JsonProperty(PropertyName = "Default deposit fee")]
public float DefaultDepositFee;
[JsonProperty(PropertyName = "Step deposit fee")]
public float StepDepositFee;
[JsonProperty(PropertyName = "Enable Withdrawal fee?")]
public bool EnableWithdrawalFee;
[JsonProperty(PropertyName = "Minimum withdrawal fee")]
public float MinWithdrawalFee;
[JsonProperty(PropertyName = "Maximum withdrawal fee")]
public float MaxWithdrawalFee;
[JsonProperty(PropertyName = "Default withdrawal fee")]
public float DefaultWithdrawalFee;
[JsonProperty(PropertyName = "Step withdrawal fee")]
public float StepWithdrawalFee;
[JsonProperty(PropertyName = "Enable breakage?")]
public bool EnableBreakage = true;
[JsonProperty(PropertyName = "Default breakage percentage during operation")]
public float DefaultBreakPercent;
[JsonProperty(PropertyName = "Breakage percentage during operation",
ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, float> BreakPercent = new Dictionary<string, float>();
[JsonProperty(PropertyName = "Repair Settings")]
public RepairSettings Repair;
[JsonProperty(PropertyName = "Display Name")]
public string DisplayName;
[JsonProperty(PropertyName = "Skin")] public ulong Skin;
[JsonProperty(PropertyName = "Spawn Settings")]
public SpawnSettings Spawn;
[JsonProperty(PropertyName = "Shop Name ({id} {owner})")]
public string ShopName;
[JsonProperty(PropertyName = "Commands to open ATM menu",
ObjectCreationHandling = ObjectCreationHandling.Replace)]
public string[] Commands = { };
[JsonProperty(PropertyName = "Permission to open ATM menu via command")]
public string PermissionToOpenATMviaCommand = string.Empty;
[JsonProperty(PropertyName =
"Notify a player when they don't have permissions when opening the ATM menu via command?")]
public bool NotifyPlayerWhenNoPermissionInCommandATM;
#endregion
public Item ToItem()
{
var item = ItemManager.CreateByName("vending.machine", 1, Skin);
if (item == null)
return null;
if (!string.IsNullOrEmpty(DisplayName)) item.name = DisplayName;
return item;
}
}
private class RepairSettings
{
[JsonProperty(PropertyName = "Items (for 1%)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<RepairItemConf> Items = new List<RepairItemConf>();
}
private class RepairItemConf
{
[JsonProperty(PropertyName = "Short Name")]
public string ShortName;
[JsonProperty(PropertyName = "Amount (for 1%)")]
public float Amount;
[JsonProperty(PropertyName = "Skin")] public ulong Skin;
[JsonProperty(PropertyName = "Title (empty - default)")]
public string Title;
[JsonIgnore] private string _publicTitle;
[JsonIgnore]
public string PublicTitle
{
get
{
if (string.IsNullOrEmpty(_publicTitle))
{
if (string.IsNullOrEmpty(Title))
_publicTitle = ItemManager.FindItemDefinition(ShortName)?.displayName.translated ??
"UNKNOWN";
else
_publicTitle = Title;
}
return _publicTitle;
}
}
}
protected override void LoadConfig()
{
base.LoadConfig();
try
{
_config = Config.ReadObject<Configuration>();
if (_config == null) throw new Exception();
if (_config.Version < Version)
UpdateConfigValues();
SaveConfig();
}
catch (Exception ex)
{
PrintError("Your configuration file contains an error.Using default configuration values.");
Debug.LogError(ex.Message);
LoadDefaultConfig();
}
}
protected override void SaveConfig()
{
Config.WriteObject(_config);
}
protected override void LoadDefaultConfig()
{
_config = new Configuration();
}
private void UpdateConfigValues()
{
PrintWarning("Config update detected! Updating config values...");
//var baseConfig = new Configuration();
if (_config.Version != default(VersionNumber))
{
if (_config.Version < new VersionNumber(1, 3, 0))
{
ConvertPlayerData();
ConvertPlayerLogs();
}
if (_config.Version < new VersionNumber(1, 3, 6))
{
var color1 = Config["Colors", "Color 1"].ToString();
var color2 = Config["Colors", "Color 2"].ToString();
var color3 = Config["Colors", "Color 3"].ToString();
var color4 = Config["Colors", "Color 4"].ToString();
var color5 = Config["Colors", "Color 5"].ToString();
var color6 = Config["Colors", "Color 6"].ToString();
var color7 = Config["Colors", "Color 7"].ToString();
var color8 = Config["Colors", "Color 8"].ToString();
_config.Colors.Color1 = new IColor(color1);
_config.Colors.Color2 = new IColor(color2);
_config.Colors.Color3 = new IColor(color3);
_config.Colors.Color4 = new IColor(color4);
_config.Colors.Color5 = new IColor(color5);
_config.Colors.Color6 = new IColor(color6);
_config.Colors.Color7 = new IColor(color7);
_config.Colors.Color8 = new IColor(color8);
_config.Colors.Color9 = new IColor(color3, 50);
_config.Colors.Color10 = new IColor(color3, 33);
_config.Colors.Color12 = new IColor(color6, 20);
if (_config.CardImage.Equals("https://i.imgur.com/Br9z7Ou.png"))
_config.CardImage = "https://i.ibb.co/ZMXtF1d/image.png";
if (_config.DepositImage.Equals("https://i.imgur.com/h2bqMu4.png"))
_config.DepositImage = "https://i.ibb.co/R2NT67x/image.png";
if (_config.WithdrawImage.Equals("https://i.imgur.com/lwVwxm3.png"))
_config.WithdrawImage = "https://i.ibb.co/qp6VLDm/image.png";
if (_config.TransferImage.Equals("https://i.imgur.com/TBIxUnz.png"))
_config.TransferImage = "https://i.ibb.co/T2ZNvFf/image.png";
if (_config.ExitImage.Equals("https://i.imgur.com/OGoMu9N.png"))
_config.ExitImage = "https://i.ibb.co/BgssZ0p/image.png";
}
}
_config.Version = Version;
PrintWarning("Config update completed!");
SaveConfig();
}
#endregion
#region Data
private ATMsData _atms;
#region Save
private void SaveATMs()
{
Interface.Oxide.DataFileSystem.WriteObject($"{Name}/ATMs", _atms);
}
#endregion
#region Load
private void LoadData()
{
LoadATMs();
}
private void LoadATMs()
{
try
{
_atms = Interface.Oxide.DataFileSystem.ReadObject<ATMsData>($"{Name}/ATMs");
}
catch (Exception e)
{
PrintError(e.ToString());
}
if (_atms == null) _atms = new ATMsData();
}
#endregion
#region Wipe
private void WipeData()
{
WipeATMs();
}
private void WipeATMs()
{
if (_atms == null)
LoadATMs();
_atms.ATMs?.Clear();
_atms.LastATMID = 0;
PrintWarning("ATMs wiped!");
}
#endregion
#region Logs
private class TransferData
{
[JsonProperty(PropertyName = "Type")] [JsonConverter(typeof(StringEnumConverter))]
public Transaction Type;
[JsonProperty(PropertyName = "Amount")]
public int Amount;
[JsonProperty(PropertyName = "Sender ID")]
public ulong SenderId;
[JsonProperty(PropertyName = "Target ID")]
public ulong TargetId;
public void Get(BasePlayer player, ref CuiElementContainer container, string parent)
{
var color = string.Empty;
var icon = string.Empty;
var symbol = string.Empty;
var title = string.Empty;
var description = string.Empty;
#region Icon
switch (Type)
{
case Transaction.Deposit:
{
color = _config.Colors.Color3.Get;
icon = _instance.Msg(player, DepositIconTitle);
symbol = _instance.Msg(player, DepositSymbolTitle);
title = _instance.Msg(player, DepositOperationTitle);
description = _instance.Msg(player, DepositOperationDescription);
break;
}
case Transaction.Withdrawal:
{
color = _config.Colors.Color5.Get;
icon = _instance.Msg(player, WithdrawalIconTitle);
symbol = _instance.Msg(player, WithdrawalSymbolTitle);
title = _instance.Msg(player, WithdrawalOperationTitle);
description = _instance.Msg(player, WithdrawalOperationDescription);
break;
}
case Transaction.Transfer:
{
var self = TargetId == 0 && SenderId != 0;
if (self)
{
color = _config.Colors.Color3.Get;
icon = _instance.Msg(player, SelfTransferlIconTitle);
symbol = _instance.Msg(player, SelfTransferSymbolTitle);
description = _instance.Msg(player, SelfTransferOperationDescription,
PlayerData.GetNotLoad(SenderId.ToString())?.DisplayName);
}
else
{
color = _config.Colors.Color5.Get;
icon = _instance.Msg(player, TransferlIconTitle);
symbol = _instance.Msg(player, TransferSymbolTitle);
description = _instance.Msg(player, TransferOperationDescription,
PlayerData.GetNotLoad(TargetId.ToString())?.DisplayName);
}
title = _instance.Msg(player, TransferOperationTitle);
break;
}
}
container.Add(new CuiPanel
{
RectTransform =
{
AnchorMin = "0 0", AnchorMax = "0 0",
OffsetMin = "5 5", OffsetMax = "30 30"
},
Image =
{
Color = color
}
}, parent, parent + ".Icon");
container.Add(new CuiLabel
{
RectTransform =
{
AnchorMin = "0 0", AnchorMax = "1 1"
},
Text =
{
Text = $"{icon}",
Align = TextAnchor.MiddleCenter,
Font = "robotocondensed-bold.ttf",
FontSize = 20,
Color = _config.Colors.Color13.Get
}
}, parent + ".Icon");
#endregion
#region Title
container.Add(new CuiLabel
{
RectTransform =
{
AnchorMin = "0 0.5", AnchorMax = "1 1",
OffsetMin = "35 0", OffsetMax = "-37.5 0"
},
Text =
{
Text = $"{title}",
Align = TextAnchor.LowerLeft,
Font = "robotocondensed-regular.ttf",
FontSize = 10,
Color = _config.Colors.Color13.Get
}
}, parent);
container.Add(new CuiLabel
{
RectTransform =
{
AnchorMin = "0 0", AnchorMax = "1 0.5",
OffsetMin = "35 0", OffsetMax = "-37.5 0"
},
Text =
{
Text = $"{description}",
Align = TextAnchor.UpperLeft,
Font = "robotocondensed-regular.ttf",
FontSize = 10,
Color = _config.Colors.Color14.Get
}
}, parent);
#endregion
#region Value
container.Add(new CuiLabel
{
RectTransform =
{
AnchorMin = "0 0", AnchorMax = "1 1",
OffsetMin = "0 0",
OffsetMax = "-10 0"
},
Text =
{
Text = _instance.Msg(player, OperationsValueFormat, symbol, Amount),
Align = TextAnchor.MiddleRight,
Font = "robotocondensed-regular.ttf",
FontSize = 10,
Color = color
}
}, parent);
#endregion
}
}
private enum GatherLogType
{
Gather,
Loot,
Collect,
Kill
}
private class GatherLogData
{
[JsonProperty(PropertyName = "Type")] [JsonConverter(typeof(StringEnumConverter))]
public GatherLogType Type;
[JsonProperty(PropertyName = "Short Name")]
public string ShortName;
[JsonProperty(PropertyName = "Amount")]
public int Amount;
}
#endregion
#region ATMs
private class ATMsData
{
[JsonProperty(PropertyName = "Last ATM ID")]
public int LastATMID;
[JsonProperty(PropertyName = "ATMs", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<ATMData> ATMs = new List<ATMData>();
}
private class ATMData
{
[JsonProperty(PropertyName = "Enity ID")]
public ulong EntityID;
[JsonProperty(PropertyName = "ATM ID")]
public int ID;
[JsonProperty(PropertyName = "Owner Id")]
public ulong OwnerId;
[JsonProperty(PropertyName = "Withdrawal Fee")]
public float WithdrawalFee;
[JsonProperty(PropertyName = "Deposit Fee")]
public float DepositFee;
[JsonProperty(PropertyName = "Condition")]
public float Condition;
[JsonProperty(PropertyName = "Balance")]
public float Balance;
[JsonProperty(PropertyName = "Is Admin")]
public bool IsAdmin;
public bool IsOwner(BasePlayer player)
{
return IsOwner(player.userID);
}
public bool IsOwner(ulong userId)
{
return OwnerId == userId;
}
public void LoseCondition()
{
if (IsAdmin)
return;
Condition -= LoseConditionAmount();
}
private float LoseConditionAmount()
{
var result = _config.Atm.DefaultBreakPercent;
_config.Atm.BreakPercent.Where(x => OwnerId.HasPermission(x.Key)).ForEach(check =>
{
if (result > check.Value) result = check.Value;
});
return result;
}
public bool CanOpen()
{
return Condition - LoseConditionAmount() > 0;
}
}
#endregion
#endregion
#region Hooks
private void Init()
{
_instance = this;
LoadData();
if (_config.Drop.Count == 0)
Unsubscribe(nameof(OnLootSpawn));
#if TESTING
StopwatchWrapper.OnComplete = DebugMessage;
#endif
}
private void OnServerInitialized(bool initial)
{
LoadImages();
if (_config.Currency.ControlSplit == false)
Unsubscribe(nameof(OnItemSplit));
if (Economics)
Unsubscribe(nameof(Balance));
RegisterPermissions();
RegisterCommands();
foreach (var player in BasePlayer.activePlayerList)
OnPlayerConnected(player);
RenameATMs();
timer.In(20, SpawnATMs);
}
private void OnPlayerConnected(BasePlayer player)
{
if (player == null || !player.userID.IsSteamId()) return;
GetAvatar(player.userID,
avatar => ImageLibrary?.Call("AddImage", avatar, $"avatar_{player.UserIDString}"));
#if TESTING
Debug.Log($"[OnPlayerConnected] called GetOrCreate with id={player.UserIDString}");
#endif
var data = PlayerData.GetOrCreate(player.UserIDString);
if (data == null) return;
data.DisplayName = player.displayName;
if (_config.UseCardExpiry)
CheckCard(player.userID);
if (_config.CardAutoCreation && !HasCard(player))
CreateCard(player);
}
private void OnPlayerDisconnected(BasePlayer player)
{
UnloadAndSavePlayer(player.UserIDString);
}
private void OnServerSave()
{
timer.In(Random.Range(2, 7), ClearDataCache);
timer.In(Random.Range(2, 7), SaveATMs);
}
private void Unload()
{
try
{
foreach (var player in BasePlayer.activePlayerList)
{
CuiHelper.DestroyUi(player, Layer);
UnloadAndSavePlayer(player.UserIDString);
}
_vendingMachines.ForEach(entity =>
{
if (entity != null)
entity.Kill();
});
SaveATMs();
}
finally
{
_instance = null;
_config = null;
}
}
#region Wipe
private void OnNewSave(string filename)
{
if (_config.Wipe.ATMs) WipeATMs();
}
#endregion
#region Loot
private void OnLootSpawn(LootContainer container)
{
if (container == null || _config.Drop.Count <= 0) return;
var dropInfo = _config.Drop.Find(x => x.Enabled && x.PrefabName.Contains(container.PrefabName));
if (dropInfo == null || Random.Range(0, 100) > dropInfo.DropChance) return;
NextTick(() =>
{
if (container == null) return;
var inventory = container.inventory;
if (inventory == null) return;
if (inventory.capacity <= inventory.itemList.Count)
inventory.capacity = inventory.itemList.Count + 1;
_config.Currency.ToItem(Random.Range(dropInfo.MinAmount, dropInfo.MaxAmount))
?.MoveToContainer(inventory);
});
}
#endregion
#region NPC
private void OnUseNPC(BasePlayer npc, BasePlayer player)
{
if (player == null || npc == null || !_config.NPC.NPCs.Contains(npc.UserIDString)) return;
if (!string.IsNullOrEmpty(_config.Permission) && !player.HasPermission(_config.Permission))
{
SendNotify(player, NoPermissions, 1);
return;
}
MainUi(player, first: true);
}
#endregion
#region ATM
private void OnEntitySpawned(VendingMachine entity)
{
NextTick(() =>
{
if (entity == null ||
entity.skinID != _config.Atm.Skin ||
_atms.ATMs.Exists(x => x.EntityID == entity.net.ID.Value))
return;
var data = new ATMData
{
ID = ++_atms.LastATMID,
EntityID = entity.net.ID.Value,
OwnerId = 0,
Balance = 0,
Condition = 100,
DepositFee = _config.Atm.Spawn.ConfAddons.DepositFee,
WithdrawalFee = _config.Atm.Spawn.ConfAddons.WithdrawFee,
IsAdmin = true
};
_atms.ATMs.Add(data);
if (!string.IsNullOrEmpty(_config.Atm.ShopName))
{
entity.shopName = _config.Atm.ShopName.Replace("{id}", data.ID.ToString()).Replace("{owner}", _config.Atm.Spawn.ConfAddons.DisplayName);
entity.UpdateMapMarker();
}
});
}
private void OnEntityBuilt(Planner plan, GameObject go)
{
if (plan == null || go == null) return;
var entity = go.ToBaseEntity() as VendingMachine;
if (entity == null) return;
var player = plan.GetOwnerPlayer();
if (player == null) return;
var item = player.GetActiveItem();
if (item == null || item.skin != _config.Atm.Skin) return;
var data = new ATMData
{
ID = ++_atms.LastATMID,
EntityID = entity.net.ID.Value,
OwnerId = player.userID,
Balance = 0,
Condition = 100,
DepositFee = _config.Atm.DefaultDepositFee,
WithdrawalFee = _config.Atm.DefaultWithdrawalFee
};
_atms.ATMs.Add(data);
if (!string.IsNullOrEmpty(_config.Atm.ShopName))
{
entity.shopName = _config.Atm.ShopName.Replace("{id}", data.ID.ToString()).Replace("{owner}", player.displayName);
entity.UpdateMapMarker();
}
}
private void OnEntityDeath(VendingMachine entity, HitInfo info)
{
if (entity == null || entity.net == null)
return;
_atms.ATMs.RemoveAll(x => x.EntityID == entity.net.ID.Value);
}
private bool? CanUseVending(BasePlayer player, VendingMachine machine)
{
if (machine == null ||
player == null ||
machine.skinID != _config.Atm.Skin) return null;
var data = _atms.ATMs.Find(x => x.EntityID == machine.net.ID.Value);
if (data == null)
return null;
if (!HasCard(player))
{
SendNotify(player, NotBankCard, 1);
return false;
}
if (!data.CanOpen())
{
SendNotify(player, BrokenATM, 1);
return false;
}
_atmByPlayer[player.userID] = data;
ATMUi(player, First: true);
return false;
}
private void OnEntityKill(VendingMachine machine)
{
if (machine == null || machine.skinID != _config.Atm.Skin) return;
LogToFile(Name, Environment.StackTrace, this);
}
#endregion
#region Split
private Item OnItemSplit(Item item, int amount)
{
if (item == null || item.info.shortname != _config.Currency.ShortName ||
_config.Currency.Skin != item.skin) return null;
item.amount -= amount;
var newItem = ItemManager.CreateByItemID(item.info.itemid, 1, item.skin);
newItem.amount = amount;
newItem.condition = item.condition;
if (!string.IsNullOrEmpty(item.name)) newItem.name = item.name;
if (item.IsBlueprint()) newItem.blueprintTarget = item.blueprintTarget;
item.MarkDirty();
return newItem;
}
private object CanCombineDroppedItem(DroppedItem droppedItem, DroppedItem targetItem)
{
if (droppedItem == null || targetItem == null) return null;
var item = droppedItem.GetItem();
if (item == null) return null;
var tItem = targetItem.GetItem();
if (tItem == null || item.skin == tItem.skin) return null;
return item.skin == _config.Currency.Skin || tItem.skin == _config.Currency.Skin;
}
private object CanStackItem(Item item, Item targetItem)
{
if (item == null || targetItem == null || item.skin == targetItem.skin) return null;
return item.info.shortname == targetItem.info.shortname &&
(item.skin == _config.Currency.Skin || targetItem.skin == _config.Currency.Skin) &&
item.skin == targetItem.skin
? (object) (item.amount + targetItem.amount < item.info.stackable)
: null;
}
#endregion
#region Tracking
#region Gather Tracking
private void OnCollectiblePickup(CollectibleEntity collectible, BasePlayer player)
{
foreach (var item in collectible.itemList) OnCollect(player, item.itemDef.shortname, (int) item.amount);
}
private void OnCropGather(GrowableEntity plant, Item item, BasePlayer player)
{
OnGather(player, item.info.shortname, item.amount);
}
private void OnEntityDeath(ResourceEntity entity, HitInfo info)
{
if (entity == null || info == null) return;
var initiatorPlayer = info.InitiatorPlayer;
if (initiatorPlayer == null) return;
var resourceEntity = entity.resourceDispenser;
if (resourceEntity == null || resourceEntity.gatherType != ResourceDispenser.GatherType.Ore) return;
OnGather(initiatorPlayer, entity.ShortPrefabName, 1);
}
private void OnGather(BasePlayer player, string shortname, int amount)
{
if (player == null || string.IsNullOrEmpty(shortname) || amount <= 0) return;
AddPlayerTracking(GatherLogType.Gather, player, shortname, amount);
}
private void OnCollect(BasePlayer player, string shortname, int amount)
{
if (player == null || string.IsNullOrEmpty(shortname) || amount <= 0) return;
AddPlayerTracking(GatherLogType.Collect, player, shortname, amount);
}
#endregion
#region Loot
private readonly Dictionary<ulong, ulong> _lootedContainers = new Dictionary<ulong, ulong>();
private void OnLootEntity(BasePlayer player, LootContainer container)
{
if (player == null || container == null || container.net == null || !container.net.ID.IsValid) return;
var netID = container.net.ID.Value;
if (_lootedContainers.ContainsKey(netID)) return;
_lootedContainers.Add(netID, player.userID);
AddPlayerTracking(GatherLogType.Loot, player, container.ShortPrefabName);
}
#endregion
#region Players
private void OnEntityDeath(BaseCombatEntity entity, HitInfo info)
{
if (entity == null || entity.net == null || info == null)
return;
var initiator = info.InitiatorPlayer;
if (initiator == null) return;
var isNpc = entity.IsNpc || (entity as BasePlayer)?.userID.IsSteamId() == false;
if (!isNpc) return;
AddPlayerTracking(GatherLogType.Kill, initiator, entity.ShortPrefabName);
}
#endregion
#endregion
#region Image Library
private void OnPluginLoaded(Plugin plugin)
{
if (plugin.Name == "ImageLibrary") _enabledImageLibrary = true;
}
private void OnPluginUnloaded(Plugin plugin)
{
if (plugin.Name == "ImageLibrary") _enabledImageLibrary = false;
}
#endregion
#endregion
#region Commands
private void CmdOpenBank(IPlayer cov, string command, string[] args)
{
var player = cov?.Object as BasePlayer;
if (player == null) return;
if (_enabledImageLibrary == false)
{
SendNotify(player, NoILError, 1);
BroadcastILNotInstalled();
return;
}
if (!string.IsNullOrEmpty(_config.Permission) &&
!player.HasPermission(_config.Permission))
{
SendNotify(player, NoPermissions, 1);
return;
}
MainUi(player, first: true);
}
[ConsoleCommand("UI_BankSystem")]
private void CmdConsoleBank(ConsoleSystem.Arg arg)
{
var player = arg?.Player();
if (player == null || !arg.HasArgs()) return;
#if TESTING
try
{
#endif
switch (arg.Args[0])
{
case "close":
{
_atmByPlayer.Remove(player.userID);
break;
}
case "cardcreate":
{
CreateCard(player);
MainUi(player);
break;
}
case "page":
{
ulong targetId;
int amount, transactionPage, gatherPage;
if (!arg.HasArgs(5) ||
!int.TryParse(arg.Args[1], out amount) ||
!ulong.TryParse(arg.Args[2], out targetId) ||
!int.TryParse(arg.Args[3], out transactionPage) ||
!int.TryParse(arg.Args[4], out gatherPage)) return;
MainUi(player, amount, targetId, transactionPage, gatherPage);
break;
}
case "setamount":
{
ulong targetId;
int amount, transactionPage, gatherPage;
if (!arg.HasArgs(5) ||
!ulong.TryParse(arg.Args[1], out targetId) ||
!int.TryParse(arg.Args[2], out transactionPage) ||
!int.TryParse(arg.Args[3], out gatherPage) ||
!int.TryParse(arg.Args[4], out amount)) return;
MainUi(player, amount, targetId, transactionPage, gatherPage);
break;
}
case "select":
{
int amount, type, transactionPage, gatherPage;
ulong target;
if (!arg.HasArgs(6)
|| !int.TryParse(arg.Args[1], out type)
|| !int.TryParse(arg.Args[2], out amount)
|| !ulong.TryParse(arg.Args[3], out target)
|| !int.TryParse(arg.Args[4], out transactionPage)
|| !int.TryParse(arg.Args[5], out gatherPage)) return;
if (type == 0)
MainUi(player, amount, target, transactionPage, gatherPage, true);
else
ATMUi(player, 4, amount, target, true);
break;
}
case "settransferinfo":
{
int amount;
ulong target;
if (!arg.HasArgs(3) || !int.TryParse(arg.Args[1], out amount) || amount <= 0
|| !ulong.TryParse(arg.Args[2], out target)) return;
MainUi(player, amount, target);
break;
}
case "ui_transfer":
{
int amount;
ulong target;
if (!arg.HasArgs(3) ||
!int.TryParse(arg.Args[1], out amount) || amount <= 0 ||
!ulong.TryParse(arg.Args[2], out target)) return;
if (_config.Economy.ShowBalance(player) < amount)
{
SendNotify(player, NotEnoughMoney, 1);
return;
}
_config.Economy.Transfer(player.userID, target, amount);
var targetPlayer = RelationshipManager.FindByID(target);
if (t
// ... [Code preview truncated due to length. Full source in attached file] ...