protected override void OnExecute()
        {
            m_Weapon = m_Inventory.selected.GetComponent <AiBaseWeapon>();
            if (m_Weapon == null)
            {
#if UNITY_EDITOR
                if (m_IsDebug)
                {
                    Debug.LogError("No weapon is equipped so cannot find an optimal attack position, support for fists is not present at this time.");
                }
#endif

                EndAction(false);
                return;
            }

            float distanceToTarget = Vector3.Distance(agent.transform.position, target.value.position);
            if (distanceToTarget > m_Weapon.maximumRange && distanceToTarget < m_Weapon.minimumRange)
            {
#if UNITY_EDITOR
                if (m_IsDebug)
                {
                    Debug.Log("Already within attack range so not moving again.");
                }
#endif

                EndAction(false);
                return;
            }

            SetTargetPosition();
        }
        //This is called once each time the task is enabled.
        //Call EndAction() to mark the action as finished, either in success or failure.
        //EndAction can be called from anywhere.
        protected override void OnExecute()
        {
            // TODO cache the inventory items and subscribe to changes
            // TODO don't consider changing weapon every cycle, only every x seconds
            int          optimalSlot   = -1;
            AiBaseWeapon optimalWeapon = null;
            float        currentDeviationFromMidPoint = float.PositiveInfinity;

            for (int i = 0; i < agent.numSlots; i++)
            {
                IQuickSlotItem item = agent.GetSlotItem(i);
                if (item == null)
                {
                    continue;
                }

                AiBaseWeapon weapon = item.GetComponent <AiBaseWeapon>();
                if (optimalWeapon == null || (distanceToTarget.value >= weapon.minimumRange && distanceToTarget.value <= weapon.maximumRange))
                {
                    // TODO add a preference for higher damage weapons
                    float deviation = Mathf.Abs(distanceToTarget.value - weapon.optimalRange);
                    if (deviation < currentDeviationFromMidPoint)
                    {
                        // TODO add a penalty for changing weapons (that is only chang weapons when it is truly worthwhile)
                        currentDeviationFromMidPoint = deviation;
                        optimalSlot   = i;
                        optimalWeapon = weapon;
                    }
                }
            }

            if (optimalWeapon != agent.selected.GetComponent <AiBaseWeapon>())
            {
                agent.SelectSlot(optimalSlot);
            }

            EndAction(true);
        }