C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using ConVar;
using Newtonsoft.Json;
using Oxide.Core.Plugins;
using UnityEngine;
using Oxide.Game.Rust.Cui;
namespace Oxide.Plugins
{
[Info("Repair Cost", "Rustoholics", "0.1.1")]
[Description("Alter the repair cost of items")]
public class RepairCost : CovalencePlugin
{
#region Dependencies
[PluginReference]
private Plugin Economics;
#endregion
#region Variables
private Dictionary<string,RepairBench> _repairBenches = new Dictionary<string,RepairBench>();
private Dictionary<string,string> _repairGui = new Dictionary<string,string>();
private Dictionary<string,ulong> _repairGuiItem = new Dictionary<string,ulong>();
private Dictionary<string, Timer> _repairTimers = new Dictionary<string, Timer>();
#endregion
#region Config
private Configuration _config;
protected override void SaveConfig() => Config.WriteObject(_config);
protected override void LoadDefaultConfig() => _config = new Configuration();
private class Configuration
{
public Dictionary<string, Dictionary<string, object>> RepairCosts = new Dictionary<string, Dictionary<string, object>>
{
{"global", new Dictionary<string, object>
{
{"enabled", false},
{"multiplier", 5.0f},
{"items", new Dictionary<string, float>()},
{"economics", 0.0d}
}
},
{"smg.mp5", new Dictionary<string, object>
{
{"enabled", true},
{"multiplier", 6.0f},
{
"items", new Dictionary<string, float>
{
{"smgbody", 1.0f}
}
},
{"economics", 100.0d}
}
},
{"rifle.lr300", new Dictionary<string, object>
{
{"enabled", true},
{"multiplier", 10.0f},
{"items", new Dictionary<string, float>()},
{"economics", 100.0d}
}
},
{"pistol.m92", new Dictionary<string, object>
{
{"enabled", true},
{"multiplier", 5.0f},
{"items", new Dictionary<string, float>()},
{"economics", 100.0d}
}
},
{"rifle.l96", new Dictionary<string, object>
{
{"enabled", true},
{"multiplier", 10.0f},
{"items", new Dictionary<string, float>()},
{"economics", 100.0d}
}
},
{"lmg.m249", new Dictionary<string, object>
{
{"enabled", true},
{"multiplier", 10.0f},
{"items", new Dictionary<string, float>()},
{"economics", 100.0d}
}
}
};
}
protected override void LoadConfig()
{
base.LoadConfig();
try
{
_config = Config.ReadObject<Configuration>();
if (_config == null) throw new Exception();
SaveConfig();
}
catch
{
PrintError("Your configuration file contains an error.Using default configuration values.");
LoadDefaultConfig();
}
}
#endregion
#region Language
private string Lang(string key, string id = null, params object[] args) => string.Format(lang.GetMessage(key, this, id), args);
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["NotEnoughMaterials"] = "You do not have enough materials to repair this item",
["EconomicsRequired"] = " and {0} coins",
["NotEnoughCoins"] = "You do not have enough coins to make this repair"
}, this);
}
#endregion
#region Hooks
void CanLootEntity(BasePlayer player, RepairBench container)
{
_repairBenches[player.UserIDString] = container;
}
void OnLootEntityEnd(BasePlayer player, RepairBench container)
{
if (_repairTimers.ContainsKey(player.UserIDString))
{
_repairTimers[player.UserIDString].Destroy();
_repairTimers.Remove(player.UserIDString);
}
CloseGui(player);
if (_repairBenches.ContainsKey(player.UserIDString))
{
_repairBenches.Remove(player.UserIDString);
}
}
void OnLootEntity(BasePlayer player, RepairBench container)
{
CheckAndPresentGui(player, container);
}
object OnItemRepair(BasePlayer player, Item itemToRepair)
{
if (!IsCustomRepairItem(itemToRepair))
{
return null;
}
RepairBench repairBenchEntity = _repairBenches[player.UserIDString];
var list = RepairList(player, itemToRepair);
var economicsRequired = EconomicsRequired(itemToRepair);
if (!PlayerHasEnough(player, list, economicsRequired))
{
player.ChatMessage(Lang("NotEnoughMaterials", player.UserIDString));
return true;
}
if (Economics != null && economicsRequired > 0)
{
if (!Economics.Call<bool>("Withdraw", player.UserIDString, economicsRequired))
{
player.ChatMessage(Lang("NotEnoughCoins", player.UserIDString));
return true;
}
}
foreach (ItemAmount itemAmount in list)
{
player.inventory.Take((List<Item>) null, itemAmount.itemid, (int)itemAmount.amount);
}
Facepunch.Pool.FreeList<ItemAmount>(ref list);
itemToRepair.DoRepair(0.2f);
if (Global.developer > 0)
Debug.Log((object) ("Item repaired! condition : " + (object) itemToRepair.condition + "/" + (object) itemToRepair.maxCondition));
Effect.server.Run("assets/bundled/prefabs/fx/repairbench/itemrepair.prefab", repairBenchEntity, 0U, Vector3.zero, Vector3.zero);
return true;
}
// Remove any open GUIs on unloading the plugin, to avoid stuck GUIs
void Unload()
{
foreach (var userIdString in _repairGui.Keys.ToArray())
{
var player = BasePlayer.FindByID(Convert.ToUInt64(userIdString));
if (player != null && player.IsConnected)
{
CloseGui(player);
}
}
}
void OnItemRemovedFromContainer(ItemContainer container, Item item)
{
NextTick(() =>
{
if (item == null || container == null)
{
return;
}
BasePlayer player;
if (container.entityOwner != null && container.entityOwner is RepairBench)
{
if (item.GetOwnerPlayer() == null) return;
// Check if bench is empty
if (container.itemList.Count == 0)
{
player = item.GetOwnerPlayer();
CloseGui(player);
}
return;
}
if (item.GetRootContainer() == null) return;
if (!(item.GetRootContainer().entityOwner is RepairBench)) return;
if (container.GetOwnerPlayer() == null) return;
player = container.GetOwnerPlayer();
CheckAndPresentGui(player, (RepairBench)item.GetRootContainer().entityOwner);
});
}
#endregion
#region GUI
void CheckAndPresentGui(BasePlayer player, RepairBench container)
{
var item = container.inventory.GetSlot(0);
if (item != null && UseCustomRepairGui(item, player))
{
// Check if Repair GUI is already open
if (!_repairGui.ContainsKey(player.UserIDString))
{
WriteGui(player, item); // It's not open so write it
}else if(_repairGuiItem[player.UserIDString] != item.uid)
{
CloseGui(player); // It's open but for a different item, so close that GUI and open a new one
WriteGui(player, item);
}
}
else
{
CloseGui(player);
}
}
bool UseCustomRepairGui(Item item, BasePlayer player)
{
if (!IsCustomRepairItem(item))
{
return false;
}
ItemDefinition targetItem = (UnityEngine.Object) item.info.isRedirectOf != (UnityEngine.Object) null ? item.info.isRedirectOf : item.info;
if ((player.blueprints.HasUnlocked(targetItem) ? 1 : (!((UnityEngine.Object) targetItem.Blueprint != (UnityEngine.Object) null) ? 0 : (!targetItem.Blueprint.isResearchable ? 1 : 0))) == 0)
return false;
if (!item.info.condition.repairable || item.condition.Equals(item.maxCondition))
{
return false;
}
return true;
}
void WriteGui(BasePlayer player, Item itemToRepair)
{
var list = RepairList(player, itemToRepair);
var economicsRequired = EconomicsRequired(itemToRepair);
if (list == null)
{
return;
}
var panel = new CuiPanel();
if (itemToRepair.info.HasSkins)
{
panel.RectTransform.AnchorMin = "0.5 0";
panel.RectTransform.AnchorMax = "0.5 0";
panel.RectTransform.OffsetMin = "326 343";
panel.RectTransform.OffsetMax = "564 413";
}
else
{
panel.RectTransform.AnchorMin = "0.5 0";
panel.RectTransform.AnchorMax = "0.5 0";
panel.RectTransform.OffsetMin = "326 179";
panel.RectTransform.OffsetMax = "564 249";
}
panel.Image.Color = "0.25 0.24 0.22 1.0";
var text = new CuiLabel();
text.Text.Color = "1.0 1.0 1.0 1.0";
if (!PlayerHasEnough(player, list, economicsRequired))
{
text.Text.Color = "0.73 0.4 0.29 1.0";
}
text.Text.Align = TextAnchor.MiddleCenter;
text.Text.FontSize = 12;
text.Text.Font = "RobotoCondensed-Regular.ttf";
text.Text.Text = "Repair cost: ";
var n = 0;
foreach (var i in list)
{
if (n > 0)
{
text.Text.Text += ", ";
}
text.Text.Text += Convert.ToString(i.amount) + " " + i.itemDef.displayName.english;
n++;
}
if (economicsRequired > 0)
{
text.Text.Text += Lang("EconomicsRequired", player.UserIDString, economicsRequired);
}
var container = new CuiElementContainer();
var menu = container.Add(panel, "Overlay");
if (_repairGui.ContainsKey(player.UserIDString))
{
return; // Final check to make sure this player doesn't have a GUI already
}
container.Add(text, menu, "RepairText");
_repairGui[player.UserIDString] = menu;
_repairGuiItem[player.UserIDString] = itemToRepair.uid;
CuiHelper.AddUi(player, container);
}
void CloseGui(BasePlayer player)
{
if (!_repairGui.ContainsKey(player.UserIDString))
{
return;
}
CuiHelper.DestroyUi(player, _repairGui[player.UserIDString]);
_repairGui.Remove(player.UserIDString);
_repairGuiItem.Remove(player.UserIDString);
}
#endregion
#region Repair Items List and Amount Modifiers
private List<ItemAmount> RepairList(BasePlayer player, Item itemToRepair)
{
ItemDefinition info = itemToRepair.info;
ItemBlueprint component = info.GetComponent<ItemBlueprint>();
List<ItemAmount> list = Facepunch.Pool.GetList<ItemAmount>();
RepairBench.GetRepairCostList(component, list);
return ApplyItemListMultiplier(list, itemToRepair);
}
private List<ItemAmount> ApplyItemListMultiplier(List<ItemAmount> list, Item itemToRepair)
{
List<ItemAmount> newlist = new List<ItemAmount>();
var repairCostFraction = RepairBench.RepairCostFraction(itemToRepair);
float multiplier = 1;
if (_config.RepairCosts.ContainsKey(itemToRepair.info.shortname) && _config.RepairCosts[itemToRepair.info.shortname].ContainsKey("multiplier"))
{
multiplier = Convert.ToSingle(_config.RepairCosts[itemToRepair.info.shortname]["multiplier"]);
}
else if(_config.RepairCosts.ContainsKey("global") && _config.RepairCosts["global"].ContainsKey("enabled") && (bool)_config.RepairCosts["global"]["enabled"] && _config.RepairCosts["global"].ContainsKey("multiplier"))
{
multiplier = Convert.ToSingle(_config.RepairCosts["global"]["multiplier"]);
}
foreach (ItemAmount itemAmount in list)
{
if (itemAmount.itemDef.category != ItemCategory.Component)
{
itemAmount.amount = Mathf.CeilToInt(itemAmount.amount * repairCostFraction * multiplier);
newlist.Add(itemAmount);
}
}
// Add any extra items
if (_config.RepairCosts[itemToRepair.info.shortname].ContainsKey("items"))
{
var items = (IEnumerable)_config.RepairCosts[itemToRepair.info.shortname]["items"];
var json = JsonConvert.SerializeObject(items);
var dictionary = JsonConvert.DeserializeObject<Dictionary<string, float>>(json);
foreach (var customItem in dictionary)
{
var itemDefinition = ItemManager.FindItemDefinition(customItem.Key);
if (itemDefinition == null) // Could not find an item definition matching this key, skip it
{
continue;
}
var isNew = true;
foreach (var newItem in newlist)
{
// The item is already in the list, so override it
if (newItem.itemid == itemDefinition.itemid)
{
newItem.amount = Mathf.CeilToInt(Convert.ToSingle(customItem.Value));
isNew = false;
break;
}
}
if (isNew)
{
newlist.Add(new ItemAmount(itemDefinition, customItem.Value));
}
}
}
Facepunch.Pool.FreeList<ItemAmount>(ref list);
return newlist;
}
#endregion
#region Checking Functions
bool IsCustomRepairItem(Item item)
{
if (_config.RepairCosts.ContainsKey(item.info.shortname) && _config.RepairCosts[item.info.shortname].ContainsKey("enabled"))
{
return (bool)_config.RepairCosts[item.info.shortname]["enabled"];
}
if (_config.RepairCosts.ContainsKey("global") && _config.RepairCosts["global"].ContainsKey("enabled"))
{
return (bool)_config.RepairCosts["global"]["enabled"];
}
return false;
}
bool PlayerHasEnough(BasePlayer player, List<ItemAmount> list, double economics=0d)
{
foreach (ItemAmount itemAmount in list)
{
int amount = player.inventory.GetAmount(itemAmount.itemDef.itemid);
if (itemAmount.amount > amount)
{
return false;
}
}
if (Economics != null && economics > 0)
{
if (Economics.Call<double>("Balance", player.UserIDString) < economics)
{
return false;
}
}
return true;
}
double EconomicsRequired(Item item)
{
if (Economics == null)
{
return 0d;
}
if (_config.RepairCosts.ContainsKey(item.info.shortname) &&
_config.RepairCosts[item.info.shortname].ContainsKey("enabled") &&
_config.RepairCosts[item.info.shortname].ContainsKey("economics") &&
Convert.ToDouble(_config.RepairCosts[item.info.shortname]["economics"]) > 0)
{
return Convert.ToDouble(_config.RepairCosts[item.info.shortname]["economics"]);
}
if (_config.RepairCosts.ContainsKey("global") &&
_config.RepairCosts["global"].ContainsKey("economics") &&
Convert.ToDouble(_config.RepairCosts["global"]["economics"]) > 0)
{
return Convert.ToDouble(_config.RepairCosts["global"]["economics"]);
}
return 0d;
}
#endregion
}
}