1 using Microsoft.Xna.Framework;
2 using Microsoft.Xna.Framework.Graphics;
4 using System.Collections.Generic;
7 using System.Linq.Expressions;
20 private static int nextProjectile = ProjectileID.Count;
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>();
39 private static HookList AddHook<F>(Expression<Func<GlobalProjectile, F>> func) {
45 internal static int ReserveProjectileID() {
48 int reserveID = nextProjectile;
53 public static int ProjectileCount => nextProjectile;
61 return type >= ProjectileID.Count && type < ProjectileCount ? projectiles[type - ProjectileID.Count] : null;
64 internal static void ResizeArrays() {
65 Array.Resize(ref Main.projectileLoaded, nextProjectile);
66 Array.Resize(ref Main.projectileTexture, nextProjectile);
67 Array.Resize(ref Main.projHostile, nextProjectile);
68 Array.Resize(ref Main.projHook, nextProjectile);
69 Array.Resize(ref Main.projFrames, nextProjectile);
70 Array.Resize(ref Main.projPet, nextProjectile);
71 Array.Resize(ref Lang._projectileNameCache, nextProjectile);
72 Array.Resize(ref ProjectileID.Sets.YoyosLifeTimeMultiplier, nextProjectile);
73 Array.Resize(ref ProjectileID.Sets.YoyosMaximumRange, nextProjectile);
74 Array.Resize(ref ProjectileID.Sets.YoyosTopSpeed, nextProjectile);
75 Array.Resize(ref ProjectileID.Sets.CanDistortWater, nextProjectile);
76 Array.Resize(ref ProjectileID.Sets.MinionShot, nextProjectile);
77 Array.Resize(ref ProjectileID.Sets.SentryShot, nextProjectile);
78 Array.Resize(ref ProjectileID.Sets.ForcePlateDetection, nextProjectile);
79 Array.Resize(ref ProjectileID.Sets.TrailingMode, nextProjectile);
80 Array.Resize(ref ProjectileID.Sets.TrailCacheLength, nextProjectile);
81 Array.Resize(ref ProjectileID.Sets.LightPet, nextProjectile);
82 Array.Resize(ref ProjectileID.Sets.Homing, nextProjectile);
83 Array.Resize(ref ProjectileID.Sets.IsADD2Turret, nextProjectile);
84 Array.Resize(ref ProjectileID.Sets.TurretFeature, 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);
88 Array.Resize(ref ProjectileID.Sets.NeedsUUID, nextProjectile);
89 Array.Resize(ref ProjectileID.Sets.StardustDragon, nextProjectile);
90 Array.Resize(ref ProjectileID.Sets.NoLiquidDistortion, nextProjectile);
91 for (
int k = ProjectileID.Count; k < nextProjectile; k++) {
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);
103 for (
int i = 0; i < nextProjectile; i++) {
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() {
118 nextProjectile = ProjectileID.Count;
119 globalProjectiles.Clear();
120 globalIndexes.Clear();
121 globalIndexesByType.Clear();
124 internal static bool IsModProjectile(Projectile projectile) {
125 return projectile.type >= ProjectileID.Count;
128 private static HookList HookSetDefaults = AddHook<Action<Projectile>>(g => g.SetDefaults);
130 internal static void SetDefaults(Projectile projectile,
bool createModProjectile =
true) {
131 if (IsModProjectile(projectile) && createModProjectile) {
132 projectile.modProjectile = GetProjectile(projectile.type).NewInstance(projectile);
134 projectile.globalProjectiles = InstancedGlobals.Select(g => g.NewInstance(projectile)).ToArray();
135 projectile.modProjectile?.SetDefaults();
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;
167 private static HookList HookPreAI = AddHook<Func<Projectile, bool>>(g => g.
PreAI);
169 public static bool PreAI(Projectile projectile) {
174 if (result && projectile.modProjectile != null) {
175 return projectile.modProjectile.PreAI();
180 private static HookList HookAI = AddHook<Action<Projectile>>(g => g.
AI);
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()) {
252 private delegate
bool DelegateTileCollideStyle(Projectile projectile, ref
int width, ref
int height, ref
bool fallThrough);
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();
302 private static HookList HookPreKill = AddHook<Func<Projectile, int, bool>>(g => g.
PreKill);
304 public static bool PreKill(Projectile projectile,
int timeLeft) {
309 if (result && projectile.modProjectile != null) {
310 return projectile.modProjectile.PreKill(timeLeft);
315 private static HookList HookKill = AddHook<Action<Projectile, int>>(g => g.
Kill);
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()) {
353 private delegate
void DelegateModifyDamageHitbox(Projectile projectile, ref Rectangle hitbox);
357 projectile.modProjectile?.ModifyDamageHitbox(ref hitbox);
363 private static HookList HookCanHitNPC = AddHook<Func<Projectile, NPC, bool?>>(g => g.
CanHitNPC);
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);
399 private static HookList HookOnHitNPC = AddHook<Action<Projectile, NPC, int, float, bool>>(g => g.
OnHitNPC);
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);
409 private static HookList HookCanHitPvp = AddHook<Func<Projectile, Player, bool>>(g => g.
CanHitPvp);
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);
434 private static HookList HookOnHitPvp = AddHook<Action<Projectile, Player, int, bool>>(g => g.
OnHitPvp);
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);
458 private delegate
void DelegateModifyHitPlayer(Projectile projectile, Player target, ref
int damage, ref
bool crit);
461 public static void ModifyHitPlayer(Projectile projectile, Player target, ref
int damage, ref
bool crit) {
462 projectile.modProjectile?.ModifyHitPlayer(target, ref damage, ref crit);
469 private static HookList HookOnHitPlayer = AddHook<Action<Projectile, Player, int, bool>>(g => g.
OnHitPlayer);
471 public static void OnHitPlayer(Projectile projectile, Player target,
int damage,
bool crit) {
472 projectile.modProjectile?.OnHitPlayer(target, damage, crit);
479 private static HookList HookColliding = AddHook<Func<Projectile, Rectangle, Rectangle, bool?>>(g => g.
Colliding);
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;
497 private static HookList HookGetAlpha = AddHook<Func<Projectile, Color, Color?>>(g => g.
GetAlpha);
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);
543 private static HookList HookPostDraw = AddHook<Action<Projectile, SpriteBatch, Color>>(g => g.
PostDraw);
545 public static void PostDraw(Projectile projectile, SpriteBatch spriteBatch, Color lightColor) {
546 projectile.modProjectile?.PostDraw(spriteBatch, lightColor);
556 var flag = GetProjectile(type)?.CanUseGrapple(player);
560 if (canGrapple.HasValue) {
570 bool? flag = GetProjectile(type)?.SingleGrappleHook(player);
574 if (singleHook.HasValue) {
581 private delegate
void DelegateUseGrapple(Player player, ref
int type);
585 GetProjectile(type)?.UseGrapple(player, ref type);
593 return distance > projectile.modProjectile?.GrappleRange();
596 private delegate
void DelegateNumGrappleHooks(Projectile projectile, Player player, ref
int numHooks);
599 public static void NumGrappleHooks(Projectile projectile, Player player, ref
int numHooks) {
600 projectile.modProjectile?.NumGrappleHooks(player, ref numHooks);
607 private delegate
void DelegateGrappleRetreatSpeed(Projectile projectile, Player player, ref
float speed);
611 projectile.modProjectile?.GrappleRetreatSpeed(player, ref speed);
618 private delegate
void DelegateGrapplePullSpeed(Projectile projectile, Player player, ref
float speed);
621 public static void GrapplePullSpeed(Projectile projectile, Player player, ref
float speed) {
622 projectile.modProjectile?.GrapplePullSpeed(player, ref speed);
629 private delegate
void DelegateGrappleTargetPoint(Projectile projectile, Player player, ref
float grappleX, ref
float grappleY);
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");
static void ModifyDamageHitbox(Projectile projectile, ref Rectangle hitbox)
static bool HasMethod(Type t, string method, params Type[] args)
static void PostAI(Projectile projectile)
static void Kill(Projectile projectile, int timeLeft)
static bool CanCutTiles(Projectile projectile)
static bool CanHitPlayer(Projectile projectile, Player target)
virtual void Kill(Projectile projectile, int timeLeft)
Allows you to control what happens when a projectile is killed (for example, creating dust or making ...
static Color GetAlpha(Projectile projectile, Color lightColor)
static bool PreKill(Projectile projectile, int timeLeft)
This serves as the central class from which projectile-related functions are carried out...
static bool AllowVanillaClients
static byte[] SendExtraAI(Projectile projectile, ref BitsByte flags)
static bool GrappleOutOfRange(float distance, Projectile projectile)
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.
static bool MinionContactDamage(Projectile projectile)
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 void OnHitPlayer(Projectile projectile, Player target, int damage, bool crit)
Allows you to create special effects when a hostile projectile hits a player.
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...
GlobalProjectile Instance(Projectile projectile)
static void PostDraw(Projectile projectile, SpriteBatch spriteBatch, Color lightColor)
virtual bool CanCutTiles(Projectile projectile)
Return true or false to specify if the projectile can cut tiles, like vines. Return null for vanilla ...
virtual bool ShouldUpdatePosition(Projectile projectile)
Whether or not the given projectile should update its position based on factors such as its velocity...
This serves as the central class which loads mods. It contains many static fields and methods related...
static ModProjectile GetProjectile(int type)
Gets the ModProjectile instance corresponding to the specified type.
virtual bool CanHitPvp(Projectile projectile, Player target)
Allows you to determine whether a projectile can hit the given opponent player. Return false to block...
static bool ShouldUpdatePosition(Projectile projectile)
virtual bool MinionContactDamage(Projectile projectile)
Whether or not a minion can damage NPCs by touching them. Returns false by default. Note that this will only be used if the projectile is considered a pet.
static byte[] ReadExtraAI(BinaryReader reader, BitsByte flags)
static bool SingleGrappleHook(int type, Player player)
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 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 bool PreDrawExtras(Projectile projectile, SpriteBatch spriteBatch)
Allows you to draw things behind a projectile. Returns false to stop the game from drawing extras tex...
static void AI(Projectile projectile)
static void OnHitPlayer(Projectile projectile, Player target, int damage, bool crit)
static void OnHitPvp(Projectile projectile, Player target, int damage, bool crit)
static void OnHitNPC(Projectile projectile, NPC target, int damage, float knockback, bool crit)
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 void CutTiles(Projectile projectile)
Code ran when the projectile cuts tiles. Only runs if CanCutTiles() returns true. Useful when program...
virtual bool PreAI(Projectile projectile)
Allows you to determine how any projectile behaves. Return false to stop the vanilla AI and the AI ho...
static void ProjectileAI(Projectile projectile)
static bool PreAI(Projectile projectile)
HookList(MethodInfo method)
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...
static void NumGrappleHooks(Projectile projectile, Player player, ref int numHooks)
static bool CanDamage(Projectile projectile)
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...
static bool PreDrawExtras(Projectile projectile, SpriteBatch spriteBatch)
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 void AI(Projectile projectile)
Allows you to determine how any projectile behaves. This will only be called if PreAI returns true...
virtual bool PreKill(Projectile projectile, int timeLeft)
Allows you to determine whether the vanilla code for Kill and the Kill hook will be called...
static void GrappleRetreatSpeed(Projectile projectile, Player player, ref float speed)
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. This method is only called for the owner of the projectile, meaning that in multi-player, projectiles owned by a player call this method on that client, and projectiles owned by the server such as enemy projectiles call this method on the server.
static void UseGrapple(Player player, ref int type)
static bool CanHitPvp(Projectile projectile, Player target)
static bool PreDraw(Projectile projectile, SpriteBatch spriteBatch, Color lightColor)
virtual bool CanDamage(Projectile projectile)
Whether or not the given projectile is capable of killing tiles (such as grass) and damaging NPCs/pla...
static void GrappleTargetPoint(Projectile projectile, Player player, ref float grappleX, ref float grappleY)
static void ModifyHitPvp(Projectile projectile, Player target, ref int damage, ref bool crit)
virtual void PostAI(Projectile projectile)
Allows you to determine how any projectile behaves. This will be called regardless of what PreAI retu...
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...
static void CutTiles(Projectile projectile)
virtual bool OnTileCollide(Projectile projectile, Vector2 oldVelocity)
Allows you to determine what happens when a projectile collides with a tile. OldVelocity is the veloc...
static bool OnTileCollide(Projectile projectile, Vector2 oldVelocity)
static bool CanHitNPC(Projectile projectile, NPC target)
virtual string Name
Stores the name of the mod. This name serves as the mod's identification, and also helps with saving ...
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...
This class serves as a place for you to place all your properties and hooks for each projectile...
static void ModifyHitPlayer(Projectile projectile, Player target, ref int damage, ref bool crit)
static bool TileCollideStyle(Projectile projectile, ref int width, ref int height, ref bool fallThrough)
Mod is an abstract class that you will override. It serves as a central place from which the mod's co...
virtual void ModifyDamageHitbox(Projectile projectile, ref Rectangle hitbox)
Allows you to change the hitbox used by a projectile for damaging players and NPCs.
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. Defaults to 11, but vanilla hooks go up to 24.
static void ModifyHitNPC(Projectile projectile, NPC target, ref int damage, ref float knockback, ref bool crit, ref int hitDirection)
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 CanHitNPC(Projectile projectile, NPC target)
Allows you to determine whether a projectile can hit the given NPC. Return true to allow hitting the ...
readonly MethodInfo method
static void DrawOffset(Projectile projectile, ref int offsetX, ref int offsetY, ref float originX)
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 PreDraw(Projectile projectile, SpriteBatch spriteBatch, Color lightColor)
Allows you to draw things behind a projectile, or to modify the way the projectile is drawn...
static bool CanUseGrapple(int type, Player player)
static void DrawHeldProjInFrontOfHeldItemAndArms(Projectile projectile, ref bool flag)
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...
This class allows you to modify and use hooks for all projectiles, including vanilla projectiles...
virtual void SetDefaults(Projectile projectile)
Allows you to set the properties of any and every projectile that gets created.
static void ReceiveExtraAI(Projectile projectile, byte[] extraAI)
virtual Color GetAlpha(Projectile projectile, Color lightColor)
Allows you to determine the color and transparency in which a projectile is drawn. Return null to use the default color (normally light and buff color). Returns null by default.
static void GrapplePullSpeed(Projectile projectile, Player player, ref float speed)
virtual bool InstancePerEntity
Whether to create a new GlobalProjectile instance for every Projectile that exists. Useful for storing information on a projectile. Defaults to false. Return true if you need to store information (have non-static fields).
static bool Colliding(Projectile projectile, Rectangle projHitbox, Rectangle targetHitbox)
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.