diff options
| author | Daniel Weipert <code@drogueronin.de> | 2023-08-18 16:07:39 +0200 | 
|---|---|---|
| committer | Daniel Weipert <code@drogueronin.de> | 2023-08-18 16:07:39 +0200 | 
| commit | d3e65b98ca932aef1e05e33d74eaf62be520cdd4 (patch) | |
| tree | 3645410b3c4c857d1a602f6b6abda71b106aae64 /resources/js | |
| parent | aa44f67ab57673528e96a4a075fbd8cd0354bd68 (diff) | |
inventory and items
Diffstat (limited to 'resources/js')
| -rw-r--r-- | resources/js/classes/InventoryItem.js | 40 | ||||
| -rw-r--r-- | resources/js/classes/Item.js | 22 | ||||
| -rw-r--r-- | resources/js/classes/State.js | 2 | ||||
| -rw-r--r-- | resources/js/db.js | 16 | ||||
| -rw-r--r-- | resources/js/game.js | 17 | ||||
| -rw-r--r-- | resources/js/helpers.js | 7 | ||||
| -rw-r--r-- | resources/js/ui.js | 148 | 
7 files changed, 246 insertions, 6 deletions
diff --git a/resources/js/classes/InventoryItem.js b/resources/js/classes/InventoryItem.js new file mode 100644 index 0000000..9dfdbcc --- /dev/null +++ b/resources/js/classes/InventoryItem.js @@ -0,0 +1,40 @@ +class InventoryItem { +  /** +   * @type {Item} +   */ +  item = null; + +  /** +   * @type {number} +   */ +  quantity = 1; + +  /** +   * @param {Item} item +   */ +  constructor (item) { +    this.item = item; +  } + +  /* Item */ + +  get slug () { +    return this.item.slug; +  } + +  get name () { +    return this.item.name; +  } + +  get category () { +    return this.item.category; +  } + +  get type () { +    return this.item.type; +  } + +  get sprite () { +    return this.item.sprite; +  } +} diff --git a/resources/js/classes/Item.js b/resources/js/classes/Item.js index e274a20..6207cc2 100644 --- a/resources/js/classes/Item.js +++ b/resources/js/classes/Item.js @@ -1 +1,21 @@ -class Item {} +class Item { +  constructor (slug) { +    this.slug = slug; +  } + +  get name () { +    return slugToName(this.slug); +  } + +  get category () { +    return DB.items[this.slug].category; +  } + +  get type () { +    return DB.items[this.slug].type; +  } + +  get sprite () { +    return DB.items[this.slug].sprite; +  } +} diff --git a/resources/js/classes/State.js b/resources/js/classes/State.js index 2384a85..c0065d1 100644 --- a/resources/js/classes/State.js +++ b/resources/js/classes/State.js @@ -10,7 +10,7 @@ class State {    monsters = [];    /** -   * @type {Item[]} +   * @type {InventoryItem[]}     */    inventory = []; diff --git a/resources/js/db.js b/resources/js/db.js index 96b971a..64b2e9b 100644 --- a/resources/js/db.js +++ b/resources/js/db.js @@ -1,16 +1,19 @@  const DB = {    allMonsters: [],    allAnimations: {}, +  allItems: [],    monsters: {},    shapes: {},    elements: {},    techniques: {},    statusEffects: {}, +  items: {},  };  async function initializeDB () {    DB.allMonsters = await fetch('/db/all-monsters.json').then((response) => response.json());    DB.allAnimations = await fetch('/db/animations.json').then((response) => response.json()); +  DB.allItems = await fetch('/db/all-items.json').then((response) => response.json());    DB.shapes = await fetch('/modules/tuxemon/mods/tuxemon/db/shape/shapes.json').then((response) => response.json()); @@ -60,3 +63,16 @@ async function fetchStatusEffect (slug) {    return new StatusEffect(slug);  } + +/** + * @param {string} slug + * + * @returns {Promise<StatusEffect>} + */ +async function fetchItem (slug) { +  if (! DB.items[slug]) { +    DB.items[slug] = await fetch(`/modules/tuxemon/mods/tuxemon/db/item/${slug}.json`).then((response) => response.json()); +  } + +  return new Item(slug); +} diff --git a/resources/js/game.js b/resources/js/game.js index 140f9d5..e383677 100644 --- a/resources/js/game.js +++ b/resources/js/game.js @@ -462,6 +462,7 @@ UI.elements.menuCatch.addEventListener('click', Game.catchMonster);    state.enemy.monster = await fetchMonster(possibleStarterMonsters[Math.round(Math.random() * (possibleStarterMonsters.length - 1))]);    state.partyMonsters = [ +    await fetchMonster('dollfin'),      await fetchMonster(possibleStarterMonsters[Math.round(Math.random() * (possibleStarterMonsters.length - 1))]),      await fetchMonster('corvix'),      await fetchMonster('lunight'), @@ -477,6 +478,22 @@ UI.elements.menuCatch.addEventListener('click', Game.catchMonster);    state.activeMonster = state.partyMonsters[0];    state.activeTechnique = state.activeMonster.activeTechniques[0]; +  state.inventory = [ +    new InventoryItem(await fetchItem('tuxeball')), +    new InventoryItem(await fetchItem('ancient_egg')), +    new InventoryItem(await fetchItem('sweet_sand')), +    new InventoryItem(await fetchItem('tectonic_drill')), +    new InventoryItem(await fetchItem('surfboard')), +    new InventoryItem(await fetchItem('sledgehammer')), +    new InventoryItem(await fetchItem('raise_melee')), +    new InventoryItem(await fetchItem('raise_speed')), +    new InventoryItem(await fetchItem('mm_fire')), +    new InventoryItem(await fetchItem('mm_water')), +    new InventoryItem(await fetchItem('cureall')), +    new InventoryItem(await fetchItem('potion')), +    new InventoryItem(await fetchItem('super_potion')), +  ]; +    UI.drawEnemyMonster();    UI.drawActiveMonster();    UI.drawActiveTechniques(); diff --git a/resources/js/helpers.js b/resources/js/helpers.js index 019f822..1622eb2 100644 --- a/resources/js/helpers.js +++ b/resources/js/helpers.js @@ -43,3 +43,10 @@ function mixColors(...colors) {    return `rgb(${r}, ${g}, ${b})`;  } + +/** + * @returns {string} + */ +function randomString () { +  return (Math.random() + 1).toString(36).substring(2); +} diff --git a/resources/js/ui.js b/resources/js/ui.js index 3739ce6..455e785 100644 --- a/resources/js/ui.js +++ b/resources/js/ui.js @@ -1,6 +1,11 @@  const Template = {    popup: document.querySelector('#tpl___popup'), +  tabs: document.querySelector('#tpl___tabs'), +  tabHeading: document.querySelector('#tpl___tabs__tab-heading'), +  tabPanels: document.querySelector('#tpl___tabs__panels'), +  tabPanel: document.querySelector('#tpl___tabs__tab-panel'), +    battleMonster: document.querySelector('#tpl___battle__monster'),    battleHpBar: document.querySelector('#tpl___battle__hp-bar'),    battleExpBar: document.querySelector('#tpl___battle__exp-bar'), @@ -17,6 +22,9 @@ const Template = {    movesetList: document.querySelector('#tpl___moveset__list'),    movesetItem: document.querySelector('#tpl___moveset__item'), +  inventory: document.querySelector('#tpl___inventory'), +  inventoryItem: document.querySelector('#tpl___inventory__item'), +    menuJournal:  document.querySelector('#tpl___menu__journal'),    dialogSave:  document.querySelector('#tpl___dialog__save'),    dialogLoad:  document.querySelector('#tpl___dialog__load'), @@ -49,7 +57,22 @@ const UI = {      const templateBase = document.createElement('div');      templateBase.innerHTML = template.innerHTML.trim(); -    return templateBase.firstChild; +    const templateNode = templateBase.firstChild; + +    /** +     * @param {HTMLElement} targetElement +     */ +    templateNode.appendTo = function (targetElement) { +      if (templateNode.dataset.templateType && templateNode.dataset.templateType === 'multiple') { +        for (const child of [...this.children]) { +          targetElement.appendChild(child); +        } +      } else { +        targetElement.appendChild(this); +      } +    }; + +    return templateNode;    },    /** @@ -69,6 +92,56 @@ const UI = {    },    /** +   * @typedef {Object} Tab +   * @property {HTMLElement} heading +   * @property {HTMLElement} content +   * @inner +   * +   * @param {Tab[]} tabs +   * +   * @returns {HTMLElement} +   */ +  createTabs (tabs) { +    const wrap = UI.createTemplate(Template.tabs); +    const panelsNode = UI.createTemplate(Template.tabPanels); + +    wrap.style.gridTemplateColumns = '1fr '.repeat(tabs.length); + +    const name = randomString(); + +    for (const idx in tabs) { +      const tab = tabs[idx]; +      const tabHeading = UI.createTemplate(Template.tabHeading); +      const tabPanel = UI.createTemplate(Template.tabPanel); + +      const inputId = `${name}_${idx}`; +      const panelId = randomString(); + +      const tabHeadingInput = tabHeading.querySelector('[data-template-slot="input"]'); +      tabHeadingInput.name = name; +      tabHeadingInput.id = inputId; +      tabHeadingInput.setAttribute('aria-controls', panelId); +      if (idx == 0) { +        tabHeadingInput.checked = true; +      } + +      const tabHeadingLabel = tabHeading.querySelector('[data-template-slot="label"]'); +      tabHeadingLabel.setAttribute('for', inputId); +      tabHeadingLabel.appendChild(tab.heading); + +      tabPanel.id = panelId; +      tabPanel.appendChild(tab.content); + +      tabHeading.appendTo(wrap); +      panelsNode.appendChild(tabPanel); +    } + +    wrap.appendChild(panelsNode); + +    return wrap; +  }, + +  /**     * @param {HTMLElement} slotNode     * @param {HTMLElement} replacingNode     * @@ -527,15 +600,82 @@ const UI = {      UI.drawPopup(popup);    }, -  openInventoryMenu () { // TODO +  openInventoryMenu () {      const popup = UI.createPopup(); +    const inventory = UI.createTemplate(Template.inventory); + +    const tabs = { +      heal: { +        heading: 'Heal', +        items: [], +      }, +      stats: { +        heading: 'Stats', +        items: [], +      }, +      balls: { +        heading: 'Balls', +        items: [], +      }, +      techniques: { +        heading: 'Techniques', +        items: [], +      }, +      other: { +        heading: 'Other', +        items: [], +      }, +      keyItems: { +        heading: 'Key Items', +        items: [], +      }, +    }; -    const inventory = document.createElement('div'); -    inventory.id = 'inventory';      for (const item of state.inventory) { +      const inventoryItemNode = UI.createTemplate(Template.inventoryItem); + +      inventoryItemNode.querySelector('[data-template-slot="sprite"]').src = `/modules/tuxemon/mods/tuxemon/${item.sprite}`; +      inventoryItemNode.querySelector('[data-template-slot="name"]').textContent = item.name; +      inventoryItemNode.querySelector('[data-template-slot="quantity"]').textContent = item.quantity; + +      if (['potion', 'revive'].includes(item.category)) { +        tabs['heal'].items.push(inventoryItemNode); +      } +      else if (['stats'].includes(item.category)) { +        tabs['stats'].items.push(inventoryItemNode); +      } +      else if (['capture'].includes(item.category)) { +        tabs['balls'].items.push(inventoryItemNode); +      } +      else if (['technique'].includes(item.category)) { +        tabs['techniques'].items.push(inventoryItemNode); +      } +      else if (['KeyItem'].includes(item.type)) { +        tabs['keyItems'].items.push(inventoryItemNode); +      } +      else { +        tabs['other'].items.push(inventoryItemNode); +      }      } +    const tabsNode = UI.createTabs(Object.values(tabs).map((tab) => { +      const content = document.createElement('div'); +      for (const item of tab.items) { +        content.appendChild(item); +      } + +      return { +        heading: document.createTextNode(tab.heading), +        content: content, +      }; +    })); + +    tabsNode.style.gridTemplateColumns = '1fr 1fr 1fr'; +    inventory.appendChild(tabsNode); +      popup.querySelector('.popup').appendChild(inventory); +    popup.classList.add('inventory__popup'); +      UI.drawPopup(popup);    },  | 
