Iron's Spells 'n Spellbooks

Iron's Spells 'n Spellbooks

11M Downloads

Active Spell Overlay Customization Request

Willem07 opened this issue ยท 1 comments

commented

Feature description

Please add my changes to the Active Spell in the user interface so it can be moved around the screen.
Feel free to edit the icon's position according to your preferences; it is centered by default.

package io.redspace.ironsspellbooks.gui.overlays;

import com.mojang.blaze3d.systems.RenderSystem;
import io.redspace.ironsspellbooks.IronsSpellbooks;
import io.redspace.ironsspellbooks.api.registry.SpellRegistry;
import io.redspace.ironsspellbooks.api.spells.AbstractSpell;
import io.redspace.ironsspellbooks.api.spells.ISpellContainer;
import io.redspace.ironsspellbooks.config.ClientConfigs;
import io.redspace.ironsspellbooks.item.CastingItem;
import io.redspace.ironsspellbooks.item.Scroll;
import io.redspace.ironsspellbooks.player.ClientMagicData;
import io.redspace.ironsspellbooks.registries.ItemRegistry;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.client.gui.overlay.ForgeGui;
import net.minecraftforge.client.gui.overlay.IGuiOverlay;

public class ActiveSpellOverlay implements IGuiOverlay {
    public static ActiveSpellOverlay instance = new ActiveSpellOverlay();

    protected static final ResourceLocation WIDGETS_LOCATION = new ResourceLocation("textures/gui/widgets.png");
    public final static ResourceLocation TEXTURE = new ResourceLocation(IronsSpellbooks.MODID, "textures/gui/icons.png");

    public enum Anchor {
        Center, TopLeft, TopRight, BottomLeft, BottomRight
    }

    public void render(ForgeGui gui, GuiGraphics guiHelper, float partialTick, int screenWidth, int screenHeight) {
        Player player = Minecraft.getInstance().player;
        if (player == null) return;

        ItemStack stack = player.getMainHandItem();
        AbstractSpell spell;

        if (hasRightClickCasting(stack.getItem())) {
            if (ISpellContainer.isSpellContainer(stack)) {
                spell = ISpellContainer.get(stack).getSpellAtIndex(0).getSpell();
            } else {
                spell = ClientMagicData.getSpellSelectionManager().getSelectedSpellData().getSpell();
            }
        } else {
            stack = player.getOffhandItem();
            if (hasRightClickCasting(stack.getItem())) {
                if (ISpellContainer.isSpellContainer(stack)) {
                    spell = ISpellContainer.get(stack).getSpellAtIndex(0).getSpell();
                } else {
                    spell = ClientMagicData.getSpellSelectionManager().getSelectedSpellData().getSpell();
                }
            } else {
                return;
            }
        }

        if (stack.isEmpty() || spell == SpellRegistry.none()) {
            return;
        }

        // Get position settings from ClientConfigs
        int configOffsetX = ClientConfigs.ACTIVE_SPELL_OVERLAY_X_OFFSET.get();
        int configOffsetY = ClientConfigs.ACTIVE_SPELL_OVERLAY_Y_OFFSET.get();
        Anchor anchor = ClientConfigs.ACTIVE_SPELL_OVERLAY_ANCHOR.get();

        // Determine the position based on the binding
        int positionX = getPositionX(anchor, screenWidth) + configOffsetX;
        int positionY = getPositionY(anchor, screenHeight) + configOffsetY;

        guiHelper.blit(WIDGETS_LOCATION, positionX, positionY, 24, 22, 29, 24);
        guiHelper.blit(spell.getSpellIconResource(), positionX + 3, positionY + 4, 0, 0, 16, 16, 16, 16);

        float cooldownPercent = ClientMagicData.getCooldownPercent(spell);
        if (cooldownPercent > 0 && !stack.getItem().equals(ItemRegistry.SCROLL.get())) {
            int pixels = (int) (16 * cooldownPercent + 1f);
            guiHelper.blit(TEXTURE, positionX + 3, positionY + 20 - pixels, 47, 87, 16, pixels);
        }
    }

    private static boolean hasRightClickCasting(Item item) {
        return item instanceof Scroll || item instanceof CastingItem;
    }

    private static int getPositionX(Anchor anchor, int screenWidth) {
        switch (anchor) {
            case TopLeft: return 20; // You can customize it as you wish
            case TopRight: return screenWidth - 20 - 29; // Adjust the width and height of the icon
            case BottomLeft: return 20; // Customize it as you like
            case BottomRight: return screenWidth - 20 - 29; // Adjust the width and height of the icon
            case Center:
            default: return screenWidth / 2 - 14; // For the center, you can set the offset
        }
    }

    private static int getPositionY(Anchor anchor, int screenHeight) {
        switch (anchor) {
            case TopLeft:
            case TopRight: return 20; // Height for the top corners
            case BottomLeft:
            case BottomRight: return screenHeight - 20 - 24; // Adjust the height of the icon
            case Center:
            default: return screenHeight / 2 - 12; // For the center
        }
    }
}
package io.redspace.ironsspellbooks.config;

import io.redspace.ironsspellbooks.gui.overlays.ManaBarOverlay;
import io.redspace.ironsspellbooks.gui.overlays.RecastOverlay;
import io.redspace.ironsspellbooks.gui.overlays.SpellBarOverlay;
import io.redspace.ironsspellbooks.gui.overlays.ActiveSpellOverlay; // Added for the new class
import io.redspace.ironsspellbooks.gui.overlays.ManaBarOverlay.Anchor;
import io.redspace.ironsspellbooks.gui.overlays.ManaBarOverlay.Display;
import net.minecraftforge.common.ForgeConfigSpec;

public class ClientConfigs {
    public static final ForgeConfigSpec.Builder BUILDER = new ForgeConfigSpec.Builder();
    public static final ForgeConfigSpec.ConfigValue<Boolean> SHOW_FIRST_PERSON_ARMS;
    public static final ForgeConfigSpec.ConfigValue<Boolean> SHOW_FIRST_PERSON_ITEMS;
    public static final ForgeConfigSpec.ConfigValue<Boolean> REPLACE_GHAST_FIREBALL;
    public static final ForgeConfigSpec.ConfigValue<Boolean> REPLACE_BLAZE_FIREBALL;
    public static final ForgeConfigSpec.ConfigValue<Integer> MANA_BAR_Y_OFFSET;
    public static final ForgeConfigSpec.ConfigValue<Integer> MANA_BAR_X_OFFSET;
    public static final ForgeConfigSpec.ConfigValue<Integer> MANA_TEXT_X_OFFSET;
    public static final ForgeConfigSpec.ConfigValue<Integer> MANA_TEXT_Y_OFFSET;
    public static final ForgeConfigSpec.ConfigValue<Boolean> MANA_BAR_TEXT_VISIBLE;
    public static final ForgeConfigSpec.ConfigValue<Boolean> ENABLE_BOSS_MUSIC;
    public static final ForgeConfigSpec.ConfigValue<ManaBarOverlay.Anchor> MANA_BAR_ANCHOR;
    public static final ForgeConfigSpec.ConfigValue<ManaBarOverlay.Display> MANA_BAR_DISPLAY;
    public static final ForgeConfigSpec.ConfigValue<ManaBarOverlay.Display> SPELL_BAR_DISPLAY;
    public static final ForgeConfigSpec.ConfigValue<Integer> SPELL_BAR_Y_OFFSET;
    public static final ForgeConfigSpec.ConfigValue<Integer> SPELL_BAR_X_OFFSET;
    public static final ForgeConfigSpec.ConfigValue<SpellBarOverlay.Anchor> SPELL_BAR_ANCHOR;
    public static final ForgeConfigSpec.ConfigValue<RecastOverlay.Anchor> RECAST_ANCHOR;
    public static final ForgeConfigSpec.ConfigValue<Integer> RECAST_Y_OFFSET;
    public static final ForgeConfigSpec.ConfigValue<Integer> RECAST_X_OFFSET;
    public static final ForgeConfigSpec.ConfigValue<ActiveSpellOverlay.Anchor> ACTIVE_SPELL_OVERLAY_ANCHOR;

    // New parameters for ActiveSpellOverlay
    public static final ForgeConfigSpec.ConfigValue<Integer> ACTIVE_SPELL_OVERLAY_X_OFFSET;
    public static final ForgeConfigSpec.ConfigValue<Integer> ACTIVE_SPELL_OVERLAY_Y_OFFSET;

    public static final ForgeConfigSpec SPEC;

    public ClientConfigs() {
    }

    static {
        BUILDER.comment("##############################################################################################");
        BUILDER.comment("##                                                                                          ##");
        BUILDER.comment("##                                                                                          ##");
        BUILDER.comment("##                                                                                          ##");
        BUILDER.comment("##                                                                                          ##");
        BUILDER.comment("##                                                                                          ##");
        BUILDER.comment("##   ATTENTION: These are client configs. For gameplay settings, go to the SERVER CONFIGS   ##");
        BUILDER.comment("##                                                                                          ##");
        BUILDER.comment("##                                                                                          ##");
        BUILDER.comment("##                                                                                          ##");
        BUILDER.comment("##                                                                                          ##");
        BUILDER.comment("##                                                                                          ##");
        BUILDER.comment("##############################################################################################");
        BUILDER.comment("");

        // Configuration for ManaBar
        BUILDER.push("UI");
        BUILDER.push("ManaBar");
        BUILDER.comment("By default (Contextual), the mana bar only appears when you are holding a magic item or are not at max mana.");
        MANA_BAR_DISPLAY = BUILDER.defineEnum("manaBarDisplay", Display.Contextual);
        BUILDER.comment("Used to adjust mana bar's position (11 is one full hunger bar up).");
        MANA_BAR_X_OFFSET = BUILDER.define("manaBarXOffset", 0);
        MANA_BAR_Y_OFFSET = BUILDER.define("manaBarYOffset", 0);
        MANA_BAR_TEXT_VISIBLE = BUILDER.define("manaBarTextVisible", true);
        MANA_BAR_ANCHOR = BUILDER.defineEnum("manaBarAnchor", Anchor.Hunger);
        MANA_TEXT_X_OFFSET = BUILDER.define("manaTextXOffset", 0);
        MANA_TEXT_Y_OFFSET = BUILDER.define("manaTextYOffset", 0);
        BUILDER.pop();

        // Configuration for SpellBar
        BUILDER.push("SpellBar");
        BUILDER.comment("By default (Always), the spell bar always shows the spells in your equipped spellbook. Contextual will hide them when not in use.");
        SPELL_BAR_DISPLAY = BUILDER.defineEnum("spellBarDisplay", Display.Always);
        BUILDER.comment("Used to adjust spell bar's position.");
        SPELL_BAR_X_OFFSET = BUILDER.define("spellBarXOffset", 0);
        SPELL_BAR_Y_OFFSET = BUILDER.define("spellBarYOffset", 0);
        SPELL_BAR_ANCHOR = BUILDER.defineEnum("spellBarAnchor", SpellBarOverlay.Anchor.Hotbar);
        BUILDER.pop();

        // Configuration for RecastOverlay
        BUILDER.push("RecastOverlay");
        RECAST_ANCHOR = BUILDER.defineEnum("recastAnchor", RecastOverlay.Anchor.TopCenter);
        RECAST_X_OFFSET = BUILDER.define("recastXOffset", 0);
        RECAST_Y_OFFSET = BUILDER.define("recastYOffset", 0);
        BUILDER.pop();

        // Configuration for ActiveSpellOverlay
        BUILDER.push("ActiveSpellOverlay");
        BUILDER.comment("Adjusts the position of the Active Spell Overlay on the screen.");
        ACTIVE_SPELL_OVERLAY_X_OFFSET = BUILDER.define("activeSpellOverlayXOffset", 0);
        ACTIVE_SPELL_OVERLAY_Y_OFFSET = BUILDER.define("activeSpellOverlayYOffset", 0);
        ACTIVE_SPELL_OVERLAY_ANCHOR = BUILDER.defineEnum("activeSpellOverlayAnchor", ActiveSpellOverlay.Anchor.Center);
        BUILDER.pop();

        // Configuration for Animations
        BUILDER.push("Animations");
        BUILDER.comment("What to render in first person while casting.");
        SHOW_FIRST_PERSON_ARMS = BUILDER.define("showFirstPersonArms", true);
        SHOW_FIRST_PERSON_ITEMS = BUILDER.define("showFirstPersonItems", true);
        BUILDER.pop();

        // Configuration for Renderers
        BUILDER.push("Renderers");
        BUILDER.comment("By default, both fireballs are replaced with an enhanced model used by fire spells.");
        REPLACE_GHAST_FIREBALL = BUILDER.define("replaceGhastFireballs", true);
        REPLACE_BLAZE_FIREBALL = BUILDER.define("replaceBlazeFireballs", true);
        BUILDER.pop();

        // Configuration for Music
        BUILDER.push("Music");
        ENABLE_BOSS_MUSIC = BUILDER.define("enableBossMusic", true);
        BUILDER.pop();

        SPEC = BUILDER.build();
    }
}

How it improves the player experience

Some interfaces from other mods overlap with the active spell, so I decided to move it to a different location.