diff --git a/SpaceCore/Patches/SkillBuffPatcher.cs b/SpaceCore/Patches/SkillBuffPatcher.cs index ccdeeee8..36c812ea 100644 --- a/SpaceCore/Patches/SkillBuffPatcher.cs +++ b/SpaceCore/Patches/SkillBuffPatcher.cs @@ -1,9 +1,10 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using System.Reflection.Emit; using System.Text; -using HarmonyLib; +using HarmonyLib; // el diavolo nuevo using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Spacechase.Shared.Patching; @@ -12,7 +13,6 @@ using StardewValley; using StardewValley.GameData.Objects; using StardewValley.Menus; -using static System.Net.Mime.MediaTypeNames; using static SpaceCore.Skills; namespace SpaceCore.Patches; @@ -51,10 +51,7 @@ data.Buffs is null || // If there is custom data, find the matching buff to wrap. foreach ( var buffData in data.Buffs ) { - if (buffData.CustomFields?.Any(b => b.Key.StartsWith("spacechase.SpaceCore.SkillBuff.") || - b.Key.StartsWith("spacechase0.SpaceCore.SkillBuff.") || - b.Key.StartsWith("spacechase0.SpaceCore/HealthRegeneration") || - b.Key.StartsWith("spacechase0.SpaceCore/StaminaRegeneration") ) ?? false) + if (SkillBuff.TryGetAdditionalBuffEffects(buffData.CustomFields, out var skills, out float health, out float stamina)) { Buff matchingBuff = null; string id = buffData.BuffId; @@ -113,62 +110,118 @@ private static IEnumerable After_BuffsDisplay_GetClic continue; } - StringBuilder sb = new StringBuilder(); - sb.Append("+"); - sb.Append(skillLevel.Value); - sb.Append(" "); - sb.Append(skill.GetName()); - sb.Append("\n"); - sb.Append(Game1.content.LoadString("Strings\\StringsFromCSFiles:Buff.cs.508")); + StringBuilder sb = new(); + sb.Append(SkillBuff.FormattedBuffEffect(skillLevel.Value, skillLevel.Key)); + sb.AppendLine(); + sb.Append(Game1.content.LoadString("Strings/StringsFromCSFiles:Buff.cs.508")); sb.Append(buff.displaySource ?? buff.source); yield return new ClickableTextureComponent("", Rectangle.Empty, null, sb.ToString(), skill.Icon, new Rectangle(0, 0, 16, 16), 4f); } } - private static IEnumerable Transpile_IClickableMenu_DrawHoverText(IEnumerable instructions) + private static IEnumerable Transpile_IClickableMenu_DrawHoverText(ILGenerator gen, MethodBase original, IEnumerable il) { - List codeInstructions = new List(instructions); - int step = 0; - yield return codeInstructions[0]; - for (int i = 1; i < codeInstructions.Count; i++) - { - if (!codeInstructions[i - 1].Is(OpCodes.Ldarg_S, 8) || (!(codeInstructions[i].opcode == OpCodes.Brfalse_S) && !(codeInstructions[i].opcode == OpCodes.Brfalse))) - { - yield return codeInstructions[i]; - continue; - } + var matcher = new CodeMatcher(il); - if (step == 0) - { - yield return new CodeInstruction(OpCodes.Ldarg_S, 8); - yield return new CodeInstruction(OpCodes.Ldarg_S, 9); - yield return new CodeInstruction(OpCodes.Ldloc_2); - yield return CodeInstruction.Call(typeof(SkillBuffPatcher), nameof(GetHeightAdjustment)); - yield return new CodeInstruction(OpCodes.Stloc_2); - } - else if (step == 1) - { - yield return new CodeInstruction(OpCodes.Ldarg_S, 2); - yield return new CodeInstruction(OpCodes.Ldarg_S, 9); - yield return new CodeInstruction(OpCodes.Ldloc_1); - yield return CodeInstruction.Call(typeof(SkillBuffPatcher), nameof(GetWidthAdjustment)); - yield return new CodeInstruction(OpCodes.Stloc_1); - } - else if (step == 2) - { - yield return new CodeInstruction(OpCodes.Ldarg_S, 0); - yield return new CodeInstruction(OpCodes.Ldarg_S, 2); - yield return new CodeInstruction(OpCodes.Ldarg_S, 9); - yield return new CodeInstruction(OpCodes.Ldloc, 5); - yield return new CodeInstruction(OpCodes.Ldloc, 6); - yield return CodeInstruction.Call(typeof(SkillBuffPatcher), nameof(DrawCustomSkillBuff)); - yield return new CodeInstruction(OpCodes.Stloc, 6); - } + matcher.Start(); + + // Add to HoverText TextureBox height: + + // MATCH: if (buffIconsToDisplay != null) + matcher.MatchEndForward( + new(OpCodes.Ldarg_S, (byte)8), + new(OpCodes.Brfalse_S)); + + // INSERT: height += SkillBuffPatcher.GetHeightAdjustment(buffIconsToDisplay, hoveredItem, height) + matcher.InsertAndAdvance( + new(OpCodes.Ldarg_S, 8), + new(OpCodes.Ldarg_S, 9), + new(OpCodes.Ldloc_2), + CodeInstruction.Call(typeof(SkillBuffPatcher), nameof(SkillBuffPatcher.GetHeightAdjustment)), + new(OpCodes.Stloc_2)); + + // Check to set HoverText TextureBox minimum width: + + // MATCH: if (buffIconsToDisplay != null) + matcher.MatchEndForward( + new(OpCodes.Ldarg_S, (byte)8), + new(OpCodes.Brfalse_S)); + + // INSERT: width = SkillBuffPatcher.GetWidthAdjustment(font, hoveredItem, width) + matcher.InsertAndAdvance( + new(OpCodes.Ldarg_S, 2), + new(OpCodes.Ldarg_S, 9), + new(OpCodes.Ldloc_1), + CodeInstruction.Call(typeof(SkillBuffPatcher), nameof(GetWidthAdjustment)), + new(OpCodes.Stloc_1)); + + // Draw SkillBuff custom skill buff effects: + + // above the divider (health + stamina): + + // these are attributes more closely tied to health/stamina than + // skills and combat attributes, so they're drawn separately + + // MATCH: if (buffIconsToDisplay != null) + matcher.MatchEndForward( + new(OpCodes.Ldarg_S, (byte)8), + new(OpCodes.Brfalse)); // not _s + + // INSERT: y += SkillBuffPatcher.DrawAdditionalBuffEffects(b, font, hoveredItem, x, y) + matcher.InsertAndAdvance( + new(OpCodes.Ldarg_S, 0), + new(OpCodes.Ldarg_S, 2), + new(OpCodes.Ldarg_S, 9), + new(OpCodes.Ldloc, 5), + new(OpCodes.Ldloc, 6), + CodeInstruction.Call(typeof(SkillBuffPatcher), nameof(DrawAdditionalBuffEffects)), + new(OpCodes.Stloc, 6)); + + // optional divider ( | skills + attributes): + + // given the base game divider draw behaviour requires you to have included some + // basic buff attributes, items with only SpaceCore custom skill buff effects + // need to manually draw the divider and their buff effects outside of the usual branch + + // INSERT: y += SkillBuffPatcher.DrawCustomSkillBuffEffectsIfNoBasicEffects(b, font, hoveredItem, x, y, width, buffIconsToDisplay, craftingIngredients) + matcher.InsertAndAdvance( + new(OpCodes.Ldarg_S, 0), + new(OpCodes.Ldarg_S, 2), + new(OpCodes.Ldarg_S, 9), + new(OpCodes.Ldloc, 5), + new(OpCodes.Ldloc, 6), + new(OpCodes.Ldloc, 1), + new(OpCodes.Ldarg_S, 8), + new(OpCodes.Ldarg_S, 16), + CodeInstruction.Call(typeof(SkillBuffPatcher), nameof(DrawCustomSkillBuffEffectsIfNoBasicEffects)), + new(OpCodes.Stloc, 6)); + + // below the divider (skills + attributes): - yield return codeInstructions[i]; - step++; + // these are drawn above basic skills, as it might look odd having them + // below basic non-skill attributes, such as attack, defence, magnetism, ... + + // MATCH: b.Draw(Game1.staminaRect, new Rectangle(...), new Color(...)); + matcher.MatchEndForward(new CodeMatch(op => op.Is(OpCodes.Callvirt, AccessTools.Method(typeof(SpriteBatch), nameof(SpriteBatch.Draw), [typeof(Texture2D), typeof(Rectangle), typeof(Color)])))); + + // INSERT: y += SkillBuffPatcher.DrawCustomSkillBuffEffects(b, font, hoveredItem, x, y) + matcher.InsertAndAdvance( + new(OpCodes.Ldarg_S, 0), + new(OpCodes.Ldarg_S, 2), + new(OpCodes.Ldarg_S, 9), + new(OpCodes.Ldloc, 5), + new(OpCodes.Ldloc, 6), + CodeInstruction.Call(typeof(SkillBuffPatcher), nameof(DrawCustomSkillBuffEffects)), + new(OpCodes.Stloc, 6)); + + if (matcher.IsInvalid) + { + Log.Error($"Failed to apply {nameof(SkillBuffPatcher)} {nameof(Transpile_IClickableMenu_DrawHoverText)}. Custom buff effects will not be listed on items."); + return il; } + + return matcher.InstructionEnumeration(); } private static int GetHeightAdjustment(string[] buffIconsToDisplay, Item hoveredItem, int height) @@ -184,22 +237,25 @@ data.Buffs is null || bool addedAny = false; foreach (var buffData in data.Buffs) { - if (buffData.CustomFields is null) - continue; - foreach (var entry in Skills.SkillBuff.ParseCustomFields(buffData.CustomFields)) + if (SkillBuff.TryGetAdditionalBuffEffects(buffData.CustomFields, out var skills, out float health, out float stamina)) { addedAny = true; - height += 34; - } - if (buffData.CustomFields.ContainsKey("spacechase0.SpaceCore/HealthRegeneration")) - { - addedAny = true; - height += 34; - } - if (buffData.CustomFields.ContainsKey("spacechase0.SpaceCore/StaminaRegeneration")) - { - addedAny = true; - height += 34; + foreach (var entry in skills) + { + Skills.Skill skill = Skills.GetSkill(entry.Key); + if (skill is null) + continue; + + height += 34 + 5; + } + if (health != 0) + { + height += 34; + } + if (stamina != 0) + { + height += 34; + } } } @@ -221,36 +277,36 @@ data.Buffs is null || return width; } - foreach ( var buffData in data.Buffs ) + foreach (var buffData in data.Buffs) { - if (buffData.CustomFields is null) - continue; - foreach (var entry in Skills.SkillBuff.ParseCustomFields(buffData.CustomFields)) + if (SkillBuff.TryGetAdditionalBuffEffects(buffData.CustomFields, out var skills, out float health, out float stamina)) { - Skills.Skill skill = Skills.GetSkill(entry.Key); + foreach (var entry in skills) + { + Skills.Skill skill = Skills.GetSkill(entry.Key); + if (skill is null) + continue; - if (skill is null) + width = Math.Max(width, (int)font.MeasureString("+99 " + skill.GetName()).X) + 92; + } + if (health != 0) { - continue; + width = Math.Max(width, (int)font.MeasureString("+999 " + I18n.HealthRegen()).X) + 92; + } + if (stamina != 0) + { + width = Math.Max(width, (int)font.MeasureString("+999 " + I18n.StaminaRegen()).X) + 92; } - - width = Math.Max(width, (int)font.MeasureString("+99 " + skill.GetName()).X) + 92; - } - - if (buffData.CustomFields.ContainsKey("spacechase0.SpaceCore/HealthRegeneration")) - { - width = Math.Max(width, (int)font.MeasureString("+999 " + I18n.HealthRegen()).X) + 92; - } - if (buffData.CustomFields.ContainsKey("spacechase0.SpaceCore/StaminaRegeneration")) - { - width = Math.Max(width, (int)font.MeasureString("+999 " + I18n.StaminaRegen()).X) + 92; } } return width; } - private static int DrawCustomSkillBuff(SpriteBatch b, SpriteFont font, Item hoveredItem, int x, int y) + /// + /// For items with basic buff attributes, draws custom skill buff effects, or does nothing if no custom skill effects are found. + /// + private static int DrawCustomSkillBuffEffects(SpriteBatch b, SpriteFont font, Item hoveredItem, int x, int y) { if (hoveredItem is null || !Game1.objectData.TryGetValue(hoveredItem.ItemId, out ObjectData data) || @@ -260,43 +316,90 @@ data.Buffs is null || return y; } + Vector2 offset = new Vector2(16 + 4, 16); + Point spacing = new Point(34, 34 + 5); + foreach (var buffData in data.Buffs) { - if (buffData.CustomFields is null) - continue; - foreach (var entry in Skills.SkillBuff.ParseCustomFields(buffData.CustomFields)) + if (SkillBuff.TryGetAdditionalBuffEffects(buffData.CustomFields, out var skills, out float health, out float stamina)) { - Skills.Skill skill = Skills.GetSkill(entry.Key); - - if (skill is null) + foreach (var entry in skills) { - continue; - } - string text = $"+{entry.Value} {skill.GetName()}"; + Skills.Skill skill = Skills.GetSkill(entry.Key); + if (skill is null) + continue; - Utility.drawWithShadow(b, skill.SkillsPageIcon, new Vector2(x + 16 + 4, y + 16), new Rectangle(0, 0, 10, 10), Color.White, 0f, Vector2.Zero, 3f, flipped: false, 0.95f); - Utility.drawTextWithShadow(b, text, font, new Vector2(x + 16 + 34 + 4, y + 16), Game1.textColor); - y += 34; + SkillBuff.DrawBuffEffect(b, new Vector2(x, y) + offset, entry.Value, skill.GetName(), font: font, icon: skill.SkillsPageIcon, spacing: spacing.X); + y += spacing.Y; + } } + } - if (buffData.CustomFields.ContainsKey("spacechase0.SpaceCore/HealthRegeneration")) - { - float amt = float.Parse(buffData.CustomFields["spacechase0.SpaceCore/HealthRegeneration"]); - string text = (amt >= 0 ? "+" : "") + amt + " " + I18n.HealthRegen(); - Utility.drawWithShadow(b, Game1.mouseCursors, new Vector2(x + 16 + 4, y + 16), new Rectangle(0, 438, 10, 10), Color.White, 0f, Vector2.Zero, 3f, flipped: false, 0.95f); - Utility.drawTextWithShadow(b, text, font, new Vector2(x + 16 + 34 + 4, y + 16), Game1.textColor); - y += 34; - } - if (buffData.CustomFields.ContainsKey("spacechase0.SpaceCore/StaminaRegeneration")) + return y; + } + + /// + /// For all items, draws any SpaceCore additional buff effects, or does nothing if no additional effects are found. + /// + private static int DrawAdditionalBuffEffects(SpriteBatch b, SpriteFont font, Item hoveredItem, int x, int y) + { + if (hoveredItem is null || + !Game1.objectData.TryGetValue(hoveredItem.ItemId, out ObjectData data) || + data.Buffs is null || + data.Buffs.All(b => b.CustomFields is null || b.CustomFields.Count == 0)) + { + return y; + } + + Vector2 offset = new Vector2(16 + 4, 16); + Point spacing = new Point(34, 34); + + foreach (var buffData in data.Buffs) + { + if (SkillBuff.TryGetAdditionalBuffEffects(buffData.CustomFields, out var skills, out float health, out float stamina)) { - float amt = float.Parse(buffData.CustomFields["spacechase0.SpaceCore/StaminaRegeneration"]); - string text = (amt >= 0 ? "+" : "") + amt + " " + I18n.StaminaRegen(); - Utility.drawWithShadow(b, Game1.mouseCursors, new Vector2(x + 16 + 4, y + 16), new Rectangle((amt < 0) ? 140 : 0, 428, 10, 10), Color.White, 0f, Vector2.Zero, 3f, flipped: false, 0.95f); - Utility.drawTextWithShadow(b, text, font, new Vector2(x + 16 + 34 + 4, y + 16), Game1.textColor); - y += 34; + if (stamina != 0) + { + SkillBuff.DrawStaminaRegenBuffEffect(b, new Vector2(x, y) + offset, stamina, font: font, spacing: spacing.X); + y += spacing.Y; + } + if (health != 0) + { + SkillBuff.DrawHealthRegenBuffEffect(b, new Vector2(x, y) + offset, health, font: font, spacing: spacing.X); + y += spacing.Y; + } } } return y; } + + /// + /// For hovered items without basic buff attributes, draws a divider and custom skill buff effects, or does nothing if no custom skill effects are found.. + /// + private static int DrawCustomSkillBuffEffectsIfNoBasicEffects(SpriteBatch b, SpriteFont font, Item hoveredItem, int x, int y, int width, string[] buffIconsToDisplay, CraftingRecipe craftingIngredients) + { + // duplicate spacecore code + if (hoveredItem is null || + !Game1.objectData.TryGetValue(hoveredItem.ItemId, out ObjectData data) || + data.Buffs is null || + data.Buffs.All(b => b.CustomFields is null || b.CustomFields.Count == 0)) + { + return y; + } + + // handle alternate branch in base game code without transpiling labels + if (buffIconsToDisplay is null) + { + // duplicate base game code + y += 16; + b.Draw(Game1.staminaRect, new Rectangle(x + 12, y + 6, width - ((craftingIngredients is not null) ? 4 : 24), 2), new Color(207, 147, 103) * 0.8f); + + // duplicate spacecore code + y += SkillBuffPatcher.DrawCustomSkillBuffEffects(b, font, hoveredItem, x, y); + } + + // this is a miserable method + return y; + } } diff --git a/SpaceCore/Skills.cs b/SpaceCore/Skills.cs index ac9aa0e5..1f895d3d 100644 --- a/SpaceCore/Skills.cs +++ b/SpaceCore/Skills.cs @@ -3,6 +3,7 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; +using System.Text; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Newtonsoft.Json; @@ -117,20 +118,33 @@ public class SkillBuff : Buff public SkillBuff(Buff buff, string id, Dictionary customFields) : base(id, buff.source, buff.displaySource, buff.millisecondsDuration, buff.iconTexture, buff.iconSheetIndex, buff.effects, false, buff.displayName, buff.description) { - foreach (var entry in ParseCustomFields(customFields)) + if (SkillBuff.TryGetAdditionalBuffEffects(customFields, out var skills, out float health, out float stamina)) { - SkillLevelIncreases[entry.Key] = entry.Value; + foreach (var entry in skills) + this.SkillLevelIncreases[entry.Key] = entry.Value; + this.HealthRegen = health; + this.StaminaRegen = stamina; } - if (customFields.TryGetValue(RegenHealth, out string regenStr) && float.TryParse(regenStr, out float regen)) - HealthRegen = regen; - if (customFields.TryGetValue(RegenStamina, out regenStr) && float.TryParse(regenStr, out regen)) - StaminaRegen = regen; - } - public static IEnumerable> ParseCustomFields(Dictionary customFields) + /// + /// Parses a given dictionary, probably a CustomFields field, for any SpaceCore additional buff effects. + /// + /// + /// Map of SpaceCore IDs to their respective values, or an empty dictionary if none are found. + /// Float value of health regenerated per second. + /// Float value of energy regenerated per second. + /// Returns whether any additional buff effects were found with tangible (non-zero or non-empty) values. + public static bool TryGetAdditionalBuffEffects(Dictionary dict, out Dictionary skills, out float health, out float stamina) { - foreach (KeyValuePair entry in customFields) + skills = []; + health = 0; + stamina = 0; + + if (dict is null || !dict.Any()) + return false; + + foreach (var entry in dict) { if (!entry.Key.StartsWith(SkillBuffField) && !entry.Key.StartsWith(SkillBuffFieldLegacy)) { @@ -144,22 +158,94 @@ public static IEnumerable> ParseCustomFields(Dictionar continue; } - yield return KeyValuePair.Create(skillId, level); + skills.Add(skillId, level); } + + if (dict.TryGetValue(RegenHealth, out string regenStr) && float.TryParse(regenStr, out float regen)) + health = regen; + if (dict.TryGetValue(RegenStamina, out regenStr) && float.TryParse(regenStr, out regen)) + stamina = regen; + + return skills.Any() || health != 0 || stamina != 0; } public string DescriptionHook() { - string ret = ""; + StringBuilder sb = new(); if (HealthRegen != 0) { - ret += (HealthRegen > 0 ? "+" : "") + HealthRegen + " " + I18n.HealthRegen(); + sb.Append(FormattedBuffEffect(HealthRegen, I18n.HealthRegen())); } if (StaminaRegen != 0) { - ret += (StaminaRegen > 0 ? "+" : "") + StaminaRegen + " " + I18n.StaminaRegen(); + sb.Append(FormattedBuffEffect(StaminaRegen, I18n.StaminaRegen())); } - return ret; + return sb.ToString(); + } + + /// + /// Formats a buff effect value into a signed label. + /// + /// Buff effect value. + /// Translated label. + public static string FormattedBuffEffect(float value, string label = null) + { + return string.IsNullOrWhiteSpace(label) ? $"{(value > 0 ? "+" : "")}{value}" : $"{(value > 0 ? "+" : "")}{value} {label}"; + } + + /// + /// Draws a buff icon and formatted buff effect value label. + /// + /// Local display pixel draw position. + /// Buff effect value. + /// Translated label. Will be formatted into a standardised style when drawn. + /// Font used to draw label. Defaults to . + /// Texture used for buff icon. + /// Area in icon texture used for buff icon when drawn. Defaults to entire texture. + /// Opacity of icon and label when drawn. + /// Display pixel spacing between icon and text. + /// Relative opacity of shadow when drawn. + public static void DrawBuffEffect(SpriteBatch b, Vector2 position, float value, string label = null, SpriteFont font = null, Texture2D icon = null, Rectangle? iconSource = null, float alpha = 1, int spacing = 8 * Game1.pixelZoom, float shadowAlpha = 1) + { + string text = SkillBuff.FormattedBuffEffect(value, label); + int xOffset = 0; + + if (icon is not null) + { + Utility.drawWithShadow(b, icon, position, iconSource ?? icon.Bounds, Color.White * alpha, 0f, Vector2.Zero, 3f, flipped: false, layerDepth: 0.95f, shadowIntensity: 0.35f * shadowAlpha * alpha); + xOffset += spacing; + } + Utility.drawTextWithShadow(b, text, font ?? Game1.smallFont, position + new Vector2(xOffset, 0), Game1.textColor * alpha); + } + + /// + /// Draws a buff icon and formatted buff effect value label in the style of a SpaceCore buff. + /// + /// Local display pixel draw position. + /// Health regeneration value. + /// Whether to draw label in addition to buff effect value. + /// Font used to draw label. Defaults to . + /// Opacity of icon and label when drawn. + /// Display pixel spacing between icon and text. + /// Relative opacity of shadow when drawn. + public static void DrawHealthRegenBuffEffect(SpriteBatch b, Vector2 position, float value, bool drawText = true, SpriteFont font = null, float alpha = 1, int spacing = 8 * Game1.pixelZoom, float shadowAlpha = 1) + { + SkillBuff.DrawBuffEffect(b, position, value, drawText ? I18n.HealthRegen() : null, font, Game1.mouseCursors, new Rectangle(0, 438, 10, 10), alpha: alpha, spacing: spacing, shadowAlpha: shadowAlpha); + } + + /// + /// Draws a buff icon and formatted buff effect value label in the style of a SpaceCore buff. + /// + /// Local display pixel draw position. + /// Stamina regeneration value. + /// Whether to draw label in addition to buff effect value. + /// Font used to draw label. Defaults to . + /// Opacity of icon and label when drawn. + /// Display pixel spacing between icon and text. + /// Relative opacity of shadow when drawn. + public static void DrawStaminaRegenBuffEffect(SpriteBatch b, Vector2 position, float value, bool drawText = true, SpriteFont font = null, float alpha = 1, int spacing = 8 * Game1.pixelZoom, float shadowAlpha = 1) + { + SkillBuff.DrawBuffEffect(b, position, value, drawText ? I18n.StaminaRegen() : null, font, Game1.mouseCursors, new Rectangle((value < 0) ? 140 : 0, 428, 10, 10), alpha: alpha, spacing: spacing, shadowAlpha: shadowAlpha); } public override void OnAdded() diff --git a/SpaceCore/VanillaAssetExpansion/Buffs.cs b/SpaceCore/VanillaAssetExpansion/Buffs.cs index 9b1c18cb..d292fbc3 100644 --- a/SpaceCore/VanillaAssetExpansion/Buffs.cs +++ b/SpaceCore/VanillaAssetExpansion/Buffs.cs @@ -1,11 +1,8 @@ -using System; -using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using HarmonyLib; using StardewValley; using StardewValley.Menus; +using static SpaceCore.Skills; namespace SpaceCore.VanillaAssetExpansion { @@ -20,13 +17,7 @@ public static void Postfix(Buff __instance) if (__instance is Skills.SkillBuff) return; - if (__instance.customFields == null) - return; - - if (__instance.customFields.Any(b => b.Key.StartsWith("spacechase.SpaceCore.SkillBuff.") || - b.Key.StartsWith("spacechase0.SpaceCore.SkillBuff.") || - b.Key.StartsWith("spacechase0.SpaceCore/HealthRegeneration") || - b.Key.StartsWith("spacechase0.SpaceCore/StaminaRegeneration"))) + if (SkillBuff.TryGetAdditionalBuffEffects(__instance.customFields, out var _, out float _, out float _)) { Game1.player.applyBuff(new Skills.SkillBuff(__instance, __instance.id, __instance.customFields)); } @@ -77,22 +68,13 @@ public static void Prefix(Buff buff, ref object __state) if (!DataLoader.Buffs(Game1.content).TryGetValue(buff.id, out var buffData)) return; - if (buffData.CustomFields == null) - return; - if (buffData.CustomFields.TryGetValue("spacechase0.SpaceCore/HealthRegeneration", out string valStr)) + if (SkillBuff.TryGetAdditionalBuffEffects(buffData.CustomFields, out var _, out float health, out float stamina)) { - if (float.TryParse(valStr, out float val)) - { - buff.description += (val >= 0 ? "+" : "") + val + " " + I18n.HealthRegen(); - } - } - if (buffData.CustomFields.TryGetValue("spacechase0.SpaceCore/StaminaRegeneration", out valStr)) - { - if (float.TryParse(valStr, out float val)) - { - buff.description += (val >= 0 ? "+" : "") + val + " " + I18n.StaminaRegen(); - } + if (health != 0) + buff.description += SkillBuff.FormattedBuffEffect(health, I18n.HealthRegen()); + if (stamina != 0) + buff.description += SkillBuff.FormattedBuffEffect(stamina, I18n.StaminaRegen()); } }