private void CheckAcquire() { for (int i = AcquireTargets.Count - 1; i >= 0; i--) { var w = AcquireTargets[i]; using (w.Comp.MyCube.Pin()) using (w.Comp.Ai?.MyGrid.Pin()) { var comp = w.Comp; if (w.Comp.Ai == null || comp.Ai.MyGrid.MarkedForClose || !comp.Ai.HasPower || comp.Ai.Concealed || comp.MyCube.MarkedForClose || !comp.Ai.DbReady || !w.Set.Enable || !comp.State.Value.Online || !comp.Set.Value.Overrides.Activate) { w.AcquiringTarget = false; AcquireTargets.RemoveAtFast(i); continue; } var gridAi = w.Comp.Ai; var sinceCheck = Tick - w.Target.CheckTick; var seekProjectile = w.ProjectilesNear || w.TrackProjectiles && gridAi.CheckProjectiles; var checkTime = w.Target.TargetChanged || sinceCheck > 239 || sinceCheck > 60 && Count == w.LoadId || seekProjectile; if (checkTime || gridAi.TargetResetTick == Tick && w.Target.HasTarget) { if (seekProjectile || comp.TrackReticle || gridAi.TargetingInfo.TargetInRange && gridAi.TargetingInfo.ValidTargetExists(w)) { if (comp.TrackingWeapon != null && comp.TrackingWeapon.System.DesignatorWeapon && comp.TrackingWeapon != w && comp.TrackingWeapon.Target.HasTarget) { var topMost = comp.TrackingWeapon.Target.Entity?.GetTopMostParent(); GridAi.AcquireTarget(w, false, topMost); } else { GridAi.AcquireTarget(w, gridAi.TargetResetTick == Tick); } } if (w.Target.HasTarget || !gridAi.TargetingInfo.TargetInRange) { w.AcquiringTarget = false; AcquireTargets.RemoveAtFast(i); if (w.Target.HasTarget && MpActive) { w.Target.SyncTarget(comp.WeaponValues.Targets[w.WeaponId], w.WeaponId); if (WeaponsSyncCheck.Add(w)) { WeaponsToSync.Add(w); comp.Ai.NumSyncWeapons++; w.SendTarget = true; if (Tick - w.LastSyncTick > 20) { w.SendSync = true; } w.LastSyncTick = Tick; } } } } } } }
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()) { gridAi.Concealed = ((uint)gridAi.MyGrid.Flags & 4) > 0; 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.State.Value.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; InputStateData inputState; if (PlayerMouseStates.TryGetValue(compCurPlayer.PlayerId, out inputState)) { leftClick = inputState.MouseButtonLeft; // && currentControl; rightClick = inputState.MouseButtonRight; // && currentControl; } else { inputState = PlayerMouseStates[-1]; } /// /// 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; 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 || w.State.ManualShoot == ShootClick)) || 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 (!IsClient && w.IsTurret && !w.TrackTarget && !w.Target.HasTarget && gridAi.TargetingInfo.TargetInRange) { if (w.Target != w.Comp.TrackingWeapon.Target) { w.Target = w.Comp.TrackingWeapon.Target; w.Target.SyncTarget(comp.WeaponValues.Targets[w.WeaponId], w.WeaponId); if (WeaponsSyncCheck.Add(w)) { WeaponsToSync.Add(w); comp.Ai.NumSyncWeapons++; w.SendTarget = true; if (Tick - w.LastSyncTick > 20) { w.SendSync = true; } w.LastSyncTick = Tick; } } } 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); } /// /// Update Weapon Hud Info /// //if (HandlesInput && (w.State.Sync.Heat > 0 || w.State.Sync.Reloading) && HudUi.WeaponsToDisplayCheck.Add(w)) if (HandlesInput && !Session.Config.MinimalHud && ((w.State.Sync.Reloading && Tick - w.LastLoadedTick > 30) || (w.State.Sync.Heat > 0)) && ActiveControlBlock != null && gridAi.SubGrids.Contains(ActiveControlBlock.CubeGrid)) { HudUi.TexturesToAdd++; HudUi.WeaponsToDisplay.Add(w); } /// /// Determine if its time to shoot /// /// w.AiShooting = w.Target.TargetLock && !comp.UserControlled; var reloading = w.ActiveAmmoDef.AmmoDef.Const.Reloadable && (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 && !inputState.InMenu && (j % 2 == 0 && leftClick || j == 1 && rightClick); 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 && gridAi.Focus.HasFocus; if (canShoot && (shoot || w.LockOnFireState)) { if (w.System.DelayCeaseFire && (validShootStates || manualShot || w.FinishBurst)) { w.CeaseFireDelayTick = Tick; } 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) { if (!comp.UnlimitedPower) { 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) { w.StopShooting(); } 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(); } }