C#:
using ConVar;
using Newtonsoft.Json;
using Oxide.Core.Plugins;
using System;
using System.Collections.Generic;
using UnityEngine;
using Oxide.Game.Rust.Cui;
namespace Oxide.Plugins {
[Info("COVID19", "Mercury", "0.0.2")]
[Description("COVID19 RUST'a")]
class COVID19 : RustPlugin {
/// <summary>
/// Обновление 0.0.2
/// - Исправлена проблема с заваливанием игрока
/// - Изменил интерфейс плагина
/// - Добавлена возможность выдавать защитный костюм и антидот через команду по НИКУ игрока
/// </summary>
#region Reference
[PluginReference]
Plugin IQChat;
public void SendChat(string Message, BasePlayer player, Chat.ChatChannel channel = Chat.ChatChannel.Global) {
if (IQChat) IQChat?.Call("API_ALERT_PLAYER", player, Message, "[COVID19]\n");
else player.SendConsoleCommand("chat.add", channel, 0, Message);
}
#endregion
#region Vars
public Dictionary<ulong, int> InfectionPlayer = new Dictionary<ulong, int>();
string AntiDote = "syringe.medical";
#endregion
#region Data
public InfectionData DateUpArrow = new InfectionData();
public class InfectionData {
public int TDay;
public int UPRare;
}
void ReadData() => DateUpArrow = Oxide.Core.Interface.Oxide.DataFileSystem.ReadObject<InfectionData>("COVID19/COVID19");
void WriteData() => Oxide.Core.Interface.Oxide.DataFileSystem.WriteObject("COVID19/COVID19", DateUpArrow);
void RegisteredData() {
int ThisDay = DateTime.Now.Day;
if (DateUpArrow == null) {
DateUpArrow.TDay = ThisDay;
DateUpArrow.UPRare = 1;
Puts("Дата заражения выбрана успешно");
return;
}
if (DateUpArrow.TDay != ThisDay) {
DateUpArrow.TDay = ThisDay;
DateUpArrow.UPRare += config.InfectionSetting.UpInfectionRare;
PrintWarning("Шанс заражения был увеличен");
}
}
#endregion
#region Configuration
private static Configuration config = new Configuration();
private class Configuration {
[JsonProperty("Настройка предметов")]
public ItemSettings ItemSetting = new ItemSettings();
[JsonProperty("Настройка заражения")]
public InfectionSettings InfectionSetting = new InfectionSettings();
[JsonProperty("Настройка выпадения антидота из ящиков.Пример [crate_normal] = 15")]
public Dictionary<string, int> CrateDropSetting = new Dictionary<string, int>();
internal class InfectionSettings {
[JsonProperty("Сколько времени давать на поиск антидота(в секундах)")]
public int TimeSearchAntidote;
[JsonProperty("На сколько увеличивать шанс заражения каждый день - %")]
public int UpInfectionRare;
[JsonProperty("Животные от которых можно заразиться и шанс.Пример - [bear] = 10")]
public Dictionary<string, int> AnimalInfection = new Dictionary<string, int>();
[JsonProperty("Еда от которой можно заразиться и шанс.Пример - [horsemeat.raw] = 10")]
public Dictionary<string, int> FoodInfection = new Dictionary<string, int>();
[JsonProperty("Шанс заразиться от лутания труопв игроков и NPC")]
public int CorpseInfectionRare;
}
internal class ItemSettings {
[JsonProperty("Отображаемое имя для шприца с Антидотом")]
public string AntidoteName;
[JsonProperty("SkinID для шприца с Антидотом")]
public ulong AntidoteSkinID;
[JsonProperty("Shortname для одежды,на которую не действует вирус")]
public string ShortnameAntiName;
[JsonProperty("Отображаемое имя для одежды,на которую не действует вирус")]
public string ArmorAntiName;
[JsonProperty("SkinID для для одежды,на которую не действует вирус")]
public ulong ArmorAntiSkinID;
}
public static Configuration GetNewConfiguration() {
return new Configuration {
InfectionSetting = new InfectionSettings {
UpInfectionRare = 5, TimeSearchAntidote = 300, CorpseInfectionRare = 10, AnimalInfection = new Dictionary<string, int> {
["bear"]
= 2, ["boar"] = 2, ["chicken"] = 1, ["horse"] = 5, ["stag"] = 2, ["wolf"] = 3,
}
, FoodInfection = new Dictionary<string, int> {
["chicken.spoiled"]
= 50, ["humanmeat.spoiled"] = 70, ["wolfmeat.spoiled"] = 50, ["humanmeat.raw"] = 50,
}
,
}
, ItemSetting = new ItemSettings {
AntidoteName = "Антидот", AntidoteSkinID = 2473091511, ArmorAntiName = "Защитный костюм", ShortnameAntiName = "hazmatsuit_scientist_peacekeeper", ArmorAntiSkinID = 2473116132
}
, CrateDropSetting = new Dictionary<string, int> {
["crate_normal"]
= 70, ["crate_basic"] = 50, ["crate_elite"] = 100,
}
,
}
;
}
}
protected override void LoadConfig() {
base.LoadConfig();
try {
config = Config.ReadObject<Configuration>();
if (config == null) LoadDefaultConfig();
}
catch {
PrintWarning($"Ошибка чтения #3527 конфигурации 'oxide/config/{Name}', создаём новую конфигурацию!!");
LoadDefaultConfig();
}
NextTick(SaveConfig);
}
protected override void LoadDefaultConfig() => config = Configuration.GetNewConfiguration();
protected override void SaveConfig() => Config.WriteObject(config);
#endregion
#region Hooks
void Unload() {
WriteData();
foreach (var player in BasePlayer.activePlayerList) CuiHelper.DestroyUi(player, COVID_UI);
}
private void OnServerInitialized() {
ReadData();
RegisteredData();
WriteData();
}
void OnNewSave(string filename) {
int ThisDay = DateTime.Now.Day;
DateUpArrow.TDay = ThisDay;
DateUpArrow.UPRare = 1;
}
private void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
if (entity == null || info == null) return;
var Initiator = info.Initiator;
if (Initiator == null) return;
var player = entity as BasePlayer;
if (player == null) return;
var InfectionTarget = config.InfectionSetting;
if (((bool)(Initiator as BaseAnimalNPC))) {
string Animal = Initiator.ShortPrefabName.ToLower();
int Rare = config.InfectionSetting.AnimalInfection[Animal];
if (!IsRare(Rare)) return;
if (!InfectionTarget.AnimalInfection.ContainsKey(Animal)) return;
InfectionMetods(player);
}
}
void OnEntityDeath(BaseCombatEntity entity, HitInfo info) {
if (entity == null) return;
if (info == null) return;
if (info?.InitiatorPlayer == null || info == null) return;
var player = info?.InitiatorPlayer;
if (player == null) return;
if (entity?.ToPlayer() == null) return;
if (entity?.ToPlayer().userID == player.userID) {
if (InfectionPlayer.ContainsKey(player.userID)) {
InfectionPlayer.Remove(player.userID);
CuiHelper.DestroyUi(player, COVID_UI);
return;
}
}
}
void OnEntitySpawned(BaseNetworkable entity) => SpawnMetods((BaseEntity)entity);
void OnPlayerRespawned(BasePlayer player) {
if (player == null) return;
if (!InfectionPlayer.ContainsKey(player.userID)) return;
InfectionPlayer.Remove(player.userID);
}
void SpawnMetods(BaseEntity entity) {
var cfg = config.CrateDropSetting;
if (!cfg.ContainsKey(entity.ShortPrefabName)) return;
if (!IsRare(cfg[entity.ShortPrefabName])) return;
if (entity.GetComponent<LootContainer>() == null) return;
var AntidoteCFG = config.ItemSetting;
var item = (Item)CreateItem(AntiDote, 1, AntidoteCFG.AntidoteName, AntidoteCFG.AntidoteSkinID);
item?.MoveToContainer(entity.GetComponent<LootContainer>().inventory);
}
private void OnLootEntity(BasePlayer player, BaseEntity entity) {
if (entity.OwnerID >= 7656000000) return;
if ((bool)(entity as BaseCorpse)) {
var Rare = config.InfectionSetting.CorpseInfectionRare;
if (!IsRare(Rare)) return;
InfectionMetods(player);
entity.OwnerID = player.userID;
}
}
object OnItemAction(Item item, string action, BasePlayer player) {
var Eat = config.InfectionSetting.FoodInfection;
if (Eat.ContainsKey(item.info.shortname.ToLower()) && action == "consume") {
int Rare = Eat[item.info.shortname];
if (!IsRare(Rare)) return null;
InfectionMetods(player);
}
return null;
}
void OnHealingItemUse(MedicalTool tool, BasePlayer player) {
if (tool == null) return;
if (player == null) return;
if (tool.skinID == config.ItemSetting.AntidoteSkinID) DisinfectionMetods(player);
}
#endregion
#region Metods
void InfectionMetods(BasePlayer player) {
foreach (var inv in player.inventory.containerWear.itemList) {
var Armor = config.ItemSetting;
if (inv.info.shortname == Armor.ShortnameAntiName && inv.skin == Armor.ArmorAntiSkinID) return;
}
if (player.IsWounded()) return;
if (!InfectionPlayer.ContainsKey(player.userID)) {
int Time = (int)(config.InfectionSetting.TimeSearchAntidote + CurrentTime());
InfectionPlayer.Add(player.userID, Time);
SendChat(lang.GetMessage("CHAT_INFECTION_ADD", this, player.UserIDString), player);
InterfaceTimer(player);
return;
}
SendChat(lang.GetMessage("CHAT_INFECTION_RETRY_ADD", this, player.UserIDString), player);
player.BecomeWounded();
CuiHelper.DestroyUi(player, COVID_UI);
}
void DisinfectionMetods(BasePlayer player) {
if (!InfectionPlayer.ContainsKey(player.userID)) {
SendChat(lang.GetMessage("CHAT_DESINFECTION_USE_ANTIDOT_NO_INFECTION", this, player.UserIDString), player);
player.Heal(20);
return;
}
InfectionPlayer.Remove(player.userID);
player.Heal(30);
SendChat(lang.GetMessage("CHAT_DESINFECTION_USE_ANTIDOT", this, player.UserIDString), player);
CuiHelper.DestroyUi(player, COVID_UI);
}
void InfectionDessmound(BasePlayer player) {
if (!InfectionPlayer.ContainsKey(player.userID)) return;
SendChat(lang.GetMessage("CHAT_INFECTION_KILL", this, player.UserIDString), player);
player.BecomeWounded();
InfectionPlayer.Remove(player.userID);
CuiHelper.DestroyUi(player, COVID_UI);
}
public bool IsRare(int Rare) {
if ((Rare + DateUpArrow.UPRare) >= UnityEngine.Random.Range(0, 100)) return true;
else return false;
}
#region Items
Item CreateItem(string Shortname, int Amount, string DisplayName = "", ulong SkinID = 0) {
Item Items = ItemManager.CreateByName(Shortname, Amount, SkinID);
if (!string.IsNullOrEmpty(DisplayName)) Items.name = DisplayName;
return Items;
}
private Item OnItemSplit(Item item, int amount) {
if (plugins.Find("ChestStacks") || plugins.Find("Stacks") || plugins.Find("CustomSkinsStacksFix") || plugins.Find("SkinBox")) return null;
var Antidote = config.ItemSetting;
if (item.skin == Antidote.AntidoteSkinID) {
Item x = ItemManager.CreateByPartialName(AntiDote, amount, Antidote.AntidoteSkinID);
x.name = Antidote.AntidoteName;
x.skin = Antidote.AntidoteSkinID;
x.amount = amount;
item.amount -= amount;
return x;
}
return null;
}
object CanCombineDroppedItem(DroppedItem item, DroppedItem targetItem) {
if (item.GetItem().skin != targetItem.GetItem().skin) return false;
return null;
}
object CanStackItem(Item item, Item targetItem) {
if (item.skin != targetItem.skin) return false;
return null;
}
#endregion
#endregion
#region Command
[ConsoleCommand("covid")]
//covid give_antidote STEAMID
void ConsoleCovidCommand(ConsoleSystem.Arg arg) {
switch (arg.Args[0].ToLower()) {
case "give_antidote" : {
BasePlayer player = BasePlayer.Find(arg.Args[1]);
if (player == null || !player.IsConnected) return;
var Antidote = config.ItemSetting;
player.GiveItem(CreateItem(AntiDote, 1, Antidote.AntidoteName, Antidote.AntidoteSkinID));
Puts($"Успешно выдан антидот игроку {player.displayName}");
break;
}
case "give_armor" : {
BasePlayer player = BasePlayer.Find(arg.Args[1]);
if (player == null || !player.IsConnected) return;
var Armor = config.ItemSetting;
player.GiveItem(CreateItem(Armor.ShortnameAntiName, 1, Armor.ArmorAntiName, Armor.ArmorAntiSkinID));
Puts($"Успешно выдан защитный костюм игроку {player.displayName}");
break;
}
}
}
#endregion
#region UI
public static string COVID_UI = "COVID_PARENT";
void InterfaceTimer(BasePlayer player) {
CuiElementContainer container = new CuiElementContainer();
CuiHelper.DestroyUi(player, COVID_UI);
container.Add(new CuiPanel {
CursorEnabled = false, Image = {
Color = "0 0 0 0.4029412"
}
, RectTransform = {
AnchorMin = "0.5 0", AnchorMax = "0.5 0", OffsetMin = "-198.911 86", OffsetMax = "181.957 108.045"
}
}
, "Hud", COVID_UI);
container.Add(new CuiElement {
Name = "AlertPlayer", Parent = COVID_UI, Components = {
new CuiTextComponent {
Text = lang.GetMessage("UI_YOU_INFECTION", this, player.UserIDString), Font = "robotocondensed-regular.ttf", FontSize = 12, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1"
}
, new CuiRectTransformComponent {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-190.704 -11.022", OffsetMax = "190.706 11.022"
}
}
}
);
CuiHelper.AddUi(player, container);
TimerUpdate(player);
}
void TimerUpdate(BasePlayer player) {
timer.Once(1f, () => {
if (player.IsWounded()) return;
if (player.IsDead()) return;
if (!InfectionPlayer.ContainsKey(player.userID)) return;
int Time = (int)(InfectionPlayer[player.userID] - CurrentTime());
if (Time <= 0) InfectionDessmound(player);
CuiElementContainer container = new CuiElementContainer();
CuiHelper.DestroyUi(player, "TimerTick");
container.Add(new CuiElement {
Name = "TimerTick", Parent = COVID_UI, Components = {
new CuiTextComponent {
Text = String.Format(lang.GetMessage("UI_FULL_INFECTION_TIMER", this, player.UserIDString), FormatTime(TimeSpan.FromSeconds(Time))), Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1"
}
, new CuiOutlineComponent {
Color = "0 0 0 0.5", Distance = "1 -1"
}
, new CuiRectTransformComponent {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-190.433 11.022", OffsetMax = "190.707 35.041"
}
}
}
);
CuiHelper.AddUi(player, container);
TimerUpdate(player);
}
);
}
#endregion
#region Helps
static DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0);
static double CurrentTime() => DateTime.UtcNow.Subtract(epoch).TotalSeconds;
public static string FormatTime(TimeSpan time) {
string result = string.Empty;
if (time.Days != 0) result += $"{Format(time.Days, "д", "д", "д")} ";
if (time.Hours != 0) result += $"{Format(time.Hours, "ч", "ч", "ч")} ";
if (time.Minutes != 0) result += $"{Format(time.Minutes, "м", "м", "м")} ";
if (time.Seconds != 0) result += $"{Format(time.Seconds, "с", "с", "с")} ";
return result;
}
private static string Format(int units, string form1, string form2, string form3) {
var tmp = units % 10;
if (units >= 5 && units <= 20 || tmp >= 5 && tmp <= 9) return $"{units} {form1}";
if (tmp >= 2 && tmp <= 4) return $"{units} {form2}";
return $"{units} {form3}";
}
#endregion
#region Lang
private new void LoadDefaultMessages() {
lang.RegisterMessages(new Dictionary<string, string> {
["UI_FULL_INFECTION_TIMER"]
= "UNTIL THE COMPLETE DEFEAT IS LEFT {0}", ["UI_YOU_INFECTION"] = "YOU ARE INFECTED WITH A VIRUS.USE THE ANTIDOTE.", ["CHAT_INFECTION_ADD"] = "You have become infected with COVID-19, find the antidote or you will die!", ["CHAT_INFECTION_KILL"] = "You did not survive COVID-19", ["CHAT_INFECTION_RETRY_ADD"] = "You re-contracted COVID-19 during an illness and you were infected", ["CHAT_DESINFECTION_USE_ANTIDOT"] = "You used an antidote from COVID-19, and successfully recovered!", ["CHAT_DESINFECTION_USE_ANTIDOT_NO_INFECTION"] = "You used a COVID-19 antidote when you weren’t infected\nPrevention above all else!",
}
, this);
lang.RegisterMessages(new Dictionary<string, string> {
["UI_FULL_INFECTION_TIMER"]
= "ДО ПОЛНОГО ПОРАЖЕНИЯ ОСТАЛОСЬ {0}", ["UI_YOU_INFECTION"] = "ВЫ ЗАРАЖЕНЫ ВИРУСОМ.ВОСПОЛЬЗУЙТЕСЬ АНТИДОТОМ.", ["CHAT_INFECTION_ADD"] = "Вы заразились COVID-19, найдите антидот или вы умрете!", ["CHAT_INFECTION_KILL"] = "Вас поразил COVID-19", ["CHAT_INFECTION_RETRY_ADD"] = "Вы повторно заразились COVID-19 во время болезни и вас поразила зараза", ["CHAT_DESINFECTION_USE_ANTIDOT"] = "Вы использовали антидот от COVID-19,и успешно излечились!", ["CHAT_DESINFECTION_USE_ANTIDOT_NO_INFECTION"] = "Вы использовали антидот от COVID-19,когда не были заражены\nПрофилактика превыше всего!",
}
, this, "ru");
PrintWarning("Языковой файл загружен успешно");
}
#endregion
}
}