1using Microsoft.Xna.Framework;
2using Microsoft.Xna.Framework.Graphics;
4using System.Collections.Generic;
7using System.Linq.Expressions;
8using System.Reflection;
10using Terraria.Localization;
21 internal static readonly IList<ModProjectile> projectiles =
new List<ModProjectile>();
22 internal static readonly IList<GlobalProjectile> globalProjectiles =
new List<GlobalProjectile>();
24 internal static readonly IDictionary<string, int> globalIndexes =
new Dictionary<string, int>();
25 internal static readonly IDictionary<Type, int> globalIndexesByType =
new Dictionary<Type, int>();
37 private static List<HookList>
hooks =
new List<HookList>();
45 internal static int ReserveProjectileID() {
61 return type >= ProjectileID.Count && type <
ProjectileCount ? projectiles[type - ProjectileID.Count] :
null;
64 internal static void ResizeArrays() {
72 Array.Resize(ref ProjectileID.Sets.YoyosLifeTimeMultiplier,
nextProjectile);
73 Array.Resize(ref ProjectileID.Sets.YoyosMaximumRange,
nextProjectile);
75 Array.Resize(ref ProjectileID.Sets.CanDistortWater,
nextProjectile);
78 Array.Resize(ref ProjectileID.Sets.ForcePlateDetection,
nextProjectile);
80 Array.Resize(ref ProjectileID.Sets.TrailCacheLength,
nextProjectile);
85 Array.Resize(ref ProjectileID.Sets.MinionTargettingFeature,
nextProjectile);
86 Array.Resize(ref ProjectileID.Sets.MinionSacrificable,
nextProjectile);
87 Array.Resize(ref ProjectileID.Sets.DontAttachHideToAlpha,
nextProjectile);
89 Array.Resize(ref ProjectileID.Sets.StardustDragon,
nextProjectile);
90 Array.Resize(ref ProjectileID.Sets.NoLiquidDistortion,
nextProjectile);
92 Lang._projectileNameCache[k] = LocalizedText.Empty;
93 ProjectileID.Sets.YoyosLifeTimeMultiplier[k] = -1;
94 ProjectileID.Sets.YoyosMaximumRange[k] = 200f;
95 ProjectileID.Sets.YoyosTopSpeed[k] = 10f;
96 ProjectileID.Sets.CanDistortWater[k] =
true;
97 Main.projectileLoaded[k] =
true;
98 Main.projFrames[k] = 1;
99 ProjectileID.Sets.TrailingMode[k] = -1;
100 ProjectileID.Sets.TrailCacheLength[k] = 10;
102 Array.Resize(ref Projectile.perIDStaticNPCImmunity,
nextProjectile);
104 Projectile.perIDStaticNPCImmunity[i] =
new uint[200];
107 InstancedGlobals = globalProjectiles.Where(g => g.InstancePerEntity).ToArray();
108 for (
int i = 0; i < InstancedGlobals.Length; i++) {
109 InstancedGlobals[i].instanceIndex = i;
111 foreach (var hook
in hooks) {
112 hook.arr = ModLoader.BuildGlobalHook(globalProjectiles, hook.method);
116 internal static void Unload() {
119 globalProjectiles.Clear();
120 globalIndexes.Clear();
121 globalIndexesByType.Clear();
124 internal static bool IsModProjectile(Projectile projectile) {
125 return projectile.type >= ProjectileID.Count;
130 internal static void SetDefaults(Projectile projectile,
bool createModProjectile =
true) {
131 if (IsModProjectile(projectile) && createModProjectile) {
134 projectile.globalProjectiles = InstancedGlobals.Select(g => g.NewInstance(projectile)).ToArray();
141 internal static GlobalProjectile GetGlobalProjectile(Projectile projectile,
Mod mod,
string name) {
143 return globalIndexes.TryGetValue(mod.
Name +
':' + name, out index) ? globalProjectiles[index].
Instance(projectile) :
null;
146 internal static GlobalProjectile GetGlobalProjectile(Projectile projectile, Type type) {
148 return globalIndexesByType.TryGetValue(type, out index) ? (index > -1 ? globalProjectiles[index].Instance(projectile) :
null) :
null;
152 if (
PreAI(projectile)) {
153 int type = projectile.type;
154 bool useAiType = projectile.modProjectile !=
null && projectile.modProjectile.aiType > 0;
156 projectile.type = projectile.modProjectile.aiType;
158 projectile.VanillaAI();
160 projectile.type = type;
169 public static bool PreAI(Projectile projectile) {
174 if (result && projectile.modProjectile !=
null) {
175 return projectile.modProjectile.PreAI();
182 public static void AI(Projectile projectile) {
183 projectile.modProjectile?.AI();
192 public static void PostAI(Projectile projectile) {
193 projectile.modProjectile?.PostAI();
201 public static byte[]
SendExtraAI(Projectile projectile, ref BitsByte flags) {
202 if (projectile.modProjectile !=
null) {
204 using (MemoryStream stream =
new MemoryStream()) {
206 projectile.modProjectile.SendExtraAI(modWriter);
208 data = stream.ToArray();
211 if (data.Length > 0) {
212 flags[Projectile.maxAI + 1] =
true;
221 if (flags[Projectile.maxAI + 1]) {
222 return reader.ReadBytes(reader.ReadByte());
229 if (extraAI.Length > 0 && projectile.modProjectile !=
null) {
230 using (MemoryStream stream =
new MemoryStream(extraAI)) {
232 projectile.modProjectile.ReceiveExtraAI(reader);
241 if (IsModProjectile(projectile) && !projectile.modProjectile.ShouldUpdatePosition()) {
255 public static bool TileCollideStyle(Projectile projectile, ref
int width, ref
int height, ref
bool fallThrough) {
256 if (IsModProjectile(projectile) && !projectile.modProjectile.TileCollideStyle(ref width, ref height, ref fallThrough)) {
270 public static bool OnTileCollide(Projectile projectile, Vector2 oldVelocity) {
275 if (result && projectile.modProjectile !=
null) {
276 return projectile.modProjectile.OnTileCollide(oldVelocity);
286 if (canCutTiles.HasValue) {
287 return canCutTiles.Value;
290 return projectile.modProjectile?.CanCutTiles();
295 public static void CutTiles(Projectile projectile) {
299 projectile.modProjectile?.CutTiles();
304 public static bool PreKill(Projectile projectile,
int timeLeft) {
309 if (result && projectile.modProjectile !=
null) {
310 return projectile.modProjectile.PreKill(timeLeft);
317 public static void Kill(Projectile projectile,
int timeLeft) {
318 projectile.modProjectile?.Kill(timeLeft);
328 if (projectile.modProjectile !=
null && !projectile.modProjectile.CanDamage()) {
342 if (projectile.modProjectile !=
null && projectile.modProjectile.MinionContactDamage()) {
357 projectile.modProjectile?.ModifyDamageHitbox(ref hitbox);
365 public static bool?
CanHitNPC(Projectile projectile, NPC target) {
369 if (canHit.HasValue && !canHit.Value) {
372 if (canHit.HasValue) {
376 if (projectile.modProjectile !=
null) {
377 bool? canHit = projectile.modProjectile.CanHitNPC(target);
378 if (canHit.HasValue && !canHit.Value) {
381 if (canHit.HasValue) {
388 private delegate
void DelegateModifyHitNPC(Projectile projectile, NPC target, ref
int damage, ref
float knockback, ref
bool crit, ref
int hitDirection);
391 public static void ModifyHitNPC(Projectile projectile, NPC target, ref
int damage, ref
float knockback, ref
bool crit, ref
int hitDirection) {
392 projectile.modProjectile?.ModifyHitNPC(target, ref damage, ref knockback, ref crit, ref hitDirection);
395 g.
Instance(projectile).
ModifyHitNPC(projectile, target, ref damage, ref knockback, ref crit, ref hitDirection);
401 public static void OnHitNPC(Projectile projectile, NPC target,
int damage,
float knockback,
bool crit) {
402 projectile.modProjectile?.OnHitNPC(target, damage, knockback, crit);
405 g.
Instance(projectile).
OnHitNPC(projectile, target, damage, knockback, crit);
411 public static bool CanHitPvp(Projectile projectile, Player target) {
417 if (projectile.modProjectile !=
null) {
418 return projectile.modProjectile.CanHitPvp(target);
423 private delegate
void DelegateModifyHitPvp(Projectile projectile, Player target, ref
int damage, ref
bool crit);
426 public static void ModifyHitPvp(Projectile projectile, Player target, ref
int damage, ref
bool crit) {
427 projectile.modProjectile?.ModifyHitPvp(target, ref damage, ref crit);
436 public static void OnHitPvp(Projectile projectile, Player target,
int damage,
bool crit) {
437 projectile.modProjectile?.OnHitPvp(target, damage, crit);
446 public static bool CanHitPlayer(Projectile projectile, Player target) {
452 if (projectile.modProjectile !=
null) {
453 return projectile.modProjectile.CanHitPlayer(target);
461 public static void ModifyHitPlayer(Projectile projectile, Player target, ref
int damage, ref
bool crit) {
462 projectile.modProjectile?.ModifyHitPlayer(target, ref damage, ref crit);
471 public static void OnHitPlayer(Projectile projectile, Player target,
int damage,
bool crit) {
472 projectile.modProjectile?.OnHitPlayer(target, damage, crit);
481 public static bool?
Colliding(Projectile projectile, Rectangle projHitbox, Rectangle targetHitbox) {
483 bool? colliding = g.
Instance(projectile).
Colliding(projectile, projHitbox, targetHitbox);
484 if (colliding.HasValue) {
485 return colliding.Value;
488 return projectile.modProjectile?.Colliding(projHitbox, targetHitbox);
492 if (projectile.modProjectile !=
null) {
493 flag = projectile.modProjectile.drawHeldProjInFrontOfHeldItemAndArms;
499 public static Color?
GetAlpha(Projectile projectile, Color lightColor) {
502 if (color.HasValue) {
506 return projectile.modProjectile?.GetAlpha(lightColor);
509 public static void DrawOffset(Projectile projectile, ref
int offsetX, ref
int offsetY, ref
float originX) {
510 if (projectile.modProjectile !=
null) {
511 offsetX = projectile.modProjectile.drawOffsetX;
512 offsetY = -projectile.modProjectile.drawOriginOffsetY;
513 originX += projectile.modProjectile.drawOriginOffsetX;
519 public static bool PreDrawExtras(Projectile projectile, SpriteBatch spriteBatch) {
524 if (result && projectile.modProjectile !=
null) {
525 return projectile.modProjectile.PreDrawExtras(spriteBatch);
530 private static HookList HookPreDraw = AddHook<Func<Projectile, SpriteBatch, Color, bool>>(g => g.PreDraw);
532 public static bool PreDraw(Projectile projectile, SpriteBatch spriteBatch, Color lightColor) {
535 result &= g.
Instance(projectile).
PreDraw(projectile, spriteBatch, lightColor);
537 if (result && projectile.modProjectile !=
null) {
538 return projectile.modProjectile.PreDraw(spriteBatch, lightColor);
545 public static void PostDraw(Projectile projectile, SpriteBatch spriteBatch, Color lightColor) {
546 projectile.modProjectile?.PostDraw(spriteBatch, lightColor);
560 if (canGrapple.HasValue) {
574 if (singleHook.HasValue) {
593 return distance > projectile.modProjectile?.GrappleRange();
599 public static void NumGrappleHooks(Projectile projectile, Player player, ref
int numHooks) {
600 projectile.modProjectile?.NumGrappleHooks(player, ref numHooks);
611 projectile.modProjectile?.GrappleRetreatSpeed(player, ref speed);
621 public static void GrapplePullSpeed(Projectile projectile, Player player, ref
float speed) {
622 projectile.modProjectile?.GrapplePullSpeed(player, ref speed);
632 public static void GrappleTargetPoint(Projectile projectile, Player player, ref
float grappleX, ref
float grappleY) {
633 projectile.modProjectile?.GrappleTargetPoint(player, ref grappleX, ref grappleY);
640 private static HookList HookDrawBehind = AddHook<Action<Projectile, int, List<int>, List<int>, List<int>, List<int>>>(g => g.DrawBehind);
642 internal static void DrawBehind(Projectile projectile,
int index, List<int> drawCacheProjsBehindNPCsAndTiles, List<int> drawCacheProjsBehindNPCs, List<int> drawCacheProjsBehindProjectiles, List<int> drawCacheProjsOverWiresUI) {
643 projectile.modProjectile?.DrawBehind(index, drawCacheProjsBehindNPCsAndTiles, drawCacheProjsBehindNPCs, drawCacheProjsBehindProjectiles, drawCacheProjsOverWiresUI);
646 g.
Instance(projectile).
DrawBehind(projectile, index, drawCacheProjsBehindNPCsAndTiles, drawCacheProjsBehindNPCs, drawCacheProjsBehindProjectiles, drawCacheProjsOverWiresUI);
650 private static bool HasMethod(Type t,
string method, params Type[] args) {
655 var type = projectile.GetType();
657 bool hasInstanceFields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
659 if (hasInstanceFields) {
661 throw new Exception(type +
" has instance fields but does not set InstancePerEntity to true. Either use static fields, or per instance globals");
This class allows you to modify and use hooks for all projectiles, including vanilla projectiles....
virtual void OnHitPvp(Projectile projectile, Player target, int damage, bool crit)
Allows you to create special effects when a projectile hits an opponent player.
virtual ? bool CanUseGrapple(int type, Player player)
Whether or not a grappling hook that shoots this type of projectile can be used by the given player....
virtual bool InstancePerEntity
Whether to create a new GlobalProjectile instance for every Projectile that exists....
virtual void GrapplePullSpeed(Projectile projectile, Player player, ref float speed)
The speed at which the grapple pulls the player after hitting something. Defaults to 11,...
virtual void Kill(Projectile projectile, int timeLeft)
Allows you to control what happens when a projectile is killed (for example, creating dust or making ...
virtual bool PreDraw(Projectile projectile, SpriteBatch spriteBatch, Color lightColor)
Allows you to draw things behind a projectile, or to modify the way the projectile is drawn....
virtual void ModifyHitPlayer(Projectile projectile, Player target, ref int damage, ref bool crit)
Allows you to modify the damage, etc., that a hostile projectile does to a player.
virtual bool PreAI(Projectile projectile)
Allows you to determine how any projectile behaves. Return false to stop the vanilla AI and the AI ho...
virtual void OnHitPlayer(Projectile projectile, Player target, int damage, bool crit)
Allows you to create special effects when a hostile projectile hits a player.
virtual ? bool CanCutTiles(Projectile projectile)
Return true or false to specify if the projectile can cut tiles, like vines. Return null for vanilla ...
virtual void PostDraw(Projectile projectile, SpriteBatch spriteBatch, Color lightColor)
Allows you to draw things in front of a projectile. This method is called even if PreDraw returns fal...
virtual bool CanHitPlayer(Projectile projectile, Player target)
Allows you to determine whether a hostile projectile can hit the given player. Return false to block ...
virtual bool OnTileCollide(Projectile projectile, Vector2 oldVelocity)
Allows you to determine what happens when a projectile collides with a tile. OldVelocity is the veloc...
virtual void PostAI(Projectile projectile)
Allows you to determine how any projectile behaves. This will be called regardless of what PreAI retu...
virtual void OnHitNPC(Projectile projectile, NPC target, int damage, float knockback, bool crit)
Allows you to create special effects when a projectile hits an NPC (for example, inflicting debuffs)....
virtual void CutTiles(Projectile projectile)
Code ran when the projectile cuts tiles. Only runs if CanCutTiles() returns true. Useful when program...
virtual void ModifyHitNPC(Projectile projectile, NPC target, ref int damage, ref float knockback, ref bool crit, ref int hitDirection)
Allows you to modify the damage, knockback, etc., that a projectile does to an NPC....
virtual ? bool CanHitNPC(Projectile projectile, NPC target)
Allows you to determine whether a projectile can hit the given NPC. Return true to allow hitting the ...
virtual ? Color GetAlpha(Projectile projectile, Color lightColor)
Allows you to determine the color and transparency in which a projectile is drawn....
virtual void ModifyDamageHitbox(Projectile projectile, ref Rectangle hitbox)
Allows you to change the hitbox used by a projectile for damaging players and NPCs.
virtual bool ShouldUpdatePosition(Projectile projectile)
Whether or not the given projectile should update its position based on factors such as its velocity,...
virtual bool CanHitPvp(Projectile projectile, Player target)
Allows you to determine whether a projectile can hit the given opponent player. Return false to block...
virtual void UseGrapple(Player player, ref int type)
This code is called whenever the player uses a grappling hook that shoots this type of projectile....
virtual bool CanDamage(Projectile projectile)
Whether or not the given projectile is capable of killing tiles (such as grass) and damaging NPCs/pla...
virtual void NumGrappleHooks(Projectile projectile, Player player, ref int numHooks)
How many of this type of grappling hook the given player can latch onto blocks before the hooks start...
virtual bool MinionContactDamage(Projectile projectile)
Whether or not a minion can damage NPCs by touching them. Returns false by default....
virtual ? bool Colliding(Projectile projectile, Rectangle projHitbox, Rectangle targetHitbox)
Allows you to use custom collision detection between a projectile and a player or NPC that the projec...
virtual void ModifyHitPvp(Projectile projectile, Player target, ref int damage, ref bool crit)
Allows you to modify the damage, etc., that a projectile does to an opponent player.
GlobalProjectile Instance(Projectile projectile)
virtual void GrappleTargetPoint(Projectile projectile, Player player, ref float grappleX, ref float grappleY)
The location that the grappling hook pulls the player to. Defaults to the center of the hook projecti...
virtual bool PreKill(Projectile projectile, int timeLeft)
Allows you to determine whether the vanilla code for Kill and the Kill hook will be called....
virtual void DrawBehind(Projectile projectile, int index, List< int > drawCacheProjsBehindNPCsAndTiles, List< int > drawCacheProjsBehindNPCs, List< int > drawCacheProjsBehindProjectiles, List< int > drawCacheProjsOverWiresUI)
When used in conjunction with "projectile.hide = true", allows you to specify that this projectile sh...
virtual ? bool SingleGrappleHook(int type, Player player)
Whether or not a grappling hook can only have one hook per player in the world at a time....
virtual void AI(Projectile projectile)
Allows you to determine how any projectile behaves. This will only be called if PreAI returns true.
virtual bool TileCollideStyle(Projectile projectile, ref int width, ref int height, ref bool fallThrough)
Allows you to determine how a projectile interacts with tiles. Width and height determine the project...
virtual void GrappleRetreatSpeed(Projectile projectile, Player player, ref float speed)
The speed at which the grapple retreats back to the player after not hitting anything....
virtual bool PreDrawExtras(Projectile projectile, SpriteBatch spriteBatch)
Allows you to draw things behind a projectile. Returns false to stop the game from drawing extras tex...
virtual void SetDefaults(Projectile projectile)
Allows you to set the properties of any and every projectile that gets created.
Mod is an abstract class that you will override. It serves as a central place from which the mod's co...
virtual string Name
Stores the name of the mod. This name serves as the mod's identification, and also helps with saving ...
This serves as the central class which loads mods. It contains many static fields and methods related...
static bool AllowVanillaClients
This class serves as a place for you to place all your properties and hooks for each projectile....
virtual ? bool CanUseGrapple(Player player)
This code is called whenever the player uses a grappling hook that shoots this type of projectile....
virtual void UseGrapple(Player player, ref int type)
This code is called whenever the player uses a grappling hook that shoots this type of projectile....
virtual ModProjectile NewInstance(Projectile projectileClone)
Create a new instance of this ModProjectile for a Projectile instance. Called at the end of Projectil...
virtual ? bool SingleGrappleHook(Player player)
Whether or not a grappling hook can only have one hook per player in the world at a time....
readonly MethodInfo method
HookList(MethodInfo method)
This serves as the central class from which projectile-related functions are carried out....
static void PostDraw(Projectile projectile, SpriteBatch spriteBatch, Color lightColor)
static HookList HookCanDamage
static bool ShouldUpdatePosition(Projectile projectile)
static void GrappleRetreatSpeed(Projectile projectile, Player player, ref float speed)
static bool PreKill(Projectile projectile, int timeLeft)
static void OnHitNPC(Projectile projectile, NPC target, int damage, float knockback, bool crit)
static HookList HookTileCollideStyle
static void DrawHeldProjInFrontOfHeldItemAndArms(Projectile projectile, ref bool flag)
static HookList HookModifyHitPlayer
static ? Color GetAlpha(Projectile projectile, Color lightColor)
static ModProjectile GetProjectile(int type)
Gets the ModProjectile instance corresponding to the specified type.
static void OnHitPvp(Projectile projectile, Player target, int damage, bool crit)
static bool TileCollideStyle(Projectile projectile, ref int width, ref int height, ref bool fallThrough)
static HookList HookGrapplePullSpeed
static void GrappleTargetPoint(Projectile projectile, Player player, ref float grappleX, ref float grappleY)
static HookList HookPreDraw
delegate void DelegateModifyHitPlayer(Projectile projectile, Player target, ref int damage, ref bool crit)
delegate void DelegateGrapplePullSpeed(Projectile projectile, Player player, ref float speed)
static int ProjectileCount
static HookList HookOnHitPlayer
static bool GrappleOutOfRange(float distance, Projectile projectile)
static HookList HookSingleGrappleHook
static void ProjectileAI(Projectile projectile)
delegate void DelegateUseGrapple(Player player, ref int type)
static ? bool CanCutTiles(Projectile projectile)
static HookList HookGrappleTargetPoint
static ? bool SingleGrappleHook(int type, Player player)
static HookList HookShouldUpdatePosition
delegate bool DelegateTileCollideStyle(Projectile projectile, ref int width, ref int height, ref bool fallThrough)
static void ModifyHitNPC(Projectile projectile, NPC target, ref int damage, ref float knockback, ref bool crit, ref int hitDirection)
static HookList HookOnHitNPC
static bool CanHitPvp(Projectile projectile, Player target)
static void PostAI(Projectile projectile)
static bool CanHitPlayer(Projectile projectile, Player target)
delegate void DelegateModifyDamageHitbox(Projectile projectile, ref Rectangle hitbox)
delegate void DelegateModifyHitNPC(Projectile projectile, NPC target, ref int damage, ref float knockback, ref bool crit, ref int hitDirection)
static HookList HookPreDrawExtras
static void DrawOffset(Projectile projectile, ref int offsetX, ref int offsetY, ref float originX)
static bool PreDrawExtras(Projectile projectile, SpriteBatch spriteBatch)
static HookList HookOnHitPvp
static HookList HookPostAI
static bool CanDamage(Projectile projectile)
static void ModifyHitPvp(Projectile projectile, Player target, ref int damage, ref bool crit)
static HookList HookCanUseGrapple
static HookList HookGrappleRetreatSpeed
static HookList HookNumGrappleHooks
static bool PreDraw(Projectile projectile, SpriteBatch spriteBatch, Color lightColor)
static void GrapplePullSpeed(Projectile projectile, Player player, ref float speed)
static HookList HookCutTiles
static void ModifyHitPlayer(Projectile projectile, Player target, ref int damage, ref bool crit)
static HookList HookDrawBehind
static void Kill(Projectile projectile, int timeLeft)
static bool OnTileCollide(Projectile projectile, Vector2 oldVelocity)
static ? bool CanUseGrapple(int type, Player player)
delegate void DelegateGrappleRetreatSpeed(Projectile projectile, Player player, ref float speed)
static ? bool Colliding(Projectile projectile, Rectangle projHitbox, Rectangle targetHitbox)
static void CutTiles(Projectile projectile)
static void ModifyDamageHitbox(Projectile projectile, ref Rectangle hitbox)
static HookList HookModifyHitPvp
static bool MinionContactDamage(Projectile projectile)
static bool PreAI(Projectile projectile)
static HookList HookCanHitNPC
static HookList HookPreKill
static byte[] SendExtraAI(Projectile projectile, ref BitsByte flags)
static void UseGrapple(Player player, ref int type)
static HookList HookGetAlpha
static HookList HookPreAI
static HookList HookUseGrapple
static HookList HookPostDraw
static HookList HookMinionContactDamage
static HookList HookCanHitPlayer
static void AI(Projectile projectile)
static void ReceiveExtraAI(Projectile projectile, byte[] extraAI)
static byte[] ReadExtraAI(BinaryReader reader, BitsByte flags)
static HookList HookCanHitPvp
static HookList HookOnTileCollide
static int nextProjectile
static List< HookList > hooks
static void OnHitPlayer(Projectile projectile, Player target, int damage, bool crit)
static HookList HookCanCutTiles
static ? bool CanHitNPC(Projectile projectile, NPC target)
static HookList HookModifyHitNPC
static HookList HookSetDefaults
static void NumGrappleHooks(Projectile projectile, Player player, ref int numHooks)
delegate void DelegateModifyHitPvp(Projectile projectile, Player target, ref int damage, ref bool crit)
delegate void DelegateGrappleTargetPoint(Projectile projectile, Player player, ref float grappleX, ref float grappleY)
static HookList AddHook< F >(Expression< Func< GlobalProjectile, F > > func)
static HookList HookModifyDamageHitbox
static bool HasMethod(Type t, string method, params Type[] args)
delegate void DelegateNumGrappleHooks(Projectile projectile, Player player, ref int numHooks)
static HookList HookColliding