Add Player Menu with Inventory drawer, house selection, and mobile-first header
This commit is contained in:
@@ -124,6 +124,9 @@
|
||||
|
||||
if (data.result === 'success_ahead') {
|
||||
if (window.soundFX) window.soundFX.playMagicSuccess();
|
||||
if (window.notifyNewItem && data.new_item) {
|
||||
window.notifyNewItem(data.new_item);
|
||||
}
|
||||
modalIcon.innerText = "❄️⚡";
|
||||
modalTitle.innerText = "Hervorragend kombiniert!";
|
||||
modalTitle.style.color = "#ffd700";
|
||||
@@ -133,6 +136,7 @@
|
||||
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 = "🟣";
|
||||
|
||||
@@ -207,11 +207,15 @@
|
||||
score += 500;
|
||||
if (scoreVal) scoreVal.innerText = score;
|
||||
if (window.soundFX) window.soundFX.playKeyChime();
|
||||
if (window.notifyNewItem) {
|
||||
window.notifyNewItem({ icon: "🗝️", name: "Geknickter Silberschlüssel" });
|
||||
}
|
||||
if (statusMsg) {
|
||||
statusMsg.innerHTML = "✨ <strong>Schlüssel gefangen!</strong> Fliege jetzt zur schweren Holztür rechts und öffne das Schloss!";
|
||||
statusMsg.innerHTML = "✨ <strong>Schlüssel gefangen & im Beutel!</strong> Fliege zur Holztür rechts und öffne das Schloss!";
|
||||
statusMsg.style.color = "#2ecc71";
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// Master key follows player
|
||||
masterKey.x = player.x + 10;
|
||||
|
||||
Executable
+225
@@ -0,0 +1,225 @@
|
||||
// Player Menu & Inventory (Zauberer-Beutel & Profil)
|
||||
(function() {
|
||||
const drawer = document.getElementById('playerDrawer');
|
||||
const drawerBackdrop = document.getElementById('drawerBackdrop');
|
||||
const bagBtn = document.getElementById('openBagBtn');
|
||||
const closeBtn = document.getElementById('closeDrawerBtn');
|
||||
const bagBadge = document.getElementById('bagBadge');
|
||||
const bagHouseIcon = document.getElementById('bagHouseIcon');
|
||||
|
||||
// Tabs
|
||||
const tabBtns = document.querySelectorAll('.drawer-tab-btn');
|
||||
const tabPanes = document.querySelectorAll('.drawer-tab-pane');
|
||||
|
||||
// Item Detail Card
|
||||
const itemDetailBox = document.getElementById('itemDetailBox');
|
||||
const itemDetailIcon = document.getElementById('itemDetailIcon');
|
||||
const itemDetailName = document.getElementById('itemDetailName');
|
||||
const itemDetailDesc = document.getElementById('itemDetailDesc');
|
||||
const itemDetailActionBtn = document.getElementById('itemDetailActionBtn');
|
||||
|
||||
// House selection buttons
|
||||
const houseBtns = document.querySelectorAll('.house-select-btn');
|
||||
|
||||
let currentItem = null;
|
||||
let lumosActive = false;
|
||||
|
||||
window.togglePlayerDrawer = function() {
|
||||
if (!drawer) return;
|
||||
const isOpen = drawer.classList.contains('open');
|
||||
if (isOpen) {
|
||||
closePlayerDrawer();
|
||||
} else {
|
||||
openPlayerDrawer();
|
||||
}
|
||||
};
|
||||
|
||||
window.openPlayerDrawer = function(tabName) {
|
||||
if (!drawer) return;
|
||||
drawer.classList.add('open');
|
||||
if (drawerBackdrop) drawerBackdrop.classList.add('open');
|
||||
document.body.style.overflow = 'hidden';
|
||||
if (window.soundFX) window.soundFX.playStoneSlide();
|
||||
if (tabName) switchTab(tabName);
|
||||
};
|
||||
|
||||
window.closePlayerDrawer = function() {
|
||||
if (!drawer) return;
|
||||
drawer.classList.remove('open');
|
||||
if (drawerBackdrop) drawerBackdrop.classList.remove('open');
|
||||
document.body.style.overflow = '';
|
||||
if (window.soundFX) window.soundFX.playStoneSlide();
|
||||
};
|
||||
|
||||
if (bagBtn) bagBtn.addEventListener('click', window.togglePlayerDrawer);
|
||||
if (closeBtn) closeBtn.addEventListener('click', window.closePlayerDrawer);
|
||||
if (drawerBackdrop) drawerBackdrop.addEventListener('click', window.closePlayerDrawer);
|
||||
|
||||
window.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape' && drawer && drawer.classList.contains('open')) {
|
||||
window.closePlayerDrawer();
|
||||
}
|
||||
});
|
||||
|
||||
// Tab Switching
|
||||
tabBtns.forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
const target = btn.dataset.tab;
|
||||
switchTab(target);
|
||||
});
|
||||
});
|
||||
|
||||
function switchTab(tabId) {
|
||||
tabBtns.forEach(b => b.classList.toggle('active', b.dataset.tab === tabId));
|
||||
tabPanes.forEach(p => p.classList.toggle('active', p.id === tabId));
|
||||
if (window.soundFX) window.soundFX.playBottleClink();
|
||||
}
|
||||
|
||||
// Item Selection in Bag
|
||||
const itemSlots = document.querySelectorAll('.inv-item-slot');
|
||||
itemSlots.forEach(slot => {
|
||||
slot.addEventListener('click', () => {
|
||||
selectItem(slot);
|
||||
});
|
||||
});
|
||||
|
||||
function selectItem(slot) {
|
||||
itemSlots.forEach(s => s.classList.remove('selected'));
|
||||
slot.classList.add('selected');
|
||||
|
||||
const itemId = slot.dataset.itemId;
|
||||
const itemName = slot.dataset.itemName;
|
||||
const itemIcon = slot.dataset.itemIcon;
|
||||
const itemDesc = slot.dataset.itemDesc;
|
||||
const actionLabel = slot.dataset.actionLabel;
|
||||
const action = slot.dataset.action;
|
||||
|
||||
currentItem = { id: itemId, name: itemName, icon: itemIcon, action: action };
|
||||
|
||||
if (itemDetailBox) {
|
||||
itemDetailBox.style.display = 'block';
|
||||
itemDetailIcon.innerText = itemIcon;
|
||||
itemDetailName.innerText = itemName;
|
||||
itemDetailDesc.innerText = itemDesc;
|
||||
itemDetailActionBtn.innerText = actionLabel || "Benutzen ✨";
|
||||
itemDetailActionBtn.onclick = () => performItemAction(action);
|
||||
}
|
||||
|
||||
if (window.soundFX) window.soundFX.playBottleClink();
|
||||
}
|
||||
|
||||
function performItemAction(action) {
|
||||
if (action === 'lumos') {
|
||||
lumosActive = !lumosActive;
|
||||
let glow = document.getElementById('lumosLightOverlay');
|
||||
if (!glow) {
|
||||
glow = document.createElement('div');
|
||||
glow.id = 'lumosLightOverlay';
|
||||
glow.className = 'lumos-light';
|
||||
document.body.appendChild(glow);
|
||||
}
|
||||
glow.classList.toggle('active', lumosActive);
|
||||
itemDetailActionBtn.innerText = lumosActive ? "Nox / Erlöschen 🌑" : "Lumos wirken 💡";
|
||||
if (window.soundFX) window.soundFX.playKeyChime();
|
||||
showFloatingToast(lumosActive ? "💡 Lumos! Dein Zauberstab erleuchtet die Kammer." : "🌑 Nox! Das Zauberlicht erlischt.");
|
||||
} else if (action === 'read_scroll') {
|
||||
// Open scroll modal
|
||||
window.closePlayerDrawer();
|
||||
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');
|
||||
if (modalBackdrop) {
|
||||
modalIcon.innerText = "📜";
|
||||
modalTitle.innerText = "Snapes Logik-Rätsel";
|
||||
modalText.innerHTML = `
|
||||
<div style="font-family: 'Caveat', cursive; font-size: 1.35rem; line-height: 1.7; text-align: left; max-height: 50vh; overflow-y: auto; padding: 0.5rem 1rem;">
|
||||
<em>"Gefahr liegt vor euch, die Rettung zurück,<br>
|
||||
Zwei von uns helfen euch, habt ihr das Glück,<br>
|
||||
Eine von sieben führt euch hindurch,<br>
|
||||
Eine bringt den, der sie trinkt, sicher zurück,<br>
|
||||
Zwei von ihnen enthalten nur Brennnesselwein,<br>
|
||||
Drei sind tödlich, schenkt ihr sie ein.<br>
|
||||
Wählt oder bleibt auf ewig hier stehen,<br>
|
||||
Vier Hinweise helfen euch, alles zu sehen..."</em><br><br>
|
||||
<strong>1.</strong> Links neben jedem Wein steht immer Gift.<br>
|
||||
<strong>2.</strong> Die Enden sind verschieden, keines führt nach vorn.<br>
|
||||
<strong>3.</strong> Weder Zwerg noch Riese birgt Gift.<br>
|
||||
<strong>4.</strong> Zweite von links & zweite von rechts schmecken gleich!
|
||||
</div>
|
||||
`;
|
||||
modalBtn.innerText = "Verstanden ➔";
|
||||
modalBtn.onclick = () => modalBackdrop.classList.remove('show');
|
||||
modalBackdrop.classList.add('show');
|
||||
}
|
||||
} else if (action === 'broom_polish') {
|
||||
if (window.soundFX) window.soundFX.playWhoosh();
|
||||
showFloatingToast("🧹 Der Nimbus 2000 glänzt wie neu. Die Zweige sind perfekt gestutzt!");
|
||||
} else if (action === 'examine_key') {
|
||||
if (window.soundFX) window.soundFX.playKeyChime();
|
||||
showFloatingToast("🗝️ Der alte Silberschlüssel ist schwer und trägt Spuren vergangener Kämpfe.");
|
||||
} else if (action === 'feel_power') {
|
||||
if (window.soundFX) window.soundFX.playMagicSuccess();
|
||||
showFloatingToast("💎 Eine unendliche Wärme durchströmt deine Finger. Der Stein schützt die Welt!");
|
||||
}
|
||||
}
|
||||
|
||||
// House selection
|
||||
houseBtns.forEach(btn => {
|
||||
btn.addEventListener('click', async () => {
|
||||
const house = btn.dataset.house;
|
||||
try {
|
||||
const res = await fetch('/api/player/house', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ house: house })
|
||||
});
|
||||
const data = await res.json();
|
||||
if (data.success) {
|
||||
houseBtns.forEach(b => b.classList.toggle('active', b.dataset.house === house));
|
||||
if (bagHouseIcon) bagHouseIcon.innerText = data.house.icon;
|
||||
document.documentElement.style.setProperty('--house-accent', data.house.accent);
|
||||
if (window.soundFX) window.soundFX.playMagicSuccess();
|
||||
showFloatingToast(`Du gehörst nun stolz zum Haus ${data.house.name} ${data.house.icon}!`);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Toast Notification
|
||||
window.showFloatingToast = function(msg) {
|
||||
let toast = document.getElementById('floatingEscapeToast');
|
||||
if (!toast) {
|
||||
toast = document.createElement('div');
|
||||
toast.id = 'floatingEscapeToast';
|
||||
toast.className = 'escape-toast';
|
||||
document.body.appendChild(toast);
|
||||
}
|
||||
toast.innerHTML = msg;
|
||||
toast.classList.add('show');
|
||||
clearTimeout(toast._timeout);
|
||||
toast._timeout = setTimeout(() => {
|
||||
toast.classList.remove('show');
|
||||
}, 3500);
|
||||
};
|
||||
|
||||
window.notifyNewItem = function(item) {
|
||||
if (!item) return;
|
||||
if (bagBadge) {
|
||||
let count = parseInt(bagBadge.innerText, 10) || 0;
|
||||
bagBadge.innerText = count + 1;
|
||||
bagBadge.classList.add('pulse');
|
||||
setTimeout(() => bagBadge.classList.remove('pulse'), 2000);
|
||||
}
|
||||
if (window.soundFX) window.soundFX.playMagicSuccess();
|
||||
window.showFloatingToast(`🎒 <strong>Neuer Gegenstand im Beutel:</strong> ${item.icon} ${item.name}!`);
|
||||
};
|
||||
|
||||
// Auto-select first item if available
|
||||
if (itemSlots.length > 0) {
|
||||
selectItem(itemSlots[0]);
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user