Иконка ресурса

FREE BountyHunter : 1.0.0 1.0.0

Нет прав для скачивания
C#:
using System;
using System.Collections.Generic;
using System.Linq;
using Oxide.Core;
using Oxide.Core.Plugins;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("Bounty Hunter", "0killrest", "1.0.0")]
    [Description("Place bounties on players, hunt them down for rewards")]
    internal class BountyHunter : RustPlugin
    {
        #region Configuration
        private static ConfigData config;
        
        private class ConfigData
        {
            public bool Enabled { get; set; } = true;
            public int MinBountyAmount { get; set; } = 100;
            public int MaxBountyAmount { get; set; } = 10000;
            public int HunterRewardPercentage { get; set; } = 90; // 90% goes to hunter, 10% tax
            public bool AnnounceNewBounty { get; set; } = true;
            public bool ShowBountyOnMap { get; set; } = true;
            public int BountyExpiryHours { get; set; } = 48;
            public List<string> BannedFromBounty { get; set; }
            
            public ConfigData()
            {
                BannedFromBounty = new List<string> { "admin", "vip" };
            }
        }
        
        protected override void LoadConfig()
        {
            base.LoadConfig();
            config = Config.ReadObject<ConfigData>();
            if (config == null)
            {
                LoadDefaultConfig();
            }
        }
        
        protected override void LoadDefaultConfig()
        {
            config = new ConfigData();
            PrintWarning("Default configuration created.Edit it in oxide/config/BountyHunter.json");
            SaveConfig();
        }
        
        protected override void SaveConfig() => Config.WriteObject(config);
        #endregion

        #region Data Storage
        private Dictionary<ulong, BountyData> activeBounties = new Dictionary<ulong, BountyData>();
        private Dictionary<ulong, HunterStats> hunterStats = new Dictionary<ulong, HunterStats>();
        
        private class BountyData
        {
            public ulong TargetId { get; set; }
            public string TargetName { get; set; }
            public ulong PlacedById { get; set; }
            public string PlacedByName { get; set; }
            public int Amount { get; set; }
            public DateTime PlacedTime { get; set; }
            public bool IsActive { get; set; } = true;
        }
        
        private class HunterStats
        {
            public int BountiesCollected { get; set; }
            public int TotalEarned { get; set; }
            public int CurrentStreak { get; set; }
            public int BestStreak { get; set; }
        }
        
        private void LoadData()
        {
            activeBounties = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<ulong, BountyData>>("BountyHunter_Active") ?? new Dictionary<ulong, BountyData>();
            hunterStats = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<ulong, HunterStats>>("BountyHunter_Stats") ?? new Dictionary<ulong, HunterStats>();
        }
        
        private void SaveData()
        {
            Interface.Oxide.DataFileSystem.WriteObject("BountyHunter_Active", activeBounties);
            Interface.Oxide.DataFileSystem.WriteObject("BountyHunter_Stats", hunterStats);
        }
        #endregion

        #region Hooks
        private void Init()
        {
            LoadData();
            permission.RegisterPermission("bountyhunter.admin", this);
            permission.RegisterPermission("bountyhunter.immune", this);
            permission.RegisterPermission("bountyhunter.place", this);
        }
        
        private void OnServerInitialized()
        {
            if (config.Enabled)
            {
                // Check for expired bounties every hour
                timer.Repeat(3600f, 0, () => CheckExpiredBounties());
                
                // Update map markers for bounties
                if (config.ShowBountyOnMap)
                {
                    timer.Repeat(60f, 0, () => UpdateBountyMarkers());
                }
            }
        }
        
        private void Unload()
        {
            SaveData();
        }
        
        private void OnServerSave() => SaveData();
        
        private void OnPlayerDeath(BasePlayer victim, HitInfo info)
        {
            if (!config.Enabled) return;
            if (victim == null) return;
            
            BasePlayer killer = info?.InitiatorPlayer;
            if (killer == null || killer == victim) return;
            
            // Check if victim has a bounty
            if (activeBounties.ContainsKey(victim.userID))
            {
                var bounty = activeBounties[victim.userID];
                if (!bounty.IsActive) return;
                
                // Check if killer is immune
                if (permission.UserHasPermission(killer.UserIDString, "bountyhunter.immune"))
                {
                    SendReply(killer, $"<color=yellow>{victim.displayName} has a bounty, but you are immune to bounty hunting!</color>");
                    return;
                }
                
                // Calculate reward
                int reward = (int)(bounty.Amount * (config.HunterRewardPercentage / 100f));
                int tax = bounty.Amount - reward;
                
                // Give reward to killer
                Item rewardScrap = ItemManager.Create(ItemManager.FindItemDefinition("scrap"), reward);
                if (rewardScrap != null)
                {
                    killer.inventory.GiveItem(rewardScrap);
                }
                
                // Update hunter stats
                if (!hunterStats.ContainsKey(killer.userID))
                {
                    hunterStats[killer.userID] = new HunterStats();
                }
                hunterStats[killer.userID].BountiesCollected++;
                hunterStats[killer.userID].TotalEarned += reward;
                hunterStats[killer.userID].CurrentStreak++;
                if (hunterStats[killer.userID].CurrentStreak > hunterStats[killer.userID].BestStreak)
                {
                    hunterStats[killer.userID].BestStreak = hunterStats[killer.userID].CurrentStreak;
                }
                
                // Reset streak for others? No, streak is personal
                
                // Announce to server
                Server.Broadcast($"<color=red>🔪 BOUNTY COLLECTED!</color> <color=green>{killer.displayName}</color> claimed <color=yellow>{reward} scrap</color> for eliminating <color=orange>{victim.displayName}</color>!");
                
                // Notify the one who placed the bounty
                var placer = BasePlayer.FindByID(bounty.PlacedById);
                if (placer != null && placer.IsConnected)
                {
                    SendReply(placer, $"<color=green>Your bounty on {victim.displayName} has been claimed by {killer.displayName}! {reward} scrap paid out.</color>");
                }
                
                // Remove bounty
                activeBounties.Remove(victim.userID);
                SaveData();
                
                // Visual effect on kill
                Effect.server.Run("assets/prefabs/locks/keylock/effects/lock.code.updated.prefab", victim.transform.position, Vector3.zero);
                
                // Remove map marker
                RemoveBountyMarker(victim.userID);
                
                return;
            }
            
            // If killer killed someone without bounty, reset their streak
            if (hunterStats.ContainsKey(killer.userID))
            {
                if (hunterStats[killer.userID].CurrentStreak > 0)
                {
                    hunterStats[killer.userID].CurrentStreak = 0;
                    SendReply(killer, $"<color=yellow>Your bounty hunting streak has been reset!</color>");
                }
            }
        }
        
        private void CheckExpiredBounties()
        {
            var expired = new List<ulong>();
            
            foreach (var bounty in activeBounties)
            {
                if ((DateTime.UtcNow - bounty.Value.PlacedTime).TotalHours > config.BountyExpiryHours)
                {
                    expired.Add(bounty.Key);
                    
                    // Notify placer
                    var placer = BasePlayer.FindByID(bounty.Value.PlacedById);
                    if (placer != null && placer.IsConnected)
                    {
                        SendReply(placer, $"<color=yellow>Your bounty on {bounty.Value.TargetName} has expired.You lost {bounty.Value.Amount} scrap.</color>");
                    }
                }
            }
            
            foreach (var targetId in expired)
            {
                RemoveBountyMarker(targetId);
                activeBounties.Remove(targetId);
            }
            
            if (expired.Count > 0)
            {
                SaveData();
                Puts($"Expired {expired.Count} bounties");
            }
        }
        
        private void UpdateBountyMarkers()
        {
            if (!config.ShowBountyOnMap) return;
            
            foreach (var bounty in activeBounties)
            {
                var target = BasePlayer.FindByID(bounty.Key);
                if (target != null && target.IsConnected && !target.IsDead())
                {
                    AddOrUpdateBountyMarker(target);
                }
            }
        }
        
        private void AddOrUpdateBountyMarker(BasePlayer target)
        {
            // Remove old marker first
            RemoveBountyMarker(target.userID);
            
            // Add new marker
            foreach (var player in BasePlayer.activePlayerList)
            {
                if (player != target) // Target doesn't see their own marker
                {
                    player.SendConsoleCommand("createmarker", 
                        $"bounty_{target.userID}", 
                        $"🔪 BOUNTY: {activeBounties[target.userID].Amount} scrap", 
                        "red", 
                        target.transform.position);
                }
            }
        }
        
        private void RemoveBountyMarker(ulong targetId)
        {
            foreach (var player in BasePlayer.activePlayerList)
            {
                player.SendConsoleCommand("removemarker", $"bounty_{targetId}");
            }
        }
        #endregion

        #region Core Logic
        private bool CanPlaceBounty(BasePlayer placer, BasePlayer target, int amount)
        {
            // Check if enabled
            if (!config.Enabled)
            {
                SendReply(placer, "Bounty system is currently disabled.");
                return false;
            }
            
            // Check self
            if (placer.userID == target.userID)
            {
                SendReply(placer, "You cannot place a bounty on yourself!");
                return false;
            }
            
            // Check if target has immunity
            if (permission.UserHasPermission(target.UserIDString, "bountyhunter.immune"))
            {
                SendReply(placer, "This player is immune to bounties!");
                return false;
            }
            
            // Check if target already has active bounty
            if (activeBounties.ContainsKey(target.userID))
            {
                SendReply(placer, $"<color=red>{target.displayName} already has an active bounty of {activeBounties[target.userID].Amount} scrap!</color>");
                return false;
            }
            
            // Check amount limits
            if (amount < config.MinBountyAmount)
            {
                SendReply(placer, $"Minimum bounty amount is {config.MinBountyAmount} scrap");
                return false;
            }
            
            if (amount > config.MaxBountyAmount)
            {
                SendReply(placer, $"Maximum bounty amount is {config.MaxBountyAmount} scrap");
                return false;
            }
            
            // Check if placer has enough scrap
            int playerScrap = placer.inventory.GetAmount(ItemManager.FindItemDefinition("scrap").itemid);
            if (playerScrap < amount)
            {
                SendReply(placer, $"You don't have enough scrap! You have {playerScrap}, need {amount}");
                return false;
            }
            
            // Check permission
            if (!permission.UserHasPermission(placer.UserIDString, "bountyhunter.place"))
            {
                SendReply(placer, "You don't have permission to place bounties!");
                return false;
            }
            
            return true;
        }
        
        private bool PlaceBounty(BasePlayer placer, BasePlayer target, int amount)
        {
            if (!CanPlaceBounty(placer, target, amount)) return false;
            
            // Take scrap from placer
            placer.inventory.Take(null, ItemManager.FindItemDefinition("scrap").itemid, amount);
            
            // Create bounty
            var bounty = new BountyData
            {
                TargetId = target.userID,
                TargetName = target.displayName,
                PlacedById = placer.userID,
                PlacedByName = placer.displayName,
                Amount = amount,
                PlacedTime = DateTime.UtcNow,
                IsActive = true
            };
            
            activeBounties[target.userID] = bounty;
            SaveData();
            
            // Add map marker
            if (config.ShowBountyOnMap)
            {
                AddOrUpdateBountyMarker(target);
            }
            
            // Announce
            if (config.AnnounceNewBounty)
            {
                string message = $"<color=red>⚠️ BOUNTY PLACED!</color> <color=orange>{target.displayName}</color> now has a <color=yellow>{amount} scrap</color> bounty on their head!";
                Server.Broadcast(message);
            }
            
            // Visual effect
            Effect.server.Run("assets/prefabs/locks/keylock/effects/lock.code.updated.prefab", target.transform.position, Vector3.zero);
            
            // Notify target
            SendReply(target, $"<color=red>⚠️ A bounty of {amount} scrap has been placed on your head by {placer.displayName}!</color>");
            SendReply(target, $"<color=yellow>Survive {config.BountyExpiryHours} hours to remove it, or someone will claim it!</color>");
            
            SendReply(placer, $"<color=green>✅ Bounty of {amount} scrap placed on {target.displayName}!</color>");
            
            Puts($"Bounty placed: {target.displayName} ({target.userID}) for {amount} scrap by {placer.displayName}");
            
            return true;
        }
        #endregion

        #region Commands
        [ChatCommand("bounty")]
        private void cmdBounty(BasePlayer player, string command, string[] args)
        {
            if (args.Length == 0)
            {
                ShowBountyHelp(player);
                return;
            }
            
            switch (args[0].ToLower())
            {
                case "place":
                case "set":
                    if (args.Length < 3)
                    {
                        SendReply(player, "Usage: /bounty place <playerName> <amount>");
                        return;
                    }
                    
                    var targetName = args[1];
                    if (!int.TryParse(args[2], out int amount))
                    {
                        SendReply(player, "Amount must be a number!");
                        return;
                    }
                    
                    var target = BasePlayer.Find(targetName);
                    if (target == null)
                    {
                        SendReply(player, "Player not found!");
                        return;
                    }
                    
                    PlaceBounty(player, target, amount);
                    break;
                    
                case "list":
                    ShowBountyList(player);
                    break;
                    
                case "top":
                    ShowTopHunters(player);
                    break;
                    
                case "stats":
                    ShowMyStats(player);
                    break;
                    
                case "remove":
                    if (args.Length < 2)
                    {
                        SendReply(player, "Usage: /bounty remove <playerName>");
                        return;
                    }
                    
                    if (!player.IsAdmin && !permission.UserHasPermission(player.UserIDString, "bountyhunter.admin"))
                    {
                        SendReply(player, "Only admins can remove bounties!");
                        return;
                    }
                    
                    var removeTarget = BasePlayer.Find(args[1]);
                    if (removeTarget == null)
                    {
                        SendReply(player, "Player not found!");
                        return;
                    }
                    
                    if (activeBounties.ContainsKey(removeTarget.userID))
                    {
                        RemoveBountyMarker(removeTarget.userID);
                        activeBounties.Remove(removeTarget.userID);
                        SaveData();
                        SendReply(player, $"Removed bounty on {removeTarget.displayName}");
                    }
                    else
                    {
                        SendReply(player, "That player has no active bounty");
                    }
                    break;
                    
                default:
                    ShowBountyHelp(player);
                    break;
            }
        }
        
        private void ShowBountyHelp(BasePlayer player)
        {
            SendReply(player, "<color=yellow>=== Bounty Hunter System ===</color>");
            SendReply(player, "/bounty place <name> <amount> - Place bounty on player");
            SendReply(player, "/bounty list - Show active bounties");
            SendReply(player, "/bounty top - Show top hunters");
            SendReply(player, "/bounty stats - Show your hunting stats");
            SendReply(player, $"Min bounty: {config.MinBountyAmount} | Max: {config.MaxBountyAmount}");
            SendReply(player, $"Reward: {config.HunterRewardPercentage}% of bounty amount");
        }
        
        private void ShowBountyList(BasePlayer player)
        {
            if (activeBounties.Count == 0)
            {
                SendReply(player, "<color=yellow>No active bounties at the moment!</color>");
                return;
            }
            
            SendReply(player, "<color=yellow>=== Active Bounties ===</color>");
            foreach (var bounty in activeBounties)
            {
                var target = BasePlayer.FindByID(bounty.Key);
                string status = target != null && target.IsConnected ? "🟢 Online" : "⚫ Offline";
                SendReply(player, $"🔪 {bounty.Value.TargetName} - {bounty.Value.Amount} scrap - Placed by {bounty.Value.PlacedByName} - {status}");
            }
        }
        
        private void ShowTopHunters(BasePlayer player)
        {
            var topHunters = hunterStats.OrderByDescending(h => h.Value.BountiesCollected).Take(10).ToList();
            
            if (topHunters.Count == 0)
            {
                SendReply(player, "<color=yellow>No hunters yet! Be the first!</color>");
                return;
            }
            
            SendReply(player, "<color=yellow>=== Top 10 Bounty Hunters ===</color>");
            int rank = 1;
            foreach (var hunter in topHunters)
            {
                var hunterPlayer = BasePlayer.FindByID(hunter.Key);
                string name = hunterPlayer != null ? hunterPlayer.displayName : hunter.Key.ToString();
                SendReply(player, $"#{rank} - {name} - {hunter.Value.BountiesCollected} kills - {hunter.Value.TotalEarned} scrap earned");
                rank++;
            }
        }
        
        private void ShowMyStats(BasePlayer player)
        {
            if (!hunterStats.ContainsKey(player.userID))
            {
                SendReply(player, "<color=yellow>You haven't collected any bounties yet!</color>");
                return;
            }
            
            var stats = hunterStats[player.userID];
            SendReply(player, "<color=yellow>=== Your Hunter Stats ===</color>");
            SendReply(player, $"🔪 Bounties collected: {stats.BountiesCollected}");
            SendReply(player, $"💰 Total earned: {stats.TotalEarned} scrap");
            SendReply(player, $"🔥 Current streak: {stats.CurrentStreak}");
            SendReply(player, $"🏆 Best streak: {stats.BestStreak}");
        }
        
        [ConsoleCommand("bounty.reload")]
        private void cmdReload(ConsoleSystem.Arg args)
        {
            if (args.Connection != null && !permission.UserHasPermission(args.Connection.UserId.ToString(), "bountyhunter.admin"))
            {
                args.ReplyWith("No permission");
                return;
            }
            
            LoadConfig();
            LoadData();
            args.ReplyWith("BountyHunter reloaded");
            Puts("BountyHunter configuration reloaded");
        }
        
        [ConsoleCommand("bounty.clearall")]
        private void cmdClearAll(ConsoleSystem.Arg args)
        {
            if (args.Connection != null && !permission.UserHasPermission(args.Connection.UserId.ToString(), "bountyhunter.admin"))
            {
                args.ReplyWith("No permission");
                return;
            }
            
            foreach (var bounty in activeBounties)
            {
                RemoveBountyMarker(bounty.Key);
            }
            
            activeBounties.Clear();
            SaveData();
            args.ReplyWith("All bounties cleared");
        }
        #endregion
    }
}

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок
Сверху