public override void Update(float deltaTime) { if (item == null) { #if DEBUG DebugConsole.ThrowError("Error in salvage mission " + Prefab.Identifier + " (item was null)"); #endif return; } if (IsClient) { if (item.ParentInventory != null && item.body != null) { item.body.FarseerBody.BodyType = BodyType.Dynamic; } return; } switch (State) { case 0: if (item.ParentInventory != null && item.body != null) { item.body.FarseerBody.BodyType = BodyType.Dynamic; } if (showMessageWhenPickedUp) { if (!(item.GetRootInventoryOwner() is Character)) { return; } } else { Submarine parentSub = item.CurrentHull?.Submarine ?? item.GetRootInventoryOwner()?.Submarine; if (parentSub == null || parentSub.Info.Type != SubmarineType.Player) { return; } } State = 1; break; case 1: if (!Submarine.MainSub.AtEndPosition && !Submarine.MainSub.AtStartPosition) { return; } State = 2; break; } }
public AIObjectiveGetItem(Character character, Item targetItem, AIObjectiveManager objectiveManager, bool equip = true, float priorityModifier = 1) : base(character, objectiveManager, priorityModifier) { currSearchIndex = -1; this.equip = equip; this.targetItem = targetItem; moveToTarget = targetItem?.GetRootInventoryOwner(); }
private bool HasBeenCollected(Item item) { if (item == null) { return(false); } if (item.Removed) { return(false); } var owner = item.GetRootInventoryOwner(); if (owner.Submarine != null && owner.Submarine.Info.Type == SubmarineType.Player) { return(true); } else if (owner is Character c) { return(c.Info != null && GameMain.GameSession.CrewManager.CharacterInfos.Contains(c.Info)); } return(false); }
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 (character.LockHands) { Abandon = true; return; } if (itemIdentifiers != null && !isDoneSeeking) { if (checkInventory) { if (CheckInventory()) { isDoneSeeking = true; } } if (!isDoneSeeking) { bool dangerousPressure = character.CurrentHull == null || character.CurrentHull.LethalPressure > 0; if (dangerousPressure) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Seeking item aborted, because the pressure is dangerous.", Color.Yellow); #endif Abandon = true; return; } FindTargetItem(); 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 Reset(); } 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, out _, 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; } if (equip) { if (HumanAIController.TryToMoveItem(targetItem, character.Inventory)) { targetItem.Equip(character); 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 (character.Inventory.TryPutItem(targetItem, character, new List <InvSlotType>() { InvSlotType.Any })) { IsCompleted = true; } else { Abandon = true; #if DEBUG DebugConsole.NewMessage($"{character.Name}: Failed to equip/move the item '{targetItem.Name}' into the character inventory. Aborting.", Color.Red); #endif } } } 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 = () => targetItem == null || targetItem.GetRootInventoryOwner() != moveToTarget, DialogueIdentifier = "dialogcannotreachtarget", TargetName = (moveToTarget as MapEntity)?.Name ?? (moveToTarget as Character)?.Name ?? moveToTarget.ToString() }); }, onAbandon: () => { ignoredItems.Add(targetItem); Reset(); }, onCompleted: () => RemoveSubObjective(ref goToObjective)); } }
protected override void Act(float deltaTime) { if (character.LockHands) { Abandon = true; return; } if (itemIdentifiers != null && !isDoneSeeking) { if (checkInventory) { if (CheckInventory()) { isDoneSeeking = true; } } if (!isDoneSeeking) { bool dangerousPressure = character.CurrentHull == null || character.CurrentHull.LethalPressure > 0; if (dangerousPressure) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Seeking item aborted, because the pressure is dangerous.", Color.Yellow); #endif Abandon = true; return; } FindTargetItem(); 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; } if (character.IsItemTakenBySomeoneElse(targetItem)) { #if DEBUG DebugConsole.NewMessage($"{character.Name}: Found an item, but it's already equipped by someone else.", Color.Yellow); #endif // Try again Reset(); 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, out _, 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; } if (equip) { int targetSlot = -1; //check if all the slots required by the item are free foreach (InvSlotType slots in pickable.AllowedSlots) { if (slots.HasFlag(InvSlotType.Any)) { continue; } for (int i = 0; i < character.Inventory.Items.Length; i++) { //slot not needed by the item, continue if (!slots.HasFlag(character.Inventory.SlotTypes[i])) { continue; } targetSlot = i; //slot free, continue var otherItem = character.Inventory.Items[i]; if (otherItem == null) { continue; } //try to move the existing item to LimbSlot.Any and continue if successful if (otherItem.AllowedSlots.Contains(InvSlotType.Any) && character.Inventory.TryPutItem(otherItem, character, new List <InvSlotType>() { InvSlotType.Any })) { continue; } //if everything else fails, simply drop the existing item otherItem.Drop(character); } } if (character.Inventory.TryPutItem(targetItem, targetSlot, false, false, character)) { targetItem.Equip(character); 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 (character.Inventory.TryPutItem(targetItem, null, new List <InvSlotType>() { InvSlotType.Any })) { IsCompleted = true; } else { Abandon = true; #if DEBUG DebugConsole.NewMessage($"{character.Name}: Failed to equip/move the item '{targetItem.Name}' into the character inventory. Aborting.", Color.Red); #endif } } } 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 = () => targetItem == null || targetItem.GetRootInventoryOwner() != moveToTarget, DialogueIdentifier = "dialogcannotreachtarget", TargetName = (moveToTarget as MapEntity)?.Name ?? (moveToTarget as Character)?.Name ?? moveToTarget.ToString() }); }, onAbandon: () => { ignoredItems.Add(targetItem); Reset(); }, onCompleted: () => RemoveSubObjective(ref goToObjective)); } }