protected override void Act(float deltaTime) { if (character.LockHands) { Abandon = true; return; } if (character.Submarine == null) { Abandon = true; return; } if (identifiersOrTags != null && !isDoneSeeking) { if (checkInventory) { if (CheckInventory()) { isDoneSeeking = true; } } if (!isDoneSeeking) { if (!AllowDangerousPressure) { bool dangerousPressure = character.CurrentHull == null || character.CurrentHull.LethalPressure > 0 && character.PressureProtection <= 0; if (dangerousPressure) { #if DEBUG string itemName = targetItem != null ? targetItem.Name : identifiersOrTags.FirstOrDefault(); DebugConsole.NewMessage($"{character.Name}: Seeking item ({itemName}) aborted, because the pressure is dangerous.", Color.Yellow); #endif Abandon = true; return; } } FindTargetItem(); if (!objectiveManager.IsCurrentOrder <AIObjectiveGoTo>()) { objectiveManager.GetObjective <AIObjectiveIdle>().Wander(deltaTime); } return; } } if (targetItem == null || targetItem.Removed) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Target null or removed. Aborting.", Color.Red); #endif Abandon = true; return; } else if (isDoneSeeking && moveToTarget == null) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Move target null. Aborting.", Color.Red); #endif Abandon = true; return; } if (character.IsItemTakenBySomeoneElse(targetItem)) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Found an item, but it's already equipped by someone else.", Color.Yellow); #endif if (originalTarget == null) { // Try again ignoredItems.Add(targetItem); ResetInternal(); } else { Abandon = true; } return; } bool canInteract = false; if (moveToTarget is Character c) { if (character == c) { canInteract = true; moveToTarget = null; } else { character.SelectCharacter(c); canInteract = character.CanInteractWith(c, maxDist: DefaultReach); character.DeselectCharacter(); } } else if (moveToTarget is Item parentItem) { canInteract = character.CanInteractWith(parentItem, checkLinked: false); } if (canInteract) { var pickable = targetItem.GetComponent <Pickable>(); if (pickable == null) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Target not pickable. Aborting.", Color.Yellow); #endif Abandon = true; return; } Inventory itemInventory = targetItem.ParentInventory; var slots = itemInventory?.FindIndices(targetItem); if (HumanAIController.TakeItem(targetItem, character.Inventory, Equip, Wear, storeUnequipped: true)) { if (TakeWholeStack && slots != null) { foreach (int slot in slots) { foreach (Item item in itemInventory.GetItemsAt(slot).ToList()) { HumanAIController.TakeItem(item, character.Inventory, equip: false, storeUnequipped: true); } } } IsCompleted = true; } else { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Failed to equip/move the item '{targetItem.Name}' into the character inventory. Aborting.", Color.Red); #endif Abandon = true; } } else if (moveToTarget != null) { TryAddSubObjective(ref goToObjective, constructor: () => { return(new AIObjectiveGoTo(moveToTarget, character, objectiveManager, repeat: false, getDivingGearIfNeeded: AllowToFindDivingGear, closeEnough: DefaultReach) { // If the root container changes, the item is no longer where it was (taken by someone -> need to find another item) AbortCondition = obj => targetItem == null || targetItem.GetRootInventoryOwner() != moveToTarget, SpeakIfFails = false }); }, onAbandon: () => { if (originalTarget == null) { // Try again ignoredItems.Add(targetItem); ResetInternal(); } else { Abandon = true; } }, onCompleted: () => RemoveSubObjective(ref goToObjective)); } }