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

FREE LandClaimSystem : 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;
using Random = System.Random;

namespace Oxide.Plugins
{
    [Info("Land Claim System", "0killrest", "1.0.0")]
    [Description("Players can buy land plots with bonuses and passive income")]
    internal class LandClaimSystem : RustPlugin
    {
        #region Configuration
        private static ConfigData config;
        
        private class ConfigData
        {
            public bool Enabled { get; set; } = true;
            public float PlotSize { get; set; } = 50f;
            public int PlotCost { get; set; } = 5000;
            public float DamageReductionPercent { get; set; } = 50f;
            public float PassiveIncomeScrapPerHour { get; set; } = 100f;
            public int MaxPlotsPerPlayer { get; set; } = 1;
            public int MaxPlotsPerClan { get; set; } = 3;
            public bool AllowPlotTrading { get; set; } = true;
            public bool ShowPlotBoundaries { get; set; } = true;
            
            public ConfigData() { }
        }
        
        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/LandClaimSystem.json");
            SaveConfig();
        }
        
        protected override void SaveConfig() => Config.WriteObject(config);
        #endregion

        #region Data Storage
        private Dictionary<ulong, List<LandPlot>> playerPlots = new Dictionary<ulong, List<LandPlot>>();
        private Dictionary<string, LandPlot> plotsByPosition = new Dictionary<string, LandPlot>();
        
        private class LandPlot
        {
            public ulong OwnerId { get; set; }
            public string OwnerName { get; set; }
            public Vector3 Center { get; set; }
            public float Radius { get; set; }
            public DateTime PurchaseDate { get; set; }
            public float LastIncomeTime { get; set; }
            public List<ulong> SharedWith { get; set; } = new List<ulong>();
        }
        
        private void LoadData()
        {
            playerPlots = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<ulong, List<LandPlot>>>("LandClaim_Plots") ?? new Dictionary<ulong, List<LandPlot>>();
            
            // Rebuild position index
            plotsByPosition.Clear();
            foreach (var plots in playerPlots.Values)
            {
                foreach (var plot in plots)
                {
                    string key = GetPlotKey(plot.Center);
                    plotsByPosition[key] = plot;
                }
            }
        }
        
        private void SaveData()
        {
            Interface.Oxide.DataFileSystem.WriteObject("LandClaim_Plots", playerPlots);
        }
        
        private string GetPlotKey(Vector3 position)
        {
            int gridX = Mathf.FloorToInt(position.x / config.PlotSize);
            int gridZ = Mathf.FloorToInt(position.z / config.PlotSize);
            return $"{gridX}_{gridZ}";
        }
        #endregion

        #region Hooks
        private void Init()
        {
            LoadData();
            permission.RegisterPermission("landclaim.admin", this);
            permission.RegisterPermission("landclaim.extraplot", this); // Allows extra plot
        }
        
        private void OnServerInitialized()
        {
            if (config.Enabled)
            {
                // Start passive income timer
                timer.Repeat(3600f, 0, () => DistributePassiveIncome());
                
                // Show boundaries to players (if enabled)
                if (config.ShowPlotBoundaries)
                {
                    timer.Repeat(30f, 0, () => UpdateBoundariesForAll());
                }
            }
        }
        
        private void Unload()
        {
            SaveData();
        }
        
        private void OnServerSave() => SaveData();
        
        private void OnEntityTakeDamage(BuildingBlock block, HitInfo info)
        {
            if (!config.Enabled) return;
            if (info == null) return;
            
            // Get plot at block position
            var plot = GetPlotAtPosition(block.transform.position);
            if (plot == null) return;
            
            // Check if attacker is owner or shared
            bool isOwner = info.InitiatorPlayer != null && (plot.OwnerId == info.InitiatorPlayer.userID || plot.SharedWith.Contains(info.InitiatorPlayer.userID));
            
            if (!isOwner)
            {
                // Apply damage reduction for non-owners
                info.damageTypes.ScaleAll(1f - (config.DamageReductionPercent / 100f));
                
                // Send notification to owner
                var owner = BasePlayer.FindByID(plot.OwnerId);
                if (owner != null && owner.IsConnected)
                {
                    SendReply(owner, $"<color=red>⚠️ Your land at {GetGridPosition(plot.Center)} is under attack!</color>");
                }
            }
        }
        
        private void DistributePassiveIncome()
        {
            if (!config.Enabled || config.PassiveIncomeScrapPerHour <= 0) return;
            
            foreach (var plot in GetAllPlots())
            {
                var owner = BasePlayer.FindByID(plot.OwnerId);
                if (owner != null && owner.IsConnected)
                {
                    int scrapAmount = (int)config.PassiveIncomeScrapPerHour;
                    Item scrap = ItemManager.Create(ItemManager.FindItemDefinition("scrap"), scrapAmount);
                    if (scrap != null && owner.inventory.GiveItem(scrap))
                    {
                        SendReply(owner, $"<color=green>🏆 Land income! You received {scrapAmount} scrap from your territory.</color>");
                    }
                }
            }
        }
        
        private void UpdateBoundariesForAll()
        {
            if (!config.ShowPlotBoundaries) return;
            
            foreach (var player in BasePlayer.activePlayerList)
            {
                // Show boundaries of plots near player
                foreach (var plot in GetAllPlots())
                {
                    if (Vector3.Distance(player.transform.position, plot.Center) < config.PlotSize + 50f)
                    {
                        ShowPlotBoundary(player, plot);
                    }
                }
            }
        }
        
        private void ShowPlotBoundary(BasePlayer player, LandPlot plot)
        {
            // Simple boundary visualization using effect
            Color color = plot.OwnerId == player.userID ? Color.green : Color.red;
            
            // Draw circle effect (visual only)
            // Note: Full boundary visualization would require more complex rendering
        }
        #endregion

        #region Core Logic
        private string GetGridPosition(Vector3 position)
        {
            int gridSize = 10;
            float mapSize = TerrainMeta.Size.x;
            float cellSize = mapSize / gridSize;
            
            char xChar = (char)('A' + Mathf.FloorToInt(position.x / cellSize));
            int zNum = Mathf.FloorToInt(position.z / cellSize) + 1;
            
            return $"{xChar}{zNum}";
        }
        
        private LandPlot GetPlotAtPosition(Vector3 position)
        {
            string key = GetPlotKey(position);
            return plotsByPosition.ContainsKey(key) ? plotsByPosition[key] : null;
        }
        
        private IEnumerable<LandPlot> GetAllPlots()
        {
            return playerPlots.Values.SelectMany(p => p);
        }
        
        private int GetPlayerPlotCount(ulong userId)
        {
            return playerPlots.ContainsKey(userId) ? playerPlots[userId].Count : 0;
        }
        
        private bool CanBuyPlot(BasePlayer player, Vector3 position)
        {
            // Check max plots
            int maxPlots = config.MaxPlotsPerPlayer;
            if (permission.UserHasPermission(player.UserIDString, "landclaim.extraplot"))
            {
                maxPlots += 1;
            }
            
            if (GetPlayerPlotCount(player.userID) >= maxPlots)
            {
                SendReply(player, $"<color=red>You already own the maximum number of plots ({maxPlots})!</color>");
                return false;
            }
            
            // Check if position is already claimed
            var existingPlot = GetPlotAtPosition(position);
            if (existingPlot != null)
            {
                SendReply(player, $"<color=red>This area is already claimed by {existingPlot.OwnerName}!</color>");
                return false;
            }
            
            // Check if player has enough scrap
            if (player.inventory.GetAmount(ItemManager.FindItemDefinition("scrap")) < config.PlotCost)
            {
                SendReply(player, $"<color=red>You need {config.PlotCost} scrap to buy a land plot!</color>");
                return false;
            }
            
            return true;
        }
        
        private bool BuyPlot(BasePlayer player, Vector3 position)
        {
            if (!CanBuyPlot(player, position)) return false;
            
            // Deduct scrap
            player.inventory.Take(null, ItemManager.FindItemDefinition("scrap").itemid, config.PlotCost);
            
            // Create plot
            var plot = new LandPlot
            {
                OwnerId = player.userID,
                OwnerName = player.displayName,
                Center = position,
                Radius = config.PlotSize,
                PurchaseDate = DateTime.UtcNow,
                LastIncomeTime = Time.realtimeSinceStartup
            };
            
            if (!playerPlots.ContainsKey(player.userID))
            {
                playerPlots[player.userID] = new List<LandPlot>();
            }
            
            playerPlots[player.userID].Add(plot);
            string key = GetPlotKey(position);
            plotsByPosition[key] = plot;
            
            SaveData();
            
            SendReply(player, $"<color=green>✅ You purchased a land plot at {GetGridPosition(position)} for {config.PlotCost} scrap!</color>");
            SendReply(player, $"<color=yellow>Benefits: {config.DamageReductionPercent}% damage reduction to your buildings, {config.PassiveIncomeScrapPerHour} scrap/hour passive income.</color>");
            
            // Visual effect
            Effect.server.Run("assets/prefabs/locks/keylock/effects/lock.code.updated.prefab", position, Vector3.zero);
            
            return true;
        }
        #endregion

        #region Commands
        [ChatCommand("land")]
        private void cmdLand(BasePlayer player, string command, string[] args)
        {
            if (args.Length == 0)
            {
                SendReply(player, "<color=yellow>=== Land Claim System ===</color>");
                SendReply(player, "/land buy - Buy the land you're standing on");
                SendReply(player, "/land info - Show info about current land");
                SendReply(player, "/land my - List your land plots");
                SendReply(player, "/land share <name> - Share land with another player");
                SendReply(player, "/land unshare <name> - Remove player from shared access");
                return;
            }
            
            switch (args[0].ToLower())
            {
                case "buy":
                    BuyPlot(player, player.transform.position);
                    break;
                    
                case "info":
                    var plot = GetPlotAtPosition(player.transform.position);
                    if (plot == null)
                    {
                        SendReply(player, "<color=yellow>This land is unclaimed.Use /land buy to claim it!</color>");
                        SendReply(player, $"Cost: {config.PlotCost} scrap | Size: {config.PlotSize}m");
                    }
                    else
                    {
                        SendReply(player, $"<color=green>=== Land Info ===</color>");
                        SendReply(player, $"Owner: {plot.OwnerName}");
                        SendReply(player, $"Location: {GetGridPosition(plot.Center)}");
                        SendReply(player, $"Purchased: {plot.PurchaseDate:yyyy-MM-dd}");
                        SendReply(player, $"Shared with: {(plot.SharedWith.Count > 0 ? plot.SharedWith.Count.ToString() : "None")}");
                    }
                    break;
                    
                case "my":
                    if (playerPlots.ContainsKey(player.userID) && playerPlots[player.userID].Count > 0)
                    {
                        SendReply(player, "<color=green>=== Your Land Plots ===</color>");
                        foreach (var p in playerPlots[player.userID])
                        {
                            SendReply(player, $"📍 {GetGridPosition(p.Center)} - {p.Radius}m radius");
                        }
                    }
                    else
                    {
                        SendReply(player, "You don't own any land yet.Use /land buy");
                    }
                    break;
                    
                case "share":
                    if (args.Length < 2)
                    {
                        SendReply(player, "Usage: /land share <playerName>");
                        return;
                    }
                    
                    var targetPlayer = BasePlayer.Find(args[1]);
                    if (targetPlayer == null)
                    {
                        SendReply(player, "Player not found");
                        return;
                    }
                    
                    var currentPlot = GetPlotAtPosition(player.transform.position);
                    if (currentPlot == null || currentPlot.OwnerId != player.userID)
                    {
                        SendReply(player, "You don't own this land!");
                        return;
                    }
                    
                    if (!currentPlot.SharedWith.Contains(targetPlayer.userID))
                    {
                        currentPlot.SharedWith.Add(targetPlayer.userID);
                        SaveData();
                        SendReply(player, $"<color=green>Added {targetPlayer.displayName} to your land!</color>");
                        SendReply(targetPlayer, $"<color=green>{player.displayName} shared their land with you!</color>");
                    }
                    break;
                    
                case "unshare":
                    if (args.Length < 2)
                    {
                        SendReply(player, "Usage: /land unshare <playerName>");
                        return;
                    }
                    
                    var removePlayer = BasePlayer.Find(args[1]);
                    if (removePlayer == null)
                    {
                        SendReply(player, "Player not found");
                        return;
                    }
                    
                    var plotToUnshare = GetPlotAtPosition(player.transform.position);
                    if (plotToUnshare == null || plotToUnshare.OwnerId != player.userID)
                    {
                        SendReply(player, "You don't own this land!");
                        return;
                    }
                    
                    if (plotToUnshare.SharedWith.Remove(removePlayer.userID))
                    {
                        SaveData();
                        SendReply(player, $"<color=yellow>Removed {removePlayer.displayName} from your land.</color>");
                    }
                    break;
            }
        }
        
        [ConsoleCommand("land.give")]
        private void cmdGiveLand(ConsoleSystem.Arg args)
        {
            if (args.Connection != null && !permission.UserHasPermission(args.Connection.UserId.ToString(), "landclaim.admin"))
            {
                args.ReplyWith("No permission");
                return;
            }
            
            if (args.Args == null || args.Args.Length < 3)
            {
                args.ReplyWith("Usage: land.give <steamID> <x> <z>");
                return;
            }
            
            ulong steamId = Convert.ToUInt64(args.Args[0]);
            float x = Convert.ToSingle(args.Args[1]);
            float z = Convert.ToSingle(args.Args[2]);
            float y = TerrainMeta.HeightMap.GetHeight(new Vector3(x, 0, z));
            
            var player = BasePlayer.FindByID(steamId);
            if (player == null)
            {
                args.ReplyWith("Player not found");
                return;
            }
            
            var plot = new LandPlot
            {
                OwnerId = steamId,
                OwnerName = player.displayName,
                Center = new Vector3(x, y, z),
                Radius = config.PlotSize,
                PurchaseDate = DateTime.UtcNow,
                LastIncomeTime = Time.realtimeSinceStartup
            };
            
            if (!playerPlots.ContainsKey(steamId))
            {
                playerPlots[steamId] = new List<LandPlot>();
            }
            
            playerPlots[steamId].Add(plot);
            string key = GetPlotKey(plot.Center);
            plotsByPosition[key] = plot;
            SaveData();
            
            args.ReplyWith($"Gave land plot at ({x}, {z}) to {player.displayName}");
        }
        
        [ConsoleCommand("land.reload")]
        private void cmdReload(ConsoleSystem.Arg args)
        {
            if (args.Connection != null && !permission.UserHasPermission(args.Connection.UserId.ToString(), "landclaim.admin"))
            {
                args.ReplyWith("No permission");
                return;
            }
            
            LoadConfig();
            LoadData();
            args.ReplyWith("LandClaimSystem reloaded");
        }
        #endregion
    }
}

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