C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Plugins;
using UnityEngine;
using Oxide.Game.Rust.Cui;
using Network;
using VLB;
namespace Oxide.Plugins {
[Info("Shop", "Skuli Dropek", "1.1.62")]
[Description("In-game store, standalone plugin compatible with WelcomePanel")]
public class Shop : RustPlugin {
[PluginReference]
private Plugin WelcomePanel, ImageLibrary, Economics, ServerRewards, NoEscape;
static Shop plugin;
#region [Hooks]
private void Init() => plugin = this;
private void OnServerInitialized() {
//data
LoadCategoryData();
LoadItemData();
LoadCommandData();
LoadHumanNPCData();
LoadWipeBlockData();
LoadPlayerData();
LoadCdData();
//permissions
RegisterPerms();
//commands
RegisterCustomCmds();
//other
SelectLayout();
DownloadImages();
ImageQueCheck();
//store existing categories
foreach (var category in categories.Keys) {
storedCategories.Add(category);
CategoryNamesCheck(category);
}
if (config.gl.gradually) timer.Once(0.5f, () => {
PlayerComponent(true);
}
);
}
void OnPlayerConnected(BasePlayer player) {
if (config.gl.gradually) PlayerComponent(true, player);
PreloadImages(player);
}
void OnPlayerDisconnected(BasePlayer player) {
if (config.gl.gradually) PlayerComponent(false, player);
}
private void Unload() {
if (config.gl.gradually) PlayerComponent(false);
foreach (var player in BasePlayer.activePlayerList) DestroyShop(player);
SavePlayerData();
}
private void OnNewSave(string filename) {
if (wipeBlock == null || wipeBlock["Wipe Block"].Enabled == null || !wipeBlock["Wipe Block"].Enabled || !wipeBlock["Wipe Block"].StartOnMapWipe) return;
wipeBlock["Wipe Block"].WipeTimeStamp = DateTimeOffset.Now.ToUnixTimeSeconds();
SaveWipeBlockData();
}
#endregion
#region [Methods/Functions]
private void RegisterPerms() {
//register main perm
if (config.ms.requirePerm) permission.RegisterPermission($"{Name}.use", this);
//register perms for sales
foreach (string perm in config.gs.perms.Keys) permission.RegisterPermission($"{Name}.{perm}", this);
//register category permission
foreach (string category in categories.Keys) {
if (categories[category].Permission != null) permission.RegisterPermission($"{Name}.{categories[category].Permission}", this);
}
}
private bool TakeFrom(BasePlayer player, string currencyType, int amount) {
if (currencyType.ToLower() != "rp" && currencyType.ToLower() != "eco") {
var itemDef = ItemManager.FindItemDefinition(currencyType);
if (itemDef == null) {
Puts($" <color=#C2291D>!</color> '{currencyType}' <color=#C2291D>is not correct shortname.</color>");
return false;
}
int inventory = player.inventory.GetAmount(itemDef.itemid);
if (inventory < amount) {
return false;
}
player.inventory.Take(null, itemDef.itemid, amount);
return true;
}
if (currencyType == "rp") {
if (ServerRewards == null) {
Puts("ServerRewards is not loaded!");
return false;
}
var playersRP = ServerRewards?.Call<int>("CheckPoints", player.userID);
if (playersRP < amount) return false;
ServerRewards?.Call("TakePoints", player.userID, amount);
CurrencyBtns(player);
return true;
}
if (currencyType == "eco") {
if (Economics == null) {
Puts("Economics is not loaded!");
return false;
}
double playersEco = Economics.Call<double>("Balance", player.UserIDString);
if (playersEco < Convert.ToDouble(amount)) {
return false;
}
Economics.CallHook("Withdraw", player.UserIDString, Convert.ToDouble(amount));
CurrencyBtns(player);
return true;
}
return false;
}
private bool GiveTo(BasePlayer player, string itemType, int amount, string name = "default", ulong skinId = 0) {
if (itemType.ToLower() != "rp" && itemType.ToLower() != "eco") {
if (itemType.Contains("{")) {
string[] shortnameSplit = itemType.Split('{');
itemType = shortnameSplit[0];
}
var item = ItemManager.CreateByName(itemType, amount, skinId);
if (item != null) {
if (name != "default") item.name = name;
player.GiveItem(item);
return true;
}
}
if (itemType == "rp") {
if (ServerRewards == null) {
Puts("ServerRewards is not loaded!");
return false;
}
ServerRewards?.Call("AddPoints", player.userID, amount);
//refresh currency text
CurrencyBtns(player);
return true;
}
if (itemType == "eco") {
if (Economics == null) {
Puts("Economics is not loaded!");
return false;
}
Economics.CallHook("Deposit", player.UserIDString, (double)amount);
CurrencyBtns(player);
return true;
}
return false;
}
void CreateCooldownEntry(BasePlayer player, string item) {
if (config.ms.cooldowns) {
if (cooldownData.ContainsKey(item)) {
if (!playerData.ContainsKey(player.userID)) playerData.Add(player.userID, new PlayerData());
if (playerData[player.userID].cooldowns.ContainsKey(item)) playerData[player.userID].cooldowns[item] = DateTimeOffset.Now.ToUnixTimeSeconds();
else playerData[player.userID].cooldowns.Add(item, DateTimeOffset.Now.ToUnixTimeSeconds());
}
}
}
private bool BuildChecks(BasePlayer player) {
//is building blocked?
if (!player.CanBuild() && config.ms.requireBuild) {
if (config.ns.cuiFx) _RunNotif(player, 0.45f, 1);
if (config.ns.notifs) {
//create message if missing
if (config.ns.msgs["buildingBlocked"] == null) {
config.ns.msgs.Add("buildingBlocked", "<size=13><b>BUILDING BLOCKED</b></size>\n\nYou can't use shop while you are building blocked.");
SaveConfig();
}
_RunNotif(player, config.ns.duration, 2, new string[] {
config.ns.fail["Panel Color"], config.ns.fail["Accent Color"], config.ns.msgs["buildingBlocked"], config.ns.fail["Sound Prefab"]
}
);
}
return false;
}
//is building authed?
if (!player.IsBuildingAuthed() && config.ms.requireTC) {
if (config.ns.cuiFx) _RunNotif(player, 0.45f, 1);
if (config.ns.notifs) {
//create message if missing
if (config.ns.msgs["notTCAuthed"] == null) {
config.ns.msgs.Add("notTCAuthed", "<size=13><b>NO BUILDING PRIV.</b></size>\n\nYou need to be TC authorized in order to use shop.");
SaveConfig();
}
_RunNotif(player, config.ns.duration, 2, new string[] {
config.ns.fail["Panel Color"], config.ns.fail["Accent Color"], config.ns.msgs["buildingBlocked"], config.ns.fail["Sound Prefab"]
}
);
}
return false;
}
return true;
}
private void Buy(BasePlayer player, string category, string itemName, int amount) {
if (!BuildChecks(player)) return;
//combat block check
if (InCombat(player)) {
if (config.ns.cuiFx) _RunNotif(player, 0.45f, 1);
if (config.ns.notifs) _RunNotif(player, config.ns.duration, 2, new string[] {
config.ns.fail["Panel Color"], config.ns.fail["Accent Color"], config.ns.msgs["noEscape"], config.ns.fail["Sound Prefab"]
}
);
return;
}
//category permission check
if (categories[category].Permission != null) {
if (!permission.UserHasPermission(player.UserIDString, $"shop.{categories[category].Permission}")) {
if (config.ns.cuiFx) _RunNotif(player, 0.45f, 1);
if (config.ns.notifs) _RunNotif(player, config.ns.duration, 2, new string[] {
config.ns.fail["Panel Color"], config.ns.fail["Accent Color"], config.ns.msgs["noPermission"], config.ns.fail["Sound Prefab"]
}
);
return;
}
}
//if item is cooldown limited
if (config.ms.cooldowns) {
if (cooldownData.ContainsKey(itemName)) {
//can buy only one
if (amount > 1) {
_RunNotif(player, config.ns.duration, 2, new string[] {
config.ns.fail["Panel Color"], config.ns.fail["Accent Color"], "This item is cooldown restricted, you can buy only one.", config.ns.fail["Sound Prefab"]
}
);
return;
}
// is player on cooldown
if (playerData.ContainsKey(player.userID)) {
if (playerData[player.userID].cooldowns.ContainsKey(itemName)) {
long timeNow = DateTimeOffset.Now.ToUnixTimeSeconds();
long timeDif = timeNow - playerData[player.userID].cooldowns[itemName];
if (timeDif < cooldownData[itemName]) {
_RunNotif(player, config.ns.duration, 2, new string[] {
config.ns.fail["Panel Color"], config.ns.fail["Accent Color"], "You are on cooldown, please wait.", config.ns.fail["Sound Prefab"]
}
);
return;
}
}
}
}
}
if (items[itemName].BlockAmountChange && items[itemName].DefaultAmount != amount) {
if (config.ns.notifs) _RunNotif(player, config.ns.duration, 2, new string[] {
config.ns.fail["Panel Color"], config.ns.fail["Accent Color"], $"Error", config.ns.fail["Sound Prefab"]
}
);
return;
}
//check sales
int price = PriceAfterSales(player, category, itemName);
if (itemName.StartsWith("cmd") || itemName.StartsWith("command")) {
//skip
}
else price = (int)Math.Ceiling((double)PriceAfterSales(player, category, itemName) * ((double)amount / (double)items[itemName].DefaultAmount));
//price = price * amount;
//take currency
if (TakeFrom(player, items[itemName].Currency, price)) {
CreateCooldownEntry(player, itemName);
//if success
GiveTo(player, itemName, amount, items[itemName].DisplayName, items[itemName].Skin);
if (config.ns.cuiFx) _RunNotif(player, 0.45f, 0);
if (config.ns.notifs) _RunNotif(player, config.ns.duration, 2, new string[] {
config.ns.suc["Panel Color"], config.ns.suc["Accent Color"], $"{ReplaceNT(config.ns.msgs["onPurchase"], itemName, price, amount)}", config.ns.suc["Sound Prefab"]
}
);
}
else {
//if failed
if (config.ns.cuiFx) _RunNotif(player, 0.45f, 1);
if (config.ns.notifs) _RunNotif(player, config.ns.duration, 2, new string[] {
config.ns.fail["Panel Color"], config.ns.fail["Accent Color"], $"{ReplaceNT(config.ns.msgs["noFunds"], itemName, price, amount)}", config.ns.fail["Sound Prefab"]
}
);
}
}
private void Sell(BasePlayer player, string category, string itemName, int amount) {
if (!BuildChecks(player)) return;
//combat block check
if (InCombat(player)) {
if (config.ns.cuiFx) _RunNotif(player, 0.45f, 1);
if (config.ns.notifs) _RunNotif(player, config.ns.duration, 2, new string[] {
config.ns.fail["Panel Color"], config.ns.fail["Accent Color"], config.ns.msgs["noEscape"], config.ns.fail["Sound Prefab"]
}
);
return;
}
//category permission check
if (categories[category].Permission != null) {
if (!permission.UserHasPermission(player.UserIDString, $"shop.{categories[category].Permission}")) {
if (config.ns.cuiFx) _RunNotif(player, 0.45f, 1);
if (config.ns.notifs) _RunNotif(player, config.ns.duration, 2, new string[] {
config.ns.fail["Panel Color"], config.ns.fail["Accent Color"], config.ns.msgs["noPermission"], config.ns.fail["Sound Prefab"]
}
);
return;
}
}
//check sales
int price = PriceAfterSales(player, category, itemName, true);
if (itemName.StartsWith("cmd") || itemName.StartsWith("command")) {
//skip
}
else price = (int)((double)PriceAfterSales(player, category, itemName, true) * ((double)amount / (double)items[itemName].DefaultAmount));
if (price == 0) return;
//take currency
if (TakeFrom(player, itemName, amount)) {
GiveTo(player, items[itemName].Currency, price);
if (config.ns.cuiFx) _RunNotif(player, 0.45f, 0);
if (config.ns.notifs) _RunNotif(player, config.ns.duration, 2, new string[] {
config.ns.suc["Panel Color"], config.ns.suc["Accent Color"], $"{ReplaceNT(config.ns.msgs["onSale"], itemName, price, amount)}", config.ns.suc["Sound Prefab"]
}
);
}
else {
if (config.ns.cuiFx) _RunNotif(player, 0.45f, 1);
if (config.ns.notifs) _RunNotif(player, config.ns.duration, 2, new string[] {
config.ns.fail["Panel Color"], config.ns.fail["Accent Color"], $"{ReplaceNT(config.ns.msgs["noItemToSell"], itemName, price, amount)}", config.ns.fail["Sound Prefab"]
}
);
}
}
private void BuyCommand(BasePlayer player, string category, string command) {
//category permission check
if (categories[category].Permission != null) {
if (!permission.UserHasPermission(player.UserIDString, $"shop.{categories[category].Permission}")) {
if (config.ns.cuiFx) _RunNotif(player, 0.45f, 1);
if (config.ns.notifs) _RunNotif(player, config.ns.duration, 2, new string[] {
config.ns.fail["Panel Color"], config.ns.fail["Accent Color"], config.ns.msgs["noPermission"], config.ns.fail["Sound Prefab"]
}
);
return;
}
}
if (!BuildChecks(player)) return;
if (InCombat(player)) {
if (config.ns.cuiFx) _RunNotif(player, 0.45f, 1);
if (config.ns.notifs) _RunNotif(player, config.ns.duration, 2, new string[] {
config.ns.fail["Panel Color"], config.ns.fail["Accent Color"], config.ns.msgs["noEscape"], config.ns.fail["Sound Prefab"]
}
);
return;
}
string[] splits = command.Split('/');
string cmd = commands[splits[1]].Command;
//if item is cooldown limited
if (config.ms.cooldowns) {
if (cooldownData.ContainsKey(command)) {
// is player on cooldown
if (playerData.ContainsKey(player.userID)) {
if (playerData[player.userID].cooldowns.ContainsKey(command)) {
long timeNow = DateTimeOffset.Now.ToUnixTimeSeconds();
long timeDif = timeNow - playerData[player.userID].cooldowns[command];
if (timeDif < cooldownData[command]) {
_RunNotif(player, config.ns.duration, 2, new string[] {
config.ns.fail["Panel Color"], config.ns.fail["Accent Color"], "You are on cooldown, please wait.", config.ns.fail["Sound Prefab"]
}
);
return;
}
}
}
}
}
int price = PriceAfterSales(player, category, command);
if (TakeFrom(player, commands[splits[1]].Currency, price)) {
CreateCooldownEntry(player, command);
Server.Command(cmd.Replace("{steamid}", $"{player.userID}").Replace("{playername}", $"{player.displayName}"));
SendReply(player, commands[splits[1]].Message);
if (config.ns.cuiFx) _RunNotif(player, 0.45f, 0);
if (config.ns.notifs) _RunNotif(player, config.ns.duration, 2, new string[] {
config.ns.suc["Panel Color"], config.ns.suc["Accent Color"], $"{ReplaceNT(config.ns.msgs["onPurchase"], commands[splits[1]].DisplayName, price, 1, true)}", config.ns.suc["Sound Prefab"]
}
);
}
else {
//if failed
if (config.ns.cuiFx) _RunNotif(player, 0.45f, 1);
if (config.ns.notifs) _RunNotif(player, config.ns.duration, 2, new string[] {
config.ns.fail["Panel Color"], config.ns.fail["Accent Color"], $"{ReplaceNT(config.ns.msgs["noFunds"], commands[splits[1]].DisplayName, price, 1, true)}", config.ns.fail["Sound Prefab"]
}
);
}
}
private int PriceAfterSales(BasePlayer player, string category, string itemName, bool sell = false, bool fullprice = false) {
int price = 0;
if (itemName.Contains("cmd/") || itemName.Contains("command/")) {
string[] splits = itemName.Split('/');
price = commands[splits[1]].BuyPrice;
}
else {
price = items[itemName].BuyPrice;
}
if (fullprice) return price;
if (sell) price = items[itemName].SellPrice;
List<float> availableSales = new List<float> {
}
;
//check if category has sale
if (categories[category].Sale != null && categories[category].Sale != 0) availableSales.Add(categories[category].Sale);
//check global sale for item
if (config.gs.items.ContainsKey(itemName)) availableSales.Add(config.gs.items[itemName]);
//check player permission sales
foreach (string perm in config.gs.perms.Keys) {
if (permission.UserHasPermission(player.UserIDString, "shop." + perm)) {
if (!availableSales.Contains(config.gs.perms[perm])) availableSales.Append(config.gs.perms[perm]);
}
}
float discount = 0;
int dec = 0;
if (availableSales.Count != 0) discount = availableSales.Max();
if (discount != 0 && discount > 0) dec = Convert.ToInt32((Convert.ToSingle(price) / 100f) * (discount * 100f));
return price - dec;
}
private string GetCurrencyType(BasePlayer player, string itemName) {
string currency = "";
if (itemName.Contains("cmd/") || itemName.Contains("command/")) {
string[] splits = itemName.Split('/');
currency = commands[splits[1]].Currency;
}
else {
currency = items[itemName].Currency;
}
return currency;
}
private long IsWipeBlocked(string item) {
if (wipeBlock["Wipe Block"].WipeTimeStamp == 0 && wipeBlock["Wipe Block"].WipeTimeStamp == null) return 0;
if (!wipeBlock["Wipe Block"].Items.ContainsKey(item)) return 0;
long itemTimeBlock = wipeBlock["Wipe Block"].Items[item];
long timeNow = DateTimeOffset.Now.ToUnixTimeSeconds();
long timePassed = timeNow - wipeBlock["Wipe Block"].WipeTimeStamp;
if (timePassed < itemTimeBlock) return itemTimeBlock - timePassed;
else return 0;
}
private bool InCombat(BasePlayer player) {
if (NoEscape == null) return false;
if (config.cb.combatBlock && (bool)NoEscape.Call("IsCombatBlocked", player)) return true;
if (config.cb.raidBlock && (bool)NoEscape.Call("IsRaidBlocked", player)) return true;
return false;
}
string ReplaceNT(string msg, string item, int price, int amount, bool command = false) {
if (command) {
msg = msg.Replace("{item}", item).Replace("{price}", $"{price}").Replace("{amount}", $"{amount}");
return msg;
}
if (!item.StartsWith("cmd/") && !item.StartsWith("command/")) {
if (items[item].DisplayName == "default") {
var itemDef = ItemManager.FindItemDefinition(item);
if (itemDef != null) item = itemDef.displayName.translated;
}
else item = items[item].DisplayName;
}
msg = msg.Replace("{item}", item).Replace("{price}", $"{price}").Replace("{amount}", $"{amount}");
return msg;
}
bool IsDigitsOnly(string str) {
foreach (char c in str) {
if (c < '0' || c > '9') return false;
}
return true;
}
#endregion
#region [UI Functions]
#region Commands
private void RegisterCustomCmds() {
cmd.AddChatCommand(config.ms.cmd, this, "CustomShopCommands");
}
void CustomShopCommands(BasePlayer player, string command, string[] args) {
if (!readyCheck(player)) return;
if (!config._as.addon) {
if (command == config.ms.cmd) {
try {
//default category
var list = ItemOrder(player, storedCategories[0], 18, 0);
CreateDefaultCui(player);
CreateCui(player);
CategorySelection(player);
OpenShopPage(player, storedCategories[0], 0);
ButtonHL(player, 0);
}
catch {
Puts($"\nError found in configuration files.\nPlease make sure that:\n\n• You didn't break json formating.Online Json validator can be used to check it.\n• You not missing any file in your data/Shop folder\n• Check if Item.json and Categories.json are not empty.\n\n\n If you still having issues, feel free to open support ticket and I will assist you soon as I can.(within 16 hours usually)");
SendReply(player, "<color=#E74F17><size=18>Error found in configuration files.</size></color>\nPlease make sure that:\n\n• You didn't break json formating.Online Json validator can be used to check it.\n• You not missing any file in your data/Shop folder\n• Check if Item.json and Categories.json are not empty.\n\n\n If you still having issues, feel free to open support ticket and I will assist you soon as I can.(within 16 hours usually)");
}
}
}
else {
if (player.IsAdmin) SendReply(player, "Shop is set to be used as addon for WelcomePanel.");
}
}
[ConsoleCommand("shopclose")]
private void CloseShop(ConsoleSystem.Arg arg) {
var player = arg?.Player();
if (arg.Player() == null) return;
CuiHelper.DestroyUi(player, "bg");
CuiHelper.DestroyUi(player, "shopD_containeOverlayr");
CuiHelper.DestroyUi(player, "shopD_container");
CuiHelper.DestroyUi(player, "empty");
CuiHelper.DestroyUi(player, "container");
CuiHelper.DestroyUi(player, "close_btn");
}
[ConsoleCommand("shop_page")]
// OPEN PAGE UI BUTTON COMMAND
private void shop_page(ConsoleSystem.Arg arg) {
var player = arg?.Player();
var args = arg.Args;
if (player == null) return;
if (!readyCheck(player)) return;
if (!config._as.addon) {
CreateCui(player);
if (args.Length == 3) ButtonHL(player, Convert.ToInt32(args[2]));
//$"shop_page {storedCategories[i + startingIndex]} 0 {i + startingIndex}"
OpenShopPage(player, args[0], Convert.ToInt32(args[1]));
}
else {
CreateCui(player);
OpenShopPage(player, args[0], Convert.ToInt32(args[1]));
}
}
[ConsoleCommand("shop_categories")]
//???
private void shop_categories(ConsoleSystem.Arg arg) {
var player = arg?.Player();
if (player == null) return;
var args = arg.Args;
if (!readyCheck(player)) return;
if (args == null) {
CreateCui(player);
CategorySelection(player);
}
else {
CreateCui(player);
CategorySelection(player, Convert.ToInt32(args[0]));
}
}
[ConsoleCommand("shopDefault_categories")]
// ???
private void shopDefault_categories(ConsoleSystem.Arg arg) {
var player = arg?.Player();
if (player == null) return;
var args = arg.Args;
CategorySelection(player, Convert.ToInt32(args[0]));
}
[ConsoleCommand("shop_cmd")]
// SHOP ACTIONS UI BUTTON COMMANDS
private void shop_cmd(ConsoleSystem.Arg arg) {
var player = arg?.Player();
if (player == null) return;
var args = arg.Args;
if (!readyCheck(player)) return;
if (args[0] == "buy") Buy(player, args[1], args[2], Convert.ToInt32(args[3]));
// category item amount
if (args[0] == "sell") Sell(player, args[1], args[2], Convert.ToInt32(args[3]));
if (args[0] == "buyCmd") BuyCommand(player, args[1], args[2]);
if (args[0] == "select") {
// index item category currency type
CreateSelectionCui(player, Convert.ToInt32(args[2]), args[1], args[3], args[4]);
}
if (args[0] == "swap") {
if (args[5] == "sell") CreateSelectionCui(player, Convert.ToInt32(args[2]), args[1], args[3], args[4], true);
if (args[5] == "buy") CreateSelectionCui(player, Convert.ToInt32(args[2]), args[1], args[3], args[4], false);
}
if (args[0] == "default_text") CuiHelper.DestroyUi(player, "amount_btn");
if (args[0] == "input") {
try {
if (IsDigitsOnly(args[6])) {
if (!amountStorage.ContainsKey(player.userID)) amountStorage.Add(player.userID, Convert.ToInt32(args[6]));
else amountStorage[player.userID] = Convert.ToInt32(args[6]);
}
else CreateSelectionCui(player, Convert.ToInt32(args[2]), args[1], args[3], args[4], false, false);
if (args[5] == "buy") {
//index item category-currency-sell onInput?
CreateSelectionCui(player, Convert.ToInt32(args[2]), args[1], args[3], args[4], false, true);
}
if (args[5] == "sell") {
//index item category-currency-sell onInput?
CreateSelectionCui(player, Convert.ToInt32(args[2]), args[1], args[3], args[4], true, true);
}
}
catch {
}
}
}
#endregion
#region Shared
// list of all categories
private List<string> storedCategories = new List<string>();
// create categories buttons
private void CategorySelection(BasePlayer player, int page = 0) {
// position to start from list of categories
int startingIndex = 6 * page;
if (!config._as.addon) startingIndex = 10 * page;
// count list of categories
int countWhole = storedCategories.Count();
int _lenght = countWhole - startingIndex;
// anchors for category buttons (standalone version)
string[] cm_Anchors = {
"0.01 0.81/0.98 0.885", "0.01 0.735/0.98 0.81", "0.01 0.66/0.98 0.735", "0.01 0.585/0.98 0.660", "0.01 0.510/0.98 0.585", "0.01 0.435/0.98 0.510", "0.01 0.360/0.98 0.435", "0.01 0.285/0.98 0.360", "0.01 0.210/0.98 0.285", "0.01 0.135/0.98 0.210",
}
;
//ref
var _cM = CUIClass.CreateOverlay("empty", "0 0 0 0", "0 0", "0 0", false, 0.0f, "assets/icons/iconmaterial.mat");
//assets/content/ui/uibackgroundblur.mat
if (config._as.addon) {
//adjust anchors based on number of buttons to show up
cm_Anchors = new string[] {
"0.13 0.67/0.49 0.97", "0.505 0.67/0.87 0.97", "0.13 0.35/0.49 0.65", "0.505 0.35/0.87 0.65", "0.13 0.03/0.49 0.33", "0.505 0.03/0.87 0.33",
}
;
if (_lenght < 5) cm_Anchors = new string[] {
"0.13 0.51/0.49 0.81", "0.13 0.19/0.49 0.49", "0.505 0.51/0.87 0.81", "0.505 0.19/0.87 0.49",
}
;
if (_lenght < 3) //&&
cm_Anchors = new string[] {
"0.13 0.35/0.49 0.65", "0.51 0.35/0.87 0.65",
}
;
//create categories
for (int i = 0; i < _lenght; i++) {
if (cm_Anchors.Length < i + 1) continue;
string[] anchorSplit = cm_Anchors[i].Split('/');
CUIClass.CreateButton(ref _cM, "cm_btn", "container", "0.115 0.115 0.115 0.9", $"", 22, anchorSplit[0], anchorSplit[1], $"shop_page {storedCategories[i + startingIndex]} 0", "", "1 1 1 0.7", 0.2f, TextAnchor.MiddleCenter, $"robotocondensed-bold.ttf", "assets/content/ui/uibackgroundblur.mat");
CUIClass.CreateImage(ref _cM, "cm_btn_img", $"cm_btn", $"{Img(categories[storedCategories[i + startingIndex]].Image)}", "0.12 0.35", "0.27 0.65", 0.2f);
CUIClass.CreateText(ref _cM, "cm_btn_text", "cm_btn", "1 1 1 0.8", $"{storedCategories[i + startingIndex].ToUpper().Replace('_', ' ')}", 18, "0.30 0", "0.87 1", TextAnchor.MiddleCenter, $"robotocondensed-bold.ttf", 0.2f);
}
//page buttons
if (page != 0) CUIClass.CreateButton(ref _cM, "cm_btn_prev", "container", "0 0 0 0", "‹", 80, "0.0 0", "0.13 1", $"shop_categories {page - 1}", "", "1 1 1 0.8", 0.0f, TextAnchor.MiddleCenter, $"robotocondensed-bold.ttf", "assets/icons/iconmaterial.mat");
if (countWhole - startingIndex > 6) CUIClass.CreateButton(ref _cM, "cm_btn_next", "container", "0 0 0 0", "›", 80, "0.87 0", "1 1", $"shop_categories {page + 1}", "", "1 1 1 0.8", 0.0f, TextAnchor.MiddleCenter, $"robotocondensed-bold.ttf", "assets/icons/iconmaterial.mat");
}
else {
//color for buttons, stupid but works
string[] cm_btnColors = {
config.us.buttons["Button Color 1."], config.us.buttons["Button Color 2."], config.us.buttons["Button Color 1."], config.us.buttons["Button Color 2."], config.us.buttons["Button Color 1."], config.us.buttons["Button Color 2."], config.us.buttons["Button Color 1."], config.us.buttons["Button Color 2."], config.us.buttons["Button Color 1."], config.us.buttons["Button Color 2."],
}
;
if (page != 0 && countWhole - startingIndex > 10) {
CUIClass.CreateButton(ref _cM, "cm_btn_prev", "shopD_side", "0 0 0 0", "ˆ ", 40, "0.0 0.0", "0.5 0.125", $"shopDefault_categories {page - 1}", "", "1 1 1 0.8", 0.0f, TextAnchor.MiddleRight, $"robotocondensed-bold.ttf", "assets/icons/iconmaterial.mat");
CUIClass.CreateButton(ref _cM, "cm_btn_next", "shopD_side", "0 0 0 0", " ˇ", 40, "0.5 0.0", "1 0.125", $"shopDefault_categories {page + 1}", "", "1 1 1 0.8", 0.0f, TextAnchor.UpperLeft, $"robotocondensed-bold.ttf", "assets/icons/iconmaterial.mat");
}
else {
// page buttons
if (page != 0) CUIClass.CreateButton(ref _cM, "cm_btn_prev", "shopD_side", "0 0 0 0", "ˆ", 40, "0.0 0.0", "1 0.125", $"shopDefault_categories {page - 1}", "", "1 1 1 0.8", 0.0f, TextAnchor.MiddleCenter, $"robotocondensed-bold.ttf", "assets/icons/iconmaterial.mat");
if (countWhole - startingIndex > 10) CUIClass.CreateButton(ref _cM, "cm_btn_next", "shopD_side", "0 0 0 0", "ˇ", 40, "0.0 0.0", "1 0.125", $"shopDefault_categories {page + 1}", "", "1 1 1 0.8", 0.0f, TextAnchor.UpperCenter, $"robotocondensed-bold.ttf", "assets/icons/iconmaterial.mat");
}
// create categories
for (int i = 0; i < _lenght; i++) {
if (cm_Anchors.Length < i + 1) continue;
string[] anchorSplit = cm_Anchors[i].Split('/');
CUIClass.CreateButton(ref _cM, $"cm_btn{i}", "shopD_side", "0 0 0 0", $"", 22, anchorSplit[0], anchorSplit[1], $"shop_page {storedCategories[i + startingIndex]} 0 {i + startingIndex}", "", "1 1 1 0.7", 0.2f, TextAnchor.MiddleCenter, $"robotocondensed-bold.ttf", "assets/icons/iconmaterial.mat");
// apply ui asset on every second button only
if (cm_btnColors[i] == config.us.buttons["Button Color 1."]) CUIClass.PullFromAssets(ref _cM, "btn_highlight2", $"cm_btn{i}", "0 0 0 0.6", "assets/content/ui/ui.background.transparent.linearltr.tga", 0.2f, 0.4f, "0 0", "1.2 1");
CUIClass.CreateImage(ref _cM, "cm_btn_img", $"cm_btn{i}", $"{Img(categories[storedCategories[i + startingIndex]].Image)}", "0.05 0.2", "0.165 0.8", 0.2f);
CUIClass.CreateText(ref _cM, "cm_btn_text", $"cm_btn{i}", "1 1 1 0.8", $"{storedCategories[i + startingIndex].Replace('_', ' ')}", 15, "0.22 0", "0.87 1", TextAnchor.MiddleLeft, $"robotocondensed-bold.ttf", 0.2f);
CuiHelper.DestroyUi(player, $"cm_btn{i}");
}
// destroy all before AddUi
for (var i = 0; i < 11; i++) CuiHelper.DestroyUi(player, $"cm_btn{i}");
}
CuiHelper.DestroyUi(player, "cm_btn_next");
CuiHelper.DestroyUi(player, "cm_btn_prev");
CuiHelper.AddUi(player, _cM);
CuiHelper.DestroyUi(player, "empty");
}
// open certain page from category
private void OpenShopPage(BasePlayer player, string category, int page) {
int maxItems = 18;
var list = ItemOrder(player, category, maxItems, page);
ShowItems(player, list, category);
}
// create list of items to show
private List<string> ItemOrder(BasePlayer player, string category, int numberOfItems, int page) {
List<string> storedList = Facepunch.Pool.GetList<string>();
int startingIndex = numberOfItems * page;
int countWhole = categories[category].Items.Count();
int itemsToShow = countWhole - (startingIndex + 1);
int _length = numberOfItems;
bool last = false;
if (itemsToShow < numberOfItems) _length = itemsToShow + 1;
if (countWhole - startingIndex < numberOfItems + 1) last = true;
CreatePageBtns(player, category, page, last);
for (var i = startingIndex; i < startingIndex + _length; i++) storedList.Add(categories[category].Items[i]);
return storedList;
}
// show items from created list
private void ShowItems(BasePlayer player, List<string> items, string category) {
if (config.gl.gradually) {
var run = _monoBehavior[player];
if (run == null) PlayerComponent(true, player);
if (run != null) run.CreateItems(player, items, category);
}
else {
int count = 0;
foreach (string item in items) {
CreateItemCui(player, count, items[count], category);
count++;
}
Facepunch.Pool.FreeList(ref items);
}
CurrencyBtns(player);
}
// create ui container for items
private void CreateCui(BasePlayer player) {
string anchorMin = "0.5 0.5";
string anchorMax = "0.5 0.5";
string offsetMin = container_Offset[0];
string offsetMax = container_Offset[1];
if (config._as.addon) {
anchorMin = config._as.offset["AnchorMin"];
anchorMax = config._as.offset["AnchorMax"];
offsetMin = config._as.offset["OffSetMin"];
offsetMax = config._as.offset["OffSetMax"];
}
var _base = CUIClass.CreateOverlay("empty", "0 0 0 0", "0 0", "0 0", false, 0.0f, "assets/icons/iconmaterial.mat");
//assets/content/ui/uibackgroundblur.mat
//offset
CUIClass.CreatePanel(ref _base, "container", layer, "0.25 0.23 0.22 0", anchorMin, anchorMax, true, 0.3f, 0f, "assets/icons/iconmaterial.mat", offsetMin, offsetMax, true);
//parented panel
CuiHelper.DestroyUi(player, "empty");
CuiHelper.DestroyUi(player, "container");
CuiHelper.DestroyUi(player, "close_btn");
CuiHelper.AddUi(player, _base);
CuiHelper.DestroyUi(player, "empty");
}
// create single item ui
private void CreateItemCui(BasePlayer player, int index, string item = "test", string category = "Attire") {
string img = "";
string displayName = null;
if (item.Contains("cmd/") || item.Contains("command/")) {
string[] splits = item.Split('/');
if (commands[splits[1]].Image == null) img = "https://rustplugins.net/products/shop/rustlogo.jpg";
else img = commands[splits[1]].Image;
if (commands[splits[1]].ShowDisplayName != null && commands[splits[1]].ShowDisplayName) displayName = commands[splits[1]].DisplayName;
}
else {
if (items[item].Image == null) img = "https://rustplugins.net/products/shop/rustlogo.jpg";
else img = items[item].Image;
if (items[item].ShowDisplayName != null && items[item].ShowDisplayName) displayName = items[item].DisplayName;
}
string prefix = "https://rustlabs.com/img/items180/";
int fullPrice = PriceAfterSales(player, category, item, false, true);
int salePrice = PriceAfterSales(player, category, item);
string currencyType = GetCurrencyType(player, item);
string price = $"0 <b>$</b>";
string pAnchor = "0.94";
string[] anchorSplit = anchorSet[index].Split('/');
if (!img.StartsWith("http")) img = prefix + img;
//ui
var _item = CUIClass.CreateOverlay("empty", "0 0 0 0", "0 0", "0 0", false, 0.0f, "assets/icons/iconmaterial.mat");
//assets/content/ui/uibackgroundblur.mat
//item 0.115 0.115 0.115 0.8
CUIClass.CreateButton(ref _item, $"item{index}", "container", $"{config.gl.itemUI["Background Color"]}", $"\n <size=11>{displayName}</size>", 4, anchorSplit[0], anchorSplit[1], $"shop_cmd select {item} {index} {category} {currencyType}", "", "1 1 1 0.7", config.gl.fadeIn, TextAnchor.UpperLeft, $"robotocondensed-regular.ttf", "assets/content/ui/uibackgroundblur-ingamemenu.mat");
CUIClass.CreateImage(ref _item, "img", $"item{index}", $"{Img(img)}", "0.18 0.20", "0.82 0.82", config.gl.fadeIn);
//is wipe blocked
if (IsWipeBlocked(item) > 0) {
long wipeBlock = (long)IsWipeBlocked(item);
string cooldownFormated = "";
if (wipeBlock > 0) {
TimeSpan cooldownTS = TimeSpan.FromSeconds(wipeBlock);
cooldownFormated = string.Format("{0:D1}D : {1:D2}H : {2:D2}M", cooldownTS.Days, cooldownTS.Hours, cooldownTS.Minutes);
if (wipeBlock < 86400) cooldownFormated = string.Format("{0:D2}H : {1:D2}M", cooldownTS.Hours, cooldownTS.Minutes);
CUIClass.CreatePanel(ref _item, "red_box", $"item{index}", "0.56 0.20 0.15 1.0", "0.125 0.40", $"0.885 0.61", false, 0.1f, 0f, "assets/content/ui/uibackgroundblur.mat");
CUIClass.CreateButton(ref _item, $"wipeblock_cvr{index}", "container", "0.115 0.115 0.115 0.05", cooldownFormated, 11 + fontAdjustment, anchorSplit[0], anchorSplit[1], $"", "", "1 1 1 0.7", 0.5f, TextAnchor.MiddleCenter, $"robotocondensed-bold.ttf", "assets/icons/iconmaterial.mat");
}
}
else {
//is on cooldown
if (config.ms.cooldowns) {
if (cooldownData.ContainsKey(item) || cooldownData.ContainsKey("cmd/" + item) || cooldownData.ContainsKey("command/" + item)) {
// is player on cooldown
if (playerData.ContainsKey(player.userID)) {
if (playerData[player.userID].cooldowns.ContainsKey(item)) {
long timeNow = DateTimeOffset.Now.ToUnixTimeSeconds();
long timeDif = timeNow - playerData[player.userID].cooldowns[item];
if (timeDif < cooldownData[item]) {
TimeSpan countdownFormated = TimeSpan.FromSeconds(cooldownData[item] - timeDif);
string countDownText = string.Format("{0:D1}D : {1:D2}H : {2:D2}M", countdownFormated.Days, countdownFormated.Hours, countdownFormated.Minutes);
CUIClass.CreatePanel(ref _item, "red_box", $"item{index}", "0.56 0.20 0.15 1.0", "0.125 0.40", $"0.885 0.61", false, 0.1f, 0f, "assets/content/ui/uibackgroundblur.mat");
CUIClass.CreateButton(ref _item, $"wipeblock_cvr{index}", "container", "0.115 0.115 0.115 0.05", countDownText, 11 + fontAdjustment, anchorSplit[0], anchorSplit[1], $"", "", "1 1 1 0.7", 0.5f, TextAnchor.MiddleCenter, $"robotocondensed-bold.ttf", "assets/icons/iconmaterial.mat");
}
}
}
}
}
}
//is on sale?
if (fullPrice != salePrice) {
price = $"<size={7 + fontAdjustment}>-{fullPrice}-</size> {salePrice}";
CUIClass.CreatePanel(ref _item, "sale", $"item{index}", "0.808 0.259 0.161 1", "0.05 0.80", $"0.35 0.945", false, 0.1f, 0f, "assets/content/ui/uibackgroundblur.mat");
CUIClass.CreateText(ref _item, "text", "sale", "1 1 1 0.8", $"SALE", 10 + fontAdjustment, "0 0", "1 0.9", TextAnchor.MiddleCenter, $"robotocondensed-bold.ttf", 0.5f);
}
else {
price = $"{fullPrice}";
}
//currency type?
if (currencyType == "rp") price += $"<b>RP</b>";
if (currencyType == "eco") price += $"<b>$</b>";
if (currencyType != "eco" && currencyType != "rp") {
price += "";
pAnchor = "0.79";
string currencyImage = $"https://rustlabs.com/img/items180/{currencyType}.png";
if (config.gl.forceImage != null) currencyImage = config.gl.forceImage;
CUIClass.CreateImage(ref _item, "img", $"item{index}", $"{Img(currencyImage)}", "0.805 0.045", "0.95 0.20", 0.5f);
}
//item price
CUIClass.CreateText(ref _item, "text", $"item{index}", $"{config.gl.itemUI["Text Color"]}", price, 11 + fontAdjustment, "0.03 0.05", $"{pAnchor} 1", TextAnchor.LowerRight, $"robotocondensed-regular.ttf", 0.5f);
//end
CuiHelper.AddUi(player, _item);
CuiHelper.DestroyUi(player, "empty");
}
// create page buttons for list of items
private void CreatePageBtns(BasePlayer player, string category, int currentPage = 0, bool last = false, bool npc = false, string npcId = "0") {
string upCmd = $"shop_page {category} {currentPage - 1}";
string downCmd = $"shop_page {category} {currentPage + 1}";
if (npc) {
upCmd = $"npc_page {npcId} {currentPage - 1}";
downCmd = $"npc_page {npcId} {currentPage + 1}";
}
var _btnP = CUIClass.CreateOverlay("empty", "0 0 0 0", "0 0", "0 0", false
// ... [Code preview truncated due to length. Full source in attached file] ...