using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
namespace SoulHarvest.Projectiles;
public class DeathSickleProjectile : ModProjectile
{
private bool serverAuthorized;
private Vector2 authoritativeCenter;
private Vector2 authoritativeVelocity;
internal void AuthorizeServerMotion()
{
if (Main.netMode == NetmodeID.MultiplayerClient)
return;
serverAuthorized = true;
authoritativeCenter = Projectile.Center;
authoritativeVelocity = Projectile.velocity;
}
public override void SetDefaults()
{
Projectile.friendly = true;
Projectile.hostile = false;
Projectile.width = 56;
Projectile.height = 56;
Projectile.tileCollide = false;
Projectile.penetrate = -1;
Projectile.ignoreWater = true;
Projectile.timeLeft = 480;
Projectile.light = 0.8f;
Projectile.localNPCHitCooldown = 15;
Projectile.usesLocalNPCImmunity = true;
}
public override bool ShouldUpdatePosition() => false;
public override void AI()
{
if (Main.netMode == NetmodeID.Server)
{
if (!serverAuthorized)
{
Projectile.Kill();
return;
}
Projectile.Center = authoritativeCenter;
Projectile.velocity = authoritativeVelocity;
}
Projectile.localAI[0]++;
if (Projectile.localAI[0] >= 480f)
{
Projectile.Kill();
return;
}
Projectile.rotation += 0.48f;
if (Main.netMode != NetmodeID.Server)
{
Dust blood = Dust.NewDustDirect(Projectile.position, Projectile.width, Projectile.height, DustID.Blood, Scale: 1.1f);
blood.noGravity = true;
blood.velocity *= 0.2f;
if (Main.rand.NextBool(2))
{
Dust soul = Dust.NewDustDirect(Projectile.position, Projectile.width, Projectile.height, DustID.AncientLight, Scale: 0.85f);
soul.noGravity = true;
soul.velocity *= 0.1f;
}
}
NPC? target = FindTarget(700f);
if (target is not null)
{
float speed = Projectile.velocity.Length();
float curve = MathHelper.ToRadians(18f) * (float)System.Math.Sin(Projectile.localAI[0] * 0.09f);
Vector2 desiredVelocity = (target.Center - Projectile.Center).SafeNormalize(Vector2.UnitX).RotatedBy(curve) * speed;
Projectile.velocity = Vector2.Lerp(Projectile.velocity, desiredVelocity, 0.09f);
}
Projectile.position += Projectile.velocity;
if (Main.netMode == NetmodeID.Server)
{
authoritativeCenter = Projectile.Center;
authoritativeVelocity = Projectile.velocity;
}
}
private NPC? FindTarget(float maximumDistance)
{
NPC? target = null;
foreach (NPC npc in Main.ActiveNPCs)
{
if (!npc.CanBeChasedBy(Projectile))
continue;
float distance = Vector2.Distance(npc.Center, Projectile.Center);
if (distance < maximumDistance)
{
maximumDistance = distance;
target = npc;
}
}
return target;
}
}
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
namespace SoulHarvest.Projectiles;
public class DeathSickleProjectile : ModProjectile
{
private bool serverAuthorized;
private Vector2 authoritativeCenter;
private Vector2 authoritativeVelocity;
internal void AuthorizeServerMotion()
{
if (Main.netMode == NetmodeID.MultiplayerClient)
return;
serverAuthorized = true;
authoritativeCenter = Projectile.Center;
authoritativeVelocity = Projectile.velocity;
}
public override void SetDefaults()
{
Projectile.friendly = true;
Projectile.hostile = false;
Projectile.width = 56;
Projectile.height = 56;
Projectile.tileCollide = false;
Projectile.penetrate = -1;
Projectile.ignoreWater = true;
Projectile.timeLeft = 480;
Projectile.light = 0.8f;
Projectile.localNPCHitCooldown = 15;
Projectile.usesLocalNPCImmunity = true;
}
public override bool ShouldUpdatePosition() => false;
public override void AI()
{
if (Main.netMode == NetmodeID.Server)
{
if (!serverAuthorized)
{
Projectile.Kill();
return;
}
Projectile.Center = authoritativeCenter;
Projectile.velocity = authoritativeVelocity;
}
Projectile.localAI[0]++;
if (Projectile.localAI[0] >= 480f)
{
Projectile.Kill();
return;
}
Projectile.rotation += 0.48f;
if (Main.netMode != NetmodeID.Server)
{
Dust blood = Dust.NewDustDirect(Projectile.position, Projectile.width, Projectile.height, DustID.Blood, Scale: 1.1f);
blood.noGravity = true;
blood.velocity *= 0.2f;
if (Main.rand.NextBool(2))
{
Dust soul = Dust.NewDustDirect(Projectile.position, Projectile.width, Projectile.height, DustID.AncientLight, Scale: 0.85f);
soul.noGravity = true;
soul.velocity *= 0.1f;
}
}
NPC? target = FindTarget(700f);
if (target is not null)
{
float speed = Projectile.velocity.Length();
float curve = MathHelper.ToRadians(18f) * (float)System.Math.Sin(Projectile.localAI[0] * 0.09f);
Vector2 desiredVelocity = (target.Center - Projectile.Center).SafeNormalize(Vector2.UnitX).RotatedBy(curve) * speed;
Projectile.velocity = Vector2.Lerp(Projectile.velocity, desiredVelocity, 0.09f);
}
Projectile.position += Projectile.velocity;
if (Main.netMode == NetmodeID.Server)
{
authoritativeCenter = Projectile.Center;
authoritativeVelocity = Projectile.velocity;
}
}
private NPC? FindTarget(float maximumDistance)
{
NPC? target = null;
foreach (NPC npc in Main.ActiveNPCs)
{
if (!npc.CanBeChasedBy(Projectile))
continue;
float distance = Vector2.Distance(npc.Center, Projectile.Center);
if (distance < maximumDistance)
{
maximumDistance = distance;
target = npc;
}
}
return target;
}
}