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

FREE ScavengerHunt : 1.4.7 1.4.7

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
/*
 * https://github.com/DocValerian/rust-plugins
 * Copyright (C) 2022 DocValerian
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.* 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
 * GNU General Public License for more details.* 
 * You should have received a copy of the GNU General Public License
 * along with this program.If not, see <http://www.gnu.org/licenses/>.* 
 * Questions and (limited) Support can be found in our Discord: https://discord.gg/8tkBFRjg3W
 * 
 */
using System.Collections.Generic;
using Oxide.Core;
using Oxide.Core.Plugins;
using UnityEngine;
using System.Linq;
using System;
using Network;
using Oxide.Game.Rust.Cui;
using Newtonsoft.Json;
using Random = System.Random;
using System.Collections;

namespace Oxide.Plugins
{
    [Info("ScavengerHunt", "DocValerian", "1.4.7")]
    class ScavengerHunt : RustPlugin
    {
        static ScavengerHunt Plugin;

        [PluginReference]
        private Plugin ImageLibrary, ServerRewards, LootBoxSpawner, ZNTitleManager;

        const string permUse = "scavengerhunt.use";
        bool HasPermission(string id, string perm) => permission.UserHasPermission(id, perm);

        #region ConfigDataLoad
        protected override void SaveConfig() => Config.WriteObject(Cfg);
        protected override void LoadConfig()
        {
            base.LoadConfig();

            try
            {
                Cfg = Config.ReadObject<Configuration>();
            }
            catch (JsonException ex)
            {
                Puts(ex.Message);
                PrintError("Your configuration file contains a json error, shown above.Please fix this.");
                return;
            }
            catch (Exception ex)
            {
                Puts(ex.Message);
                LoadDefaultConfig();
            }

            if (Cfg == null)
            {
                Puts("Config is null");
                LoadDefaultConfig();
            }

            SaveConfig();
        }
        protected override void LoadDefaultConfig()
        {
            Cfg = new Configuration();
        }
        static Configuration Cfg = new Configuration();
        class Configuration
        {
            public int maxActiveHunts = 1;
            public float rerollBasePrice = 100f;
            public float rerollMultiplyer = 0.9f;

            [JsonProperty(PropertyName = "Scanvenger Quest Levels")]
            public Dictionary<string, ZNScavengerLevel> huntLevels = new Dictionary<string, ZNScavengerLevel>()
            {
                ["scavenge.easy"] = new ZNScavengerLevel { id = "scavenge.easy", numItems = 3, rewardPerCompletion = 1200, stacks = 3,
                    possibleItemNames = collectorItems,
                    questPoints = 4
                },
                ["scavenge.normal"] = new ZNScavengerLevel { id = "scavenge.normal", numItems = 4, rewardPerCompletion = 3000, stacks = 4,
                    possibleItemNames = collectorItems,
                    questPoints = 8
                },
                ["scavenge.hard"] = new ZNScavengerLevel { id = "scavenge.hard", numItems = 5, rewardPerCompletion = 3500, stacks = 6,
                    possibleItemNames = collectorItems,
                    questPoints = 16
                },
                ["scavenge.grind"] = new ZNScavengerLevel { id = "scavenge.grind", numItems = 7, rewardPerCompletion = 6000, stacks = 8,
                    possibleItemNames = collectorItems,
                    questPoints = 32
                },
                ["scavenge.insane"] = new ZNScavengerLevel { id = "scavenge.insane", numItems = 9, rewardPerCompletion = 10000, stacks = 9,
                    possibleItemNames = collectorItems,
                    questPoints = 64
                },
                ["hunting.normal"] = new ZNScavengerLevel
                {
                    id = "hunting.normal",
                    numItems = 3,
                    rewardPerCompletion = 4000,
                    stacks = 5,
                    possibleItemNames = hunterItems,
                    questPoints = 10
                },
                ["hunting.hard"] = new ZNScavengerLevel
                {
                    id = "hunting.hard",
                    numItems = 4,
                    rewardPerCompletion = 6500,
                    stacks = 7,
                    possibleItemNames = hunterItems,
                    questPoints = 20
                },
                ["hunting.grind"] = new ZNScavengerLevel
                {
                    id = "hunting.grind",
                    numItems = 6,
                    rewardPerCompletion = 10000,
                    stacks = 11,
                    possibleItemNames = hunterItems,
                    questPoints = 40
                },
                ["farming.normal"] = new ZNScavengerLevel
                {
                    id = "farming.normal",
                    numItems = 3,
                    rewardPerCompletion = 4000,
                    stacks = 2,
                    possibleItemNames = farmerItems,
                    questPoints = 10
                },
                ["farming.hard"] = new ZNScavengerLevel
                {
                    id = "farming.hard",
                    numItems = 4,
                    rewardPerCompletion = 6500,
                    stacks = 4,
                    possibleItemNames = farmerItems,
                    questPoints = 20
                },
                ["farming.grind"] = new ZNScavengerLevel
                {
                    id = "farming.grind",
                    numItems = 6,
                    rewardPerCompletion = 10000,
                    stacks = 7,
                    possibleItemNames = farmerItems,
                    questPoints = 40
                },
            };

            [JsonProperty(PropertyName = "Item Stacksize/Rarity Config")]
            public Dictionary<string, int> itemAmountPerStack = new Dictionary<string, int>()
            {
                ["bleach"] = 8,
                ["knife.butcher"] = 5,
                ["bucket.water"] = 3,
                ["pitchfork"] = 5,
                ["sickle"] = 5,
                ["woodcross"] = 3,
                ["smallwaterbottle"] = 3,
                ["antiradpills"] = 3,
                ["metalspring"] = 6,
                ["metalblade"] = 10,
                ["tarp"] = 3,
                ["roadsigns"] = 10,
                ["semibody"] = 2,
                ["can.beans"] = 5,
                ["gravestone"] = 3,
                ["coffin.storage"] = 3,
                ["chocholate"] = 10,
                ["smgbody"] = 1,
                ["sewingkit"] = 10,
                ["ammo.pistol.hv"] = 18,
                ["ammo.pistol.fire"] = 32,
                ["ammo.pistol"] = 37,
                ["hat.boonie"] = 3,
                ["mask.balaclava"] = 3,
                ["hat.beenie"] = 3,
                ["riot.helmet"] = 2,
                ["hat.wolf"] = 2,
                ["wall.graveyard.fence"] = 3,
                ["vehicle.1mod.cockpit.armored"] = 2,
                ["vehicle.1mod.passengers.armored"] = 2,
                ["vehicle.1mod.cockpit"] = 2,
                ["vehicle.1mod.cockpit.with.engine"] = 2,
                ["vehicle.2mod.passengers"] = 2,
                ["vehicle.1mod.rear.seats"] = 2,
                ["vehicle.1mod.engine"] = 2,
                ["vehicle.1mod.flatbed"] = 2,
                ["vehicle.2mod.fuel.tank"] = 2,
                ["vehicle.1mod.storage"] = 2,
                ["vehicle.2mod.flatbed"] = 2,
                ["stones"] = 350000,
                ["metal.ore"] = 100000,
                ["hq.metal.ore"] = 800,
                ["sulfur.ore"] = 70000,
                ["wood"] = 500000,
                ["scrap"] = 9000,
                ["fat.animal"] = 1000,
                ["bone.fragments"] = 2500,
                ["leather"] = 1000,
                ["bearmeat"] = 500,
                ["deermeat.raw"] = 50,
                ["meat.boar"] = 250,
                ["wolfmeat.raw"] = 200,
                ["chicken.raw"] = 50,
            };

            public int ChallengeEveryMinutes = 60;
            public int ChallengeCooldownMinutes = 20;
            public int WinnerReward = 5000;
            public int SecondReward = 2500;
            public int ThirdReward = 1200;
            public int ParticipantReward = 500;
            public int MinRewardScore = 30;
            public ulong infoPlayerID = 1212;
        }

        class StoredData
        {
            public DateTime lastChallengeTime = DateTime.Now.AddMinutes(-99);
            public string lastChallengeId = "";
            public CurrentChallenge currentChallenge;
            public HashSet<ulong> noUIPlayers = new HashSet<ulong>();
        }
        StoredData storedData;

        private List<TimedChallenge> Challenges = new List<TimedChallenge> {
            new TimedChallenge{ 
                id = "farmStone", 
                challengeScoreName = "Stone Nodes/Piles", 
                itemToFind = "stones", 
                name = "Stone Challenge", 
                duration = 30,
                title_f = "Stonemason",
                title_m = "Stonemason",
                title_e_f = "Queen of Rock",
                title_e_m = "King of Rock"
            },
            new TimedChallenge{ 
                id = "farmWood",
                challengeScoreName = "Trees/Stumps", 
                itemToFind = "wood", 
                name = "Lumber Challenge", 
                duration = 15,
                title_f = "Lumberjane",
                title_m = "Lumberjack",
                title_e_f = "Forest Queen",
                title_e_m = "Forest King"
            },
            new TimedChallenge{ 
                id = "farmMetal",   
                challengeScoreName = "Metal Nodes/Piles", 
                itemToFind = "metal.ore", 
                name = "Metal Challenge", 
                duration = 30,
                title_f = "Iron Lady",
                title_m = "Iron Man",
                title_e_f = "Queen of Metal",
                title_e_m = "King of Metal"
            },
            new TimedChallenge{ 
                id = "farmSulfur", 
                challengeScoreName = "Sulfur Nodes/Piles", 
                itemToFind = "sulfur.ore", 
                name = "Sulfur Challenge", 
                duration = 30,
                title_f = "Chemist",
                title_m = "Chemist",
                title_e_f = "Master Alchemist",
                title_e_m = "Master Alchemist"
            },
            new TimedChallenge{
                id = "farmBarrel",
                challengeScoreName = "Barrels",
                itemToFind = "barrel",
                name = "Barrel Challenge",
                duration = 15,
                title_f = "Road Warrior",
                title_m = "Road Warrior",
                title_e_f = "Queen of the Road",
                title_e_m = "King of the Road"
            },
            new TimedChallenge{
                id = "farmFish",
                challengeScoreName = "Fish",
                itemToFind = "fish",
                name = "Fishing Challenge",
                duration = 20,
                title_f = "Mermaid",
                title_m = "Master Fisher",
                title_e_f = "Queen of the Ocean",
                title_e_m = "King of the Ocean"
            },

            new TimedChallenge{
                id = "farmUnderworld",
                challengeScoreName = "Underground/-water NPCs",
                itemToFind = "dweller",
                name = "Underworld Challenge",
                duration = 20,
                title_f = "Dark Mistress",
                title_m = "Master of Darkness",
                title_e_f = "Goddess of the Underworld",
                title_e_m = "God of the Underworld"
            },
            new TimedChallenge{
                id = "farmPlants",
                challengeScoreName = "Plants",
                itemToFind = "plants",
                name = "Plant Challenge",
                duration = 20,
                title_f = "Herbalist",
                title_m = "Herbalist",
                title_e_f = "Goddess of Harvest",
                title_e_m = "God of Harvest"
            },
        };

        void Loaded()
        {
            Plugin = this;
            permission.RegisterPermission(permUse, this);
            //storedData = new StoredData();
            storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>("ScavengerHunt");
            SaveData(storedData);

        }

        private void OnServerInitialized()
        {
            StartChallengeCoroutine();
            loadLiveUI();
            initTitles();
        }

        void Unload()
        {
            StopChallengeCoroutine();
            foreach (var player in UiPlayers.ToList())
            {
                killUI(player);
            }

            foreach (var player in LiveUiPlayers.ToList())
            {
                killLiveUI(player);
            }
        }


        private static void LoadData<T>(out T data, string filename = null)
        {
            try
            {
                data = Interface.Oxide.DataFileSystem.ReadObject<T>(filename ?? "ScavengerHunt");
            }
            catch (JsonException ex)
            {
                Plugin.Puts("E1:" + ex.Message);
                data = default(T);
            }
            catch (Exception ex)
            {
                Plugin.Puts("E2: " + ex.Message + "\n"+ex.InnerException);
                data = default(T);
            }
        }

        private static void SaveData<T>(T data, string filename = null) =>
        Interface.Oxide.DataFileSystem.WriteObject(filename ?? "ScavengerHunt", data);
        #endregion

        #region global params
        private static List<string> collectorItems = new List<string>() { 
            "knife.butcher", 
            "bucket.water", 
            "pitchfork", 
            "sickle", 
            "woodcross", 
            "smallwaterbottle", 
            "antiradpills", 
            "metalspring", 
            "metalblade",
            "tarp", 
            "roadsigns",
            "semibody", 
            "can.beans", 
            "gravestone", 
            "coffin.storage", 
            "chocholate", 
            "smgbody", 
            "sewingkit", 
            "ammo.pistol.hv", 
            "ammo.pistol.fire", 
            "ammo.pistol", 
            "hat.boonie", 
            "mask.balaclava", 
            "hat.beenie", 
            "riot.helmet", 
            "hat.wolf",
            "vehicle.1mod.cockpit.armored",
            "vehicle.1mod.passengers.armored", 
            "vehicle.1mod.cockpit",
            "vehicle.1mod.cockpit.with.engine",
            "vehicle.2mod.passengers", 
            "vehicle.1mod.rear.seats", 
            "vehicle.1mod.engine", 
            "vehicle.1mod.flatbed", 
            "vehicle.2mod.fuel.tank", 
            "vehicle.1mod.storage", 
            "vehicle.2mod.flatbed" 
        };
        private static List<string> farmerItems = new List<string>() {
            "stones",
            "metal.ore",
            "hq.metal.ore",
            "sulfur.ore",
            "wood",
            "scrap",
        };
        private static List<string> hunterItems = new List<string>() {
            "fat.animal",
            "bone.fragments",
            "leather",
            "bearmeat",
            "deermeat.raw",
            "meat.boar",
            "wolfmeat.raw",
            "chicken.raw",
        };
        private Dictionary<ulong, ScavengerManager> _sm = new Dictionary<ulong, ScavengerManager>();
        private Coroutine challengeCoroutine { get; set; }
        private static List<string> plantList = new List<string>() { "potato", "cloth", "red.berry", "blue.berry", "green.berry", "yellow.berry", "white.berry", "black.berry", "mushroom", "pumpkin", "corn"};
        private Dictionary<string, int> fishValueList = new Dictionary<string, int>()
        {
            ["fish.anchovy"] = 2,
            ["fish.catfish"] = 9,
            ["fish.herring"] = 2,
            ["fish.minnows"] = 1,
            ["fish.orangeroughy"] = 7,
            ["fish.salmon"] = 5,
            ["fish.sardine"] = 2,
            ["fish.smallshark"] = 8,
            ["fish.troutsmall"] = 3,
            ["fish.yellowperch"] = 5
        };
        #endregion

        #region Classes

        class TimedChallenge
        {
            public string id { get; set; }
            public string name { get; set; }
            public string itemToFind { get; set; }
            public string challengeScoreName { get; set; }
            public int duration { get; set; }

            public string type = "farming";
            public string title_m { get; set; }
            public string title_f { get; set; }
            public string title_e_m { get; set; }
            public string title_e_f { get; set; }
        }

        class CurrentChallenge
        {
            public TimedChallenge info { get; set; }
            public DateTime startTime { get; set; }
            public Dictionary<ulong, int> highscores { get; set; }
            public Dictionary<ulong, string> playerNames { get; set; }

            public CurrentChallenge(TimedChallenge tc) : base()
            {
                info = tc;
                startTime = DateTime.Now;
                highscores = new Dictionary<ulong, int>();
                playerNames = new Dictionary<ulong, string>();
            }
        }
      

        public class ZNScavengerLevel
        {
            public string id { get; set; }
            public int numItems { get; set; }
            public List<string> possibleItemNames { get; set; }
            public int rewardPerCompletion { get; set; }
            public int stacks { get; set; }
            public int questPoints { get; set; }

        } 

        public class ZNScavengingQuest
        {
            public ulong id { get; set; }
            public Dictionary<string, int> itemsToFind { get; set; }
            public int promisedReward { get; set; }
            public bool isComplete { get; set; }
            public int promisedQuestPoints { get; set; }
            public string level { get; set; }

            public ZNScavengingQuest() : base()
            {
            }
            public ZNScavengingQuest(string qLevel) : base()
            {
                id = (ulong)DateTimeOffset.Now.ToUnixTimeMilliseconds();
                level = qLevel;
                initQuest();
            }

            private void initQuest()
            {
                if (!Cfg.huntLevels.ContainsKey(level)) return;
                ZNScavengerLevel l = Cfg.huntLevels[level];

                itemsToFind = new Dictionary<string, int>();
                itemsToFind.Add("bleach", Cfg.itemAmountPerStack["bleach"] * l.stacks);
                int amountPerStack = 1;

                foreach (string prefab in Plugin.UniqueRandomKeys(l.possibleItemNames).Take(l.numItems))
                {
                    if (Cfg.itemAmountPerStack.ContainsKey(prefab)) amountPerStack = Cfg.itemAmountPerStack[prefab];
                    itemsToFind.Add(prefab, (amountPerStack * l.stacks));
                }
                promisedReward = l.rewardPerCompletion;
                promisedQuestPoints = l.questPoints;
            }

            public void Pay(BasePlayer player)
            {
                if (player.inventory.containerMain.IsEmpty()) return;

                Dictionary<string, int> playerItems = Plugin.GetPlayerItems(player);
                int taken = 0;
                int totalRemain = 0;
                int itmID;

                foreach (KeyValuePair<string, int> d in itemsToFind.ToList())
                {

                    totalRemain += itemsToFind[d.Key];
                    if (!(playerItems.ContainsKey(d.Key)) || d.Value == 0) continue;
                    totalRemain -= itemsToFind[d.Key];

                    itmID = ItemManager.itemDictionaryByName[d.Key].itemid;
                    taken = player.inventory.containerMain.Take(null, itmID, d.Value);

                    itemsToFind[d.Key] -= taken;
                    totalRemain += itemsToFind[d.Key];
                }
                if (totalRemain == 0) isComplete = true;

            }
        }
        private class ScavengerManager
        {
            public ulong playerID;
            private BasePlayer bPlayer;
            public Dictionary<ulong, ZNScavengingQuest> quests = new Dictionary<ulong, ZNScavengingQuest>();
            public ZNScavengingQuest lastTempQuest;
            public int questGenerationCounter = 0;
            public int questsCompleted = 0;
            public int questsAbandoned = 0;
            public int questsPoints = 0;

            public ScavengerManager(ulong playerId) : base()
            {
                playerID = playerId;
            }
            public static ScavengerManager Get(ulong playerId, bool wipe = false)
            {
                if (Plugin._sm.ContainsKey(playerId) && !wipe)
                    return Plugin._sm[playerId];

                var fileName = $"{Plugin.Name}/{playerId}";

                ScavengerManager manager;
                if (Interface.Oxide.DataFileSystem.ExistsDatafile(fileName) && !wipe)
                {
                    // Load existing Data
                    ScavengerHunt.LoadData(out manager, fileName);
                    if (!(manager is ScavengerManager)) return null;
                }
                else
                {
                    // Create a completely new Playerdataset
                    manager = new ScavengerManager(playerId);
                    ScavengerHunt.SaveData(manager, fileName);
                }

                Interface.Oxide.DataFileSystem.GetDatafile(fileName).Settings = new JsonSerializerSettings
                {
                    DefaultValueHandling = DefaultValueHandling.Populate
                };
                manager.bPlayer = BasePlayer.FindAwakeOrSleeping(playerId.ToString());
                Plugin._sm[playerId] = manager;

                return manager;
            }

            public void SaveData()
            {
                ScavengerHunt.SaveData(this, $"{Plugin.Name}/{playerID}");
            }
            public void SetTempQuest(ZNScavengingQuest q)
            {
                lastTempQuest = q;
                questGenerationCounter++;
            }

            public void AcceptQuest()
            {
                if (lastTempQuest == null) return;
                quests[lastTempQuest.id] = lastTempQuest;
                lastTempQuest = null;
            }

            public void AbandonQuest()
            {
                if (CurrentQuest().isComplete)
                {
                    FinishQuest();
                    return;
                }
                quests.Clear();
                questsAbandoned++;
                SaveData();
            }
            public void Pay()
            {
                ZNScavengingQuest q = CurrentQuest();
                if (q.isComplete)
                {
                    FinishQuest();
                    return;
                }
                q.Pay(bPlayer);
                SaveData();
            }

            public void FinishQuest()
            {
                ZNScavengingQuest q = CurrentQuest();
                if (q.isComplete)
                {
                    lastTempQuest = null;
                    questGenerationCounter = 0;
                    quests.Clear();
                    questsCompleted++;
                    questsPoints += q.promisedQuestPoints;
                    Plugin.ZNTitleManager?.Call("CheckScore", Plugin.Name + "_" + "quests", (float)questsPoints, playerID);
                    SaveData(); 
                    Item blood = ItemManager.CreateByName("blood", q.promisedReward);
                    bPlayer.GiveItem(blood, BaseEntity.GiveItemReason.PickedUp);
                }
            }

            public ZNScavengingQuest CurrentQuest()
            {
                if (quests.Count == 0) return null;

                foreach(ZNScavengingQuest q in quests.Values)
                {
                    //for now we only need one
                    return q;
                }

                return null;
            }


        }

        public static class Coroutines
        {
            private static Dictionary<float, YieldInstruction> mem;
            public static void Clear()
            {
                if (mem != null)
                {
                    mem.Clear();
                    mem = null;
                }
            }
            public static YieldInstruction WaitForSeconds(float delay)
            {
                if (mem == null)
                {
                    mem = new Dictionary<float, YieldInstruction>();
                }

                YieldInstruction yield;
                if (!mem.TryGetValue(delay, out yield))
                {
                    yield = new WaitForSeconds(delay);
                    mem.Add(delay, yield);
                }

                return yield;
            }

            
        }
        #endregion

        #region Hooks
        void OnPlayerSleepEnded(BasePlayer player)
        {
            if (!(storedData.noUIPlayers.Contains(player.userID)) && !LiveUiPlayers.Contains(player))
            {
                LiveUiPlayers.Add(player);
            }
        }
        void OnPlayerDisconnected(BasePlayer player)
        {
            killUI(player);
            killLiveUI(player);
            if (_sm.ContainsKey(player.userID))
            {
                _sm[player.userID].SaveData();
                _sm.Remove(player.userID);
            }
        }

        private void OnEntityDeath(BaseCombatEntity victimEntity, HitInfo hitInfo)
        {
            // Ignore - there is no victim for some reason
            if (victimEntity == null)
                return;

            // Try to avoid error when entity was destroyed
            if (victimEntity.gameObject == null)
                return;

            // barrel bleach
            var name = victimEntity.ShortPrefabName;
            if (name.Contains("barrel") && !name.Contains("hobo"))
            {
                var KillerEntity = victimEntity.lastAttacker ?? hitInfo?.Initiator;
                if (!(KillerEntity is BasePlayer))
                    return;

                checkChallengeProgress((BasePlayer)KillerEntity, "barrel");
                float rand = UnityEngine.Random.Range(1, 101);
                if (rand > 50) return;
                Item item = ItemManager.CreateByName("bleach", 1);
                item.name = "Quest Item /q";
                item.Drop((victimEntity.transform.position+new Vector3(0f,1f,0f)), Vector3.down);
            }
            // dweller kill challenge
            if (name.Contains("dweller"))
            {
                var KillerEntity = victimEntity.lastAttacker ?? hitInfo?.Initiator;
                if (!(KillerEntity is BasePlayer))
                    return;

                checkChallengeProgress((BasePlayer)KillerEntity, "dweller");
            }
        }

        Item OnFishCatch(Item fish, BaseFishingRod fishingRod, BasePlayer player)
        {
            if (fish.info == null || fish.info.shortname == null) return fish;

            if (fishValueList.ContainsKey(fish.info.shortname))
            {
                checkChallengeProgress(player, "fish", fishValueList[fish.info.shortname]);
            }
            return fish;
        }

        private void OnDispenserBonus(ResourceDispenser dispenser, BaseEntity entity, Item item)
        {
            var player = entity as BasePlayer;
            if (player == null) return;
            checkChallengeProgress(player, item.info.shortname);
        }
        object OnCollectiblePickup(CollectibleEntity collectible, BasePlayer player)
        {
            if (player == null) return null;
            Item item = collectible.GetItem();
            for (int i = 0; i < collectible.itemList.Length; i++)
            {
                ItemAmount itemAmount = collectible.itemList[i];
                string itemName = itemAmount.itemDef.shortname;
                checkChallengeProgress(player, itemName);
                if (plantList.Contains(itemName)) checkChallengeProgress(player, "plants");  
            }
            return null;
        }

        #endregion

        #region Commands

        [ConsoleCommand("shunt.close")]
        private void CmdClose(ConsoleSystem.Arg arg)
        {
            var player = arg.Connection.player as BasePlayer;
            if (player == null || !HasPermission(arg.Player().UserIDString, permUse))
                return;
            killUI(player);

            if (_sm.ContainsKey(player.userID))
            {
                _sm[player.userID].SaveData();
            }
        }

        [ConsoleCommand("shunt.generate")]
        private void CmdGenerate(ConsoleSystem.Arg arg)
        {
            var player = arg.Connection.player as BasePlayer;
            if (player == null || !HasPermission(arg.Player().UserIDString, permUse))
                return;
            string levelId = arg.GetString(0);

            if (_sm.ContainsKey(player.userID))
            {
                ZNScavengingQuest q = new ZNScavengingQuest(levelId);
                _sm[player.userID].SetTempQuest(q);
                CuiHelper.DestroyUi(player, mainName + "_quest");
                GUIQuestElement(player, mainName + "_quest", mainName + "_main", q, eSelectQTop);

            }
        }
        [ConsoleCommand("shunt.accept")]
        private void CmdAccept(ConsoleSystem.Arg arg)
        {
            var player = arg.Connection.player as BasePlayer;
            if (player == null || !HasPermission(arg.Player().UserIDString, permUse))
                return;
            string levelId = arg.GetString(0);

            if (_sm.ContainsKey(player.userID))
            {
                _sm[player.userID].AcceptQuest();
                CuiHelper.DestroyUi(player, mainName + "_quest");
                CuiHelper.DestroyUi(player, mainName + "_main");
                GUIMainElement(player, mainName + "_main", _sm[player.userID]);

            }
        }
        [ConsoleCommand("shunt.abandon")]
        private void CmdAbandon(ConsoleSystem.Arg arg)
        {
            var player = arg.Connection.player as BasePlayer;
            if (player == null || !HasPermission(arg.Player().UserIDString, permUse))
                return;
            string levelId = arg.GetString(0);

            if (_sm.ContainsKey(player.userID))
            {
                _sm[player.userID].AbandonQuest();
                CuiHelper.DestroyUi(player, mainName + "_quest");
                CuiHelper.DestroyUi(player, mainName + "_main");
                GUIMainElement(player, mainName + "_main", _sm[player.userID]);

            }
        }

        [ConsoleCommand("shunt.pay")]
        private void CmdPay(ConsoleSystem.Arg arg)
        {
            var player = arg.Connection.player as BasePlayer;
            if (player == null || !HasPermission(arg.Player().UserIDString, permUse))
                return;
            string levelId = arg.GetString(0);

            if (_sm.ContainsKey(player.userID))
            {
                _sm[player.userID].Pay();
                CuiHelper.DestroyUi(player, mainName + "_quest");
                CuiHelper.DestroyUi(player, mainName + "_main");
                GUIMainElement(player, mainName + "_main", _sm[player.userID]);

            }
        }

        [ConsoleCommand("shunt.finish")]
        private void CmdFinish(ConsoleSystem.Arg arg)
        {
            var player = arg.Connection.player as BasePlayer;
            if (player == null || !HasPermission(arg.Player().UserIDString, permUse))
                return;
            string levelId = arg.GetString(0);

            if (_sm.ContainsKey(player.userID))
            {
                _sm[player.userID].FinishQuest();
                CuiHelper.DestroyUi(player, mainName + "_quest");
                CuiHelper.DestroyUi(player, mainName + "_main");
                GUIMainElement(player, mainName + "_main", _sm[player.userID]);

            }
        }


        [ConsoleCommand("shunt.admset")]
        private void CmdAdmSet(ConsoleSystem.Arg arg)
        {
            var player = arg.Connection.player as BasePlayer;
            if (player == null || !player.IsAdmin)
                return;
            ulong pId = ulong.Parse(arg.GetString(0));
            int score = arg.GetInt(1);

           if(storedData.currentChallenge.highscores.ContainsKey(pId))
            {
                storedData.currentChallenge.highscores[pId] = score;
            }
        }

        [ChatCommand("qold")]
        void MainCommand(BasePlayer player, string command, string[] args)
        {
            if (!HasPermission(player.UserIDString, permUse))
            {
                SendReply(player, "You don't have permission to use this command");
                return;
            }
            if (!_sm.ContainsKey(player.userID))
            {
                _sm[player.userID] = ScavengerManager.Get(player.userID);
            }
            reloadUI(player);
        }

        [ChatCommand("qc")]
        void ChallengeUICommand(BasePlayer player, string command, string[] args)
        {
            if (!HasPermission(player.UserIDString, permUse))
            {
                SendReply(player, "You don't have permission to use this command");
                return;
            }

            if(args.Length == 1)
            {
                switch (args[0])
                {
                    case "ui":
                        toggleUI(player);
                        return;
                    default:
                        break;
                }
            }
                
            showInfoMessage(player);
        }

        [ChatCommand("qcs")]
        void ChallengeADMCommand(BasePlayer player, string command, string[] args)
        {
            if (!player.IsAdmin)
            {
                SendReply(player, "You don't have permission to use this command");
                return;
            }
            if(storedData.currentChallenge != null) finishChallenge();
            storedData.currentChallenge = null;
            storedData.lastChallengeTime = DateTime.Now.AddMinutes(-99);
            SaveData(storedData);
        }

        #endregion

        #region Functions
        private void initTitles() 
        {
            // Challenge Titles
            foreach(TimedChallenge c in Challenges)
            {
                ZNTitleManager?.Call("UpsertTitle", getTitleID(c), c.name, c.challengeScoreName, c.title_e_m, c.title_e_f, c.title_m, c.title_f);
            }
            // Quest Title
            ZNTitleManager?.Call("UpsertTitle", Plugin.Name + "_" +"quests", "Quests", "/Q Score", "Quest Master", "Quest Queen", "Adventurer", "Scavenger");

        }

        private string getTitleID(TimedChallenge t)
        {
            return Plugin.Name + "_" + t.id;
            
        }
        private void loadLiveUI()
        {
            foreach (var p in BasePlayer.activePlayerList)
            {
                if (!(storedData.noUIPlayers.Contains(p.userID)) && !LiveUiPlayers.Contains(p))
                {
                    LiveUiPlayers.Add(p);
                }
            }
        }
        private void toggleUI(BasePlayer player)
        {
            string msg = "<color=green>ZN-Quests:</color> Challenge Quest UI ";
            if (storedData.noUIPlayers.Contains(player.userID))
            {
                storedData.noUIPlayers.Remove(player.userID);
                msg += "<color=green>Activated!</color>";
                reloadLiveUI(player);
            }
            else
            {
                storedData.noUIPlayers.Add(player.userID);
                msg += "<color=red>Disabled!</color>";
                killLiveUI(player);
            }
            SendReply(player, msg);
        }
        private void showInfoMessage(BasePlayer player)
        {
            string msg = "<color=orange>===== ZN Quests - Challenges ======</color>";
            msg += "\nQuest Challenges are timed server wide challenges.";
            msg += "\nGoal is to collect the current resource (farm&gather).";
            msg += "\nIt counts only number of nodes finished or piles gathered, to";
            msg += "\nkeep it fair for everyone, no matter their levels";
            if (storedData.currentChallenge != null)
            {
                CurrentChallenge c = storedData.currentChallenge;
                msg += "\n\n<color=green>Current Challenge:</color>";
                msg += "\nFind: \t\t\t\t" + c.info.challengeScoreName;
                msg += "\nTime Left: \t\t\t"+ (c.info.duration - (DateTime.Now- c.startTime).Minutes) + " minutes";
            }
            else
            {
                msg += "\n\n<color=green>Next Challenge:</color>";
                msg += "\nStarts in: \t\t\t\t" + (Cfg.ChallengeCooldownMinutes - (DateTime.Now - storedData.lastChallengeTime).Minutes) + " minutes";
                msg += "\nCan't be: \t\t\t\t" + storedData.lastChallengeId;

            }
            msg += "\n\n<color=green>Commands:</color>";
            msg += "\n/qc \t\t\t\tshow this info";
            msg += "\n/qc ui \t\t\ttoggle info UI";
            msg += "\n/loot \t\t\t\tGet your reward if you won.";

            msg += "\n\n<color=green>Rules:</color>";
            msg += "\nA Challenge lasts: \t<color=orange>10-30 minutes</color>";
            msg += "\nChallenge cooldown: \t<color=orange>" + Cfg.ChallengeCooldownMinutes+ " minutes</color> (til next)";
            msg += "\nYou need to reach \t<color=red>Min Reward Score " + (Cfg.MinRewardScore) +"</color>";

            msg += "\nWinner gets: \t\t<color=orange>" + (Cfg.WinnerReward) + " Blood</color>";
            msg += "\n2nd gets: \t\t\t<color=orange>" + (Cfg.SecondReward) + " Blood</color>";
            msg += "\n3rd gets: \t\t\t<color=orange>" + (Cfg.ThirdReward) + " Blood</color>";
            msg += "\nParticipant: \t\t<color=orange>" + (Cfg.ParticipantReward) + " Blood</color>";

            SendReply(player, msg);
        }
        private void checkChallengeProgress(BasePlayer player, string item, int value = 1)
        {
            if (storedData.currentChallenge == null) return;
            CurrentChallenge c = storedData.currentChallenge;
            if (c.info.itemToFind != item)
            {
                return;
            }
            addPlayerScore(player, value);
        }

        private void addPlayerScore(BasePlayer player, int value = 1)
        {
            CurrentChallenge c = storedData.currentChallenge;
            if (c.highscores.ContainsKey(player.userID))
            {
                c.highscores[player.userID] += value;
            }
            else
            {
                c.highscores.Add(player.userID, value);
            }
            if (!(c.playerNames.ContainsKey(player.userID))) c.playerNames.Add(player.userID, player.displayName);
        }
        private void StopChallengeCoroutine()
        {
            if (challengeCoroutine != null)
            {
                ServerMgr.Instance.StopCoroutine(challengeCoroutine);
                challengeCoroutine = null;
            }
        }

        private void StartChallengeCoroutine()
        {
            StopChallengeCoroutine();
            timer.Once(0.2f, () =>
            {
                challengeCoroutine = ServerMgr.Instance.StartCoroutine(ChallengeCoroutine());
            });
        }
        private IEnumerator ChallengeCoroutine()
        {
            float secondsToNextAction = 2f;
            while (true)
            {
                // start a new challenge
                if(storedData.currentChallenge == null)
                {
                    double minutesSinceLast = (DateTime.Now - storedData.lastChallengeTime).TotalMinutes;
                    if (minutesSinceLast <= Cfg.ChallengeCooldownMinutes)
                    {
                        secondsToNextAction = 60f;                       
                    }
                    else
                    {
                        secondsToNextAction = 2f;
                        TimedChallenge c = Challenges.GetRandom();
                        if (c.id == storedData.lastChallengeId) continue;
                        Puts("DEBUG: START new Challenge "  + c.name);
                        storedData.lastChallengeId = c.id;
                        storedData.currentChallenge = new CurrentChallenge(c);
                        Server.Broadcast("<color=green>ZN-Quests:</color> A new challenge quest for <color=orange>" + c.challengeScoreName + "</color> has started!");

                        storedData.currentChallenge.highscores.Add(Cfg.infoPlayerID, Cfg.MinRewardScore);
                        storedData.currentChallenge.playerNames.Add(Cfg.infoPlayerID, "--- MIN REWARD SCORE ---");

                        loadLiveUI();

                        /* DEBUG CODE
                        storedData.currentChallenge.highscores.Add(2325235235, 12);
                        storedData.currentChallenge.playerNames.Add(2325235235, "FooBar");
                        storedData.currentChallenge.highscores.Add(43534, 15);
                        storedData.currentChallenge.playerNames.Add(43534, "test er ment");

                        storedData.currentChallenge.highscores.Add(232355235235, 5);
                        storedData.currentChallenge.playerNames.Add(232355235235, "Foorethr Bar");
                        storedData.currentChallenge.highscores.Add(434534, 3);
                        storedData.currentChallenge.playerNames.Add(434534, "test 44ent");

                        storedData.currentChallenge.highscores.Add(23252352354, 2);
                        storedData.currentChallenge.playerNames.Add(23252352354, "F4f ar");
                        storedData.currentChallenge.highscores.Add(435344, 1);
                        storedData.currentChallenge.playerNames.Add(435344, "erhret ment");

                        storedData.currentChallenge.highscores.Add(232523523544, 9);
                        storedData.currentChallenge.playerNames.Add(232523523544, "trr rth");
                        storedData.currentChallenge.highscores.Add(4353444, 52);
                        storedData.currentChallenge.playerNames.Add(4353444, "bnm tzj tr");

                        storedData.currentChallenge.highscores.Add(2325235, 11);
                        storedData.currentChallenge.playerNames.Add(2325235, "ttz");
                        storedData.currentChallenge.highscores.Add(4353, 16);
                        storedData.currentChallenge.playerNames.Add(4353, "tzjukiuk");

                        storedData.currentChallenge.highscores.Add(232523525, 14);
                        storedData.currentChallenge.playerNames.Add(232523525, "vsddf");
                        storedData.currentChallenge.highscores.Add(4334, 42);
                        storedData.currentChallenge.playerNames.Add(4334, "bts");

                        storedData.currentChallenge.highscores.Add(76561197998677819, 44);
                        storedData.currentChallenge.playerNames.Add(76561197998677819, "DocValerian");
                        */
                    }

                }
                // finish challenge
                else if((DateTime.Now - storedData.currentChallenge.startTime).TotalMinutes >= storedData.currentChallenge.info.duration)
                {

                    finishChallenge();
                    storedData.lastChallengeTime = DateTime.Now;
                    storedData.currentChallenge = null;
                    secondsToNextAction = 15f;
                }
                // run challenge progression
                else
                {
                    if (LiveUiPlayers.Count > 0)
                    {
                        foreach (BasePlayer p in LiveUiPlayers)
                        {
                            reloadLiveUI(p);
                        }
                    }

                }

                SaveData(storedData);

                //yield return Coroutines.WaitForSeconds(2f);
                //continue;
                yield return Coroutines.WaitForSeconds(secondsToNextAction);
            }
        }

        private void finishChallenge()
        {
            CurrentChallenge c = storedData.currentChallenge;
            Puts("DEBUG: FINISH Challenge " + c.info.name);
            foreach (var player in LiveUiPlayers.ToList())
            {
                killLiveUI(player);
            }
            List<ulong> sortedChallengers = sortChallengers(c.highscores);
            int place = 1;
            string msg = "<color=green>ZN-Quests:</color> The " + c.info.name + " has ended.";
            foreach (ulong cId in sortedChallengers)
            {
                if (cId == Cfg.infoPlayerID) continue;
                if(c.highscores[cId] < Cfg.MinRewardScore)
                {
                    if(place == 1)
                    {
                        Server.Broadcast(msg + "\nNobody reached the minimum reward limit :(");
                    }
                    Puts("Place: " + place+ " player: " + cId + " did not reach min score of " + Cfg.MinRewardScore);
                    break;
                }
                else
                { 
                    switch (place)
                    {
                        case 1:
                            msg += "\nScores:";
                            setRewardClaim(cId, Cfg.WinnerReward, "WINNER");
                            ZNTitleManager?.Call("CheckScore", getTitleID(c.info), (float)c.highscores[cId], cId);
                            break;
                        case 2:
                            setRewardClaim(cId, Cfg.SecondReward, "SECOND");
                            break;
                        case 3:
                            setRewardClaim(cId, Cfg.ThirdReward, "THIRD");
                            break;
                        default:
                            setRewardClaim(cId, Cfg.ParticipantReward, "participant");
                            break;
                    }

                    if(place <= 10)
                    {
                        msg += "\n - " + place + " - <color=orange>" + c.playerNames[cId] + "</color> (score: " + c.highscores[cId] + ")";
                    }
                    place++;
                }
            }
            Server.Broadcast(msg);

        }

        private void setRewardClaim(ulong pId, int reward, string place)
        {
            Puts(place+": " + pId + " with " + storedData.currentChallenge.highscores[pId]);
            LootBoxSpawner.Call("storeChallengeClaim", pId, reward);
            var p = BasePlayer.FindByID(pId);
            if (p != null)
            {
                SendReply(p, "<color=green>ZN-Quest:</color> You are "+place+" in the last Challenge Quest.\nUse <color=orange>/loot</color> to claim your reward.");
            }
        }


// ... [Code preview truncated due to length. Full source in attached file] ...

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