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

FREE ZLevelsRemastered : 3.3.1 3.3.1

Нет прав для скачивания
C#:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Core.Libraries.Covalence;
using Oxide.Game.Rust.Cui;
using UnityEngine;
using Newtonsoft.Json;
using Rust;
using Newtonsoft.Json.Converters;
namespace Oxide.Plugins {
    [Info("ZLevels Remastered", "nivex", "3.3.1")]
    [Description("Lets players level up as they harvest resources, fish, and craft")]
    class ZLevelsRemastered : RustPlugin {
        [PluginReference]
        Plugin EventManager, CraftingController, ZoneManager, Economics, IQEconomic, ServerRewards, SkillTree;
        private StoredData data = new();
        private Dictionary<string, ItemDefinition> CraftItems;
        private CraftData _craftData = new();
        private StringBuilder _sb = new();
        private bool newSaveDetected;
        private bool bonusOn;
        private int MaxB = 10001;
        private int MinB = 10;
        private HashSet<ulong> uiMovePlayers = new();
        public enum Skills {
            ACQUIRE, CRAFTING, MINING, SKINNING, WOODCUTTING, FISHING, ALL
        }
        [JsonConverter(typeof(StringEnumConverter))]
        public enum ClientPanels {
            None, Overall, Overlay, OverlayNonScaled, HudMenu, Hud, Contacts, Clans, Crafting, Inventory, Map, TechTree, Under, UnderNonScaled
        }
        private Skills[] AllSkills = new Skills[] {
            Skills.ACQUIRE, Skills.CRAFTING, Skills.MINING, Skills.SKINNING, Skills.WOODCUTTING, Skills.FISHING
        }
        ;
        private class CraftData {
            public Dictionary<string, CraftInfo> CraftList = new();
            public CraftData() {
            }
        }
        private class CraftInfo {
            public int MaxBulkCraft;
            public int MinBulkCraft;
            public string shortName;
            public bool Enabled;
            public CraftInfo() {
            }
        }
        private class StoredData {
            public Hash<ulong, PlayerInfo> PlayerInfo = new();
            [JsonProperty(ItemConverterType = typeof(Vector2Converter))]
            public Dictionary<ulong, Vector2> UiPositions = new();
            public StoredData() {
            }
        }
        private class PlayerInfo : IEquatable<PlayerInfo> {
            private double _acquireLevel = 1.0;
            private double _acquirePoints = 10.0;
            private double _craftingLevel = 1.0;
            private double _craftingPoints = 10.0;
            private double _miningLevel = 1.0;
            private double _miningPoints = 10.0;
            private double _skinningLevel = 1.0;
            private double _skinningPoints = 10.0;
            private double _woodcuttingLevel = 1.0;
            private double _woodcuttingPoints = 10.0;
            private double _fishingLevel = 1.0;
            private double _fishingPoints = 10.0;
            private double _lastDeath = 0.0;
            private double _xpMultiplier = 100.0;
            private double RoundValue(double value) => Math.Round(value, 2, MidpointRounding.AwayFromZero);
            [JsonProperty(PropertyName = "AL")]
            public double ACQUIRE_LEVEL {
                get => RoundValue(_acquireLevel);
                set => _acquireLevel = RoundValue(value);
            }
            [JsonProperty(PropertyName = "AP")]
            public double ACQUIRE_POINTS {
                get => RoundValue(_acquirePoints);
                set => _acquirePoints = RoundValue(value);
            }
            [JsonProperty(PropertyName = "CL")]
            public double CRAFTING_LEVEL {
                get => RoundValue(_craftingLevel);
                set => _craftingLevel = RoundValue(value);
            }
            [JsonProperty(PropertyName = "CP")]
            public double CRAFTING_POINTS {
                get => RoundValue(_craftingPoints);
                set => _craftingPoints = RoundValue(value);
            }
            [JsonProperty(PropertyName = "ML")]
            public double MINING_LEVEL {
                get => RoundValue(_miningLevel);
                set => _miningLevel = RoundValue(value);
            }
            [JsonProperty(PropertyName = "MP")]
            public double MINING_POINTS {
                get => RoundValue(_miningPoints);
                set => _miningPoints = RoundValue(value);
            }
            [JsonProperty(PropertyName = "SL")]
            public double SKINNING_LEVEL {
                get => RoundValue(_skinningLevel);
                set => _skinningLevel = RoundValue(value);
            }
            [JsonProperty(PropertyName = "SP")]
            public double SKINNING_POINTS {
                get => RoundValue(_skinningPoints);
                set => _skinningPoints = RoundValue(value);
            }
            [JsonProperty(PropertyName = "WCL")]
            public double WOODCUTTING_LEVEL {
                get => RoundValue(_woodcuttingLevel);
                set => _woodcuttingLevel = RoundValue(value);
            }
            [JsonProperty(PropertyName = "WCP")]
            public double WOODCUTTING_POINTS {
                get => RoundValue(_woodcuttingPoints);
                set => _woodcuttingPoints = RoundValue(value);
            }
            [JsonProperty(PropertyName = "FL")]
            public double FISHING_LEVEL {
                get => RoundValue(_fishingLevel);
                set => _fishingLevel = RoundValue(value);
            }
            [JsonProperty(PropertyName = "FP")]
            public double FISHING_POINTS {
                get => RoundValue(_fishingPoints);
                set => _fishingPoints = RoundValue(value);
            }
            [JsonProperty(PropertyName = "LD")]
            public double LAST_DEATH {
                get => RoundValue(_lastDeath);
                set => _lastDeath = RoundValue(value);
            }
            [JsonProperty(PropertyName = "XPM")]
            public double XP_MULTIPLIER {
                get => RoundValue(_xpMultiplier);
                set => _xpMultiplier = RoundValue(value);
            }
            [JsonProperty(PropertyName = "CUI")]
            public bool CUI = true;
            [JsonProperty(PropertyName = "CUIMOVE")]
            public bool CUIMOVE;
            [JsonProperty(PropertyName = "ONOFF")]
            public bool ENABLED = true;
            public PlayerInfo() {
            }
            public bool Equals(PlayerInfo other) {
                if (other == null) return false;
                return ACQUIRE_LEVEL == other.ACQUIRE_LEVEL && ACQUIRE_POINTS == other.ACQUIRE_POINTS && CRAFTING_LEVEL == other.CRAFTING_LEVEL && CRAFTING_POINTS == other.CRAFTING_POINTS && MINING_LEVEL == other.MINING_LEVEL && MINING_POINTS == other.MINING_POINTS && SKINNING_LEVEL == other.SKINNING_LEVEL && SKINNING_POINTS == other.SKINNING_POINTS && WOODCUTTING_LEVEL == other.WOODCUTTING_LEVEL && WOODCUTTING_POINTS == other.WOODCUTTING_POINTS && FISHING_LEVEL == other.FISHING_LEVEL && FISHING_POINTS == other.FISHING_POINTS && XP_MULTIPLIER == other.XP_MULTIPLIER && CUI == other.CUI && CUIMOVE == other.CUIMOVE && ENABLED == other.ENABLED;
            }
            public override bool Equals(object obj) {
                return obj is PlayerInfo other && Equals(other);
            }
            public override int GetHashCode() {
                HashCode hash = new();
                hash.Add(ACQUIRE_LEVEL);
                hash.Add(ACQUIRE_POINTS);
                hash.Add(CRAFTING_LEVEL);
                hash.Add(CRAFTING_POINTS);
                hash.Add(MINING_LEVEL);
                hash.Add(MINING_POINTS);
                hash.Add(SKINNING_LEVEL);
                hash.Add(SKINNING_POINTS);
                hash.Add(WOODCUTTING_LEVEL);
                hash.Add(WOODCUTTING_POINTS);
                hash.Add(FISHING_LEVEL);
                hash.Add(FISHING_POINTS);
                hash.Add(XP_MULTIPLIER);
                hash.Add(CUI);
                hash.Add(CUIMOVE);
                hash.Add(ENABLED);
                return hash.ToHashCode();
            }
            public static bool operator ==(PlayerInfo left, PlayerInfo right) {
                if (ReferenceEquals(left, right)) return true;
                if (left is null) return false;
                return left.Equals(right);
            }
            public static bool operator !=(PlayerInfo left, PlayerInfo right) {
                return !(left == right);
            }
            internal bool IsDefault(PlayerInfo other) => Equals(other);
        }
#region Main
        private void Init() {
            Unsubscribe();
            RegisterPermissions();
            int index = 0;
            foreach (Skills skill in AllSkills) {
                if (IsSkillEnabled(skill)) {
                    skillIndex.Add(skill, ++index);
                }
            }
        }
        private void Unload() {
            Clean();
            SaveData();
            foreach (var player in BasePlayer.activePlayerList) {
                DestroyGUI(player);
            }
            if (TOD_Sky.Instance?.Components?.Time != null) {
                TOD_Sky.Instance.Components.Time.OnSunrise -= OnTimeSunrise;
                TOD_Sky.Instance.Components.Time.OnSunset -= OnTimeSunset;
            }
        }
        protected new void Puts(string format, params object[] args) {
            if (string.IsNullOrWhiteSpace(format)) return;
            string message = Localize(format, null, args);
            if (string.IsNullOrWhiteSpace(message)) return;
            Interface.Oxide.LogInfo("[{0}] {1}", nameof(ZLevelsRemastered), message);
        }
        private void OnNewSave(string strFilename) {
            if (config.generic.wipeDataOnNewSave) {
                Puts("New save detected...");
                newSaveDetected = true;
            }
        }
        private void OnServerInitialized() {
            LoadData();
            if (config.nightbonus.enableNightBonus && TOD_Sky.Instance.IsNight) {
                pointsPerHitCurrent = config.nightbonus.pointsPerHitAtNight;
                resourceMultipliersCurrent = config.nightbonus.resourceMultipliersAtNight;
                pointsPerHitPowerToolCurrent = config.nightbonus.pointsPerPowerToolAtNight;
                bonusOn = true;
            }
            else {
                pointsPerHitCurrent = config.settings.pointsPerHit;
                resourceMultipliersCurrent = config.settings.resourceMultipliers;
                pointsPerHitPowerToolCurrent = config.settings.pointsPerPowerTool;
            }
            foreach (var player in BasePlayer.allPlayerList) {
                var pi = GetPlayerInfo(player);
                if (pi != null && player.IsConnected) CreateGUI(player, pi);
            }
            Puts("Stats can be reset by > zl.reset <");
            Subscribe();
            SaveData();
            RegisterCommands();
        }
        private void OnPlayerConnected(BasePlayer player) => OnPlayerSleepEnded(player);
        private void OnPlayerDisconnected(BasePlayer player) {
            if (!ReferenceEquals(player, null)) uiMovePlayers.Remove(player.userID);
            if (player != null) GetPlayerInfo(player);
        }
        private void OnEntityKill(BasePlayer player) => OnPlayerSleep(player);
        private void OnPlayerRespawned(BasePlayer player) => OnPlayerSleepEnded(player);
        private void OnPlayerSleepEnded(BasePlayer player) => CreateGUI(player, GetPlayerInfo(player));
        private void OnPlayerSleep(BasePlayer player) => DestroyGUI(player);
        private void OnEntityDeath(BasePlayer player, HitInfo info) {
            if (info == null || !IsValid(player) || isZoneExcluded(player)) return;
            DestroyGUI(player);
            if (!hasRights(player.UserIDString)) return;
            var pi = GetPlayerInfo(player);
            if (!pi.ENABLED || permission.UserHasPermission(player.UserIDString, config.generic.permissionNameXP)) return;
            string L(string key, params object[] args) => Localize(key, player.UserIDString, args);
            bool isSuicide = info.damageTypes.Has(DamageType.Suicide) && (player.IsAdmin || player.IsDeveloper || !player.CanSuicide());
            if (!config.generic.penaltyOnSuicide && isSuicide) return;
            if (!config.generic.penaltyOnDeath && !isSuicide) return;
            if (EventManager?.Call("IsEventPlayer", player) != null) return;
            if (Interface.CallHook("CanBePenalized", player) != null) return;
            _sb.Clear();
            foreach (Skills skill in AllSkills) {
                if (IsSkillEnabled(skill)) {
                    var penalty = GetPenalty(player, pi, skill, isSuicide);
                    if (penalty > 0) {
                        _sb.AppendLine(L("* -{0} {1} XP.", penalty, L(skill + "Skill")));
                        removePoints(pi, skill, penalty);
                    }
                }
            }
            if (_sb.Length > 0) {
                Message(player, "PenaltyText", _sb.ToString());
            }
            pi.LAST_DEATH = ToEpochTime(DateTime.UtcNow);
        }
        private void OnDispenserGather(ResourceDispenser dispenser, BasePlayer player, Item item) {
            if (item == null || dispenser == null || !hasRights(player)) return;
            Skills? skill = dispenser.gatherType switch {
                ResourceDispenser.GatherType.Tree => Skills.WOODCUTTING, ResourceDispenser.GatherType.Flesh => Skills.SKINNING, ResourceDispenser.GatherType.Ore => Skills.MINING, _ => null
            }
            ;
            if (skill == null || !IsSkillEnabled(skill.Value)) return;
            var pi = GetPlayerInfo(player);
            if (!pi.ENABLED) return;
            Item activeItem = player.GetActiveItem();
            if (permission.UserHasPermission(player.UserIDString, config.generic.BlockWeaponsGather) && activeItem?.info.category == ItemCategory.Weapon) return;
            if (!config.functions.ShouldAllowGather(item.info.shortname, out bool grantXPOnly)) return;
            int prevAmount = item.amount;
            bool isPowerTool = false;
            if (skill != Skills.SKINNING && activeItem != null) {
                HeldEntity heldEntity = activeItem.GetHeldEntity() as HeldEntity;
                if (heldEntity is Jackhammer || heldEntity is Chainsaw) {
                    if (skill == Skills.WOODCUTTING && !CanUseChainsaw(player)) {
                        return;
                    }
                    if (skill == Skills.MINING && !CanUseJackhammer(player)) {
                        return;
                    }
                    if (!config.functions.gibs && dispenser.GetComponent<ServerGib>() != null) {
                        return;
                    }
                    isPowerTool = true;
                }
            }
            if (!config.functions.gibs && skill == Skills.MINING && dispenser.GetComponent<ServerGib>() != null) {
                return;
            }
            int amount = levelHandler(pi, player, item.amount, skill.Value, dispenser.baseEntity, isPowerTool);
            if (!grantXPOnly) {
                item.amount = amount;
            }
            if (item.amount != prevAmount) {
                Interface.CallHook("OnZLevelDispenserGather", dispenser, player, item, prevAmount, item.amount, isPowerTool);
            }
        }
        private bool CanUseJackhammer(BasePlayer player) => permission.UserHasPermission(player.UserIDString, config.generic.AllowJackhammerGather);
        private bool CanUseChainsaw(BasePlayer player) => permission.UserHasPermission(player.UserIDString, config.generic.AllowChainsawGather);
        private void OnDispenserBonus(ResourceDispenser dispenser, BasePlayer player, Item item) => OnDispenserGather(dispenser, player, item);
        private object OnCollectiblePickup(CollectibleEntity collectible, BasePlayer player) {
            if (collectible == null || collectible.itemList.IsNullOrEmpty() || !hasRights(player)) return null;
            var pi = GetPlayerInfo(player);
            if (!pi.ENABLED) return null;
            if (config.functions.enabledCollectibleEntity.TryGetValue(collectible.ShortPrefabName, out var enabled) && !enabled) return null;
            for (int i = 0; i < collectible.itemList.Length; i++) {
                ItemAmount itemAmount = collectible.itemList[i];
                if (itemAmount?.itemDef?.shortname == null || !TryGetCollectibleSkill(itemAmount.itemDef.shortname, player, out Skills skill)) continue;
                int prevAmount = (int)itemAmount.amount;
                itemAmount.amount = levelHandler(pi, player, prevAmount, skill, collectible);
                if (Interface.CallHook("OnZLevelCollectiblePickup", itemAmount, player, collectible, prevAmount, itemAmount.amount) != null) {
                    return true;
                }
            }
            return null;
        }
        private void OnCollectiblePickedup(CollectibleEntity collectible, BasePlayer player, Item item) {
            if (collectible == null || item?.info?.shortname == null || !hasRights(player)) return;
            var pi = GetPlayerInfo(player);
            if (!pi.ENABLED) return;
            if (config.functions.enabledCollectibleEntity.TryGetValue(collectible.ShortPrefabName, out var enabled) && !enabled) return;
            if (!TryGetCollectibleSkill(item.info.shortname, player, out Skills skill)) return;
            int prevAmount = item.amount;
            item.amount = levelHandler(pi, player, item.amount, skill, collectible);
            Interface.CallHook("OnZLevelCollectiblePickedup", item, player, collectible, prevAmount, item.amount);
        }
        private bool TryGetCollectibleSkill(string shortname, BasePlayer player, out Skills skill) {
            switch (shortname) {
                case "black.berry" or "blue.berry" or "bone.fragments" or "clone.seed" or "clone.orchid" or "clone.rose" or "clone.sunflower" or "cloth" or "corn" or "diesel_barrel" or "green.berry" or "mushroom" or "orchid" or "potato" or "pumpkin" or "red.berry" or "rose" or "seed.black.berry" or "seed.blue.berry" or "seed.corn" or "seed.green.berry" or "seed.hemp" or "seed.orchid" or "seed.potato" or "seed.pumpkin" or "seed.red.berry" or "seed.rose" or "seed.sunflower" or "seed.wheat" or "seed.white.berry" or "seed.yellow.berry" or "sunflower" or "wheat" or "white.berry" or "yellow.berry" : skill = IsSkillEnabled(Skills.ACQUIRE) ? Skills.ACQUIRE : Skills.SKINNING;
                break;
                case "hq.metal.ore" or "metal.ore" or "sulfur.ore" or "stones" : skill = config.settings.MiningStonesOre ? Skills.MINING : Skills.ACQUIRE;
                break;
                case "wood" : skill = config.settings.AcquireWood ? Skills.ACQUIRE : Skills.WOODCUTTING;
                break;
                default : if (IsSkillEnabled(Skills.ACQUIRE)) skill = Skills.ACQUIRE;
                else if (IsSkillEnabled(Skills.SKINNING)) skill = Skills.SKINNING;
                else {
                    skill = default;
                    return false;
                }
                if (_warnings.Add(shortname)) {
                    Puts("WARNING: {0} picked up undefined item: {1}. Defaulting to {2} skill.", player, shortname, Localize(skill + "Skill"));
                }
                break;
            }
            return IsSkillEnabled(skill);
        }
        private HashSet<string> _warnings = new();
        private void OnFishCatch(Item item, BaseFishingRod rod, BasePlayer player) {
            if (item?.info == null || rod == null || !hasRights(player) || !IsSkillEnabled(Skills.FISHING)) return;
            var pi = GetPlayerInfo(player);
            if (!pi.ENABLED) return;
            double level = getLevel(pi, Skills.FISHING);
            if (!TryGainXP(pi, player, Skills.FISHING, rod, config.settings.fishingDetails.xpPerCatch)) return;
            int prevAmount = item.amount;
            bool actualFish = TryGetFishable(item.info, out ItemModFishable fishable) && !fishable.IsJunk;
            double chance = GetFishingBonusChance(level);
            bool extraFish = actualFish && (chance >= 100.0 || chance > 0.0 && UnityEngine.Random.Range(0f, 100f) < chance);
            if (extraFish) {
                item.amount++;
            }
            Interface.CallHook("OnZLevelFishCatch", item, rod, player, prevAmount, item.amount, extraFish);
        }
        private void OnTimeSunset() {
            if (!config.nightbonus.enableNightBonus || bonusOn) {
                return;
            }
            bonusOn = true;
            pointsPerHitCurrent = config.nightbonus.pointsPerHitAtNight;
            resourceMultipliersCurrent = config.nightbonus.resourceMultipliersAtNight;
            pointsPerHitPowerToolCurrent = config.nightbonus.pointsPerPowerToolAtNight;
            if (config.nightbonus.broadcastEnabledBonus) {
                foreach (var player in BasePlayer.activePlayerList) Message(player, "NightBonusOn");
            }
            if (config.nightbonus.logEnabledBonusConsole) Puts("Nightbonus points enabled");
        }
        private void OnTimeSunrise() {
            if (!config.nightbonus.enableNightBonus || !bonusOn) {
                return;
            }
            bonusOn = false;
            pointsPerHitCurrent = config.settings.pointsPerHit;
            resourceMultipliersCurrent = config.settings.resourceMultipliers;
            pointsPerHitPowerToolCurrent = config.settings.pointsPerPowerTool;
            if (config.nightbonus.broadcastEnabledBonus) {
                foreach (var player in BasePlayer.activePlayerList) Message(player, "NightBonusOff");
            }
            if (config.nightbonus.logEnabledBonusConsole) Puts("Nightbonus points disabled");
        }
        private object OnGrowableGathered(GrowableEntity plant, Item item, BasePlayer player) {
            if (item == null || !hasRights(player)) return true;
            var pi = GetPlayerInfo(player);
            if (!pi.ENABLED) return true;
            Skills skill;
            if (IsSkillEnabled(Skills.ACQUIRE)) skill = Skills.ACQUIRE;
            else skill = Skills.SKINNING;
            var prevAmount = item.amount;
            item.amount = levelHandler(pi, player, item.amount, skill, plant);
            Interface.CallHook("OnZLevelGrowableGathered", plant, item, player, prevAmount, item.amount);
            return null;
        }
        private object OnItemCraft(ItemCraftTask task, BasePlayer crafter, Item fromTempBlueprint) {
            if (!hasRights(crafter)) return null;
            var pi = GetPlayerInfo(crafter);
            if (!pi.ENABLED) return null;
            var bypassCraftLevelRequirement = CanInstantCraftNoLevelRequirement(crafter);
            var craftingTime = task.blueprint.time;
            if (bypassCraftLevelRequirement) {
                craftingTime = 0;
            }
            else if (IsSkillEnabled(Skills.CRAFTING)) {
                if (pi.CRAFTING_LEVEL > 1) craftingTime -= task.blueprint.time * (float)((pi.CRAFTING_LEVEL * config.settings.craftingDetails.percent) / 100);
            }
            else return null;
            if (craftingTime <= 0) {
                craftingTime = 0;
                foreach (var craftInfo in _craftData.CraftList.Values) {
                    if (!craftInfo.Enabled || craftInfo.shortName != task.blueprint.targetItem.shortname) {
                        continue;
                    }
                    if (task.amount >= craftInfo.MinBulkCraft && task.amount <= craftInfo.MaxBulkCraft && task.amount > 0) {
                        var stacks = GetStacks(task.amount * task.blueprint.amountToCreate, task.blueprint.targetItem.stackable);
                        if (!HasPlace(crafter, stacks)) {
                            ReturnCraft(task, crafter);
                            return true;
                        }
                        if (bypassCraftLevelRequirement || CanInstantCraft(crafter)) {
                            if (!task.blueprint.name.Contains("(Clone)")) task.blueprint = UnityEngine.Object.Instantiate(task.blueprint);
                            task.blueprint.amountToCreate *= task.amount;
                            crafter.inventory.crafting.FinishCrafting(task);
                            task.cancelled = true;
                            return true;
                        }
                    }
                }
            }
            if (!task.blueprint.name.Contains("(Clone)")) task.blueprint = UnityEngine.Object.Instantiate(task.blueprint);
            task.blueprint.time = craftingTime;
            return null;
        }
        private List<int> GetStacks(int amount, int maxStack) {
            List<int> stacks = new();
            while (amount > maxStack && amount > 0) {
                amount -= maxStack;
                stacks.Add(maxStack);
            }
            if (amount > 0) {
                stacks.Add(amount);
            }
            return stacks;
        }
        private bool HasPlace(BasePlayer crafter, List<int> stacks) {
            if (!config.settings.craftingDetails.slots) {
                return true;
            }
            var capacity = crafter.inventory.containerMain.capacity + crafter.inventory.containerBelt.capacity;
            var taken = crafter.inventory.containerMain.itemList.Count + crafter.inventory.containerBelt.itemList.Count;
            var slots = capacity - taken;
            if (slots - stacks.Count < 0) {
                return false;
            }
            return slots > 0;
        }
        private bool CanInstantCraftNoLevelRequirement(BasePlayer crafter) {
            return config.settings.craftingDetails.noLevelRequirement && permission.UserHasPermission(crafter.UserIDString, config.settings.craftingDetails.Permission);
        }
        private bool CanInstantCraft(BasePlayer crafter) {
            if (config.settings.craftingDetails.usePermission) {
                return permission.UserHasPermission(crafter.UserIDString, config.settings.craftingDetails.Permission);
            }
            return true;
        }
        private void ReturnCraft(ItemCraftTask task, BasePlayer crafter) {
            task.cancelled = true;
            Message(crafter, "NoSlots");
            foreach (var item in task.takenItems) {
                if (item.amount > 0) crafter.GiveItem(item);
            }
        }
        private object OnItemCraftFinished(ItemCraftTask task, Item item, ItemCrafter craft) {
            if (task == null) return null;
            var crafter = craft?.owner;
            if (crafter == null || !hasRights(crafter.UserIDString)) return null;
            var bypassLevelRequirement = CanInstantCraftNoLevelRequirement(crafter);
            if (!bypassLevelRequirement && !IsSkillEnabled(Skills.CRAFTING)) return null;
            var pi = GetPlayerInfo(crafter);
            var xpPercentBefore = getExperiencePercent(pi, Skills.CRAFTING);
            if (task.blueprint == null) {
                Puts("There is problem obtaining task.blueprint on 'OnItemCraftFinished' hook! This is usually caused by some incompatable plugins.");
                return null;
            }
            var experienceGain = (task.blueprint.time + 0.99f) / config.settings.craftingDetails.time;
            if (experienceGain == 0) return null;
            double Level = pi.CRAFTING_LEVEL;
            double Points = pi.CRAFTING_POINTS;
            Points += experienceGain * config.settings.craftingDetails.xp;
            if (Points >= getLevelPoints(Level + 1)) {
                var levelCap = config.settings.levelCaps.CRAFTING;
                var maxLevel = levelCap > 0 && Level + 1 > levelCap;
                if (!maxLevel) {
                    Level = getPointsLevel(Points, Skills.CRAFTING);
                    string format = $"<color={config.settings.colors.CRAFTING}>{Localize("LevelUpText", crafter.UserIDString)}</color>";
                    string message = string.Format(format, Localize("CRAFTINGSkill", crafter.UserIDString), Level, Points, getLevelPoints(Level + 1), pi.CRAFTING_LEVEL * Convert.ToDouble(config.settings.craftingDetails.percent));
                    Player.Message(crafter, message, string.IsNullOrEmpty(config.generic.pluginPrefix) ? string.Empty : config.generic.pluginPrefix, config.generic.steamIDIcon);
                    GiveReward(crafter, Skills.CRAFTING, Level);
                    if (config.generic.enableLevelupBroadcast) {
                        foreach (var target in BasePlayer.activePlayerList) {
                            if (target != null && target.userID != crafter.userID && hasRights(target.UserIDString) && GetPlayerInfo(target).ENABLED) {
                                Message(target, "LevelUpTextBroadcast", crafter.displayName, Level, config.settings.colors.CRAFTING, Localize("CRAFTINGSkill", target.UserIDString));
                            }
                        }
                    }
                }
            }
            try {
                if (item.info.shortname != "lantern_a" && item.info.shortname != "lantern_b") setPointsAndLevel(pi, Skills.CRAFTING, Points, Level);
            }
            catch {
            }
            try {
                var xpPercentAfter = getExperiencePercent(pi, Skills.CRAFTING);
                if (xpPercentAfter != xpPercentBefore) GUIUpdateSkill(crafter, Skills.CRAFTING);
            }
            catch {
            }
            if (task.amount > 0) return null;
            if (task.blueprint != null && task.blueprint.name.Contains("(Clone)")) {
                var behaviours = task.blueprint.GetComponents<MonoBehaviour>();
                foreach (var behaviour in behaviours) {
                    if (behaviour.name.Contains("(Clone)")) UnityEngine.Object.Destroy(behaviour);
                }
            }
            return null;
        }
#endregion Serverhooks
#region Commands
        [HookMethod("SendHelpText"), ChatCommand("stathelp")]
        private void SendHelpText(BasePlayer player) {
            string L(string key) => Localize(key, player.UserIDString);
            _sb.Clear();
            _sb.AppendLine(L("<size=18><color=orange>ZLevels</color></size><size=14><color=#ce422b>REMASTERED</color></size>"));
            _sb.AppendLine(L("/stats - Displays your stats."));
            _sb.AppendLine(L("/statsui - Enable/Disable stats UI. Use /statsui reset to restore its position."));
            _sb.AppendLine(L("/statsui move - Start/finish moving the UI, or click DONE to finish moving the UI. /statsui button - Show/hide the move button."));
            _sb.AppendLine(L("/statsonoff - Enable/Disable whole leveling."));
            _sb.AppendLine(L("/statinfo - Displays information about skills."));
            _sb.AppendLine(L("/stathelp - Displays the help."));
            //sb.AppendLine("/topskills - Display max levels reached so far.");
            if (_sb.Length > 0) SendReply(player, _sb.ToString());
        }
        private void PointsPerHitCommand(IPlayer user, string command, string[] args) {
            if (!user.IsAdmin) return;
            string L(string key, params object[] args) => Localize(key, user.Id, args);
            if (args.Length < 2) {
                Reply(user, "Syntax: zl.pointsperhit skill number");
                Reply(user, "Possible skills are: WC, M, S, A, C, *(All skills)");
                _sb.Clear();
                _sb.Append(L("Current points per hit:"));
                foreach (var currSkill in AllSkills) {
                    if (currSkill == Skills.FISHING || !IsSkillEnabled(currSkill)) continue;
                    _sb.Append(L(" {0} > {1} |", L(currSkill + "Skill"), pointsPerHitCurrent.Get(currSkill)));
                }
                user.Reply(_sb.ToString().TrimEnd('|'));
                return;
            }
            if (!double.TryParse(args[1], out var points) || points < 1) {
                Reply(user, "Incorrect number. Must be greater than or equal to 1");
                return;
            }
            var skillName = args[0].ToUpper();
            Skills skill;
            if (skillName == "*") skill = Skills.ALL;
            else if (skillName.Equals("C")) skill = Skills.CRAFTING;
            else if (skillName.Equals("WC")) skill = Skills.WOODCUTTING;
            else if (skillName.Equals("M")) skill = Skills.MINING;
            else if (skillName.Equals("A")) skill = Skills.ACQUIRE;
            else if (skillName.Equals("S")) skill = Skills.SKINNING;
            else {
                Reply(user, "Incorrect skill. Possible skills are: WC, M, S, A, C, *(All skills).");
                return;
            }
            if (skill == Skills.ALL) {
                foreach (var currSkill in AllSkills) {
                    if (currSkill == Skills.FISHING || !IsSkillEnabled(currSkill)) continue;
                    pointsPerHitCurrent.Set(currSkill, points);
                }
                _sb.Clear();
                _sb.Append(L("New points per hit:"));
                foreach (var currSkill in AllSkills) {
                    if (currSkill == Skills.FISHING || !IsSkillEnabled(currSkill)) continue;
                    _sb.Append(L(" {0} > {1} |", L(currSkill + "Skill"), pointsPerHitCurrent.Get(currSkill)));
                }
                user.Reply(_sb.ToString().TrimEnd('|'));
            }
            else {
                pointsPerHitCurrent.Set(skill, points);
                _sb.Clear();
                _sb.Append(L("New points per hit:"));
                foreach (var currSkill in AllSkills) {
                    if (currSkill == Skills.FISHING || !IsSkillEnabled(currSkill)) continue;
                    _sb.Append(L(" {0} > {1} |", L(currSkill + "Skill"), pointsPerHitCurrent.Get(currSkill)));
                }
                user.Reply(_sb.ToString().TrimEnd('|'));
            }
        }
        private void PlayerXpmCommand(IPlayer user, string command, string[] args) {
            if (!user.IsAdmin) return;
            if (args.Length < 1) {
                Reply(user, "XPM USE 1");
                Reply(user, "XPM USE 2");
                return;
            }
            IPlayer target = covalence.Players.FindPlayer(args[0]);
            if (target == null) {
                Reply(user, "PLAYER NOT FOUND");
                return;
            }
            if (!data.PlayerInfo.TryGetValue(Convert.ToUInt64(target.Id), out var playerData)) {
                Reply(user, "PlayerData is NULL!");
                return;
            }
            if (args.Length < 2) {
                var bonus1 = getXpMulti(playerData, target.Id);
                var baseMultiplier = playerData.XP_MULTIPLIER;
                if (baseMultiplier != bonus1) {
                    Reply(user, "Current XP multiplier for player '{0}' is {1}% with vip raising total to {2}%", target.Name, baseMultiplier, bonus1);
                }
                else Reply(user, "Current XP multiplier for player '{0}' is {1}%", target.Name, baseMultiplier);
                return;
            }
            double multiplier = -1;
            if (double.TryParse(args[1], out multiplier)) {
                if (multiplier <= 0) {
                    Reply(user, "Incorrect number. Must be greater than 0");
                    return;
                }
            }
            playerData.XP_MULTIPLIER = multiplier;
            var bonus2 = getXpMulti(playerData, target.Id);
            if (multiplier != bonus2) {
                Reply(user, "New XP multiplier for player '{0}' is {1}% with vip raising total to {2}%", target.Name, multiplier, bonus2);
            }
            else Reply(user, "New XP multiplier for player '{0}' is {1}%", target.Name, bonus2);
        }
        private void InfoCommand(IPlayer user, string command, string[] args) {
            if (!user.IsAdmin) {
                return;
            }
            if (args.Length < 1) {
                if (!GetLookingAtPlayer(user)) {
                    Reply(user, "INFO USE");
                }
                return;
            }
            IPlayer target = covalence.Players.FindPlayer(args[0]);
            if (target == null) {
                Reply(user, "PLAYER NOT FOUND");
                return;
            }
            if (!data.PlayerInfo.TryGetValue(Convert.ToUInt64(target.Id), out var playerData)) {
                Reply(user, "PlayerData is NULL!");
                return;
            }
            PrintInfo(user, target.Id, target.Name, playerData);
        }
        private bool GetLookingAtPlayer(IPlayer user) {
            BasePlayer player = user.Object as BasePlayer;
            if (player == null) return false;
            BasePlayer target = RelationshipManager.GetLookingAtPlayer(player);
            if (target == null) return false;
            if (!data.PlayerInfo.TryGetValue(target.userID, out var playerData)) return false;
            PrintInfo(user, target.UserIDString, target.displayName, playerData);
            return true;
        }
        private void PrintInfo(IPlayer user, string targetId, string targetName, PlayerInfo playerData) {
            string L(string key) => Localize(key, user.Id);
            TextTable textTable = new();
            textTable.AddColumn(L("FieldInfo"));
            textTable.AddColumn(L("Level"));
            textTable.AddColumn(L("Points"));
            textTable.AddRow(L("ACQUIRESkill"), $"{playerData.ACQUIRE_LEVEL:#0.##}", $"{playerData.ACQUIRE_POINTS:#0.##}");
            textTable.AddRow(L("CRAFTINGSkill"), $"{playerData.CRAFTING_LEVEL:#0.##}", $"{playerData.CRAFTING_POINTS:#0.##}");
            textTable.AddRow(L("MININGSkill"), $"{playerData.MINING_LEVEL:#0.##}", $"{playerData.MINING_POINTS:#0.##}");
            textTable.AddRow(L("SKINNINGSkill"), $"{playerData.SKINNING_LEVEL:#0.##}", $"{playerData.SKINNING_POINTS:#0.##}");
            textTable.AddRow(L("WOODCUTTINGSkill"), $"{playerData.WOODCUTTING_LEVEL:#0.##}", $"{playerData.WOODCUTTING_POINTS:#0.##}");
            textTable.AddRow(L("FISHINGSkill"), $"{playerData.FISHING_LEVEL:#0.##}", $"{playerData.FISHING_POINTS:#0.##}");
            textTable.AddRow(L("XPM"), $"{getXpMulti(playerData, targetId):#0.##}%", string.Empty);
            user.Reply($"\n{L("STATS")}{targetName}\n{textTable}");
        }
        private void ResetCommand(IPlayer user, string command, string[] args) {
            if (!user.IsAdmin) return;
            if (args.Length != 1 || args[0] != "true") {
                Reply(user, "RESET USE");
                return;
            }
            WipeData();
            SaveData();
            foreach (var player in BasePlayer.activePlayerList) {
                CreateGUI(player, GetPlayerInfo(player));
            }
            Reply(user, "Userdata was successfully reset to zero");
            Puts("{0} ({1}) reset userdata to zero", user.Name, user.Id);
        }
        private void ZlvlCommand(IPlayer user, string command, string[] args) {
            if (!user.IsAdmin) return;
            string L(string key) => Localize(key, user.Id);
            if (args.Length < 3) {
                _sb.Clear();
                _sb.AppendLine(L("Syntax: zl.lvl name|steamid skill [OPERATOR]NUMBER"));
                _sb.AppendLine(L("Example: zl.lvl Player WC /2 -- Player gets his WC level divided by 2."));
                _sb.AppendLine(L("Example: zl.lvl * * +3 -- Everyone currently playing in the server gets +3 for all skills."));
                _sb.AppendLine(L("Example: zl.lvl ** * /2 -- Everyone (including offline players) gets their level divided by 2."));
                _sb.AppendLine(L("Instead of names you can use wildcard(*): * - affects online players, ** - affects all players"));
                _sb.AppendLine(L("Possible operators: *(XP Modified %), +(Adds level), -(Removes level), /(Divides level)")).AppendLine();
                user.Reply(_sb.ToString());
                return;
            }
            var playerName = args[0];
            IPlayer target = covalence.Players.FindPlayer(playerName);
            if (playerName != "*" && playerName != "**" && target == null) {
                Reply(user, "PLAYER NOT FOUND");
                return;
            }
            if (playerName != "*" && playerName != "**" && !data.PlayerInfo.ContainsKey(Convert.ToUInt64(target.Id))) {
                Reply(user, "PlayerData is NULL!");
                return;
            }
            if (target != null || playerName == "*" || playerName == "**") {
                var playerMode = 0;
                // Exact player
                if (playerName == "*") playerMode = 1;
                // Online players
                else if (playerName == "**") playerMode = 2;
                // All players
                var skillName = args[1].ToUpper();
                Skills skill;
                if (skillName == "*") skill = Skills.ALL;
                else if (skillName.Equals("C")) skill = Skills.CRAFTING;
                else if (skillName.Equals("WC")) skill = Skills.WOODCUTTING;
                else if (skillName.Equals("M")) skill = Skills.MINING;
                else if (skillName.Equals("A")) skill = Skills.ACQUIRE;
                else if (skillName.Equals("S")) skill = Skills.SKINNING;
                else if (skillName.Equals("F")) skill = Skills.FISHING;
                else {
                    Reply(user, "Incorrect skill. Possible skills are: WC, M, S, A, C, F, *(All skills).");
                    return;
                }
                var mode = 0;
                // 0 = SET, 1 = ADD, 2 = SUBTRACT, 3 = multiplier, 4 = divide
                int value;
                bool correct;
                if (args[2][0] == '+') {
                    mode = 1;
                    correct = int.TryParse(args[2].Replace("+", string.Empty), out value);
                }
                else if (args[2][0] == '-') {
                    mode = 2;
                    correct = int.TryParse(args[2].Replace("-", string.Empty), out value);
                }
                else if (args[2][0] == '*') {
                    mode = 3;
                    correct = int.TryParse(args[2].Replace("*", string.Empty), out value);
                }
                else if (args[2][0] == '/') {
                    mode = 4;
                    correct = int.TryParse(args[2].Replace("/", string.Empty), out value);
                }
                else {
                    correct = int.TryParse(args[2], out value);
                }
                if (correct) {
                    if (mode == 3)  // Change XP Multiplier.
                    {
                        if (skill != Skills.ALL) {
                            Reply(user, "XPMultiplier is changeable for all skills! Use * instead of {0}.", skill);
                            return;
                        }
                        if (playerMode == 1) {
                            foreach (var currPlayer in BasePlayer.activePlayerList) editMultiplierForPlayer(value, currPlayer.userID);
                        }
                        else if (playerMode == 2) editMultiplierForPlayer(value);
                        else if (target != null) editMultiplierForPlayer(value, Convert.ToUInt64(target.Id));
                        var whom = playerMode == 1 ? L("ALL ONLINE PLAYERS") : playerMode == 2 ? L("ALL PLAYERS") : target.Name;
                        Reply(user, "XP rates has changed to {0}% of normal XP for {1}", value, whom);
                        return;
                    }
                    if (playerMode == 1) {
                        foreach (var connPlayer in covalence.Players.Connected) {
                            adminModifyPlayerStats(user, skill, value, mode, connPlayer);
                        }
                    }
                    else if (playerMode == 2) {
                        foreach (var other in covalence.Players.All) {
                            if (data.PlayerInfo.ContainsKey(Convert.ToUInt64(other.Id))) {
                                adminModifyPlayerStats(user, skill, value, mode, other);
                            }
                        }
                    }
                    else {
                        adminModifyPlayerStats(user, skill, value, mode, target);
                    }
                }
            }
        }
        private void CheckCommand(IPlayer user, string command, string[] args) {
            if (!user.IsAdmin) return;
            int count = 0;
            var pi = CreatePlayerInfo();
            foreach (var info in data.PlayerInfo) {
                if (info.Value.IsDefault(pi)) {
                    count++;
                }
            }
            Reply(user, "{0} / {1} entries in datafile can be removed", count, data.PlayerInfo.Count);
        }
        private void CleanCommand(IPlayer user, string command, string[] args) {
            if (!user.IsAdmin) return;
            int count = data.PlayerInfo.Count;
            int cleaned = Clean();
            Reply(user, "{0} / {1} entries in datafile have been removed", cleaned, count);
            SaveData();
        }
        private int Clean() {
            int count = 0;
            if (data == null) {
                return count;
            }
            var pi = CreatePlayerInfo();
            foreach (var info in data.PlayerInfo.ToList()) {
                if (info.Value.IsDefault(pi)) {
                    count++;
                    data.PlayerInfo.Remove(info.Key);
                }
            }
            return count;
        }
        private void PenaltyCommand(IPlayer user, string command, string[] args) {
            if (!user.IsAdmin) return;
            if (args.Length == 1 && args[0] == "status") {
                Reply(user, config.generic.penaltyOnDeath ? "Penalty is currently enabled." : "Penalty is currently disabled.");
                return;
            }
            if (args.Length == 0) config.generic.penaltyOnDeath = !config.generic.penaltyOnDeath;
            else config.generic.penaltyOnSuicide = !config.generic.penaltyOnSuicide;
            if (config.generic.penaltyOnDeath || config.generic.penaltyOnSuicide) {
                Subscribe(nameof(OnEntityDeath));
                Reply(user, "Penalty is now enabled.");
            }
            else {
                Unsubscribe(nameof(OnEntityDeath));
                Reply(user, "Penalty is now disabled.");
            }
            SaveConfig();
        }
        [ChatCommand("stats")]
        private void StatsCommand(BasePlayer player, string command, string[] args) {
            if (!hasRights(player)) {
                Message(player, "NoPermission");
                return;
            }
            string id = player.UserIDString;
            string L(string key, params object[] args) => Localize(key, id, args);
            _sb.Clear();
            _sb.Appen
// ... [Code preview truncated due to length. Full source in attached file] ...

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