implement sanity gameplay effects and improve insanity mechanics
This commit is contained in:
@@ -2,8 +2,7 @@ package net.fretux.mindmotion;
|
|||||||
|
|
||||||
import com.mojang.logging.LogUtils;
|
import com.mojang.logging.LogUtils;
|
||||||
import net.fretux.mindmotion.command.SanityCommand;
|
import net.fretux.mindmotion.command.SanityCommand;
|
||||||
import net.fretux.mindmotion.event.CombatEvents;
|
import net.fretux.mindmotion.event.CommonEvents;
|
||||||
import net.fretux.mindmotion.event.PlayerTickHandler;
|
|
||||||
import net.fretux.mindmotion.network.ModMessages;
|
import net.fretux.mindmotion.network.ModMessages;
|
||||||
import net.minecraftforge.common.MinecraftForge;
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
@@ -28,8 +27,7 @@ public class AscendMindMotion {
|
|||||||
net.fretux.mindmotion.client.ClientBootstrap.init(modEventBus)
|
net.fretux.mindmotion.client.ClientBootstrap.init(modEventBus)
|
||||||
);
|
);
|
||||||
MinecraftForge.EVENT_BUS.register(this);
|
MinecraftForge.EVENT_BUS.register(this);
|
||||||
MinecraftForge.EVENT_BUS.register(PlayerTickHandler.class);
|
MinecraftForge.EVENT_BUS.register(new CommonEvents());
|
||||||
MinecraftForge.EVENT_BUS.register(CombatEvents.class);
|
|
||||||
MinecraftForge.EVENT_BUS.register(SanityCommand.class);
|
MinecraftForge.EVENT_BUS.register(SanityCommand.class);
|
||||||
LOGGER.info("Ascend: Mind and Motion initialized!");
|
LOGGER.info("Ascend: Mind and Motion initialized!");
|
||||||
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, ConfigMM.CLIENT_SPEC);
|
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, ConfigMM.CLIENT_SPEC);
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ public final class ConfigMM {
|
|||||||
public final ForgeConfigSpec.DoubleValue BASE_SANITY_REGEN_LIGHT;
|
public final ForgeConfigSpec.DoubleValue BASE_SANITY_REGEN_LIGHT;
|
||||||
public final ForgeConfigSpec.DoubleValue BASE_SANITY_DECAY_DARK;
|
public final ForgeConfigSpec.DoubleValue BASE_SANITY_DECAY_DARK;
|
||||||
public final ForgeConfigSpec.BooleanValue ENABLE_LOW_SANITY_SOUNDS;
|
public final ForgeConfigSpec.BooleanValue ENABLE_LOW_SANITY_SOUNDS;
|
||||||
|
public final ForgeConfigSpec.BooleanValue ENABLE_SANITY_GAMEPLAY_EFFECTS;
|
||||||
public final ForgeConfigSpec.DoubleValue SCRATCHING_CHANCE;
|
public final ForgeConfigSpec.DoubleValue SCRATCHING_CHANCE;
|
||||||
public final ForgeConfigSpec.DoubleValue PANIC_CHANCE;
|
public final ForgeConfigSpec.DoubleValue PANIC_CHANCE;
|
||||||
public final ForgeConfigSpec.IntValue TEMPO_DECAY_DELAY;
|
public final ForgeConfigSpec.IntValue TEMPO_DECAY_DELAY;
|
||||||
@@ -104,6 +105,10 @@ public final class ConfigMM {
|
|||||||
.comment("Enable creepy noises when sanity is low.")
|
.comment("Enable creepy noises when sanity is low.")
|
||||||
.define("enableLowSanitySounds", true);
|
.define("enableLowSanitySounds", true);
|
||||||
|
|
||||||
|
ENABLE_SANITY_GAMEPLAY_EFFECTS = b
|
||||||
|
.comment("Enable gameplay penalties from low sanity and high insanity, beyond shaders and sounds.")
|
||||||
|
.define("enableSanityGameplayEffects", true);
|
||||||
|
|
||||||
b.pop().push("insanity");
|
b.pop().push("insanity");
|
||||||
|
|
||||||
SCRATCHING_CHANCE = b
|
SCRATCHING_CHANCE = b
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ public class CommonEvents {
|
|||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public void onPlayerHurt(LivingHurtEvent event) {
|
public void onPlayerHurt(LivingHurtEvent event) {
|
||||||
if (!(event.getEntity() instanceof net.minecraft.world.entity.player.Player player)) return;
|
if (!(event.getEntity() instanceof net.minecraft.world.entity.player.Player player)) return;
|
||||||
|
if (player.level().isClientSide) return;
|
||||||
|
|
||||||
player.getCapability(PlayerCapabilityProvider.SANITY).ifPresent(sanity -> sanity.reduceSanity(1));
|
player.getCapability(PlayerCapabilityProvider.SANITY).ifPresent(sanity -> sanity.reduceSanity(1));
|
||||||
player.getCapability(PlayerCapabilityProvider.TEMPO).ifPresent(tempo -> tempo.addTempo(4));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
@@ -20,7 +20,17 @@ public class CommonEvents {
|
|||||||
event.getOriginal().reviveCaps();
|
event.getOriginal().reviveCaps();
|
||||||
event.getEntity().getCapability(PlayerCapabilityProvider.SANITY).ifPresent(newCap ->
|
event.getEntity().getCapability(PlayerCapabilityProvider.SANITY).ifPresent(newCap ->
|
||||||
event.getOriginal().getCapability(PlayerCapabilityProvider.SANITY)
|
event.getOriginal().getCapability(PlayerCapabilityProvider.SANITY)
|
||||||
.ifPresent(oldCap -> newCap.setSanity(oldCap.getSanity()))
|
.ifPresent(oldCap -> {
|
||||||
|
newCap.setSanity(oldCap.getSanity());
|
||||||
|
newCap.setInsanity(oldCap.getInsanity());
|
||||||
|
})
|
||||||
|
);
|
||||||
|
event.getEntity().getCapability(PlayerCapabilityProvider.TEMPO).ifPresent(newCap ->
|
||||||
|
event.getOriginal().getCapability(PlayerCapabilityProvider.TEMPO)
|
||||||
|
.ifPresent(oldCap -> {
|
||||||
|
newCap.setTempo(oldCap.getTempo());
|
||||||
|
newCap.setVentCooldown(oldCap.getVentCooldown());
|
||||||
|
})
|
||||||
);
|
);
|
||||||
event.getOriginal().invalidateCaps();
|
event.getOriginal().invalidateCaps();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import net.minecraft.tags.BiomeTags;
|
|||||||
import net.minecraft.world.effect.MobEffectInstance;
|
import net.minecraft.world.effect.MobEffectInstance;
|
||||||
import net.minecraft.world.effect.MobEffects;
|
import net.minecraft.world.effect.MobEffects;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.entity.monster.Monster;
|
||||||
import net.minecraft.world.level.block.Blocks;
|
import net.minecraft.world.level.block.Blocks;
|
||||||
import net.minecraftforge.event.TickEvent;
|
import net.minecraftforge.event.TickEvent;
|
||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
@@ -189,7 +190,11 @@ public class PlayerTickHandler {
|
|||||||
insanity = sanity.getInsanity();
|
insanity = sanity.getInsanity();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
float percent = (value / sanity.getMaxSanity()) * 100f;
|
float percent = (sanity.getSanity() / sanity.getMaxSanity()) * 100f;
|
||||||
|
float insanityPercent = (insanity / sanity.getMaxSanity()) * 100f;
|
||||||
|
if (ConfigMM.COMMON.ENABLE_SANITY_GAMEPLAY_EFFECTS.get()) {
|
||||||
|
applySanityGameplayPressure(player, percent, insanityPercent);
|
||||||
|
}
|
||||||
if (percent <= 70 && Math.random() < 0.03) {
|
if (percent <= 70 && Math.random() < 0.03) {
|
||||||
applyShiver(player);
|
applyShiver(player);
|
||||||
}
|
}
|
||||||
@@ -208,7 +213,6 @@ public class PlayerTickHandler {
|
|||||||
if (percent <= 50 && Math.random() < ConfigMM.COMMON.PANIC_CHANCE.get()) {
|
if (percent <= 50 && Math.random() < ConfigMM.COMMON.PANIC_CHANCE.get()) {
|
||||||
applyPanic(player);
|
applyPanic(player);
|
||||||
}
|
}
|
||||||
float insanityPercent = (insanity / sanity.getMaxSanity()) * 100f;
|
|
||||||
if (insanityPercent > 0) {
|
if (insanityPercent > 0) {
|
||||||
if (insanityPercent > 60 && Math.random() < ConfigMM.COMMON.PANIC_CHANCE.get()) {
|
if (insanityPercent > 60 && Math.random() < ConfigMM.COMMON.PANIC_CHANCE.get()) {
|
||||||
applyPanic(player);
|
applyPanic(player);
|
||||||
@@ -240,6 +244,68 @@ public class PlayerTickHandler {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void applySanityGameplayPressure(Player player, float sanityPercent, float insanityPercent) {
|
||||||
|
float lowSanity = clamp01((55f - sanityPercent) / 55f);
|
||||||
|
float highInsanity = clamp01((insanityPercent - 35f) / 65f);
|
||||||
|
float pressure = Math.max(lowSanity, highInsanity);
|
||||||
|
if (pressure <= 0f) return;
|
||||||
|
|
||||||
|
if (!player.getAbilities().instabuild) {
|
||||||
|
player.causeFoodExhaustion(0.08f + pressure * 0.18f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sanityPercent <= 35f) {
|
||||||
|
int amplifier = sanityPercent <= 15f ? 1 : 0;
|
||||||
|
player.addEffect(new MobEffectInstance(MobEffects.DIG_SLOWDOWN, 60, amplifier, true, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isUsingItem() && (sanityPercent <= 25f || insanityPercent >= 70f)) {
|
||||||
|
float interruptChance = 0.06f + pressure * 0.12f;
|
||||||
|
if (player.getRandom().nextFloat() < interruptChance) {
|
||||||
|
player.stopUsingItem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sanityPercent <= 15f || insanityPercent >= 80f) && player.getRandom().nextFloat() < 0.08f + pressure * 0.10f) {
|
||||||
|
applyStumble(player, pressure);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (insanityPercent >= 45f) {
|
||||||
|
int tempoLoss = Math.max(1, Math.round(highInsanity * 4f));
|
||||||
|
player.getCapability(PlayerCapabilityProvider.TEMPO).ifPresent(tempo -> tempo.reduceTempo(tempoLoss));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (insanityPercent >= 60f && player.getRandom().nextFloat() < 0.18f + highInsanity * 0.20f) {
|
||||||
|
alertNearbyMonsters(player, 10.0 + highInsanity * 10.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void applyStumble(Player player, float pressure) {
|
||||||
|
double strength = 0.08 + pressure * 0.16;
|
||||||
|
double x = (player.getRandom().nextDouble() - 0.5) * strength;
|
||||||
|
double z = (player.getRandom().nextDouble() - 0.5) * strength;
|
||||||
|
player.setDeltaMovement(player.getDeltaMovement().add(x, 0.0, z));
|
||||||
|
player.hurtMarked = true;
|
||||||
|
if (player.isSprinting() && player.getRandom().nextFloat() < 0.5f) {
|
||||||
|
player.setSprinting(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void alertNearbyMonsters(Player player, double radius) {
|
||||||
|
player.level().getEntitiesOfClass(Monster.class, player.getBoundingBox().inflate(radius),
|
||||||
|
monster -> monster.isAlive() && monster.hasLineOfSight(player)
|
||||||
|
).forEach(monster -> {
|
||||||
|
if (monster.getTarget() == null || monster.getRandom().nextFloat() < 0.35f) {
|
||||||
|
monster.setTarget(player);
|
||||||
|
}
|
||||||
|
monster.getNavigation().moveTo(player, 1.1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float clamp01(float value) {
|
||||||
|
return Math.max(0f, Math.min(1f, value));
|
||||||
|
}
|
||||||
|
|
||||||
private static void handleTempoTick(Player player, int currentTick) {
|
private static void handleTempoTick(Player player, int currentTick) {
|
||||||
player.getCapability(PlayerCapabilityProvider.TEMPO).ifPresent(tempo -> {
|
player.getCapability(PlayerCapabilityProvider.TEMPO).ifPresent(tempo -> {
|
||||||
int cd = tempo.getVentCooldown();
|
int cd = tempo.getVentCooldown();
|
||||||
|
|||||||
Reference in New Issue
Block a user