Skip to content

feat(slender): tear his own screen as the pages go - #252

Merged
TheMeinerLP merged 2 commits into
mainfrom
feat/slender-vhs-static
Sep 6, 2026
Merged

feat(slender): tear his own screen as the pages go#252
TheMeinerLP merged 2 commits into
mainfrom
feat/slender-vhs-static

Conversation

@TheMeinerLP

@TheMeinerLP TheMeinerLP commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Proposed changes

The slender is the only player in a round without a page counter. The survivors watch theirs climb; he only learns the score when it ends. This gives him that counter as a picture coming apart — the same worn-tape look the survivors get from seeing him, turned back on him and driven by the round rather than by a line of sight.

PageGlitchService (game/.../glitch/) drives two things, both only on his screen:

  • a baseline that climbs a level at a time as the pages disappear, up to the worst of SlenderGaze.LEVELS when the last one goes. Until the first page is found there is NONE, not the weakest level: an untouched round has nothing to say yet.
  • a pulse on every find, one level above the baseline, held for pageGlitchPulseSeconds before falling back.

Three things in here are worth a look in review:

GazeSink.attach(player, worldTint) splits the two halves of the signal. The veil says how far the round has got; the DARKEN_SCREEN bit takes the world's lighting with it. That is right for a survivor looking at the slender and wrong for the slender himself — darkening his world takes the sight he hunts with. He gets the veil alone.

The signal instance is shared with SlenderGazeService instead of a second one being built. A player has one carrier, and two boss bars would each expand to a full-screen quad and stack — the diagnostic note about exactly that failure is already in BossBarGazeSignal. Slender and survivors are disjoint, so the two services never address the same player, except across a hand-over, which the service watches for.

A bug fix that fell out of the hand-over case. PlayerQuitListener promotes a living survivor to slender when the old one quits, so neither the death nor the disconnect listener in SlenderGazeService covered him. Left tracked, levelFor measured him against himself: distance zero, which reads as the worst level, for the rest of the round. He is dropped on SlenderReviveEvent now.

Nothing is needed in the resource pack. The channel, the font and the shader are already there; the four cygnus:gui/glitch/level_N textures removed in cygnus-pack#28 stay removed, they belong to the camera-overlay route this does not use.

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation Update (if none of the other choices apply)

Checklist

  • I have read the CONTRIBUTING.md
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if appropriate)

10 tests in PageGlitchServiceTest cover the clean start, both ends of the baseline, the pulse and how long it holds, the hand-over to a new slender, the missing world tint, the round's end, the off switch and a missing slender. BossBarGazeSignalTest gains the tint-less attach, SlenderGazeServiceTest the promoted survivor, GameConfigReaderTest the two settings. Both are documented in config.properties.example.

Further comments

An earlier revision of this branch played a sound instead of drawing anything, and pointed at a VHS noise built for it in cygnus-pack#34. That was a misreading of the request; the sound is gone from here. Whether the pack keeps that asset is a separate call — nothing in Cygnus references it any more.

The pulse is one level above the baseline, so at the last page it has nowhere left to go. That is deliberate: at that point the round is over within seconds anyway. The baseline curve is linear across SlenderGaze.LEVELS; if it should stay clean longer and then fall apart late, that is one line in level().

The slender is the only player without a page counter, so how far the round has
got never reaches him until it ends. SlenderStaticService turns it into sound: a
carpet whose gap shrinks from slenderStaticQuietInterval down to
slenderStaticFranticInterval as the pages disappear, plus a burst of its own on
every single find. Only he hears it, played on his own entity, so neither side
can place the other by it.

PageProvider now raises PageFoundEvent on every find with the running count.
PageDiscoveryCompletedEvent only ever covered the last page, which is one moment
in a round that spends the rest of its time getting worse.

The configured key is sent as named instead of being resolved against the vanilla
registry: a VHS noise shipped in the resource pack is the sound this wants, and
SoundEvent.fromKey would drop it. Defaults to weather.rain until that key exists.
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Test results

  360 files    360 suites   2m 8s ⏱️
  594 tests   588 ✅  6 💤 0 ❌
1 785 runs  1 767 ✅ 18 💤 0 ❌

Results for commit da367c6.

♻️ This comment has been updated with latest results.

cygnus:vhs_static now exists: three 2.2 second takes of tape hiss, high-passed at
520 Hz so the pitch drop to 0.7 this effect applies leaves it hissing instead of
humming (OneLiteFeatherNET/cygnus-pack#34).

weather.rain was only ever a stand-in for it and reads as weather, not as a tape.
A server without the pack now hears nothing here, which is the right way round
for a horror cue.
@TheMeinerLP
TheMeinerLP merged commit 655e1c4 into main Sep 6, 2026
7 checks passed
@TheMeinerLP TheMeinerLP changed the title feat(slender): let him hear the pages going feat(slender): tear his own screen as the pages go Sep 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant