public MyDroneStrafeBehaviour(MyRemoteControl remoteControl, MySpaceStrafeData strafeData, bool activate, List <MyUserControllableGun> weapons, List <MyFunctionalBlock> tools, Vector3D firstWaypoint)
        {
            m_remoteControl = remoteControl;
            ReturnPosition  = m_remoteControl.PositionComp.GetPosition();

            LoadStrafeData(strafeData);

            m_weapons = weapons;
            m_tools   = tools;
            MyPlayer player = m_remoteControl.GetNearestPlayer();

            m_target                = player != null ? player.Character as MyEntity : null;
            m_lastTargetUpdate      = MySandboxGame.TotalGamePlayTimeInMilliseconds;
            m_lastWeaponUpdate      = m_lastTargetUpdate;
            m_waypointReachedTimeMs = m_lastTargetUpdate;
            m_firstWaypoint         = firstWaypoint;

            NeedUpdate = activate;
        }
        private void UpdateWaypoint()
        {
            int currentTime = MySandboxGame.TotalGamePlayTimeInMilliseconds;

            //find new target player
            if ((m_target == null && currentTime - m_lastTargetUpdate >= 5000) || currentTime - m_lostStartTimeMs >= m_lostTimeMs)
            {
                MyPlayer player = m_remoteControl.GetNearestPlayer();
                m_target           = player != null ? player.Character as MyEntity : null;
                m_lastTargetUpdate = currentTime;
                if (m_target != null)
                {
                    m_lostStartTimeMs   = currentTime;
                    m_farAwayFromTarget = true;
                }
                else
                {
                    m_lostStartTimeMs += 5000;
                }
            }

            if (m_farAwayFromTarget && currentTime - m_lastTargetUpdate >= 5000)
            {
                m_lastTargetUpdate = currentTime;
                NeedUpdate         = true;
            }

            //weapon/suicide update
            float distSq = -1f;

            if (m_operational && currentTime - m_lastWeaponUpdate >= 300)
            {
                m_lastWeaponUpdate = currentTime;
                distSq             = Vector3.DistanceSquared((Vector3)m_target.PositionComp.GetPosition(), (Vector3)m_remoteControl.PositionComp.GetPosition());
                WeaponsUpdate(distSq);
            }

            if (currentTime - m_waypointReachedTimeMs >= m_waypointMaxTime)
            {
                NeedUpdate = true;
            }

            if (!NeedUpdate || m_target == null)
            {
                return;
            }

            //active and prepare waypoints
            IsActive = true;
            if (distSq < 0)
            {
                distSq = Vector3.DistanceSquared((Vector3)m_target.PositionComp.GetPosition(), (Vector3)m_remoteControl.PositionComp.GetPosition());
            }
            m_farAwayFromTarget = distSq > m_maxManeuverDistanceSq;
            bool origUpdate = NeedUpdate;

            if (m_remoteControl.HasWaypoints())
            {
                m_remoteControl.ClearWaypoints();
                //MyGuiAudio.PlaySound(MyGuiSounds.PlayTakeItem); //debug
            }
            m_remoteControl.SetAutoPilotEnabled(true);
            NeedUpdate = origUpdate;

            Vector3D newWaypoint;

            if (m_firstWaypoint != Vector3D.Zero)
            {
                newWaypoint     = m_firstWaypoint;
                m_firstWaypoint = Vector3D.Zero;
            }
            else if (!m_operational && m_kamikazeBehavior)
            {
                //no functional weapons -> ram the player
                if (m_remoteControl.TargettingAimDelta > 0.02f)
                {
                    return;
                }
                newWaypoint = m_target.PositionComp.GetPosition() + m_target.WorldMatrix.Up * PlayerYAxisOffset * 2 - Vector3D.Normalize(m_remoteControl.PositionComp.GetPosition() - m_target.PositionComp.GetPosition()) * m_kamikazeBehaviorDistance;
            }
            else if (!m_operational && !m_kamikazeBehavior)
            {
                //no functional weapons -> try to escape
                newWaypoint = ReturnPosition + Vector3.One * 0.01f;
            }
            else if (m_farAwayFromTarget)
            {
                //too far away from target
                newWaypoint = m_target.PositionComp.GetPosition() + Vector3D.Normalize(m_remoteControl.PositionComp.GetPosition() - m_target.PositionComp.GetPosition()) * m_playerTargetDistance;
            }
            else
            {
                //in proximity to target
                m_lostStartTimeMs = currentTime;
                if (currentTime - m_waypointReachedTimeMs <= m_waypointDelayMs)
                {
                    return;
                }
                newWaypoint = GetRandomPoint();
            }

            //Add new point to waypoints
            Vector3D currentToWaypoint = newWaypoint - m_remoteControl.WorldMatrix.Translation;

            currentToWaypoint.Normalize();
            m_waypointReachedTimeMs = currentTime;
            var strafeLocalDir = Vector3.TransformNormal((Vector3)currentToWaypoint, m_remoteControl.PositionComp.WorldMatrixNormalizedInv);

            Base6Directions.Direction strafeDir = Base6Directions.GetClosestDirection(ref strafeLocalDir);
            bool commitKamikadze = m_kamikazeBehavior && !m_operational;

            m_remoteControl.ChangeFlightMode(MyRemoteControl.FlightMode.OneWay);
            m_remoteControl.SetAutoPilotSpeedLimit(commitKamikadze ? 100f : m_speedLimit);
            m_remoteControl.SetCollisionAvoidance(commitKamikadze ? false : m_avoidCollisions);
            m_remoteControl.ChangeDirection(strafeDir);
            m_remoteControl.AddWaypoint(newWaypoint, m_farAwayFromTarget || commitKamikadze ? "Player Vicinity" : "Strafe");

            NeedUpdate = false;
            IsActive   = true;
        }