private bool ClientFakeTargetUpdate(PacketObj data) { var packet = data.Packet; data.ErrorPacket.NoReprocess = true; var targetPacket = (FakeTargetPacket)packet; var myGrid = MyEntities.GetEntityByIdOrDefault(packet.EntityId) as MyCubeGrid; GridAi ai; if (myGrid != null && GridTargetingAIs.TryGetValue(myGrid, out ai)) { if (ai.MIds[(int)packet.PType] < packet.MId) { ai.MIds[(int)packet.PType] = packet.MId; long playerId; if (SteamToPlayer.TryGetValue(packet.SenderId, out playerId)) { FakeTarget dummyTarget; if (PlayerDummyTargets.TryGetValue(playerId, out dummyTarget)) { dummyTarget.Update(targetPacket.Pos, ai, null, targetPacket.TargetId); } else { return(Error(data, Msg("Player dummy target not found"))); } } else { return(Error(data, Msg("SteamToPlayer missing Player"))); } } else { Log.Line($"ClientFakeTargetUpdate: mid fail - senderId:{packet.SenderId} - mId:{ai.MIds[(int)packet.PType]} >= {packet.MId}"); } data.Report.PacketValid = true; } else { return(Error(data, Msg($"GridId: {packet.EntityId}", myGrid != null), Msg("Ai"))); } return(true); }
public override void HandleInput() { if (HandlesInput && !SuppressWc) { if (ControlRequest != ControlQuery.None) { UpdateControlKeys(); } UiInput.UpdateInputState(); if (MpActive) { if (UiInput.InputChanged && ActiveControlBlock != null) { SendMouseUpdate(TrackingAi, ActiveControlBlock); } GridAi.FakeTargets fakeTargets; if (TrackingAi != null && TargetUi.DrawReticle && PlayerDummyTargets.TryGetValue(PlayerId, out fakeTargets)) { if (fakeTargets.ManualTarget.LastUpdateTick == Tick) { SendAimTargetUpdate(TrackingAi, fakeTargets.ManualTarget); } if (fakeTargets.PaintedTarget.LastUpdateTick == Tick) { SendPaintedTargetUpdate(TrackingAi, fakeTargets.PaintedTarget); } } if (PacketsToServer.Count > 0) { ProccessClientPacketsForServer(); } } if (Tick60 && SoundsToClean.Count > 0) { CleanSounds(); } } }
private bool ClientFakeTargetUpdate(PacketObj data) { var packet = data.Packet; data.ErrorPacket.NoReprocess = true; var targetPacket = (FakeTargetPacket)packet; var myGrid = MyEntities.GetEntityByIdOrDefault(packet.EntityId) as MyCubeGrid; GridAi ai; if (myGrid != null && GridTargetingAIs.TryGetValue(myGrid, out ai)) { long playerId; if (SteamToPlayer.TryGetValue(packet.SenderId, out playerId)) { FakeTargets dummyTargets; if (PlayerDummyTargets.TryGetValue(playerId, out dummyTargets)) { dummyTargets.ManualTarget.Sync(targetPacket, ai); dummyTargets.PaintedTarget.Sync(targetPacket, ai); } else { return(Error(data, Msg("Player dummy target not found"))); } } else { return(Error(data, Msg("SteamToPlayer missing Player"))); } data.Report.PacketValid = true; } else { return(Error(data, Msg($"GridId: {packet.EntityId}", myGrid != null), Msg("Ai"))); } return(true); }
private bool ServerMarkedTargetUpdate(PacketObj data) { var packet = data.Packet; var targetPacket = (FakeTargetPacket)packet; var myGrid = MyEntities.GetEntityByIdOrDefault(packet.EntityId) as MyCubeGrid; if (myGrid == null) { return(Error(data, Msg($"GridId:{packet.EntityId} - entityExists:{MyEntities.EntityExists(packet.EntityId)}"))); } GridAi ai; long playerId; if (GridTargetingAIs.TryGetValue(myGrid, out ai) && SteamToPlayer.TryGetValue(packet.SenderId, out playerId)) { GridAi.FakeTargets fakeTargets; uint[] mIds; if (PlayerMIds.TryGetValue(packet.SenderId, out mIds) && mIds[(int)packet.PType] < packet.MId && PlayerDummyTargets.TryGetValue(playerId, out fakeTargets)) { mIds[(int)packet.PType] = packet.MId; fakeTargets.PaintedTarget.Sync(targetPacket, ai); PacketsToClient.Add(new PacketInfo { Entity = myGrid, Packet = targetPacket }); data.Report.PacketValid = true; } else { Log.Line($"ServerFakeTargetUpdate: MidsHasSenderId:{PlayerMIds.ContainsKey(packet.SenderId)} - midsNull:{mIds == null} - senderId:{packet.SenderId}"); } } else { return(Error(data, Msg($"GridAi not found, is marked:{myGrid.MarkedForClose}, has root:{GridToMasterAi.ContainsKey(myGrid)}"))); } return(true); }
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 (IsServer && comp.Data.Repo.Base.State.PlayerId > 0 && !ai.Data.Repo.ControllingPlayers.ContainsKey(comp.Data.Repo.Base.State.PlayerId)) { comp.ResetPlayerControl(); } if (comp.Platform.State != MyWeaponPlatform.PlatformState.Ready || comp.IsAsleep || !comp.IsWorking || comp.MyCube.MarkedForClose || comp.IsDisabled) { continue; } 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.Manual && TargetUi.DrawReticle && !InMenu && comp.Ai.Construct.RootAi.Data.Repo.ControllingPlayers.ContainsKey(PlayerId) && (!UiInput.CameraBlockView && comp.Data.Repo.Base.Set.Overrides.CameraChannel == 0 || UiInput.CameraChannelId > 0 && UiInput.CameraChannelId == comp.Data.Repo.Base.Set.Overrides.CameraChannel)); if (!MpActive && IsServer) { comp.Data.Repo.Base.State.TrackingReticle = track; } var needsUpdate = MpActive && track != wasTrack && (comp.Data.Repo.Base.State.PlayerId <= 0 || isControllingPlayer); if (needsUpdate) { comp.Session.SendTrackReticleUpdate(comp, track); } } comp.ManualMode = comp.Data.Repo.Base.State.TrackingReticle && comp.Data.Repo.Base.Set.Overrides.Control == GroupOverrides.ControlModes.Manual; GridAi.FakeTargets fakeTargets = null; if (comp.ManualMode || comp.Data.Repo.Base.Set.Overrides.Control == GroupOverrides.ControlModes.Painter) { PlayerDummyTargets.TryGetValue(comp.Data.Repo.Base.State.PlayerId, out fakeTargets); } comp.PainterMode = comp.Data.Repo.Base.Set.Overrides.Control == GroupOverrides.ControlModes.Painter && fakeTargets?.PaintedTarget.EntityId != 0 && !fakeTargets.PaintedTarget.Dirty; comp.FakeMode = comp.ManualMode || comp.PainterMode; 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.ManualMode; 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.AmmoDef.Const.MustCharge && w.State.Action != ShootOff) { w.LostPowerIsThisEverUsed(); } /// ///Check Reload /// if (w.ActiveAmmoDef.AmmoDef.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 addWeaponToHud = HandlesInput && (w.HeatPerc >= 0.01 || w.Reloading && (w.System.ReloadTime >= 240 || w.ShowBurstDelayAsReload && Tick - w.ReloadEndTick > 0 && w.System.Values.HardPoint.Loading.DelayAfterBurst >= 240)); if (addWeaponToHud && !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.AmmoDef.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 && !comp.FakeMode || comp.ManualMode && Tick - fakeTargets?.ManualTarget.LastUpdateTick > 120) { w.Target.Reset(Tick, States.Expired, !comp.ManualMode); } 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); w.FastTargetResetTick = Tick + 6; } else if (w.AiEnabled) { if (!Weapon.TrackingTarget(w, w.Target, out targetLock) && !IsClient && w.Target.ExpiredTick != Tick) { w.Target.Reset(Tick, States.LostTracking, !comp.ManualMode && (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 || QCount == 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 = comp.FakeMode && !w.Target.IsFakeTarget || (!noAmmo && !w.Target.HasTarget && w.TrackTarget && (comp.TargetNonThreats && ai.TargetingInfo.OtherInRange || ai.TargetingInfo.ThreatInRange) && (!comp.UserControlled && !Settings.Enforcement.DisableAi || w.State.Action == ShootClick)); if (!IsClient && (seek || w.TrackTarget && ai.TargetResetTick == Tick && !comp.UserControlled && !Settings.Enforcement.DisableAi) && !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.AmmoDef.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 paintedTarget = comp.PainterMode && w.Target.IsFakeTarget && w.Target.IsAligned; var validShootStates = paintedTarget || 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.AmmoDef.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.AmmoDef.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.AmmoDef.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(); } }