Client LuaCsForBarotrauma
AIObjectiveInspectNoises.cs
1 using System;
2 
3 namespace Barotrauma
4 {
6  {
7  public override Identifier Identifier { get; set; } = "inspect noises".ToIdentifier();
8 
9  private AIObjectiveGoTo inspectNoiseObjective;
10 
14  const float InspectNoisePriority = 10.0f;
18  const float InspectNoisePriorityIncrease = 10.0f;
19  private const float InspectNoiseInterval = 1.0f;
20  private float inspectNoiseTimer;
21 
27  private const float InspectNoiseExpirationDelay = 60.0f;
28  private float inspectNoiseExpirationTimer = 0.0f;
29 
30  protected override float GetPriority() => inspectNoiseObjective?.Priority ?? 0.0f;
31 
33  : base(character, objectiveManager, priorityModifier)
34  {
35  inspectNoiseTimer = Rand.Range(0.0f, InspectNoiseInterval);
36  }
37 
38  public override void Update(float deltaTime)
39  {
40  base.Update(deltaTime);
41  inspectNoiseTimer -= deltaTime;
42  if (inspectNoiseTimer <= 0.0f)
43  {
44  CheckEnemyNoises();
45  inspectNoiseTimer = InspectNoiseInterval;
46  }
47  //if we're not currently inspecting the noise (something else taking priority), forget about it after a while
48  if (inspectNoiseObjective != null && objectiveManager.GetActiveObjective() != inspectNoiseObjective)
49  {
50  inspectNoiseExpirationTimer += deltaTime;
51  if (inspectNoiseExpirationTimer > InspectNoiseExpirationDelay)
52  {
53  inspectNoiseObjective.Abandon = true;
54  }
55  }
56  }
57 
61  private void CheckEnemyNoises()
62  {
63  if (character.CurrentHull == null) { return; }
64 
65  //forget about inspecting if we're doing another subobjective (= fighting something)
66  if (inspectNoiseObjective != null &&
67  CurrentSubObjective != inspectNoiseObjective)
68  {
69  inspectNoiseObjective.Abandon = true;
70  }
71 
72  foreach (var aiTarget in AITarget.List)
73  {
74  if (aiTarget.ShouldBeIgnored()) { continue; }
75  if (!aiTarget.IsWithinSector(character.WorldPosition)) { continue; }
76  if (aiTarget.Entity is not Item item) { continue; }
77  if (!item.HasTag(Tags.ProvocativeToHumanAI)) { continue; }
78  if (item.GetRootInventoryOwner() is Character targetCharacter &&
79  AIObjectiveFightIntruders.IsValidTarget(targetCharacter, character, targetCharactersInOtherSubs: false))
80  {
81  float dist = character.CurrentHull.GetApproximateDistance(character.Position, targetCharacter.Position, targetCharacter.CurrentHull, aiTarget.SoundRange, distanceMultiplierPerClosedDoor: 2);
82  if (dist * HumanAIController.Hearing > aiTarget.SoundRange) { continue; }
83 
84  character.Speak(TextManager.Get("dialogheardenemy").Value, identifier: "heardenemy".ToIdentifier(), minDurationBetweenSimilar: 30.0f);
85  if (inspectNoiseObjective != null && subObjectives.Contains(inspectNoiseObjective))
86  {
87  //priority of inspecting noises increases with each noise
88  //but orders still remain a higher priority
89  inspectNoiseObjective.Priority = Math.Min(inspectNoiseObjective.Priority + InspectNoisePriorityIncrease, AIObjectiveManager.LowestOrderPriority - 1);
90  //only refresh the target if the character hasn't yet started inspecting the noise
91  //(if it has, it should not switch the target, otherwise you could e.g. bounce an NPC back and forth by firing guns at different sides of an outpost)
92  if (objectiveManager.GetActiveObjective() != inspectNoiseObjective &&
93  inspectNoiseObjective.Target != targetCharacter.CurrentHull)
94  {
95  CreateInspectNoiseObjective(targetCharacter.CurrentHull, priority: inspectNoiseObjective.Priority);
96  }
97  }
98  else
99  {
100  CreateInspectNoiseObjective(targetCharacter.CurrentHull, priority: InspectNoisePriority);
101  }
102  }
103  }
104 
105  void CreateInspectNoiseObjective(ISpatialEntity target, float priority)
106  {
107  RemoveSubObjective(ref inspectNoiseObjective);
108  inspectNoiseObjective = new AIObjectiveGoTo(target, character, objectiveManager)
109  {
110  Priority = priority,
111  SourceObjective = this
112  };
113  inspectNoiseObjective.Completed += () => { inspectNoiseObjective = null; inspectNoiseExpirationTimer = 0.0f; };
114  inspectNoiseObjective.Abandoned += () => { inspectNoiseObjective = null; inspectNoiseExpirationTimer = 0.0f; };
115  AddSubObjective(inspectNoiseObjective);
116  }
117  }
118 
119  protected override void Act(float deltaTime)
120  {
121  }
122 
123  protected override bool CheckObjectiveState() => false;
124  }
125 }
AIObjective SourceObjective
Which objective (if any) created this objective. When this is a subobjective, the parent objective is...
float Priority
Final priority value after all calculations.
void AddSubObjective(AIObjective objective, bool addFirst=false)
Action Completed
A single shot event. Automatically cleared after launching. Use OnCompleted method for implementing (...
Action Abandoned
A single shot event. Automatically cleared after launching. Use OnAbandoned method for implementing (...
override bool CheckObjectiveState()
Should return whether the objective is completed or not.
AIObjectiveInspectNoises(Character character, AIObjectiveManager objectiveManager, float priorityModifier=1)
override void Update(float deltaTime)
AIObjective GetActiveObjective()
void Speak(string message, ChatMessageType? messageType=null, float delay=0.0f, Identifier identifier=default, float minDurationBetweenSimilar=0.0f)
virtual Vector2 WorldPosition
Definition: Entity.cs:49
float GetApproximateDistance(Vector2 startPos, Vector2 endPos, Hull targetHull, float maxDistance, float distanceMultiplierPerClosedDoor=0)
Approximate distance from this hull to the target hull, moving through open gaps without passing thro...
float Hearing
Affects how far the character can hear sounds created by AI targets with the tag ProvocativeToHumanAI...