Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -88,39 +88,20 @@ public sealed interface GameConfig permits GameConfigImpl, InternalGameConfig {
Key DEFAULT_DAMAGE_SOUND = Key.key("entity.player.hurt");

/**
* The static the slender hears while the survivors take his pages away.
* The {@link #pageGlitchPulseSeconds()} a configuration gets when it says nothing.
* <p>
* A resource pack sound rather than a vanilla one: three 2.2 second takes of tape hiss the
* client picks between, high-passed at 520 Hz so the effect's own pitch drop to 0.7 leaves
* it hissing rather than humming. Nothing in vanilla comes close - rain is the nearest, and
* it reads as weather.
* </p>
* <p>
* A server running without the Cygnus pack therefore hears nothing here. That is the right
* way round: the static is a horror cue, and half of one played through the wrong sample is
* worse than none.
* Long enough that a find registers as its own event on screen, short enough that the slender
* is not looking through it while he chases somebody.
* </p>
*/
Key DEFAULT_SLENDER_STATIC_SOUND = Key.key("cygnus", "vhs_static");

/** The {@link #slenderStaticQuietInterval()} a configuration gets when it says nothing. */
int DEFAULT_SLENDER_STATIC_QUIET_INTERVAL = 12;

/** The {@link #slenderStaticFranticInterval()} a configuration gets when it says nothing. */
int DEFAULT_SLENDER_STATIC_FRANTIC_INTERVAL = 3;
int DEFAULT_PAGE_GLITCH_PULSE_SECONDS = 3;

/**
* The longest {@link #slenderStaticQuietInterval()} a configuration may ask for. Past this a
* round could end before the slender has heard the static twice, which makes it noise rather
* than a clock.
* The longest {@link #pageGlitchPulseSeconds()} a configuration may ask for. Past this a find
* late in the round would still be on his screen when the next one lands, and the pulse stops
* being a pulse.
*/
int MAX_SLENDER_STATIC_INTERVAL = 120;

/** The {@link #slenderStaticMinVolume()} a configuration gets when it says nothing. */
float DEFAULT_SLENDER_STATIC_MIN_VOLUME = 0.15F;

/** The {@link #slenderStaticMaxVolume()} a configuration gets when it says nothing. */
float DEFAULT_SLENDER_STATIC_MAX_VOLUME = 0.8F;
int MAX_PAGE_GLITCH_PULSE_SECONDS = 30;

/**
* The largest {@link #glitchRange()} a configuration may ask for. Beyond this the slender would
Expand Down Expand Up @@ -334,60 +315,24 @@ static Builder builder() {
Key damageSound();

/**
* Returns whether the slender hears static as the survivors collect his pages.
*
* @return {@code true} while the static is on
* @since 2.14.0
*/
boolean slenderStaticEnabled();

/**
* Returns the sound the static is built from.
* Returns whether the slender's own screen tears as the survivors collect his pages.
* <p>
* The key is not resolved against the sound registry here: a resource pack sound is a perfectly
* good answer and would not be found in it. It is sent as named.
* The effect rides the same channel as the gaze glitch and is therefore drawn by the resource
* pack, which is why it is gated by the overlays as well as by this setting.
* </p>
*
* @return the sound key, never {@code null}
* @since 2.14.0
*/
Key slenderStaticSound();

/**
* Returns how many seconds lie between two bursts while no page has been found.
*
* @return the interval in seconds, at most {@link #MAX_SLENDER_STATIC_INTERVAL}
* @since 2.14.0
*/
int slenderStaticQuietInterval();

/**
* Returns how many seconds lie between two bursts once every page is gone.
* <p>
* The gap shrinks from {@link #slenderStaticQuietInterval()} towards this value as the pages
* disappear, which is what tells the slender how late in the round he is.
* </p>
*
* @return the interval in seconds, below {@link #slenderStaticQuietInterval()}
* @since 2.14.0
*/
int slenderStaticFranticInterval();

/**
* Returns how loud the static is while no page has been found.
*
* @return the volume, between 0 and {@link #slenderStaticMaxVolume()}
* @since 2.14.0
* @return {@code true} while the page glitch is on
* @since 2.15.0
*/
float slenderStaticMinVolume();
boolean pageGlitchEnabled();

/**
* Returns how loud the static is once every page is gone.
* Returns how long a single find holds the glitch one level above where the round stands.
*
* @return the volume, at most 1
* @since 2.14.0
* @return the pulse in seconds, at most {@link #MAX_PAGE_GLITCH_PULSE_SECONDS}
* @since 2.15.0
*/
float slenderStaticMaxVolume();
int pageGlitchPulseSeconds();

/**
* Returns how close the slender has to be before the sight of him tears a survivor's view.
Expand Down Expand Up @@ -596,63 +541,24 @@ sealed interface Builder permits GameConfigBuilder {
Builder damageSound(Key damageSound);

/**
* Sets whether the slender hears static as the survivors collect his pages.
*
* @param slenderStaticEnabled {@code true} to keep the static on
* @return the builder instance
* @since 2.14.0
*/
Builder slenderStaticEnabled(boolean slenderStaticEnabled);

/**
* Sets the sound the static is built from.
*
* @param slenderStaticSound the sound key
* @return the builder instance
* @since 2.14.0
*/
Builder slenderStaticSound(Key slenderStaticSound);

/**
* Sets how many seconds lie between two bursts while no page has been found.
*
* @param slenderStaticQuietInterval the interval in seconds
* @return the builder instance
* @throws IllegalArgumentException if the interval is below 1 or above
* {@link GameConfig#MAX_SLENDER_STATIC_INTERVAL}
* @since 2.14.0
*/
Builder slenderStaticQuietInterval(int slenderStaticQuietInterval);

/**
* Sets how many seconds lie between two bursts once every page is gone.
*
* @param slenderStaticFranticInterval the interval in seconds
* @return the builder instance
* @throws IllegalArgumentException if the interval is below 1
* @since 2.14.0
*/
Builder slenderStaticFranticInterval(int slenderStaticFranticInterval);

/**
* Sets how loud the static is while no page has been found.
* Sets whether the slender's own screen tears as the survivors collect his pages.
*
* @param slenderStaticMinVolume the volume
* @param pageGlitchEnabled {@code true} to keep the page glitch on
* @return the builder instance
* @throws IllegalArgumentException if the volume is below 0 or above 1
* @since 2.14.0
* @since 2.15.0
*/
Builder slenderStaticMinVolume(float slenderStaticMinVolume);
Builder pageGlitchEnabled(boolean pageGlitchEnabled);

/**
* Sets how loud the static is once every page is gone.
* Sets how long a single find holds the glitch above where the round stands.
*
* @param slenderStaticMaxVolume the volume
* @param pageGlitchPulseSeconds the pulse in seconds
* @return the builder instance
* @throws IllegalArgumentException if the volume is below 0 or above 1
* @since 2.14.0
* @throws IllegalArgumentException if the pulse is below 1 or above
* {@link GameConfig#MAX_PAGE_GLITCH_PULSE_SECONDS}
* @since 2.15.0
*/
Builder slenderStaticMaxVolume(float slenderStaticMaxVolume);
Builder pageGlitchPulseSeconds(int pageGlitchPulseSeconds);

/**
* Sets how close the slender has to be before the sight of him tears a survivor's view.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,8 @@ public final class GameConfigBuilder implements GameConfig.Builder {
private int glitchRange = GameConfig.DEFAULT_GLITCH_RANGE;
private int glitchCloseRange = GameConfig.DEFAULT_GLITCH_CLOSE_RANGE;
private int glitchViewAngle = GameConfig.DEFAULT_GLITCH_VIEW_ANGLE;
private boolean slenderStaticEnabled;
private Key slenderStaticSound = GameConfig.DEFAULT_SLENDER_STATIC_SOUND;
// Pre-set for the same reason as the glitch distances above: build() checks the two intervals
// and the two volumes against each other, and a builder that was never told about the static
// would trip those checks on a pair of zeroes.
private int slenderStaticQuietInterval = GameConfig.DEFAULT_SLENDER_STATIC_QUIET_INTERVAL;
private int slenderStaticFranticInterval = GameConfig.DEFAULT_SLENDER_STATIC_FRANTIC_INTERVAL;
private float slenderStaticMinVolume = GameConfig.DEFAULT_SLENDER_STATIC_MIN_VOLUME;
private float slenderStaticMaxVolume = GameConfig.DEFAULT_SLENDER_STATIC_MAX_VOLUME;
private boolean pageGlitchEnabled;
private int pageGlitchPulseSeconds = GameConfig.DEFAULT_PAGE_GLITCH_PULSE_SECONDS;

@Override
public GameConfig.Builder minPlayers(int minPlayers) {
Expand Down Expand Up @@ -207,66 +200,22 @@ public GameConfig.Builder glitchViewAngle(int glitchViewAngle) {
}

@Override
public GameConfig.Builder slenderStaticEnabled(boolean slenderStaticEnabled) {
this.slenderStaticEnabled = slenderStaticEnabled;
public GameConfig.Builder pageGlitchEnabled(boolean pageGlitchEnabled) {
this.pageGlitchEnabled = pageGlitchEnabled;
return this;
}

@Override
public GameConfig.Builder slenderStaticSound(Key slenderStaticSound) {
this.slenderStaticSound = slenderStaticSound;
return this;
}

@Override
public GameConfig.Builder slenderStaticQuietInterval(int slenderStaticQuietInterval) {
if (slenderStaticQuietInterval < 1
|| slenderStaticQuietInterval > GameConfig.MAX_SLENDER_STATIC_INTERVAL) {
public GameConfig.Builder pageGlitchPulseSeconds(int pageGlitchPulseSeconds) {
if (pageGlitchPulseSeconds < 1 || pageGlitchPulseSeconds > GameConfig.MAX_PAGE_GLITCH_PULSE_SECONDS) {
throw new IllegalArgumentException(
"Slender static quiet interval must be between 1 and "
+ GameConfig.MAX_SLENDER_STATIC_INTERVAL + " seconds");
}
this.slenderStaticQuietInterval = slenderStaticQuietInterval;
return this;
}

@Override
public GameConfig.Builder slenderStaticFranticInterval(int slenderStaticFranticInterval) {
if (slenderStaticFranticInterval < 1) {
throw new IllegalArgumentException("Slender static frantic interval must be at least 1 second");
"Page glitch pulse must be between 1 and "
+ GameConfig.MAX_PAGE_GLITCH_PULSE_SECONDS + " seconds");
}
this.slenderStaticFranticInterval = slenderStaticFranticInterval;
return this;
}

@Override
public GameConfig.Builder slenderStaticMinVolume(float slenderStaticMinVolume) {
this.slenderStaticMinVolume = checkVolume(slenderStaticMinVolume, "minimum");
return this;
}

@Override
public GameConfig.Builder slenderStaticMaxVolume(float slenderStaticMaxVolume) {
this.slenderStaticMaxVolume = checkVolume(slenderStaticMaxVolume, "maximum");
this.pageGlitchPulseSeconds = pageGlitchPulseSeconds;
return this;
}

/**
* Checks a static volume against the range a sound can carry.
*
* @param volume the volume to check
* @param name how the volume is named in the message of a failure
* @return the volume
* @throws IllegalArgumentException if the volume is outside 0 to 1
*/
private static float checkVolume(float volume, String name) {
if (volume < 0.0F || volume > 1.0F) {
throw new IllegalArgumentException(
"Slender static " + name + " volume must be between 0 and 1");
}
return volume;
}

/**
* {@inheritDoc}
* <p>
Expand All @@ -285,16 +234,6 @@ public GameConfig build() {
"Glitch close range (" + glitchCloseRange + ") must be below the glitch range ("
+ glitchRange + ")");
}
if (slenderStaticFranticInterval >= slenderStaticQuietInterval) {
throw new IllegalArgumentException(
"Slender static frantic interval (" + slenderStaticFranticInterval
+ ") must be below the quiet interval (" + slenderStaticQuietInterval + ")");
}
if (slenderStaticMinVolume > slenderStaticMaxVolume) {
throw new IllegalArgumentException(
"Slender static minimum volume (" + slenderStaticMinVolume
+ ") must not be above the maximum volume (" + slenderStaticMaxVolume + ")");
}
return new GameConfigImpl(
minPlayers,
maxPlayers,
Expand All @@ -316,12 +255,8 @@ public GameConfig build() {
glitchRange,
glitchCloseRange,
glitchViewAngle,
slenderStaticEnabled,
slenderStaticSound,
slenderStaticQuietInterval,
slenderStaticFranticInterval,
slenderStaticMinVolume,
slenderStaticMaxVolume
pageGlitchEnabled,
pageGlitchPulseSeconds
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,8 @@
* @param glitchCloseRange the distance in blocks at which the tearing is at its worst
* @param glitchViewAngle how far off the centre of their view he may stand and still count
* as seen, in degrees
* @param slenderStaticEnabled whether the slender hears static as his pages are collected
* @param slenderStaticSound the sound the static is built from
* @param slenderStaticQuietInterval the seconds between two bursts while no page has been found
* @param slenderStaticFranticInterval the seconds between two bursts once every page is gone
* @param slenderStaticMinVolume how loud the static is while no page has been found
* @param slenderStaticMaxVolume how loud the static is once every page is gone
* @param pageGlitchEnabled whether the slender's screen tears as his pages are collected
* @param pageGlitchPulseSeconds how long a single find holds the glitch above the round's level
* @author theEvilReaper
* @version 1.4.0
* @since 1.0.0
Expand All @@ -64,12 +60,8 @@ public record GameConfigImpl(
int glitchRange,
int glitchCloseRange,
int glitchViewAngle,
boolean slenderStaticEnabled,
Key slenderStaticSound,
int slenderStaticQuietInterval,
int slenderStaticFranticInterval,
float slenderStaticMinVolume,
float slenderStaticMaxVolume
boolean pageGlitchEnabled,
int pageGlitchPulseSeconds
) implements GameConfig {

}
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,8 @@
* <li>glitchRange</li>
* <li>glitchCloseRange</li>
* <li>glitchViewAngle</li>
* <li>slenderStaticEnabled</li>
* <li>slenderStaticSound</li>
* <li>slenderStaticQuietInterval</li>
* <li>slenderStaticFranticInterval</li>
* <li>slenderStaticMinVolume</li>
* <li>slenderStaticMaxVolume</li>
* <li>pageGlitchEnabled</li>
* <li>pageGlitchPulseSeconds</li>
* </ul>
* <p>
* If a property can not be found in the file, the default value will be used.
Expand All @@ -65,7 +61,6 @@ public final class GameConfigReader {
private static final Pattern SHA1_PATTERN = Pattern.compile("[0-9a-fA-F]{40}");
private static final String PAGE_PROXIMITY_SOUND_KEY = "pageProximitySound";
private static final String DAMAGE_SOUND_KEY = "damageSound";
private static final String SLENDER_STATIC_SOUND_KEY = "slenderStaticSound";

private final Path path;

Expand Down Expand Up @@ -128,12 +123,8 @@ public GameConfig getConfig() {
.glitchRange(getInt(properties, "glitchRange", internal.glitchRange()))
.glitchCloseRange(getInt(properties, "glitchCloseRange", internal.glitchCloseRange()))
.glitchViewAngle(getInt(properties, "glitchViewAngle", internal.glitchViewAngle()))
.slenderStaticEnabled(getBoolean(properties, "slenderStaticEnabled", internal.slenderStaticEnabled()))
.slenderStaticSound(getSound(properties, SLENDER_STATIC_SOUND_KEY, internal.slenderStaticSound()))
.slenderStaticQuietInterval(getInt(properties, "slenderStaticQuietInterval", internal.slenderStaticQuietInterval()))
.slenderStaticFranticInterval(getInt(properties, "slenderStaticFranticInterval", internal.slenderStaticFranticInterval()))
.slenderStaticMinVolume(getFloat(properties, "slenderStaticMinVolume", internal.slenderStaticMinVolume()))
.slenderStaticMaxVolume(getFloat(properties, "slenderStaticMaxVolume", internal.slenderStaticMaxVolume()));
.pageGlitchEnabled(getBoolean(properties, "pageGlitchEnabled", internal.pageGlitchEnabled()))
.pageGlitchPulseSeconds(getInt(properties, "pageGlitchPulseSeconds", internal.pageGlitchPulseSeconds()));

return configBuilder.build();
}
Expand Down
Loading
Loading