diff options
| author | Daniel Weipert <code@drogueronin.de> | 2023-08-21 15:30:31 +0200 | 
|---|---|---|
| committer | Daniel Weipert <code@drogueronin.de> | 2023-08-21 15:30:31 +0200 | 
| commit | ab3c0db2147a3ce0528ecbe8fe01c5b020a329f8 (patch) | |
| tree | e870f93d1f6766ca22e0fd47760a9772f0e47c5b /resources | |
| parent | ca093f0fb457a7037eb8a3acf3304e0646fa4278 (diff) | |
reorder and player defeated logic
Diffstat (limited to 'resources')
| -rw-r--r-- | resources/css/menu.css | 8 | ||||
| -rw-r--r-- | resources/js/game.js | 230 | ||||
| -rw-r--r-- | resources/js/main.js | 2 | ||||
| -rw-r--r-- | resources/js/ui.js | 140 | 
4 files changed, 256 insertions, 124 deletions
| diff --git a/resources/css/menu.css b/resources/css/menu.css index 1c5fb76..eee0b5f 100644 --- a/resources/css/menu.css +++ b/resources/css/menu.css @@ -85,6 +85,14 @@ +.monster-selection { +  display: grid; +  grid-template-columns: 1fr 1fr 1fr; +} + + + +  #status {    color: #fff;    background-color: #000; diff --git a/resources/js/game.js b/resources/js/game.js index d31d6e5..fad882b 100644 --- a/resources/js/game.js +++ b/resources/js/game.js @@ -22,6 +22,8 @@ const Game = {    isInBattle: false,    didTechniqueHit: false, +  /* Battle */ +    async progressTurn () {      Game.isProgressingTurn = true;      Memory.state.turn++; @@ -106,8 +108,37 @@ const Game = {        }        Game.removePhaseEvents('action', 'opponent'); -      Game.playerIsChoosingNextMonster = true; -      UI.openPartyMenu(); +      // whole party defeated +      if (!Memory.state.player.monsters.some((monster) => monster.hp > 0)) { +        if (Game.isBattleType('trainer')) { +          if (Memory.state.currentArea.encounters.length > 0) { +            await Game.encounterWildMonster(); +          } else { +            await Game.encounterTrainer(); +          } +        } + +        else if (Game.isBattleType('monster')) { +          if (Memory.state.currentArea.monsterProgress < Memory.state.currentArea.requiredEncounters) { +            Memory.state.currentArea.monsterProgress = 0; +            UI.drawStatus(); +          } + +          await Game.encounterWildMonster(); +        } + +        // heal all monsters full +        for (const monster of Memory.state.player.monsters) { +          monster.hp = monster.stats.hp; +        } +      } + +      // party members still left +      else { +        Game.playerIsChoosingNextMonster = true; +        const monsterSelectionNode = UI.createPlayerDefeatedMonsterSelection(); +        UI.openPlayerDefeatedMonsterSelection(monsterSelectionNode); +      }      }    }, @@ -325,6 +356,11 @@ const Game = {        const statusEffectLeech = Math.floor(monster.stats.hp / 16);        Game.addPhaseEvent(Game.phases.postAction, monster, () => { +        // if issuer is defeated => don't +        if (monster.statusEffect.issuer.hp <= 0) { +          return; +        } +          monster.hp -= statusEffectLeech;          monster.statusEffect.issuer.hp += statusEffectLeech; @@ -442,6 +478,7 @@ const Game = {            return;          } +        // technique          Game.doBattleAnimation = false;          await Game.tryUseTechnique(            await fetchTechnique(Memory.state.opponent.activeMonster.getLearnableTechniques()[Math.floor(Math.random() * Memory.state.opponent.activeMonster.getLearnableTechniques().length)].technique), @@ -452,6 +489,10 @@ const Game = {          await Game.progressTurn(); +        // item +        if (Memory.state.opponent.inventory.length > 0) { +        } +          Game.opponentActionTimeout = null;        }, Math.max(500, 2000 - (speedDifference * 10)));        console.log( @@ -473,7 +514,7 @@ const Game = {      }      let target = event.target; -    while (!target.classList.contains('techniques__technique')) { +    while (target.dataset.gameElementType !== 'menuBattleTechniquesTechnique') {        target = target.parentNode;      } @@ -492,6 +533,81 @@ const Game = {      }));    }, + +  /* Progression */ + +  async encounterWildMonster () { +    const randomMonster = Memory.state.currentArea.encounters[Math.floor(Math.random() * Memory.state.currentArea.encounters.length)]; +    const randomLevel = Math.floor(Math.random() * (randomMonster.level_range[1] - randomMonster.level_range[0]) + randomMonster.level_range[0]); + +    const monster = await fetchMonster(randomMonster.monster); +    monster.level = randomLevel; + +    const wildMonster = new Trainer({ monsters: [monster] }); +    wildMonster.type = 'monster'; +    await wildMonster.initialize(); +    Memory.state.opponent = wildMonster; + +    UI.drawOpponentMonster(); +  }, + +  async encounterTrainer () { +    Game.clearCurrentTurn(); + +    const nextTrainer = Memory.state.currentArea.trainers[Memory.state.currentArea.trainerProgress]; + +    const trainer = new Trainer(nextTrainer); +    if (nextTrainer.name === 'Rival') { +      trainer.monsters.push(Memory.state.rivalMonster); +    } +    await trainer.initialize() +    Memory.state.opponent = trainer; + +    UI.drawOpponentMonster(); +    UI.drawStatus(); +  }, + +  async encounterNextTrainerMonster () { +    const activeMonsterIdx = Memory.state.opponent.monsters.indexOf(Memory.state.opponent.activeMonster); +    Memory.state.opponent.activeMonster = Memory.state.opponent.monsters[activeMonsterIdx + 1]; + +    UI.drawOpponentMonster(); +  }, + +  async progressToNextArea () { +    Game.isLoadingArea = true; +    Game.clearCurrentTurn(); + +    const currentArea = Memory.state.currentArea; +    const nextArea = await fetchArea(currentArea.nextArea); + +    await Game.jumpToArea(nextArea); + +    if (nextArea.encounters.length > 0) { +      await Game.encounterWildMonster(); +    } else { +      await Game.encounterTrainer(); +    } + +    UI.drawStatus(); + +    Game.isLoadingArea = false; +  }, + +  /** +   * @param {Area} area +   */ +  async jumpToArea (area) { +    Game.clearCurrentTurn(); + +    Memory.state.currentArea = area; + +    UI.drawArea(area); +  }, + + +  /* Menu - Inventory */ +    /**     * @param {InventoryItem} item     * @param {Monster} monster @@ -571,22 +687,8 @@ const Game = {      inventory.splice(inventory.indexOf(item), 1);    }, -  /** -   * @param {string} type -   * -   * @returns {boolean} -   */ -  isBattleType (type) { -    return Memory.state.opponent.type === type; -  }, -  /** -   * @param {Monster} monster -   */ -  async evolveMonster (monster) { -    await fetchMonster(monster.evolutions[0].monster_slug); -    monster.evolve(monster.evolutions[0]); -  }, +  /* Menu - Catch */    /**     * @returns {boolean} @@ -620,82 +722,44 @@ const Game = {      await Game.progressTurn();    }, -  getStageOfDaySimple () { -    const hours = (new Date()).getHours(); -    if (hours >= 6 && hours < 18) { -      return 'day'; -    } else { -      return 'night'; -    } -  }, + +  /* Helper */    /** -   * @param {Area} area +   * @param {Monster} monster     */ -  async jumpToArea (area) { -    Game.clearCurrentTurn(); +  setActivePlayerMonster (monster) { +    Memory.state.player.activeMonster = monster; +    Memory.state.activeTechnique = Memory.state.player.activeMonster.activeTechniques[0]; -    Memory.state.currentArea = area; - -    UI.drawArea(area); +    UI.drawActiveMonster(); +    UI.drawActiveTechniques();    }, -  async progressToNextArea () { -    Game.isLoadingArea = true; -    Game.clearCurrentTurn(); - -    const currentArea = Memory.state.currentArea; -    const nextArea = await fetchArea(currentArea.nextArea); - -    await Game.jumpToArea(nextArea); - -    if (nextArea.encounters.length > 0) { -      await Game.encounterWildMonster(); -    } else { -      await Game.encounterTrainer(); -    } - -    UI.drawStatus(); - -    Game.isLoadingArea = false; +  /** +   * @param {Monster} monster +   */ +  async evolveMonster (monster) { +    await fetchMonster(monster.evolutions[0].monster_slug); +    monster.evolve(monster.evolutions[0]);    }, -  async encounterWildMonster () { -    const randomMonster = Memory.state.currentArea.encounters[Math.floor(Math.random() * Memory.state.currentArea.encounters.length)]; -    const randomLevel = Math.floor(Math.random() * (randomMonster.level_range[1] - randomMonster.level_range[0]) + randomMonster.level_range[0]); - -    const monster = await fetchMonster(randomMonster.monster); -    monster.level = randomLevel; - -    const wildMonster = new Trainer({ monsters: [monster] }); -    wildMonster.type = 'monster'; -    await wildMonster.initialize(); -    Memory.state.opponent = wildMonster; - -    UI.drawOpponentMonster(); +  /** +   * @param {string} type +   * +   * @returns {boolean} +   */ +  isBattleType (type) { +    return Memory.state.opponent.type === type;    }, -  async encounterTrainer () { -    Game.clearCurrentTurn(); - -    const nextTrainer = Memory.state.currentArea.trainers[Memory.state.currentArea.trainerProgress]; - -    const trainer = new Trainer(nextTrainer); -    if (nextTrainer.name === 'Rival') { -      trainer.monsters.push(Memory.state.rivalMonster); +  getStageOfDaySimple () { +    const hours = (new Date()).getHours(); +    if (hours >= 6 && hours < 18) { +      return 'day'; +    } else { +      return 'night';      } -    await trainer.initialize() -    Memory.state.opponent = trainer; - -    UI.drawOpponentMonster(); -    UI.drawStatus(); -  }, - -  async encounterNextTrainerMonster () { -    const activeMonsterIdx = Memory.state.opponent.monsters.indexOf(Memory.state.opponent.activeMonster); -    Memory.state.opponent.activeMonster = Memory.state.opponent.monsters[activeMonsterIdx + 1]; - -    UI.drawOpponentMonster();    },  }; diff --git a/resources/js/main.js b/resources/js/main.js index 8622731..4fd9c62 100644 --- a/resources/js/main.js +++ b/resources/js/main.js @@ -15,7 +15,7 @@    });    await Memory.state.player.initialize(); -  Memory.state.activeTechnique = Memory.state.player.activeMonster.activeTechniques[0]; +  Game.setActivePlayerMonster(Memory.state.player.monsters[0]);    Memory.state.activeBall = Memory.state.player.inventory[0]; // tuxeball    Memory.state.rivalMonster = await fetchMonster(possibleStarterMonsters[Math.round(Math.random() * (possibleStarterMonsters.length - 1))]); diff --git a/resources/js/ui.js b/resources/js/ui.js index c67e2f0..820a49c 100644 --- a/resources/js/ui.js +++ b/resources/js/ui.js @@ -350,6 +350,20 @@ const UI = {    },    /** +   * @returns {HTMLElement} +   */ +  createPlayerDefeatedMonsterSelection () { +    const monsterSelectionNode = UI.createMonsterSelection(Memory.state.player.monsters.filter((monster) => monster.hp > 0)); + +    monsterSelectionNode.addEventListener('monster:selected', (event) => { +      Game.setActivePlayerMonster(event.detail.monster); +      Game.playerIsChoosingNextMonster = false; +    }); + +    return monsterSelectionNode; +  }, + +  /**     * @param {HTMLElement} battleMonsterNode     */    drawOpponentMonster () { @@ -454,6 +468,20 @@ const UI = {      UI.drawStatus();    }, +  /** +   * @param {HTMLElement} monsterSelectionNode +   */ +  openPlayerDefeatedMonsterSelection (monsterSelectionNode) { +    const popup = UI.createPopup().cloneNode(true); // remove event listeners + +    monsterSelectionNode.addEventListener('monster:selected', () => { +      popup.remove(); +    }); + +    popup.querySelector('[data-template-slot="content"]').appendChild(monsterSelectionNode); +    UI.drawPopup(popup); +  }, +    /* Battle - Action Feedback */ @@ -572,6 +600,52 @@ const UI = {    inventorySelectionMode: 'use', +  /** +   * @param {Monster[]} monsters +   * +   * @returns {HTMLElement} +   */ +  createMonsterSelection (monsters) { +    const template = document.createElement('div'); +    template.classList.add('monster-selection'); + +    for (const monster of monsters) { +      const monsterNode = UI.createMonsterSelectionMonster(monster); + +      monsterNode.addEventListener('monster:selected', (event) => { +        template.dispatchEvent(new CustomEvent('monster:selected', { +          detail: { +            node: monsterNode, +            monster: event.detail.monster, +          }, +        })); +      }); + +      template.appendChild(monsterNode); +    } + +    return template; +  }, + +  /** +   * @param {Monster} monster +   * +   * @returns {HTMLElement} +   */ +  createMonsterSelectionMonster (monster) { +    const template = UI.createPartyMonster(monster); + +    template.addEventListener('click', () => { +      template.dispatchEvent(new CustomEvent('monster:selected', { +        detail: { +          monster: monster, +        }, +      })); +    }); + +    return template; +  }, +    drawStatus () {      const currentArea = Memory.state.currentArea; @@ -618,13 +692,8 @@ const UI = {          }          if (UI.partySelectionMode === 'select') { -          Memory.state.player.activeMonster = monster; -          Memory.state.activeTechnique = Memory.state.player.activeMonster.activeTechniques[0]; - -          UI.drawActiveMonster(); -          UI.drawActiveTechniques(); +          Game.setActivePlayerMonster(monster); -          Game.playerIsChoosingNextMonster = false;            popup.remove();          }          else if (UI.partySelectionMode === 'stats') { @@ -998,7 +1067,7 @@ const UI = {      const inventoryItemNode = UI.createTemplate(Template.inventoryItem);      inventoryItemNode.title = item.description; -    inventoryItemNode.dataset.templateItem = item.slug; +    inventoryItemNode.dataset.inventoryItem = item.slug;      inventoryItemNode.querySelector('[data-template-slot="sprite"]').src = `/modules/tuxemon/mods/tuxemon/${item.sprite}`;      inventoryItemNode.querySelector('[data-template-slot="name"]').textContent = item.name; @@ -1026,7 +1095,7 @@ const UI = {     * @param {InventoryItem} item     */    redrawInventoryItem (item) { -    const itemNode = document.querySelector(`#inventory *[data-template-item="${item.slug}"]`); +    const itemNode = document.querySelector(`#inventory *[data-inventory-item="${item.slug}"]`);      if (item.quantity === 0) {        itemNode.remove();      } @@ -1042,47 +1111,38 @@ const UI = {     * @returns {HTMLElement}     */    createItemMonsterSelection (item, monsters) { -    const template = document.createElement('div'); +    const template = UI.createMonsterSelection( +      monsters.filter((monster) => Game.canUseItem(item, monster)) +    ); -    /** -     * @param {Monster} monster -     * -     * @returns {(HTMLElement|null)} -     */ -    const createMonsterNode = (monster) => { -      if (!Game.canUseItem(item, monster)) { -        return null; -      } +    const onMonsterSelectd = async (event) => { +      const monster = event.detail.monster; +      const monsterNode = event.detail.node || event.target; + +      await Game.useItem(item, monster); -      const monsterNode = UI.createPartyMonster(monster); +      if (item.quantity === 0) { +        Game.removeItemFromInventory(Memory.state.player.inventory, item); +        template.dispatchEvent(new Event('item:isExhausted')); +      } -      monsterNode.addEventListener('click', async () => { -        await Game.useItem(item, monster); +      else { +        const canStillUseItem = Game.canUseItem(item, monster); +        if (canStillUseItem) { +          const replacingMonsterNode = UI.createMonsterSelectionMonster(monster); +          replacingMonsterNode.addEventListener('monster:selected', onMonsterSelectd); -        if (item.quantity === 0) { -          Game.removeItemFromInventory(Memory.state.player.inventory, item); -          template.dispatchEvent(new Event('item:isExhausted')); +          monsterNode.replaceWith(replacingMonsterNode);          } else { -          const replacingMonsterNode = createMonsterNode(monster); -          if (replacingMonsterNode) { -            monsterNode.replaceWith(replacingMonsterNode); -          } else { -            monsterNode.remove(); -            template.dispatchEvent(new Event('monster:lostCondition')); -          } +          monsterNode.remove(); +          template.dispatchEvent(new Event('monster:lostCondition'));          } +      } -        UI.redrawInventoryItem(item); -      }); - -      return monsterNode; +      UI.redrawInventoryItem(item);      }; -    for (const monster of monsters) { -      const monsterNode = createMonsterNode(monster); - -      monsterNode && template.appendChild(monsterNode); -    } +    template.addEventListener('monster:selected', onMonsterSelectd);      return template;    }, | 
