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)); } }
protected override void Act(float deltaTime) { if (container == null || (container.Item != null && container.Item.IsThisOrAnyContainerIgnoredByAI())) { Abandon = true; return; } ItemToContain = item ?? character.Inventory.FindItem(i => CheckItem(i) && i.Container != container.Item, recursive: true); if (ItemToContain != null) { if (!character.CanInteractWith(ItemToContain, checkLinked: false)) { Abandon = true; return; } if (character.CanInteractWith(container.Item, checkLinked: false)) { if (RemoveExisting) { HumanAIController.UnequipContainedItems(container.Item); } else if (RemoveEmpty) { HumanAIController.UnequipEmptyItems(container.Item); } Inventory originalInventory = ItemToContain.ParentInventory; var slots = originalInventory?.FindIndices(ItemToContain); if (container.Inventory.TryPutItem(ItemToContain, null)) { if (MoveWholeStack && slots != null) { foreach (int slot in slots) { foreach (Item item in originalInventory.GetItemsAt(slot).ToList()) { container.Inventory.TryPutItem(item, null); } } IsCompleted = true; } } else { if (ItemToContain.ParentInventory == character.Inventory && character.Submarine == Submarine.MainSub) { ItemToContain.Drop(character); } Abandon = true; } } else { TryAddSubObjective(ref goToObjective, () => new AIObjectiveGoTo(container.Item, character, objectiveManager, getDivingGearIfNeeded: AllowToFindDivingGear) { DialogueIdentifier = "dialogcannotreachtarget", TargetName = container.Item.Name, abortCondition = obj => !ItemToContain.IsOwnedBy(character), SpeakIfFails = !objectiveManager.IsCurrentOrder <AIObjectiveCleanupItems>() }, onAbandon: () => Abandon = true, onCompleted: () => RemoveSubObjective(ref goToObjective)); } } else { if (character.Submarine == null) { Abandon = true; } else { // No matching items in the inventory, try to get an item TryAddSubObjective(ref getItemObjective, () => new AIObjectiveGetItem(character, itemIdentifiers, objectiveManager, equip: Equip, checkInventory: checkInventory, spawnItemIfNotFound: spawnItemIfNotFound) { GetItemPriority = GetItemPriority, ignoredContainerIdentifiers = ignoredContainerIdentifiers, ignoredItems = containedItems, AllowToFindDivingGear = AllowToFindDivingGear, AllowDangerousPressure = AllowDangerousPressure, TargetCondition = ConditionLevel }, onAbandon: () => { Abandon = true; }, onCompleted: () => { if (getItemObjective?.TargetItem != null) { containedItems.Add(getItemObjective.TargetItem); } RemoveSubObjective(ref getItemObjective); }); } } }
protected override void Act(float deltaTime) { if (container?.Item == null || container.Item.Removed || container.Item.IsThisOrAnyContainerIgnoredByAI(character)) { Abandon = true; return; } ItemToContain = item ?? character.Inventory.FindItem(i => CheckItem(i) && i.Container != container.Item, recursive: true); if (ItemToContain != null) { if (!character.CanInteractWith(ItemToContain, checkLinked: false)) { Abandon = true; return; } if (character.CanInteractWith(container.Item, checkLinked: false)) { if (RemoveExisting) { HumanAIController.UnequipContainedItems(container.Item); } else if (RemoveEmpty) { HumanAIController.UnequipEmptyItems(container.Item); } Inventory originalInventory = ItemToContain.ParentInventory; var slots = originalInventory?.FindIndices(ItemToContain); if (container.Inventory.TryPutItem(ItemToContain, null)) { if (MoveWholeStack && slots != null) { foreach (int slot in slots) { foreach (Item item in originalInventory.GetItemsAt(slot).ToList()) { container.Inventory.TryPutItem(item, null); } } IsCompleted = true; } } else { if (ItemToContain.ParentInventory == character.Inventory && character.IsInFriendlySub) { ItemToContain.Drop(character); } Abandon = true; } } else { TryAddSubObjective(ref goToObjective, () => new AIObjectiveGoTo(container.Item, character, objectiveManager, getDivingGearIfNeeded: AllowToFindDivingGear) { DialogueIdentifier = "dialogcannotreachtarget", TargetName = container.Item.Name, AbortCondition = obj => container?.Item == null || container.Item.Removed || container.Item.IsThisOrAnyContainerIgnoredByAI(character) || ItemToContain == null || ItemToContain.Removed || !ItemToContain.IsOwnedBy(character) || container.Item.GetRootInventoryOwner() is Character c && c != character, SpeakIfFails = !objectiveManager.IsCurrentOrder <AIObjectiveCleanupItems>() },