public void ThrustToVelocity(Vector3D velocity)
            {
                if (thrustPidController == null)
                {
                    throw new Exception("wat de neuk thrustPid is null");
                }
                if (thrustControl == null)
                {
                    throw new Exception("wat de neuk thrustControl is null");
                }
                if (ingameTime == null)
                {
                    throw new Exception("wat de neuk ingameTime is null");
                }

                Vector3D difference    = velocity - ControlVelocity;
                double   differenceMag = difference.Normalize();
                double   percent       = thrustPidController.NextValue(differenceMag, (lastTime - ingameTime.Time).TotalSeconds);

                percent = MathHelperD.Clamp(percent, 0, 1);

                thrustControl.ApplyForce(difference, percent);

                lastTime = ingameTime.Time;
            }
Esempio n. 2
0
            /// <summary>
            /// Calculates the output value of a PID loop, given an error and a time step.
            /// </summary>
            /// <param name="error">The difference between the Desired and Actual measurement.</param>
            /// <param name="timeStep">How long it's been since this method has been called (in seconds).</param>
            /// <returns>The value needed to correct the difference in measurement.</returns>
            public double CorrectError(double error, double timeStep)
            {
                // Derivative term
                double dInput          = error - _lastError;
                double errorDerivative = _firstRun ? 0 : dInput / timeStep;

                // Integral term
                if (!_useIntegralDecay)
                {
                    _errorIntegral += error * timeStep;
                    _errorIntegral  = MathHelperD.Clamp(_errorIntegral, _minOutput, _maxOutput);
                }
                else
                {
                    _errorIntegral = (_errorIntegral * _integralDecay) + (error * timeStep);
                }

                // Compute the output
                double output = _Kp * error + _Ki * _errorIntegral + _Kd * errorDerivative;

                // Save the error for the next use
                _lastError = error;
                _firstRun  = false;
                return(output);
            }
Esempio n. 3
0
            /// <summary>
            /// PRONAV
            /// </summary>
            /// <param name="target"></param>
            /// <returns>Heading we need to aim at</returns>
            public Vector3D Navigate(HaE_Entity target)
            {
                Vector3D targetpos = target.entityInfo.Position;

                if (target.entityInfo.HitPosition.HasValue)
                {
                    targetpos = target.entityInfo.HitPosition.Value;
                }

                Vector3D myVel = controller.control.GetShipVelocities().LinearVelocity;

                Vector3D rangeVec   = targetpos - controller.control.GetPosition();
                Vector3D closingVel = target.entityInfo.Velocity - myVel;

                Vector3D accel = CalculateAccel(rangeVec, closingVel);

                accel += -controller.control.GetNaturalGravity();                              //Gravity term

                double maxForwardAccel = ThrustUtils.GetForwardThrust(controller.thrusters, controller.control);

                maxForwardAccel /= controller.control.CalculateShipMass().PhysicalMass;

                double forwardAccel = maxForwardAccel;
                double accelMag     = accel.Normalize();

                forwardAccel -= accelMag;
                forwardAccel  = MathHelperD.Clamp(forwardAccel, 0, maxForwardAccel);

                accel *= accelMag;
                accel += Vector3D.Normalize(rangeVec) * forwardAccel;
                return(accel);
            }
Esempio n. 4
0
        public bool Update()
        {
            //time = distance / rate

            double rate = MathHelperD.Clamp(lastValue - shipData[Data.Hydrogen].Value, 0, double.MaxValue) / (p.Time - lastTime).TotalSeconds;             //rate = amount / time

            double distance = shipData[Data.Hydrogen].Value;

            double time = distance / rate;

            values[index] = time;
            index++;
            if (index >= VALUES)
            {
                index = 0;
            }

            val = values.Average();

            lastValue = shipData[Data.Hydrogen].Value;
            lastTime  = p.Time;

            if (double.IsNaN(val))
            {
                val = 0;
            }

            if (val != Value)
            {
                Value = val;
                return(true);
            }
            return(false);
        }
Esempio n. 5
0
        /*
         * /// Whip's Get Rotation Angles Method v14 - 9/25/18 ///
         * Dependencies: AngleBetween
         */

        internal static double AngleBetween(Vector3D a, Vector3D b) //returns radians
        {
            if (Vector3D.IsZero(a) || Vector3D.IsZero(b))
            {
                return(0);
            }

            return(Math.Acos(MathHelperD.Clamp(a.Dot(b) / Math.Sqrt(a.LengthSquared() * b.LengthSquared()), -1, 1)));
        }
Esempio n. 6
0
        public double Update(double error, TimeSpan sincelastupdate)
        {
            double dt = sincelastupdate.TotalSeconds;

            diff_error   = (error - last_error) / dt;
            accum_error += error * dt;
            last_error   = error;
            double value = P * error + I * accum_error + D * diff_error;

            return(MathHelperD.Clamp(value, Min, Max));
        }
Esempio n. 7
0
 public static double GetAngleBetween(Vector3D a, Vector3D b)
 {
     if (Vector3D.IsZero(a) || Vector3D.IsZero(b))
     {
         return(0);
     }
     if (Vector3D.IsUnit(ref a) && Vector3D.IsUnit(ref b))
     {
         return(Math.Acos(MathHelperD.Clamp(a.Dot(b), -1, 1)));
     }
     return(Math.Acos(MathHelperD.Clamp(a.Dot(b) / Math.Sqrt(a.LengthSquared() * b.LengthSquared()), -1, 1)));
 }
            public void ThrustToVelocity(Vector3D velocity)
            {
                Vector3D difference    = velocity - ControlVelocity;
                double   differenceMag = difference.Normalize();
                double   percent       = thrustPidController.NextValue(differenceMag, (lastTime - ingameTime.Time).TotalSeconds);

                percent = MathHelperD.Clamp(percent, 0, 1);

                thrustControl.ApplyForce(difference, percent);

                lastTime = ingameTime.Time;
            }
Esempio n. 9
0
    public void Apply(float pitch, float yaw, float roll, float dT, bool killRot = false, Vector3D?error = null)
    {
        var inputVec    = new Vector3D(-pitch, yaw, roll) * dT;
        var rotationVec = new Vector3D();

        inputVec.X  += reference.RotationIndicator.X * dT * 100;
        inputVec.Y  += reference.RotationIndicator.Y * dT * 100;
        inputVec.Z  += reference.RollIndicator * dT * 100;
        rotationVec += inputVec;
        if (killRot)
        {
            KillRotError += AngularVelocity * 200 * dT;
            if (KillRotError.Length() < .1)
            {
                KillRotError *= 0;
            }
            rotationVec += new Vector3D(
                MathHelperD.Clamp(KillRotError.X, -100, 100),
                MathHelperD.Clamp(KillRotError.Y, -100, 100),
                MathHelperD.Clamp(KillRotError.Z, -100, 100));
            KillRotError += inputVec;
            KillRotError *= 0.7f;
        }

        if (error.HasValue)
        {
            gravController.currentError.X = error.Value.X - pitch;
            gravController.currentError.Y = error.Value.Y - yaw;
            gravController.currentError.Z = error.Value.Z + roll;
            gravController.Step(dT);
            rotationVec += gravController.output;
        }

        bool applyOverride = inputVec.Length() > 0 || killRot && KillRotError.Length() != 0;

        rotationVec  *= MathHelper.RadiansPerSecondToRPM;
        rotationVec.X = MathHelper.Clamp(rotationVec.X, -300, 300);
        rotationVec.Y = MathHelper.Clamp(rotationVec.Y, -300, 300);
        rotationVec.Z = MathHelper.Clamp(rotationVec.Z, -300, 300);
        foreach (var tuple in gyrosToControl)
        {
            var gyro = tuple.Value;
            if (applyOverride)
            {
                var rotation = Vector3.TransformNormal(rotationVec, tuple.Key);
                gyro.Pitch = rotation.X;
                gyro.Yaw   = rotation.Y;
                gyro.Roll  = rotation.Z;
            }
            gyro.GyroOverride = applyOverride;
        }
    }
Esempio n. 10
0
        internal void DrawLineOffsetEffect(Vector3D pos, Vector3D direction, double tracerLength, float beamRadius, Vector4 color)
        {
            MatrixD matrix;
            var     up       = MatrixD.Identity.Up;
            var     startPos = pos + -(direction * tracerLength);

            MatrixD.CreateWorld(ref startPos, ref direction, ref up, out matrix);
            var offsetMaterial  = AmmoDef.Const.TracerMaterial;
            var tracerLengthSqr = tracerLength * tracerLength;
            var maxOffset       = AmmoDef.AmmoGraphics.Lines.OffsetEffect.MaxOffset;
            var minLength       = AmmoDef.AmmoGraphics.Lines.OffsetEffect.MinLength;
            var maxLength       = MathHelperD.Clamp(AmmoDef.AmmoGraphics.Lines.OffsetEffect.MaxLength, 0, tracerLength);

            double currentForwardDistance = 0;

            while (currentForwardDistance < tracerLength)
            {
                currentForwardDistance += MyUtils.GetRandomDouble(minLength, maxLength);
                var lateralXDistance = MyUtils.GetRandomDouble(maxOffset * -1, maxOffset);
                var lateralYDistance = MyUtils.GetRandomDouble(maxOffset * -1, maxOffset);
                Offsets.Add(new Vector3D(lateralXDistance, lateralYDistance, currentForwardDistance * -1));
            }

            for (int i = 0; i < Offsets.Count; i++)
            {
                Vector3D fromBeam;
                Vector3D toBeam;

                if (i == 0)
                {
                    fromBeam = matrix.Translation;
                    toBeam   = Vector3D.Transform(Offsets[i], matrix);
                }
                else
                {
                    fromBeam = Vector3D.Transform(Offsets[i - 1], matrix);
                    toBeam   = Vector3D.Transform(Offsets[i], matrix);
                }

                Vector3 dir     = (toBeam - fromBeam);
                var     length  = dir.Length();
                var     normDir = dir / length;
                MyTransparentGeometry.AddLineBillboard(offsetMaterial, color, fromBeam, normDir, length, beamRadius);

                if (Vector3D.DistanceSquared(matrix.Translation, toBeam) > tracerLengthSqr)
                {
                    break;
                }
            }
            Offsets.Clear();
        }
Esempio n. 11
0
        internal void Init(ProInfo info, double firstStepSize, double maxSpeed)
        {
            System     = info.System;
            AmmoDef    = info.AmmoDef;
            Ai         = info.Ai;
            IsShrapnel = info.IsShrapnel;
            if (ParentId != ulong.MaxValue)
            {
                Log.Line($"invalid avshot, parentId:{ParentId}");
            }
            ParentId        = info.Id;
            Model           = (info.AmmoDef.Const.PrimeModel || info.AmmoDef.Const.TriggerModel) ? Model = ModelState.Exists : Model = ModelState.None;
            PrimeEntity     = info.PrimeEntity;
            TriggerEntity   = info.TriggerEntity;
            Origin          = info.Origin;
            Offset          = AmmoDef.Const.OffsetEffect;
            MaxTracerLength = info.TracerLength;
            MuzzleId        = info.MuzzleId;
            WeaponId        = info.WeaponId;
            MaxSpeed        = maxSpeed;
            MaxStepSize     = MaxSpeed * MyEngineConstants.PHYSICS_STEP_SIZE_IN_SECONDS;
            ShootVelStep    = info.ShooterVel * MyEngineConstants.PHYSICS_STEP_SIZE_IN_SECONDS;
            info.Ai.WeaponBase.TryGetValue(info.Target.FiringCube, out FiringWeapon);
            MaxTrajectory = info.MaxTrajectory;
            ShotFade      = info.ShotFade;
            ShrinkInited  = false;
            HitEmitter.CanPlayLoopSounds = false;
            if (AmmoDef.Const.DrawLine)
            {
                Tracer = !AmmoDef.Const.IsBeamWeapon && firstStepSize < MaxTracerLength && !MyUtils.IsZero(firstStepSize - MaxTracerLength, 1E-01F) ? TracerState.Grow : TracerState.Full;
            }
            else
            {
                Tracer = TracerState.Off;
            }

            if (AmmoDef.Const.Trail)
            {
                MaxGlowLength  = MathHelperD.Clamp(AmmoDef.AmmoGraphics.Lines.Trail.DecayTime * MaxStepSize, 0.1f, MaxTrajectory);
                Trail          = AmmoDef.AmmoGraphics.Lines.Trail.Back ? TrailState.Back : Trail = TrailState.Front;
                GlowShrinkSize = !AmmoDef.AmmoGraphics.Lines.Trail.UseColorFade ? AmmoDef.Const.TrailWidth / AmmoDef.AmmoGraphics.Lines.Trail.DecayTime : 1f / AmmoDef.AmmoGraphics.Lines.Trail.DecayTime;
                Back           = Trail == TrailState.Back;
            }
            else
            {
                Trail = TrailState.Off;
            }
            TotalLength = MathHelperD.Clamp(MaxTracerLength + MaxGlowLength, 0.1f, MaxTrajectory);
        }
Esempio n. 12
0
        internal void LineVariableEffects()
        {
            var color = AmmoDef.AmmoGraphics.Lines.Tracer.Color;

            if (AmmoDef.Const.LineColorVariance)
            {
                var cv          = AmmoDef.AmmoGraphics.Lines.ColorVariance;
                var randomValue = MyUtils.GetRandomFloat(cv.Start, cv.End);
                color.X *= randomValue;
                color.Y *= randomValue;
                color.Z *= randomValue;
            }
            Color = color;
            var tracerWidth = AmmoDef.AmmoGraphics.Lines.Tracer.Width;
            var trailWidth  = AmmoDef.Const.TrailWidth;

            if (AmmoDef.Const.LineWidthVariance)
            {
                var wv          = AmmoDef.AmmoGraphics.Lines.WidthVariance;
                var randomValue = MyUtils.GetRandomFloat(wv.Start, wv.End);
                tracerWidth += randomValue;
                if (AmmoDef.AmmoGraphics.Lines.Trail.UseWidthVariance)
                {
                    trailWidth += randomValue;
                }
            }

            var target = TracerFront + (-Direction * TotalLength);

            ClosestPointOnLine = MyUtils.GetClosestPointOnLine(ref TracerFront, ref target, ref Ai.Session.CameraPos);
            DistanceToLine     = (float)Vector3D.Distance(ClosestPointOnLine, Ai.Session.CameraMatrix.Translation);

            if (AmmoDef.Const.IsBeamWeapon && Vector3D.DistanceSquared(TracerFront, TracerBack) > 640000)
            {
                target             = TracerFront + (-Direction * (TotalLength - MathHelperD.Clamp(DistanceToLine * 6, DistanceToLine, MaxTrajectory * 0.5)));
                ClosestPointOnLine = MyUtils.GetClosestPointOnLine(ref TracerFront, ref target, ref Ai.Session.CameraPos);
                DistanceToLine     = (float)Vector3D.Distance(ClosestPointOnLine, Ai.Session.CameraMatrix.Translation);
            }

            double scale = 0.1f;

            ScaleFov    = Math.Tan(MyAPIGateway.Session.Camera.FovWithZoom * 0.5);
            TracerWidth = Math.Max(tracerWidth, scale * ScaleFov * (DistanceToLine / 100));
            TrailWidth  = Math.Max(trailWidth, scale * ScaleFov * (DistanceToLine / 100));
            TrailScaler = ((float)TrailWidth / trailWidth);
        }
Esempio n. 13
0
        private double CalcAccelToStopAtPos(double deltaPos, double curSpd, double maxAccel, double posAccuracy, double AccelPerDeltaPosFactor)
        {
            double accel;
            double absDeltaPos = Math.Abs(deltaPos);
            //if (absDeltaPos >= posAccuracy)
            //{
            int signDeltaPos = Math.Sign(deltaPos);

            if (Math.Sign(curSpd) != signDeltaPos)
            {
                //удаляемся или не движемся
                //accel = maxAccel * signDeltaPos;
                accel = MathHelperD.Clamp(AccelPerDeltaPosFactor * deltaPos * maxAccel, -maxAccel, maxAccel);
                ToLog("\nудаляемся", true);
            }
            else
            {
                //приближаемся, оценим тормозной путь
                double temp        = 0.5 * curSpd * curSpd;
                double brakingDist = temp / maxAccel;
                ToLog("\nbrakingDist: " + brakingDist.ToString("#0.000"), true);
                if (absDeltaPos >= brakingDist)
                {
                    //еще успеем затормозить, поэтому даем максимальное ускорение
                    //accel = maxAccel * signDeltaPos;
                    accel = MathHelperD.Clamp(AccelPerDeltaPosFactor * deltaPos * maxAccel, -maxAccel, maxAccel);
                    ToLog("\nеще успеем: " + absDeltaPos.ToString("#0.00000") + " / " + brakingDist.ToString("#0.00000"), true);
                }
                else
                {
                    //уменьшаем ускорение
                    accel = -temp / deltaPos;
                    ToLog("\nуменьш: " + accel.ToString("#0.000"), true);
                }
            }
            //}
            //else
            //{
            //    accel = AccelPerDeltaPosFactor * deltaPos * maxAccel;
            //    ToLog("\n!!!",true);
            //}
            return(accel);
        }
Esempio n. 14
0
 // check value, set random value if allowed and value not set
 protected float CheckValue(float value, bool randomize, float minValue, float maxValue, TimeSpan duration, string description)
 {
     // overcast
     if (value < 0 && randomize)
     {
         value = (random.Next((int)maxValue * 100) / 100);  // ensure there is a value if range is 0 - 1
     }
     else
     {
         float correctedValue = (float)MathHelperD.Clamp(value, minValue, maxValue);
         if (correctedValue != value)
         {
             Trace.TraceInformation("Invalid value for {0} for weather at {1} : {2}; value must be between {3} and {4}, clamped to {5}",
                                    description, duration.ToString(), value, minValue, maxValue, correctedValue);
             value = correctedValue;
         }
     }
     return(value);
 }
Esempio n. 15
0
        internal void PrepOffsetEffect(Vector3D tracerStart, Vector3D direction, double tracerLength)
        {
            var up       = MatrixD.Identity.Up;
            var startPos = tracerStart + -(direction * tracerLength);

            MatrixD.CreateWorld(ref startPos, ref direction, ref up, out OffsetMatrix);
            TracerLengthSqr = tracerLength * tracerLength;
            var maxOffset = AmmoDef.AmmoGraphics.Lines.OffsetEffect.MaxOffset;
            var minLength = AmmoDef.AmmoGraphics.Lines.OffsetEffect.MinLength;
            var maxLength = MathHelperD.Clamp(AmmoDef.AmmoGraphics.Lines.OffsetEffect.MaxLength, 0, tracerLength);

            double currentForwardDistance = 0;

            while (currentForwardDistance <= tracerLength)
            {
                currentForwardDistance += MyUtils.GetRandomDouble(minLength, maxLength);
                var lateralXDistance = MyUtils.GetRandomDouble(maxOffset * -1, maxOffset);
                var lateralYDistance = MyUtils.GetRandomDouble(maxOffset * -1, maxOffset);
                Offsets.Add(new Vector3D(lateralXDistance, lateralYDistance, currentForwardDistance * -1));
            }
        }
Esempio n. 16
0
        private static double SignalDamper(double signal, double maxSignal, double value, double maxValue, double beginDamperWorkFactor)
        {
            double resault = signal;

            double beginDamperWork = beginDamperWorkFactor * maxValue;
            double absValue        = Math.Abs(value);

            if (absValue > beginDamperWork && Math.Sign(signal) == Math.Sign(value))
            {
                double damperWidth  = maxValue - beginDamperWork;
                double damperFactor = MathHelperD.Clamp((maxValue - absValue) / damperWidth, -1.0, 1.0);
                if (damperFactor >= 0.0)
                {
                    resault = signal * damperFactor;
                }
                else
                {
                    resault = maxSignal * damperFactor;
                }
            }

            return(resault);
        }
Esempio n. 17
0
            private Vector3D HPN()
            {
                double lambda  = LOSRate;
                double gamma   = (PGAIN * LOSRate);
                float  cos     = MyMath.FastCos((float)gamma - (float)lambda);
                double IPNGain = (RelativeVelocityVec.Length() * PGAIN) / (MissileVelocityVec.Length() * cos);

                IPNGain = MathHelperD.Clamp(IPNGain, MINN, MAXN);
                IPNGain = (!double.IsNaN(IPNGain)) ? IPNGain : PGAIN;

                DebugEcho($"IPNGain: {IPNGain:#.###}");


                Vector3D accelerationNormal;

                accelerationNormal  = IPNGain * RelativeVelocityVec.Cross(CalculateRotVec());       //PPN term
                accelerationNormal += IPNGain * TargetAccel / 2;                                    //APN term
                accelerationNormal += IPNGain * LosDelta;                                           //HPN term
                accelerationNormal += -rc.GetNaturalGravity();                                      //Gravity term
                accelerationNormal += NewLos;                                                       //LosBias term

                return(accelerationNormal);
            }
Esempio n. 18
0
        private void DamageVoxel(HitEntity hitEnt, ProInfo info)
        {
            var entity  = hitEnt.Entity;
            var destObj = hitEnt.Entity as MyVoxelBase;

            if (destObj == null || entity == null || !hitEnt.HitPos.HasValue)
            {
                return;
            }
            var shieldHeal = info.AmmoDef.DamageScales.Shields.Type == ShieldDef.ShieldType.Heal;

            if (!info.AmmoDef.Const.VoxelDamage || shieldHeal)
            {
                info.BaseDamagePool = 0;
                return;
            }

            using (destObj.Pin())
            {
                var detonateOnEnd = info.AmmoDef.Const.AmmoAreaEffect && info.AmmoDef.AreaEffect.Detonation.DetonateOnEnd && info.AmmoDef.AreaEffect.AreaEffect != AreaEffectType.Radiant;

                info.ObjectsHit++;
                float damageScale = 1;
                if (info.AmmoDef.Const.VirtualBeams)
                {
                    damageScale *= info.WeaponCache.Hits;
                }

                var scaledDamage = info.BaseDamagePool * damageScale;
                var fallOff      = info.AmmoDef.Const.FallOffScaling && info.DistanceTraveled > info.AmmoDef.DamageScales.FallOff.Distance;
                if (fallOff)
                {
                    var fallOffMultipler = (float)MathHelperD.Clamp(1.0 - ((info.DistanceTraveled - info.AmmoDef.DamageScales.FallOff.Distance) / (info.AmmoDef.Const.MaxTrajectory - info.AmmoDef.DamageScales.FallOff.Distance)), info.AmmoDef.DamageScales.FallOff.MinMultipler, 1);
                    scaledDamage *= fallOffMultipler;
                }

                var oRadius       = info.AmmoDef.AreaEffect.AreaEffectRadius;
                var minTestRadius = info.DistanceTraveled - info.PrevDistanceTraveled;
                var tRadius       = oRadius < minTestRadius ? minTestRadius : oRadius;
                var objHp         = (int)MathHelper.Clamp(MathFuncs.VolumeCube(MathFuncs.LargestCubeInSphere(tRadius)), 1, double.MaxValue);
                var sync          = MpActive && IsServer;

                if (tRadius > 5)
                {
                    objHp *= 5;
                }
                if (scaledDamage < objHp)
                {
                    var reduceBy = objHp / scaledDamage;
                    oRadius /= reduceBy;
                    if (oRadius < 1)
                    {
                        oRadius = 1;
                    }

                    info.BaseDamagePool = 0;
                }
                else
                {
                    info.BaseDamagePool -= objHp;
                    if (oRadius < minTestRadius)
                    {
                        oRadius = minTestRadius;
                    }
                }
                destObj.PerformCutOutSphereFast(hitEnt.HitPos.Value, (float)oRadius, true);

                if (detonateOnEnd)
                {
                    var det     = info.AmmoDef.AreaEffect.Detonation;
                    var dRadius = det.DetonationRadius;
                    var dObjHp  = (int)MathHelper.Clamp(MathFuncs.VolumeCube(MathFuncs.LargestCubeInSphere(dRadius)), 1, double.MaxValue);
                    if (dRadius > 5)
                    {
                        dObjHp *= 5;
                    }
                    dObjHp *= 5;
                    var dDamage  = det.DetonationDamage;
                    var reduceBy = dObjHp / dDamage;

                    dRadius /= reduceBy;
                    if (dRadius < 1.5)
                    {
                        dRadius = 1.5f;
                    }
                    if (sync)
                    {
                        destObj.PerformCutOutSphereFast(hitEnt.HitPos.Value, dRadius, true);
                    }
                }
            }
        }
Esempio n. 19
0
        internal void Run()
        {
            if (Session.Tick180)
            {
                Log.LineShortDate($"(DRAWS) --------------- AvShots:[{AvShots.Count}] OnScreen:[{_onScreens}] Shrinks:[{_shrinks}] Glows:[{_glows}] Models:[{_models}] P:[{Session.Projectiles.ActiveProjetiles.Count}] P-Pool:[{Session.Projectiles.ProjectilePool.Count}] AvPool:[{AvShotPool.Count}] (AvBarrels 1:[{AvBarrels1.Count}] 2:[{AvBarrels2.Count}])", "stats");
                _glows   = 0;
                _shrinks = 0;
            }

            _onScreens = 0;
            _models    = 0;
            for (int i = AvShots.Count - 1; i >= 0; i--)
            {
                var av = AvShots[i];
                if (av.OnScreen != AvShot.Screen.None)
                {
                    _onScreens++;
                }
                var refreshed = av.LastTick == Session.Tick;

                if (refreshed && av.Tracer != AvShot.TracerState.Off && av.OnScreen != AvShot.Screen.None)
                {
                    var color    = av.Color;
                    var segColor = av.SegmentColor;

                    if (av.ShotFade > 0)
                    {
                        var fade = MathHelper.Clamp(1f - av.ShotFade, 0.005f, 1f);
                        color    *= fade;
                        segColor *= fade;
                    }

                    if (!av.AmmoDef.Const.OffsetEffect)
                    {
                        if (av.Tracer != AvShot.TracerState.Shrink)
                        {
                            if (av.AmmoDef.Const.TracerMode == AmmoConstants.Texture.Normal)
                            {
                                MyTransparentGeometry.AddLineBillboard(av.AmmoDef.Const.TracerTextures[0], color, av.TracerBack, av.PointDir, (float)av.VisualLength, (float)av.TracerWidth);
                            }
                            else if (av.AmmoDef.Const.TracerMode != AmmoConstants.Texture.Resize)
                            {
                                MyTransparentGeometry.AddLineBillboard(av.AmmoDef.Const.TracerTextures[av.TextureIdx], color, av.TracerBack, av.PointDir, (float)av.VisualLength, (float)av.TracerWidth);
                            }
                            else
                            {
                                var    seg           = av.AmmoDef.AmmoGraphics.Lines.Tracer.Segmentation;
                                var    stepPos       = av.TracerBack;
                                var    segTextureCnt = av.AmmoDef.Const.SegmentTextures.Length;
                                var    gapTextureCnt = av.AmmoDef.Const.TracerTextures.Length;
                                var    segStepLen    = seg.SegmentLength / segTextureCnt;
                                var    gapStepLen    = seg.SegmentGap / gapTextureCnt;
                                var    gapEnabled    = gapStepLen > 0;
                                int    j             = 0;
                                double travel        = 0;
                                while (travel < av.VisualLength)
                                {
                                    var mod   = j++ % 2;
                                    var gap   = gapEnabled && (av.SegmentGaped && mod == 0 || !av.SegmentGaped && mod == 1);
                                    var first = travel <= 0;

                                    double  width;
                                    double  rawLen;
                                    Vector4 dyncColor;
                                    if (!gap)
                                    {
                                        rawLen    = first ? av.SegmentLenTranserved : seg.SegmentLength;
                                        width     = av.SegmentWidth;
                                        dyncColor = segColor;
                                    }
                                    else
                                    {
                                        rawLen    = first ? av.SegmentLenTranserved : seg.SegmentGap;
                                        width     = av.TracerWidth;
                                        dyncColor = color;
                                    }

                                    var notLast   = travel + rawLen < av.VisualLength;
                                    var len       = notLast ? rawLen : av.VisualLength - travel;
                                    var clampStep = !gap?MathHelperD.Clamp((int)((len / segStepLen) + 0.5) - 1, 0, segTextureCnt - 1) : MathHelperD.Clamp((int)((len / gapStepLen) + 0.5) - 1, 0, gapTextureCnt);

                                    var material = !gap ? av.AmmoDef.Const.SegmentTextures[(int)clampStep] : av.AmmoDef.Const.TracerTextures[(int)clampStep];

                                    MyTransparentGeometry.AddLineBillboard(material, dyncColor, stepPos, av.PointDir, (float)len, (float)width);
                                    if (!notLast)
                                    {
                                        travel = av.VisualLength;
                                    }
                                    else
                                    {
                                        travel += len;
                                    }
                                    stepPos += (av.PointDir * len);
                                }
                            }
                        }
                    }
                    else
                    {
                        var list = av.Offsets;
                        for (int x = 0; x < list.Count; x++)
                        {
                            Vector3D fromBeam;
                            Vector3D toBeam;

                            if (x == 0)
                            {
                                fromBeam = av.OffsetMatrix.Translation;
                                toBeam   = Vector3D.Transform(list[x], av.OffsetMatrix);
                            }
                            else
                            {
                                fromBeam = Vector3D.Transform(list[x - 1], av.OffsetMatrix);
                                toBeam   = Vector3D.Transform(list[x], av.OffsetMatrix);
                            }

                            Vector3 dir     = (toBeam - fromBeam);
                            var     length  = dir.Length();
                            var     normDir = dir / length;
                            MyTransparentGeometry.AddLineBillboard(av.AmmoDef.Const.TracerTextures[0], color, fromBeam, normDir, length, (float)av.TracerWidth);

                            if (Vector3D.DistanceSquared(av.OffsetMatrix.Translation, toBeam) > av.TracerLengthSqr)
                            {
                                break;
                            }
                        }
                        list.Clear();
                    }
                }

                var shrinkCnt = av.TracerShrinks.Count;
                if (shrinkCnt > _shrinks)
                {
                    _shrinks = shrinkCnt;
                }

                if (shrinkCnt > 0)
                {
                    RunShrinks(av);
                }

                var glowCnt = av.GlowSteps.Count;

                if (glowCnt > _glows)
                {
                    _glows = glowCnt;
                }

                if (av.Trail != AvShot.TrailState.Off)
                {
                    var steps       = av.AmmoDef.AmmoGraphics.Lines.Trail.DecayTime;
                    var widthScaler = !av.AmmoDef.AmmoGraphics.Lines.Trail.UseColorFade;
                    var remove      = false;
                    for (int j = glowCnt - 1; j >= 0; j--)
                    {
                        var glow = av.GlowSteps[j];

                        if (!refreshed)
                        {
                            glow.Line = new LineD(glow.Line.From + av.ShootVelStep, glow.Line.To + av.ShootVelStep, glow.Line.Length);
                        }

                        if (av.OnScreen != AvShot.Screen.None)
                        {
                            var reduction = (av.GlowShrinkSize * glow.Step);
                            var width     = widthScaler ? (av.AmmoDef.Const.TrailWidth - reduction) * av.TrailScaler : av.AmmoDef.Const.TrailWidth * av.TrailScaler;
                            var color     = av.AmmoDef.AmmoGraphics.Lines.Trail.Color;

                            if (!widthScaler)
                            {
                                color *= MathHelper.Clamp(1f - reduction, 0.01f, 1f);
                            }

                            MyTransparentGeometry.AddLineBillboard(av.AmmoDef.Const.TrailTextures[0], color, glow.Line.From, glow.Line.Direction, (float)glow.Line.Length, width);
                        }

                        if (++glow.Step >= steps)
                        {
                            glow.Parent = null;
                            glow.Step   = 0;
                            remove      = true;
                            glowCnt--;
                            Glows.Push(glow);
                        }
                    }

                    if (remove)
                    {
                        av.GlowSteps.Dequeue();
                    }
                }

                if (glowCnt == 0 && shrinkCnt == 0 && av.MarkForClose)
                {
                    AvShotPool.Return(av);
                    AvShots.RemoveAtFast(i);
                }
            }
        }
Esempio n. 20
0
 /// <summary>
 /// Sets the animation to a particular frame whilst clamping it to the frame count range.
 /// </summary>
 public void SetFrameClamp(double frame)
 {
     SetFrame(MathHelperD.Clamp(frame, 0, FrameCount));
 }
Esempio n. 21
0
        private void DamageShield(HitEntity hitEnt, ProInfo info)
        {
            var shield = hitEnt.Entity as IMyTerminalBlock;

            if (shield == null || !hitEnt.HitPos.HasValue)
            {
                return;
            }
            info.ObjectsHit++;

            var damageScale = 1;
            var fallOff     = info.AmmoDef.Const.FallOffScaling && info.DistanceTraveled > info.AmmoDef.DamageScales.FallOff.Distance;

            if (info.AmmoDef.Const.VirtualBeams)
            {
                damageScale *= info.WeaponCache.Hits;
            }
            var damageType   = info.AmmoDef.DamageScales.Shields.Type;
            var energy       = damageType == ShieldDef.ShieldType.Energy;
            var heal         = damageType == ShieldDef.ShieldType.Heal;
            var shieldByPass = info.AmmoDef.DamageScales.Shields.Type == ShieldDef.ShieldType.Bypass;

            var areaEffect    = info.AmmoDef.AreaEffect;
            var detonateOnEnd = info.AmmoDef.AreaEffect.Detonation.DetonateOnEnd && areaEffect.AreaEffect != AreaEffectType.Disabled && !shieldByPass;
            var areaDamage    = areaEffect.AreaEffect != AreaEffectType.Disabled ? areaEffect.AreaEffectDamage * (areaEffect.AreaEffectRadius * 0.5f) : 0;
            var scaledDamage  = (((info.BaseDamagePool * damageScale) + areaDamage) * info.AmmoDef.Const.ShieldModifier) * info.AmmoDef.Const.ShieldBypassMod;

            if (fallOff)
            {
                var fallOffMultipler = MathHelperD.Clamp(1.0 - ((info.DistanceTraveled - info.AmmoDef.DamageScales.FallOff.Distance) / (info.AmmoDef.Const.MaxTrajectory - info.AmmoDef.DamageScales.FallOff.Distance)), info.AmmoDef.DamageScales.FallOff.MinMultipler, 1);
                scaledDamage *= fallOffMultipler;
            }

            var detonateDamage = detonateOnEnd ? (areaEffect.Detonation.DetonationDamage * (areaEffect.Detonation.DetonationRadius * 0.5f)) * info.AmmoDef.Const.ShieldModifier : 0;

            var combinedDamage = (float)(scaledDamage + detonateDamage);

            if (heal)
            {
                combinedDamage *= -1;
            }

            var hit = SApi.PointAttackShieldExt(shield, hitEnt.HitPos.Value, info.Target.FiringCube.EntityId, combinedDamage, energy, info.AmmoDef.AmmoGraphics.ShieldHitDraw);

            if (hit.HasValue)
            {
                if (heal)
                {
                    info.BaseDamagePool = 0;
                    return;
                }
                var objHp = hit.Value;
                if (info.EwarActive)
                {
                    info.BaseHealthPool -= 1;
                }
                else if (objHp > 0)
                {
                    if (!shieldByPass)
                    {
                        info.BaseDamagePool = 0;
                    }
                    else
                    {
                        info.BaseDamagePool *= info.AmmoDef.Const.ShieldBypassMod;
                    }
                }
                else
                {
                    info.BaseDamagePool = (objHp * -1);
                }
                if (info.AmmoDef.Mass <= 0)
                {
                    return;
                }

                var speed = info.AmmoDef.Trajectory.DesiredSpeed > 0 ? info.AmmoDef.Trajectory.DesiredSpeed : 1;
                ApplyProjectileForce((MyEntity)shield.CubeGrid, hitEnt.HitPos.Value, hitEnt.Intersection.Direction, info.AmmoDef.Mass * speed);
            }
        }
Esempio n. 22
0
        internal static void DeferedAvStateUpdates(Session s)
        {
            for (int x = 0; x < s.Projectiles.DeferedAvDraw.Count; x++)
            {
                var d = s.Projectiles.DeferedAvDraw[x];
                var i = d.Info;
                var a = i.AvShot;

                var lineEffect = a.AmmoDef.Const.Trail || a.AmmoDef.Const.DrawLine;
                var saveHit    = d.Hit;
                ++a.LifeTime;
                a.LastTick       = s.Tick;
                a.StepSize       = d.StepSize;
                a.EstTravel      = a.StepSize * a.LifeTime;
                a.ShortStepSize  = d.ShortStepSize ?? d.StepSize;
                a.ShortEstTravel = MathHelperD.Clamp((a.EstTravel - a.StepSize) + a.ShortStepSize, 0, double.MaxValue);

                a.VisualLength = d.VisualLength;
                a.TracerFront  = d.TracerFront;
                a.Direction    = i.Direction;
                a.PointDir     = !saveHit && !a.Back && a.GlowSteps.Count > 0 ? a.GlowSteps[a.GlowSteps.Count - 1].Line.Direction : i.VisualDir;
                a.TracerBack   = a.TracerFront + (-a.Direction * a.VisualLength);

                a.OnScreen = Screen.None; // clear OnScreen
                if (i.ModelOnly)
                {
                    a.ModelSphereCurrent.Center = a.TracerFront;
                    if (a.Triggered)
                    {
                        a.ModelSphereCurrent.Radius = i.TriggerGrowthSteps < a.AmmoDef.Const.AreaEffectSize ? a.TriggerMatrix.Scale.AbsMax() : a.AmmoDef.Const.AreaEffectSize;
                    }

                    if (s.Camera.IsInFrustum(ref a.ModelSphereCurrent))
                    {
                        a.OnScreen = Screen.ModelOnly;
                    }
                }
                else if (lineEffect || a.Model == ModelState.None && a.AmmoDef.Const.AmmoParticle)
                {
                    var rayTracer = new RayD(a.TracerBack, a.PointDir);
                    var rayTrail  = new RayD(a.TracerFront + (-a.Direction * a.ShortEstTravel), a.Direction);

                    //DsDebugDraw.DrawRay(rayTracer, VRageMath.Color.White, 0.25f, (float) VisualLength);
                    //DsDebugDraw.DrawRay(rayTrail, VRageMath.Color.Orange, 0.25f, (float)ShortEstTravel);

                    double?dist;
                    s.CameraFrustrum.Intersects(ref rayTracer, out dist);

                    if (dist != null && dist <= a.VisualLength)
                    {
                        a.OnScreen = Screen.Tracer;
                    }
                    else if (a.AmmoDef.Const.Trail)
                    {
                        s.CameraFrustrum.Intersects(ref rayTrail, out dist);
                        if (dist != null && dist <= a.ShortEstTravel + a.ShortStepSize)
                        {
                            a.OnScreen = Screen.Trail;
                        }
                    }

                    if (a.OnScreen != Screen.None && !a.TrailActivated && a.AmmoDef.Const.Trail)
                    {
                        a.TrailActivated = true;
                    }

                    if (a.OnScreen == Screen.None && a.TrailActivated)
                    {
                        a.OnScreen = Screen.Trail;
                    }

                    if (a.Model != ModelState.None)
                    {
                        a.ModelSphereCurrent.Center = a.TracerFront;
                        if (a.Triggered)
                        {
                            a.ModelSphereCurrent.Radius = i.TriggerGrowthSteps < a.AmmoDef.Const.AreaEffectSize ? a.TriggerMatrix.Scale.AbsMax() : a.AmmoDef.Const.AreaEffectSize;
                        }

                        if (a.OnScreen == Screen.None && s.Camera.IsInFrustum(ref a.ModelSphereCurrent))
                        {
                            a.OnScreen = Screen.ModelOnly;
                        }
                    }
                }
                if (a.OnScreen == Screen.None && Vector3D.DistanceSquared(a.TracerFront, a.Ai.Session.CameraPos) <= 225)
                {
                    a.OnScreen = Screen.InProximity;
                }


                if (i.MuzzleId == -1)
                {
                    return;
                }

                if (saveHit)
                {
                    a.HitVelocity = a.Hit.HitVelocity;
                    a.Hitting     = !a.ShrinkInited;
                }
                a.LastStep = a.Hitting || MyUtils.IsZero(a.MaxTrajectory - a.ShortEstTravel, 1E-01F);

                if (a.AmmoDef.Const.DrawLine)
                {
                    if (a.AmmoDef.Const.IsBeamWeapon || !saveHit && MyUtils.IsZero(a.MaxTracerLength - a.VisualLength, 1E-01F))
                    {
                        a.Tracer = TracerState.Full;
                    }
                    else if (a.Tracer != TracerState.Off && a.VisualLength <= 0)
                    {
                        a.Tracer = TracerState.Off;
                    }
                    else if (a.Hitting && !i.ModelOnly && lineEffect && a.VisualLength / a.StepSize > 1 && !MyUtils.IsZero(a.EstTravel - a.ShortEstTravel, 1E-01F))
                    {
                        a.Tracer      = TracerState.Shrink;
                        a.TotalLength = MathHelperD.Clamp(a.VisualLength + a.MaxGlowLength, 0.1f, Vector3D.Distance(a.Origin, a.TracerFront));
                    }
                    else if (a.Tracer == TracerState.Grow && a.LastStep)
                    {
                        a.Tracer = TracerState.Full;
                    }
                }

                var lineOnScreen = a.OnScreen > (Screen)2;

                if (lineEffect && (a.Active || lineOnScreen))
                {
                    a.LineVariableEffects();
                }

                if (a.Tracer != TracerState.Off && lineOnScreen)
                {
                    if (a.Tracer == TracerState.Shrink && !a.ShrinkInited)
                    {
                        a.Shrink();
                    }
                    else if (a.AmmoDef.Const.IsBeamWeapon && a.Hitting && a.AmmoDef.Const.HitParticle && !(a.MuzzleId != 0 && (a.AmmoDef.Const.ConvergeBeams || a.AmmoDef.Const.OneHitParticle)))
                    {
                        ContainmentType containment;
                        s.CameraFrustrum.Contains(ref a.Hit.HitPos, out containment);
                        if (containment != ContainmentType.Disjoint)
                        {
                            a.RunBeam();
                        }
                    }

                    if (a.AmmoDef.Const.OffsetEffect)
                    {
                        a.PrepOffsetEffect(a.TracerFront, a.PointDir, a.VisualLength);
                    }
                }

                var backAndGrowing = a.Back && a.Tracer == TracerState.Grow;
                if (a.Trail != TrailState.Off && !backAndGrowing && lineOnScreen)
                {
                    a.RunGlow(ref a.EmptyShrink);
                }

                if (!a.Active && a.OnScreen != Screen.None)
                {
                    a.Active = true;
                    s.Av.AvShots.Add(a);
                }
                a.Hitting = false;
            }
            s.Projectiles.DeferedAvDraw.Clear();
        }
Esempio n. 23
0
        internal static bool WeaponLookAt(Weapon weapon, ref Vector3D targetDir, double targetDistSqr, bool setWeapon, bool canSeeOnly, out bool isTracking)
        {
            var system = weapon.System;
            var target = weapon.Target;

            isTracking = false;
            //Get weapon direction and orientation
            Vector3D currentVector;

            Vector3D.CreateFromAzimuthAndElevation(weapon.Azimuth, weapon.Elevation, out currentVector);
            Vector3D.Rotate(ref currentVector, ref weapon.WeaponConstMatrix, out currentVector);

            var      up = weapon.MyPivotUp;
            Vector3D left;

            Vector3D.Cross(ref up, ref currentVector, out left);
            if (!Vector3D.IsUnit(ref left) && !Vector3D.IsZero(left))
            {
                left.Normalize();
            }
            Vector3D forward;

            Vector3D.Cross(ref left, ref up, out forward);
            var constraintMatrix = new MatrixD {
                Forward = forward, Left = left, Up = up,
            };

            // ugly as sin inlined compute GetRotationAngles + AngleBetween, returning the desired az/el doubles;
            var      transposeMatrix = MatrixD.Transpose(constraintMatrix);
            Vector3D localTargetVector;

            Vector3D.TransformNormal(ref targetDir, ref transposeMatrix, out localTargetVector);
            var flattenedTargetVector = new Vector3D(localTargetVector.X, 0, localTargetVector.Z);
            var azVecIsZero           = Vector3D.IsZero(flattenedTargetVector);
            var flatSqr = flattenedTargetVector.LengthSquared();

            var desiredAzimuth = azVecIsZero ? 0 : Math.Acos(MathHelperD.Clamp(-flattenedTargetVector.Z / Math.Sqrt(flatSqr), -1, 1)) * -Math.Sign(localTargetVector.X); //right is positive;

            if (Math.Abs(desiredAzimuth) < 1E-6 && localTargetVector.Z > 0)                                                                                              //check for straight back case
            {
                desiredAzimuth = Math.PI;
            }

            double desiredElevation;

            if (Vector3D.IsZero(flattenedTargetVector)) //check for straight up case
            {
                desiredElevation = MathHelper.PiOver2 * Math.Sign(localTargetVector.Y);
            }
            else
            {
                var elVecIsZero = Vector3D.IsZero(localTargetVector) || Vector3D.IsZero(flattenedTargetVector);
                desiredElevation = elVecIsZero ? 0 : Math.Acos(MathHelperD.Clamp(localTargetVector.Dot(flattenedTargetVector) / Math.Sqrt(localTargetVector.LengthSquared() * flatSqr), -1, 1)) * Math.Sign(localTargetVector.Y); //up is positive
            }

            // return result of desired values being in tolerances
            if (canSeeOnly)
            {
                if (weapon.Azimuth + desiredAzimuth > weapon.MaxAzToleranceRadians && weapon.MaxAzToleranceRadians < Math.PI)
                {
                    return(false);
                }

                if (weapon.Azimuth + desiredAzimuth < weapon.MinAzToleranceRadians && weapon.MinAzToleranceRadians > -Math.PI)
                {
                    return(false);
                }

                if (desiredElevation < weapon.MinElToleranceRadians || desiredElevation > weapon.MaxElToleranceRadians)
                {
                    return(false);
                }

                return(true);
            }

            // check for backAround constraint
            double azToTraverse;

            if (weapon.MaxAzToleranceRadians < Math.PI && weapon.MinAzToleranceRadians > -Math.PI)
            {
                var azAngle = weapon.Azimuth + desiredAzimuth;
                if (azAngle > Math.PI)
                {
                    azAngle -= MathHelperD.TwoPi;
                }
                else if (azAngle < -Math.PI)
                {
                    azAngle = MathHelperD.TwoPi + azAngle;
                }
                azToTraverse = azAngle - weapon.Azimuth;
            }
            else
            {
                azToTraverse = desiredAzimuth;
            }

            // Clamp step within limits.
            var azStep = MathHelperD.Clamp(azToTraverse, -system.AzStep, system.AzStep);
            var elStep = MathHelperD.Clamp(desiredElevation - weapon.Elevation, -system.ElStep, system.ElStep);

            // epsilon based on target type and distance
            var epsilon = target.IsProjectile || system.Session.Tick120 ? 1E-06d : targetDistSqr <= 640000 ? 1E-03d : targetDistSqr <= 3240000 ? 1E-04d : 1E-05d;

            // check if step is within epsilon of zero;
            var azLocked = MyUtils.IsZero(azStep, (float)epsilon);
            var elLocked = MyUtils.IsZero(elStep, (float)epsilon);

            // are az and el both within tolerance of target
            var locked = azLocked && elLocked;

            // Compute actual angle to rotate subparts
            var az = weapon.Azimuth + azStep;
            var el = weapon.Elevation + elStep;

            // This is where we should clamp. az and el are measured relative the WorldMatrix.Forward.
            // desiredAzimuth is measured off of the CURRENT heading of the barrel. The limits are based off of
            // WorldMatrix.Forward as well.
            var azHitLimit = false;
            var elHitLimit = false;

            // Check azimuth angles
            if (az > weapon.MaxAzToleranceRadians && weapon.MaxAzToleranceRadians < Math.PI)
            {
                // Hit upper azimuth limit
                az         = weapon.MaxAzToleranceRadians;
                azHitLimit = true;
            }
            else if (az < weapon.MinAzToleranceRadians && weapon.MinAzToleranceRadians > -Math.PI)
            {
                // Hit lower azimuth limit
                az         = weapon.MinAzToleranceRadians;
                azHitLimit = true;
            }

            // Check elevation angles
            if (el > weapon.MaxElToleranceRadians)
            {
                // Hit upper elevation limit
                el         = weapon.MaxElToleranceRadians;
                elHitLimit = true;
            }
            else if (el < weapon.MinElToleranceRadians)
            {
                // Hit lower elevation limit
                el         = weapon.MinElToleranceRadians;
                elHitLimit = true;
            }


            // Weapon has a degree of freedom to move towards target
            var tracking = !azHitLimit && !elHitLimit;

            if (setWeapon)
            {
                isTracking = tracking;

                if (!azLocked)
                {
                    weapon.Azimuth     = az;
                    weapon.AzimuthTick = system.Session.Tick;
                }

                if (!elLocked)
                {
                    weapon.Elevation     = el;
                    weapon.ElevationTick = system.Session.Tick;
                }
            }


            return(!locked);
        }
Esempio n. 24
0
        /// <summary>
        /// SkyDrawer constructor
        /// </summary>
        public MSTSSkyDrawer(Viewer viewer)
        {
            MSTSSkyViewer   = viewer;
            MSTSSkyMaterial = viewer.MaterialManager.Load("MSTSSky");
            // Instantiate classes
            MSTSSkyMesh    = new MSTSSkyMesh(MSTSSkyViewer.RenderProcess);
            MSTSSkyVectors = new SunMoonPos();

            //viewer.World.MSTSSky.MSTSSkyMaterial.Viewer.MaterialManager.sunDirection.Y < 0
            // Set default values
            mstsskyseasonType = (int)MSTSSkyViewer.Simulator.Season;
            date.ordinalDate  = 82 + mstsskyseasonType * 91;
            // TODO: Set the following three externally from ORTS route files (future)
            date.month = 1 + date.ordinalDate / 30;
            date.day   = 21;
            date.year  = 2010;
            // Default wind speed and direction
            mstsskywindSpeed     = 5.0f; // m/s (approx 11 mph)
            mstsskywindDirection = 4.7f; // radians (approx 270 deg, i.e. westerly)

            // The following keyboard commands are used for viewing sky and weather effects in "demo" mode.
            // Control- and Control+ for overcast, Shift- and Shift+ for fog and - and + for time.

            // Don't let multiplayer clients adjust the weather.
            if (!MPManager.IsClient())
            {
                // Overcast ranges from 0 (completely clear) to 1 (completely overcast).
                viewer.UserCommandController.AddEvent(UserCommand.DebugOvercastIncrease, KeyEventType.KeyDown, (GameTime gameTIme) =>
                {
                    mstsskyovercastFactor = (float)MathHelperD.Clamp(mstsskyovercastFactor + gameTIme.ElapsedGameTime.TotalSeconds / 10, 0, 1);
                });
                viewer.UserCommandController.AddEvent(UserCommand.DebugOvercastDecrease, KeyEventType.KeyDown, (GameTime gameTIme) =>
                {
                    mstsskyovercastFactor = (float)MathHelperD.Clamp(mstsskyovercastFactor - gameTIme.ElapsedGameTime.TotalSeconds / 10, 0, 1);
                });
                // Fog ranges from 10m (can't see anything) to 100km (clear arctic conditions).
                viewer.UserCommandController.AddEvent(UserCommand.DebugFogIncrease, KeyEventType.KeyDown, (GameTime gameTIme) =>
                {
                    mstsskyfogDistance = (float)MathHelperD.Clamp(mstsskyfogDistance - gameTIme.ElapsedGameTime.TotalSeconds * mstsskyfogDistance, 10, 100000);
                });
                viewer.UserCommandController.AddEvent(UserCommand.DebugFogDecrease, KeyEventType.KeyDown, (GameTime gameTIme) =>
                {
                    mstsskyfogDistance = (float)MathHelperD.Clamp(mstsskyfogDistance + gameTIme.ElapsedGameTime.TotalSeconds * mstsskyfogDistance, 10, 100000);
                });
            }
            // Don't let clock shift if multiplayer.
            if (!MPManager.IsMultiPlayer())
            {
                // Shift the clock forwards or backwards at 1h-per-second.
                viewer.UserCommandController.AddEvent(UserCommand.DebugClockForwards, KeyEventType.KeyDown, (GameTime gameTIme) =>
                {
                    MSTSSkyViewer.Simulator.ClockTime += gameTIme.ElapsedGameTime.TotalSeconds * 3600;
                });
                viewer.UserCommandController.AddEvent(UserCommand.DebugClockBackwards, KeyEventType.KeyDown, (GameTime gameTIme) =>
                {
                    MSTSSkyViewer.Simulator.ClockTime -= gameTIme.ElapsedGameTime.TotalSeconds * 3600;
                });
            }
            // Server needs to notify clients of weather changes.
            if (MPManager.IsServer())
            {
                viewer.UserCommandController.AddEvent(UserCommand.DebugOvercastIncrease, KeyEventType.KeyReleased, SendMultiPlayerSkyChangeNotification);
                viewer.UserCommandController.AddEvent(UserCommand.DebugOvercastDecrease, KeyEventType.KeyReleased, SendMultiPlayerSkyChangeNotification);
                viewer.UserCommandController.AddEvent(UserCommand.DebugFogIncrease, KeyEventType.KeyReleased, SendMultiPlayerSkyChangeNotification);
                viewer.UserCommandController.AddEvent(UserCommand.DebugFogDecrease, KeyEventType.KeyReleased, SendMultiPlayerSkyChangeNotification);
            }
        }
Esempio n. 25
0
        internal static bool TrackingTarget(Weapon weapon, Target target)
        {
            Vector3D targetPos;
            Vector3  targetLinVel = Vector3.Zero;
            Vector3  targetAccel  = Vector3.Zero;
            var      system       = weapon.System;
            Vector3D targetCenter;

            var rayCheckTest = !weapon.Comp.Session.IsClient && weapon.Comp.State.Value.CurrentPlayerControl.ControlType == ControlType.None && weapon.ActiveAmmoDef.AmmoDef.Trajectory.Guidance == GuidanceType.None && (!weapon.Casting && weapon.Comp.Session.Tick - weapon.Comp.LastRayCastTick > 29 || weapon.System.Values.HardPoint.Other.MuzzleCheck && weapon.Comp.Session.Tick - weapon.LastMuzzleCheck > 29);

            if (rayCheckTest && !weapon.RayCheckTest())
            {
                return(false);
            }

            if (weapon.Comp.TrackReticle)
            {
                targetCenter = weapon.Comp.Ai.DummyTarget.Position;
            }
            else if (target.IsProjectile)
            {
                if (target.Projectile == null)
                {
                    Log.Line($"TrackingTarget: is projectile and it is null");
                    targetCenter = Vector3D.Zero;
                }
                else
                {
                    targetCenter = target.Projectile.Position;
                }
            }
            else if (!target.IsFakeTarget)
            {
                if (target.Entity == null)
                {
                    Log.Line($"TrackingTarget: is entity and it is null");
                    targetCenter = Vector3D.Zero;
                }
                else
                {
                    targetCenter = target.Entity.PositionComp.WorldAABB.Center;
                }
            }
            else
            {
                targetCenter = Vector3D.Zero;
            }

            var needsPrediction = weapon.System.Prediction != Prediction.Off && (!weapon.ActiveAmmoDef.AmmoDef.Const.IsBeamWeapon && weapon.ActiveAmmoDef.AmmoDef.Const.DesiredProjectileSpeed > 0);

            if (needsPrediction)
            {
                if (weapon.Comp.TrackReticle)
                {
                    targetLinVel = weapon.Comp.Ai.DummyTarget.LinearVelocity;
                    targetAccel  = weapon.Comp.Ai.DummyTarget.Acceleration;
                }
                else
                {
                    var topMostEnt = target.Entity?.GetTopMostParent();
                    if (target.Projectile != null)
                    {
                        targetLinVel = target.Projectile.Velocity;
                        targetAccel  = target.Projectile.AccelVelocity;
                    }
                    else if (topMostEnt?.Physics != null)
                    {
                        targetLinVel = topMostEnt.Physics.LinearVelocity;
                        targetAccel  = topMostEnt.Physics.LinearAcceleration;
                    }
                }
                if (Vector3D.IsZero(targetLinVel, 5E-03))
                {
                    targetLinVel = Vector3.Zero;
                }
                if (Vector3D.IsZero(targetAccel, 5E-03))
                {
                    targetAccel = Vector3.Zero;
                }
                targetPos = weapon.GetPredictedTargetPosition(targetCenter, targetLinVel, targetAccel);
            }
            else
            {
                targetPos = targetCenter;
            }

            weapon.Target.TargetPos = targetPos;

            double rangeToTargetSqr;

            Vector3D.DistanceSquared(ref targetPos, ref weapon.MyPivotPos, out rangeToTargetSqr);
            var targetDir = targetPos - weapon.MyPivotPos;
            var locked    = true;

            if (weapon.Comp.TrackReticle || rangeToTargetSqr <= weapon.MaxTargetDistanceSqr)
            {
                var maxAzimuthStep   = system.AzStep;
                var maxElevationStep = system.ElStep;

                Vector3D currentVector;
                Vector3D.CreateFromAzimuthAndElevation(weapon.Azimuth, weapon.Elevation, out currentVector);
                currentVector = Vector3D.Rotate(currentVector, weapon.WeaponConstMatrix);

                var up   = weapon.MyPivotUp;
                var left = Vector3D.Cross(up, currentVector);
                if (!Vector3D.IsUnit(ref left) && !Vector3D.IsZero(left))
                {
                    left.Normalize();
                }
                var forward          = Vector3D.Cross(left, up);
                var constraintMatrix = new MatrixD {
                    Forward = forward, Left = left, Up = up,
                };

                double desiredAzimuth;
                double desiredElevation;
                MathFuncs.GetRotationAngles(ref targetDir, ref constraintMatrix, out desiredAzimuth, out desiredElevation);

                var azConstraint  = Math.Min(weapon.MaxAzimuthRadians, Math.Max(weapon.MinAzimuthRadians, desiredAzimuth));
                var elConstraint  = Math.Min(weapon.MaxElevationRadians, Math.Max(weapon.MinElevationRadians, desiredElevation));
                var elConstrained = Math.Abs(elConstraint - desiredElevation) > 0.0000001;
                var azConstrained = Math.Abs(azConstraint - desiredAzimuth) > 0.0000001;
                weapon.Target.IsTracking = !azConstrained && !elConstrained;

                if (weapon.Target.IsTracking && weapon.Comp.State.Value.CurrentPlayerControl.ControlType != ControlType.Camera && !weapon.Comp.ResettingSubparts)
                {
                    var oldAz   = weapon.Azimuth;
                    var oldEl   = weapon.Elevation;
                    var epsilon = target.IsProjectile ? 1E-06d : rangeToTargetSqr <= 640000 ? 1E-03d : rangeToTargetSqr <= 3240000 ? 1E-04d : 1E-05d;
                    var az      = weapon.Azimuth + MathHelperD.Clamp(desiredAzimuth, -maxAzimuthStep, maxAzimuthStep);
                    var el      = weapon.Elevation + MathHelperD.Clamp(desiredElevation - weapon.Elevation, -maxElevationStep, maxElevationStep);

                    var azDiff   = oldAz - az;
                    var elDiff   = oldEl - el;
                    var azLocked = MyUtils.IsZero(azDiff, (float)epsilon);
                    var elLocked = MyUtils.IsZero(elDiff, (float)epsilon);

                    locked = azLocked && elLocked;
                    var aim = !azLocked || !elLocked;
                    if (aim)
                    {
                        if (!azLocked)
                        {
                            weapon.Azimuth = az;
                        }
                        if (!elLocked)
                        {
                            weapon.Elevation = el;
                        }
                        weapon.IsHome = false;
                        weapon.AimBarrel(azDiff, elDiff, !azLocked, !elLocked);
                    }
                }
            }
            else
            {
                weapon.Target.IsTracking = false;
            }

            if (weapon.Comp.State.Value.CurrentPlayerControl.ControlType == ControlType.Camera)
            {
                return(weapon.Target.IsTracking);
            }

            var isAligned = false;

            if (weapon.Target.IsTracking)
            {
                isAligned = locked || MathFuncs.IsDotProductWithinTolerance(ref weapon.MyPivotDir, ref targetDir, weapon.AimingTolerance);
            }

            var wasAligned = weapon.Target.IsAligned;

            weapon.Target.IsAligned = isAligned;
            var alignedChange = wasAligned != isAligned;

            if (alignedChange && isAligned)
            {
                if (weapon.System.DesignatorWeapon)
                {
                    for (int i = 0; i < weapon.Comp.Platform.Weapons.Length; i++)
                    {
                        var w = weapon.Comp.Platform.Weapons[i];
                        w.Target.StateChange(false, Target.States.Expired);
                        w.Target.CheckTick -= 240;
                    }
                }
            }
            else if (alignedChange && !weapon.System.DelayCeaseFire)
            {
                weapon.StopShooting();
            }

            weapon.Target.TargetLock = weapon.Target.IsTracking && weapon.Target.IsAligned;
            return(weapon.Target.IsTracking);
        }
Esempio n. 26
0
        private static void DamageProjectile(HitEntity hitEnt, ProInfo attacker)
        {
            var pTarget = hitEnt.Projectile;

            if (pTarget == null)
            {
                return;
            }

            attacker.ObjectsHit++;
            var objHp          = pTarget.Info.BaseHealthPool;
            var integrityCheck = attacker.AmmoDef.DamageScales.MaxIntegrity > 0;

            if (integrityCheck && objHp > attacker.AmmoDef.DamageScales.MaxIntegrity)
            {
                return;
            }

            float damageScale = 1;

            if (attacker.AmmoDef.Const.VirtualBeams)
            {
                damageScale *= attacker.WeaponCache.Hits;
            }

            var scaledDamage = attacker.BaseDamagePool * damageScale;

            var fallOff = attacker.AmmoDef.Const.FallOffScaling && attacker.DistanceTraveled > attacker.AmmoDef.DamageScales.FallOff.Distance;

            if (fallOff)
            {
                var fallOffMultipler = (float)MathHelperD.Clamp(1.0 - ((attacker.DistanceTraveled - attacker.AmmoDef.DamageScales.FallOff.Distance) / (attacker.AmmoDef.Const.MaxTrajectory - attacker.AmmoDef.DamageScales.FallOff.Distance)), attacker.AmmoDef.DamageScales.FallOff.MinMultipler, 1);
                scaledDamage *= fallOffMultipler;
            }

            if (scaledDamage >= objHp)
            {
                attacker.BaseDamagePool    -= objHp;
                pTarget.Info.BaseHealthPool = 0;
                pTarget.State = Projectile.ProjectileState.Destroy;
            }
            else
            {
                attacker.BaseDamagePool      = 0;
                pTarget.Info.BaseHealthPool -= scaledDamage;

                if (attacker.DetonationDamage > 0 && attacker.AmmoDef.AreaEffect.Detonation.DetonateOnEnd)
                {
                    var areaSphere = new BoundingSphereD(pTarget.Position, attacker.AmmoDef.AreaEffect.Detonation.DetonationRadius);
                    foreach (var sTarget in attacker.Ai.LiveProjectile)
                    {
                        if (areaSphere.Contains(sTarget.Position) != ContainmentType.Disjoint)
                        {
                            if (attacker.DetonationDamage >= sTarget.Info.BaseHealthPool)
                            {
                                sTarget.Info.BaseHealthPool = 0;
                                sTarget.State = Projectile.ProjectileState.Destroy;
                            }
                            else
                            {
                                sTarget.Info.BaseHealthPool -= attacker.DetonationDamage;
                            }
                        }
                    }
                }
            }
        }
Esempio n. 27
0
        public AmmoConstants(WeaponAmmoTypes ammo, WeaponDefinition wDef, Session session, WeaponSystem system)
        {
            MyInventory.GetItemVolumeAndMass(ammo.AmmoDefinitionId, out MagMass, out MagVolume);

            MagazineDef    = MyDefinitionManager.Static.GetAmmoMagazineDefinition(ammo.AmmoDefinitionId);
            TracerMaterial = MyStringId.GetOrCompute(ammo.AmmoDef.AmmoGraphics.Lines.TracerMaterial);
            TrailMaterial  = MyStringId.GetOrCompute(ammo.AmmoDef.AmmoGraphics.Lines.Trail.Material);

            if (ammo.AmmoDefinitionId.SubtypeId.String != "Energy" || ammo.AmmoDefinitionId.SubtypeId.String == string.Empty)
            {
                AmmoItem = new MyPhysicalInventoryItem()
                {
                    Amount = 1, Content = MyObjectBuilderSerializer.CreateNewObject <MyObjectBuilder_AmmoMagazine>(ammo.AmmoDefinitionId.SubtypeName)
                }
            }
            ;

            for (int i = 0; i < wDef.Ammos.Length; i++)
            {
                var ammoType = wDef.Ammos[i];
                if (ammoType.AmmoRound.Equals(ammo.AmmoDef.Shrapnel.AmmoRound))
                {
                    ShrapnelId = i;
                }
            }

            IsMine             = ammo.AmmoDef.Trajectory.Guidance == DetectFixed || ammo.AmmoDef.Trajectory.Guidance == DetectSmart || ammo.AmmoDef.Trajectory.Guidance == DetectTravelTo;
            IsField            = ammo.AmmoDef.Trajectory.FieldTime > 0;
            IsHybrid           = ammo.AmmoDef.HybridRound;
            IsTurretSelectable = !ammo.IsShrapnel || ammo.AmmoDef.HardPointUsable;


            AmmoParticle        = ammo.AmmoDef.AmmoGraphics.Particles.Ammo.Name != string.Empty;
            AmmoParticleShrinks = ammo.AmmoDef.AmmoGraphics.Particles.Ammo.ShrinkByDistance;
            HitParticleShrinks  = ammo.AmmoDef.AmmoGraphics.Particles.Hit.ShrinkByDistance;

            HitParticle = ammo.AmmoDef.AmmoGraphics.Particles.Hit.Name != string.Empty;

            DrawLine          = ammo.AmmoDef.AmmoGraphics.Lines.Tracer.Enable;
            LineColorVariance = ammo.AmmoDef.AmmoGraphics.Lines.ColorVariance.Start > 0 && ammo.AmmoDef.AmmoGraphics.Lines.ColorVariance.End > 0;
            LineWidthVariance = ammo.AmmoDef.AmmoGraphics.Lines.WidthVariance.Start > 0 || ammo.AmmoDef.AmmoGraphics.Lines.WidthVariance.End > 0;
            SpeedVariance     = ammo.AmmoDef.Trajectory.SpeedVariance.Start > 0 || ammo.AmmoDef.Trajectory.SpeedVariance.End > 0;
            RangeVariance     = ammo.AmmoDef.Trajectory.RangeVariance.Start > 0 || ammo.AmmoDef.Trajectory.RangeVariance.End > 0;
            TrailWidth        = ammo.AmmoDef.AmmoGraphics.Lines.Trail.CustomWidth > 0 ? ammo.AmmoDef.AmmoGraphics.Lines.Trail.CustomWidth : ammo.AmmoDef.AmmoGraphics.Lines.Tracer.Width;
            TargetOffSet      = ammo.AmmoDef.Trajectory.Smarts.Inaccuracy > 0;

            TargetLossTime   = ammo.AmmoDef.Trajectory.TargetLossTime > 0 ? ammo.AmmoDef.Trajectory.TargetLossTime : int.MaxValue;
            CanZombie        = TargetLossTime > 0 && TargetLossTime != int.MaxValue && !IsMine;
            MaxLifeTime      = ammo.AmmoDef.Trajectory.MaxLifeTime > 0 ? ammo.AmmoDef.Trajectory.MaxLifeTime : int.MaxValue;
            MaxChaseTime     = ammo.AmmoDef.Trajectory.Smarts.MaxChaseTime > 0 ? ammo.AmmoDef.Trajectory.Smarts.MaxChaseTime : int.MaxValue;
            MaxObjectsHit    = ammo.AmmoDef.ObjectsHit.MaxObjectsHit > 0 ? ammo.AmmoDef.ObjectsHit.MaxObjectsHit : int.MaxValue;
            BaseDamage       = ammo.AmmoDef.BaseDamage;
            MaxTargets       = ammo.AmmoDef.Trajectory.Smarts.MaxTargets;
            TargetLossDegree = ammo.AmmoDef.Trajectory.TargetLossDegree > 0 ? (float)Math.Cos(MathHelper.ToRadians(ammo.AmmoDef.Trajectory.TargetLossDegree)) : 0;

            ShieldModifier  = ammo.AmmoDef.DamageScales.Shields.Modifier > 0 ? ammo.AmmoDef.DamageScales.Shields.Modifier : 1;
            ShieldBypassMod = ammo.AmmoDef.DamageScales.Shields.BypassModifier > 0 && ammo.AmmoDef.DamageScales.Shields.BypassModifier < 1 ? ammo.AmmoDef.DamageScales.Shields.BypassModifier : 1;
            AmmoSkipAccel   = ammo.AmmoDef.Trajectory.AccelPerSec <= 0;
            FeelsGravity    = ammo.AmmoDef.Trajectory.GravityMultiplier > 0;

            MaxTrajectory    = ammo.AmmoDef.Trajectory.MaxTrajectory;
            MaxTrajectorySqr = MaxTrajectory * MaxTrajectory;
            HasBackKickForce = ammo.AmmoDef.BackKickForce > 0;

            MaxLateralThrust = MathHelperD.Clamp(ammo.AmmoDef.Trajectory.Smarts.MaxLateralThrust, 0.000001, 1);

            Fields(ammo.AmmoDef, out PulseInterval, out PulseChance, out Pulse);
            AreaEffects(ammo.AmmoDef, out AreaEffect, out AreaEffectDamage, out AreaEffectSize, out DetonationDamage, out AmmoAreaEffect, out AreaRadiusSmall, out AreaRadiusLarge, out DetonateRadiusSmall, out DetonateRadiusLarge, out Ewar, out EwarEffect, out EwarTriggerRange);

            DamageScales(ammo.AmmoDef, out DamageScaling, out FallOffScaling, out ArmorScaling, out CustomDamageScales, out CustomBlockDefinitionBasesToScales, out SelfDamage, out VoxelDamage);
            Beams(ammo.AmmoDef, out IsBeamWeapon, out VirtualBeams, out RotateRealBeam, out ConvergeBeams, out OneHitParticle, out OffsetEffect);
            CollisionShape(ammo.AmmoDef, out CollisionIsLine, out CollisionSize, out TracerLength);
            SmartsDelayDistSqr = (CollisionSize * ammo.AmmoDef.Trajectory.Smarts.TrackingDelay) * (CollisionSize * ammo.AmmoDef.Trajectory.Smarts.TrackingDelay);
            PrimeEntityPool    = Models(ammo.AmmoDef, wDef, out PrimeModel, out TriggerModel, out ModelPath);
            Energy(ammo, system, wDef, out EnergyAmmo, out MustCharge, out Reloadable, out EnergyMagSize, out BurstMode, out HasShotReloadDelay);
            Sound(ammo.AmmoDef, session, out HitSound, out AmmoTravelSound, out HitSoundDistSqr, out AmmoTravelSoundDistSqr, out AmmoSoundMaxDistSqr);
            MagazineSize = EnergyAmmo ? EnergyMagSize : MagazineDef.Capacity;
            GetPeakDps(ammo, system, wDef, out PeakDps, out ShotsPerSec, out BaseDps, out AreaDps, out DetDps);

            DesiredProjectileSpeed = (float)(!IsBeamWeapon ? ammo.AmmoDef.Trajectory.DesiredSpeed : MaxTrajectory * MyEngineConstants.UPDATE_STEPS_PER_SECOND);
            Trail = ammo.AmmoDef.AmmoGraphics.Lines.Trail.Enable;
        }
Esempio n. 28
0
    private GyroControl _Seek(ShipControlCommons shipControl,
                              Vector3D targetVector, Vector3D?targetUp,
                              out double yawPitchError, out double rollError)
    {
        var angularVelocity = shipControl.AngularVelocity;

        if (angularVelocity == null)
        {
            // No ship controller, no action
            yawPitchError = rollError = Math.PI;
            return(shipControl.GyroControl);
        }

        Vector3D    referenceForward;
        Vector3D    referenceLeft;
        Vector3D    referenceUp;
        GyroControl gyroControl;

        // See if local orientation is the same as the ship
        if (shipControl.ShipUp == ShipUp && shipControl.ShipForward == ShipForward)
        {
            // Use same reference vectors and GyroControl
            referenceForward = shipControl.ReferenceForward;
            referenceLeft    = shipControl.ReferenceLeft;
            referenceUp      = shipControl.ReferenceUp;
            gyroControl      = shipControl.GyroControl;
        }
        else
        {
            referenceForward = GetReferenceVector(shipControl, ShipForward);
            referenceLeft    = GetReferenceVector(shipControl, ShipLeft);
            referenceUp      = GetReferenceVector(shipControl, ShipUp);
            // Need our own GyroControl instance in this case
            gyroControl = new GyroControl();
            gyroControl.Init(shipControl.Blocks,
                             shipUp: ShipUp,
                             shipForward: ShipForward);
        }

        targetVector = Vector3D.Normalize(targetVector);

        // Invert our world matrix
        var toLocal = MatrixD.Transpose(MatrixD.CreateWorld(Vector3D.Zero, referenceForward, referenceUp));

        // And bring targetVector & angular velocity into local space
        var localTarget = Vector3D.TransformNormal(-targetVector, toLocal);
        var localVel    = Vector3D.TransformNormal((Vector3D)angularVelocity, toLocal);

        // Use simple trig to get the error angles
        var yawError   = Math.Atan2(localTarget.X, localTarget.Z);
        var pitchError = Math.Atan2(localTarget.Y, localTarget.Z);

        // Set desired angular velocity
        var desiredYawVel   = yawPID.Compute(yawError);
        var desiredPitchVel = pitchPID.Compute(pitchError);

        //shipControl.Echo(string.Format("desiredVel = {0:F3}, {1:F3}", desiredYawVel, desiredPitchVel));

        // Translate to gyro outputs
        double gyroYaw = 0.0;

        if (Math.Abs(desiredYawVel) >= ControlThreshold)
        {
            gyroYaw = yawVPID.Compute(desiredYawVel - localVel.X);
        }
        double gyroPitch = 0.0;

        if (Math.Abs(desiredPitchVel) >= ControlThreshold)
        {
            gyroPitch = pitchVPID.Compute(desiredPitchVel - localVel.Y);
        }

        //shipControl.Echo(string.Format("yaw, pitch = {0:F3}, {1:F3}", gyroYaw, gyroPitch));

        gyroControl.SetAxisVelocity(GyroControl.Yaw, (float)gyroYaw);
        gyroControl.SetAxisVelocity(GyroControl.Pitch, (float)gyroPitch);

        // Determine total yaw/pitch error
        yawPitchError = Math.Acos(MathHelperD.Clamp(Vector3D.Dot(targetVector, referenceForward), -1.0, 1.0));

        if (targetUp != null)
        {
            // Also adjust roll by rotating targetUp vector
            localTarget = Vector3D.TransformNormal((Vector3D)targetUp, toLocal);

            rollError = Math.Atan2(localTarget.X, localTarget.Y);

            var desiredRollVel = rollPID.Compute(rollError);

            //shipControl.Echo(string.Format("desiredRollVel = {0:F3}", desiredRollVel));

            double gyroRoll = 0.0;
            if (Math.Abs(desiredRollVel) >= ControlThreshold)
            {
                gyroRoll = rollVPID.Compute(desiredRollVel - localVel.Z);
            }

            //shipControl.Echo(string.Format("roll = {0:F3}", gyroRoll));

            gyroControl.SetAxisVelocity(GyroControl.Roll, (float)gyroRoll);

            // Only care about absolute error
            rollError = Math.Abs(rollError);
        }
        else
        {
            rollError = 0.0;
        }

        return(gyroControl);
    }
Esempio n. 29
0
        internal void UpdatePivotPos()
        {
            if (PosChangedTick == Comp.Session.Tick || AzimuthPart?.Parent == null || ElevationPart?.Entity == null || MuzzlePart?.Entity == null || Comp.Platform.State != CorePlatform.PlatformState.Ready)
            {
                return;
            }

            var parentPart  = ParentIsSubpart ? AzimuthPart.Parent : Comp.MyCube;
            var worldMatrix = parentPart.PositionComp.WorldMatrixRef;

            PosChangedTick = Comp.Session.Tick;
            var azimuthMatrix   = AzimuthPart.Entity.PositionComp.WorldMatrixRef;
            var elevationMatrix = ElevationPart.Entity.PositionComp.WorldMatrixRef;
            var weaponCenter    = MuzzlePart.Entity.PositionComp.WorldAABB.Center;

            BarrelOrigin = weaponCenter;

            var centerTestPos = azimuthMatrix.Translation;
            var muzzleRadius  = MuzzlePart.Entity.PositionComp.LocalVolume.Radius;

            MyPivotUp  = azimuthMatrix.Up;
            MyPivotFwd = elevationMatrix.Forward;

            if (System.TurretMovement == CoreSystem.TurretType.ElevationOnly)
            {
                Vector3D forward;
                var      eLeft = elevationMatrix.Left;
                Vector3D.Cross(ref eLeft, ref MyPivotUp, out forward);
                WeaponConstMatrix = new MatrixD {
                    Forward = forward, Up = MyPivotUp, Left = elevationMatrix.Left
                };
            }
            else
            {
                var forward = !AlternateForward ? worldMatrix.Forward : Vector3D.TransformNormal(AzimuthInitFwdDir, worldMatrix);

                Vector3D left;
                Vector3D.Cross(ref MyPivotUp, ref forward, out left);

                WeaponConstMatrix = new MatrixD {
                    Forward = forward, Up = MyPivotUp, Left = left
                };
            }

            Vector3D pivotLeft;

            Vector3D.Cross(ref MyPivotUp, ref MyPivotFwd, out pivotLeft);
            if (Vector3D.IsZero(pivotLeft))
            {
                MyPivotPos = centerTestPos;
            }
            else
            {
                Vector3D barrelUp;
                Vector3D.Cross(ref MyPivotFwd, ref pivotLeft, out barrelUp);
                var azToMuzzleOrigin = weaponCenter - centerTestPos;

                double azToMuzzleDot;
                Vector3D.Dot(ref azToMuzzleOrigin, ref barrelUp, out azToMuzzleDot);

                double myPivotUpDot;
                Vector3D.Dot(ref MyPivotUp, ref barrelUp, out myPivotUpDot);

                var pivotOffsetMagnitude = MathHelperD.Clamp(azToMuzzleDot / myPivotUpDot, -muzzleRadius, muzzleRadius);

                var pivotOffset = pivotOffsetMagnitude * MyPivotUp - (pivotOffsetMagnitude * MyPivotFwd);

                MyPivotPos = centerTestPos + pivotOffset;
            }
            if (!Vector3D.IsZero(AimOffset))
            {
                var pivotRotMatrix = new MatrixD {
                    Forward = MyPivotFwd, Left = elevationMatrix.Left, Up = elevationMatrix.Up
                };
                Vector3D offSet;
                Vector3D.Rotate(ref AimOffset, ref pivotRotMatrix, out offSet);

                MyPivotPos += offSet;
            }

            if (!Comp.Debug)
            {
                return;
            }
            MyCenterTestLine = new LineD(centerTestPos, centerTestPos + (MyPivotUp * 20));
            MyPivotTestLine  = new LineD(MyPivotPos, MyPivotPos - (WeaponConstMatrix.Left * 10));
            MyBarrelTestLine = new LineD(weaponCenter, weaponCenter + (MyPivotFwd * 16));
            MyAimTestLine    = new LineD(MyPivotPos, MyPivotPos + (MyPivotFwd * 20));
            AzimuthFwdLine   = new LineD(weaponCenter, weaponCenter + (WeaponConstMatrix.Forward * 19));
            if (Target.HasTarget)
            {
                MyShootAlignmentLine = new LineD(MyPivotPos, Target.TargetPos);
            }
        }
Esempio n. 30
0
 internal void ResetHit()
 {
     ShrinkInited = false;
     TotalLength  = MathHelperD.Clamp(MaxTracerLength + MaxGlowLength, 0.1f, MaxTrajectory);
 }