Feature: Integrate all four Hogwarts mini-games (Duel, Potion Brewing, Cryptex Lock, Cornish Pixies)

This commit is contained in:
Maxi
2026-09-22 19:43:12 +02:00
parent 0e20549a44
commit 2ce944d1cd
13 changed files with 1662 additions and 13 deletions
+137
View File
@@ -0,0 +1,137 @@
// Magisches Runen-Drehschloss (Cryptex Engine)
(function() {
const DIALS = [
// Dial 0: Houses
[
{ icon: '🦁', name: 'Löwe' },
{ icon: '🐍', name: 'Schlange' },
{ icon: '🦅', name: 'Rabe' },
{ icon: '🦡', name: 'Dachs' }
],
// Dial 1: Astral
[
{ icon: '☀️', name: 'Sonne' },
{ icon: '🌙', name: 'Mond' },
{ icon: '⭐', name: 'Stern' },
{ icon: '⚡', name: 'Blitz' }
],
// Dial 2: Elements
[
{ icon: '🔥', name: 'Feuer' },
{ icon: '💧', name: 'Wasser' },
{ icon: '🌿', name: 'Kräuter' },
{ icon: '💨', name: 'Wind' }
],
// Dial 3: Artifacts
[
{ icon: '🗝️', name: 'Schlüssel' },
{ icon: '🪄', name: 'Zauberstab' },
{ icon: '📜', name: 'Rolle' },
{ icon: '⚗️', name: 'Phiole' }
]
];
// Initial indices (unsolved)
const state = [0, 0, 1, 0];
let isUnlocked = false;
// Elements
const feedbackBox = document.getElementById('cryptexFeedback');
const successPanel = document.getElementById('cryptexSuccess');
const unlockBtn = document.getElementById('unlockCryptexBtn');
window.stepDial = function(dialIdx, dir) {
if (isUnlocked) return;
const dial = DIALS[dialIdx];
state[dialIdx] = (state[dialIdx] + dir + dial.length) % dial.length;
const symEl = document.getElementById(`sym${dialIdx}`);
const lblEl = document.getElementById(`lbl${dialIdx}`);
// Quick flip animation
symEl.style.transform = dir > 0 ? 'translateY(15px) scale(0.8)' : 'translateY(-15px) scale(0.8)';
symEl.style.opacity = '0.3';
setTimeout(() => {
const currentItem = dial[state[dialIdx]];
symEl.innerText = currentItem.icon;
lblEl.innerText = currentItem.name;
symEl.style.transform = 'translateY(0) scale(1)';
symEl.style.opacity = '1';
}, 100);
if (window.soundFX) window.soundFX.playStoneSlide();
};
window.checkCryptex = async function() {
if (isUnlocked) return;
const currentCombination = [
DIALS[0][state[0]].icon,
DIALS[1][state[1]].icon,
DIALS[2][state[2]].icon,
DIALS[3][state[3]].icon
];
try {
const res = await fetch('/api/cryptex/unlock', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ combination: currentCombination })
});
const data = await res.json();
if (data.success) {
isUnlocked = true;
unlockBtn.style.display = 'none';
if (window.soundFX) {
window.soundFX.playKeyChime();
window.soundFX.playMagicSuccess();
}
// Show golden shine on cylinders
document.querySelectorAll('.dial-cylinder').forEach(c => {
c.style.borderColor = 'var(--gold)';
c.style.boxShadow = '0 0 20px var(--gold)';
});
if (feedbackBox) {
feedbackBox.style.display = 'block';
feedbackBox.style.background = 'rgba(46, 204, 113, 0.25)';
feedbackBox.style.border = '1px solid #2ecc71';
feedbackBox.style.color = '#2ecc71';
feedbackBox.innerText = data.message;
}
if (data.new_item && window.notifyNewItem) {
window.notifyNewItem(data.new_item);
}
setTimeout(() => {
if (successPanel) successPanel.style.display = 'block';
}, 800);
} else {
if (window.soundFX) window.soundFX.playWhoosh();
const box = document.querySelector('.cryptex-box');
box.style.transform = 'translateX(-8px)';
setTimeout(() => box.style.transform = 'translateX(8px)', 80);
setTimeout(() => box.style.transform = 'translateX(-4px)', 160);
setTimeout(() => box.style.transform = 'translateX(0)', 240);
if (feedbackBox) {
feedbackBox.style.display = 'block';
feedbackBox.style.background = 'rgba(231, 76, 60, 0.25)';
feedbackBox.style.border = '1px solid #e74c3c';
feedbackBox.style.color = '#e74c3c';
feedbackBox.innerText = data.message;
}
}
} catch (e) {
console.error("Cryptex check error:", e);
}
};
})();