3 using System.Collections.Generic;
11 public override string DebugTag => $
"{Identifier} ({gearTag})";
21 private Item targetItem;
22 private int? oxygenSourceSlotIndex;
31 gearTag = needsDivingSuit ? Tags.HeavyDivingGear : Tags.LightDivingGear;
34 protected override void Act(
float deltaTime)
37 if (targetItem ==
null && gearTag == Tags.LightDivingGear)
43 bool findDivingGear = targetItem ==
null ||
51 if (gearTag == Tags.LightDivingGear)
58 targetItem = divingSuit;
59 findDivingGear =
false;
64 TryAddSubObjective(ref getDivingGear, () =>
68 character.Speak(TextManager.Get(
"DialogGetDivingGear").Value, null, 0.0f,
"getdivinggear".ToIdentifier(), 30.0f);
73 AllowToFindDivingGear =
false,
74 AllowDangerousPressure =
true,
78 if (gearTag == Tags.HeavyDivingGear)
80 if (mustFindMorePressureProtection)
84 getItemObjective.ItemFilter = it => IsSuitablePressureProtection(it, gearTag, character);
90 getItemObjective.GetItemPriority = it => IsSuitablePressureProtection(it, gearTag, character) ? 1000.0f : 1.0f;
92 getItemObjective.GetItemPriority = it =>
94 if (IsSuitablePressureProtection(it, gearTag, character))
103 return mustFindMorePressureProtection ? 0.0f : 1.0f;
107 return getItemObjective;
116 RemoveSubObjective(ref getDivingGear);
119 foreach (
Item mask
in masks)
121 if (mask != targetItem)
132 float min = GetMinOxygen(character);
135 TryAddSubObjective(ref getOxygen, () =>
137 if (character.IsOnPlayerTeam)
139 if (HumanAIController.HasItem(character, Tags.OxygenSource, out _, conditionPercentage: min))
141 character.Speak(TextManager.Get(
"dialogswappingoxygentank").Value, null, 0,
"swappingoxygentank".ToIdentifier(), 30.0f);
142 if (character.Inventory.FindAllItems(i => i.HasTag(Tags.OxygenSource) && i.Condition > min, recursive: true).Count == 1)
144 character.Speak(TextManager.Get(
"dialoglastoxygentank").Value, null, 0.0f,
"dialoglastoxygentank".ToIdentifier(), 30.0f);
149 character.Speak(TextManager.Get(
"DialogGetOxygenTank").Value, null, 0,
"getoxygentank".ToIdentifier(), 30.0f);
153 var objective =
new AIObjectiveContainItem(character, Tags.OxygenSource, container, objectiveManager, spawnItemIfNotFound: character.TeamID ==
CharacterTeamType.FriendlyNPC)
155 AllowToFindDivingGear =
false,
156 AllowDangerousPressure =
true,
157 ConditionLevel = MIN_OXYGEN,
158 RemoveExistingWhenNecessary =
true,
159 TargetSlot = oxygenSourceSlotIndex
161 if (container.HasSubContainers)
166 objective.RemoveExistingPredicate = i => objective.IsInTargetSlot(i);
172 int remainingTanks = ReportOxygenTankCount();
174 TryAddSubObjective(ref getOxygen, () =>
176 return new AIObjectiveContainItem(character, Tags.OxygenSource, targetItem.GetComponent<
ItemContainer>(), objectiveManager, spawnItemIfNotFound: character.TeamID ==
CharacterTeamType.FriendlyNPC)
178 AllowToFindDivingGear =
false,
179 AllowDangerousPressure =
true,
180 RemoveExisting =
true
186 if (remainingTanks > 0 && !HumanAIController.HasItem(character, Tags.OxygenSource, out _, conditionPercentage: 0.01f))
188 character.Speak(TextManager.Get(
"dialogcantfindtoxygen").Value,
null, 0,
"cantfindoxygen".ToIdentifier(), 30.0f);
191 onCompleted: () => RemoveSubObjective(ref getOxygen));
195 RemoveSubObjective(ref getOxygen);
196 ReportOxygenTankCount();
199 int ReportOxygenTankCount()
201 if (character.Submarine !=
Submarine.MainSub) {
return 1; }
202 int remainingOxygenTanks =
Submarine.MainSub.GetItems(
false).Count(i => i.HasTag(Tags.OxygenSource) && i.Condition > 1);
203 if (remainingOxygenTanks == 0)
205 character.Speak(TextManager.Get(
"DialogOutOfOxygenTanks").Value,
null, 0.0f,
"outofoxygentanks".ToIdentifier(), 30.0f);
207 else if (remainingOxygenTanks < 10)
209 character.Speak(TextManager.Get(
"DialogLowOnOxygenTanks").Value,
null, 0.0f,
"lowonoxygentanks".ToIdentifier(), 30.0f);
211 return remainingOxygenTanks;
219 if (tag == Tags.HeavyDivingGear)
231 private bool IsSuitableContainedOxygenSource(
Item item)
235 item.
HasTag(Tags.OxygenSource) &&
240 private void TrySetTargetItem(Item item)
242 if (targetItem == item) {
return; }
244 oxygenSourceSlotIndex = targetItem?.GetComponent<
ItemContainer>()?.FindSuitableSubContainerIndex(Tags.OxygenSource);
250 getDivingGear =
null;
253 oxygenSourceSlotIndex =
null;
263 if (minOxygen > min && character.
Inventory.
AllItems.Any(i => i.HasTag(Tags.OxygenSource) && i.ConditionPercentage >= minOxygen))
override bool AllowWhileHandcuffed
static float GetMinOxygen(Character character)
AIObjectiveFindDivingGear(Character character, bool needsDivingSuit, AIObjectiveManager objectiveManager, float priorityModifier=1)
override void Act(float deltaTime)
override Identifier Identifier
static bool IsSuitablePressureProtection(Item item, Identifier tag, Character character)
override bool KeepDivingGearOn
override bool AbandonWhenCannotCompleteSubObjectives
override bool CheckObjectiveState()
Should return whether the objective is completed or not.
readonly Character character
readonly AIObjectiveManager objectiveManager
bool FailedToFindDivingGearForDepth
bool HasEquippedItem(Item item, InvSlotType? slotType=null, Func< InvSlotType, bool > predicate=null)
CharacterInventory Inventory
Item GetEquippedItem(Identifier tagOrIdentifier=default, InvSlotType? slotType=null)
override bool TryPutItem(Item item, Character user, IEnumerable< InvSlotType > allowedSlots=null, bool createNetworkEvent=true, bool ignoreCondition=false)
If there is room, puts the item in the inventory and returns true, otherwise returns false
static readonly List< InvSlotType > AnySlot
virtual Vector2 WorldPosition
static bool HasItem(Character character, Identifier tagOrIdentifier, out IEnumerable< Item > items, Identifier containedTag=default, float conditionPercentage=0, bool requireEquipped=false, bool recursive=true, Func< Item, bool > predicate=null)
Note: uses a single list for matching items. The item is reused each time when the method is called....
bool NeedsDivingGear(Hull hull, out bool needsSuit)
Item FindItem(Func< Item, bool > predicate, bool recursive)
virtual IEnumerable< Item > AllItems
All items contained in the inventory. Stacked items are returned as individual instances....
bool IsInSlot(Item item, int index)
ItemInventory OwnInventory
Inventory ParentInventory
bool HasTag(Identifier tag)
IEnumerable< Item > ContainedItems
int? FindSuitableSubContainerIndex(Identifier itemTagOrIdentifier)
Returns the index of the first slot whose restrictions match the specified tag or identifier
const float PressureWarningThreshold
How many units before crush depth the pressure warning is shown
readonly float PressureProtection
How deep down does the item protect from pressure? Determined by status effects.
float GetRealWorldDepth(float worldPositionY)
Calculate the "real" depth in meters from the surface of Europa (the value you see on the nav termina...