Terraria ModLoader  0.11.7.5
A mod to make and play Terraria mods
NPCLoader.cs
Go to the documentation of this file.
1 using Microsoft.Xna.Framework;
2 using Microsoft.Xna.Framework.Graphics;
3 using System;
4 using System.Collections.Generic;
5 using System.IO;
6 using System.Linq;
7 using System.Linq.Expressions;
8 using System.Reflection;
9 using Terraria.GameContent.UI;
10 using Terraria.ID;
11 using Terraria.Localization;
12 
13 namespace Terraria.ModLoader
14 {
15  //todo: further documentation
19  public static class NPCLoader
20  {
21  internal static bool loaded = false;
22  private static int nextNPC = NPCID.Count;
23  internal static readonly IList<ModNPC> npcs = new List<ModNPC>();
24  internal static readonly IList<GlobalNPC> globalNPCs = new List<GlobalNPC>();
25  internal static GlobalNPC[] InstancedGlobals = new GlobalNPC[0];
26  internal static readonly IDictionary<string, int> globalIndexes = new Dictionary<string, int>();
27  internal static readonly IDictionary<Type, int> globalIndexesByType = new Dictionary<Type, int>();
28  internal static readonly IDictionary<int, int> bannerToItem = new Dictionary<int, int>();
29  private static int vanillaSkeletonCount = NPCID.Sets.Skeletons.Count;
30  private static readonly int[] shopToNPC = new int[Main.MaxShopIDs - 1];
34  public static readonly IList<int> blockLoot = new List<int>();
35 
36  private class HookList
37  {
38  public GlobalNPC[] arr = new GlobalNPC[0];
39  public readonly MethodInfo method;
40 
41  public HookList(MethodInfo method) {
42  this.method = method;
43  }
44  }
45 
46  private static List<HookList> hooks = new List<HookList>();
47 
48  private static HookList AddHook<F>(Expression<Func<GlobalNPC, F>> func) {
49  var hook = new HookList(ModLoader.Method(func));
50  hooks.Add(hook);
51  return hook;
52  }
53 
54  static NPCLoader() {
55  shopToNPC[1] = NPCID.Merchant;
56  shopToNPC[2] = NPCID.ArmsDealer;
57  shopToNPC[3] = NPCID.Dryad;
58  shopToNPC[4] = NPCID.Demolitionist;
59  shopToNPC[5] = NPCID.Clothier;
60  shopToNPC[6] = NPCID.GoblinTinkerer;
61  shopToNPC[7] = NPCID.Wizard;
62  shopToNPC[8] = NPCID.Mechanic;
63  shopToNPC[9] = NPCID.SantaClaus;
64  shopToNPC[10] = NPCID.Truffle;
65  shopToNPC[11] = NPCID.Steampunker;
66  shopToNPC[12] = NPCID.DyeTrader;
67  shopToNPC[13] = NPCID.PartyGirl;
68  shopToNPC[14] = NPCID.Cyborg;
69  shopToNPC[15] = NPCID.Painter;
70  shopToNPC[16] = NPCID.WitchDoctor;
71  shopToNPC[17] = NPCID.Pirate;
72  shopToNPC[18] = NPCID.Stylist;
73  shopToNPC[19] = NPCID.TravellingMerchant;
74  shopToNPC[20] = NPCID.SkeletonMerchant;
75  shopToNPC[21] = NPCID.DD2Bartender;
76  }
77 
78  internal static int ReserveNPCID() {
79  if (ModNet.AllowVanillaClients) throw new Exception("Adding npcs breaks vanilla client compatibility");
80 
81  int reserveID = nextNPC;
82  nextNPC++;
83  return reserveID;
84  }
85 
86  public static int NPCCount => nextNPC;
87 
93  public static ModNPC GetNPC(int type) {
94  return type >= NPCID.Count && type < NPCCount ? npcs[type - NPCID.Count] : null;
95  }
96  //change initial size of Terraria.Player.npcTypeNoAggro and NPCBannerBuff to NPCLoader.NPCCount()
97  //in Terraria.Main.MouseText replace 251 with NPCLoader.NPCCount()
98  //in Terraria.Main.DrawNPCs and Terraria.NPC.NPCLoot remove type too high check
99  //replace a lot of 540 immediates
100  //in Terraria.GameContent.UI.EmoteBubble make CountNPCs internal
101  internal static void ResizeArrays(bool unloading) {
102  Array.Resize(ref Main.NPCLoaded, nextNPC);
103  Array.Resize(ref Main.townNPCCanSpawn, nextNPC);
104  Array.Resize(ref Main.slimeRainNPC, nextNPC);
105  Array.Resize(ref Main.npcTexture, nextNPC);
106  Array.Resize(ref Main.npcAltTextures, nextNPC);
107  Array.Resize(ref Main.npcCatchable, nextNPC);
108  Array.Resize(ref Main.npcFrameCount, nextNPC);
109  Array.Resize(ref NPC.killCount, nextNPC);
110  Array.Resize(ref NPC.npcsFoundForCheckActive, nextNPC);
111  Array.Resize(ref Lang._npcNameCache, nextNPC);
112  Array.Resize(ref EmoteBubble.CountNPCs, nextNPC);
113  Array.Resize(ref WorldGen.TownManager._hasRoom, nextNPC);
114  Array.Resize(ref NPCID.Sets.TrailingMode, nextNPC);
115  Array.Resize(ref NPCID.Sets.BelongsToInvasionOldOnesArmy, nextNPC);
116  Array.Resize(ref NPCID.Sets.TeleportationImmune, nextNPC);
117  Array.Resize(ref NPCID.Sets.UsesNewTargetting, nextNPC);
118  Array.Resize(ref NPCID.Sets.FighterUsesDD2PortalAppearEffect, nextNPC);
119  Array.Resize(ref NPCID.Sets.StatueSpawnedDropRarity, nextNPC);
120  Array.Resize(ref NPCID.Sets.NoEarlymodeLootWhenSpawnedFromStatue, nextNPC);
121  Array.Resize(ref NPCID.Sets.NeedsExpertScaling, nextNPC);
122  Array.Resize(ref NPCID.Sets.ProjectileNPC, nextNPC);
123  Array.Resize(ref NPCID.Sets.SavesAndLoads, nextNPC);
124  Array.Resize(ref NPCID.Sets.TrailCacheLength, nextNPC);
125  Array.Resize(ref NPCID.Sets.MPAllowedEnemies, nextNPC);
126  Array.Resize(ref NPCID.Sets.TownCritter, nextNPC);
127  Array.Resize(ref NPCID.Sets.HatOffsetY, nextNPC);
128  Array.Resize(ref NPCID.Sets.FaceEmote, nextNPC);
129  Array.Resize(ref NPCID.Sets.ExtraFramesCount, nextNPC);
130  Array.Resize(ref NPCID.Sets.AttackFrameCount, nextNPC);
131  Array.Resize(ref NPCID.Sets.DangerDetectRange, nextNPC);
132  Array.Resize(ref NPCID.Sets.AttackTime, nextNPC);
133  Array.Resize(ref NPCID.Sets.AttackAverageChance, nextNPC);
134  Array.Resize(ref NPCID.Sets.AttackType, nextNPC);
135  Array.Resize(ref NPCID.Sets.PrettySafe, nextNPC);
136  Array.Resize(ref NPCID.Sets.MagicAuraColor, nextNPC);
137  Array.Resize(ref NPCID.Sets.BossHeadTextures, nextNPC);
138  Array.Resize(ref NPCID.Sets.ExcludedFromDeathTally, nextNPC);
139  Array.Resize(ref NPCID.Sets.TechnicallyABoss, nextNPC);
140  Array.Resize(ref NPCID.Sets.MustAlwaysDraw, nextNPC);
141  Array.Resize(ref NPCID.Sets.ExtraTextureCount, nextNPC);
142  Array.Resize(ref NPCID.Sets.NPCFramingGroup, nextNPC);
143  Array.Resize(ref NPCID.Sets.TownNPCsFramingGroups, nextNPC);
144  for (int k = NPCID.Count; k < nextNPC; k++) {
145  Main.NPCLoaded[k] = true;
146  Main.npcFrameCount[k] = 1;
147  Lang._npcNameCache[k] = LocalizedText.Empty;
148  NPCID.Sets.TrailingMode[k] = -1;
149  NPCID.Sets.StatueSpawnedDropRarity[k] = -1f;
150  NPCID.Sets.TrailCacheLength[k] = 10;
151  NPCID.Sets.DangerDetectRange[k] = -1;
152  NPCID.Sets.AttackTime[k] = -1;
153  NPCID.Sets.AttackAverageChance[k] = 1;
154  NPCID.Sets.AttackType[k] = -1;
155  NPCID.Sets.PrettySafe[k] = -1;
156  NPCID.Sets.MagicAuraColor[k] = Color.White;
157  NPCID.Sets.BossHeadTextures[k] = -1;
158  }
159 
160  InstancedGlobals = globalNPCs.Where(g => g.InstancePerEntity).ToArray();
161  for (int i = 0; i < InstancedGlobals.Length; i++) {
162  InstancedGlobals[i].instanceIndex = i;
163  }
164  foreach (var hook in hooks) {
165  hook.arr = ModLoader.BuildGlobalHook(globalNPCs, hook.method);
166  }
167 
168  if (!unloading) {
169  loaded = true;
170  }
171  }
172 
173  internal static void Unload() {
174  loaded = false;
175  npcs.Clear();
176  nextNPC = NPCID.Count;
177  globalNPCs.Clear();
178  globalIndexes.Clear();
179  globalIndexesByType.Clear();
180  bannerToItem.Clear();
181  while (NPCID.Sets.Skeletons.Count > vanillaSkeletonCount) {
182  NPCID.Sets.Skeletons.RemoveAt(NPCID.Sets.Skeletons.Count - 1);
183  }
184  }
185 
186  internal static bool IsModNPC(NPC npc) {
187  return npc.type >= NPCID.Count;
188  }
189 
190  private static HookList HookSetDefaults = AddHook<Action<NPC>>(g => g.SetDefaults);
191 
192  internal static void SetDefaults(NPC npc, bool createModNPC = true) {
193  if (IsModNPC(npc)) {
194  if (createModNPC) {
195  npc.modNPC = GetNPC(npc.type).NewInstance(npc);
196  }
197  else //the default NPCs created and bound to ModNPCs are initialized before ResizeArrays. They come here during SetupContent.
198  {
199  Array.Resize(ref npc.buffImmune, BuffLoader.BuffCount);
200  }
201  }
202  npc.globalNPCs = InstancedGlobals.Select(g => g.NewInstance(npc)).ToArray();
203  npc.modNPC?.SetDefaults();
204  foreach (GlobalNPC g in HookSetDefaults.arr) {
205  g.Instance(npc).SetDefaults(npc);
206  }
207  }
208 
209  internal static GlobalNPC GetGlobalNPC(NPC npc, Mod mod, string name) {
210  int index;
211  return globalIndexes.TryGetValue(mod.Name + ':' + name, out index) ? globalNPCs[index].Instance(npc) : null;
212  }
213 
214  internal static GlobalNPC GetGlobalNPC(NPC npc, Type type) {
215  int index;
216  return globalIndexesByType.TryGetValue(type, out index) ? (index > -1 ? globalNPCs[index].Instance(npc) : null) : null;
217  }
218 
219  private static HookList HookScaleExpertStats = AddHook<Action<NPC, int, float>>(g => g.ScaleExpertStats);
220 
221  public static void ScaleExpertStats(NPC npc, int numPlayers, float bossLifeScale) {
222  npc.modNPC?.ScaleExpertStats(numPlayers, bossLifeScale);
223 
224  foreach (GlobalNPC g in HookScaleExpertStats.arr) {
225  g.Instance(npc).ScaleExpertStats(npc, numPlayers, bossLifeScale);
226  }
227  }
228 
229  private static HookList HookResetEffects = AddHook<Action<NPC>>(g => g.ResetEffects);
230 
231  public static void ResetEffects(NPC npc) {
232  npc.modNPC?.ResetEffects();
233 
234  foreach (GlobalNPC g in HookResetEffects.arr) {
235  g.Instance(npc).ResetEffects(npc);
236  }
237  }
238 
239  public static void NPCAI(NPC npc) {
240  if (PreAI(npc)) {
241  int type = npc.type;
242  bool useAiType = npc.modNPC != null && npc.modNPC.aiType > 0;
243  if (useAiType) {
244  npc.type = npc.modNPC.aiType;
245  }
246  npc.VanillaAI();
247  if (useAiType) {
248  npc.type = type;
249  }
250  AI(npc);
251  }
252  PostAI(npc);
253  }
254 
255  private static HookList HookPreAI = AddHook<Func<NPC, bool>>(g => g.PreAI);
256 
257  public static bool PreAI(NPC npc) {
258  bool result = true;
259  foreach (GlobalNPC g in HookPreAI.arr) {
260  result &= g.Instance(npc).PreAI(npc);
261  }
262  if (result && npc.modNPC != null) {
263  return npc.modNPC.PreAI();
264  }
265  return result;
266  }
267 
268  private static HookList HookAI = AddHook<Action<NPC>>(g => g.AI);
269 
270  public static void AI(NPC npc) {
271  npc.modNPC?.AI();
272 
273  foreach (GlobalNPC g in HookAI.arr) {
274  g.Instance(npc).AI(npc);
275  }
276  }
277 
278  private static HookList HookPostAI = AddHook<Action<NPC>>(g => g.PostAI);
279 
280  public static void PostAI(NPC npc) {
281  npc.modNPC?.PostAI();
282 
283  foreach (GlobalNPC g in HookPostAI.arr) {
284  g.Instance(npc).PostAI(npc);
285  }
286  }
287 
288  public static void SendExtraAI(NPC npc, BinaryWriter writer) {
289  if (npc.modNPC != null) {
290  byte[] data;
291  using (MemoryStream stream = new MemoryStream()) {
292  using (BinaryWriter modWriter = new BinaryWriter(stream)) {
293  npc.modNPC.SendExtraAI(modWriter);
294  modWriter.Flush();
295  data = stream.ToArray();
296  }
297  }
298  writer.Write((byte)data.Length);
299  if (data.Length > 0) {
300  writer.Write(data);
301  }
302  }
303  }
304 
305  public static void ReceiveExtraAI(NPC npc, BinaryReader reader) {
306  if (npc.modNPC != null) {
307  byte[] extraAI = reader.ReadBytes(reader.ReadByte());
308  if (extraAI.Length > 0) {
309  using (MemoryStream stream = new MemoryStream(extraAI)) {
310  using (BinaryReader modReader = new BinaryReader(stream)) {
311  npc.modNPC.ReceiveExtraAI(modReader);
312  }
313  }
314  }
315  }
316  }
317 
318  private static HookList HookFindFrame = AddHook<Action<NPC, int>>(g => g.FindFrame);
319 
320  public static void FindFrame(NPC npc, int frameHeight) {
321  int type = npc.type;
322  if (npc.modNPC != null && npc.modNPC.animationType > 0) {
323  npc.type = npc.modNPC.animationType;
324  }
325  npc.VanillaFindFrame(frameHeight);
326  npc.type = type;
327  npc.modNPC?.FindFrame(frameHeight);
328 
329  foreach (GlobalNPC g in HookFindFrame.arr) {
330  g.Instance(npc).FindFrame(npc, frameHeight);
331  }
332  }
333 
334  private static HookList HookHitEffect = AddHook<Action<NPC, int, double>>(g => g.HitEffect);
335 
336  public static void HitEffect(NPC npc, int hitDirection, double damage) {
337  npc.VanillaHitEffect(hitDirection, damage);
338  npc.modNPC?.HitEffect(hitDirection, damage);
339 
340  foreach (GlobalNPC g in HookHitEffect.arr) {
341  g.Instance(npc).HitEffect(npc, hitDirection, damage);
342  }
343  }
344 
345  private delegate void DelegateUpdateLifeRegen(NPC npc, ref int damage);
346  private static HookList HookUpdateLifeRegen = AddHook<DelegateUpdateLifeRegen>(g => g.UpdateLifeRegen);
347 
348  public static void UpdateLifeRegen(NPC npc, ref int damage) {
349  npc.modNPC?.UpdateLifeRegen(ref damage);
350 
351  foreach (GlobalNPC g in HookUpdateLifeRegen.arr) {
352  g.Instance(npc).UpdateLifeRegen(npc, ref damage);
353  }
354  }
355 
356  private static HookList HookCheckActive = AddHook<Func<NPC, bool>>(g => g.CheckActive);
357 
358  public static bool CheckActive(NPC npc) {
359  if (npc.modNPC != null && !npc.modNPC.CheckActive()) {
360  return false;
361  }
362  foreach (GlobalNPC g in HookCheckActive.arr) {
363  if (!g.Instance(npc).CheckActive(npc)) {
364  return false;
365  }
366  }
367  return true;
368  }
369 
370  private static HookList HookCheckDead = AddHook<Func<NPC, bool>>(g => g.CheckDead);
371 
372  public static bool CheckDead(NPC npc) {
373  bool result = true;
374 
375  if (npc.modNPC != null) {
376  result = npc.modNPC.CheckDead();
377  }
378 
379  foreach (GlobalNPC g in HookCheckDead.arr) {
380  result &= g.Instance(npc).CheckDead(npc);
381  }
382 
383  return result;
384  }
385 
386  private static HookList HookSpecialNPCLoot = AddHook<Func<NPC, bool>>(g => g.SpecialNPCLoot);
387 
388  public static bool SpecialNPCLoot(NPC npc) {
389  foreach (GlobalNPC g in HookSpecialNPCLoot.arr) {
390  if (g.Instance(npc).SpecialNPCLoot(npc)) {
391  return true;
392  }
393  }
394  if (npc.modNPC != null) {
395  return npc.modNPC.SpecialNPCLoot();
396  }
397  return false;
398  }
399 
400  private static HookList HookPreNPCLoot = AddHook<Func<NPC, bool>>(g => g.PreNPCLoot);
401 
402  public static bool PreNPCLoot(NPC npc) {
403  bool result = true;
404  foreach (GlobalNPC g in HookPreNPCLoot.arr) {
405  result &= g.Instance(npc).PreNPCLoot(npc);
406  }
407 
408  if (result && npc.modNPC != null) {
409  result = npc.modNPC.PreNPCLoot();
410  }
411 
412  if (!result) {
413  blockLoot.Clear();
414  return false;
415  }
416 
417  return true;
418  }
419 
420  private static HookList HookNPCLoot = AddHook<Action<NPC>>(g => g.NPCLoot);
421 
422  public static void NPCLoot(NPC npc) {
423  npc.modNPC?.NPCLoot();
424 
425  foreach (GlobalNPC g in HookNPCLoot.arr) {
426  g.Instance(npc).NPCLoot(npc);
427  }
428  blockLoot.Clear();
429  }
430 
431  public static void BossLoot(NPC npc, ref string name, ref int potionType) {
432  npc.modNPC?.BossLoot(ref name, ref potionType);
433  }
434 
435  public static void BossBag(NPC npc, ref int bagType) {
436  if (npc.modNPC != null) {
437  bagType = npc.modNPC.bossBag;
438  }
439  }
440 
441  private static HookList HookOnCatchNPC = AddHook<Action<NPC, Player, Item>>(g => g.OnCatchNPC);
442 
443  public static void OnCatchNPC(NPC npc, Player player, Item item) {
444  npc.modNPC?.OnCatchNPC(player, item);
445 
446  foreach (GlobalNPC g in HookOnCatchNPC.arr) {
447  g.Instance(npc).OnCatchNPC(npc, player, item);
448  }
449  }
450 
451  private delegate bool DelegateCanHitPlayer(NPC npc, Player target, ref int cooldownSlot);
452  private static HookList HookCanHitPlayer = AddHook<DelegateCanHitPlayer>(g => g.CanHitPlayer);
453 
454  public static bool CanHitPlayer(NPC npc, Player target, ref int cooldownSlot) {
455  foreach (GlobalNPC g in HookCanHitPlayer.arr) {
456  if (!g.Instance(npc).CanHitPlayer(npc, target, ref cooldownSlot)) {
457  return false;
458  }
459  }
460  if (npc.modNPC != null) {
461  return npc.modNPC.CanHitPlayer(target, ref cooldownSlot);
462  }
463  return true;
464  }
465 
466  private delegate void DelegateModifyHitPlayer(NPC npc, Player target, ref int damage, ref bool crit);
467  private static HookList HookModifyHitPlayer = AddHook<DelegateModifyHitPlayer>(g => g.ModifyHitPlayer);
468 
469  public static void ModifyHitPlayer(NPC npc, Player target, ref int damage, ref bool crit) {
470  npc.modNPC?.ModifyHitPlayer(target, ref damage, ref crit);
471 
472  foreach (GlobalNPC g in HookModifyHitPlayer.arr) {
473  g.Instance(npc).ModifyHitPlayer(npc, target, ref damage, ref crit);
474  }
475  }
476 
477  private static HookList HookOnHitPlayer = AddHook<Action<NPC, Player, int, bool>>(g => g.OnHitPlayer);
478 
479  public static void OnHitPlayer(NPC npc, Player target, int damage, bool crit) {
480  npc.modNPC?.OnHitPlayer(target, damage, crit);
481 
482  foreach (GlobalNPC g in HookOnHitPlayer.arr) {
483  g.Instance(npc).OnHitPlayer(npc, target, damage, crit);
484  }
485  }
486 
487  private static HookList HookCanHitNPC = AddHook<Func<NPC, NPC, bool?>>(g => g.CanHitNPC);
488 
489  public static bool? CanHitNPC(NPC npc, NPC target) {
490  bool? flag = null;
491  foreach (GlobalNPC g in HookCanHitNPC.arr) {
492  bool? canHit = g.Instance(npc).CanHitNPC(npc, target);
493  if (canHit.HasValue && !canHit.Value) {
494  return false;
495  }
496  if (canHit.HasValue) {
497  flag = canHit.Value;
498  }
499  }
500  if (npc.modNPC != null) {
501  bool? canHit = npc.modNPC.CanHitNPC(target);
502  if (canHit.HasValue && !canHit.Value) {
503  return false;
504  }
505  if (canHit.HasValue) {
506  flag = canHit.Value;
507  }
508  }
509  return flag;
510  }
511 
512  private delegate void DelegateModifyHitNPC(NPC npc, NPC target, ref int damage, ref float knockback, ref bool crit);
513  private static HookList HookModifyHitNPC = AddHook<DelegateModifyHitNPC>(g => g.ModifyHitNPC);
514 
515  public static void ModifyHitNPC(NPC npc, NPC target, ref int damage, ref float knockback, ref bool crit) {
516  npc.modNPC?.ModifyHitNPC(target, ref damage, ref knockback, ref crit);
517 
518  foreach (GlobalNPC g in HookModifyHitNPC.arr) {
519  g.Instance(npc).ModifyHitNPC(npc, target, ref damage, ref knockback, ref crit);
520  }
521  }
522 
523  private static HookList HookOnHitNPC = AddHook<Action<NPC, NPC, int, float, bool>>(g => g.OnHitNPC);
524 
525  public static void OnHitNPC(NPC npc, NPC target, int damage, float knockback, bool crit) {
526  npc.modNPC?.OnHitNPC(target, damage, knockback, crit);
527  foreach (GlobalNPC g in HookOnHitNPC.arr) {
528  g.Instance(npc).OnHitNPC(npc, target, damage, knockback, crit);
529  }
530  }
531 
532  private static HookList HookCanBeHitByItem = AddHook<Func<NPC, Player, Item, bool?>>(g => g.CanBeHitByItem);
533 
534  public static bool? CanBeHitByItem(NPC npc, Player player, Item item) {
535  bool? flag = null;
536  foreach (GlobalNPC g in HookCanBeHitByItem.arr) {
537  bool? canHit = g.Instance(npc).CanBeHitByItem(npc, player, item);
538  if (canHit.HasValue && !canHit.Value) {
539  return false;
540  }
541  if (canHit.HasValue) {
542  flag = canHit.Value;
543  }
544  }
545  if (npc.modNPC != null) {
546  bool? canHit = npc.modNPC.CanBeHitByItem(player, item);
547  if (canHit.HasValue && !canHit.Value) {
548  return false;
549  }
550  if (canHit.HasValue) {
551  flag = canHit.Value;
552  }
553  }
554  return flag;
555  }
556 
557  private delegate void DelegateModifyHitByItem(NPC npc, Player player, Item item, ref int damage, ref float knockback, ref bool crit);
558  private static HookList HookModifyHitByItem = AddHook<DelegateModifyHitByItem>(g => g.ModifyHitByItem);
559 
560  public static void ModifyHitByItem(NPC npc, Player player, Item item, ref int damage, ref float knockback, ref bool crit) {
561  npc.modNPC?.ModifyHitByItem(player, item, ref damage, ref knockback, ref crit);
562 
563  foreach (GlobalNPC g in HookModifyHitByItem.arr) {
564  g.Instance(npc).ModifyHitByItem(npc, player, item, ref damage, ref knockback, ref crit);
565  }
566  }
567 
568  private static HookList HookOnHitByItem = AddHook<Action<NPC, Player, Item, int, float, bool>>(g => g.OnHitByItem);
569 
570  public static void OnHitByItem(NPC npc, Player player, Item item, int damage, float knockback, bool crit) {
571  npc.modNPC?.OnHitByItem(player, item, damage, knockback, crit);
572 
573  foreach (GlobalNPC g in HookOnHitByItem.arr) {
574  g.Instance(npc).OnHitByItem(npc, player, item, damage, knockback, crit);
575  }
576  }
577 
578  private static HookList HookCanBeHitByProjectile = AddHook<Func<NPC, Projectile, bool?>>(g => g.CanBeHitByProjectile);
579 
580  public static bool? CanBeHitByProjectile(NPC npc, Projectile projectile) {
581  bool? flag = null;
582  foreach (GlobalNPC g in HookCanBeHitByProjectile.arr) {
583  bool? canHit = g.Instance(npc).CanBeHitByProjectile(npc, projectile);
584  if (canHit.HasValue && !canHit.Value) {
585  return false;
586  }
587  if (canHit.HasValue) {
588  flag = canHit.Value;
589  }
590  }
591  if (npc.modNPC != null) {
592  bool? canHit = npc.modNPC.CanBeHitByProjectile(projectile);
593  if (canHit.HasValue && !canHit.Value) {
594  return false;
595  }
596  if (canHit.HasValue) {
597  flag = canHit.Value;
598  }
599  }
600  return flag;
601  }
602 
603  private delegate void DelegateModifyHitByProjectile(NPC npc, Projectile projectile, ref int damage, ref float knockback, ref bool crit, ref int hitDirection);
604  private static HookList HookModifyHitByProjectile = AddHook<DelegateModifyHitByProjectile>(g => g.ModifyHitByProjectile);
605 
606  public static void ModifyHitByProjectile(NPC npc, Projectile projectile, ref int damage, ref float knockback, ref bool crit, ref int hitDirection) {
607  npc.modNPC?.ModifyHitByProjectile(projectile, ref damage, ref knockback, ref crit, ref hitDirection);
608 
609  foreach (GlobalNPC g in HookModifyHitByProjectile.arr) {
610  g.Instance(npc).ModifyHitByProjectile(npc, projectile, ref damage, ref knockback, ref crit, ref hitDirection);
611  }
612  }
613 
614  private static HookList HookOnHitByProjectile = AddHook<Action<NPC, Projectile, int, float, bool>>(g => g.OnHitByProjectile);
615 
616  public static void OnHitByProjectile(NPC npc, Projectile projectile, int damage, float knockback, bool crit) {
617  npc.modNPC?.OnHitByProjectile(projectile, damage, knockback, crit);
618 
619  foreach (GlobalNPC g in HookOnHitByProjectile.arr) {
620  g.Instance(npc).OnHitByProjectile(npc, projectile, damage, knockback, crit);
621  }
622  }
623 
624  private delegate bool DelegateStrikeNPC(NPC npc, ref double damage, int defense, ref float knockback, int hitDirection, ref bool crit);
625  private static HookList HookStrikeNPC = AddHook<DelegateStrikeNPC>(g => g.StrikeNPC);
626 
627  public static bool StrikeNPC(NPC npc, ref double damage, int defense, ref float knockback, int hitDirection, ref bool crit) {
628  bool flag = true;
629  if (npc.modNPC != null) {
630  flag = npc.modNPC.StrikeNPC(ref damage, defense, ref knockback, hitDirection, ref crit);
631  }
632  foreach (GlobalNPC g in HookStrikeNPC.arr) {
633  if (!g.Instance(npc).StrikeNPC(npc, ref damage, defense, ref knockback, hitDirection, ref crit)) {
634  flag = false;
635  }
636  }
637  return flag;
638  }
639 
640  private delegate void DelegateBossHeadSlot(NPC npc, ref int index);
641  private static HookList HookBossHeadSlot = AddHook<DelegateBossHeadSlot>(g => g.BossHeadSlot);
642 
643  public static void BossHeadSlot(NPC npc, ref int index) {
644  npc.modNPC?.BossHeadSlot(ref index);
645 
646  foreach (GlobalNPC g in HookBossHeadSlot.arr) {
647  g.Instance(npc).BossHeadSlot(npc, ref index);
648  }
649  }
650 
651  private delegate void DelegateBossHeadRotation(NPC npc, ref float rotation);
652  private static HookList HookBossHeadRotation = AddHook<DelegateBossHeadRotation>(g => g.BossHeadRotation);
653 
654  public static void BossHeadRotation(NPC npc, ref float rotation) {
655  npc.modNPC?.BossHeadRotation(ref rotation);
656 
657  foreach (GlobalNPC g in HookBossHeadRotation.arr) {
658  g.Instance(npc).BossHeadRotation(npc, ref rotation);
659  }
660  }
661 
662  private delegate void DelegateBossHeadSpriteEffects(NPC npc, ref SpriteEffects spriteEffects);
663  private static HookList HookBossHeadSpriteEffects = AddHook<DelegateBossHeadSpriteEffects>(g => g.BossHeadSpriteEffects);
664 
665  public static void BossHeadSpriteEffects(NPC npc, ref SpriteEffects spriteEffects) {
666  npc.modNPC?.BossHeadSpriteEffects(ref spriteEffects);
667 
668  foreach (GlobalNPC g in HookBossHeadSpriteEffects.arr) {
669  g.Instance(npc).BossHeadSpriteEffects(npc, ref spriteEffects);
670  }
671  }
672 
673  private static HookList HookGetAlpha = AddHook<Func<NPC, Color, Color?>>(g => g.GetAlpha);
674 
675  public static Color? GetAlpha(NPC npc, Color lightColor) {
676  foreach (GlobalNPC g in HookGetAlpha.arr) {
677  Color? color = g.Instance(npc).GetAlpha(npc, lightColor);
678  if (color.HasValue) {
679  return color.Value;
680  }
681  }
682  return npc.modNPC?.GetAlpha(lightColor);
683  }
684 
685  private delegate void DelegateDrawEffects(NPC npc, ref Color drawColor);
686  private static HookList HookDrawEffects = AddHook<DelegateDrawEffects>(g => g.DrawEffects);
687 
688  public static void DrawEffects(NPC npc, ref Color drawColor) {
689  npc.modNPC?.DrawEffects(ref drawColor);
690 
691  foreach (GlobalNPC g in HookDrawEffects.arr) {
692  g.Instance(npc).DrawEffects(npc, ref drawColor);
693  }
694  }
695 
696  private static HookList HookPreDraw = AddHook<Func<NPC, SpriteBatch, Color, bool>>(g => g.PreDraw);
697 
698  public static bool PreDraw(NPC npc, SpriteBatch spriteBatch, Color drawColor) {
699  bool result = true;
700  foreach (GlobalNPC g in HookPreDraw.arr) {
701  result &= g.Instance(npc).PreDraw(npc, spriteBatch, drawColor);
702  }
703  if (result && npc.modNPC != null) {
704  return npc.modNPC.PreDraw(spriteBatch, drawColor);
705  }
706  return result;
707  }
708 
709  private static HookList HookPostDraw = AddHook<Action<NPC, SpriteBatch, Color>>(g => g.PostDraw);
710 
711  public static void PostDraw(NPC npc, SpriteBatch spriteBatch, Color drawColor) {
712  npc.modNPC?.PostDraw(spriteBatch, drawColor);
713 
714  foreach (GlobalNPC g in HookPostDraw.arr) {
715  g.Instance(npc).PostDraw(npc, spriteBatch, drawColor);
716  }
717  }
718 
719  private static HookList HookDrawBehind = AddHook<Action<NPC, int>>(g => g.DrawBehind);
720 
721  internal static void DrawBehind(NPC npc, int index)
722  {
723  npc.modNPC?.DrawBehind(index);
724 
725  foreach (GlobalNPC g in HookDrawBehind.arr) {
726  g.Instance(npc).DrawBehind(npc, index);
727  }
728  }
729 
730  private delegate bool? DelegateDrawHealthBar(NPC npc, byte bhPosition, ref float scale, ref Vector2 position);
731  private static HookList HookDrawHealthBar = AddHook<DelegateDrawHealthBar>(g => g.DrawHealthBar);
732 
733  public static bool DrawHealthBar(NPC npc, ref float scale) {
734  Vector2 position = new Vector2(npc.position.X + npc.width / 2, npc.position.Y + npc.gfxOffY);
735  if (Main.HealthBarDrawSettings == 1) {
736  position.Y += npc.height + 10f + Main.NPCAddHeight(npc.whoAmI);
737  }
738  else if (Main.HealthBarDrawSettings == 2) {
739  position.Y -= 24f + Main.NPCAddHeight(npc.whoAmI) / 2f;
740  }
741  foreach (GlobalNPC g in HookDrawHealthBar.arr) {
742  bool? result = g.Instance(npc).DrawHealthBar(npc, Main.HealthBarDrawSettings, ref scale, ref position);
743  if (result.HasValue) {
744  if (result.Value) {
745  DrawHealthBar(npc, position, scale);
746  }
747  return false;
748  }
749  }
750  if (NPCLoader.IsModNPC(npc)) {
751  bool? result = npc.modNPC.DrawHealthBar(Main.HealthBarDrawSettings, ref scale, ref position);
752  if (result.HasValue) {
753  if (result.Value) {
754  DrawHealthBar(npc, position, scale);
755  }
756  return false;
757  }
758  }
759  return true;
760  }
761 
762  private static void DrawHealthBar(NPC npc, Vector2 position, float scale) {
763  float alpha = Lighting.Brightness((int)(npc.Center.X / 16f), (int)(npc.Center.Y / 16f));
764  Main.instance.DrawHealthBar(position.X, position.Y, npc.life, npc.lifeMax, alpha, scale);
765  }
766 
767  private delegate void DelegateEditSpawnRate(Player player, ref int spawnRate, ref int maxSpawns);
768  private static HookList HookEditSpawnRate = AddHook<DelegateEditSpawnRate>(g => g.EditSpawnRate);
769 
770  public static void EditSpawnRate(Player player, ref int spawnRate, ref int maxSpawns) {
771  foreach (GlobalNPC g in HookEditSpawnRate.arr) {
772  g.EditSpawnRate(player, ref spawnRate, ref maxSpawns);
773  }
774  }
775 
776  private delegate void DelegateEditSpawnRange(Player player, ref int spawnRangeX, ref int spawnRangeY,
777  ref int safeRangeX, ref int safeRangeY);
778  private static HookList HookEditSpawnRange = AddHook<DelegateEditSpawnRange>(g => g.EditSpawnRange);
779 
780  public static void EditSpawnRange(Player player, ref int spawnRangeX, ref int spawnRangeY,
781  ref int safeRangeX, ref int safeRangeY) {
782  foreach (GlobalNPC g in HookEditSpawnRange.arr) {
783  g.EditSpawnRange(player, ref spawnRangeX, ref spawnRangeY, ref safeRangeX, ref safeRangeY);
784  }
785  }
786 
787  private static HookList HookEditSpawnPool = AddHook<Action<Dictionary<int, float>, NPCSpawnInfo>>(g => g.EditSpawnPool);
788 
789  public static int? ChooseSpawn(NPCSpawnInfo spawnInfo) {
790  NPCSpawnHelper.Reset();
791  NPCSpawnHelper.DoChecks(spawnInfo);
792  IDictionary<int, float> pool = new Dictionary<int, float>();
793  pool[0] = 1f;
794  foreach (ModNPC npc in npcs) {
795  float weight = npc.SpawnChance(spawnInfo);
796  if (weight > 0f) {
797  pool[npc.npc.type] = weight;
798  }
799  }
800  foreach (GlobalNPC g in HookEditSpawnPool.arr) {
801  g.EditSpawnPool(pool, spawnInfo);
802  }
803  float totalWeight = 0f;
804  foreach (int type in pool.Keys) {
805  if (pool[type] < 0f) {
806  pool[type] = 0f;
807  }
808  totalWeight += pool[type];
809  }
810  float choice = (float)Main.rand.NextDouble() * totalWeight;
811  foreach (int type in pool.Keys) {
812  float weight = pool[type];
813  if (choice < weight) {
814  return type;
815  }
816  choice -= weight;
817  }
818  return null;
819  }
820 
821  private static HookList HookSpawnNPC = AddHook<Action<int, int, int>>(g => g.SpawnNPC);
822 
823  public static int SpawnNPC(int type, int tileX, int tileY) {
824  var npc = type >= NPCID.Count ?
825  GetNPC(type).SpawnNPC(tileX, tileY) :
826  NPC.NewNPC(tileX * 16 + 8, tileY * 16, type);
827 
828  foreach (GlobalNPC g in HookSpawnNPC.arr) {
829  g.Instance(Main.npc[npc]).SpawnNPC(npc, tileX, tileY);
830  }
831 
832  return npc;
833  }
834 
835  public static void CanTownNPCSpawn(int numTownNPCs, int money) {
836  foreach (ModNPC npc in npcs) {
837  if (npc.npc.townNPC && NPC.TypeToHeadIndex(npc.npc.type) >= 0 && !NPC.AnyNPCs(npc.npc.type) &&
838  npc.CanTownNPCSpawn(numTownNPCs, money)) {
839  Main.townNPCCanSpawn[npc.npc.type] = true;
840  if (WorldGen.prioritizedTownNPC == 0) {
841  WorldGen.prioritizedTownNPC = npc.npc.type;
842  }
843  }
844  }
845  }
846 
847  public static bool CheckConditions(int type) {
848  return GetNPC(type)?.CheckConditions(WorldGen.roomX1, WorldGen.roomX2, WorldGen.roomY1, WorldGen.roomY2) ?? true;
849  }
850 
851  public static string TownNPCName(int type) {
852  return GetNPC(type)?.TownNPCName() ?? "";
853  }
854 
855  public static bool UsesPartyHat(NPC npc) {
856  return npc.modNPC?.UsesPartyHat() ?? true;
857  }
858 
859  private static HookList HookCanChat = AddHook<Func<NPC, bool?>>(g => g.CanChat);
860 
861  public static bool CanChat(NPC npc, bool vanillaCanChat) {
862  bool defaultCanChat = npc.modNPC?.CanChat() ?? vanillaCanChat;
863 
864  foreach (GlobalNPC g in HookCanChat.arr) {
865  bool? canChat = g.Instance(npc).CanChat(npc);
866  if (canChat.HasValue) {
867  if (!canChat.Value) {
868  return false;
869  }
870  defaultCanChat = true;
871  }
872  }
873 
874  return defaultCanChat;
875  }
876 
877  private delegate void DelegateGetChat(NPC npc, ref string chat);
878  private static HookList HookGetChat = AddHook<DelegateGetChat>(g => g.GetChat);
879 
880  public static void GetChat(NPC npc, ref string chat) {
881  if (npc.modNPC != null) {
882  chat = npc.modNPC.GetChat();
883  }
884  else if (chat.Equals("")) {
885  chat = Language.GetTextValue("tModLoader.DefaultTownNPCChat");
886  }
887  foreach (GlobalNPC g in HookGetChat.arr) {
888  g.Instance(npc).GetChat(npc, ref chat);
889  }
890  }
891 
892  public static void SetChatButtons(ref string button, ref string button2) {
893  if (Main.player[Main.myPlayer].talkNPC >= 0) {
894  NPC npc = Main.npc[Main.player[Main.myPlayer].talkNPC];
895  npc.modNPC?.SetChatButtons(ref button, ref button2);
896  }
897  }
898 
899  private static HookList HookPreChatButtonClicked = AddHook<Func<NPC, bool, bool>>(g => g.PreChatButtonClicked);
900 
901  public static bool PreChatButtonClicked(bool firstButton) {
902  NPC npc = Main.npc[Main.LocalPlayer.talkNPC];
903 
904  bool result = true;
905  foreach (GlobalNPC g in HookPreChatButtonClicked.arr) {
906  result &= g.Instance(npc).PreChatButtonClicked(npc, firstButton);
907  }
908 
909  if (!result) {
910  Main.PlaySound(SoundID.MenuTick);
911  return false;
912  }
913 
914  return true;
915  }
916 
917  private delegate void DelegateOnChatButtonClicked(NPC npc, bool firstButton);
918  private static HookList HookOnChatButtonClicked = AddHook<DelegateOnChatButtonClicked>(g => g.OnChatButtonClicked);
919 
920  public static void OnChatButtonClicked(bool firstButton) {
921  NPC npc = Main.npc[Main.LocalPlayer.talkNPC];
922  bool shop = false;
923 
924  if (npc.modNPC != null) {
925  npc.modNPC.OnChatButtonClicked(firstButton, ref shop);
926  Main.PlaySound(SoundID.MenuTick);
927  if (shop) {
928  Main.playerInventory = true;
929  Main.npcChatText = "";
930  Main.npcShop = Main.MaxShopIDs - 1;
931  Main.instance.shop[Main.npcShop].SetupShop(npc.type);
932  }
933  }
934  foreach (GlobalNPC g in HookOnChatButtonClicked.arr) {
935  g.Instance(npc).OnChatButtonClicked(npc, firstButton);
936  }
937  }
938 
939  private delegate void DelegateSetupShop(int type, Chest shop, ref int nextSlot);
940  private static HookList HookSetupShop = AddHook<DelegateSetupShop>(g => g.SetupShop);
941 
942  public static void SetupShop(int type, Chest shop, ref int nextSlot) {
943  if (type < shopToNPC.Length) {
944  type = shopToNPC[type];
945  }
946  else {
947  GetNPC(type)?.SetupShop(shop, ref nextSlot);
948  }
949  foreach (GlobalNPC g in HookSetupShop.arr) {
950  g.SetupShop(type, shop, ref nextSlot);
951  }
952  }
953 
954  private delegate void DelegateSetupTravelShop(int[] shop, ref int nextSlot);
955  private static HookList HookSetupTravelShop = AddHook<DelegateSetupTravelShop>(g => g.SetupTravelShop);
956 
957  public static void SetupTravelShop(int[] shop, ref int nextSlot) {
958  foreach (GlobalNPC g in HookSetupTravelShop.arr) {
959  g.SetupTravelShop(shop, ref nextSlot);
960  }
961  }
962 
963  private static HookList HookCanGoToStatue = AddHook<Func<NPC, bool, bool?>>(g => g.CanGoToStatue);
964 
965  public static bool CanGoToStatue(NPC npc, bool toKingStatue, bool vanillaCanGo) {
966  bool defaultCanGo = npc.modNPC?.CanGoToStatue(toKingStatue) ?? vanillaCanGo;
967 
968  foreach (GlobalNPC g in HookCanGoToStatue.arr) {
969  bool? canGo = g.Instance(npc).CanGoToStatue(npc, toKingStatue);
970  if (canGo.HasValue) {
971  if (!canGo.Value) {
972  return false;
973  }
974  defaultCanGo = true;
975  }
976  }
977 
978  return defaultCanGo;
979  }
980 
981  private static HookList HookOnGoToStatue = AddHook<Action<NPC, bool>>(g => g.OnGoToStatue);
982 
983  public static void OnGoToStatue(NPC npc, bool toKingStatue) {
984  npc.modNPC?.OnGoToStatue(toKingStatue);
985 
986  foreach (GlobalNPC g in HookOnGoToStatue.arr) {
987  g.OnGoToStatue(npc, toKingStatue);
988  }
989  }
990 
991  private delegate void DelegateBuffTownNPC(ref float damageMult, ref int defense);
992  private static HookList HookBuffTownNPC = AddHook<DelegateBuffTownNPC>(g => g.BuffTownNPC);
993 
994  public static void BuffTownNPC(ref float damageMult, ref int defense) {
995  foreach (GlobalNPC g in HookBuffTownNPC.arr) {
996  g.BuffTownNPC(ref damageMult, ref defense);
997  }
998  }
999  //attack type 0 = throwing
1000  // num405 = type, num406 = damage, knockBack, scaleFactor7 = speed multiplier, num407 = attack delay
1001  // num408 = unknown, maxValue3 = unknown, num409 = gravity correction factor, num411 = random speed offset
1002  //attack type 1 = shooting
1003  // num413 = type, num414 = damage, scaleFactor8 = speed multiplier, num415 = attack delay,
1004  // num416 = unknown, maxValue4 = unknown, knockBack2, num417 = gravity correction,
1005  // flag53 = in between shots, num418 = random speed offset
1006  //attack type 2 = magic
1007  // num423 = type, num424 = damage, scaleFactor9 = speed multiplier, num425 = attack delay,
1008  // num426 = unknown, maxValue5 = unknown, knockBack3, num427 = gravity correction factor,
1009  // num429 = aura light multiplier, num430 = random speed offset
1010  //attack type 3 = swinging
1011  // num439 = unknown, maxValue6 = unknown, num440 = damage, num441 = knockback,
1012  // num442 = item width, num443 = item height
1013  //unknowns are associated with ai[1], localAI[1], and localAI[3] when ai[0] is either 0 or 8
1014  //check patch files for town NPC attacks
1015  private delegate void DelegateTownNPCAttackStrength(NPC npc, ref int damage, ref float knockback);
1016  private static HookList HookTownNPCAttackStrength = AddHook<DelegateTownNPCAttackStrength>(g => g.TownNPCAttackStrength);
1017 
1018  public static void TownNPCAttackStrength(NPC npc, ref int damage, ref float knockback) {
1019  npc.modNPC?.TownNPCAttackStrength(ref damage, ref knockback);
1020 
1021  foreach (GlobalNPC g in HookTownNPCAttackStrength.arr) {
1022  g.Instance(npc).TownNPCAttackStrength(npc, ref damage, ref knockback);
1023  }
1024  }
1025 
1026  private delegate void DelegateTownNPCAttackCooldown(NPC npc, ref int cooldown, ref int randExtraCooldown);
1027  private static HookList HookTownNPCAttackCooldown = AddHook<DelegateTownNPCAttackCooldown>(g => g.TownNPCAttackCooldown);
1028 
1029  public static void TownNPCAttackCooldown(NPC npc, ref int cooldown, ref int randExtraCooldown) {
1030  npc.modNPC?.TownNPCAttackCooldown(ref cooldown, ref randExtraCooldown);
1031 
1032  foreach (GlobalNPC g in HookTownNPCAttackCooldown.arr) {
1033  g.Instance(npc).TownNPCAttackCooldown(npc, ref cooldown, ref randExtraCooldown);
1034  }
1035  }
1036 
1037  private delegate void DelegateTownNPCAttackProj(NPC npc, ref int projType, ref int attackDelay);
1038  private static HookList HookTownNPCAttackProj = AddHook<DelegateTownNPCAttackProj>(g => g.TownNPCAttackProj);
1039 
1040  public static void TownNPCAttackProj(NPC npc, ref int projType, ref int attackDelay) {
1041  npc.modNPC?.TownNPCAttackProj(ref projType, ref attackDelay);
1042 
1043  foreach (GlobalNPC g in HookTownNPCAttackProj.arr) {
1044  g.Instance(npc).TownNPCAttackProj(npc, ref projType, ref attackDelay);
1045  }
1046  }
1047 
1048  private delegate void DelegateTownNPCAttackProjSpeed(NPC npc, ref float multiplier, ref float gravityCorrection,
1049  ref float randomOffset);
1050  private static HookList HookTownNPCAttackProjSpeed = AddHook<DelegateTownNPCAttackProjSpeed>(g => g.TownNPCAttackProjSpeed);
1051 
1052  public static void TownNPCAttackProjSpeed(NPC npc, ref float multiplier, ref float gravityCorrection,
1053  ref float randomOffset) {
1054  npc.modNPC?.TownNPCAttackProjSpeed(ref multiplier, ref gravityCorrection, ref randomOffset);
1055 
1056  foreach (GlobalNPC g in HookTownNPCAttackProjSpeed.arr) {
1057  g.Instance(npc).TownNPCAttackProjSpeed(npc, ref multiplier, ref gravityCorrection, ref randomOffset);
1058  }
1059  }
1060 
1061  private delegate void DelegateTownNPCAttackShoot(NPC npc, ref bool inBetweenShots);
1062  private static HookList HookTownNPCAttackShoot = AddHook<DelegateTownNPCAttackShoot>(g => g.TownNPCAttackShoot);
1063 
1064  public static void TownNPCAttackShoot(NPC npc, ref bool inBetweenShots) {
1065  npc.modNPC?.TownNPCAttackShoot(ref inBetweenShots);
1066 
1067  foreach (GlobalNPC g in HookTownNPCAttackShoot.arr) {
1068  g.Instance(npc).TownNPCAttackShoot(npc, ref inBetweenShots);
1069  }
1070  }
1071 
1072  private delegate void DelegateTownNPCAttackMagic(NPC npc, ref float auraLightMultiplier);
1073  private static HookList HookTownNPCAttackMagic = AddHook<DelegateTownNPCAttackMagic>(g => g.TownNPCAttackMagic);
1074 
1075  public static void TownNPCAttackMagic(NPC npc, ref float auraLightMultiplier) {
1076  npc.modNPC?.TownNPCAttackMagic(ref auraLightMultiplier);
1077 
1078  foreach (GlobalNPC g in HookTownNPCAttackMagic.arr) {
1079  g.Instance(npc).TownNPCAttackMagic(npc, ref auraLightMultiplier);
1080  }
1081  }
1082 
1083  private delegate void DelegateTownNPCAttackSwing(NPC npc, ref int itemWidth, ref int itemHeight);
1084  private static HookList HookTownNPCAttackSwing = AddHook<DelegateTownNPCAttackSwing>(g => g.TownNPCAttackSwing);
1085 
1086  public static void TownNPCAttackSwing(NPC npc, ref int itemWidth, ref int itemHeight) {
1087  npc.modNPC?.TownNPCAttackSwing(ref itemWidth, ref itemHeight);
1088 
1089  foreach (GlobalNPC g in HookTownNPCAttackSwing.arr) {
1090  g.Instance(npc).TownNPCAttackSwing(npc, ref itemWidth, ref itemHeight);
1091  }
1092  }
1093 
1094  private delegate void DelegateDrawTownAttackGun(NPC npc, ref float scale, ref int item, ref int closeness);
1095  private static HookList HookDrawTownAttackGun = AddHook<DelegateDrawTownAttackGun>(g => g.DrawTownAttackGun);
1096 
1097  public static void DrawTownAttackGun(NPC npc, ref float scale, ref int item, ref int closeness) {
1098  npc.modNPC?.DrawTownAttackGun(ref scale, ref item, ref closeness);
1099 
1100  foreach (GlobalNPC g in HookDrawTownAttackGun.arr) {
1101  g.Instance(npc).DrawTownAttackGun(npc, ref scale, ref item, ref closeness);
1102  }
1103  }
1104 
1105  private delegate void DelegateDrawTownAttackSwing(NPC npc, ref Texture2D item, ref int itemSize, ref float scale, ref Vector2 offset);
1106  private static HookList HookDrawTownAttackSwing = AddHook<DelegateDrawTownAttackSwing>(g => g.DrawTownAttackSwing);
1107 
1108  public static void DrawTownAttackSwing(NPC npc, ref Texture2D item, ref int itemSize, ref float scale, ref Vector2 offset) {
1109  npc.modNPC?.DrawTownAttackSwing(ref item, ref itemSize, ref scale, ref offset);
1110 
1111  foreach (GlobalNPC g in HookDrawTownAttackSwing.arr) {
1112  g.Instance(npc).DrawTownAttackSwing(npc, ref item, ref itemSize, ref scale, ref offset);
1113  }
1114  }
1115 
1116  private static bool HasMethod(Type t, string method, params Type[] args) {
1117  return t.GetMethod(method, args).DeclaringType != typeof(GlobalNPC);
1118  }
1119 
1120  internal static void VerifyGlobalNPC(GlobalNPC npc) {
1121  var type = npc.GetType();
1122 
1123  bool hasInstanceFields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
1124  .Any(f => f.DeclaringType != typeof(GlobalNPC));
1125  if (hasInstanceFields) {
1126  if (!npc.InstancePerEntity) {
1127  throw new Exception(type + " has instance fields but does not set InstancePerEntity to true. Either use static fields, or per instance globals");
1128  }
1129  }
1130  }
1131  }
1132 }
static void BossLoot(NPC npc, ref string name, ref int potionType)
Definition: NPCLoader.cs:431
static void NPCLoot(NPC npc)
Definition: NPCLoader.cs:422
static void BossHeadSpriteEffects(NPC npc, ref SpriteEffects spriteEffects)
Definition: NPCLoader.cs:665
static void PostDraw(NPC npc, SpriteBatch spriteBatch, Color drawColor)
Definition: NPCLoader.cs:711
static bool CheckDead(NPC npc)
Definition: NPCLoader.cs:372
static void TownNPCAttackProj(NPC npc, ref int projType, ref int attackDelay)
Definition: NPCLoader.cs:1040
virtual bool CanHitPlayer(NPC npc, Player target, ref int cooldownSlot)
Allows you to determine whether an NPC can hit the given player. Return false to block the NPC from h...
Definition: GlobalNPC.cs:210
static void NPCAI(NPC npc)
Definition: NPCLoader.cs:239
virtual bool PreNPCLoot(NPC npc)
Allows you to determine whether or not the NPC will drop anything at all. Return false to stop the NP...
Definition: GlobalNPC.cs:183
static void DrawTownAttackSwing(NPC npc, ref Texture2D item, ref int itemSize, ref float scale, ref Vector2 offset)
Definition: NPCLoader.cs:1108
This server as a central class to help modders spawn their npcs. It&#39;s basically the vanilla spawn cod...
static void AI(NPC npc)
Definition: NPCLoader.cs:270
static void BuffTownNPC(ref float damageMult, ref int defense)
Definition: NPCLoader.cs:994
This class serves as a place for you to place all your properties and hooks for each NPC...
Definition: ModNPC.cs:14
static int ChooseSpawn(NPCSpawnInfo spawnInfo)
Definition: NPCLoader.cs:789
virtual void OnHitByProjectile(NPC npc, Projectile projectile, int damage, float knockback, bool crit)
Allows you to create special effects when an NPC is hit by a projectile.
Definition: GlobalNPC.cs:331
virtual bool CheckDead(NPC npc)
Whether or not an NPC should be killed when it reaches 0 health. You may program extra effects in thi...
Definition: GlobalNPC.cs:166
static void TownNPCAttackShoot(NPC npc, ref bool inBetweenShots)
Definition: NPCLoader.cs:1064
static bool AllowVanillaClients
Definition: ModNet.cs:53
virtual void DrawTownAttackSwing(NPC npc, ref Texture2D item, ref int itemSize, ref float scale, ref Vector2 offset)
Allows you to customize how a town NPC&#39;s weapon is drawn when the NPC is swinging it (the NPC must ha...
Definition: GlobalNPC.cs:628
virtual void ModifyHitNPC(NPC npc, NPC target, ref int damage, ref float knockback, ref bool crit)
Allows you to modify the damage, knockback, etc., that an NPC does to a friendly NPC.
Definition: GlobalNPC.cs:252
static void BossHeadRotation(NPC npc, ref float rotation)
Definition: NPCLoader.cs:654
static void OnHitByItem(NPC npc, Player player, Item item, int damage, float knockback, bool crit)
Definition: NPCLoader.cs:570
static bool DrawHealthBar(NPC npc, ref float scale)
Definition: NPCLoader.cs:733
static void UpdateLifeRegen(NPC npc, ref int damage)
Definition: NPCLoader.cs:348
virtual bool CanChat(NPC npc)
Allows you to determine whether this NPC can talk with the player. Return true to allow talking with ...
Definition: GlobalNPC.cs:474
virtual void SetupShop(int type, Chest shop, ref int nextSlot)
Allows you to add items to an NPC&#39;s shop. The type parameter is the type of the NPC that this shop be...
Definition: GlobalNPC.cs:510
virtual float SpawnChance(NPCSpawnInfo spawnInfo)
Whether or not this NPC can spawn with the given spawning conditions. Return the weight for the chanc...
Definition: ModNPC.cs:556
virtual void OnCatchNPC(NPC npc, Player player, Item item)
Allows you to make things happen when an NPC is caught. Ran Serverside.
Definition: GlobalNPC.cs:200
static void BossBag(NPC npc, ref int bagType)
Definition: NPCLoader.cs:435
A struct that stores information regarding where an NPC is naturally spawning and the player it is sp...
Definition: NPCSpawnInfo.cs:6
static bool PreDraw(NPC npc, SpriteBatch spriteBatch, Color drawColor)
Definition: NPCLoader.cs:698
virtual void TownNPCAttackStrength(NPC npc, ref int damage, ref float knockback)
Allows you to determine the damage and knockback of a town NPC&#39;s attack before the damage is scaled...
Definition: GlobalNPC.cs:553
static void PostAI(NPC npc)
Definition: NPCLoader.cs:280
static void HitEffect(NPC npc, int hitDirection, double damage)
Definition: NPCLoader.cs:336
static bool StrikeNPC(NPC npc, ref double damage, int defense, ref float knockback, int hitDirection, ref bool crit)
Definition: NPCLoader.cs:627
static void ScaleExpertStats(NPC npc, int numPlayers, float bossLifeScale)
Definition: NPCLoader.cs:221
static void ReceiveExtraAI(NPC npc, BinaryReader reader)
Definition: NPCLoader.cs:305
virtual void SpawnNPC(int npc, int tileX, int tileY)
Allows you to customize an NPC (for example, its position or ai array) after it naturally spawns and ...
Definition: GlobalNPC.cs:466
virtual void ResetEffects(NPC npc)
This is where you reset any fields you add to your subclass to their default states. This is necessary in order to reset your fields if they are conditionally set by a tick update but the condition is no longer satisfied.
Definition: GlobalNPC.cs:101
static void TownNPCAttackSwing(NPC npc, ref int itemWidth, ref int itemHeight)
Definition: NPCLoader.cs:1086
virtual void EditSpawnRange(Player player, ref int spawnRangeX, ref int spawnRangeY, ref int safeRangeX, ref int safeRangeY)
Allows you to modify the range at which NPCs can spawn around the given player. The spawnRanges deter...
Definition: GlobalNPC.cs:448
virtual void SetupTravelShop(int[] shop, ref int nextSlot)
Allows you to add items to the traveling merchant&#39;s shop. Add an item by setting shop[nextSlot] to th...
Definition: GlobalNPC.cs:518
static bool CanHitNPC(NPC npc, NPC target)
Definition: NPCLoader.cs:489
virtual void GetChat(NPC npc, ref string chat)
Allows you to modify the chat message of any NPC that the player can talk to.
Definition: GlobalNPC.cs:483
static void OnCatchNPC(NPC npc, Player player, Item item)
Definition: NPCLoader.cs:443
virtual void ScaleExpertStats(NPC npc, int numPlayers, float bossLifeScale)
Allows you to customize an NPC&#39;s stats in expert mode.
Definition: GlobalNPC.cs:94
virtual void UpdateLifeRegen(NPC npc, ref int damage)
Allows you to make the NPC either regenerate health or take damage over time by setting npc...
Definition: GlobalNPC.cs:149
virtual void BossHeadRotation(NPC npc, ref float rotation)
Allows you to customize the rotation of an NPC&#39;s boss head icon on the map.
Definition: GlobalNPC.cs:361
This serves as the central class which loads mods. It contains many static fields and methods related...
Definition: ModLoader.cs:28
virtual void OnHitNPC(NPC npc, NPC target, int damage, float knockback, bool crit)
Allows you to create special effects when an NPC hits a friendly NPC.
Definition: GlobalNPC.cs:263
virtual void ModifyHitByProjectile(NPC npc, Projectile projectile, ref int damage, ref float knockback, ref bool crit, ref int hitDirection)
Allows you to modify the damage, knockback, etc., that an NPC takes from a projectile.
Definition: GlobalNPC.cs:320
static bool CanBeHitByItem(NPC npc, Player player, Item item)
Definition: NPCLoader.cs:534
virtual void OnHitByItem(NPC npc, Player player, Item item, int damage, float knockback, bool crit)
Allows you to create special effects when an NPC is hit by a melee weapon.
Definition: GlobalNPC.cs:298
virtual bool InstancePerEntity
Whether to create a new GlobalNPC instance for every NPC that exists. Useful for storing information ...
Definition: GlobalNPC.cs:46
static void ModifyHitByProjectile(NPC npc, Projectile projectile, ref int damage, ref float knockback, ref bool crit, ref int hitDirection)
Definition: NPCLoader.cs:606
virtual void AI(NPC npc)
Allows you to determine how any NPC behaves. This will only be called if PreAI returns true...
Definition: GlobalNPC.cs:117
static void ModifyHitNPC(NPC npc, NPC target, ref int damage, ref float knockback, ref bool crit)
Definition: NPCLoader.cs:515
virtual void DrawBehind(NPC npc, int index)
When used in conjunction with "npc.hide = true", allows you to specify that this npc should be drawn ...
Definition: GlobalNPC.cs:415
virtual int SpawnNPC(int tileX, int tileY)
Allows you to customize how this NPC is created when it naturally spawns (for example, its position or ai array). Return the return value of NPC.NewNPC. By default this method spawns this NPC on top of the tile at the given coordinates.
Definition: ModNPC.cs:566
virtual void ModifyHitByItem(NPC npc, Player player, Item item, ref int damage, ref float knockback, ref bool crit)
Allows you to modify the damage, knockback, etc., that an NPC takes from a melee weapon.
Definition: GlobalNPC.cs:286
virtual void TownNPCAttackProjSpeed(NPC npc, ref float multiplier, ref float gravityCorrection, ref float randomOffset)
Allows you to determine the speed at which a town NPC throws a projectile when it attacks...
Definition: GlobalNPC.cs:581
NPC npc
The NPC object that this ModNPC controls.
Definition: ModNPC.cs:21
static bool PreNPCLoot(NPC npc)
Definition: NPCLoader.cs:402
static void TownNPCAttackCooldown(NPC npc, ref int cooldown, ref int randExtraCooldown)
Definition: NPCLoader.cs:1029
static void TownNPCAttackProjSpeed(NPC npc, ref float multiplier, ref float gravityCorrection, ref float randomOffset)
Definition: NPCLoader.cs:1052
virtual void FindFrame(NPC npc, int frameHeight)
Allows you to modify the frame from an NPC&#39;s texture that is drawn, which is necessary in order to an...
Definition: GlobalNPC.cs:132
static int SpawnNPC(int type, int tileX, int tileY)
Definition: NPCLoader.cs:823
virtual bool CanGoToStatue(NPC npc, bool toKingStatue)
Whether this NPC can be telported a King or Queen statue. Return true to allow the NPC to teleport to...
Definition: GlobalNPC.cs:526
virtual void OnHitPlayer(NPC npc, Player target, int damage, bool crit)
Allows you to create special effects when an NPC hits a player (for example, inflicting debuffs)...
Definition: GlobalNPC.cs:231
static void SetupShop(int type, Chest shop, ref int nextSlot)
Definition: NPCLoader.cs:942
virtual void PostAI(NPC npc)
Allows you to determine how any NPC behaves. This will be called regardless of what PreAI returns...
Definition: GlobalNPC.cs:124
virtual void DrawEffects(NPC npc, ref Color drawColor)
Allows you to add special visual effects to an NPC (such as creating dust), and modify the color in w...
Definition: GlobalNPC.cs:387
static void DrawTownAttackGun(NPC npc, ref float scale, ref int item, ref int closeness)
Definition: NPCLoader.cs:1097
virtual bool CanBeHitByItem(NPC npc, Player player, Item item)
Allows you to determine whether an NPC can be hit by the given melee weapon when swung. Return true to allow hitting the NPC, return false to block hitting the NPC, and return null to use the vanilla code for whether the NPC can be hit. Returns null by default.
Definition: GlobalNPC.cs:273
virtual bool CanBeHitByProjectile(NPC npc, Projectile projectile)
Allows you to determine whether an NPC can be hit by the given projectile. Return true to allow hitti...
Definition: GlobalNPC.cs:307
static bool PreAI(NPC npc)
Definition: NPCLoader.cs:257
static void CanTownNPCSpawn(int numTownNPCs, int money)
Definition: NPCLoader.cs:835
virtual void SetDefaults(NPC npc)
Allows you to set the properties of any and every NPC that gets created.
Definition: GlobalNPC.cs:85
static bool CanGoToStatue(NPC npc, bool toKingStatue, bool vanillaCanGo)
Definition: NPCLoader.cs:965
static void DrawEffects(NPC npc, ref Color drawColor)
Definition: NPCLoader.cs:688
virtual bool PreAI(NPC npc)
Allows you to determine how any NPC behaves. Return false to stop the vanilla AI and the AI hook from...
Definition: GlobalNPC.cs:109
static void SendExtraAI(NPC npc, BinaryWriter writer)
Definition: NPCLoader.cs:288
virtual void BossHeadSlot(NPC npc, ref int index)
Allows you to customize the boss head texture used by an NPC based on its state. Set index to -1 to s...
Definition: GlobalNPC.cs:353
virtual bool CheckActive(NPC npc)
Whether or not to run the code for checking whether an NPC will remain active. Return false to stop t...
Definition: GlobalNPC.cs:157
static void OnChatButtonClicked(bool firstButton)
Definition: NPCLoader.cs:920
This class allows you to modify and use hooks for all NPCs, including vanilla mobs. Create an instance of an overriding class then call Mod.AddGlobalNPC to use this.
Definition: GlobalNPC.cs:11
static bool CheckActive(NPC npc)
Definition: NPCLoader.cs:358
virtual bool StrikeNPC(NPC npc, ref double damage, int defense, ref float knockback, int hitDirection, ref bool crit)
Allows you to use a custom damage formula for when an NPC takes damage from any source. For example, you can change the way defense works or use a different crit multiplier. Return false to stop the game from running the vanilla damage formula; returns true by default.
Definition: GlobalNPC.cs:344
virtual void TownNPCAttackShoot(NPC npc, ref bool inBetweenShots)
Allows you to tell the game that a town NPC has already created a projectile and will still create mo...
Definition: GlobalNPC.cs:590
static void EditSpawnRate(Player player, ref int spawnRate, ref int maxSpawns)
Definition: NPCLoader.cs:770
static bool HasMethod(Type t, string method, params Type[] args)
Definition: NPCLoader.cs:1116
static void OnHitByProjectile(NPC npc, Projectile projectile, int damage, float knockback, bool crit)
Definition: NPCLoader.cs:616
static bool CheckConditions(int type)
Definition: NPCLoader.cs:847
static void BossHeadSlot(NPC npc, ref int index)
Definition: NPCLoader.cs:643
static ModNPC GetNPC(int type)
Gets the ModNPC instance corresponding to the specified type.
Definition: NPCLoader.cs:93
static void TownNPCAttackMagic(NPC npc, ref float auraLightMultiplier)
Definition: NPCLoader.cs:1075
virtual void HitEffect(NPC npc, int hitDirection, double damage)
Allows you to make things happen whenever an NPC is hit, such as creating dust or gores...
Definition: GlobalNPC.cs:141
static string TownNPCName(int type)
Definition: NPCLoader.cs:851
GlobalNPC Instance(NPC npc)
virtual bool DrawHealthBar(NPC npc, byte hbPosition, ref float scale, ref Vector2 position)
Allows you to control how the health bar for the given NPC is drawn. The hbPosition parameter is the ...
Definition: GlobalNPC.cs:427
virtual string Name
Stores the name of the mod. This name serves as the mod&#39;s identification, and also helps with saving ...
Definition: Mod.cs:42
This serves as the central class from which NPC-related functions are carried out. It also stores a list of mod NPCs by ID.
Definition: NPCLoader.cs:19
static void FindFrame(NPC npc, int frameHeight)
Definition: NPCLoader.cs:320
static void OnHitNPC(NPC npc, NPC target, int damage, float knockback, bool crit)
Definition: NPCLoader.cs:525
static bool UsesPartyHat(NPC npc)
Definition: NPCLoader.cs:855
static void GetChat(NPC npc, ref string chat)
Definition: NPCLoader.cs:880
virtual void TownNPCAttackProj(NPC npc, ref int projType, ref int attackDelay)
Allows you to determine the projectile type of a town NPC&#39;s attack, and how long it takes for the pro...
Definition: GlobalNPC.cs:571
This serves as the central class from which buff-related functions are supported and carried out...
Definition: BuffLoader.cs:14
virtual void ModifyHitPlayer(NPC npc, Player target, ref int damage, ref bool crit)
Allows you to modify the damage, etc., that an NPC does to a player.
Definition: GlobalNPC.cs:221
static void OnGoToStatue(NPC npc, bool toKingStatue)
Definition: NPCLoader.cs:983
virtual bool CanTownNPCSpawn(int numTownNPCs, int money)
Whether or not the conditions have been met for this town NPC to be able to move into town...
Definition: ModNPC.cs:576
static bool CanBeHitByProjectile(NPC npc, Projectile projectile)
Definition: NPCLoader.cs:580
virtual void EditSpawnRate(Player player, ref int spawnRate, ref int maxSpawns)
Allows you to modify the chance of NPCs spawning around the given player and the maximum number of NP...
Definition: GlobalNPC.cs:437
static Color GetAlpha(NPC npc, Color lightColor)
Definition: NPCLoader.cs:675
static bool SpecialNPCLoot(NPC npc)
Definition: NPCLoader.cs:388
virtual void EditSpawnPool(IDictionary< int, float > pool, NPCSpawnInfo spawnInfo)
Allows you to control which NPCs can spawn and how likely each one is to spawn. The pool parameter ma...
Definition: GlobalNPC.cs:457
virtual bool PreDraw(NPC npc, SpriteBatch spriteBatch, Color drawColor)
Allows you to draw things behind an NPC, or to modify the way the NPC is drawn. Return false to stop ...
Definition: GlobalNPC.cs:397
Mod is an abstract class that you will override. It serves as a central place from which the mod&#39;s co...
Definition: Mod.cs:24
virtual bool SpecialNPCLoot(NPC npc)
Allows you to call NPCLoot on your own when the NPC dies, rather then letting vanilla call it on its ...
Definition: GlobalNPC.cs:174
static void ModifyHitByItem(NPC npc, Player player, Item item, ref int damage, ref float knockback, ref bool crit)
Definition: NPCLoader.cs:560
static bool CanChat(NPC npc, bool vanillaCanChat)
Definition: NPCLoader.cs:861
static void SetupTravelShop(int[] shop, ref int nextSlot)
Definition: NPCLoader.cs:957
virtual bool PreChatButtonClicked(NPC npc, bool firstButton)
Allows you to determine if something can happen whenever a button is clicked on this NPC&#39;s chat windo...
Definition: GlobalNPC.cs:492
virtual void DrawTownAttackGun(NPC npc, ref float scale, ref int item, ref int closeness)
Allows you to customize how a town NPC&#39;s weapon is drawn when the NPC is shooting (the NPC must have ...
Definition: GlobalNPC.cs:617
static bool PreChatButtonClicked(bool firstButton)
Definition: NPCLoader.cs:901
virtual void NPCLoot(NPC npc)
Allows you to make things happen when an NPC dies (for example, dropping items and setting ModWorld f...
Definition: GlobalNPC.cs:191
virtual Color GetAlpha(NPC npc, Color drawColor)
Allows you to determine the color and transparency in which an NPC is drawn. Return null to use the d...
Definition: GlobalNPC.cs:378
virtual void TownNPCAttackMagic(NPC npc, ref float auraLightMultiplier)
Allows you to control the brightness of the light emitted by a town NPC&#39;s aura when it performs a mag...
Definition: GlobalNPC.cs:598
static void SetChatButtons(ref string button, ref string button2)
Definition: NPCLoader.cs:892
virtual bool CanHitNPC(NPC npc, NPC target)
Allows you to determine whether an NPC can hit the given friendly NPC. Return true to allow hitting t...
Definition: GlobalNPC.cs:240
virtual void PostDraw(NPC npc, SpriteBatch spriteBatch, Color drawColor)
Allows you to draw things in front of this NPC. This method is called even if PreDraw returns false...
Definition: GlobalNPC.cs:407
virtual void OnChatButtonClicked(NPC npc, bool firstButton)
Allows you to make something happen whenever a button is clicked on this NPC&#39;s chat window...
Definition: GlobalNPC.cs:501
virtual void TownNPCAttackSwing(NPC npc, ref int itemWidth, ref int itemHeight)
Allows you to determine the width and height of the item a town NPC swings when it attacks...
Definition: GlobalNPC.cs:607
virtual void BossHeadSpriteEffects(NPC npc, ref SpriteEffects spriteEffects)
Allows you to flip an NPC&#39;s boss head icon on the map.
Definition: GlobalNPC.cs:369
static void ModifyHitPlayer(NPC npc, Player target, ref int damage, ref bool crit)
Definition: NPCLoader.cs:469
virtual void OnGoToStatue(NPC npc, bool toKingStatue)
Allows you to make things happen when this NPC teleports to a King or Queen statue. This method is only called server side.
Definition: GlobalNPC.cs:536
static void ResetEffects(NPC npc)
Definition: NPCLoader.cs:231
static void TownNPCAttackStrength(NPC npc, ref int damage, ref float knockback)
Definition: NPCLoader.cs:1018
static void EditSpawnRange(Player player, ref int spawnRangeX, ref int spawnRangeY, ref int safeRangeX, ref int safeRangeY)
Definition: NPCLoader.cs:780
virtual void TownNPCAttackCooldown(NPC npc, ref int cooldown, ref int randExtraCooldown)
Allows you to determine the cooldown between each of a town NPC&#39;s attack. The cooldown will be a numb...
Definition: GlobalNPC.cs:562
static void DrawHealthBar(NPC npc, Vector2 position, float scale)
Definition: NPCLoader.cs:762
virtual void BuffTownNPC(ref float damageMult, ref int defense)
Allows you to modify the stats of town NPCs. Useful for buffing town NPCs when certain bosses are def...
Definition: GlobalNPC.cs:544
static bool CanHitPlayer(NPC npc, Player target, ref int cooldownSlot)
Definition: NPCLoader.cs:454
static void OnHitPlayer(NPC npc, Player target, int damage, bool crit)
Definition: NPCLoader.cs:479