C#:
using Enumerable = System.Linq.Enumerable;
using Facepunch;
using Oxide.Core;
using System.Text;
using Oxide.Core.Plugins;
using System;
using System.Collections.Generic;
using Oxide.Plugins.TPShopExtensionMethods;
using UnityEngine;
using Newtonsoft.Json;
using Oxide.Game.Rust.Cui;
using System.Collections;
using UnityEngine.Networking;
using System.IO;
namespace Oxide.Plugins {
[Info("TPShop", "pluginfuel.ru", "20.0.2")]
[Description("Дополнение для сборки")]
internal class TPShop : RustPlugin {
private void CONFIRMATIONSUI(BasePlayer player, int itemID, int indexCategory, int amount, ThemeType themetype) {
Configuration.InterfaceSettings.ThemeCustomization theme = themetype == ThemeType.Dark ? _config.interfaceSettings.DarkTheme : _config.interfaceSettings.LightTheme;
Configuration.CategoryShop.Product product = GetCategories(player)[indexCategory].product.Find(x => x.ID == itemID);
float discount = GetUserDiscount(player);
int playerLim = GetLimit(player, product, true);
string limit = playerLim == -1 ? GetLang("TPShop_UI_PATTERN", player.UserIDString) : playerLim + "/" + product.GetLimitLotWipe(player, true);
CuiElementContainer container = new CuiElementContainer {
new CuiElement {
Name = ConfirmationsPanel, Parent = PanelProduct, Components = {
new CuiRawImageComponent {
Color = theme.colorMainBG, Png = _imageUI.GetImage("ITEM_CONFIRM")
}
, new CuiRectTransformComponent {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-230.488 -109.615", OffsetMax = "261.007 77.799"
}
}
}
, new CuiElement {
Name = "IMAGE_PRODUCT_BACKGROUND", Parent = ConfirmationsPanel, Components = {
new CuiRawImageComponent {
Color = theme.colortext6, Png = _imageUI.GetImage("BACKGROUND_PRODUCT")
}
, new CuiRectTransformComponent {
AnchorMin = "0 1", AnchorMax = "0 1", OffsetMin = "46.52 -114.22", OffsetMax = "122.52 -42.22"
}
}
}
}
;
if (!string.IsNullOrWhiteSpace(product.Url) || product.Type == ItemType.Kit || product.Type == ItemType.Command) {
container.Add(new CuiElement {
Name = "PRODUCT_IMAGE", Parent = "IMAGE_PRODUCT_BACKGROUND", Components = {
new CuiRawImageComponent {
Color = "1 1 1 1", Png = GetImage(string.IsNullOrWhiteSpace(product.Url) ? "NONE" : product.Url)
}
, new CuiRectTransformComponent {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-30 -30", OffsetMax = "30 30"
}
}
}
);
}
else if (product.Type == ItemType.CustomItem) {
container.Add(new CuiElement {
Name = "PRODUCT_IMAGE", Parent = "IMAGE_PRODUCT_BACKGROUND", Components = {
new CuiRawImageComponent {
Color = "1 1 1 1", Png = GetImage(product.ShortName + 60, product.SkinID)
}
, new CuiRectTransformComponent {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-30 -30", OffsetMax = "30 30"
}
}
}
);
}
else if (product.Type == ItemType.Item) {
container.Add(new CuiElement {
Name = "PRODUCT_IMAGE", Parent = "IMAGE_PRODUCT_BACKGROUND", Components = {
new CuiImageComponent {
Color = "1 1 1 1", ItemId = ItemManager.FindItemDefinition(product.ShortName).itemid
}
, new CuiRectTransformComponent {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-30 -30", OffsetMax = "30 30"
}
}
}
);
}
else {
container.Add(new CuiElement {
Name = "PRODUCT_IMAGE", Parent = "IMAGE_PRODUCT_BACKGROUND", Components = {
new CuiImageComponent {
Color = "1 1 1 1", ItemId = ItemManager.FindItemDefinition("blueprintbase").itemid
}
, new CuiRectTransformComponent {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-30 -30", OffsetMax = "30 30"
}
}
}
);
container.Add(new CuiElement {
Name = "PRODUCT_IMAGE", Parent = "IMAGE_PRODUCT_BACKGROUND", Components = {
new CuiImageComponent {
Color = "1 1 1 1", ItemId = ItemManager.FindItemDefinition(product.ShortName).itemid
}
, new CuiRectTransformComponent {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-30 -30", OffsetMax = "30 30"
}
}
}
);
}
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0.5 1", AnchorMax = "0.5 1", OffsetMin = "-118.134 -68.265", OffsetMax = "8.346 -39.543"
}
, Text = {
Text = product.GetProductName(player.UserIDString), Font = "robotocondensed-bold.ttf", FontSize = 8, Align = TextAnchor.LowerLeft, Color = theme.colortext7
}
,
}
, ConfirmationsPanel);
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0.5 1", AnchorMax = "0.5 1", OffsetMin = "-118.134 -137.191", OffsetMax = "8.346 -70.689"
}
, Text = {
Text = GetLang("TPShop_UI_PRODUCT_INFO", player.UserIDString, $"{GetDiscountedPrice(product.Price * amount, discount):F2}{_config.economicsCustomization.PrefixBalance}", product.Amount * amount, limit), Font = "robotocondensed-regular.ttf", FontSize = 8, Align = TextAnchor.MiddleLeft, Color = theme.Colortext5
}
,
}
, ConfirmationsPanel);
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "1 0.5", AnchorMax = "1 0.5", OffsetMin = "-228.122 -8.202", OffsetMax = "-44.678 54.164"
}
, Text = {
Text = product.GetProductDescription(), Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.UpperLeft, Color = theme.Colortext5
}
,
}
, ConfirmationsPanel);
container.Add(new CuiElement {
Name = "PRODUCT_BUY_BTN", Parent = ConfirmationsPanel, Components = {
new CuiRawImageComponent {
Color = theme.colortext8, Png = _imageUI.GetImage("ITEM_BUY")
}
, new CuiRectTransformComponent {
AnchorMin = "1 0", AnchorMax = "1 0", OffsetMin = "-162.4 42.9", OffsetMax = "-109.4 63.9"
}
}
}
);
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1"
}
, Button = {
Command = $"UI_HandlerShop PRODUCT_BUY {itemID} {indexCategory} {amount} {themetype}", Color = "0 0 0 0"
}
, Text = {
Text = GetLang("TPShop_UI_BTN_BUY", player.UserIDString).ToUpper(), Font = "robotocondensed-regular.ttf", FontSize = 8, Align = TextAnchor.MiddleCenter
}
}
, "PRODUCT_BUY_BTN");
container.Add(new CuiElement {
Name = "PRODUCT_CLOSE_BTN", Parent = ConfirmationsPanel, Components = {
new CuiRawImageComponent {
Color = theme.closeBtnColor2, Png = _imageUI.GetImage("ITEM_BUY")
}
, new CuiRectTransformComponent {
AnchorMin = "1 0", AnchorMax = "1 0", OffsetMin = "-100 42.9", OffsetMax = "-47 63.9"
}
}
}
);
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1"
}
, Button = {
Close = "CONFIRMATIONS_PANEL", Color = "0 0 0 0"
}
, Text = {
Text = GetLang("TPShop_UI_PRODUCT_INFO_EXIT", player.UserIDString), Font = "robotocondensed-regular.ttf", FontSize = 8, Align = TextAnchor.MiddleCenter
}
}
, "PRODUCT_CLOSE_BTN");
// Add to cart button
container.Add(new CuiElement {
Name = "PRODUCT_CART_BTN", Parent = ConfirmationsPanel, Components = {
new CuiRawImageComponent {
Color = "0.2 0.6 0.8 0.8", Png = _imageUI.GetImage("ITEM_BUY")
}
, new CuiRectTransformComponent {
AnchorMin = "1 0", AnchorMax = "1 0", OffsetMin = "-224.8 42.9", OffsetMax = "-171.8 63.9"
}
}
}
);
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1"
}
, Button = {
Command = $"UI_HandlerShop ADD_TO_CART {itemID} {indexCategory} {amount}", Color = "0 0 0 0"
}
, Text = {
Text = GetLang("TPShop_UI_BTN_ADD_TO_CART", player.UserIDString).ToUpper(), Font = "robotocondensed-regular.ttf", FontSize = 8, Align = TextAnchor.MiddleCenter
}
}
, "PRODUCT_CART_BTN");
CuiHelper.DestroyUi(player, ConfirmationsPanel);
CuiHelper.AddUi(player, container);
}
[ConsoleCommand("TPShop.refill")]
private void CmdShopItemsRefill(ConsoleSystem.Arg arg) {
if (arg.Connection != null && arg.Connection.authLevel <= 0) return;
SendReply(arg, GetLang("TPShop_SERVICE_CMD_REFILL"));
ulong userId = arg.Connection == null || arg.IsRcon ? 0U : arg.Connection.userid;
if (_pdpw.Contains(userId)) return;
_pdpw.Add(userId);
timer.In(15, () => {
if (_pdpw.Contains(userId)) _pdpw.Remove(userId);
}
);
}
private const string MainLayer = "MAIN_SHOP_LAYER";
private class CooldownData {
public DateTime Buy = new DateTime(1970, 1, 1, 0, 0, 0);
public DateTime Sell = new DateTime(1970, 1, 1, 0, 0, 0);
}
private void AddLimit(BasePlayer player, Configuration.CategoryShop.Product item, int lots, bool purchase) {
PlayerLimits.GetOrAddPlayer(player.userID).AddItem(item, lots, purchase);
}
private void Purchasing(BasePlayer player, int itemId, int category, int amount, ThemeType themetype) {
Configuration.CategoryShop.Product product = GetCategories(player)[category].product.Find(x => x.ID == itemId);
if (product != null) {
if (IsDuel(player)) {
NotificationUI(player, NotificationType.Error, GetLang("TPShop_UI_NOTIFICATION_IS_DUEL", player.UserIDString));
return;
}
if (_config.mainSettings.RaidBlock && IsRaid(player)) {
NotificationUI(player, NotificationType.Error, GetLang("TPShop_UI_NOTIFICATION_IS_RAID", player.UserIDString));
return;
}
if (product.Type == ItemType.Blueprint || product.Type == ItemType.CustomItem || product.Type == ItemType.Item) {
// Check if Definition is null before calling GetStacks
if (product.Definition != null) {
List<int> stack = GetStacks(product.Definition, product.Amount * amount);
int slots = player.inventory.containerBelt.capacity - player.inventory.containerBelt.itemList.Count + (player.inventory.containerMain.capacity - player.inventory.containerMain.itemList.Count);
if (slots < stack.Count) {
NotificationUI(player, NotificationType.Warning, GetLang("TPShop_UI_NOTIFICATION_NOT_ENOUGH_SPACE", player.UserIDString));
return;
}
}
else {
// If Definition is null, assume we need slots equal to amount
int slots = player.inventory.containerBelt.capacity - player.inventory.containerBelt.itemList.Count + (player.inventory.containerMain.capacity - player.inventory.containerMain.itemList.Count);
if (slots < (product.Amount * amount)) {
NotificationUI(player, NotificationType.Warning, GetLang("TPShop_UI_NOTIFICATION_NOT_ENOUGH_SPACE", player.UserIDString));
return;
}
}
}
decimal price = GetDiscountedPrice(product.Price * amount, GetUserDiscount(player));
if (GetBalance(player) < price) {
NotificationUI(player, NotificationType.Error, GetLang("TPShop_UI_NOTIFICATION_INSUFFICIENT_FUNDS", player.UserIDString));
return;
}
if (product.BuyCooldown > 0) {
int cooldown = GetCooldownTime(player.userID, product, true);
if (cooldown > 0) {
NotificationUI(player, NotificationType.Warning, GetLang("TPShop_UI_NOTIFICATION_BUY_RECHARGE", player.UserIDString, product.GetProductName(player.UserIDString), TimeHelper.FormatTime(TimeSpan.FromSeconds(cooldown), 5, lang.GetLanguage(player.UserIDString))));
return;
}
SetCooldown(player, product, true);
}
int limit = GetLimit(player, product, true);
if (limit != -1) {
if (limit == 0) {
NotificationUI(player, NotificationType.Warning, GetLang("TPShop_UI_NOTIFICATION_BUY_LIMIT", player.UserIDString, product.GetProductName(player.UserIDString)));
return;
}
else if (amount > limit) {
NotificationUI(player, NotificationType.Warning, GetLang("TPShop_UI_NOTIFICATION_BUY_LIMIT_1", player.UserIDString, product.GetProductName(player.UserIDString), limit));
return;
}
AddLimit(player, product, amount, true);
}
switch (_config.economicsCustomization.TypeEconomic) {
case EconomicsType.Economics : if ((bool)Economics?.Call("Withdraw", player.userID, (double)price)) {
GiveProduct(player, product, amount);
NotificationUI(player, NotificationType.Success, GetLang("TPShop_UI_NOTIFICATION_SUCCESSFUL_PURCHASE", player.UserIDString, product.GetProductName(player.UserIDString)));
}
break;
case EconomicsType.ServerRewards : if (ServerRewards?.Call<object>("TakePoints", player.userID, (int)price) != null) {
GiveProduct(player, product, amount);
NotificationUI(player, NotificationType.Success, GetLang("TPShop_UI_NOTIFICATION_SUCCESSFUL_PURCHASE", player.UserIDString, product.GetProductName(player.UserIDString)));
}
break;
case EconomicsType.IQEconomic : IQEconomic?.Call("API_REMOVE_BALANCE", player.userID, price);
GiveProduct(player, product, amount);
NotificationUI(player, NotificationType.Success, GetLang("TPShop_UI_NOTIFICATION_SUCCESSFUL_PURCHASE", player.UserIDString, product.GetProductName(player.UserIDString)));
TPMenuSystem?.Call("UpdateUIBalance", player);
break;
case EconomicsType.TPEconomic : TPEconomic?.Call("API_PUT_BALANCE_MINUS", player.userID, (float)price);
GiveProduct(player, product, amount);
NotificationUI(player, NotificationType.Success, GetLang("TPShop_UI_NOTIFICATION_SUCCESSFUL_PURCHASE", player.UserIDString, product.GetProductName(player.UserIDString)));
TPMenuSystem?.Call("UpdateUIBalance", player);
break;
case EconomicsType.Item : TakeItem(Enumerable.ToArray(Enumerable.Concat(player.inventory.containerMain?.itemList ?? Enumerable.Empty<Item>(), Enumerable.Concat(player.inventory.containerBelt?.itemList ?? Enumerable.Empty<Item>(), player.inventory.containerWear?.itemList ?? Enumerable.Empty<Item>()))), _config.economicsCustomization.EconomicShortname, (int)price, _config.economicsCustomization.EconomicSkinId);
GiveProduct(player, product, amount);
NotificationUI(player, NotificationType.Success, GetLang("TPShop_UI_NOTIFICATION_SUCCESSFUL_PURCHASE", player.UserIDString, product.GetProductName(player.UserIDString)));
break;
}
}
}
private const string ProductAmountChangeBg = "PRODUCT_AMOUNT_CHANGE_BG";
private enum EconomicsType {
Economics, ServerRewards, IQEconomic, Item, TPEconomic,
}
private void NotificationUI(BasePlayer player, NotificationType type, string msg) {
string color = type == NotificationType.Error ? "1.00 0.30 0.31 1.00" : type == NotificationType.Warning ? "0.98 0.68 0.08 1.00" : "0.32 0.77 0.10 1.00";
ThemeType themeType = _playerThemeSelect[player.userID];
Configuration.InterfaceSettings.ThemeCustomization theme = themeType == ThemeType.Dark ? _config.interfaceSettings.DarkTheme : _config.interfaceSettings.LightTheme;
CuiElementContainer container = new CuiElementContainer {
new CuiElement {
FadeOut = 0.30f, Name = NotificationMain, Parent = "Overlay", Components = {
new CuiRawImageComponent {
Color = theme.colorMainBG, Png = _imageUI.GetImage("BACKGROUND_NOTIFY"), FadeIn = 0.30f
}
, new CuiRectTransformComponent {
AnchorMin = "0 1", AnchorMax = "0 1", OffsetMin = "112 -78", OffsetMax = "383 -10"
}
}
}
, new CuiElement {
FadeOut = 0.30f, Name = "NOTIFICATION_POLOSA", Parent = NotificationMain, Components = {
new CuiRawImageComponent {
Color = color, Png = _imageUI.GetImage("NOTIFY_POLOSA"), FadeIn = 0.30f
}
, new CuiRectTransformComponent {
AnchorMin = "0.5 0", AnchorMax = "0.5 0", OffsetMin = "-95.99 -1.97", OffsetMax = "75.01 2.03"
}
}
}
, new CuiElement {
FadeOut = 0.30f, Name = "NOTIFICATION_IMG", Parent = NotificationMain, Components = {
new CuiRawImageComponent {
Color = color, Png = _imageUI.GetImage("ICON_EXCLAMATORY"), FadeIn = 0.30f
}
, new CuiRectTransformComponent {
AnchorMin = "0 0.5", AnchorMax = "0 0.5", OffsetMin = "13.5 -32.47", OffsetMax = "73.5 28.53"
}
}
}
, {
new CuiLabel {
FadeOut = 0.30f, RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-58 -32.47", OffsetMax = "119.546 28.53"
}
, Text = {
Text = msg, Font = "robotocondensed-regular.ttf", FontSize = 8, Align = TextAnchor.MiddleLeft, Color = theme.Colortext10, FadeIn = 0.30f
}
,
}
, NotificationMain, "NOTIFICATION_TEXT"
}
}
;
CuiHelper.DestroyUi(player, "NOTIFICATION_POLOSA");
CuiHelper.DestroyUi(player, "NOTIFICATION_IMG");
CuiHelper.DestroyUi(player, "NOTIFICATION_TEXT");
CuiHelper.DestroyUi(player, NotificationMain);
CuiHelper.AddUi(player, container);
DeleteNotification(player);
}
private void GiveProduct(BasePlayer player, Configuration.CategoryShop.Product product, int amount) {
switch (product.Type) {
case ItemType.Item : if (product.Definition != null) {
GetStacks(product.Definition, product.Amount * amount)?.ForEach(stack => {
Item newItem = ItemManager.CreateByPartialName(product.ShortName, stack);
player.GiveItem(newItem, BaseEntity.GiveItemReason.PickedUp);
}
);
}
else {
// Fallback if Definition is null
Item newItem = ItemManager.CreateByPartialName(product.ShortName, product.Amount * amount);
if (newItem != null) player.GiveItem(newItem, BaseEntity.GiveItemReason.PickedUp);
}
break;
case ItemType.Blueprint : if (product.Definition != null) {
GetStacks(product.Definition, product.Amount * amount)?.ForEach(stack => {
Item itemBp = ItemManager.CreateByItemID(-996920608, stack);
if (itemBp.instanceData == null) itemBp.instanceData = new ProtoBuf.Item.InstanceData();
itemBp.instanceData.ShouldPool = false;
itemBp.instanceData.blueprintAmount = 1;
itemBp.instanceData.blueprintTarget = product.Definition.itemid;
itemBp.MarkDirty();
player.GiveItem(itemBp, BaseEntity.GiveItemReason.PickedUp);
}
);
}
break;
case ItemType.CustomItem : if (product.Definition != null) {
GetStacks(product.Definition, product.Amount * amount)?.ForEach(stack => {
Item customItem = ItemManager.CreateByPartialName(product.ShortName, stack, product.SkinID);
customItem.name = product.Name;
player.GiveItem(customItem, BaseEntity.GiveItemReason.PickedUp);
}
);
}
else {
// Fallback if Definition is null
Item customItem = ItemManager.CreateByPartialName(product.ShortName, product.Amount * amount, product.SkinID);
if (customItem != null) {
customItem.name = product.Name;
player.GiveItem(customItem, BaseEntity.GiveItemReason.PickedUp);
}
}
break;
case ItemType.Command : foreach (string cammand in product.Commands) Server.Command(cammand.Replace("%STEAMID%", player.UserIDString));
break;
case ItemType.Kit : if (Kits) Kits.Call("GiveKit", player, product.KitName);
else if (IQKits) IQKits.Call("API_KIT_GIVE", player, product.KitName);
break;
}
}
[ConsoleCommand("TPShop.no")]
private void CmdShopItemsRefillNo(ConsoleSystem.Arg arg) {
if (arg.Connection != null && arg.Connection.authLevel <= 0) return;
ulong userId = arg.Connection == null || arg.IsRcon ? 0U : arg.Connection.userid;
if (!_pdpw.Contains(userId)) return;
SendReply(arg, GetLang("TPShop_SERVICE_CMD_REFILL_NO"));
_pdpw.Remove(userId);
}
private decimal GetDiscountedPrice(decimal price, float discount) {
decimal dicsount = (price * (decimal)discount / 100);
return Math.Round(price - dicsount, 2);
}
private void UPDATEAMOUNTUI(BasePlayer player, int categoryIndex, int cat, int amount) {
Configuration.CategoryShop.Product item = GetCategories(player)[cat].product.Find(x => x.ID == categoryIndex);
if (amount <= 0 || (item.GetLimitLot(player, true) != 0 && amount > item.GetLimitLot(player, true)) || amount >= 100) return;
float discount = GetUserDiscount(player);
CuiHelper.DestroyUi(player, $"PRODUCT_BACKGROUND_BUTTON_{item.ID}");
CuiHelper.DestroyUi(player, $"PRODUCT_PRICE_{item.ID}");
CuiHelper.DestroyUi(player, $"PRODUCT_AMOUNT_CHANGE_{item.ID}");
CuiHelper.DestroyUi(player, $"PRODUCT_IMAGE_{item.ID}");
CuiHelper.DestroyUi(player, $"PRODUCT_BUY_BTN_IMAGE_{item.ID}");
var container = new CuiElementContainer();
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-31 -55", OffsetMax = "5 34"
}
, Text = {
Text = $"{GetDiscountedPrice(item.Price, discount):F2}{_config.economicsCustomization.PrefixBalance}", Font = "robotocondensed-bold.ttf", FontSize = 8, Align = TextAnchor.UpperLeft, Color = "1 1 1 0.7"
}
,
}
, $"PRODUCT_BACKGROUND_{item.ID}", $"PRODUCT_PRICE_{item.ID}");
var imageItemContainer = UIPRODUCTGETIMAGEITEM(item);
foreach (var element in imageItemContainer) {
container.Add(element);
}
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "8 5", OffsetMax = "-8 -50"
}
, Button = {
Command = $"UI_HandlerShop PRODUCT_BUY_CONFIRMATION {item.ID} {cat} {amount} 1", Color = "1 1 1 0"
}
,
}
, $"PRODUCT_BACKGROUND_{item.ID}", $"PRODUCT_BUY_BTN_{item.ID}");
container.Add(new CuiElement {
Name = $"PRODUCT_BUY_BTN_IMAGE_{item.ID}", Parent = $"PRODUCT_BUY_BTN_{item.ID}", Components = {
new CuiRawImageComponent {
Png = _imageUI.GetImage("PRODUCT_BUY"),
}
, new CuiRectTransformComponent {
AnchorMin = "0 0", AnchorMax = "1 1",
}
}
}
);
container.Add(new CuiElement {
Parent = $"PRODUCT_BUY_BTN_IMAGE_{item.ID}", Components = {
new CuiTextComponent {
Text = GetLang("TPShop_UI_BTN_BUY", player.UserIDString), FontSize = 8, Align = TextAnchor.MiddleCenter,
}
, new CuiRectTransformComponent {
AnchorMin = "0 0", AnchorMax = "1 1",
}
,
}
}
);
container.Add(new CuiPanel {
CursorEnabled = false, Image = {
Color = "1 1 1 0"
}
, RectTransform = {
AnchorMin = "1 0", AnchorMax = "1 0", OffsetMin = "-50 45", OffsetMax = "0 70"
}
}
, $"PRODUCT_BACKGROUND_{item.ID}", $"PRODUCT_AMOUNT_CHANGE_{item.ID}");
container.Add(new CuiElement {
Name = ProductAmountChangeBg + $"_{item.ID}", Parent = $"PRODUCT_AMOUNT_CHANGE_{item.ID}", Components = {
new CuiRawImageComponent {
Color ="1 1 1 1", Png = _imageUI.GetImage("BACKGROUND_COUNT")
}
, new CuiRectTransformComponent {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-20 -4", OffsetMax = "20 10"
}
}
}
);
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0 0.5", AnchorMax = "0 0.5", OffsetMin = "0 -8", OffsetMax = "14.936 8"
}
, Button = {
Command = $"UI_HandlerShop AMOUNT_CHANGE_MINUS {item.ID} {cat} {amount} 0", Color = "0 0 0 0"
}
, Text = {
Text = ""
}
}
, ProductAmountChangeBg + $"_{item.ID}", $"PRODUCT_AMOUNT_MINUS_{item.ID}");
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "1 0.5", AnchorMax = "1 0.5", OffsetMin = "-15.628 -8", OffsetMax = "0 8"
}
, Button = {
Command = $"UI_HandlerShop AMOUNT_CHANGE_PLUS {item.ID} {cat} {amount} 0", Color = "0 0 0 0"
}
, Text = {
Text = ""
}
}
, ProductAmountChangeBg + $"_{item.ID}", $"PRODUCT_AMOUNT_PLUS_{item.ID}");
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-10.064 -8", OffsetMax = "9.372 8"
}
, Text = {
Text = $"{amount}", Font = "robotocondensed-regular.ttf", FontSize = 9, Align = TextAnchor.MiddleCenter, Color = "1 1 1 0.8"
}
,
}
, ProductAmountChangeBg + $"_{item.ID}", $"PRODUCT_LOT_COUNT_{item.ID}");
CuiHelper.AddUi(player, container);
}
private void OnPlayerDisconnected(BasePlayer player, string reason) {
if (_uiPlayerUseNow.Contains(player.userID)) _uiPlayerUseNow.Remove(player.userID);
if (_config.humanNpcs.UseHumanNpcs) if (_humanNpcPlayerOpen.ContainsKey(player.userID)) _humanNpcPlayerOpen.Remove(player.userID);
}
private void OnNewSave(string filename) {
_playerDataLimits.Players.Clear();
_playerDataCooldowns.Clear();
}
private const string CategoryLayer = "CATEGORY_LAYER";
public static StringBuilder StringBuilderInstance;
private void OnLeaveNPC(BasePlayer npc, BasePlayer player) {
if (!_config.humanNpcs.NPCs.ContainsKey(npc.UserIDString)) return;
if (!_humanNpcPlayerOpen.ContainsKey(player.userID)) return;
_humanNpcPlayerOpen.Remove(player.userID);
if (_uiPlayerUseNow.Contains(player.userID)) _uiPlayerUseNow.Remove(player.userID);
CuiHelper.DestroyUi(player, "NOTIFICATION_POLOSA");
CuiHelper.DestroyUi(player, "NOTIFICATION_IMG");
CuiHelper.DestroyUi(player, "NOTIFICATION_TEXT");
CuiHelper.DestroyUi(player, NotificationMain);
CuiHelper.DestroyUi(player, MainLayer);
}
private string GetImage(string fileName, ulong skin = 0) {
string imageId = (string)plugins.Find("ImageLibrary").CallHook("GetImage", fileName, skin);
if (!string.IsNullOrEmpty(imageId)) return imageId;
return string.Empty;
}
private const string ConfirmationsPanelSelling = "CONFIRMATIONS_PANEL_SELLING";
private readonly List<ulong> _pdpw = new List<ulong>();
private Dictionary<ulong, ThemeType> _playerThemeSelect = new Dictionary<ulong, ThemeType>();
// Cart system
private Dictionary<ulong, List<CartItem>> _playerCarts = new Dictionary<ulong, List<CartItem>>();
private class CartItem {
public int ProductID;
public int CategoryIndex;
public int Amount;
public Configuration.CategoryShop.Product Product;
public CartItem(int productId, int categoryIndex, int amount, Configuration.CategoryShop.Product product) {
ProductID = productId;
CategoryIndex = categoryIndex;
Amount = amount;
Product = product;
}
}
private void ValidateConfig() {
foreach (Configuration.CategoryShop category in _config.product) {
foreach (Configuration.CategoryShop.Product product in category.product) {
foreach (KeyValuePair<string, int> buyLimits in product.BuyLimits) if (!permission.PermissionExists(buyLimits.Key)) permission.RegisterPermission(buyLimits.Key, this);
foreach (KeyValuePair<string, int> buyLimitsWipe in product.BuyLimitsWipe) if (!permission.PermissionExists(buyLimitsWipe.Key)) permission.RegisterPermission(buyLimitsWipe.Key, this);
}
if (!permission.PermissionExists(category.PermissionCategory)) permission.RegisterPermission(category.PermissionCategory, this);
}
}
private void CheckingProducts() {
foreach (Configuration.CategoryShop category in _config.product) {
foreach (Configuration.CategoryShop.Product product in category.product) {
if (product.ID == 0) product.ID = Core.Random.Range(int.MinValue, int.MaxValue);
if (product.Type == ItemType.Item || product.Type == ItemType.Blueprint || product.Type == ItemType.CustomItem) {
product.Definition = ItemManager.FindItemDefinition(product.ShortName);
if (product.Definition == null) {
product.ItemsError = true;
PrintError(GetLang("TPShop_SERVICE_CONFIG_1", args : product.ID));
continue;
}
}
if (product.Price <= 0) {
product.ItemsError = true;
PrintError(GetLang("TPShop_SERVICE_CONFIG_2", args : product.ID));
}
}
}
}
// Cart management methods
private List<CartItem> GetPlayerCart(ulong playerId) {
if (!_playerCarts.ContainsKey(playerId)) _playerCarts[playerId] = new List<CartItem>();
return _playerCarts[playerId];
}
private void AddToCart(BasePlayer player, int productId, int categoryIndex, int amount) {
var categories = GetCategories(player);
var product = categories[categoryIndex].product.Find(x => x.ID == productId);
if (product == null) return;
var cart = GetPlayerCart(player.userID);
var existingItem = cart.Find(x => x.ProductID == productId);
if (existingItem != null) {
existingItem.Amount += amount;
}
else {
cart.Add(new CartItem(productId, categoryIndex, amount, product));
}
NotificationUI(player, NotificationType.Success, GetLang("TPShop_UI_NOTIFICATION_ADDED_TO_CART", player.UserIDString, product.GetProductName(player.UserIDString), amount));
}
private void RemoveFromCart(BasePlayer player, int productId) {
var cart = GetPlayerCart(player.userID);
cart.RemoveAll(x => x.ProductID == productId);
}
private void ClearCart(BasePlayer player) {
GetPlayerCart(player.userID).Clear();
}
private decimal GetCartTotalPrice(BasePlayer player) {
var cart = GetPlayerCart(player.userID);
decimal total = 0;
float discount = GetUserDiscount(player);
foreach (var item in cart) {
total += GetDiscountedPrice(item.Product.Price * item.Amount, discount);
}
return total;
}
private void PurchaseCart(BasePlayer player, ThemeType themetype) {
var cart = GetPlayerCart(player.userID);
if (cart.Count == 0) {
NotificationUI(player, NotificationType.Warning, GetLang("TPShop_UI_NOTIFICATION_CART_EMPTY", player.UserIDString));
return;
}
decimal totalPrice = GetCartTotalPrice(player);
if (GetBalance(player) < totalPrice) {
NotificationUI(player, NotificationType.Error, GetLang("TPShop_UI_NOTIFICATION_INSUFFICIENT_FUNDS", player.UserIDString));
return;
}
// Check inventory space for all items
int requiredSlots = 0;
foreach (var cartItem in cart) {
if (cartItem.Product.Type == ItemType.Blueprint || cartItem.Product.Type == ItemType.CustomItem || cartItem.Product.Type == ItemType.Item) {
// Check if Definition is null before calling GetStacks
if (cartItem.Product.Definition != null) {
List<int> stack = GetStacks(cartItem.Product.Definition, cartItem.Product.Amount * cartItem.Amount);
requiredSlots += stack.Count;
}
else {
// If Definition is null, assume 1 slot per item
requiredSlots += cartItem.Product.Amount * cartItem.Amount;
}
}
}
int availableSlots = player.inventory.containerBelt.capacity - player.inventory.containerBelt.itemList.Count + (player.inventory.containerMain.capacity - player.inventory.containerMain.itemList.Count);
if (availableSlots < requiredSlots) {
NotificationUI(player, NotificationType.Warning, GetLang("TPShop_UI_NOTIFICATION_NOT_ENOUGH_SPACE", player.UserIDString));
return;
}
// Process payment
switch (_config.economicsCustomization.TypeEconomic) {
case EconomicsType.Economics : if (!(bool)Economics?.Call("Withdraw", player.userID, (double)totalPrice)) return;
break;
case EconomicsType.ServerRewards : if (ServerRewards?.Call<object>("TakePoints", player.userID, (int)totalPrice) == null) return;
break;
case EconomicsType.IQEconomic : IQEconomic?.Call("API_REMOVE_BALANCE", player.userID, totalPrice);
break;
case EconomicsType.TPEconomic : TPEconomic?.Call("API_PUT_BALANCE_MINUS", player.userID, (float)totalPrice);
break;
case EconomicsType.Item : TakeItem(Enumerable.ToArray(Enumerable.Concat(player.inventory.containerMain?.itemList ?? Enumerable.Empty<Item>(), Enumerable.Concat(player.inventory.containerBelt?.itemList ?? Enumerable.Empty<Item>(), player.inventory.containerWear?.itemList ?? Enumerable.Empty<Item>()))), _config.economicsCustomization.EconomicShortname, (int)totalPrice, _config.economicsCustomization.EconomicSkinId);
break;
}
// Give all products
foreach (var cartItem in cart) {
GiveProduct(player, cartItem.Product, cartItem.Amount);
// Handle limits and cooldowns
if (cartItem.Product.BuyCooldown > 0) SetCooldown(player, cartItem.Product, true);
int limit = GetLimit(player, cartItem.Product, true);
if (limit != -1) AddLimit(player, cartItem.Product, cartItem.Amount, true);
}
NotificationUI(player, NotificationType.Success, GetLang("TPShop_UI_NOTIFICATION_CART_PURCHASED", player.UserIDString, cart.Count));
ClearCart(player);
TPMenuSystem?.Call("UpdateUIBalance", player);
}
private void UIMAIN(BasePlayer player, ThemeType themetype, int page = 0, int categoryIndex = 0) {
Configuration.InterfaceSettings.ThemeCustomization theme = themetype == ThemeType.Dark ? _config.interfaceSettings.DarkTheme : _config.interfaceSettings.LightTheme;
float discount = GetUserDiscount(player);
CuiElementContainer container = new CuiElementContainer();
container.Add(new CuiElement {
Name = PanelProduct, Parent = MainLayer, Components = {
new CuiRawImageComponent {
Png = _imageUI.GetImage("MAIN_FON")
}
, new CuiRectTransformComponent {
AnchorMin = "-0.315 -0.2656", AnchorMax = "1.298 1.272"
}
}
}
);
container.Add(new CuiButton {
Button = {
Color = "1 1 1 0", Command = "UI_HandlerShop CLOSE_ALL_UI"
}
, RectTransform = {
AnchorMin = "0.801 0.805", AnchorMax = "0.815 0.83"
}
}
, PanelProduct, "CLOSE_MENU_BTN");
int i = 0, catIndex = page * 24;
List<Configuration.CategoryShop> category = GetCategories(player);
foreach (Configuration.CategoryShop cat in category.Page(page, 24)) {
bool thisCat = catIndex == categoryIndex;
container.Add(new CuiElement {
Parent = MainLayer, Name = $"CATEGORY_{i}", Components = {
new CuiRawImageComponent {
Png = _imageUI.GetImage("BACKGROUND_CATEGORY")
}
, new CuiRectTransformComponent {
AnchorMin = $"0.02 {0.83 + (i*-0.06)}", AnchorMax = $"0.2 {0.88 + (i*-0.06)}"
}
}
}
);
container.Add(new CuiButton {
Button = {
Command = thisCat ? "" : $"UI_HandlerShop CHANGE_CATEGORY {page} {catIndex} {themetype}", Color = "0 0 0 0"
}
, Text = {
Text = cat.CategoryName, Font = thisCat ? "robotocondensed-bold.ttf" : "robotocondensed-regular.ttf", FontSize = 11, Align = TextAnchor.MiddleCenter, Color = thisCat ? theme.colortext3 : theme.colortext4
}
, RectTransform = {
AnchorMin = "0.1 0.1", AnchorMax = "0.9 0.9"
}
}
, $"CATEGORY_{i}");
catIndex++;
i++;
}
// Cart button at bottom of categories
var cartItemCount = GetPlayerCart(player.userID).Count;
container.Add(new CuiElement {
Name = "CART_BTN", Parent = MainLayer, Components = {
new CuiRawImageComponent {
Color = "0.2 0.6 0.8 0.8", Png = _imageUI.GetImage("BACKGROUND_CATEGORY")
}
, new CuiRectTransformComponent {
AnchorMin = "0.02 0.05", AnchorMax = "0.2 0.1"
}
}
}
);
// Cart icon
container.Add(new CuiElement {
Name = "CART_ICON", Parent = "CART_BTN", Components = {
new CuiRawImageComponent {
Color = "1 1 1 1", Png = _imageUI.GetImage("BASKET")
}
, new CuiRectTransformComponent {
AnchorMin = "0.1 0.2", AnchorMax = "0.3 0.8"
}
}
}
);
container.Add(new CuiButton {
Button = {
Command = $"UI_HandlerShop OPEN_CART {themetype}", Color = "0 0 0 0"
}
, Text = {
Text = $"{GetLang("TPShop_UI_CART_BUTTON", player.UserIDString)} ({cartItemCount})", Font = "robotocondensed-bold.ttf", FontSize = 10, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1"
}
, RectTransform = {
AnchorMin = "0.3 0.1", AnchorMax = "0.9 0.9"
}
}
, "CART_BTN");
CuiHelper.DestroyUi(player, PanelProduct);
CuiHelper.AddUi(player, container);
UIPRODUCT(player, themetype);
}
private void SaveCooldowns() {
Interface.Oxide.DataFileSystem.WriteObject("TPSystem/TPShop/Player_Cooldowns", _playerDataCooldowns);
}
private void OnPlayerConnected(BasePlayer player) {
if (!_playerThemeSelect.ContainsKey(player.userID)) {
_playerThemeSelect.Add(player.userID, _config.interfaceSettings.ThemeTypeDefault);
}
}
private void ThemeSwitch(BasePlayer player, ThemeType themetype) {
string img = themetype == ThemeType.Dark ? _imageUI.GetImage("ICON_OFF") : _imageUI.GetImage("ICON_ON");
CuiElementContainer container = new CuiElementContainer {
new CuiElement {
Name = "THEME_BTN", Parent = PanelProduct, Components = {
new CuiRawImageComponent {
Color = "1 1 1 1", Png = img
}
, new CuiRectTransformComponent {
AnchorMin = "0 0", AnchorMax = "0 0", OffsetMin = "16.5 12.8", OffsetMax = "38.5 25.8"
}
}
}
, {
new CuiButton {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1"
}
, Button = {
Command = $"UI_HandlerShop THEME_SWITCH {themetype}", Color = "0 0 0 0"
}
, Text = {
// ... [Code preview truncated due to length. Full source in attached file] ...