diff options
-rw-r--r-- | db/story/battle-rival-one.json | 19 | ||||
-rw-r--r-- | db/story/introduction.json | 46 | ||||
-rw-r--r-- | db/story/select-starter-monster.json | 35 | ||||
-rw-r--r-- | resources/js/db.js | 60 | ||||
-rw-r--r-- | resources/js/definitions.js | 1 | ||||
-rw-r--r-- | resources/js/story.js | 90 |
6 files changed, 205 insertions, 46 deletions
diff --git a/db/story/battle-rival-one.json b/db/story/battle-rival-one.json new file mode 100644 index 0000000..499b01d --- /dev/null +++ b/db/story/battle-rival-one.json @@ -0,0 +1,19 @@ +{ + "characters": { + "rival": { + "slug": "spyder_billie", + "text": [ + "spyder_papertown_firstfight", + "spyder_papertown_firstfight_win", + "spyder_papertown_firstfight_lose", + "spyder_papertown_firstfight_after" + ], + "monsters": [ + { + "slug": "RIVAL", + "level": 5 + } + ] + } + } +} diff --git a/db/story/introduction.json b/db/story/introduction.json new file mode 100644 index 0000000..7fa2ea3 --- /dev/null +++ b/db/story/introduction.json @@ -0,0 +1,46 @@ +{ + "characters": { + "ceo": { + "slug": "omnichannel-ceo", + "text": [ + "spyder_intro00", + "spyder_intro01" + ] + }, + + "shopKeeper": { + "slug": "tuxemart-keeper", + "text": [ + "spyder_intro_shopkeeper1", + "spyder_intro_shopkeeper4" + ] + } + }, + + "monsters": [ + { + "slug": "budaye", + "level": 5 + }, + { + "slug": "dollfin", + "level": 5 + }, + { + "slug": "grintot", + "level": 5 + }, + { + "slug": "ignibus", + "level": 5 + }, + { + "slug": "memnomnom", + "level": 5 + } + ], + + "money": 250, + + "area": "paper-town" +} diff --git a/db/story/select-starter-monster.json b/db/story/select-starter-monster.json new file mode 100644 index 0000000..017a284 --- /dev/null +++ b/db/story/select-starter-monster.json @@ -0,0 +1,35 @@ +{ + "characters": { + "dante": { + "slug": "spyder_dante", + "text": [ + "spyder_papertown_myfirstmon_notmet", + "spyder_papertown_myfirstmon1", + "spyder_papertown_myfirstmon2" + ] + } + }, + + "monsters": [ + { + "slug": "tweesher", + "level": 5 + }, + { + "slug": "lambert", + "level": 5 + }, + { + "slug": "nut", + "level": 5 + }, + { + "slug": "agnite", + "level": 5 + }, + { + "slug": "rockitten", + "level": 5 + } + ] +} diff --git a/resources/js/db.js b/resources/js/db.js index 35ed7bd..6e53b7e 100644 --- a/resources/js/db.js +++ b/resources/js/db.js @@ -4,6 +4,21 @@ * @property {string} monster_slug * @property {string} at_level * @property {string} item + * + * @typedef {Object} DB_NPC + * @property {string} slug + * @property {Object[]} template + * @property {string} template[].sprite_name + * + * @typedef {Object} DB_Story + * @property {number} money + * @property {string} area + * @property {Object<string, DB_StoryCharacter>} characters + * + * @typedef {Object} DB_StoryCharacter + * @property {string} slug + * @property {string[]} text + * @property {Object[]} monsters */ // @@ -64,17 +79,37 @@ const DB = { /** * @typedef {Object} DB_Item * - * @type {Object.<string, DB_Item>} + * @type {Object.<ItemSlug, DB_Item>} */ items: {}, + /** + * @typedef {Object} DB_NPC + * + * @type {Object.<string, DB_NPC>} + */ npcs: {}, + /** + * @typedef {Object} DB_Area + * + * @type {Object.<AreaSlug, DB_Area>} + */ areas: {}, + /** + * @type {Object.<StorySlug, DB_Story>} + */ + story: {}, + + /** + * @typedef {string} DB_Translation + * + * @type {Object.<string, DB_Translation>} + */ translations: {}, - currencies : {}, + currencies: {}, }; async function initializeDB () { @@ -152,7 +187,7 @@ async function fetchStatusEffect (slug) { } /** - * @param {string} slug + * @param {ItemSlug} slug * * @returns {Promise<Item>} */ @@ -167,7 +202,7 @@ async function fetchItem (slug) { /** * @param {string} slug * - * @returns {Promise<Object>} + * @returns {Promise<Npc>} */ async function fetchNpc (slug) { if (! DB.npcs[slug]) { @@ -178,9 +213,22 @@ async function fetchNpc (slug) { } /** + * @param {StorySlug} slug + * + * @returns {Promise<DB_Story>} + */ +async function fetchStory (slug) { + if (! DB.story[slug]) { + DB.story[slug] = await fetchDBData(`/db/story/${slug}.json`).then((response) => response.json()); + } + + return DB.story[slug]; +} + +/** * @param {string} locale * - * @returns {Promise<Object>} + * @returns {Promise<DB_Translation>} */ async function fetchTranslation (locale) { if (! DB.translations[locale]) { @@ -191,7 +239,7 @@ async function fetchTranslation (locale) { } /** - * @param {string} slug + * @param {AreaSlug} slug * * @returns {Promise<Area>} */ diff --git a/resources/js/definitions.js b/resources/js/definitions.js index f39025d..25f55f2 100644 --- a/resources/js/definitions.js +++ b/resources/js/definitions.js @@ -3,6 +3,7 @@ * @typedef {string} TechniqueSlug * @typedef {string} ItemSlug * @typedef {string} AreaSlug + * @typedef {string} StorySlug */ // diff --git a/resources/js/story.js b/resources/js/story.js index 1901829..0ceb224 100644 --- a/resources/js/story.js +++ b/resources/js/story.js @@ -14,20 +14,20 @@ const Story = { }, async introduction () { - await UI.buildAndShowStoryPopup({ speaker: await fetchNpc('omnichannel-ceo'), text: translate('spyder_intro00', true) }); - await UI.buildAndShowStoryPopup({ speaker: await fetchNpc('omnichannel-ceo'), text: translate('spyder_intro01', true) }); - await UI.buildAndShowStoryPopup({ speaker: await fetchNpc('tuxemart-keeper'), text: translate('spyder_intro_shopkeeper1', true) }); + const story = await fetchStory('introduction'); + const characterCeo = story.characters.ceo; + const characterShopKeeper = story.characters.shopKeeper; + const npcCeo = await fetchNpc(characterCeo.slug); + const npcShopKeeper = await fetchNpc(characterShopKeeper.slug); + + await UI.buildAndShowStoryPopup({ speaker: npcCeo, text: translate(characterCeo.text[0], true) }); + await UI.buildAndShowStoryPopup({ speaker: npcCeo, text: translate(characterCeo.text[1], true) }); + await UI.buildAndShowStoryPopup({ speaker: npcShopKeeper, text: translate(characterShopKeeper.text[0], true) }); const possibleStarterMonsters = await Promise.all( - [ - 'budaye', - 'dollfin', - 'grintot', - 'ignibus', - 'memnomnom', - ].map(async (monsterSlug) => { - const monster = await fetchMonster(monsterSlug); - monster.level = 5; + story.monsters.map(async (monsterData) => { + const monster = await fetchMonster(monsterData.slug); + monster.level = monsterData.level; return monster; }) ); @@ -41,16 +41,16 @@ const Story = { event.detail.popup.remove(); - await UI.buildAndShowStoryPopup({ speaker: await fetchNpc('tuxemart-keeper'), text: translate('spyder_intro_shopkeeper4', true) }); + await UI.buildAndShowStoryPopup({ speaker: npcShopKeeper, text: translate(characterShopKeeper.text[1], true) }); // set rival monster Memory.state.rivalMonster = event.detail.monster.slug; // set initial values - Memory.state.money = 250; + Memory.state.money = story.money; // go to starting area - await Game.goToArea('paper-town'); + await Game.goToArea(story.area); resolve(); })); @@ -58,20 +58,18 @@ const Story = { }, 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_myfirstmon1', true) }); - await UI.buildAndShowStoryPopup({ speaker: await fetchNpc('spyder_dante'), text: translate('spyder_papertown_myfirstmon2', true) }); + const story = await fetchStory('select-starter-monster'); + const characterDante = story.characters.dante; + const npcDante = await fetchNpc(characterDante.slug); + + await UI.buildAndShowStoryPopup({ speaker: npcDante, text: translate(characterDante.text[0], true) }); + await UI.buildAndShowStoryPopup({ speaker: npcDante, text: translate(characterDante.text[1], true) }); + await UI.buildAndShowStoryPopup({ speaker: npcDante, text: translate(characterDante.text[2], true) }); const possibleStarterMonsters = await Promise.all( - [ - 'tweesher', - 'lambert', - 'nut', - 'agnite', - 'rockitten', - ].map(async (monsterSlug) => { - const monster = await fetchMonster(monsterSlug); - monster.level = 5; + story.monsters.map(async (monsterData) => { + const monster = await fetchMonster(monsterData.slug); + monster.level = monsterData.level; return monster; }) ); @@ -86,9 +84,6 @@ const Story = { Memory.state.player.monsters.push(event.detail.monster); Game.setActivePlayerMonster(event.detail.monster); - // go to starting area - await Game.goToArea('paper-town'); - UI.drawActiveMonster(); UI.drawActiveTechniques(); @@ -102,22 +97,37 @@ const Story = { }, async battleRivalOne () { - const rivalMonster = await fetchMonster(Memory.state.rivalMonster); - rivalMonster.level = 5; - Memory.state.opponent = new Trainer({ monsters: [ rivalMonster ] }); + const story = await fetchStory('battle-rival-one'); + const characterRival = story.characters.rival; + const npcRival = await fetchNpc(story.characters.rival.slug); + + Memory.state.opponent = new Trainer({ + monsters: await Promise.all( + characterRival.monsters.map(async (monsterData) => { + if (monsterData.slug === 'RIVAL') { + monsterData.slug = Memory.state.rivalMonster; + } + + const monster = await fetchMonster(monsterData.slug); + monster.level = monsterData.level; + + return monster; + }) + ) + }); await Memory.state.opponent.initialize(); - await UI.buildAndShowStoryPopup({ speaker: await fetchNpc('spyder_billie'), text: translate('spyder_papertown_firstfight', true) }); + await UI.buildAndShowStoryPopup({ speaker: npcRival, text: translate(characterRival.text[0], true) }); await Story.battle(); if (Game.didWinStoryBattle) { - await UI.buildAndShowStoryPopup({ speaker: await fetchNpc('spyder_billie'), text: translate('spyder_papertown_firstfight_win', true) }); + await UI.buildAndShowStoryPopup({ speaker: npcRival, text: translate(characterRival.text[1], true) }); } else { - await UI.buildAndShowStoryPopup({ speaker: await fetchNpc('spyder_billie'), text: translate('spyder_papertown_firstfight_lose', true) }); + await UI.buildAndShowStoryPopup({ speaker: npcRival, text: translate(characterRival.text[2], true) }); } - await UI.buildAndShowStoryPopup({ speaker: await fetchNpc('spyder_billie'), text: translate('spyder_papertown_firstfight_after', true) }); + await UI.buildAndShowStoryPopup({ speaker: npcRival, text: translate(characterRival.text[3], true) }); Game.healParty(); }, @@ -125,7 +135,7 @@ const Story = { // Helper /** - * @param {string} slug + * @param {StorySlug} slug */ async progress (slug) { if (!Story[slug]) { @@ -143,8 +153,8 @@ const Story = { }, /** - * @param {string} fromSlug - * @param {string} toSlug + * @param {StorySlug} fromSlug + * @param {StorySlug} toSlug */ async immediateProgress (fromSlug, toSlug) { Memory.state.storyProgress[fromSlug] = true; |