XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

DeathMod

【Terraria】DeathMod (now aka Soul Harvest)

公开
关注 0 Fork 0 Star 0
UTF-8
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;

namespace SoulHarvest.Projectiles;

public class BloodCrescentProjectile : ModProjectile
{
    private bool serverAuthorized;
    private Vector2 authoritativeCenter;
    private Vector2 authoritativeVelocity;
    private readonly float[] authoritativeAI = new float[3];

    internal void AuthorizeServerMotion()
    {
        if (Main.netMode == NetmodeID.MultiplayerClient)
            return;
        serverAuthorized = true;
        authoritativeCenter = Projectile.Center;
        authoritativeVelocity = Projectile.velocity;
        for (int index = 0; index < authoritativeAI.Length; index++)
            authoritativeAI[index] = float.IsFinite(Projectile.ai[index]) ? Projectile.ai[index] : 0f;
    }

    public override void SetStaticDefaults()
    {
        ProjectileID.Sets.TrailCacheLength[Type] = 12;
        ProjectileID.Sets.TrailingMode[Type] = 2;
    }

    public override void SetDefaults()
    {
        Projectile.width = 34;
        Projectile.height = 34;
        Projectile.friendly = true;
        Projectile.tileCollide = false;
        Projectile.ignoreWater = true;
        Projectile.penetrate = 4;
        Projectile.timeLeft = 210;
        Projectile.DamageType = DamageClass.Melee;
    }

    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;
            for (int index = 0; index < authoritativeAI.Length; index++)
                Projectile.ai[index] = authoritativeAI[index];
        }
        Projectile.localAI[0]++;
        float timer = Projectile.localAI[0];
        if (timer >= 210f)
        {
            Projectile.Kill();
            return;
        }
        Player owner = Main.player[Projectile.owner];
        if (!owner.active || owner.dead)
        {
            Projectile.Kill();
            return;
        }
        float outboundTime = Projectile.ai[0] > 0f ? 52f : 34f;
        if (timer < outboundTime)
            Projectile.velocity = Projectile.velocity.RotatedBy(0.008f * System.Math.Sign(Projectile.ai[2] == 0f ? 1f : Projectile.ai[2]));
        else
        {
            Vector2 toOwner = owner.Center - Projectile.Center;
            float returnSpeed = 13f + Projectile.ai[1] * 5f;
            Projectile.velocity = Vector2.Lerp(Projectile.velocity, toOwner.SafeNormalize(Vector2.UnitY) * returnSpeed, 0.11f);
            if (timer > outboundTime + 12f && toOwner.LengthSquared() < 24f * 24f)
                Projectile.Kill();
        }
        Projectile.rotation += 0.34f * System.Math.Sign(Projectile.velocity.X);
        if (Main.netMode != NetmodeID.Server)
        {
            Lighting.AddLight(Projectile.Center, new Vector3(0.55f, 0.03f, 0.08f));
            if (Main.rand.NextBool(2))
            {
                Dust dust = Dust.NewDustPerfect(Projectile.Center, DustID.Blood, -Projectile.velocity * 0.1f, 70,
                    new Color(240, 35, 65), 0.85f + Projectile.ai[1] * 0.25f);
                dust.noGravity = true;
            }
        }
        if (!Projectile.active)
            return;
        Projectile.position += Projectile.velocity;
        if (Main.netMode == NetmodeID.Server)
        {
            authoritativeCenter = Projectile.Center;
            authoritativeVelocity = Projectile.velocity;
        }
    }

    public override void OnHitNPC(NPC target, NPC.HitInfo hit, int damageDone)
    {
        Projectile.velocity = Projectile.velocity.RotatedByRandom(0.35f) * 0.92f;
        if (Main.netMode == NetmodeID.Server)
        {
            authoritativeCenter = Projectile.Center;
            authoritativeVelocity = Projectile.velocity;
        }
    }

    public override bool PreDraw(ref Color lightColor) => ReaperProjectileHelper.DrawTrail(Projectile, new Color(245, 25, 70), scaleMultiplier: 1f + Projectile.ai[1] * 0.18f, copies: 10);
}