TeamLumi / luminescent-team

GNU Affero General Public License v3.0
12 stars 5 forks source link

3.0 Dex Toggle #87

Open AarCon opened 6 months ago

AarCon commented 6 months ago

[!WARNING] BLOCKED UNTIL 3.0 BALANCING IS FINISHED BLOCKED UNTIL ALL IMAGES (MON AND ITEM) ARE AVAILABLE IN THE REPO

List of Pokemon Images still needed - 3.0 pokemon form image pm0101_02_00_00_L.webp for Frenzied Lord of the Hollow does not exist - 3.0 pokemon form image pm0549_02_00_00_L.webp for Frenzied Lady of the Ridge does not exist - 3.0 pokemon form image pm0713_02_00_00_L.webp for Frenzied Lord of the Tundra does not exist - 3.0 pokemon form image pm0900_01_00_00_L.webp for Frenzied Lord of the Woods does not exist - 3.0 pokemon form image pm0966_01_00_00_L.webp for Segin Starmobile Revravroom does not exist - 3.0 pokemon form image pm0966_02_00_00_L.webp for Schedar Starmobile Revravroom does not exist - 3.0 pokemon form image pm0966_03_00_00_L.webp for Navi Starmobile Revravroom does not exist - 3.0 pokemon form image pm0966_04_00_00_L.webp for Ruchbah Starmobile Revravroom does not exist - 3.0 pokemon form image pm0966_05_00_00_L.webp for Caph Starmobile Revravroom does not exist - 3.0 pokemon form image pm1017_04_00_00_L.webp for Terastal Teal Mask does not exist - 3.0 pokemon form image pm1017_05_00_00_L.webp for Terastal Wellspring Mask does not exist - 3.0 pokemon form image pm1017_06_00_00_L.webp for Terastal Hearthflame Mask does not exist - 3.0 pokemon form image pm1017_07_00_00_L.webp for Terastal Cornerstone Mask does not exist
List of Item Images still needed - Evolution Items may be missing still. Need to add test to check.

Summary

This will add a toggle that will change the data being shown on the Dex page from 2.0F data to 3.0 data. The main method of doing this was by making both datasets, generated by the custom plugin, available to the components and dynamically switching between them. To dynamically switch between them, a hook was made to provide a global state to monitor which mode the site was in ("3.0" or "2.0"). In order to control this state, a toggle was created to exist alongside the Search Bar and Features Button. Additionally, all functions that use a dataset from in game will have a mode parameter to switch between "3.0" and "2.0", with "2.0" being the default mode.

On top of adding a toggle, the URL to visit pages will also need change to accommodate the dual datasets as there are discrepancies using the pokemonId. These discrepancies mainly apply to alternate forms of Pokémon as the initial dex is extended to include ScVi Pokémon. Where Clone Venusaur was originally #1013, it has been pushed up to be #1028. This will continue to be excacerbated as new generations are added to the game. To account for this, the format moving forward will need to be luminescent.team/pokedex/{monsNo}_{formNo} with any additional form and if there is no formNo, then that and the underscore are omitted to get luminescent.team/pokedex/{monsNo}.

Providing Dual Datasets

In order to allow for multiple datasets, the custom plugin, luminescent-pokedex-data-plugin, needed to be changed. This plugin, found here: plugins/pokedex-data-plugin/index.js is the heart of the entire Pokédex site. All that really needed to happen was to add the 3.0 data to each of the components in order to switch between them. However, the execution of this proved difficult as the original implementation used the pokemonId. In order to get around this, both the monsNo and formNo were necessary to uniquely identify and differentiate each Pokémon.

One thing that may need to be changed in the future is usage of the map function in the await Promise.all call. Currently, I am mapping over the 3.0 Pokémon dataset since every pokemon in that list is also in the 2.0 dataset but not vice versa. From there as it is iterating through the dataset, it will create a 3.0 json for mon and if there is a corresponding monsNo and formNo in the 2.0 data, it will create a json for the 2.0 data as well. If there is no corresponding 2.0 mon, the 3.0 json is used instead. This allows for an easy check if there is a corresponding mon in the React components by comparing the 2 datasets directly. If there's not a difference between the object instances, the component errors and shows that the 2.0 mon is not available in 3.0. Afaik, there shouldn't be a case for the opposite happening.

In the plugin, the Pokémon data generated comes from the getPokemon function from plugins/pokedex-data-plugin/dex/pokemon.js. Three notable changes to this function are as follows:

  1. The Pokedex Description is supplied here as the globalState module and hook cannot be called in the same file (see src/components/Pokedex2/PokemonPageContent.jsx).
  2. The Evolution Tree is supplied here now because you cannot use a hook's state within a loop even recursive loops like the getEvolutionTree function uses (more details on hooks can be found here). Because of this, the EvolutionGraph component needed to be refactored slightly to take the entire evolution tree.
  3. The getTechMachineLearnset function was rewritten to take the pokemonId and return the TM learnset object. There was a bug in the original code that was fixed a while back and I am now migrating this over to the plugins' functions.

Function Changes

The main change to all functions that used raw data from in game was adding a mode parameter to all functions to run in either "3.0" mode or "2.0" mode with "2.0" being the default. All datasets that are 3.0 data have a suffix of "3" at the end of their name declarations as seen in plugins/pokedex-data-plugin/dex/data3.js. Beyond that, the only other global change was that tests were added for the 3.0 mode if the original tests failed using 3.0 data.

Reduce Function Changes:

With the addition of mode, any constant that was using the reduce function and was calling a function with a mode param, needed to be refactored to look more like this:

const POKEMON_IDS_BY_EGG_GROUP3 = PersonalTable3.Personal.reduce((pokemonMap, currentPokemon) => {
  return createPokemonByEggGroupMap(pokemonMap, currentPokemon, "3.0");
}, {});

The constants that I found that follow this are the POKEMON_NAME_MAP, and POKEMON_IDS_BY_EGG_GROUP.

Evolution Function Changes:

Luckily the only change needed for this function was adding the mode to switch inbetween datasets. However, this did need to be added to the plugins' functions from the original functions as it was not added originally and is needed to be here as mentioned above.

Moves Function Changes:

As mentioned above, some of these functions had bugs in them, namely the generateMovesViaLearnset and getTechMachineLearnset functions.

Component Changes:

As mentioned previously, any function that deals directly with a dataset from the game has added a mode parameter, so any component that calls these functions needs to provide a mode. In this case however, we can provide that mode with the globalState hook that was made. In order to use the globalState, you need to call it like below:

import { useGlobalState } from '../common/GlobalState';

    // Inside the component's function
    const [globalState, updateMode] = useGlobalState();

    // Using the globalState
    console.log(globalState.mode)
    // This will output either "2.0" or "3.0" depending on the current state of the mode.

The mode will carry through to any page within the same tab/window that the Pokédex is open on. It does this through caching the mode in the sessionStorage (with cookies) so that you don't have to change the mode every time you refresh or navigate to a different Pokémon. This mode can be changed with the ModeSwitch component which will exist at the top of the Pokedex List page and individual Pokemon Dex pages

Another universal change is the links to different Pokémon will now use the {monsNo}_{formNo} format.

Evolution Graph Changes:

A minor, but complicated change was made in this component to allow Applin render their evolution tree properly. This changed the original function of adding a defaultEvo at the 3rd index of the first branch if the second branch had a 3rd index and the first branch didn't. Instead, it will iterate over each branch of the evolution tree and if there is a mon at the 3rd index of the final branch and not in the other branch(es), it will add defaultEvos to the previous branch(es). Currently, this only affects the Mime and Applin lines. This change should hopefully hold up the test of time as long as an evo line which has a branching evo line with only two stages gets another evo on only one of the branches. (I hate trying to think about the complexity of Evolution Lines -_-).

PokemonItems Changes:

Instead of using the getPokemon function directly, it will take each of the items from the pokemon objects provided by the custom plugin.

Pokemon List Page Changes:

The list of pokemon will change based on the mode that the website is currently in. This is done by useEffect hook to update every time the globalState.mode is changed

Pokemon Page Changes:

The list of pokemon in the Search Box will dynamically change based on the globalState.mode. If the current pokemon does not exist in 2.0, it will the default the Search Box to be nothing and display that the pokemon doesn't exist in the current mode.

Pokemon Move Set List Changes:

The TM learnset will now be passed directly from the plugin's provided data rather than using the function from outside of the plugin.