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:
@@ -171,6 +171,18 @@ async function runPlaytest() {
|
||||
if (actionBtn) await actionBtn.click();
|
||||
await new Promise(r => setTimeout(r, 400));
|
||||
}
|
||||
|
||||
// Click NAT (Josef)
|
||||
const natBtn = await page.$('.hotspot-nat');
|
||||
if (natBtn) {
|
||||
await natBtn.click();
|
||||
await new Promise(r => setTimeout(r, 700));
|
||||
console.log('📸 09b: Capturing NAT (Josef) Dialog...');
|
||||
await page.screenshot({ path: path.join(SCREENSHOTS_DIR, '09b_tavern_nat_dialog.png') });
|
||||
const actionBtn = await page.$('.dialog-actions .action-btn');
|
||||
if (actionBtn) await actionBtn.click();
|
||||
await new Promise(r => setTimeout(r, 400));
|
||||
}
|
||||
}
|
||||
|
||||
// 7. TAVERN: HINTERLAND (Mane hiking)
|
||||
@@ -196,7 +208,7 @@ async function runPlaytest() {
|
||||
}
|
||||
|
||||
// 8. TAVERN: SECRET HINTERZIMMER (VIP Rave via Secret Tap)
|
||||
console.log('🗝️ Returning to Schankraum to trigger Secret Tap...');
|
||||
console.log('🗝️ Returning to Schankraum to check Secret Tap (initially invisible)...');
|
||||
const schankraumTab = await page.$('.room-tab:nth-child(1)');
|
||||
if (schankraumTab) {
|
||||
await schankraumTab.click();
|
||||
@@ -242,23 +254,46 @@ async function runPlaytest() {
|
||||
await new Promise(r => setTimeout(r, 400));
|
||||
}
|
||||
|
||||
console.log('⚔️ Testing Gstanzl-Duel...');
|
||||
console.log('⚔️ Testing Gstanzl-Duel and [✕] Exit Button...');
|
||||
const duelBtn = await page.$('.duel-trigger');
|
||||
if (duelBtn) {
|
||||
await duelBtn.click();
|
||||
await new Promise(r => setTimeout(r, 700));
|
||||
console.log('📸 15: Capturing Gstanzl Duel...');
|
||||
console.log('📸 15: Capturing Gstanzl Duel with [✕] button...');
|
||||
await page.screenshot({ path: path.join(SCREENSHOTS_DIR, '15_tavern_gstanzl_duel.png') });
|
||||
const firstAnswer = await page.$('.choice-btn');
|
||||
if (firstAnswer) {
|
||||
await firstAnswer.click();
|
||||
await new Promise(r => setTimeout(r, 500));
|
||||
|
||||
// Test the [✕] close button
|
||||
const closeDuelBtn = await page.$('.duel-close-btn');
|
||||
if (closeDuelBtn) {
|
||||
console.log('Testing duel exit via [✕] button...');
|
||||
await closeDuelBtn.click();
|
||||
await new Promise(r => setTimeout(r, 600));
|
||||
const duelClosed = await page.$('.duel-box') === null;
|
||||
console.log('Duel modal closed successfully by [✕]:', duelClosed);
|
||||
}
|
||||
// Close duel if won or modal
|
||||
const actionBtn = await page.$('.duel-box .action-btn');
|
||||
if (actionBtn) await actionBtn.click();
|
||||
}
|
||||
|
||||
// Test reload persistence in Tavern Act
|
||||
console.log('💾 Testing game state reload persistence...');
|
||||
const stateBeforeReload = await page.evaluate(() => {
|
||||
const app = document.querySelector('#app')?.__vue_app__;
|
||||
const pinia = app?.config?.globalProperties?.$pinia;
|
||||
const s = pinia?._s.get('game');
|
||||
return s ? { currentAct: s.currentAct, kronkorken: s.kronkorken, beers: s.beers } : null;
|
||||
});
|
||||
console.log('State before reload:', stateBeforeReload);
|
||||
|
||||
await page.reload({ waitUntil: 'networkidle0' });
|
||||
await new Promise(r => setTimeout(r, 1000));
|
||||
|
||||
const stateAfterReload = await page.evaluate(() => {
|
||||
const app = document.querySelector('#app')?.__vue_app__;
|
||||
const pinia = app?.config?.globalProperties?.$pinia;
|
||||
const s = pinia?._s.get('game');
|
||||
return s ? { currentAct: s.currentAct, kronkorken: s.kronkorken, beers: s.beers } : null;
|
||||
});
|
||||
console.log('State after reload:', stateAfterReload);
|
||||
|
||||
// 10. PARTY EXPRESS (Act IV)
|
||||
console.log('🚂 Advancing to Party Express (Act IV)...');
|
||||
await page.evaluate(() => {
|
||||
@@ -310,6 +345,16 @@ async function runPlaytest() {
|
||||
console.log('📸 18: Capturing Certificate Modal...');
|
||||
await page.screenshot({ path: path.join(SCREENSHOTS_DIR, '18_certificate_screen.png') });
|
||||
|
||||
// Test NOCHMAL SPIELEN button
|
||||
console.log('🔄 Testing NOCHMAL SPIELEN button...');
|
||||
const restartBtn = await page.$('.restart-btn');
|
||||
if (restartBtn) {
|
||||
await restartBtn.click();
|
||||
await new Promise(r => setTimeout(r, 1000));
|
||||
console.log('📸 19: Capturing post-restart Intro screen...');
|
||||
await page.screenshot({ path: path.join(SCREENSHOTS_DIR, '19_post_restart_intro.png') });
|
||||
}
|
||||
|
||||
// Verify all images loaded properly
|
||||
const brokenImages = await page.evaluate(() => {
|
||||
const imgs = Array.from(document.querySelectorAll('img'));
|
||||
|
||||
Reference in New Issue
Block a user