C#:
//Requires: RustNET
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Game.Rust.Cui;
using Oxide.Core.Plugins;
using UnityEngine;
using System.Linq;
using Oxide.Core.Libraries.Covalence;
namespace Oxide.Plugins {
[Info("BountyNET", "k1lly0u", "0.1.8")]
[Description("A bounty system that can only be access via a RustNET terminal")]
class BountyNET : RustPlugin {
[PluginReference]
Plugin Clans, Friends, PopupNotifications, Economics, ServerRewards;
private static BountyNET ins;
private StoredData storedData;
private OfflinePlayers offlinePlayers;
private DynamicConfigFile data, offline;
private Dictionary<ulong, ulong> bountyCreator = new Dictionary<ulong, ulong>();
private Dictionary<StorageContainer, ulong> openContainers = new Dictionary<StorageContainer, ulong>();
private Dictionary<int, string> idToDisplayName = new Dictionary<int, string>();
private string boxPrefab = "assets/prefabs/deployable/woodenbox/woodbox_deployed.prefab";
private FriendManager friendManager;
#region Oxide Hooks
private void Loaded() {
permission.RegisterPermission("bountynet.use", this);
permission.RegisterPermission("bountynet.admin", this);
lang.RegisterMessages(messages, this);
friendManager = new GameObject("FriendManager").AddComponent<FriendManager>();
data = Interface.Oxide.DataFileSystem.GetFile("RustNET/bounty_data");
offline = Interface.Oxide.DataFileSystem.GetFile("RustNET/bounty_offlineplayers");
}
private void OnServerInitialized() {
ins = this;
idToDisplayName = ItemManager.itemList.ToDictionary(x => x.itemid, y => y.displayName.english);
LoadData();
offlinePlayers.RemoveOldPlayers();
RustNET.RegisterModule(Title, this);
RustNET.ins.AddImage(Title, configData.RustNETIcon);
foreach (BasePlayer player in BasePlayer.activePlayerList) OnPlayerInit(player);
}
private void OnPlayerInit(BasePlayer player) {
PlayerData playerData;
if (storedData.players.TryGetValue(player.userID, out playerData)) {
if (playerData.activeBounties.Count > 0) BroadcastToPlayer(player, string.Format(msg("Chat.OutstandingBounties", player.userID), playerData.activeBounties.Count));
playerData.displayName = player.displayName;
}
offlinePlayers.OnPlayerInit(player.UserIDString);
}
private void OnPlayerDisconnected(BasePlayer player) {
PlayerData playerData;
if (storedData.players.TryGetValue(player.userID, out playerData)) playerData.UpdateWantedTime();
offlinePlayers.AddOfflinePlayer(player.UserIDString);
}
private object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
if (entity == null || info == null) return null;
if (entity is StorageContainer && openContainers.ContainsKey(entity as StorageContainer)) return false;
return null;
}
private void OnEntityDeath(BaseCombatEntity entity, HitInfo info) {
if (entity == null || info == null) return;
BasePlayer victim = entity.ToPlayer();
BasePlayer attacker = info.InitiatorPlayer;
if (victim == null || attacker == null || attacker.GetComponent<NPCPlayer>()) return;
PlayerData victimData;
if (!storedData.players.TryGetValue(victim.userID, out victimData)) return;
if (victimData.activeBounties.Count == 0) return;
if (IsFriendlyPlayer(victim.userID, attacker.userID)) {
BroadcastToPlayer(attacker, msg("Chat.IsFriend1", attacker.userID));
return;
}
victimData.UpdateWantedTime();
List<int> rewards = victimData.activeBounties.Select(x => x.rewardId).ToList();
victimData.activeBounties.Clear();
PlayerData attackerData;
if (!storedData.players.TryGetValue(attacker.userID, out attackerData)) {
attackerData = new PlayerData(attacker.displayName);
storedData.players.Add(attacker.userID, attackerData);
}
attackerData.ClaimRewards(rewards);
BroadcastToPlayer(attacker, string.Format(msg("Chat.RewardPending"), victim.displayName, rewards.Count));
}
private object CanLootEntity(BasePlayer player, StorageContainer container) {
if (player == null || container == null || !openContainers.ContainsKey(container)) return null;
if (openContainers[container] != player.userID) return false;
return null;
}
private void OnPlayerLootEnd(PlayerLoot inventory) {
BasePlayer player = inventory.GetComponent<BasePlayer>();
if (bountyCreator.ContainsKey(player.userID)) {
StorageContainer container = inventory.entitySource.GetComponent<StorageContainer>();
if (container != null) {
if (container.inventory.itemList.Count == 0) SendReply(player, msg("Chat.NoItemsDeposited", player.userID));
else CreateNewBounty(player, bountyCreator[player.userID], 0, 0, container.inventory, false);
openContainers.Remove(container);
ClearContainer(container.inventory);
container.DieInstantly();
}
bountyCreator.Remove(player.userID);
}
}
private void OnServerSave() => SaveData();
private void Unload() {
if (!ServerMgr.Instance.Restarting) SaveData();
if (friendManager != null) UnityEngine.Object.Destroy(friendManager.gameObject);
ins = null;
}
#endregion
#region Functions
private void BroadcastToPlayer(BasePlayer player, string message) {
if (configData.Notifications.UsePopupNotifications && PopupNotifications) PopupNotifications?.Call("CreatePopupOnPlayer", message, player, configData.Notifications.PopupDuration);
else SendReply(player, message);
}
private void PopupToPlayer(BasePlayer player, string message, float duration = 5f) {
string panelId = $"RustNET.Popup {UnityEngine.Random.Range(0, 100000)}";
CuiElementContainer container = RustNET.UI.Container(RustNET.uiColors[RustNET.Colors.Background], "0.15 0.115", "0.85 0.145", false, "Hud", panelId);
RustNET.UI.Label(ref container, message, 11, "0 0", "1 1", TextAnchor.MiddleCenter, panelId);
CuiHelper.AddUi(player, container);
timer.In(duration, () => CuiHelper.DestroyUi(player, panelId));
}
private void CreateNewBounty(BasePlayer initiator, ulong targetId, int rpAmount, int ecoAmount, ItemContainer container, bool notify) {
IPlayer target = covalence.Players.FindPlayerById(targetId.ToString());
PlayerData playerData;
if (!storedData.players.TryGetValue(targetId, out playerData)) {
playerData = new PlayerData(target?.Name ?? "No Name");
storedData.players.Add(targetId, playerData);
}
playerData.totalBounties++;
int rewardId = GetUniqueId();
storedData.rewards.Add(rewardId, new RewardInfo(rpAmount, ecoAmount, container));
playerData.activeBounties.Add(new PlayerData.BountyInfo(initiator.userID, initiator.displayName, rewardId));
BasePlayer targetPlayer = target?.Object as BasePlayer;
if (targetPlayer != null) BroadcastToPlayer(targetPlayer, string.Format(msg("Chat.PlacedTarget", targetPlayer.userID), initiator.displayName));
if (notify) PopupToPlayer(initiator, string.Format(msg("UI.Add.PlacedInitiator", initiator.userID), target?.Name ?? "No Name"));
else BroadcastToPlayer(initiator, string.Format(msg("Chat.PlacedInitiator", initiator.userID), target?.Name ?? "No Name"));
if (configData.Notifications.BroadcastNewBounties) {
foreach (BasePlayer player in BasePlayer.activePlayerList) {
if (player == initiator || player.userID == targetId) continue;
BroadcastToPlayer(player, string.Format(msg("Chat.PlacedGlobal", player.userID), initiator.displayName, target?.Name ?? "No Name"));
}
}
}
private void GivePlayerRewards(BasePlayer player, RewardInfo rewardInfo, bool notify) {
if (rewardInfo.econAmount > 0 && Economics) Economics?.Call("Deposit", player.UserIDString, (double)rewardInfo.econAmount);
if (rewardInfo.rpAmount > 0 && ServerRewards) ServerRewards?.Call("AddPoints", player.userID, rewardInfo.rpAmount);
if (rewardInfo.rewardItems.Count > 0) {
foreach (RewardInfo.ItemData itemData in rewardInfo.rewardItems) {
Item item = CreateItem(itemData);
player.GiveItem(item, BaseEntity.GiveItemReason.PickedUp);
}
}
if (notify) PopupToPlayer(player, msg("UI.Reward.Claimed", player.userID));
}
private Item CreateItem(RewardInfo.ItemData itemData) {
Item item = ItemManager.CreateByItemID(itemData.itemid, itemData.amount, itemData.skin);
item.condition = itemData.condition;
if (itemData.instanceData != null) itemData.instanceData.Restore(item);
BaseProjectile weapon = item.GetHeldEntity() as BaseProjectile;
if (weapon != null) {
if (!string.IsNullOrEmpty(itemData.ammotype)) weapon.primaryMagazine.ammoType = ItemManager.FindItemDefinition(itemData.ammotype);
weapon.primaryMagazine.contents = itemData.ammo;
}
if (itemData.contents != null) {
foreach (var contentData in itemData.contents) {
var newContent = ItemManager.CreateByItemID(contentData.itemid, contentData.amount);
if (newContent != null) {
newContent.condition = contentData.condition;
newContent.MoveToContainer(item.contents);
}
}
}
return item;
}
private void SpawnItemContainer(BasePlayer player) {
StorageContainer container = (StorageContainer)GameManager.server.CreateEntity(boxPrefab, player.transform.position + player.eyes.BodyForward(), new Quaternion(), true);
container.enableSaving = false;
container.Spawn();
openContainers.Add(container, player.userID);
timer.In(0.15f, () => OpenInventory(player, container));
}
private void OpenInventory(BasePlayer player, StorageContainer container) {
player.inventory.loot.Clear();
player.inventory.loot.entitySource = container;
player.inventory.loot.itemSource = null;
player.inventory.loot.AddContainer(container.inventory);
player.inventory.loot.SendImmediate();
player.ClientRPCPlayer(null, player, "RPC_OpenLootPanel", "generic");
player.SendNetworkUpdate();
}
private void ClearContainer(ItemContainer itemContainer) {
if (itemContainer == null || itemContainer.itemList == null) return;
while (itemContainer.itemList.Count > 0) {
var item = itemContainer.itemList[0];
item.RemoveFromContainer();
item.Remove(0f);
}
}
private int GetUniqueId() {
int uid = UnityEngine.Random.Range(0, 10000);
if (storedData.rewards.ContainsKey(uid)) return GetUniqueId();
return uid;
}
private double CurrentTime() => DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds;
private List<BasePlayer> FindPlayer(string partialNameOrId) {
List<BasePlayer> players = new List<BasePlayer>();
foreach (BasePlayer player in BasePlayer.activePlayerList) {
if (partialNameOrId == player.UserIDString) return new List<BasePlayer>() {
player
}
;
if (player.displayName.ToLower().Contains(partialNameOrId.ToLower())) players.Add(player);
}
return players;
}
private string FormatTime(double time) {
TimeSpan dateDifference = TimeSpan.FromSeconds((float)time);
var days = dateDifference.Days;
var hours = dateDifference.Hours;
hours += (days * 24);
var mins = dateDifference.Minutes;
var secs = dateDifference.Seconds;
if (hours > 0) return string.Format("{0:00}h {1:00}m {2:00}s", hours, mins, secs);
else return string.Format("{0:00}m {1:00}s", mins, secs);
}
private string RemoveTag(string str) {
if (str.StartsWith("[") && str.Contains("]") && str.Length > str.IndexOf("]")) {
str = str.Substring(str.IndexOf("]") + 1).Trim();
}
if (str.StartsWith("[") && str.Contains("]") && str.Length > str.IndexOf("]")) RemoveTag(str);
return str;
}
private string TrimToSize(string str) {
if (str.Length > 20) str = str.Substring(0, 20);
return str;
}
private string GetHelpString(ulong playerId, bool title) => title ? msg("UI.Help.Title", playerId) : msg("UI.Help", playerId);
private bool AllowPublicAccess() => true;
#endregion
#region Friends
private class FriendManager : MonoBehaviour {
private List<FriendEntry> friends = new List<FriendEntry>();
private void Awake() {
enabled = false;
InvokeHandler.InvokeRepeating(this, RemoveOldData, 60, 60);
}
public void OnFriendshipEnded(string playerId, string friendId) {
friends.Add(new FriendEntry(playerId, friendId));
}
public bool WereFriends(string playerId, string friendId) {
bool flag = false;
IEnumerable<FriendEntry> entries = friends.Where(x => x.playerId == playerId || x.friendId == playerId);
foreach(FriendEntry entry in entries) {
if (entry.playerId == friendId || entry.friendId == friendId) {
flag = true;
break;
}
}
entries = null;
return flag;
}
public bool WereFriends(ulong playerId, ulong friendId) => WereFriends(playerId.ToString(), friendId.ToString());
private void RemoveOldData() {
double currentTime = DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds;
for (int i = friends.Count - 1; i >= 0; i--) {
FriendEntry entry = friends.ElementAt(i);
if (currentTime > entry.removeAt) friends.Remove(entry);
}
}
public struct FriendEntry {
public string playerId;
public string friendId;
public double removeAt;
public FriendEntry(string playerId, string friendId) {
this.playerId = playerId;
this.friendId = friendId;
removeAt = DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds + 3600;
}
}
}
public bool IsFriendlyPlayer(ulong playerId, ulong friendId) {
if (playerId == friendId || IsFriend(playerId, friendId) || IsClanmate(playerId, friendId) || IsTeamMate(playerId, friendId) || friendManager.WereFriends(playerId, friendId)) return true;
return false;
}
private bool IsClanmate(ulong playerId, ulong friendId) {
if (!Clans || !configData.IgnoreClans) return false;
object playerTag = Clans?.Call("GetClanOf", playerId);
object friendTag = Clans?.Call("GetClanOf", friendId);
if ((playerTag is string && !string.IsNullOrEmpty((string)playerTag)) && (friendTag is string && !string.IsNullOrEmpty((string)friendTag))) if (playerTag == friendTag) return true;
return false;
}
private bool IsFriend(ulong playerID, ulong friendID) {
if (!Friends || !configData.IgnoreFriends) return false;
return (bool)Friends?.Call("AreFriends", playerID, friendID);
}
private bool IsTeamMate(ulong playerId, ulong friendId) {
BasePlayer player = RelationshipManager.FindByID(playerId);
if (player == null) return false;
RelationshipManager.PlayerTeam playerTeam = RelationshipManager.Instance.FindTeam(player.currentTeam);
if (playerTeam != null) return playerTeam.members.Contains(friendId) || playerTeam.invites.Contains(friendId);
return false;
}
private void OnFriendRemoved(string playerId, string friendId) {
friendManager.OnFriendshipEnded(playerId.ToString(), friendId.ToString());
}
private void OnServerCommand(ConsoleSystem.Arg arg) {
string command = arg?.cmd?.FullName;
if (string.IsNullOrEmpty(command)) return;
BasePlayer player = arg.Player();
if (player == null) return;
if (command == "relationshipmanager.leaveteam") {
RelationshipManager.PlayerTeam currentTeam = RelationshipManager.Instance.FindTeam(player.currentTeam);
if (currentTeam == null) return;
foreach (ulong member in currentTeam.members) {
if (player.userID == member) continue;
OnFriendRemoved(player.UserIDString, member.ToString());
}
return;
}
if (command == "relationshipmanager.kickmember") {
RelationshipManager.PlayerTeam currentTeam = RelationshipManager.Instance.FindTeam(player.currentTeam);
if (currentTeam == null) return;
ulong target = arg.GetULong(0, (ulong)0);
foreach (ulong member in currentTeam.members) {
if (target == member) continue;
OnFriendRemoved(target.ToString(), member.ToString());
}
}
}
#endregion
#region UI
#region Main Menu
private CuiElementContainer CreateBountyContainer(BasePlayer player, int terminalId, string title, string returnCommand = null) {
CuiElementContainer container = RustNET.ins.GetBaseContainer(player, terminalId, Title);
RustNET.UI.Panel(ref container, RustNET.uiColors[RustNET.Colors.Panel], "0.04 0.765", "0.96 0.8");
RustNET.UI.Label(ref container, msg("UI.Menu.Bounty", player.userID) + title, 12, "0.05 0.765", "0.8 0.8", TextAnchor.MiddleLeft);
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], RustNET.msg("UI.Return", player.userID), 11, "0.82 0.765", "0.96 0.8", string.IsNullOrEmpty(returnCommand) ? $"bounty.changepage {terminalId} home" : returnCommand);
if (!permission.UserHasPermission(player.UserIDString, "bountynet.use")) {
RustNET.UI.Label(ref container, msg("UI.Menu.NoPermission", player.userID), 12, "0.05 0.5", "0.95 0.7");
CuiHelper.DestroyUi(player, RustNET.RustNET_Panel);
CuiHelper.AddUi(player, container);
return null;
}
return container;
}
private void CreateConsoleWindow(BasePlayer player, int terminalId, int page) {
CuiElementContainer container = CreateBountyContainer(player, terminalId, string.Empty, $"rustnet.changepage {terminalId}");
if (container != null) {
int i = 0;
if (configData.Rewards.AllowItems) {
RustNET.UI.Panel(ref container, RustNET.uiColors[RustNET.Colors.Panel], $"0.04 {(0.725f - (i * 0.04f))}", $"0.31 {(0.755f - (i * 0.04f))}");
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], msg("UI.Menu.AddItems", player.userID), 11, $"0.05 {0.725f - (i * 0.04f)}", $"0.3 {0.755f - (i * 0.04f)}", $"bounty.changepage {terminalId} add items", TextAnchor.MiddleLeft);
i++;
}
if (configData.Rewards.AllowServerRewards && ServerRewards) {
RustNET.UI.Panel(ref container, RustNET.uiColors[RustNET.Colors.Panel], $"0.04 {(0.725f - (i * 0.04f))}", $"0.31 {(0.755f - (i * 0.04f))}");
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], msg("UI.Menu.AddRP", player.userID), 11, $"0.05 {0.725f - (i * 0.04f)}", $"0.3 {0.755f - (i * 0.04f)}", $"bounty.changepage {terminalId} add rp", TextAnchor.MiddleLeft);
i++;
}
if (configData.Rewards.AllowEconomics && Economics) {
RustNET.UI.Panel(ref container, RustNET.uiColors[RustNET.Colors.Panel], $"0.04 {(0.725f - (i * 0.04f))}", $"0.31 {(0.755f - (i * 0.04f))}");
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], msg("UI.Menu.AddEco", player.userID), 11, $"0.05 {0.725f - (i * 0.04f)}", $"0.3 {0.755f - (i * 0.04f)}", $"bounty.changepage {terminalId} add eco", TextAnchor.MiddleLeft);
i++;
}
RustNET.UI.Panel(ref container, RustNET.uiColors[RustNET.Colors.Panel], $"0.04 {(0.725f - (i * 0.04f))}", $"0.31 {(0.755f - (i * 0.04f))}");
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], msg("UI.Menu.Cancel", player.userID), 11, $"0.05 {0.725f - (i * 0.04f)}", $"0.3 {0.755f - (i * 0.04f)}", $"bounty.changepage {terminalId} cancel 0", TextAnchor.MiddleLeft);
i++;
RustNET.UI.Panel(ref container, RustNET.uiColors[RustNET.Colors.Panel], $"0.04 {(0.725f - (i * 0.04f))}", $"0.31 {(0.755f - (i * 0.04f))}");
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], msg("UI.Menu.Claim", player.userID), 11, $"0.05 {0.725f - (i * 0.04f)}", $"0.3 {0.755f - (i * 0.04f)}", $"bounty.changepage {terminalId} claim 0", TextAnchor.MiddleLeft);
i++;
RustNET.UI.Panel(ref container, RustNET.uiColors[RustNET.Colors.Panel], $"0.04 {(0.725f - (i * 0.04f))}", $"0.31 {(0.755f - (i * 0.04f))}");
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], msg("UI.Menu.View", player.userID), 11, $"0.05 {0.725f - (i * 0.04f)}", $"0.3 {0.755f - (i * 0.04f)}", $"bounty.changepage {terminalId} view 0", TextAnchor.MiddleLeft);
i++;
RustNET.UI.Panel(ref container, RustNET.uiColors[RustNET.Colors.Panel], $"0.04 {(0.725f - (i * 0.04f))}", $"0.31 {(0.755f - (i * 0.04f))}");
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], msg("UI.Menu.Wanted", player.userID), 11, $"0.05 {0.725f - (i * 0.04f)}", $"0.3 {0.755f - (i * 0.04f)}", $"bounty.changepage {terminalId} wanted 0", TextAnchor.MiddleLeft);
i++;
RustNET.UI.Panel(ref container, RustNET.uiColors[RustNET.Colors.Panel], $"0.04 {(0.725f - (i * 0.04f))}", $"0.31 {(0.755f - (i * 0.04f))}");
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], msg("UI.Menu.Hunters", player.userID), 11, $"0.05 {0.725f - (i * 0.04f)}", $"0.3 {0.755f - (i * 0.04f)}", $"bounty.changepage {terminalId} hunters 0", TextAnchor.MiddleLeft);
i++;
CuiHelper.DestroyUi(player, RustNET.RustNET_Panel);
CuiHelper.AddUi(player, container);
}
}
#endregion
#region Bounty Creation
private void CreatePlayerSelectionMenu(BasePlayer player, int terminalId, int page, bool isOffline, string type) {
CuiElementContainer container = CreateBountyContainer(player, terminalId, msg("UI.SelectPlayer", player.userID));
if (container != null) {
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], isOffline ? msg("UI.Selection.Offline", player.userID) : msg("UI.Selection.Online", player.userID), 11, "0.59 0.765", "0.81 0.8", $"bounty.changepage {terminalId} selection {page} {!isOffline} {type}");
int count = 0;
int startAt = page * 90;
IPlayer[] players = isOffline ? offlinePlayers.GetOfflineList().OrderBy(x => x.Name).ToArray() : covalence.Players.Connected.OrderBy(x => x.Name).ToArray();
for (int i = startAt; i < (startAt + 90 > players.Length ? players.Length : startAt + 90);
i++) {
IPlayer target = players.ElementAt(i);
//if (target.Id == player.UserIDString)
//continue;
PlayerData playerData;
if (storedData.players.TryGetValue(ulong.Parse(target.Id), out playerData)) {
if (playerData.GetBountyOf(player.userID) != null) continue;
}
float[] position = GetButtonPosition(count);
if (count == 0 || count % 5 == 0) RustNET.UI.Panel(ref container, RustNET.uiColors[RustNET.Colors.Panel], $"0.04 {position[1]}", $"0.96 {position[3]}");
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], string.IsNullOrEmpty(target.Name) ? target.Id : TrimToSize(RemoveTag(target.Name)), 11, $"{position[0]} {position[1]}", $"{position[2]} {position[3]}", $"bounty.addbounty {type} {terminalId} {target.Id} 0");
count++;
}
int totalPages = players.Length / 90;
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], RustNET.msg("UI.Back", player.userID), 11, "0.3 0.01", "0.44 0.04", page > 0 ? $"bounty.changepage {terminalId} selection {page - 1} {isOffline} {type}" : "");
RustNET.UI.Label(ref container, string.Format(RustNET.msg("UI.Page", player.userID), page + 1, totalPages + 1), 11, "0.44 0.01", "0.56 0.04");
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], RustNET.msg("UI.Next", player.userID), 11, "0.56 0.01", "0.7 0.04", page + 1 <= totalPages ? $"bounty.changepage {terminalId} selection {page + 1} {isOffline} {type}" : "");
CuiHelper.DestroyUi(player, RustNET.RustNET_Panel);
CuiHelper.AddUi(player, container);
}
}
private void CreateNewAmountMenu(BasePlayer player, int terminalId, ulong targetId, int amount, bool isRp) {
CuiElementContainer container = CreateBountyContainer(player, terminalId, msg("UI.Tip.SelectAmount", player.userID));
if (container != null) {
string targetName = covalence.Players.FindPlayerById(targetId.ToString())?.Name ?? targetId.ToString();
RustNET.UI.Panel(ref container, RustNET.uiColors[RustNET.Colors.Panel], $"0.04 0.725", $"0.96 0.755");
RustNET.UI.Label(ref container, string.Format(isRp ? msg("UI.Tip.SelectAmountRP", player.userID) : msg("UI.Tip.SelectAmountEco", player.userID), targetName), 11, $"0.05 0.725", $"0.95 0.755", TextAnchor.MiddleLeft);
RustNET.UI.Panel(ref container, RustNET.uiColors[RustNET.Colors.Panel], $"0.04 0.685", $"0.96 0.715");
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], "- 1000", 11, $"0.04 0.685", $"0.1 0.715", $"bounty.addbounty {(isRp ? "rp" : "eco")} {terminalId} {targetId} {amount - 1000}", TextAnchor.MiddleCenter);
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], "- 100", 11, $"0.11 0.685", $"0.16 0.715", $"bounty.addbounty {(isRp ? "rp" : "eco")} {terminalId} {targetId} {amount - 100}", TextAnchor.MiddleCenter);
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], "- 10", 11, $"0.17 0.685", $"0.22 0.715", $"bounty.addbounty {(isRp ? "rp" : "eco")} {terminalId} {targetId} {amount - 10}", TextAnchor.MiddleCenter);
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], "- 1", 11, $"0.23 0.685", $"0.28 0.715", $"bounty.addbounty {(isRp ? "rp" : "eco")} {terminalId} {targetId} {amount - 1}", TextAnchor.MiddleCenter);
RustNET.UI.Label(ref container, string.Format((isRp ? msg("UI.Reward.RP", player.userID) : msg("UI.Reward.Econ", player.userID)), amount), 11, $"0.28 0.685", $"0.48 0.715", TextAnchor.MiddleCenter);
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], "+ 1", 11, $"0.48 0.685", $"0.53 0.715", $"bounty.addbounty {(isRp ? "rp" : "eco")} {terminalId} {targetId} {amount + 1}", TextAnchor.MiddleCenter);
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], "+ 10", 11, $"0.54 0.685", $"0.59 0.715", $"bounty.addbounty {(isRp ? "rp" : "eco")} {terminalId} {targetId} {amount + 10}", TextAnchor.MiddleCenter);
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], "+ 100", 11, $"0.6 0.685", $"0.65 0.715", $"bounty.addbounty {(isRp ? "rp" : "eco")} {terminalId} {targetId} {amount + 100}", TextAnchor.MiddleCenter);
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], "+ 1000", 11, $"0.66 0.685", $"0.72 0.715", $"bounty.addbounty {(isRp ? "rp" : "eco")} {terminalId} {targetId} {amount + 1000}", TextAnchor.MiddleCenter);
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], msg("UI.Add.Confirm", player.userID), 11, $"0.82 0.685", $"0.96 0.715", $"bounty.addbounty {(isRp ? "rp" : "eco")} {terminalId} {targetId} {amount} confirm", TextAnchor.MiddleCenter);
CuiHelper.DestroyUi(player, RustNET.RustNET_Panel);
CuiHelper.AddUi(player, container);
}
}
#endregion
#region Cancel Bounty
private void CreateCancelBountyMenu(BasePlayer player, int terminalId, int page) {
CuiElementContainer container = CreateBountyContainer(player, terminalId, msg("UI.Tip.Cancel", player.userID));
if (container != null) {
Dictionary<ulong, PlayerData.BountyInfo> activeBounties = storedData.players.Where(x => x.Value.activeBounties.Exists(y => y.initiatorId == player.userID)).ToDictionary(x => x.Key, y => y.Value.activeBounties.FirstOrDefault(x => x.initiatorId == player.userID));
if (activeBounties == null || activeBounties.Count == 0) RustNET.UI.Label(ref container, msg("UI.Cancel.NoneSet", player.userID), 12, "0.05 0.5", "0.95 0.7");
else {
RustNET.UI.Panel(ref container, RustNET.uiColors[RustNET.Colors.Panel], $"0.04 {0.725f}", $"0.96 {0.755f}");
RustNET.UI.Label(ref container, msg("UI.View.Name", player.userID), 11, $"0.05 {0.725f}", $"0.24 {0.755f}", TextAnchor.MiddleLeft);
RustNET.UI.Label(ref container, msg("UI.View.TimeActive", player.userID), 11, $"0.25 {0.725f}", $"0.44 {0.755f}");
RustNET.UI.Label(ref container, msg("UI.View.Reward", player.userID), 11, $"0.45 {0.725f}", $"0.81 {0.755f}", TextAnchor.MiddleLeft);
int count = 1;
int startAt = page * 17;
for (int i = startAt; i < (startAt + 17 > activeBounties.Count ? activeBounties.Count : startAt + 17);
i++) {
var bountyInfo = activeBounties.ElementAt(i);
RustNET.UI.Panel(ref container, RustNET.uiColors[RustNET.Colors.Panel], $"0.04 {(0.725f - (count * 0.04f))}", $"0.96 {(0.755f - (count * 0.04f))}");
RustNET.UI.Label(ref container, $"> {covalence.Players.FindPlayerById(bountyInfo.Key.ToString())?.Name ?? bountyInfo.Key.ToString()}", 11, $"0.05 {0.725f - (count * 0.04f)}", $"0.24 {0.755f - (count * 0.04f)}", TextAnchor.MiddleLeft);
RustNET.UI.Label(ref container, FormatTime(CurrentTime() - bountyInfo.Value.initiatedTime), 11, $"0.25 {0.725f - (count * 0.04f)}", $"0.44 {0.755f - (count * 0.04f)}");
RustNET.UI.Label(ref container, storedData.rewards[bountyInfo.Value.rewardId].GetRewardString(player.userID), 10, $"0.45 {0.725f - (count * 0.04f)}", $"0.81 {0.755f - (count * 0.04f)}", TextAnchor.MiddleLeft);
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], msg("UI.View.Cancel", player.userID), 11, $"0.82 {0.725f - (count * 0.04f)}", $"0.96 {0.755f - (count * 0.04f)}", $"bounty.cancelbounty {terminalId} {page} {bountyInfo.Key} {player.userID} false");
count++;
}
int totalPages = activeBounties.Count / 17;
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], RustNET.msg("UI.Back", player.userID), 11, "0.3 0.01", "0.44 0.04", page > 0 ? $"bounty.changepage {terminalId} cancel {page - 1}" : "");
RustNET.UI.Label(ref container, string.Format(RustNET.msg("UI.Page", player.userID), page + 1, totalPages + 1), 11, "0.44 0.01", "0.56 0.04");
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], RustNET.msg("UI.Next", player.userID), 11, "0.56 0.01", "0.7 0.04", page + 1 <= totalPages ? $"bounty.changepage {terminalId} cancel {page + 1}" : "");
}
CuiHelper.DestroyUi(player, RustNET.RustNET_Panel);
CuiHelper.AddUi(player, container);
}
}
#endregion
#region Claim
private void CreateClaimMenu(BasePlayer player, int terminalId, int page) {
CuiElementContainer container = CreateBountyContainer(player, terminalId, msg("UI.Tip.Claim", player.userID));
if (container != null) {
PlayerData playerData;
if (!storedData.players.TryGetValue(player.userID, out playerData) || playerData.unclaimedRewards.Count == 0) RustNET.UI.Label(ref container, msg("UI.Claim.NoRewardsPending", player.userID), 12, "0.05 0.5", "0.95 0.7");
else {
RustNET.UI.Panel(ref container, RustNET.uiColors[RustNET.Colors.Panel], $"0.04 {0.725f}", $"0.96 {0.755f}");
RustNET.UI.Label(ref container, msg("UI.View.Reward", player.userID), 11, $"0.05 {0.725f}", $"0.81 {0.755f}", TextAnchor.MiddleLeft);
int count = 1;
int startAt = page * 17;
for (int i = startAt; i < (startAt + 17 > playerData.unclaimedRewards.Count ? playerData.unclaimedRewards.Count : startAt + 17);
i++) {
RewardInfo rewardInfo = storedData.rewards[playerData.unclaimedRewards.ElementAt(i)];
RustNET.UI.Panel(ref container, RustNET.uiColors[RustNET.Colors.Panel], $"0.04 {(0.725f - (count * 0.04f))}", $"0.96 {(0.755f - (count * 0.04f))}");
RustNET.UI.Label(ref container, $"> {rewardInfo.GetRewardString(player.userID)}", 11, $"0.05 {0.725f - (count * 0.04f)}", $"0.81 {0.755f - (count * 0.04f)}", TextAnchor.MiddleLeft);
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], msg("UI.Claim.ClaimReward", player.userID), 11, $"0.82 {0.725f - (count * 0.04f)}", $"0.96 {0.755f - (count * 0.04f)}", $"bounty.claimreward {terminalId} {page} {playerData.unclaimedRewards.ElementAt(i)}");
count++;
}
int totalPages = playerData.unclaimedRewards.Count / 17;
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], RustNET.msg("UI.Back", player.userID), 11, "0.3 0.01", "0.44 0.04", page > 0 ? $"bounty.changepage {terminalId} claim {page - 1}" : "");
RustNET.UI.Label(ref container, string.Format(RustNET.msg("UI.Page", player.userID), page + 1, totalPages + 1), 11, "0.44 0.01", "0.56 0.04");
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], RustNET.msg("UI.Next", player.userID), 11, "0.56 0.01", "0.7 0.04", page + 1 <= totalPages ? $"bounty.changepage {terminalId} claim {page + 1}" : "");
}
CuiHelper.DestroyUi(player, RustNET.RustNET_Panel);
CuiHelper.AddUi(player, container);
}
}
#endregion
#region Bounty View
private void CreateBountyViewMenu(BasePlayer player, int terminalId, int page) {
CuiElementContainer container = CreateBountyContainer(player, terminalId, msg("UI.View.ActiveBounties", player.userID));
if (container != null) {
Dictionary<ulong, PlayerData> activeBounties = storedData.players.Where(x => x.Value.activeBounties.Count > 0).ToDictionary(x => x.Key, y => y.Value);
if (activeBounties == null || activeBounties.Count == 0) RustNET.UI.Label(ref container, msg("UI.View.NoActiveBounties", player.userID), 12, "0.05 0.5", "0.95 0.7");
else {
RustNET.UI.Panel(ref container, RustNET.uiColors[RustNET.Colors.Panel], $"0.04 {0.725f}", $"0.96 {0.755f}");
RustNET.UI.Label(ref container, msg("UI.View.Name", player.userID), 11, $"0.05 {0.725f}", $"0.39 {0.755f}", TextAnchor.MiddleLeft);
RustNET.UI.Label(ref container, msg("UI.Wanted.CurrentTime", player.userID), 11, $"0.4 {0.725f}", $"0.63 {0.755f}");
RustNET.UI.Label(ref container, msg("UI.Wanted.ActiveBounties", player.userID), 11, $"0.64 {0.725f}", $"0.79 {0.755f}");
int count = 1;
int startAt = page * 17;
for (int i = startAt; i < (startAt + 17 > activeBounties.Count ? activeBounties.Count : startAt + 17);
i++) {
KeyValuePair<ulong, PlayerData> playerData = activeBounties.ElementAt(i);
RustNET.UI.Panel(ref container, RustNET.uiColors[RustNET.Colors.Panel], $"0.04 {(0.725f - (count * 0.04f))}", $"0.96 {(0.755f - (count * 0.04f))}");
RustNET.UI.Label(ref container, $"> {playerData.Value.displayName}", 11, $"0.05 {0.725f - (count * 0.04f)}", $"0.39 {0.755f - (count * 0.04f)}", TextAnchor.MiddleLeft);
RustNET.UI.Label(ref container, FormatTime(CurrentTime() - playerData.Value.activeBounties.Min(x => x.initiatedTime)), 11, $"0.4 {0.725f - (count * 0.04f)}", $"0.63 {0.755f - (count * 0.04f)}");
RustNET.UI.Label(ref container, playerData.Value.activeBounties.Count.ToString(), 11, $"0.64 {0.725f - (count * 0.04f)}", $"0.79 {0.755f - (count * 0.04f)}");
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], msg("UI.ViewBounties", player.userID), 11, $"0.82 {0.725f - (count * 0.04f)}", $"0.96 {0.755f - (count * 0.04f)}", $"bounty.viewbounties {terminalId} {playerData.Key} 0");
count++;
}
int totalPages = activeBounties.Count / 17;
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], RustNET.msg("UI.Back", player.userID), 11, "0.3 0.01", "0.44 0.04", page > 0 ? $"bounty.changepage {terminalId} view {page - 1}" : "");
RustNET.UI.Label(ref container, string.Format(RustNET.msg("UI.Page", player.userID), page + 1, totalPages + 1), 11, "0.44 0.01", "0.56 0.04");
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], RustNET.msg("UI.Next", player.userID), 11, "0.56 0.01", "0.7 0.04", page + 1 <= totalPages ? $"bounty.changepage {terminalId} view {page + 1}" : "");
}
CuiHelper.DestroyUi(player, RustNET.RustNET_Panel);
CuiHelper.AddUi(player, container);
}
}
private void CreateIndividualBountyView(BasePlayer player, int terminalId, ulong targetId, int page) {
CuiElementContainer container = CreateBountyContainer(player, terminalId, string.Format(msg("UI.View.ActiveBountiesPlayer", player.userID), covalence.Players.FindPlayerById(targetId.ToString())?.Name ?? targetId.ToString()), $"bounty.changepage {terminalId} view 0");
if (container != null) {
PlayerData playerData;
if (!storedData.players.TryGetValue(targetId, out playerData) || playerData.activeBounties.Count == 0) RustNET.UI.Label(ref container, msg("UI.View.NoActiveBountiesPlayer", player.userID), 12, "0.05 0.5", "0.95 0.7");
else {
RustNET.UI.Panel(ref container, RustNET.uiColors[RustNET.Colors.Panel], $"0.04 {0.725f}", $"0.96 {0.755f}");
RustNET.UI.Label(ref container, msg("UI.View.PlacedBy", player.userID), 11, $"0.05 {0.725f}", $"0.24 {0.755f}", TextAnchor.MiddleLeft);
RustNET.UI.Label(ref container, msg("UI.View.TimeActive", player.userID), 11, $"0.25 {0.725f}", $"0.44 {0.755f}");
RustNET.UI.Label(ref container, msg("UI.View.Reward", player.userID), 11, $"0.45 {0.725f}", $"0.91 {0.755f}", TextAnchor.MiddleLeft);
if (player.IsAdmin || permission.UserHasPermission(player.UserIDString, "bountynet.admin")) RustNET.UI.Label(ref container, msg("UI.View.AdminCancel", player.userID), 11, $"0.82 {0.725f}", $"0.95 {0.755f}", TextAnchor.MiddleRight);
int count = 1;
int startAt = page * 17;
for (int i = startAt; i < (startAt + 17 > playerData.activeBounties.Count ? playerData.activeBounties.Count : startAt + 17);
i++) {
PlayerData.BountyInfo bountyInfo = playerData.activeBounties.ElementAt(i);
RustNET.UI.Panel(ref container, RustNET.uiColors[RustNET.Colors.Panel], $"0.04 {(0.725f - (count * 0.04f))}", $"0.96 {(0.755f - (count * 0.04f))}");
RustNET.UI.Label(ref container, $"> {bountyInfo.initiatorName}", 11, $"0.05 {0.725f - (count * 0.04f)}", $"0.24 {0.755f - (count * 0.04f)}", TextAnchor.MiddleLeft);
RustNET.UI.Label(ref container, FormatTime(CurrentTime() - bountyInfo.initiatedTime), 11, $"0.25 {0.725f - (count * 0.04f)}", $"0.44 {0.755f - (count * 0.04f)}");
RustNET.UI.Label(ref container, storedData.rewards[bountyInfo.rewardId].GetRewardString(player.userID), 10, $"0.45 {0.725f - (count * 0.04f)}", $"0.925 {0.755f - (count * 0.04f)}", TextAnchor.MiddleLeft);
if (player.IsAdmin || permission.UserHasPermission(player.UserIDString, "bountynet.admin")) RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], "X", 10, $"0.935 {0.725f - (count * 0.04f)}", $"0.96 {0.755f - (count * 0.04f)}", $"bounty.cancelbounty {terminalId} {page} {targetId} {bountyInfo.initiatorId} true");
count++;
}
int totalPages = playerData.activeBounties.Count / 17;
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], RustNET.msg("UI.Back", player.userID), 11, "0.3 0.01", "0.44 0.04", page > 0 ? $"bounty.viewbounties {terminalId} {targetId} {page - 1}" : "");
RustNET.UI.Label(ref container, string.Format(RustNET.msg("UI.Page", player.userID), page + 1, totalPages + 1), 11, "0.44 0.01", "0.56 0.04");
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], RustNET.msg("UI.Next", player.userID), 11, "0.56 0.01", "0.7 0.04", page + 1 <= totalPages ? $"bounty.viewbounties {terminalId} {targetId} {page + 1}" : "");
}
CuiHelper.DestroyUi(player, RustNET.RustNET_Panel);
CuiHelper.AddUi(player, container);
}
}
#endregion
#region Most Wanted
private void CreateWantedMenu(BasePlayer player, int terminalId, int page) {
CuiElementContainer container = CreateBountyContainer(player, terminalId, msg("UI.Tip.Wanted", player.userID));
if (container != null) {
PlayerData[] wantedPlayers = storedData.players.Values.Where(x => x.totalBounties > 0).OrderByDescending(x => x.totalWantedTime + x.GetCurrentWantedTime()).ToArray();
if (wantedPlayers == null || wantedPlayers.Length == 0) RustNET.UI.Label(ref container, msg("UI.Wanted.NoWantedPlayers", player.userID), 12, "0.05 0.5", "0.95 0.7");
else {
RustNET.UI.Panel(ref container, RustNET.uiColors[RustNET.Colors.Panel], $"0.04 {0.725f}", $"0.96 {0.755f}");
RustNET.UI.Label(ref container, msg("UI.View.Name", player.userID), 11, $"0.05 {0.725f}", $"0.39 {0.755f}", TextAnchor.MiddleLeft);
RustNET.UI.Label(ref container, msg("UI.Wanted.TotalTime", player.userID), 11, $"0.4 {0.725f}", $"0.63 {0.755f}");
RustNET.UI.Label(ref container, msg("UI.Wanted.TotalBounties", player.userID), 11, $"0.64 {0.725f}", $"0.79 {0.755f}");
RustNET.UI.Label(ref container, msg("UI.Wanted.ActiveBounties", player.userID), 11, $"0.8 {0.725f}", $"0.95 {0.755f}");
int count = 1;
int startAt = page * 17;
for (int i = startAt; i < (startAt + 17 > wantedPlayers.Length ? wantedPlayers.Length : startAt + 17);
i++) {
PlayerData playerData = wantedPlayers.ElementAt(i);
RustNET.UI.Panel(ref container, RustNET.uiColors[RustNET.Colors.Panel], $"0.04 {(0.725f - (count * 0.04f))}", $"0.96 {(0.755f - (count * 0.04f))}");
RustNET.UI.Label(ref container, $"> {playerData.displayName}", 11, $"0.05 {0.725f - (count * 0.04f)}", $"0.39 {0.755f - (count * 0.04f)}", TextAnchor.MiddleLeft);
RustNET.UI.Label(ref container, FormatTime(playerData.totalWantedTime + playerData.GetCurrentWantedTime()), 11, $"0.4 {0.725f - (count * 0.04f)}", $"0.63 {0.755f - (count * 0.04f)}");
RustNET.UI.Label(ref container, playerData.totalBounties.ToString(), 11, $"0.64 {0.725f - (count * 0.04f)}", $"0.79 {0.755f - (count * 0.04f)}");
RustNET.UI.Label(ref container, playerData.activeBounties.Count.ToString(), 11, $"0.8 {0.725f - (count * 0.04f)}", $"0.95 {0.755f - (count * 0.04f)}");
count++;
}
int totalPages = wantedPlayers.Length / 17;
RustNET.UI.Button(ref container, RustNET.uiColors[RustNET.Colors.Button], RustNET.msg("UI.Back", player.userID), 11, "0.3 0.01", "0.44 0.04", page > 0 ? $"bounty.changepage
// ... [Code preview truncated due to length. Full source in attached file] ...