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 SoulHarvest.Items;
using SoulHarvest.Tiles;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using Terraria;
using Terraria.Audio;
using Terraria.GameContent;
using Terraria.GameContent.UI.Elements;
using Terraria.ID;
using Terraria.Localization;
using Terraria.ModLoader;
using Terraria.UI;

namespace SoulHarvest.UI;

internal sealed class AltarRecipeEntry : UIElement
{
    private readonly Item result;
    private readonly List<Item> ingredients = [];
    private readonly List<int> requiredTiles = [];
    private readonly float layoutScale;
    private readonly int ingredientColumns;
    private readonly int ingredientRows;

    public AltarRecipeEntry(Recipe recipe, float layoutScale)
    {
        this.layoutScale = layoutScale;
        result = recipe.createItem.Clone();
        foreach (Item ingredient in recipe.requiredItem)
            if (!ingredient.IsAir)
                ingredients.Add(ingredient.Clone());
        requiredTiles.AddRange(recipe.requiredTile);
        ingredientColumns = Math.Max(1, Math.Min(4, ingredients.Count));
        ingredientRows = Math.Max(1, (ingredients.Count + ingredientColumns - 1) / ingredientColumns);
        Width.Set(0f, 1f);
        Height.Set(Math.Max(104f, 64f + ingredientRows * 44f) * layoutScale, 0f);
    }

    protected override void DrawSelf(SpriteBatch spriteBatch)
    {
        Rectangle bounds = GetDimensions().ToRectangle();
        Texture2D pixel = TextureAssets.MagicPixel.Value;
        Color background = IsMouseHovering ? new Color(42, 35, 63) : new Color(29, 24, 47);
        spriteBatch.Draw(pixel, bounds, background * 0.97f);
        AltarDrawHelpers.DrawBorder(spriteBatch, pixel, bounds, new Color(91, 69, 123), Math.Max(1, (int)MathF.Round(2f * layoutScale)));
        spriteBatch.Draw(pixel, new Rectangle(bounds.X, bounds.Y, Math.Max(2, (int)MathF.Round(3f * layoutScale)), bounds.Height), new Color(127, 69, 166));

        Vector2 resultCenter = new(bounds.X + 34f * layoutScale, bounds.Y + 40f * layoutScale);
        AltarDrawHelpers.DrawItemSlot(spriteBatch, pixel, resultCenter, 48f * layoutScale, new Color(51, 35, 70), new Color(117, 73, 147));
        AltarDrawHelpers.DrawItemIcon(spriteBatch, result, resultCenter, 40f * layoutScale);
        string resultName = AltarDrawHelpers.FitText(result.Name, 118f * layoutScale, 0.68f * layoutScale);
        Utils.DrawBorderString(
            spriteBatch,
            resultName,
            new Vector2(bounds.X + 62f * layoutScale, bounds.Y + 16f * layoutScale),
            new Color(235, 220, 255),
            0.68f * layoutScale);
        if (result.stack > 1)
            Utils.DrawBorderString(spriteBatch, $"×{result.stack}", new Vector2(bounds.X + 62f * layoutScale, bounds.Y + 43f * layoutScale), Color.White, 0.62f * layoutScale);

        int dividerX = bounds.X + (int)MathF.Round(176f * layoutScale);
        spriteBatch.Draw(pixel, new Rectangle(dividerX, bounds.Y + (int)MathF.Round(10f * layoutScale), Math.Max(1, (int)MathF.Round(layoutScale)), bounds.Height - (int)MathF.Round(38f * layoutScale)), new Color(83, 60, 108) * 0.72f);

        float ingredientsLeft = bounds.X + 188f * layoutScale;
        float ingredientsWidth = Math.Max(1f, bounds.Right - 8f * layoutScale - ingredientsLeft);
        float cellWidth = ingredientsWidth / ingredientColumns;
        for (int index = 0; index < ingredients.Count; index++)
        {
            Item ingredient = ingredients[index];
            int column = index % ingredientColumns;
            int row = index / ingredientColumns;
            float centerX = ingredientsLeft + cellWidth * (column + 0.5f);
            float centerY = bounds.Y + (ingredientRows == 1 ? 34f : 27f + row * 44f) * layoutScale;
            Vector2 iconCenter = new(centerX, centerY);
            AltarDrawHelpers.DrawItemSlot(spriteBatch, pixel, iconCenter, 39f * layoutScale, new Color(37, 31, 53), new Color(82, 66, 104));
            AltarDrawHelpers.DrawItemIcon(spriteBatch, ingredient, iconCenter, 31f * layoutScale);
            string amount = ingredient.stack > 1 ? $"×{ingredient.stack}" : string.Empty;
            if (ingredientRows == 1)
            {
                string ingredientText = AltarDrawHelpers.FitText(ingredient.Name + (amount.Length > 0 ? $" {amount}" : string.Empty), Math.Max(40f * layoutScale, cellWidth - 4f * layoutScale), 0.55f * layoutScale);
                Vector2 textSize = FontAssets.MouseText.Value.MeasureString(ingredientText) * (0.55f * layoutScale);
                Utils.DrawBorderString(spriteBatch, ingredientText, new Vector2(centerX - textSize.X * 0.5f, bounds.Y + 58f * layoutScale), Color.White, 0.55f * layoutScale);
            }
            else if (amount.Length > 0)
            {
                Vector2 amountSize = FontAssets.MouseText.Value.MeasureString(amount) * (0.48f * layoutScale);
                Utils.DrawBorderString(spriteBatch, amount, iconCenter + new Vector2(17f, 14f) * layoutScale - amountSize, Color.White, 0.48f * layoutScale);
            }

            int hitboxSize = Math.Max(1, (int)MathF.Round(42f * layoutScale));
            Rectangle iconHitbox = new((int)(iconCenter.X - hitboxSize * 0.5f), (int)(iconCenter.Y - hitboxSize * 0.5f), hitboxSize, hitboxSize);
            if (iconHitbox.Contains(Main.MouseScreen.ToPoint()))
                Main.instance.MouseText($"{ingredient.Name}{(amount.Length > 0 ? $" {amount}" : string.Empty)}");
        }

        string station = GetCraftingStationText();
        Utils.DrawBorderString(
            spriteBatch,
            Language.GetTextValue("Mods.SoulHarvest.UI.RecipeCraftingStation", station),
            new Vector2(bounds.X + 12f * layoutScale, bounds.Bottom - 24f * layoutScale),
            new Color(137, 211, 225),
            0.58f * layoutScale);

        float resultHitboxSize = 52f * layoutScale;
        Rectangle resultHitbox = new((int)(resultCenter.X - resultHitboxSize * 0.5f), (int)(resultCenter.Y - resultHitboxSize * 0.5f), (int)resultHitboxSize, (int)resultHitboxSize);
        if (resultHitbox.Contains(Main.MouseScreen.ToPoint()) && resultName != result.Name)
            Main.instance.MouseText(result.Name);
    }

    private string GetCraftingStationText()
    {
        if (requiredTiles.Count == 0)
            return Language.GetTextValue("Mods.SoulHarvest.UI.RecipeStationByHand");

        List<string> names = [];
        foreach (int tileType in requiredTiles)
        {
            string name = tileType switch
            {
                TileID.WorkBenches => Language.GetTextValue("Mods.SoulHarvest.UI.RecipeStationWorkbench"),
                TileID.Anvils => Language.GetTextValue("Mods.SoulHarvest.UI.RecipeStationAnvil"),
                _ when tileType == ModContent.TileType<DeathAltarTile>() => Language.GetTextValue("Mods.SoulHarvest.UI.RecipeStationDeathAltar"),
                _ => Language.GetTextValue("Mods.SoulHarvest.UI.RecipeStationUnknown", tileType)
            };
            if (!names.Contains(name))
                names.Add(name);
        }
        return string.Join(" / ", names);
    }

}