Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
LockOnHelper.cs
Go to the documentation of this file.
1using System;
6using Terraria.ID;
7
8namespace Terraria.GameInput;
9
10public class LockOnHelper
11{
12 public enum LockOnMode
13 {
17 }
18
19 private const float LOCKON_RANGE = 2000f;
20
21 private const int LOCKON_HOLD_LIFETIME = 40;
22
23 public static LockOnMode UseMode = LockOnMode.ThreeDS;
24
25 private static bool _enabled;
26
27 private static bool _canLockOn;
28
29 private static List<int> _targets = new List<int>();
30
31 private static int _pickedTarget;
32
33 private static int _lifeTimeCounter;
34
35 private static int _lifeTimeArrowDisplay;
36
37 private static int _threeDSTarget = -1;
38
39 private static int _targetClosestTarget = -1;
40
41 public static bool ForceUsability = false;
42
43 private static float[,] _drawProgress = new float[200, 2];
44
45 public static NPC AimedTarget
46 {
47 get
48 {
49 if (_pickedTarget == -1 || _targets.Count < 1)
50 {
51 return null;
52 }
54 }
55 }
56
58 {
59 get
60 {
62 if (aimedTarget == null)
63 {
64 return Vector2.Zero;
65 }
66 Vector2 vector = aimedTarget.Center;
68 {
69 vector = pos;
70 vector += Main.npc[index].Distance(Main.player[Main.myPlayer].Center) / 2000f * Main.npc[index].velocity * 45f;
71 }
72 Player player = Main.player[Main.myPlayer];
73 int num = ItemID.Sets.LockOnAimAbove[player.inventory[player.selectedItem].type];
74 while (num > 0 && vector.Y > 100f)
75 {
76 Point point = vector.ToTileCoordinates();
77 point.Y -= 4;
78 if (!WorldGen.InWorld(point.X, point.Y, 10) || WorldGen.SolidTile(point.X, point.Y))
79 {
80 break;
81 }
82 vector.Y -= 16f;
83 num--;
84 }
86 if (num2.HasValue)
87 {
88 vector.Y -= aimedTarget.height / 2;
89 Vector2 v = vector - player.Center;
90 Vector2 vector2 = v.SafeNormalize(Vector2.Zero);
91 vector2.Y -= 1f;
92 float num3 = v.Length();
93 num3 = (float)Math.Pow(num3 / 700f, 2.0) * 700f;
94 vector.Y += vector2.Y * num3 * num2.Value * 1f;
95 vector.X += (0f - vector2.X) * num3 * num2.Value * 1f;
96 }
97 return vector;
98 }
99 }
100
101 public static bool Enabled => _enabled;
102
103 public static void CycleUseModes()
104 {
105 switch (UseMode)
106 {
107 case LockOnMode.FocusTarget:
108 UseMode = LockOnMode.TargetClosest;
109 break;
110 case LockOnMode.TargetClosest:
111 UseMode = LockOnMode.ThreeDS;
112 break;
113 case LockOnMode.ThreeDS:
114 UseMode = LockOnMode.TargetClosest;
115 break;
116 }
117 }
118
119 public static void Update()
120 {
121 _canLockOn = false;
122 if (!CanUseLockonSystem())
123 {
124 SetActive(on: false);
125 return;
126 }
127 if (--_lifeTimeArrowDisplay < 0)
128 {
130 }
133 if (PlayerInput.Triggers.JustPressed.LockOn && !PlayerInput.WritingText)
134 {
135 _lifeTimeCounter = 40;
138 }
139 if (!_enabled)
140 {
141 return;
142 }
143 if (UseMode == LockOnMode.FocusTarget && PlayerInput.Triggers.Current.LockOn)
144 {
145 if (_lifeTimeCounter <= 0)
146 {
147 SetActive(on: false);
148 return;
149 }
151 }
154 {
155 SetActive(on: false);
156 }
157 if (UseMode == LockOnMode.TargetClosest)
158 {
159 SetActive(on: false);
161 }
162 if (_enabled)
163 {
164 Player player = Main.player[Main.myPlayer];
166 bool flag = false;
167 if (ShouldLockOn(player) && (ItemID.Sets.LockOnIgnoresCollision[player.inventory[player.selectedItem].type] || Collision.CanHit(player.Center, 0, 0, predictedPosition, 0, 0) || Collision.CanHitLine(player.Center, 0, 0, predictedPosition, 0, 0) || Collision.CanHit(player.Center, 0, 0, aimedTarget.Center, 0, 0) || Collision.CanHitLine(player.Center, 0, 0, aimedTarget.Center, 0, 0)))
168 {
169 flag = true;
170 }
171 if (flag)
172 {
173 _canLockOn = true;
174 }
175 }
176 }
177
178 public static bool CanUseLockonSystem()
179 {
180 if (!ForceUsability)
181 {
183 }
184 return true;
185 }
186
187 public static void SetUP()
188 {
189 if (_canLockOn)
190 {
191 _ = AimedTarget;
193 }
194 }
195
196 public static void SetDOWN()
197 {
198 if (_canLockOn)
199 {
201 }
202 }
203
204 private static bool ShouldLockOn(Player p)
205 {
206 int type = p.inventory[p.selectedItem].type;
207 if (type == 496)
208 {
209 return false;
210 }
211 return true;
212 }
213
214 public static void Toggle(bool forceOff = false)
215 {
216 _lifeTimeCounter = 40;
219 if (forceOff)
220 {
221 _enabled = false;
222 }
223 }
224
225 private static void FindMostViableTarget(LockOnMode context, ref int targetVar)
226 {
227 targetVar = -1;
228 if (UseMode == context && CanUseLockonSystem())
229 {
230 List<int> t = new List<int>();
231 int t2 = -1;
232 Utils.Swap(ref t, ref _targets);
236 Utils.Swap(ref t, ref _targets);
238 if (t2 >= 0)
239 {
240 targetVar = t[t2];
241 }
242 t.Clear();
243 }
244 }
245
246 private static void HandlePressing()
247 {
248 if (UseMode == LockOnMode.TargetClosest)
249 {
251 }
252 else if (UseMode == LockOnMode.ThreeDS)
253 {
254 if (!_enabled)
255 {
256 SetActive(on: true);
257 }
258 else
259 {
261 }
262 }
263 else if (!_enabled)
264 {
265 SetActive(on: true);
266 }
267 else
268 {
270 }
271 }
272
273 private static void CycleTargetFocus()
274 {
275 int num = _targets[_pickedTarget];
277 if (_targets.Count < 1 || (_targets.Count == 1 && num == _targets[0]))
278 {
279 SetActive(on: false);
280 return;
281 }
282 _pickedTarget = 0;
283 for (int i = 0; i < _targets.Count; i++)
284 {
285 if (_targets[i] > num)
286 {
287 _pickedTarget = i;
288 break;
289 }
290 }
291 }
292
293 private static void CycleTargetThreeDS()
294 {
295 int num = _targets[_pickedTarget];
298 if (_targets.Count < 1 || (_targets.Count == 1 && num == _targets[0]) || num == _targets[_pickedTarget])
299 {
300 SetActive(on: false);
301 }
302 }
303
304 private static bool CanEnable()
305 {
306 if (Main.player[Main.myPlayer].dead)
307 {
308 return false;
309 }
310 return true;
311 }
312
313 private static void SetActive(bool on)
314 {
315 if (on)
316 {
317 if (CanEnable())
318 {
321 if (_pickedTarget >= 0)
322 {
323 _enabled = true;
324 }
325 }
326 }
327 else
328 {
329 _enabled = false;
330 _targets.Clear();
332 _threeDSTarget = -1;
334 }
335 }
336
337 private static void RefreshTargets(Vector2 position, float radius)
338 {
339 _targets.Clear();
341 _ = Main.player[Main.myPlayer].Center;
342 Main.player[Main.myPlayer].DirectionTo(Main.MouseWorld);
343 for (int i = 0; i < Main.npc.Length; i++)
344 {
345 NPC nPC = Main.npc[i];
346 if (ValidTarget(nPC) && !(nPC.Distance(position) > radius) && rectangle.Intersects(nPC.Hitbox) && !(Lighting.GetSubLight(nPC.Center).Length() / 3f < 0.03f))
347 {
348 _targets.Add(i);
349 }
350 }
351 }
352
353 private static void GetClosestTarget(Vector2 position)
354 {
355 _pickedTarget = -1;
356 float num = -1f;
357 if (UseMode == LockOnMode.ThreeDS)
358 {
361 for (int i = 0; i < _targets.Count; i++)
362 {
363 int num2 = _targets[i];
364 NPC obj = Main.npc[num2];
365 float num3 = Vector2.Dot(obj.DirectionFrom(center), value);
366 if (ValidTarget(obj) && (_pickedTarget == -1 || !(num3 <= num)))
367 {
368 _pickedTarget = i;
369 num = num3;
370 }
371 }
372 return;
373 }
374 for (int j = 0; j < _targets.Count; j++)
375 {
376 int num4 = _targets[j];
377 NPC nPC = Main.npc[num4];
378 if (ValidTarget(nPC) && (_pickedTarget == -1 || !(nPC.Distance(position) >= num)))
379 {
381 num = nPC.Distance(position);
382 }
383 }
384 }
385
386 private static bool ValidTarget(NPC n)
387 {
388 if (n == null || !n.active || n.dontTakeDamage || n.friendly || n.isLikeATownNPC || n.life < 1 || n.immortal)
389 {
390 return false;
391 }
392 if (n.aiStyle == 25 && n.ai[0] == 0f)
393 {
394 return false;
395 }
396 return true;
397 }
398
399 private static void SetLockPosition(Vector2 position)
400 {
402 Main.mouseX = (PlayerInput.MouseX = (int)position.X);
403 Main.mouseY = (PlayerInput.MouseY = (int)position.Y);
404 }
405
406 private static void ResetLockPosition()
407 {
409 Main.mouseX = PlayerInput.MouseX;
410 Main.mouseY = PlayerInput.MouseY;
411 }
412
413 public static void Draw(SpriteBatch spriteBatch)
414 {
415 if (Main.gameMenu)
416 {
417 return;
418 }
420 Rectangle rectangle = new Rectangle(0, 0, value.Width, 12);
421 Rectangle rectangle2 = new Rectangle(0, 16, value.Width, 12);
422 Color t = Main.OurFavoriteColor.MultiplyRGBA(new Color(0.75f, 0.75f, 0.75f, 1f));
423 t.A = 220;
425 t2.A = 220;
426 float num = 0.94f + (float)Math.Sin(Main.GlobalTimeWrappedHourly * ((float)Math.PI * 2f)) * 0.06f;
427 t2 *= num;
428 t *= num;
429 Utils.Swap(ref t, ref t2);
430 Color color = t.MultiplyRGBA(new Color(0.8f, 0.8f, 0.8f, 0.8f));
431 Color color2 = t.MultiplyRGBA(new Color(0.8f, 0.8f, 0.8f, 0.8f));
432 float gravDir = Main.player[Main.myPlayer].gravDir;
433 float num2 = 1f;
434 float num3 = 0.1f;
435 float num4 = 0.8f;
436 float num5 = 1f;
437 float num6 = 10f;
438 float num7 = 10f;
439 bool flag = false;
440 for (int i = 0; i < _drawProgress.GetLength(0); i++)
441 {
442 int num8 = 0;
443 if (_pickedTarget != -1 && _targets.Count > 0 && i == _targets[_pickedTarget])
444 {
445 num8 = 2;
446 }
447 else if ((flag && _targets.Contains(i)) || (UseMode == LockOnMode.ThreeDS && _threeDSTarget == i) || (UseMode == LockOnMode.TargetClosest && _targetClosestTarget == i))
448 {
449 num8 = 1;
450 }
451 _drawProgress[i, 0] = MathHelper.Clamp(_drawProgress[i, 0] + ((num8 == 1) ? num3 : (0f - num3)), 0f, 1f);
452 _drawProgress[i, 1] = MathHelper.Clamp(_drawProgress[i, 1] + ((num8 == 2) ? num3 : (0f - num3)), 0f, 1f);
453 float num9 = _drawProgress[i, 0];
454 if (num9 > 0f)
455 {
456 float num10 = 1f - num9 * num9;
457 Vector2 pos = Main.npc[i].Top + new Vector2(0f, 0f - num7 - num10 * num6) * gravDir - Main.screenPosition;
458 pos = Main.ReverseGravitySupport(pos, Main.npc[i].height);
459 spriteBatch.Draw(value, pos, rectangle, color * num9, 0f, rectangle.Size() / 2f, new Vector2(0.58f, 1f) * num2 * num4 * (1f + num9) / 2f, SpriteEffects.None, 0f);
460 spriteBatch.Draw(value, pos, rectangle2, color2 * num9 * num9, 0f, rectangle2.Size() / 2f, new Vector2(0.58f, 1f) * num2 * num4 * (1f + num9) / 2f, SpriteEffects.None, 0f);
461 }
462 float num11 = _drawProgress[i, 1];
463 if (num11 > 0f)
464 {
465 int num12 = Main.npc[i].width;
466 if (Main.npc[i].height > num12)
467 {
468 num12 = Main.npc[i].height;
469 }
470 num12 += 20;
471 if ((float)num12 < 70f)
472 {
473 num5 *= (float)num12 / 70f;
474 }
475 float num13 = 3f;
476 Vector2 vector = Main.npc[i].Center;
477 if (_targets.Count >= 0 && _pickedTarget >= 0 && _pickedTarget < _targets.Count && i == _targets[_pickedTarget] && NPC.GetNPCLocation(i, seekHead: true, averageDirection: false, out var _, out var pos2))
478 {
479 vector = pos2;
480 }
481 for (int j = 0; (float)j < num13; j++)
482 {
483 float num14 = (float)Math.PI * 2f / num13 * (float)j + Main.GlobalTimeWrappedHourly * ((float)Math.PI * 2f) * 0.25f;
484 Vector2 vector2 = new Vector2(0f, num12 / 2).RotatedBy(num14);
487 float rotation = num14 * (float)((gravDir == 1f) ? 1 : (-1)) + (float)Math.PI * (float)((gravDir == 1f) ? 1 : 0);
488 spriteBatch.Draw(value, pos3, rectangle, t * num11, rotation, rectangle.Size() / 2f, new Vector2(0.58f, 1f) * num2 * num5 * (1f + num11) / 2f, SpriteEffects.None, 0f);
489 spriteBatch.Draw(value, pos3, rectangle2, t2 * num11 * num11, rotation, rectangle2.Size() / 2f, new Vector2(0.58f, 1f) * num2 * num5 * (1f + num11) / 2f, SpriteEffects.None, 0f);
490 }
491 }
492 }
493 }
494}
void Draw(Texture2D texture, Vector2 position, Color color)
static float Clamp(float value, float min, float max)
Definition MathHelper.cs:46
static double Pow(double x, double y)
static double Sin(double a)
const double PI
Definition Math.cs:16
static bool CanHit(Entity source, Entity target)
Definition Collision.cs:344
static bool CanHitLine(Vector2 Position1, int Width1, int Height1, Vector2 Position2, int Width2, int Height2)
Definition Collision.cs:551
Vector2 Center
Definition Entity.cs:43
static Asset< Texture2D > LockOnCursor
static void GetClosestTarget(Vector2 position)
static void RefreshTargets(Vector2 position, float radius)
static void FindMostViableTarget(LockOnMode context, ref int targetVar)
static void SetActive(bool on)
static void Draw(SpriteBatch spriteBatch)
static bool ShouldLockOn(Player p)
static void Toggle(bool forceOff=false)
static void SetLockPosition(Vector2 position)
static TriggersPack Triggers
static bool[] LockOnIgnoresCollision
Definition ItemID.cs:1090
static ? float[] LockOnAimCompensation
Definition ItemID.cs:1094
static int[] LockOnAimAbove
Definition ItemID.cs:1092
static Vector3 GetSubLight(Vector2 position)
Definition Lighting.cs:122
static int myPlayer
Definition Main.cs:1801
static Vector2 ReverseGravitySupport(Vector2 pos, float height=0f)
Definition Main.cs:3005
static Vector2 MouseWorld
Definition Main.cs:2776
static Vector2 screenPosition
Definition Main.cs:1715
static Microsoft.Xna.Framework.Color OurFavoriteColor
Definition Main.cs:902
static NPC[] npc
Definition Main.cs:1685
static bool gameMenu
Definition Main.cs:1926
static Player[] player
Definition Main.cs:1803
static float GlobalTimeWrappedHourly
Definition Main.cs:405
static bool GetNPCLocation(int i, bool seekHead, bool averageDirection, out int index, out Vector2 pos)
Definition NPC.cs:12664
Item[] inventory
Definition Player.cs:1257
static Rectangle CenteredRectangle(Vector2 center, Vector2 size)
Definition Utils.cs:604
static bool SolidTile(Tile testTile)
static bool InWorld(int x, int y, int fluff=0)
Definition WorldGen.cs:5816
static float Dot(Vector2 value1, Vector2 value2)
Definition Vector2.cs:121