Initial commit: Harry Potter Escape Adventure on bootle.dev.waiswuaschd.de
This commit is contained in:
Executable
+181
@@ -0,0 +1,181 @@
|
||||
// Snape's 7 Potions Riddle & Interactive Bottle Board
|
||||
(function() {
|
||||
let selectedBottle = null;
|
||||
const slots = document.querySelectorAll('.bottle-slot');
|
||||
const selectedInfo = document.getElementById('selectedBottleInfo');
|
||||
const btnDrinkAhead = document.getElementById('btnDrinkAhead');
|
||||
const btnDrinkBack = document.getElementById('btnDrinkBack');
|
||||
const modalBackdrop = document.getElementById('modalBackdrop');
|
||||
const modalTitle = document.getElementById('modalTitle');
|
||||
const modalText = document.getElementById('modalText');
|
||||
const modalBtn = document.getElementById('modalBtn');
|
||||
const modalIcon = document.getElementById('modalIcon');
|
||||
|
||||
// Bottle Descriptions based on Book Clues
|
||||
const bottleDescriptions = {
|
||||
1: "Eine dunkelbraune Phiole mittlerer Größe. Auf der linken Seite von Flasche 2.",
|
||||
2: "Eine schlanke, grüne Glasflasche. Schmeckt laut Hinweis 4 exakt wie Flasche 6!",
|
||||
3: "🔍 Die kleinste Flasche von allen (der 'Zwerg')! Sie enthält kaum mehr als einen einzigen Schluck.",
|
||||
4: "Ein eigenartiger, kantiger Glaskolben mit trüber, unruhiger Flüssigkeit.",
|
||||
5: "Eine bauchige Flasche aus Rauchglas. Steht direkt links von Flasche 6.",
|
||||
6: "Eine elegante Flasche, die Zwillingsschwester von Flasche 2, auch wenn sie äußerlich verschieden wirken.",
|
||||
7: "🏺 Die größte Flasche in der Reihe (der 'Riese')! Ein schwerer, bauchiger Dekanter."
|
||||
};
|
||||
|
||||
slots.forEach(slot => {
|
||||
slot.addEventListener('click', (e) => {
|
||||
if (e.target.tagName === 'SELECT') return; // Don't trigger on tag dropdown
|
||||
selectSlot(slot);
|
||||
});
|
||||
|
||||
// Drag & Drop / Reordering support
|
||||
slot.setAttribute('draggable', 'true');
|
||||
slot.addEventListener('dragstart', (e) => {
|
||||
e.dataTransfer.setData('text/plain', slot.dataset.index);
|
||||
if (window.soundFX) window.soundFX.playStoneSlide();
|
||||
});
|
||||
|
||||
slot.addEventListener('dragover', (e) => {
|
||||
e.preventDefault();
|
||||
slot.classList.add('drag-over');
|
||||
});
|
||||
|
||||
slot.addEventListener('dragleave', () => {
|
||||
slot.classList.remove('drag-over');
|
||||
});
|
||||
|
||||
slot.addEventListener('drop', (e) => {
|
||||
e.preventDefault();
|
||||
slot.classList.remove('drag-over');
|
||||
const sourceIndex = e.dataTransfer.getData('text/plain');
|
||||
const sourceSlot = document.querySelector(`.bottle-slot[data-index="${sourceIndex}"]`);
|
||||
if (sourceSlot && sourceSlot !== slot) {
|
||||
swapSlots(sourceSlot, slot);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function swapSlots(slotA, slotB) {
|
||||
if (window.soundFX) {
|
||||
window.soundFX.playStoneSlide();
|
||||
window.soundFX.playBottleClink();
|
||||
}
|
||||
// Swap inner contents except the pedestal number
|
||||
const tempHTML = slotA.innerHTML;
|
||||
slotA.innerHTML = slotB.innerHTML;
|
||||
slotB.innerHTML = tempHTML;
|
||||
|
||||
// Restore event listeners on newly swapped selects
|
||||
attachTagListeners();
|
||||
selectSlot(slotB);
|
||||
}
|
||||
|
||||
function selectSlot(slot) {
|
||||
slots.forEach(s => s.classList.remove('selected'));
|
||||
slot.classList.add('selected');
|
||||
selectedBottle = parseInt(slot.dataset.index, 10);
|
||||
|
||||
if (window.soundFX) window.soundFX.playBottleClink();
|
||||
|
||||
if (btnDrinkAhead) btnDrinkAhead.disabled = false;
|
||||
if (btnDrinkBack) btnDrinkBack.disabled = false;
|
||||
|
||||
if (selectedInfo) {
|
||||
const desc = bottleDescriptions[selectedBottle] || "Eine geheimnisvolle Flasche.";
|
||||
selectedInfo.innerHTML = `Gewählt: <strong>Flasche ${selectedBottle}</strong> — <em>${desc}</em>`;
|
||||
}
|
||||
}
|
||||
|
||||
function attachTagListeners() {
|
||||
document.querySelectorAll('.bottle-tag-select').forEach(sel => {
|
||||
sel.addEventListener('change', () => {
|
||||
if (window.soundFX) window.soundFX.playStoneSlide();
|
||||
});
|
||||
});
|
||||
}
|
||||
attachTagListeners();
|
||||
|
||||
// Drink to pass Ahead (Black Fire)
|
||||
if (btnDrinkAhead) {
|
||||
btnDrinkAhead.addEventListener('click', () => {
|
||||
if (!selectedBottle) return;
|
||||
drinkBottle(selectedBottle, 'ahead');
|
||||
});
|
||||
}
|
||||
|
||||
// Drink to pass Back (Purple Fire)
|
||||
if (btnDrinkBack) {
|
||||
btnDrinkBack.addEventListener('click', () => {
|
||||
if (!selectedBottle) return;
|
||||
drinkBottle(selectedBottle, 'back');
|
||||
});
|
||||
}
|
||||
|
||||
async function drinkBottle(bottleIdx, gate) {
|
||||
if (window.soundFX) window.soundFX.playBottleClink();
|
||||
|
||||
try {
|
||||
const res = await fetch('/api/bottles/drink', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ bottle: bottleIdx, gate: gate, lang: 'de' })
|
||||
});
|
||||
const data = await res.json();
|
||||
|
||||
if (data.result === 'success_ahead') {
|
||||
if (window.soundFX) window.soundFX.playMagicSuccess();
|
||||
modalIcon.innerText = "❄️⚡";
|
||||
modalTitle.innerText = "Hervorragend kombiniert!";
|
||||
modalTitle.style.color = "#ffd700";
|
||||
modalText.innerHTML = `Du hast die <strong>kleinste Flasche (Flasche 3, den 'Zwerg')</strong> getrunken!<br><br>
|
||||
${data.message}<br><br>
|
||||
Das schwarze Feuer teilt sich mit einem frostigen Zischen. Der Weg zum Stein der Weisen liegt frei vor dir!`;
|
||||
modalBtn.innerText = "Zum Finale & Escape-Triumph 🏆";
|
||||
modalBtn.onclick = () => { window.location.href = data.next_url; };
|
||||
modalBackdrop.classList.add('show');
|
||||
} else if (data.result === 'success_back') {
|
||||
if (window.soundFX) window.soundFX.playMagicSuccess();
|
||||
modalIcon.innerText = "🟣";
|
||||
modalTitle.innerText = "Rückzug gesichert!";
|
||||
modalText.innerHTML = `Du hast die <strong>größte Flasche (Flasche 7, den 'Riesen')</strong> getrunken.<br><br>
|
||||
${data.message}<br><br>
|
||||
Du kannst sicher durch die violetten Flammen zurückweichen, um deinen Gefährten zu helfen oder den Besenflug nochmals zu betreten.`;
|
||||
modalBtn.innerText = "Zurück zum Besenflug 🧹";
|
||||
modalBtn.onclick = () => { window.location.href = data.next_url; };
|
||||
modalBackdrop.classList.add('show');
|
||||
} else if (data.result === 'poison') {
|
||||
if (window.soundFX) window.soundFX.playPoisonSizzle();
|
||||
modalIcon.innerText = "💀";
|
||||
modalTitle.innerText = "Tödliches Gift!";
|
||||
modalTitle.style.color = "#e74c3c";
|
||||
modalText.innerHTML = `${data.message}<br><br>
|
||||
<strong>Snapes Rätsel-Hinweis:</strong><br>
|
||||
<em>"So schlau sich das Gift auch zu tarnen mag,<br>
|
||||
stets steht es zur Linken vom Wein im Gelag."</em>`;
|
||||
modalBtn.innerText = "Erneut analysieren 📜";
|
||||
modalBtn.onclick = () => { modalBackdrop.classList.remove('show'); };
|
||||
modalBackdrop.classList.add('show');
|
||||
} else if (data.result === 'wine') {
|
||||
if (window.soundFX) window.soundFX.playPoisonSizzle();
|
||||
modalIcon.innerText = "🍷";
|
||||
modalTitle.innerText = "Harmloser Brennnesselwein";
|
||||
modalTitle.style.color = "#e67e22";
|
||||
modalText.innerHTML = `${data.message}<br><br>
|
||||
Du spürst keinerlei Schutz vor der Hitze der Flammen. Wenn du jetzt hineintrittst, verbrennst du! Lies die Verse auf dem Pergament noch einmal gründlich.`;
|
||||
modalBtn.innerText = "Verstanden 📜";
|
||||
modalBtn.onclick = () => { modalBackdrop.classList.remove('show'); };
|
||||
modalBackdrop.classList.add('show');
|
||||
} else {
|
||||
if (window.soundFX) window.soundFX.playPoisonSizzle();
|
||||
modalIcon.innerText = "⚠️";
|
||||
modalTitle.innerText = "Falsche Flamme!";
|
||||
modalText.innerText = data.message;
|
||||
modalBtn.innerText = "Zurück";
|
||||
modalBtn.onclick = () => { modalBackdrop.classList.remove('show'); };
|
||||
modalBackdrop.classList.add('show');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user