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);
        }
Example #2
0
        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);
        }
Example #4
0
        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);
        }
Example #5
0
        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();
            }
        }