Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
NPCUtils.cs
Go to the documentation of this file.
1using System;
3
4namespace Terraria.Utilities;
5
6public static class NPCUtils
7{
8 public delegate bool SearchFilter<T>(T entity) where T : Entity;
9
10 public delegate void NPCTargetingMethod(NPC searcher, bool faceTarget, Vector2? checkPosition);
11
12 public static class SearchFilters
13 {
14 public static bool OnlyCrystal(NPC npc)
15 {
16 if (npc.type == 548)
17 {
19 }
20 return false;
21 }
22
23 public static SearchFilter<Player> OnlyPlayersInCertainDistance(Vector2 position, float maxDistance)
24 {
25 return (Player player) => player.Distance(position) <= maxDistance;
26 }
27
28 public static bool NonBeeNPCs(NPC npc)
29 {
30 if (npc.type != 211 && npc.type != 210 && npc.type != 222)
31 {
32 return npc.CanBeChasedBy();
33 }
34 return false;
35 }
36
37 public static SearchFilter<Player> DownwindFromNPC(NPC npc, float maxDistanceX)
38 {
39 return delegate(Player player)
40 {
41 float windSpeedCurrent = Main.windSpeedCurrent;
42 float num = player.Center.X - npc.Center.X;
43 float num2 = Math.Abs(num);
44 float num3 = Math.Abs(player.Center.Y - npc.Center.Y);
45 return player.active && !player.dead && num3 < 100f && num2 < maxDistanceX && ((num > 0f && windSpeedCurrent > 0f) || (num < 0f && windSpeedCurrent < 0f));
46 };
47 }
48 }
49
50 public enum TargetType
51 {
52 None,
53 NPC,
54 Player,
56 }
57
58 public struct TargetSearchResults
59 {
61
62 private int _nearestNPCIndex;
63
64 private float _nearestNPCDistance;
65
66 private int _nearestTankIndex;
67
68 private float _nearestTankDistance;
69
70 private float _adjustedTankDistance;
71
73
75 {
76 get
77 {
78 switch (_nearestTargetType)
79 {
80 case TargetType.Player:
81 case TargetType.TankPet:
82 return _nearestTankIndex;
83 case TargetType.NPC:
85 default:
86 return -1;
87 }
88 }
89 }
90
92 {
93 TargetType.Player => NearestTankOwner.Hitbox,
94 TargetType.TankPet => Main.projectile[NearestTankOwner.tankPet].Hitbox,
95 TargetType.NPC => NearestNPC.Hitbox,
96 _ => Rectangle.Empty,
97 };
98
100
102
104 {
105 get
106 {
107 if (_nearestNPCIndex != -1)
108 {
109 return Main.npc[_nearestNPCIndex];
110 }
111 return null;
112 }
113 }
114
115 public bool FoundNPC => _nearestNPCIndex != -1;
116
118
120
122 {
123 get
124 {
125 if (_nearestTankIndex != -1)
126 {
128 }
129 return null;
130 }
131 }
132
133 public bool FoundTank => _nearestTankIndex != -1;
134
136
138
140
142
143 public TargetSearchResults(NPC searcher, int nearestNPCIndex, float nearestNPCDistance, int nearestTankIndex, float nearestTankDistance, float adjustedTankDistance, TargetType tankType)
144 {
145 _nearestNPCIndex = nearestNPCIndex;
146 _nearestNPCDistance = nearestNPCDistance;
147 _nearestTankIndex = nearestTankIndex;
148 _adjustedTankDistance = adjustedTankDistance;
149 _nearestTankDistance = nearestTankDistance;
150 _nearestTankType = tankType;
151 if (_nearestNPCIndex != -1 && _nearestTankIndex != -1)
152 {
154 {
156 }
157 else
158 {
159 _nearestTargetType = tankType;
160 }
161 }
162 else if (_nearestNPCIndex != -1)
163 {
165 }
166 else if (_nearestTankIndex != -1)
167 {
168 _nearestTargetType = tankType;
169 }
170 else
171 {
173 }
174 }
175 }
176
177 [Flags]
179 {
180 None = 0,
181 NPCs = 1,
182 Players = 2,
183 All = 3
184 }
185
186 public static TargetSearchResults SearchForTarget(Vector2 position, TargetSearchFlag flags = TargetSearchFlag.All, SearchFilter<Player> playerFilter = null, SearchFilter<NPC> npcFilter = null)
187 {
188 return SearchForTarget(null, position, flags, playerFilter, npcFilter);
189 }
190
191 public static TargetSearchResults SearchForTarget(NPC searcher, TargetSearchFlag flags = TargetSearchFlag.All, SearchFilter<Player> playerFilter = null, SearchFilter<NPC> npcFilter = null)
192 {
193 return SearchForTarget(searcher, searcher.Center, flags, playerFilter, npcFilter);
194 }
195
196 public static TargetSearchResults SearchForTarget(NPC searcher, Vector2 position, TargetSearchFlag flags = TargetSearchFlag.All, SearchFilter<Player> playerFilter = null, SearchFilter<NPC> npcFilter = null)
197 {
198 float num = float.MaxValue;
199 int nearestNPCIndex = -1;
200 float num2 = float.MaxValue;
201 float nearestTankDistance = float.MaxValue;
202 int nearestTankIndex = -1;
203 TargetType tankType = TargetType.Player;
204 if (flags.HasFlag(TargetSearchFlag.NPCs))
205 {
206 for (int i = 0; i < 200; i++)
207 {
208 NPC nPC = Main.npc[i];
209 if (nPC.active && nPC.whoAmI != searcher.whoAmI && (npcFilter == null || npcFilter(nPC)))
210 {
211 float num3 = Vector2.DistanceSquared(position, nPC.Center);
212 if (num3 < num)
213 {
214 nearestNPCIndex = i;
215 num = num3;
216 }
217 }
218 }
219 }
220 if (flags.HasFlag(TargetSearchFlag.Players))
221 {
222 for (int j = 0; j < 255; j++)
223 {
224 Player player = Main.player[j];
225 if (!player.active || player.dead || player.ghost || (playerFilter != null && !playerFilter(player)))
226 {
227 continue;
228 }
229 float num4 = Vector2.Distance(position, player.Center);
230 float num5 = num4 - (float)player.aggro;
231 bool flag = searcher != null && player.npcTypeNoAggro[searcher.type];
232 if (searcher != null && flag && searcher.direction == 0)
233 {
234 num5 += 1000f;
235 }
236 if (num5 < num2)
237 {
238 nearestTankIndex = j;
239 num2 = num5;
240 nearestTankDistance = num4;
241 tankType = TargetType.Player;
242 }
243 if (player.tankPet >= 0 && !flag)
244 {
245 Vector2 center = Main.projectile[player.tankPet].Center;
246 num4 = Vector2.Distance(position, center);
247 num5 = num4 - 200f;
248 if (num5 < num2 && num5 < 200f && Collision.CanHit(position, 0, 0, center, 0, 0))
249 {
250 nearestTankIndex = j;
251 num2 = num5;
252 nearestTankDistance = num4;
253 tankType = TargetType.TankPet;
254 }
255 }
256 }
257 }
258 return new TargetSearchResults(searcher, nearestNPCIndex, (float)Math.Sqrt(num), nearestTankIndex, nearestTankDistance, num2, tankType);
259 }
260
261 public static void TargetClosestOldOnesInvasion(NPC searcher, bool faceTarget = true, Vector2? checkPosition = null)
262 {
264 if (searchResults.FoundTarget)
265 {
266 searcher.target = searchResults.NearestTargetIndex;
267 searcher.targetRect = searchResults.NearestTargetHitbox;
268 if (searcher.ShouldFaceTarget(ref searchResults) && faceTarget)
269 {
270 searcher.FaceTarget();
271 }
272 }
273 }
274
275 public static void TargetClosestNonBees(NPC searcher, bool faceTarget = true, Vector2? checkPosition = null)
276 {
278 if (searchResults.FoundTarget)
279 {
280 searcher.target = searchResults.NearestTargetIndex;
281 searcher.targetRect = searchResults.NearestTargetHitbox;
282 if (searcher.ShouldFaceTarget(ref searchResults) && faceTarget)
283 {
284 searcher.FaceTarget();
285 }
286 }
287 }
288
289 public static void TargetClosestDownwindFromNPC(NPC searcher, float distanceMaxX, bool faceTarget = true, Vector2? checkPosition = null)
290 {
291 TargetSearchResults searchResults = SearchForTarget(searcher, TargetSearchFlag.Players, SearchFilters.DownwindFromNPC(searcher, distanceMaxX));
292 if (searchResults.FoundTarget)
293 {
294 searcher.target = searchResults.NearestTargetIndex;
295 searcher.targetRect = searchResults.NearestTargetHitbox;
296 if (searcher.ShouldFaceTarget(ref searchResults) && faceTarget)
297 {
298 searcher.FaceTarget();
299 }
300 }
301 }
302
303 public static void TargetClosestCommon(NPC searcher, bool faceTarget = true, Vector2? checkPosition = null)
304 {
305 searcher.TargetClosest(faceTarget);
306 }
307
308 public static void TargetClosestBetsy(NPC searcher, bool faceTarget = true, Vector2? checkPosition = null)
309 {
311 if (searchResults.FoundTarget)
312 {
313 TargetType value = searchResults.NearestTargetType;
314 if (searchResults.FoundTank && !searchResults.NearestTankOwner.dead)
315 {
316 value = TargetType.Player;
317 }
318 searcher.target = searchResults.NearestTargetIndex;
319 searcher.targetRect = searchResults.NearestTargetHitbox;
320 if (searcher.ShouldFaceTarget(ref searchResults, value) && faceTarget)
321 {
322 searcher.FaceTarget();
323 }
324 }
325 }
326}
static double Sqrt(double d)
static double Abs(double value)
static bool CanHit(Entity source, Entity target)
Definition Collision.cs:344
Vector2 Center
Definition Entity.cs:43
float Distance(Vector2 Other)
Definition Entity.cs:187
Rectangle Hitbox
Definition Entity.cs:164
static float windSpeedCurrent
Definition Main.cs:1360
static Projectile[] projectile
Definition Main.cs:1691
static NPC[] npc
Definition Main.cs:1685
static Player[] player
Definition Main.cs:1803
bool ShouldFaceTarget(ref NPCUtils.TargetSearchResults searchResults, NPCUtils.TargetType? overrideTargetType=null)
Definition NPC.cs:69788
void TargetClosest(bool faceTarget=true)
Definition NPC.cs:69934
bool dontTakeDamageFromHostiles
Definition NPC.cs:279
void FaceTarget()
Definition NPC.cs:69827
bool CanBeChasedBy(object attacker=null, bool ignoreDontTakeDamage=false)
Definition NPC.cs:86852
int type
Definition NPC.cs:445
int WhoAmIToTargettingIndex
Definition NPC.cs:718
bool[] npcTypeNoAggro
Definition Player.cs:2547
static SearchFilter< Player > DownwindFromNPC(NPC npc, float maxDistanceX)
Definition NPCUtils.cs:37
static SearchFilter< Player > OnlyPlayersInCertainDistance(Vector2 position, float maxDistance)
Definition NPCUtils.cs:23
static TargetSearchResults SearchForTarget(NPC searcher, Vector2 position, TargetSearchFlag flags=TargetSearchFlag.All, SearchFilter< Player > playerFilter=null, SearchFilter< NPC > npcFilter=null)
Definition NPCUtils.cs:196
static void TargetClosestBetsy(NPC searcher, bool faceTarget=true, Vector2? checkPosition=null)
Definition NPCUtils.cs:308
static void TargetClosestCommon(NPC searcher, bool faceTarget=true, Vector2? checkPosition=null)
Definition NPCUtils.cs:303
static void TargetClosestOldOnesInvasion(NPC searcher, bool faceTarget=true, Vector2? checkPosition=null)
Definition NPCUtils.cs:261
delegate void NPCTargetingMethod(NPC searcher, bool faceTarget, Vector2? checkPosition)
static void TargetClosestDownwindFromNPC(NPC searcher, float distanceMaxX, bool faceTarget=true, Vector2? checkPosition=null)
Definition NPCUtils.cs:289
static TargetSearchResults SearchForTarget(Vector2 position, TargetSearchFlag flags=TargetSearchFlag.All, SearchFilter< Player > playerFilter=null, SearchFilter< NPC > npcFilter=null)
Definition NPCUtils.cs:186
delegate bool SearchFilter< T >(T entity)
static void TargetClosestNonBees(NPC searcher, bool faceTarget=true, Vector2? checkPosition=null)
Definition NPCUtils.cs:275
static TargetSearchResults SearchForTarget(NPC searcher, TargetSearchFlag flags=TargetSearchFlag.All, SearchFilter< Player > playerFilter=null, SearchFilter< NPC > npcFilter=null)
Definition NPCUtils.cs:191
static float DistanceSquared(Vector2 value1, Vector2 value2)
Definition Vector2.cs:107
static float Distance(Vector2 value1, Vector2 value2)
Definition Vector2.cs:91
TargetSearchResults(NPC searcher, int nearestNPCIndex, float nearestNPCDistance, int nearestTankIndex, float nearestTankDistance, float adjustedTankDistance, TargetType tankType)
Definition NPCUtils.cs:143