Server LuaCsForBarotrauma
All Classes Namespaces Functions Variables Enumerations Enumerator Properties Events
AITarget.cs
1 using Microsoft.Xna.Framework;
2 using System;
3 using System.Collections.Generic;
4 using System.Xml.Linq;
5 
6 namespace Barotrauma
7 {
8  partial class AITarget
9  {
10  public static List<AITarget> List = new List<AITarget>();
11 
12  private Entity entity;
13  public Entity Entity
14  {
15  get
16  {
17  if (entity != null && entity.Removed) { return null; }
18  return entity;
19  }
20  }
21 
22  private float soundRange;
23  private float sightRange;
24 
28  public float FadeOutTime { get; private set; } = 2;
29 
30  public bool Static { get; private set; }
31  public bool StaticSound { get; private set; }
32  public bool StaticSight { get; private set; }
33 
34  public float SoundRange
35  {
36  get { return soundRange; }
37  set
38  {
39  if (float.IsNaN(value))
40  {
41  DebugConsole.ThrowError("Attempted to set the SoundRange of an AITarget to NaN.\n" + Environment.StackTrace.CleanupStackTrace());
42  return;
43  }
44  soundRange = MathHelper.Clamp(value, MinSoundRange, MaxSoundRange);
45  if (soundRange > 0.0f && !Static && FadeOutTime > 0.0f)
46  {
47  NeedsUpdate = true;
48  }
49  }
50  }
51 
52  public float SightRange
53  {
54  get { return sightRange; }
55  set
56  {
57  if (float.IsNaN(value))
58  {
59  DebugConsole.ThrowError("Attempted to set the SightRange of an AITarget to NaN.\n" + Environment.StackTrace.CleanupStackTrace());
60  return;
61  }
62  sightRange = MathHelper.Clamp(value, MinSightRange, MaxSightRange);
63  if (sightRange > 0 && !Static && FadeOutTime > 0.0f)
64  {
65  NeedsUpdate = true;
66  }
67  }
68  }
69 
70  private float sectorRad = MathHelper.TwoPi;
71  public float SectorDegrees
72  {
73  get { return MathHelper.ToDegrees(sectorRad); }
74  set { sectorRad = MathHelper.ToRadians(value); }
75  }
76 
77  private Vector2 sectorDir;
78  public Vector2 SectorDir
79  {
80  get { return sectorDir; }
81  set
82  {
83  if (!MathUtils.IsValid(value))
84  {
85  string errorMsg = "Invalid AITarget sector direction (" + value + ")\n" + Environment.StackTrace.CleanupStackTrace();
86  DebugConsole.ThrowError(errorMsg);
87  GameAnalyticsManager.AddErrorEventOnce("AITarget.SectorDir:" + entity?.ToString(), GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
88  return;
89  }
90  sectorDir = value;
91  }
92  }
93 
94  public float SonarDisruption
95  {
96  get;
97  set;
98  }
99 
101  public Identifier SonarIconIdentifier;
102 
103  private bool inDetectable;
104 
105  public double InDetectableSetTime;
106 
110  public bool InDetectable
111  {
112  get
113  {
114  return inDetectable || (SoundRange <= 0 && SightRange <= 0);
115  }
116  set
117  {
118  inDetectable = value;
119  if (inDetectable)
120  {
121  InDetectableSetTime = Timing.TotalTime;
122  NeedsUpdate = true;
123  }
124  }
125  }
126 
127 
128  public float MinSoundRange, MinSightRange;
129  public float MaxSoundRange = 100000, MaxSightRange = 100000;
130 
134  public bool NeedsUpdate
135  {
136  get;
137  private set;
138  } = true;
139 
140  public TargetType Type { get; private set; }
141 
142  public enum TargetType
143  {
144  Any,
145  HumanOnly,
146  EnemyOnly
147  }
148 
149  public Vector2 WorldPosition
150  {
151  get
152  {
153  if (entity == null || entity.Removed)
154  {
155 #if DEBUG
156  DebugConsole.ThrowError("Attempted to access a removed AITarget\n" + Environment.StackTrace.CleanupStackTrace());
157 #endif
158  GameAnalyticsManager.AddErrorEventOnce("AITarget.WorldPosition:EntityRemoved",
159  GameAnalyticsManager.ErrorSeverity.Error,
160  "Attempted to access a removed AITarget\n" + Environment.StackTrace.CleanupStackTrace());
161  return Vector2.Zero;
162  }
163 
164  return entity.WorldPosition;
165  }
166  }
167 
168  public Vector2 SimPosition
169  {
170  get
171  {
172  if (entity == null || entity.Removed)
173  {
174 #if DEBUG
175  DebugConsole.ThrowError("Attempted to access a removed AITarget\n" + Environment.StackTrace.CleanupStackTrace());
176 #endif
177  GameAnalyticsManager.AddErrorEventOnce("AITarget.WorldPosition:EntityRemoved",
178  GameAnalyticsManager.ErrorSeverity.Error,
179  "Attempted to access a removed AITarget\n" + Environment.StackTrace.CleanupStackTrace());
180  return Vector2.Zero;
181  }
182 
183  return entity.SimPosition;
184  }
185  }
186 
190  public bool ShouldBeIgnored()
191  {
192  if (InDetectable) { return true; }
193  if (Entity == null) { return true; }
195  {
196  return true;
197  }
198  return false;
199  }
200 
201  public AITarget(Entity e, XElement element) : this(e)
202  {
203  SightRange = element.GetAttributeFloat("sightrange", 0.0f);
204  SoundRange = element.GetAttributeFloat("soundrange", 0.0f);
205  MinSightRange = element.GetAttributeFloat("minsightrange", 0f);
206  MinSoundRange = element.GetAttributeFloat("minsoundrange", 0f);
207  MaxSightRange = element.GetAttributeFloat("maxsightrange", SightRange);
208  MaxSoundRange = element.GetAttributeFloat("maxsoundrange", SoundRange);
209  FadeOutTime = element.GetAttributeFloat("fadeouttime", FadeOutTime);
210  Static = element.GetAttributeBool("static", Static);
211  StaticSight = element.GetAttributeBool("staticsight", StaticSight);
212  StaticSound = element.GetAttributeBool("staticsound", StaticSound);
213  if (Static)
214  {
215  StaticSound = true;
216  StaticSight = true;
217  }
218  SonarDisruption = element.GetAttributeFloat("sonardisruption", 0.0f);
219  string label = element.GetAttributeString("sonarlabel", "");
220  SonarLabel = TextManager.Get(label).Fallback(label);
221  SonarIconIdentifier = element.GetAttributeIdentifier("sonaricon", Identifier.Empty);
222  Type = element.GetAttributeEnum("type", TargetType.Any);
223  Reset();
224  }
225 
226  public AITarget(Entity e)
227  {
228  entity = e;
229  List.Add(this);
230  }
231 
232  public void Update(float deltaTime)
233  {
234  InDetectable = false;
235  if (!Static && FadeOutTime > 0)
236  {
237  // The aitarget goes silent/invisible if the components don't keep it active
238  if (!StaticSight && sightRange > 0)
239  {
240  DecreaseSightRange(deltaTime);
241  }
242  if (!StaticSound && soundRange > 0)
243  {
244  DecreaseSoundRange(deltaTime);
245  }
246  if (sightRange <= 0 && soundRange <= 0)
247  {
248  NeedsUpdate = false;
249  }
250  }
251  else
252  {
253  NeedsUpdate = false;
254  }
255  }
256 
257  public void IncreaseSoundRange(float deltaTime, float speed = 1)
258  {
259  SoundRange += speed * deltaTime * (MaxSoundRange / FadeOutTime);
260  }
261 
262  public void IncreaseSightRange(float deltaTime, float speed = 1)
263  {
264  SightRange += speed * deltaTime * (MaxSightRange / FadeOutTime);
265  }
266 
267  public void DecreaseSoundRange(float deltaTime, float speed = 1)
268  {
269  SoundRange -= speed * deltaTime * (MaxSoundRange / FadeOutTime);
270  }
271 
272  public void DecreaseSightRange(float deltaTime, float speed = 1)
273  {
274  SightRange -= speed * deltaTime * (MaxSightRange / FadeOutTime);
275  }
276 
277  public bool HasSector()
278  {
279  return sectorRad < MathHelper.TwoPi;
280  }
281 
282  public bool IsWithinSector(Vector2 worldPosition)
283  {
284  if (!HasSector()) { return true; }
285  Vector2 diff = worldPosition - WorldPosition;
286  return Math.Abs(MathUtils.GetShortestAngle(MathUtils.VectorToAngle(diff), MathUtils.VectorToAngle(sectorDir))) <= sectorRad * 0.5f;
287  }
288 
289  public void Remove()
290  {
291  List.Remove(this);
292  entity = null;
293  }
294 
295  public void Reset()
296  {
297  if (Static)
298  {
299  SightRange = MaxSightRange;
301  }
302  else
303  {
304  // Non-static ai targets must be kept alive by a custom logic (e.g. item components)
305  SightRange = StaticSight ? MaxSightRange : MinSightRange;
307  }
308  }
309  }
310 }
AITarget(Entity e, XElement element)
Definition: AITarget.cs:201
Vector2? SectorDir
Definition: AITarget.cs:79
double InDetectableSetTime
Definition: AITarget.cs:105
float SonarDisruption
Definition: AITarget.cs:95
void DecreaseSoundRange(float deltaTime, float speed=1)
Definition: AITarget.cs:267
bool NeedsUpdate
Does the AI target do something that requires Update() to be called (e.g. static targets don't need t...
Definition: AITarget.cs:135
float FadeOutTime
How long does it take for the ai target to fade out if not kept alive.
Definition: AITarget.cs:28
AITarget(Entity e)
Definition: AITarget.cs:226
Identifier SonarIconIdentifier
Definition: AITarget.cs:101
void IncreaseSoundRange(float deltaTime, float speed=1)
Definition: AITarget.cs:257
void IncreaseSightRange(float deltaTime, float speed=1)
Definition: AITarget.cs:262
static List< AITarget > List
Definition: AITarget.cs:10
bool ShouldBeIgnored()
Is some condition met (e.g. entity null, indetectable, outside level) that prevents anyone from detec...
Definition: AITarget.cs:190
void DecreaseSightRange(float deltaTime, float speed=1)
Definition: AITarget.cs:272
LocalizedString SonarLabel
Definition: AITarget.cs:100
bool IsWithinSector(Vector2 worldPosition)
Definition: AITarget.cs:282
TargetType Type
Definition: AITarget.cs:140
bool InDetectable
Should be reset to false each frame and kept indetectable by e.g. a status effect.
Definition: AITarget.cs:111
Vector2 SimPosition
Definition: AITarget.cs:169
Vector2 WorldPosition
Definition: AITarget.cs:150
void Update(float deltaTime)
Definition: AITarget.cs:232
virtual Vector2 WorldPosition
Definition: Entity.cs:49
virtual Vector2 SimPosition
Definition: Entity.cs:45
static bool IsPositionAboveLevel(Vector2 worldPosition)
Is the position above the upper boundary of the level ("outside bounds", where nothing should be able...
LocalizedString Fallback(LocalizedString fallback, bool useDefaultLanguageIfFound=true)
Use this text instead if the original text cannot be found.