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

FREE DayZMags : 0.2 0.2

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Network;
using Newtonsoft.Json;
using Oxide.Game.Rust.Cui;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace Oxide.Plugins {
    [Info("DayZMags", "Jake_Rich", 0.2)]
    [Description("DayZMags")]
    public class DayZMags : RustPlugin {
        public static DayZMags _plugin {
            get;
            set;
        }
        public const float DRAG_RELOAD_UPDATE = 0.01f;
        public const string SHORTNAME_MAGAZINE = "pistol.eoka";
        public const string SHORTNAME_MODITEM = "battery.small";
        //TODO: Make magazines unequipable (don't let them move into hotbar perhaps?)
        //TODO: Drag unloading magazines out of weapons
        //TODO: Add monobehaviors (make sure they aren't saved / are unloaded upon unload)
        //TODO: Send network update when weapons are picked up (bugfix)
        //TODO: Make weapons have no ammo in them after they are created
        Item localPlayerWeaponFuck;
        Timer _timer;
        public static bool testing = true;
        public static bool infiniteAmmo = false;
        public static Dictionary<Item, Magazine> magData {
            get;
            set;
        }
        = new Dictionary<Item, Magazine>();
        //TODO: Remove when items are destroyed
        public static Dictionary<BasePlayer, PlayerData> playerData {
            get;
            set;
        }
        = new Dictionary<BasePlayer, DayZMags.PlayerData>();
        public static PlayerData GetPlayerData(BasePlayer player) {
            PlayerData data;
            if (!playerData.TryGetValue(player, out data)) {
                data = new PlayerData(player);
                playerData.Add(player, data);
            }
            return data;
        }
        //TODO: When reloading plugin, set condition of all magazines to 0 (otherwise they will be stuck unreloadable with a constant cooldown)
        //TODO: When loading large magazine, set capacity of gun to the size of the magazine (may be clientside)
#region Save / Load hooks
        void Init() {
            _plugin = this;
        }
        void OnServerInitialized() {
            AmmoSkinIDs = new HashSet<ulong>(AmmoDefinitions.Values.Select(x => x._skinID));
            WrappedAmmoSkinIDs = new HashSet<ulong>(WrappedAmmoDefinitions.Values.Select(x => x._skinID));
            MagazineSkinIDs = new HashSet<ulong>(MagazineDefinitions.Values.Select(x => x._skinID));
            var batDef = ItemManager.itemList.First(x => x.shortname == "battery.small");
            if (batDef.stackable == 1) {
                batDef.stackable = 2;
            }
            foreach (var weapon in GameObject.FindObjectsOfType<BaseProjectile>())  //Add custom component to all weapons
            {
                OnEntitySpawned(weapon);
            }
            foreach (var player in GameObject.FindObjectsOfType<BasePlayer>())  //Add custom component to all weapons
            {
                OnItemInit(player?.inventory?.AllItems());
            }
            foreach(var storage in GameObject.FindObjectsOfType<StorageContainer>()) {
                OnItemInit(storage?.inventory?.itemList);
            }
        }
        void Unload() {
            foreach (var weapon in GameObject.FindObjectsOfType<Weapon>())  //Remove components
            {
                GameObject.Destroy(weapon);
            }
            var batDef = ItemManager.itemList.First(x => x.shortname == "battery.small");
            if (batDef.stackable == 2) {
                batDef.stackable = 1;
            }
        }
#endregion
#region Item hooks
        void OnItemInit(IEnumerable<Item> items) {
            if (items == null) {
                Puts($"OnItemInit() items is null");
                return;
            }
            foreach(var item in items) {
                OnItemInit(item);
            }
        }
        void OnItemInit(Item item) {
            var held = item?.GetHeldEntity();
            if (held == null) {
                return;
            }
            if (!(held is BaseProjectile)) {
                return;
            }
            if (MagazineHelper.IsMagazine(item)) {
                return;
            }
            if (held.GetComponent<Weapon>() == null) {
                held.gameObject.AddComponent<Weapon>();
            }
        }
#endregion
#region Inventory hooks
        object GetMaxStackable(Item item) {
            //Puts("GetMaxStackable");
            if (item.skin == 0) {
                return null;
            }
            if (AmmoHelper.IsAmmo(item)) {
                Puts($"IsAmmo with stacksize of {AmmoHelper.GetAmmoInfo(item.skin)._stackLimit}");
                return AmmoHelper.GetAmmoInfo(item.skin)._stackLimit;
            }
            return null;
        }
        object CanMoveItem(Item movedItem, PlayerInventory playerLoot, uint targetContainerID, int targetSlot) {
            //Puts($"Can move item");
            var container = playerLoot.FindContainer(targetContainerID);
            if (container == null) {
                Puts("Container NULL");
                return null;
            }
            Item targetItem = container.GetSlot(targetSlot);
#region Dragging Magazines onto weapons
            if (MagazineHelper.IsMagazine(movedItem)) {
                if (MagazineHelper.IsMagazine(targetItem)) {
                    return null;
                }
                var weaponEntity = targetItem?.GetHeldEntity();
                if (weaponEntity != null) {
                    if (weaponEntity.GetComponent<Weapon>() == null) {
                        weaponEntity.gameObject.AddComponent<Weapon>();
                    }
                }
                if (movedItem.info.shortname == SHORTNAME_MODITEM) {
                    Puts($"IsMagazine() returned true for a MagazineModItem!");
                    return true;
                }
                var weapon = targetItem?.GetHeldEntity()?.GetComponent<Weapon>();
                //Dragging magazine onto a weapon
                var magazine = MagazineHelper.GetMagazine(movedItem);
                if (weapon == null) {
                    weapon = container?.parent?.GetHeldEntity()?.GetComponent<Weapon>();
                    //Dragging a magazine into a weapons modification slots
                }
                if (weapon != null) {
                    weapon.AttachMagazine(magazine);
                    return true;
                }
                if (targetItem == null) {
                    _plugin.Puts("targetItem is null");
                }
                if (targetItem?.GetHeldEntity() == null) {
                    _plugin.Puts("targetheld is null");
                }
                if (targetItem?.GetHeldEntity()?.GetComponentInParent<Weapon>() == null) {
                    _plugin.Puts("Component is null");
                }
                if (targetItem == null) {
                    _plugin.Puts(" is null");
                }
                Puts("Is Magazine");
                /*else if (TryMoveToEmpty(container, movedItem, targetSlot)) //Dragging magazine into empty slots (not really needed)
                {
                    return true;
                }
                else
                {
                    SwapPosition(targetItem, movedItem); //Swapping items (not needed)
                }*/
                /*
                if (IsMagazine(item) || !IsAmmo(item))
                {
                    SwapPosition(item, movedItem);
                    return true;
                }*/
                return null;
            }
#endregion
#region Drag To Add Ammo to Magazine
            if (targetItem != null) {
                if (MagazineHelper.IsMagazine(targetItem))  //Item being dragged to is a Magazine
                {
                    var magazine = MagazineHelper.GetMagazine(targetItem);
                    if (AmmoHelper.IsAmmo(movedItem)) {
                        magazine.TryDragLoad(movedItem);
                        return true;
                    }
                }
            }
#endregion
#region Dragging Magazine out of weapon
            if (MagazineHelper.IsModMagazineItem(movedItem)) {
                if (movedItem.contents == null) {
                    Puts("ModMagazineItem contents is null!");
                    return true;
                }
                if (movedItem.contents.itemList.Count == 0) {
                    Puts("ModMagazineItem contents is empty!");
                    return true;
                }
                MagazineHelper.GetMagazine(movedItem.contents.itemList[0]).RemoveFromWeapon(movedItem.parent.parent);
                return true;
            }
#endregion
#region Moving around unstackable items
#endregion
            return null;
        }
        //TODO: Increase modification slots of all weapons +1
        //TODO: Leave first slot free for weapon magazine
        //TODO: Decrease magazine bullet count when weapon is fired
        //TODO: Check if there is already a magazine in the gun when reloading
        //TODO: Hide bullet inserted into inventory when reloading gun
        //TODO: Magazine with 0 bullets
        //TODO: Only reload with invisible bullet if the player has the correct magazine for the gun
        //TODO: Only moved 29 bullets into an "empty" magazine
        //TODO: Alternate ammos for all bullets, to prevent players reloading without magazines
        //TODO: Function to detect if ammo fits in magazine, if magazine fits in gun, and config for magazine size + accepted weapons
        //TODO: Ammo package that can be unwrapped from airdrops / helis
        //TODO: Alternate capacity magazines for some guns (m249 can use stanag or m249 belt) (ak can use 75 round clip from heli drop)
        //TODO: Give weapon magazines (in loot, when crafting items)
        void OnItemRemovedFromContainer(ItemContainer container, Item item) {
            if (!MagazineHelper.IsMagazine(item)) {
                //Puts($"OnItemRemoved() not magazine!");
                return;
            }
            if (container.parent == null) {
                //Puts($"OnItemRemoved() parent null!");
                return;
            }
            var weapon = container.parent.GetHeldEntity() as BaseProjectile;
            if (weapon == null) {
                //Puts($"OnItemRemoved() not weapon!");
                return;
            }
            weapon.primaryMagazine.contents = 0;
            weapon.SendNetworkUpdateImmediate();
        }
        object OnItemAction(Item item, string action) {
            switch (action) {
#region Unloading Ammo from magazines, and magazines from guns
                case "unload_ammo" : {
                    if (MagazineHelper.IsMagazine(item)) {
                        MagazineHelper.GetMagazine(item).Unload();
                        return true;
                    }
                    var weapon = item.GetHeldEntity().GetComponent<Weapon>();
                    if (weapon.HasLoadedMagazine())  //TODO: Move to Weapon class (Unloading weapon's magazine based on mod item)
                    {
                        weapon.DetachMagazine();
                        return true;
                    }
                    break;
                }
#endregion
                case "unwrap" : {
                    if (!AmmoHelper.IsWrappedAmmo(item)) {
                        return null;
                    }
                    var player = item.GetOwnerPlayer();
                    if (player == null) {
                        return true;
                    }
                    var info = AmmoHelper.GetWrappedAmmoInfo(item);
                    item.UseItem();
                    player.GiveItem(AmmoHelper.CreateAmmo(info._ammo, info._unwrapAmount));
                    return true;
                }
            }
            return null;
        }
        object CanStackItem(Item item1, Item item2) {
            //Puts($"CanStack()");
            if (item1.skin == 0 || item2.skin == 0) {
                return null;
            }
            if (item1.skin != item2.skin) {
                return false;
            }
            if (AmmoHelper.IsAmmo(item1) && AmmoHelper.IsAmmo(item2)) {
                Puts("CanStack() both are ammo!");
                return true;
            }
            return null;
        }
        object CanAcceptItem(ItemContainer container, Item item)  //Prevent magazines (eoka) going into hotbar
        {
            if (MagazineHelper.IsMagazine(item)) {
                var player = container?.GetOwnerPlayer();
                if (player == null) {
                    return null;
                }
                if (container == player.inventory.containerBelt) {
                    return ItemContainer.CanAcceptResult.CannotAccept;
                }
            }
            return null;
        }
        void OnItemCraftFinished(ItemCraftTask task, Item item) {
            if (MagazineHelper.IsMagazine(item)) {
                MagazineHelper.InitializeMagazine(item);
            }
        }
#endregion
#region Entity hooks
        void OnEntitySpawned(BaseNetworkable entity) {
            var projectile = entity as BaseProjectile;
            if (projectile != null) {
                if (!MagazineHelper.IsMagazine(projectile)) {
                    return;
                }
                if (projectile.GetComponent<Weapon>() != null) {
                    return;
                }
                projectile.gameObject.AddComponent<Weapon>();
                Puts($"Added weapon component");
            }
        }
#endregion
#region Reload hooks (PlayerInput too)
        void OnPlayerInput(BasePlayer player, InputState input) {
            if (input.WasJustPressed(BUTTON.RELOAD)) {
                GetPlayerData(player).OnReloadButtonDown();
            }
            else if (input.WasJustReleased(BUTTON.RELOAD)) {
                GetPlayerData(player).OnReloadButtonUp();
            }
        }
        object OnStartReload(BasePlayer player, BaseProjectile weapon) {
            Puts($"OnStartReload");
            GetPlayerData(player).OnReloadStart(weapon);
            return null;
        }
        object OnReloadMagazine(BasePlayer player, BaseProjectile weapon) {
            Puts($"OnReloadMagazine");
            GetPlayerData(player).OnReloadEnd(weapon);
            weapon.SendNetworkUpdateImmediate(false);
            global : : ItemManager.DoRemoves();
            player.inventory.ServerUpdate(0f);
            return true;
        }
#endregion
#region Pickup Items
        //TODO: Add override if NoDespawning is loaded (add support to NoDespawning to override pickup single)
        object OnItemPickup(Item item, BasePlayer player) {
            if (MagazineHelper.IsMagazine(item)) {
                player.GiveItem(item);
                return true;
            }
            return null;
        }
#endregion
#region Other hooks
        void OnWeaponFired(BaseProjectile baseProjectile, BasePlayer player, ItemModProjectile mod, ProtoBuf.ProjectileShoot projectiles) {
            var weapon = baseProjectile.GetComponent<Weapon>();
            weapon.OnWeaponFired();
            if (infiniteAmmo) {
                baseProjectile.primaryMagazine.contents+= 1;
            }
        }
#endregion
        //TODO: Remove
#region Inventory Helpers (not needed, will remove later)
        public void SwapPosition(Item item1, Item item2) {
            if (item1.parent == item2.parent)  //Swaping within same container
            {
                int pos1 = item1.position;
                item1.position = item2.position;
                item1.MarkDirty();
                item2.position = pos1;
                item2.MarkDirty();
                return;
            }
            var container2 = item2.parent;
            int item2Slot = item2.position;
            int item1Slot = item1.position;
            item2.MoveToContainer(item1.parent, item1Slot);
            item1.MoveToContainer(container2, item2Slot);
        }
        public bool TryMoveToEmpty(ItemContainer targetContainer, Item itemMoved, int slot) {
            if (targetContainer == itemMoved.parent) {
                if (targetContainer.SlotTaken(slot)) {
                    return false;
                }
                itemMoved.position = slot;
                itemMoved.MarkDirty();
                return true;
            }
            if (targetContainer.SlotTaken(slot)) {
                return false;
            }
            itemMoved.MoveToContainer(targetContainer, slot, false);
            return true;
        }
#endregion
#region Debug Messages
        public static void Error(string error) {
            if (testing) {
                _plugin.Puts($"Error: {error}");
            }
        }
#endregion
#region Classes
        //TODO: Magazines aren't getting initialized
        public class PlayerData {
            private BasePlayer _player {
                get;
                set;
            }
            private Item _fakeAmmo {
                get;
                set;
            }
            private bool _reloadStarted {
                get;
                set;
            }
            private bool _reloadFinished {
                get;
                set;
            }
            private BaseProjectile _reloadWeapon {
                get;
                set;
            }
            public PlayerData(BasePlayer player) {
                _player = player;
            }
            public void OnReloadButtonDown() {
                if (!HasMagazine()) {
                    return;
                }
                var weaponInfo = GetWeapon().GetDefinition();
                if (weaponInfo == null) {
                    Error("OnReloadButtonDown() weaponInfo null!");
                    return;
                }
                var magazine = GetBestMagazine(weaponInfo.GetWeaponType());
                if (magazine == null) {
                    Error($"OnReloadButtonDown() magzine is null");
                    return;
                }
                CreateFakeAmmo(magazine);
                //TODO: Only create fake ammo if a valid magazine is in the player's inventory (based on players weapon)
            }
            public void OnReloadButtonUp() {
                RemoveFakeAmmo();
            }
            public void OnReloadStart(BaseProjectile weapon) {
                _reloadFinished = false;
                RemoveFakeAmmo();
                //this.StartReloadCooldown(this.reloadTime);
                //TODO: Eject magazine (only in hardcore mode)
                _reloadWeapon = weapon;
                _reloadStarted = true;
            }
            public void OnReloadEnd(BaseProjectile weaponEntity) {
                if (weaponEntity != _reloadWeapon) {
                    _plugin.Puts($"OnReloadEnd reload weapon doesnt equal current weapon");
                    CancelReload();
                    return;
                }
                if (!_reloadStarted) {
                    _plugin.Puts($"OnReloadEnd reload not started");
                    CancelReload();
                    return;
                }
                var weapon = weaponEntity.GetComponent<Weapon>();
                var mag = GetBestMagazine(weapon.GetWeaponType());
                if (mag == null) {
                    _plugin.Puts($"OnReloadEnd not valid magazines!");
                    return;
                }
                //Do reload here
                weapon.AttachMagazine(mag);
                _reloadWeapon = null;
            }
            public void OnSwitchWeapons() {
                RemoveFakeAmmo();
                CancelReload();
            }
            private void CancelReload() {
                RemoveFakeAmmo();
                //Just to be safe
            }
            private void RemoveFakeAmmo() {
                if (_fakeAmmo == null) {
                    return;
                }
                _fakeAmmo.Remove();
                ItemManager.DoRemoves();
            }
            private void CreateFakeAmmo(Magazine magazine) {
                _fakeAmmo = AmmoHelper.CreateTempAmmo(magazine.GetLoadedAmmoType());
                if (_fakeAmmo == null) {
                    Error($"CreateFakeAmmo() _fakeAmmo null");
                }
                _player.inventory.GiveItem(_fakeAmmo);
            }
            public bool HasMagazine() {
                return _player.inventory.AllItems().Any(x => MagazineHelper.IsMagazine(x));
            }
            public bool HasMagazine(WeaponType weapon) {
                return _player.inventory.AllItems().Any(x => MagazineHelper.IsMagazine(x, weapon));
            }
            public Magazine GetBestMagazine(WeaponType weapon) {
                //TODO: Holy fucked up LINQ batman!
                return _player.inventory.AllItems().Where(x => MagazineHelper.IsMagazine(x, weapon)).Select(x=>MagazineHelper.GetMagazine(x)).Where(x=>x.Bullets > 0).OrderByDescending(x => x.Bullets).FirstOrDefault();
            }
            public bool HasWeapon() {
                return _player.GetHeldEntity() is BaseProjectile;
            }
            public Weapon GetWeapon() {
                return (_player.GetHeldEntity() as BaseProjectile).GetComponent<Weapon>();
            }
        }
        public class WeaponInfo {
            private HashSet<AmmoType> _allowedAmmo {
                get;
                set;
            }
            public WeaponType _type {
                get;
                set;
            }
            public int ModSlots {
                get;
                set;
            }
            public WeaponInfo(WeaponType type, int modSlots, params AmmoType[] ammo) {
                _allowedAmmo = new HashSet<AmmoType>(ammo);
                _type = type;
                modSlots = modSlots;
            }
            public bool AcceptsAmmo(AmmoType ammo) {
                return _allowedAmmo.Contains(ammo);
            }
            public bool AcceptsAmmo(Item item) {
                return AcceptsAmmo(AmmoHelper.GetAmmoInfo(item)._ammoType);
            }
            public WeaponType GetWeaponType() {
                return _type;
            }
        }
        public class MagazineInfo {
            public ulong _skinID {
                get;
                set;
            }
            public string _name {
                get;
                set;
            }
            public int _capacity {
                get;
                set;
            }
            public List<WeaponType> allowedWeapons {
                get;
                set;
            }
            = new List<WeaponType>();
            public AmmoType _allowedAmmo {
                get;
                set;
            }
            public int _amountPerReload {
                get;
                set;
            }
            public float _timePerReload {
                get;
                set;
            }
            public MagazineInfo(ulong skinID, string name, int capacity, AmmoType ammo, int reloadAmount, float timePerReload, params WeaponType[] weapons) {
                _allowedAmmo = ammo;
                _skinID = skinID;
                _name = name;
                _capacity = capacity;
                allowedWeapons = weapons.ToList();
                _amountPerReload = reloadAmount;
                _timePerReload = timePerReload;
            }
            public bool WeaponAccepts(WeaponType type) {
                return allowedWeapons.Contains(type);
            }
        }
        public class WrappedAmmoInfo {
            public AmmoType _ammo {
                get;
                set;
            }
            public string _name {
                get;
                set;
            }
            public ulong _skinID {
                get;
                set;
            }
            public int _stackLimit {
                get;
                set;
            }
            public int _unwrapAmount {
                get;
                set;
            }
            public WrappedAmmoInfo(ulong skinID, string name, int unwrapAmount, AmmoType ammo, int stackLimit) {
                _skinID = skinID;
                _name = name;
                _unwrapAmount = unwrapAmount;
                _stackLimit = stackLimit;
                _ammo = ammo;
            }
        }
        public class AmmoInfo {
            public string _name;
            public ulong _skinID;
            public int _stackLimit;
            public string _shortname;
            public AmmoType _ammoType {
                get;
                set;
            }
            public AmmoInfo(ulong skinID, string name, string shortname, int stackLimit, AmmoType ammoType) {
                _skinID = skinID;
                _name = name;
                _shortname = shortname;
                _stackLimit = stackLimit;
                _ammoType = ammoType;
            }
            public Item CreateItem(int amount) {
                Item item = ItemManager.CreateByPartialName("battery.small", amount);
                item.skin = _skinID;
                item.name = _name;
                return item;
            }
            public Item CreateFakeAmmo() {
                return ItemManager.CreateByPartialName(_shortname, 1);
            }
        }
        public class Magazine {
            Item _modItem {
                get;
                set;
            }
            Item _mag {
                get;
                set;
            }
            //Item _weapon { get; set; }
            BaseProjectile _magazineEntity {
                get;
                set;
            }
            MagazineInfo _definition {
                get;
                set;
            }
            Timer _timer {
                get;
                set;
            }
            private int _bullets {
                get;
                set;
            }
            private ItemDefinition _bulletDefinition {
                get;
                set;
            }
            = ItemManager.FindItemDefinition("ammo.shotgun");
            private AmmoType _loadedAmmoType {
                get;
                set;
            }
            public int Bullets {
                get {
                    return _bullets;
                }
            }
            public Magazine(Item item) {
                _mag = item;
                _magazineEntity = item.GetHeldEntity() as BaseProjectile;
                if (_magazineEntity == null) {
                    _plugin.Puts($"Magazine Entity is null");
                }
                _definition = _plugin.GetDefinition(item.skin);
                _bullets = _magazineEntity.primaryMagazine.contents;
            }
            public AmmoType GetAmmoType() {
                return _definition._allowedAmmo;
            }
            public AmmoType GetLoadedAmmoType() {
                return GetAmmoType();
            }
            public MagazineInfo GetDefinition() {
                return _definition;
            }
            public bool IsModItem(Item item) {
                return item != null && _modItem == item;
            }
            private void SetupModItem(BaseProjectile weaponEntity) {
                if (_modItem == null) {
                    _modItem = ItemManager.CreateByName(SHORTNAME_MODITEM, Mathf.Max(1, _bullets), _definition._skinID);
                }
                _modItem.amount = _bullets;
                _mag.RemoveFromContainer();
                _plugin.Puts("1");
                _modItem.SetParent(weaponEntity.GetItem().contents);
                _modItem.position = 0;
                _plugin.Puts("3");
                weaponEntity.GetItem().MarkDirty();
                _modItem.MarkDirty();
                if (_modItem.contents == null) {
                    _modItem.contents = new ItemContainer();
                    _modItem.contents.ServerInitialize(_modItem, 1);
                    _modItem.contents.GiveUID();
                    //I dont remember how much of this you need, but I aint testing it
                    _modItem.contents.allowedContents = ItemContainer.ContentsType.Generic;
                    _modItem.contents.SetLocked(false);
                }
                _mag.MoveToContainer(_modItem.contents);
                _plugin.Puts("5");
                weaponEntity.SendNetworkUpdateImmediate();
                _plugin.Puts("7");
            }
            public void UseAmmo(int amount = 1) {
                if (_bullets == 0) {
                    return;
                }
                _bullets = Mathf.Max(0, --_bullets);
                UpdateAmmoCount();
            }
            public void Unload() {
                var player = _mag?.parent.GetOwnerPlayer();
                if (player == null) {
                    _plugin.Puts($"Magazine.Unload() null player!");
                    return;
                }
                player.GiveItem(AmmoHelper.CreateAmmo(_definition._allowedAmmo, _bullets));
                //TODO: Change this to handle overriden bullet types and use loadedammotype
                _bullets = 0;
                UpdateAmmoCount();
            }
            public void FillAmmo(Item ammo) {
                int amount = _definition._amountPerReload;
                if (testing) {
                    amount = _definition._capacity;
                }
                if (_bullets >= _definition._capacity) {
                    return;
                }
                if (_bullets + amount > _definition._capacity) {
                    amount = _definition._capacity - _bullets;
                }
                amount = Mathf.Min(amount, ammo.amount);
                ammo.UseItem(amount);
                _bullets += amount;
                UpdateAmmoCount();
            }
            private bool IsFull() {
                return _bullets >= _definition._capacity;
            }
            private void UpdateAmmoCount() {
                _magazineEntity.primaryMagazine.contents = _bullets;
                _magazineEntity.SendNetworkUpdateImmediate();
                _mag.MarkDirty();
                if (_modItem != null) {
                    //_plugin.Puts($"Mod item IS NOT null, {_bullets} bullets left");
                    _modItem.amount = _bullets;
                    _modItem.MarkDirty();
                }
                //TODO: Update item here as well
            }
            public bool CanWeaponAccept(Item weapon) {
                if (weapon == null) {
                    return false;
                }
                WeaponInfo def;
                if (!WeaponDefinitions.TryGetValue(weapon.info.shortname, out def)) {
                    return false;
                }
                return _definition.allowedWeapons.Contains(def.GetWeaponType());
            }
            public bool CanWeaponAccept(WeaponType type) {
                return _definition.allowedWeapons.Contains(type);
            }
            public void RemoveFromWeapon(Item weapon) {
                BaseProjectile weaponEntity = weapon.GetHeldEntity() as BaseProjectile;
                weaponEntity.primaryMagazine.contents = 0;
                _modItem.RemoveFromContainer();
                var container = weaponEntity.GetOwnerPlayer().inventory.containerMain;
                weaponEntity.GetOwnerPlayer().GiveItem(_mag);
                /*if (!_mag.MoveToContainer(container)) //??????? Wasn't working original way, changed to this and it didn't work, changed to original now it works
                {
                    _plugin.Puts($"Failed to move into container {container == null}");
                    _mag.Drop(container.dropPosition, container.dropVelocity);
                }*/
                //weaponEntity.GetOwnerPlayer().GiveItem(_mag);
                weaponEntity.SendNetworkUpdateImmediate();
                _mag.MarkDirty();
                _mag.GetHeldEntity().SendNetworkUpdateImmediate();
            }
            public void MoveToPlayerInventory() {
            }
            public void TryDragLoad(Item draggedItem) {
                if (AmmoHelper.GetAmmoInfo(draggedItem.skin)._ammoType != _definition._allowedAmmo) {
                    return;
                }
                if (HasCooldown()) {
                    _plugin.Puts("Drag reload has cooldown!");
                    return;
                }
                if (IsFull()) {
                    _plugin.Puts("Drag reload already full!");
                    return;
                }
                FillAmmo(draggedItem);
                _plugin.Puts("Drag loaded magazine");
                StartCooldown();
            }
            public void AddToWeapon(Item weaponItem) {
                if (weaponItem == null) {
                    return;
                }
                if (_mag?.parent?.parent == weaponItem)  //Don't reload magazine if it's already in the gun
                {
                    return;
                }
                var weapon = weaponItem.GetHeldEntity().GetComponent<Weapon>();
                BaseProjectile weaponEntity = weaponItem.GetHeldEntity() as BaseProjectile;
                if (weaponEntity == null) {
                    return;
                }
                weaponEntity.primaryMagazine.contents = _bullets;
                SetupModItem(weaponEntity);
            }
            public void SetModMagItem(Item item) {
                _modItem = item;
            }
#region Drag-Reload cooldown
            private void StartCooldown() {
                _timer?.Destroy();
                _mag.condition = 2;
                _timer = _plugin.timer.Every(DRAG_RELOAD_UPDATE, CooldownTick);
            }
            private bool HasCooldown() {
                return _mag.condition != 1;
            }
            private void StopCooldown() {
                _timer?.Destroy();
                _mag.condition = 1;
            }
            private void CooldownTick() {
                if (!HasCooldown()) {
                    return;
                }
                _mag.conditionNormalized += DRAG_RELOAD_UPDATE / _definition._timePerReload;
                //_plugin.Puts($"Update: Mag condition is {_mag.conditionNormalized} ({_mag.condition}/{_mag.maxCondition}) ({DRAG_RELOAD_UPDATE * _definition._timePerReload * _mag.info.condition.max})");
                if (_mag.conditionNormalized >= 1) {
                    StopCooldown();
                }
            }
#endregion
        }
        public class Weapon : MonoBehaviour {
            private Magazine _mag {
                get;
                set;
            }
            private BaseProjectile _entity {
                get;
                set;
            }
            private WeaponType _type {
                get {
                    return _definition._type;
                }
            }
            private WeaponInfo _definition {
                get;
                set;
            }
            private void Awake() {
                _entity = GetComponent<BaseProjectile>();
                _definition = WeaponHelper.GetWeaponInfo(_entity);
                var magItem = _entity.GetItem()?.contents?.itemList?.FirstOrDefault(x => MagazineHelper.IsModMagazineItem(x));
                if (magItem == null) {
                    return;
                }
                _mag = MagazineHelper.GetMagazine(magItem.contents.itemList[0]);
                _mag.SetModMagItem(_entity.GetItem().contents.itemList[0]);
            }
            public void OnWeaponFired() {
                _mag.UseAmmo();
            }
            public Magazine GetMagazine() {
                return _mag;
            }
            public void AttachMagazine(Magazine mag) {
                if (_mag != null) {
                    DetachMagazine();
                }
                _mag = mag;
                _mag.AddToWeapon(_entity.GetItem());
            }
            public void DetachMagazine() {
                _mag.RemoveFromWeapon(_entity.GetItem());
                _mag = null;
            }
            public WeaponType GetWeaponType() {
                return _type;
            }
            public bool HasLoadedMagazine() {
                return _mag != null;
            }
            public WeaponInfo GetDefinition() {
                return _definition;
            }
        }
#endregion
#region Static classes
        public static class WeaponHelper {
            public static WeaponInfo GetWeaponInfo(BaseProjectile weapon) {
                _plugin.Puts($"GetWeaponInfo() {weapon.GetItem().info.shortname}");
                return WeaponDefinitions[weapon.GetItem().info.shortname];
            }
            public static WeaponInfo GetWeaponInfo(Item item) {
                return WeaponDefinitions[item.info.shortname];
            }
        }
        public static class AmmoHelper {
            public static Item CreateAmmo(AmmoType ammo, int amount) {
                var info = GetAmmoInfo(ammo);
                return info.CreateItem(amount);
            }
            public static Item CreateTempAmmo(AmmoType ammo) {
                _plugin.Puts($"CreateTempAmmo type {ammo} {GetAmmoInfo(ammo)._shortname}");
                return ItemManager.CreateByName(GetAmmoInfo(ammo)._shortname, 1);
            }
            public static bool IsWrappedAmmo(Item item) {
                return WrappedAmmoDefinitions.ContainsKey(item.skin);
            }
            public static bool IsWrappedAmmo(ulong skinID) {
                return WrappedAmmoDefinitions.ContainsKey(skinID);
            }
            public static bool IsAmmo(Item item) {
                //Keep as simple check for ammo type, to allow dragging ammo to magazines not move the magazine
                return AmmoSkinIDs.Contains(item.skin);
            }
            public static WrappedAmmoInfo GetWrappedAmmoInfo(Item item) {
                return WrappedAmmoDefinitions[item.skin];
            }
            public static AmmoInfo GetAmmoInfo(AmmoType ammo) {
                return AmmoDefinitions.Values.FirstOrDefault(x => x._ammoType == ammo);
            }
            public static AmmoInfo GetAmmoInfo(ulong skinID) {
                return AmmoDefinitions[skinID];
            }
            public static AmmoInfo GetAmmoInfo(Item item) {
                return AmmoDefinitions[item.skin];
            }
        }
        public static class MagazineHelper {
            public static MagazineInfo GetMagazineInfo(Item item) {
                return MagazineDefinitions[item.skin];
            }
            public static bool IsModMagazineItem(Item item) {
                if (item == null) {
                    return false;
                }
                return item.info.shortname == SHORTNAME_MODITEM && IsMagazineSkin(item.skin);
            }
            public static bool IsMagazine(Item item) {
                if (item == null) {
                    return false;
                }
                if (item.info.shortname != SHORTNAME_MAGAZINE) {
                    return false;
                }
                return MagazineDefinitions.ContainsKey(item.skin);
            }
            public static bool IsMagazine(Item item, WeaponType weaponType) {
                if (item == null) {
                    return false;
                }
                if (item.info.shortname != SHORTNAME_MAGAZINE) {
                    return false;
                }
                MagazineInfo info;
                if (!MagazineDefinitions.TryGetValue(item.skin, out info)) {
                    return false;
                }
                return info.WeaponAccepts(weaponType);
            }
            public static bool IsMagazineSkin(ulong skinID) {
                return MagazineDefinitions.ContainsKey(skinID);
            }
            public static bool IsMagazine(HeldEntity entity) {
                if (entity == null) {
                    return false;
                }
                Item item = entity.GetItem();
                if (item == null) {
                    return false;
                }
                return IsMagazine(item);
            }
            public static Magazine GetMagazine(Item item) {
                if (item == null) {
                    return null;
                }
                Magazine data;
                if (!magData.TryGetValue(item, out data)) {
                    data = new Magazine(item);
                    magData.Add(item, data);
                }
                return data;
            }
            public static void InitializeMagazine(Item item) {
                var info = GetMagazineInfo(item);
                if (info == null) {
                    return;
                }
                item.name = info._name;
                var weapon = item.GetHeldEntity() as BaseProjectile;
                weapon.primaryMagazine.capacity = info._capacity;
                weapon.primaryMagazine.contents = 0;
                item.condition = 1;
                item.info.condition.max = 10000;
                item.maxCondition = item.info.condition.max;
                if (item.contents != null) {
                    item.contents.capacity = 0;
                }
            }
        }
        public static class PlayerHelper  //Not used yet
        {
        }
#endregion
        public static HashSet<ulong> AmmoSkinIDs;
        public static HashSet<ulong> WrappedAmmoSkinIDs;
        public static HashSet<ulong> MagazineSkinIDs;
#region Crafting Recipes
#region Recipe Classes
        public class CraftRecipe {
            public List<ItemAmount> RequiredIngredients {
                get;
                set;
            }
            = new List<ItemAmount>();
            public string ItemName {
                get;
                set;
            }
            public string Description {
                get;
                set;
            }
            public ItemAmount ResultItem {
                get;
                set;
            }
            public float CraftTime {
                get;
                set;
            }
            public CraftRecipe() {
            }
            public CraftRecipe(string itemName, float craftTime, string description, string productShortname, int productAmount, ulong productSkin, params ItemAmount[] ingredients) {
                ItemName = itemName;
                CraftTime = craftTime;
                Description = description;
                ResultItem = new ItemAmount(productShortname, productAmount, productSkin);
                RequiredIngredients.AddRange(ingredients);
            }
            public bool HasItems(BasePlayer player, int amount) {
                if (amount > 10000 || amount < 1) {
                    _plugin.PrintError($"HasItems() out of range! {amount}");
                    return false;
                }
                Item[] items = player.inventory.AllItems();
                foreach (var item in RequiredIngredients) {
                    if (items.Where(x => x.skin == item.skinID && x.info.shortname == item.shortname).Sum(x => x.amount) < item.amount * amount) {
                        return false;
                    }
                }
                return true;
            }
            public void AddIngredient(string shortname, int amount = 1, ulong skin = 0) {
                RequiredIngredients.Add(new ItemAmount(shortname, amount, skin));
            }
        }
        public class ItemAmount {
            public string shortname {
                get;
                set;
            }
            public int amount {
                get;
                set;
            }
            public ulong skinID {
                get;
                set;
            }
            public ItemAmount() {
            }
            public ItemAmount(string shortname, int amount = 1, ulong skinID = 0) {
                this.shortname = shortname;
                this.amount = amount;
                this.skinID = skinID;
            }
            public int ItemID() {
                var item = ItemManager.itemList.FirstOrDefault(x => x.shortname == shortname);
                if (item == null) {
                    return -1;
                }
                return item.itemid;
            }
        }
#endregion
        public class ModSettings {
            public string PluginName {
                get;
                set;
            }
            public List<CraftRecipe> Recipes = new List<CraftRecipe>();
            public CraftRecipe NewRecipe() {
                var recipe = new CraftRecipe();
                Recipes.Add(recipe);
                return recipe;
            }
            public CraftRecipe AddRecipe(CraftRecipe recipe) {
                Recipes.Add(recipe);
                return recipe;
            }
        }
        private string GetCraftingRecipes() {
            var mod = new ModSettings();
            mod.Recipes = new List<CraftRecipe>() {
                new CraftRecipe() {
                    CraftTime = 20f, ItemName = "Bolt Clip (5 Rounds)", ResultItem = new ItemAmount("pistol.eoka", 1, 946779217), Description = "A 5 Round Clip for the bolt action rifle.", RequiredIngredients = new List<ItemAmount>() {
                        new ItemAmount("wood", 100), new ItemAmount("metal.fragments", 500),
                    }
                    ,
                }
                , new CraftRecipe() {
                    CraftTime = 30f, ItemName = "AK Magazine (30 Rounds)", ResultItem = new ItemAmount("pistol.eoka", 1, 946778674), Description = "A magazine for the ak47 assault rifle.Holds 30 rifle rounds.", RequiredIngredients = new List<ItemAmount>() {
                        new ItemAmount("wood", 100), new ItemAmount("metal.fragments", 500),
                    }
                    ,
                }
                , new CraftRecipe() {
                    CraftTime = 20f, ItemName = "Semi-Pistol Magazine (10 Rounds)", ResultItem = new ItemAmount("pistol.eoka", 1, 946783613), Description = "A traditional magazine for the semi-auto pistol.Holds 10 pistol rounds.", RequiredIngredients = new List<ItemAmount>() {
                        new ItemAmount("wood", 100), new ItemAmount("metal.fragments", 500),
                    }
                    ,
                }
                , new CraftRecipe() {
                    CraftTime = 15f, ItemName = "Python Speedloader", ResultItem = new ItemAmount("pistol.eoka", 1, 946784019), Description = "A six round speedloader for a python revolver
// ... [Code preview truncated due to length. Full source in attached file] ...

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