feat(sasch40): improve Act III, add state persistence and fix portraits
- Fix character portrait crops and version assets to portrait_v2, ensuring correct identities (resolving Nat/Verena mismatch) - Update Schankraum scene image and configure Nginx cache-control to prevent stale asset caching - Make secret beer tap completely invisible in tavern until clicked - Reposition room hotspots in Act III to eliminate overlapping click targets - Add exit button [✕] to Bavarian Gstanzl duel minigame - Implement localStorage persistence in gameStore to maintain progress across page reloads - Enable clean game state and storage reset when clicking "Nochmal spielen" - Expand automated playtest script to cover Nat dialogue, duel exit, reload persistence, and game restart
This commit is contained in:
@@ -26,11 +26,20 @@ const duelStep = ref(0)
|
||||
const duelWon = ref(false)
|
||||
const zulumanMirrorActive = ref(false)
|
||||
|
||||
const secretTapDiscovered = ref(store.unlockedEasterEggs.includes('hinterzimmer'))
|
||||
|
||||
function switchRoom(room: TavernRoom) {
|
||||
sound.playDialogueBlip()
|
||||
currentRoom.value = room
|
||||
}
|
||||
|
||||
function triggerSecretTap() {
|
||||
sound.playFanfare()
|
||||
secretTapDiscovered.value = true
|
||||
store.unlockEasterEgg('hinterzimmer')
|
||||
currentRoom.value = 'hinterzimmer'
|
||||
}
|
||||
|
||||
function enterSecretHinterzimmer() {
|
||||
sound.playFanfare()
|
||||
store.unlockEasterEgg('hinterzimmer')
|
||||
@@ -229,7 +238,7 @@ function proceedToExpress() {
|
||||
|
||||
<!-- ================= 1. GASTSTUBE (SCHANKRAUM) ================= -->
|
||||
<template v-if="currentRoom === 'schankraum'">
|
||||
<img src="/assets/scenes/tavern.jpg" alt="Gaststube Zum wummernden Ritter" class="tavern-bg" />
|
||||
<img src="/assets/scenes/schankraum_v2.jpg?v=2" alt="Gaststube Zum wummernden Ritter" class="tavern-bg" />
|
||||
|
||||
<!-- Verena on the wooden gallery -->
|
||||
<button class="hotspot hotspot-verena" @click="openCharacterDialog('verena')">
|
||||
@@ -267,10 +276,17 @@ function proceedToExpress() {
|
||||
<span class="hotspot-badge glow-door">Zum Marktplatz ▶</span>
|
||||
</button>
|
||||
|
||||
<!-- SECRET EASTER EGG TRIGGER: Hidden Beer Tap to Hinterzimmer -->
|
||||
<button class="hotspot secret-tap-hotspot" @click="enterSecretHinterzimmer" title="Ein sonderbarer goldener Zapfhahn...">
|
||||
<span class="secret-tap-icon pulse">🗝️</span>
|
||||
<span class="secret-badge">Geheimer Zapfhahn</span>
|
||||
<!-- SECRET EASTER EGG TRIGGER: Hidden Beer Tap to Hinterzimmer (Completely invisible until clicked) -->
|
||||
<button
|
||||
class="hotspot secret-tap-hotspot"
|
||||
:class="{ 'tap-invisible': !secretTapDiscovered && !store.unlockedEasterEggs.includes('hinterzimmer') }"
|
||||
@click="triggerSecretTap"
|
||||
:title="secretTapDiscovered || store.unlockedEasterEggs.includes('hinterzimmer') ? 'Ein sonderbarer Zapfhahn...' : undefined"
|
||||
>
|
||||
<template v-if="secretTapDiscovered || store.unlockedEasterEggs.includes('hinterzimmer')">
|
||||
<span class="secret-tap-icon pulse">🗝️</span>
|
||||
<span class="secret-badge">Geheimer Zapfhahn</span>
|
||||
</template>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
@@ -465,8 +481,11 @@ function proceedToExpress() {
|
||||
<div v-if="duelActive" class="dialog-overlay">
|
||||
<div class="dialog-box duel-box">
|
||||
<div class="duel-header">
|
||||
<h3>⚔️ BAYERISCHES BELEIDIGUNGS-GSTANZL</h3>
|
||||
<span class="duel-score">Runde {{ duelStep + 1 }} von 3</span>
|
||||
<div class="duel-title-group">
|
||||
<h3>⚔️ BAYERISCHES BELEIDIGUNGS-GSTANZL</h3>
|
||||
<span class="duel-score">Runde {{ duelStep + 1 }} von 3</span>
|
||||
</div>
|
||||
<button class="duel-close-btn" @click="duelActive = false" aria-label="Minispiel verlassen">✕</button>
|
||||
</div>
|
||||
|
||||
<div v-if="!duelWon">
|
||||
@@ -578,14 +597,30 @@ function proceedToExpress() {
|
||||
/* Secret Tap Easter Egg */
|
||||
.secret-tap-hotspot {
|
||||
position: absolute;
|
||||
top: 73%;
|
||||
left: 88%;
|
||||
top: 72%;
|
||||
left: 82%;
|
||||
background: rgba(234, 179, 8, 0.2);
|
||||
border: 1.5px dashed #ffd700;
|
||||
border-radius: 12px;
|
||||
padding: 3px 6px;
|
||||
cursor: pointer;
|
||||
z-index: 12;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.secret-tap-hotspot.tap-invisible,
|
||||
.secret-tap-hotspot.tap-invisible:hover,
|
||||
.secret-tap-hotspot.tap-invisible:active,
|
||||
.secret-tap-hotspot.tap-invisible:focus {
|
||||
background: transparent !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
outline: none !important;
|
||||
transform: translate(-50%, -50%) !important;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
padding: 0 !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.secret-tap-icon {
|
||||
@@ -599,18 +634,18 @@ function proceedToExpress() {
|
||||
}
|
||||
|
||||
/* 1. Schankraum Hotspots */
|
||||
.hotspot-verena { top: 16%; left: 78%; }
|
||||
.hotspot-armend { top: 62%; left: 24%; }
|
||||
.hotspot-lutz { top: 38%; left: 20%; }
|
||||
.hotspot-amy { top: 52%; left: 80%; }
|
||||
.hotspot-mirror { top: 32%; left: 63%; }
|
||||
.hotspot-door-marktplatz { top: 56%; left: 90%; }
|
||||
.hotspot-verena { top: 17%; left: 28%; }
|
||||
.hotspot-mirror { top: 30%; left: 68%; }
|
||||
.hotspot-amy { top: 45%; left: 32%; }
|
||||
.hotspot-lutz { top: 54%; left: 56%; }
|
||||
.hotspot-armend { top: 62%; left: 18%; }
|
||||
.hotspot-door-marktplatz { top: 50%; left: 84%; }
|
||||
|
||||
/* 2. Marktplatz Hotspots */
|
||||
.mario-container {
|
||||
position: absolute;
|
||||
top: 52%;
|
||||
left: 34%;
|
||||
top: 44%;
|
||||
left: 30%;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
@@ -664,12 +699,12 @@ function proceedToExpress() {
|
||||
100% { opacity: 1; transform: scale(1.3); }
|
||||
}
|
||||
|
||||
.hotspot-nat { top: 62%; left: 74%; }
|
||||
.hotspot-door-back-gaststube { top: 72%; left: 16%; }
|
||||
.hotspot-door-hinterland { top: 36%; left: 84%; }
|
||||
.hotspot-nat { top: 62%; left: 70%; }
|
||||
.hotspot-door-back-gaststube { top: 72%; left: 20%; }
|
||||
.hotspot-door-hinterland { top: 32%; left: 76%; }
|
||||
|
||||
/* 3. Hinterland Hotspots */
|
||||
.hotspot-mane { top: 50%; left: 42%; }
|
||||
.hotspot-mane { top: 44%; left: 36%; }
|
||||
.hiking-anim {
|
||||
animation: hikeBob 1.2s infinite ease-in-out;
|
||||
}
|
||||
@@ -684,8 +719,8 @@ function proceedToExpress() {
|
||||
transform: rotate(20deg);
|
||||
}
|
||||
|
||||
.hotspot-hansi { top: 66%; left: 78%; }
|
||||
.hotspot-door-back-marktplatz { top: 74%; left: 20%; }
|
||||
.hotspot-hansi { top: 60%; left: 74%; }
|
||||
.hotspot-door-back-marktplatz { top: 72%; left: 22%; }
|
||||
|
||||
/* 4. Hinterzimmer Hotspots & Strobe */
|
||||
.strobe-overlay {
|
||||
@@ -704,24 +739,10 @@ function proceedToExpress() {
|
||||
100% { background: rgba(168, 85, 247, 0.25); }
|
||||
}
|
||||
|
||||
.hotspot-pue { top: 46%; left: 48%; }
|
||||
.rave-pulse {
|
||||
animation: raveGlow 1s infinite alternate;
|
||||
}
|
||||
|
||||
@keyframes raveGlow {
|
||||
0% { box-shadow: 0 0 4px #eab308; }
|
||||
100% { box-shadow: 0 0 16px #ec4899; }
|
||||
}
|
||||
|
||||
.crystal-laser {
|
||||
font-size: 13px;
|
||||
animation: pulseAnim 0.8s infinite;
|
||||
}
|
||||
|
||||
.hotspot-flo { top: 40%; left: 22%; }
|
||||
.hotspot-viktor { top: 62%; left: 78%; }
|
||||
.hotspot-door-back-vip { top: 78%; left: 50%; }
|
||||
.hotspot-flo { top: 38%; left: 24%; }
|
||||
.hotspot-viktor { top: 52%; left: 62%; }
|
||||
.hotspot-pue { top: 64%; left: 82%; }
|
||||
.hotspot-door-back-vip { top: 74%; left: 45%; }
|
||||
|
||||
.pulse {
|
||||
animation: pulseAnim 1.5s infinite;
|
||||
@@ -958,11 +979,18 @@ function proceedToExpress() {
|
||||
|
||||
/* Gstanzl */
|
||||
.duel-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
border-bottom: 1px solid #78350f;
|
||||
margin-bottom: 10px;
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
|
||||
.duel-title-group {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.duel-header h3 {
|
||||
font-family: 'Press Start 2P', monospace;
|
||||
font-size: 8px;
|
||||
@@ -975,6 +1003,31 @@ function proceedToExpress() {
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
.duel-close-btn {
|
||||
background: #7f1d1d;
|
||||
color: #fef08a;
|
||||
border: 1px solid #ef4444;
|
||||
border-radius: 50%;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
margin-left: 8px;
|
||||
flex-shrink: 0;
|
||||
transition: all 0.2s ease;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.duel-close-btn:hover {
|
||||
background: #dc2626;
|
||||
transform: scale(1.1);
|
||||
box-shadow: 0 0 8px rgba(239, 68, 68, 0.6);
|
||||
}
|
||||
|
||||
.insult-bubble {
|
||||
background: #451a03;
|
||||
border-left: 3px solid #ef4444;
|
||||
|
||||
Reference in New Issue
Block a user