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 System;
using System.IO;
using Terraria;
using Terraria.ID;

namespace SoulHarvest.Common;

public static class ReaperCombatRegistry
{
    // Death is intentionally presented at a boss-weapon scale.  This value only
    // scales the weapon sprite; it must never be reused as an attack-range
    // multiplier.
    public const float DeathWeaponDrawScale = 2.58f;
    public const float DeathPrimaryMaximumTempo = 5f;
    public const float CrescentOuterRadiusRatio = 0.91f;
    public const float StandardCrescentThicknessRatio = 0.455f;
    public const float DeathPrimaryHalfSweep = 2.43f;
    // The 100x160 Death sprite reaches roughly 406 world pixels from its handle
    // at the presentation scale above.  A 447px crescent places its 91% hot rim
    // on that cutting edge while remaining close to the original 430px attack
    // presentation instead of inheriting the weapon's +50% scale.
    public const float DeathPrimaryCrescentRadius = 447f;
    public const float DeathPrimaryBladeReach = DeathPrimaryCrescentRadius
        * CrescentOuterRadiusRatio;
    public const float DeathPrimaryCollisionReach = 430f;

    public static float GetDeathWeaponDrawScale(in SickleCombatSnapshot snapshot)
        => DeathWeaponDrawScale * snapshot.DeathRangeMultiplier;

    public static float GetDeathPrimaryCrescentRadius(in SickleCombatSnapshot snapshot)
        => DeathPrimaryCrescentRadius * snapshot.DeathRangeMultiplier;

    public static float GetDeathPrimaryBladeReach(in SickleCombatSnapshot snapshot)
        => DeathPrimaryBladeReach * snapshot.DeathRangeMultiplier;

    public static float GetDeathPrimaryCollisionReach(in SickleCombatSnapshot snapshot)
        => DeathPrimaryCollisionReach * snapshot.DeathRangeMultiplier;

    public static ReaperFormId ResolveUsableForm(ReaperProgressionState progression)
    {
        ReaperFormId form = progression.CurrentForm;
        if (form == ReaperFormId.Death)
            return progression.DeathFormUnlocked ? form : ReaperFormId.Base;
        if (ReaperDefinitions.IsBranchForm(form))
            return progression.GetStage(form) != ReaperStage.Locked ? form : ReaperFormId.Base;
        return ReaperFormId.Base;
    }

    public static int GetBaseDamage(ReaperFormId form, ReaperStage stage)
    {
        return ReaperDefinitions.GetForm(form).GetBaseDamage(form is ReaperFormId.Base or ReaperFormId.Death
            ? ReaperStage.StageI
            : stage);
    }

    public static int GetUseTime(ReaperFormId form, ReaperStage stage, int phase = 0)
    {
        if (form == ReaperFormId.Death)
            // Every primary beat shares one clock. Phase-dependent use times made
            // auto-reuse alternately wait for the held projectile and then race it,
            // which was perceived as random attack frequency at high tempo.
            return 24;
        return ReaperDefinitions.GetForm(form).BaseUseTime;
    }

    public static int GetPrimaryPhaseCount(ReaperFormId form, ReaperStage stage) => form switch
    {
        ReaperFormId.Base => 2,
        ReaperFormId.Bone => 3,
        ReaperFormId.Blood => stage >= ReaperStage.StageII ? 3 : 2,
        ReaperFormId.Infernal => stage >= ReaperStage.StageIII ? 4 : 3,
        ReaperFormId.Frost => 3,
        ReaperFormId.Soul => 3,
        ReaperFormId.Void => stage >= ReaperStage.StageII ? 4 : 2,
        ReaperFormId.Death => 6,
        _ => 2
    };

    public static float GetPrimaryDamageMultiplier(in SickleCombatSnapshot snapshot, int phase) => snapshot.Form switch
    {
        ReaperFormId.Base => phase == 0 ? 1f : 1.15f,
        ReaperFormId.Bone => phase switch { 0 => 0.9f, 1 => 1f, _ => 1.25f },
        ReaperFormId.Blood => phase switch { 0 => 1f, 1 => 1.1f, _ => 1.35f },
        ReaperFormId.Infernal => snapshot.Stage >= ReaperStage.StageIII
            ? phase switch { 0 => 0.95f, 1 => 1.05f, 2 => 1.15f, _ => 1.55f }
            : phase switch { 0 => 0.95f, 1 => 1.05f, _ => snapshot.Stage >= ReaperStage.StageII ? 1.35f : 1.25f },
        ReaperFormId.Frost => phase switch { 0 => 0.95f, 1 => 1f, _ => 0.62f },
        ReaperFormId.Soul => phase switch { 0 => 0.95f, 1 => 1f, _ => 1.15f },
        ReaperFormId.Void => phase switch { 0 => 1.15f, 1 => 1.2f, _ => 0.8f },
        ReaperFormId.Death => phase switch { 0 => 1.1f, 1 => 1.05f, 2 => 1.15f, 3 => 0.6f, 4 => 1.05f, _ => 1.65f },
        _ => 1f
    };

    public static int GetSpecialCooldown(ReaperFormId form, ReaperStage stage) => form switch
    {
        ReaperFormId.Base => 270,
        ReaperFormId.Bone => stage switch { ReaperStage.StageI => 270, ReaperStage.StageII => 300, _ => 330 },
        ReaperFormId.Blood => stage >= ReaperStage.StageII ? 420 : 360,
        ReaperFormId.Infernal => stage switch { ReaperStage.StageI => 270, ReaperStage.StageII => 330, _ => 420 },
        ReaperFormId.Frost => 270,
        ReaperFormId.Soul => stage switch { ReaperStage.StageI => 300, ReaperStage.StageII => 330, _ => 360 },
        ReaperFormId.Void => stage switch { ReaperStage.StageI => 330, ReaperStage.StageII => 360, _ => 420 },
        ReaperFormId.Death => 480,
        _ => 300
    };

    public static int GetUltimateCooldown(ReaperFormId form) => form switch
    {
        ReaperFormId.Bone => 720,
        ReaperFormId.Blood => 900,
        ReaperFormId.Infernal => 840,
        ReaperFormId.Frost => 840,
        ReaperFormId.Soul => 900,
        ReaperFormId.Void => 960,
        ReaperFormId.Death => 1200,
        _ => 0
    };

    public static Color GetPrimaryColor(ReaperFormId form) => form switch
    {
        ReaperFormId.Bone => new Color(80, 235, 255),
        ReaperFormId.Blood => new Color(235, 45, 80),
        ReaperFormId.Infernal => new Color(255, 125, 25),
        ReaperFormId.Frost => new Color(105, 195, 255),
        ReaperFormId.Soul => new Color(120, 100, 255),
        ReaperFormId.Void => new Color(190, 55, 255),
        ReaperFormId.Death => new Color(235, 35, 65),
        _ => new Color(80, 205, 225)
    };

    public static Color GetSecondaryColor(ReaperFormId form) => form switch
    {
        ReaperFormId.Bone => new Color(235, 245, 220),
        ReaperFormId.Blood => new Color(255, 145, 175),
        ReaperFormId.Infernal => new Color(255, 235, 85),
        ReaperFormId.Frost => new Color(235, 255, 255),
        ReaperFormId.Soul => new Color(75, 245, 255),
        ReaperFormId.Void => new Color(255, 85, 235),
        ReaperFormId.Death => new Color(255, 145, 175),
        _ => new Color(210, 250, 255)
    };

    public static int GetDust(ReaperFormId form) => form switch
    {
        ReaperFormId.Bone => DustID.DungeonSpirit,
        ReaperFormId.Blood => DustID.Blood,
        ReaperFormId.Infernal => DustID.Torch,
        ReaperFormId.Frost => DustID.IceTorch,
        ReaperFormId.Soul => DustID.AncientLight,
        ReaperFormId.Void or ReaperFormId.Death => DustID.Shadowflame,
        _ => DustID.AncientLight
    };

    /// <summary>
    /// Resolves the immutable weapon artwork captured by an action. Branch forms
    /// use one texture per progression stage; base and Death retain their fixed
    /// silhouettes.
    /// </summary>
    public static string GetTexturePath(ReaperFormId form, ReaperStage stage)
    {
        stage = NormalizePresentationStage(form, stage);
        return (form, stage) switch
        {
            (ReaperFormId.Bone, ReaperStage.StageI) => "SoulHarvest/Items/ReaperStages/BoneSickle_StageI",
            (ReaperFormId.Bone, ReaperStage.StageII) => "SoulHarvest/Items/ReaperStages/BoneSickle_StageII",
            (ReaperFormId.Bone, _) => "SoulHarvest/Items/ReaperStages/BoneSickle_StageIII",
            (ReaperFormId.Blood, ReaperStage.StageI) => "SoulHarvest/Items/ReaperStages/BloodSickle_StageI",
            (ReaperFormId.Blood, ReaperStage.StageII) => "SoulHarvest/Items/ReaperStages/BloodSickle_StageII",
            (ReaperFormId.Blood, _) => "SoulHarvest/Items/ReaperStages/BloodSickle_StageIII",
            (ReaperFormId.Infernal, ReaperStage.StageI) => "SoulHarvest/Items/ReaperStages/InfernalSickle_StageI",
            (ReaperFormId.Infernal, ReaperStage.StageII) => "SoulHarvest/Items/ReaperStages/InfernalSickle_StageII",
            (ReaperFormId.Infernal, _) => "SoulHarvest/Items/ReaperStages/InfernalSickle_StageIII",
            (ReaperFormId.Frost, ReaperStage.StageI) => "SoulHarvest/Items/ReaperStages/FrostSickle_StageI",
            (ReaperFormId.Frost, ReaperStage.StageII) => "SoulHarvest/Items/ReaperStages/FrostSickle_StageII",
            (ReaperFormId.Frost, _) => "SoulHarvest/Items/ReaperStages/FrostSickle_StageIII",
            (ReaperFormId.Soul, ReaperStage.StageI) => "SoulHarvest/Items/ReaperStages/SoulSickle_StageI",
            (ReaperFormId.Soul, ReaperStage.StageII) => "SoulHarvest/Items/ReaperStages/SoulSickle_StageII",
            (ReaperFormId.Soul, _) => "SoulHarvest/Items/ReaperStages/SoulSickle_StageIII",
            (ReaperFormId.Void, ReaperStage.StageI) => "SoulHarvest/Items/ReaperStages/VoidSickle_StageI",
            (ReaperFormId.Void, ReaperStage.StageII) => "SoulHarvest/Items/ReaperStages/VoidSickle_StageII",
            (ReaperFormId.Void, _) => "SoulHarvest/Items/ReaperStages/VoidSickle_StageIII",
            (ReaperFormId.Death, _) => "SoulHarvest/Items/DeathSickle",
            _ => "SoulHarvest/Items/NormalSickle"
        };
    }

    public static Vector2 GetHandleAnchor(ReaperFormId form, ReaperStage stage)
    {
        _ = NormalizePresentationStage(form, stage);
        return form switch
        {
            ReaperFormId.Bone => new Vector2(0.25f, 0.94f),
            ReaperFormId.Blood => new Vector2(0.13f, 0.94f),
            ReaperFormId.Infernal or ReaperFormId.Void => new Vector2(0.13f, 0.93f),
            ReaperFormId.Frost => new Vector2(0.18f, 0.93f),
            ReaperFormId.Soul => new Vector2(0.20f, 0.93f),
            ReaperFormId.Death => new Vector2(0.08f, 0.94f),
            _ => new Vector2(0.06f, 0.95f)
        };
    }

    public static float GetTextureRotationCorrection(ReaperFormId form, ReaperStage stage)
    {
        _ = NormalizePresentationStage(form, stage);
        return form switch
        {
            ReaperFormId.Bone => 1.046f,
            ReaperFormId.Blood => 0.824f,
            ReaperFormId.Infernal => 0.695f,
            ReaperFormId.Frost => 0.904f,
            ReaperFormId.Soul => 0.984f,
            ReaperFormId.Void => 0.846f,
            ReaperFormId.Death => 0.72f,
            _ => 0.98f
        };
    }

    public static float GetBladeTipLength(ReaperFormId form, ReaperStage stage)
    {
        _ = NormalizePresentationStage(form, stage);
        return form switch
        {
            ReaperFormId.Bone => 129.7f,
            ReaperFormId.Blood => 131.6f,
            ReaperFormId.Infernal => 119f,
            ReaperFormId.Frost => 112.2f,
            ReaperFormId.Soul => 124.6f,
            ReaperFormId.Void => 137.8f,
            ReaperFormId.Death => 230f,
            _ => 157.4f
        };
    }

    private static ReaperStage NormalizePresentationStage(ReaperFormId form, ReaperStage stage)
    {
        if (form == ReaperFormId.Death)
            return ReaperStage.StageIII;
        if (!ReaperDefinitions.IsBranchForm(form))
            return ReaperStage.StageI;
        return stage switch
        {
            ReaperStage.StageII => ReaperStage.StageII,
            ReaperStage.StageIII => ReaperStage.StageIII,
            _ => ReaperStage.StageI
        };
    }

    public static float GetReach(in SickleCombatSnapshot snapshot)
    {
        if (snapshot.Form == ReaperFormId.Void)
            return GetBladeTipLength(snapshot.Form, snapshot.Stage)
                * (snapshot.Skill1 switch { 2 => 1.08f, >= 3 => 1.14f, _ => 1.03f });
        return snapshot.Form == ReaperFormId.Death ? 190f : 112f + snapshot.StageNumber * 10f;
    }

    public static float GetCollisionWidth(in SickleCombatSnapshot snapshot)
    {
        if (snapshot.Form == ReaperFormId.Void)
            return snapshot.Skill1 switch { 1 => 18f, 2 => 22f, >= 3 => 26f, _ => 18f };
        return 18f + snapshot.StageNumber * 3f;
    }
}