An exploration-map mod for Slay the Spire 2. It replaces the linear act map with a four-direction grid that can be explored from any previously visited room.
Target: Slay the Spire 2 0.111.x, .NET 9.
- 13×13 coordinate space with 18–22 generated grid rooms and exactly 10 generated dead ends. Boss one and a separately placed hidden room bring the normal total to 20–24 rooms; a double-boss act adds boss two for 21–25 rooms.
- Every connection is one cardinal grid step. Generation keeps branches apart when possible; if rooms become positionally adjacent, all such adjacencies are connected and may form a small incidental mesh.
- Map diameter has a soft cap of 16: layouts above it are probabilistically regenerated, with a 25% additional reroll chance per excess step and a 90% cap.
- The farthest generated dead end from the Ancient/Neow start is always a rest site. Boss one is appended beyond that rest site, so it cannot be used as a junction on the way to another branch.
- In a double-boss act, boss two is appended one room beyond boss one.
- The nearest non-boss dead end is always a treasure room.
- Nine ordinary generated dead ends contain the pre-boss rest site plus treasure 1, shop 1, elite 3, rest 2, and one independently weighted treasure/shop/rest room with 50%/25%/25% odds. The tenth, second-farthest dead end is the super-secret room.
- A second hidden room is added after the base map and boss chain. Empty cardinally adjacent cells, excluding boss-adjacent positions, are selected with weight equal to the cube of their existing-neighbor count and connected to every adjacent room.
- Each hidden room has a 75% chance to be an unknown room forced to resolve as an event and a 25% chance to be a treasure room.
- Non-dead-end ordinary rooms start from the previous rounded 67% monster / 33% unknown allocation, then convert exactly one additional monster room into an unknown room. Across the 18–22 base-room range this yields 3–5 unknown and 4–6 monster rooms.
- Monster coordinates within graph distance 2 of the start use the act's weak encounter pool; later coordinates use the regular pool.
- Normal encounters, including combats rolled by unknown rooms, follow vanilla-style immediate-repeat protection: prefer an encounter that differs from and shares no encounter tags with the previous normal combat, relax the tag rule only when necessary, and permit an exact repeat only when unavoidable.
- Spoils Map remains compatible: after MysteriousMap replaces the vanilla special map, its quest marker is retargeted to the guaranteed nearest treasure dead end. The same correction is reapplied after loading a save.
- Any ordinary unvisited node adjacent to any visited node can be entered. Hidden rooms must first be discovered by throwing a map-targeted potion at an adjacent visited room.
- Visited shops remain selectable; this includes unknown rooms that resolved into shops. Other visited nodes do not.
- Re-entering an unknown-room shop preserves its resolved shop type instead of rolling the question mark again.
- A revisited shop keeps its exact remaining inventory, prices, sale state, and card-removal state, including across save-and-quit. Leaving a shop immediately freezes concrete merchandise IDs; the next visit reconstructs from that snapshot, so relics obtained elsewhere cannot advance the relic sequence and alter the shop shelves.
- In multiplayer, each peer reliably synchronizes its own shop inventory before the host writes the run save, so client purchases, Courier restocks, and card removal remain authoritative after reloading.
- Revisiting a shop does not advance the act-floor counter.
- Meal Ticket and Maw Bank trigger only on the first visit to a shop coordinate. Suppressed repeat-entry hooks return completed tasks so the room-transition pipeline cannot stall after fading out.
- In multiplayer, the host's map-mode and four reveal-option values are embedded in the synchronized run-start payload and save marker. Activation is confirmed again through the game's native modifier run-created/run-loaded lifecycle before the transport marker removes itself, so map mode does not depend solely on one patched construction call. The Mind, Compass, Treasure Map, and Blue Map are locked for every participant during the run and use the host's starting values; local preferences return after cleanup.
- Multiplayer map choices retain the vanilla vote UI, split-vote resolution, host-selected winning coordinate, and network movement action. Votes are validated against the same exploration frontier on every peer.
- Floor/history lookup follows visit order rather than coordinate row.
- Ancient, Neow, boss, and normal controls share the same visual center on the compact grid. After path dots enter the scene tree, connections involving a special node are laid out again between the two nodes' transformed visual pivots, accounting for anchors and the 0.30 scale.
- Path highlighting records only the physical edge used to discover each new room. Merely exploring both endpoints of another mesh connection no longer highlights that unused edge.
- By default, only explored rooms and the currently reachable frontier are visible; other rooms and their connecting paths are hidden.
- Natural discovery is derived exclusively from saved visit history, hidden-room discovery state, and map connectivity. Reveal settings only affect presentation, so toggling The Mind off cannot erase or obstruct the real exploration frontier.
- Four Isaac-inspired reveal options are available under General Settings in a collapsible MysteriousMap group:
- The global switch controls whether future acts use MysteriousMap; existing generated acts remain playable.
- The Mind reveals every ordinary room's actual type. Undiscovered hidden-room positions appear as isolated dotted X markers until potion discovery.
- The Compass reveals every special room.
- Treasure Map reveals every ordinary room position and its connecting paths; currently inaccessible node icons are left blank. It does not reveal hidden rooms.
- Blue Map displays the hidden and super-secret room positions as isolated dotted X markers. Their icons and real connections stay hidden, and they still require potion discovery before entry.
- While map mode is enabled, Winged Boots is removed from Neow's positive-option pool and Golden Compass is removed from Tezcatara's third option pool.
- As a feasibility prototype, combat-only single-target potions can be aimed only at previously visited map nodes while MysteriousMap is open outside combat, including after combat resolution. Mouse and controller use the vanilla targeting arrow and each map point's built-in selection reticle. Selecting a node plays the throw VFX, reveals adjacent hidden rooms with a fade-in, and consumes the potion while intentionally skipping its gameplay effect. AnyTime potions such as Fruit Juice and Blood Potion retain their vanilla map-screen behavior.
- The mod selection list and details panel localize the mod name and description in English, Simplified Chinese, and Traditional Chinese while retaining the vanilla panel styling.
- The vanilla
travelconsole command still works as a debug override. It only togglesNMapScreen.IsDebugTravelEnabled; it is not used for normal exploration.
- Shop state is stored in a versioned Mysterious Map save marker. If that marker is absent or invalid, the affected shop safely falls back to a newly generated inventory.
- Discovered hidden-room coordinates are run-wide rather than player-specific. Map-targeted potion messages apply the reveal even when replicated potion removal arrived first, so every multiplayer character and peer shares the same hidden-room state; the coordinates remain stored in a separate versioned save marker.
- Hidden-room identity is stored as two exact coordinates and tagged independently of vanilla's mutable
MapPoint.CanBeModifiedflag. Version-1 saves recover those coordinates from a deterministic reference map; a failed migration disables hidden markers for that act rather than hiding ordinary exploration nodes. - Mouse/controller behavior is patched against private
NMapScreenmethods and therefore needs re-auditing after game updates. - Map-node potion targeting remains a feasibility test and intentionally skips potion effects and potion-use hooks. Potion removal and used-potion history are applied locally and synchronized between multiplayer peers.
- Multiplayer uses deterministic topology and host-side destination validation, but has not yet been exercised in a live lobby.
- Every multiplayer participant must have the same MysteriousMap build installed so the synchronized mode marker and gameplay patches can be resolved.
- The travel animation uses an explored adjacent source when possible. The player marker can still appear to jump because the design permits expanding from an older explored node rather than only the latest room.
Generation/,Map/,Patches/, andRooms/contain the mod source.assets/localization/contains English, Simplified Chinese, and Traditional Chinese localization.tests/MysteriousMap.Tests/contains deterministic map-generation tests.tests/MysteriousMap.CompatibilityTests/resolves and temporarily applies every Harmony patch against an installed game assembly.tools/pack_godot_pck.pybuilds the localization PCK used by the mod package.
Install the .NET 9 SDK and Python 3, then point STS2_GAME_DIR at a Slay the Spire 2 installation:
$env:STS2_GAME_DIR = "C:\path\to\Slay the Spire 2"
.\build.ps1The installable folder is written to build\MysteriousMap. Copy that folder into the game's mods directory.
To build and deploy both to the game and a local ModUploader workspace:
.\deploy.ps1 -UploaderRoot "C:\path\to\ModUploader"Run the deterministic generator test with:
dotnet run --project .\tests\MysteriousMap.Tests\MysteriousMap.Tests.csproj -c ReleaseResolve and temporarily apply every Harmony patch against the installed DLL with:
dotnet run --project .\tests\MysteriousMap.CompatibilityTests\MysteriousMap.CompatibilityTests.csproj -c Release