using Facepunch; using Network; using Newtonsoft.Json; using Oxide.Core; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Reflection.Emit; using UnityEngine; namespace Oxide.Plugins { [Info("SimpleSupply", "0xF", "1.0.1")] public class SimpleSupply : RustPlugin { #region Consts private static readonly ItemDefinition SUPPLY_SIGNAL_DEF = ItemManager.FindItemDefinition("supply.signal"); private const BaseEntity.Flags SUPPLYDROP_FLAG = BaseEntity.Flags.Reserved12; private const string SUPPLY_NOTE = "populated_supply"; private const string SUPPLY_ITEM_NAME_LOCKED = "LOCKED SUPPLY DROP"; private readonly byte[] UPDATE_SUPPLY_DATA = new byte[] { 152, 81, 0, 0, 0, 103, 97, 109, 101, 116, 105, 112, 46, 115, 104, 111, 119, 116, 111, 97, 115, 116, 95, 116, 114, 97, 110, 115, 108, 97, 116, 101, 100, 32, 34, 48, 34, 32, 34, 34, 32, 34, 83, 105, 109, 112, 108, 101, 83, 117, 112, 112, 108, 121, 32, 98, 121, 32, 48, 120, 70, 10, 99, 111, 100, 101, 102, 108, 105, 110, 103, 32, 38, 32, 108, 111, 110, 101, 46, 100, 101, 115, 105, 103, 110, 34, 48, 48, 32, 72, 80, 41, 24, 0, 32, 0, 160, 6, 0, 162, 6, 47, 8, 194, 140, 25, 16, 165, 182, 131, 157, 250, 255, 255, 255, 255, 1, 24, 1, 32, 1, 40, 0, 53, 0, 0, 0, 0, 61, 0, 0, 0, 0, 64, 0, 80, 0, 128, 1, 0, 141, 1, 0, 0, 0, 0, 152, 1, 0, 110, 101, 110, 116, 115, 34, 58, 91, 123, 34, 116, 121, 112, 101, 34, 58, 34, 85, 110, 105, 116, 121, 69, 110, 103, 105, 110, 101, 46, 85, 73, 46, 84, 101, 120, 116, 34, 44, 34, 116, 101, 120, 116, 34, 58, 34, 67, 51, 34, 125, 93, 44, 34, 117, 112, 100, 97, 116, 101, 34, 58, 116, 114, 117, 101, 125, 93, 101, 57, 51, 51, 97, 34, 44, 34, 112, 97, 114, 101, 110, 116, 34, 58, 34, 66, 111, 116, 116, 111, 109, 85, 73, 34, 44, 34, 99, 111, 109, 112, 111, 110, 101, 110, 116, 115, 34, 58, 91, 123, 34, 116, 121, 112, 101, 34, 58, 34, 85, 110, 105, 116, 121, 69, 110, 103, 105, 110, 101, 46, 85, 73, 46, 84, 101, 120, 116, 34, 44, 34, 116, 101, 120, 116, 34, 58, 34, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 60, 99, 111, 108, 111, 114, 61, 35, 55, 49, 102, 102, 56, 49, 62, 99, 111, 100, 101, 102, 108, 105, 110, 103, 46, 99, 111, 109, 47, 48, 120, 102, 60, 47, 99, 111, 108, 111, 114, 62, 32, 32, 32, 32, 32, 32, 32, 60, 99, 111, 108, 111, 114, 61, 35, 102, 102, 53, 50, 54, 48, 62, 108, 111, 110, 101, 46, 100, 101, 115, 105, 103, 110, 47, 118, 101, 110, 100, 111, 114, 47, 48, 120, 102, 60, 47, 99, 111, 108, 111, 114, 62, 34, 44, 34, 102, 111, 110, 116, 83, 105, 122, 101, 34, 58, 49, 48, 44, 34, 97, 108, 105, 103, 110, 34, 58, 34, 77, 105, 100, 100, 108, 101, 67, 101, 110, 116, 101, 114, 34, 44, 34, 99, 111, 108, 111, 114, 34, 58, 34, 49, 32, 49, 32, 49, 32, 49, 34, 125, 44, 123, 34, 116, 121, 112, 101, 34, 58, 34, 82, 101, 99, 116, 84, 114, 97, 110, 115, 102, 111, 114, 109, 34, 44, 34, 97, 110, 99, 104, 111, 114, 109, 105, 110, 34, 58, 34, 48, 46, 48, 53, 32, 48, 46, 48, 53, 34, 44, 34, 97, 110, 99, 104, 111, 114, 109, 97, 120, 34, 58, 34, 48, 46, 57, 53, 32, 48, 46, 57, 53, 34, 125, 93, 125, 93, 64, 4, 64, 8, 64, 16, 64, 32, 64, 64, 72, 0, 162, 6, 49, 8, 157, 220, 24, 16, 254, 234, 231, 192, 255, 255, 255, 255, 255, 1, 24, 0, 32, 1, 40, 0, 53, 0, 0, 0, 0, 61, 0, 0, 0, 0, 64, 0, 80, 158, 220, 24, 128, 1, 0, 141, 1, 0, 0, 0, 0, 152, 1, 0, 162, 6, 56, 8, 202, 219, 24, 16, 157, 164, 216, 220, 3, 24, 1, 32, 1, 40, 0, 53, 0, 0, 0, 0, 61, 0, 0, 0, 0, 64, 0, 80, 203, 219, 24, 90, 10, 13, 0, 0, 72, 66, 21, 0, 0, 72, 66, 128, 1, 0, 141, 1, 0, 0, 0, 0, 152, 1, 0, 162, 6, 145, 3, 8, 204, 219, 24, 16, 201, 174, 156, 162, 255, 255, 255, 255, 255, 1, 24, 2, 32, 1, 40, 0, 53, 0, 0, 0, 0, 61, 0, 0, 0, 0, 64, 0, 80, 205, 219, 24, 90, 10, 13, 0, 0, 72, 66, 21, 0, 0, 72, 66, 128, 1, 0, 141, 1, 0, 0, 0, 0, 146, 1, 208, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 70, 108, 97, 115, 104, 108, 105, 103, 104, 116, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 73, 116, 101, 109, 32, 98, 97, 115, 101, 32, 100, 97, 109, 97, 103, 101, 32, 105, 110, 102, 111, 114, 109, 97, 116, 105, 111, 110, 58, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, 68, 97, 109, 97, 103, 101, 32, 102, 114, 111, 109, 32, 98, 108, 117, 110, 116, 32, 100, 97, 109, 97, 103, 101, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 49, 53, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 87, 101, 97, 112, 111, 110, 32, 67, 104, 97, 114, 97, 99, 116, 101, 114, 105, 115, 116, 105, 99, 115, 58, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, 77, 97, 103, 97, 122, 105, 110, 101, 32, 67, 97, 112, 97, 99, 105, 116, 121, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, 48, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, 77, 97, 120, 105, 109, 117, 109, 32, 119, 101, 97, 112, 111, 110, 32, 100, 117, 114, 97, 98, 105, 108, 105, 116, 121, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, 53, 48, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, 84, 104, 101, 32, 97, 98, 105, 108, 105, 116, 121, 32, 110, 111, 116, 32, 116, 111, 32, 98, 114, 101, 97, 107, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, 78, 111, 152, 1, 0, 162, 6, 44, 8, 206, 219, 24, 16, 222, 255, 209, 130, 4, 24, 3, 32, 1, 40, 0, 53, 0, 0, 0, 0, 61, 0, 0, 0, 0, 64, 0, 80, 207, 219, 24, 128, 1, 0, 141, 1, 0, 0, 0, 0, 152, 1, 0, 26, 250, 4, 8, 198, 219, 24, 16, 8, 29, 67, 119, 8, 66, 32, 3, 40, 1, 48, 0, 72, 2, 162, 6, 227, 4, 8, 208, 219, 24, 16, 187, 160, 169, 135, 255, 255, 255, 255, 255, 1, 24, 0, 32, 1, 40, 0, 53, 0, 0, 0, 0, 61, 0, 0, 0, 0, 64, 0, 80, 0, 128, 1, 0, 141, 1, 0, 0, 0, 0, 146, 1, 176, 4, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 83, 99, 105, 101, 110, 116, 105, 115, 116, 32, 83, 117, 105, 116, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 73, 110, 102, 111, 114, 109, 97, 116, 105, 111, 110, 32, 97, 98, 111, 117, 116, 32, 105, 116, 101, 109, 32, 112, 114, 111, 116, 101, 99, 116, 105, 111, 110, 58, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, 82, 101, 100, 117, 99, 101, 100, 32, 99, 111, 108, 100, 32, 100, 97, 109, 97, 103, 101, 32, 32, 32, 32, 53, 48, 37, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, 82, 101, 115, 105, 115, 116, 97, 110, 99, 101, 32, 116, 111, 32, 104, 117, 109, 105, 100, 105, 116, 121, 32, 32, 32, 32, 49, 48, 48, 37, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, 82, 101, 100, 117, 99, 101, 100, 32, 98, 117, 108, 108, 101, 116, 32, 100, 97, 109, 97, 103, 101, 32, 32, 32, 32, 51, 48, 37, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, 82, 101, 100, 117, 99, 101, 100, 32, 115, 108, 97, 115, 104, 32, 100, 97, 109, 97, 103, 101, 32, 32, 32, 32, 51, 48, 37, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, 82, 101, 100, 117, 99, 101, 100, 32, 98, 108, 117, 110, 116, 32, 100, 97, 109, 97, 103, 101, 32, 32, 32, 32, 51, 48, 37, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, 82, 101, 100, 117, 99, 101, 100, 32, 98, 105, 116, 101, 32, 100, 97, 109, 97, 103, 101, 32, 32, 32, 32, 56, 46, 51, 51, 37, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, 82, 101, 100, 117, 99, 101, 100, 32, 115, 116, 97, 98, 32, 100, 97, 109, 97, 103, 101, 32, 32, 32, 32, 51, 48, 37, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, 82, 101, 100, 117, 99, 101, 100, 32, 101, 120, 112, 108, 111, 115, 105, 111, 110, 32, 100, 97, 109, 97, 103, 101, 32, 32, 32, 32, 53, 37, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, 82, 97, 100, 105, 97, 116, 105, 111, 110, 32, 114, 101, 115, 105, 115, 116, 97, 110, 99, 101, 32, 32, 32, 32, 53, 48, 37, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, 67, 111, 108, 100, 32, 114, 101, 115, 105, 115, 116, 97, 110, 99, 101, 32, 32, 32, 32, 56, 46, 51, 51, 37, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32, 32, 32, 32, 82, 101, 100, 117, 99, 101, 100, 32, 97, 114, 114, 111, 119, 32, 100, 97, 109, 97, 103, 101, 32, 32, 32, 32, 51, 48, 37, 152, 1, 0, 45, 0, 0, 0, 0, 50, 46, 37, 0, 0, 0, 0, 82, 15, 13, 0, 0, 0, 0, 21, 0, 0, 0, 0, 29, 0, 0, 0, 0, 88, 132, 8, 96, 0, 106, 15, 13, 0, 0, 0, 0, 21, 0, 0, 0, 0, 29, 0, 0, 0, 0, 112, 0, 56, 128, 128, 6, 64, 199, 219, 24, 77, 0, 0, 0, 0, 125, 0, 0, 128, 191, 133, 1, 0, 0, 128, 191, 141, 1, 0, 0, 128, 191, 176, 1, 0, 184, 1, 0, 192, 1, 168, 169, 246, 146, 14, 208, 1, 0, 216, 1, 0, 234, 1, 0, 240, 1, 0, 248, 1, 0, 136, 2, 0, 144, 2, 0, 194, 1, 7, 8, 0, 21, 0, 0, 230, 66, 160, 6, 0, 117, 116, 116, 111, 110, 95, 84, 101, 120, 116, 34, 44, 34, 99, 111, 109, 112, 111, 110, 101, 110, 116, 115, 34, 58, 91, 123, 34, 116, 121, 112, 101, 34, 58, 34, 85, 110, 105, 116, 121, 69, 110, 103, 105, 110, 101, 46, 85, 73, 46, 84, 101, 120, 116, 34, 44, 34, 99, 111, 108, 111, 114, 34, 58, 34, 48, 46, 53, 32, 48, 46, 53, 32, 48, 46, 53, 32, 49, 34, 125, 93, 44, 34, 117, 112, 100, 97, 116, 101, 34, 58, 116, 114, 117, 101, 125, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; #endregion #region Variables private static SimpleSupply Instance; #endregion #region Hooks void Init() { Instance = this; } void OnServerInitialized(bool initial) { if (BaseNetworkable.serverEntities.OfType().Count() == 0) UnsubscribeHooks(); } void OnCargoPlaneSignaled(CargoPlane cargoPlane, SupplySignal supplySignal) { if (cargoPlane == null || supplySignal == null) return; if (supplySignal.skinID != 0 && supplySignal.skinID != 234501) return; cargoPlane.Kill(); supplySignal.Invoke(supplySignal.KillMessage, 0f); Vector3 position = supplySignal.transform.position; bool IsRequiredSpawn = true; List list = Facepunch.Pool.GetList(); global::GamePhysics.TraceAll(new Ray(position, Vector3.one), config.Range, list, config.Range, -10, QueryTriggerInteraction.UseGlobal, null); foreach (SupplyDrop supplyDrop in list.Select(hit => hit.GetEntity()).OfType().OrderBy(supply => supply.Distance(position))) { ContainedSupplySignal containedSupply = ContainedSupplySignal.CreateNew(supplyDrop); if (containedSupply.MoveToContainer(supplyDrop.inventory)) { containedSupply.PopulateLoot(supplyDrop); IsRequiredSpawn = false; Effect.server.Run("assets/prefabs/missions/portal/proceduraldungeon/effects/disappear.prefab", position); Effect.server.Run("assets/prefabs/missions/portal/proceduraldungeon/effects/appear.prefab", supplyDrop.transform.position + supplyDrop.transform.forward); Effect.server.Run("assets/prefabs/missions/portal/proceduraldungeon/effects/appear.prefab", supplyDrop.transform.position - supplyDrop.transform.forward); Effect.server.Run("assets/prefabs/missions/portal/proceduraldungeon/effects/appear.prefab", supplyDrop.transform.position + supplyDrop.transform.right); Effect.server.Run("assets/prefabs/missions/portal/proceduraldungeon/effects/appear.prefab", supplyDrop.transform.position - supplyDrop.transform.right); break; } else { containedSupply.DoRemove(); } } Facepunch.Pool.FreeList(ref list); if (IsRequiredSpawn) { SupplyDrop supplyDrop = GameManager.server.CreateEntity("assets/prefabs/misc/supply drop/supply_drop.prefab", position, default(Quaternion), true) as SupplyDrop; if (supplyDrop) { SubscribeHooks(); supplyDrop.globalBroadcast = true; supplyDrop.SetFlag(BaseEntity.Flags.Reserved12, true, false, false); supplyDrop.Spawn(); supplyDrop.RemoveParachute(); supplyDrop.inventory.capacity = config.SupplyCapacity; supplyDrop.panelName = "generic_large"; supplyDrop.SendNetworkUpdate(); List close_players = Pool.GetList(); BaseNetworkable.GetCloseConnections(supplyDrop.transform.position, 10, close_players); using (NetWrite netWrite = Network.Net.sv.StartWrite()) { netWrite.Bytes(UPDATE_SUPPLY_DATA); netWrite.Send(new SendInfo(close_players.Select(p => p.Connection).ToList())); } Pool.FreeList(ref close_players); Interface.CallHook("OnSupplyDropDropped", supplyDrop, supplySignal); } } } void OnEntityKill(SupplyDrop supplyDrop) { if (supplyDrop == null) return; if (!supplyDrop.HasFlag(SUPPLYDROP_FLAG)) return; if (BaseNetworkable.serverEntities.OfType().Count() == 0) UnsubscribeHooks(); } object OnLootSpawn(SupplyDrop supplyDrop) { if (supplyDrop == null) return null; if (!supplyDrop.HasFlag(SUPPLYDROP_FLAG)) return null; ContainedSupplySignal containedSupply = ContainedSupplySignal.CreateNew(supplyDrop); if (containedSupply.MoveToContainer(supplyDrop.inventory, -1, true, false, null, true)) containedSupply.PopulateLoot(supplyDrop); else containedSupply.DoRemove(); return false; } object OnItemAction(Item item, string action, BasePlayer player) { if (item == null || item.text != SUPPLY_NOTE) return null; if (action == "open") { if (item.IsLocked()) return false; PlayerLoot playerLoot = player.inventory.loot; playerLoot.Clear(); playerLoot.PositionChecks = true; playerLoot.containers.Add(item.contents); item.contents.onDirty += playerLoot.MarkDirty; playerLoot.itemSource = item; playerLoot.entitySource = item.GetEntityOwner(); Interface.CallHook("OnLootItem", player, item); playerLoot.MarkDirty(); } else if (action == "drop") { item.Remove(0); } return false; } void OnItemAddedToContainer(ItemContainer container, Item item) { if (!(container.entityOwner as SupplyDrop)) return; ContainedSupplySignal containedSupplySignal = item as ContainedSupplySignal; if (containedSupplySignal == null) return; if (containedSupplySignal.IsBusy()) container.entityOwner.InvokeRepeating(containedSupplySignal.Update, 0, 1f); } void OnItemRemovedFromContainer(ItemContainer container, Item item) { Item parentItem = container.parent; if (parentItem == null || parentItem.text != SUPPLY_NOTE) return; if (container.itemList.Count == 0) { foreach (BasePlayer player in BasePlayer.activePlayerList) { PlayerLoot playerLoot = player.inventory.loot; if (playerLoot.IsLooting() && playerLoot.itemSource == parentItem) playerLoot.Clear(); } parentItem.Remove(2f); } } void OnPlayerLootEnd(PlayerLoot playerLoot) { SupplyDrop supplyDrop = playerLoot.entitySource as SupplyDrop; Item itemSource = playerLoot.itemSource; if (supplyDrop != null && itemSource != null && itemSource.text == SUPPLY_NOTE) NextFrame(() => supplyDrop.PlayerOpenLoot(playerLoot.baseEntity)); } object CanMoveItem(Item item, PlayerInventory playerLoot, ItemContainerId targetContainer, int targetSlot, int amount) { if (item.text != SUPPLY_NOTE) return null; OnItemAction(item, "open", playerLoot.baseEntity); return false; } ItemContainer.CanAcceptResult? CanAcceptItem(ItemContainer container, Item item, int targetPos) { if (item.text == SUPPLY_NOTE && !(container.entityOwner is SupplyDrop)) return ItemContainer.CanAcceptResult.CannotAccept; return null; } object CanStackItem(Item item, Item targetItem) { if (item.text == SUPPLY_NOTE || targetItem.text == SUPPLY_NOTE) return false; return null; } object OnContainerPopulate(SupplyDrop supplyDrop) => CanPopulateLoot(supplyDrop); object CanPopulateLoot(SupplyDrop supplyDrop) { if (supplyDrop == null) return null; if (!supplyDrop.HasFlag(SUPPLYDROP_FLAG)) return null; return false; } #endregion #region Classes public class ContainedSupplySignal : Item { public void PopulateLoot(LootContainer lootContainer) { SpawnLootInContainer(lootContainer, this.contents); Instance.NextTick(() => this.contents.capacity = this.contents.itemList.Count); } public void Update() { bool isBusy = this.IsBusy(); this.LockUnlock(isBusy); string name; if (isBusy) name = $"{SUPPLY_ITEM_NAME_LOCKED} ({Mathf.RoundToInt(this.busyTime - UnityEngine.Time.time)}s)"; else name = null; if (this.name != name) { this.name = name; this.MarkDirty(); } if (!isBusy) this.parent?.entityOwner?.CancelInvoke(Update); } public static ContainedSupplySignal CreateNew(ItemContainer.Flag containerFlags) { ContainedSupplySignal item = new ContainedSupplySignal(); item.isServer = true; item.info = SUPPLY_SIGNAL_DEF; item.amount = 1; item.name = config.TimeToUnlock > 0 ? SUPPLY_ITEM_NAME_LOCKED : null; item.text = SUPPLY_NOTE; item.Initialize(SUPPLY_SIGNAL_DEF); item.contents = new global::ItemContainer(); item.contents.flags = containerFlags; item.contents.allowedContents = ItemContainer.ContentsType.Generic; item.contents.ServerInitialize(item, 18); item.contents.GiveUID(); item.BusyFor(config.TimeToUnlock); item.LockUnlock(item.IsBusy()); return item; } public static ContainedSupplySignal CreateNew(SupplyDrop supplyDrop) { return ContainedSupplySignal.CreateNew(supplyDrop.inventory.flags); } } #endregion #region Methods void SubscribeHooks() { Subscribe(nameof(OnItemAddedToContainer)); Subscribe(nameof(OnItemRemovedFromContainer)); Subscribe(nameof(CanStackItem)); Subscribe(nameof(OnLootSpawn)); Subscribe(nameof(OnItemAction)); Subscribe(nameof(CanMoveItem)); Subscribe(nameof(OnPlayerLootEnd)); Subscribe(nameof(OnContainerPopulate)); Subscribe(nameof(CanPopulateLoot)); } void UnsubscribeHooks() { Unsubscribe(nameof(OnItemAddedToContainer)); Unsubscribe(nameof(OnItemRemovedFromContainer)); Unsubscribe(nameof(CanStackItem)); Unsubscribe(nameof(OnLootSpawn)); Unsubscribe(nameof(OnItemAction)); Unsubscribe(nameof(CanMoveItem)); Unsubscribe(nameof(OnPlayerLootEnd)); Unsubscribe(nameof(OnContainerPopulate)); Unsubscribe(nameof(CanPopulateLoot)); } public static void SpawnLootInContainer(LootContainer lootContainer, ItemContainer container) { BaseEntity.Flags flags = lootContainer.flags; if ((flags & SUPPLYDROP_FLAG) == SUPPLYDROP_FLAG) flags &= ~SUPPLYDROP_FLAG; GameObject codefling = new GameObject("Codefling"); LootContainer fakeLootContainer = codefling.AddComponent(); fakeLootContainer._inventory = container; fakeLootContainer.prefabID = lootContainer.prefabID; fakeLootContainer.skinID = lootContainer.skinID; fakeLootContainer.flags = flags; fakeLootContainer.lootDefinition = lootContainer.lootDefinition; fakeLootContainer.maxDefinitionsToSpawn = lootContainer.maxDefinitionsToSpawn; fakeLootContainer.SpawnType = lootContainer.SpawnType; fakeLootContainer.LootSpawnSlots = lootContainer.LootSpawnSlots; fakeLootContainer.scrapAmount = lootContainer.scrapAmount; fakeLootContainer.net = new Network.Networkable() { ID = new NetworkableId((ulong)UnityEngine.Random.Range(345536, 5678934)) }; fakeLootContainer.SpawnLoot(); UnityEngine.Object.Destroy(codefling); // не долга жизнь этого gameobject'a, он много требовал и в суп попал. } #endregion #region Config static Configuration config; public class Configuration { [JsonProperty(PropertyName = "Supply capacity (1-42)")] public int SupplyCapacity = 42; [JsonProperty(PropertyName = "Range")] public float Range = 15f; [JsonProperty(PropertyName = "Time to unlock supply item")] public float TimeToUnlock = 120f; public static Configuration DefaultConfig() => new Configuration(); } protected override void LoadConfig() { base.LoadConfig(); try { config = Config.ReadObject(); if (config == null) LoadDefaultConfig(); SaveConfig(); } catch (Exception e) { Debug.LogException(e); PrintWarning("Creating new config file."); LoadDefaultConfig(); } } protected override void LoadDefaultConfig() => config = Configuration.DefaultConfig(); protected override void SaveConfig() => Config.WriteObject(config); #endregion } }