diff --git a/build.gradle b/build.gradle index 82aa999..f9bd660 100644 --- a/build.gradle +++ b/build.gradle @@ -184,6 +184,9 @@ dependencies { implementation fg.deobf("curse.maven:quark-243121:3840125") implementation fg.deobf("curse.maven:architects-palette-433862:4498424") implementation fg.deobf("curse.maven:geckolib-388172:4181370") + implementation fg.deobf("curse.maven:cofh-core-69162:4801048") // wold plushie effects + implementation fg.deobf("curse.maven:alexs-mobs-426558:3853078") // wold plushie effects + implementation fg.deobf("curse.maven:citadel-331936:3783096") // alex mobs dep //faster loading implementation fg.deobf("curse.maven:lazydfu-433518:3209972") diff --git a/gradle.properties b/gradle.properties index 6fc6dc3..2215d6f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -38,7 +38,7 @@ mod_name=VHat Can I Roll? # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. mod_license=GNU LGPL 3.0 # The mod version. See https://semver.org/ -mod_version=1.0 +mod_version=1.1 # The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. # This should match the base package used for the mod sources. # See https://maven.apache.org/guides/mini/guide-naming-conventions.html diff --git a/src/main/java/com/radimous/vhatcaniroll/Config.java b/src/main/java/com/radimous/vhatcaniroll/Config.java index ed74e7d..01d93e4 100644 --- a/src/main/java/com/radimous/vhatcaniroll/Config.java +++ b/src/main/java/com/radimous/vhatcaniroll/Config.java @@ -6,12 +6,28 @@ public class Config { public static final ForgeConfigSpec SPEC; public static final ForgeConfigSpec.BooleanValue VAULT_SCREEN_BUTTON; public static final ForgeConfigSpec.BooleanValue ALLOW_DUPE; + public static final ForgeConfigSpec.IntValue BUTTON_X; + public static final ForgeConfigSpec.IntValue BUTTON_Y; + public static final ForgeConfigSpec.BooleanValue COMBINE_LVL_TO_ABILITIES; static { ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder(); + + COMBINE_LVL_TO_ABILITIES = builder + .comment("combine +lvl to abilities into one row") + .define("combineLvlToAbilities", true); + + builder.push("BUTTON"); VAULT_SCREEN_BUTTON = builder .comment("open VHat can I roll? from vault screen") .define("vaultScreenButton", true); + BUTTON_X = builder + .comment("x position of the button") + .defineInRange("buttonPositionX", 5, Integer.MIN_VALUE, Integer.MAX_VALUE); + BUTTON_Y = builder + .comment("y position of the button") + .defineInRange("buttonPositionY", 109, Integer.MIN_VALUE, Integer.MAX_VALUE); + builder.pop(); builder.push("DEBUG"); ALLOW_DUPE = builder diff --git a/src/main/java/com/radimous/vhatcaniroll/GearModifierScreen.java b/src/main/java/com/radimous/vhatcaniroll/GearModifierScreen.java index 984b73e..d7eaf98 100644 --- a/src/main/java/com/radimous/vhatcaniroll/GearModifierScreen.java +++ b/src/main/java/com/radimous/vhatcaniroll/GearModifierScreen.java @@ -31,10 +31,11 @@ import java.util.List; public class GearModifierScreen extends AbstractElementScreen { //TODO: code cleanup - variable naming, magic numbers, some logic reordering etc - //TODO: legendary modifiers private ModifierListContainer modifierList; private final TextInputElement lvlInput; + private boolean legendary; + private LabelElement legendaryLabel; private int currIndex = 0; private final List> tabs = new ArrayList<>(); @@ -68,6 +69,7 @@ public class GearModifierScreen extends AbstractElementScreen { this.lvlInput = this.addElement(createLvlInput()); createLvlButtons(); + createLegendaryButton(); // inner black window this.modifierList = new ModifierListContainer( @@ -97,12 +99,16 @@ public class GearModifierScreen extends AbstractElementScreen { this.lvlInput.setInput(String.valueOf(this.getCurrLvl() - 1)); } - private void updateModifierList() { + private void updateModifierList(boolean keepScroll) { + var oldScroll = this.modifierList.getScroll(); this.removeElement(this.modifierList); this.modifierList = new ModifierListContainer( Spatials.positionXY(7, 50).size(this.getGuiSpatial().width() - 14, this.getGuiSpatial().height() - 57), this) .layout(this.translateWorldSpatial()); + if (keepScroll) { + this.modifierList.setScroll(oldScroll); + } this.addElement(this.modifierList); ScreenLayout.requestLayout(); @@ -149,7 +155,7 @@ public class GearModifierScreen extends AbstractElementScreen { this.addElement(tab); } this.currIndex = tabIndex; - updateModifierList(); + updateModifierList(false); } private TextInputElement createLvlInput() { @@ -163,7 +169,7 @@ public class GearModifierScreen extends AbstractElementScreen { editBox.setMaxLength(3); editBox.setValue(String.valueOf(VaultBarOverlay.vaultLevel)); }); - inputElement.onTextChanged(s -> updateModifierList()); + inputElement.onTextChanged(s -> updateModifierList(true)); return inputElement; } @@ -206,6 +212,31 @@ public class GearModifierScreen extends AbstractElementScreen { this.addElement(btnPlus); } + private void toggleLegend() { + this.legendary = !this.legendary; + updateLegendaryLabel(); + updateModifierList(true); + } + + private void updateLegendaryLabel() { + if (this.legendaryLabel != null) { + this.removeElement(this.legendaryLabel); + } + var formatting = this.legendary ? ChatFormatting.GOLD : ChatFormatting.WHITE; + this.legendaryLabel = new LabelElement<>(Spatials.positionXY(this.getGuiSpatial().width() - 5 - 13, 38), + new TextComponent("✦").withStyle(formatting), LabelTextStyle.defaultStyle()) + .layout(this.translateWorldSpatial()); + this.addElement(legendaryLabel); + } + + private void createLegendaryButton() { + updateLegendaryLabel(); + NineSliceButtonElement btnLegend = + new NineSliceButtonElement<>(Spatials.positionXY(this.getGuiSpatial().width() - 8 - 13, 35).size(14, 14), + ScreenTextures.BUTTON_EMPTY_TEXTURES, this::toggleLegend).layout(this.translateWorldSpatial()); + this.addElement(btnLegend); + } + private void createTabs() { for (int i = 0; i < VHatCanIRoll.getVaultGearItems().size(); i++) { addTab(i); @@ -226,6 +257,10 @@ public class GearModifierScreen extends AbstractElementScreen { this.translateWorldSpatial())); } + public boolean isLegendary() { + return legendary; + } + @Override public boolean keyPressed(int keyCode, int scanCode, int modifiers) { // left/right to increase/decrease lvl @@ -250,6 +285,10 @@ public class GearModifierScreen extends AbstractElementScreen { if (keyCode == InputConstants.KEY_TAB && hasShiftDown()) { switchTab((currIndex - 1 + VHatCanIRoll.getVaultGearItems().size()) % VHatCanIRoll.getVaultGearItems().size()); } + // alt to toggle legendary + if (keyCode == InputConstants.KEY_LALT || keyCode == InputConstants.KEY_RALT) { + toggleLegend(); + } return super.keyPressed(keyCode, scanCode, modifiers); } } \ No newline at end of file diff --git a/src/main/java/com/radimous/vhatcaniroll/Helper.java b/src/main/java/com/radimous/vhatcaniroll/Helper.java index f495743..d9349a4 100644 --- a/src/main/java/com/radimous/vhatcaniroll/Helper.java +++ b/src/main/java/com/radimous/vhatcaniroll/Helper.java @@ -1,11 +1,16 @@ package com.radimous.vhatcaniroll; +import com.radimous.vhatcaniroll.mixin.EffectConfigAccessor; import com.radimous.vhatcaniroll.mixin.VaultGearTierConfigAccessor; import iskallia.vault.config.gear.VaultGearTierConfig; import iskallia.vault.gear.attribute.VaultGearAttribute; import iskallia.vault.gear.attribute.VaultGearAttributeRegistry; +import iskallia.vault.gear.attribute.ability.AbilityLevelAttribute; +import iskallia.vault.gear.attribute.ability.special.base.SpecialAbilityModification; import iskallia.vault.gear.attribute.config.BooleanFlagGenerator; import iskallia.vault.gear.attribute.config.ConfigurableAttributeGenerator; +import iskallia.vault.gear.attribute.custom.EffectGearAttribute; +import iskallia.vault.init.ModConfigs; import iskallia.vault.util.TextComponentUtils; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; @@ -27,19 +32,19 @@ public class Helper { new ChatFormatting[]{ChatFormatting.RED, ChatFormatting.GREEN, ChatFormatting.BLUE, ChatFormatting.YELLOW, ChatFormatting.LIGHT_PURPLE, ChatFormatting.AQUA, ChatFormatting.WHITE}; - public static List getModifierList(int lvl, VaultGearTierConfig cfg) { + public static List getModifierList(int lvl, VaultGearTierConfig cfg, boolean legendary) { Map modifierGroup = ((VaultGearTierConfigAccessor) cfg).getModifierGroup(); ArrayList modList = new ArrayList<>(); for (VaultGearTierConfig.ModifierAffixTagGroup affixTagGroup : modifierGroup.keySet()) { - processAffixTagGroup(lvl, affixTagGroup, modifierGroup, modList); + processAffixTagGroup(lvl, affixTagGroup, modifierGroup, modList, legendary); } return modList; } private static void processAffixTagGroup(int lvl, VaultGearTierConfig.ModifierAffixTagGroup affixTagGroup, Map modifierGroup, - ArrayList modList) { + ArrayList modList, boolean legendary) { if (affixTagGroup.equals(VaultGearTierConfig.ModifierAffixTagGroup.ABILITY_ENHANCEMENT)) { return; } @@ -48,11 +53,17 @@ public class Helper { } modList.add(new TextComponent(affixTagGroup.toString().replace("_", " ")).withStyle(ChatFormatting.BOLD)); - Map groupCounts = countGroups(lvl, affixTagGroup, modifierGroup); + Map groupCounts = countGroups(lvl, affixTagGroup, modifierGroup, legendary); List grList = new ArrayList<>(); for (VaultGearTierConfig.ModifierTierGroup modifierTierGroup : modifierGroup.get(affixTagGroup)) { - ArrayList> mTierList = getModifierTiers(lvl, modifierTierGroup); + ArrayList> mTierList; + if (legendary) { + mTierList = getLegendaryModifierTiers(lvl, modifierTierGroup); + } else { + mTierList = getModifierTiers(lvl, modifierTierGroup); + } + if (mTierList.isEmpty()) { continue; } @@ -80,10 +91,16 @@ public class Helper { } private static Map countGroups(int lvl, VaultGearTierConfig.ModifierAffixTagGroup affixTagGroup, - Map modifierGroup) { + Map modifierGroup, + boolean legendary) { Map groupCounts = new HashMap<>(); for (VaultGearTierConfig.ModifierTierGroup modifierTierGroup : modifierGroup.get(affixTagGroup)) { - ArrayList> mTierList = getModifierTiers(lvl, modifierTierGroup); + ArrayList> mTierList; + if (legendary) { + mTierList = getLegendaryModifierTiers(lvl, modifierTierGroup); + } else { + mTierList = getModifierTiers(lvl, modifierTierGroup); + } if (mTierList.isEmpty()) { continue; } @@ -93,6 +110,26 @@ public class Helper { return groupCounts; } + private static ArrayList> getLegendaryModifierTiers(int lvl, + VaultGearTierConfig.ModifierTierGroup modifierTierGroup) { + + var res = new ArrayList>(); + var highest = modifierTierGroup.getHighestForLevel(lvl); + if (highest == null) { + return res; // empty + } + int index = Math.min(highest.getModifierTier() + 2, modifierTierGroup.size() - 1); + var legendTier = modifierTierGroup.get(index); + if (legendTier == null || legendTier.getWeight() == 0){ + return res; // empty + } + if (legendTier.getModifierConfiguration() instanceof BooleanFlagGenerator.BooleanFlag bf && + !bf.get()) { + return res; // empty + } + res.add(legendTier); + return res; // only one + } @NotNull private static ArrayList> getModifierTiers(int lvl, VaultGearTierConfig.ModifierTierGroup modifierTierGroup) { return modifierTierGroup.getModifiersForLevel(lvl).stream() @@ -115,39 +152,82 @@ public class Helper { } C minConfig = (C) val.get(0).getModifierConfiguration(); C maxConfig = (C) val.get(val.size() - 1).getModifierConfiguration(); - MutableComponent res = null; - if (val.size() > 1) { - res = atrGenerator.getConfigRangeDisplay(atr.getReader(), minConfig, maxConfig); - } + MutableComponent res; ResourceLocation atrRegName = atr.getRegistryName(); if (atrRegName == null) { return new TextComponent("ERR - NULL REGISTRY NAME"); } String atrName = atrRegName.toString(); - var minConfigDisplay = atrGenerator.getConfigDisplay(atr.getReader(), minConfig); - if (res == null && minConfigDisplay != null) { + var minConfigDisplay = atrGenerator.getConfigDisplay(atr.getReader(), minConfig); + var maxConfigDisplay = atrGenerator.getConfigDisplay(atr.getReader(), maxConfig); + + if (val.size() > 1) { + // range + res = atrGenerator.getConfigRangeDisplay(atr.getReader(), minConfig, maxConfig); + + if (res != null && minConfig instanceof AbilityLevelAttribute.Config minConfigAbility) { + return abilityLvlComponent(res, atr, minConfigAbility); + } + if (res != null && atrName.equals("the_vault:wendarr_affinity")) { + return res.append(" God Affinity").withStyle(atr.getReader().getColoredTextStyle()); + } + if (atrName.equals("the_vault:effect_avoidance") && minConfigDisplay != null) { + // res -> "30% - 50%" + // single -> "30% Poison Avoidance" + // minRange -> "30%" + var single = minConfigDisplay.withStyle(atr.getReader().getColoredTextStyle()); + var minRange = atrGenerator.getConfigRangeDisplay(atr.getReader(), minConfig, minConfig); + if (minRange != null && res != null) { + res.append(single.getString().replace(minRange.getString(), "")); + // res -> "30% - 50% Poison Avoidance" + } + } + if (minConfig instanceof EffectGearAttribute.Config minEffectConfig + && maxConfig instanceof EffectGearAttribute.Config + && maxConfigDisplay != null) { + var effectStr = ((EffectConfigAccessor)minEffectConfig).getAmplifier() + "-" + + maxConfigDisplay.getString(); + return new TextComponent(effectStr).withStyle(atr.getReader().getColoredTextStyle()); + + } + if (res != null) { + return atr.getReader().formatConfigDisplay(LogicalSide.CLIENT, res); + } + } + if (minConfigDisplay != null) { res = minConfigDisplay.withStyle(atr.getReader().getColoredTextStyle()); - if (atrName.equals("the_vault:added_ability_level")) { - return res.append(" added ability levels").withStyle(atr.getReader().getColoredTextStyle()); + if (minConfig instanceof AbilityLevelAttribute.Config minConfigAbility) { + return abilityLvlComponent(res, atr, minConfigAbility); } if (atrName.equals("the_vault:wendarr_affinity")) { return TextComponentUtils.replace(TextComponentUtils.createSourceStack(LogicalSide.CLIENT), res, "Wendarr Affinity", new TextComponent("God Affinity")) .withStyle(atr.getReader().getColoredTextStyle()); } + if (minConfig instanceof EffectGearAttribute.Config ) { + return minConfigDisplay; + } return res; } - if (res != null && atrName.equals("the_vault:added_ability_level")) { + return new TextComponent("ERR - NULL DISPLAY " + atrName); + } + private static Component abilityLvlComponent(MutableComponent res, VaultGearAttribute atr, + AbilityLevelAttribute.Config minConfig) { + + if (Config.COMBINE_LVL_TO_ABILITIES.get()) { return res.append(" added ability levels").withStyle(atr.getReader().getColoredTextStyle()); + } else { + var abComp = new TextComponent("+").withStyle(atr.getReader().getColoredTextStyle()); + var optSkill = ModConfigs.ABILITIES.getAbilityById(minConfig.getAbilityKey()); + if (optSkill.isEmpty()) { + return res.append(" added ability levels").withStyle(atr.getReader().getColoredTextStyle()); + } + var abName = optSkill.get().getName(); + abComp.append(res); + abComp.append(" to level of "); + abComp.append(new TextComponent(abName).withStyle(SpecialAbilityModification.getAbilityStyle())); + return abComp; } - if (res != null && atrName.equals("the_vault:wendarr_affinity")) { - return res.append(" God Affinity").withStyle(atr.getReader().getColoredTextStyle()); - } - if (atrName.equals("the_vault:effect_avoidance") && minConfigDisplay != null) { - var single = minConfigDisplay.withStyle(atr.getReader().getColoredTextStyle()); - res.append(single.getString().replace(minConfigDisplay.getString(), "")); - } - return atr.getReader().formatConfigDisplay(LogicalSide.CLIENT, res); } } diff --git a/src/main/java/com/radimous/vhatcaniroll/ModifierListContainer.java b/src/main/java/com/radimous/vhatcaniroll/ModifierListContainer.java index 79c233e..010a6e8 100644 --- a/src/main/java/com/radimous/vhatcaniroll/ModifierListContainer.java +++ b/src/main/java/com/radimous/vhatcaniroll/ModifierListContainer.java @@ -19,15 +19,17 @@ public class ModifierListContainer extends VerticalScrollClipContainer optCfg = VaultGearTierConfig.getConfig(parent.getCurrGear()); LabelElement itemName = new LabelElement<>( Spatials.positionXY(k, 5).width(this.innerWidth() - k).height(15), new TextComponent( - parent.getCurrGear().getItem().toString().toUpperCase() + " - LVL " + parent.getCurrLvl()).withStyle(ChatFormatting.UNDERLINE), LabelTextStyle.defaultStyle() + parent.getCurrGear().getItem().toString().toUpperCase() + " - LVL " + parent.getCurrLvl()) + .withStyle(ChatFormatting.UNDERLINE).withStyle(legendary ? ChatFormatting.GOLD : ChatFormatting.WHITE), LabelTextStyle.defaultStyle() ); this.addElement(itemName); if (optCfg.isPresent()) { VaultGearTierConfig cfg = optCfg.get(); - for (var modifier : Helper.getModifierList(parent.getCurrLvl(), cfg)) { + for (var modifier : Helper.getModifierList(parent.getCurrLvl(), cfg, legendary)) { LabelElement labelelement = new LabelElement<>( Spatials.positionXY(k, i).width(this.innerWidth() - k).height(15), modifier, LabelTextStyle.defaultStyle() ); @@ -41,6 +43,12 @@ public class ModifierListContainer extends VerticalScrollClipContainer world.width(21).height(21).translateX(gui.right() + 5).translateY(this.getTabContentSpatial().bottom() + 109) + (screen, gui, parent, world) -> world.width(21).height(21).translateX(gui.right() + Config.BUTTON_X.get()).translateY(this.getTabContentSpatial().bottom() + Config.BUTTON_Y.get()) ) .tooltip((tooltipRenderer, poseStack, mouseX, mouseY, tooltipFlag) -> { tooltipRenderer.renderTooltip(poseStack, List.of(new TextComponent("Gear modifiers")), mouseX, mouseY, ItemStack.EMPTY, TooltipDirection.RIGHT); @@ -59,7 +59,7 @@ public class StatisticsElementContainerScreenMixin extends AbstractSkillTabEleme this.addElement( new FakeItemSlotElement<>(Spatials.positionXY(-3, 3), () -> new ItemStack(ModItems.CHESTPLATE), () -> false, ScreenTextures.EMPTY, ScreenTextures.EMPTY ).layout( - (screen, gui, parent, world) -> world.width(21).height(21).translateX(gui.right() + 5).translateY(this.getTabContentSpatial().bottom() + 109) + (screen, gui, parent, world) -> world.width(21).height(21).translateX(gui.right() + Config.BUTTON_X.get()).translateY(this.getTabContentSpatial().bottom() + Config.BUTTON_Y.get()) ) .tooltip((tooltipRenderer, poseStack, mouseX, mouseY, tooltipFlag) -> { tooltipRenderer.renderTooltip(poseStack, List.of(new TextComponent("Gear modifiers")), mouseX, mouseY, ItemStack.EMPTY, TooltipDirection.RIGHT); diff --git a/src/main/resources/vhatcaniroll.mixins.json b/src/main/resources/vhatcaniroll.mixins.json index 721fe39..ee97764 100644 --- a/src/main/resources/vhatcaniroll.mixins.json +++ b/src/main/resources/vhatcaniroll.mixins.json @@ -5,10 +5,11 @@ "compatibilityLevel": "JAVA_8", "refmap": "vhatcaniroll.refmap.json", "mixins": [ + "EffectConfigAccessor" ], "client": [ - "VaultGearTierConfigAccessor", - "StatisticsElementContainerScreenMixin" + "StatisticsElementContainerScreenMixin", + "VaultGearTierConfigAccessor" ], "injectors": { "defaultRequire": 1