Client LuaCsForBarotrauma
AIObjectiveCleanupItem.cs
3 using Microsoft.Xna.Framework;
4 using System;
5 using System.Collections.Generic;
6 using System.Linq;
7 
8 namespace Barotrauma
9 {
11  {
12  public override Identifier Identifier { get; set; } = "cleanup item".ToIdentifier();
13  public override bool KeepDivingGearOn => true;
14  public override bool AllowAutomaticItemUnequipping => false;
15  protected override bool AllowWhileHandcuffed => false;
16 
17  public readonly Item item;
18  public bool IsPriority { get; set; }
19 
20  private readonly List<Item> ignoredContainers = new List<Item>();
21  private AIObjectiveDecontainItem decontainObjective;
22  private int itemIndex = 0;
23 
27  protected override bool ConcurrentObjectives => true;
28 
30  : base(character, objectiveManager, priorityModifier)
31  {
32  this.item = item;
33  }
34 
35  protected override float GetPriority()
36  {
37  if (!IsAllowed)
38  {
40  return Priority;
41  }
42  else
43  {
44  float distanceFactor = 0.9f;
46  {
47  distanceFactor = GetDistanceFactor(item.WorldPosition, verticalDistanceMultiplier: 5, maxDistance: 5000,
48  factorAtMinDistance: 0.9f, factorAtMaxDistance: 0);
49  }
50  bool isSelected = character.HasItem(item);
51  float selectedBonus = isSelected ? 100 - MaxDevotion : 0;
52  float devotion = (CumulatedDevotion + selectedBonus) / 100;
53  float reduction = IsPriority ? 1 : isSelected ? 2 : 3;
54  float max = AIObjectiveManager.LowestOrderPriority - reduction;
55  Priority = MathHelper.Lerp(0, max, MathHelper.Clamp(devotion + (distanceFactor * PriorityModifier), 0, 1));
56  if (decontainObjective == null)
57  {
58  // Halve the priority until there's a decontain objective (a valid container was found).
59  Priority /= 2;
60  }
61  }
62  return Priority;
63  }
64 
65  protected override void Act(float deltaTime)
66  {
67  if (subObjectives.Any()) { return; }
68  if (HumanAIController.FindSuitableContainer(character, item, ignoredContainers, ref itemIndex, out Item suitableContainer))
69  {
70  if (suitableContainer != null)
71  {
72  bool equip = item.GetComponent<Holdable>() != null ||
73  item.AllowedSlots.Any(s => s != InvSlotType.Any) &&
74  item.AllowedSlots.None(s =>
75  s == InvSlotType.Card ||
76  s == InvSlotType.Head ||
77  s == InvSlotType.Headset ||
78  s == InvSlotType.InnerClothes ||
79  s == InvSlotType.OuterClothes ||
80  s == InvSlotType.HealthInterface);
81 
82  TryAddSubObjective(ref decontainObjective, () => new AIObjectiveDecontainItem(character, item, objectiveManager, targetContainer: suitableContainer.GetComponent<ItemContainer>())
83  {
84  Equip = equip,
85  TakeWholeStack = true,
86  DropIfFails = true
87  },
88  onCompleted: () =>
89  {
90  if (equip)
91  {
92  HumanAIController.ReequipUnequipped();
93  }
94  IsCompleted = true;
95  },
96  onAbandon: () =>
97  {
98  if (equip)
99  {
101  }
102  if (decontainObjective != null && decontainObjective.ContainObjective != null && decontainObjective.ContainObjective.CanBeCompleted)
103  {
104  ignoredContainers.Add(suitableContainer);
105  }
106  else
107  {
108  Abandon = true;
109  }
110  });
111  }
112  else
113  {
114  Abandon = true;
115  }
116  }
117  objectiveManager.GetObjective<AIObjectiveIdle>().Wander(deltaTime);
118  }
119 
120  protected override bool CheckObjectiveState()
121  {
122  if (item.IgnoreByAI(character) || Item.DeconstructItems.Contains(item))
123  {
124  Abandon = true;
125  }
126  else if (item.ParentInventory != null && item.GetRootInventoryOwner() != character)
127  {
128  if (!objectiveManager.HasOrder<AIObjectiveCleanupItems>())
129  {
130  // Don't allow taking items from containers in the idle state.
131  Abandon = true;
132  }
133  else if (item.Container != null && !AIObjectiveCleanupItems.IsValidContainer(item.Container, character))
134  {
135  // Target was picked up or moved by someone.
136  Abandon = true;
137  }
138  }
139  return !Abandon && IsCompleted;
140  }
141 
142  public override void Reset()
143  {
144  base.Reset();
145  ignoredContainers.Clear();
146  itemIndex = 0;
147  decontainObjective = null;
148  }
149 
150  public void DropTarget()
151  {
152  if (item != null && character.HasItem(item))
153  {
154  item.Drop(character);
155  }
156  }
157  }
158 }
override bool CheckObjectiveState()
Should return whether the objective is completed or not.
override bool ConcurrentObjectives
Allows decontainObjective to be interrupted if this objective gets abandoned (e.g....
AIObjectiveCleanupItem(Item item, Character character, AIObjectiveManager objectiveManager, float priorityModifier=1)
override void Act(float deltaTime)
static bool IsValidContainer(Item container, Character character)
float Priority
Final priority value after all calculations.
static float GetDistanceFactor(Vector2 selfPos, Vector2 targetWorldPos, float factorAtMaxDistance, float verticalDistanceMultiplier=3, float maxDistance=10000.0f, float factorAtMinDistance=1.0f)
Get a normalized value representing how close the target position is. The value is a rough estimation...
const float LowestOrderPriority
Maximum priority of an order given to the character (rightmost order in the crew list)
bool HasItem(Item item, bool requireEquipped=false, InvSlotType? slotType=null)
bool FindSuitableContainer(Item containableItem, out Item suitableContainer)
IEnumerable< InvSlotType > AllowedSlots
static HashSet< Item > DeconstructItems
Items that have been marked for deconstruction