/// <summary> /// If the missile is near the target and not getting closer, detonate. /// </summary> private void ProximityDetonate() { if (!MyAPIGateway.Multiplayer.IsServer || myDescr.DetonateRange == 0f) { return; } Target cached = CurrentTarget; if (!cached.FiringDirection.HasValue) { return; } Vector3D myPosition = MyEntity.GetPosition(); Vector3D targetPosition = cached.GetPosition(); double distSq; Vector3D.DistanceSquared(ref myPosition, ref targetPosition, out distSq); if (distSq < myDescr.DetonateRange * myDescr.DetonateRange && Vector3.Normalize(MyEntity.GetLinearVelocity()).Dot(cached.FiringDirection.Value) < Static.Cos_Angle_Detonate) { Log.DebugLog("proximity detonation, target: " + cached.Entity + ", target position: " + cached.GetPosition() + ", real position: " + cached.Entity.GetPosition() + ", type: " + cached.GetType().Name, Logger.severity.INFO); Explode(); m_stage = Stage.Terminated; } }
private void Update() { Target cached = CurrentTarget; if (!cached.FiringDirection.HasValue) { return; } Log.TraceLog("target: " + cached.Entity.getBestName() + ", ContactPoint: " + cached.ContactPoint); Log.TraceLog("FiringDirection invalid: " + cached.FiringDirection, Logger.severity.FATAL, condition: !cached.FiringDirection.IsValid()); Log.TraceLog("ContactPoint invalid: " + cached.ContactPoint, Logger.severity.FATAL, condition: !cached.ContactPoint.IsValid()); Vector3 targetDirection; switch (m_stage) { case Stage.Boost: Log.DebugLog("m_gravData == null", Logger.severity.FATAL, condition: m_gravData == null); targetDirection = -m_gravData.Normal; break; case Stage.MidCourse: Vector3 toTarget = cached.GetPosition() - MyEntity.GetPosition(); targetDirection = Vector3.Normalize(Vector3.Reject(toTarget, m_gravData.Normal)); break; case Stage.SemiActive: case Stage.Golis: case Stage.Guided: targetDirection = cached.FiringDirection.Value; break; default: return; } Vector3 forward = MyEntity.WorldMatrix.Forward; float angle = (float)Math.Acos(Vector3.Dot(forward, targetDirection)); Log.DebugLog("forward: " + forward + ", targetDirection: " + targetDirection + ", angle: " + angle); if (m_stage <= Stage.Guided && angle > 0.001f) // if the angle is too small, the matrix will be invalid { // rotate missile float rotate = Math.Min(angle, myDescr.RotationPerUpdate); Vector3 axis = forward.Cross(targetDirection); axis.Normalize(); Quaternion rotation = Quaternion.CreateFromAxisAngle(axis, rotate); if (!Stopped) { MatrixD WorldMatrix = MyEntity.WorldMatrix; MatrixD newMatrix = WorldMatrix.GetOrientation(); newMatrix = MatrixD.Transform(newMatrix, rotation); newMatrix.Translation = WorldMatrix.Translation; MyEntity.WorldMatrix = newMatrix; } } { // accelerate if facing target if (angle < Static.Angle_AccelerateWhen && addSpeedPerUpdate > 0f && MyEntity.GetLinearVelocity().LengthSquared() < myAmmo.AmmoDefinition.DesiredSpeed * myAmmo.AmmoDefinition.DesiredSpeed) { //Log.DebugLog("accelerate. angle: " + angle, "Update()"); if (!Stopped) { MyEntity.Physics.LinearVelocity += MyEntity.WorldMatrix.Forward * addSpeedPerUpdate; } } } if (myDescr.TargetRange != 0f && CurrentTarget is LastSeenTarget) { Vector3D myPosition = MyEntity.GetPosition(); Vector3D realTargetPos = CurrentTarget.Entity.GetPosition(); double distSq; Vector3D.DistanceSquared(ref myPosition, ref realTargetPos, out distSq); if (distSq < myDescr.TargetRange * myDescr.TargetRange) { Log.DebugLog("Promoting targeting"); SetTarget(new TurretTarget(CurrentTarget.Entity, CurrentTarget.TType)); } } if (myDescr.AcquisitionAngle == MathHelper.Pi) // otherwise we check while outside of AcquisitionAngle see CanRotateTo { ProximityDetonate(); } }