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

FREE HorseBreeds : 1.2.1 1.2.1

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

namespace Oxide.Plugins
{
    // Lets players change their mounted horse's visual breed (0-9) via chat or admin console.
    // Optional payment: ServerRewards RP, Economics money, a configurable item, or free if all are disabled.
    [Info("Horse Breeds", "iLakSkiL", "1.2.1")]
    [Description("Change the breed of your horse.")]
    public class HorseBreeds : RustPlugin
    {
        // Soft dependencies — only used when the matching config flag is true.
        [PluginReference]
        private Plugin ServerRewards, Economics;

        #region Configuration

        private Configuration _config;

        // Maps to oxide/config/HorseBreeds.json. Only one currency mode should be enabled at a time.
        public class Configuration
        {
            [JsonProperty(PropertyName = "Use ServerRewards")]
            public bool currencySR = false;

            [JsonProperty(PropertyName = "Use Economics")]
            public bool currencyEC = false;

            [JsonProperty(PropertyName = "Use Item as Currency")]
            public bool currencyItem = false;

            // Item shortname (e.g. "scrap") when currencyItem is true.
            [JsonProperty(PropertyName = "Item Short Name")]
            public string itemToUse = "scrap";

            [JsonProperty(PropertyName = "Horse Breed Costs")]
            public Costs costs = new Costs();

            // cost0-cost9 align with RidableHorse breed indices (see /horse help).
            public class Costs
            {
                [JsonProperty(PropertyName = "Dapple Grey")]
                public double cost4 = 20;

                [JsonProperty(PropertyName = "Red Roan")]
                public double cost7 = 20;

                [JsonProperty(PropertyName = "Appalosa")]
                public double cost0 = 30;

                [JsonProperty(PropertyName = "Bay")]
                public double cost1 = 30;

                [JsonProperty(PropertyName = "Buckskin")]
                public double cost2 = 30;

                [JsonProperty(PropertyName = "Pinto")]
                public double cost6 = 30;

                [JsonProperty(PropertyName = "Chestnut")]
                public double cost3 = 40;

                [JsonProperty(PropertyName = "Piebald")]
                public double cost5 = 40;

                [JsonProperty(PropertyName = "White Thoroughbred")]
                public double cost8 = 50;

                [JsonProperty(PropertyName = "Black Thoroughbred")]
                public double cost9 = 50;
            }
        }

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                _config = Config.ReadObject<Configuration>();
                if (_config == null)
                    throw new JsonException("Config deserialized to null.");
                SaveConfig();
            }
            catch (Exception ex)
            {
                // Fall back so commands never run with a null _config reference.
                PrintError($"Error reading config: {ex.Message}. Loading default config.");
                LoadDefaultConfig();
            }
        }

        protected override void LoadDefaultConfig()
        {
            _config = new Configuration();
            Puts("Loading Default Config");
            SaveConfig();
        }

        protected override void SaveConfig() => Config.WriteObject(_config);

        #endregion

        #region Hooks

        private void Loaded()
        {
            // horsebreeds.use — required for /horse
            // horsebreeds.bypass — skips payment (grant to admins/VIPs as needed)
            permission.RegisterPermission("horsebreeds.use", this);
            permission.RegisterPermission("horsebreeds.bypass", this);

            if (_config == null)
            {
                LoadDefaultConfig();
                return;
            }

            // Enforce a single payment method; conflicting flags reset the config.
            if ((_config.currencySR && _config.currencyEC) || (_config.currencySR && _config.currencyItem) || (_config.currencyItem && _config.currencyEC))
            {
                Puts("ERROR: Cannot use more than one currency type. Default config loaded.");
                LoadDefaultConfig();
            }

            if (_config.currencyItem && string.IsNullOrWhiteSpace(_config.itemToUse))
            {
                Puts("ERROR: Item Short Name listed as currency is not valid. Default config loaded.");
                LoadDefaultConfig();
            }
        }

        #endregion

        #region Commands

        // In-game: /horse help  |  /horse <breed name or 0-9>
        [ChatCommand("horse")]
        private void horseChatCmd(BasePlayer player, string command, string[] args)
        {
            if (player == null)
                return;

            if (!permission.UserHasPermission(player.UserIDString, "horsebreeds.use"))
            {
                Player.Message(player, "Horse Breeds:You do not have permission to use this command.");
                return;
            }

            // Exactly one argument: either "help" or a breed identifier.
            if (args == null || args.Length != 1)
            {
                Player.Message(player, "Horse Breeds: Syntax Error. Use \"/horse help\" for more info.");
                return;
            }

            if (args[0].Equals("help", StringComparison.OrdinalIgnoreCase))
            {
                SendHelp(player);
                return;
            }

            if (!TryGetMountedHorse(player, out var horse))
            {
                Player.Message(player, "Horse Breeds:You must be on a horse to use this command.");
                return;
            }

            if (!IsValidBreed(args[0], out int breed, out string breedName, out double cost))
            {
                Player.Message(player, "Horse Breeds: Invalid Breed. Use \"/horse help\" for more info.");
                return;
            }

            if (permission.UserHasPermission(player.UserIDString, "horsebreeds.bypass"))
                cost = 0;

            ChangeHorse(player, horse, breed, breedName, cost);
        }

        // Server console or admin client: horse <player> <breed>
        [ConsoleCommand("horse")]
        private void horseConsoleCmd(ConsoleSystem.Arg arg)
        {
            // arg.Connection == null means dedicated server console (always allowed).
            if (arg.Connection != null && !arg.IsAdmin)
                return;

            if (arg.Args == null || arg.Args.Length != 2)
            {
                Puts("Syntax: horse <player> <breed>");
                return;
            }

            var target = RustCore.FindPlayer(arg.Args[0].ToString());
            if (target == null)
            {
                Puts($"Player '{arg.Args[0]}' not found");
                return;
            }

            if (!target.IsConnected)
            {
                Puts($"Player '{arg.Args[0]}' is not online");
                return;
            }

            if (!TryGetMountedHorse(target, out var horse))
            {
                Puts($"Player '{arg.Args[0]}' is not on a horse");
                return;
            }

            if (!IsValidBreed(arg.Args[1].ToString(), out int breed, out string breedName, out double cost))
            {
                Puts("Invalid breed type");
                return;
            }

            if (permission.UserHasPermission(target.UserIDString, "horsebreeds.bypass"))
                cost = 0;

            ChangeHorse(target, horse, breed, breedName, cost);
        }

        #endregion

        #region Helpers

        // Lists all breeds and prices; currency label reflects the active payment mode.
        private void SendHelp(BasePlayer player)
        {
            string currency = "free";
            if (_config.currencySR)
                currency = "RP";
            else if (_config.currencyEC)
                currency = "Dollars";
            else if (_config.currencyItem)
                currency = _config.itemToUse;

            Player.Message(player,
                "Horse Breeds:\n\nTo change the breed of your horse, use \"/horse (breed)\" while sitting on a horse. (breed) can either be the name or the numerical value of the breed below.\n\n" +
                "Breed # - Breed Name - Cost\n" +
                $"0 - Appalosa - {_config.costs.cost0} {currency}\n" +
                $"1 - Bay - {_config.costs.cost1} {currency}\n" +
                $"2 - Buckskin - {_config.costs.cost2} {currency}\n" +
                $"3 - Chestnut - {_config.costs.cost3} {currency}\n" +
                $"4 - Dapple Grey - {_config.costs.cost4} {currency}\n" +
                $"5 - Piebald - {_config.costs.cost5} {currency}\n" +
                $"6 - Pinto - {_config.costs.cost6} {currency}\n" +
                $"7 - Red Roan - {_config.costs.cost7} {currency}\n" +
                $"8 - White Thoroughbred - {_config.costs.cost8} {currency}\n" +
                $"9 - Black Thoroughbred - {_config.costs.cost9} {currency}");
        }

        // GetMountedVehicle returns the vehicle parent; horses are RidableHorse (not the old RidableHorse2 type).
        private static bool TryGetMountedHorse(BasePlayer player, out RidableHorse horse)
        {
            horse = player.GetMountedVehicle() as RidableHorse;
            return horse != null;
        }

        // currentBreedIndex is private on RidableHorse — compare breed assets via GetBreed() instead.
        private static bool IsSameBreed(RidableHorse horse, int breedIndex)
        {
            if (horse.breeds == null || breedIndex < 0 || breedIndex >= horse.breeds.Length)
                return false;

            var current = horse.GetBreed();
            return current != null && current == horse.breeds[breedIndex];
        }

        // Charges the player (if configured), then calls horse.SetBreed(index) on the game entity.
        private void ChangeHorse(BasePlayer player, RidableHorse horse, int breed, string breedName, double cost)
        {
            if (horse == null)
            {
                Player.Message(player, "Horse Breeds:You must be on a horse to use this command.");
                return;
            }

            if (IsSameBreed(horse, breed))
            {
                Player.Message(player, $"Horse Breeds: Your horse is already a {breedName}");
                return;
            }

            // --- ServerRewards (RP points) ---
            if (_config.currencySR)
            {
                if (ServerRewards == null)
                {
                    Player.Message(player, "Horse Breeds: ServerRewards is not loaded.");
                    return;
                }

                var balanceObj = ServerRewards.Call("CheckPoints", player.userID);
                if (balanceObj == null)
                {
                    Player.Message(player, "Horse Breeds: Could not read ServerRewards balance.");
                    return;
                }

                int balance = Convert.ToInt32(balanceObj);
                if (balance < cost)
                {
                    Player.Message(player, "Horse Breeds: Insufficient balance");
                    return;
                }

                horse.SetBreed(breed);
                if (cost > 0)
                    ServerRewards.Call("TakePoints", player.userID, (int)Math.Round(cost));

                Player.Message(player, $"Horse Breeds: Your horse is now a {breedName}");
                Puts($"{player.displayName}'s horse breed has been changed to {breedName}.");
                return;
            }

            // --- Economics (money) ---
            if (_config.currencyEC)
            {
                if (Economics == null)
                {
                    Player.Message(player, "Horse Breeds: Economics is not loaded.");
                    return;
                }

                var balanceObj = Economics.Call("Balance", player.userID);
                if (balanceObj == null)
                {
                    Player.Message(player, "Horse Breeds: Could not read Economics balance.");
                    return;
                }

                double balance = Convert.ToDouble(balanceObj);
                if (balance < cost)
                {
                    Player.Message(player, "Horse Breeds: Insufficient balance");
                    return;
                }

                horse.SetBreed(breed);
                if (cost > 0)
                    Economics.Call("Withdraw", player.userID, cost);

                Player.Message(player, $"Horse Breeds: Your horse is now a {breedName}");
                Puts($"{player.displayName}'s horse breed has been changed to {breedName}.");
                return;
            }

            // --- Item currency (searches belt, main, wear via PlayerInventory) ---
            if (_config.currencyItem)
            {
                var item = player.inventory.FindItemByItemName(_config.itemToUse);
                if (item == null)
                {
                    Player.Message(player, "Horse Breeds: Insufficient balance");
                    return;
                }

                int itemAmount = player.inventory.GetAmount(item.info.itemid);
                int amountToTake = (int)Math.Round(cost);
                if (amountToTake > itemAmount)
                {
                    Player.Message(player, "Horse Breeds: Insufficient balance");
                    return;
                }

                var taken = new List<Item>();
                int removed = player.inventory.Take(taken, item.info.itemid, amountToTake);
                // Only apply breed if the full cost was removed (Take can partially fail).
                if (removed < amountToTake)
                {
                    Player.Message(player, "Horse Breeds: Insufficient balance");
                    return;
                }

                horse.SetBreed(breed);
                Player.Message(player, $"Horse Breeds: Your horse is now a {breedName}");
                Puts($"{player.displayName}'s horse breed has been changed to {breedName}.");
                return;
            }

            // --- No currency enabled: free breed change ---
            horse.SetBreed(breed);
            Player.Message(player, $"Horse Breeds: Your horse is now a {breedName}");
            Puts($"{player.displayName}'s horse breed has been changed to {breedName}.");
        }

        // Parses user input (number or name) into breed index, display name, and config cost.
        private bool IsValidBreed(string option, out int breed, out string breedName, out double cost)
        {
            breed = -1;
            breedName = null;
            cost = 0;

            if (string.IsNullOrWhiteSpace(option))
                return false;

            var key = option.Trim().ToLowerInvariant();

            // Numeric shorthand: /horse 3
            if (int.TryParse(key, out int index) && TryGetBreedByIndex(index, out breed, out breedName, out cost))
                return true;

            // Name aliases (exact match on normalized string to avoid false positives).
            if (key == "appalosa" || key == "appaloosa")
                return TryGetBreedByIndex(0, out breed, out breedName, out cost);
            if (key == "bay")
                return TryGetBreedByIndex(1, out breed, out breedName, out cost);
            if (key == "buckskin")
                return TryGetBreedByIndex(2, out breed, out breedName, out cost);
            if (key == "chestnut")
                return TryGetBreedByIndex(3, out breed, out breedName, out cost);
            if (key == "dapple" || key == "dapple grey" || key == "dapplegray" || key == "dapple gray")
                return TryGetBreedByIndex(4, out breed, out breedName, out cost);
            if (key == "piebald")
                return TryGetBreedByIndex(5, out breed, out breedName, out cost);
            if (key == "pinto")
                return TryGetBreedByIndex(6, out breed, out breedName, out cost);
            if (key == "red roan" || key == "redroan")
                return TryGetBreedByIndex(7, out breed, out breedName, out cost);
            if (key == "white thoroughbred" || key == "white")
                return TryGetBreedByIndex(8, out breed, out breedName, out cost);
            if (key == "black thoroughbred" || key == "black")
                return TryGetBreedByIndex(9, out breed, out breedName, out cost);

            return false;
        }

        // Maps game breed index 0-9 to display name and cost from config.
        private bool TryGetBreedByIndex(int index, out int breed, out string breedName, out double cost)
        {
            breed = index;
            breedName = null;
            cost = 0;

            switch (index)
            {
                case 0:
                    breedName = "Appalosa";
                    cost = _config.costs.cost0;
                    return true;
                case 1:
                    breedName = "Bay";
                    cost = _config.costs.cost1;
                    return true;
                case 2:
                    breedName = "Buckskin";
                    cost = _config.costs.cost2;
                    return true;
                case 3:
                    breedName = "Chestnut";
                    cost = _config.costs.cost3;
                    return true;
                case 4:
                    breedName = "Dapple Grey";
                    cost = _config.costs.cost4;
                    return true;
                case 5:
                    breedName = "Piebald";
                    cost = _config.costs.cost5;
                    return true;
                case 6:
                    breedName = "Pinto";
                    cost = _config.costs.cost6;
                    return true;
                case 7:
                    breedName = "Red Roan";
                    cost = _config.costs.cost7;
                    return true;
                case 8:
                    breedName = "White Thoroughbred";
                    cost = _config.costs.cost8;
                    return true;
                case 9:
                    breedName = "Black Thoroughbred";
                    cost = _config.costs.cost9;
                    return true;
                default:
                    return false;
            }
        }

        #endregion
    }
}

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