예제 #1
0
        internal void Clean()
        {
            for (int j = 0; j < CleanUp.Count; j++)
            {
                var p = CleanUp[j];
                for (int i = 0; i < p.VrPros.Count; i++)
                {
                    var virtInfo = p.VrPros[i];
                    virtInfo.Info.Clean(Session.Tick);
                    VirtInfoPool.Return(virtInfo.Info);
                }
                p.VrPros.Clear();

                if (p.DynamicGuidance)
                {
                    DynTrees.UnregisterProjectile(p);
                }

                p.PruningProxyId = -1;

                p.Info.Clean(Session.Tick);
                ProjectilePool.Push(p);
                ActiveProjetiles.Remove(p);
            }

            CleanUp.Clear();
        }
예제 #2
0
        internal void ProjectileClose()
        {
            if (GenerateShrapnel && Info.Age >= Info.ConsumableDef.Const.MinArmingTime)
            {
                SpawnShrapnel();
            }

            for (int i = 0; i < Watchers.Count; i++)
            {
                Watchers[i].DeadProjectiles.Add(this);
            }
            Watchers.Clear();

            foreach (var seeker in Seekers)
            {
                seeker.Info.Target.Reset(Info.System.Session.Tick, Target.States.ProjectileClosed);
            }
            Seekers.Clear();

            if (EnableAv && Info.AvShot.ForceHitParticle)
            {
                Info.AvShot.HitEffects(true);
            }

            State = ProjectileState.Dead;

            var detInfo = Info.ConsumableDef.AreaEffect.Detonation;
            var afInfo  = Info.ConsumableDef.AreaEffect;
            var detExp  = !afInfo.Explosions.NoVisuals && (afInfo.AreaEffect == AreaEffectType.Explosive || afInfo.AreaEffect == AreaEffectType.Radiant && afInfo.Explosions.CustomParticle != string.Empty) && detInfo.DetonateOnEnd && (!detInfo.ArmOnlyOnHit || Info.ObjectsHit > 0);

            if (EnableAv)
            {
                if (ModelState == EntityState.Exists)
                {
                    ModelState = EntityState.None;
                }
                if (!Info.AvShot.Active)
                {
                    Info.System.Session.Av.AvShotPool.Return(Info.AvShot);
                }
                else
                {
                    Info.AvShot.EndState = new AvClose {
                        EndPos = Position, Dirty = true, DetonateFakeExp = detExp
                    }
                };
            }
            else if (Info.ConsumableDef.Const.VirtualBeams)
            {
                for (int i = 0; i < VrPros.Count; i++)
                {
                    var vp = VrPros[i];
                    if (!vp.AvShot.Active)
                    {
                        Info.System.Session.Av.AvShotPool.Return(vp.AvShot);
                    }
                    else
                    {
                        vp.AvShot.EndState = new AvClose {
                            EndPos = Position, Dirty = true, DetonateFakeExp = detExp
                        }
                    };

                    Info.System.Session.Projectiles.VirtInfoPool.Return(vp);
                }
                VrPros.Clear();
            }
            if (DynamicGuidance)
            {
                DynTrees.UnregisterProjectile(this);
            }

            PruningProxyId = -1;
            Info.Clean();
        }
예제 #3
0
        internal void EwarEffects()
        {
            switch (Info.ConsumableDef.Const.AreaEffect)
            {
            case AreaEffectType.AntiSmart:
                var eWarSphere = new BoundingSphereD(Position, Info.ConsumableDef.Const.AreaEffectSize);
                DynTrees.GetAllProjectilesInSphere(Info.System.Session, ref eWarSphere, EwaredProjectiles, false);
                for (int j = 0; j < EwaredProjectiles.Count; j++)
                {
                    var netted = EwaredProjectiles[j];
                    if (netted.Info.Target.FiringCube.CubeGrid.IsSameConstructAs(Info.Target.FiringCube.CubeGrid) || netted.Info.Target.IsProjectile)
                    {
                        continue;
                    }
                    if (Info.WeaponRng.ClientProjectileRandom.NextDouble() * 100f < Info.ConsumableDef.Const.PulseChance || !Info.ConsumableDef.Const.Pulse)
                    {
                        Info.BaseEwarPool -= Info.ConsumableDef.Const.AreaEffectDamage;
                        if (Info.BaseEwarPool <= 0)
                        {
                            Info.EwarActive = true;
                            netted.Info.Target.Projectile   = this;
                            netted.Info.Target.IsProjectile = true;
                            Seekers.Add(netted);
                        }
                    }

                    Info.WeaponRng.ClientProjectileCurrentCounter++;
                }
                EwaredProjectiles.Clear();
                return;

            case AreaEffectType.PushField:
                if (Info.EwarAreaPulse && Info.WeaponRng.ClientProjectileRandom.NextDouble() * 100f <= Info.ConsumableDef.Const.PulseChance || !Info.ConsumableDef.Const.Pulse)
                {
                    Info.EwarActive = true;
                }
                break;

            case AreaEffectType.PullField:
                if (Info.EwarAreaPulse && Info.WeaponRng.ClientProjectileRandom.NextDouble() * 100f <= Info.ConsumableDef.Const.PulseChance || !Info.ConsumableDef.Const.Pulse)
                {
                    Info.EwarActive = true;
                }
                break;

            case AreaEffectType.JumpNullField:
                if (Info.EwarAreaPulse && Info.WeaponRng.ClientProjectileRandom.NextDouble() * 100f <= Info.ConsumableDef.Const.PulseChance || !Info.ConsumableDef.Const.Pulse)
                {
                    Info.EwarActive = true;
                }
                break;

            case AreaEffectType.AnchorField:
                if (Info.EwarAreaPulse && Info.WeaponRng.ClientProjectileRandom.NextDouble() * 100f <= Info.ConsumableDef.Const.PulseChance || !Info.ConsumableDef.Const.Pulse)
                {
                    Info.EwarActive = true;
                }
                break;

            case AreaEffectType.EnergySinkField:
                if (Info.EwarAreaPulse && Info.WeaponRng.ClientProjectileRandom.NextDouble() * 100f <= Info.ConsumableDef.Const.PulseChance || !Info.ConsumableDef.Const.Pulse)
                {
                    Info.EwarActive = true;
                }
                break;

            case AreaEffectType.EmpField:
                if (Info.EwarAreaPulse && Info.WeaponRng.ClientProjectileRandom.NextDouble() * 100f <= Info.ConsumableDef.Const.PulseChance || !Info.ConsumableDef.Const.Pulse)
                {
                    Info.EwarActive = true;
                }
                break;

            case AreaEffectType.OffenseField:
                if (Info.EwarAreaPulse && Info.WeaponRng.ClientProjectileRandom.NextDouble() * 100f <= Info.ConsumableDef.Const.PulseChance || !Info.ConsumableDef.Const.Pulse)
                {
                    Info.EwarActive = true;
                }
                break;

            case AreaEffectType.NavField:
                if (!Info.ConsumableDef.Const.Pulse || Info.EwarAreaPulse && Info.WeaponRng.ClientProjectileRandom.NextDouble() * 100f <= Info.ConsumableDef.Const.PulseChance)
                {
                    Info.EwarActive = true;
                }
                break;

            case AreaEffectType.DotField:
                if (Info.EwarAreaPulse && Info.WeaponRng.ClientProjectileRandom.NextDouble() * 100f <= Info.ConsumableDef.Const.PulseChance || !Info.ConsumableDef.Const.Pulse)
                {
                    Info.EwarActive = true;
                }
                break;
            }
            Info.WeaponRng.ClientProjectileCurrentCounter++;
        }
예제 #4
0
        internal void Start()
        {
            Position = Info.Origin;
            AccelDir = Info.Direction;
            var cameraStart = Info.System.Session.CameraPos;

            Vector3D.DistanceSquared(ref cameraStart, ref Info.Origin, out DistanceFromCameraSqr);
            GenerateShrapnel = Info.ConsumableDef.Const.ShrapnelId > -1;
            var probability = Info.ConsumableDef.AmmoGraphics.VisualProbability;

            EnableAv                  = !Info.ConsumableDef.Const.VirtualBeams && !Info.System.Session.DedicatedServer && DistanceFromCameraSqr <= Info.System.Session.SyncDistSqr && (probability >= 1 || probability >= MyUtils.GetRandomDouble(0.0f, 1f));
            ModelState                = EntityState.None;
            LastEntityPos             = Position;
            LastHitEntVel             = null;
            Info.AvShot               = null;
            Info.Age                  = -1;
            ChaseAge                  = 0;
            NewTargets                = 0;
            ZombieLifeTime            = 0;
            LastOffsetTime            = 0;
            PruningProxyId            = -1;
            EntitiesNear              = false;
            CachedPlanetHit           = false;
            PositionChecked           = false;
            MineSeeking               = false;
            MineActivated             = false;
            MineTriggered             = false;
            LinePlanetCheck           = false;
            AtMaxRange                = false;
            ShieldBypassed            = false;
            FakeGravityNear           = false;
            HadTarget                 = false;
            WasTracking               = false;
            Intersecting              = false;
            EndStep                   = 0;
            Info.PrevDistanceTraveled = 0;
            Info.DistanceTraveled     = 0;
            PrevEndPointToCenterSqr   = double.MaxValue;


            CachedId        = Info.MuzzleId == -1 ? Info.WeaponCache.VirutalId : Info.MuzzleId;
            Guidance        = Info.ConsumableDef.Trajectory.Guidance;
            DynamicGuidance = Guidance != GuidanceType.None && Guidance != GuidanceType.TravelTo && !Info.ConsumableDef.Const.IsBeamWeapon && Info.EnableGuidance;
            if (DynamicGuidance)
            {
                DynTrees.RegisterProjectile(this);
            }
            FeelsGravity = Info.ConsumableDef.Const.FeelsGravity;

            Info.MyPlanet = Info.Ai.MyPlanet;
            if (!Info.System.Session.VoxelCaches.TryGetValue(Info.UniqueMuzzleId, out Info.VoxelCache))
            {
                Log.Line($"ProjectileStart VoxelCache Failure with Id:{Info.UniqueMuzzleId} BlockMarked:{Info.Target.FiringCube?.MarkedForClose}, setting to default cache:");
                Info.VoxelCache = Info.System.Session.VoxelCaches[ulong.MaxValue];
            }
            if (Info.MyPlanet != null)
            {
                Info.VoxelCache.PlanetSphere.Center = Info.Ai.ClosestPlanetCenter;
            }

            Info.MyShield            = Info.Ai.MyShield;
            Info.InPlanetGravity     = Info.Ai.InPlanetGravity;
            Info.AiVersion           = Info.Ai.Version;
            Info.Ai.ProjectileTicker = Info.Ai.Session.Tick;

            if (Guidance == GuidanceType.Smart && DynamicGuidance)
            {
                SmartsOn     = true;
                MaxChaseTime = Info.ConsumableDef.Const.MaxChaseTime;
                SmartSlot    = Info.WeaponRng.ClientProjectileRandom.Next(10);
                Info.WeaponRng.ClientProjectileCurrentCounter++;
            }
            else
            {
                MaxChaseTime = int.MaxValue;
                SmartsOn     = false;
                SmartSlot    = 0;
            }

            if (Info.Target.IsProjectile)
            {
                OriginTargetPos = Info.Target.Projectile.Position;
                Info.Target.Projectile.Seekers.Add(this);
            }
            else if (Info.Target.Entity != null)
            {
                OriginTargetPos = Info.Target.Entity.PositionComp.WorldAABB.Center;
            }
            else
            {
                OriginTargetPos = Vector3D.Zero;
            }
            LockedTarget = !Vector3D.IsZero(OriginTargetPos);

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

            var targetSpeed = (float)(!Info.ConsumableDef.Const.IsBeamWeapon ? Info.ConsumableDef.Trajectory.DesiredSpeed : Info.MaxTrajectory * MyEngineConstants.UPDATE_STEPS_PER_SECOND);

            if (Info.ConsumableDef.Const.SpeedVariance && !Info.ConsumableDef.Const.IsBeamWeapon)
            {
                var min           = Info.ConsumableDef.Trajectory.SpeedVariance.Start;
                var max           = Info.ConsumableDef.Trajectory.SpeedVariance.End;
                var speedVariance = (float)Info.WeaponRng.ClientProjectileRandom.NextDouble() * (max - min) + min;
                Info.WeaponRng.ClientProjectileCurrentCounter++;
                DesiredSpeed = targetSpeed + speedVariance;
            }
            else
            {
                DesiredSpeed = targetSpeed;
            }

            float variance = 0;

            if (Info.ConsumableDef.Const.RangeVariance)
            {
                var min = Info.ConsumableDef.Trajectory.RangeVariance.Start;
                var max = Info.ConsumableDef.Trajectory.RangeVariance.End;
                variance            = (float)Info.WeaponRng.ClientProjectileRandom.NextDouble() * (max - min) + min;
                Info.MaxTrajectory -= variance;
                Info.WeaponRng.ClientProjectileCurrentCounter++;
            }

            if (Vector3D.IsZero(PredictedTargetPos))
            {
                PredictedTargetPos = Position + (AccelDir * Info.MaxTrajectory);
            }
            PrevTargetPos       = PredictedTargetPos;
            PrevTargetVel       = Vector3D.Zero;
            Info.ObjectsHit     = 0;
            Info.BaseHealthPool = Info.ConsumableDef.Health;
            Info.BaseEwarPool   = Info.ConsumableDef.Health;
            Info.TracerLength   = Info.ConsumableDef.Const.TracerLength <= Info.MaxTrajectory ? Info.ConsumableDef.Const.TracerLength : Info.MaxTrajectory;

            MaxTrajectorySqr = Info.MaxTrajectory * Info.MaxTrajectory;

            if (!Info.IsShrapnel)
            {
                StartSpeed = Info.ShooterVel;
            }

            MoveToAndActivate = LockedTarget && !Info.ConsumableDef.Const.IsBeamWeapon && Guidance == GuidanceType.TravelTo;

            if (MoveToAndActivate)
            {
                var distancePos = !Vector3D.IsZero(PredictedTargetPos) ? PredictedTargetPos : OriginTargetPos;
                if (variance > 0)
                {
                    var forward = Info.WeaponRng.ClientProjectileRandom.Next(100) < 50;
                    Info.WeaponRng.ClientProjectileCurrentCounter++;
                    distancePos = forward ? distancePos + (AccelDir * variance) : distancePos + (-AccelDir * variance);
                }
                Vector3D.DistanceSquared(ref Info.Origin, ref distancePos, out DistanceToTravelSqr);
            }
            else
            {
                DistanceToTravelSqr = MaxTrajectorySqr;
            }

            PickTarget = Info.ConsumableDef.Trajectory.Smarts.OverideTarget && !Info.Target.IsFakeTarget && !Info.LockOnFireState;
            if (PickTarget || LockedTarget)
            {
                NewTargets++;
            }

            var staticIsInRange  = Info.Ai.ClosestStaticSqr * 0.5 < MaxTrajectorySqr;
            var pruneStaticCheck = Info.Ai.ClosestPlanetSqr * 0.5 < MaxTrajectorySqr || Info.Ai.StaticGridInRange;

            PruneQuery = (DynamicGuidance && pruneStaticCheck) || FeelsGravity && staticIsInRange || !DynamicGuidance && !FeelsGravity && staticIsInRange ? MyEntityQueryType.Both : MyEntityQueryType.Dynamic;

            if (Info.Ai.PlanetSurfaceInRange && Info.Ai.ClosestPlanetSqr <= MaxTrajectorySqr)
            {
                LinePlanetCheck = true;
                PruneQuery      = MyEntityQueryType.Both;
            }

            if (DynamicGuidance && PruneQuery == MyEntityQueryType.Dynamic && staticIsInRange)
            {
                CheckForNearVoxel(60);
            }

            var accelPerSec = Info.ConsumableDef.Trajectory.AccelPerSec;

            ConstantSpeed       = accelPerSec <= 0;
            AccelInMetersPerSec = accelPerSec > 0 ? accelPerSec : DesiredSpeed;
            var desiredSpeed     = (AccelDir * DesiredSpeed);
            var relativeSpeedCap = StartSpeed + desiredSpeed;

            MaxVelocity          = relativeSpeedCap;
            MaxSpeed             = MaxVelocity.Length();
            MaxSpeedSqr          = MaxSpeed * MaxSpeed;
            DeltaVelocityPerTick = accelPerSec * StepConst;
            AccelVelocity        = (AccelDir * DeltaVelocityPerTick);

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

            if (Info.IsShrapnel)
            {
                Vector3D.Normalize(ref Velocity, out Info.Direction);
            }

            InitalStep = !Info.IsShrapnel && ConstantSpeed ? desiredSpeed * StepConst : Velocity * StepConst;

            TravelMagnitude = Velocity * StepConst;
            FieldTime       = Info.ConsumableDef.Const.Ewar || Info.ConsumableDef.Const.IsMine ? Info.ConsumableDef.Trajectory.FieldTime : 0;
            State           = !Info.ConsumableDef.Const.IsBeamWeapon ? ProjectileState.Alive : ProjectileState.OneAndDone;

            if (EnableAv)
            {
                Info.AvShot = Info.System.Session.Av.AvShotPool.Get();
                Info.AvShot.Init(Info, AccelInMetersPerSec * StepConst, MaxSpeed, ref AccelDir);
                Info.AvShot.SetupSounds(DistanceFromCameraSqr); //Pool initted sounds per Projectile type... this is expensive
                if (Info.ConsumableDef.Const.HitParticle && !Info.ConsumableDef.Const.IsBeamWeapon || Info.ConsumableDef.Const.AreaEffect == AreaEffectType.Explosive && !Info.ConsumableDef.AreaEffect.Explosions.NoVisuals && Info.ConsumableDef.Const.AreaEffectSize > 0 && Info.ConsumableDef.Const.AreaEffectDamage > 0)
                {
                    var hitPlayChance = Info.ConsumableDef.AmmoGraphics.Particles.Hit.Extras.HitPlayChance;
                    Info.AvShot.HitParticleActive = hitPlayChance >= 1 || hitPlayChance >= MyUtils.GetRandomDouble(0.0f, 1f);
                }
                Info.AvShot.FakeExplosion = Info.AvShot.HitParticleActive && Info.ConsumableDef.Const.AreaEffect == AreaEffectType.Explosive && Info.ConsumableDef.AmmoGraphics.Particles.Hit.Name == string.Empty;
            }

            if (!Info.ConsumableDef.Const.PrimeModel && !Info.ConsumableDef.Const.TriggerModel)
            {
                ModelState = EntityState.None;
            }
            else
            {
                if (EnableAv)
                {
                    ModelState = EntityState.Exists;

                    double triggerModelSize = 0;
                    double primeModelSize   = 0;
                    if (Info.ConsumableDef.Const.TriggerModel)
                    {
                        triggerModelSize = Info.AvShot.TriggerEntity.PositionComp.WorldVolume.Radius;
                    }
                    if (Info.ConsumableDef.Const.PrimeModel)
                    {
                        primeModelSize = Info.AvShot.PrimeEntity.PositionComp.WorldVolume.Radius;
                    }
                    var largestSize = triggerModelSize > primeModelSize ? triggerModelSize : primeModelSize;

                    Info.AvShot.ModelSphereCurrent.Radius = largestSize * 2;
                }
            }

            if (EnableAv)
            {
                LineOrNotModel        = Info.ConsumableDef.Const.DrawLine || ModelState == EntityState.None && Info.ConsumableDef.Const.AmmoParticle;
                Info.AvShot.ModelOnly = !LineOrNotModel && ModelState == EntityState.Exists;
            }
        }