Extradimensional Haunted Mansion Helper
by MegaScience
HTML
<div class="map-grid">
<div class="panel bottom middle">
<h3>General</h3>
<label><input id="general1" type="checkbox" /> <span class="unsafe">Field of View grows (Leave ASAP)</span></label>
<label><input id="general2" type="checkbox" /> <span class="unsafe">Field of View shrinks (Leave ASAP)</span></label>
<label><input id="general3" type="checkbox" /> <span title="Ignore message and keep trying to exit left.">Floor entirely lit; Keep trying to exit left</span></label>
<label><input id="general4" type="checkbox" /> <span class="safe" title="You can jump on the wall trim where the note desk used to be to get to the left exit.">Light goes out briefly and sinkhole appears</span></label>
<label><input id="general5" type="checkbox" /> <span>Floor numbers on upper level incorrect</span></label>
<label><input id="general6" type="checkbox" /> <span title="Item is named Fearful Masquerade Mask.">Sad mask on face</span></label>
<label><input id="general7" type="checkbox" /> <span title="Item is named Scary Masquerade Mask">Angry mask on face</span></label>
</div>
<div class="panel bottom left">
<h3>Bottom-Left</h3>
<label><input id="bottomleft1" type="checkbox" /> <span class="task" title="Click notes and exit left">Notes don't have Lightbulb Notifier</span></label>
<label><input id="bottomleft2" type="checkbox" /> <span>No Toy Soldier right of ladder</span></label>
<label><input id="bottomleft3" type="checkbox" /> <span class="safe task" title="Only anomaly where you don't leave via left portal.">Sophilia guides to a portal. Use it to exit</span></label>
</div>
<div class="panel top left">
<h3>Top-Left</h3>
<label><input id="topleft1" type="checkbox" /> <span>Extra picture frames around window</span></label>
<label><input id="topleft2" type="checkbox" /> <span>Upside-down statues on ceiling</span></label>
...
CSS
@counter-style anomalyType {
system: fixed;
symbols: "\200B" "🛡️" "⚠️" "📝";
}
:root {
--primary-text-color: rgb(187, 187, 187);
--label-border-width: 2px;
--label-negative-border-width: calc(-1 * var(--label-border-width));
--prefix-unset: 1;
--prefix-safe: 2;
--prefix-unsafe: 3;
--prefix-task: 4;
}
html, body {
margin: 0;
padding: 0;
}
body {
display: flex;
flex-direction: column;
background-color: black;
color: var(--primary-text-color);
font-family: Arial, Helvetica, sans-serif;
counter-reset: anomaliesFound;
}
.map-grid {
--gap: 3px;
--columns: 3;
--rows: 2;
display: grid;
grid-template-columns: repeat(var(--columns), 1fr);
grid-template-rows: repeat(var(--rows), 1fr);
width: 100vw;
max-width: 100%;
aspect-ratio: var(--columns) / var(--rows);
margin: var(--gap);
gap: var(--gap);
.top { grid-row: 1; }
.bottom { grid-row: 2; }
.left { grid-column: 1; }
.middle { grid-column: 2; }
.right { grid-column: 3; }
}
h3 {
margin: 0;
text-decoration: underline white;
}
.panel {
background-color: rgb(63, 63, 63);
border: 2px ridge black;
border-radius: 15px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 2px;
}
label {
display: flex;
align-items: flex-start;
width: 100%;
counter-reset: isSafe var(--prefix-unset) isTask var(--prefix-unset);
input[type="checkbox"] {
flex-shrink: 0;
}
input:checked + span {
color: rgb(0, 180, 0);
text-decoration: line-through black 2px;
-webkit-text-stroke: black 2px;
paint-order: stroke fill;
counter-increment: anomaliesFound;
}
span {
flex: 1;
&.unsafe { counter-set: isSafe var(--prefix-unsafe); }
...
JavaScript
class checkboxControllerClass {
static storageName = 'maplestory2025EHM'
static checkboxes = document.querySelectorAll('label input[id][type="checkbox"]')
static checkboxStorage = {}
static loadCheckboxes() {
const data = window.localStorage.getItem(this.storageName)
if (data !== null) {
this.checkboxStorage = JSON.parse(data)
for (const checkbox of this.checkboxes) checkbox.checked = this.checkboxStorage[checkbox.id]
}
}
static saveCheckboxes() {
for (const checkbox of this.checkboxes) this.checkboxStorage[checkbox.id] = checkbox.checked
window.localStorage.setItem(this.storageName, JSON.stringify(this.checkboxStorage))
}
static init() {
this.loadCheckboxes()
for (const checkbox of this.checkboxes) checkbox.addEventListener('input', () => this.saveCheckboxes())
}
}
checkboxControllerClass.init()