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

FREE RustySkills : 1.1.13 1.1.13

Нет прав для скачивания
C#:
using System.Collections.Generic;
using Oxide.Game.Rust.Cui;
using Newtonsoft.Json;
using Oxide.Core;
using System.IO;
using Rust;
using Oxide.Core.Libraries.Covalence;
using UnityEngine;
using System;
using System.Linq;
using System.Globalization;
using Oxide.Core.Plugins;
namespace Oxide.Plugins {
    [Info("RustySkills", "__red", "1.1.13")]
    class RustySkills : RustPlugin {
        /// <summary>
        /// Имитирует одну секунду для таймеров./// </summary>
        private const int ONE_SECOND_IMIT = 1;
        /// <summary>
        /// Имитирует числовой нуль
        /// </summary>
        private const int INT_NULL = 0;
        [PluginReference]
        private Plugin ImageLibrary;
#region Config
        /// <summary>
        /// Объект конфигурации плагина
        /// </summary>
        private class PluginConfig {
            /// <summary>
            /// Префикс чата для плагина
            /// </summary>
            [JsonProperty("CFG_PLUGIN_CHAT_PREFIX")]
            public string CHAT_PREFIX;
            /// <summary>
            /// Цвет префикса чата для плагина
            /// </summary>
            [JsonProperty("CFG_PLUGIN_CHAT_PREFIX_COLOR")]
            public string CHAT_PREFIX_COLOR;
            /// <summary>
            /// Максимальный уровень умений
            /// </summary>
            [JsonProperty("CFG_SPELL_MAX_LEVEL")]
            public int MAX_LEVEL;
            /// <summary>
            /// Минимальный уровень умений
            /// </summary>
            [JsonProperty("CFG_SPELL_MIN_LEVEL")]
            public int MIN_LEVEL;
            /// <summary>
            /// Модификатор сложности улучшения умений
            /// </summary>
            [JsonProperty("CFG_SPELL_EXP_MOD")]
            public int EXP_MODIFIER;
            /// <summary>
            /// Время в секундах для отката умений при их переключении
            /// </summary>
            [JsonProperty("CFG_SWITCH_COLDOWN_DEFAULT")]
            public int SWITCH_COLDOWN_DEAFULT;
            /// <summary>
            /// Время в секундах для отображения экстра информации (уворот, критический удар)
            /// </summary>
            [JsonProperty("CFG_EXTRA_SHOW_TIME")]
            public int EXTRA_SHOW_TIMER;
            /// <summary>
            /// Возвращает экземпляр создания нового класса конфигурации
            /// </summary>
            /// <returns></returns>
            public static PluginConfig CreateDefault() {
                return new PluginConfig() {
                    CHAT_PREFIX = "[RS]: ", CHAT_PREFIX_COLOR = "#ff00dd4f", MAX_LEVEL = 5, MIN_LEVEL = 1, EXP_MODIFIER = 10, SWITCH_COLDOWN_DEAFULT = 15, EXTRA_SHOW_TIMER = 2,
                }
                ;
            }
        }
        /// <summary>
        /// Сохраняет конфигурацию плагина
        /// </summary>
        protected override void SaveConfig() {
            Config.WriteObject(_Config);
        }
        /// <summary>
        /// Загрудает конфигурацию плагина
        /// </summary>
        protected override void LoadConfig() {
            base.LoadConfig();
            _Config = Config.ReadObject<PluginConfig>();
        }
        /// <summary>
        /// Загружает конфигурацию плагина по умолчанию
        /// </summary>
        protected override void LoadDefaultConfig() {
            PrintWarning("Plugin created a new config file !", this);
            _Config = PluginConfig.CreateDefault();
        }
#endregion
#region Spell Data Types
        /// <summary>
        /// Перечисление.Указывает на тип умения
        /// </summary>
        public enum SpellType {
            /// <summary>
            /// Пустой тип
            /// </summary>
            Empty = -1,  /// <summary>
            /// Умение на модификацию урона
            /// </summary>
            Damage = 0,  /// <summary>
            /// Умение на блокирование некоторого урона
            /// </summary>
            Defense = 1,  /// <summary>
            /// Умение на нанесение критического удара
            /// </summary>
            Critical = 2,  /// <summary>
            /// Умение на уворот от полученного урона
            /// </summary>
            Evasion = 4,  /// <summary>
            /// Умение на возврат урона
            /// </summary>
            Spike = 5,  /// <summary>
            /// Умение на восстановление жизни от нанесенного урона
            /// </summary>
            Vampiric = 6
        }
        /// <summary>
        /// Главный класс оболочка для умений
        /// </summary>
        public class Spell {
            /// <summary>
            /// Возвращает информацию об эффекте умения
            /// </summary>
            public SpellEffect Effect {
                get;
                set;
            }
            /// <summary>
            /// Возвращает информацию об умении
            /// </summary>
            public SpellData Data {
                get;
                set;
            }
            /// <summary>
            /// Возвращает информацию об уровне умения
            /// </summary>
            public SpellLevel Level {
                get;
                set;
            }
            /// <summary>
            /// Конструктор по умолчанию
            /// </summary>
            public Spell() {
                Effect = new SpellEffect();
                Data = new SpellData();
                Level = new SpellLevel();
            }
            /// <summary>
            /// Конструктор по умолчанию с иньекцией кода
            /// </summary>
            /// <param name="effect">Экземпляр эффекта</param>
            /// <param name="data">Экземпляр данных</param>
            /// <param name="level">Экземпляр уровня</param>
            public Spell(SpellEffect effect, SpellData data, SpellLevel level) {
                Effect = effect;
                Data = data;
                Level = level;
            }
            /// <summary>
            /// Метод - прототип./// Создает новый экземпляр умения с указанными параметрами
            /// </summary>
            /// <param name="effect">Экземпляр эффекта</param>
            /// <param name="data">Экземпляр данных</param>
            /// <param name="level">Экземпляр уровня</param>
            /// <returns></returns>
            public static Spell Create(SpellEffect effect, SpellData data, SpellLevel level) {
                return new Spell(effect, data, level);
            }
        }
        /// <summary>
        /// Структура эффектов умения
        /// </summary>
        public class SpellEffect {
            /// <summary>
            /// Возвращает тип умения
            /// </summary>
            public SpellType EffectType {
                get;
                set;
            }
            /// <summary>
            /// Возвращает текущий бонус умения
            /// </summary>
            public int CurrentBonus {
                get;
                set;
            }
            /// <summary>
            /// Возвращает следующий бонус умения
            /// </summary>
            public int NextBonus {
                get;
                set;
            }
            /// <summary>
            /// Возвращает коллекцию бонусов умения на разных уровнях
            /// </summary>
            public Dictionary<int, float> BonusCollection {
                get;
                set;
            }
            /// <summary>
            /// Конструктор по умолчанию
            /// </summary>
            public SpellEffect() {
                EffectType = SpellType.Empty;
                CurrentBonus = 0;
                NextBonus = 0;
                BonusCollection = new Dictionary<int, float>();
            }
            /// <summary>
            /// Создает новый экземпляр эффектов умения с указанными параметрами
            /// </summary>
            /// <param name="type">Тип уменя</param>
            /// <param name="cub">Текущий бонус</param>
            /// <param name="neb">Будущий бонус</param>
            /// <param name="collection">Коллекция бонусов</param>
            /// <returns></returns>
            public static SpellEffect Create(SpellType type, int cub, int neb, Dictionary<int, float> collection) {
                return new SpellEffect() {
                    EffectType = type, CurrentBonus = cub, NextBonus = neb, BonusCollection = collection
                }
                ;
            }
            /// <summary>
            /// Создает новый экземпляр эффектов умения по умолчанию
            /// </summary>
            /// <param name="type"></param>
            /// <returns></returns>
            public static SpellEffect CreateDefault(SpellType type) {
                SpellEffect effect = new SpellEffect {
                    EffectType = type, BonusCollection = CreateDefaultBonus()
                }
                ;
                effect.CurrentBonus = effect.CalculateBonus(SpellLevel.MIN_LEVEL);
                effect.NextBonus = effect.CalculateNextBonus(SpellLevel.MIN_LEVEL);
                return effect;
            }
            /// <summary>
            /// Обновляет данные о бонусах
            /// </summary>
            /// <param name="level"></param>
            public void UpdateBonus(int level) {
                CurrentBonus = CalculateBonus(level);
                NextBonus = CalculateNextBonus(level);
            }
            /// <summary>
            /// Пересчитывает следующий бонус согласно уровню
            /// </summary>
            /// <param name="level">Уровень</param>
            /// <returns></returns>
            public int CalculateBonus(int level) {
                if (BonusCollection.ContainsKey(level)) {
                    return (int)BonusCollection[level];
                }
                else {
                    return default(int);
                }
            }
            /// <summary>
            /// Пересчитывает будущий бонус согласно уровню
            /// </summary>
            /// <param name="level">Уровень</param>
            /// <returns></returns>
            public int CalculateNextBonus(int level) {
                if (BonusCollection.ContainsKey(level + 1)) {
                    return (int)BonusCollection[level + 1];
                }
                else {
                    return default(int);
                }
            }
            /// <summary>
            /// Создает бонус по умолчанию
            /// </summary>
            /// <returns></returns>
            private static Dictionary<int, float> CreateDefaultBonus() {
                return new Dictionary<int, float>() {
                    [1]
                    = 3f, [2] = 6f, [3] = 9f, [4] = 12f, [5] = 15f,
                }
                ;
            }
        }
        /// <summary>
        /// Структура для хранения данных об умении
        /// </summary>
        public class SpellData {
            /// <summary>
            /// Уникальный идентификатор умения
            /// </summary>
            public int Id {
                get;
                set;
            }
            /// <summary>
            /// Картинка умения
            /// </summary>
            public string Icon {
                get;
                set;
            }
            /// <summary>
            /// Название умения
            /// </summary>
            public string Name {
                get;
                set;
            }
            /// <summary>
            /// Описание умения
            /// </summary>
            public string Description {
                get;
                set;
            }
            /// <summary>
            /// Массив данных об информации умения на разных уровнях
            /// </summary>
            public string[] Help {
                get;
                set;
            }
            public bool IsSwitched {
                get;
                internal set;
            }
            /// <summary>
            /// Конструктор по умолчанию
            /// </summary>
            public SpellData() {
                Id = -1;
                Icon = "";
                Name = "";
                Description = "";
                Help = new string[6];
            }
            /// <summary>
            /// Создает новый экземпляр данных умения с заданными
            /// параметрами
            /// </summary>
            /// <param name="id">Идентификатор</param>
            /// <param name="icon">Картинка</param>
            /// <param name="name">Название</param>
            /// <param name="desc">Описание</param>
            /// <param name="help">Массив информации об уровнях</param>
            /// <returns></returns>
            public static SpellData Create(int id, string icon, string name, string desc, string[] help) {
                return new SpellData() {
                    Id = id, Icon = icon, Name = name, Description = desc, Help = help
                }
                ;
            }
            /// <summary>
            /// Обновлеяет описание умения
            /// </summary>
            /// <param name="newDesc"></param>
            public void Update(string newDesc) {
                Description = newDesc;
            }
            /// <summary>
            /// Обновляет массив информации об умении
            /// </summary>
            /// <param name="newHelp"></param>
            public void Update(string[] newHelp) {
                Help = newHelp;
            }
        }
        /// <summary>
        /// Структура для хранения информации об уровне умения
        /// </summary>
        public class SpellLevel {
            /// <summary>
            /// Минимальный уровень умения
            /// </summary>
            public const int MIN_LEVEL = 1;
            /// <summary>
            /// Максимальный уровень умения
            /// </summary>
            public const int MAX_LEVEL = 5;
            /// <summary>
            /// Модификатор улучшения умения
            /// </summary>
            public const int EXP_MODIFIER = 140;
            /// <summary>
            /// Возвращает текущий уровень умения
            /// </summary>
            public int Level {
                get;
                set;
            }
            /// <summary>
            /// Возвращает текущее количество опыта умения
            /// </summary>
            public int CurrentExp {
                get;
                set;
            }
            /// <summary>
            /// Возвращает количество опыта требуемое для повышения уровня умения
            /// </summary>
            public int NeededExp {
                get;
                set;
            }
            /// <summary>
            /// Конструктор по умолчанию
            /// </summary>
            public SpellLevel() {
                Level = -1;
                CurrentExp = -1;
                NeededExp = -1;
            }
            /// <summary>
            /// Переставляет курсор уровня на указанную позицию
            /// </summary>
            /// <param name="level">позиция уровня</param>
            public void Seek(int level) {
                Level = level;
            }
            /// <summary>
            /// Переставляет курсор опыта на указанные позиции
            /// </summary>
            /// <param name="currentExp">текущее состояние опыта</param>
            /// <param name="neededExp">требуемое состояние опыта</param>
            public void Seek(int currentExp, int neededExp) {
                CurrentExp = currentExp;
                NeededExp = neededExp;
            }
            /// <summary>
            /// Итерирует уровень умения
            /// </summary>
            public void IterLevel() {
                if (Level >= MAX_LEVEL) {
                    return;
                }
                Level++;
                Seek(0, GetNeededExp());
            }
            /// <summary>
            /// Итерирует текущее количество опыта уровня
            /// </summary>
            public void IterExp() {
                if (CurrentExp < NeededExp) {
                    CurrentExp++;
                }
                if (CurrentExp >= NeededExp) {
                    IterLevel();
                }
            }
            /// <summary>
            /// Устанавливает значение текущего количества опыта на указанное
            /// </summary>
            /// <param name="exp">количество опыта</param>
            public void GiveExp(int exp) {
                if (CurrentExp < NeededExp) {
                    CurrentExp += exp;
                }
                if (CurrentExp >= NeededExp) {
                    IterLevel();
                }
            }
            /// <summary>
            /// Возвращает результат формулы для пересчета требуемого количество опыта
            /// </summary>
            /// <returns></returns>
            public int GetNeededExp() {
                return ((Level + (Level + 1)) + EXP_MODIFIER);
            }
            /// <summary>
            /// Создает экземпляр класса по умолчанию для текущего объекта
            /// </summary>
            /// <returns></returns>
            public static SpellLevel CreateDefault() {
                return new SpellLevel() {
                    Level = 1, CurrentExp = 0, NeededExp = 3
                }
                ;
            }
            /// <summary>
            /// Создает новый экземпляр в соответствии с указанными параметрами
            /// </summary>
            /// <param name="level">Уровень</param>
            /// <param name="currentExp">текущее количество опыта</param>
            /// <param name="neededExp">требуемое количество опыта</param>
            /// <returns></returns>
            public static SpellLevel CreateCustom(int level, int currentExp, int neededExp) {
                return new SpellLevel() {
                    Level = level, CurrentExp = currentExp, NeededExp = neededExp
                }
                ;
            }
            /// <summary>
            /// Возвращает строковое представление для текущего объекта
            /// </summary>
            /// <returns></returns>
            public override string ToString() {
                return $"Level: {Level}, CurrentExp: {CurrentExp}, NeededExp: {NeededExp}";
            }
        }
#endregion
#region Factory
        /// <summary>
        /// Список уникальных идентификаторов умений
        /// </summary>
        public enum Spells {
            /// <summary>
            /// Ярость
            /// </summary>
            Rage = 0,  /// <summary>
            /// Защита
            /// </summary>
            Shield = 1,  /// <summary>
            /// Уклонение
            /// </summary>
            Evasion = 2,  /// <summary>
            /// Контр-удар
            /// </summary>
            Spike = 3,  /// <summary>
            /// Вампирик
            /// </summary>
            Vampiric = 4,  /// <summary>
            /// Критический удар
            /// </summary>
            Critical = 5
        }
        /// <summary>
        /// Класс для реализации прототипа./// Создает умения по умолчанию
        /// </summary>
        public class SpellFactory {
            /// <summary>
            /// Создает умение "Ярость"
            /// </summary>
            /// <returns></returns>
            public static Spell CreateRageSpell() {
                return Spell.Create(SpellEffect.CreateDefault(SpellType.Damage), SpellData.Create((int)Spells.Rage, "icon", "Мощь", "Увеличивает наносимый вами урон по игрокам и существам", new string[] {
                    "1Lvl: 3%", "2Lvl: 6%", "3Lvl: 9%", "4Lvl: 12%", "5Lvl: 15%"
                }
                ), SpellLevel.CreateDefault());
            }
            /// <summary>
            /// Создает умение "Защита"
            /// </summary>
            /// <returns></returns>
            public static Spell CreateShieldSpell() {
                return Spell.Create(SpellEffect.CreateDefault(SpellType.Defense), SpellData.Create((int)Spells.Shield, "icon", "Крепость", "Блокирует некоторое количество урона получаемое персонажем от игровых существ.", new string[] {
                    "1Lvl: 3%", "2Lvl: 6%", "3Lvl: 9%", "4Lvl: 12%", "5Lvl: 15%"
                }
                ), SpellLevel.CreateDefault());
            }
            /// <summary>
            /// Создает умение "Контр-удар"
            /// </summary>
            /// <returns></returns>
            public static Spell CreateSpikeSpell() {
                return Spell.Create(SpellEffect.CreateDefault(SpellType.Spike), SpellData.Create((int)Spells.Spike, "icon", "Отражение", "С шансом равным уровню умения Вы возвращаете урон атакующему Вас игровому существу.", new string[] {
                    "1Lvl: 3%", "2Lvl: 6%", "3Lvl: 9%", "4Lvl: 12%", "5Lvl: 15%"
                }
                ), SpellLevel.CreateDefault());
            }
            /// <summary>
            /// Создает умение "Вампирик"
            /// </summary>
            /// <returns></returns>
            public static Spell CreateVampiricSpell() {
                return Spell.Create(SpellEffect.CreateDefault(SpellType.Vampiric), SpellData.Create((int)Spells.Vampiric, "icon", "Вампиризм", "Восстанавливает Ваше здоровье от наносимых Вами атак", new string[] {
                    "1Lvl: 3%", "2Lvl: 6%", "3Lvl: 9%", "4Lvl: 12%", "5Lvl: 15%"
                }
                ), SpellLevel.CreateDefault());
            }
            /// <summary>
            /// Создает умение "Критический удар"
            /// </summary>
            /// <returns></returns>
            public static Spell CreateCriticalSpell() {
                SpellEffect effect = new SpellEffect {
                    EffectType = SpellType.Critical, BonusCollection = new Dictionary<int, float>() {
                        [1]
                        = 2, [2] = 2.2f, [3] = 2.3f, [4] = 2.4f, [5] = 2.7f,
                    }
                }
                ;
                effect.CurrentBonus = effect.CalculateBonus(SpellLevel.MIN_LEVEL);
                effect.NextBonus = effect.CalculateNextBonus(SpellLevel.MIN_LEVEL);
                return Spell.Create(effect, SpellData.Create((int)Spells.Critical, "icon", "Фокусировка", "С некоторой вероятностью Вы можете нанести своей цели дополнительный урон", new string[] {
                    "1Lvl: x2", "2Lvl: x2.2", "3Lvl: x2.3", "4Lvl: x2.4", "5Lvl: x2.7"
                }
                ), SpellLevel.CreateDefault());
            }
            /// <summary>
            /// Создает умение "Уклонение"
            /// </summary>
            /// <returns></returns>
            public static Spell CreateEvasionSpell() {
                return Spell.Create(SpellEffect.CreateDefault(SpellType.Evasion), SpellData.Create((int)Spells.Evasion, "icon", "Ловкость", "С некоторой вероятностью Вы можете увернуться от урона получаемого игровыми существами", new string[] {
                    "1Lvl: 3%", "2Lvl: 6%", "3Lvl: 9%", "4Lvl: 12%", "5Lvl: 15%"
                }
                ), SpellLevel.CreateDefault());
            }
            /// <summary>
            /// Создает умение согласно указанному идентификатору
            /// </summary>
            /// <param name="id">идентификатор умения</param>
            /// <returns></returns>
            public static Spell CreateByID(int id) {
                if (id == (int)Spells.Rage) {
                    return CreateRageSpell();
                }
                else if (id == (int)Spells.Shield) {
                    return CreateShieldSpell();
                }
                else if (id == (int)Spells.Critical) {
                    return CreateCriticalSpell();
                }
                else if (id == (int)Spells.Evasion) {
                    return CreateEvasionSpell();
                }
                else if (id == (int)Spells.Vampiric) {
                    return CreateVampiricSpell();
                }
                else if (id == (int)Spells.Spike) {
                    return CreateSpikeSpell();
                }
                else {
                    return null;
                }
            }
        }
        /// <summary>
        /// Используется для хранения данных об умениях игроков
        /// </summary>
        [JsonObject]
        public class SpellPlayerStore {
            /// <summary>
            /// Возвращает уникальный идентификатор STEAM игрока
            /// </summary>
            public string PlayerSteamId {
                get;
                set;
            }
            /// <summary>
            /// Возвращает имя игрока
            /// </summary>
            public string PlayerName {
                get;
                set;
            }
            /// <summary>
            /// Возвращает текущее активное умение для игрока
            /// !!МОЖЕТ БЫТЬ NULL
            /// </summary>
            public Spell ActiveSpell {
                get;
                set;
            }
            /// <summary>
            /// Возвращает список всех умений игрока
            /// </summary>
            public List<Spell> AllSpells {
                get;
                set;
            }
            /// <summary>
            /// Конструктор по умолчанию
            /// </summary>
            public SpellPlayerStore() {
                PlayerSteamId = "";
                PlayerName = "";
                ActiveSpell = null;
            }
            /// <summary>
            /// Конструктор с иньекцией кода
            /// </summary>
            /// <param name="steam">иденртфикатор steam</param>
            /// <param name="name">имя игрока</param>
            /// <param name="active">активное умение</param>
            /// <param name="spells">список всех умений</param>
            public SpellPlayerStore(string steam, string name, Spell active, List<Spell> spells) {
                PlayerSteamId = steam;
                PlayerName = name;
                ActiveSpell = active;
                AllSpells = spells;
            }
        }
        /// <summary>
        /// Контролёр эффектов для текущего плагина
        /// </summary>
        public static class EffectController {
            /// <summary>
            /// Возвращает результат скалирования по формуле
            /// для выдачи критического урона
            /// </summary>
            /// <param name="current">текущее значение бонуса</param>
            /// <returns></returns>
            public static float GetCriticalScale(int current) {
                return current;
            }
            /// <summary>
            /// Возвращает результат вычитания по формуле
            /// для восполнение здоровья
            /// </summary>
            /// <param name="total">нанесенный урон</param>
            /// <param name="bonus">текущее значение бонуса</param>
            /// <returns></returns>
            public static float GetVampireCount(float total, int bonus) {
                return (total / 100f) * bonus;
            }
            public static bool IsAction(int current) {
                int result = UnityEngine.Random.Range(0, 100);
                if (result <= current) {
                    return true;
                }
                else {
                    return false;
                }
            }
            /// <summary>
            /// Возвращает результат скалирования по формуле для
            /// увеличения наносимого урона
            /// </summary>
            /// <param name="current">текущее значение бонуса</param>
            /// <returns></returns>
            public static float GetAttackScale(int current) {
                return (1 + ((float)current / 100));
            }
            /// <summary>
            /// Возвращает результат скалирования по формуле для
            /// блокирования определенного количества урона
            /// </summary>
            /// <param name="current">текущее значение бонуса</param>
            /// <returns></returns>
            public static float GetBlockScale(int current) {
                return (1 - ((float)current / 100));
            }
            /// <summary>
            /// Возвращает результат скалирования по формуле
            /// для возврата определенного количества урона
            /// </summary>
            /// <param name="total">общее количество нанесенного урона</param>
            /// <param name="current">текущее значение бонуса</param>
            /// <returns></returns>
            public static float GetSpikeScale(float total, int current) {
                float dmg = ((total / 100f) * current);
                return (total * dmg);
            }
        }
        public class SwitcheableData {
            public bool IsSpellSwitched;
            public int ExpireSeconds;
        }
#endregion
#region Variables
        /// <summary>
        /// Обозначает строковое представление для привилегии "админ"
        /// </summary>
        private const string PERMISSION_ADMIN = "rustyskills.admin";
        /// <summary>
        /// Обозначает строковое представление для привилегии "вип"
        /// </summary>
        private const string PERMISSION_VIP = "rustyskills.vip";
        /// <summary>
        /// Множители для привилегий
        /// </summary>
        private Dictionary<string, int> PermissionMultipliers;
        /// <summary>
        /// Активные умений персонажей
        /// </summary>
        private Dictionary<BasePlayer, Spell> ActiveSpells;
        /// <summary>
        /// Хранилище всех персонажей, которые взаимодействиуют с плагином
        /// </summary>
        private Dictionary<BasePlayer, SpellPlayerStore> OnlinePlayersStore;
        private Dictionary<BasePlayer, SwitcheableData> SpellsSwitcher;
        /// <summary>
        /// Объект конфигурации плагина
        /// </summary>
        private PluginConfig _Config;
#endregion
#region Initialization
        /// <summary>
        /// Конструктор по умолчанию
        /// </summary>
        public RustySkills() {
            ActiveSpells = new Dictionary<BasePlayer, Spell>();
            PermissionMultipliers = new Dictionary<string, int>();
            OnlinePlayersStore = new Dictionary<BasePlayer, SpellPlayerStore>();
            SpellsSwitcher = new Dictionary<BasePlayer, SwitcheableData>();
            PrintWarning("Initializing by default constructor !");
            RegisterPermissions();
        }
        /// <summary>
        /// Регистрирует привилегии для плагина
        /// </summary>
        private void RegisterPermissions() {
            permission.RegisterPermission(PERMISSION_ADMIN, this);
            permission.RegisterPermission(PERMISSION_VIP, this);
            PermissionMultipliers.Add(PERMISSION_ADMIN, 3);
            PermissionMultipliers.Add(PERMISSION_VIP, 2);
        }
#endregion
#region Instruments
        /// <summary>
        /// Сохраняет всех игроков на сервере
        /// </summary>
        private void SaveAllPlayers() {
            foreach (var player in BasePlayer.activePlayerList) {
                if (IsActiveSpell(player)) {
                    SavePlayer(player);
                }
            }
        }
        /// <summary>
        /// Загружает всех игроков на сервере
        /// </summary>
        private void LoadAllPlayers() {
            foreach (var player in BasePlayer.activePlayerList) {
                LoadPlayer(player);
            }
        }
#endregion
#region Hooks
        //Server hook
        /// <summary>
        /// Присходит при загрузе плагина
        /// </summary>
        void Loaded() {
            LoadAllPlayers();
        }
        /// <summary>
        /// Происходит при выгрузке плагина
        /// </summary>
        void Unload() {
            SaveAllPlayers();
            foreach(var player in BasePlayer.activePlayerList) {
                if(OnlinePlayersStore.ContainsKey(player)) {
                    DestroyExpLine(player);
                    DissectPanels(player);
                    DestroyExtraInfoPanel(player);
                }
            }
        }
        /// <summary>
        /// Происходит при инициализации игрока
        /// </summary>
        /// <param name="player"></param>
        void OnPlayerInit(BasePlayer player) {
            LoadPlayer(player);
            SetPanels(player);
            if(SpellsSwitcher.ContainsKey(player)) {
                SpellsSwitcher.Remove(player);
            }
            SpellsSwitcher.Add(player, new SwitcheableData());
        }
        /// <summary>
        /// Происходит перед получение урона
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="info"></param>
        void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
            if (info.InitiatorPlayer == null) {
                return;
            }
            BasePlayer attacker = info.InitiatorPlayer;
            if (entity.ToPlayer() == null) {
                return;
            }
            BasePlayer victim = entity.ToPlayer();
            if (attacker == victim) {
                return;
            }
            if (IsActiveSpell(attacker, SpellType.Vampiric)) {
                Spell aSpell = ActiveSpells[attacker];
                float vampire = EffectController.GetVampireCount(info.damageTypes.Total(), aSpell.Effect.CurrentBonus);
                attacker.Heal(vampire);
                if (EffectController.IsAction(3)) {
                    AddExpToSpell(attacker, aSpell.Data.Id, 1);
                }
#if PRAGMA_DEBUG
                SendReply(attacker, $"Вы восполнили себе здоровье в объеме: {vampire}");
#endif
            }
            if (IsActiveSpell(attacker, SpellType.Critical)) {
                Spell aSpell = ActiveSpells[attacker];
                if(EffectController.IsAction(aSpell.Effect.CurrentBonus)) {
                    info.damageTypes.ScaleAll(EffectController.GetCriticalScale(aSpell.Effect.CurrentBonus));
                    AddExpToSpell(attacker, aSpell.Data.Id, 1);
                    info.damageTypes.ScaleAll(aSpell.Effect.CurrentBonus);
                    //SendReply(attacker, $"Вы нанесли критический урон {info.damageTypes.Total()}");
                    SetExtraInfoPanel(attacker, "Крит.удар !");
                }
            }
            if (IsActiveSpell(attacker, SpellType.Damage)) {
                Spell aSpell = ActiveSpells[attacker];
                float old = info.damageTypes.Total();
                //DEBUG
                info.damageTypes.ScaleAll(EffectController.GetAttackScale(aSpell.Effect.CurrentBonus));
#if PRAGMA_DEBUG
                SendReply(attacker, $"Old: {old}, Mult.: {multiplier}, Total: {info.damageTypes.Total()}");
#endif
                if(EffectController.IsAction(3)) {
                    AddExpToSpell(attacker, aSpell.Data.Id, 1);
                }
            }
            if (IsActiveSpell(victim)) {
                Spell spell = ActiveSpells[victim];
                if (IsActiveSpell(victim, SpellType.Defense)) {
                    float old = info.damageTypes.Total();
                    //DEBUG
                    info.damageTypes.ScaleAll(EffectController.GetBlockScale(spell.Effect.CurrentBonus));
#if PRAGMA_DEBUG
                    SendReply(victim, $"Old: {old}, Mult.: {multiplier}, Total: {info.damageTypes.Total()}");
#endif
                }
                else if (IsActiveSpell(victim, SpellType.Evasion)) {
                    if (EffectController.IsAction(spell.Effect.CurrentBonus)) {
                        info.damageTypes.ScaleAll(INT_NULL);
#if PRAGMA_DEBUG
                        SendReply(victim, $"<color=#ff0000ff>[SK]</color>: <color=#008000ff>Вы успешно увернулись от атаки</color>");
#endif
                        SetExtraInfoPanel(attacker, "Уклонение");
                    }
                }
                else if (IsActiveSpell(victim, SpellType.Spike)) {
                    float ret = EffectController.GetSpikeScale(info.damageTypes.Total(), spell.Effect.CurrentBonus);
                    attacker.Hurt(ret);
#if PRAGMA_DEBUG
                    SendReply(victim, $"Ваш противник получил возврат урона в количестве: {ret}");
#endif
                    SetExtraInfoPanel(attacker, "Возврат урона !");
                }
                if (EffectController.IsAction(3)) {
                    AddExpToSpell(victim, spell.Data.Id, 1);
                }
            }
        }
        /// <summary>
        /// Происходит при отключении игрока от сервера
        /// </summary>
        /// <param name="player"></param>
        /// <param name="reason"></param>
        void OnPlayerDisconnected(BasePlayer player, string reason) {
            SavePlayer(player);
            ActiveSpells.Remove(player);
            OnlinePlayersStore.Remove(player);
        }
#endregion
#region Data Store
        /// <summary>
        /// Назначает активное умение указанному игроку
        /// </summary>
        /// <param name="player">игрок</param>
        /// <param name="active">активное умение</param>
        public void SetActive(BasePlayer player, Spell active) {
            if (OnlinePlayersStore.ContainsKey(player)) {
                AddToStore(player, OnlinePlayersStore[player].ActiveSpell.Data.Id, OnlinePlayersStore[player].ActiveSpell);
                OnlinePlayersStore[player].ActiveSpell = active;
            }
        }
        /// <summary>
        /// Добавляет указанное умение в коллекцию умений игрока
        /// </summary>
        /// <param name="player">игрок</param>
        /// <param name="id">идентификатор умения</param>
        /// <param name="spell">умение</param>
        public void AddToStore(BasePlayer player, int id, Spell spell) {
            if (spell == null) {
                return;
            }
            if (id == -1) {
                return;
            }
            if (OnlinePlayersStore.ContainsKey(player)) {
                if (OnlinePlayersStore[player].AllSpells.Contains(spell)) {
                    for (int i = 0; i < OnlinePlayersStore[player].AllSpells.Count; i++) {
                        if (OnlinePlayersStore[player].AllSpells[i].Data.Id == id) {
                            OnlinePlayersStore[player].AllSpells[i] = spell;
                        }
                    }
                }
                else {
                    bool reWrite = false;
                    for (int i = 0; i < OnlinePlayersStore[player].AllSpells.Count; i++) {
                        if (OnlinePlayersStore[player].AllSpells[i].Data.Name == null) {
                            OnlinePlayersStore[player].AllSpells[i] = spell;
                            reWrite = true;
                        }
                    }
                    if (!reWrite) {
                        OnlinePlayersStore[player].AllSpells.Add(spell);
                    }
                }
            }
        }
        /// <summary>
        /// Загружает указанного игрока
        /// </summary>
        /// <param name="player">игрок</param>
        private void LoadPlayer(BasePlayer player) {
            SpellPlayerStore store;
            List<Spell> loadeable = Interface.Oxide.DataFileSystem.ReadObject<List<Spell>>(Title + "\\" + player.displayName + "_spells");
            if (loadeable != null) {
                int count = 0;
                foreach (var spell in loadeable) {
                    PrintWarning($"[{player.displayName}_spells]: Id:{spell.Data.Id}, Name:{spell.Data.Name}, Lvl:{spell.Level.Level}");
                    count++;
                }
                PrintWarning($"Finding '{count}' spells for player: '{player.displayName}'");
                if(count == 0) {
                    loadeable = null;
                    loadeable = new List<Spell>() {
                        SpellFactory.CreateRageSpell(), SpellFactory.CreateShieldSpell(), SpellFactory.CreateCriticalSpell(), SpellFactory.CreateVampiricSpell(), SpellFactory.CreateEvasionSpell(), SpellFactory.CreateSpikeSpell()
                    }
                    ;
                }
            }
            store = new SpellPlayerStore(player.UserIDString, player.displayName, null, loadeable);
            AddToStore(player, store);
            timer.Once(10, () => {
                SetPanels(player);
                try {
                    SpellsSwitcher.Add(player, new SwitcheableData());
                }
                catch(Exception) {
                }
            }
            );
        }
        /// <summary>
        /// Сохраняет указанного игрока
        /// </summary>
        /// <param name="player">игрок</param>
        private void SavePlayer(BasePlayer player) {
            if (OnlinePlayersStore.ContainsKey(player)) {
                PrintWarning($"Saving player({player.displayName}) and him spell store");
                Interface.Oxide.DataFileSystem.WriteObject(Title + "\\" + player.displayName + "_spells", OnlinePlayersStore[player].AllSpells);
            }
        }
#endregion
#region Spells Store
        /// <summary>
        /// Добавляет хранилище для хранения в коллекцию
        /// </summary>
        /// <param name="player"></param>
        /// <param name="spell"></param>
        public void AddToStore(BasePlayer player, SpellPlayerStore spell) {
            if (!OnlinePlayersStore.ContainsKey(player)) {
                OnlinePlayersStore.Add(player, spell);
            }
        }
        /// <summary>
        /// Удаляет хранилище из коллекции хранения
        /// </summary>
        /// <param name="player"></param>
        public void RemoveFromStore(BasePlayer player) {
            if (!OnlinePlayersStore.ContainsKey(player)) {
                return;
            }
            OnlinePlayersStore.Remove(player);
        }
        /// <summary>
        /// Получает хранилище указанного игрока из коллекции
        /// </summary>
        /// <param name="player">игрок</param>
        /// <returns></returns>
        public SpellPlayerStore GetFromStore(BasePlayer player) {
            if (!OnlinePlayersStore.ContainsKey(player)) {
                return null;
            }
            return OnlinePlayersStore[player];
        }
        /// <summary>
        /// Возвращает указанное умение из хранилища указанного игрока
        /// </summary>
        /// <param name="player">игрок</param>
        /// <param name="store">хранилище</param>
        /// <param name="spellId">идентификатор умения</param>
        /// <returns></returns>
        public Spell GetSpellFromStore(BasePlayer player, SpellPlayerStore store, int spellId) {
            Spell spell = null;
            if (store != null) {
                if (store.AllSpells.Count != 0) {
                    for (int i = 0; i < store.AllSpells.Count; i++) {
                        if (store.AllSpells[i].Data.Id == spellId) {
                            if (store.AllSpells[i].Data.Name == null) {
                                store.AllSpells.Remove(store.AllSpells[i]);
                                PrintWarning("Null spell is deleted");
                                continue;
                            }
                            spell = store.AllSpells[i];
                            //PrintWarning($"Finded spell for player: '{player.displayName}' spell: '{store.AllSpells[i].Data.Name}'");
                            break;
                        }
                    }
                }
            }
            if (spell == null) {
                return null;
            }
            else {
                return spell;
            }
        }
#endregion
#region Image Library
        void OnServerInitialized() {
            try {
                ImageLibrary.Call("isLoaded", null);
            }
            catch (Exception) {
                PrintWarning("No Image Library..load ImageLibrary to use this Plugin", Name);
                Interface.Oxide.UnloadPlugin(Name);
                return;
            }
            AddImage("http://zehack.ru/rustyskills/attack.png", "attack_icon");
            AddImage("http://zehack.ru/rustyskills/shield.png", "shield_icon");
            AddImage("http://zehack.ru/rustyskills/critical.png", "critical_icon");
            AddImage("http://zehack.ru/rustyskills/vampiric.png", "vampiric_icon");
            AddImage("http://zehack.ru/rustyskills/evasion.png", "evasion_icon");
            AddImage("http://zehack.ru/rustyskills/spike.png", "spike_icon");
        }
        //ADD THESE
        public string GetImage(string shortname, ulong skin = 0) => (string)ImageLibrary.Call("GetImage", shortname, skin);
        public bool AddImage(string url, string shortname, ulong skin = 0) => (bool)ImageLibrary?.Call("AddImage", url, shortname, skin);
#endregion
#region GUI & Timers
        public class UI {
            public static CuiElementContainer CreateElementContainer(string panelName, string color, string aMin, string aMax, bool useCursor = false, string parent = "Overlay") {
                var NewElement = new CuiElementContainer() {
                    {
                        new CuiPanel {
                            Image = {
                                Color = color
                            }
                            , RectTransform = {
                                AnchorMin = aMin, AnchorMax = aMax
                            }
                            , CursorEnabled = useCursor
                        }
                        , new CuiElement().Parent = parent, panelName
                    }
                }
                ;
                return NewElement;
            }
            public static void LoadImage(ref CuiElementContainer container, string panel, string url, string aMin, string aMax) {
                container.Add(new CuiElement {
                    Name = CuiHelper.GetGuid(), Parent = panel, FadeOut = 0.15f, Components = {
                        new CuiRawImageComponent {
                            Url = url, FadeIn = 0.3f
                        }
                        , new CuiRectTransformComponent {
                            AnchorMin = aMin, AnchorMax = aMax
                        }
                    }
                }
                );
            }
            public static void CreateInput(ref CuiElementContainer container, string panel, string color, string text, int size, string aMin, string aMax, string command, bool password, int charLimit, TextAnchor align = TextAnchor.MiddleCenter) {
                container.Add(new CuiElement {
                    Name = CuiHelper.GetGuid(), Parent = panel, Components = {
                        new CuiInputFieldComponent {
                            Text = text, FontSize = size, Align = align, Color = color, Command = command, IsPassword
// ... [Code preview truncated due to length. Full source in attached file] ...

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