コード例 #1
0
        private void OnArrestTargetReached()
        {
            if (HumanAIController.HasItem(character, "handlocker", out Item handCuffs) && Enemy.Stun > 0 && character.CanInteractWith(Enemy))
            {
                if (HumanAIController.TryToMoveItem(handCuffs, Enemy.Inventory))
                {
                    handCuffs.Equip(Enemy);
                }
                else
                {
#if DEBUG
                    DebugConsole.NewMessage($"{character.Name}: Failed to handcuff the target.", Color.Red);
#endif
                }
                // Confiscate stolen goods.
                foreach (var item in Enemy.Inventory.Items)
                {
                    if (item == null || item == handCuffs)
                    {
                        continue;
                    }
                    if (item.StolenDuringRound)
                    {
                        item.Drop(character);
                        character.Inventory.TryPutItem(item, character, new List <InvSlotType>()
                        {
                            InvSlotType.Any
                        });
                    }
                }
                // TODO: enable
                //character.Speak(TextManager.Get("DialogTargetArrested"), null, 3.0f, "targetarrested", 30.0f);
                IsCompleted = true;
            }
        }
コード例 #2
0
        protected override void Act(float deltaTime)
        {
            if (abortCondition != null && abortCondition())
            {
                Abandon = true;
                return;
            }
            if (AllowCoolDown)
            {
                coolDownTimer -= deltaTime;
            }
            if (seekAmmunitionObjective == null && seekWeaponObjective == null)
            {
                if (Mode != CombatMode.Retreat && TryArm() && !IsEnemyDisabled)
                {
                    OperateWeapon(deltaTime);
                }
                if (HoldPosition)
                {
                    SteeringManager.Reset();
                }
                else if (seekAmmunitionObjective == null && seekWeaponObjective == null)
                {
                    Move(deltaTime);
                }
                switch (Mode)
                {
                case CombatMode.Offensive:
                    if (TargetEliminated && objectiveManager.IsCurrentOrder <AIObjectiveFightIntruders>())
                    {
                        character.Speak(TextManager.Get("DialogTargetDown"), null, 3.0f, "targetdown", 30.0f);
                    }
                    break;

                case CombatMode.Arrest:
                    if (HumanAIController.HasItem(Enemy, "handlocker", out _, requireEquipped: true))
                    {
                        IsCompleted = true;
                    }
                    else if (Enemy.IsKnockedDown &&
                             !objectiveManager.IsCurrentObjective <AIObjectiveFightIntruders>() &&
                             !HumanAIController.HasItem(character, "handlocker", out _, requireEquipped: false))
                    {
                        IsCompleted = true;
                    }
                    break;
                }
            }
        }
コード例 #3
0
        protected override void Act(float deltaTime)
        {
            if (character.LockHands || targetCharacter == null || targetCharacter.CurrentHull == null || targetCharacter.Removed || targetCharacter.IsDead)
            {
                Abandon = true;
                return;
            }
            var otherRescuer = targetCharacter.SelectedBy;

            if (otherRescuer != null && otherRescuer != character)
            {
                // Someone else is rescuing/holding the target.
                Abandon = otherRescuer.IsPlayer || character.GetSkillLevel("medical") < otherRescuer.GetSkillLevel("medical");
                return;
            }
            if (targetCharacter != character)
            {
                if (targetCharacter.IsIncapacitated)
                {
                    // Check if the character needs more oxygen
                    if (!ignoreOxygen && character.SelectedCharacter == targetCharacter || character.CanInteractWith(targetCharacter))
                    {
                        // Replace empty oxygen and welding fuel.
                        if (HumanAIController.HasItem(targetCharacter, AIObjectiveFindDivingGear.HEAVY_DIVING_GEAR, out IEnumerable <Item> suits, requireEquipped: true))
                        {
                            Item suit = suits.FirstOrDefault();
                            if (suit != null)
                            {
                                AIController.UnequipEmptyItems(character, suit);
                                AIController.UnequipContainedItems(character, suit, it => it.HasTag("weldingfuel"));
                            }
                        }
                        else if (HumanAIController.HasItem(targetCharacter, AIObjectiveFindDivingGear.LIGHT_DIVING_GEAR, out IEnumerable <Item> masks, requireEquipped: true))
                        {
                            Item mask = masks.FirstOrDefault();
                            if (mask != null)
                            {
                                AIController.UnequipEmptyItems(character, mask);
                                AIController.UnequipContainedItems(character, mask, it => it.HasTag("weldingfuel"));
                            }
                        }
                        bool ShouldRemoveDivingSuit() => targetCharacter.OxygenAvailable < CharacterHealth.InsufficientOxygenThreshold && targetCharacter.CurrentHull?.LethalPressure <= 0;

                        if (ShouldRemoveDivingSuit())
                        {
                            suits.ForEach(suit => suit.Drop(character));
                        }
                        else if (suits.Any() && suits.None(s => s.OwnInventory?.AllItems != null && s.OwnInventory.AllItems.Any(it => it.HasTag(AIObjectiveFindDivingGear.OXYGEN_SOURCE) && it.ConditionPercentage > 0)))
                        {
                            // The target has a suit equipped with an empty oxygen tank.
                            // Can't remove the suit, because the target needs it.
                            // If we happen to have an extra oxygen tank in the inventory, let's swap it.
                            Item spareOxygenTank = FindOxygenTank(targetCharacter) ?? FindOxygenTank(character);
                            if (spareOxygenTank != null)
                            {
                                Item suit = suits.FirstOrDefault();
                                if (suit != null)
                                {
                                    // Insert the new oxygen tank
                                    TryAddSubObjective(ref replaceOxygenObjective, () => new AIObjectiveContainItem(character, spareOxygenTank, suit.GetComponent <ItemContainer>(), objectiveManager),
                                                       onCompleted: () => RemoveSubObjective(ref replaceOxygenObjective),
                                                       onAbandon: () =>
                                    {
                                        RemoveSubObjective(ref replaceOxygenObjective);
                                        ignoreOxygen = true;
                                        if (ShouldRemoveDivingSuit())
                                        {
                                            suits.ForEach(suit => suit.Drop(character));
                                        }
                                    });
                                    return;
                                }
                            }

                            Item FindOxygenTank(Character c) =>
                            c.Inventory.FindItem(i =>
                                                 i.HasTag(AIObjectiveFindDivingGear.OXYGEN_SOURCE) &&
                                                 i.ConditionPercentage > 1 &&
                                                 i.FindParentInventory(inv => inv.Owner is Item otherItem && otherItem.HasTag("diving")) == null,
                                                 recursive: true);
                        }
                    }
                    if (HumanAIController.GetHullSafety(targetCharacter.CurrentHull, targetCharacter) < HumanAIController.HULL_SAFETY_THRESHOLD)
                    {
                        // Incapacitated target is not in a safe place -> Move to a safe place first
                        if (character.SelectedCharacter != targetCharacter)
                        {
                            if (targetCharacter.CurrentHull != null && HumanAIController.VisibleHulls.Contains(targetCharacter.CurrentHull) && targetCharacter.CurrentHull.DisplayName != null)
                            {
                                character.Speak(TextManager.GetWithVariables("DialogFoundUnconsciousTarget", new string[2] {
                                    "[targetname]", "[roomname]"
                                },
                                                                             new string[2] {
                                    targetCharacter.Name, targetCharacter.CurrentHull.DisplayName
                                }, new bool[2] {
                                    false, true
                                }),
                                                null, 1.0f, "foundunconscioustarget" + targetCharacter.Name, 60.0f);
                            }
                            // Go to the target and select it
                            if (!character.CanInteractWith(targetCharacter))
                            {
                                RemoveSubObjective(ref replaceOxygenObjective);
                                RemoveSubObjective(ref goToObjective);
                                TryAddSubObjective(ref goToObjective, () => new AIObjectiveGoTo(targetCharacter, character, objectiveManager)
                                {
                                    CloseEnough        = CloseEnoughToTreat,
                                    DialogueIdentifier = "dialogcannotreachpatient",
                                    TargetName         = targetCharacter.DisplayName
                                },
                                                   onCompleted: () => RemoveSubObjective(ref goToObjective),
                                                   onAbandon: () =>
                                {
                                    RemoveSubObjective(ref goToObjective);
                                    Abandon = true;
                                });
                            }
                            else
                            {
                                character.SelectCharacter(targetCharacter);
                            }
                        }
                        else
                        {
                            // Drag the character into safety
                            if (safeHull == null)
                            {
                                if (findHullTimer > 0)
                                {
                                    findHullTimer -= deltaTime;
                                }
                                else
                                {
                                    safeHull      = objectiveManager.GetObjective <AIObjectiveFindSafety>().FindBestHull(HumanAIController.VisibleHulls);
                                    findHullTimer = findHullInterval * Rand.Range(0.9f, 1.1f);
                                }
                            }
                            if (safeHull != null && character.CurrentHull != safeHull)
                            {
                                RemoveSubObjective(ref replaceOxygenObjective);
                                RemoveSubObjective(ref goToObjective);
                                TryAddSubObjective(ref goToObjective, () => new AIObjectiveGoTo(safeHull, character, objectiveManager),
                                                   onCompleted: () => RemoveSubObjective(ref goToObjective),
                                                   onAbandon: () =>
                                {
                                    RemoveSubObjective(ref goToObjective);
                                    safeHull = character.CurrentHull;
                                });
                            }
                        }
                    }
                }
            }

            if (subObjectives.Any())
            {
                return;
            }

            if (targetCharacter != character && !character.CanInteractWith(targetCharacter))
            {
                RemoveSubObjective(ref replaceOxygenObjective);
                RemoveSubObjective(ref goToObjective);
                // Go to the target and select it
                TryAddSubObjective(ref goToObjective, () => new AIObjectiveGoTo(targetCharacter, character, objectiveManager)
                {
                    CloseEnough        = CloseEnoughToTreat,
                    DialogueIdentifier = "dialogcannotreachpatient",
                    TargetName         = targetCharacter.DisplayName
                },
                                   onCompleted: () => RemoveSubObjective(ref goToObjective),
                                   onAbandon: () =>
                {
                    RemoveSubObjective(ref goToObjective);
                    Abandon = true;
                });
            }
            else
            {
                // We can start applying treatment
                if (character != targetCharacter && character.SelectedCharacter != targetCharacter)
                {
                    if (targetCharacter.CurrentHull.DisplayName != null)
                    {
                        character.Speak(TextManager.GetWithVariables("DialogFoundWoundedTarget", new string[2] {
                            "[targetname]", "[roomname]"
                        },
                                                                     new string[2] {
                            targetCharacter.Name, targetCharacter.CurrentHull.DisplayName
                        }, new bool[2] {
                            false, true
                        }),
                                        null, 1.0f, "foundwoundedtarget" + targetCharacter.Name, 60.0f);
                    }
                }
                GiveTreatment(deltaTime);
            }
        }
        protected override void Act(float deltaTime)
        {
            if (character.LockHands)
            {
                Abandon = true;
                return;
            }
            targetItem = character.Inventory.FindItemByTag(gearTag, true);
            if (targetItem == null || !character.HasEquippedItem(targetItem))
            {
                TryAddSubObjective(ref getDivingGear, () =>
                {
                    if (targetItem == null)
                    {
                        character.Speak(TextManager.Get("DialogGetDivingGear"), null, 0.0f, "getdivinggear", 30.0f);
                    }
                    return(new AIObjectiveGetItem(character, gearTag, objectiveManager, equip: true)
                    {
                        AllowStealing = true,
                        AllowToFindDivingGear = false,
                        AllowDangerousPressure = true
                    });
                },
                                   onAbandon: () => Abandon = true,
                                   onCompleted: () => RemoveSubObjective(ref getDivingGear));
            }
            else
            {
                if (!EjectEmptyTanks(character, targetItem, out var containedItems))
                {
#if DEBUG
                    DebugConsole.ThrowError($"{character.Name}: AIObjectiveFindDivingGear failed - the item \"" + targetItem + "\" has no proper inventory");
#endif
                    Abandon = true;
                    return;
                }
                if (containedItems.None(it => it != null && it.HasTag(OXYGEN_SOURCE) && it.Condition > MIN_OXYGEN))
                {
                    // No valid oxygen source loaded.
                    // Seek oxygen that has min 10% condition left.
                    TryAddSubObjective(ref getOxygen, () =>
                    {
                        if (!HumanAIController.HasItem(character, "oxygensource", out _, conditionPercentage: 10))
                        {
                            character.Speak(TextManager.Get("DialogGetOxygenTank"), null, 0, "getoxygentank", 30.0f);
                        }
                        return(new AIObjectiveContainItem(character, OXYGEN_SOURCE, targetItem.GetComponent <ItemContainer>(), objectiveManager, spawnItemIfNotFound: character.TeamID == CharacterTeamType.FriendlyNPC)
                        {
                            AllowToFindDivingGear = false,
                            AllowDangerousPressure = true,
                            ConditionLevel = MIN_OXYGEN
                        });
                    },
                                       onAbandon: () =>
                    {
                        // Try to seek any oxygen sources.
                        TryAddSubObjective(ref getOxygen, () =>
                        {
                            return(new AIObjectiveContainItem(character, OXYGEN_SOURCE, targetItem.GetComponent <ItemContainer>(), objectiveManager, spawnItemIfNotFound: character.TeamID == CharacterTeamType.FriendlyNPC)
                            {
                                AllowToFindDivingGear = false,
                                AllowDangerousPressure = true
                            });
                        },
                                           onAbandon: () => Abandon = true,
                                           onCompleted: () => RemoveSubObjective(ref getOxygen));
                    },
                                       onCompleted: () => RemoveSubObjective(ref getOxygen));
                }
            }
        }
コード例 #5
0
        protected override void Act(float deltaTime)
        {
            if (character.LockHands)
            {
                Abandon = true;
                return;
            }
            targetItem = character.Inventory.FindItemByTag(gearTag, true);
            if (targetItem == null && gearTag == LIGHT_DIVING_GEAR)
            {
                targetItem = character.Inventory.FindItemByTag(HEAVY_DIVING_GEAR, true);
            }
            if (targetItem == null || !character.HasEquippedItem(targetItem, slotType: InvSlotType.OuterClothes | InvSlotType.Head | InvSlotType.InnerClothes) && targetItem.ContainedItems.Any(i => i.HasTag(OXYGEN_SOURCE) && i.Condition > 0))
            {
                TryAddSubObjective(ref getDivingGear, () =>
                {
                    if (targetItem == null && character.IsOnPlayerTeam)
                    {
                        character.Speak(TextManager.Get("DialogGetDivingGear"), null, 0.0f, "getdivinggear", 30.0f);
                    }
                    return(new AIObjectiveGetItem(character, gearTag, objectiveManager, equip: true)
                    {
                        AllowStealing = HumanAIController.NeedsDivingGear(character.CurrentHull, out _),
                        AllowToFindDivingGear = false,
                        AllowDangerousPressure = true,
                        EquipSlotType = InvSlotType.OuterClothes | InvSlotType.Head | InvSlotType.InnerClothes,
                        Wear = true
                    });
                },
                                   onAbandon: () => Abandon = true,
                                   onCompleted: () =>
                {
                    RemoveSubObjective(ref getDivingGear);
                    if (gearTag == HEAVY_DIVING_GEAR && HumanAIController.HasItem(character, LIGHT_DIVING_GEAR, out IEnumerable <Item> masks, requireEquipped: true))
                    {
                        foreach (Item mask in masks)
                        {
                            if (mask != targetItem)
                            {
                                character.Inventory.TryPutItem(mask, character, CharacterInventory.anySlot);
                            }
                        }
                    }
                });
            }
            else
            {
                float min = GetMinOxygen(character);
                if (targetItem.OwnInventory != null && targetItem.OwnInventory.AllItems.None(it => it != null && it.HasTag(OXYGEN_SOURCE) && it.Condition > min))
                {
                    TryAddSubObjective(ref getOxygen, () =>
                    {
                        if (character.IsOnPlayerTeam)
                        {
                            if (HumanAIController.HasItem(character, OXYGEN_SOURCE, out _, conditionPercentage: min))
                            {
                                character.Speak(TextManager.Get("dialogswappingoxygentank"), null, 0, "swappingoxygentank", 30.0f);
                                if (character.Inventory.FindAllItems(i => i.HasTag(OXYGEN_SOURCE) && i.Condition > min).Count == 1)
                                {
                                    character.Speak(TextManager.Get("dialoglastoxygentank"), null, 0.0f, "dialoglastoxygentank", 30.0f);
                                }
                            }
                            else
                            {
                                character.Speak(TextManager.Get("DialogGetOxygenTank"), null, 0, "getoxygentank", 30.0f);
                            }
                        }
                        return(new AIObjectiveContainItem(character, OXYGEN_SOURCE, targetItem.GetComponent <ItemContainer>(), objectiveManager, spawnItemIfNotFound: character.TeamID == CharacterTeamType.FriendlyNPC)
                        {
                            AllowToFindDivingGear = false,
                            AllowDangerousPressure = true,
                            ConditionLevel = MIN_OXYGEN,
                            RemoveExisting = true
                        });
                    },
                                       onAbandon: () =>
                    {
                        getOxygen          = null;
                        int remainingTanks = ReportOxygenTankCount();
                        // Try to seek any oxygen sources, even if they have minimal amount of oxygen.
                        TryAddSubObjective(ref getOxygen, () =>
                        {
                            return(new AIObjectiveContainItem(character, OXYGEN_SOURCE, targetItem.GetComponent <ItemContainer>(), objectiveManager, spawnItemIfNotFound: character.TeamID == CharacterTeamType.FriendlyNPC)
                            {
                                AllowToFindDivingGear = false,
                                AllowDangerousPressure = true,
                                RemoveExisting = true
                            });
                        },
                                           onAbandon: () =>
                        {
                            Abandon = true;
                            if (remainingTanks > 0 && !HumanAIController.HasItem(character, OXYGEN_SOURCE, out _, conditionPercentage: 0.01f))
                            {
                                character.Speak(TextManager.Get("dialogcantfindtoxygen"), null, 0, "cantfindoxygen", 30.0f);
                            }
                        },
                                           onCompleted: () => RemoveSubObjective(ref getOxygen));
                    },
                                       onCompleted: () =>
                    {
                        RemoveSubObjective(ref getOxygen);
                        ReportOxygenTankCount();
                    });

                    int ReportOxygenTankCount()
                    {
                        if (character.Submarine != Submarine.MainSub)
                        {
                            return(1);
                        }
                        int remainingOxygenTanks = Submarine.MainSub.GetItems(false).Count(i => i.HasTag(OXYGEN_SOURCE) && i.Condition > 1);

                        if (remainingOxygenTanks == 0)
                        {
                            character.Speak(TextManager.Get("DialogOutOfOxygenTanks"), null, 0.0f, "outofoxygentanks", 30.0f);
                        }
                        else if (remainingOxygenTanks < 10)
                        {
                            character.Speak(TextManager.Get("DialogLowOnOxygenTanks"), null, 0.0f, "lowonoxygentanks", 30.0f);
                        }
                        return(remainingOxygenTanks);
                    }
                }
            }
        }
コード例 #6
0
        protected override void Act(float deltaTime)
        {
            if (character.LockHands)
            {
                Abandon = true;
                return;
            }
            targetItem = character.Inventory.FindItemByTag(gearTag, true);
            if (targetItem == null || !character.HasEquippedItem(targetItem, slotType: InvSlotType.OuterClothes | InvSlotType.Head | InvSlotType.InnerClothes) && targetItem.ContainedItems.Any(i => i.HasTag(OXYGEN_SOURCE) && i.Condition > 0))
            {
                TryAddSubObjective(ref getDivingGear, () =>
                {
                    if (targetItem == null && character.IsOnPlayerTeam)
                    {
                        character.Speak(TextManager.Get("DialogGetDivingGear"), null, 0.0f, "getdivinggear", 30.0f);
                    }
                    return(new AIObjectiveGetItem(character, gearTag, objectiveManager, equip: true)
                    {
                        AllowStealing = HumanAIController.NeedsDivingGear(character.CurrentHull, out _),
                        AllowToFindDivingGear = false,
                        AllowDangerousPressure = true,
                        EquipSlotType = InvSlotType.OuterClothes | InvSlotType.Head | InvSlotType.InnerClothes,
                        Wear = true
                    });
                },
                                   onAbandon: () => Abandon = true,
                                   onCompleted: () => RemoveSubObjective(ref getDivingGear));
            }
            else
            {
                // Seek oxygen that has at least 10% condition left, if we are inside a friendly sub.
                // The margin helps us to survive, because we might need some oxygen before we can find more oxygen.
                // When we are venturing outside of our sub, let's just suppose that we have enough oxygen with us and optimize it so that we don't keep switching off half used tanks.
                float min = character.Submarine != Submarine.MainSub ? 0.01f : MIN_OXYGEN;
                if (targetItem.OwnInventory != null && targetItem.OwnInventory.AllItems.None(it => it != null && it.HasTag(OXYGEN_SOURCE) && it.Condition > min))
                {
                    TryAddSubObjective(ref getOxygen, () =>
                    {
                        if (character.IsOnPlayerTeam)
                        {
                            if (HumanAIController.HasItem(character, "oxygensource", out _, conditionPercentage: min))
                            {
                                character.Speak(TextManager.Get("dialogswappingoxygentank"), null, 0, "swappingoxygentank", 30.0f);
                            }
                            else
                            {
                                character.Speak(TextManager.Get("DialogGetOxygenTank"), null, 0, "getoxygentank", 30.0f);
                            }
                        }
                        return(new AIObjectiveContainItem(character, OXYGEN_SOURCE, targetItem.GetComponent <ItemContainer>(), objectiveManager, spawnItemIfNotFound: character.TeamID == CharacterTeamType.FriendlyNPC)
                        {
                            AllowToFindDivingGear = false,
                            AllowDangerousPressure = true,
                            ConditionLevel = MIN_OXYGEN,
                            RemoveExisting = true
                        });
                    },
                                       onAbandon: () =>
                    {
                        getOxygen          = null;
                        int remainingTanks = ReportOxygenTankCount();
                        // Try to seek any oxygen sources, even if they have minimal amount of oxygen.
                        TryAddSubObjective(ref getOxygen, () =>
                        {
                            return(new AIObjectiveContainItem(character, OXYGEN_SOURCE, targetItem.GetComponent <ItemContainer>(), objectiveManager, spawnItemIfNotFound: character.TeamID == CharacterTeamType.FriendlyNPC)
                            {
                                AllowToFindDivingGear = false,
                                AllowDangerousPressure = true,
                                RemoveExisting = true
                            });
                        },
                                           onAbandon: () =>
                        {
                            Abandon = true;
                            if (remainingTanks > 0 && !HumanAIController.HasItem(character, "oxygensource", out _, conditionPercentage: 0.01f))
                            {
                                character.Speak(TextManager.Get("dialogcantfindtoxygen"), null, 0, "cantfindoxygen", 30.0f);
                            }
                        },
                                           onCompleted: () => RemoveSubObjective(ref getOxygen));
                    },
                                       onCompleted: () =>
                    {
                        RemoveSubObjective(ref getOxygen);
                        ReportOxygenTankCount();
                    });

                    int ReportOxygenTankCount()
                    {
                        if (character.Submarine != Submarine.MainSub)
                        {
                            return(1);
                        }
                        int remainingOxygenTanks = Submarine.MainSub.GetItems(false).Count(i => i.HasTag("oxygensource") && i.Condition > 1);

                        if (remainingOxygenTanks == 0)
                        {
                            character.Speak(TextManager.Get("DialogOutOfOxygenTanks"), null, 0.0f, "outofoxygentanks", 30.0f);
                        }
                        else if (remainingOxygenTanks < 10)
                        {
                            character.Speak(TextManager.Get("DialogLowOnOxygenTanks"), null, 0.0f, "lowonoxygentanks", 30.0f);
                        }
                        return(remainingOxygenTanks);
                    }
                }
            }
        }
コード例 #7
0
 protected override bool Check() => HumanAIController.HasItem(character, gearTag, "oxygensource") || HumanAIController.HasItem(character, fallbackTag, "oxygensource");
コード例 #8
0
 protected override bool Check() => HumanAIController.HasItem(character, gearTag, out _, "oxygensource", requireEquipped: true) || HumanAIController.HasItem(character, fallbackTag, out _, "oxygensource", requireEquipped: true);
コード例 #9
0
 private void Engage()
 {
     if (character.LockHands || Enemy == null)
     {
         Mode = CombatMode.Retreat;
         SteeringManager.Reset();
         return;
     }
     retreatTarget = null;
     RemoveSubObjective(ref retreatObjective);
     RemoveSubObjective(ref seekAmmunition);
     if (followTargetObjective != null && followTargetObjective.Target != Enemy)
     {
         RemoveFollowTarget();
     }
     TryAddSubObjective(ref followTargetObjective,
                        constructor: () => new AIObjectiveGoTo(Enemy, character, objectiveManager, repeat: true, getDivingGearIfNeeded: true, closeEnough: 50)
     {
         IgnoreIfTargetDead = true,
         DialogueIdentifier = "dialogcannotreachtarget",
         TargetName         = Enemy.DisplayName
     },
                        onAbandon: () =>
     {
         Abandon = true;
         SteeringManager.Reset();
     });
     if (followTargetObjective == null)
     {
         return;
     }
     if (Mode == CombatMode.Arrest && Enemy.Stun > 2)
     {
         if (HumanAIController.HasItem(character, "handlocker", out Item handCuffs))
         {
             if (!arrestingRegistered)
             {
                 arrestingRegistered              = true;
                 followTargetObjective.Completed += OnArrestTargetReached;
             }
             followTargetObjective.CloseEnough = 100;
         }
         else
         {
             RemoveFollowTarget();
             SteeringManager.Reset();
         }
     }
     else if (WeaponComponent == null)
     {
         RemoveFollowTarget();
         SteeringManager.Reset();
     }
     else
     {
         followTargetObjective.CloseEnough =
             WeaponComponent is RangedWeapon ? 1000 :
             WeaponComponent is MeleeWeapon mw ? mw.Range :
             WeaponComponent is RepairTool rt ? rt.Range : 50;
     }
 }