using System; using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Linq; using Newtonsoft.Json; using Oxide.Core; using Oxide.Core.Plugins; using Oxide.Game.Rust.Cui; using UnityEngine; namespace Oxide.Plugins { [Info("TeamInfo", "AhigaO#4485", "1.2.1")] internal class TeamInfo : RustPlugin { #region Static private const string Layer = "UI_TeamInfo"; private Configuration _config; private Dictionary _data; private Dictionary> playersTeams = new Dictionary>(); private bool update; private float Size; private float Square; private string perm; #region Image [PluginReference] private Plugin ImageLibrary; private int ILCheck = 0; private Dictionary Images = new Dictionary(); private void AddImage(string url) { if (!ImageLibrary.Call("HasImage", url)) ImageLibrary.Call("AddImage", url, url); Images.Add(url, ImageLibrary.Call("GetImage", url)); } private string GetImage(string url) => Images[url]; private void LoadImages() => AddImage("https://i.imgur.com/23mB8WD.png"); #endregion #region Classes private class Configuration { [JsonProperty(PropertyName = "Offset from left angle")] public int offsetX = 5; [JsonProperty(PropertyName = "Offset from bottom")] public int offsetY = 350; [JsonProperty(PropertyName = "Enable visible player position")] public bool playerPosVisible = true; [JsonProperty(PropertyName = "If the figure in the player’s position is displayed not correctly change to True")] public bool playerPosNum = false; [JsonProperty(PropertyName = "Enable visible player item")] public bool playerItemVisible = true; [JsonProperty(PropertyName = "Method of displaying active items(true - ImageLibrary display items with skins(but have change to bug) | false - rust method display items without skins(always works))")] public bool useDefault = true; [JsonProperty(PropertyName = "Name permission")] public string permission = "teaminfo.use"; } #endregion #endregion #region Config protected override void LoadConfig() { base.LoadConfig(); try { _config = Config.ReadObject(); if (_config == null) throw new Exception(); SaveConfig(); } catch { PrintError("Your configuration file contains an error. Using default configuration values."); LoadDefaultConfig(); } } protected override void SaveConfig() => Config.WriteObject(_config); protected override void LoadDefaultConfig() => _config = new Configuration(); #endregion #region Data private void LoadData() => _data = Interface.Oxide.DataFileSystem.ExistsDatafile($"{Name}/data") ? Interface.Oxide.DataFileSystem.ReadObject>($"{Name}/data") : new Dictionary(); private void OnServerSave() => SaveData(); private void SaveData() { if (_data != null) Interface.Oxide.DataFileSystem.WriteObject($"{Name}/data", _data); } #endregion #region OxideHooks private void OnServerInitialized() { if (!ImageLibrary) { if (ILCheck == 3) { PrintError("ImageLibrary not found!Unloading"); Interface.Oxide.UnloadPlugin(Name); return; } timer.In(1, () => { ILCheck++; OnServerInitialized(); }); return; } LoadData(); LoadImages(); perm = _config.permission; if (!permission.PermissionExists(perm)) permission.RegisterPermission(perm, this); var size = ConVar.Server.worldsize; Size = size / 2f; Square = Mathf.Floor(size / 146.3f); foreach (var check in RelationshipManager.ServerInstance.teams) { var playerList = new List(); foreach (var checkTeamPlayer in check.Value.members) playerList.Add(BasePlayer.FindByID(checkTeamPlayer)); var team = check.Value; playersTeams.TryAdd(team, playerList); SortTeams(team); } update = true; foreach (var check in BasePlayer.activePlayerList) OnPlayerConnected(check); if (_config.playerPosVisible) ServerMgr.Instance.StartCoroutine(UpdateTime()); } private void Unload() { update = false; SaveData(); foreach (var check in BasePlayer.activePlayerList) CuiHelper.DestroyUi(check, Layer + ".bg"); } private void OnPlayerConnected(BasePlayer player) { if (player == null) return; _data.TryAdd(player.userID, true); if (!update) return; ShowUIMain(player.Team); } private void OnUserPermissionGranted(string id, string permName) { if (permName != perm || id == null || !update) return; ShowUIMain(BasePlayer.FindAwakeOrSleeping(id)?.Team); } private void OnUserPermissionRevoked(string id, string permName) { if (permName != perm || id == null || !update) return; CuiHelper.DestroyUi(BasePlayer.FindAwakeOrSleeping(id), Layer + ".bg"); } private void OnActiveItemChanged(BasePlayer player, Item oldItem, Item newItem) { if (player?.Team == null || !update) return; ShowUIItem(player.Team); } private void OnPlayerHealthChange(BasePlayer player, float oldValue, float newValue) { if (player?.Team == null || !update) return; ShowUIHPBar(player.Team); } private void OnPlayerDisconnected(BasePlayer player, string reason) { if (player?.Team == null || !update) return; CuiHelper.DestroyUi(player, Layer + ".bg"); timer.In(1, () => { ShowUIMain(player.Team); }); } private void OnTeamAcceptInvite(RelationshipManager.PlayerTeam team, BasePlayer player) { if (player?.Team == null || !update) return; playersTeams[team].Add(player); SortTeams(team); ShowUIMain(team); } private void OnTeamPromote(RelationshipManager.PlayerTeam team, BasePlayer newLeader) => NextTick(() => { if (team == null || !update) return; ShowUIMain(team); }); private void OnTeamLeave(RelationshipManager.PlayerTeam team, BasePlayer player) { if (player?.Team == null || !update) return; playersTeams[team].Remove(player); SortTeams(team); CuiHelper.DestroyUi(player, Layer + ".bg"); NextTick(() => { ShowUIMain(team); }); } private void OnPlayerSleepEnded(BasePlayer player) { if (player?.Team == null || !update) return; ShowUIMain(player.Team); } private void OnLoseCondition(Item item, ref float amount) { if (item?.GetOwnerPlayer()?.Team == null || !update) return; ShowUIItem(item.GetOwnerPlayer().Team); } private void OnPlayerDeath(BasePlayer player, HitInfo info) { if (player?.Team == null || !update) return; CuiHelper.DestroyUi(player, Layer + ".bg"); NextTick(() => { ShowUIMain(player.Team); }); } private void OnPlayerRecover(BasePlayer player) { if (player?.Team == null || !update) return; NextTick(() => { ShowUIHPBar(player.Team); }); } private void OnPlayerWound(BasePlayer player, HitInfo info) { if (player?.Team == null || !update) return; NextTick(() => { ShowUIHPBar(player.Team); }); } private void OnTeamCreate(BasePlayer player) { NextTick(() => { if (player == null) return; var playerTeam = player.Team; playersTeams.TryAdd(playerTeam, new List { player }); SortTeams(playerTeam); if (!update) return; ShowUIMain(playerTeam); }); } private void OnTeamDisband(RelationshipManager.PlayerTeam team) { if (team == null || !playersTeams.ContainsKey(team)) return; playersTeams.Remove(team); SortTeams(team); } #endregion #region Commands [ChatCommand("teaminfo")] private void cmdChat(BasePlayer player, string command, string[] args) { if (player?.Team == null || args.Length != 1) return; switch (args[0]) { case "open": update = true; _data[player.userID] = true; ShowUIMain(player.Team); break; case "close": CuiHelper.DestroyUi(player, Layer + ".bg"); _data[player.userID] = false; update = false; break; default: PrintWarning("Available commands: \n/teaminfo open\n/teaminfo close"); break; } } #endregion #region Functions private void SortTeams(RelationshipManager.PlayerTeam team) { var teamList = playersTeams[team]; var playerList = new List(); var leader = team.teamLeader; foreach (var check in teamList) if (check.userID == leader) playerList.Add(check); foreach (var check in teamList) if (check.userID != leader) playerList.Add(check); playersTeams[team] = playerList; } private bool GetPlayerData(BasePlayer player) { bool status; if (_data.TryGetValue(player.userID, out status)) return status; _data.Add(player.userID, true); return true; } private string GetCorrectName(string name, int length) { string res = name; if (name.Length > length) res = name.Substring(0, length); return res; } private string GetGrid(Vector3 pos) { var letter = 'A'; var xCoordinate = Mathf.Floor((pos.x + Size) / 146.3f); var z = Square - Mathf.Floor((pos.z + Size) / 146.3f) - (_config.playerPosNum ? 0 : 1); letter = (char)(letter + xCoordinate % 26); return xCoordinate > 25 ? $"A{letter}{z}" : $"{letter}{z}"; } private bool HasPermission(string id) => permission.UserHasPermission(id, perm); private IEnumerator UpdateTime() { while (update) { foreach (var check in BasePlayer.activePlayerList) ShowUIPos(check.Team); yield return new WaitForSeconds(5f); } } #endregion #region UI private void ShowUIPos(RelationshipManager.PlayerTeam team) { if (team == null) return; var container = new CuiElementContainer(); List playerList; playersTeams.TryGetValue(team, out playerList); if (playerList == null) return; var leader = team.teamLeader; var posY = 0; container.Add(new CuiPanel { RectTransform = { AnchorMin = "1 1", AnchorMax = "1 1", }, Image = { Color = "0 0 0 0.8" } }, Layer + ".bg", Layer + ".pos"); foreach (var check in playerList.OrderBy(x => leader == x.userID)) { container.Add(new CuiElement { Parent = Layer + ".pos", Components = { new CuiTextComponent { Text = GetGrid(check.transform.position), FontSize = 12, Font = "robotocondensed-regular.ttf", Color = "1 1 1 1", Align = TextAnchor.UpperRight }, new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = $"120 {posY}", OffsetMax = $"148 {posY + 26}" }, new CuiOutlineComponent { Color = "0 0 0 0.9", Distance = "-0.5 -0.5" } } }); posY += 28; } foreach (var check in playerList) { if (check == null || !GetPlayerData(check) || !HasPermission(check.UserIDString)) continue; CuiHelper.DestroyUi(check, Layer + ".pos"); CuiHelper.AddUi(check, container); } } private void ShowUIItem(RelationshipManager.PlayerTeam team) { if (!_config.playerItemVisible || team == null) return; var container = new CuiElementContainer(); List playerList; playersTeams.TryGetValue(team, out playerList); if (playerList == null) return; var leader = team.teamLeader; var posY = 0; container.Add(new CuiPanel { RectTransform = { AnchorMin = "1 1", AnchorMax = "1 1", }, Image = { Color = "0 0 0 0.8" } }, Layer + ".bg", Layer + ".item"); foreach (var check in playerList.OrderBy(x => leader == x.userID)) { var item = check.GetActiveItem(); if (item != null) { var weapon = item.GetHeldEntity()?.GetComponent(); container.Add(new CuiPanel { RectTransform = { AnchorMin = "0 0", AnchorMax = "0 0", OffsetMin = $"154 {posY}", OffsetMax = $"180 {posY + 26}" }, Image = { Color = "0 0 0 0.8" } }, Layer + ".item", Layer + posY + ".item"); if (_config.useDefault) container.Add(new CuiElement { Parent = Layer + posY + ".item", Components = { new CuiImageComponent { ItemId = item.info.itemid, SkinId = item.skin }, new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "2 2", OffsetMax = "-2 -2" } } }); else container.Add(new CuiElement { Parent = Layer + posY + ".item", Components = { new CuiRawImageComponent { Png = ImageLibrary.Call("GetImage", item.info.shortname, item.skin) }, new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "2 2", OffsetMax = "-2 -2" } } }); container.Add(new CuiPanel { RectTransform = { AnchorMin = "0 0", AnchorMax = $"0 {item.condition / item.maxCondition}", OffsetMin = "0 0", OffsetMax = "2 0" }, Image = { Color = "0 0.73 0 0.85" } }, Layer + posY + ".item"); container.Add(new CuiLabel { RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 -2" }, Text = { Text = weapon == null ? item.amount + "x" : weapon.primaryMagazine.contents.ToString(), FontSize = 8, Font = "robotocondensed-regular.ttf", Color = "1 1 1 1", Align = TextAnchor.LowerRight, } }, Layer + posY + ".item"); } posY += 28; } foreach (var check in playerList) { if (check == null || !GetPlayerData(check) || !HasPermission(check.UserIDString)) continue; CuiHelper.DestroyUi(check, Layer + ".item"); CuiHelper.AddUi(check, container); } } private void ShowUIHPBar(RelationshipManager.PlayerTeam team) { if (team == null) return; var container = new CuiElementContainer(); List playerList; playersTeams.TryGetValue(team, out playerList); if (playerList == null) return; var leader = team.teamLeader; var posY = 0; container.Add(new CuiPanel { RectTransform = { AnchorMin = "0 0", AnchorMax = "0 0", }, Image = { Color = "0 0 0 0.8" } }, Layer + ".bg", Layer + ".hpBar"); foreach (var check in playerList.OrderBy(x => leader == x.userID)) { if (check == null) continue; var curHp = Math.Ceiling(check.Health()); var maxHp = check.MaxHealth(); var isWounded = check.IsWounded(); var isDead = check.IsDead(); container.Add(new CuiPanel { RectTransform = { AnchorMin = "0 0", AnchorMax = "0 0", OffsetMin = $"28 {posY}", OffsetMax = $"149 {posY + 12}" }, Image = { Color = "0.25 0.25 0.25 0.85" } }, Layer + ".hpBar", Layer + posY + ".hpBar"); if (!isWounded && !isDead) { var newValue = (int)(curHp / maxHp * 121); var pendingHealth = check.metabolism.pending_health.value; container.Add(new CuiPanel { RectTransform = { AnchorMin = "0 0", AnchorMax = "0 1", OffsetMin = "0 0", OffsetMax = $"{newValue} 0" }, Image = { Color = $"{1 - curHp / maxHp - 0.27} {curHp / maxHp - 0.27} 0 1" } }, Layer + posY + ".hpBar"); if (pendingHealth > 0) container.Add(new CuiPanel { RectTransform = { AnchorMin = "0 0", AnchorMax = "0 1", OffsetMin = $"{newValue} 0", OffsetMax = $"{(pendingHealth + newValue > 121 ? 121 : pendingHealth + newValue)} 0" }, Image = { Color = "0 0.73 0 0.35" } }, Layer + posY + ".hpBar"); } container.Add(new CuiLabel { RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 -4", OffsetMax = "0 5" }, Text = { Text = isDead || curHp == 0 ? "DEAD" : isWounded ? "WOUNDED" : curHp.ToString(CultureInfo.InvariantCulture), FontSize = 13, Font = "robotocondensed-bold.ttf", Color = "1 1 1 1", Align = TextAnchor.MiddleCenter } }, Layer + posY + ".hpBar"); posY += 28; } foreach (var check in playerList) { if (check == null || !GetPlayerData(check) || !HasPermission(check.UserIDString)) continue; CuiHelper.DestroyUi(check, Layer + ".hpBar"); CuiHelper.AddUi(check, container); } } private void ShowUIMain(RelationshipManager.PlayerTeam team) { if (team == null) return; var container = new CuiElementContainer(); List playerList; playersTeams.TryGetValue(team, out playerList); if (playerList == null) return; var leader = team.teamLeader; var posY = 0; container.Add(new CuiPanel { RectTransform = { AnchorMin = "0.005 0.24", AnchorMax = "0.005 0.24", OffsetMin = $"{_config.offsetX} {_config.offsetY}", OffsetMax = $"{_config.offsetX} {_config.offsetY}" }, Image = { Color = "0 0 0 0" } }, "Under", Layer + ".bg"); foreach (var check in playerList.OrderBy(x => team.teamLeader == x.userID)) { if (check == null) continue; var isLeader = check.userID == leader; container.Add(new CuiPanel { RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = $"0 {posY}", OffsetMax = $"180 {posY + 26}" }, Image = { Color = "0.9686 0.9216 0.8824 0" } }, Layer + ".bg", Layer + posY); container.Add(new CuiElement { Parent = Layer + posY, Name = Layer + posY + ".avatar", Components = { new CuiRawImageComponent { Png = ImageLibrary.Call("GetImage", check.UserIDString) }, new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "0 1", OffsetMin = "0 0", OffsetMax = "26 0" } } }); if (isLeader) container.Add(new CuiElement { Parent = Layer + posY, Components = { new CuiRawImageComponent { Png = GetImage("https://i.imgur.com/23mB8WD.png") }, new CuiRectTransformComponent { AnchorMin = "0 1", AnchorMax = "0 1", OffsetMin = "28 -12", OffsetMax = "45 0" } } }); container.Add(new CuiElement { Parent = Layer + posY, Components = { new CuiTextComponent { Text = GetCorrectName(check.displayName, 20), FontSize = 12, Font = "robotocondensed-bold.ttf", Color = "1 1 1 1", Align = TextAnchor.UpperLeft }, new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = isLeader ? "46 0" : "28 0", OffsetMax = "0 0" }, new CuiOutlineComponent { Color = "0 0 0 0.9", Distance = "-0.5 -0.5" } } }); posY += 28; } foreach (var check in playerList) { if (check == null || !GetPlayerData(check) || !HasPermission(check.UserIDString)) continue; CuiHelper.DestroyUi(check, Layer + ".bg"); CuiHelper.AddUi(check, container); } ShowUIHPBar(team); ShowUIItem(team); ShowUIPos(team); } #endregion } }