Пример #1
0
        internal void AddProjectileTargets() // This calls AI late for fragments need to fix
        {
            for (int i = 0; i < AddTargets.Count; i++)
            {
                var p = AddTargets[i];
                for (int t = 0; t < p.Info.Ai.TargetAis.Count; t++)
                {
                    var targetAi      = p.Info.Ai.TargetAis[t];
                    var addProjectile = p.Info.AmmoDef.Trajectory.Guidance != GuidanceType.None && targetAi.PointDefense;
                    if (!addProjectile && targetAi.PointDefense)
                    {
                        if (Vector3.Dot(p.Info.Direction, p.Info.Origin - targetAi.MyGrid.PositionComp.WorldMatrixRef.Translation) < 0)
                        {
                            var targetSphere = targetAi.MyGrid.PositionComp.WorldVolume;
                            targetSphere.Radius *= 3;
                            var testRay    = new RayD(p.Info.Origin, p.Info.Direction);
                            var quickCheck = Vector3D.IsZero(targetAi.GridVel, 0.025) && targetSphere.Intersects(testRay) != null;

                            if (!quickCheck)
                            {
                                var deltaPos        = targetSphere.Center - p.Info.Origin;
                                var deltaVel        = targetAi.GridVel - p.Info.Ai.GridVel;
                                var timeToIntercept = MathFuncs.Intercept(deltaPos, deltaVel, p.Info.AmmoDef.Const.DesiredProjectileSpeed);
                                var predictedPos    = targetSphere.Center + (float)timeToIntercept * deltaVel;
                                targetSphere.Center = predictedPos;
                            }

                            if (quickCheck || targetSphere.Intersects(testRay) != null)
                            {
                                addProjectile = true;
                            }
                        }
                    }
                    if (addProjectile)
                    {
                        targetAi.DeadProjectiles.Remove(p);
                        targetAi.LiveProjectile.Add(p);
                        targetAi.LiveProjectileTick = Session.Tick;
                        targetAi.NewProjectileTick  = Session.Tick;
                        p.Watchers.Add(targetAi);
                    }
                }
            }
            AddTargets.Clear();
        }
Пример #2
0
        internal void ActivateMine()
        {
            var ent = Info.Target.Entity;

            MineActivated = true;
            AtMaxRange    = false;
            var targetPos       = ent.PositionComp.WorldAABB.Center;
            var deltaPos        = targetPos - Position;
            var targetVel       = ent.Physics?.LinearVelocity ?? Vector3.Zero;
            var deltaVel        = targetVel - Vector3.Zero;
            var timeToIntercept = MathFuncs.Intercept(deltaPos, deltaVel, DesiredSpeed);
            var predictedPos    = targetPos + (float)timeToIntercept * deltaVel;

            PredictedTargetPos = predictedPos;
            PrevTargetPos      = predictedPos;
            PrevTargetVel      = targetVel;
            LockedTarget       = true;

            if (Guidance == GuidanceType.DetectFixed)
            {
                return;
            }
            Vector3D.DistanceSquared(ref Info.Origin, ref predictedPos, out DistanceToTravelSqr);
            Info.DistanceTraveled     = 0;
            Info.PrevDistanceTraveled = 0;

            Info.Direction    = Vector3D.Normalize(predictedPos - Position);
            AccelDir          = Info.Direction;
            VelocityLengthSqr = 0;

            MaxVelocity   = (Info.Direction * DesiredSpeed);
            MaxSpeed      = MaxVelocity.Length();
            MaxSpeedSqr   = MaxSpeed * MaxSpeed;
            AccelVelocity = (Info.Direction * DeltaVelocityPerTick);

            if (ConstantSpeed)
            {
                Velocity          = MaxVelocity;
                VelocityLengthSqr = MaxSpeed * MaxSpeed;
            }
            else
            {
                Velocity = AccelVelocity;
            }

            if (Guidance == GuidanceType.DetectSmart)
            {
                SmartsOn     = true;
                MaxChaseTime = Info.ConsumableDef.Const.MaxChaseTime;

                if (SmartsOn && Info.ConsumableDef.Const.TargetOffSet && LockedTarget)
                {
                    OffSetTarget();
                    OffsetSqr = Info.ConsumableDef.Trajectory.Smarts.Inaccuracy * Info.ConsumableDef.Trajectory.Smarts.Inaccuracy;
                }
                else
                {
                    TargetOffSet = Vector3D.Zero;
                    OffsetSqr    = 0;
                }
            }

            TravelMagnitude = Velocity * StepConst;
        }
Пример #3
0
        internal void Shoot() // Inlined due to keens mod profiler
        {
            try
            {
                var session    = Comp.Session;
                var tick       = session.Tick;
                var bps        = System.Values.HardPoint.Loading.BarrelsPerShot;
                var targetable = ActiveAmmoDef.AmmoDef.Health > 0 && !ActiveAmmoDef.AmmoDef.Const.IsBeamWeapon;

                if (_ticksUntilShoot++ < System.DelayToFire)
                {
                    if (AvCapable && System.PreFireSound && !PreFiringEmitter.IsPlaying)
                    {
                        StartPreFiringSound();
                    }

                    if (ActiveAmmoDef.AmmoDef.Const.MustCharge || System.AlwaysFireFullBurst)
                    {
                        FinishBurst = true;
                    }

                    if (!PreFired)
                    {
                        var nxtMuzzle = NextMuzzle;
                        for (int i = 0; i < bps; i++)
                        {
                            _muzzlesToFire.Clear();
                            _muzzlesToFire.Add(MuzzleIdToName[NextMuzzle]);
                            if (i == bps)
                            {
                                NextMuzzle++;
                            }
                            nxtMuzzle = (nxtMuzzle + (System.Values.HardPoint.Loading.SkipBarrels + 1)) % _numOfBarrels;
                        }

                        uint prefireLength;
                        if (System.WeaponAnimationLengths.TryGetValue(EventTriggers.PreFire, out prefireLength))
                        {
                            if (_prefiredTick + prefireLength <= tick)
                            {
                                EventTriggerStateChanged(EventTriggers.PreFire, true, _muzzlesToFire);
                                _prefiredTick = tick;
                            }
                        }
                        PreFired = true;
                    }
                    return;
                }

                if (PreFired)
                {
                    EventTriggerStateChanged(EventTriggers.PreFire, false);
                    _muzzlesToFire.Clear();
                    PreFired = false;
                }

                if (System.HasBarrelRotation)
                {
                    SpinBarrel();
                    if (BarrelRate < 9)
                    {
                        if (_spinUpTick <= tick)
                        {
                            BarrelRate++;
                            _spinUpTick = tick + _ticksBeforeSpinUp;
                        }
                        return;
                    }
                }

                if (ShootTick > tick)
                {
                    return;
                }

                if (LockOnFireState && (Target.Entity != Comp.Ai.Focus.Target[0] || Target.Entity != Comp.Ai.Focus.Target[1]))
                {
                    Comp.Ai.Focus.GetPriorityTarget(out Target.Entity);
                }

                ShootTick = tick + TicksPerShot;

                if (!IsShooting)
                {
                    StartShooting();
                }

                var burstDelay = (uint)System.Values.HardPoint.Loading.DelayAfterBurst;

                if (ActiveAmmoDef.AmmoDef.Const.BurstMode && ++State.ShotsFired > System.ShotsPerBurst)
                {
                    State.ShotsFired = 1;
                    EventTriggerStateChanged(EventTriggers.BurstReload, false);
                }
                else if (ActiveAmmoDef.AmmoDef.Const.HasShotReloadDelay && System.ShotsPerBurst > 0 && ++State.ShotsFired == System.ShotsPerBurst)
                {
                    State.ShotsFired = 0;
                    ShootTick        = burstDelay > TicksPerShot ? tick + burstDelay : tick + TicksPerShot;
                }

                if (Comp.Ai.VelocityUpdateTick != tick)
                {
                    Comp.Ai.GridVel            = Comp.Ai.MyGrid.Physics?.LinearVelocity ?? Vector3D.Zero;
                    Comp.Ai.IsStatic           = Comp.Ai.MyGrid.Physics?.IsStatic ?? false;
                    Comp.Ai.VelocityUpdateTick = tick;
                }

                var targetAiCnt = Comp.Ai.TargetAis.Count;

                Projectile vProjectile = null;
                if (ActiveAmmoDef.AmmoDef.Const.VirtualBeams)
                {
                    vProjectile = CreateVirtualProjectile();
                }

                for (int i = 0; i < bps; i++)
                {
                    var current = NextMuzzle;
                    var muzzle  = Muzzles[current];
                    if (muzzle.LastUpdateTick != tick)
                    {
                        var dummy   = Dummies[current];
                        var newInfo = dummy.Info;
                        muzzle.Direction      = newInfo.Direction;
                        muzzle.Position       = newInfo.Position;
                        muzzle.LastUpdateTick = tick;
                    }

                    if (ActiveAmmoDef.AmmoDef.Const.Reloadable)
                    {
                        if (State.Sync.CurrentAmmo == 0)
                        {
                            break;
                        }
                        State.Sync.CurrentAmmo--;
                    }

                    if (ActiveAmmoDef.AmmoDef.Const.HasBackKickForce && !Comp.Ai.IsStatic)
                    {
                        Comp.Ai.MyGrid.Physics.AddForce(MyPhysicsForceType.APPLY_WORLD_IMPULSE_AND_WORLD_ANGULAR_IMPULSE, -muzzle.Direction * ActiveAmmoDef.AmmoDef.BackKickForce, muzzle.Position, Vector3D.Zero);
                    }

                    if (PlayTurretAv)
                    {
                        if (System.BarrelEffect1 && tick - muzzle.LastAv1Tick > System.Barrel1AvTicks && !muzzle.Av1Looping)
                        {
                            muzzle.LastAv1Tick = tick;
                            muzzle.Av1Looping  = System.Values.HardPoint.Graphics.Barrel1.Extras.Loop;
                            session.Av.AvBarrels1.Add(new AvBarrel {
                                Weapon = this, Muzzle = muzzle, StartTick = tick
                            });
                        }

                        if (System.BarrelEffect2 && tick - muzzle.LastAv2Tick > System.Barrel2AvTicks && !muzzle.Av2Looping)
                        {
                            muzzle.LastAv2Tick = tick;
                            muzzle.Av2Looping  = System.Values.HardPoint.Graphics.Barrel2.Extras.Loop;
                            session.Av.AvBarrels2.Add(new AvBarrel {
                                Weapon = this, Muzzle = muzzle, StartTick = tick
                            });
                        }
                    }

                    for (int j = 0; j < System.Values.HardPoint.Loading.TrajectilesPerBarrel; j++)
                    {
                        if (System.Values.HardPoint.DeviateShotAngle > 0)
                        {
                            var dirMatrix    = Matrix.CreateFromDir(muzzle.Direction);
                            var randomFloat1 = MyUtils.GetRandomFloat(-System.Values.HardPoint.DeviateShotAngle, System.Values.HardPoint.DeviateShotAngle);
                            var randomFloat2 = MyUtils.GetRandomFloat(0.0f, MathHelper.TwoPi);

                            muzzle.DeviatedDir = Vector3.TransformNormal(-new Vector3(
                                                                             MyMath.FastSin(randomFloat1) * MyMath.FastCos(randomFloat2),
                                                                             MyMath.FastSin(randomFloat1) * MyMath.FastSin(randomFloat2),
                                                                             MyMath.FastCos(randomFloat1)), dirMatrix);
                        }
                        else
                        {
                            muzzle.DeviatedDir = muzzle.Direction;
                        }

                        if (ActiveAmmoDef.AmmoDef.Const.VirtualBeams && j == 0)
                        {
                            MyEntity primeE   = null;
                            MyEntity triggerE = null;

                            if (ActiveAmmoDef.AmmoDef.Const.PrimeModel)
                            {
                                primeE = ActiveAmmoDef.AmmoDef.Const.PrimeEntityPool.Get();
                            }

                            if (ActiveAmmoDef.AmmoDef.Const.TriggerModel)
                            {
                                triggerE = session.TriggerEntityPool.Get();
                            }

                            var info = session.Projectiles.VirtInfoPool.Get();
                            info.InitVirtual(System, Comp.Ai, ActiveAmmoDef.AmmoDef, primeE, triggerE, Target, WeaponId, muzzle.MuzzleId, muzzle.Position, muzzle.DeviatedDir);
                            vProjectile.VrPros.Add(new VirtualProjectile {
                                Info = info, VisualShot = session.Av.AvShotPool.Get()
                            });

                            if (!ActiveAmmoDef.AmmoDef.Const.RotateRealBeam)
                            {
                                vProjectile.Info.WeaponCache.VirutalId = 0;
                            }
                            else if (i == _nextVirtual)
                            {
                                vProjectile.Info.Origin                = muzzle.Position;
                                vProjectile.Info.Direction             = muzzle.DeviatedDir;
                                vProjectile.Info.WeaponCache.VirutalId = _nextVirtual;
                            }

                            Comp.Session.Projectiles.ActiveProjetiles.Add(vProjectile);
                        }
                        else
                        {
                            var p = Comp.Session.Projectiles.ProjectilePool.Count > 0 ? Comp.Session.Projectiles.ProjectilePool.Pop() : new Projectile();
                            p.Info.Id                    = Comp.Session.Projectiles.CurrentProjectileId++;
                            p.Info.System                = System;
                            p.Info.Ai                    = Comp.Ai;
                            p.Info.AmmoDef               = ActiveAmmoDef.AmmoDef;
                            p.Info.Overrides             = Comp.Set.Value.Overrides;
                            p.Info.Target.Entity         = Target.Entity;
                            p.Info.Target.Projectile     = Target.Projectile;
                            p.Info.Target.IsProjectile   = Target.Projectile != null;
                            p.Info.Target.IsFakeTarget   = Comp.TrackReticle;
                            p.Info.Target.FiringCube     = Comp.MyCube;
                            p.Info.WeaponId              = WeaponId;
                            p.Info.MuzzleId              = muzzle.MuzzleId;
                            p.Info.BaseDamagePool        = BaseDamage;
                            p.Info.EnableGuidance        = Comp.Set.Value.Guidance;
                            p.Info.DetonationDamage      = ActiveAmmoDef.AmmoDef.Const.DetonationDamage;
                            p.Info.AreaEffectDamage      = ActiveAmmoDef.AmmoDef.Const.AreaEffectDamage;
                            p.Info.WeaponCache           = WeaponCache;
                            p.Info.WeaponCache.VirutalId = -1;
                            p.Info.Seed                  = Comp.Seed;
                            p.Info.LockOnFireState       = LockOnFireState;
                            p.Info.ShooterVel            = Comp.Ai.GridVel;
                            p.Info.Origin                = muzzle.Position;
                            p.Info.OriginUp              = MyPivotUp;
                            p.PredictedTargetPos         = Target.TargetPos;
                            p.Info.Direction             = muzzle.DeviatedDir;
                            p.State              = Projectile.ProjectileState.Start;
                            p.Info.PrimeEntity   = ActiveAmmoDef.AmmoDef.Const.PrimeModel ? ActiveAmmoDef.AmmoDef.Const.PrimeEntityPool.Get() : null;
                            p.Info.TriggerEntity = ActiveAmmoDef.AmmoDef.Const.TriggerModel ? session.TriggerEntityPool.Get() : null;
                            Comp.Session.Projectiles.ActiveProjetiles.Add(p);

                            if (targetable)
                            {
                                for (int t = 0; t < targetAiCnt; t++)
                                {
                                    var targetAi      = Comp.Ai.TargetAis[t];
                                    var addProjectile = ActiveAmmoDef.AmmoDef.Trajectory.Guidance != GuidanceType.None && targetAi.PointDefense;
                                    if (!addProjectile && targetAi.PointDefense)
                                    {
                                        if (Vector3.Dot(p.Info.Direction, p.Info.Origin - targetAi.MyGrid.PositionComp.WorldMatrixRef.Translation) < 0)
                                        {
                                            var targetSphere = targetAi.MyGrid.PositionComp.WorldVolume;
                                            targetSphere.Radius *= 3;
                                            var testRay    = new RayD(p.Info.Origin, p.Info.Direction);
                                            var quickCheck = Vector3D.IsZero(targetAi.GridVel, 0.025) && targetSphere.Intersects(testRay) != null;
                                            if (!quickCheck)
                                            {
                                                var deltaPos        = targetSphere.Center - MyPivotPos;
                                                var deltaVel        = targetAi.GridVel - Comp.Ai.GridVel;
                                                var timeToIntercept = MathFuncs.Intercept(deltaPos, deltaVel, ActiveAmmoDef.AmmoDef.Const.DesiredProjectileSpeed);
                                                var predictedPos    = targetSphere.Center + (float)timeToIntercept * deltaVel;
                                                targetSphere.Center = predictedPos;
                                            }

                                            if (quickCheck || targetSphere.Intersects(testRay) != null)
                                            {
                                                addProjectile = true;
                                            }
                                        }
                                    }
                                    if (addProjectile)
                                    {
                                        targetAi.LiveProjectile.Add(p);
                                        targetAi.LiveProjectileTick = tick;
                                        targetAi.NewProjectileTick  = tick;
                                        p.Watchers.Add(targetAi);
                                    }
                                }
                            }
                        }
                    }

                    _muzzlesToFire.Add(MuzzleIdToName[current]);

                    if (HeatPShot > 0)
                    {
                        if (!HeatLoopRunning)
                        {
                            Comp.Session.FutureEvents.Schedule(UpdateWeaponHeat, null, 20);
                            HeatLoopRunning = true;
                        }

                        State.Sync.Heat  += HeatPShot;
                        Comp.CurrentHeat += HeatPShot;
                        if (State.Sync.Heat >= System.MaxHeat)
                        {
                            if (!Comp.Session.IsClient && Comp.Set.Value.Overload > 1)
                            {
                                var dmg = .02f * Comp.MaxIntegrity;
                                Comp.Slim.DoDamage(dmg, MyDamageType.Environment, true, null, Comp.Ai.MyGrid.EntityId);
                            }
                            EventTriggerStateChanged(EventTriggers.Overheated, true);
                            State.Sync.Overheated = true;
                            StopShooting();
                            break;
                        }
                    }

                    if (i == bps)
                    {
                        NextMuzzle++;
                    }

                    NextMuzzle = (NextMuzzle + (System.Values.HardPoint.Loading.SkipBarrels + 1)) % _numOfBarrels;
                }

                if (IsShooting)
                {
                    EventTriggerStateChanged(state: EventTriggers.Firing, active: true, muzzles: _muzzlesToFire);
                }

                if (!ActiveAmmoDef.AmmoDef.Const.MustCharge && ActiveAmmoDef.AmmoDef.Const.BurstMode && (State.Sync.CurrentAmmo > 0 || ActiveAmmoDef.AmmoDef.Const.EnergyAmmo) && State.ShotsFired == System.ShotsPerBurst)
                {
                    uint delay = 0;
                    FinishBurst = false;
                    if (System.WeaponAnimationLengths.TryGetValue(EventTriggers.Firing, out delay))
                    {
                        session.FutureEvents.Schedule(o => { EventTriggerStateChanged(EventTriggers.BurstReload, true); }, null, delay);
                    }
                    else
                    {
                        EventTriggerStateChanged(EventTriggers.BurstReload, true);
                    }

                    if (AvCapable && RotateEmitter != null && RotateEmitter.IsPlaying)
                    {
                        StopRotateSound();
                    }
                    if (IsShooting)
                    {
                        StopShooting();
                    }

                    ShootTick = burstDelay > TicksPerShot ? tick + burstDelay + delay : tick + TicksPerShot + delay;
                }
                else if (((ActiveAmmoDef.AmmoDef.Const.BurstMode && System.AlwaysFireFullBurst) || ActiveAmmoDef.AmmoDef.Const.MustCharge) && State.Sync.CurrentAmmo > 0 && State.ShotsFired < System.ShotsPerBurst)
                {
                    FinishBurst = true;
                }

                else if (ActiveAmmoDef.AmmoDef.Const.Reloadable && (State.Sync.CurrentAmmo == 0 || (State.ShotsFired == System.ShotsPerBurst && ActiveAmmoDef.AmmoDef.Const.MustCharge)) && !State.Sync.Reloading)
                {
                    StartReload();
                }


                if (State.ManualShoot == TerminalActionState.ShootOnce && --State.SingleShotCounter <= 0)
                {
                    State.ManualShoot = TerminalActionState.ShootOff;
                }

                _muzzlesToFire.Clear();

                _nextVirtual = _nextVirtual + 1 < bps ? _nextVirtual + 1 : 0;
            }
            catch (Exception e)
            {
                Log.Line($"Error in shoot: {e}");
            }
        }