C#:
using Oxide.Core.Plugins;
using System.Collections.Generic;
using Oxide.Plugins.XDStatisticsExtensionMethods;
using Oxide.Game.Rust.Cui;
using System.Linq;
using Rust;
using Rust.Ai.Gen2;
using UnityEngine.Networking;
using System;
using UnityEngine;
using Facepunch;
using Oxide.Core;
using System.Collections;
using System.Text;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
using Oxide.Core.Libraries;
using UnityEngine.UI;
using Newtonsoft.Json.Linq;
namespace Oxide.Plugins {
[Info("XDStatistics", "DezLife", "3.2.4")]
[Description("Multifunctional statistics for your server!")]
class XDStatistics : RustPlugin {
private Dictionary<CatType, Dictionary<ulong, CashedData>> GetTopPlayersByAllCategories(List<CatType> catTypes = null) {
Dictionary<CatType, Dictionary<ulong, CashedData>> result = new();
CatType[] values = catTypes == null ? (CatType[]) Enum.GetValues(typeof(CatType)) : catTypes.ToArray();
if (PlayerInfo._players == null || PlayerInfo._players.Count == 0) return result;
foreach (CatType catType in values) {
Dictionary<ulong, CashedData> playerRatings = new();
foreach (KeyValuePair<ulong, PlayerInfo> player in PlayerInfo._players) {
if(player.Value.IsIgnore || ignoreReservedPlayer.Contains(player.Key) || _config.settings.ignoreList.Contains(player.Key)) continue;
CashedData data = catType switch {
CatType.Score => new CashedData(0, player.Value.Name, player.Value.Score), CatType.Killer => new CashedData(player.Value.PlayerPvpStats.Kills, player.Value.Name), CatType.PlayedTime => new CashedData(player.Value.playedTime.PlayedForWipe, player.Value.Name), CatType.Gather => new CashedData(player.Value.TotalResourcesGathered, player.Value.Name), CatType.Explosive => new CashedData(player.Value.TotalExplosivesUsed, player.Value.Name), CatType.KillerNpc => new CashedData(player.Value.PlayerPvpStats.KillsNpc, player.Value.Name), CatType.KillerAnimal => new CashedData(player.Value.PlayerPvpStats.KillsAnimal, player.Value.Name), CatType.Builder => new CashedData(player.Value.MiscStats.BuildingsPlaced, player.Value.Name), CatType.Fermer => new CashedData(player.Value.TotalCropsGrown, player.Value.Name), _ => throw new ArgumentOutOfRangeException()
}
;
playerRatings.Add(player.Key, data);
}
Dictionary<ulong, CashedData> sortedPlayers = playerRatings.OrderByDescending(p => p.Value.FullValue()).Take(15).ToDictionary(p => p.Key, p => p.Value);
result.Add(catType, sortedPlayers);
}
return result;
}
private void CloseLayer(BasePlayer player) {
CuiHelper.DestroyUi(player, UI_USER_STAT);
CuiHelper.DestroyUi(player, UI_SEARCH_USER);
CuiHelper.DestroyUi(player, UI_TOP_TEN_USER);
}
private void OnEntityDeath(BaseAnimalNPC entity, HitInfo info) {
if (entity == null || info == null) return;
BasePlayer player = info.InitiatorPlayer;
if (player != null && player.IsPlayer()) {
PlayerInfo playerstat = PlayerInfo.GetOrCreate(player.userID);
playerstat.UpdatePvpStats(builder => builder.WithKillsAnimal(), score : Instance._config.settingsScore.AnimalScore);
}
}
private void UpdateTopCash() => cashedTopUser = GetTopPlayersByAllCategories();
private Dictionary<uint, string> _prefabID2Item = new();
private void DiscordPrintTopFive() {
(string, string) data = GetRandomTopPlayer(_config.discordMessage._discordCategories);
if (!string.IsNullOrWhiteSpace(data.Item1) && !string.IsNullOrWhiteSpace(data.Item2)) SendDiscordMessage(CleanUpString(lang.GetMessage(data.Item1, this)), new List<string> {
data.Item2
}
, false);
timer.Once(_config.discordMessage.discordSendTopTime, DiscordPrintTopFive);
}
private JObject API_GetPlayerPlayedTime(ulong id) => JObject.FromObject(PlayerInfo.Get(id)?.playedTime);
private Dictionary<string, int> GetCategory(PlayerInfo statInfo, int cat) {
Dictionary<string, int> result = new();
switch (cat) {
case 0 : List<KeyValuePair<string, int>> resourceGathering = statInfo.ResourceGatheringStats.ToList();
resourceGathering.Sort((a, b) => b.Value.CompareTo(a.Value));
AddItems(resourceGathering, 8);
result.Add("all", statInfo.TotalResourcesGathered);
break;
case 1 : AddItems(statInfo.ExplosiveUsageStats.ToList(), 8);
result.Add("all", statInfo.TotalExplosivesUsed);
break;
case 2 : List<KeyValuePair<string, int>> orderedHarvesting = statInfo.CropGrowthStats.ToList();
orderedHarvesting.Sort((a, b) => b.Value.CompareTo(a.Value));
AddItems(orderedHarvesting, 9);
result.Add("all", statInfo.TotalCropsGrown);
break;
default : return null;
}
return result;
void AddItems(IReadOnlyList<KeyValuePair<string, int>> source, int count) {
for (int i = 0; i < Math.Min(count, source.Count);
i++) {
if (_config.settingsScore.blackListed.Contains(source[i].Key)) continue;
result.Add(source[i].Key, source[i].Value);
}
}
}
private enum CatType {
Score, Killer, KillerNpc, KillerAnimal, PlayedTime, Gather, Explosive, Builder, Fermer
}
private void OnDispenserGathered(ResourceDispenser dispenser, BasePlayer player, Item item) {
if (player == null || item == null) return;
PlayerInfo playerstat = PlayerInfo.GetOrCreate(player.userID);
playerstat.AddOrUpdateResource(item.info.shortname, item.amount);
}
private abstract class SplitDatafile<T> where T : SplitDatafile<T>, new() {
public static Dictionary<ulong, T> _players = new();
protected static string[] GetFiles(string baseFolder) {
try {
int json = ".json".Length;
string[] paths = Interface.Oxide.DataFileSystem.GetFiles(baseFolder, "*.json");
for (int i = 0; i < paths.Length; i++) {
string path = paths[i];
int separatorIndex = path.LastIndexOf("/", StringComparison.Ordinal);
paths[i] = path.Substring(separatorIndex + 1, path.Length - separatorIndex - 1 - json);
}
return paths;
}
catch {
return Array.Empty<string>();
}
}
protected static void Delete(string baseFolder, ulong userId) {
if (!_players.Remove(userId, out T _)) return;
try {
Interface.Oxide.DataFileSystem.DeleteDataFile(baseFolder + userId);
}
catch (Exception e) {
Interface.Oxide.LogError(e.ToString());
}
}
protected static T Save(string baseFolder, ulong userId) {
T data;
if (!_players.TryGetValue(userId, out data)) return null;
Interface.Oxide.DataFileSystem.WriteObject(baseFolder + userId, data);
return data;
}
protected static T Get(string baseFolder, ulong userId) {
T data;
if (_players.TryGetValue(userId, out data)) return data;
return null;
}
protected static T Load(string baseFolder, ulong userId) {
T data = null;
try {
data = Interface.Oxide.DataFileSystem.ReadObject<T>(baseFolder + userId);
}
catch (Exception e) {
Interface.Oxide.LogError(e.ToString());
}
return _players[userId] = data;
}
protected static T GetOrLoad(string baseFolder, ulong userId) {
T data;
if (_players.TryGetValue(userId, out data)) return data;
return Load(baseFolder, userId);
}
protected static T GetOrCreate(string baseFolder, ulong userId) {
return GetOrLoad(baseFolder, userId) ?? (_players[userId] = new T());
}
protected static T ClearAndSave(string baseFolder, ulong userId) {
if (_players.TryGetValue(userId, out T data)) {
data = new T();
_players[userId] = data;
Interface.Oxide.DataFileSystem.WriteObject(baseFolder + userId, data);
return data;
}
return null;
}
}
private void Init() {
Instance = this;
LoadDataIgnoreList();
LoadDataFiles();
LoadDataPrize();
}
private const bool RU = true;
private void OnWeaponFired(BaseProjectile projectile, BasePlayer player) {
if (projectile == null || player == null || !player.IsPlayer()) return;
if (projectile.primaryMagazine == null || projectile.primaryMagazine.ammoType == null) return;
PlayerInfo playerstat = PlayerInfo.GetOrCreate(player.userID);
playerstat.AddOrUpdateExplosive(null, projectile.primaryMagazine.ammoType.shortname);
}
private static class TimeHelper {
public static string FormatTime(TimeSpan time, int maxSubstr = 5, string language = "ru") {
return language == "ru" ? FormatTimeRussian(time, maxSubstr) : FormatTimeDefault(time);
}
private static string FormatTimeRussian(TimeSpan time, int maxSubstr) {
List<string> substrings = new List<string>();
if (time.Days != 0 && substrings.Count < maxSubstr) {
substrings.Add(Format(time.Days, "д"));
}
if (time.Hours != 0 && substrings.Count < maxSubstr) {
substrings.Add(Format(time.Hours, "ч"));
}
if (time.Minutes != 0 && substrings.Count < maxSubstr) {
substrings.Add(Format(time.Minutes, "м"));
}
if (time.Days == 0 && time.Seconds != 0 && substrings.Count < maxSubstr) {
substrings.Add(Format(time.Seconds, "с"));
}
if (substrings.Count == 0) {
substrings.Add("0с");
}
return string.Join(" ", substrings);
}
private static string FormatTimeDefault(TimeSpan time) {
List<string> parts = new List<string>();
if (time.Days > 0) {
parts.Add($"{time.Days} day{(time.Days == 1 ? string.Empty : "s")}");
}
if (time.Hours > 0) {
parts.Add($"{time.Hours} hour{(time.Hours == 1 ? string.Empty : "s")}");
}
if (time.Minutes > 0) {
parts.Add($"{time.Minutes} minute{(time.Minutes == 1 ? string.Empty : "s")}");
}
if (time.Seconds > 0) {
parts.Add($"{time.Seconds} second{(time.Seconds == 1 ? string.Empty : "s")}");
}
if (parts.Count == 0) {
parts.Add("0 seconds");
}
return string.Join(", ", parts);
}
private static string Format(int units, string form) {
return $"{units}{form}";
}
}
public static bool IsObjectNull(object obj) => ReferenceEquals(obj, null);
private int WipeTime;
protected override void SaveConfig() {
Config.WriteObject(_config);
}
private class FakePlayer {
[JsonProperty("userId")]
public string userId;
[JsonProperty("displayName")]
public string displayName;
public bool isMuted;
}
private int? API_GetGathered(ulong id, string shortname) {
Dictionary<string, int> data = API_GetGathered(id);
int amount;
if (data?.TryGetValue(shortname, out amount) == true) return amount;
return null;
}
private void OnCollectiblePickedup(CollectibleEntity collectible, BasePlayer player, Item item) {
if (player == null || collectible == null || item == null) return;
PlayerInfo playerstat = PlayerInfo.GetOrCreate(player.userID);
switch (item.info.category) {
case ItemCategory.Food when !item.info.shortname.Contains("seed") : playerstat.AddOrUpdateCrop(item.info.shortname, item.amount, _config.settingsScore.PlantScore);
break;
case ItemCategory.Food : break;
default : playerstat.AddOrUpdateResource(item.info.shortname, item.amount, true);
break;
}
}
private void ChatPrintTopFive() {
(string, string) data = GetRandomTopPlayer(_config.chatMessage._chatCategories);
if (!string.IsNullOrWhiteSpace(data.Item1) && !string.IsNullOrWhiteSpace(data.Item2)) foreach (BasePlayer item in BasePlayer.activePlayerList) item.ChatMessage(data.Item1.GetAdaptedMessage(item.UserIDString, data.Item2));
timer.Once(_config.chatMessage.chatSendTopTime, ChatPrintTopFive);
}
private void ParseTopUserForPrize() {
_prizePlayerData.Clear();
Dictionary<CatType, Dictionary<ulong, CashedData>> TopPlayers = GetTopPlayersByAllCategories(_config.settingsPrize.rewardsCategoryList);
foreach (KeyValuePair<CatType, Dictionary<ulong, CashedData>> topPlayer in TopPlayers) {
if (!_config.settingsPrize.PrizeByCategory.TryGetValue(topPlayer.Key.ToString(), out List<Configuration.SettingsPrize.Reward> rewards) || !rewards.Any()) continue;
foreach ((KeyValuePair<ulong, CashedData> player, int index) in topPlayer.Value.Select((value, index) => (value, index))) {
int top = index + 1;
Configuration.SettingsPrize.Reward reward = rewards.FirstOrDefault(x => x.top == top);
if (!_prizePlayerData.ContainsKey(player.Key)) {
_prizePlayerData[player.Key] = new List<PrizePlayer>();
}
_prizePlayerData[player.Key].Add(new PrizePlayer {
catType = topPlayer.Key, value = player.Value.FullValue(), top = top, isRewarded = !reward?.rewardOnConnected ?? false,
}
);
if (reward is {
rewardOnConnected : false
}
) reward.RewardPlayer(player.Key.ToString());
if (top >= rewards.Count) break;
}
}
SaveDataPrize();
if (_config.settings.wipeData) ClearData();
}
private void OnEntityBuilt(Planner plan, GameObject go) {
BasePlayer player = plan != null ? plan.GetOwnerPlayer() : null;
if (player == null) return;
BaseEntity entity = go != null ? go.ToBaseEntity() : null;
if (entity == null) return;
BuildingBlock bBlock = entity as BuildingBlock;
NextTick(() => {
if (bBlock == null || bBlock.IsDestroyed) return;
PlayerInfo playerstat = PlayerInfo.GetOrCreate(player.userID);
playerstat.IncrementBuildingsPlaced(score : _config.settingsScore.BuildingScore);
}
);
}
private void OnEntityDeath(BradleyAPC entity, HitInfo info) {
if (entity == null || info == null) return;
BasePlayer player = info.InitiatorPlayer;
if (player != null && player.IsPlayer()) {
PlayerInfo playerstat = PlayerInfo.GetOrCreate(player.userID);
playerstat.UpdatePvpStats(builder => builder.WithBradleyKill(), score : Instance._config.settingsScore.BradleyScore);
}
}
private void OnServerInitializedEx() {
timer.Once(60f, CheckInMinute);
if (_config.chatMessage.chatSendTop && _config.chatMessage._chatCategories.Count > 0) timer.Once(_config.chatMessage.chatSendTopTime, ChatPrintTopFive);
if (_config.discordMessage.discordTopFiveUse && _config.discordMessage._discordCategories.Count > 0 && !string.IsNullOrEmpty(_config.discordMessage.weebHook)) timer.Once(_config.discordMessage.discordSendTopTime, DiscordPrintTopFive);
timer.Every(3 * 60, UpdateTopCash);
timer.Every(_config.settings.dataSaveTime * 60, () => {
SaveDataFiles();
SaveDataIgnoreList();
SaveDataPrize();
}
);
UpdateTopCash();
}
private bool IsFriends(ulong userID, ulong targetID) {
if (Friends is not null) return Friends.Call("HasFriend", userID, targetID) is true;
return RelationshipManager.ServerInstance.playerToTeam.TryGetValue(userID, out RelationshipManager.PlayerTeam team) && team.members.Contains(targetID);
}
private void UserStat(BasePlayer player, ulong target = 0) {
ulong userid = target == 0 ? player.userID : target;
PlayerInfo statInfo = PlayerInfo.GetOrCreate(userid);
string color = BasePlayer.FindByID(userid) != null ? "0.55 0.78 0.24 1" : "0.8 0.28 0.2 1";
int kills = _config.settings.pveServerMode ? statInfo.PlayerPvpStats.KillsNpc : statInfo.PlayerPvpStats.Kills;
string titleKills = _config.settings.pveServerMode ? "STAT_UI_PVP_KILLS_NPC".GetAdaptedMessage(player.UserIDString) : "STAT_UI_PVP_KILLS".GetAdaptedMessage(player.UserIDString);
string pageTitle = "<color=white>" + statInfo.Name + "</color>";
var container = new CuiElementContainer();
container.Add(new CuiPanel {
CursorEnabled = false, Image = {
Color = "0 0 0 0"
}
, RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-400.254 -331.554", OffsetMax = "393.974 274.446"
}
}
, UI_INTERFACE, UI_USER_STAT);
container.Add(new CuiPanel {
CursorEnabled = false, Image = {
Color = "0 0 0 0"
}
, RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1"
}
}
, UI_USER_STAT, UI_USER_STAT_INFO);
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0 1", AnchorMax = "0 1", OffsetMin = "14.908 -69.438", OffsetMax = "227.492 -53.162"
}
, Text = {
Text = "STAT_UI_INFO".GetAdaptedMessage(player.UserIDString, pageTitle), Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.MiddleLeft, Color = "1 1 1 1"
}
}
, UI_USER_STAT_INFO, "INFO_USER_NICK");
container.Add(new CuiElement {
Name = "USER_AVATAR_LAYER", Parent = UI_USER_STAT_INFO, Components = {
new CuiRawImageComponent {
Color = color, Png = _imageUI.GetImage("2")
}
, new CuiRectTransformComponent {
AnchorMin = "0 1", AnchorMax = "0 1", OffsetMin = "15 -130", OffsetMax = "68 -77"
}
}
}
);
container.Add(new CuiElement {
Name = "AVATAR_ON_STEAM", Parent = "USER_AVATAR_LAYER", Components = {
new CuiRawImageComponent {
SteamId = target == 0 ? player.UserIDString : target.ToString(), Color = "1 1 1 1"
}
, new CuiRectTransformComponent {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-25 -25", OffsetMax = "25 25"
}
}
}
);
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0 1", AnchorMax = "0 1", OffsetMin = "15.477 -179.883", OffsetMax = "87.323 -161.717"
}
, Text = {
Text = "STAT_UI_ACTIVITY".GetAdaptedMessage(player.UserIDString), Font = "robotocondensed-regular.ttf", FontSize = 11, Align = TextAnchor.MiddleLeft, Color = "1 1 1 1"
}
}
, UI_USER_STAT_INFO, "USER_ACTIVE");
if (target == 0 && (_config.settings.availabilityUse && (permission.UserHasPermission(player.UserIDString, PermAvailability) || _config.settings.dropStatUse && permission.UserHasPermission(player.UserIDString, PermReset)))) {
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0 1", AnchorMax = "0 1", OffsetMin = "15.477 -290.083", OffsetMax = "87.323 -271.917"
}
, Text = {
Text = "STAT_UI_SETTINGS".GetAdaptedMessage(player.UserIDString), Font = "robotocondensed-regular.ttf", FontSize = 11, Align = TextAnchor.MiddleLeft, Color = "1 1 1 1"
}
}
, UI_USER_STAT_INFO, "USER_SETINGS");
}
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0 1", AnchorMax = "0 1", OffsetMin = "14.8 -151.281", OffsetMax = "227.38 -134.319"
}
, Text = {
Text = "STAT_UI_PLACE_TOP".GetAdaptedMessage(player.UserIDString, GetTopScore(target == 0 ? player.userID : target)), Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.MiddleLeft, Color = "0.8538514 0.8491456 0.8867924 1"
}
}
, UI_USER_STAT_INFO, "TOP_IN_USER");
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0 1", AnchorMax = "0 1", OffsetMin = "14.69 -201.181", OffsetMax = "227.27 -184.219"
}
, Text = {
Text = "STAT_UI_ACTIVITY_TODAY".GetAdaptedMessage(player.UserIDString, TimeHelper.FormatTime(TimeSpan.FromMinutes(statInfo.playedTime.PlayedToday), 5, lang.GetLanguage(player.UserIDString))), Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.MiddleLeft, Color = "0.8538514 0.8491456 0.8867924 1"
}
}
, UI_USER_STAT_INFO, "TODAY_ACTIVE_USER");
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-382.31 79.219", OffsetMax = "-169.73 96.181"
}
, Text = {
Text = "STAT_UI_ACTIVITY_TOTAL".GetAdaptedMessage(player.UserIDString, TimeHelper.FormatTime(TimeSpan.FromMinutes(statInfo.playedTime.PlayedForWipe), 5, lang.GetLanguage(player.UserIDString))), Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.MiddleLeft, Color = "0.8538514 0.8491456 0.8867924 1"
}
}
, UI_USER_STAT_INFO, "ALLTIME_ACTIVE_USER");
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-382.31 56.919", OffsetMax = "-169.73 73.881"
}
, Text = {
Text = "STAT_UI_SCORE".GetAdaptedMessage(player.UserIDString, statInfo.ScoreFormatted()), Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.MiddleLeft, Color = "0.8538514 0.8491456 0.8867924 1"
}
}
, UI_USER_STAT_INFO, "SCORE_USER");
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "1 1", AnchorMax = "1 1", OffsetMin = "-209.5 -67.825", OffsetMax = "-130.043 -53.66"
}
, Text = {
Text = "STAT_UI_PVP".GetAdaptedMessage(player.UserIDString), Font = "robotocondensed-regular.ttf", FontSize = 11, Align = TextAnchor.MiddleLeft, Color = "1 1 1 1"
}
}
, UI_USER_STAT_INFO, "PVP_STAT_USER");
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "1 0.5", AnchorMax = "1 0.5", OffsetMin = "-209.505 36.618", OffsetMax = "-13.975 50.782"
}
, Text = {
Text = "STAT_UI_FAVORITE_WEAPON".GetAdaptedMessage(player.UserIDString), Font = "robotocondensed-regular.ttf", FontSize = 11, Align = TextAnchor.MiddleLeft, Color = "1 1 1 1"
}
}
, UI_USER_STAT_INFO, "RIFLE_FAVORITE_USER");
container.Add(new CuiElement {
Name = "KILL_STAT_PLAYER", Parent = UI_USER_STAT_INFO, Components = {
new CuiImageComponent() {
Color = "0.968627453 0.921631568632 0.882352948 0.03529412", Material = "assets/content/ui/namefontmaterial.mat", ImageType = Image.Type.Tiled
}
, new CuiRectTransformComponent {
AnchorMin = "1 1", AnchorMax = "1 1", OffsetMin = "-209.389 -123.243", OffsetMax = "-14.469 -78.4"
}
}
}
);
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0 0.5", AnchorMax = "0 0.5", OffsetMin = "19 -7.014", OffsetMax = "97 8.414"
}
, Text = {
Text = titleKills, Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.MiddleLeft, Color = "1 1 1 1"
}
}
, "KILL_STAT_PLAYER", "LABEL_KILL_AMOUNT");
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "1 0.5", AnchorMax = "1 0.5", OffsetMin = "-98 -7.014", OffsetMax = "-16.845 8.414"
}
, Text = {
Text = kills.ToString(), Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.MiddleRight, Color = "0.8538514 0.8491456 0.8867924 1"
}
}
, "KILL_STAT_PLAYER", "LABEL_KILL_AMOUNTTWO");
container.Add(new CuiElement {
Name = "KILLSHOT_STAT_PLAYER", Parent = UI_USER_STAT_INFO, Components = {
new CuiImageComponent() {
Color = "0.968627453 0.921631568632 0.882352948 0.03529412", Material = "assets/content/ui/namefontmaterial.mat", ImageType = Image.Type.Tiled
}
, new CuiRectTransformComponent {
AnchorMin = "1 1", AnchorMax = "1 1", OffsetMin = "-209.389 -173.691", OffsetMax = "-14.469 -128.849"
}
}
}
);
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0 0.5", AnchorMax = "0 0.5", OffsetMin = "19 -7.014", OffsetMax = "97 8.414"
}
, Text = {
Text = "STAT_UI_PVP_DEATH".GetAdaptedMessage(player.UserIDString), Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.MiddleLeft, Color = "1 1 1 1"
}
}
, "KILLSHOT_STAT_PLAYER", "LABEL_KILL_AMOUNT");
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "1 0.5", AnchorMax = "1 0.5", OffsetMin = "-98 -7.014", OffsetMax = "-16.845 8.414"
}
, Text = {
Text = statInfo.PlayerPvpStats.Deaths.ToString(), Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.MiddleRight, Color = "0.8538514 0.8491456 0.8867924 1"
}
}
, "KILLSHOT_STAT_PLAYER", "LABEL_KILL_AMOUNTTWO");
container.Add(new CuiElement {
Name = "DEATCH_STAT_PLAYER", Parent = UI_USER_STAT_INFO, Components = {
new CuiImageComponent() {
Color = "0.968627453 0.921631568632 0.882352948 0.03529412", Material = "assets/content/ui/namefontmaterial.mat", ImageType = Image.Type.Tiled
}
, new CuiRectTransformComponent {
AnchorMin = "1 1", AnchorMax = "1 1", OffsetMin = "-209.39 -224.721", OffsetMax = "-14.47 -179.879"
}
}
}
);
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0 0.5", AnchorMax = "0 0.5", OffsetMin = "19 -7.014", OffsetMax = "97 8.414"
}
, Text = {
Text = "STAT_UI_PVP_KDR".GetAdaptedMessage(player.UserIDString), Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.MiddleLeft, Color = "1 1 1 1"
}
}
, "DEATCH_STAT_PLAYER", "LABEL_KILL_AMOUNT");
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "1 0.5", AnchorMax = "1 0.5", OffsetMin = "-98 -7.014", OffsetMax = "-16.845 8.414"
}
, Text = {
Text = statInfo.PlayerPvpStats.CalculateKDR(kills), Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.MiddleRight, Color = "0.8538514 0.8491456 0.8867924 1"
}
}
, "DEATCH_STAT_PLAYER", "LABEL_KILL_AMOUNTTWO");
container.Add(new CuiElement {
Name = "FAVORITE_WEAPON_STAT_PLAYER", Parent = UI_USER_STAT_INFO, Components = {
new CuiImageComponent() {
Color = "0.968627453 0.921631568632 0.882352948 0.03529412", Material = "assets/content/ui/namefontmaterial.mat", ImageType = Image.Type.Tiled
}
, new CuiRectTransformComponent {
AnchorMin = "1 1", AnchorMax = "1 1", OffsetMin = "-210.15 -324.607", OffsetMax = "-13.977 -278.569"
}
}
}
);
KeyValuePair<string, PlayerInfo.WeaponInfo> weaponTop = statInfo.WeaponUsed.OrderByDescending(x => x.Value.Kills).Take(1).FirstOrDefault();
if (weaponTop.Key != null) {
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0 0.5", AnchorMax = "0 0.5", OffsetMin = "46.321 -16.5", OffsetMax = "176.509 16.5"
}
, Text = {
Text = "STAT_UI_FAVORITE_WEAPON_KILLS".GetAdaptedMessage(player.UserIDString, weaponTop.Value.Kills, weaponTop.Value.Shots), Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1"
}
}
, "FAVORITE_WEAPON_STAT_PLAYER", "LABEL_KILL_AMOUNT");
container.Add(new CuiElement {
Name = "WEAPON_IMG_USER", Parent = "FAVORITE_WEAPON_STAT_PLAYER", Components = {
new CuiImageComponent {
ItemId = ItemManager.FindItemDefinition(weaponTop.Key).itemid,
}
, new CuiRectTransformComponent {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-88.5 -16.5", OffsetMax = "-55.5 16.5"
}
}
}
);
}
else {
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1"
}
, Text = {
Text = "STAT_UI_FAVORITE_WEAPON_NOT_DATA".GetAdaptedMessage(player.UserIDString), Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1"
}
}
, "FAVORITE_WEAPON_STAT_PLAYER", "LABEL_KILL_AMOUNT");
}
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "1 0.5", AnchorMax = "1 0.5", OffsetMin = "-209.498 -63.383", OffsetMax = "-79.669 -49.219"
}
, Text = {
Text = "STAT_UI_OTHER_STAT".GetAdaptedMessage(player.UserIDString), Font = "robotocondensed-regular.ttf", FontSize = 11, Align = TextAnchor.MiddleLeft, Color = "1 1 1 1"
}
}
, UI_USER_STAT_INFO, "OTHER_STAT_LABEL");
CloseLayer(player);
CuiHelper.DestroyUi(player, "USER_STAT");
CuiHelper.AddUi(player, container);
CategoryStatUser(player, target);
OtherStatUser(player, target);
if (target == 0) {
if (_config.settings.dropStatUse && permission.UserHasPermission(player.UserIDString, PermReset)) ButtonDropStat(player, statInfo);
if (_config.settings.availabilityUse && permission.UserHasPermission(player.UserIDString, PermAvailability)) ButtonHideStat(player, statInfo);
}
}
public const string UI_SEARCH_USER = "SEARCH_USER";
private void UpdatePlayerStats(ulong playerId) {
PlayerInfo playerstat = PlayerInfo.GetOrCreate(playerId);
playerstat.UpdatePvpStats(builder => builder.WithHeliKill(), Instance._config.settingsScore.HeliScore);
}
private JObject API_GetAllPlayerStat(ulong id) => JObject.FromObject(PlayerInfo.Get(id));
private void SendMsgRewardWipe(BasePlayer player) {
if (!_prizePlayerData.TryGetValue(player.userID, out List<PrizePlayer> playerGrant)) return;
const string langKey = "STAT_TOP_PLAYER_WIPE_";
foreach (PrizePlayer item in playerGrant) {
string categoryKey = item.catType.ToString();
if (_config.settingsPrize.PrizeByCategory.TryGetValue(categoryKey, out List<Configuration.SettingsPrize.Reward> rewards)) {
Configuration.SettingsPrize.Reward reward = rewards.FirstOrDefault(r => r.top == item.top);
if (reward != null) {
if(!item.isRewarded) reward.RewardPlayer(player.UserIDString);
string message = $"{langKey + item.catType}".GetAdaptedMessage(player.UserIDString, item.top) + "\n" + reward.entryRewardMessage;
player.ChatMessage(message);
}
}
}
NextTick(() => {
_prizePlayerData.Remove(player.userID);
SaveDataPrize();
}
);
}
private void CategoryStatUser(BasePlayer player, ulong target = 0, int cat = 0) {
var container = new CuiElementContainer();
PlayerInfo statInfo = PlayerInfo.GetOrCreate(target == 0 ? player.userID : target);
Dictionary<string, int> list = GetCategory(statInfo, cat);
container.Add(new CuiPanel {
CursorEnabled = false, Image = {
Color = "0.5803922 0.572549 0.6117647 0.4313726"
}
, RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = $"151.69 {181.046 - ((list.Count - 1) * 50.729)}", OffsetMax = $"153.21 225.49"
}
}
, UI_USER_STAT_INFO, "STAT_LINE");
container.Add(new CuiPanel {
CursorEnabled = false, Image = {
Color = "0.5803922 0.572549 0.6117647 1"
}
, RectTransform = {
AnchorMin = "0.5 1", AnchorMax = "0.5 1", OffsetMin = $"-0.761 {-23.343 - ((list.Count - 1) * 30.729)}", OffsetMax = "0.761 0.17"
}
}
, "STAT_LINE", "STAT_LINE_CHILD");
container.Add(new CuiPanel {
CursorEnabled = false, Image = {
Color = "0 0 0 0"
}
, RectTransform = {
AnchorMin = "0.5 1", AnchorMax = "0.5 1", OffsetMin = "-146.988 -71.4", OffsetMax = "146.388 -53.16"
}
}
, UI_USER_STAT_INFO, "MENU_USER_STAT");
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0 0.5", AnchorMax = "0 0.5", OffsetMin = "0.312 -9.12", OffsetMax = "84.704 9.121"
}
, Button = {
Command = $"UI_HandlerStat changeCategory {target} 0", Color = "0 0 0 0"
}
, Text = {
Text = "STAT_UI_CATEGORY_GATHER".GetAdaptedMessage(player.UserIDString), Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.MiddleCenter,
}
}
, "MENU_USER_STAT", "Panel_5655");
container.Add(new CuiPanel {
CursorEnabled = false, Image = {
Color = cat == 0 ? "0.2988604 0.6886792 0.120194 0.6431373" : "0 0 0 0"
}
, RectTransform = {
AnchorMin = "0.5 0", AnchorMax = "0.5 0", OffsetMin = "-42.347 0", OffsetMax = "42.196 1.871"
}
}
, "Panel_5655", "Panel_8052");
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-61.983 -9.121", OffsetMax = "31.232 9.12"
}
, Button = {
Command = $"UI_HandlerStat changeCategory {target} 1", Color = "0 0 0 0"
}
, Text = {
Text = "STAT_UI_CATEGORY_EXPLOSED".GetAdaptedMessage(player.UserIDString), Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.MiddleCenter,
}
}
, "MENU_USER_STAT", "Panel_56551");
container.Add(new CuiPanel {
CursorEnabled = false, Image = {
Color = cat == 1 ? "0.2988604 0.6886792 0.120194 0.6431373" : "0 0 0 0"
}
, RectTransform = {
AnchorMin = "0.5 0", AnchorMax = "0.5 0", OffsetMin = "-46.608 0", OffsetMax = "46.608 1.871"
}
}
, "Panel_56551", "Panel_8052");
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "1 0.5", AnchorMax = "1 0.5", OffsetMin = "-115.459 -9.12", OffsetMax = "0.001 9.121"
}
, Button = {
Command = $"UI_HandlerStat changeCategory {target} 2", Color = "0 0 0 0"
}
, Text = {
Text = "STAT_UI_CATEGORY_PLANT".GetAdaptedMessage(player.UserIDString), Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.MiddleCenter,
}
}
, "MENU_USER_STAT", "Panel_56553");
container.Add(new CuiPanel {
CursorEnabled = false, Image = {
Color = cat == 2 ? "0.2988604 0.6886792 0.120194 0.6431373" : "0 0 0 0"
}
, RectTransform = {
AnchorMin = "0.5 0", AnchorMax = "0.5 0", OffsetMin = "-57.73 0", OffsetMax = "57.73 1.871"
}
}
, "Panel_56553", "Panel_8052");
container.Add(new CuiPanel {
CursorEnabled = false, Image = {
Color = "0 0 0 0"
}
, RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-146.991 -124.121", OffsetMax = "146.389 226.031"
}
}
, "USER_STAT_INFO", "MAIN_LIST_STAT_USER");
int y = 0;
string userLang = lang.GetLanguage(player.UserIDString);
foreach (KeyValuePair<string, int> item in list) {
float fade = 0.15f * y;
string itemName;
if (_itemName.ContainsKey(item.Key)) itemName = userLang == "ru" ? _itemName[item.Key].RUdisplayName : _itemName[item.Key].ENdisplayName;
else {
itemName = "";
ItemDefinition itemDefinition = ItemManager.FindItemDefinition(item.Key);
if (itemDefinition != null && itemDefinition.displayName is {
english : not null
}
) {
itemName = itemDefinition.displayName.english;
}
}
container.Add(new CuiPanel {
FadeOut = 0.30f, RectTransform = {
AnchorMin = "0.5 1", AnchorMax = "0.5 1", OffsetMin = $"-146.118 {-44.977 - (y * 50.729)}", OffsetMax = $"146.692 {-0.765 - (y * 50.729)}"
}
, Image = {
Color = "0.968627453 0.921631568632 0.882352948 0.03529412", Material = "assets/content/ui/namefontmaterial.mat", FadeIn = fade
}
,
}
, "MAIN_LIST_STAT_USER", "STAT_USER_LINE");
string name = cat == 0 ? item.Value.ToFormattedString() : item.Value.ToString();
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "26.03 -10.534", OffsetMax = "126.03 12.574"
}
, Text = {
Text = name, Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.MiddleRight, Color = "0.8538514 0.8491456 0.8867924 1", FadeIn = fade
}
}
, "STAT_USER_LINE", "STAT_USER_AMOUNT");
if (item.Key == "all") {
string langGet = cat switch {
0 => "STAT_USER_TOTAL_GATHERED", 1 => "STAT_USER_TOTAL_EXPLODED", _ => "STAT_USER_TOTAL_GROWED"
}
;
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-128 -10.534", OffsetMax = "50 12.574"
}
, Text = {
Text = langGet.GetAdaptedMessage(player.UserIDString), Font = "robotocondensed-regular.ttf", FontSize = 11, Align = TextAnchor.MiddleLeft, Color = "1 1 1 1", FadeIn = fade
}
}
, "STAT_USER_LINE", "ALL_TOTAL");
}
else {
container.Add(new CuiElement {
Name = "IMAGE_ITEM", Parent = "STAT_USER_LINE", Components = {
new CuiImageComponent {
ItemId = ItemManager.FindItemDefinition(item.Key).itemid, FadeIn = fade
}
, new CuiRectTransformComponent {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-128 -17.5", OffsetMax = "-93 17.5"
}
}
}
);
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-73.17 -10.534", OffsetMax = "50 12.574"
}
, Text = {
Text = itemName, Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.MiddleLeft, Color = "0.8538514 0.8491456 0.8867924 1" , FadeIn = fade
}
}
, "STAT_USER_LINE");
}
y++;
}
CuiHelper.DestroyUi(player, "MENU_USER_STAT");
CuiHelper.DestroyUi(player, "MAIN_LIST_STAT_USER");
CuiHelper.DestroyUi(player, "STAT_LINE");
CuiHelper.AddUi(player, container);
}
private void ButtonDropStat(BasePlayer player, PlayerInfo info) {
var container = new CuiElementContainer();
container.Add(new CuiPanel {
CursorEnabled = false, Image = {
Color = "0 0 0 0"
}
, RectTransform = {
AnchorMin = "0 0.5", AnchorMax = "0 0.5", OffsetMin = "13.75 -29.559", OffsetMax = "160.23 -15.727"
}
}
, UI_USER_STAT_INFO, "BUTTON_REFRESH_STAT");
container.Add(new CuiElement {
Name = "USER_REFRESH_STAT", Parent = "BUTTON_REFRESH_STAT", Components = {
new CuiImageComponent {
Color = "1 1 1 1", Sprite = "assets/icons/clear_list.png"
}
, new CuiRectTransformComponent {
AnchorMin = "0 0.5", AnchorMax = "0 0.5", OffsetMin = "1.74 -6.5", OffsetMax = "14.74 6.5"
}
}
}
);
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "1 0.5", AnchorMax = "1 0.5", OffsetMin = "-120.55 -6.916", OffsetMax = "21.75 8.202"
}
, Text = {
Text = "STAT_UI_RESET_STAT".GetAdaptedMessage(player.UserIDString), Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.MiddleLeft, Color = "0.8538514 0.8491456 0.8867924 1"
}
}
, "BUTTON_REFRESH_STAT", "LABEL_REFRESH_USER");
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1"
}
, Button = {
Command = "UI_HandlerStat confirm", Color = "0 0 0 0"
}
, Text = {
// ... [Code preview truncated due to length. Full source in attached file] ...