C#:
using System;
using System.Collections.Generic;
using System.Linq;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Plugins;
using Oxide.Game.Rust.Cui;
using Newtonsoft.Json;
using UnityEngine;
namespace Oxide.Plugins {
[Info("NWGMarket", "NWG Team", "4.0.0")]
[Description("In-game Shop and Economy for NWG with ImageLibrary integration.")]
public class NWGMarket : RustPlugin {
#region References
[PluginReference]
private Plugin ImageLibrary;
#endregion
#region UI Constants
private static class UIConstants {
// Theme: Sage Green & Dark
public const string PanelColor = "0.15 0.15 0.15 0.98";
public const string HeaderColor = "0.1 0.1 0.1 1";
public const string Primary = "0.718 0.816 0.573 1";
// Sage Green
public const string Secondary = "0.851 0.325 0.31 1";
// Red/Rust
public const string Accent = "1 0.647 0 1";
// Orange
public const string Text = "0.867 0.867 0.867 1";
// Soft White
public const string OverlayColor = "0.05 0.05 0.05 0.98";
public const string ButtonInactive = "0.15 0.15 0.15 0.7";
public const string ButtonActive = "0.718 0.816 0.573 0.8";
// Sage Green Transparent
public const string BuyButton = "0.3 0.5 0.2 0.8";
public const string SellButton = "0.7 0.2 0.2 0.8";
public const string SellAllButton = "0.851 0.325 0.31 0.9";
// Red/Rust
public const string ItemPanel = "0.1 0.1 0.1 0.6";
}
#endregion
#region Config
private class PluginConfig {
public double StartingBalance = 2500.0;
public string CurrencySymbol = "$";
public string ShopTitle = "NWG STORE";
public string ShopCommand = "shop";
public string BalanceCommand = "balance";
public List<ShopCategory> Categories = new List<ShopCategory>();
}
private class ShopCategory {
public string Name;
public List<ShopItem> Items = new List<ShopItem>();
}
private class ShopItem {
public string ShortName;
public string DisplayName;
public ulong SkinId;
public int Amount = 1;
public double BuyPrice;
public double SellPrice;
public string Command;
}
private PluginConfig _config;
#endregion
#region Data
private class StoredData {
public Dictionary<ulong, double> Balances = new Dictionary<ulong, double>();
}
private StoredData _data;
private readonly Dictionary<string, ItemDefinition> _itemDefCache = new Dictionary<string, ItemDefinition>();
// Key: PlayerID, Value: Search Term
private readonly Dictionary<ulong, string> _searchFilters = new Dictionary<ulong, string>();
#endregion
#region Lifecycle
private void Init() {
LoadConfigVariables();
LoadData();
cmd.AddChatCommand(_config.ShopCommand, this, nameof(CmdShop));
cmd.AddChatCommand(_config.BalanceCommand, this, nameof(CmdBalance));
}
private void LoadData() {
_data = Interface.Oxide.DataFileSystem.ReadObject<StoredData>("NWG_Market") ?? new StoredData();
}
private void LoadConfigVariables() {
_config = Config.ReadObject<PluginConfig>();
if (_config == null || _config.Categories.Count == 0) {
LoadDefaultConfig();
}
}
protected override void LoadDefaultConfig() {
Puts("Generating NWG Market Defaults with requested pricing.");
_config = new PluginConfig();
// Resources
var resCat = new ShopCategory {
Name = "Resources"
}
;
resCat.Items.Add(new ShopItem {
ShortName = "wood", Amount = 1000, BuyPrice = 100, SellPrice = 20
}
);
resCat.Items.Add(new ShopItem {
ShortName = "stones", Amount = 1000, BuyPrice = 200, SellPrice = 40
}
);
resCat.Items.Add(new ShopItem {
ShortName = "metal.fragments", Amount = 1000, BuyPrice = 400, SellPrice = 80
}
);
resCat.Items.Add(new ShopItem {
ShortName = "metal.refined", Amount = 100, BuyPrice = 500, SellPrice = 100
}
);
resCat.Items.Add(new ShopItem {
ShortName = "sulfur", Amount = 1000, BuyPrice = 500, SellPrice = 100
}
);
resCat.Items.Add(new ShopItem {
ShortName = "cloth", Amount = 100, BuyPrice = 400, SellPrice = 80
}
);
resCat.Items.Add(new ShopItem {
ShortName = "leather", Amount = 100, BuyPrice = 200, SellPrice = 40
}
);
resCat.Items.Add(new ShopItem {
ShortName = "charcoal", Amount = 1000, BuyPrice = 500, SellPrice = 100
}
);
_config.Categories.Add(resCat);
// Weapons
var weapCat = new ShopCategory {
Name = "Weapons"
}
;
weapCat.Items.Add(new ShopItem {
ShortName = "rifle.ak", Amount = 1, BuyPrice = 3000, SellPrice = 600
}
);
weapCat.Items.Add(new ShopItem {
ShortName = "rifle.semi", Amount = 1, BuyPrice = 1500, SellPrice = 300
}
);
weapCat.Items.Add(new ShopItem {
ShortName = "smg.thompson", Amount = 1, BuyPrice = 1200, SellPrice = 250
}
);
weapCat.Items.Add(new ShopItem {
ShortName = "pistol.semi", Amount = 1, BuyPrice = 950, SellPrice = 200
}
);
weapCat.Items.Add(new ShopItem {
ShortName = "shotgun.pump", Amount = 1, BuyPrice = 1000, SellPrice = 200
}
);
weapCat.Items.Add(new ShopItem {
ShortName = "bow.hunting", Amount = 1, BuyPrice = 120, SellPrice = 20
}
);
weapCat.Items.Add(new ShopItem {
ShortName = "crossbow", Amount = 1, BuyPrice = 300, SellPrice = 60
}
);
weapCat.Items.Add(new ShopItem {
ShortName = "pistol.revolver", Amount = 1, BuyPrice = 600, SellPrice = 120
}
);
_config.Categories.Add(weapCat);
// Ammo
var ammoCat = new ShopCategory {
Name = "Ammunition"
}
;
ammoCat.Items.Add(new ShopItem {
ShortName = "ammo.rifle", Amount = 128, BuyPrice = 750, SellPrice = 150
}
);
ammoCat.Items.Add(new ShopItem {
ShortName = "ammo.pistol", Amount = 128, BuyPrice = 350, SellPrice = 70
}
);
ammoCat.Items.Add(new ShopItem {
ShortName = "ammo.shotgun", Amount = 64, BuyPrice = 200, SellPrice = 40
}
);
ammoCat.Items.Add(new ShopItem {
ShortName = "ammo.rifle.explosive", Amount = 64, BuyPrice = 1250, SellPrice = 250
}
);
ammoCat.Items.Add(new ShopItem {
ShortName = "arrow.wooden", Amount = 64, BuyPrice = 100, SellPrice = 20
}
);
_config.Categories.Add(ammoCat);
// Medicine
var medCat = new ShopCategory {
Name = "Medicine"
}
;
medCat.Items.Add(new ShopItem {
ShortName = "syringe.medical", Amount = 1, BuyPrice = 100, SellPrice = 20
}
);
medCat.Items.Add(new ShopItem {
ShortName = "largemedkit", Amount = 1, BuyPrice = 200, SellPrice = 40
}
);
_config.Categories.Add(medCat);
// Tools
var toolCat = new ShopCategory {
Name = "Tools"
}
;
toolCat.Items.Add(new ShopItem {
ShortName = "mining.quarry", Amount = 1, BuyPrice = 12500, SellPrice = 2000, DisplayName = "Mining Quarry"
}
);
toolCat.Items.Add(new ShopItem {
ShortName = "mining.pumpjack", Amount = 1, BuyPrice = 17500, SellPrice = 2500, DisplayName = "Pump Jack"
}
);
toolCat.Items.Add(new ShopItem {
ShortName = "survey.charge", Amount = 1, BuyPrice = 1000, SellPrice = 100, DisplayName = "Survey Charge"
}
);
toolCat.Items.Add(new ShopItem {
ShortName = "jackhammer", Amount = 1, BuyPrice = 1500, SellPrice = 300
}
);
toolCat.Items.Add(new ShopItem {
ShortName = "chainsaw", Amount = 1, BuyPrice = 1200, SellPrice = 240
}
);
_config.Categories.Add(toolCat);
SaveConfig();
}
protected override void SaveConfig() => Config.WriteObject(_config);
private void Unload() {
foreach (var player in BasePlayer.activePlayerList) CuiHelper.DestroyUi(player, "NWG_Market_UI");
SaveData();
}
private void OnServerSave() => SaveData();
private void SaveData() => Interface.Oxide.DataFileSystem.WriteObject("NWG_Market", _data);
private void OnPlayerDisconnected(BasePlayer player) {
if (player == null) return;
_searchFilters.Remove(player.userID);
}
#endregion
#region Economy Hook API
[HookMethod("Balance")]
public double Balance(ulong playerId) => _data.Balances.TryGetValue(playerId, out var bal) ? bal : _config.StartingBalance;
[HookMethod("Withdraw")]
public bool Withdraw(ulong playerId, double amount) {
var bal = Balance(playerId);
if (bal < amount) return false;
_data.Balances[playerId] = bal - amount;
return true;
}
[HookMethod("Deposit")]
public bool Deposit(ulong playerId, double amount) {
if (amount < 0) return false;
_data.Balances[playerId] = Balance(playerId) + amount;
return true;
}
#endregion
#region Commands
private void CmdShop(BasePlayer player) => ShowCategory(player, 0);
private void CmdBalance(BasePlayer player) => SendReply(player, GetMessage(Lang.Balance, player.UserIDString, _config.CurrencySymbol, Balance(player.userID)));
[ConsoleCommand("market.buy")]
private void ConsoleBuy(ConsoleSystem.Arg arg) {
var player = arg.Player();
if (player == null) return;
int catIdx = arg.GetInt(0);
int itemIdx = arg.GetInt(1);
if (catIdx < 0 || catIdx >= _config.Categories.Count) return;
var item = _config.Categories[catIdx].Items[itemIdx];
// Verify item exists
var def = GetItemDef(item.ShortName);
if (def == null) {
// Item invalid/removed from game
return;
}
if (Withdraw(player.userID, item.BuyPrice)) {
var giveItem = ItemManager.Create(def, item.Amount, item.SkinId);
if (giveItem != null) {
player.GiveItem(giveItem);
SendReply(player, GetMessage(Lang.Purchased, player.UserIDString, item.Amount, item.ShortName));
}
else {
Deposit(player.userID, item.BuyPrice);
// Refund
// Log error?
}
}
else SendReply(player, GetMessage(Lang.InsufficientFunds, player.UserIDString));
ShowCategory(player, catIdx);
}
[ConsoleCommand("market.sell")]
private void ConsoleSell(ConsoleSystem.Arg arg) {
var player = arg.Player();
if (player == null) return;
int catIdx = arg.GetInt(0);
int itemIdx = arg.GetInt(1);
var item = _config.Categories[catIdx].Items[itemIdx];
var def = GetItemDef(item.ShortName);
if (def == null) return;
if (player.inventory.GetAmount(def.itemid) >= item.Amount) {
player.inventory.Take(null, def.itemid, item.Amount);
Deposit(player.userID, item.SellPrice);
SendReply(player, GetMessage(Lang.Sold, player.UserIDString, item.Amount, item.ShortName));
}
else {
SendReply(player, GetMessage(Lang.NotEnoughItems, player.UserIDString, item.DisplayName ?? item.ShortName));
}
ShowCategory(player, catIdx);
}
[ConsoleCommand("market.cat")]
private void ConsoleCategory(ConsoleSystem.Arg arg) => ShowCategory(arg.Player(), arg.GetInt(0), arg.GetInt(1));
[ConsoleCommand("market.close")]
private void ConsoleClose(ConsoleSystem.Arg arg) => CuiHelper.DestroyUi(arg.Player(), "NWG_Market_UI");
[ConsoleCommand("market.sellall")]
private void ConsoleSellAll(ConsoleSystem.Arg arg) {
var player = arg.Player();
if (player == null) return;
int catIdx = arg.GetInt(0);
if (catIdx < 0 || catIdx >= _config.Categories.Count) return;
var cat = _config.Categories[catIdx];
double totalEarned = 0;
int totalSold = 0;
foreach (var item in cat.Items) {
if (item.SellPrice <= 0) continue;
var def = GetItemDef(item.ShortName);
if (def == null) continue;
int available = player.inventory.GetAmount(def.itemid);
int stacks = available / item.Amount;
if (stacks <= 0) continue;
int toTake = stacks * item.Amount;
player.inventory.Take(null, def.itemid, toTake);
double earned = stacks * item.SellPrice;
totalEarned += earned;
totalSold += toTake;
}
if (totalEarned > 0) {
Deposit(player.userID, totalEarned);
SendReply(player, GetMessage(Lang.SoldBulk, player.UserIDString, totalSold, _config.CurrencySymbol, totalEarned));
}
else {
SendReply(player, GetMessage(Lang.NothingToSell, player.UserIDString));
}
ShowCategory(player, catIdx);
}
[ConsoleCommand("market.sellallitem")]
private void ConsoleSellAllItem(ConsoleSystem.Arg arg) {
var player = arg.Player();
if (player == null) return;
int catIdx = arg.GetInt(0);
int itemIdx = arg.GetInt(1);
if (catIdx < 0 || catIdx >= _config.Categories.Count) return;
var cat = _config.Categories[catIdx];
if (itemIdx < 0 || itemIdx >= cat.Items.Count) return;
var item = cat.Items[itemIdx];
if (item.SellPrice <= 0) return;
var def = GetItemDef(item.ShortName);
if (def == null) return;
int available = player.inventory.GetAmount(def.itemid);
int stacks = available / item.Amount;
if (stacks <= 0) {
SendReply(player, GetMessage(Lang.NotEnoughItems, player.UserIDString, item.DisplayName ?? item.ShortName));
ShowCategory(player, catIdx);
return;
}
int toTake = stacks * item.Amount;
player.inventory.Take(null, def.itemid, toTake);
double earned = stacks * item.SellPrice;
Deposit(player.userID, earned);
SendReply(player, GetMessage(Lang.Sold, player.UserIDString, toTake, item.DisplayName ?? item.ShortName));
ShowCategory(player, catIdx);
}
[ConsoleCommand("market.search")]
private void ConsoleSearch(ConsoleSystem.Arg arg) {
var player = arg.Player();
if (player == null) return;
string term = arg.GetString(0);
if (string.IsNullOrWhiteSpace(term)) _searchFilters.Remove(player.userID);
else _searchFilters[player.userID] = term;
ShowCategory(player, 0);
// Refresh UI, catIdx ignored in search mode mostly
}
[ConsoleCommand("market.clearsearch")]
private void ConsoleClearSearch(ConsoleSystem.Arg arg) {
var player = arg.Player();
if (player != null) {
_searchFilters.Remove(player.userID);
ShowCategory(player, 0);
}
}
#endregion
#region UI
private void ShowCategory(BasePlayer player, int catIndex, int page = 0) {
if (player == null) return;
CuiHelper.DestroyUi(player, "NWG_Market_UI");
var elements = new CuiElementContainer();
var root = elements.Add(new CuiPanel {
Image = {
Color = UIConstants.OverlayColor
}
, RectTransform = {
AnchorMin = "0.1 0.1", AnchorMax = "0.9 0.9"
}
, CursorEnabled = true
}
, "Overlay", "NWG_Market_UI");
// Header
elements.Add(new CuiPanel {
Image = {
Color = UIConstants.HeaderColor
}
, RectTransform = {
AnchorMin = "0 0.92", AnchorMax = "1 1"
}
}
, root);
elements.Add(new CuiLabel {
Text = {
Text = _config.ShopTitle, Color = UIConstants.Primary, FontSize = 24, Align = TextAnchor.MiddleLeft, Font = "robotocondensed-bold.ttf"
}
, RectTransform = {
AnchorMin = "0.02 0.92", AnchorMax = "0.5 1"
}
}
, root);
var balanceText = GetMessage(Lang.UIBalance, player.UserIDString, _config.CurrencySymbol, Balance(player.userID));
elements.Add(new CuiLabel {
Text = {
Text = balanceText, FontSize = 18, Align = TextAnchor.MiddleRight
}
, RectTransform = {
AnchorMin = "0.5 0.92", AnchorMax = "0.9 1"
}
}
, root);
// Close Button
elements.Add(new CuiButton {
Button = {
Command = "market.close", Color = UIConstants.Secondary
}
, RectTransform = {
AnchorMin = "0.93 0.93", AnchorMax = "0.99 0.99"
}
, Text = {
Text = GetMessage(Lang.UIClose, player.UserIDString), FontSize = 20, Align = TextAnchor.MiddleCenter
}
}
, root);
// Sidebar
for (int i = 0; i < _config.Categories.Count; i++) {
float y = 0.85f - (i * 0.06f);
var btnColor = i == catIndex ? UIConstants.ButtonActive : UIConstants.ButtonInactive;
elements.Add(new CuiButton {
Button = {
Command = $"market.cat {i} 0", Color = btnColor
}
, RectTransform = {
AnchorMin = $"0.01 {y-0.05f}", AnchorMax = $"0.17 {y}"
}
, Text = {
Text = _config.Categories[i].Name.ToUpper(), Color = UIConstants.Primary, FontSize = 12, Align = TextAnchor.MiddleCenter
}
}
, root);
}
// Sell All Button (below category buttons)
float sellAllY = 0.85f - (_config.Categories.Count * 0.06f) - 0.02f;
elements.Add(new CuiButton {
Button = {
Command = $"market.sellall {catIndex}", Color = UIConstants.SellAllButton
}
, // Use Accent or specific SellAll color
RectTransform = {
AnchorMin = $"0.01 {sellAllY - 0.05f}", AnchorMax = $"0.17 {sellAllY}"
}
, Text = {
Text = GetMessage(Lang.UISellAll, player.UserIDString), FontSize = 12, Align = TextAnchor.MiddleCenter, Font = "robotocondensed-bold.ttf"
}
}
, root);
// Search Bar (Top Center/Right)
string currentSearch = _searchFilters.ContainsKey(player.userID) ? _searchFilters[player.userID] : "";
bool isSearching = !string.IsNullOrEmpty(currentSearch);
elements.Add(new CuiElement {
Parent = root, Components = {
new CuiInputFieldComponent {
Command = "market.search", Text = currentSearch, FontSize = 12, Align = TextAnchor.MiddleLeft, CharsLimit = 20, Color = UIConstants.Text
}
, new CuiRectTransformComponent {
AnchorMin = "0.35 0.93", AnchorMax = "0.55 0.98"
}
}
}
);
// Search Placeholder/Label
if (string.IsNullOrEmpty(currentSearch)) {
elements.Add(new CuiLabel {
Text = {
Text = GetMessage(Lang.UISearch, player.UserIDString), FontSize = 12, Align = TextAnchor.MiddleLeft, Color = "1 1 1 0.3"
}
, RectTransform = {
AnchorMin = "0.355 0.93", AnchorMax = "0.55 0.98"
}
}
, root);
}
// Clear Search Button
if (isSearching) {
elements.Add(new CuiButton {
Button = {
Command = "market.clearsearch", Color = UIConstants.Secondary
}
, RectTransform = {
AnchorMin = "0.56 0.93", AnchorMax = "0.62 0.98"
}
, Text = {
Text = GetMessage(Lang.UIClear, player.UserIDString), FontSize = 12, Align = TextAnchor.MiddleCenter
}
}
, root);
}
// Grid Setup
List<ShopItem> displayItems;
if (isSearching) {
displayItems = new List<ShopItem>();
foreach (var c in _config.Categories) {
foreach (var item in c.Items) {
if ((item.DisplayName ?? item.ShortName).Contains(currentSearch, StringComparison.OrdinalIgnoreCase)) displayItems.Add(item);
}
}
}
else {
// Safety check for category index
if (catIndex < 0 || catIndex >= _config.Categories.Count) catIndex = 0;
displayItems = _config.Categories[catIndex].Items;
}
int perPage = 12;
int maxPage = (int)Math.Ceiling((double)displayItems.Count / perPage) - 1;
if (page < 0) page = 0;
if (page > maxPage) page = maxPage;
if (page < 0) page = 0;
// if count is 0, maxPage is -1
int start = page * perPage;
int end = Math.Min(start + perPage, displayItems.Count);
// Pagination Controls (Bottom)
if (maxPage > 0) {
// Prev
if (page > 0) {
elements.Add(new CuiButton {
Button = {
Command = $"market.cat {catIndex} {page-1}", Color = UIConstants.ButtonInactive
}
, RectTransform = {
AnchorMin = "0.4 0.02", AnchorMax = "0.48 0.07"
}
, Text = {
Text = GetMessage(Lang.UIPrev, player.UserIDString), FontSize = 14, Align = TextAnchor.MiddleCenter
}
}
, root);
}
// Next
if (page < maxPage) {
elements.Add(new CuiButton {
Button = {
Command = $"market.cat {catIndex} {page+1}", Color = UIConstants.ButtonInactive
}
, RectTransform = {
AnchorMin = "0.52 0.02", AnchorMax = "0.6 0.07"
}
, Text = {
Text = GetMessage(Lang.UINext, player.UserIDString), FontSize = 14, Align = TextAnchor.MiddleCenter
}
}
, root);
}
// Page Info
elements.Add(new CuiLabel {
Text = {
Text = $"{page+1}/{maxPage+1}", FontSize = 12, Align = TextAnchor.MiddleCenter
}
, RectTransform = {
AnchorMin = "0.48 0.02", AnchorMax = "0.52 0.07"
}
}
, root);
}
// Render Items
for (int i = 0; i < (end - start);
i++) {
var item = displayItems[start + i];
int r = i / 4, c = i % 4;
float xMin = 0.2f + (c * 0.19f), yMax = 0.88f - (r * 0.26f);
var pnl = elements.Add(new CuiPanel {
Image = {
Color = UIConstants.ItemPanel
}
, RectTransform = {
AnchorMin = $"{xMin} {yMax-0.24f}", AnchorMax = $"{xMin+0.18f} {yMax}"
}
}
, root);
// Icon
string icon = (string)ImageLibrary?.Call("GetImage", item.ShortName, item.SkinId) ?? "";
elements.Add(new CuiElement {
Parent = pnl, Components = {
new CuiRawImageComponent {
Png = icon
}
, new CuiRectTransformComponent {
AnchorMin = "0.2 0.4", AnchorMax = "0.8 0.9"
}
}
}
);
// Name
elements.Add(new CuiLabel {
Text = {
Text = item.DisplayName ?? item.ShortName.ToUpper(), FontSize = 10, Align = TextAnchor.MiddleCenter
}
, RectTransform = {
AnchorMin = "0 0.25", AnchorMax = "1 0.45"
}
}
, pnl);
// Buttons
bool hasBuy = item.BuyPrice > 0;
bool hasSell = item.SellPrice > 0;
int realCatIdx = isSearching ? -1 : catIndex;
// Wait, if searching, catIndex might be irrelevant for market.buy command?
// The market.buy command expects (int catIdx, int itemIdx).
// If we are searching, we are displaying a flat list. The indexes won't match the original categories!
// CRITICAL ISSUE: The buy/sell commands rely on (CategoryIndex, ItemIndex).
// With search, we are presenting a synthetic list.
// FIX: We need a way to reference the item. Or we must lookup the original indices.
// Lookup original indices:
int originalCatIdx = -1;
int originalItemIdx = -1;
// Brute force find coordinates
for(int ci=0; ci<_config.Categories.Count; ci++) {
int idx = _config.Categories[ci].Items.IndexOf(item);
if (idx != -1) {
originalCatIdx = ci;
originalItemIdx = idx;
break;
}
}
if (originalCatIdx == -1) continue;
// Should not happen
var buyText = GetMessage(Lang.UIBuy, player.UserIDString, _config.CurrencySymbol, item.BuyPrice);
var sellText = GetMessage(Lang.UISell, player.UserIDString, _config.CurrencySymbol, item.SellPrice);
var sellAllText = GetMessage(Lang.UISellAllItem, player.UserIDString);
// Use original indices for commands
if (hasBuy && hasSell) {
elements.Add(new CuiButton {
Button = {
Command = $"market.buy {originalCatIdx} {originalItemIdx}", Color = UIConstants.BuyButton
}
, RectTransform = {
AnchorMin = "0.03 0.05", AnchorMax = "0.34 0.2"
}
, Text = {
Text = buyText, FontSize = 8, Align = TextAnchor.MiddleCenter
}
}
, pnl);
elements.Add(new CuiButton {
Button = {
Command = $"market.sell {originalCatIdx} {originalItemIdx}", Color = UIConstants.SellButton
}
, RectTransform = {
AnchorMin = "0.36 0.05", AnchorMax = "0.65 0.2"
}
, Text = {
Text = sellText, FontSize = 8, Align = TextAnchor.MiddleCenter
}
}
, pnl);
elements.Add(new CuiButton {
Button = {
Command = $"market.sellallitem {originalCatIdx} {originalItemIdx}", Color = UIConstants.SellAllButton
}
, RectTransform = {
AnchorMin = "0.67 0.05", AnchorMax = "0.97 0.2"
}
, Text = {
Text = sellAllText, FontSize = 8, Align = TextAnchor.MiddleCenter
}
}
, pnl);
}
else if (hasBuy) {
elements.Add(new CuiButton {
Button = {
Command = $"market.buy {originalCatIdx} {originalItemIdx}", Color = UIConstants.BuyButton
}
, RectTransform = {
AnchorMin = "0.05 0.05", AnchorMax = "0.95 0.2"
}
, Text = {
Text = buyText, FontSize = 9, Align = TextAnchor.MiddleCenter
}
}
, pnl);
}
else if (hasSell) {
elements.Add(new CuiButton {
Button = {
Command = $"market.sell {originalCatIdx} {originalItemIdx}", Color = UIConstants.SellButton
}
, RectTransform = {
AnchorMin = "0.05 0.05", AnchorMax = "0.48 0.2"
}
, Text = {
Text = sellText, FontSize = 9, Align = TextAnchor.MiddleCenter
}
}
, pnl);
elements.Add(new CuiButton {
Button = {
Command = $"market.sellallitem {originalCatIdx} {originalItemIdx}", Color = UIConstants.SellAllButton
}
, RectTransform = {
AnchorMin = "0.52 0.05", AnchorMax = "0.95 0.2"
}
, Text = {
Text = sellAllText, FontSize = 9, Align = TextAnchor.MiddleCenter
}
}
, pnl);
}
}
CuiHelper.AddUi(player, elements);
}
#endregion
#region Localization
private class Lang {
public const string Balance = "Balance";
public const string Purchased = "Purchased";
public const string InsufficientFunds = "InsufficientFunds";
public const string Sold = "Sold";
public const string NothingToSell = "NothingToSell";
public const string NotEnoughItems = "NotEnoughItems";
public const string SoldBulk = "SoldBulk";
public const string UIBalance = "UI.Balance";
public const string UISellAll = "UI.SellAll";
public const string UIBuy = "UI.Buy";
public const string UISell = "UI.Sell";
public const string UISellAllItem = "UI.SellAllItem";
public const string UIClose = "UI.Close";
public const string UISearch = "UI.Search";
public const string UIClear = "UI.Clear";
public const string UIPrev = "UI.Prev";
public const string UINext = "UI.Next";
}
protected override void LoadDefaultMessages() {
lang.RegisterMessages(new Dictionary<string, string> {
[Lang.Balance]
= "<color=#b7d092>[NWG]</color> Balance: <color=#b7d092>{0}{1:N2}</color>", [Lang.Purchased] = "<color=#b7d092>[NWG]</color> Purchased <color=#FFA500>{0}x {1}</color>", [Lang.InsufficientFunds] = "<color=#d9534f>[NWG]</color> Insufficient funds.", [Lang.Sold] = "<color=#b7d092>[NWG]</color> Sold <color=#FFA500>{0}x {1}</color>", [Lang.NothingToSell] = "<color=#d9534f>[NWG]</color> Nothing to sell in this category.", [Lang.NotEnoughItems] = "<color=#d9534f>[NWG]</color> You don't have enough <color=#FFA500>{0}</color> to sell.", [Lang.SoldBulk] = "<color=#b7d092>[NWG]</color> Sold <color=#FFA500>{0}</color> items for <color=#b7d092>{1}{2:N0}</color>", [Lang.UIBalance] = "BALANCE: <color=#b7d092>{0}{1:N0}</color>", [Lang.UISellAll] = "⚡ SELL ALL", [Lang.UIBuy] = "BUY\n{0}{1:N0}", [Lang.UISell] = "SELL\n{0}{1:N0}", [Lang.UISellAllItem] = "SELL\nALL", [Lang.UIClose] = "✕", [Lang.UISearch] = "Search...", [Lang.UIClear] = "X", [Lang.UIPrev] = "<", [Lang.UINext] = ">"
}
, this);
}
private string GetMessage(string key, string userId, params object[] args) => string.Format(lang.GetMessage(key, this, userId), args);
#endregion
#region Helpers
private ItemDefinition GetItemDef(string shortname) {
if (string.IsNullOrEmpty(shortname)) return null;
if (_itemDefCache.TryGetValue(shortname, out var def)) return def;
def = ItemManager.FindItemDefinition(shortname);
if (def != null) _itemDefCache[shortname] = def;
return def;
}
#endregion
}
}