using SoulHarvest.Common; using SoulHarvest.Items; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using ReLogic.Content; using System; using System.Collections.Generic; using System.Text; using Terraria; using Terraria.Audio; using Terraria.GameContent; using Terraria.GameContent.UI.Elements; using Terraria.GameInput; using Terraria.ID; using Terraria.Localization; using Terraria.ModLoader; using Terraria.UI; namespace SoulHarvest.UI; internal sealed class ReaperTreeDetailPanel : UIElement { private readonly ReaperTreeButton upgradeButton; private ReaperTreeNodeModel? node; private float layoutScale = 1f; public ReaperTreeDetailPanel(ReaperProgressionPanel owner) { SetPadding(0f); upgradeButton = new ReaperTreeButton(owner.RequestSelectedUpgrade, new Color(87, 25, 29), new Color(137, 32, 36), new Color(231, 69, 70)); Append(upgradeButton); } public void ApplyLayoutScale(float scale) { layoutScale = scale; upgradeButton.Left.Set(12f * scale, 0f); upgradeButton.Top.Set(-50f * scale, 1f); upgradeButton.Width.Set(-24f * scale, 1f); upgradeButton.Height.Set(38f * scale, 0f); upgradeButton.ApplyLayoutScale(scale, 0.68f); } public void SetNode(ReaperTreeNodeModel selected) => node = selected; public void RefreshActionState() { if (node is null) { upgradeButton.Enabled = false; upgradeButton.SetText(Language.GetTextValue("Mods.SoulHarvest.UI.ReaperTree.SelectNodeButton")); return; } upgradeButton.Enabled = node.CanRequest && node.Affordable; string key = node.Completed ? "CompleteButton" : !node.CanRequest || !node.Affordable ? "LockedButton" : node.Kind == ReaperTreeNodeKind.Stage ? "IlluminateButton" : "UpgradeButton"; upgradeButton.SetText(Language.GetTextValue($"Mods.SoulHarvest.UI.ReaperTree.{key}")); } protected override void DrawSelf(SpriteBatch spriteBatch) { Rectangle bounds = GetDimensions().ToRectangle(); Texture2D pixel = TextureAssets.MagicPixel.Value; spriteBatch.Draw(pixel, bounds, new Color(13, 12, 15) * 0.99f); ReaperTreeDraw.DrawBorder(spriteBatch, pixel, bounds, new Color(72, 64, 60), Math.Max(1, (int)(2f * layoutScale))); ReaperTreeDraw.DrawInsetBorder(spriteBatch, pixel, bounds, Math.Max(3, (int)(6f * layoutScale)), new Color(126, 41, 47) * 0.66f, 1); if (node is null) return; Color color = node.Kind == ReaperTreeNodeKind.Common ? new Color(203, 197, 176) : ReaperUIData.GetPrimaryColor(node.Form); float categoryScale = 0.5f * layoutScale; string category = AltarDrawHelpers.FitText(node.Category, bounds.Width - 28f * layoutScale, categoryScale); Utils.DrawBorderString(spriteBatch, category, new Vector2(bounds.X + 14f * layoutScale, bounds.Y + 14f * layoutScale), color * 0.86f, categoryScale); Vector2 iconCenter = new(bounds.X + 38f * layoutScale, bounds.Y + 68f * layoutScale); ReaperTreeDraw.DrawDiamond(spriteBatch, pixel, iconCenter, 26f * layoutScale, new Color(7, 7, 9)); ReaperTreeDraw.DrawDiamondOutline(spriteBatch, pixel, iconCenter, 28f * layoutScale, color * 0.72f, Math.Max(1f, 2f * layoutScale)); Texture2D formTexture = ReaperUIData.GetFormTexture(node.Form); Rectangle frame = formTexture.Frame(); float iconScale = Math.Min(1f, 43f * layoutScale / Math.Max(frame.Width, frame.Height)); spriteBatch.Draw(formTexture, iconCenter, frame, node.Lit || node.Kind == ReaperTreeNodeKind.Base ? Color.White : new Color(102, 97, 98), 0f, frame.Size() * 0.5f, iconScale, SpriteEffects.None, 0f); float titleScale = 0.68f * layoutScale; float titleLeft = bounds.X + 70f * layoutScale; string title = AltarDrawHelpers.FitText(node.Title, Math.Max(10f, bounds.Right - titleLeft - 15f * layoutScale), titleScale); Utils.DrawBorderString(spriteBatch, title, new Vector2(titleLeft, bounds.Y + 48f * layoutScale), new Color(239, 226, 209), titleScale); DrawLevels(spriteBatch, pixel, node, new Vector2(titleLeft + 3f * layoutScale, bounds.Y + 91f * layoutScale), color); int dividerY = bounds.Y + (int)(118f * layoutScale); spriteBatch.Draw(pixel, new Rectangle(bounds.X + (int)(14f * layoutScale), dividerY, bounds.Width - (int)(28f * layoutScale), Math.Max(1, (int)layoutScale)), new Color(103, 90, 82) * 0.52f); float textScale = 0.54f * layoutScale; float textLeft = bounds.X + 15f * layoutScale; float textWidth = bounds.Width - 30f * layoutScale; int availableLines = Math.Max(2, (int)((bounds.Height - 268f * layoutScale) / (17f * layoutScale))); ReaperTreeDraw.DrawWrappedText(spriteBatch, node.Description, new Vector2(textLeft, bounds.Y + 134f * layoutScale), textWidth, textScale, new Color(187, 178, 169), availableLines); int statusTop = Math.Max((int)(bounds.Y + 270f * layoutScale), (int)(bounds.Bottom - 151f * layoutScale)); spriteBatch.Draw(pixel, new Rectangle(bounds.X + (int)(14f * layoutScale), statusTop, bounds.Width - (int)(28f * layoutScale), Math.Max(1, (int)layoutScale)), new Color(103, 90, 82) * 0.52f); string statusLabel = Language.GetTextValue("Mods.SoulHarvest.UI.ReaperTree.StatusLabel", node.Status); ReaperTreeDraw.DrawWrappedText(spriteBatch, statusLabel, new Vector2(textLeft, statusTop + 13f * layoutScale), textWidth, 0.55f * layoutScale, node.CanRequest && node.Affordable ? color : new Color(211, 172, 164), 2); if (!string.IsNullOrWhiteSpace(node.Cost)) ReaperTreeDraw.DrawWrappedText(spriteBatch, node.Cost, new Vector2(textLeft, statusTop + 47f * layoutScale), textWidth, 0.49f * layoutScale, new Color(161, 151, 143), 3); } private void DrawLevels(SpriteBatch batch, Texture2D pixel, ReaperTreeNodeModel selected, Vector2 start, Color color) { if ((selected.Kind is ReaperTreeNodeKind.Common or ReaperTreeNodeKind.DeathUpgrade) && ReaperDefinitions.IsUnlimitedCommonNode(selected.CommonNode)) { const int shownLevels = 8; int filledLevels = selected.CurrentLevel == 0 ? 0 : (selected.CurrentLevel - 1) % shownLevels + 1; float cycleSpacing = 12f * layoutScale; for (int level = 0; level < shownLevels; level++) { bool filled = level < filledLevels; ReaperTreeDraw.DrawDiamond(batch, pixel, start + new Vector2(level * cycleSpacing, 0f), (filled ? 4.5f : 3.7f) * layoutScale, filled ? color : new Color(55, 51, 51)); } Utils.DrawBorderString(batch, $"∞ Lv.{selected.CurrentLevel}", start + new Vector2((shownLevels + 0.2f) * cycleSpacing, -8f * layoutScale), color, 0.52f * layoutScale); return; } int maximum = Math.Max(1, selected.MaximumLevel); float spacing = Math.Min(15f * layoutScale, Math.Max(30f * layoutScale, GetDimensions().Width - 90f * layoutScale) / maximum); for (int level = 0; level < maximum; level++) { bool filled = level < selected.CurrentLevel; ReaperTreeDraw.DrawDiamond(batch, pixel, start + new Vector2(level * spacing, 0f), (filled ? 4.5f : 3.7f) * layoutScale, filled ? color : new Color(55, 51, 51)); } } }