Apotheosis

Apotheosis

81M Downloads

[Suggestion] QoL feature - static enchantment XP cost.

LuciusV opened this issue ยท 2 comments

commented

I propose to make enchanting at enchantment table cost for level X fixed at value XP(level X) - XP(level X-3)
Example:
if I enchant item at lvl200 and have xp exactly for level 200, enchanting would substract that much xp so I'll left with 197 level.
But if I do same enchant at level 1000, I will end up at level 997 (and lose a lot of xp - difference between 1000 and 997 level).
Because it's very easy to place some king of experience obelisk and dump extra levels before enchanting, I'm suggesting this quality of life feature to only substract experience equal to level of enchanting, regardless of player's current level.

Same can be done with reforging table

commented

Shouldn't this already be the case?
(When you enchant sth. you get displayed the actual (raw) experience cost)

This also applies to the reforging table
(It doesn't show the actual (raw) cost but you don't lose x levels)

Cost is independent from player level:

/**
* Determines the level of the given enchantment table slot.
* An item with 0 enchantability cannot be enchanted, so this method returns zero.
* Slot 2 (the highest level slot) always receives a level equal to power * 2.
* Slot 1 recieves between 60% and 80% of Slot 2.
* Slot 0 receives between 20% and 40% of Slot 2.
*
* @param rand Pre-seeded random.
* @param num Enchantment Slot Number [0-2]
* @param eterna Enchantment Power (Eterna Level)
* @param stack Itemstack to be enchanted.
* @return The level that the table will use for this specific slot.
*/
public static int getEnchantmentCost(RandomSource rand, int num, float eterna, ItemStack stack) {
int level = Math.round(eterna * 2);
if (num == 2) return level;
float lowBound = 0.6F - 0.4F * (1 - num);
float highBound = 0.8F - 0.4F * (1 - num);
return Math.max(1, Math.round(level * Mth.nextFloat(rand, lowBound, highBound)));
}

The calculated cost is then passed as level for this part:

/**
* Gets the experience cost when enchanting at a particular slot. This computes the true xp cost as if you had exactly as many levels as the level cost.
* <p>
* For a slot S and level L, the costs are the following:<br>
* S == 0 -> cost = XP(L)<br>
* S == 1 -> cost = XP(L) + XP(L-1)<br>
* S == 2 -> cost = XP(L) + XP(L-1) + XP(L-2)
* <p>
* And so on and so forth, if there were ever to be more than three slots.
*
* @param level The level of the slot
* @param slot The slot index
* @return The cost, in experience points, of buying the enchantment in a particular slot.
*/
public static int getExpCostForSlot(int level, int slot) {
int cost = 0;
for (int i = 0; i <= slot; i++) {
cost += EnchantmentUtils.getExperienceForLevel(level - i);
}
return cost - 1; // Eating exactly the amount will put you one point below the level, so offset by one here.
}

And charged here:
https://github.com/Shadows-of-Fire/Placebo/blob/eb42ba8e88a83f66c1c4413c9f1e4eb61214dca4/src/main/java/dev/shadowsoffire/placebo/util/EnchantmentUtils.java#L18-L29

    public static boolean chargeExperience(Player player, int cost) {
        final int playerExperience = getExperience(player);

        if (playerExperience >= cost) {
            player.giveExperiencePoints(-cost);

            // Due to rounding errors, the bar can get stuck displaying nothing when it should be empty.
            if (getExperience(player) <= 0) player.experienceProgress = 0F;
            return true;
        }
        return false;
    }
commented

Yeah this is already a thing (and has been so for a while now).