const Story = { async start () { const settingsPopup = UI.createPopup(); settingsPopup.querySelector('[data-template-slot="content"]').append(UI.createSettingsMenu()); UI.drawPopup(settingsPopup); await new Promise((resolve) => { settingsPopup.addEventListener('close', UI.wrapCallback(async () => { resolve(); })); }); await Story.progress('introduction'); }, async introduction () { const possibleStarterMonsters = await Promise.all( [ 'budaye', 'dollfin', 'grintot', 'ignibus', 'memnomnom', ].map(async (monsterSlug) => await fetchMonster(monsterSlug)) ); const monsterSelection = UI.openStarterMonsterSelection(possibleStarterMonsters, { title: translate('story:introduction:monster_selection:title', true) }); await new Promise((resolve) => { monsterSelection.addEventListener('starter:monster:selected', UI.wrapCallback(async (event) => { if (!confirm(`Select ${event.detail.monster.name}?`)) { return; } event.detail.popup.remove(); await UI.buildAndShowStoryPopup({ speaker: await fetchNpc('spyder_dante'), text: translate('spyder_intro_shopkeeper4', true) }); // set rival monster Memory.state.rivalMonster = event.detail.monster.slug; // initialize state variables Memory.state.money = 250; Memory.state.opponent = new Trainer({ monsters: [] }); await Memory.state.opponent.initialize(); Memory.state.player = new Trainer({ monsters: [] }); await Memory.state.player.initialize(); // go to starting area await Game.goToArea('paper-town'); resolve(); })); }); }, async selectStarterMonster () { await UI.buildAndShowStoryPopup({ speaker: await fetchNpc('spyder_dante'), text: translate('spyder_papertown_myfirstmon_notmet', true) }); await UI.buildAndShowStoryPopup({ speaker: await fetchNpc('spyder_dante'), text: translate('spyder_papertown_myfirstmon2', true) }); const possibleStarterMonsters = await Promise.all( [ 'tweesher', 'lambert', 'nut', 'agnite', 'rockitten', ].map(async (monsterSlug) => await fetchMonster(monsterSlug)) ); const monsterSelection = UI.openStarterMonsterSelection(possibleStarterMonsters, { title: translate('story:select_starter_monster:monster_selection:title', true) }); await new Promise((resolve) => { monsterSelection.addEventListener('starter:monster:selected', UI.wrapCallback(async (event) => { if (!confirm(`Select ${event.detail.monster.name}?`)) { return; } Memory.state.player = new Trainer({ monsters: [ event.detail.monster, ] }); await Memory.state.player.initialize(); Game.setActivePlayerMonster(Memory.state.player.monsters[0]); // go to starting area await Game.goToArea('paper-town'); UI.drawActiveMonster(); UI.drawActiveTechniques(); event.detail.popup.remove(); resolve(); })); }); await Story.progress('battleRivalOne'); }, async battleRivalOne () { Memory.state.opponent = new Trainer({ monsters: [ await fetchMonster(Memory.state.rivalMonster) ] }); await Memory.state.opponent.initialize(); await UI.buildAndShowStoryPopup({ speaker: await fetchNpc('spyder_rivalbillie'), text: translate('spyder_papertown_firstfight', true) }); await Story.battle(); }, // Helper /** * @param {string} slug * * @returns {Promise} */ async progress (slug) { if (!Story[slug]) { return; } Memory.state.currentStory = slug; Memory.saveToLocalStorage(); await Story[slug](); Memory.state.storyProgress[slug] = true; Memory.state.currentStory = null; Memory.saveToLocalStorage(); }, /** * @returns {Promise} */ async battle () { const previousArea = Object.assign({}, Memory.state.currentArea); Game.isStoryBattle = true; Memory.state.Game.isInBattle = true; Memory.saveToLocalStorage(); UI.drawBattle(); UI.showBattle(); await new Promise((resolve) => { const interval = setInterval(() => { if (!Game.isStoryBattle) { clearInterval(interval); resolve(); } }, 100); }); if (previousArea.slug === Memory.state.currentArea.slug) { Memory.state.currentArea.trainerProgress = previousArea.trainerProgress; UI.drawStatus(); } }, };