internal void MoveAmmo() { for (int i = 0; i < AmmoToPullQueue.Count; i++) { var weaponAmmoToPull = AmmoToPullQueue[i]; var weapon = weaponAmmoToPull.Weapon; var inventoriesToPull = weaponAmmoToPull.Inventories; if (!weapon.Comp.InventoryInited || weapon.Comp.Platform.State != MyWeaponPlatform.PlatformState.Ready) { InventoryMoveRequestPool.Return(weaponAmmoToPull); continue; } for (int j = 0; j < inventoriesToPull.Count; j++) { var mag = inventoriesToPull[j]; var amt = mag.Amount; var item = mag.Item; if (weapon.Comp.BlockInventory.ItemsCanBeAdded(amt, weapon.ActiveAmmoDef.AmmoDef.Const.AmmoItem) && mag.Inventory.ItemsCanBeRemoved(amt, item.Item)) { mag.Inventory.RemoveItems(item.Item.ItemId, amt); weapon.Comp.BlockInventory.Add(weapon.ActiveAmmoDef.AmmoDef.Const.AmmoItem, amt); } } weapon.Ammo.CurrentMags = weapon.Comp.BlockInventory.GetItemAmount(weapon.ActiveAmmoDef.AmmoDefinitionId).ToIntSafe(); InventoryMoveRequestPool.Return(weaponAmmoToPull); } AmmoToPullQueue.Clear(); }
internal void MoveAmmo() { MyTuple <Weapon, MyTuple <MyInventory, int>[]> weaponAmmoToPull; while (AmmoToPullQueue.TryDequeue(out weaponAmmoToPull)) { var weapon = weaponAmmoToPull.Item1; if (!weapon.Comp.InventoryInited) { continue; } var inventoriesToPull = weaponAmmoToPull.Item2; var def = weapon.ActiveAmmoDef.AmmoDefinitionId; var magItem = weapon.ActiveAmmoDef.AmmoDef.Const.AmmoItem; weapon.Comp.IgnoreInvChange = true; for (int i = 0; i < inventoriesToPull.Length; i++) { var amt = inventoriesToPull[i].Item2; inventoriesToPull[i].Item1.RemoveItemsOfType(amt, def); weapon.Comp.BlockInventory.Add(magItem, amt); } if (inventoriesToPull.Length > 0) { weapon.State.Sync.CurrentMags = weapon.Comp.BlockInventory.GetItemAmount(weapon.ActiveAmmoDef.AmmoDefinitionId); if (weapon.CanReload) { weapon.StartReload(); } } weapon.Comp.IgnoreInvChange = false; } }
internal void PurgeAll() { FutureEvents.Purge((int)Tick); PurgeTerminalSystem(); foreach (var reports in Reporter.ReportData.Values) { foreach (var report in reports) { report.Clean(); Reporter.ReportPool.Return(report); } reports.Clear(); } Reporter.ReportData.Clear(); Reporter.ReportPool.Clean(); PacketsToClient.Clear(); PacketsToServer.Clear(); foreach (var suit in (PacketType[])Enum.GetValues(typeof(PacketType))) { foreach (var pool in PacketPools.Values) { pool.Clean(); } PacketPools.Clear(); } foreach (var item in _effectedCubes) { var cubeid = item.Key; var blockInfo = item.Value; var functBlock = blockInfo.FunctBlock; var cube = blockInfo.CubeBlock; if (cube == null || cube.MarkedForClose) { _effectPurge.Enqueue(cubeid); continue; } functBlock.EnabledChanged -= ForceDisable; functBlock.Enabled = blockInfo.FirstState; cube.SetDamageEffect(false); _effectPurge.Enqueue(cubeid); } while (_effectPurge.Count != 0) { _effectedCubes.Remove(_effectPurge.Dequeue()); } Av.Glows.Clear(); Av.AvShotPool.Clean(); DeferedUpBlockTypeCleanUp(true); BlockTypeCleanUp.Clear(); foreach (var map in GridToFatMap.Keys) { RemoveGridFromMap(map); } GridToFatMap.Clear(); FatMapPool.Clean(); DirtyGridsTmp.Clear(); foreach (var structure in WeaponPlatforms.Values) { foreach (var system in structure.WeaponSystems) { foreach (var ammo in system.Value.WeaponAmmoTypes) { ammo.AmmoDef.Const.PrimeEntityPool?.Clean(); } } structure.WeaponSystems.Clear(); } WeaponPlatforms.Clear(); foreach (var gridToMap in GridToBlockTypeMap) { foreach (var map in gridToMap.Value) { map.Value.ClearImmediate(); ConcurrentListPool.Return(map.Value); } gridToMap.Value.Clear(); BlockTypePool.Return(gridToMap.Value); } GridToBlockTypeMap.Clear(); foreach (var playerGrids in PlayerEntityIdInRange) { playerGrids.Value.Clear(); } PlayerEntityIdInRange.Clear(); DirtyGrids.Clear(); DsUtil.Purge(); DsUtil2.Purge(); _effectActive = false; ShootingWeapons.Clear(); AcquireTargets.Clear(); RemoveEffectsFromGrid.Clear(); WeaponAmmoPullQueue.Clear(); AmmoToPullQueue.Clear(); Hits.Clear(); AllArmorBaseDefinitions.Clear(); HeavyArmorBaseDefinitions.Clear(); AllArmorBaseDefinitions.Clear(); AcquireTargets.Clear(); ChargingWeapons.Clear(); LargeBlockSphereDb.Clear(); SmallBlockSphereDb.Clear(); AnimationsToProcess.Clear(); _subTypeIdToWeaponDefs.Clear(); WeaponDefinitions.Clear(); SlimsSortedList.Clear(); _destroyedSlims.Clear(); _destroyedSlimsClient.Clear(); _slimHealthClient.Clear(); _slimsSet.Clear(); _turretDefinitions.Clear(); foreach (var comp in CompsToStart) { PlatFormPool.Return(comp.Platform); comp.Platform = null; } foreach (var readd in CompReAdds) { PlatFormPool.Return(readd.Comp.Platform); readd.Comp.Platform = null; } foreach (var comp in CompsDelayed) { PlatFormPool.Return(comp.Platform); comp.Platform = null; } PlatFormPool.Clean(); CompsToStart.ClearImmediate(); CompsDelayed.Clear(); CompReAdds.Clear(); GridAiPool.Clean(); Av.RipMap.Clear(); foreach (var mess in Av.KeensBrokenParticles) { Av.KeenMessPool.Return(mess); } Av.KeensBrokenParticles.Clear(); foreach (var av in Av.AvShots) { av.GlowSteps.Clear(); Av.AvShotPool.Return(av); } Av.AvShotPool.Clean(); Av.AvBarrels1.Clear(); Av.AvBarrels2.Clear(); Av.AvShots.Clear(); Av.HitSounds.Clear(); foreach (var errorpkt in ClientSideErrorPktList) { errorpkt.Packet.CleanUp(); } ClientSideErrorPktList.Clear(); GridEffectPool.Clean(); GridEffectsPool.Clean(); BlockTypePool.Clean(); ConcurrentListPool.Clean(); GroupInfoPool.Clean(); TargetInfoPool.Clean(); Projectiles.Clean(); WeaponCoreBlockDefs.Clear(); VanillaIds.Clear(); VanillaCoreIds.Clear(); WeaponCoreFixedBlockDefs.Clear(); WeaponCoreTurretBlockDefs.Clear(); foreach (var p in Projectiles.ProjectilePool) { p.AmmoEffect?.Stop(); } Projectiles.ShrapnelToSpawn.Clear(); Projectiles.ShrapnelPool.Clean(); Projectiles.FragmentPool.Clean(); Projectiles.ActiveProjetiles.ApplyChanges(); Projectiles.ActiveProjetiles.Clear(); Projectiles.ProjectilePool.Clear(); Projectiles.HitEntityPool.Clean(); Projectiles.CleanUp.Clear(); Projectiles.VirtInfoPool.Clean(); DbsToUpdate.Clear(); GridTargetingAIs.Clear(); DsUtil = null; DsUtil2 = null; SlimsSortedList = null; Enforced = null; StallReporter = null; Proccessor = null; Physics = null; Camera = null; Projectiles = null; TrackingAi = null; UiInput = null; TargetUi = null; Placer = null; WheelUi = null; TargetGps = null; SApi.Unload(); SApi = null; Api = null; ApiServer = null; Reporter = null; WeaponDefinitions = null; AnimationsToProcess = null; ProjectileTree.Clear(); ProjectileTree = null; Av = null; HudUi = null; AllDefinitions = null; SoundDefinitions = null; ActiveCockPit = null; ActiveControlBlock = null; ControlledEntity = null; }
internal void PurgeAll() { PurgedAll = true; FutureEvents.Purge((int)Tick); foreach (var comp in CompsToStart) { if (comp?.Platform != null) { CloseComps(comp.MyCube); } } foreach (var readd in CompReAdds) { if (!readd.Ai.Closed) { readd.Ai.AiForceClose(); } if (readd.Comp?.Platform != null) { CloseComps(readd.Comp.MyCube); } } foreach (var comp in CompsDelayed) { if (comp?.Platform != null) { CloseComps(comp.MyCube); } } foreach (var gridAi in DelayedAiClean) { if (!gridAi.Closed) { gridAi.AiForceClose(); } } PlatFormPool.Clean(); CompsToStart.ClearImmediate(); DelayedAiClean.ClearImmediate(); CompsDelayed.Clear(); CompReAdds.Clear(); GridAiPool.Clean(); PurgeTerminalSystem(this); HudUi.Purge(); TerminalMon.Purge(); foreach (var reports in Reporter.ReportData.Values) { foreach (var report in reports) { report.Clean(); Reporter.ReportPool.Return(report); } reports.Clear(); } Reporter.ReportData.Clear(); Reporter.ReportPool.Clean(); PacketsToClient.Clear(); PacketsToServer.Clear(); AcqManager.Clean(); CleanSounds(true); foreach (var e in Emitters) { e.StopSound(true); } foreach (var e in Av.HitEmitters) { e.StopSound(true); } foreach (var e in Av.FireEmitters) { e.StopSound(true); } foreach (var e in Av.TravelEmitters) { e.StopSound(true); } Emitters.Clear(); Av.HitEmitters.Clear(); Av.FireEmitters.Clear(); Av.TravelEmitters.Clear(); foreach (var item in EffectedCubes) { var cubeid = item.Key; var blockInfo = item.Value; var functBlock = blockInfo.FunctBlock; if (functBlock == null || functBlock.MarkedForClose) { _effectPurge.Enqueue(cubeid); continue; } functBlock.EnabledChanged -= ForceDisable; functBlock.Enabled = blockInfo.FirstState; functBlock.SetDamageEffect(false); if (HandlesInput) { functBlock.AppendingCustomInfo -= blockInfo.AppendCustomInfo; } _effectPurge.Enqueue(cubeid); } while (_effectPurge.Count != 0) { EffectedCubes.Remove(_effectPurge.Dequeue()); } Av.Glows.Clear(); Av.AvShotPool.Clean(); DeferedUpBlockTypeCleanUp(true); BlockTypeCleanUp.Clear(); foreach (var map in GridToInfoMap.Keys) { RemoveGridFromMap(map); } GridToInfoMap.Clear(); GridMapPool.Clean(); DirtyGridsTmp.Clear(); foreach (var structure in WeaponPlatforms.Values) { foreach (var system in structure.WeaponSystems) { system.Value.PreFirePairs.Clear(); system.Value.FireWhenDonePairs.Clear(); system.Value.FirePerShotPairs.Clear(); system.Value.RotatePairs.Clear(); system.Value.ReloadPairs.Clear(); foreach (var ammo in system.Value.AmmoTypes) { ammo.AmmoDef.Const.PrimeEntityPool?.Clean(); ammo.AmmoDef.Const.HitDefaultSoundPairs.Clear(); ammo.AmmoDef.Const.HitVoxelSoundPairs.Clear(); ammo.AmmoDef.Const.HitShieldSoundPairs.Clear(); ammo.AmmoDef.Const.HitFloatingSoundPairs.Clear(); ammo.AmmoDef.Const.HitPlayerSoundPairs.Clear(); ammo.AmmoDef.Const.TravelSoundPairs.Clear(); ammo.AmmoDef.Const.CustomSoundPairs.Clear(); } } structure.WeaponSystems.Clear(); } WeaponPlatforms.Clear(); foreach (var gridToMap in GridToBlockTypeMap) { foreach (var map in gridToMap.Value) { ConcurrentListPool.Return(map.Value); } gridToMap.Value.Clear(); BlockTypePool.Return(gridToMap.Value); } GridToBlockTypeMap.Clear(); foreach (var playerGrids in PlayerEntityIdInRange) { playerGrids.Value.Clear(); } PlayerEntityIdInRange.Clear(); DirtyGridInfos.Clear(); DsUtil.Purge(); DsUtil2.Purge(); ShootingWeapons.Clear(); WeaponToPullAmmo.Clear(); AmmoToPullQueue.Clear(); ChargingWeaponsIndexer.Clear(); WeaponsToRemoveAmmoIndexer.Clear(); ChargingWeapons.Clear(); Hits.Clear(); HomingWeapons.Clear(); GridToMasterAi.Clear(); Players.Clear(); IdToCompMap.Clear(); AllArmorBaseDefinitions.Clear(); HeavyArmorBaseDefinitions.Clear(); AllArmorBaseDefinitions.Clear(); AcquireTargets.Clear(); LargeBlockSphereDb.Clear(); SmallBlockSphereDb.Clear(); AnimationsToProcess.Clear(); _subTypeIdToWeaponDefs.Clear(); WeaponDefinitions.Clear(); SlimsSortedList.Clear(); _destroyedSlims.Clear(); _destroyedSlimsClient.Clear(); _slimHealthClient.Clear(); _slimsSet.Clear(); _turretDefinitions.Clear(); _tmpNearByBlocks.Clear(); foreach (var av in Av.AvShots) { av.GlowSteps.Clear(); Av.AvShotPool.Return(av); } Av.AvShotPool.Clean(); Av.AvBarrels1.Clear(); Av.AvBarrels2.Clear(); Av.AvShots.Clear(); Av.HitSounds.Clear(); foreach (var errorpkt in ClientSideErrorPkt) { errorpkt.Packet.CleanUp(); } ClientSideErrorPkt.Clear(); GridEffectPool.Clean(); GridEffectsPool.Clean(); BlockTypePool.Clean(); ConcurrentListPool.Clean(); TargetInfoPool.Clean(); PacketObjPool.Clean(); InventoryMoveRequestPool.Clean(); WeaponCoreBlockDefs.Clear(); VanillaIds.Clear(); VanillaCoreIds.Clear(); WeaponCoreFixedBlockDefs.Clear(); WeaponCoreTurretBlockDefs.Clear(); VoxelCaches.Clear(); ArmorCubes.Clear(); foreach (var p in Projectiles.ProjectilePool) { p.Info?.AvShot?.AmmoEffect?.Stop(); } Projectiles.ShrapnelToSpawn.Clear(); Projectiles.ShrapnelPool.Clean(); Projectiles.FragmentPool.Clean(); Projectiles.ActiveProjetiles.Clear(); Projectiles.ProjectilePool.Clear(); Projectiles.HitEntityPool.Clean(); Projectiles.VirtInfoPool.Clean(); DbsToUpdate.Clear(); GridTargetingAIs.Clear(); DsUtil = null; DsUtil2 = null; SlimsSortedList = null; Settings = null; StallReporter = null; TerminalMon = null; Physics = null; Camera = null; Projectiles = null; TrackingAi = null; UiInput = null; TargetUi = null; Placer = null; TargetGps = null; SApi.Unload(); SApi = null; Api = null; ApiServer = null; Reporter = null; WeaponDefinitions = null; AnimationsToProcess = null; ProjectileTree.Clear(); ProjectileTree = null; Av = null; HudUi = null; AllDefinitions = null; SoundDefinitions = null; ActiveCockPit = null; ActiveControlBlock = null; ControlledEntity = null; TmpStorage = null; }
internal void AmmoPull() // In Thread { try { foreach (var weapon in WeaponToPullAmmo) { using (weapon.Comp.Ai?.MyGrid.Pin()) using (weapon.Comp.MyCube.Pin()) { if (weapon.Comp.MyCube.MarkedForClose || weapon.Comp.Ai == null || weapon.Comp.Ai.MarkedForClose || weapon.Comp.Ai.MyGrid.MarkedForClose || !weapon.Comp.InventoryInited || weapon.Comp.Platform.State != MyWeaponPlatform.PlatformState.Ready) { InvPullClean.Add(weapon); continue; } var defId = weapon.ActiveAmmoDef.AmmoDefinitionId; var freeSpace = weapon.System.MaxAmmoVolume - weapon.Comp.CurrentInventoryVolume; var spotsFree = (int)(freeSpace / weapon.ActiveAmmoDef.AmmoDef.Const.MagVolume); var magsNeeded = (int)((weapon.System.FullAmmoVolume - weapon.CurrentAmmoVolume) / weapon.ActiveAmmoDef.AmmoDef.Const.MagVolume); magsNeeded = magsNeeded > spotsFree ? spotsFree : magsNeeded; var ammoPullRequests = InventoryMoveRequestPool.Get(); ammoPullRequests.Weapon = weapon; var magsAdded = 0; var logged = 0; foreach (var inventory in weapon.Comp.Ai.InventoryMonitor.Values) { MyConcurrentList <BetterInventoryItem> items; if (AmmoThreadItemList.TryGetValue(inventory, out items)) { for (int l = items.Count - 1; l >= 0; l--) { var item = items[l]; if (!item.DefId.Equals(defId)) { continue; } var magsAvailable = item.Amount; if (magsAvailable > 0 && magsNeeded > 0 && ((IMyInventory)inventory).CanTransferItemTo(weapon.Comp.BlockInventory, defId)) { if (magsAvailable >= magsNeeded) { ammoPullRequests.Inventories.Add(new InventoryMags { Inventory = inventory, Item = item, Amount = magsNeeded }); magsAdded += magsNeeded; item.Amount -= magsNeeded; magsNeeded = 0; } else { ammoPullRequests.Inventories.Add(new InventoryMags { Inventory = inventory, Item = item, Amount = magsAvailable }); magsNeeded -= magsAvailable; magsAdded += magsAvailable; item.Amount -= magsAvailable; items.RemoveAtFast(l); BetterInventoryItems.Return(item); } weapon.CurrentAmmoVolume = magsAdded * weapon.ActiveAmmoDef.AmmoDef.Const.MagVolume; } if (magsNeeded <= 0) { break; } } } else if (logged++ == 0) { Log.Line($"[Inventory invalid in AmmoPull] Weapon:{weapon.Comp.MyCube.BlockDefinition.Id.SubtypeName} - blockMarked:{weapon.Comp.MyCube.MarkedForClose} - aiMarked:{weapon.Comp.Ai.MarkedForClose} - cTick:{Tick - weapon.Comp.Ai.AiCloseTick} - mTick:{Tick - weapon.Comp.Ai.AiMarkedTick} - sTick:{Tick - weapon.Comp.Ai.CreatedTick}"); } } if (ammoPullRequests.Inventories.Count > 0) { AmmoToPullQueue.Add(ammoPullRequests); } else { InventoryMoveRequestPool.Return(ammoPullRequests); } } InvPullClean.Add(weapon); } } catch (Exception e) { Log.Line($"Error in AmmoPull: {e}"); } }
internal void AmmoPull() { var cachedInv = new Dictionary <MyDefinitionId, Dictionary <MyInventory, MyFixedPoint> >(); Weapon weapon; while (WeaponAmmoPullQueue.TryDequeue(out weapon)) { using (weapon.Comp.Ai?.MyGrid.Pin()) using (weapon.Comp.MyCube.Pin()) { if (weapon.Comp.MyCube.MarkedForClose || weapon.Comp.Ai == null || weapon.Comp.Ai.MyGrid.MarkedForClose || !weapon.Comp.InventoryInited || weapon.Comp.Platform.State != MyWeaponPlatform.PlatformState.Ready || weapon.Comp.MyCube == null) { continue; } var def = weapon.ActiveAmmoDef.AmmoDefinitionId; float itemMass; float itemVolume; MyInventory.GetItemVolumeAndMass(def, out itemMass, out itemVolume); var fullAmount = 0.75f * weapon.System.MaxAmmoVolume; var weaponInventory = weapon.Comp.BlockInventory; var magsNeeded = (int)((fullAmount - weapon.CurrentAmmoVolume) / itemVolume); if (magsNeeded == 0 && weapon.System.MaxAmmoVolume > itemVolume) { magsNeeded = 1; } var magsAdded = 0; lock (weapon.Comp.Ai.AmmoInventories[def]) { List <MyTuple <MyInventory, int> > inventories = new List <MyTuple <MyInventory, int> >(); if (!cachedInv.ContainsKey(def)) { cachedInv[def] = weapon.Comp.Ai.AmmoInventories[def].ToDictionary(kvp => kvp.Key, kvp => kvp.Value, new InventoryCompare()); } foreach (var currentInventory in weapon.Comp.Ai.AmmoInventories[def]) { var inventory = currentInventory.Key; var magsAvailable = (int)cachedInv[def][inventory]; if (((IMyInventory)inventory).CanTransferItemTo(weaponInventory, def)) { if (magsAvailable >= magsNeeded) { inventories.Add(new MyTuple <MyInventory, int> { Item1 = inventory, Item2 = magsNeeded }); magsAdded += magsNeeded; magsNeeded = 0; } else { inventories.Add(new MyTuple <MyInventory, int> { Item1 = inventory, Item2 = magsAvailable }); magsNeeded -= magsAvailable; magsAdded += magsAvailable; } cachedInv[def][inventory] -= magsAdded; } } weapon.CurrentAmmoVolume += magsAdded * itemVolume; if (inventories.Count > 0) { AmmoToPullQueue.Enqueue(new MyTuple <Weapon, MyTuple <MyInventory, int>[]> { Item1 = weapon, Item2 = inventories.ToArray() }); } weapon.Comp.Session.AmmoPulls++; } } } cachedInv.Clear(); }
internal void AmmoPull() // In Thread { Weapon weapon = null; try { for (int i = WeaponToPullAmmo.Count - 1; i >= 0; i--) { weapon = WeaponToPullAmmo[i]; using (weapon.Comp.Ai?.MyGrid.Pin()) using (weapon.Comp.MyCube.Pin()) { if (weapon.Comp.MyCube.MarkedForClose || weapon.Comp.Ai == null || weapon.Comp.Ai.MarkedForClose || weapon.Comp.Ai.MyGrid.MarkedForClose || !weapon.Comp.InventoryInited || weapon.Comp.Platform.State != MyWeaponPlatform.PlatformState.Ready) { InvPullClean.Add(weapon); continue; } var defId = weapon.ActiveAmmoDef.AmmoDefinitionId; var freeSpace = weapon.System.MaxAmmoVolume - weapon.Comp.CurrentInventoryVolume; var spotsFree = (int)(freeSpace / weapon.ActiveAmmoDef.AmmoDef.Const.MagVolume); var magsNeeded = (int)((weapon.System.FullAmmoVolume - weapon.CurrentAmmoVolume) / weapon.ActiveAmmoDef.AmmoDef.Const.MagVolume); magsNeeded = magsNeeded > spotsFree ? spotsFree : magsNeeded; var ammoPullRequests = InventoryMoveRequestPool.Get(); ammoPullRequests.Weapon = weapon; var magsAdded = 0; for (int j = 0; j < weapon.Comp.Ai.Inventories.Count; j++) { var inventory = weapon.Comp.Ai.Inventories[j]; var items = AmmoThreadItemList[inventory]; for (int l = items.Count - 1; l >= 0; l--) { var item = items[l]; if (!item.DefId.Equals(defId)) { continue; } var magsAvailable = item.Amount; if (magsAvailable > 0 && magsNeeded > 0 && ((IMyInventory)inventory).CanTransferItemTo(weapon.Comp.BlockInventory, defId)) { if (magsAvailable >= magsNeeded) { ammoPullRequests.Inventories.Add(new InventoryMags { Inventory = inventory, Item = item, Amount = magsNeeded }); magsAdded += magsNeeded; item.Amount -= magsNeeded; magsNeeded = 0; } else { ammoPullRequests.Inventories.Add(new InventoryMags { Inventory = inventory, Item = item, Amount = magsAvailable }); magsNeeded -= magsAvailable; magsAdded += magsAvailable; item.Amount -= magsAvailable; items.RemoveAtFast(l); BetterInventoryItems.Return(item); } weapon.CurrentAmmoVolume = magsAdded * weapon.ActiveAmmoDef.AmmoDef.Const.MagVolume; } if (magsNeeded <= 0) { break; } } } if (ammoPullRequests.Inventories.Count > 0) { AmmoToPullQueue.Add(ammoPullRequests); } else { InventoryMoveRequestPool.Return(ammoPullRequests); } } InvPullClean.Add(weapon); } } catch (Exception e) { Log.Line($"Error in AmmoPull: {e}"); if (weapon != null) { UniqueListRemove(weapon, WeaponToPullAmmoIndexer, WeaponToPullAmmo); } } }