Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions MoonShared/APIs/IWearMoreRingsApi.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using StardewValley.Objects;

namespace MoonShared.APIs;

public interface IWearMoreRingsAPI_2
{
int RingSlotCount();
Ring GetRing(int slot);
}
1 change: 1 addition & 0 deletions MoonShared/MoonShared.projitems
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<Compile Include="$(MSBuildThisFileDirectory)APIs\IMargo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)APIs\IProducerFrameworkAPI.cs" />
<Compile Include="$(MSBuildThisFileDirectory)APIs\ISpaceCore.cs" />
<Compile Include="$(MSBuildThisFileDirectory)APIs\IWearMoreRingsApi.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Attributes\SAsset.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Attributes\Parser.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Attributes\Log.cs" />
Expand Down
11 changes: 11 additions & 0 deletions WizardryManaBar/Core/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,24 @@

namespace WizardryManaBar.Core
{
internal static class ManaBarModes
{
public const string Compact = "Compact";
public const string Custom = "Custom";
}

[SConfig]
public class Config
{
[SConfig.Option()]
public bool RenderManaBar { get; set; } = true;


// Compact uses the vanilla bar frame + ManaBarIcon; Custom uses manabg.png as the full frame.
[SConfig.Option(new string[] { ManaBarModes.Compact, ManaBarModes.Custom })]
public string ManaBarMode { get; set; } = ManaBarModes.Compact;


[SConfig.Option(-500, 500, 1)]
public int XManaBarOffset { get; set; } = 0;

Expand Down
94 changes: 86 additions & 8 deletions WizardryManaBar/Core/Events.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using MoonShared.APIs;
using MoonShared.Attributes;
using SpaceCore.Events;
using StardewModdingAPI;
Expand All @@ -16,6 +17,7 @@ public class Events
{
private const string ManaFill = "moonslime.ManaBarApi.ManaFill";
private const string ManaRestore = "moonslime.ManaBarApi.ManaRestore";
private const string MagicStardewSpellBookQualifiedItemId = "(O)MagicStardew.SpellBook";

private const int ManaBarOriginalBaseMana = 100;
private const int ManaBarBaseHeight = 168;
Expand All @@ -32,6 +34,14 @@ public class Events

private static readonly Rectangle ManaPipSourceRect = new Rectangle(398, 497, ManaPipSourceWidth, ManaPipSourceHeight);

// Custom art mode uses manabg.png as a vanilla-style 12x56 bar frame.
private static readonly Rectangle CompactFrameTopSource = new Rectangle(268, 408, 12, 16);
private static readonly Rectangle CompactFrameMiddleSource = new Rectangle(268, 424, 12, 16);
private static readonly Rectangle CompactFrameBottomSource = new Rectangle(268, 448, 12, 16);
private static readonly Rectangle CustomFrameTopSource = new Rectangle(0, 0, 12, 16);
private static readonly Rectangle CustomFrameMiddleSource = new Rectangle(0, 16, 12, 24);
private static readonly Rectangle CustomFrameBottomSource = new Rectangle(0, 40, 12, 16);

private const int ManaPipDrawWidth = ManaPipSourceWidth * ManaPipDrawScale;
private const int ManaPipDrawHeight = ManaPipSourceHeight * ManaPipDrawScale;
private const int ManaPipOverlap = ManaPipSourceOverlap * ManaPipDrawScale;
Expand All @@ -50,6 +60,7 @@ public class Events
private static Vector2 CachedBottomOfBar;
private static Rectangle CachedMiddleRect;
private static Rectangle CachedBottomRect;
private static bool WarnedInvalidCustomFrameTexture;

// --- Cached dynamic filler ---
private static int CachedCurrentMana = -1;
Expand Down Expand Up @@ -268,10 +279,31 @@ private static Rectangle[] BuildManaPipRects(int pipCount, int fillerBottom)

private static void DrawStaticBar(SpriteBatch sb)
{
sb.Draw(Game1.mouseCursors, CachedTopOfBar, new Rectangle(268, 408, 12, 16), Color.White, 0f, Vector2.Zero, 4f, SpriteEffects.None, 1f);
if (IsCustomManaBarMode())
{
Texture2D customFrame = Assets.ManaBG;
if (customFrame.Width >= 12 && customFrame.Height >= 56)
{
DrawFrame(sb, customFrame, CustomFrameTopSource, CustomFrameMiddleSource, CustomFrameBottomSource);
return;
}

if (!WarnedInvalidCustomFrameTexture)
{
WarnedInvalidCustomFrameTexture = true;
ModEntry.Instance.Monitor.Log($"Custom mana bar art must be at least 12x56 pixels, but Mods/moonslime.ManaBarApi/textures is {customFrame.Width}x{customFrame.Height}. Falling back to compact mode.", LogLevel.Warn);
}
}

DrawFrame(sb, Game1.mouseCursors, CompactFrameTopSource, CompactFrameMiddleSource, CompactFrameBottomSource);
sb.Draw(Assets.ManaBarIcon, CachedTopOfBar, new Rectangle(0, 0, 12, 12), Color.White, 0f, Vector2.Zero, 4f, SpriteEffects.None, 1f);
sb.Draw(Game1.mouseCursors, CachedMiddleRect, new Rectangle(256, 424, 12, 16), Color.White);
sb.Draw(Game1.mouseCursors, new Vector2(CachedBottomRect.X, CachedBottomRect.Y), new Rectangle(256, 448, 12, 16), Color.White, 0f, Vector2.Zero, 4f, SpriteEffects.None, 1f);
}

private static void DrawFrame(SpriteBatch sb, Texture2D texture, Rectangle topSource, Rectangle middleSource, Rectangle bottomSource)
{
sb.Draw(texture, CachedTopOfBar, topSource, Color.White, 0f, Vector2.Zero, 4f, SpriteEffects.None, 1f);
sb.Draw(texture, CachedMiddleRect, middleSource, Color.White);
sb.Draw(texture, new Vector2(CachedBottomRect.X, CachedBottomRect.Y), bottomSource, Color.White, 0f, Vector2.Zero, 4f, SpriteEffects.None, 1f);
}

private static void DrawFiller(SpriteBatch sb)
Expand Down Expand Up @@ -317,20 +349,66 @@ public static Color GetBlueToWhiteLerpColor(float power)

public static float SetBarsPosition()
{
if (ModEntry.Config.ManaBarExtraSnaps == -1)
return 56f;

int extraCount = 1;
if (Game1.showingHealth) extraCount++;
if (ModEntry.MagicStardewLoaded) extraCount++;
if (ShouldSnapToMagicStardewManaBar()) extraCount++;

extraCount += ModEntry.Config.ManaBarExtraSnaps;

if (ModEntry.Config.ManaBarExtraSnaps == -1)
return 56f * Math.Max(1, extraCount);
}

private static bool IsCustomManaBarMode()
{
return string.Equals(ModEntry.Config.ManaBarMode, ManaBarModes.Custom, StringComparison.OrdinalIgnoreCase);
}

private static bool ShouldSnapToMagicStardewManaBar()
{
if (!ModEntry.MagicStardewLoaded || !Context.IsWorldReady || Game1.currentLocation is null || Game1.eventUp)
return false;

Farmer player = Game1.player;
if (player is null)
return false;

return HasMagicStardewSpellBook(player);
}

private static bool HasMagicStardewSpellBook(Farmer player)
{
if (player.leftRing.Value?.QualifiedItemId == MagicStardewSpellBookQualifiedItemId || player.rightRing.Value?.QualifiedItemId == MagicStardewSpellBookQualifiedItemId)
return true;

if (HasMagicStardewSpellBookInWearMoreRingsSlot())
return true;

foreach (Item item in player.Items)
{
return 56f;
if (item?.QualifiedItemId == MagicStardewSpellBookQualifiedItemId)
return true;
}
else

return false;
}

private static bool HasMagicStardewSpellBookInWearMoreRingsSlot()
{
var wearMoreRingsApi = ModEntry.Instance.Helper.ModRegistry.GetApi<IWearMoreRingsAPI_2>("bcmpinc.WearMoreRings");
if (wearMoreRingsApi is null)
return false;

int slotCount = wearMoreRingsApi.RingSlotCount();
for (int i = 0; i < slotCount; i++)
{
return 56f * extraCount;
if (wearMoreRingsApi.GetRing(i)?.QualifiedItemId == MagicStardewSpellBookQualifiedItemId)
return true;
}

return false;
}

private static void OnDayStarted(object sender, DayStartedEventArgs e)
Expand Down
3 changes: 3 additions & 0 deletions WizardryManaBar/i18n/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
"config.RenderManaBar": "Render Mana Bar",
"config.RenderManaBar.tooltip": "Should the mana bar be rendered at all?",

"config.ManaBarMode": "Mana Bar Mode",
"config.ManaBarMode.tooltip": "Compact: Stardew's Health Bar with ManaBarIcon.png overlaid.\nCustom: Uses manabg.png as the full Mana Bar.",

"config.XManaBarOffset": "Mana Bar X offset",
"config.XManaBarOffset.tooltip": "Control where the mana bar is on the X axis of the screen.\nNote: If Snapping is not set to -1, bar will move when the player's health shows up.",

Expand Down