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

DeathMod

【Terraria】DeathMod (now aka Soul Harvest)

公开
关注 0 Fork 0 Star 0
UTF-8
using SoulHarvest.Common;
using Microsoft.Xna.Framework;
using System;
using System.IO;
using Terraria;
using Terraria.DataStructures;
using Terraria.ID;
using Terraria.ModLoader;

namespace SoulHarvest.Projectiles;

/// <summary>
/// The thin crimson cut lines placed on every enemy awaiting the next domain harvest.
/// Their deterministic rotations are reused by the actual blades so each execution
/// lands exactly on its own warning line.
/// </summary>
public class DeathDomainHarvestTelegraphProjectile : ModProjectile
{
    private int TargetIndex => (int)Projectile.ai[0];
    private int TelegraphFrames => Math.Clamp((int)Projectile.ai[1], 1, 180);
    private int SlashCount => Math.Clamp((int)Projectile.ai[2], 1, 5);
    private float Mastery => MathHelper.Clamp((Projectile.ai[2] - SlashCount) * 10f, 0f, 1f);

    public override string Texture => "Terraria/Images/Projectile_0";

    public override void SetStaticDefaults()
    {
        ProjectileID.Sets.DrawScreenCheckFluff[Type] = 3600;
    }

    public override void SetDefaults()
    {
        Projectile.width = 2;
        Projectile.height = 2;
        Projectile.friendly = false;
        Projectile.hostile = false;
        Projectile.tileCollide = false;
        Projectile.ignoreWater = true;
        Projectile.penetrate = -1;
        Projectile.timeLeft = 120;
        Projectile.netImportant = false;
    }

    public override void OnSpawn(IEntitySource source)
    {
        Projectile.timeLeft = TelegraphFrames + 6;
    }

    public override bool? CanDamage() => false;

    public override void SendExtraAI(BinaryWriter writer)
    {
        writer.Write(Projectile.rotation);
        writer.Write(Projectile.scale);
    }

    public override void ReceiveExtraAI(BinaryReader reader)
    {
        Projectile.rotation = reader.ReadSingle();
        Projectile.scale = reader.ReadSingle();
    }

    public override void AI()
    {
        if (TargetIndex >= 0 && TargetIndex < Main.maxNPCs && Main.npc[TargetIndex].active)
            Projectile.Center = Main.npc[TargetIndex].Center;

        if (Main.dedServ || !Main.rand.NextBool(18))
            return;

        int slash = Main.rand.Next(SlashCount);
        float rotation = DeathDomainHarvestSlashProjectile.GetSlashRotation(Projectile.rotation, slash);
        float halfLength = DeathDomainHarvestSlashProjectile.GetSlashLength(Mastery, Projectile.scale, slash) * 0.5f;
        Vector2 direction = rotation.ToRotationVector2();
        Vector2 end = Projectile.Center + direction * (Main.rand.NextBool() ? halfLength : -halfLength);
        Dust dust = Dust.NewDustPerfect(
            end,
            DustID.RedTorch,
            direction.RotatedByRandom(0.45f) * Main.rand.NextFloat(0.25f, 1.2f),
            95,
            new Color(255, 15, 50),
            Main.rand.NextFloat(0.45f, 0.8f));
        dust.noGravity = true;
    }

    public override bool PreDraw(ref Color lightColor)
    {
        float remaining = MathHelper.Clamp((Projectile.timeLeft - 5f) / Math.Max(1f, TelegraphFrames), 0f, 1f);
        float urgency = 1f - remaining;
        float pulse = 0.72f + (float)Math.Sin(Main.GlobalTimeWrappedHourly * (7f + urgency * 9f) + Projectile.identity) * 0.20f;
        Vector2 center = Projectile.Center - Main.screenPosition;

        for (int slash = 0; slash < SlashCount; slash++)
        {
            float rotation = DeathDomainHarvestSlashProjectile.GetSlashRotation(Projectile.rotation, slash);
            float length = DeathDomainHarvestSlashProjectile.GetSlashLength(Mastery, Projectile.scale, slash);
            float linePulse = pulse * (0.90f + 0.10f * (float)Math.Sin(slash * 1.9f + Main.GlobalTimeWrappedHourly * 3f));
            DrawTaperedLine(center, rotation, length, (6f + Mastery * 2f) * Projectile.scale,
                new Color(120, 0, 25, 0) * (0.24f + urgency * 0.22f));
            DrawTaperedLine(center, rotation, length, (1.35f + urgency * 0.85f) * Projectile.scale,
                new Color(255, 8, 48, 0) * linePulse);
        }
        return false;
    }

    private static void DrawTaperedLine(Vector2 center, float rotation, float length, float maximumWidth, Color color)
    {
        Vector2 start = center - rotation.ToRotationVector2() * length * 0.5f;
        DeathDomainPrimitiveTextureSystem.DrawBlade(start, rotation, length, maximumWidth, color);
    }
}