Make sanity more intense

This commit is contained in:
2025-11-15 22:02:08 +01:00
parent 99be5edf3e
commit 0bfe52a3ee
8 changed files with 274 additions and 31 deletions
@@ -1,11 +1,14 @@
package net.fretux.mindmotion; package net.fretux.mindmotion;
import com.mojang.logging.LogUtils; import com.mojang.logging.LogUtils;
import net.fretux.mindmotion.command.SanityCommand;
import net.fretux.mindmotion.event.CombatEvents; import net.fretux.mindmotion.event.CombatEvents;
import net.fretux.mindmotion.event.PlayerTickHandler; 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.event.RegisterCommandsEvent;
import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
@@ -19,6 +22,7 @@ public class AscendMindMotion {
public AscendMindMotion() { public AscendMindMotion() {
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
modEventBus.addListener(this::commonSetup); modEventBus.addListener(this::commonSetup);
MinecraftForge.EVENT_BUS.register(this);
MinecraftForge.EVENT_BUS.register(PlayerTickHandler.class); MinecraftForge.EVENT_BUS.register(PlayerTickHandler.class);
MinecraftForge.EVENT_BUS.register(CombatEvents.class); MinecraftForge.EVENT_BUS.register(CombatEvents.class);
LOGGER.info("Ascend: Mind and Motion initialized!"); LOGGER.info("Ascend: Mind and Motion initialized!");
@@ -27,4 +31,9 @@ public class AscendMindMotion {
private void commonSetup(final FMLCommonSetupEvent event) { private void commonSetup(final FMLCommonSetupEvent event) {
ModMessages.register(); ModMessages.register();
} }
@SubscribeEvent
public static void registerCommands(RegisterCommandsEvent event) {
SanityCommand.register(event.getDispatcher());
}
} }
@@ -41,16 +41,10 @@ public class SanityTempoOverlay {
int insanityFill = (int) (BAR_WIDTH * insanityPercent); int insanityFill = (int) (BAR_WIDTH * insanityPercent);
RenderSystem.enableBlend(); RenderSystem.enableBlend();
// --- TEMPO BAR ---
drawRoundedBar(gui, xTempo, y, BAR_WIDTH, BAR_HEIGHT, 0xFF33AFFF, tempoFill); drawRoundedBar(gui, xTempo, y, BAR_WIDTH, BAR_HEIGHT, 0xFF33AFFF, tempoFill);
gui.drawString(mc.font, Component.literal("Tempo"), xTempo, y - 10, 0x66CCFF, false); gui.drawString(mc.font, Component.literal("Tempo"), xTempo, y - 10, 0x66CCFF, false);
// --- SANITY OR INSANITY BAR ---
boolean insaneMode = sanity <= 0; boolean insaneMode = sanity <= 0;
if (!insaneMode) { if (!insaneMode) {
// Normal sanity bar
drawRoundedBar(gui, xSanity, y, BAR_WIDTH, BAR_HEIGHT, 0xFFFFFFFF, sanityFill); drawRoundedBar(gui, xSanity, y, BAR_WIDTH, BAR_HEIGHT, 0xFFFFFFFF, sanityFill);
gui.drawString(mc.font, Component.literal("Sanity"), xSanity + BAR_WIDTH - 30, y - 10, 0xFFFFFF, false); gui.drawString(mc.font, Component.literal("Sanity"), xSanity + BAR_WIDTH - 30, y - 10, 0xFFFFFF, false);
} else { } else {
@@ -93,15 +93,25 @@ public class SanityShaderHandler {
float blur = 0f; float blur = 0f;
float vig = 0f; float vig = 0f;
float fog = 0f; float fog = 0f;
float flash = 0f;
if (sanityPct < 0.5f) { if (sanityPct < 0.5f) {
blur = (0.5f - sanityPct) * 0.6f; blur = (0.5f - sanityPct) * 0.6f;
vig = (0.5f - sanityPct) * 0.4f; vig = (0.5f - sanityPct) * 0.4f;
fog = (0.5f - sanityPct) * 0.25f; fog = (0.5f - sanityPct) * 0.25f;
} }
blur += insanityPct * 0.25f; if (insanityPct >= 0.8f) {
vig += insanityPct * 0.35f; float level = (insanityPct - 0.8f) / 0.2f;
fog += insanityPct * 0.35f; flash = 0.5f * level;
if (mc.player.getRandom().nextFloat() < 0.01f) {
flash += 0.4f;
}
flash = Math.min(flash, 1f);
}
var uFlash = effect.getUniform("FlashStrength");
if (uFlash != null) uFlash.set(flash);
blur += insanityPct * 0.25f;
vig += insanityPct * 0.35f;
fog += insanityPct * 0.35f;
blur = Math.min(blur, 1f); blur = Math.min(blur, 1f);
vig = Math.min(vig, 1f); vig = Math.min(vig, 1f);
fog = Math.min(fog, 1f); fog = Math.min(fog, 1f);
@@ -114,6 +124,24 @@ public class SanityShaderHandler {
var uFog = effect.getUniform("FogStrength"); var uFog = effect.getUniform("FogStrength");
if (uFog != null) uFog.set(fog); if (uFog != null) uFog.set(fog);
float shake = 0f;
float pulse = 0f;
if (sanityPct <= 0.125f) {
float lowSan = (0.125f - sanityPct) / 0.125f;
shake = lowSan * 0.010f;
pulse = lowSan * 0.6f;
}
shake += insanityPct * 0.012f;
pulse += insanityPct * 0.8f;
shake = Math.min(shake, 0.025f);
pulse = Math.min(pulse, 1f);
var uShake = effect.getUniform("ShakeStrength");
if (uShake != null) uShake.set(shake);
var uPulse = effect.getUniform("PulseStrength");
if (uPulse != null) uPulse.set(pulse);
float time = (mc.level.getGameTime() % 200000) / 20f;
var uTime = effect.getUniform("Time");
if (uTime != null) uTime.set(time);
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@@ -0,0 +1,41 @@
package net.fretux.mindmotion.command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.FloatArgumentType;
import net.fretux.mindmotion.player.PlayerCapabilityProvider;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.server.level.ServerPlayer;
public class SanityCommand {
public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
dispatcher.register(Commands.literal("sanity")
.requires(source -> source.hasPermission(2)) // OP only
.then(Commands.literal("set")
.then(Commands.argument("sanity", FloatArgumentType.floatArg(0, 80))
.then(Commands.argument("insanity", FloatArgumentType.floatArg(0, 80))
.executes(ctx -> {
ServerPlayer player = ctx.getSource().getPlayer();
float sanity = FloatArgumentType.getFloat(ctx, "sanity");
float insanity = FloatArgumentType.getFloat(ctx, "insanity");
player.getCapability(PlayerCapabilityProvider.SANITY).ifPresent(cap -> {
cap.setSanity(sanity);
cap.setInsanity(insanity);
});
ctx.getSource().sendSuccess(() ->
net.minecraft.network.chat.Component.literal(
"Set sanity = " + sanity + ", insanity = " + insanity),
true
);
return 1;
})
)
)
)
);
}
}
@@ -4,6 +4,7 @@ import net.fretux.mindmotion.network.ModMessages;
import net.fretux.mindmotion.network.SyncStatsS2CPacket; import net.fretux.mindmotion.network.SyncStatsS2CPacket;
import net.fretux.mindmotion.player.PlayerCapabilityProvider; import net.fretux.mindmotion.player.PlayerCapabilityProvider;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
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;
@@ -23,6 +24,8 @@ public class PlayerTickHandler {
private static final int TEMPO_TICK_INTERVAL = 15; private static final int TEMPO_TICK_INTERVAL = 15;
private static final int COMBAT_DECAY_DELAY = 100; private static final int COMBAT_DECAY_DELAY = 100;
private static final Map<UUID, Integer> lastCombatTick = new ConcurrentHashMap<>(); private static final Map<UUID, Integer> lastCombatTick = new ConcurrentHashMap<>();
private static final Map<UUID, Integer> insanityDamageTicks = new ConcurrentHashMap<>();
private static final Map<UUID, Integer> lowSanitySoundCooldown = new ConcurrentHashMap<>();
@SubscribeEvent @SubscribeEvent
public static void onPlayerTick(TickEvent.PlayerTickEvent event) { public static void onPlayerTick(TickEvent.PlayerTickEvent event) {
@@ -58,7 +61,7 @@ public class PlayerTickHandler {
float value = sanity.getSanity(); float value = sanity.getSanity();
float insanity = sanity.getInsanity(); float insanity = sanity.getInsanity();
float delta = 0f; float delta = 0f;
boolean inDark = player.level().getMaxLocalRawBrightness(player.blockPosition()) < 5; boolean inDark = player.level().getMaxLocalRawBrightness(player.blockPosition()) < 8;
boolean inRain = player.level().isRainingAt(player.blockPosition()); boolean inRain = player.level().isRainingAt(player.blockPosition());
boolean isHungry = player.getFoodData().getFoodLevel() < 6; boolean isHungry = player.getFoodData().getFoodLevel() < 6;
boolean nearLava = player.level().getBlockState(player.blockPosition().below()).is(Blocks.LAVA); boolean nearLava = player.level().getBlockState(player.blockPosition().below()).is(Blocks.LAVA);
@@ -67,26 +70,85 @@ public class PlayerTickHandler {
boolean sleeping = player.isSleeping(); boolean sleeping = player.isSleeping();
boolean inLight = player.level().getMaxLocalRawBrightness(player.blockPosition()) > 12; boolean inLight = player.level().getMaxLocalRawBrightness(player.blockPosition()) > 12;
boolean nearTorch = player.level().getBlockState(player.blockPosition().above()).is(Blocks.TORCH); boolean nearTorch = player.level().getBlockState(player.blockPosition().above()).is(Blocks.TORCH);
if (inDark) delta -= 2f; if (inDark) delta -= 0.02f;
if (inRain) delta -= 0.04f; if (inRain) delta -= 0.04f;
if (isHungry) delta -= 0.06f; if (isHungry) delta -= 0.06f;
if (nearLava) delta -= 0.05f; if (nearLava) delta -= 0.05f;
if (underWater) delta -= 0.04f; if (underWater) delta -= 0.04f;
if (inWater && !underWater) delta -= 0.02f; if (inWater && !underWater) delta -= 0.02f;
int light = player.level().getMaxLocalRawBrightness(player.blockPosition());
if (light <= 2) delta -= 0.10f;
else if (light <= 5) delta -= 0.05f;
if (player.level().isThundering()) delta -= 0.06f;
if (player.level().getBiome(player.blockPosition())
.is(BiomeTags.IS_END)) {
delta -= 0.02f;
}
if (player.level().getBiome(player.blockPosition())
.is(BiomeTags.IS_NETHER)) {
delta -= 0.015f;
}
if (player.level().dimension() == net.minecraft.world.level.Level.NETHER)
delta -= 0.12f;
if (player.level().dimension() == net.minecraft.world.level.Level.END)
delta -= 0.08f;
if (!player.level().getEntities(player, player.getBoundingBox().inflate(30),
e -> e.getType().toString().contains("warden")).isEmpty()) {
delta -= 0.15f;
}
long hostileCount = player.level().getEntities(player,
player.getBoundingBox().inflate(10),
e -> e instanceof net.minecraft.world.entity.Mob && !(e instanceof net.minecraft.world.entity.animal.Animal)
).size();
delta -= hostileCount * 0.005f;
if (inLight) delta += 0.03f; if (inLight) delta += 0.03f;
if (nearTorch) delta += 0.05f; if (nearTorch) delta += 0.05f;
if (sleeping) delta += 0.25f; if (sleeping) delta += 0.25f;
if (player.getUseItem() != null && player.getUseItem().isEdible()) delta += 0.05f; if (player.getUseItem() != null && player.getUseItem().isEdible()) delta += 0.05f;
if (player.level().getBlockState(player.blockPosition().below())
.is(net.minecraft.world.level.block.Blocks.CAMPFIRE)) {
delta += 0.08f;
}
if (player.level().getBlockState(player.blockPosition().below())
.is(Blocks.FURNACE) || (player.level().getBlockState(player.blockPosition().below())
.is(Blocks.BLAST_FURNACE)) || (player.level().getBlockState(player.blockPosition().below())
.is(Blocks.SMOKER))) {
delta += 0.04f;
}
long animalCount = player.level().getEntities(player,
player.getBoundingBox().inflate(6),
e -> e instanceof net.minecraft.world.entity.animal.Animal
).size();
delta += animalCount * 0.01f;
long villagerCount = player.level().getEntities(player,
player.getBoundingBox().inflate(8),
e -> e instanceof net.minecraft.world.entity.npc.Villager
).size();
delta += villagerCount * 0.02f;
if (player.level().getBlockState(player.blockPosition().below()).is(Blocks.BEACON))
delta += 0.15f;
if (player.getMainHandItem().is(Blocks.POPPY.asItem())
|| player.getMainHandItem().is(Blocks.DANDELION.asItem())) {
delta += 0.04f;
}
if (player.isSleepingLongEnough())
delta += 0.10f;
sanity.setSanity(value + delta); sanity.setSanity(value + delta);
if (sanity.getSanity() <= 0) { if (sanity.getSanity() > 0) {
sanity.setSanity(0); sanity.setInsanity(Math.max(0, insanity - 0.15f));
insanityDamageTicks.remove(player.getUUID());
} else {
sanity.setInsanity(Math.min(sanity.getMaxSanity(), insanity + 0.3f)); sanity.setInsanity(Math.min(sanity.getMaxSanity(), insanity + 0.3f));
if (sanity.getInsanity() >= sanity.getMaxSanity()) { if (sanity.getInsanity() >= sanity.getMaxSanity()) {
player.kill(); UUID id = player.getUUID();
int ticks = insanityDamageTicks.getOrDefault(id, 0) + SANITY_TICK_INTERVAL;
insanityDamageTicks.put(id, ticks);
float damage = 1.0f + (ticks / 100f);
player.hurt(player.damageSources().magic(), damage);
player.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 40, 1));
return; return;
} }
} else if (sanity.getInsanity() > 0) {
sanity.setInsanity(Math.max(0, insanity - 0.15f));
} }
float percent = (value / sanity.getMaxSanity()) * 100f; float percent = (value / sanity.getMaxSanity()) * 100f;
if (percent <= 70 && Math.random() < 0.03) { if (percent <= 70 && Math.random() < 0.03) {
@@ -107,6 +169,17 @@ public class PlayerTickHandler {
applyScratching(player); applyScratching(player);
} }
} }
if (percent <= 30f) {
UUID id = player.getUUID();
int cd = lowSanitySoundCooldown.getOrDefault(id, 0) - SANITY_TICK_INTERVAL;
if (cd <= 0) {
playSanitySound(player);
cd = 20 * (6 + player.getRandom().nextInt(15));
}
lowSanitySoundCooldown.put(id, cd);
} else {
lowSanitySoundCooldown.remove(player.getUUID());
}
}); });
} }
@@ -141,4 +214,38 @@ public class PlayerTickHandler {
player.hurt(player.damageSources().magic(), 2f); player.hurt(player.damageSources().magic(), 2f);
applyShiver(player); applyShiver(player);
} }
private static void playSanitySound(Player player) {
var level = player.level();
if (level.isClientSide) return;
var sounds = new net.minecraft.sounds.SoundEvent[]{
net.minecraft.sounds.SoundEvents.ZOMBIE_AMBIENT,
net.minecraft.sounds.SoundEvents.ENDERMAN_STARE,
net.minecraft.sounds.SoundEvents.SPIDER_AMBIENT,
net.minecraft.sounds.SoundEvents.CREEPER_PRIMED,
net.minecraft.sounds.SoundEvents.HUSK_AMBIENT,
net.minecraft.sounds.SoundEvents.WARDEN_ANGRY
};
net.minecraft.sounds.SoundEvent chosen =
sounds[player.getRandom().nextInt(sounds.length)];
var holder = net.minecraft.core.registries.BuiltInRegistries.SOUND_EVENT.wrapAsHolder(chosen);
float yaw = player.getYRot();
double angleRad = Math.toRadians(yaw + 180 + player.getRandom().nextInt(40) - 20);
double dist = 4.0 + player.getRandom().nextDouble() * 3.0;
double dx = player.getX() + Math.cos(angleRad) * dist;
double dz = player.getZ() + Math.sin(angleRad) * dist;
double dy = player.getY();
if (player instanceof ServerPlayer sp) {
sp.connection.send(
new net.minecraft.network.protocol.game.ClientboundSoundPacket(
holder,
net.minecraft.sounds.SoundSource.AMBIENT,
dx, dy, dz,
1.0f,
0.9f + player.getRandom().nextFloat() * 0.2f,
player.getRandom().nextLong()
)
);
}
}
} }
@@ -5,6 +5,9 @@ uniform float Desat;
uniform float BlurAmount; uniform float BlurAmount;
uniform float Vignette; uniform float Vignette;
uniform float FogStrength; uniform float FogStrength;
uniform float PulseStrength;
uniform float Time;
uniform float FlashStrength;
in vec2 texCoord; in vec2 texCoord;
in vec2 oneTexel; in vec2 oneTexel;
@@ -17,29 +20,53 @@ vec4 sampleBlur() {
float w = BlurAmount * 0.5; float w = BlurAmount * 0.5;
vec4 sum = vec4(0.0); vec4 sum = vec4(0.0);
sum += texture(DiffuseSampler, texCoord + oneTexel * vec2(-1, 0)) * w; sum += texture(DiffuseSampler, texCoord + oneTexel * vec2(-1, 0)) * w;
sum += texture(DiffuseSampler, texCoord + oneTexel * vec2( 1, 0)) * w; sum += texture(DiffuseSampler, texCoord + oneTexel * vec2( 1, 0)) * w;
sum += texture(DiffuseSampler, texCoord + oneTexel * vec2( 0, -1)) * w; sum += texture(DiffuseSampler, texCoord + oneTexel * vec2( 0,-1)) * w;
sum += texture(DiffuseSampler, texCoord + oneTexel * vec2( 0, 1)) * w; sum += texture(DiffuseSampler, texCoord + oneTexel * vec2( 0, 1)) * w;
vec4 center = texture(DiffuseSampler, texCoord) * (1.0 - w * 4.0); vec4 center = texture(DiffuseSampler, texCoord) * (1.0 - w * 4.0);
return center + sum; return center + sum;
} }
void main() { void main() {
vec4 col = texture(DiffuseSampler, texCoord); vec4 col = texture(DiffuseSampler, texCoord);
// Blur
vec4 blurred = sampleBlur(); vec4 blurred = sampleBlur();
col = mix(col, blurred, BlurAmount); col = mix(col, blurred, BlurAmount);
// Grayscale
float gray = dot(col.rgb, vec3(0.2126, 0.7152, 0.0722)); float gray = dot(col.rgb, vec3(0.2126, 0.7152, 0.0722));
col.rgb = mix(col.rgb, vec3(gray), clamp(Desat, 0.0, 1.0)); col.rgb = mix(col.rgb, vec3(gray), clamp(Desat, 0.0, 1.0));
col.rgb = mix(col.rgb, vec3(0.75, 0.75, 0.8), FogStrength); // Fog
col.rgb = mix(col.rgb, vec3(0.75), FogStrength);
float dist = distance(texCoord, vec2(0.5, 0.5)); // Stronger base vignette
float vign = smoothstep(0.3, 0.7, dist); float dist = distance(texCoord, vec2(0.5));
col.rgb = mix(col.rgb, col.rgb * 0.4, vign * Vignette); float vign = smoothstep(0.15, 0.6, dist);
col.rgb = mix(col.rgb, vec3(0.0), vign * Vignette);
// Pulsating vignette toward black
if (PulseStrength > 0.001) {
float pulse = (sin(Time * 4.0) * 0.5 + 0.5);
pulse *= PulseStrength;
float pVig = smoothstep(0.2, 0.8, dist);
col.rgb = mix(col.rgb, vec3(0.0), pVig * pulse);
}
if (FlashStrength > 0.001) {
float wave = sin(Time * 12.0); // slower: 12 instead of 40
float intensity = (abs(wave) * 0.65) * FlashStrength;
// max 25% brightness shift even at 100% insanity
// shift colors subtly instead of full white/black
vec3 flashColor = wave > 0.0
? vec3(0.9, 0.9, 1.0) // pale bluish-white
: vec3(0.05, 0.05, 0.07); // deep blue-black
col.rgb = mix(col.rgb, flashColor, intensity);
}
fragColor = vec4(col.rgb, 1.0); fragColor = vec4(col.rgb, 1.0);
} }
@@ -72,6 +72,30 @@
"type": "float", "type": "float",
"count": 1, "count": 1,
"values": [ 0.0 ] "values": [ 0.0 ]
},
{
"name": "ShakeStrength",
"type": "float",
"count": 1,
"values": [ 0.0 ]
},
{
"name": "PulseStrength",
"type": "float",
"count": 1,
"values": [ 0.0 ]
},
{
"name": "Time",
"type": "float",
"count": 1,
"values": [ 0.0 ]
},
{
"name": "FlashStrength",
"type": "float",
"count": 1,
"values": [ 0.0 ]
} }
] ]
} }
@@ -4,11 +4,24 @@ in vec4 Position;
uniform mat4 ProjMat; uniform mat4 ProjMat;
uniform vec2 OutSize; uniform vec2 OutSize;
uniform float ShakeStrength;
uniform float Time;
out vec2 texCoord; out vec2 texCoord;
void main() { void main() {
vec4 outPos = ProjMat * vec4(Position.xy, 0.0, 1.0);
// screen-shake offset in *pixels*
float px = sin(Time * 25.0 + Position.x * 5.0) * ShakeStrength * 20.0;
float py = cos(Time * 20.0 + Position.y * 7.0) * ShakeStrength * 20.0;
// convert from pixels → normalized coordinates
vec2 offset = vec2(px / OutSize.x, py / OutSize.y);
vec2 shaken = Position.xy + offset;
texCoord = shaken / OutSize;
vec4 outPos = ProjMat * vec4(shaken, 0.0, 1.0);
gl_Position = vec4(outPos.xy, 0.0, 1.0); gl_Position = vec4(outPos.xy, 0.0, 1.0);
texCoord = Position.xy / OutSize;
} }