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

FREE WaterBases : 1.0.20 1.0.20

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using UnityEngine;
namespace Oxide.Plugins {
    [Info("WaterBases", "Nikedemos", "1.0.20")]
    [Description("Allows vanilla-like constructions on water surface - and underwater too!")]
    public class WaterBases : RustPlugin {
        private static WaterBases Instance;
#region CONST & STATIC
        public const string PREFAB_SHARK_ALIVE = "assets/rust.ai/agents/fish/simpleshark.prefab";
        public const string PREFAB_SHARK_DEAD = "assets/rust.ai/agents/fish/shark.corpse.prefab";
        public const string PREFAB_FLOOR_SQUARE = "assets/prefabs/building core/floor/floor.prefab";
        public const string PREFAB_FLOOR_TRIANGLE = "assets/prefabs/building core/floor.triangle/floor.triangle.prefab";
        public const string PREFAB_BARREL = "assets/prefabs/resource/diesel barrel/diesel_barrel_world.prefab";
        public const string PREFAB_NETTING = "assets/prefabs/building/wall.frame.netting/wall.frame.netting.prefab";
        public const string PREFAB_BARREL_COLLECTABLE = "assets/content/structures/excavator/prefabs/diesel_collectable.prefab";
        public const string PREFAB_OILRIG_1 = "OilrigAI";
        public const string PREFAB_OILRIG_2 = "OilrigAI2";
        public const string PREFAB_POOL_BIG = "assets/prefabs/misc/summer_dlc/abovegroundpool/abovegroundpool.deployed.prefab";
        public const string PREFAB_POOL_SMALL = "assets/prefabs/misc/summer_dlc/paddling_pool/paddlingpool.deployed.prefab";
        public const string PREFAB_BUILD_EFFECT = "assets/bundled/prefabs/fx/build/frame_place.prefab";
        public const string CMD_WB_GIVE = "wb.give";
        public const int ITEM_INNER_TUBE = -697981032;
        public const int ITEM_BUILDING_PLANNER = 1525520776;
        public const ulong ITEM_SKIN_FOUNDATION_SQUARE = 2484982352;
        public const ulong ITEM_SKIN_FOUNDATION_TRIANGLE = 2485021365;
        public static LayerMask DeployedMask = LayerMask.GetMask("Deployed");
        public static LayerMask ConstructionMask = LayerMask.GetMask("Construction");
        public static BaseEntity.Flags FLAG_ALREADY_APPLIED = BaseEntity.Flags.OnFire;
        private static object ReusableObject;
        private static bool ReusableBool;
        private static string ReusableString;
        private static float ReusableFloat;
        private static bool ReusableBool2;
        private static string ReusableString2;
        private static float ReusableFloat2;
        private static int ReusableInt2;
        private static ulong ReusableUlong2;
        public static readonly List<string> FramePrefabs = new List<string> {
            "assets/prefabs/building core/floor.frame/floor.frame.prefab", "assets/prefabs/building core/floor.triangle.frame/floor.triangle.frame.prefab", "assets/prefabs/building core/wall.frame/wall.frame.prefab"
        }
        ;
        public static readonly List<ulong> RelevantSkins = new List<ulong> {
            ITEM_SKIN_FOUNDATION_SQUARE, ITEM_SKIN_FOUNDATION_TRIANGLE,
        }
        ;
        public static List<Vector3> FloorBarrelPositionsSquare = new List<Vector3> {
            new Vector3(0F, -0.4F, 0.33F), new Vector3(0F, -0.4F, -0.33F), new Vector3(-0.33F, -0.4F, 1.12F), new Vector3(-0.33F, -0.4F, 0.36F), new Vector3(-0.33F, -0.4F, -0.36F), new Vector3(-0.33F, -0.4F, -1.12F), new Vector3(0.33F, -0.4F, 1.12F), new Vector3(0.33F, -0.4F, 0.36F), new Vector3(0.33F, -0.4F, -1.12F), new Vector3(0.33F, -0.4F, -0.36F)
        }
        ;
        public static List<Vector3> FloorBarrelRotationsSquare = new List<Vector3> {
            new Vector3(0F, 90F, 90F), new Vector3(0F, 90F, 270F), new Vector3(0F, 0F, 90F), new Vector3(0F, 0F, 90F), new Vector3(0F, 0F, 90F), new Vector3(0F, 0F, 90F), new Vector3(0F, 0F, 270F), new Vector3(0F, 0F, 270F), new Vector3(0F, 0F, 270F), new Vector3(0F, 0F, 270F)
        }
        ;
        public static List<Vector3> FloorBarrelPositionsTriangle= new List<Vector3> {
            new Vector3(0F, -0.4F, -0.6F+1.5F), new Vector3(0.42F, -0.4F, -0.42F+1.5F), new Vector3(-0.42F, -0.4F, -0.42F+1.5F), new Vector3(0F, -0.4F, -1.17F+1.5F), new Vector3(0F, -0.4F, -1.17F+1.5F)
        }
        ;
        public static List<Vector3> FloorBarrelRotationsTriangle = new List<Vector3> {
            new Vector3(0F, 90F, 90F), new Vector3(0F, 0F, 90F), new Vector3(0F, 180F, 90F), new Vector3(0F, 180F, 90F), new Vector3(0F, 0F, 90F)
        }
        ;
#endregion
#region LANG
        public const string MSG_ITEM_NAME_TRIANGLE = "MSG_ITEM_NAME_TRIANGLE";
        public const string MSG_ITEM_NAME_SQUARE = "MSG_ITEM_NAME_SQUARE";
        public const string MSG_CHAT_PREFIX = "MSG_CHAT_PREFIX";
        public const string MSG_DEPLOY_ERROR = "MSG_DEPLOY_ERROR";
        public const string MSG_CRAFT = "MSG_CRAFT";
        public const string MSG_DEPLOY_RESULT_BUILDING_BLOCKED = "MSG_DEPLOY_RESULT_BUILDING_BLOCKED";
        public const string MSG_DEPLOY_RESULT_TOPOLOGY_MISMATCH = "MSG_DEPLOY_RESULT_TOPOLOGY_MISMATCH";
        public const string MSG_DEPLOY_RESULT_NO_PERM_DEPLOY = "MSG_DEPLOY_RESULT_NO_PERM_DEPLOY";
        public const string MSG_DEPLOY_RESULT_NO_PERM_EXPAND = "MSG_DEPLOY_RESULT_NO_PERM_EXPAND";
        public const string MSG_DEPLOY_RESULT_TOO_SHALLOW = "MSG_DEPLOY_RESULT_TOO_SHALLOW";
        public const string MSG_DEPLOY_RESULT_TOO_DEEP = "MSG_DEPLOY_RESULT_TOO_DEEP";
        public const string MSG_DEPLOY_RESULT_OUTSIDE_GRID = "MSG_DEPLOY_RESULT_OUTSIDE_GRID";
        public const string MSG_DEPLOY_RESULT_TOO_CLOSE_TO_OILRIG = "MSG_DEPLOY_RESULT_TOO_CLOSE_TO_OILRIG";
        public const string MSG_DEPLOY_RESULT_TOO_CLOSE_TO_SHORE = "MSG_DEPLOY_RESULT_TOO_CLOSE_TO_SHORE";
        public const string MSG_DEPLOY_RESULT_TOO_FAR_FROM_SHORE = "MSG_DEPLOY_RESULT_TOO_FAR_FROM_SHORE";
        public const string MSG_DEPLOY_RESULT_TOO_MANY_FOUNDATIONS = "MSG_DEPLOY_RESULT_TOO_MANY_FOUNDATIONS";
        public const string MSG_DEPLOY_RESULT_IN_POOL = "MSG_DEPLOY_RESULT_IN_POOL";
        public const string MSG_DEPLOY_RESULT_LACKS_ITEM = "MSG_DEPLOY_RESULT_LACKS_ITEM";
        public const string MSG_DEPLOY_RESULT_PEBCAK = "MSG_DEPLOY_RESULT_PEBCAK";
        public const string MSG_DEPLOY_RESULT_OCEANLEVEL = "MSG_DEPLOY_RESULT_OCEANLEVEL";
        public const string MSG_EXPAND_REINFORCEMENT_NOT_ALLOWED = "MSG_EXPAND_REINFORCEMENT_NOT_ALLOWED";
        public const string MSG_REINFORCEMENT_NOT_ALLOWED = "MSG_REINFORCEMENT_NOT_ALLOWED";
        public const string MSG_REINFORCEMENT_LACKS_ITEM = "MSG_REINFORCEMENT_LACKS_ITEM";
        public const string MSG_EXPAND_REINFORCEMENT_WRONG_ABOVE = "MSG_EXPAND_REINFORCEMENT_WRONG_ABOVE";
        public const string MSG_EXPAND_REINFORCEMENT_LACKS_ITEM = "MSG_EXPAND_REINFORCEMENT_LACKS_ITEM";
        public const string MSG_UNDERWATER_NETTING_NO_PERM = "MSG_UNDERWATER_NETTING_NO_PERM";
        public const string MSG_UNDERWATER_NETTING_TOO_SHALLOW = "MSG_UNDERWATER_NETTING_TOO_SHALLOW";
        public const string MSG_CRAFTING_NO_PERM = "MSG_CRAFTING_NO_PERM";
        public const string MSG_CRAFTING_NO_MATERIALS = "MSG_CRAFTING_NO_MATERIALS";
        public const string MSG_CRAFTING_INSUFFICIENT_WB_LEVEL = "MSG_CRAFTING_INSUFFICIENT_WB_LEVEL";
        public const string MSG_MAX_TIER_REACHED_MAIN = "MSG_MAX_TIER_REACHED_MAIN";
        public const string MSG_MAX_TIER_REACHED_FRAME = "MSG_MAX_TIER_REACHED_FRAME";
        public const string MSG_MAX_TIER_REACHED_FOUNDATION = "MSG_MAX_TIER_REACHED_FOUNDATION";
        public const string MSG_CARGO_PATH_WARNING = "MSG_CARGO_PATH_WARNING";
        public const string MSG_CARGO_PATH_PREVENTION = "MSG_CARGO_PATH_PREVENTION";
        public const string MSG_VALUE_HAS_BEEN_SET = "MSG_VALUE_HAS_BEEN_SET";
        public const string MSG_CFG_RUNDOWN_FORMAT = "MSG_CFG_RUNDOWN_FORMAT";
        public const string MSG_CFG_DETAILS_FORMAT = "MSG_CFG_DETAILS_FORMAT";
        public const string MSG_CFG_NO_SETTING_FOUND = "MSG_CFG_NO_SETTING_FOUND";
        public const string MSG_CFG_DEFAULT = "MSG_CFG_DEFAULT";
        private Dictionary<string, string> LangMessages = new Dictionary<string, string> {
            [MSG_CHAT_PREFIX]
            = "<color=#4897ce>[Water Bases]</color>", [MSG_DEPLOY_ERROR] = "ERROR:", [MSG_ITEM_NAME_SQUARE] = "Water Foundation (SQUARE)", [MSG_ITEM_NAME_TRIANGLE] = "Water Foundation (TRIANGLE)", [MSG_CRAFT] = "Craft", [MSG_DEPLOY_RESULT_BUILDING_BLOCKED] = "You're building blocked.", [MSG_DEPLOY_RESULT_TOPOLOGY_MISMATCH] = "You're not allowed to build on this topology.", [MSG_DEPLOY_RESULT_NO_PERM_DEPLOY] = "You're not allowed to deploy new water foundations.", [MSG_DEPLOY_RESULT_NO_PERM_EXPAND] = "You're not allowed to expand existing water foundations.", [MSG_DEPLOY_RESULT_TOO_SHALLOW] = "You're not allowed to build in water this shallow.", [MSG_DEPLOY_RESULT_TOO_DEEP] = "You're not allowed to build in water this deep.", [MSG_DEPLOY_RESULT_OUTSIDE_GRID] = "You're not allowed to build outside of the map grid.", [MSG_DEPLOY_RESULT_TOO_CLOSE_TO_OILRIG] = "You're not allowed to build this close to the Oil Rig.", [MSG_DEPLOY_RESULT_TOO_CLOSE_TO_SHORE] = "You're not allowed to build this close to shore.", [MSG_DEPLOY_RESULT_TOO_FAR_FROM_SHORE] = "You're not allowed to build this far from shore.", [MSG_DEPLOY_RESULT_TOO_MANY_FOUNDATIONS] = "You're not allowed this many water foundations per building.", [MSG_DEPLOY_RESULT_IN_POOL] = "Nice try, but building in swimming pools would be a little bit much.", [MSG_MAX_TIER_REACHED_MAIN] = "You're not allowed to upgrade walls/floors/windows/doorways to tier this high.", [MSG_MAX_TIER_REACHED_FRAME] = "You're not allowed to upgrade floor frames/wall frames to tier this high.", [MSG_MAX_TIER_REACHED_FOUNDATION] = "You're not allowed to upgrade water foundations to tier this high.", [MSG_CARGO_PATH_PREVENTION] = "You're not allowed to build this close to the path of the Cargo Ship.", [MSG_CARGO_PATH_WARNING] = "You're building in the path of the Cargo Ship.Your structure is at risk.", [MSG_EXPAND_REINFORCEMENT_NOT_ALLOWED] = "You're not allowed to expand reinforcements like this.Use a hammer on the fully repaired Water Foundation instead.", [MSG_REINFORCEMENT_LACKS_ITEM] = "You need a proper Water Foundation item in your inventory to reinforce this water foundation.", [MSG_EXPAND_REINFORCEMENT_LACKS_ITEM] = "You need 2 proper Water Foundation items in your inventory to expand this reinforced water foundation.", [MSG_REINFORCEMENT_NOT_ALLOWED] = "You're not allowed to reinforce Water Foundations.", [MSG_UNDERWATER_NETTING_NO_PERM] = "You're not allowed to deploy underwater netting.", [MSG_UNDERWATER_NETTING_TOO_SHALLOW] = "The water needs to be at least {0} meters deep for this netting to work.", [MSG_CRAFTING_NO_MATERIALS] = "You need {0} to craft a {1}.", [MSG_CRAFTING_NO_PERM] = "You're not allowed to craft Water Foundations.", [MSG_CRAFTING_INSUFFICIENT_WB_LEVEL] = "You need a Level {0} Workbench to craft Water Foundations.", [MSG_DEPLOY_RESULT_LACKS_ITEM] = "You need a proper Water Foundation item in your inventory to expand this water foundation.", [MSG_EXPAND_REINFORCEMENT_WRONG_ABOVE] = "You can't expand like that.The shapes of the reinforcement and the water foundation above it must match.", [MSG_VALUE_HAS_BEEN_SET] = "Config value <color=yellow>{0}</color> has been set to {1} by an admin.", [MSG_CFG_DEFAULT] = "Here's the current settings.Type <color=yellow>/wb_cfg settingName</color> with no parameters to see the description, the current value and what the accepted arguments are.Type <color=yellow>/wb_cfg settingName acceptedValue</color> to change the setting.", [MSG_CFG_RUNDOWN_FORMAT] = "/wb_cfg <color=yellow>{0}</color> (currently: {1})", [MSG_CFG_DETAILS_FORMAT] = "<color=green>{0}</color>:\n{1} ({2})\nThis value is currently set to: {3}\n", [MSG_CFG_NO_SETTING_FOUND] = "No setting with that name has been found.Type /wb_cfg to get a rundown.", [MSG_DEPLOY_RESULT_PEBCAK] = "That's not how you expand your foundations! You only need to deploy one blue doughnut as a starter.Then take out your building plan, select a square or triangle floor (NOT foundation!) and build just like in vanilla.", [MSG_DEPLOY_RESULT_OCEANLEVEL] = "You can only build or expand Water Foundations when the ocean level is {0}."
        }
        ;
        private static string MSG(string msg, string userID = null, params object[] args) {
            if (args == null) {
                return Instance.lang.GetMessage(msg, Instance, userID);
            }
            else {
                return string.Format(Instance.lang.GetMessage(msg, Instance, userID), args);
            }
        }
        private static string MSG_RESULT(DeploymentResult result, string userID = null) {
            switch (result) {
                default : case DeploymentResult.Success : {
                    return null;
                }
                case DeploymentResult.BuildingBlocked : {
                    return $"{MSG(MSG_DEPLOY_ERROR, userID)} {MSG(MSG_DEPLOY_RESULT_BUILDING_BLOCKED, userID)}";
                }
                case DeploymentResult.TopologyMismatch : {
                    return $"{MSG(MSG_DEPLOY_ERROR, userID)} {MSG(MSG_DEPLOY_RESULT_TOPOLOGY_MISMATCH, userID)}";
                }
                case DeploymentResult.NoPermissionToDeploy : {
                    return $"{MSG(MSG_DEPLOY_ERROR, userID)} {MSG(MSG_DEPLOY_RESULT_NO_PERM_DEPLOY, userID)}";
                }
                case DeploymentResult.NoPermissionToExpand : {
                    return $"{MSG(MSG_DEPLOY_ERROR, userID)} {MSG(MSG_DEPLOY_RESULT_NO_PERM_EXPAND, userID)}";
                }
                case DeploymentResult.WaterTooShallow : {
                    return $"{MSG(MSG_DEPLOY_ERROR, userID)} {MSG(MSG_DEPLOY_RESULT_TOO_SHALLOW, userID)}";
                }
                case DeploymentResult.WaterTooDeep : {
                    return $"{MSG(MSG_DEPLOY_ERROR, userID)} {MSG(MSG_DEPLOY_RESULT_TOO_DEEP, userID)}";
                }
                case DeploymentResult.DeployedInPool : {
                    return $"{MSG(MSG_DEPLOY_ERROR, userID)} {MSG(MSG_DEPLOY_RESULT_IN_POOL, userID)}";
                }
                case DeploymentResult.TooCloseToOilrig : {
                    return $"{MSG(MSG_DEPLOY_ERROR, userID)} {MSG(MSG_DEPLOY_RESULT_TOO_CLOSE_TO_OILRIG, userID)}";
                }
                case DeploymentResult.TooCloseToShore : {
                    return $"{MSG(MSG_DEPLOY_ERROR, userID)} {MSG(MSG_DEPLOY_RESULT_TOO_CLOSE_TO_SHORE, userID)}";
                }
                case DeploymentResult.TooFarFromShore : {
                    return $"{MSG(MSG_DEPLOY_ERROR, userID)} {MSG(MSG_DEPLOY_RESULT_TOO_FAR_FROM_SHORE, userID)}";
                }
                case DeploymentResult.TooManyFoundations : {
                    return $"{MSG(MSG_DEPLOY_ERROR, userID)} {MSG(MSG_DEPLOY_RESULT_TOO_MANY_FOUNDATIONS, userID)}";
                }
                case DeploymentResult.OnCargoShipPath : {
                    return $"{MSG(MSG_DEPLOY_ERROR, userID)} {MSG(Instance.configData.CargoShipPathHandling == CargoPathHandling.Prevent ? MSG_CARGO_PATH_PREVENTION : MSG_CARGO_PATH_WARNING, userID)}";
                }
                case DeploymentResult.NoRequiredItem : {
                    return $"{MSG(MSG_DEPLOY_ERROR, userID)} {MSG(MSG_DEPLOY_RESULT_LACKS_ITEM, userID)}";
                }
                case DeploymentResult.OutsideMapGrid : {
                    return $"{MSG(MSG_DEPLOY_ERROR, userID)} {MSG(MSG_DEPLOY_RESULT_OUTSIDE_GRID, userID)}";
                }
                case DeploymentResult.ProblemExistsBetweenChairAndKeyboard : {
                    return $"{MSG(MSG_DEPLOY_ERROR, userID)} {MSG(MSG_DEPLOY_RESULT_PEBCAK, userID)}";
                }
                case DeploymentResult.OceanLevel : {
                    return $"{MSG(MSG_DEPLOY_ERROR, userID)} {MSG(MSG_DEPLOY_RESULT_OCEANLEVEL, userID, Instance.configData.GlobalOceanLevelBaseline)}";
                }
            }
        }
#endregion
#region PERMISSIONS
        public const string PERM_ADMIN = "waterbases.admin";
        public const string PERM_VIP1 = "waterbases.vip1";
        public const string PERM_VIP2 = "waterbases.vip2";
        public const string PERM_VIP3 = "waterbases.vip3";
        public const string PERM_VIP4 = "waterbases.vip4";
        public const string PERM_VIP5 = "waterbases.vip5";
#endregion
#region HOOKS
        void OnServerInitialized() {
            Instance = this;
            ToastsCached = new Dictionary<string, Translate.Phrase>();
            lang.RegisterMessages(LangMessages, this);
            permission.RegisterPermission(PERM_ADMIN, this);
            permission.RegisterPermission(PERM_VIP1, this);
            permission.RegisterPermission(PERM_VIP2, this);
            permission.RegisterPermission(PERM_VIP3, this);
            permission.RegisterPermission(PERM_VIP4, this);
            permission.RegisterPermission(PERM_VIP5, this);
            AddCovalenceCommand(CMD_WB_GIVE, nameof(CommandGiveFoundation));
            LoadConfigData();
            ProcessConfigData();
            ConfigValues = new Dictionary<string, InteractiveConfigValue>();
            GenerateAllInteractiveConfigValues();
            //ConvertBrokenFlags();
            //KillOldFlags();
            RecalculateUnderwaterAndSharkHarvestLootWeights();
            GuiManager.ReGenerateGUI();
            ActivateSpecialStuff();
        }
        void Unload() {
            var stopwatch = new Stopwatch();
            stopwatch.Start();
            foreach (var helper in UnityEngine.Object.FindObjectsOfType<NettingSharkHelper>()) {
                UnityEngine.Object.DestroyImmediate(helper);
            }
            var elapsed1 = stopwatch.ElapsedMilliseconds;
            stopwatch.Restart();
            foreach (var helper in UnityEngine.Object.FindObjectsOfType<InverseFoundationHelper>()) {
                UnityEngine.Object.DestroyImmediate(helper);
            }
            var elapsed2 = stopwatch.ElapsedMilliseconds;
            stopwatch.Restart();
            foreach (var helper in UnityEngine.Object.FindObjectsOfType<UnderwaterNetHelper>()) {
                UnityEngine.Object.DestroyImmediate(helper);
            }
            var elapsed3 = stopwatch.ElapsedMilliseconds;
            stopwatch.Restart();
            foreach (var player in BasePlayer.activePlayerList) {
                GuiManager.HideGUI(player);
            }
            var elapsed4 = stopwatch.ElapsedMilliseconds;
            stopwatch.Restart();
            configData.OilrigPositions = null;
            configData.ProfileTopologyMask = null;
            configData.NettingSharks = null;
            GuiManager.CleanupGUI();
            ToastsCached = null;
            stopwatch.Stop();
            var elapsed5 = stopwatch.ElapsedMilliseconds;
            stopwatch.Stop();
            PrintError($"UNLOAD TIMING DEBUG: PHASE 1 = {elapsed1} ms, PHASE 2 = {elapsed2} ms, PHASE 3 = {elapsed3} ms, PHASE 4 = {elapsed4} ms, PHASE 5 = {elapsed5} ms.");
            Instance = null;
        }
        void OnPlayerDeath(BasePlayer player, HitInfo info) {
            GuiManager.HideGUI(player);
        }
        object OnDispenserGather(ResourceDispenser dispenser, BasePlayer player, Item item) {
            if (!configData.SharkHarvestingLootEnabled) {
                return null;
            }
            if (dispenser.baseEntity.PrefabName != PREFAB_SHARK_DEAD) {
                return null;
            }
            float chance = dispenser.baseEntity.Health() / dispenser.baseEntity.MaxHealth();
            if (UnityEngine.Random.Range(0F, 1F) < chance) {
                var randomItem = CreateRandomSharkHarvestItem();
                if (randomItem == null) {
                    return null;
                }
                player.GiveItem(randomItem, BaseEntity.GiveItemReason.ResourceHarvested);
            }
            return null;
        }
        void OnItemRemovedFromContainer(ItemContainer container, Item item) {
            if (item.info.itemid != ITEM_BUILDING_PLANNER) {
                return;
            }
            var player = container.GetOwnerPlayer();
            if (player == null) {
                return;
            }
            if (player.svActiveItemID == item.uid) {
                GuiManager.HideGUI(player);
            }
        }
        void OnActiveItemChanged(BasePlayer player, Item oldItem, Item newItem) {
            if (newItem != null) {
                if (newItem.info.itemid == ITEM_BUILDING_PLANNER) {
                    if (oldItem?.info.itemid != ITEM_BUILDING_PLANNER || oldItem == null) {
                        GuiManager.ShowGUI(player);
                    }
                }
                else {
                    if (oldItem != null) {
                        if (oldItem.info.itemid == ITEM_BUILDING_PLANNER) {
                            GuiManager.HideGUI(player);
                        }
                    }
                }
            }
            else {
                if (oldItem != null) {
                    if (oldItem.info.itemid == ITEM_BUILDING_PLANNER) {
                        GuiManager.HideGUI(player);
                    }
                }
            }
        }
        object OnItemRecycle(Item item, Recycler recycler) {
            if (!IsSkinRelevant(item.skin)) {
                return null;
            }
            //var costList = Facepunch.Pool.GetList<SerializableItemAmount>();
            List<SerializableItemAmount> costList;
            if (item.skin == ITEM_SKIN_FOUNDATION_SQUARE) {
                costList = Instance.configData.CraftingCostSquare;
            }
            else {
                costList = Instance.configData.CraftingCostTriangle;
            }
            foreach (var cost in costList) {
                recycler.MoveItemToOutput(ItemManager.CreateByName(cost.Shortname, Mathf.CeilToInt((float)cost.Amount / 2F)));
            }
            //Facepunch.Pool.FreeList<SerializableItemAmount>(ref costList);
            item.UseItem(1);
            item.MarkDirty();
            return true;
        }
        object OnStructureUpgrade(BuildingBlock block, BasePlayer player, BuildingGrade.Enum grade) {
            if (IsInWaterBase(block)) {
                var prof = GetPermissionProfile(player);
                bool isFrame = false;
                bool isWaterFoundation = false;
                var maxTier = prof.MaxBuildingGradeGeneric;
                if (IsWaterFoundation(block)) {
                    maxTier = prof.MaxBuildingGradeWaterFoundations;
                    isWaterFoundation = true;
                }
                else {
                    if (FramePrefabs.Contains(block.PrefabName)) {
                        maxTier = prof.MaxBuildingGradeFrames;
                        isFrame = true;
                    }
                }
                //check if the grade has not exceeded config max
                if ((int)grade > (int)maxTier) {
                    TellMessage(player, MSG(isWaterFoundation ? MSG_MAX_TIER_REACHED_FOUNDATION : isFrame ? MSG_MAX_TIER_REACHED_FRAME : MSG_MAX_TIER_REACHED_MAIN, player.UserIDString), false, true);
                    return true;
                }
            }
            return null;
        }
        void OnEntitySpawned(SimpleShark shark) {
            if (Instance == null) {
                return;
            }
            if (configData == null) {
                return;
            }
            if (shark == null) {
                return;
            }
            if (!IsInternal(shark)) {
                return;
            }
            if (shark.IsDestroyed) {
                return;
            }
            if (shark.net == null) {
                return;
            }
            if (configData.NettingSharks == null) {
                return;
            }
            var newNettingSharkCompo = shark.gameObject.AddComponent<NettingSharkHelper>();
            newNettingSharkCompo.Prepare(shark);
            if (configData.NettingSharks.ContainsKey(shark.net.ID.Value)) {
                configData.NettingSharks.Remove(shark.net.ID.Value);
            }
            if (configData.NettingSharks.Count >= configData.UnderwaterNetsSharkPopulationLimitGlobal) {
                shark.Invoke(() => shark.Kill(), 0.02F);
            }
            configData.NettingSharks.Add(shark.net.ID.Value, shark);
        }
        void OnEntityKill(SimpleShark shark) {
            if (Instance == null) {
                return;
            }
            if (configData == null) {
                return;
            }
            if (!IsInternal(shark)) {
                return;
            }
            if (!configData.NettingSharks.ContainsKey(shark.net.ID.Value)) {
                configData.NettingSharks.Remove(shark.net.ID.Value);
            }
        }
        object OnHammerHit(BasePlayer player, HitInfo info) {
            if (player.IsBuildingBlocked()) return null;
            //see if the player has enough resources to create inverse...if (info.HitEntity == null) return null;
            if (info.HitEntity.IsDestroyed) return null;
            var buildingBlock = info.HitEntity as BuildingBlock;
            if (buildingBlock == null) {
                return null;
            }
            if (buildingBlock.health != buildingBlock.MaxHealth()) {
                return null;
            }
            if (!IsWaterFoundation(buildingBlock)) {
                return null;
            }
            var allChildren = buildingBlock.GetComponentsInChildren<BuildingBlock>();
            BuildingBlock inverseFloorAlready = null;
            foreach (var block in allChildren) {
                if (block.net.ID == buildingBlock.net.ID) continue;
                inverseFloorAlready = block;
                break;
            }
            if (inverseFloorAlready == null) {
                var needed = FindNeededFoundationItemsInInventory(player, buildingBlock);
                if (needed == null) {
                    TellMessage(player, $"{MSG(MSG_DEPLOY_ERROR)} {MSG(MSG_REINFORCEMENT_LACKS_ITEM, player.UserIDString)}", false, true);
                    return true;
                }
                ConsumeFromSpecificItemList(ref needed);
                BuildInverseFoundationAtWaterFoundation(player, buildingBlock);
                return true;
            }
            return null;
        }
        void OnEntityBuilt(Planner planner, GameObject gameObject) {
            var baseEntity = gameObject.GetComponent<BaseEntity>();
            var maybeInflatable = baseEntity as WaterInflatable;
            //normal building, not from inflatable
            if (maybeInflatable == null) {
                var maybeDecayEntity = baseEntity as DecayEntity;
                if (maybeDecayEntity == null) {
                    return;
                }
                var newBuildingBlock = baseEntity as BuildingBlock;
                var player = planner.GetOwnerPlayer();
                if (newBuildingBlock != null) {
                    if (IsInWaterBase(newBuildingBlock)) {
                        //should this BECOME a water foundation? or an inverse foundation?
                        if (newBuildingBlock.PrefabName == PREFAB_FLOOR_SQUARE || newBuildingBlock.PrefabName == PREFAB_FLOOR_TRIANGLE) {
                            bool isInverse;
                            var nearby = TryGetAdjacentSpecialFoundation(newBuildingBlock, out isInverse);
                            if (nearby == null) {
                                //for now, maybe let's leave it as generic?
                                if (Mathf.Abs(newBuildingBlock.transform.localEulerAngles.z) < 0.1F) {
                                    MarkAsInternalGenericDecayEntity(newBuildingBlock);
                                }
                                else {
                                    MarkAsInternalGenericDecayEntityInversed(newBuildingBlock);
                                }
                                return;
                            }
                            if (!isInverse) {
                                if (newBuildingBlock.PrefabName == PREFAB_FLOOR_SQUARE) {
                                    MarkAsInternalFoundationSquare(newBuildingBlock);
                                }
                                else {
                                    MarkAsInternalFoundationTriangle(newBuildingBlock);
                                }
                                TurnFloorIntoWaterFoundation(newBuildingBlock, player, false);
                                return;
                            }
                            else {
                                //Instance.PrintWarning("PLACING INVERSE FOUNDATION...");
                                if (newBuildingBlock.PrefabName == PREFAB_FLOOR_SQUARE) {
                                    MarkAsInternalFoundationSquareInversed(newBuildingBlock);
                                }
                                else {
                                    MarkAsInternalFoundationTriangleInversed(newBuildingBlock);
                                }
                                var maybeAboveYou = TryFindWaterFoundationAboveYou(newBuildingBlock);
                                bool fatalErrorOccured = false;
                                if (maybeAboveYou == null) {
                                    //Instance.PrintWarning("MAYBE ABOVE YOU = NULL");
                                    var prof = GetPermissionProfile(player);
                                    //first and foremost: how many water foundation does the building have?
                                    //if you don't do this check, you're gonna have a REALLY bad time
                                    var waterFoundations = CountBuildingWaterFoundations(newBuildingBlock);
                                    if (waterFoundations +1 >= prof.MaxWaterFoundationsPerBuilding) {
                                        TellMessage(player, $"{MSG(MSG_DEPLOY_ERROR, player.UserIDString)} {MSG(MSG_DEPLOY_RESULT_TOO_MANY_FOUNDATIONS, player.UserIDString)}", false, true);
                                        DelayedKillWithGibs(newBuildingBlock);
                                        return;
                                    }
                                    if (!prof.CanExpandWaterFoundations) {
                                        TellMessage(player, $"{MSG(MSG_DEPLOY_ERROR, player.UserIDString)} {MSG(MSG_EXPAND_REINFORCEMENT_NOT_ALLOWED, player.UserIDString)}", false, true);
                                        DelayedKillWithGibs(newBuildingBlock);
                                        return;
                                    }
                                    //do you have enough of needed kind? you need two!
                                    var neededItems = FindNeededFoundationItemsInInventory(player, newBuildingBlock, 2);
                                    if (neededItems == null) {
                                        TellMessage(player, $"{MSG(MSG_DEPLOY_ERROR, player.UserIDString)} {MSG(MSG_EXPAND_REINFORCEMENT_LACKS_ITEM, player.UserIDString)}", false, true);
                                        DelayedKillWithGibs(newBuildingBlock);
                                        return;
                                    }
                                    //consume the item
                                    ConsumeFromSpecificItemList(ref neededItems);
                                    //let's make a foundation first.relative please.var transf = GetWorldTransformRelativeTo(newBuildingBlock.transform, Vector3.down * 1.5F, new Vector3(0F, 0F, -180F));
                                    //Instance.PrintError("ATTEMPTING TO BUILD A NORMAL FOUNDATION FIRST...");
                                    maybeAboveYou = BuildWaterFoundationAt(player, false, newBuildingBlock.PrefabName == PREFAB_FLOOR_SQUARE ? ITEM_SKIN_FOUNDATION_SQUARE : ITEM_SKIN_FOUNDATION_TRIANGLE, transf.Item1, transf.Item2);
                                    if (maybeAboveYou == null) {
                                        //Instance.PrintError("FATAL ERROR: BUILDING A NORMAL WATER FOUNDATION ABOVE HAS FAILED, IT'S NULL!");
                                        fatalErrorOccured = true;
                                    }
                                    else {
                                        if (maybeAboveYou.net == null) {
                                            //Instance.PrintError("FATAL ERROR: BUILDING A NORMAL WATER FOUNDATION ABOVE HAS FAILED, IT HAS.NET THAT IS NULL!");
                                            fatalErrorOccured = true;
                                        }
                                    }
                                    maybeAboveYou.AttachToBuilding(nearby);
                                    if (newBuildingBlock.PrefabName == PREFAB_FLOOR_SQUARE) {
                                        MarkAsInternalFoundationSquareInversed(newBuildingBlock);
                                    }
                                    else {
                                        MarkAsInternalFoundationTriangleInversed(newBuildingBlock);
                                    }
                                    newBuildingBlock.AttachToBuilding(nearby);
                                }
                                else {
                                    //the foundation above you is not null.ARE YOU CATCHING YOURSELF HERE?!
                                    //Instance.PrintError("MAYBE ABOVE YOU = NOT NULL");
                                    if (maybeAboveYou == newBuildingBlock) {
                                        //Instance.PrintError("FATAL ERROR: INVERSE FOUNDATION FOUND ITSELF AS THE NORMAL FOUNDATION ABOVE");
                                        fatalErrorOccured = true;
                                    }
                                    else {
                                        //Instance.PrintError("OK: MAYBE ABOVE YOU IS NOT THE SAME AS NEW BLOCK");
                                    }
                                    if (maybeAboveYou.net == null) {
                                        //Instance.PrintError("FATAL ERROR: MAYBE ABOVE YOU HAS NULL NET");
                                        fatalErrorOccured = true;
                                    }
                                    else {
                                        //Instance.PrintError($"OK: MAYBE ABOVE YOU NET IS NOT NULL.NET ID = {maybeAboveYou.net.ID}");
                                    }
                                    //is the foundation above you the same shape as you?
                                    var expectedType = GetSpecificType(maybeAboveYou) == InternalEntityType.FoundationSquare ? InternalEntityType.FoundationSquareInversed : InternalEntityType.FoundationTriangleInversed;
                                    var yourActualType = GetSpecificType(newBuildingBlock);
                                    if (expectedType != yourActualType) {
                                        TellMessage(player, $"{MSG(MSG_EXPAND_REINFORCEMENT_WRONG_ABOVE, player.UserIDString)}", false, true);
                                        DelayedKillWithGibs(newBuildingBlock);
                                        return;
                                    }
                                    //do you have enough of needed kind?
                                    var neededItems = FindNeededFoundationItemsInInventory(player, newBuildingBlock);
                                    if (neededItems == null) {
                                        TellMessage(player, $"{MSG(MSG_DEPLOY_ERROR, player.UserIDString)} {MSG(MSG_EXPAND_REINFORCEMENT_LACKS_ITEM, player.UserIDString)}", false, true);
                                        DelayedKillWithGibs(newBuildingBlock);
                                        return;
                                    }
                                    //consume the item
                                    ConsumeFromSpecificItemList(ref neededItems);
                                }
                                if (fatalErrorOccured) {
                                    //Instance.PrintError($"FATAL ERROR DETECTED.PLEASE COPY THE TEXT FROM THE CONSOLE AND GIVE IT TO NIKEDEMOS!");
                                    //TellMessage(player, "Fatal error detected.Attempting to NOT crash the server...success.At least there's that.Tell the  admin to check the server console.");
                                    if (newBuildingBlock != null) {
                                        DelayedKillWithGibs(newBuildingBlock);
                                    }
                                    return;
                                }
                                //Instance.PrintError($"NO ERRORS, ATTEMPTING TO TURN UPSIDE DOWN FLOOR INTO INVERSE FOUNDATION...");
                                TurnFloorIntoInverseFoundation(newBuildingBlock, maybeAboveYou, player);
                                return;
                            }
                        }
                        else {
                            //give it generic skin - but still, inverse or not?
                            //for now, maybe let's leave it as generic?
                            if (Mathf.Abs(newBuildingBlock.transform.localEulerAngles.z) < 0.1F) {
                                MarkAsInternalGenericDecayEntity(newBuildingBlock);
                            }
                            else {
                                MarkAsInternalGenericDecayEntityInversed(newBuildingBlock);
                            }
                            //still a building block
                            ApplyUpkeepMultiplier(newBuildingBlock);
                        }
                    }
                }
                else {
                    //not a building block, so it must be a regular decay entity
                    if (IsInWaterBase(maybeDecayEntity)) {
                        var maybeStability = maybeDecayEntity as StabilityEntity;
                        if (maybeStability != null) {
                            if (IsUnderwaterNetting(maybeStability, true)) {
                                if (Instance.configData.UnderwaterNetsCollectJunk) {
                                    var prof = GetPermissionProfile(player);
                                    if (prof.CanDeployUnderwaterNets) {
                                        if (UnderwaterNetHelper.IsWaterDeepEnoughForNettings(maybeStability.transform.position)) {
                                            MonoiseUnderwaterNetting(maybeStability);
                                        }
                                        else {
                                            TellMessage(player, $"{MSG(MSG_DEPLOY_ERROR, player.UserIDString)} {MSG(MSG_UNDERWATER_NETTING_TOO_SHALLOW, player.UserIDString, Instance.configData.UnderwaterNetsMinWaterDepth)}", false, true);
                                            DelayedKillWithGibs(maybeStability);
                                            return;
                                        }
                                    }
                                    else {
                                        TellMessage(player, $"{MSG(MSG_DEPLOY_ERROR, player.UserIDString)} {MSG(MSG_UNDERWATER_NETTING_NO_PERM, player.UserIDString)}", false, true);
                                        DelayedKillWithGibs(maybeStability);
                                        return;
                                    }
                                }
                            }
                        }
                        ApplyUpkeepMultiplier(maybeDecayEntity);
                    }
                }
            }
            else  //from inflatable
            {
                if (!IsSkinRelevant(maybeInflatable.skinID)) {
                    return;
                }
                var player = planner.GetOwnerPlayer();
                Instance.NextTick(() => {
                    var position = maybeInflatable.transform.position;
                    if (Instance.configData.AdjustDeployedWaterLevel) {
                        var waterHeight = WaterLevel.GetWaterSurface(position, false, false);
                        position.y = waterHeight;
                    }
                    BuildWaterFoundationAt(player, true, maybeInflatable.skinID, position, Quaternion.Euler(maybeInflatable.transform.eulerAngles.WithX(0).WithZ(0)));
                    maybeInflatable.Kill(BaseNetworkable.DestroyMode.None);
                }
                );
            }
        }
        void OnItemAddedToContainer(ItemContainer container, Item item) {
            if (Instance == null) return;
            if (container == null) return;
            if (item == null) return;
            if (item.info.itemid != ITEM_INNER_TUBE) return;
            if (!IsSkinRelevant(item.skin)) return;
            EnsureFoundationItemName(item);
        }
#endregion
#region MONO
        public class NettingSharkHelper : MonoBehaviour {
            public float LastCheckAt = float.MinValue;
            public float CheckEvery = 1F;
            public bool SeemsToBeAsleepCurrent = false;
            public bool SeemsToBeAsleepPrevious = false;
            public float WentToSleepAt = float.MinValue;
            public SimpleShark OwnerShark;
            public bool NoNeedToUpdateAnymore = false;
            public void Prepare(SimpleShark shark) {
                OwnerShark = shark;
                if (!shark.HasFlag(FLAG_ALREADY_APPLIED)) {
                    shark.SetHealth(Instance.configData.UnderwaterNetsSharkHealthMultiplier * shark.health);
                    shark.SetMaxHealth(Instance.configData.UnderwaterNetsSharkHealthMultiplier * shark.health);
                    shark.maxSpeed = shark.maxSpeed * Instance.configData.UnderwaterNetsSharkSpeedMultiplier;
                    shark.minSpeed = shark.minSpeed * Instance.configData.UnderwaterNetsSharkSpeedMultiplier;
                    shark.maxTurnSpeed = shark.maxTurnSpeed * Instance.configData.UnderwaterNetsSharkSpeedMultiplier;
                    shark.minTurnSpeed = shark.minTurnSpeed * Instance.configData.UnderwaterNetsSharkSpeedMultiplier;
                    shark.SetFlag(FLAG_ALREADY_APPLIED, true, false, true);
                    shark.SendChildrenNetworkUpdateImmediate();
                }
                //might aswell be reapplied
                shark.aggroRange = Instance.configData.UnderwaterNetsSharkAggroRange;
            }
            private void FixedUpdate() {
                if (NoNeedToUpdateAnymore) {
                    return;
                }
                if (Time.time < LastCheckAt + CheckEvery) {
                    return;
                }
                SeemsToBeAsleepPrevious = SeemsToBeAsleepCurrent;
                SeemsToBeAsleepCurrent = !BaseNetworkable.HasCloseConnections(transform.position, 100F);
                //did something change?
                if (SeemsToBeAsleepCurrent != SeemsToBeAsleepPrevious) {
                    //yes it did.//did you just go to sleep fron non-sleep, or did you just wake up?
                    if (SeemsToBeAsleepCurrent) {
                        //you just went to sleep
                        WentToSleepAt = Time.time;
                    }
                    else {
                        //you just woke up
                        WentToSleepAt = float.MinValue;
                    }
                }
                else {
                    //nope.check.if (SeemsToBeAsleepCurrent)
                    {
                        if (Time.time > WentToSleepAt + Instance.configData.UnderwaterNetsSharkSleepDespawnTimer) {
                            //that's it for you.Kill yourself.NoNeedToUpdateAnymore = true;
                            OwnerShark.Kill();
                        }
                    }
                }
            }
        }
        public class UnderwaterNetHelper : MonoBehaviour {
            //reapproacchi.keep TimerSetOn separately to SecondsAdded.public StabilityEntity OwnerNetting;
            public float NextCreateUnderwaterJunk;
            public float TimerSetWithTimestamp = float.MinValue;
            public float TimerSetWithSecondsAdded = 0;
            public bool TimerRunning = false;
            public void Prepare(StabilityEntity netting) {
                OwnerNetting = netting;
                //when the first one spawns, it will set off the timer.NextRandomTimeSpawnJunk();
            }
            public static bool IsWaterDeepEnoughForNettings(Vector3 position) {
                if (Instance.configData.UnderwaterNetsMinWaterDepth <= 0F) {
                    return true;
                }
                var depth = WaterLevel.GetOverallWaterDepth(position, false, false);
                if (depth < Instance.configData.UnderwaterNetsMinWaterDepth) {
                    return false;
                }
                return true;
            }
            public void SetupSharkTimer() {
                TimerSetWithTimestamp = Time.realtimeSinceStartup;
                TimerSetWithSecondsAdded = UnityEngine.Random.Range(Instance.configData.UnderwaterNetsSharkRandomTimerMin, Instance.configData.UnderwaterNetsRandomTimerMax);
                TimerRunning = true;
            }
            public void ShortenSharkTimer() {
                TimerRunning = true;
                //make sure the value is between 0 and 100
                TimerSetWithSecondsAdded *= (100F - Mathf.Clamp(Instance.configData.UnderwaterNetsSharkTimerShortenByPercent, 0F, 100F)) / 100F;
                //normalize back to 0 - 1 range
            }
            public void NextRandomTimeSpawnJunk() {
                float nextRandomTime = NextRandomTime(Instance.configData.UnderwaterNetsRandomTimerMin, Instance.configData.UnderwaterNetsRandomTimerMax);
                NextCreateUnderwaterJunk = nextRandomTime;
            }
            private void TryCreateRandomUnderwaterJunk() {
                var countBeforeAdding = CountNettingItems(OwnerNetting);
                if (countBeforeAdding >= Instance.configData.UnderwaterNetsItemLimit) {
                    //Instance.PrintWarning($"{countBeforeAdding} is too many alreaaaadyyyYYY, no timer action!!!! Making sure the timer is stopped.");
                    TimerRunning = false;
                    return;
                }
                var newItem = CreateRandomItemFromTable(Instance.configData.UnderwaterLoot, Instance.configData.UnderwaterLootWeightSum);
                if (newItem == null) {
                    return;
     
// ... [Code preview truncated due to length. Full source in attached file] ...

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