C#:
using System.Collections.Generic;
using UnityEngine;
using Oxide.Core.Plugins;
using Newtonsoft.Json;
using Rust;
using System.Linq;
using System.Collections;
using Oxide.Core;
using System;
using System.Text;
using ConVar;
namespace Oxide.Plugins
{
[Info("Ore Planter Seed", "NiceGame", "2.07")]
[Description("Выпадение семян руды.")]
class OrePlanter : RustPlugin
{
private List<uint> oreCashe = new List<uint>();
private List<uint> _oreCashe = new List<uint>();
ConfigData _config;
ConfigData GetDefaultConfig()
{
return new ConfigData {
Lootdrop = true,
lootBox = new LootBox()
{
PrefabBox = "assets/bundled/prefabs/radtown/crate_normal.prefab"
},
oreConfig = new OreConfig()
{
// 2858298374 - MVK
// 2858302463 - Ava
Name = "Осколок руды",
stageTime = 30,
Amount = 1,
ItemSkinID = 2858302463,
Prefabs = new List<string>()
{
"assets/bundled/prefabs/radtown/ore_metal.prefab",
"assets/bundled/prefabs/radtown/ore_stone.prefab",
"assets/bundled/prefabs/radtown/ore_sulfur.prefab"
}
},
percentBox = new PercentBox()
{
PercentOreDefault = 1,
PercentOreBabyVip = 3,
PercentOreVip = 7
},
permissionOre = new PermissionOre()
{
FoxVip = "oreplanter.vip",
BabyFox = "oreplanter.babyvip",
GiveSeed = "oreplanter.giveseed"
},
chatEdit = new ChatEdit()
{
PrefixChat = "NiceGame",
ColorPrefix = "#F07427",
ColorMessage = "#939393"
},
oreGather = new OreGather()
{
stackGather = 1,
Cooked = false
},
LootInOreList = new List<LootInOre>()
{
new LootInOre
{
nameItem = "gears",
MinAmountItem = 1,
MaxAmountItem = 5,
PercentItem = 50
},
new LootInOre
{
nameItem = "metalpipe",
MinAmountItem = 1,
MaxAmountItem = 5,
PercentItem = 40
}
}
};
}
class ConfigData
{
[JsonProperty("Появление ящика,или выпадение из руды. По дефолту из руды")]
public bool Lootdrop;
[JsonProperty("Настройка процентов")]
public PercentBox percentBox;
[JsonProperty("Настройка ящиков")]
public LootBox lootBox;
[JsonProperty("Настройка лута выпадение из руды")]
public List<LootInOre> LootInOreList;
[JsonProperty("Настройка руды")]
public OreConfig oreConfig;
[JsonProperty("Настройка пермишенов")]
public PermissionOre permissionOre;
[JsonProperty("Настройка чата")]
public ChatEdit chatEdit;
[JsonProperty("Настройка добычи руды")]
public OreGather oreGather;
}
class OreConfig
{
[JsonProperty("Название семени - default <осколок руды>")]
public string Name;
[JsonProperty("Префабы руды")]
public List<string> Prefabs;
[JsonProperty("Количество выпадение семени")]
public int Amount = 1;
[JsonProperty("ID иконки из мастерской")]
public uint ItemSkinID;
[JsonProperty("Время роста руды")]
public int stageTime;
}
class PercentBox
{
[JsonProperty("Процентный шанс по дефолту для выпадение осколка/семя")]
public int PercentOreDefault;
[JsonProperty("Процентный шанс для випки = BABYVIP для выпадение осколка/семя")]
public int PercentOreBabyVip;
[JsonProperty("Процентный шанс для випки = VIP для выпадение осколка/семя")]
public int PercentOreVip;
}
class ChatEdit
{
[JsonProperty("Префикс")]
public string PrefixChat;
[JsonProperty("Цвет префикса")]
public string ColorPrefix;
[JsonProperty("Цвет сообщения в чате")]
public string ColorMessage;
}
class PermissionOre
{
[JsonProperty("Пермишен VIP")]
public string FoxVip;
[JsonProperty("Пермишен BabyVIP")]
public string BabyFox;
[JsonProperty("Пермишен для выдачи семя")]
public string GiveSeed;
}
class LootBox {
[JsonProperty("Префаб ящика")]
public string PrefabBox;
}
class LootInOre
{
[JsonProperty("Название префаба")]
public string nameItem;
[JsonProperty("Максимальное кол-во выпадение")]
public int MaxAmountItem;
[JsonProperty("Минимальное кол-во выпадение")]
public int MinAmountItem;
[JsonProperty("Шанс выпадения")]
public int PercentItem;
}
class OreGather
{
[JsonProperty("Рейт при добыче")]
public float stackGather;
[JsonProperty("Добыча уже плавленную руду")]
public bool Cooked;
}
private Coroutine start;
protected override void LoadDefaultConfig() => Config.WriteObject(GetDefaultConfig(), true);
private void OnServerInitialized()
{
if (Interface.Oxide.DataFileSystem.ExistsDatafile("OreList")) _oreCashe = Interface.Oxide.DataFileSystem.ReadObject<List<uint>>("OreList");
start = Rust.Global.Runner.StartCoroutine(LoadData());
PrintWarning("Благодарим за покупку плагина у разработчика NiceGame. Если вы передадите этот плагин сторонним лицам знайте - это лишает вас гарантированных обновлений!");
permission.RegisterPermission(_config.permissionOre.FoxVip, this);
permission.RegisterPermission(_config.permissionOre.BabyFox, this);
permission.RegisterPermission(_config.permissionOre.GiveSeed, this);
_config = Config.ReadObject<ConfigData>();
}
IEnumerator LoadData()
{
foreach (var u in _oreCashe)
{
var ent = BaseNetworkable.serverEntities.entityList.FirstOrDefault(p => (uint)p.Key.Value == u);
if (ent.Value != null)
{
ent.Value.gameObject.AddComponent<OreGrowth>();
}
else
{
oreCashe.Add(u);
}
yield return new WaitForSeconds(0.5f);
}
foreach (var u in oreCashe)
{
_oreCashe.Remove(u);
yield return new WaitForSeconds(0.5f);
}
yield return 0;
}
private void Loaded()
{
}
void Init()
{
_config = Config.ReadObject<ConfigData>();
oreplanter = this;
}
private void Unload()
{
if(start !=null) Rust.Global.Runner.StopCoroutine(start);
foreach (var resourceSeed in UnityEngine.Object.FindObjectsOfType<OreGrowth>()) resourceSeed.OnDestroy();
Interface.Oxide.DataFileSystem.WriteObject("OreList", _oreCashe);
}
public bool Percent(int percent)
{
int res = Oxide.Core.Random.Range(0,100);
if (res <= percent) return true; else return false;
}
Item GiveItems (string name, int amount)
{
Item items = ItemManager.CreateByName(name,amount);
return items;
}
public void SpawnLoot(Vector3 position, int countBox = 0)
{
Vector3 pos = new Vector3(UnityEngine.Random.Range(-0.3f, 0.3f), UnityEngine.Random.Range(0, 0), UnityEngine.Random.Range(-1, 1));
BaseEntity boxed = GameManager.server.CreateEntity(_config.lootBox.PrefabBox, position + pos,Quaternion.identity);
if(boxed == null)
{
return;
}
boxed.Spawn();
boxed.SendNetworkUpdateImmediate();
}
public Item CreateItem(string oreType,int amount, uint skinID)
{
Item item = ItemManager.CreateByName(oreType, amount,skinID);
item.name = _config.oreConfig.Name;
return item;
}
void RefundItem(BasePlayer player)
{
Item refundItem = CreateItem("seed.pumpkin",1,_config.oreConfig.ItemSkinID);
if(refundItem == null)
{
return;
}
player.GiveItem(refundItem);
}
void GiveLoot (BasePlayer player)
{
foreach(var item in _config.LootInOreList)
{
if (UnityEngine.Random.Range(0, 100) > item.PercentItem) continue;
var amount = UnityEngine.Random.Range(item.MinAmountItem, item.MaxAmountItem);
var newItem = ItemManager.CreateByName(item.nameItem, amount);
player.GiveItem(newItem);
}
}
void DropLoot(Vector3 position)
{
foreach(var item in _config.LootInOreList)
{
if (UnityEngine.Random.Range(0, 100) > item.PercentItem) continue;
var amount = UnityEngine.Random.Range(item.MinAmountItem, item.MaxAmountItem);
Item newItem = ItemManager.CreateByName(item.nameItem, amount);
newItem.Drop(position, new Vector3(), new Quaternion());
}
}
void DropSeed(BasePlayer player)
{
int rng = Oxide.Core.Random.Range(0,100);
if (permission.UserHasPermission(player.userID.ToString(), _config.permissionOre.FoxVip))
{
if(Percent(_config.percentBox.PercentOreVip))
{
Item items = CreateItem("seed.pumpkin", _config.oreConfig.Amount, _config.oreConfig.ItemSkinID);
player.GiveItem(items);
SendMSG(player, MSG("GiveBonusSeed", player.UserIDString));
return;
}
}
else if(permission.UserHasPermission(player.userID.ToString(), _config.permissionOre.BabyFox))
{
if(Percent(_config.percentBox.PercentOreBabyVip))
{
Item items = CreateItem("seed.pumpkin", _config.oreConfig.Amount, _config.oreConfig.ItemSkinID);
player.GiveItem(items);
SendMSG(player, MSG("GiveBonusSeed", player.UserIDString));
return;
}
}
else{
if(Percent(_config.percentBox.PercentOreDefault))
{
Item items = CreateItem("seed.pumpkin", _config.oreConfig.Amount, _config.oreConfig.ItemSkinID);
player.GiveItem(items);
SendMSG(player, MSG("GiveBonusSeed", player.UserIDString));
return;
}
}
}
object OnDispenserBonus(ResourceDispenser dispenser, BaseEntity entity, Item item)
{
{
BasePlayer player = entity as BasePlayer;
if (dispenser == null || player == null || item == null) return null;
if (dispenser.GetComponent<ResourceEntity>()?.skinID == 21382132)
{
if(_config.oreGather.Cooked)
{
if (item.info.shortname == "metal.ore" ||
item.info.shortname == "sulfur.ore" ||
item.info.shortname == "hq.metal.ore")
{
var cookedGive = ItemManager.Create(item.info.gameObject.GetComponent<ItemModCookable>().becomeOnCooked,
1);
cookedGive.amount = (int) (item.amount * _config.oreGather.stackGather);
player.GiveItem(cookedGive, BaseEntity.GiveItemReason.ResourceHarvested);
return true;
}
item.amount = (int) (item.amount * _config.oreGather.stackGather);
return true;
}
}
else
{
switch (item.info.shortname)
{
case "stones":
DropSeed(player);
break;
case "sulfur.ore":
DropSeed(player);
break;
case "metal.ore":
DropSeed(player);
break;
}
}
return null;
}
}
object OnDispenserGather(ResourceDispenser dispenser, BasePlayer player, Item item)
{
if (dispenser == null || player == null || item == null) return null;
if (dispenser.GetComponent<ResourceEntity>()?.skinID != 21382132) return null;
if(_config.oreGather.Cooked)
{
if (item.info.shortname == "metal.ore" ||
item.info.shortname == "sulfur.ore" ||
item.info.shortname == "hq.metal.ore")
{
var cookedGive = ItemManager.Create(item.info.gameObject.GetComponent<ItemModCookable>().becomeOnCooked,
1);
cookedGive.amount = (int) (item.amount * _config.oreGather.stackGather);
player.GiveItem(cookedGive, BaseEntity.GiveItemReason.ResourceHarvested);
return true;
}
}
item.amount = (int) (item.amount * _config.oreGather.stackGather);
return null;
}
private void OnEntityKill(BaseNetworkable entity)
{
BaseEntity baseEnt = entity.GetComponent<BaseEntity>();
var pos = baseEnt.transform.position;
if (_oreCashe.Contains((uint)baseEnt.net.ID.Value))
{
if(_config.Lootdrop)
{
DropLoot(pos);
_oreCashe.Remove((uint)baseEnt.net.ID.Value);
return;
}
else{
_oreCashe.Remove((uint)baseEnt.net.ID.Value);
SpawnLoot(pos);
return;
}
}
}
public static OrePlanter oreplanter;
class OreGrowth: BaseEntity
{
public Dictionary<BasePlayer, bool> ColliderPlayersList = new Dictionary<BasePlayer, bool>();
SphereCollider sphereCollider;
public ResourceEntity ore;
private uint netId;
private float health;
private BaseEntity parent;
private int Stages = 4;
private float NeedTime = 3 * oreplanter._config.oreConfig.stageTime;
void Awake()
{
ore = GetComponent<ResourceEntity>();
sphereCollider = gameObject.AddComponent<SphereCollider>();
sphereCollider.gameObject.layer = (int)Rust.Layer.Reserved1;
sphereCollider.isTrigger = true;
sphereCollider.radius = 10f;
netId = (uint)ore.net.ID.Value;
health = ore.health;
InvokeRepeating("UpdateStage", oreplanter._config.oreConfig.stageTime, oreplanter._config.oreConfig.stageTime);
InvokeRepeating("DrawInfo", 1f, 1);
}
private void OnTriggerEnter(Collider other)
{
var target = other.GetComponentInParent<BasePlayer>();
if (target != null && !ColliderPlayersList.ContainsKey(target))
ColliderPlayersList.Add(target, !target.IsAdmin);
}
void DrawInfo()
{
foreach (var player in ColliderPlayersList)
{
if(NeedTime != 0)
{
player.Key.SendConsoleCommand("ddraw.text", 1.01f, Color.white, ore.transform.position + Vector3.up, string.Format(oreplanter.MSG("InfoDdraw"),FormatShortTime(TimeSpan.FromSeconds(NeedTime))));
NeedTime--;
continue;
}
if(ore.Health() + 150 > 500)
{
player.Key.SendConsoleCommand("ddraw.text", 1.01f, Color.white, ore.transform.position + Vector3.up,oreplanter.MSG("InfoFull"));
}
}
}
public static string FormatShortTime(TimeSpan time)
{
string result = string.Empty;
result += $"{time.Hours.ToString("00")}:";
result += $"{time.Minutes.ToString("00")}:";
result += $"{time.Seconds.ToString("00")}";
return result;
}
private void OnTriggerExit(Collider other)
{
var target = other.GetComponentInParent<BasePlayer>();
if (target != null && ColliderPlayersList.ContainsKey(target))
ColliderPlayersList.Remove(target);
}
public void OnDestroy()
{
Destroy(this);
}
void UpdateStage()
{
if (ore == null)
{
OnDestroy();
oreplanter._oreCashe.Remove(netId);
return;
}
if (health != ore.health)
{
OnDestroy();
oreplanter._oreCashe.Remove(netId);
return;
}
if (ore.Health() + 150 > 500)
{
ore.OnAttacked(new HitInfo(new BasePlayer(), ore, DamageType.Generic, -150, ore.transform.position));
health = ore.health;
ore.health = 500;
ore.GetComponent<OreResourceEntity>().RespawnBonus();
OnDestroy();
return;
}
ore.OnAttacked(new HitInfo(new BasePlayer(), ore, DamageType.Generic, -150, ore.transform.position));
Stages--;
health = ore.health;
}
}
void OnEntitySpawned(GrowableEntity growable)
{
if (growable.skinID != _config.oreConfig.ItemSkinID) return;
var player = BasePlayer.FindByID(growable.OwnerID);
if (player == null) return;
var entity = GameManager.server.CreateEntity(_config.oreConfig.Prefabs.GetRandom(), growable.transform.position, Quaternion.identity) as OreResourceEntity;
if (entity == null)
{
return;
}
entity.health = entity.stages[2].health;
entity.stage = 2;
entity.OnParentSpawning();
SendMSG(player, MSG("PlanterSeed", player.UserIDString));
var info = new HitInfo(new BasePlayer(), entity, DamageType.Generic, -1f, entity.transform.position);
entity.OnAttacked(info);
NextTick(() =>
{
if(growable.GetPlanter() != null) growable.GetPlanter().AddChild(entity);
growable.SetParent(entity, true, true);
});
entity.gameObject.AddComponent<OreGrowth>();
entity.skinID = 21382132;
entity.SendNetworkUpdateImmediate();
_oreCashe.Add((uint)entity.net.ID.Value);
}
void AddSeed(BasePlayer player, int amount)
{
if (player == null) return;
Item items = CreateItem("seed.pumpkin", amount, _config.oreConfig.ItemSkinID);
player.GiveItem(items, BaseEntity.GiveItemReason.Crafted);
SendMSG(player, MSG("GiveSeedAdmin", player.UserIDString));
}
[ChatCommand("ore")]
void GiveSeed(BasePlayer player, string command, string[] args)
{
if (player.IsAdmin || permission.UserHasPermission(player.UserIDString, _config.permissionOre.GiveSeed))
{
if (args.Length == 1)
{
int amount;
if (!int.TryParse(args[0], out amount))
{
SendMSG(player, MSG("ErrorCMDAmount", player.UserIDString));
return;
}
AddSeed(player, amount);
return;
}
if (args.Length > 0 && args.Length == 2)
{
var target = BasePlayer.Find(args[0]);
if (target == null)
{
SendMSG(player, MSG("ErrorCMDSearch", player.UserIDString));
return;
}
int amount;
if (!int.TryParse(args[1], out amount))
{
SendMSG(player, MSG("ErrorCMDNick", player.UserIDString));
return;
}
AddSeed(target, amount);
}
}
else
{
SendMSG(player, MSG("ErrorCMDPermission", player.UserIDString));
}
}
[ChatCommand("oreinfo")]
void OreListInfo(BasePlayer player, string command, string[] args)
{
}
//Команда для разработки, по желанию можно удалить
// [ChatCommand("orel")]
// void OreListPlayer(BasePlayer player, string command, string[] args)
// {
// Puts(_oreCashe.Count.ToString());
// }
private void SendMSG(BasePlayer player, string message) => SendReply(player, $"<color={_config.chatEdit.ColorPrefix}>{_config.chatEdit.PrefixChat}:</color> <color={_config.chatEdit.ColorMessage}>{message}</color>");
private string MSG(string key, string playerid = null, params object[] args)
{
sb.Clear();
if (args != null)
{
sb.AppendFormat(lang.GetMessage(key, this, playerid), args);
return sb.ToString();
}
return lang.GetMessage(key, this, playerid);
}
void SendChat(BasePlayer player, string message, Chat.ChatChannel channel = Chat.ChatChannel.Global)
{
player.SendConsoleCommand("chat.add", channel, 0, $"<color={_config.chatEdit.ColorPrefix}>{_config.chatEdit.PrefixChat}:</color> <color={_config.chatEdit.ColorMessage}>{message}</color>");
}
public static StringBuilder sb = new StringBuilder();
private new void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<String, String>
{
["ErrorPlanterZone"] = "Сажать осколок можно только в зоне своего шкафа",
["ErrorPlanter"] = "Сажать осколок можно на земле",
["GiveBonusSeed"] = "Тебе выпал осколок",
["PlanterSeed"] = "Ты посадил руду, время роста каждой стадии",
["GiveSeedAdmin"] = "Тебе выдали осколок",
["ErrorCMDSearch"] = "Данный игрок не найден /ore nick amount",
["ErrorCMDAmount"] = "Укажи количество /ore amount",
["ErrorCMDNick"] = "Вы не указали количество /ore nick amount",
["ErrorCMDPermission"] = "Вы не указали количество /ore nick amount",
["InfoDdraw"] = "<size=25><b>Посаженная руда</b></size>\n<size=17>\nВремя до полного роста: {0}</size>" ,
["InfoFull"] = "<size=25><b>Посаженная руда</b></size>\n<size=17>\nРуда выросла, можно добывать</size>"
}, this ,"ru");
lang.RegisterMessages(new Dictionary<String, String>
{
["ErrorPlanterZone"] = "You can plant a fragment only in the area of your closet",
["ErrorPlanter"] = "You can plant a fragment on the ground",
["GiveBonusSeed"] = "You got a fragment",
["PlanterSeed"] = "You planted ore, the growth time of each stage",
["GiveSeedAdmin"] = "You were given a shard",
["ErrorCMDSearch"] = "This player was not found /ore nick amount",
["ErrorCMDAmount"] = "Specify quantity /ore amount",
["ErrorCMDNick"] = "You didn't specify the quantity /ore nick amount",
["ErrorCMDPermission"] = "You didn't specify the quantity /ore nick amount",
["InfoDdraw"] = "<size=25><b>Planted ore</b></size>\n<size=17>\ntime to full growth: {0}</size>" ,
["InfoFull"] = "<size=25><b>Planted ore</b></size>\n<size=17>\nPond has grown, it is possible to mine</size>"
}, this ,"en");
}
}
}