C#:
using UnityEngine;
using System;
using Oxide.Game.Rust.Cui;
using System.Collections.Generic;
using Oxide.Core;
using Oxide.Core.Plugins;
using Newtonsoft.Json;
using System.Linq;
using Newtonsoft.Json.Linq;
using Rust;
using System.Text;
using System.Globalization;
using System.Collections;
using UnityEngine.Networking;
namespace Oxide.Plugins {
[Info("XDStatistics", "https://discord.gg/9vyTXsJyKR", "1.0.0")]
[Description("Multifunctional statistics for your server!")]
class XDStatistics : RustPlugin {
/// <summary>
/// Вернул ткань в категорию фермерство
/// Отсортировал предметы по количеству в категории фермерство
/// Исправил добавления ботов в статистику
/// Исправил формат времени в оповещениях в чат
/// Некоторые исправления подсчета сбитие вертолета
/// Некоторые изменения в конфигурации а именно вам нужно заного настроить геймстор магазин
/// </summary>
#region ReferencePlugins
[PluginReference]
Plugin ImageLibrary, Friends, Clans, Battles, Duel, Economics, IQEconomic, ServerRewards, GameStoresRUST, RustStore;
private bool IsFriends(ulong userID, ulong targetID) {
if (Friends) return (bool)Friends?.Call("HasFriend", userID, targetID);
else if (RelationshipManager.ServerInstance.playerToTeam.ContainsKey(userID) && RelationshipManager.ServerInstance.playerToTeam[userID].members.Contains(targetID)) return true;
else return false;
}
private bool IsClans(string userID, string targetID) {
if (Clans) {
String TagUserID = (String)Clans?.Call("GetClanOf", userID);
String TagTargetID = (String)Clans?.Call("GetClanOf", targetID);
if (TagUserID == null && TagTargetID == null) return false;
return (bool)(TagUserID == TagTargetID);
}
else return false;
}
private bool IsDuel(ulong userID) {
if (Battles) return (bool)Battles?.Call("IsPlayerOnBattle", userID);
else if (Duel) return (bool)Duel?.Call("IsPlayerOnActiveDuel", BasePlayer.FindByID(userID));
else return false;
}
private string GetImage(string shortname, ulong skin = 0) => (string)ImageLibrary?.Call("GetImage", shortname, skin);
private bool AddImage(string url, string shortname, ulong skin = 0) => (bool)ImageLibrary?.Call("AddImage", url, shortname, skin);
private void SendImage(BasePlayer player, string imageName, ulong imageId = 0) => ImageLibrary?.Call("SendImage", player, imageName, imageId);
private bool HasImage(string imageName, ulong imageId = 0) => (bool)ImageLibrary.Call("HasImage", imageName, imageId);
#endregion
#region Var
private static XDStatistics _;
private readonly string permAdmin = "XDStatistics.admin";
private readonly string permReset = "XDStatistics.reset";
private readonly string permAvailability = "XDStatistics.availability";
private enum CatType {
score, killer, time, farm, raid
}
private Dictionary<string, ItemDisplayName> ItemName = new Dictionary<string, ItemDisplayName>();
private List<items> ItemList = new List<items>();
public static StringBuilder sb;
private Dictionary<uint, string> prefabID2Item = new Dictionary<uint, string>();
private Dictionary<string, string> prefabNameItem = new Dictionary<string, string>() {
["40mm_grenade_he"]
= "multiplegrenadelauncher", ["grenade.beancan.deployed"] = "grenade.beancan", ["grenade.f1.deployed"] = "grenade.f1", ["explosive.satchel.deployed"] = "explosive.satchel", ["explosive.timed.deployed"] = "explosive.timed", ["rocket_basic"] = "ammo.rocket.basic", ["rocket_hv"] = "ammo.rocket.hv", ["rocket_fire"] = "ammo.rocket.fire", ["survey_charge.deployed"] = "surveycharge"
}
;
private List<int> AlowedSeedId = new List<int>() {
1548091822, 1771755747, 1112162468, 1367190888, 858486327, -1962971928, -2086926071, -567909622, 1272194103, 854447607, 1660145984, 1783512007, -858312878
}
;
#endregion
#region Lang
protected override void LoadDefaultMessages() {
lang.RegisterMessages(new Dictionary<string, string> {
["STAT_TOP_FIVE_KILL"]
= "<size=16>Top 5 <color=#4286f4>Killers</color>\n{0}</size>", ["STAT_TOP_FIVE_FARM"] = "<size=16>Top 5 <color=#4286f4>Farmers</color>\n{0}</size>", ["STAT_TOP_FIVE_EXPLOSION"] = "<size=16>Top 5 <color=#4286f4>Explosions</color>\n{0}</size>", ["STAT_TOP_FIVE_TIMEPLAYED"] = "<size=16>Top 5 <color=#4286f4>Most Time Played</color>\n{0}</size>", ["STAT_TOP_FIVE_BUILDINGS"] = "<size=16>Top 5 <color=#4286f4>Builders</color>\n{0}</size>", ["STAT_TOP_FIVE_SCORE"] = "<size=16>Top 5 <color=#4286f4>Most points</color>\n{0}</size>", ["STAT_TOP_FIVE_FERMER"] = "<size=16>Top 5 <color=#4286f4>Farmers</color>\n{0}</size>", ["STAT_USER_TOTAL_GATHERED"] = "Total Gathered:", ["STAT_USER_TOTAL_EXPLODED"] = "Total Explosions:", ["STAT_USER_TOTAL_GROWED"] = "Total Farmed:", ["STAT_UI_MY_STAT"] = "My Statistics", ["STAT_UI_TOP_TEN"] = "Top 10 Players", ["STAT_UI_SEARCH"] = "Search", ["STAT_UI_INFO"] = "Player Information {0}", ["STAT_UI_ACTIVITY"] = "Activity", ["STAT_UI_ACTIVITY_TODAY"] = "Today: {0}", ["STAT_UI_ACTIVITY_TOTAL"] = "All Time: {0}", ["STAT_UI_SETTINGS"] = "Settings", ["STAT_UI_PLACE_TOP"] = "Place On Top: {0}", ["STAT_UI_SCORE"] = "Score: {0}", ["STAT_UI_PVP"] = "PvP Statistics", ["STAT_UI_FAVORITE_WEAPON"] = "Favorite Weapon", ["STAT_UI_PVP_KILLS"] = "Kills", ["STAT_UI_PVP_DEATH"] = "Deaths", ["STAT_UI_PVP_KDR"] = "K/D", ["STAT_UI_FAVORITE_WEAPON_KILLS"] = "Kills: {0} | Hits: {1}", ["STAT_UI_FAVORITE_WEAPON_NOT_DATA"] = "Data is still being calculated..", ["STAT_UI_OTHER_STAT"] = "Other Statistics", ["STAT_UI_HIDE_STAT"] = "Public Profile", ["STAT_UI_CONFIRM"] = "Are You Sure?", ["STAT_UI_CONFIRM_YES"] = "Yes", ["STAT_UI_CONFIRM_NO"] = "No", ["STAT_UI_RESET_STAT"] = "Reset Statistics", ["STAT_UI_CRATE_OPEN"] = "Crates Opened: {0}", ["STAT_UI_BARREL_KILL"] = "Barrels Destroyed: {0}", ["STAT_UI_ANIMAL_KILL"] = "Animal Kills: {0}", ["STAT_UI_HELI_KILL"] = "Helicopter Kills: {0}", ["STAT_UI_BRADLEY_KILL"] = "Bradley Kills: {0}", ["STAT_UI_NPC_KILL"] = "NPC Kills: {0}", ["STAT_UI_BTN_MORE"] = "Show More", ["STAT_UI_CATEGORY_GATHER"] = "Gather", ["STAT_UI_CATEGORY_EXPLOSED"] = "Explosions", ["STAT_UI_CATEGORY_PLANT"] = "Farming", ["STAT_UI_CATEGORY_TOP_KILLER"] = "Top 10 Killers", ["STAT_UI_CATEGORY_TOP_NPCKILLER"] = "Top 10 NPC Killers", ["STAT_UI_CATEGORY_TOP_TIME"] = "Top 10 Most Time Played", ["STAT_UI_CATEGORY_TOP_GATHER"] = "Top 10 Gatherers", ["STAT_UI_CATEGORY_TOP_SCORE"] = "Top 10 Most Score", ["STAT_UI_CATEGORY_TOP_EXPLOSED"] = "Top 10 Explosions", ["STAT_PRINT_WIPE"] = "Wipe Detected.Data was successfully cleared!", ["STAT_CMD_1"] = "No Permission!!", ["STAT_CMD_2"] = "Usage: stat.ignore <add/remove> <Steam ID|Name>", ["STAT_CMD_3"] = "The specified playername could not be found.Please use their SteamID.", ["STAT_CMD_4"] = "Found several players with similar names: {0}", ["STAT_CMD_5"] = "Player not found!", ["STAT_CMD_6"] = "Player {0} is already ignored", ["STAT_CMD_7"] = "You have successfully added a player {0} to the ignore list", ["STAT_CMD_8"] = "The player {0} is not in the ignore list", ["STAT_CMD_9"] = "You have successfully removed the player {0} from the ignore list", ["STAT_ADMIN_HIDE_STAT"] = "You've been added to the ignore list.You will not have access to the statistics.If this is an error, Please contact the Administrator!", ["STAT_TOP_PLAYER_WIPE_SCORE"] = "Congratulations!\nYou successfully held the {0} position in the previous wipe in the category <color=#4286f4>HIGHEST SCORE</color>\nYou received a well deserved Reward!", ["STAT_TOP_PLAYER_WIPE_TIME"] = "Congratulations!\nYou successfully held the {0} position in the previous wipe in the category <color=#4286f4>MOST TIME PLAYED</color>\nYou received a well deserved Reward!", ["STAT_TOP_PLAYER_WIPE_EXP"] = "Congratulations!\nYou successfully held the {0} position in the previous wipe in the category <color=#4286f4>MOST EXPLOSIONS</color>\nYou received a well deserved Reward!", ["STAT_TOP_PLAYER_WIPE_FARM"] = "Congratulations!\nYou successfully held the {0} position in the previous wipe in the category <color=#4286f4>MOST CROPS FARMED</color>\nYou received a well deserved Reward!", ["STAT_TOP_PLAYER_WIPE_KILL"] = "Congratulations!\nYou successfully held the {0} position in the previous wipe in the category <color=#4286f4>MOST KILLS</color>\nYou received a well deserved Reward!", ["STAT_TOP_VK_SCORE"] = "Топ {0} игрока по очкам\n {1}", ["STAT_TOP_VK_KILLER"] = "Топ {0} игрока по убийствам\n {1}", ["STAT_TOP_VK_TIME"] = "Топ {0} игрока по онлайну\n {1}", ["STAT_TOP_VK_FARM"] = "Топ {0} игрока по фарму\n {1}", ["STAT_TOP_VK_RAID"] = "Топ {0} игрока по рейдам\n {1}",
}
, this);
lang.RegisterMessages(new Dictionary<string, string> {
["STAT_TOP_FIVE_KILL"]
= "<size=16>Топ 5 <color=#4286f4>киллеры</color>\n{0}</size>", ["STAT_TOP_FIVE_FARM"] = "<size=16>Топ 5 <color=#4286f4>фармеры</color>\n{0}</size>", ["STAT_TOP_FIVE_EXPLOSION"] = "<size=16>Топ 5 <color=#4286f4>рейдеры</color>\n{0}</size>", ["STAT_TOP_FIVE_TIMEPLAYED"] = "<size=16>Топ 5 <color=#4286f4>долгожителей</color>\n{0}</size>", ["STAT_TOP_FIVE_BUILDINGS"] = "<size=16>Топ 5 <color=#4286f4>строители</color>\n{0}</size>", ["STAT_TOP_FIVE_SCORE"] = "<size=16>Топ 5 по <color=#4286f4>очкам</color>\n{0}</size>", ["STAT_TOP_FIVE_FERMER"] = "<size=16>Топ 5 <color=#4286f4>фермеров</color>\n{0}</size>", ["STAT_USER_TOTAL_GATHERED"] = "Всего добыто:", ["STAT_USER_TOTAL_EXPLODED"] = "Всего взорвано:", ["STAT_USER_TOTAL_GROWED"] = "Всего выращено:", ["STAT_UI_MY_STAT"] = "Моя Статистика", ["STAT_UI_TOP_TEN"] = "Топ 10 игроков", ["STAT_UI_SEARCH"] = "Поиск", ["STAT_UI_INFO"] = "Информация о профиле {0}", ["STAT_UI_ACTIVITY"] = "Активность", ["STAT_UI_ACTIVITY_TODAY"] = "Сегодня: {0}", ["STAT_UI_ACTIVITY_TOTAL"] = "За все время: {0}", ["STAT_UI_SETTINGS"] = "Настройки", ["STAT_UI_PLACE_TOP"] = "Место в топе: {0}", ["STAT_UI_SCORE"] = "SCORE: {0}", ["STAT_UI_PVP"] = "PVP статистика", ["STAT_UI_FAVORITE_WEAPON"] = "Фаворитное оружие", ["STAT_UI_PVP_KILLS"] = "Убийств", ["STAT_UI_PVP_DEATH"] = "Смертей", ["STAT_UI_PVP_KDR"] = "K/D", ["STAT_UI_FAVORITE_WEAPON_KILLS"] = "Убийств: {0} | Попаданий: {1}", ["STAT_UI_FAVORITE_WEAPON_NOT_DATA"] = "Данные еще собираются...", ["STAT_UI_OTHER_STAT"] = "Другая статистика", ["STAT_UI_HIDE_STAT"] = "Общедоступный профиль", ["STAT_UI_CONFIRM"] = "Вы уверены ?", ["STAT_UI_CONFIRM_YES"] = "Да", ["STAT_UI_CONFIRM_NO"] = "Нет", ["STAT_UI_RESET_STAT"] = "Обнулить статистику", ["STAT_UI_CRATE_OPEN"] = "Открыто ящиков: {0}", ["STAT_UI_BARREL_KILL"] = "Разбито бочек: {0}", ["STAT_UI_ANIMAL_KILL"] = "Убито животных: {0}", ["STAT_UI_HELI_KILL"] = "Сбито вертолетов: {0}", ["STAT_UI_BRADLEY_KILL"] = "Танков уничтожено: {0}", ["STAT_UI_NPC_KILL"] = "Убито NPC: {0}", ["STAT_UI_BTN_MORE"] = "Показать еще", ["STAT_UI_CATEGORY_GATHER"] = "Добыча", ["STAT_UI_CATEGORY_EXPLOSED"] = "Взрывчатка", ["STAT_UI_CATEGORY_PLANT"] = "Фермерство", ["STAT_UI_CATEGORY_TOP_KILLER"] = "Топ 10 киллеров", ["STAT_UI_CATEGORY_TOP_NPCKILLER"] = "Топ 10 убийц npc", ["STAT_UI_CATEGORY_TOP_TIME"] = "Топ 10 по онлайну", ["STAT_UI_CATEGORY_TOP_GATHER"] = "Топ 10 фармил", ["STAT_UI_CATEGORY_TOP_SCORE"] = "Топ 10 по очкам", ["STAT_UI_CATEGORY_TOP_EXPLOSED"] = "Топ 10 рейдеров", ["STAT_PRINT_WIPE"] = "Произошел вайп.Данные успешно удалены!", ["STAT_CMD_1"] = "Недостаточно прав!", ["STAT_CMD_2"] = "Используйте: stat.ignore <add/remove> <Steam ID|Имя>", ["STAT_CMD_3"] = "Указанный игрок не найден.Для более точного поиска укажите его SteamID.", ["STAT_CMD_4"] = "Найдено несколько игроков с похожим именем: {0}", ["STAT_CMD_5"] = "Игрок не найден!", ["STAT_CMD_6"] = "Игрок {0} уже игнорируется", ["STAT_CMD_7"] = "Вы успешно добавили игрока {0} в игнор лист", ["STAT_CMD_8"] = "Игрока {0} нет в списке игнорируемых", ["STAT_CMD_9"] = "Вы успешно убрали игрока {0} из игнор листа", ["STAT_ADMIN_HIDE_STAT"] = "Вы добавлены в игнор лист.У вас нет доступа к статистики, если это ошибка, свяжитесь с администратором!", ["STAT_TOP_PLAYER_WIPE_SCORE"] = "Поздравляю!\nВ прошлом вайпе вы успешно удерживали {0} позицию в категории <color=#4286f4>SCORE</color>\nВы заслужено получаете награду!", ["STAT_TOP_PLAYER_WIPE_TIME"] = "Поздравляю!\nВ прошлом вайпе вы успешно удерживали {0} позицию в категории <color=#4286f4>Долгожитель</color>\nВы заслужено получаете награду!", ["STAT_TOP_PLAYER_WIPE_EXP"] = "Поздравляю!\nВ прошлом вайпе вы успешно удерживали {0} позицию в категории <color=#4286f4>Рейдер</color>\nВы заслужено получаете награду!", ["STAT_TOP_PLAYER_WIPE_FARM"] = "Поздравляю!\nВ прошлом вайпе вы успешно удерживали {0} позицию в категории <color=#4286f4>Добытчик</color>\nВы заслужено получаете награду!", ["STAT_TOP_PLAYER_WIPE_KILL"] = "Поздравляю!\nВ прошлом вайпе вы успешно удерживали {0} позицию в категории <color=#4286f4>Киллер</color>\nВы заслужено получаете награду!", ["STAT_TOP_VK_SCORE"] = "Топ {0} игрока по очкам\n {1}", ["STAT_TOP_VK_KILLER"] = "Топ {0} игрока по убийствам\n {1}", ["STAT_TOP_VK_TIME"] = "Топ {0} игрока по онлайну\n {1}", ["STAT_TOP_VK_FARM"] = "Топ {0} игрока по фарму\n {1}", ["STAT_TOP_VK_RAID"] = "Топ {0} игрока по рейдам\n {1}",
}
, this, "ru");
}
#endregion
#region Configuration
private Configuration config;
private class Configuration {
public class SettingsInterface {
[JsonProperty("Цвет плашки заднего фона в топ 10 за 1 место | Background color in the top 10 for 1st place")]
public string ColorTop1 = "1 0.8431373 0 0.49";
[JsonProperty("Цвет плашки заднего фона в топ 10 за 2 место | Background color in the top 10 for 2st place")]
public string ColorTop2 = "0.7529412 0.7529412 0.7529412 0.49";
[JsonProperty("Цвет плашки заднего фона в топ 10 за 3 место | Background color in the top 10 for 3st place")]
public string ColorTop3 = "0.8039216 0.498031724 0.1960784 0.49";
}
public class Settings {
[JsonProperty("Чат команда для открытия статистики | Chat command for opening statistics")]
public string chatCommandOpenStat = "stat";
[JsonProperty("Консольная команда для открытия статистики | Console command to open statistics")]
public string consoleCommandOpenStat = "stat";
[JsonProperty("Отправлять в чат сообщения с топ 5 игроками в разных категориях | Send chat messages with top 5 players in different categories")]
public bool chatSendTop = true;
[JsonProperty("Раз в сколько секунд будет отправлятся сообщение ? | Once in how many seconds will a message be sent ?")]
public int chatSendTopTime = 600;
[JsonProperty("Включить возможность сбросить свою статистику ? (требуется XDStatistics.reset) | Enable the ability to reset your stats ? (requires XDStatistics.reset)")]
public bool dropStatUse = false;
[JsonProperty("Включить возможность скрыть свою статистику от пользователей ? (требуется XDStatistics.availability) | Enable the ability to hide your statistics from users ? (requires XDStatistics.availability)")]
public bool availabilityUse = true;
[JsonProperty("очищать данные при вайпе | Clear data when wiped")]
public bool wipeData = true;
[JsonProperty("Раз во сколько минут будут сохранятся данные | Once in a rowman, the data will be saved.")]
public int dataSaveTime = 30;
[JsonProperty("Учитывать убийство npc для фаворитного оружия ? | Consider killing an NPC for a favorite weapon ?")]
public bool npsDeathUse = false;
}
public class SettingsScore {
[JsonProperty("Очки за крафт | Points for crafting")]
public float craftScore = 1;
[JsonProperty("Очки за бочки | Points for barrels")]
public float barrelScore = 1;
[JsonProperty("Очки за установку строительных блоков | Points for installing building blocks")]
public float BuildingScore = 1;
[JsonProperty("Очки за использования взрывчатых предметов | Points for using explosive items")]
public Dictionary<string, float> ExplosionScore = new Dictionary<string, float>();
[JsonProperty("Очки за добычу ресурсов | Points for resource extraction")]
public Dictionary<string, float> GatherScore = new Dictionary<string, float>();
[JsonProperty("Очки за найденные скрап | Points for found scraps")]
public float ScrapScore = 0.5f;
[JsonProperty("Очки за сбор урожая (с плантации) | Points for harvesting (from the plantation)")]
public float PlantScore = 0.2f;
[JsonProperty("Очки за убийство животных | Points for killing animals")]
public float AnimalScore = 1;
[JsonProperty("Очки за сбитие вертолета | Points for shooting down a helicopter")]
public float HeliScore = 5;
[JsonProperty("Очки за взрыв танка | Points for tank explosion")]
public float BradleyScore = 5;
[JsonProperty("Очки за убийство нпс | Points for killing NPCs")]
public float NpcScore = 5;
[JsonProperty("Очки за убийство игроков | Points for killing players")]
public float PlayerScore = 10;
[JsonProperty("Очки за время (За кажду.минуту игры на сервере) | Points for time (for every minute of the game on the server)")]
public float TimeScore = 0.2f;
[JsonProperty("Сколько отнять очков за суицид ? | How many points to take away for suicide ?")]
public float SuicideScore = 2;
[JsonProperty("Сколько отнять очков за смерть ? | How many points to take away for death ?")]
public float DeathScore = 1;
}
public class SettingsPrize {
[JsonProperty("Использовать выдачу награды после вайпа ? | Use the award issue after the wipe ?")]
public bool prizeUse = false;
[JsonProperty("Награда в категории SCORE | Award in the SCORE category")]
public List<Prize> prizeScore = new List<Prize>();
[JsonProperty("Награда в категории Киллер | Award in the Killer category")]
public List<Prize> prizeKiller = new List<Prize>();
[JsonProperty("Награда в категории Фармила | Award in the gathering category")]
public List<Prize> prizeFarm = new List<Prize>();
[JsonProperty("Награда в категории рейдер | Reward in the Raider category")]
public List<Prize> prizeRaid = new List<Prize>();
[JsonProperty("Награда в категории Большой онлайн | Award in the Big Online categoryy")]
public List<Prize> prizeTime = new List<Prize>();
[JsonProperty("[RU][GameStores] ID магазина")]
public string ShopID = "";
[JsonProperty("[RU][GameStores] ID сервера")]
public string ServerID = "";
[JsonProperty("[RU][GameStores] Секретный ключ")]
public string SecretKey = "";
internal class Prize {
[JsonProperty("Использовать комманды в виде приза ? | Use command as a prize ?")]
public bool commandPrizeUse = true;
[JsonProperty("За какое место давать эту награду ? (от 1 до 3) если не нужно награждать эту категорию.удалите все награды | For which place to give this award ? (from 1 to 3) if you do not need to award this category.remove all rewards")]
public int top = 1;
[JsonProperty("[RU]Использовать магазин GameStore для выдачи награды")]
public bool gamestorePrizeUse = false;
[JsonProperty("[RU]Использовать магазин MoscowOVH для выдачи награды")]
public bool ovhPrizeUse = false;
[JsonProperty("Использовать [IQEconomic или Economics или ServerRewards] для выдачи награды | Use [IQEconomic or Economics or Server Rewards] to issue a reward")]
public bool economicPrizeUse = false;
[JsonProperty("Команды для приза | Command for the prize")]
public List<string> commandPrizeList = new List<string>();
[JsonProperty("[RU][GameStores или MoscowOVH] Сколько начислять денег на баланс")]
public int balancePlus = 30;
[JsonProperty("[IQEconomic или Economics или ServerRewards] Сколько начислять денег на баланс | [IQEconomic or Economics or ServerRewards] How much money to add to the balance")]
public int balanceEconomicsPlus = 100;
public void GiftPrizePlayer(BasePlayer player) {
if (commandPrizeUse) {
foreach (string cmd in commandPrizeList) _.Server.Command(cmd.Replace("%STEAMID%", player.UserIDString));
}
if (gamestorePrizeUse && _?.GameStoresRUST) {
_.webrequest.Enqueue($"https://gamestores.ru/api/?shop_id={_.config.settingsPrize.ShopID}&secret={_.config.settingsPrize.SecretKey}&server={_.config.settingsPrize.ServerID}&action=moneys&type=plus&steam_id={player.UserIDString}&amount={balancePlus}", "", (code, response) => {
switch (code) {
case 0 : {
_.PrintError("Api does not responded to a request");
break;
}
case 200 : {
break;
}
case 404 : {
_.PrintError($"Please check your configuration! {code}");
break;
}
}
}
, _);
}
if (ovhPrizeUse) {
if (_?.RustStore) {
_.RustStore.CallHook("APIChangeUserBalance", player.userID, balancePlus, new Action<string>(result => {
if (result == "SUCCESS") return;
Interface.Oxide.LogDebug($"Баланс игрока {player.userID} не был изменен, ошибка: {result}");
}
));
}
}
if (economicPrizeUse) {
if (_?.Economics) {
_.Economics.Call("Deposit", player.userID, (double)balanceEconomicsPlus);
}
else if (_?.IQEconomic) {
_.IQEconomic.Call("API_SET_BALANCE", player.userID, balanceEconomicsPlus);
}
else if (_?.ServerRewards) {
_.ServerRewards.Call("AddPoints", player.userID, balanceEconomicsPlus);
}
}
}
}
}
[JsonProperty("Основные настройки плагина | Basic plugin settings")]
public Settings settings = new Settings();
[JsonProperty("Настройка выдачи очков | Setting up the issuance of points")]
public SettingsScore settingsScore = new SettingsScore();
[JsonProperty("Настройка награды топ игрокам в каждой категории | Customize rewards for top 1 players in each category")]
public SettingsPrize settingsPrize = new SettingsPrize();
[JsonProperty("Настройки интерфейса | Interface Settings")]
public SettingsInterface settingsInterface = new SettingsInterface();
}
protected override void LoadConfig() {
base.LoadConfig();
try {
config = Config.ReadObject<Configuration>();
if (config == null) LoadDefaultConfig();
ValidateConfig();
SaveConfig();
}
catch (JsonException ex) {
Debug.LogException(ex);
LoadDefaultConfig();
}
}
private void ValidateConfig() {
if (config.settingsScore.GatherScore.Count == 0) {
config.settingsScore.GatherScore = new Dictionary<string, float> {
["wood"]
= 0.3f, ["stones"] = 0.6f, ["metal.ore"] = 1, ["sulfur.ore"] = 1.5f, ["hq.metal.ore"] = 2,
}
;
}
if (config.settingsScore.ExplosionScore.Count == 0) {
config.settingsScore.ExplosionScore = new Dictionary<string, float> {
["explosive.timed"]
= 2, ["explosive.satchel"] = 0.7f, ["grenade.beancan"] = 0.3f, ["grenade.f1"] = 0.1f, ["ammo.rocket.basic"] = 1, ["ammo.rocket.hv"] = 0.5f, ["ammo.rocket.fire"] = 0.7f, ["ammo.rifle.explosive"] = 0.02f,
}
;
}
if (!config.settingsScore.ExplosionScore.ContainsKey("ammo.rifle.explosive")) {
config.settingsScore.ExplosionScore.Add("ammo.rifle.explosive", 0.02f);
}
if (config.settingsPrize.prizeFarm.Count == 0) {
config.settingsPrize.prizeFarm = new List<Configuration.SettingsPrize.Prize> {
new Configuration.SettingsPrize.Prize {
commandPrizeList = new List<string> {
"say %STEAMID%"
}
}
, new Configuration.SettingsPrize.Prize {
top = 2, commandPrizeList = new List<string> {
"say %STEAMID%"
}
}
,
}
;
}
if (config.settingsPrize.prizeKiller.Count == 0) {
config.settingsPrize.prizeKiller = new List<Configuration.SettingsPrize.Prize> {
new Configuration.SettingsPrize.Prize {
commandPrizeList = new List<string> {
"say %STEAMID%"
}
}
, new Configuration.SettingsPrize.Prize {
top = 2, commandPrizeList = new List<string> {
"say %STEAMID%"
}
}
,
}
;
}
if (config.settingsPrize.prizeRaid.Count == 0) {
config.settingsPrize.prizeRaid = new List<Configuration.SettingsPrize.Prize> {
new Configuration.SettingsPrize.Prize {
commandPrizeList = new List<string> {
"say %STEAMID%"
}
}
, new Configuration.SettingsPrize.Prize {
top = 2, commandPrizeList = new List<string> {
"say %STEAMID%"
}
}
,
}
;
}
if (config.settingsPrize.prizeScore.Count == 0) {
config.settingsPrize.prizeScore = new List<Configuration.SettingsPrize.Prize> {
new Configuration.SettingsPrize.Prize {
commandPrizeList = new List<string> {
"say %STEAMID%"
}
}
, new Configuration.SettingsPrize.Prize {
top = 2, commandPrizeList = new List<string> {
"say %STEAMID%"
}
}
,
}
;
}
if (config.settingsPrize.prizeTime.Count == 0) {
config.settingsPrize.prizeTime = new List<Configuration.SettingsPrize.Prize> {
new Configuration.SettingsPrize.Prize {
commandPrizeList = new List<string> {
"say %STEAMID%"
}
}
, new Configuration.SettingsPrize.Prize {
top = 2, commandPrizeList = new List<string> {
"say %STEAMID%"
}
}
,
}
;
}
}
protected override void SaveConfig() {
Config.WriteObject(config);
}
protected override void LoadDefaultConfig() {
config = new Configuration();
}
#endregion
#region Data
private class StoredData {
public Dictionary<ulong, PlayerInfo> Players = new Dictionary<ulong, PlayerInfo>();
public Dictionary<ulong, PlayerInfo> IgnoreReservedPlayer = new Dictionary<ulong, PlayerInfo>();
public Dictionary<ulong, List<PrizePlayer>> PrizePlayer = new Dictionary<ulong, List<PrizePlayer>>();
public StoredData() {
}
}
private class PrizePlayer {
public string Name = string.Empty;
public CatType catType;
public int value;
public int top;
}
private class PlayerInfo {
public string Name = string.Empty;
public bool HidedStatistics = false;
public float Score = 0;
public Harvesting harvesting = new Harvesting();
public OtherStat otherStat = new OtherStat();
public Explosion explosion = new Explosion();
public Gather gather = new Gather();
public Weapon weapon = new Weapon();
public PVP pVP = new PVP();
public PlayedTime playedTime = new PlayedTime();
internal class PlayedTime {
public string DayNumber = DateTime.Now.ToShortDateString();
public int PlayedForWipe = 0;
public int PlayedToday = 0;
}
internal class Harvesting {
public Dictionary<string, int> HarvestingList = new Dictionary<string, int>();
public int AllHarvesting = 0;
}
internal class OtherStat {
public int CrateOpen = 0;
public int BarrelDeath = 0;
public int AllCraft = 0;
public int BuildingCrate = 0;
public int AnimalsKill = 0;
}
internal class Explosion {
public Dictionary<string, int> ExplosionUsed = new Dictionary<string, int>() {
["explosive.timed"]
= 0, ["explosive.satchel"] = 0, ["grenade.beancan"] = 0, ["grenade.f1"] = 0, ["ammo.rocket.basic"] = 0, ["ammo.rocket.hv"] = 0, ["ammo.rocket.fire"] = 0, ["ammo.rifle.explosive"] = 0
}
;
public int AllExplosionUsed = 0;
}
internal class Gather {
public Dictionary<string, int> GatheredTotal = new Dictionary<string, int>() {
["wood"]
= 0, ["stones"] = 0, ["metal.ore"] = 0, ["sulfur.ore"] = 0, ["hq.metal.ore"] = 0, ["scrap"] = 0,
}
;
public int AllGathered = 0;
}
internal class Weapon {
public Dictionary<string, WeaponInfo> WeaponUsed = new Dictionary<string, WeaponInfo>();
internal class WeaponInfo {
public int Kills = 0;
public int Headshots = 0;
public int Shots = 0;
}
}
internal class PVP {
public int Kills = 0;
public int KillsNpc = 0;
public int Deaths = 0;
public int Suicides = 0;
public int Shots = 0;
public int Headshots = 0;
public int HeliKill = 0;
public int BradleyKill = 0;
}
public static void AddPlayedTime(ulong id) {
var player = PlayerStat.Players.ContainsKey(id) ? PlayerStat.Players[id] : null;
if (player == null) return;
player.playedTime.PlayedToday++;
player.playedTime.PlayedForWipe++;
player.Score += _.config.settingsScore.TimeScore;
if (player.playedTime.DayNumber != DateTime.Now.ToShortDateString()) {
player.playedTime.PlayedToday = 0;
player.playedTime.DayNumber = DateTime.Now.ToShortDateString();
}
}
public static void PlayerClearData(ulong id) {
BasePlayer player = BasePlayer.FindByID(id);
PlayerStat.Players[id] = new PlayerInfo();
PlayerStat.Players[id].Name = player.displayName;
}
public static void ClearDataWipe() {
if (PlayerStat.IgnoreReservedPlayer != null) {
foreach (var item in PlayerStat.IgnoreReservedPlayer) _.NextTick(() => {
PlayerStat.IgnoreReservedPlayer[item.Key] = new PlayerInfo();
}
);
}
if (PlayerStat.Players != null) {
foreach (var item in PlayerStat.Players) {
if (item.Value.playedTime.PlayedForWipe <= 300) _.NextTick(() => {
PlayerStat.Players.Remove(item.Key);
}
);
else _.NextTick(() => {
PlayerStat.Players[item.Key] = new PlayerInfo();
}
);
}
}
}
public static PlayerInfo Find(ulong id) {
if (PlayerStat.Players.ContainsKey(id)) {
return PlayerStat.Players[id];
}
if (PlayerStat.IgnoreReservedPlayer.ContainsKey(id)) {
return PlayerStat.IgnoreReservedPlayer[id];
}
PlayerStat.Players.Add(id, new PlayerInfo());
if (PlayerStat.Players.ContainsKey(id)) {
return PlayerStat.Players[id];
}
return null;
}
}
private static StoredData PlayerStat;
private void LoadData() => PlayerStat = Interface.GetMod().DataFileSystem.ReadObject<StoredData>("XDStatistics/StatsUser");
private void SaveData() => Interface.GetMod().DataFileSystem.WriteObject("XDStatistics/StatsUser", PlayerStat);
#endregion
#region StatHooks
private void OnItemCraftFinished(ItemCraftTask task, Item item) {
PlayerInfo Player = PlayerInfo.Find(task.owner.userID);
Player.otherStat.AllCraft += item.amount;
Player.Score += config.settingsScore.craftScore;
}
private void OnEntityDeath(LootContainer entity, HitInfo info) {
if (entity == null || info == null) return;
BasePlayer player = info.InitiatorPlayer;
if (player == null) return;
if (entity.ShortPrefabName.Contains("barrel")) {
PlayerInfo Playerstat = PlayerInfo.Find(player.userID);
Playerstat.otherStat.BarrelDeath++;
Playerstat.Score += config.settingsScore.barrelScore;
}
}
private void OnEntityBuilt(Planner plan, GameObject go) {
BasePlayer player = plan?.GetOwnerPlayer();
if (player == null) return;
BaseEntity entity = go?.ToBaseEntity();
if (entity == null) return;
if (entity.PrefabName.Contains("building core")) {
PlayerInfo Playerstat = PlayerInfo.Find(player.userID);
Playerstat.otherStat.BuildingCrate++;
Playerstat.Score += config.settingsScore.BuildingScore;
}
}
private void OnExplosiveThrown(BasePlayer player, BaseEntity entity, ThrownWeapon item) {
if (player == null || item == null) return;
ExplosionProgressAdd(player, entity);
}
private void OnWeaponFired(BaseProjectile projectile, BasePlayer player) {
if (projectile == null || player == null) return;
ExplosionProgressAdd(player, null, projectile.primaryMagazine?.ammoType?.shortname);
}
private void OnRocketLaunched(BasePlayer player, BaseEntity entity) {
if (player == null || entity == null) return;
ExplosionProgressAdd(player, entity);
}
private void OnDispenserBonus(ResourceDispenser dispenser, BaseEntity entity, Item item) => OnDispenserGather(dispenser, entity, item);
private void OnDispenserGather(ResourceDispenser dispenser, BaseEntity entity, Item item) {
BasePlayer player = entity.ToPlayer();
if (player == null) return;
NextTick(() => {
ProgressAdd(player, item);
}
);
}
private void OnCollectiblePickup(Item item, BasePlayer player, CollectibleEntity entity) {
NextTick(() => {
if (AlowedSeedId.Contains(item.info.itemid)) {
PlayerInfo Playerstat = PlayerInfo.Find(player.userID);
if (!Playerstat.harvesting.HarvestingList.ContainsKey(item.info.shortname)) {
Playerstat.harvesting.HarvestingList.Add(item.info.shortname, item.amount);
}
else {
Playerstat.harvesting.HarvestingList[item.info.shortname] += item.amount;
}
Playerstat.harvesting.AllHarvesting += item.amount;
Playerstat.Score += config.settingsScore.PlantScore;
}
else ProgressAdd(player, item);
}
);
}
private void OnContainerDropItems(ItemContainer container) {
if (container == null) return;
BaseEntity entity = container.entityOwner;
if (entity == null) return;
if (!entity.ShortPrefabName.Contains("barrel")) return;
foreach (Item lootitem in container.itemList) {
if (lootitem.info.shortname == "scrap") lootitem.skin = 2352567;
}
}
void OnItemPickup(Item item, BasePlayer player) {
if (item == null || item.skin != 2352567) return;
item.skin = 0;
if (item.info.shortname == "scrap") ProgressAdd(player, item);
}
private static Dictionary<BasePlayer, List<UInt64>> LootersListCarte = new Dictionary<BasePlayer, List<UInt64>>();
private void OnLootEntity(BasePlayer player, LootContainer entity) {
if (entity == null || player == null || entity.OwnerID.IsSteamId() || entity.net == null) return;
if (!LootersListCarte.ContainsKey(player)) LootersListCarte.Add(player, new List<UInt64> {
}
);
UInt64 netId = entity.net.ID;
if (LootersListCarte[player].Contains(netId)) return;
PlayerInfo Playerstat = PlayerInfo.Find(player.userID);
Playerstat.otherStat.CrateOpen++;
foreach (var item in entity.inventory.itemList) {
if(item.info.shortname == "scrap") ProgressAdd(player, item);
}
LootersListCarte[player].Add(netId);
}
Dictionary<uint, ulong> _heliattacker = new Dictionary<uint, ulong>();
private void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
if (entity == null || info == null) return;
if (entity is BaseHelicopter && info.Initiator is BasePlayer) {
BasePlayer player = info.InitiatorPlayer;
if (player == null) return;
_heliattacker[entity.net.ID] = player.userID;
}
}
private void OnEntityDeath(BaseCombatEntity entity, HitInfo info) {
try {
if (entity == null || info == null) return;
BasePlayer player = null;
if (entity is BaseHelicopter) {
uint id = entity.net.ID;
if (!_heliattacker.ContainsKey(id)) return;
player = BasePlayer.FindByID(_heliattacker[id]);
if (player == null) return;
PlayerInfo Playerstat = PlayerInfo.Find(player.userID);
Playerstat.pVP.HeliKill++;
Playerstat.Score += config.settingsScore.HeliScore;
_heliattacker.Remove(id);
return;
}
if (info.InitiatorPlayer != null) player = info.InitiatorPlayer;
if (player == null || !player.userID.IsSteamId()) return;
PlayerInfo Playerstat2 = PlayerInfo.Find(player.userID);
if (entity is NPCPlayer) {
Playerstat2.pVP.KillsNpc++;
Playerstat2.Score += config.settingsScore.NpcScore;
if(config.settings.npsDeathUse) WeaponProgressAdd(Playerstat2, info, true);
return;
}
if (entity is BaseAnimalNPC) {
Playerstat2.otherStat.AnimalsKill++;
Playerstat2.Score += config.settingsScore.AnimalScore;
return;
}
if (entity is BradleyAPC) {
Playerstat2.pVP.BradleyKill++;
Playerstat2.Score += config.settingsScore.BradleyScore;
return;
}
}
catch (NullReferenceException ex) {
}
}
private object OnPlayerDeath(BasePlayer player, HitInfo hitInfo) {
if (player != null) {
if (hitInfo == null || !player.userID.IsSteamId()) return null;
PlayerInfo PlayerstatVic = PlayerInfo.Find(player.userID);
if (hitInfo.InitiatorPlayer != null) {
if (!hitInfo.InitiatorPlayer.userID.IsSteamId()) return null;
BasePlayer initiator = hitInfo.InitiatorPlayer;
if (IsFriends(initiator.userID, player.userID)) return null;
if (IsClans(initiator.UserIDString, player.UserIDString)) return null;
if (IsDuel(initiator.userID)) return null;
PlayerInfo PlayerstatInitiator = PlayerInfo.Find(initiator.userID);
if (hitInfo.damageTypes.GetMajorityDamageType() == DamageType.Suicide) {
PlayerstatVic.pVP.Suicides++;
PlayerstatVic.pVP.Deaths++;
PlayerstatVic.Score -= config.settingsScore.SuicideScore;
return null;
}
WeaponProgressAdd(PlayerstatInitiator, hitInfo, true);
PlayerstatInitiator.pVP.Kills++;
PlayerstatInitiator.pVP.Headshots += hitInfo.isHeadshot ? 1 : 0;
PlayerstatInitiator.Score += config.settingsScore.PlayerScore;
PlayerstatVic.pVP.Deaths++;
PlayerstatVic.Score -= config.settingsScore.DeathScore;
}
else {
if (hitInfo.damageTypes.GetMajorityDamageType() == DamageType.Suicide) return null;
PlayerstatVic.pVP.Deaths++;
PlayerstatVic.Score -= config.settingsScore.DeathScore;
}
}
return null;
}
private void OnPlayerAttack(BasePlayer attacker, HitInfo hitinfo) {
if (hitinfo == null || attacker == null || hitinfo.HitEntity == null || !attacker.IsConnected) return;
if (hitinfo.HitEntity is BaseNpc) return;
var victim = hitinfo.HitEntity as BasePlayer;
if (victim == null || !victim.userID.IsSteamId()) return;
if (victim == attacker) return;
PlayerInfo PlayerstatInitiator = PlayerInfo.Find(attacker.userID);
WeaponProgressAdd(PlayerstatInitiator, hitinfo);
PlayerstatInitiator.pVP.Shots++;
if (hitinfo.isHeadshot) PlayerstatInitiator.pVP.Headshots++;
}
void OnGrowableGathered(GrowableEntity plant, Item item, BasePlayer player) {
if (AlowedSeedId.Contains(item.info.itemid)) {
NextTick(() => {
PlayerInfo Playerstat = PlayerInfo.Find(player.userID);
if (!Playerstat.harvesting.HarvestingList.ContainsKey(item.info.shortname)) {
Playerstat.harvesting.HarvestingList.Add(item.info.shortname, item.amount);
}
else {
Playerstat.harvesting.HarvestingList[item.info.shortname] += item.amount;
}
Playerstat.harvesting.AllHarvesting += item.amount;
Playerstat.Score += config.settingsScore.PlantScore;
}
);
}
}
#endregion
#region BaseHooks
private void Unload() {
SaveData();
foreach (BasePlayer player in BasePlayer.activePlayerList) CuiHelper.DestroyUi(player, UI_INTERFACE);
ImageUi.Unload();
PlayerStat = null;
sb = null;
_ = null;
}
private void Init() {
_ = this;
sb = new StringBuilder();
LoadData();
}
private void OnNewSave() {
if (config.settingsPrize.prizeUse) {
ParseTopUserForPrize();
}
if (config.settings.wipeData) {
PlayerInfo.ClearDataWipe();
NextTick(() => {
SaveData();
}
);
PrintWarning(GetLang("STAT_PRINT_WIPE"));
}
}
priv
// ... [Code preview truncated due to length. Full source in attached file] ...