diff --git a/gradle.properties b/gradle.properties index f9ffbb9..32154ad 100644 --- a/gradle.properties +++ b/gradle.properties @@ -53,7 +53,7 @@ mod_name=Ascend: SbA # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. mod_license=All Rights Reserved # The mod version. See https://semver.org/ -mod_version=1.2.0 +mod_version=2.0.0 # 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/net/fretux/ascend/client/screen/ShrineScreen.java b/src/main/java/net/fretux/ascend/client/screen/ShrineScreen.java index ca27c90..5af91ac 100644 --- a/src/main/java/net/fretux/ascend/client/screen/ShrineScreen.java +++ b/src/main/java/net/fretux/ascend/client/screen/ShrineScreen.java @@ -20,9 +20,17 @@ public class ShrineScreen extends Screen { private int dialogueStage = 0; // 0 = intro, 1 = offer, 2 = confirm private int playerKnowledge = 0; + private final boolean essenceMode; + public ShrineScreen(boolean essenceMode) { + super(essenceMode + ? Component.literal("Remembrance Essence") + : Component.literal("Shrine of Remembrance")); + this.essenceMode = essenceMode; + } + public ShrineScreen() { - super(Component.literal("Shrine of Remembrance")); + this(false); } @Override @@ -45,6 +53,33 @@ public class ShrineScreen extends Screen { this.clearWidgets(); int buttonY = topPos + 85; + // ESSENCE MODE — skip all dialogue, go straight to options + if (essenceMode) { + addRenderableWidget(Button.builder(Component.literal("FORGET"), (btn) -> { + PacketHandler.INSTANCE.sendToServer(new ServerboundShrineChoicePacket("forget")); + Minecraft.getInstance().setScreen(null); + }).bounds(leftPos + 20, buttonY, WIDTH - 40, 20).build()); + + int y = buttonY + 25; + + addRenderableWidget(Button.builder(Component.literal("UNDERSTAND"), (btn) -> { + PacketHandler.INSTANCE.sendToServer(new ServerboundShrineChoicePacket("understand")); + Minecraft.getInstance().setScreen(null); + }).bounds(leftPos + 20, y, WIDTH - 40, 20).build()); + y += 25; + + addRenderableWidget(Button.builder(Component.literal("REST"), (btn) -> { + PacketHandler.INSTANCE.sendToServer(new ServerboundShrineChoicePacket("rest")); + Minecraft.getInstance().setScreen(null); + }).bounds(leftPos + 20, y, WIDTH - 40, 20).build()); + y += 25; + + addRenderableWidget(Button.builder(Component.literal("LEAVE"), (btn) -> { + Minecraft.getInstance().setScreen(null); + }).bounds(leftPos + 20, y, WIDTH - 40, 20).build()); + + return; + } switch (dialogueStage) { case 0 -> { // Intro Button engageButton = Button.builder(Component.literal("I WISH TO ENGAGE IN A DEAL."), (btn) -> { diff --git a/src/main/java/net/fretux/ascend/compat/IronsSpellbooksCompat.java b/src/main/java/net/fretux/ascend/compat/IronsSpellbooksCompat.java index 0d6367f..314584e 100644 --- a/src/main/java/net/fretux/ascend/compat/IronsSpellbooksCompat.java +++ b/src/main/java/net/fretux/ascend/compat/IronsSpellbooksCompat.java @@ -57,7 +57,7 @@ public class IronsSpellbooksCompat { int willpower = stats.getAttributeLevel("willpower"); applyIntelligence(player, intelligence); - applyCharisma(player, charisma); // now also handles support/summons internally + applyCharisma(player, charisma); applyMagicScaling(player, magicScaling); applyWillpowerCastEfficiency(player, willpower); }); @@ -73,20 +73,10 @@ public class IronsSpellbooksCompat { (Attribute) AttributeRegistry.MAX_MANA.get(), INT_MAX_MANA_UUID, "Ascend INT max mana", - intelligence * 2.0d + intelligence * 3.0d ); - double spellPowerPerPoint = 0.004d; - double spellPowerMax = 0.40d; - double spellPowerBonus = Math.min(intelligence * spellPowerPerPoint, spellPowerMax); - applyMultiplyBaseModifier( - player, - (Attribute) AttributeRegistry.SPELL_POWER.get(), - INT_SPELL_POWER_UUID, - "Ascend INT spell power", - spellPowerBonus - ); - double regenPerPoint = 0.002d; - double regenMax = 0.25d; + double regenPerPoint = 0.004d; + double regenMax = 0.40d; double regenBonus = Math.min(intelligence * regenPerPoint, regenMax); applyMultiplyBaseModifier( player, @@ -95,23 +85,11 @@ public class IronsSpellbooksCompat { "Ascend INT mana regen", regenBonus ); - double cdrPerPoint = 0.0015d; - double cdrMax = 0.20d; - double cdrBonus = Math.min(intelligence * cdrPerPoint, cdrMax); - applyMultiplyBaseModifier( - player, - (Attribute) AttributeRegistry.COOLDOWN_REDUCTION.get(), - INT_COOLDOWN_REDUCTION_UUID, - "Ascend INT cooldown reduction", - cdrBonus - ); } private static void clearIntelligence(Player player) { removeModifier(player, (Attribute) AttributeRegistry.MAX_MANA.get(), INT_MAX_MANA_UUID); - removeModifier(player, (Attribute) AttributeRegistry.SPELL_POWER.get(), INT_SPELL_POWER_UUID); removeModifier(player, (Attribute) AttributeRegistry.MANA_REGEN.get(), INT_MANA_REGEN_UUID); - removeModifier(player, (Attribute) AttributeRegistry.COOLDOWN_REDUCTION.get(), INT_COOLDOWN_REDUCTION_UUID); } public static void applyWillpowerCastEfficiency(Player player, int willpower) { @@ -152,7 +130,7 @@ public class IronsSpellbooksCompat { if (charisma <= 0) { return; } - double manaPerPoint = 0.5d; + double manaPerPoint = 1.5d; double bonusMana = charisma * manaPerPoint; applyAddModifier( player, @@ -221,8 +199,8 @@ public class IronsSpellbooksCompat { clearMagicScaling(player); return; } - double spPerPoint = 0.006d; - double spMax = 0.60d; + double spPerPoint = 0.0075d; + double spMax = 0.75d; double spBonus = Math.min(magicScaling * spPerPoint, spMax); applyMultiplyBaseModifier( player, @@ -231,19 +209,8 @@ public class IronsSpellbooksCompat { "Ascend Magic Scaling spell power", spBonus ); - double regenPerPoint = 0.001d; - double regenMax = 0.15d; - double regenBonus = Math.min(magicScaling * regenPerPoint, regenMax); - applyMultiplyBaseModifier( - player, - (Attribute) AttributeRegistry.MANA_REGEN.get(), - MAG_MANA_REGEN_UUID, - "Ascend Magic Scaling mana regen", - regenBonus - ); - - double cdrPerPoint = 0.001d; - double cdrMax = 0.10d; + double cdrPerPoint = 0.0012d; + double cdrMax = 0.18d; double cdrBonus = Math.min(magicScaling * cdrPerPoint, cdrMax); applyMultiplyBaseModifier( player, @@ -256,7 +223,6 @@ public class IronsSpellbooksCompat { private static void clearMagicScaling(Player player) { removeModifier(player, (Attribute) AttributeRegistry.SPELL_POWER.get(), MAG_SPELL_POWER_UUID); - removeModifier(player, (Attribute) AttributeRegistry.MANA_REGEN.get(), MAG_MANA_REGEN_UUID); removeModifier(player, (Attribute) AttributeRegistry.COOLDOWN_REDUCTION.get(), MAG_COOLDOWN_REDUCTION_UUID); } diff --git a/src/main/java/net/fretux/ascend/datagen/AscendDataGenerators.java b/src/main/java/net/fretux/ascend/datagen/AscendDataGenerators.java index 9010af3..af5516f 100644 --- a/src/main/java/net/fretux/ascend/datagen/AscendDataGenerators.java +++ b/src/main/java/net/fretux/ascend/datagen/AscendDataGenerators.java @@ -24,5 +24,7 @@ public class AscendDataGenerators { generator.addProvider(event.includeClient(), new AscendItemModelProvider(output, existingFileHelper)); generator.addProvider(event.includeServer(), new ModLootTableProvider(output)); generator.addProvider(event.includeServer(), new ModWorldGenProvider(output, event.getLookupProvider())); + generator.addProvider(event.includeServer(), new ModBlockTagProvider(output, event.getLookupProvider(), existingFileHelper)); + } } \ No newline at end of file diff --git a/src/main/java/net/fretux/ascend/datagen/AscendItemModelProvider.java b/src/main/java/net/fretux/ascend/datagen/AscendItemModelProvider.java index ad5d42e..c3c4361 100644 --- a/src/main/java/net/fretux/ascend/datagen/AscendItemModelProvider.java +++ b/src/main/java/net/fretux/ascend/datagen/AscendItemModelProvider.java @@ -19,6 +19,7 @@ public class AscendItemModelProvider extends ItemModelProvider { protected void registerModels() { assert ModItems.MOONSEYE_TOME.getId() != null; basicItem(ModItems.MOONSEYE_TOME.getId().getPath()); + basicItem(ModItems.REMEMBRANCE_ESSENCE.getId().getPath()); withExistingParent(ModBlocks.SHRINE_OF_REMEMBRANCE.getId().getPath(), modLoc("block/" + ModBlocks.SHRINE_OF_REMEMBRANCE.getId().getPath())); } diff --git a/src/main/java/net/fretux/ascend/datagen/ModBlockLootProvider.java b/src/main/java/net/fretux/ascend/datagen/ModBlockLootProvider.java index e5f0fa0..70a4f30 100644 --- a/src/main/java/net/fretux/ascend/datagen/ModBlockLootProvider.java +++ b/src/main/java/net/fretux/ascend/datagen/ModBlockLootProvider.java @@ -1,6 +1,7 @@ package net.fretux.ascend.datagen; import net.fretux.ascend.registry.ModBlocks; +import net.fretux.ascend.registry.ModItems; import net.minecraft.data.loot.BlockLootSubProvider; import net.minecraft.world.flag.FeatureFlags; @@ -14,7 +15,8 @@ public class ModBlockLootProvider extends BlockLootSubProvider { @Override protected void generate() { - + this.add(ModBlocks.SHRINE_OF_REMEMBRANCE.get(), + createSingleItemTable(ModItems.REMEMBRANCE_ESSENCE.get())); } @Override diff --git a/src/main/java/net/fretux/ascend/datagen/ModBlockTagProvider.java b/src/main/java/net/fretux/ascend/datagen/ModBlockTagProvider.java new file mode 100644 index 0000000..c67c7d1 --- /dev/null +++ b/src/main/java/net/fretux/ascend/datagen/ModBlockTagProvider.java @@ -0,0 +1,26 @@ +package net.fretux.ascend.datagen; + +import net.fretux.ascend.AscendMod; +import net.fretux.ascend.registry.ModBlocks; +import net.minecraft.core.HolderLookup; +import net.minecraft.data.PackOutput; +import net.minecraft.tags.BlockTags; +import net.minecraftforge.common.data.BlockTagsProvider; +import net.minecraftforge.common.data.ExistingFileHelper; + +import java.util.concurrent.CompletableFuture; + +public class ModBlockTagProvider extends BlockTagsProvider { + + public ModBlockTagProvider(PackOutput output, CompletableFuture provider, ExistingFileHelper existing) { + super(output, provider, AscendMod.MODID, existing); + } + + @Override + protected void addTags(HolderLookup.Provider provider) { + tag(BlockTags.MINEABLE_WITH_PICKAXE) + .add(ModBlocks.SHRINE_OF_REMEMBRANCE.get()); + tag(BlockTags.NEEDS_DIAMOND_TOOL) + .add(ModBlocks.SHRINE_OF_REMEMBRANCE.get()); + } +} diff --git a/src/main/java/net/fretux/ascend/item/RemembranceEssenceItem.java b/src/main/java/net/fretux/ascend/item/RemembranceEssenceItem.java new file mode 100644 index 0000000..f628bb1 --- /dev/null +++ b/src/main/java/net/fretux/ascend/item/RemembranceEssenceItem.java @@ -0,0 +1,40 @@ +package net.fretux.ascend.item; + +import net.fretux.ascend.network.PacketHandler; +import net.fretux.ascend.network.ServerboundShrineChoicePacket; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; + +public class RemembranceEssenceItem extends Item { + + public RemembranceEssenceItem(Properties props) { + super(props); + } + + @Override + public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { + ItemStack stack = player.getItemInHand(hand); + if (!level.isClientSide) { + player.sendSystemMessage(Component.literal("THE ESSENCE WHISPERS...")); + PacketHandler.sendToPlayerOpenEssenceUI((ServerPlayer) player); + } + return InteractionResultHolder.sidedSuccess(stack, level.isClientSide()); + } + + // Essence is consumed after the action is performed + public static void consume(Player player) { + for (InteractionHand hand : InteractionHand.values()) { + ItemStack item = player.getItemInHand(hand); + if (item.getItem() instanceof RemembranceEssenceItem) { + item.shrink(1); + return; + } + } + } +} diff --git a/src/main/java/net/fretux/ascend/network/ClientboundOpenEssenceScreenPacket.java b/src/main/java/net/fretux/ascend/network/ClientboundOpenEssenceScreenPacket.java new file mode 100644 index 0000000..36593b1 --- /dev/null +++ b/src/main/java/net/fretux/ascend/network/ClientboundOpenEssenceScreenPacket.java @@ -0,0 +1,18 @@ +package net.fretux.ascend.network; + +import net.fretux.ascend.client.screen.ShrineScreen; +import net.minecraft.client.Minecraft; +import net.minecraftforge.network.NetworkEvent; + +import java.util.function.Supplier; + +public class ClientboundOpenEssenceScreenPacket { + public ClientboundOpenEssenceScreenPacket() {} + + public static void handle(ClientboundOpenEssenceScreenPacket msg, Supplier ctx) { + ctx.get().enqueueWork(() -> { + Minecraft.getInstance().setScreen(new ShrineScreen(true)); + }); + ctx.get().setPacketHandled(true); + } +} diff --git a/src/main/java/net/fretux/ascend/network/PacketHandler.java b/src/main/java/net/fretux/ascend/network/PacketHandler.java index a3900f4..e906196 100644 --- a/src/main/java/net/fretux/ascend/network/PacketHandler.java +++ b/src/main/java/net/fretux/ascend/network/PacketHandler.java @@ -2,8 +2,10 @@ package net.fretux.ascend.network; import net.fretux.ascend.AscendMod; import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; import net.minecraftforge.network.NetworkDirection; import net.minecraftforge.network.NetworkRegistry; +import net.minecraftforge.network.PacketDistributor; import net.minecraftforge.network.simple.SimpleChannel; public class PacketHandler { @@ -35,5 +37,16 @@ public class PacketHandler { ServerboundShrineChoicePacket::toBytes, ServerboundShrineChoicePacket::new, ServerboundShrineChoicePacket::handle); + INSTANCE.registerMessage(id++, + ClientboundOpenEssenceScreenPacket.class, + (msg, buf) -> { + }, + buf -> new ClientboundOpenEssenceScreenPacket(), + ClientboundOpenEssenceScreenPacket::handle + ); + } + + public static void sendToPlayerOpenEssenceUI(ServerPlayer player) { + INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new ClientboundOpenEssenceScreenPacket()); } } \ No newline at end of file diff --git a/src/main/java/net/fretux/ascend/player/PlayerStats.java b/src/main/java/net/fretux/ascend/player/PlayerStats.java index 34694b0..bc43285 100644 --- a/src/main/java/net/fretux/ascend/player/PlayerStats.java +++ b/src/main/java/net/fretux/ascend/player/PlayerStats.java @@ -49,12 +49,14 @@ public class PlayerStats { public int getAscendXP() { return ascendXP; } - + public int getXPToNextAscendLevel() { if (ascendLevel >= MAX_ASCEND_LEVEL) return 0; - return 100 * ascendLevel; + double base = 100.0; + double growth = 1.3; + return (int) Math.ceil(base * Math.pow(growth, ascendLevel - 1)); } - + public int getUnspentPoints() { return unspentPoints; } diff --git a/src/main/java/net/fretux/ascend/registry/ModBlocks.java b/src/main/java/net/fretux/ascend/registry/ModBlocks.java index 72b4322..144d950 100644 --- a/src/main/java/net/fretux/ascend/registry/ModBlocks.java +++ b/src/main/java/net/fretux/ascend/registry/ModBlocks.java @@ -21,11 +21,10 @@ public class ModBlocks { () -> new ShrineOfRemembranceBlock( BlockBehaviour.Properties.of() .mapColor(MapColor.COLOR_PURPLE) - .strength(-1.0F, 3600000.0F) // unbreakable - .noLootTable() + .strength(50.0F, 1200.0F) + .requiresCorrectToolForDrops() .lightLevel(s -> 6) .noOcclusion() - .requiresCorrectToolForDrops() ) ); diff --git a/src/main/java/net/fretux/ascend/registry/ModItems.java b/src/main/java/net/fretux/ascend/registry/ModItems.java index 6031712..f457270 100644 --- a/src/main/java/net/fretux/ascend/registry/ModItems.java +++ b/src/main/java/net/fretux/ascend/registry/ModItems.java @@ -2,6 +2,7 @@ package net.fretux.ascend.registry; import net.fretux.ascend.AscendMod; import net.fretux.ascend.item.MoonseyeTome; +import net.fretux.ascend.item.RemembranceEssenceItem; import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.Component; import net.minecraft.world.item.CreativeModeTab; @@ -24,12 +25,17 @@ public class ModItems { .stacksTo(1) .rarity(Rarity.RARE)) ); + public static final RegistryObject REMEMBRANCE_ESSENCE = ITEMS.register( + "remembrance_essence", + () -> new RemembranceEssenceItem(new Item.Properties().stacksTo(1)) + ); public static final RegistryObject ASCEND_TAB = TABS.register("ascend_tab", () -> CreativeModeTab.builder() .title(Component.translatable("itemGroup.ascend")) .icon(() -> new ItemStack(MOONSEYE_TOME.get())) .displayItems((params, output) -> { output.accept(MOONSEYE_TOME.get()); + output.accept(REMEMBRANCE_ESSENCE.get()); }) .build() ); diff --git a/src/main/java/net/fretux/ascend/worldgen/SimpleShrineStructure.java b/src/main/java/net/fretux/ascend/worldgen/SimpleShrineStructure.java index b3c16fb..4f38c05 100644 --- a/src/main/java/net/fretux/ascend/worldgen/SimpleShrineStructure.java +++ b/src/main/java/net/fretux/ascend/worldgen/SimpleShrineStructure.java @@ -23,6 +23,7 @@ public class SimpleShrineStructure extends Structure { @Override protected Optional findGenerationPoint(GenerationContext ctx) { BlockPos pos = ctx.chunkPos().getMiddleBlockPosition(0); + int y = ctx.chunkGenerator().getFirstFreeHeight( pos.getX(), pos.getZ(), @@ -31,8 +32,28 @@ public class SimpleShrineStructure extends Structure { ctx.randomState() ); BlockPos finalPos = new BlockPos(pos.getX(), y, pos.getZ()); + if (!isValidShrineLocation(ctx, finalPos)) { + return Optional.empty(); + } return Optional.of(new GenerationStub(finalPos, builder -> { builder.addPiece(new ShrinePiece(finalPos)); })); } + + private boolean isValidShrineLocation(GenerationContext ctx, BlockPos pos) { + var column = ctx.chunkGenerator().getBaseColumn( + pos.getX(), + pos.getZ(), + ctx.heightAccessor(), + ctx.randomState() + ); + var groundState = column.getBlock(pos.getY() - 1); + if (!groundState.getFluidState().isEmpty()) return false; + if (!groundState.isSolid()) return false; + if (groundState.canBeReplaced()) return false; + if (groundState.is(net.minecraft.tags.BlockTags.SAND)) return false; + if (groundState.is(net.minecraft.tags.BlockTags.SNOW)) return false; + if (groundState.is(net.minecraft.tags.BlockTags.LEAVES)) return false; + return true; + } } diff --git a/src/main/resources/assets/ascend/lang/en_us.json b/src/main/resources/assets/ascend/lang/en_us.json index 2f607c4..2737ed2 100644 --- a/src/main/resources/assets/ascend/lang/en_us.json +++ b/src/main/resources/assets/ascend/lang/en_us.json @@ -14,7 +14,7 @@ "ascend.attribute.fortitude": "Fortitude", "ascend.attribute.fortitude.desc": "Increases max health and knockback resistance.", "ascend.attribute.intelligence": "Intelligence", - "ascend.attribute.intelligence.desc": "Boosts mana, spell power, mana regen & cooldown reduction (with Iron's Spellbooks).", + "ascend.attribute.intelligence.desc": "Increases max mana and mana regeneration. Also lowers enchantment cost and buffs potions.", "ascend.attribute.willpower": "Willpower", "ascend.attribute.willpower.desc": "Reduces sanity drain and improves stamina/tempo.", "ascend.attribute.charisma": "Charisma", @@ -26,7 +26,7 @@ "ascend.attribute.heavy_scaling": "Heavy Scaling", "ascend.attribute.heavy_scaling.desc": "Improves heavy weapon performance.", "ascend.attribute.magic_scaling": "Magic Scaling", - "ascend.attribute.magic_scaling.desc": "Increases spell power and mana efficiency for scaling spells.", + "ascend.attribute.magic_scaling.desc": "Increases spell power, spell damage, and spell cooldown reduction.", "item.ascend.moonseye_tome": "Moonseye Tome", "item.ascend.moonseye_tome.desc": "A forbidden scripture that reveals knowledge of the Depths. Grants 100 Knowledge on first use, 50 afterwards.", "item.ascend.moonseye_tome.used": "You gained %s Knowledge from the Moonseye Tome!", diff --git a/src/main/resources/assets/ascend/textures/item/remembrance_essence.png b/src/main/resources/assets/ascend/textures/item/remembrance_essence.png new file mode 100644 index 0000000..2d6fbed Binary files /dev/null and b/src/main/resources/assets/ascend/textures/item/remembrance_essence.png differ