Implement fortitude and intelligence scaling

This commit is contained in:
2025-11-08 15:14:38 +01:00
parent c9da949e45
commit 73a4f2549f
5 changed files with 239 additions and 8 deletions
@@ -0,0 +1,52 @@
package net.fretux.ascend.event;
import net.fretux.ascend.AscendMod;
import net.fretux.ascend.player.PlayerStatsProvider;
import net.minecraft.world.effect.MobEffectCategory;
import net.minecraft.world.entity.player.Player;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.entity.living.MobEffectEvent;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber(modid = AscendMod.MODID)
public class FortitudeDefenseEvents {
@SubscribeEvent
public static void onHarmfulEffectApplicable(MobEffectEvent.Applicable event) {
if (!(event.getEntity() instanceof Player player)) return;
if (player.level().isClientSide) return;
if (event.getEffectInstance() == null) return;
if (event.getEffectInstance().getEffect().getCategory() != MobEffectCategory.HARMFUL) return;
player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> {
int fortitude = stats.getAttributeLevel("fortitude");
if (fortitude <= 0) return;
double perPoint = 0.004d;
double max = 0.5d;
double chance = Math.min(fortitude * perPoint, max);
if (chance > 0 && player.getRandom().nextDouble() < chance) {
event.setResult(Event.Result.DENY);
}
});
}
@SubscribeEvent
public static void onPlayerTickFortitudeCleanse(TickEvent.PlayerTickEvent event) {
Player player = event.player;
if (player.level().isClientSide || event.phase != TickEvent.Phase.END) return;
player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> {
int fortitude = stats.getAttributeLevel("fortitude");
if (fortitude <= 0) return;
if (player.tickCount % 40 != 0) return;
double perPoint = 0.003d;
double max = 0.4d;
double chance = Math.min(fortitude * perPoint, max);
if (chance <= 0) return;
if (player.getRandom().nextDouble() >= chance) return;
player.getActiveEffects().stream()
.filter(inst -> inst.getEffect().getCategory() == MobEffectCategory.HARMFUL)
.findAny()
.ifPresent(inst -> player.removeEffect(inst.getEffect()));
});
}
}
@@ -0,0 +1,42 @@
package net.fretux.ascend.event;
import net.fretux.ascend.AscendMod;
import net.fretux.ascend.player.PlayerStatsProvider;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.player.Player;
import net.minecraftforge.event.enchanting.EnchantmentLevelSetEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber(modid = AscendMod.MODID)
public class IntelligenceEnchantmentEvents {
@SubscribeEvent
public static void onEnchantmentLevelSet(EnchantmentLevelSetEvent event) {
if (!(event.getLevel() instanceof ServerLevel serverLevel)) {
return;
}
Player player = serverLevel.getNearestPlayer(
event.getPos().getX() + 0.5,
event.getPos().getY() + 0.5,
event.getPos().getZ() + 0.5,
5.0,
false
);
if (player == null) {
return;
}
player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> {
int intelligence = stats.getAttributeLevel("intelligence");
if (intelligence <= 0) return;
int original = event.getOriginalLevel();
if (original <= 0) return;
double perPoint = 0.005d;
double max = 0.40d;
double reduction = Math.min(intelligence * perPoint, max);
int newLevel = (int) Math.max(1, Math.floor(original * (1.0d - reduction)));
event.setEnchantLevel(newLevel);
});
}
}
@@ -0,0 +1,54 @@
package net.fretux.ascend.event;
import net.fretux.ascend.AscendMod;
import net.fretux.ascend.player.PlayerStatsProvider;
import net.minecraft.world.effect.MobEffectCategory;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.player.Player;
import net.minecraftforge.event.entity.living.MobEffectEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber(modid = AscendMod.MODID)
public class IntelligencePotionEvents {
@SubscribeEvent
public static void onBeneficialEffectAdded(MobEffectEvent.Added event) {
if (!(event.getEntity() instanceof Player player)) return;
if (player.level().isClientSide) return;
MobEffectInstance inst = event.getEffectInstance();
if (inst == null) return;
if (inst.getEffect().getCategory() != MobEffectCategory.BENEFICIAL) return;
// Avoid re-scaling already huge/custom durations.
if (inst.getDuration() > 12000) return;
player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> {
int intel = stats.getAttributeLevel("intelligence");
if (intel <= 0) return;
int baseDuration = inst.getDuration();
// +0.5% duration per INT, up to +50%
double durPerPoint = 0.005d;
double durMax = 0.5d;
double durBonus = Math.min(intel * durPerPoint, durMax);
int newDuration = (int) (baseDuration * (1.0d + durBonus));
if (newDuration <= baseDuration) return; // nothing to do
// Replace effect: remove original, add scaled.
// This will fire another Added event, but newDuration > 12000 guard prevents loops.
player.removeEffect(inst.getEffect());
player.addEffect(new MobEffectInstance(
inst.getEffect(),
newDuration,
inst.getAmplifier(),
inst.isAmbient(),
inst.isVisible(),
inst.showIcon()
));
});
}
}