generated from MrSphay/codex-agent-repository-kit
665 lines
33 KiB
Java
665 lines
33 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*/
|
|
package com.vinlanx.explosionoverhaul.client;
|
|
|
|
import com.vinlanx.explosionoverhaul.Config;
|
|
import com.vinlanx.explosionoverhaul.ModSounds;
|
|
import com.vinlanx.explosionoverhaul.client.Blur;
|
|
import com.vinlanx.explosionoverhaul.client.CameraShakeConcussionEffect;
|
|
import com.vinlanx.explosionoverhaul.client.DeafnessConcussionEffect;
|
|
import com.vinlanx.explosionoverhaul.client.LowPassConcussionEffect;
|
|
import java.util.concurrent.ThreadLocalRandom;
|
|
import net.minecraft.ChatFormatting;
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.client.gui.GuiGraphics;
|
|
import net.minecraft.client.player.LocalPlayer;
|
|
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
|
|
import net.minecraft.client.resources.sounds.SoundInstance;
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.sounds.SoundEvent;
|
|
import net.minecraftforge.api.distmarker.Dist;
|
|
import net.minecraftforge.event.TickEvent;
|
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
|
import net.minecraftforge.fml.common.Mod;
|
|
import net.minecraftforge.fml.loading.FMLEnvironment;
|
|
|
|
@Mod.EventBusSubscriber(modid="explosionoverhaul", value={Dist.CLIENT})
|
|
public class ConcussionAudioEffect {
|
|
public static boolean debugSendDebugMessage = false;
|
|
public static boolean TestingHudHeart = true;
|
|
public static float currentBPM = 23.3f;
|
|
private static double heartbeatCycleTimer = 0.0;
|
|
private static float heartbeatVisualPulse = 0.0f;
|
|
private static float explosionBPMMod = 0.0f;
|
|
private static float jumpBPMMod = 0.0f;
|
|
private static boolean wasOnGround = true;
|
|
private static int idleTicks = 0;
|
|
private static boolean lubTriggered = false;
|
|
private static boolean dubTriggered = false;
|
|
|
|
@SubscribeEvent
|
|
public static void onClientTick(TickEvent.ClientTickEvent event) {
|
|
if (event.phase == TickEvent.Phase.END) {
|
|
Minecraft mc = Minecraft.m_91087_();
|
|
if (mc.f_91074_ != null && !mc.f_91074_.m_6084_()) {
|
|
ConcussionAudioEffect.stopAll();
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void stopAll() {
|
|
Blur.stop();
|
|
DeafnessConcussionEffect.stop();
|
|
LowPassConcussionEffect.stop();
|
|
CameraShakeConcussionEffect.stop();
|
|
}
|
|
|
|
public static void start(float power, double distance, boolean hasDirectLineOfSight, boolean explosionInCave) {
|
|
LocalPlayer player;
|
|
LocalPlayer player2;
|
|
LocalPlayer player3;
|
|
if (!FMLEnvironment.dist.isClient()) {
|
|
return;
|
|
}
|
|
if (!((Boolean)Config.CLIENT.enableConcussion.get()).booleanValue()) {
|
|
return;
|
|
}
|
|
Minecraft mc = Minecraft.m_91087_();
|
|
if (mc == null || mc.f_91073_ == null || mc.f_91074_ == null) {
|
|
return;
|
|
}
|
|
double rawPercent = ConcussionAudioEffect.computePercent(power, distance, explosionInCave);
|
|
if (explosionInCave) {
|
|
rawPercent = Math.min(100.0, rawPercent * 1.5);
|
|
}
|
|
double effectivePercent = hasDirectLineOfSight ? rawPercent : ConcussionAudioEffect.applyOcclusion(rawPercent);
|
|
double maxDistance = ConcussionAudioEffect.computeMaxDistance(power, explosionInCave);
|
|
if (rawPercent <= 0.0) {
|
|
LocalPlayer player4 = mc.f_91074_;
|
|
if (player4 != null && debugSendDebugMessage) {
|
|
double metersToExplosion = distance;
|
|
double onePercentDistance = maxDistance * 0.99;
|
|
String outMessage = String.format("\u041f\u043e\u0437\u0430 \u0437\u043e\u043d\u043e\u044e \u043f\u043e\u0440\u0430\u0437\u043a\u0438. \u0412\u0456\u0434\u0441\u0442\u0430\u043d\u044c \u0434\u043e \u0432\u0438\u0431\u0443\u0445\u0443: %.1f \u043c. 1%% \u043f\u043e\u0447\u0438\u043d\u0430\u0454\u0442\u044c\u0441\u044f \u0437: %.1f \u043c.", metersToExplosion, onePercentDistance);
|
|
player4.m_5661_((Component)Component.m_237113_((String)outMessage).m_130940_(ChatFormatting.GRAY), false);
|
|
}
|
|
return;
|
|
}
|
|
double normalized = Math.max(0.0, Math.min(1.0, effectivePercent / 100.0));
|
|
float intensity = (float)normalized;
|
|
if (intensity < 0.01f) {
|
|
return;
|
|
}
|
|
double baseSilentSeconds = ConcussionAudioEffect.computeBaseSilentSeconds(effectivePercent, explosionInCave);
|
|
double intensityPercent = ConcussionAudioEffect.computeBaseIntensityPercent(effectivePercent);
|
|
double multiplier = ConcussionAudioEffect.computePowerMultiplier(power);
|
|
double finalSilentSeconds = baseSilentSeconds * multiplier * (Double)Config.CLIENT.concussionDurationMultiplier.get();
|
|
double lowpassChance = ConcussionAudioEffect.computeLowpassPowerChance(power, explosionInCave) * (Double)Config.CLIENT.concussionChanceMultiplier.get() * (Double)Config.CLIENT.lowPassChanceMultiplier.get();
|
|
boolean lowpassRoll = ThreadLocalRandom.current().nextDouble() <= lowpassChance;
|
|
double chance = ConcussionAudioEffect.computePowerChance(power, explosionInCave) * (Double)Config.CLIENT.concussionChanceMultiplier.get() * (Double)Config.CLIENT.deafnessChanceMultiplier.get();
|
|
boolean roll = ThreadLocalRandom.current().nextDouble() <= chance;
|
|
boolean anyAudioEffectActive = roll || lowpassRoll;
|
|
double baseBlurSeconds = ConcussionAudioEffect.computeBaseBlurSilentSeconds(effectivePercent, explosionInCave);
|
|
double blurMultiplier = ConcussionAudioEffect.computeBlurPowerMultiplier(power);
|
|
double finalBlurSeconds = baseBlurSeconds * blurMultiplier * (Double)Config.CLIENT.concussionDurationMultiplier.get();
|
|
boolean lowpassReduced = false;
|
|
if (!lowpassRoll) {
|
|
finalBlurSeconds = roll ? finalSilentSeconds : (finalBlurSeconds /= 3.0);
|
|
lowpassReduced = true;
|
|
}
|
|
int blurSeconds = Math.max(1, (int)Math.round(finalBlurSeconds));
|
|
double blurIntensityPercent = ConcussionAudioEffect.computeBaseBlurIntensityPercent(effectivePercent);
|
|
float blurIntensity = (float)(blurIntensityPercent / 100.0);
|
|
double swayIntensityPercent = ConcussionAudioEffect.computeBaseSwayIntensityPercent(effectivePercent) * (Double)Config.CLIENT.cameraSwayIntensity.get();
|
|
float swayIntensity = (float)(swayIntensityPercent / 100.0);
|
|
if (rawPercent > 0.0 && blurIntensity >= 0.01f && anyAudioEffectActive) {
|
|
float addedBPM = 0.0f;
|
|
if (rawPercent > 80.0) {
|
|
addedBPM = 60.0f;
|
|
} else if (rawPercent > 60.0) {
|
|
addedBPM = 40.0f;
|
|
} else if (rawPercent > 30.0) {
|
|
addedBPM = 20.0f;
|
|
}
|
|
explosionBPMMod = Math.min(200.0f, explosionBPMMod + addedBPM);
|
|
try {
|
|
LocalPlayer player5;
|
|
Blur.start(blurSeconds, blurIntensity);
|
|
if (((Boolean)Config.CLIENT.enableCameraSway.get()).booleanValue()) {
|
|
CameraShakeConcussionEffect.start(blurSeconds, swayIntensity);
|
|
}
|
|
if (debugSendDebugMessage && (player5 = mc.f_91074_) != null) {
|
|
String reductionInfo = lowpassReduced ? " [LowPass reduced /3]" : "";
|
|
String blurMsg = String.format("Blur & Sway %.1f m \u2014 activated (Blur: %.2f, Sway: %.2f, Time: %ds%s)", distance, Float.valueOf(blurIntensity), Float.valueOf(swayIntensity), blurSeconds, reductionInfo);
|
|
player5.m_5661_((Component)Component.m_237113_((String)blurMsg).m_130940_(ChatFormatting.BLUE), false);
|
|
}
|
|
}
|
|
catch (Throwable player5) {}
|
|
} else if (debugSendDebugMessage && (player3 = mc.f_91074_) != null) {
|
|
String reason = !anyAudioEffectActive ? "no audio effects" : "out of range";
|
|
String blurMsg = String.format("Blur %.1f m \u2014 not activated (%s)", distance, reason);
|
|
player3.m_5661_((Component)Component.m_237113_((String)blurMsg).m_130940_(ChatFormatting.GRAY), false);
|
|
}
|
|
int lowpassSeconds = blurSeconds;
|
|
double lowpassIntensityPercent = ConcussionAudioEffect.computeBaseLowpassIntensityPercent(effectivePercent);
|
|
float lowpassIntensity = (float)(lowpassIntensityPercent / 100.0);
|
|
if (lowpassIntensity < 0.01f) {
|
|
lowpassIntensity = 0.01f;
|
|
}
|
|
String lpVisibility = hasDirectLineOfSight ? "\u043f\u0440\u044f\u043c\u0430 \u0432\u0438\u0434\u0438\u043c\u0456\u0441\u0442\u044c" : "\u043f\u0435\u0440\u0435\u0448\u043a\u043e\u0434\u0430";
|
|
int lowpassIntensityRound = (int)Math.round(lowpassIntensityPercent);
|
|
if (((Boolean)Config.CLIENT.enableLowPass.get()).booleanValue() && rawPercent > 0.0 && lowpassIntensity >= 0.01f && (lowpassRoll || LowPassConcussionEffect.isActive())) {
|
|
try {
|
|
LocalPlayer player6;
|
|
float finalLpIntensity = lowpassRoll ? lowpassIntensity : 0.0f;
|
|
int finalLpRound = lowpassRoll ? lowpassIntensityRound : 0;
|
|
LowPassConcussionEffect.start(lowpassSeconds, finalLpIntensity, effectivePercent, lpVisibility, finalLpRound);
|
|
if (debugSendDebugMessage && (player6 = mc.f_91074_) != null) {
|
|
String status = lowpassRoll ? "activated" : "refreshed";
|
|
String lpMsg = String.format("Low pass %.1f m \u2014 %s (intensity=%.2f chance=%.1f%%)", distance, status, Float.valueOf(finalLpIntensity), lowpassChance * 100.0);
|
|
player6.m_5661_((Component)Component.m_237113_((String)lpMsg).m_130940_(ChatFormatting.DARK_GREEN), false);
|
|
}
|
|
}
|
|
catch (Throwable finalLpIntensity) {}
|
|
} else if (debugSendDebugMessage && (player2 = mc.f_91074_) != null) {
|
|
String reason = rawPercent <= 0.0 || lowpassIntensity < 0.01f ? "out of range" : "chance fail";
|
|
String lpMsg = String.format("Low pass %.1f m \u2014 not activated (%s)", distance, reason);
|
|
player2.m_5661_((Component)Component.m_237113_((String)lpMsg).m_130940_(ChatFormatting.GRAY), false);
|
|
}
|
|
if (debugSendDebugMessage) {
|
|
ConcussionAudioEffect.sendDebugMessage(mc, effectivePercent, rawPercent, hasDirectLineOfSight, distance, maxDistance);
|
|
}
|
|
if (debugSendDebugMessage && (player = mc.f_91074_) != null) {
|
|
Object visibility = hasDirectLineOfSight ? "\u043f\u0440\u044f\u043c\u0430 \u0432\u0438\u0434\u0438\u043c\u0456\u0441\u0442\u044c" : "\u043f\u0435\u0440\u0435\u0448\u043a\u043e\u0434\u0430";
|
|
visibility = (String)visibility + (explosionInCave ? " | \u0432\u0438\u0431\u0443\u0445 \u0443 \u043f\u0435\u0447\u0435\u0440\u0456" : " | \u0432\u0438\u0431\u0443\u0445 \u043d\u0435 \u0432 \u043f\u0435\u0447\u0435\u0440\u0456");
|
|
visibility = (String)visibility + String.format(" | \u0444\u0456\u043d\u0430\u043b\u044c\u043d\u0438\u0439 %%: %.1f%%", effectivePercent);
|
|
player.m_5661_((Component)Component.m_237113_((String)visibility).m_130940_(ChatFormatting.GRAY), false);
|
|
String chanceMsg = String.format("\u0428\u0430\u043d\u0441 \u043a\u043e\u043d\u0442\u0443\u0437\u0456\u0457: %.1f%%", chance * 100.0);
|
|
player.m_5661_((Component)Component.m_237113_((String)chanceMsg).m_130940_(ChatFormatting.YELLOW), false);
|
|
double maxDistanceNormal = ConcussionAudioEffect.computeMaxDistance(power, false);
|
|
double maxDistanceUsed = ConcussionAudioEffect.computeMaxDistance(power, explosionInCave);
|
|
String distMsg = String.format("\u041c\u0430\u043a\u0441 \u0434\u0438\u0441\u0442\u0430\u043d\u0446\u0456\u044f (\u0437\u0432\u0438\u0447\u0430\u0439\u043d\u0430): %.1f \u043c | (\u0432 \u043f\u0435\u0447\u0435\u0440\u0456): %.1f \u043c | \u0412\u0456\u0434\u0441\u0442\u0430\u043d\u044c \u0434\u043e \u0432\u0438\u0431\u0443\u0445\u0443: %.1f \u043c", maxDistanceNormal, maxDistanceUsed, distance);
|
|
player.m_5661_((Component)Component.m_237113_((String)distMsg).m_130940_(ChatFormatting.GRAY), false);
|
|
double baseSilentNormal = ConcussionAudioEffect.computeBaseSilentSeconds(effectivePercent, false);
|
|
double baseSilentCave = ConcussionAudioEffect.computeBaseSilentSeconds(effectivePercent, true);
|
|
String silentMsg = String.format("\u0427\u0430\u0441 \u0441\u043a\u0440\u0443\u0447\u0443\u0432\u0430\u043d\u043d\u044f (\u0437\u0432\u0438\u0447\u0430\u0439\u043d\u0438\u0439): %.1fs | (\u0432 \u043f\u0435\u0447\u0435\u0440\u0456): %.1fs | \u0412\u0418\u041a\u041e\u0420\u0418\u0421\u0422\u0410\u041d\u041e: %.1fs", baseSilentNormal, baseSilentCave, baseSilentSeconds * multiplier);
|
|
player.m_5661_((Component)Component.m_237113_((String)silentMsg).m_130940_(ChatFormatting.GRAY), false);
|
|
if (roll) {
|
|
String deafnessMsg = String.format("Deafness %.1f m \u2014 activated (intensity=%.1f%% chance=%.1f%%)", distance, intensityPercent, chance * 100.0);
|
|
player.m_5661_((Component)Component.m_237113_((String)deafnessMsg).m_130940_(ChatFormatting.RED), false);
|
|
} else {
|
|
String deafnessMsg = String.format("Deafness %.1f m \u2014 not activated (chance)", distance);
|
|
player.m_5661_((Component)Component.m_237113_((String)deafnessMsg).m_130940_(ChatFormatting.GRAY), false);
|
|
}
|
|
}
|
|
if (!roll) {
|
|
return;
|
|
}
|
|
if (!((Boolean)Config.CLIENT.enableDeafness.get()).booleanValue()) {
|
|
return;
|
|
}
|
|
int intensityRound = (int)Math.round(intensityPercent);
|
|
String visibility = hasDirectLineOfSight ? "\u043f\u0440\u044f\u043c\u0430 \u0432\u0438\u0434\u0438\u043c\u0456\u0441\u0442\u044c" : "\u043f\u0435\u0440\u0435\u0448\u043a\u043e\u0434\u0430";
|
|
float intensityFromIntensityPercent = (float)(intensityPercent / 100.0);
|
|
DeafnessConcussionEffect.start(intensityFromIntensityPercent, (float)finalSilentSeconds, effectivePercent, visibility, intensityRound);
|
|
}
|
|
|
|
private static double computePercent(float power, double distance, boolean explosionInCave) {
|
|
double maxDistance = ConcussionAudioEffect.computeMaxDistance(power, explosionInCave);
|
|
if (maxDistance <= 0.0) {
|
|
return 0.0;
|
|
}
|
|
double normalized = 1.0 - Math.max(0.0, distance) / maxDistance;
|
|
return Math.max(0.0, Math.min(1.0, normalized)) * 100.0;
|
|
}
|
|
|
|
private static double computeMaxDistance(float power, boolean explosionInCave) {
|
|
double[][] points = explosionInCave ? new double[][]{{1.0, 5.0}, {3.0, 10.0}, {10.0, 50.0}, {25.0, 90.0}, {50.0, 150.0}, {80.0, 200.0}, {120.0, 200.0}} : new double[][]{{1.0, 2.0}, {3.0, 5.0}, {10.0, 30.0}, {25.0, 70.0}, {50.0, 100.0}, {80.0, 150.0}, {120.0, 200.0}};
|
|
double clampedPower = Math.max(points[0][0], Math.min(points[points.length - 1][0], (double)power));
|
|
for (int i = 1; i < points.length; ++i) {
|
|
double lowerP = points[i - 1][0];
|
|
double upperP = points[i][0];
|
|
if (!(clampedPower <= upperP)) continue;
|
|
double lowerD = points[i - 1][1];
|
|
double upperD = points[i][1];
|
|
double t = (clampedPower - lowerP) / (upperP - lowerP);
|
|
return lowerD + (upperD - lowerD) * t;
|
|
}
|
|
return points[points.length - 1][1];
|
|
}
|
|
|
|
private static double applyOcclusion(double percent) {
|
|
if (percent >= 80.0) {
|
|
return percent / 1.2;
|
|
}
|
|
if (percent >= 60.0) {
|
|
return percent / 1.4;
|
|
}
|
|
if (percent >= 40.0) {
|
|
return percent / 1.6;
|
|
}
|
|
if (percent >= 20.0) {
|
|
return percent / 3.0;
|
|
}
|
|
if (percent >= 1.0) {
|
|
return 0.0;
|
|
}
|
|
return 0.0;
|
|
}
|
|
|
|
private static void sendDebugMessage(Minecraft mc, double effectivePercent, double rawPercent, boolean hasDirectLineOfSight, double distance, double maxDistance) {
|
|
LocalPlayer player = mc.f_91074_;
|
|
if (player == null) {
|
|
return;
|
|
}
|
|
double clamped = Math.max(0.0, Math.min(100.0, effectivePercent));
|
|
if (rawPercent <= 0.0) {
|
|
double metersToExplosion = distance;
|
|
double onePercentDistance = maxDistance * 0.99;
|
|
String outMessage = String.format("\u041f\u043e\u0437\u0430 \u0437\u043e\u043d\u043e\u044e \u043f\u043e\u0440\u0430\u0437\u043a\u0438. \u0412\u0456\u0434\u0441\u0442\u0430\u043d\u044c \u0434\u043e \u0432\u0438\u0431\u0443\u0445\u0443: %.1f \u043c. 1%% \u043f\u043e\u0447\u0438\u043d\u0430\u0454\u0442\u044c\u0441\u044f \u0437: %.1f \u043c.", metersToExplosion, onePercentDistance);
|
|
player.m_5661_((Component)Component.m_237113_((String)outMessage).m_130940_(ChatFormatting.GRAY), false);
|
|
return;
|
|
}
|
|
ChatFormatting color = ConcussionAudioEffect.pickColor(clamped);
|
|
String visibility = hasDirectLineOfSight ? "\u043f\u0440\u044f\u043c\u0430 \u0432\u0438\u0434\u0438\u043c\u0456\u0441\u0442\u044c" : "\u043f\u0435\u0440\u0435\u0448\u043a\u043e\u0434\u0430";
|
|
String message = String.format("\u041f\u043e\u0442\u0443\u0436\u043d\u0456\u0441\u0442\u044c \u043a\u043e\u043d\u0442\u0443\u0437\u0456\u0457 %.1f%% (%s)", clamped, visibility);
|
|
player.m_5661_((Component)Component.m_237113_((String)message).m_130940_(color), false);
|
|
if (!hasDirectLineOfSight && rawPercent > 0.0) {
|
|
String rawMessage = String.format("(\u0434\u043e \u043f\u0435\u0440\u0435\u0448\u043a\u043e\u0434\u0438: %.1f%%)", Math.max(0.0, Math.min(100.0, rawPercent)));
|
|
player.m_5661_((Component)Component.m_237113_((String)rawMessage).m_130940_(ChatFormatting.GRAY), false);
|
|
}
|
|
}
|
|
|
|
private static ChatFormatting pickColor(double percent) {
|
|
if (percent >= 80.0) {
|
|
return ChatFormatting.RED;
|
|
}
|
|
if (percent >= 60.0) {
|
|
return ChatFormatting.GOLD;
|
|
}
|
|
if (percent >= 40.0) {
|
|
return ChatFormatting.YELLOW;
|
|
}
|
|
if (percent >= 20.0) {
|
|
return ChatFormatting.AQUA;
|
|
}
|
|
if (percent > 0.0) {
|
|
return ChatFormatting.BLUE;
|
|
}
|
|
return ChatFormatting.GRAY;
|
|
}
|
|
|
|
private static double computeBaseSilentSeconds(double effectivePercent, boolean explosionInCave) {
|
|
if (!explosionInCave) {
|
|
if (effectivePercent <= 40.0) {
|
|
return 0.0;
|
|
}
|
|
if (effectivePercent > 80.0) {
|
|
double t = (effectivePercent - 80.0) / 20.0;
|
|
return 4.0 + 1.0 * t;
|
|
}
|
|
if (effectivePercent > 60.0) {
|
|
double t = (effectivePercent - 60.0) / 20.0;
|
|
return 2.0 + 2.0 * t;
|
|
}
|
|
double t = (effectivePercent - 40.0) / 20.0;
|
|
return 1.0 + 1.0 * t;
|
|
}
|
|
if (effectivePercent <= 20.0) {
|
|
return 0.0;
|
|
}
|
|
if (effectivePercent > 80.0) {
|
|
double t = (effectivePercent - 80.0) / 20.0;
|
|
return 7.0 + 3.0 * t;
|
|
}
|
|
if (effectivePercent > 60.0) {
|
|
double t = (effectivePercent - 60.0) / 20.0;
|
|
return 4.0 + 1.0 * t;
|
|
}
|
|
double t = (effectivePercent - 20.0) / 40.0;
|
|
if (effectivePercent <= 40.0) {
|
|
double tt = (effectivePercent - 20.0) / 20.0;
|
|
return 2.0 + 1.0 * tt;
|
|
}
|
|
double tt = (effectivePercent - 40.0) / 20.0;
|
|
return 2.0 + 1.0 * tt;
|
|
}
|
|
|
|
private static double computeBaseIntensityPercent(double effectivePercent) {
|
|
if (effectivePercent <= 60.0) {
|
|
return 0.0;
|
|
}
|
|
if (effectivePercent <= 70.0) {
|
|
double t = (effectivePercent - 60.0) / 10.0;
|
|
return 0.0 + 60.0 * t;
|
|
}
|
|
if (effectivePercent <= 85.0) {
|
|
double t = (effectivePercent - 70.0) / 15.0;
|
|
return 60.0 + 20.0 * t;
|
|
}
|
|
if (effectivePercent <= 90.0) {
|
|
double t = (effectivePercent - 85.0) / 5.0;
|
|
return 80.0 + 20.0 * t;
|
|
}
|
|
return 100.0;
|
|
}
|
|
|
|
private static double computePowerMultiplier(double power) {
|
|
double[][] points = new double[][]{{2.0, 1.0}, {5.0, 1.2}, {6.0, 1.4}, {12.0, 1.8}, {13.0, 2.0}, {22.0, 2.3}, {23.0, 2.7}, {50.0, 3.0}, {51.0, 3.2}, {80.0, 5.0}, {120.0, 7.0}};
|
|
double clamped = Math.max(points[0][0], Math.min(points[points.length - 1][0], power));
|
|
for (int i = 1; i < points.length; ++i) {
|
|
double lowerP = points[i - 1][0];
|
|
double upperP = points[i][0];
|
|
if (!(clamped <= upperP)) continue;
|
|
double lowerM = points[i - 1][1];
|
|
double upperM = points[i][1];
|
|
double t = (clamped - lowerP) / (upperP - lowerP);
|
|
return lowerM + (upperM - lowerM) * t;
|
|
}
|
|
return points[points.length - 1][1];
|
|
}
|
|
|
|
private static double computePowerChance(double power, boolean explosionInCave) {
|
|
double[][] points = explosionInCave ? new double[][]{{1.0, 0.25}, {2.0, 0.3}, {3.0, 0.35}, {5.0, 0.4}, {6.0, 0.5}, {10.0, 0.75}, {15.0, 0.9}, {20.0, 1.0}, {120.0, 1.0}} : new double[][]{{1.0, 0.15}, {2.0, 0.15}, {3.0, 0.175}, {5.0, 0.215}, {6.0, 0.225}, {10.0, 0.225}, {11.0, 0.35}, {25.0, 0.4}, {26.0, 0.5}, {34.0, 0.75}, {42.0, 0.9}, {50.0, 1.0}, {120.0, 1.0}};
|
|
double clamped = Math.max(points[0][0], Math.min(points[points.length - 1][0], power));
|
|
for (int i = 1; i < points.length; ++i) {
|
|
double lowerP = points[i - 1][0];
|
|
double upperP = points[i][0];
|
|
if (!(clamped <= upperP)) continue;
|
|
double lowerC = points[i - 1][1];
|
|
double upperC = points[i][1];
|
|
double t = (clamped - lowerP) / (upperP - lowerP);
|
|
return lowerC + (upperC - lowerC) * t;
|
|
}
|
|
return 1.0;
|
|
}
|
|
|
|
private static double computeBaseBlurSilentSeconds(double effectivePercent, boolean explosionInCave) {
|
|
if (!explosionInCave) {
|
|
if (effectivePercent <= 40.0) {
|
|
return 0.0;
|
|
}
|
|
if (effectivePercent > 80.0) {
|
|
double t = (effectivePercent - 80.0) / 20.0;
|
|
return 6.0 + 2.0 * t;
|
|
}
|
|
if (effectivePercent > 60.0) {
|
|
double t = (effectivePercent - 60.0) / 20.0;
|
|
return 2.0 + 4.0 * t;
|
|
}
|
|
double t = (effectivePercent - 40.0) / 20.0;
|
|
return 0.0 + 2.0 * t;
|
|
}
|
|
if (effectivePercent <= 20.0) {
|
|
return 0.0;
|
|
}
|
|
if (effectivePercent > 80.0) {
|
|
double t = (effectivePercent - 80.0) / 20.0;
|
|
return 12.0 + 6.0 * t;
|
|
}
|
|
if (effectivePercent > 60.0) {
|
|
double t = (effectivePercent - 60.0) / 20.0;
|
|
return 6.0 + 2.0 * t;
|
|
}
|
|
if (effectivePercent <= 40.0) {
|
|
double tt = (effectivePercent - 20.0) / 20.0;
|
|
return 2.0 + 2.0 * Math.max(0.0, Math.min(1.0, tt));
|
|
}
|
|
double tt = (effectivePercent - 40.0) / 20.0;
|
|
return 2.0 + 2.0 * Math.max(0.0, Math.min(1.0, tt));
|
|
}
|
|
|
|
private static double computeBaseBlurIntensityPercent(double effectivePercent) {
|
|
if (effectivePercent < 60.0) {
|
|
return 0.0;
|
|
}
|
|
double t = (effectivePercent - 60.0) / 40.0;
|
|
return 1.0 + 49.0 * t;
|
|
}
|
|
|
|
private static double computeBaseSwayIntensityPercent(double effectivePercent) {
|
|
if (effectivePercent < 50.0) {
|
|
return 0.0;
|
|
}
|
|
double t = (effectivePercent - 50.0) / 50.0;
|
|
return 100.0 * t;
|
|
}
|
|
|
|
private static double computeBlurPowerMultiplier(double power) {
|
|
double[][] points = new double[][]{{2.0, 1.0}, {5.0, 1.2}, {6.0, 1.4}, {12.0, 1.8}, {13.0, 2.0}, {22.0, 2.3}, {23.0, 2.7}, {50.0, 3.0}, {51.0, 3.2}, {80.0, 5.0}, {120.0, 7.0}};
|
|
double clamped = Math.max(points[0][0], Math.min(points[points.length - 1][0], power));
|
|
for (int i = 1; i < points.length; ++i) {
|
|
double lowerP = points[i - 1][0];
|
|
double upperP = points[i][0];
|
|
if (!(clamped <= upperP)) continue;
|
|
double lowerM = points[i - 1][1];
|
|
double upperM = points[i][1];
|
|
double t = (clamped - lowerP) / (upperP - lowerP);
|
|
return lowerM + (upperM - lowerM) * t;
|
|
}
|
|
return points[points.length - 1][1];
|
|
}
|
|
|
|
public static void renderHeartbeatHUD(GuiGraphics ctx) {
|
|
if (!((Boolean)Config.CLIENT.showHeartbeatHUD.get()).booleanValue() || !Blur.isActive()) {
|
|
return;
|
|
}
|
|
Minecraft mc = Minecraft.m_91087_();
|
|
if (mc.f_91074_ == null) {
|
|
return;
|
|
}
|
|
float bps = currentBPM / 60.0f;
|
|
String text = String.format("%.2f bps (%.1f BPM)", Float.valueOf(bps), Float.valueOf(currentBPM));
|
|
int x = ctx.m_280182_() - 10;
|
|
int y = 10;
|
|
int color = -65536;
|
|
if (currentBPM < 30.0f) {
|
|
color = -11141291;
|
|
} else if (currentBPM < 50.0f) {
|
|
color = -171;
|
|
}
|
|
ctx.m_280056_(mc.f_91062_, text, x - mc.f_91062_.m_92895_(text), y, color, false);
|
|
}
|
|
|
|
public static float getCurrentHeartbeatVisual() {
|
|
return heartbeatVisualPulse;
|
|
}
|
|
|
|
public static void updateHeartbeat(LocalPlayer player, float blurIntensity) {
|
|
float healthPercent;
|
|
boolean isMoving;
|
|
if (player == null) {
|
|
return;
|
|
}
|
|
if (!Blur.isActive()) {
|
|
explosionBPMMod *= 0.98f;
|
|
jumpBPMMod *= 0.98f;
|
|
if ((currentBPM += (23.3f - currentBPM) * 0.05f) < 24.0f && explosionBPMMod < 0.1f && jumpBPMMod < 0.1f) {
|
|
currentBPM = 23.3f;
|
|
explosionBPMMod = 0.0f;
|
|
jumpBPMMod = 0.0f;
|
|
heartbeatVisualPulse = 0.0f;
|
|
return;
|
|
}
|
|
}
|
|
float baseBPM = 23.3f;
|
|
boolean bl = isMoving = player.m_20184_().m_165925_() > 0.001;
|
|
if (isMoving) {
|
|
if (player.m_20142_()) {
|
|
baseBPM = 50.0f;
|
|
if (!player.m_20096_()) {
|
|
baseBPM = 60.0f;
|
|
}
|
|
} else {
|
|
baseBPM = 35.0f;
|
|
}
|
|
}
|
|
if ((healthPercent = player.m_21223_() / player.m_21233_()) < 0.1f) {
|
|
baseBPM += 63.3f;
|
|
} else if (healthPercent < 0.3f) {
|
|
baseBPM += 43.3f;
|
|
}
|
|
if (!player.m_20096_() && wasOnGround && isMoving) {
|
|
jumpBPMMod = Math.min(13.3f, jumpBPMMod + 3.3f);
|
|
}
|
|
wasOnGround = player.m_20096_();
|
|
jumpBPMMod *= 0.99f;
|
|
explosionBPMMod *= 0.995f;
|
|
if (player.f_19789_ > 3.0f) {
|
|
baseBPM += Math.min(16.6f, player.f_19789_ * 1.6f);
|
|
}
|
|
if (player.m_20146_() <= 0) {
|
|
baseBPM += 5.0f;
|
|
}
|
|
if (player.m_6047_()) {
|
|
baseBPM -= 3.3f;
|
|
}
|
|
if (!isMoving) {
|
|
if (++idleTicks >= 60) {
|
|
baseBPM -= 1.6f;
|
|
idleTicks = 0;
|
|
}
|
|
} else {
|
|
idleTicks = 0;
|
|
}
|
|
float finalTarget = baseBPM + jumpBPMMod + explosionBPMMod;
|
|
if ((finalTarget = Math.max(20.0f, Math.min(130.0f, finalTarget))) > currentBPM) {
|
|
float rampSpeed = explosionBPMMod > 5.0f || Blur.isActive() ? 0.4f : 0.15f;
|
|
currentBPM += (finalTarget - currentBPM) * rampSpeed;
|
|
} else {
|
|
currentBPM += (finalTarget - currentBPM) * 0.04f;
|
|
}
|
|
double cycleSeconds = 60.0 / (double)Math.max(5.0f, currentBPM);
|
|
heartbeatCycleTimer += 0.05;
|
|
if (heartbeatCycleTimer >= cycleSeconds) {
|
|
heartbeatCycleTimer -= cycleSeconds;
|
|
lubTriggered = false;
|
|
dubTriggered = false;
|
|
}
|
|
double t = heartbeatCycleTimer;
|
|
float pulse = 0.0f;
|
|
double lubEnd = cycleSeconds * 0.35;
|
|
double pause1End = cycleSeconds * 0.45;
|
|
double dubEnd = cycleSeconds * 0.7;
|
|
if (t < lubEnd) {
|
|
s = (float)Math.sin(t / lubEnd * Math.PI);
|
|
pulse = (float)Math.pow(s, 1.2);
|
|
if (!lubTriggered) {
|
|
lubTriggered = true;
|
|
if (blurIntensity >= 0.1f && ((Boolean)Config.CLIENT.enableHeartbeatPulse.get()).booleanValue()) {
|
|
try {
|
|
Minecraft mc = Minecraft.m_91087_();
|
|
if (mc != null) {
|
|
mc.m_91106_().m_120367_((SoundInstance)SimpleSoundInstance.m_119755_((SoundEvent)((SoundEvent)ModSounds.HEART_LAB.get()), (float)1.0f, (float)100.0f));
|
|
}
|
|
}
|
|
catch (Throwable mc) {}
|
|
}
|
|
}
|
|
} else if (t > pause1End && t < dubEnd) {
|
|
s = (float)Math.sin((t - pause1End) / (dubEnd - pause1End) * Math.PI);
|
|
pulse = (float)Math.pow(s, 1.2) * 0.7f;
|
|
if (!dubTriggered) {
|
|
dubTriggered = true;
|
|
if (blurIntensity >= 0.1f && ((Boolean)Config.CLIENT.enableHeartbeatPulse.get()).booleanValue()) {
|
|
try {
|
|
Minecraft mc = Minecraft.m_91087_();
|
|
if (mc != null) {
|
|
mc.m_91106_().m_120367_((SoundInstance)SimpleSoundInstance.m_119755_((SoundEvent)((SoundEvent)ModSounds.HEART_DAB.get()), (float)1.0f, (float)100.0f));
|
|
}
|
|
}
|
|
catch (Throwable throwable) {
|
|
// empty catch block
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ((healthPercent < 0.05f || explosionBPMMod > 80.0f && t < 2.0) && ThreadLocalRandom.current().nextDouble() < 0.03) {
|
|
heartbeatCycleTimer += 0.08;
|
|
}
|
|
float pulseScale = 0.3f + blurIntensity * 1.5f;
|
|
heartbeatVisualPulse = pulse * pulseScale;
|
|
}
|
|
|
|
private static double computeBaseLowpassSilentSeconds(double effectivePercent, boolean explosionInCave) {
|
|
if (!explosionInCave) {
|
|
if (effectivePercent <= 40.0) {
|
|
return 0.0;
|
|
}
|
|
if (effectivePercent > 80.0) {
|
|
double t = (effectivePercent - 80.0) / 20.0;
|
|
return 8.0 + 2.0 * t;
|
|
}
|
|
if (effectivePercent > 60.0) {
|
|
double t = (effectivePercent - 60.0) / 20.0;
|
|
return 4.0 + 4.0 * t;
|
|
}
|
|
double t = (effectivePercent - 40.0) / 20.0;
|
|
return 2.0 + 2.0 * t;
|
|
}
|
|
if (effectivePercent <= 20.0) {
|
|
return 0.0;
|
|
}
|
|
if (effectivePercent > 80.0) {
|
|
double t = (effectivePercent - 80.0) / 20.0;
|
|
return 14.0 + 6.0 * t;
|
|
}
|
|
if (effectivePercent > 60.0) {
|
|
double t = (effectivePercent - 60.0) / 20.0;
|
|
return 8.0 + 2.0 * t;
|
|
}
|
|
if (effectivePercent <= 40.0) {
|
|
double tt = (effectivePercent - 20.0) / 20.0;
|
|
return 4.0 + 2.0 * Math.max(0.0, Math.min(1.0, tt));
|
|
}
|
|
double tt = (effectivePercent - 40.0) / 20.0;
|
|
return 4.0 + 2.0 * Math.max(0.0, Math.min(1.0, tt));
|
|
}
|
|
|
|
private static double computeBaseLowpassIntensityPercent(double effectivePercent) {
|
|
if (effectivePercent <= 40.0) {
|
|
return 0.0;
|
|
}
|
|
if (effectivePercent <= 50.0) {
|
|
double t = (effectivePercent - 40.0) / 10.0;
|
|
return 0.0 + 70.0 * t;
|
|
}
|
|
if (effectivePercent <= 70.0) {
|
|
double t = (effectivePercent - 50.0) / 20.0;
|
|
return 70.0 + 30.0 * t;
|
|
}
|
|
return 100.0;
|
|
}
|
|
|
|
private static double computeLowpassPowerMultiplier(double power) {
|
|
double[][] points = new double[][]{{2.0, 1.0}, {5.0, 1.2}, {6.0, 1.4}, {12.0, 1.8}, {13.0, 2.0}, {22.0, 2.3}, {23.0, 2.7}, {50.0, 3.0}, {51.0, 3.2}, {80.0, 5.0}, {120.0, 7.0}};
|
|
double clamped = Math.max(points[0][0], Math.min(points[points.length - 1][0], power));
|
|
for (int i = 1; i < points.length; ++i) {
|
|
double lowerP = points[i - 1][0];
|
|
double upperP = points[i][0];
|
|
if (!(clamped <= upperP)) continue;
|
|
double lowerM = points[i - 1][1];
|
|
double upperM = points[i][1];
|
|
double t = (clamped - lowerP) / (upperP - lowerP);
|
|
return lowerM + (upperM - lowerM) * t;
|
|
}
|
|
return points[points.length - 1][1];
|
|
}
|
|
|
|
private static double computeLowpassPowerChance(double power, boolean explosionInCave) {
|
|
double[][] points = explosionInCave ? new double[][]{{1.0, 0.5}, {2.0, 0.6}, {3.0, 0.7}, {5.0, 0.8}, {6.0, 0.95}, {120.0, 1.0}} : new double[][]{{1.0, 0.3}, {2.0, 0.3}, {3.0, 0.35}, {5.0, 0.43}, {6.0, 0.45}, {10.0, 0.45}, {11.0, 0.7}, {25.0, 0.8}, {26.0, 1.0}, {120.0, 1.0}};
|
|
double clamped = Math.max(points[0][0], Math.min(points[points.length - 1][0], power));
|
|
for (int i = 1; i < points.length; ++i) {
|
|
double lowerP = points[i - 1][0];
|
|
double upperP = points[i][0];
|
|
if (!(clamped <= upperP)) continue;
|
|
double lowerC = points[i - 1][1];
|
|
double upperC = points[i][1];
|
|
double t = (clamped - lowerP) / (upperP - lowerP);
|
|
return lowerC + (upperC - lowerC) * t;
|
|
}
|
|
return 1.0;
|
|
}
|
|
}
|
|
|