HornetCloakColor
Change the color of Hornet's cloak. Fully synchronized with other SSMP players.
| Last updated | a week ago |
| Total downloads | 1152 |
| Total rating | 2 |
| Categories | Cosmetic |
| Dependency string | Michael4d45-HornetCloakColor-1.7.3 |
| Dependants | 0 other packages depend on this package |
This mod requires the following mods to function
BepInEx-BepInExPack_Silksong
BepInEx modloader. Preconfigured and ready to use.
Preferred version: 5.4.2304README
HornetCloakColor
A BepInEx mod for Hollow Knight: Silksong that lets you change the color of Hornet's cloak.
Works single-player out of the box. If SSMP (Silksong Multiplayer) is also installed, the chosen color is automatically synchronized to every other player on the server so everyone sees your custom cloak in real time.
Source: github.com/Michael4d45/HornetCloakColor
Features
- Pick from 12 tasteful presets (Crimson, Scarlet, Amber, Gold, Emerald, Teal, Azure, Royal, Violet, Magenta, Obsidian, Ivory) or supply your own hex / RGB color.
- Cloak-only recolor: a custom shader matches pixels to reference cloak colors (defaults ship 16 cloak refs + 10 avoid refs in
cloak_palette.json) and recolors only cloak-like pixels. Editcloak_palette.jsonnext to the DLL to tune masking when an animation/atlas still looks wrong. - Scene-wide coverage: a separate scanner finds any sprite drawing a Hornet atlas (matched by texture name) anywhere in the scene, even renderers spawned outside the player hierarchy (e.g. steam-vent recoil pose, item-get pose), so animations don't pop back to red.
- If the shader bundle isn't embedded, the mod falls back to tinting the whole character.
- Zero-friction configuration through the BepInEx configuration manager (F1 in game).
- Works without SSMP — runs in single-player and recolors your own cloak. SSMP is a soft dependency: install it to also synchronize cloak colors with other players.
- When SSMP is installed, late-joiners receive a replay of every existing player's color on connect so nobody ever sees the wrong color.
Installation
Via a mod manager (recommended)
- Install HornetCloakColor through r2modman / Thunderstore Mod Manager.
- (Optional) Install SSMP too if you want your color to sync to other players in multiplayer.
- Launch Silksong through the mod manager.
Manual
- Install BepInEx for Silksong.
- Copy
HornetCloakColor.dllandcloak_palette.jsonintoBepInEx/plugins/HornetCloakColor/(Thunderstore builds include both). - (Optional) Install SSMP into
BepInEx/plugins/SSMP/for multiplayer sync. - Launch the game.
Usage
- Launch Silksong and reach the main menu (this ensures BepInEx finishes loading the config).
- Open the BepInEx configuration manager (default keybind: F1).
- Under HornetCloakColor → Appearance:
- Set Cloak Color Preset to White for the stock cloak look (no tint): you should see the game's normal reddish cloak, not a pale sheet. White means the tint multiply is
#FFFFFF, not that the cloak is dyed white. - Pick another preset for a tinted cloak, or set it to
Customand provide a color in the Custom Cloak Color field. Accepted formats:#AA3344,AA3344, or170,51,68(decimal 0–255). - The
cloakColors/avoidColorsentries incloak_palette.jsononly define which texels the shader treats as cloak vs protected — they are not the same as this tint preset.
- Set Cloak Color Preset to White for the stock cloak look (no tint): you should see the game's normal reddish cloak, not a pale sheet. White means the tint multiply is
- Load a save or join a multiplayer server — your cloak will be tinted immediately, and every other SSMP player with this mod installed will see the same color on your Hornet.
Players without this mod will still see vanilla Hornet — they simply won't receive the color updates. You'll still see their vanilla cloaks correctly.
cloak_palette.json
Shipped next to HornetCloakColor.dll. It tells the cloak shader which source colors in the
sprite count as the cloak (so only those pixels are recolored to your preset). You normally do
not need to edit it.
{
"cloakColors": ["#79404b", "..."],
"avoidColors": ["#ffffff", "..."],
"matchRadius": 0.135,
"avoidMatchRadius": 0.12,
"debugLogging": false,
"sceneScanTextureContains": ["hornet"],
"sceneScanPathContains": ["hornet"],
"sceneScanIntervalFrames": 3
}
(Full default lists are in Config/cloak_palette.json in the repo.)
cloakColors: reference hex colors from the vanilla atlases. Up to 16 entries. Texels close to any of them count as cloak. Add more hexes if a specific animation (recoil from a steam vent, dive, dash, etc.) still shows the original red — sample the cloak pixels from the matching atlas in an image editor and append them here.avoidColors: optional; up to 16 hex colors. Texels close to any of these in RGB get their recolor mask reduced (same smoothstep idea as matching, usingavoidMatchRadius), so skin, metal trim, etc. can stay vanilla even if they sit near a cloak reference. Leave empty[]if you do not need masking.matchRadius: how far a pixel may deviate in RGB space and still count as cloak (roughly 0.05–0.35). Raise slightly if some cloak pixels are missed after a game update.avoidMatchRadius: same scale asmatchRadius, used only for the avoid list. If omitted, it defaults to whatevermatchRadiusis after loading the file.debugLogging: whentrue, logs extra lines (e.g. each cloak color change, how many reference colors loaded, and which scene textures the scanner is matching/ignoring). Defaultfalse.sceneScanTextureContains: substrings (case-insensitive) matched against the texture's.name. Rarely useful on its own (Hornet's atlases are namedatlas0/atlas1/…), but any name match is also promoted into the texture-instance registry so future scans of the same atlas hit the fast path.sceneScanPathContains: substrings (case-insensitive) matched against the full GameObject transform path. Rescues scene-specific poses (resting in bed, sitting at things) whose atlas the active hero never renders directly. If a pose still shows red, enabledebugLogging, trigger the pose, and look for[Scanner] Ignored texture (no match): atlas0 … on '<path>'lines — add a substring of that path here.dumpDiscoveredTextures: whentrue, the first time each Hornet atlas is recognized the mod writes a PNG of it toBepInEx/plugins/HornetCloakColor/TextureDumps/. Files are named<texName>_id<InstanceID>_<width>x<height>_<source>.pngso you can correlate runtime instance IDs (from the[Registry]/[Scanner]log lines) with actual sprite sheets, and sample colors to add tocloakColors. Defaultfalse— turn on temporarily, capture the textures you care about, then turn off again.sceneScanIntervalFrames: how often (in frames) the scanner walks everytk2dSpritein the scene.1= every frame;3is a good default. Higher = cheaper but slightly slower to color newly-spawned poses.
If the file is missing or invalid, the built-in defaults are used.
Compatibility
- Game: Hollow Knight: Silksong
- BepInEx: 5.4.21 or later
- SSMP: Optional. If installed, the mod registers as both an SSMP client addon and a server addon so it works on dedicated SSMP servers and on peer-hosted games. If absent, the mod still recolors your own cloak — it just doesn't sync to other players.
- Silksong.GameLibs: Built against the
*-*floating version (whichever is published).
Building from source
# Generate the Silksong path props (once) so the output copies into your install
dotnet new -i Silksong.Templates # only if you don't already have the template
dotnet new silksongpath
# Build
dotnet build HornetCloakColor.csproj -c Release
A thunderstore/dist/*.zip is produced automatically alongside the compiled DLL if thunderstore/thunderstore.toml is configured.
How it works
-
A small
CloakRecolorMonoBehaviour is attached to each player's root GameObject (local hero and SSMP-spawned remote players). EveryLateUpdateit walks allMeshRenderers under that object (GetComponentsInChildren, including inactive children). Some animations use extra meshes or toggled child objects; only updating the root renderer missed those frames. -
A scene-wide
CloakSceneScannerruns on its own GameObject (DontDestroyOnLoad) at a high script-execution order. Every few frames it iterates everytk2dSpritein the scene and applies the local cloak color to any whose main texture matches Hornet. This catches Hornet renderers spawned outside the player hierarchy (steam-vent recoil pose, item-get pose, etc.) whereGetComponentsInChildrencan't reach. Renderers that already have aCloakRecolorancestor are skipped so per-player remote colors keep winning in multiplayer. -
"Matches Hornet" is decided in three stages:
- Texture instance registry — every atlas the per-player
CloakRecolorwalks (which is, by definition, a Hornet atlas) is recorded by itsTexture.GetInstanceID(). The scanner accepts any orphan sprite whose texture has the same instance ID. This is reliable even though Silksong ships Hornet's atlases under the generic namesatlas0–atlas3(also used by many unrelated atlases — name-only filtering would either miss them or recolor everything). - Texture name filter (
sceneScanTextureContains) — substring match againstTexture.name. Useful when something Hornet-named exists outside any tk2dSprite the hero has rendered yet. - GameObject path filter (
sceneScanPathContains) — substring match against the full transform path. Catches scene-specific poses (e.g. resting in bed, sitting at things) whose atlas the active hero never renders directly, so the registry never learns about it. The pose's GameObject typically still has "Hornet" somewhere in its path, so the path filter rescues these.
When stage 2 or 3 matches, the texture is promoted into the registry so subsequent scans hit the fast path.
- Texture instance registry — every atlas the per-player
-
Sprite sheets / atlases: Hornet’s art can live in multiple atlases (e.g. idle vs sprint). If a move still looks wrong, sample the cloak pixels from that atlas in an image editor and add or adjust hex values in
cloak_palette.json/ raisematchRadiusslightly — the mod matches by RGB distance to your reference colors, so different bakes may need tuning. -
Cloak shader path swaps the renderer's shader for
HornetCloakColor/CloakHueShiftand pushes the chosen color in HSV. The shader measures RGB distance from each texel to up to 16 cloak reference colors (fromcloak_palette.json), takes the minimum, and smoothsteps it into a mask. Optionally, distance to up to 16 avoid colors reduces that mask so non-cloak pixels are not recolored. It then replaces hue/saturation while preserving value for shading. The shader is shipped as anAssetBundleembedded in the DLL. -
Fallback (when the shader bundle isn't present) tints the whole character via the
tk2dSpritevertex color and theMeshRenderermaterial color. -
Color updates are serialized as a 5-byte packet (player ID + RGB) and sent through the standard
IClientAddonNetworkSender/IServerAddonNetworkSenderchannels exposed by SSMP. -
The server keeps a simple in-memory table of
playerId -> CloakColorand replays it to any new joiner so late arrivals see correct colors immediately.
Baking the shader bundle
The cloak-only path requires Resources/cloakshader.bundle. It's gitignored, so contributors
need to bake it in Unity once. See Shaders/README.md for step-by-step
instructions (TL;DR: open Unity 6000.0.50, drop the shader and editor script in, click
HornetCloakColor → Build Shader Bundle, copy the output to Resources/).
If the bundle isn't present the build still succeeds and the mod gracefully falls back to the legacy whole-character tint at runtime.
License
MIT — see LICENSE.txt.