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;
        }
Exemple #2
0
        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;
        }
        private void ShootWeapons()
        {
            for (int i = ShootingWeapons.Count - 1; i >= 0; i--)
            {
                var w             = ShootingWeapons[i];
                var invalidWeapon = w.Comp.MyCube.MarkedForClose || w.Comp.Ai == null || w.Comp.Ai.Concealed || w.Comp.Ai.MyGrid.MarkedForClose || w.Comp.Platform.State != CorePlatform.PlatformState.Ready;
                var smartTimer    = !w.AiEnabled && w.ActiveAmmoDef.ConsumableDef.Trajectory.Guidance == WeaponDefinition.ConsumableDef.TrajectoryDef.GuidanceType.Smart && Tick - w.LastSmartLosCheck > 180;
                var quickSkip     = invalidWeapon || smartTimer && !w.SmartLos() || w.PauseShoot;
                if (quickSkip)
                {
                    continue;
                }

                if (!w.Comp.UnlimitedPower)
                {
                    //TODO add logic for power priority
                    if (!w.System.DesignatorWeapon && w.Comp.Ai.OverPowered && (w.ActiveAmmoDef.ConsumableDef.Const.EnergyAmmo || w.ActiveAmmoDef.ConsumableDef.Const.IsHybrid) && !w.ActiveAmmoDef.ConsumableDef.Const.MustCharge)
                    {
                        if (w.ChargeDelayTicks == 0)
                        {
                            var percUseable = w.RequiredPower / w.Comp.Ai.RequestedWeaponsDraw;
                            w.OldUseablePower = w.UseablePower;
                            w.UseablePower    = (w.Comp.Ai.GridMaxPower * .98f) * percUseable;

                            if (w.DrawingPower)
                            {
                                w.DrawPower(true);
                            }
                            else
                            {
                                w.DrawPower();
                            }

                            w.ChargeDelayTicks = (uint)(((w.RequiredPower - w.UseablePower) / w.UseablePower) * MyEngineConstants.UPDATE_STEPS_PER_SECOND);
                            w.ChargeUntilTick  = Tick + w.ChargeDelayTicks;
                            w.Charging         = true;
                        }
                        else if (w.ChargeUntilTick <= Tick)
                        {
                            w.Charging        = false;
                            w.ChargeUntilTick = Tick + w.ChargeDelayTicks;
                        }
                    }
                    else if (!w.ActiveAmmoDef.ConsumableDef.Const.MustCharge && (w.Charging || w.ChargeDelayTicks > 0 || w.ResetPower))
                    {
                        w.OldUseablePower = w.UseablePower;
                        w.UseablePower    = w.RequiredPower;
                        w.DrawPower(true);
                        w.ChargeDelayTicks = 0;
                        w.Charging         = false;
                        w.ResetPower       = false;
                    }

                    if (w.Charging)
                    {
                        continue;
                    }
                }

                w.Shoot();
            }
            ShootingWeapons.Clear();
        }
        private void AiLoop()
        { //Fully Inlined due to keen's mod profiler
            foreach (var ai in GridTargetingAIs.Values)
            {
                ///
                /// GridAi update section
                ///
                ai.MyProjectiles      = 0;
                ai.ProInMinCacheRange = 0;
                ai.AccelChecked       = false;

                if (ai.MarkedForClose || !ai.GridInit || ai.MyGrid == null || ai.Construct.RootAi == null || ai.MyGrid.MarkedForClose)
                {
                    continue;
                }

                ai.Concealed = ((uint)ai.MyGrid.Flags & 4) > 0;
                if (ai.Concealed)
                {
                    continue;
                }

                if (!ai.ScanInProgress && Tick - ai.TargetsUpdatedTick > 100 && DbTask.IsComplete)
                {
                    ai.RequestDbUpdate();
                }

                if (ai.DeadProjectiles.Count > 0)
                {
                    for (int i = 0; i < ai.DeadProjectiles.Count; i++)
                    {
                        ai.LiveProjectile.Remove(ai.DeadProjectiles[i]);
                    }
                    ai.DeadProjectiles.Clear();
                    ai.LiveProjectileTick = Tick;
                }
                var enemyProjectiles = ai.LiveProjectile.Count > 0;
                ai.CheckProjectiles = Tick - ai.NewProjectileTick <= 1;

                if (ai.UpdatePowerSources || !ai.HadPower && ai.MyGrid.IsPowered || ai.HasPower && !ai.MyGrid.IsPowered || Tick10)
                {
                    ai.UpdateGridPower();
                }

                if (!ai.HasPower || Settings.Enforcement.ServerSleepSupport && IsServer && ai.AwakeComps == 0 && ai.WeaponsTracking == 0 && ai.SleepingComps > 0 && !ai.CheckProjectiles && ai.AiSleep && !ai.DbUpdated)
                {
                    continue;
                }

                if (IsServer)
                {
                    if (ai.Construct.RootAi.Construct.NewInventoryDetected)
                    {
                        ai.Construct.RootAi.Construct.CheckForMissingAmmo();
                    }
                    else if (Tick60 && ai.Construct.RootAi.Construct.RecentItems.Count > 0)
                    {
                        ai.Construct.RootAi.Construct.CheckEmptyWeapons();
                    }
                }


                ///
                /// Comp update section
                ///
                for (int i = 0; i < ai.Weapons.Count; i++)
                {
                    var comp = ai.Weapons[i];
                    if (comp.Status != Started)
                    {
                        comp.HealthCheck();
                    }

                    if (ai.DbUpdated || !comp.UpdatedState)
                    {
                        comp.DetectStateChanges();
                    }
                    if (comp.Platform.State != CorePlatform.PlatformState.Ready || comp.IsAsleep || !comp.IsWorking || comp.MyCube.MarkedForClose || comp.IsDisabled)
                    {
                        continue;
                    }

                    if (IsServer && comp.Data.Repo.Base.State.PlayerId > 0 && !ai.Data.Repo.ControllingPlayers.ContainsKey(comp.Data.Repo.Base.State.PlayerId))
                    {
                        comp.ResetPlayerControl();
                    }

                    if (HandlesInput)
                    {
                        var wasTrack = comp.Data.Repo.Base.State.TrackingReticle;

                        var isControllingPlayer = comp.Data.Repo.Base.State.PlayerId == PlayerId;
                        var track = (isControllingPlayer && (comp.Data.Repo.Base.Set.Overrides.Control != GroupOverrides.ControlModes.Auto) && TargetUi.DrawReticle && !InMenu && comp.Ai.Construct.RootAi.Data.Repo.ControllingPlayers.ContainsKey(PlayerId));
                        if (IsServer)
                        {
                            comp.Data.Repo.Base.State.TrackingReticle = track;
                        }

                        if (MpActive && track != wasTrack)
                        {
                            comp.Session.SendTrackReticleUpdate(comp, track);
                        }
                    }

                    var trackReticle = comp.Data.Repo.Base.State.TrackingReticle;
                    comp.WasControlled  = comp.UserControlled;
                    comp.UserControlled = comp.Data.Repo.Base.State.Control != ControlMode.None;

                    if (!PlayerMouseStates.TryGetValue(comp.Data.Repo.Base.State.PlayerId, out comp.InputState))
                    {
                        comp.InputState = DefaultInputStateData;
                    }
                    var compManualMode = comp.Data.Repo.Base.State.Control == ControlMode.Camera || (comp.Data.Repo.Base.Set.Overrides.Control == GroupOverrides.ControlModes.Manual && trackReticle);
                    var canManualShoot = !ai.SuppressMouseShoot && !comp.InputState.InMenu;
                    ///
                    /// Weapon update section
                    ///
                    for (int j = 0; j < comp.Platform.Weapons.Length; j++)
                    {
                        var w = comp.Platform.Weapons[j];
                        if (w.WeaponReadyTick > Tick)
                        {
                            if (w.Target.HasTarget && !IsClient)
                            {
                                w.Target.Reset(comp.Session.Tick, States.WeaponNotReady);
                            }
                            continue;
                        }

                        if (w.AvCapable && Tick20)
                        {
                            var    avWasEnabled = w.PlayTurretAv;
                            double distSqr;
                            Vector3D.DistanceSquared(ref CameraPos, ref w.MyPivotPos, out distSqr);
                            w.PlayTurretAv = distSqr < w.System.HardPointAvMaxDistSqr;
                            if (avWasEnabled != w.PlayTurretAv)
                            {
                                w.StopBarrelAvTick = Tick;
                            }
                        }

                        if (!ai.HadPower && w.ActiveAmmoDef.ConsumableDef.Const.MustCharge && w.State.Action != ShootOff)
                        {
                            if (IsServer)
                            {
                                w.State.WeaponMode(comp, ShootOff);
                                w.Ammo.CurrentAmmo = 0;
                            }

                            w.Reloading   = false;
                            w.FinishBurst = false;

                            if (w.IsShooting)
                            {
                                w.StopShooting();
                            }
                        }

                        ///
                        ///Check Reload
                        ///

                        if (w.ActiveAmmoDef.ConsumableDef.Const.Reloadable && !w.System.DesignatorWeapon && !w.Reloading)
                        {
                            if (IsServer && (w.Ammo.CurrentAmmo == 0 || w.CheckInventorySystem))
                            {
                                w.ComputeServerStorage();
                            }
                            else if (IsClient)
                            {
                                if (w.ClientReloading && w.Reload.EndId > w.ClientEndId && w.Reload.StartId == w.ClientStartId)
                                {
                                    w.Reloaded();
                                }
                                else
                                {
                                    w.ClientReload();
                                }
                            }
                        }


                        ///
                        /// Update Weapon Hud Info
                        ///
                        var isWaitingForBurstDelay = w.ShowBurstDelayAsReload && !w.Reloading && w.ShootTick > Tick && w.ShootTick >= w.LastShootTick + w.System.Values.HardPoint.Loading.DelayAfterBurst;
                        if (HandlesInput && (w.Reloading || w.HeatPerc >= 0.01 || isWaitingForBurstDelay) && Tick - w.LastLoadedTick > 30 && !Session.Config.MinimalHud && ActiveControlBlock != null && ai.SubGrids.Contains(ActiveControlBlock.CubeGrid))
                        {
                            HudUi.TexturesToAdd++;
                            HudUi.WeaponsToDisplay.Add(w);
                        }

                        if (w.System.Armor != ArmorState.IsWeapon)
                        {
                            continue;
                        }

                        if (w.Target.ClientDirty)
                        {
                            w.Target.ClientUpdate(w, w.TargetData);
                        }

                        ///
                        /// Check target for expire states
                        ///
                        bool targetLock = false;
                        var  noAmmo     = w.NoMagsToLoad && w.Ammo.CurrentAmmo == 0 && w.ActiveAmmoDef.ConsumableDef.Const.Reloadable && !w.System.DesignatorWeapon && Tick - w.LastMagSeenTick > 600;
                        if (w.Target.HasTarget)
                        {
                            if (w.PosChangedTick != Tick)
                            {
                                w.UpdatePivotPos();
                            }
                            if (!IsClient && noAmmo)
                            {
                                w.Target.Reset(Tick, States.Expired);
                            }
                            else if (!IsClient && w.Target.Entity == null && w.Target.Projectile == null && (!trackReticle || Tick - PlayerDummyTargets[comp.Data.Repo.Base.State.PlayerId].LastUpdateTick > 120))
                            {
                                w.Target.Reset(Tick, States.Expired, !trackReticle);
                            }
                            else if (!IsClient && w.Target.Entity != null && (comp.UserControlled && !w.System.SuppressFire || w.Target.Entity.MarkedForClose))
                            {
                                w.Target.Reset(Tick, States.Expired);
                            }
                            else if (!IsClient && w.Target.Projectile != null && (!ai.LiveProjectile.Contains(w.Target.Projectile) || w.Target.IsProjectile && w.Target.Projectile.State != Projectile.ProjectileState.Alive))
                            {
                                w.Target.Reset(Tick, States.Expired);
                            }
                            else if (w.AiEnabled)
                            {
                                if (!Weapon.TrackingTarget(w, w.Target, out targetLock) && !IsClient && w.Target.ExpiredTick != Tick)
                                {
                                    w.Target.Reset(Tick, States.LostTracking, !trackReticle && (w.Target.CurrentState != States.RayCheckFailed && !w.Target.HasTarget));
                                }
                            }
                            else
                            {
                                Vector3D targetPos;
                                if (w.IsTurret)
                                {
                                    if (!w.TrackTarget && !IsClient)
                                    {
                                        if ((comp.TrackingWeapon.Target.Projectile != w.Target.Projectile || w.Target.IsProjectile && w.Target.Projectile.State != Projectile.ProjectileState.Alive || comp.TrackingWeapon.Target.Entity != w.Target.Entity || comp.TrackingWeapon.Target.IsFakeTarget != w.Target.IsFakeTarget))
                                        {
                                            w.Target.Reset(Tick, States.Expired);
                                        }
                                        else
                                        {
                                            targetLock = true;
                                        }
                                    }
                                    else if (!Weapon.TargetAligned(w, w.Target, out targetPos) && !IsClient)
                                    {
                                        w.Target.Reset(Tick, States.Expired);
                                    }
                                }
                                else if (w.TrackTarget && !Weapon.TargetAligned(w, w.Target, out targetPos) && !IsClient)
                                {
                                    w.Target.Reset(Tick, States.Expired);
                                }
                            }
                        }

                        w.ProjectilesNear = enemyProjectiles && w.System.TrackProjectile && w.Comp.Data.Repo.Base.Set.Overrides.Projectiles && !w.Target.HasTarget && (w.Target.TargetChanged || SCount == w.ShortLoadId);

                        if (comp.Data.Repo.Base.State.Control == ControlMode.Camera && UiInput.MouseButtonPressed)
                        {
                            w.Target.TargetPos = Vector3D.Zero;
                        }

                        ///
                        /// Queue for target acquire or set to tracking weapon.
                        ///
                        var seek = trackReticle && !w.Target.IsFakeTarget || (!noAmmo && !w.Target.HasTarget && w.TrackTarget && (comp.TargetNonThreats && ai.TargetingInfo.OtherInRange || ai.TargetingInfo.ThreatInRange) && (!comp.UserControlled || w.State.Action == ShootClick));
                        if (!IsClient && (seek || w.TrackTarget && ai.TargetResetTick == Tick && !comp.UserControlled) && !w.AcquiringTarget && (comp.Data.Repo.Base.State.Control == ControlMode.None || comp.Data.Repo.Base.State.Control == ControlMode.Ui))
                        {
                            w.AcquiringTarget = true;
                            AcquireTargets.Add(w);
                        }

                        if (w.Target.TargetChanged) // Target changed
                        {
                            w.TargetChanged();
                        }

                        ///
                        /// Check weapon's turret to see if its time to go home
                        ///

                        if (w.TurretMode && !w.IsHome && !w.ReturingHome && !w.Target.HasTarget && Tick - w.Target.ResetTick > 239 && !comp.UserControlled && w.State.Action == ShootOff)
                        {
                            w.ScheduleWeaponHome();
                        }

                        ///
                        /// Determine if its time to shoot
                        ///
                        ///
                        w.AiShooting = targetLock && !comp.UserControlled && !w.System.SuppressFire;
                        var reloading        = w.ActiveAmmoDef.ConsumableDef.Const.Reloadable && w.ClientMakeUpShots == 0 && (w.Reloading || w.Ammo.CurrentAmmo == 0);
                        var canShoot         = !w.State.Overheated && !reloading && !w.System.DesignatorWeapon && (!w.LastEventCanDelay || w.AnimationDelayTick <= Tick || w.ClientMakeUpShots > 0);
                        var fakeTarget       = comp.Data.Repo.Base.Set.Overrides.Control == GroupOverrides.ControlModes.Painter && trackReticle && w.Target.IsFakeTarget && w.Target.IsAligned;
                        var validShootStates = fakeTarget || w.State.Action == ShootOn || w.AiShooting && w.State.Action == ShootOff;
                        var manualShot       = (compManualMode || w.State.Action == ShootClick) && canManualShoot && comp.InputState.MouseButtonLeft;
                        var delayedFire      = w.System.DelayCeaseFire && !w.Target.IsAligned && Tick - w.CeaseFireDelayTick <= w.System.CeaseFireDelay;
                        var shoot            = (validShootStates || manualShot || w.FinishBurst || delayedFire);
                        w.LockOnFireState = !shoot && w.System.LockOnFocus && ai.Construct.Data.Repo.FocusData.HasFocus && ai.Construct.Focus.FocusInRange(w);
                        var shotReady = canShoot && (shoot || w.LockOnFireState);

                        if ((shotReady || w.ShootOnce) && ai.CanShoot)
                        {
                            if (w.ShootOnce && IsServer && (shotReady || w.State.Action != ShootOnce))
                            {
                                w.ShootOnce = false;
                            }

                            if (MpActive && HandlesInput && !ManualShot)
                            {
                                ManualShot = !validShootStates && !w.FinishBurst && !delayedFire;
                            }

                            if (w.System.DelayCeaseFire && (validShootStates || manualShot || w.FinishBurst))
                            {
                                w.CeaseFireDelayTick = Tick;
                            }

                            if ((ai.AvailablePowerChanged || ai.RequestedPowerChanged || (w.RecalcPower && Tick60)) && !w.ActiveAmmoDef.ConsumableDef.Const.MustCharge)
                            {
                                if ((!ai.RequestIncrease || ai.PowerIncrease) && !Tick60)
                                {
                                    w.RecalcPower = true;
                                }
                                else
                                {
                                    w.RecalcPower      = false;
                                    w.ChargeDelayTicks = 0;
                                }
                            }
                            if (w.ChargeDelayTicks == 0 || w.ChargeUntilTick <= Tick)
                            {
                                if (!w.RequestedPower && !w.ActiveAmmoDef.ConsumableDef.Const.MustCharge && !w.System.DesignatorWeapon)
                                {
                                    if (!comp.UnlimitedPower)
                                    {
                                        ai.RequestedWeaponsDraw += w.RequiredPower;
                                    }
                                    w.RequestedPower = true;
                                }

                                ShootingWeapons.Add(w);
                            }
                            else if (w.ChargeUntilTick > Tick && !w.ActiveAmmoDef.ConsumableDef.Const.MustCharge)
                            {
                                w.Charging = true;
                                w.StopShooting(false);
                            }
                        }
                        else if (w.IsShooting)
                        {
                            w.StopShooting();
                        }
                        else if (w.BarrelSpinning)
                        {
                            w.SpinBarrel(true);
                        }

                        if (comp.Debug && !DedicatedServer)
                        {
                            WeaponDebug(w);
                        }
                    }
                }
                ai.OverPowered = ai.RequestedWeaponsDraw > 0 && ai.RequestedWeaponsDraw > ai.GridMaxPower;
                ai.DbUpdated   = false;
            }

            if (DbTask.IsComplete && DbsToUpdate.Count > 0 && !DbUpdating)
            {
                UpdateDbsInQueue();
            }
        }
        private void ShootWeapons()
        {
            for (int i = ShootingWeapons.Count - 1; i >= 0; i--)
            {
                var w = ShootingWeapons[i];
                using (w.Comp.MyCube.Pin())
                    using (w.Comp.Ai?.MyGrid.Pin())
                    {
                        if (w.Comp.MyCube.MarkedForClose || w.Comp.Ai == null || w.Comp.Ai.Concealed || w.Comp.Ai.MyGrid.MarkedForClose || w.Comp.Platform.State != MyWeaponPlatform.PlatformState.Ready)
                        {
                            ShootingWeapons.RemoveAtFast(i);
                            continue;
                        }
                        //TODO add logic for power priority
                        if (!w.System.DesignatorWeapon && w.Comp.Ai.OverPowered && (w.ActiveAmmoDef.AmmoDef.Const.EnergyAmmo || w.ActiveAmmoDef.AmmoDef.Const.IsHybrid) && !w.ActiveAmmoDef.AmmoDef.Const.MustCharge)
                        {
                            if (w.Timings.ChargeDelayTicks == 0)
                            {
                                var percUseable = w.RequiredPower / w.Comp.Ai.RequestedWeaponsDraw;
                                w.OldUseablePower = w.UseablePower;
                                w.UseablePower    = (w.Comp.Ai.GridMaxPower * .98f) * percUseable;

                                if (w.DrawingPower)
                                {
                                    w.DrawPower(true);
                                }
                                else
                                {
                                    w.DrawPower();
                                }

                                w.Timings.ChargeDelayTicks = (uint)(((w.RequiredPower - w.UseablePower) / w.UseablePower) * MyEngineConstants.UPDATE_STEPS_PER_SECOND);
                                w.Timings.ChargeUntilTick  = Tick + w.Timings.ChargeDelayTicks;
                                w.State.Sync.Charging      = true;
                            }
                            else if (w.Timings.ChargeUntilTick <= Tick)
                            {
                                w.State.Sync.Charging     = false;
                                w.Timings.ChargeUntilTick = Tick + w.Timings.ChargeDelayTicks;
                            }
                        }
                        else if (!w.ActiveAmmoDef.AmmoDef.Const.MustCharge && (w.State.Sync.Charging || w.Timings.ChargeDelayTicks > 0 || w.ResetPower))
                        {
                            w.OldUseablePower = w.UseablePower;
                            w.UseablePower    = w.RequiredPower;
                            w.DrawPower(true);
                            w.Timings.ChargeDelayTicks = 0;
                            w.State.Sync.Charging      = false;
                            w.ResetPower = false;
                        }

                        if (w.State.Sync.Charging)
                        {
                            continue;
                        }

                        if (w.Timings.ShootDelayTick <= Tick)
                        {
                            w.Shoot();
                        }
                    }
            }
            ShootingWeapons.Clear();
        }
        private void AiLoop()
        { //Fully Inlined due to keen's mod profiler
            foreach (var aiPair in GridTargetingAIs)
            {
                ///
                /// GridAi update section
                ///
                var gridAi = aiPair.Value;

                using (gridAi.MyGrid.Pin())
                {
                    if (!gridAi.GridInit || gridAi.MyGrid.MarkedForClose || gridAi.Concealed)
                    {
                        continue;
                    }

                    var readyToUpdate = Tick - gridAi.TargetsUpdatedTick > 100 && DbCallBackComplete && DbTask.IsComplete;

                    if (readyToUpdate && gridAi.UpdateOwner())
                    {
                        gridAi.RequestDbUpdate();
                    }

                    if (gridAi.DeadProjectiles.Count > 0)
                    {
                        for (int i = 0; i < gridAi.DeadProjectiles.Count; i++)
                        {
                            gridAi.LiveProjectile.Remove(gridAi.DeadProjectiles[i]);
                        }
                        gridAi.DeadProjectiles.Clear();
                        gridAi.LiveProjectileTick = Tick;
                    }
                    gridAi.CheckProjectiles = Tick - gridAi.NewProjectileTick <= 1;

                    if (!gridAi.HasPower && gridAi.HadPower || gridAi.UpdatePowerSources || !gridAi.WasPowered && gridAi.MyGrid.IsPowered || Tick10)
                    {
                        gridAi.UpdateGridPower();
                    }

                    if (!gridAi.HasPower)
                    {
                        continue;
                    }

                    ///
                    /// Comp update section
                    ///
                    for (int i = 0; i < gridAi.Weapons.Count; i++)
                    {
                        var comp = gridAi.Weapons[i];
                        using (comp.MyCube.Pin())
                        {
                            if (comp.MyCube.MarkedForClose || comp.Platform.State != MyWeaponPlatform.PlatformState.Ready)
                            {
                                continue;
                            }

                            if (!comp.State.Value.Online || !comp.Set.Value.Overrides.Activate || comp.Status != Started)
                            {
                                if (comp.Status != Started)
                                {
                                    comp.HealthCheck();
                                }
                                continue;
                            }

                            if (InMenu && Tick20 && gridAi.LastTerminal == comp.MyCube)
                            {
                                comp.TerminalRefresh();
                            }

                            var overRides     = comp.Set.Value.Overrides;
                            var compCurPlayer = comp.State.Value.CurrentPlayerControl;

                            if (HandlesInput)
                            {
                                comp.WasTrackReticle = comp.TrackReticle;
                                var isControllingPlayer = comp.State.Value.CurrentPlayerControl.PlayerId == PlayerId;

                                comp.TrackReticle = comp.OtherPlayerTrackingReticle || (isControllingPlayer && (overRides.TargetPainter || overRides.ManualControl) && TargetUi.DrawReticle && !InMenu && comp.Ai.ControllingPlayers.ContainsKey(PlayerId));

                                if (MpActive && isControllingPlayer && comp.TrackReticle != comp.WasTrackReticle)
                                {
                                    comp.Session.SendTrackReticleUpdate(comp);
                                }
                            }

                            comp.WasControlled  = comp.UserControlled;
                            comp.UserControlled = compCurPlayer.ControlType != ControlType.None;

                            var leftClick  = false;
                            var rightClick = false;

                            MouseStateData mouseState;
                            if (PlayerMouseStates.TryGetValue(compCurPlayer.PlayerId, out mouseState))
                            {
                                leftClick  = mouseState.MouseButtonLeft;  // && currentControl;
                                rightClick = mouseState.MouseButtonRight; // && currentControl;
                            }

                            ///
                            /// Weapon update section
                            ///
                            for (int j = 0; j < comp.Platform.Weapons.Length; j++)
                            {
                                var w = comp.Platform.Weapons[j];
                                if (!w.Set.Enable)
                                {
                                    if (w.Target.HasTarget && !IsClient)
                                    {
                                        w.Target.Reset(comp.Session.Tick, States.Expired);
                                    }
                                    continue;
                                }

                                if (w.Timings.WeaponReadyTick > Tick)
                                {
                                    continue;
                                }

                                if (w.AvCapable && (!w.PlayTurretAv || Tick60))
                                {
                                    var avWasEnabled = w.PlayTurretAv;
                                    w.PlayTurretAv = Vector3D.DistanceSquared(CameraPos, w.MyPivotPos) < w.System.HardPointAvMaxDistSqr;
                                    if (avWasEnabled != w.PlayTurretAv)
                                    {
                                        w.StopBarrelAv = !w.PlayTurretAv;
                                    }
                                }

                                ///
                                /// Check target for expire states
                                ///

                                if (w.Target.HasTarget && !(IsClient && w.Target.CurrentState == States.Invalid))
                                {
                                    if (w.PosChangedTick != Tick)
                                    {
                                        w.UpdatePivotPos();
                                    }

                                    if (!IsClient && w.Target.Entity == null && w.Target.Projectile == null && (!comp.TrackReticle || gridAi.DummyTarget.ClearTarget))
                                    {
                                        w.Target.Reset(Tick, States.Expired, !comp.TrackReticle);
                                    }
                                    else if (!IsClient && w.Target.Entity != null && (comp.UserControlled || w.Target.Entity.MarkedForClose))
                                    {
                                        w.Target.Reset(Tick, States.Expired);
                                    }
                                    else if (!IsClient && w.Target.Projectile != null && (!gridAi.LiveProjectile.Contains(w.Target.Projectile) || w.Target.IsProjectile && w.Target.Projectile.State != Projectile.ProjectileState.Alive))
                                    {
                                        w.Target.Reset(Tick, States.Expired);
                                    }
                                    else if (w.AiEnabled)
                                    {
                                        if (!Weapon.TrackingTarget(w, w.Target) && !IsClient)
                                        {
                                            w.Target.Reset(Tick, States.Expired, !comp.TrackReticle);
                                        }
                                    }
                                    else
                                    {
                                        Vector3D targetPos;
                                        if (w.IsTurret)
                                        {
                                            if (!w.TrackTarget && !IsClient)
                                            {
                                                if ((comp.TrackingWeapon.Target.Projectile != w.Target.Projectile || w.Target.IsProjectile && w.Target.Projectile.State != Projectile.ProjectileState.Alive || comp.TrackingWeapon.Target.Entity != w.Target.Entity || comp.TrackingWeapon.Target.IsFakeTarget != w.Target.IsFakeTarget))
                                                {
                                                    w.Target.Reset(Tick, States.Expired);
                                                }
                                            }
                                            else if (!Weapon.TargetAligned(w, w.Target, out targetPos) && !IsClient)
                                            {
                                                w.Target.Reset(Tick, States.Expired);
                                            }
                                        }
                                        else if (w.TrackTarget && !Weapon.TargetAligned(w, w.Target, out targetPos) && !IsClient)
                                        {
                                            w.Target.Reset(Tick, States.Expired);
                                        }
                                    }
                                }
                                else if (w.Target.HasTarget && MyEntities.EntityExists(comp.WeaponValues.Targets[w.WeaponId].EntityId))
                                {
                                    w.Target.HasTarget = false;
                                    comp.Session.ClientGridResyncRequests.Add(comp);
                                }

                                w.ProjectilesNear = w.TrackProjectiles && !w.Target.HasTarget && (w.Target.TargetChanged || SCount == w.ShortLoadId && gridAi.LiveProjectile.Count > 0);

                                if (compCurPlayer.ControlType == ControlType.Camera && UiInput.MouseButtonPressed)
                                {
                                    w.Target.TargetPos = Vector3D.Zero;
                                }

                                ///
                                /// Queue for target acquire or set to tracking weapon.
                                ///
                                w.SeekTarget = (!IsClient && !w.Target.HasTarget && w.TrackTarget && gridAi.TargetingInfo.TargetInRange && !comp.UserControlled) || comp.TrackReticle && !w.Target.IsFakeTarget;
                                if (!IsClient && (w.SeekTarget || w.TrackTarget && gridAi.TargetResetTick == Tick && !comp.UserControlled) && !w.AcquiringTarget && (compCurPlayer.ControlType == ControlType.None || compCurPlayer.ControlType == ControlType.Ui))
                                {
                                    w.AcquiringTarget = true;
                                    AcquireTargets.Add(w);
                                }
                                else if (w.IsTurret && !w.TrackTarget && !w.Target.HasTarget && gridAi.TargetingInfo.TargetInRange)
                                {
                                    w.Target = w.Comp.TrackingWeapon.Target;
                                }

                                if (w.Target.TargetChanged) // Target changed
                                {
                                    w.TargetChanged();
                                }

                                ///
                                /// Check weapon's turret to see if its time to go home
                                ///

                                if (w.TurretMode && (!w.Target.HasTarget && !w.ReturingHome && !w.IsHome && Tick - w.Target.ExpiredTick > 300) || comp.UserControlled != comp.WasControlled && !comp.UserControlled)
                                {
                                    w.TurretHomePosition(comp.WasControlled);
                                }

                                ///
                                /// Determine if its time to shoot
                                ///
                                ///
                                w.AiShooting = (w.Target.TargetLock || w.System.DelayCeaseFire && !w.Target.IsAligned && Tick - w.CeaseFireDelayTick <= w.System.CeaseFireDelay) && !comp.UserControlled;
                                var reloading        = (!w.ActiveAmmoDef.AmmoDef.Const.EnergyAmmo || w.ActiveAmmoDef.AmmoDef.Const.MustCharge) && (w.State.Sync.Reloading || w.OutOfAmmo);
                                var canShoot         = !w.State.Sync.Overheated && !reloading;
                                var fakeTarget       = overRides.TargetPainter && comp.TrackReticle && w.Target.IsFakeTarget && w.Target.IsAligned;
                                var validShootStates = fakeTarget || w.State.ManualShoot == ShootOn || w.State.ManualShoot == ShootOnce || w.AiShooting && w.State.ManualShoot == ShootOff;
                                var manualShot       = (compCurPlayer.ControlType == ControlType.Camera || (overRides.ManualControl && comp.TrackReticle) || w.State.ManualShoot == ShootClick) && !gridAi.SupressMouseShoot && (j % 2 == 0 && leftClick || j == 1 && rightClick);
                                var shoot            = (validShootStates || manualShot || w.FinishBurst);

                                w.LockOnFireState = !shoot && w.System.LockOnFocus && gridAi.Focus.HasFocus;

                                if (canShoot && (shoot || w.LockOnFireState))
                                {
                                    if ((gridAi.AvailablePowerChanged || gridAi.RequestedPowerChanged || (w.RecalcPower && Tick60)) && !w.ActiveAmmoDef.AmmoDef.Const.MustCharge)
                                    {
                                        if ((!gridAi.RequestIncrease || gridAi.PowerIncrease) && !Tick60)
                                        {
                                            w.RecalcPower = true;
                                        }
                                        else
                                        {
                                            w.RecalcPower = false;
                                            w.Timings.ChargeDelayTicks = 0;
                                        }
                                    }

                                    if (w.Timings.ChargeDelayTicks == 0 || w.Timings.ChargeUntilTick <= Tick)
                                    {
                                        if (!w.RequestedPower && !w.ActiveAmmoDef.AmmoDef.Const.MustCharge && !w.System.DesignatorWeapon)
                                        {
                                            gridAi.RequestedWeaponsDraw += w.RequiredPower;
                                            w.RequestedPower             = true;
                                        }

                                        ShootingWeapons.Add(w);
                                    }
                                    else if (w.Timings.ChargeUntilTick > Tick && !w.ActiveAmmoDef.AmmoDef.Const.MustCharge)
                                    {
                                        w.State.Sync.Charging = true;
                                        w.StopShooting(false, false);
                                    }
                                }
                                else if (w.IsShooting)
                                {
                                    if (!w.System.DelayCeaseFire || !w.Target.IsAligned && Tick - w.CeaseFireDelayTick > w.System.CeaseFireDelay)
                                    {
                                        w.StopShooting();
                                    }
                                    else if (w.System.DelayCeaseFire && w.Target.IsAligned)
                                    {
                                        w.CeaseFireDelayTick = Tick;
                                    }
                                }
                                else if (w.BarrelSpinning)
                                {
                                    w.SpinBarrel(true);
                                }

                                if (comp.Debug && !DedicatedServer)
                                {
                                    WeaponDebug(w);
                                }
                            }
                        }
                    }

                    gridAi.OverPowered = gridAi.RequestedWeaponsDraw > 0 && gridAi.RequestedWeaponsDraw > gridAi.GridMaxPower;
                }
            }

            if (DbCallBackComplete && DbsToUpdate.Count > 0 && DbTask.IsComplete)
            {
                UpdateDbsInQueue();
            }
        }