Merge branch 'beta' into charge-move-overhaul

This commit is contained in:
innerthunder 2024-10-20 01:55:18 -07:00
commit 6743c450da
101 changed files with 11636 additions and 8309 deletions

View File

@ -1,5 +1,5 @@
import tseslint from '@typescript-eslint/eslint-plugin'; import tseslint from '@typescript-eslint/eslint-plugin';
import stylisticTs from '@stylistic/eslint-plugin-ts' import stylisticTs from '@stylistic/eslint-plugin-ts';
import parser from '@typescript-eslint/parser'; import parser from '@typescript-eslint/parser';
import importX from 'eslint-plugin-import-x'; import importX from 'eslint-plugin-import-x';
@ -16,15 +16,15 @@ export default [
'@typescript-eslint': tseslint '@typescript-eslint': tseslint
}, },
rules: { rules: {
"eqeqeq": ["error", "always"], // Enforces the use of === and !== instead of == and != "eqeqeq": ["error", "always"], // Enforces the use of `===` and `!==` instead of `==` and `!=`
"indent": ["error", 2], // Enforces a 2-space indentation "indent": ["error", 2, { "SwitchCase": 1 }], // Enforces a 2-space indentation, enforces indentation of `case ...:` statements
"quotes": ["error", "double"], // Enforces the use of double quotes for strings "quotes": ["error", "double"], // Enforces the use of double quotes for strings
"no-var": "error", // Disallows the use of var, enforcing let or const instead "no-var": "error", // Disallows the use of `var`, enforcing `let` or `const` instead
"prefer-const": "error", // Prefers the use of const for variables that are never reassigned "prefer-const": "error", // Enforces the use of `const` for variables that are never reassigned
"no-undef": "off", // Disables the rule that disallows the use of undeclared variables (TypeScript handles this) "no-undef": "off", // Disables the rule that disallows the use of undeclared variables (TypeScript handles this)
"@typescript-eslint/no-unused-vars": [ "error", { "@typescript-eslint/no-unused-vars": [ "error", {
"args": "none", // Allows unused function parameters. Useful for functions with specific signatures where not all parameters are always used. "args": "none", // Allows unused function parameters. Useful for functions with specific signatures where not all parameters are always used.
"ignoreRestSiblings": true // Allows unused variables that are part of a rest property in object destructuring. Useful for excluding certain properties from an object while using the rest. "ignoreRestSiblings": true // Allows unused variables that are part of a rest property in object destructuring. Useful for excluding certain properties from an object while using the others.
}], }],
"eol-last": ["error", "always"], // Enforces at least one newline at the end of files "eol-last": ["error", "always"], // Enforces at least one newline at the end of files
"@stylistic/ts/semi": ["error", "always"], // Requires semicolons for TypeScript-specific syntax "@stylistic/ts/semi": ["error", "always"], // Requires semicolons for TypeScript-specific syntax
@ -32,14 +32,14 @@ export default [
"no-extra-semi": ["error"], // Disallows unnecessary semicolons for TypeScript-specific syntax "no-extra-semi": ["error"], // Disallows unnecessary semicolons for TypeScript-specific syntax
"brace-style": "off", // Note: you must disable the base rule as it can report incorrect errors "brace-style": "off", // Note: you must disable the base rule as it can report incorrect errors
"curly": ["error", "all"], // Enforces the use of curly braces for all control statements "curly": ["error", "all"], // Enforces the use of curly braces for all control statements
"@stylistic/ts/brace-style": ["error", "1tbs"], "@stylistic/ts/brace-style": ["error", "1tbs"], // Enforces the following brace style: https://eslint.style/rules/js/brace-style#_1tbs
"no-trailing-spaces": ["error", { // Disallows trailing whitespace at the end of lines "no-trailing-spaces": ["error", { // Disallows trailing whitespace at the end of lines
"skipBlankLines": false, // Enforces the rule even on blank lines "skipBlankLines": false, // Enforces the rule even on blank lines
"ignoreComments": false // Enforces the rule on lines containing comments "ignoreComments": false // Enforces the rule on lines containing comments
}], }],
"space-before-blocks": ["error", "always"], // Enforces a space before blocks "space-before-blocks": ["error", "always"], // Enforces a space before blocks
"keyword-spacing": ["error", { "before": true, "after": true }], // Enforces spacing before and after keywords "keyword-spacing": ["error", { "before": true, "after": true }], // Enforces spacing before and after keywords
"comma-spacing": ["error", { "before": false, "after": true }], // Enforces spacing after comma "comma-spacing": ["error", { "before": false, "after": true }], // Enforces spacing after commas
"import-x/extensions": ["error", "never", { "json": "always" }], // Enforces no extension for imports unless json "import-x/extensions": ["error", "never", { "json": "always" }], // Enforces no extension for imports unless json
"array-bracket-spacing": ["error", "always", { "objectsInArrays": false, "arraysInArrays": false }], // Enforces consistent spacing inside array brackets "array-bracket-spacing": ["error", "always", { "objectsInArrays": false, "arraysInArrays": false }], // Enforces consistent spacing inside array brackets
"object-curly-spacing": ["error", "always", { "arraysInObjects": false, "objectsInObjects": false }], // Enforces consistent spacing inside braces of object literals, destructuring assignments, and import/export specifiers "object-curly-spacing": ["error", "always", { "arraysInObjects": false, "objectsInObjects": false }], // Enforces consistent spacing inside braces of object literals, destructuring assignments, and import/export specifiers

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "pokemon-rogue-battle", "name": "pokemon-rogue-battle",
"version": "1.0.4", "version": "1.1.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "pokemon-rogue-battle", "name": "pokemon-rogue-battle",
"version": "1.0.4", "version": "1.1.0",
"hasInstallScript": true, "hasInstallScript": true,
"dependencies": { "dependencies": {
"@material/material-color-utilities": "^0.2.7", "@material/material-color-utilities": "^0.2.7",

View File

@ -1,7 +1,7 @@
{ {
"name": "pokemon-rogue-battle", "name": "pokemon-rogue-battle",
"private": true, "private": true,
"version": "1.0.4", "version": "1.1.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"start": "vite", "start": "vite",

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

@ -1359,69 +1359,69 @@ export default class BattleScene extends SceneBase {
} }
switch (species.speciesId) { switch (species.speciesId) {
case Species.UNOWN: case Species.UNOWN:
case Species.SHELLOS: case Species.SHELLOS:
case Species.GASTRODON: case Species.GASTRODON:
case Species.BASCULIN: case Species.BASCULIN:
case Species.DEERLING: case Species.DEERLING:
case Species.SAWSBUCK: case Species.SAWSBUCK:
case Species.FROAKIE: case Species.FROAKIE:
case Species.FROGADIER: case Species.FROGADIER:
case Species.SCATTERBUG: case Species.SCATTERBUG:
case Species.SPEWPA: case Species.SPEWPA:
case Species.VIVILLON: case Species.VIVILLON:
case Species.FLABEBE: case Species.FLABEBE:
case Species.FLOETTE: case Species.FLOETTE:
case Species.FLORGES: case Species.FLORGES:
case Species.FURFROU: case Species.FURFROU:
case Species.PUMPKABOO: case Species.PUMPKABOO:
case Species.GOURGEIST: case Species.GOURGEIST:
case Species.ORICORIO: case Species.ORICORIO:
case Species.MAGEARNA: case Species.MAGEARNA:
case Species.ZARUDE: case Species.ZARUDE:
case Species.SQUAWKABILLY: case Species.SQUAWKABILLY:
case Species.TATSUGIRI: case Species.TATSUGIRI:
case Species.PALDEA_TAUROS: case Species.PALDEA_TAUROS:
return Utils.randSeedInt(species.forms.length);
case Species.PIKACHU:
return Utils.randSeedInt(8);
case Species.EEVEE:
return Utils.randSeedInt(2);
case Species.GRENINJA:
return Utils.randSeedInt(2);
case Species.ZYGARDE:
return Utils.randSeedInt(4);
case Species.MINIOR:
return Utils.randSeedInt(6);
case Species.ALCREMIE:
return Utils.randSeedInt(9);
case Species.MEOWSTIC:
case Species.INDEEDEE:
case Species.BASCULEGION:
case Species.OINKOLOGNE:
return gender === Gender.FEMALE ? 1 : 0;
case Species.TOXTRICITY:
const lowkeyNatures = [ Nature.LONELY, Nature.BOLD, Nature.RELAXED, Nature.TIMID, Nature.SERIOUS, Nature.MODEST, Nature.MILD, Nature.QUIET, Nature.BASHFUL, Nature.CALM, Nature.GENTLE, Nature.CAREFUL ];
if (nature !== undefined && lowkeyNatures.indexOf(nature) > -1) {
return 1;
}
return 0;
case Species.GIMMIGHOUL:
// Chest form can only be found in Mysterious Chest Encounter, if this is a game mode with MEs
if (this.gameMode.hasMysteryEncounters) {
return 1; // Wandering form
} else {
return Utils.randSeedInt(species.forms.length); return Utils.randSeedInt(species.forms.length);
} case Species.PIKACHU:
return Utils.randSeedInt(8);
case Species.EEVEE:
return Utils.randSeedInt(2);
case Species.GRENINJA:
return Utils.randSeedInt(2);
case Species.ZYGARDE:
return Utils.randSeedInt(4);
case Species.MINIOR:
return Utils.randSeedInt(6);
case Species.ALCREMIE:
return Utils.randSeedInt(9);
case Species.MEOWSTIC:
case Species.INDEEDEE:
case Species.BASCULEGION:
case Species.OINKOLOGNE:
return gender === Gender.FEMALE ? 1 : 0;
case Species.TOXTRICITY:
const lowkeyNatures = [ Nature.LONELY, Nature.BOLD, Nature.RELAXED, Nature.TIMID, Nature.SERIOUS, Nature.MODEST, Nature.MILD, Nature.QUIET, Nature.BASHFUL, Nature.CALM, Nature.GENTLE, Nature.CAREFUL ];
if (nature !== undefined && lowkeyNatures.indexOf(nature) > -1) {
return 1;
}
return 0;
case Species.GIMMIGHOUL:
// Chest form can only be found in Mysterious Chest Encounter, if this is a game mode with MEs
if (this.gameMode.hasMysteryEncounters) {
return 1; // Wandering form
} else {
return Utils.randSeedInt(species.forms.length);
}
} }
if (ignoreArena) { if (ignoreArena) {
switch (species.speciesId) { switch (species.speciesId) {
case Species.BURMY: case Species.BURMY:
case Species.WORMADAM: case Species.WORMADAM:
case Species.ROTOM: case Species.ROTOM:
case Species.LYCANROC: case Species.LYCANROC:
return Utils.randSeedInt(species.forms.length); return Utils.randSeedInt(species.forms.length);
} }
return 0; return 0;
} }
@ -1886,17 +1886,17 @@ export default class BattleScene extends SceneBase {
const soundDetails = sound.key.split("/"); const soundDetails = sound.key.split("/");
switch (soundDetails[0]) { switch (soundDetails[0]) {
case "battle_anims": case "battle_anims":
case "cry": case "cry":
if (soundDetails[1].startsWith("PRSFX- ")) { if (soundDetails[1].startsWith("PRSFX- ")) {
sound.setVolume(this.masterVolume * this.fieldVolume * 0.5); sound.setVolume(this.masterVolume * this.fieldVolume * 0.5);
} else { } else {
sound.setVolume(this.masterVolume * this.fieldVolume); sound.setVolume(this.masterVolume * this.fieldVolume);
} }
break; break;
case "se": case "se":
case "ui": case "ui":
sound.setVolume(this.masterVolume * this.seVolume); sound.setVolume(this.masterVolume * this.seVolume);
} }
} }
} }
@ -1936,31 +1936,31 @@ export default class BattleScene extends SceneBase {
const keyDetails = key.split("/"); const keyDetails = key.split("/");
config["volume"] = config["volume"] ?? 1; config["volume"] = config["volume"] ?? 1;
switch (keyDetails[0]) { switch (keyDetails[0]) {
case "level_up_fanfare": case "level_up_fanfare":
case "item_fanfare": case "item_fanfare":
case "minor_fanfare": case "minor_fanfare":
case "heal": case "heal":
case "evolution": case "evolution":
case "evolution_fanfare": case "evolution_fanfare":
// These sounds are loaded in as BGM, but played as sound effects // These sounds are loaded in as BGM, but played as sound effects
// When these sounds are updated in updateVolume(), they are treated as BGM however because they are placed in the BGM Cache through being called by playSoundWithoutBGM() // When these sounds are updated in updateVolume(), they are treated as BGM however because they are placed in the BGM Cache through being called by playSoundWithoutBGM()
config["volume"] *= (this.masterVolume * this.bgmVolume); config["volume"] *= (this.masterVolume * this.bgmVolume);
break; break;
case "battle_anims": case "battle_anims":
case "cry": case "cry":
config["volume"] *= (this.masterVolume * this.fieldVolume); config["volume"] *= (this.masterVolume * this.fieldVolume);
//PRSFX sound files are unusually loud //PRSFX sound files are unusually loud
if (keyDetails[1].startsWith("PRSFX- ")) { if (keyDetails[1].startsWith("PRSFX- ")) {
config["volume"] *= 0.5; config["volume"] *= 0.5;
} }
break; break;
case "ui": case "ui":
//As of, right now this applies to the "select", "menu_open", "error" sound effects //As of, right now this applies to the "select", "menu_open", "error" sound effects
config["volume"] *= (this.masterVolume * this.uiVolume); config["volume"] *= (this.masterVolume * this.uiVolume);
break; break;
case "se": case "se":
config["volume"] *= (this.masterVolume * this.seVolume); config["volume"] *= (this.masterVolume * this.seVolume);
break; break;
} }
this.sound.play(key, config); this.sound.play(key, config);
return this.sound.get(key) as AnySound; return this.sound.get(key) as AnySound;
@ -1989,208 +1989,208 @@ export default class BattleScene extends SceneBase {
getBgmLoopPoint(bgmName: string): number { getBgmLoopPoint(bgmName: string): number {
switch (bgmName) { switch (bgmName) {
case "battle_kanto_champion": //B2W2 Kanto Champion Battle case "battle_kanto_champion": //B2W2 Kanto Champion Battle
return 13.950; return 13.950;
case "battle_johto_champion": //B2W2 Johto Champion Battle case "battle_johto_champion": //B2W2 Johto Champion Battle
return 23.498; return 23.498;
case "battle_hoenn_champion_g5": //B2W2 Hoenn Champion Battle case "battle_hoenn_champion_g5": //B2W2 Hoenn Champion Battle
return 11.328; return 11.328;
case "battle_hoenn_champion_g6": //ORAS Hoenn Champion Battle case "battle_hoenn_champion_g6": //ORAS Hoenn Champion Battle
return 11.762; return 11.762;
case "battle_sinnoh_champion": //B2W2 Sinnoh Champion Battle case "battle_sinnoh_champion": //B2W2 Sinnoh Champion Battle
return 12.235; return 12.235;
case "battle_champion_alder": //BW Unova Champion Battle case "battle_champion_alder": //BW Unova Champion Battle
return 27.653; return 27.653;
case "battle_champion_iris": //B2W2 Unova Champion Battle case "battle_champion_iris": //B2W2 Unova Champion Battle
return 10.145; return 10.145;
case "battle_kalos_champion": //XY Kalos Champion Battle case "battle_kalos_champion": //XY Kalos Champion Battle
return 10.380; return 10.380;
case "battle_alola_champion": //USUM Alola Champion Battle case "battle_alola_champion": //USUM Alola Champion Battle
return 13.025; return 13.025;
case "battle_galar_champion": //SWSH Galar Champion Battle case "battle_galar_champion": //SWSH Galar Champion Battle
return 61.635; return 61.635;
case "battle_champion_geeta": //SV Champion Geeta Battle case "battle_champion_geeta": //SV Champion Geeta Battle
return 37.447; return 37.447;
case "battle_champion_nemona": //SV Champion Nemona Battle case "battle_champion_nemona": //SV Champion Nemona Battle
return 14.914; return 14.914;
case "battle_champion_kieran": //SV Champion Kieran Battle case "battle_champion_kieran": //SV Champion Kieran Battle
return 7.206; return 7.206;
case "battle_hoenn_elite": //ORAS Elite Four Battle case "battle_hoenn_elite": //ORAS Elite Four Battle
return 11.350; return 11.350;
case "battle_unova_elite": //BW Elite Four Battle case "battle_unova_elite": //BW Elite Four Battle
return 17.730; return 17.730;
case "battle_kalos_elite": //XY Elite Four Battle case "battle_kalos_elite": //XY Elite Four Battle
return 12.340; return 12.340;
case "battle_alola_elite": //SM Elite Four Battle case "battle_alola_elite": //SM Elite Four Battle
return 19.212; return 19.212;
case "battle_galar_elite": //SWSH League Tournament Battle case "battle_galar_elite": //SWSH League Tournament Battle
return 164.069; return 164.069;
case "battle_paldea_elite": //SV Elite Four Battle case "battle_paldea_elite": //SV Elite Four Battle
return 12.770; return 12.770;
case "battle_bb_elite": //SV BB League Elite Four Battle case "battle_bb_elite": //SV BB League Elite Four Battle
return 19.434; return 19.434;
case "battle_final_encounter": //PMD RTDX Rayquaza's Domain case "battle_final_encounter": //PMD RTDX Rayquaza's Domain
return 19.159; return 19.159;
case "battle_final": //BW Ghetsis Battle case "battle_final": //BW Ghetsis Battle
return 16.453; return 16.453;
case "battle_kanto_gym": //B2W2 Kanto Gym Battle case "battle_kanto_gym": //B2W2 Kanto Gym Battle
return 13.857; return 13.857;
case "battle_johto_gym": //B2W2 Johto Gym Battle case "battle_johto_gym": //B2W2 Johto Gym Battle
return 12.911; return 12.911;
case "battle_hoenn_gym": //B2W2 Hoenn Gym Battle case "battle_hoenn_gym": //B2W2 Hoenn Gym Battle
return 12.379; return 12.379;
case "battle_sinnoh_gym": //B2W2 Sinnoh Gym Battle case "battle_sinnoh_gym": //B2W2 Sinnoh Gym Battle
return 13.122; return 13.122;
case "battle_unova_gym": //BW Unova Gym Battle case "battle_unova_gym": //BW Unova Gym Battle
return 19.145; return 19.145;
case "battle_kalos_gym": //XY Kalos Gym Battle case "battle_kalos_gym": //XY Kalos Gym Battle
return 44.810; return 44.810;
case "battle_galar_gym": //SWSH Galar Gym Battle case "battle_galar_gym": //SWSH Galar Gym Battle
return 171.262; return 171.262;
case "battle_paldea_gym": //SV Paldea Gym Battle case "battle_paldea_gym": //SV Paldea Gym Battle
return 127.489; return 127.489;
case "battle_legendary_kanto": //XY Kanto Legendary Battle case "battle_legendary_kanto": //XY Kanto Legendary Battle
return 32.966; return 32.966;
case "battle_legendary_raikou": //HGSS Raikou Battle case "battle_legendary_raikou": //HGSS Raikou Battle
return 12.632; return 12.632;
case "battle_legendary_entei": //HGSS Entei Battle case "battle_legendary_entei": //HGSS Entei Battle
return 2.905; return 2.905;
case "battle_legendary_suicune": //HGSS Suicune Battle case "battle_legendary_suicune": //HGSS Suicune Battle
return 12.636; return 12.636;
case "battle_legendary_lugia": //HGSS Lugia Battle case "battle_legendary_lugia": //HGSS Lugia Battle
return 19.770; return 19.770;
case "battle_legendary_ho_oh": //HGSS Ho-oh Battle case "battle_legendary_ho_oh": //HGSS Ho-oh Battle
return 17.668; return 17.668;
case "battle_legendary_regis_g5": //B2W2 Legendary Titan Battle case "battle_legendary_regis_g5": //B2W2 Legendary Titan Battle
return 49.500; return 49.500;
case "battle_legendary_regis_g6": //ORAS Legendary Titan Battle case "battle_legendary_regis_g6": //ORAS Legendary Titan Battle
return 21.130; return 21.130;
case "battle_legendary_gro_kyo": //ORAS Groudon & Kyogre Battle case "battle_legendary_gro_kyo": //ORAS Groudon & Kyogre Battle
return 10.547; return 10.547;
case "battle_legendary_rayquaza": //ORAS Rayquaza Battle case "battle_legendary_rayquaza": //ORAS Rayquaza Battle
return 10.495; return 10.495;
case "battle_legendary_deoxys": //ORAS Deoxys Battle case "battle_legendary_deoxys": //ORAS Deoxys Battle
return 13.333; return 13.333;
case "battle_legendary_lake_trio": //ORAS Lake Guardians Battle case "battle_legendary_lake_trio": //ORAS Lake Guardians Battle
return 16.887; return 16.887;
case "battle_legendary_sinnoh": //ORAS Sinnoh Legendary Battle case "battle_legendary_sinnoh": //ORAS Sinnoh Legendary Battle
return 22.770; return 22.770;
case "battle_legendary_dia_pal": //ORAS Dialga & Palkia Battle case "battle_legendary_dia_pal": //ORAS Dialga & Palkia Battle
return 16.009; return 16.009;
case "battle_legendary_origin_forme": //LA Origin Dialga & Palkia Battle case "battle_legendary_origin_forme": //LA Origin Dialga & Palkia Battle
return 18.961; return 18.961;
case "battle_legendary_giratina": //ORAS Giratina Battle case "battle_legendary_giratina": //ORAS Giratina Battle
return 10.451; return 10.451;
case "battle_legendary_arceus": //HGSS Arceus Battle case "battle_legendary_arceus": //HGSS Arceus Battle
return 9.595; return 9.595;
case "battle_legendary_unova": //BW Unova Legendary Battle case "battle_legendary_unova": //BW Unova Legendary Battle
return 13.855; return 13.855;
case "battle_legendary_kyurem": //BW Kyurem Battle case "battle_legendary_kyurem": //BW Kyurem Battle
return 18.314; return 18.314;
case "battle_legendary_res_zek": //BW Reshiram & Zekrom Battle case "battle_legendary_res_zek": //BW Reshiram & Zekrom Battle
return 18.329; return 18.329;
case "battle_legendary_xern_yvel": //XY Xerneas & Yveltal Battle case "battle_legendary_xern_yvel": //XY Xerneas & Yveltal Battle
return 26.468; return 26.468;
case "battle_legendary_tapu": //SM Tapu Battle case "battle_legendary_tapu": //SM Tapu Battle
return 0.000; return 0.000;
case "battle_legendary_sol_lun": //SM Solgaleo & Lunala Battle case "battle_legendary_sol_lun": //SM Solgaleo & Lunala Battle
return 6.525; return 6.525;
case "battle_legendary_ub": //SM Ultra Beast Battle case "battle_legendary_ub": //SM Ultra Beast Battle
return 9.818; return 9.818;
case "battle_legendary_dusk_dawn": //USUM Dusk Mane & Dawn Wings Necrozma Battle case "battle_legendary_dusk_dawn": //USUM Dusk Mane & Dawn Wings Necrozma Battle
return 5.211; return 5.211;
case "battle_legendary_ultra_nec": //USUM Ultra Necrozma Battle case "battle_legendary_ultra_nec": //USUM Ultra Necrozma Battle
return 10.344; return 10.344;
case "battle_legendary_zac_zam": //SWSH Zacian & Zamazenta Battle case "battle_legendary_zac_zam": //SWSH Zacian & Zamazenta Battle
return 11.424; return 11.424;
case "battle_legendary_glas_spec": //SWSH Glastrier & Spectrier Battle case "battle_legendary_glas_spec": //SWSH Glastrier & Spectrier Battle
return 12.503; return 12.503;
case "battle_legendary_calyrex": //SWSH Calyrex Battle case "battle_legendary_calyrex": //SWSH Calyrex Battle
return 50.641; return 50.641;
case "battle_legendary_riders": //SWSH Ice & Shadow Rider Calyrex Battle case "battle_legendary_riders": //SWSH Ice & Shadow Rider Calyrex Battle
return 18.155; return 18.155;
case "battle_legendary_birds_galar": //SWSH Galarian Legendary Birds Battle case "battle_legendary_birds_galar": //SWSH Galarian Legendary Birds Battle
return 0.175; return 0.175;
case "battle_legendary_ruinous": //SV Treasures of Ruin Battle case "battle_legendary_ruinous": //SV Treasures of Ruin Battle
return 6.333; return 6.333;
case "battle_legendary_kor_mir": //SV Depths of Area Zero Battle case "battle_legendary_kor_mir": //SV Depths of Area Zero Battle
return 6.442; return 6.442;
case "battle_legendary_loyal_three": //SV Loyal Three Battle case "battle_legendary_loyal_three": //SV Loyal Three Battle
return 6.500; return 6.500;
case "battle_legendary_ogerpon": //SV Ogerpon Battle case "battle_legendary_ogerpon": //SV Ogerpon Battle
return 14.335; return 14.335;
case "battle_legendary_terapagos": //SV Terapagos Battle case "battle_legendary_terapagos": //SV Terapagos Battle
return 24.377; return 24.377;
case "battle_legendary_pecharunt": //SV Pecharunt Battle case "battle_legendary_pecharunt": //SV Pecharunt Battle
return 6.508; return 6.508;
case "battle_rival": //BW Rival Battle case "battle_rival": //BW Rival Battle
return 14.110; return 14.110;
case "battle_rival_2": //BW N Battle case "battle_rival_2": //BW N Battle
return 17.714; return 17.714;
case "battle_rival_3": //BW Final N Battle case "battle_rival_3": //BW Final N Battle
return 17.586; return 17.586;
case "battle_trainer": //BW Trainer Battle case "battle_trainer": //BW Trainer Battle
return 13.686; return 13.686;
case "battle_wild": //BW Wild Battle case "battle_wild": //BW Wild Battle
return 12.703; return 12.703;
case "battle_wild_strong": //BW Strong Wild Battle case "battle_wild_strong": //BW Strong Wild Battle
return 13.940; return 13.940;
case "end_summit": //PMD RTDX Sky Tower Summit case "end_summit": //PMD RTDX Sky Tower Summit
return 30.025; return 30.025;
case "battle_rocket_grunt": //HGSS Team Rocket Battle case "battle_rocket_grunt": //HGSS Team Rocket Battle
return 12.707; return 12.707;
case "battle_aqua_magma_grunt": //ORAS Team Aqua & Magma Battle case "battle_aqua_magma_grunt": //ORAS Team Aqua & Magma Battle
return 12.062; return 12.062;
case "battle_galactic_grunt": //BDSP Team Galactic Battle case "battle_galactic_grunt": //BDSP Team Galactic Battle
return 13.043; return 13.043;
case "battle_plasma_grunt": //BW Team Plasma Battle case "battle_plasma_grunt": //BW Team Plasma Battle
return 12.974; return 12.974;
case "battle_flare_grunt": //XY Team Flare Battle case "battle_flare_grunt": //XY Team Flare Battle
return 4.228; return 4.228;
case "battle_aether_grunt": // SM Aether Foundation Battle case "battle_aether_grunt": // SM Aether Foundation Battle
return 16.00; return 16.00;
case "battle_skull_grunt": // SM Team Skull Battle case "battle_skull_grunt": // SM Team Skull Battle
return 20.87; return 20.87;
case "battle_macro_grunt": // SWSH Trainer Battle case "battle_macro_grunt": // SWSH Trainer Battle
return 11.56; return 11.56;
case "battle_star_grunt": //SV Team Star Battle case "battle_star_grunt": //SV Team Star Battle
return 133.362; return 133.362;
case "battle_galactic_admin": //BDSP Team Galactic Admin Battle case "battle_galactic_admin": //BDSP Team Galactic Admin Battle
return 11.997; return 11.997;
case "battle_skull_admin": //SM Team Skull Admin Battle case "battle_skull_admin": //SM Team Skull Admin Battle
return 15.463; return 15.463;
case "battle_oleana": //SWSH Oleana Battle case "battle_oleana": //SWSH Oleana Battle
return 14.110; return 14.110;
case "battle_star_admin": //SV Team Star Boss Battle case "battle_star_admin": //SV Team Star Boss Battle
return 9.493; return 9.493;
case "battle_rocket_boss": //USUM Giovanni Battle case "battle_rocket_boss": //USUM Giovanni Battle
return 9.115; return 9.115;
case "battle_aqua_magma_boss": //ORAS Archie & Maxie Battle case "battle_aqua_magma_boss": //ORAS Archie & Maxie Battle
return 14.847; return 14.847;
case "battle_galactic_boss": //BDSP Cyrus Battle case "battle_galactic_boss": //BDSP Cyrus Battle
return 106.962; return 106.962;
case "battle_plasma_boss": //B2W2 Ghetsis Battle case "battle_plasma_boss": //B2W2 Ghetsis Battle
return 25.624; return 25.624;
case "battle_flare_boss": //XY Lysandre Battle case "battle_flare_boss": //XY Lysandre Battle
return 8.085; return 8.085;
case "battle_aether_boss": //SM Lusamine Battle case "battle_aether_boss": //SM Lusamine Battle
return 11.33; return 11.33;
case "battle_skull_boss": //SM Guzma Battle case "battle_skull_boss": //SM Guzma Battle
return 13.13; return 13.13;
case "battle_macro_boss": //SWSH Rose Battle case "battle_macro_boss": //SWSH Rose Battle
return 11.42; return 11.42;
case "battle_star_boss": //SV Cassiopeia Battle case "battle_star_boss": //SV Cassiopeia Battle
return 25.764; return 25.764;
case "mystery_encounter_gen_5_gts": // BW GTS case "mystery_encounter_gen_5_gts": // BW GTS
return 8.52; return 8.52;
case "mystery_encounter_gen_6_gts": // XY GTS case "mystery_encounter_gen_6_gts": // XY GTS
return 9.24; return 9.24;
case "mystery_encounter_fun_and_games": // EoS Guildmaster Wigglytuff case "mystery_encounter_fun_and_games": // EoS Guildmaster Wigglytuff
return 4.78; return 4.78;
case "mystery_encounter_weird_dream": // EoS Temporal Spire case "mystery_encounter_weird_dream": // EoS Temporal Spire
return 41.42; return 41.42;
case "mystery_encounter_delibirdy": // Firel Delibirdy case "mystery_encounter_delibirdy": // Firel Delibirdy
return 82.28; return 82.28;
} }
return 0; return 0;
@ -3177,6 +3177,9 @@ export default class BattleScene extends SceneBase {
let encounter: MysteryEncounter | null; let encounter: MysteryEncounter | null;
if (!isNullOrUndefined(Overrides.MYSTERY_ENCOUNTER_OVERRIDE) && allMysteryEncounters.hasOwnProperty(Overrides.MYSTERY_ENCOUNTER_OVERRIDE)) { if (!isNullOrUndefined(Overrides.MYSTERY_ENCOUNTER_OVERRIDE) && allMysteryEncounters.hasOwnProperty(Overrides.MYSTERY_ENCOUNTER_OVERRIDE)) {
encounter = allMysteryEncounters[Overrides.MYSTERY_ENCOUNTER_OVERRIDE]; encounter = allMysteryEncounters[Overrides.MYSTERY_ENCOUNTER_OVERRIDE];
if (canBypass) {
return encounter;
}
} else if (canBypass) { } else if (canBypass) {
encounter = allMysteryEncounters[encounterType ?? -1]; encounter = allMysteryEncounters[encounterType ?? -1];
return encounter; return encounter;

View File

@ -2579,24 +2579,24 @@ export class PreSwitchOutClearWeatherAbAttr extends PreSwitchOutAbAttr {
// Clear weather only if user's ability matches the weather and no other pokemon has the ability. // Clear weather only if user's ability matches the weather and no other pokemon has the ability.
switch (weatherType) { switch (weatherType) {
case (WeatherType.HARSH_SUN): case (WeatherType.HARSH_SUN):
if (pokemon.hasAbility(Abilities.DESOLATE_LAND) if (pokemon.hasAbility(Abilities.DESOLATE_LAND)
&& pokemon.scene.getField(true).filter(p => p !== pokemon).filter(p => p.hasAbility(Abilities.DESOLATE_LAND)).length === 0) { && pokemon.scene.getField(true).filter(p => p !== pokemon).filter(p => p.hasAbility(Abilities.DESOLATE_LAND)).length === 0) {
turnOffWeather = true; turnOffWeather = true;
} }
break; break;
case (WeatherType.HEAVY_RAIN): case (WeatherType.HEAVY_RAIN):
if (pokemon.hasAbility(Abilities.PRIMORDIAL_SEA) if (pokemon.hasAbility(Abilities.PRIMORDIAL_SEA)
&& pokemon.scene.getField(true).filter(p => p !== pokemon).filter(p => p.hasAbility(Abilities.PRIMORDIAL_SEA)).length === 0) { && pokemon.scene.getField(true).filter(p => p !== pokemon).filter(p => p.hasAbility(Abilities.PRIMORDIAL_SEA)).length === 0) {
turnOffWeather = true; turnOffWeather = true;
} }
break; break;
case (WeatherType.STRONG_WINDS): case (WeatherType.STRONG_WINDS):
if (pokemon.hasAbility(Abilities.DELTA_STREAM) if (pokemon.hasAbility(Abilities.DELTA_STREAM)
&& pokemon.scene.getField(true).filter(p => p !== pokemon).filter(p => p.hasAbility(Abilities.DELTA_STREAM)).length === 0) { && pokemon.scene.getField(true).filter(p => p !== pokemon).filter(p => p.hasAbility(Abilities.DELTA_STREAM)).length === 0) {
turnOffWeather = true; turnOffWeather = true;
} }
break; break;
} }
if (simulated) { if (simulated) {
@ -4079,24 +4079,24 @@ export class PostFaintClearWeatherAbAttr extends PostFaintAbAttr {
// Clear weather only if user's ability matches the weather and no other pokemon has the ability. // Clear weather only if user's ability matches the weather and no other pokemon has the ability.
switch (weatherType) { switch (weatherType) {
case (WeatherType.HARSH_SUN): case (WeatherType.HARSH_SUN):
if (pokemon.hasAbility(Abilities.DESOLATE_LAND) if (pokemon.hasAbility(Abilities.DESOLATE_LAND)
&& pokemon.scene.getField(true).filter(p => p.hasAbility(Abilities.DESOLATE_LAND)).length === 0) { && pokemon.scene.getField(true).filter(p => p.hasAbility(Abilities.DESOLATE_LAND)).length === 0) {
turnOffWeather = true; turnOffWeather = true;
} }
break; break;
case (WeatherType.HEAVY_RAIN): case (WeatherType.HEAVY_RAIN):
if (pokemon.hasAbility(Abilities.PRIMORDIAL_SEA) if (pokemon.hasAbility(Abilities.PRIMORDIAL_SEA)
&& pokemon.scene.getField(true).filter(p => p.hasAbility(Abilities.PRIMORDIAL_SEA)).length === 0) { && pokemon.scene.getField(true).filter(p => p.hasAbility(Abilities.PRIMORDIAL_SEA)).length === 0) {
turnOffWeather = true; turnOffWeather = true;
} }
break; break;
case (WeatherType.STRONG_WINDS): case (WeatherType.STRONG_WINDS):
if (pokemon.hasAbility(Abilities.DELTA_STREAM) if (pokemon.hasAbility(Abilities.DELTA_STREAM)
&& pokemon.scene.getField(true).filter(p => p.hasAbility(Abilities.DELTA_STREAM)).length === 0) { && pokemon.scene.getField(true).filter(p => p.hasAbility(Abilities.DELTA_STREAM)).length === 0) {
turnOffWeather = true; turnOffWeather = true;
} }
break; break;
} }
if (simulated) { if (simulated) {
@ -4913,8 +4913,7 @@ export function initAbilities() {
.attr(TypeImmunityAddBattlerTagAbAttr, Type.FIRE, BattlerTagType.FIRE_BOOST, 1) .attr(TypeImmunityAddBattlerTagAbAttr, Type.FIRE, BattlerTagType.FIRE_BOOST, 1)
.ignorable(), .ignorable(),
new Ability(Abilities.SHIELD_DUST, 3) new Ability(Abilities.SHIELD_DUST, 3)
.attr(IgnoreMoveEffectsAbAttr) .attr(IgnoreMoveEffectsAbAttr),
.edgeCase(), // Does not work with secret power (unimplemented)
new Ability(Abilities.OWN_TEMPO, 3) new Ability(Abilities.OWN_TEMPO, 3)
.attr(BattlerTagImmunityAbAttr, BattlerTagType.CONFUSED) .attr(BattlerTagImmunityAbAttr, BattlerTagType.CONFUSED)
.attr(IntimidateImmunityAbAttr) .attr(IntimidateImmunityAbAttr)
@ -4958,8 +4957,7 @@ export function initAbilities() {
.attr(TypeImmunityStatStageChangeAbAttr, Type.ELECTRIC, Stat.SPATK, 1) .attr(TypeImmunityStatStageChangeAbAttr, Type.ELECTRIC, Stat.SPATK, 1)
.ignorable(), .ignorable(),
new Ability(Abilities.SERENE_GRACE, 3) new Ability(Abilities.SERENE_GRACE, 3)
.attr(MoveEffectChanceMultiplierAbAttr, 2) .attr(MoveEffectChanceMultiplierAbAttr, 2),
.edgeCase(), // does not work with secret power (unimplemented)
new Ability(Abilities.SWIFT_SWIM, 3) new Ability(Abilities.SWIFT_SWIM, 3)
.attr(StatMultiplierAbAttr, Stat.SPD, 2) .attr(StatMultiplierAbAttr, Stat.SPD, 2)
.condition(getWeatherCondition(WeatherType.RAIN, WeatherType.HEAVY_RAIN)), .condition(getWeatherCondition(WeatherType.RAIN, WeatherType.HEAVY_RAIN)),

View File

@ -88,13 +88,13 @@ export abstract class ArenaTag {
*/ */
public getAffectedPokemon(scene: BattleScene): Pokemon[] { public getAffectedPokemon(scene: BattleScene): Pokemon[] {
switch (this.side) { switch (this.side) {
case ArenaTagSide.PLAYER: case ArenaTagSide.PLAYER:
return scene.getPlayerField() ?? []; return scene.getPlayerField() ?? [];
case ArenaTagSide.ENEMY: case ArenaTagSide.ENEMY:
return scene.getEnemyField() ?? []; return scene.getEnemyField() ?? [];
case ArenaTagSide.BOTH: case ArenaTagSide.BOTH:
default: default:
return scene.getField(true) ?? []; return scene.getField(true) ?? [];
} }
} }
} }
@ -332,11 +332,11 @@ const WideGuardConditionFunc: ProtectConditionFunc = (arena, moveId) : boolean =
const move = allMoves[moveId]; const move = allMoves[moveId];
switch (move.moveTarget) { switch (move.moveTarget) {
case MoveTarget.ALL_ENEMIES: case MoveTarget.ALL_ENEMIES:
case MoveTarget.ALL_NEAR_ENEMIES: case MoveTarget.ALL_NEAR_ENEMIES:
case MoveTarget.ALL_OTHERS: case MoveTarget.ALL_OTHERS:
case MoveTarget.ALL_NEAR_OTHERS: case MoveTarget.ALL_NEAR_OTHERS:
return true; return true;
} }
return false; return false;
}; };
@ -807,24 +807,24 @@ class StealthRockTag extends ArenaTrapTag {
let damageHpRatio: number = 0; let damageHpRatio: number = 0;
switch (effectiveness) { switch (effectiveness) {
case 0: case 0:
damageHpRatio = 0; damageHpRatio = 0;
break; break;
case 0.25: case 0.25:
damageHpRatio = 0.03125; damageHpRatio = 0.03125;
break; break;
case 0.5: case 0.5:
damageHpRatio = 0.0625; damageHpRatio = 0.0625;
break; break;
case 1: case 1:
damageHpRatio = 0.125; damageHpRatio = 0.125;
break; break;
case 2: case 2:
damageHpRatio = 0.25; damageHpRatio = 0.25;
break; break;
case 4: case 4:
damageHpRatio = 0.5; damageHpRatio = 0.5;
break; break;
} }
return damageHpRatio; return damageHpRatio;
@ -1188,63 +1188,63 @@ class GrassWaterPledgeTag extends ArenaTag {
// TODO: swap `sourceMove` and `sourceId` and make `sourceMove` an optional parameter // TODO: swap `sourceMove` and `sourceId` and make `sourceMove` an optional parameter
export function getArenaTag(tagType: ArenaTagType, turnCount: number, sourceMove: Moves | undefined, sourceId: number, targetIndex?: BattlerIndex, side: ArenaTagSide = ArenaTagSide.BOTH): ArenaTag | null { export function getArenaTag(tagType: ArenaTagType, turnCount: number, sourceMove: Moves | undefined, sourceId: number, targetIndex?: BattlerIndex, side: ArenaTagSide = ArenaTagSide.BOTH): ArenaTag | null {
switch (tagType) { switch (tagType) {
case ArenaTagType.MIST: case ArenaTagType.MIST:
return new MistTag(turnCount, sourceId, side); return new MistTag(turnCount, sourceId, side);
case ArenaTagType.QUICK_GUARD: case ArenaTagType.QUICK_GUARD:
return new QuickGuardTag(sourceId, side); return new QuickGuardTag(sourceId, side);
case ArenaTagType.WIDE_GUARD: case ArenaTagType.WIDE_GUARD:
return new WideGuardTag(sourceId, side); return new WideGuardTag(sourceId, side);
case ArenaTagType.MAT_BLOCK: case ArenaTagType.MAT_BLOCK:
return new MatBlockTag(sourceId, side); return new MatBlockTag(sourceId, side);
case ArenaTagType.CRAFTY_SHIELD: case ArenaTagType.CRAFTY_SHIELD:
return new CraftyShieldTag(sourceId, side); return new CraftyShieldTag(sourceId, side);
case ArenaTagType.NO_CRIT: case ArenaTagType.NO_CRIT:
return new NoCritTag(turnCount, sourceMove!, sourceId, side); // TODO: is this bang correct? return new NoCritTag(turnCount, sourceMove!, sourceId, side); // TODO: is this bang correct?
case ArenaTagType.MUD_SPORT: case ArenaTagType.MUD_SPORT:
return new MudSportTag(turnCount, sourceId); return new MudSportTag(turnCount, sourceId);
case ArenaTagType.WATER_SPORT: case ArenaTagType.WATER_SPORT:
return new WaterSportTag(turnCount, sourceId); return new WaterSportTag(turnCount, sourceId);
case ArenaTagType.ION_DELUGE: case ArenaTagType.ION_DELUGE:
return new IonDelugeTag(sourceMove); return new IonDelugeTag(sourceMove);
case ArenaTagType.SPIKES: case ArenaTagType.SPIKES:
return new SpikesTag(sourceId, side); return new SpikesTag(sourceId, side);
case ArenaTagType.TOXIC_SPIKES: case ArenaTagType.TOXIC_SPIKES:
return new ToxicSpikesTag(sourceId, side); return new ToxicSpikesTag(sourceId, side);
case ArenaTagType.FUTURE_SIGHT: case ArenaTagType.FUTURE_SIGHT:
case ArenaTagType.DOOM_DESIRE: case ArenaTagType.DOOM_DESIRE:
return new DelayedAttackTag(tagType, sourceMove, sourceId, targetIndex!); // TODO:questionable bang return new DelayedAttackTag(tagType, sourceMove, sourceId, targetIndex!); // TODO:questionable bang
case ArenaTagType.WISH: case ArenaTagType.WISH:
return new WishTag(turnCount, sourceId, side); return new WishTag(turnCount, sourceId, side);
case ArenaTagType.STEALTH_ROCK: case ArenaTagType.STEALTH_ROCK:
return new StealthRockTag(sourceId, side); return new StealthRockTag(sourceId, side);
case ArenaTagType.STICKY_WEB: case ArenaTagType.STICKY_WEB:
return new StickyWebTag(sourceId, side); return new StickyWebTag(sourceId, side);
case ArenaTagType.TRICK_ROOM: case ArenaTagType.TRICK_ROOM:
return new TrickRoomTag(turnCount, sourceId); return new TrickRoomTag(turnCount, sourceId);
case ArenaTagType.GRAVITY: case ArenaTagType.GRAVITY:
return new GravityTag(turnCount); return new GravityTag(turnCount);
case ArenaTagType.REFLECT: case ArenaTagType.REFLECT:
return new ReflectTag(turnCount, sourceId, side); return new ReflectTag(turnCount, sourceId, side);
case ArenaTagType.LIGHT_SCREEN: case ArenaTagType.LIGHT_SCREEN:
return new LightScreenTag(turnCount, sourceId, side); return new LightScreenTag(turnCount, sourceId, side);
case ArenaTagType.AURORA_VEIL: case ArenaTagType.AURORA_VEIL:
return new AuroraVeilTag(turnCount, sourceId, side); return new AuroraVeilTag(turnCount, sourceId, side);
case ArenaTagType.TAILWIND: case ArenaTagType.TAILWIND:
return new TailwindTag(turnCount, sourceId, side); return new TailwindTag(turnCount, sourceId, side);
case ArenaTagType.HAPPY_HOUR: case ArenaTagType.HAPPY_HOUR:
return new HappyHourTag(turnCount, sourceId, side); return new HappyHourTag(turnCount, sourceId, side);
case ArenaTagType.SAFEGUARD: case ArenaTagType.SAFEGUARD:
return new SafeguardTag(turnCount, sourceId, side); return new SafeguardTag(turnCount, sourceId, side);
case ArenaTagType.IMPRISON: case ArenaTagType.IMPRISON:
return new ImprisonTag(sourceId, side); return new ImprisonTag(sourceId, side);
case ArenaTagType.FIRE_GRASS_PLEDGE: case ArenaTagType.FIRE_GRASS_PLEDGE:
return new FireGrassPledgeTag(sourceId, side); return new FireGrassPledgeTag(sourceId, side);
case ArenaTagType.WATER_FIRE_PLEDGE: case ArenaTagType.WATER_FIRE_PLEDGE:
return new WaterFirePledgeTag(sourceId, side); return new WaterFirePledgeTag(sourceId, side);
case ArenaTagType.GRASS_WATER_PLEDGE: case ArenaTagType.GRASS_WATER_PLEDGE:
return new GrassWaterPledgeTag(sourceId, side); return new GrassWaterPledgeTag(sourceId, side);
default: default:
return null; return null;
} }
} }

View File

@ -13,14 +13,14 @@ export function getBiomeName(biome: Biome | -1) {
return i18next.t("biome:unknownLocation"); return i18next.t("biome:unknownLocation");
} }
switch (biome) { switch (biome) {
case Biome.GRASS: case Biome.GRASS:
return i18next.t("biome:GRASS"); return i18next.t("biome:GRASS");
case Biome.RUINS: case Biome.RUINS:
return i18next.t("biome:RUINS"); return i18next.t("biome:RUINS");
case Biome.END: case Biome.END:
return i18next.t("biome:END"); return i18next.t("biome:END");
default: default:
return i18next.t(`biome:${Biome[biome].toUpperCase()}`); return i18next.t(`biome:${Biome[biome].toUpperCase()}`);
} }
} }

View File

@ -15,25 +15,25 @@ export const FRIENDSHIP_LOSS_FROM_FAINT = 10;
*/ */
export function getStarterValueFriendshipCap(starterCost: number): number { export function getStarterValueFriendshipCap(starterCost: number): number {
switch (starterCost) { switch (starterCost) {
case 1: case 1:
return 20; return 20;
case 2: case 2:
return 40; return 40;
case 3: case 3:
return 60; return 60;
case 4: case 4:
return 100; return 100;
case 5: case 5:
return 140; return 140;
case 6: case 6:
return 200; return 200;
case 7: case 7:
return 280; return 280;
case 8: case 8:
case 9: case 9:
return 450; return 450;
default: default:
return 600; return 600;
} }
} }

View File

@ -134,15 +134,15 @@ export class AnimConfig {
for (const te of frameTimedEvents[fte]) { for (const te of frameTimedEvents[fte]) {
let timedEvent: AnimTimedEvent | undefined; let timedEvent: AnimTimedEvent | undefined;
switch (te.eventType) { switch (te.eventType) {
case "AnimTimedSoundEvent": case "AnimTimedSoundEvent":
timedEvent = new AnimTimedSoundEvent(te.frameIndex, te.resourceName, te); timedEvent = new AnimTimedSoundEvent(te.frameIndex, te.resourceName, te);
break; break;
case "AnimTimedAddBgEvent": case "AnimTimedAddBgEvent":
timedEvent = new AnimTimedAddBgEvent(te.frameIndex, te.resourceName, te); timedEvent = new AnimTimedAddBgEvent(te.frameIndex, te.resourceName, te);
break; break;
case "AnimTimedUpdateBgEvent": case "AnimTimedUpdateBgEvent":
timedEvent = new AnimTimedUpdateBgEvent(te.frameIndex, te.resourceName, te); timedEvent = new AnimTimedUpdateBgEvent(te.frameIndex, te.resourceName, te);
break; break;
} }
timedEvent && timedEvents.push(timedEvent); timedEvent && timedEvents.push(timedEvent);
@ -243,12 +243,12 @@ class AnimFrame {
if (!init) { if (!init) {
let target = AnimFrameTarget.GRAPHIC; let target = AnimFrameTarget.GRAPHIC;
switch (pattern) { switch (pattern) {
case -2: case -2:
target = AnimFrameTarget.TARGET; target = AnimFrameTarget.TARGET;
break; break;
case -1: case -1:
target = AnimFrameTarget.USER; target = AnimFrameTarget.USER;
break; break;
} }
this.target = target; this.target = target;
this.graphicFrame = pattern >= 0 ? pattern : 0; this.graphicFrame = pattern >= 0 ? pattern : 0;
@ -808,23 +808,23 @@ export abstract class BattleAnim {
let scaleX = (frame.zoomX / 100) * (!frame.mirror ? 1 : -1); let scaleX = (frame.zoomX / 100) * (!frame.mirror ? 1 : -1);
const scaleY = (frame.zoomY / 100); const scaleY = (frame.zoomY / 100);
switch (frame.focus) { switch (frame.focus) {
case AnimFocus.TARGET: case AnimFocus.TARGET:
x += targetInitialX - targetFocusX; x += targetInitialX - targetFocusX;
y += (targetInitialY - targetHalfHeight) - targetFocusY; y += (targetInitialY - targetHalfHeight) - targetFocusY;
break; break;
case AnimFocus.USER: case AnimFocus.USER:
x += userInitialX - userFocusX; x += userInitialX - userFocusX;
y += (userInitialY - userHalfHeight) - userFocusY; y += (userInitialY - userHalfHeight) - userFocusY;
break; break;
case AnimFocus.USER_TARGET: case AnimFocus.USER_TARGET:
const point = transformPoint(this.srcLine[0], this.srcLine[1], this.srcLine[2], this.srcLine[3], const point = transformPoint(this.srcLine[0], this.srcLine[1], this.srcLine[2], this.srcLine[3],
this.dstLine[0], this.dstLine[1] - userHalfHeight, this.dstLine[2], this.dstLine[3] - targetHalfHeight, x, y); this.dstLine[0], this.dstLine[1] - userHalfHeight, this.dstLine[2], this.dstLine[3] - targetHalfHeight, x, y);
x = point[0]; x = point[0];
y = point[1]; y = point[1];
if (frame.target === AnimFrameTarget.GRAPHIC && isReversed(this.srcLine[0], this.srcLine[2], this.dstLine[0], this.dstLine[2])) { if (frame.target === AnimFrameTarget.GRAPHIC && isReversed(this.srcLine[0], this.srcLine[2], this.dstLine[0], this.dstLine[2])) {
scaleX = scaleX * -1; scaleX = scaleX * -1;
} }
break; break;
} }
const angle = -frame.angle; const angle = -frame.angle;
const key = frame.target === AnimFrameTarget.GRAPHIC ? g++ : frame.target === AnimFrameTarget.USER ? u++ : t++; const key = frame.target === AnimFrameTarget.GRAPHIC ? g++ : frame.target === AnimFrameTarget.USER ? u++ : t++;
@ -998,44 +998,44 @@ export abstract class BattleAnim {
spritePriorities[graphicIndex] = frame.priority; spritePriorities[graphicIndex] = frame.priority;
const setSpritePriority = (priority: integer) => { const setSpritePriority = (priority: integer) => {
switch (priority) { switch (priority) {
case 0: case 0:
scene.field.moveBelow(moveSprite as Phaser.GameObjects.GameObject, scene.getNonSwitchedEnemyPokemon() || scene.getNonSwitchedPlayerPokemon()!); // This bang assumes that if (the EnemyPokemon is undefined, then the PlayerPokemon function must return an object), correct assumption? scene.field.moveBelow(moveSprite as Phaser.GameObjects.GameObject, scene.getNonSwitchedEnemyPokemon() || scene.getNonSwitchedPlayerPokemon()!); // This bang assumes that if (the EnemyPokemon is undefined, then the PlayerPokemon function must return an object), correct assumption?
break; break;
case 1: case 1:
scene.field.moveTo(moveSprite, scene.field.getAll().length - 1); scene.field.moveTo(moveSprite, scene.field.getAll().length - 1);
break; break;
case 2: case 2:
switch (frame.focus) { switch (frame.focus) {
case AnimFocus.USER: case AnimFocus.USER:
if (this.bgSprite) { if (this.bgSprite) {
scene.field.moveAbove(moveSprite as Phaser.GameObjects.GameObject, this.bgSprite); scene.field.moveAbove(moveSprite as Phaser.GameObjects.GameObject, this.bgSprite);
} else { } else {
scene.field.moveBelow(moveSprite as Phaser.GameObjects.GameObject, this.user!); // TODO: is this bang correct? scene.field.moveBelow(moveSprite as Phaser.GameObjects.GameObject, this.user!); // TODO: is this bang correct?
}
break;
case AnimFocus.TARGET:
scene.field.moveBelow(moveSprite as Phaser.GameObjects.GameObject, this.target!); // TODO: is this bang correct?
break;
default:
setSpritePriority(1);
break;
} }
break; break;
case AnimFocus.TARGET: case 3:
scene.field.moveBelow(moveSprite as Phaser.GameObjects.GameObject, this.target!); // TODO: is this bang correct? switch (frame.focus) {
case AnimFocus.USER:
scene.field.moveAbove(moveSprite as Phaser.GameObjects.GameObject, this.user!); // TODO: is this bang correct?
break;
case AnimFocus.TARGET:
scene.field.moveAbove(moveSprite as Phaser.GameObjects.GameObject, this.target!); // TODO: is this bang correct?
break;
default:
setSpritePriority(1);
break;
}
break; break;
default: default:
setSpritePriority(1); setSpritePriority(1);
break;
}
break;
case 3:
switch (frame.focus) {
case AnimFocus.USER:
scene.field.moveAbove(moveSprite as Phaser.GameObjects.GameObject, this.user!); // TODO: is this bang correct?
break;
case AnimFocus.TARGET:
scene.field.moveAbove(moveSprite as Phaser.GameObjects.GameObject, this.target!); // TODO: is this bang correct?
break;
default:
setSpritePriority(1);
break;
}
break;
default:
setSpritePriority(1);
} }
}; };
setSpritePriority(frame.priority); setSpritePriority(frame.priority);
@ -1401,108 +1401,108 @@ export async function populateAnims() {
const fieldName = field.slice(0, field.indexOf(":")); const fieldName = field.slice(0, field.indexOf(":"));
const fieldData = field.slice(fieldName.length + 1, field.lastIndexOf("\n")).trim(); const fieldData = field.slice(fieldName.length + 1, field.lastIndexOf("\n")).trim();
switch (fieldName) { switch (fieldName) {
case "array": case "array":
const framesData = fieldData.split(" - - - ").slice(1); const framesData = fieldData.split(" - - - ").slice(1);
for (let fd = 0; fd < framesData.length; fd++) { for (let fd = 0; fd < framesData.length; fd++) {
anim.frames.push([]); anim.frames.push([]);
const frameData = framesData[fd]; const frameData = framesData[fd];
const focusFramesData = frameData.split(" - - "); const focusFramesData = frameData.split(" - - ");
for (let tf = 0; tf < focusFramesData.length; tf++) { for (let tf = 0; tf < focusFramesData.length; tf++) {
const values = focusFramesData[tf].replace(/ \- /g, "").split("\n"); const values = focusFramesData[tf].replace(/ \- /g, "").split("\n");
const targetFrame = new AnimFrame(parseFloat(values[0]), parseFloat(values[1]), parseFloat(values[2]), parseFloat(values[11]), parseFloat(values[3]), const targetFrame = new AnimFrame(parseFloat(values[0]), parseFloat(values[1]), parseFloat(values[2]), parseFloat(values[11]), parseFloat(values[3]),
parseInt(values[4]) === 1, parseInt(values[6]) === 1, parseInt(values[5]), parseInt(values[7]), parseInt(values[8]), parseInt(values[12]), parseInt(values[13]), parseInt(values[4]) === 1, parseInt(values[6]) === 1, parseInt(values[5]), parseInt(values[7]), parseInt(values[8]), parseInt(values[12]), parseInt(values[13]),
parseInt(values[14]), parseInt(values[15]), parseInt(values[16]), parseInt(values[17]), parseInt(values[18]), parseInt(values[19]), parseInt(values[14]), parseInt(values[15]), parseInt(values[16]), parseInt(values[17]), parseInt(values[18]), parseInt(values[19]),
parseInt(values[21]), parseInt(values[22]), parseInt(values[23]), parseInt(values[24]), parseInt(values[20]) === 1, parseInt(values[25]), parseInt(values[26]) as AnimFocus); parseInt(values[21]), parseInt(values[22]), parseInt(values[23]), parseInt(values[24]), parseInt(values[20]) === 1, parseInt(values[25]), parseInt(values[26]) as AnimFocus);
anim.frames[fd].push(targetFrame); anim.frames[fd].push(targetFrame);
}
} }
} break;
break; case "graphic":
case "graphic": const graphic = fieldData !== "''" ? fieldData : "";
const graphic = fieldData !== "''" ? fieldData : ""; anim.graphic = graphic.indexOf(".") > -1
anim.graphic = graphic.indexOf(".") > -1 ? graphic.slice(0, fieldData.indexOf("."))
? graphic.slice(0, fieldData.indexOf(".")) : graphic;
: graphic; break;
break; case "timing":
case "timing": const timingEntries = fieldData.split("- !ruby/object:PBAnimTiming ").slice(1);
const timingEntries = fieldData.split("- !ruby/object:PBAnimTiming ").slice(1); for (let t = 0; t < timingEntries.length; t++) {
for (let t = 0; t < timingEntries.length; t++) { const timingData = timingEntries[t].replace(/\n/g, " ").replace(/[ ]{2,}/g, " ").replace(/[a-z]+: ! '', /ig, "").replace(/name: (.*?),/, "name: \"$1\",")
const timingData = timingEntries[t].replace(/\n/g, " ").replace(/[ ]{2,}/g, " ").replace(/[a-z]+: ! '', /ig, "").replace(/name: (.*?),/, "name: \"$1\",") .replace(/flashColor: !ruby\/object:Color { alpha: ([\d\.]+), blue: ([\d\.]+), green: ([\d\.]+), red: ([\d\.]+)}/, "flashRed: $4, flashGreen: $3, flashBlue: $2, flashAlpha: $1");
.replace(/flashColor: !ruby\/object:Color { alpha: ([\d\.]+), blue: ([\d\.]+), green: ([\d\.]+), red: ([\d\.]+)}/, "flashRed: $4, flashGreen: $3, flashBlue: $2, flashAlpha: $1"); const frameIndex = parseInt(/frame: (\d+)/.exec(timingData)![1]); // TODO: is the bang correct?
const frameIndex = parseInt(/frame: (\d+)/.exec(timingData)![1]); // TODO: is the bang correct? let resourceName = /name: "(.*?)"/.exec(timingData)![1].replace("''", ""); // TODO: is the bang correct?
let resourceName = /name: "(.*?)"/.exec(timingData)![1].replace("''", ""); // TODO: is the bang correct? const timingType = parseInt(/timingType: (\d)/.exec(timingData)![1]); // TODO: is the bang correct?
const timingType = parseInt(/timingType: (\d)/.exec(timingData)![1]); // TODO: is the bang correct? let timedEvent: AnimTimedEvent | undefined;
let timedEvent: AnimTimedEvent | undefined; switch (timingType) {
switch (timingType) { case 0:
case 0: if (resourceName && resourceName.indexOf(".") === -1) {
if (resourceName && resourceName.indexOf(".") === -1) { let ext: string | undefined;
let ext: string | undefined; [ "wav", "mp3", "m4a" ].every(e => {
[ "wav", "mp3", "m4a" ].every(e => { if (seNames.indexOf(`${resourceName}.${e}`) > -1) {
if (seNames.indexOf(`${resourceName}.${e}`) > -1) { ext = e;
ext = e; return false;
return false; }
return true;
});
if (!ext) {
ext = ".wav";
}
resourceName += `.${ext}`;
} }
return true; timedEvent = new AnimTimedSoundEvent(frameIndex, resourceName);
}); break;
if (!ext) { case 1:
ext = ".wav"; timedEvent = new AnimTimedAddBgEvent(frameIndex, resourceName.slice(0, resourceName.indexOf(".")));
break;
case 2:
timedEvent = new AnimTimedUpdateBgEvent(frameIndex, resourceName.slice(0, resourceName.indexOf(".")));
break;
}
if (!timedEvent) {
continue;
}
const propPattern = /([a-z]+): (.*?)(?:,|\})/ig;
let propMatch: RegExpExecArray;
while ((propMatch = propPattern.exec(timingData)!)) { // TODO: is this bang correct?
const prop = propMatch[1];
let value: any = propMatch[2];
switch (prop) {
case "bgX":
case "bgY":
value = parseFloat(value);
break;
case "volume":
case "pitch":
case "opacity":
case "colorRed":
case "colorGreen":
case "colorBlue":
case "colorAlpha":
case "duration":
case "flashScope":
case "flashRed":
case "flashGreen":
case "flashBlue":
case "flashAlpha":
case "flashDuration":
value = parseInt(value);
break;
}
if (timedEvent.hasOwnProperty(prop)) {
timedEvent[prop] = value;
} }
resourceName += `.${ext}`;
} }
timedEvent = new AnimTimedSoundEvent(frameIndex, resourceName); if (!anim.frameTimedEvents.has(frameIndex)) {
break; anim.frameTimedEvents.set(frameIndex, []);
case 1:
timedEvent = new AnimTimedAddBgEvent(frameIndex, resourceName.slice(0, resourceName.indexOf(".")));
break;
case 2:
timedEvent = new AnimTimedUpdateBgEvent(frameIndex, resourceName.slice(0, resourceName.indexOf(".")));
break;
}
if (!timedEvent) {
continue;
}
const propPattern = /([a-z]+): (.*?)(?:,|\})/ig;
let propMatch: RegExpExecArray;
while ((propMatch = propPattern.exec(timingData)!)) { // TODO: is this bang correct?
const prop = propMatch[1];
let value: any = propMatch[2];
switch (prop) {
case "bgX":
case "bgY":
value = parseFloat(value);
break;
case "volume":
case "pitch":
case "opacity":
case "colorRed":
case "colorGreen":
case "colorBlue":
case "colorAlpha":
case "duration":
case "flashScope":
case "flashRed":
case "flashGreen":
case "flashBlue":
case "flashAlpha":
case "flashDuration":
value = parseInt(value);
break;
} }
if (timedEvent.hasOwnProperty(prop)) {
timedEvent[prop] = value;
}
}
if (!anim.frameTimedEvents.has(frameIndex)) {
anim.frameTimedEvents.set(frameIndex, []);
}
anim.frameTimedEvents.get(frameIndex)!.push(timedEvent); // TODO: is this bang correct? anim.frameTimedEvents.get(frameIndex)!.push(timedEvent); // TODO: is this bang correct?
} }
break; break;
case "position": case "position":
anim.position = parseInt(fieldData); anim.position = parseInt(fieldData);
break; break;
case "hue": case "hue":
anim.hue = parseInt(fieldData); anim.hue = parseInt(fieldData);
break; break;
} }
} }
} }

View File

@ -919,14 +919,14 @@ export class EncoreTag extends BattlerTag {
} }
switch (repeatableMove.move) { switch (repeatableMove.move) {
case Moves.MIMIC: case Moves.MIMIC:
case Moves.MIRROR_MOVE: case Moves.MIRROR_MOVE:
case Moves.TRANSFORM: case Moves.TRANSFORM:
case Moves.STRUGGLE: case Moves.STRUGGLE:
case Moves.SKETCH: case Moves.SKETCH:
case Moves.SLEEP_TALK: case Moves.SLEEP_TALK:
case Moves.ENCORE: case Moves.ENCORE:
return false; return false;
} }
this.moveId = repeatableMove.move; this.moveId = repeatableMove.move;
@ -1637,12 +1637,12 @@ export class HighestStatBoostTag extends AbilityBattlerTag {
this.stat = highestStat; this.stat = highestStat;
switch (this.stat) { switch (this.stat) {
case Stat.SPD: case Stat.SPD:
this.multiplier = 1.5; this.multiplier = 1.5;
break; break;
default: default:
this.multiplier = 1.3; this.multiplier = 1.3;
break; break;
} }
pokemon.scene.queueMessage(i18next.t("battlerTags:highestStatBoostOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), statName: i18next.t(getStatKey(highestStat)) }), null, false, null, true); pokemon.scene.queueMessage(i18next.t("battlerTags:highestStatBoostOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), statName: i18next.t(getStatKey(highestStat)) }), null, false, null, true);
@ -2432,15 +2432,15 @@ export class SubstituteTag extends BattlerTag {
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
switch (lapseType) { switch (lapseType) {
case BattlerTagLapseType.PRE_MOVE: case BattlerTagLapseType.PRE_MOVE:
this.onPreMove(pokemon); this.onPreMove(pokemon);
break; break;
case BattlerTagLapseType.AFTER_MOVE: case BattlerTagLapseType.AFTER_MOVE:
this.onAfterMove(pokemon); this.onAfterMove(pokemon);
break; break;
case BattlerTagLapseType.HIT: case BattlerTagLapseType.HIT:
this.onHit(pokemon); this.onHit(pokemon);
break; break;
} }
return lapseType !== BattlerTagLapseType.CUSTOM; // only remove this tag on custom lapse return lapseType !== BattlerTagLapseType.CUSTOM; // only remove this tag on custom lapse
} }
@ -2765,179 +2765,179 @@ export class PowerTrickTag extends BattlerTag {
*/ */
export function getBattlerTag(tagType: BattlerTagType, turnCount: number, sourceMove: Moves, sourceId: number): BattlerTag { export function getBattlerTag(tagType: BattlerTagType, turnCount: number, sourceMove: Moves, sourceId: number): BattlerTag {
switch (tagType) { switch (tagType) {
case BattlerTagType.RECHARGING: case BattlerTagType.RECHARGING:
return new RechargingTag(sourceMove); return new RechargingTag(sourceMove);
case BattlerTagType.BEAK_BLAST_CHARGING: case BattlerTagType.BEAK_BLAST_CHARGING:
return new BeakBlastChargingTag(); return new BeakBlastChargingTag();
case BattlerTagType.SHELL_TRAP: case BattlerTagType.SHELL_TRAP:
return new ShellTrapTag(); return new ShellTrapTag();
case BattlerTagType.FLINCHED: case BattlerTagType.FLINCHED:
return new FlinchedTag(sourceMove); return new FlinchedTag(sourceMove);
case BattlerTagType.INTERRUPTED: case BattlerTagType.INTERRUPTED:
return new InterruptedTag(sourceMove); return new InterruptedTag(sourceMove);
case BattlerTagType.CONFUSED: case BattlerTagType.CONFUSED:
return new ConfusedTag(turnCount, sourceMove); return new ConfusedTag(turnCount, sourceMove);
case BattlerTagType.INFATUATED: case BattlerTagType.INFATUATED:
return new InfatuatedTag(sourceMove, sourceId); return new InfatuatedTag(sourceMove, sourceId);
case BattlerTagType.SEEDED: case BattlerTagType.SEEDED:
return new SeedTag(sourceId); return new SeedTag(sourceId);
case BattlerTagType.NIGHTMARE: case BattlerTagType.NIGHTMARE:
return new NightmareTag(); return new NightmareTag();
case BattlerTagType.FRENZY: case BattlerTagType.FRENZY:
return new FrenzyTag(turnCount, sourceMove, sourceId); return new FrenzyTag(turnCount, sourceMove, sourceId);
case BattlerTagType.CHARGING: case BattlerTagType.CHARGING:
return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, 1, sourceMove, sourceId); return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, 1, sourceMove, sourceId);
case BattlerTagType.ENCORE: case BattlerTagType.ENCORE:
return new EncoreTag(sourceId); return new EncoreTag(sourceId);
case BattlerTagType.HELPING_HAND: case BattlerTagType.HELPING_HAND:
return new HelpingHandTag(sourceId); return new HelpingHandTag(sourceId);
case BattlerTagType.INGRAIN: case BattlerTagType.INGRAIN:
return new IngrainTag(sourceId); return new IngrainTag(sourceId);
case BattlerTagType.AQUA_RING: case BattlerTagType.AQUA_RING:
return new AquaRingTag(); return new AquaRingTag();
case BattlerTagType.DROWSY: case BattlerTagType.DROWSY:
return new DrowsyTag(); return new DrowsyTag();
case BattlerTagType.TRAPPED: case BattlerTagType.TRAPPED:
return new TrappedTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId); return new TrappedTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId);
case BattlerTagType.NO_RETREAT: case BattlerTagType.NO_RETREAT:
return new NoRetreatTag(sourceId); return new NoRetreatTag(sourceId);
case BattlerTagType.BIND: case BattlerTagType.BIND:
return new BindTag(turnCount, sourceId); return new BindTag(turnCount, sourceId);
case BattlerTagType.WRAP: case BattlerTagType.WRAP:
return new WrapTag(turnCount, sourceId); return new WrapTag(turnCount, sourceId);
case BattlerTagType.FIRE_SPIN: case BattlerTagType.FIRE_SPIN:
return new FireSpinTag(turnCount, sourceId); return new FireSpinTag(turnCount, sourceId);
case BattlerTagType.WHIRLPOOL: case BattlerTagType.WHIRLPOOL:
return new WhirlpoolTag(turnCount, sourceId); return new WhirlpoolTag(turnCount, sourceId);
case BattlerTagType.CLAMP: case BattlerTagType.CLAMP:
return new ClampTag(turnCount, sourceId); return new ClampTag(turnCount, sourceId);
case BattlerTagType.SAND_TOMB: case BattlerTagType.SAND_TOMB:
return new SandTombTag(turnCount, sourceId); return new SandTombTag(turnCount, sourceId);
case BattlerTagType.MAGMA_STORM: case BattlerTagType.MAGMA_STORM:
return new MagmaStormTag(turnCount, sourceId); return new MagmaStormTag(turnCount, sourceId);
case BattlerTagType.SNAP_TRAP: case BattlerTagType.SNAP_TRAP:
return new SnapTrapTag(turnCount, sourceId); return new SnapTrapTag(turnCount, sourceId);
case BattlerTagType.THUNDER_CAGE: case BattlerTagType.THUNDER_CAGE:
return new ThunderCageTag(turnCount, sourceId); return new ThunderCageTag(turnCount, sourceId);
case BattlerTagType.INFESTATION: case BattlerTagType.INFESTATION:
return new InfestationTag(turnCount, sourceId); return new InfestationTag(turnCount, sourceId);
case BattlerTagType.PROTECTED: case BattlerTagType.PROTECTED:
return new ProtectedTag(sourceMove); return new ProtectedTag(sourceMove);
case BattlerTagType.SPIKY_SHIELD: case BattlerTagType.SPIKY_SHIELD:
return new ContactDamageProtectedTag(sourceMove, 8); return new ContactDamageProtectedTag(sourceMove, 8);
case BattlerTagType.KINGS_SHIELD: case BattlerTagType.KINGS_SHIELD:
return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.ATK, -1); return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.ATK, -1);
case BattlerTagType.OBSTRUCT: case BattlerTagType.OBSTRUCT:
return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.DEF, -2); return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.DEF, -2);
case BattlerTagType.SILK_TRAP: case BattlerTagType.SILK_TRAP:
return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.SPD, -1); return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.SPD, -1);
case BattlerTagType.BANEFUL_BUNKER: case BattlerTagType.BANEFUL_BUNKER:
return new ContactPoisonProtectedTag(sourceMove); return new ContactPoisonProtectedTag(sourceMove);
case BattlerTagType.BURNING_BULWARK: case BattlerTagType.BURNING_BULWARK:
return new ContactBurnProtectedTag(sourceMove); return new ContactBurnProtectedTag(sourceMove);
case BattlerTagType.ENDURING: case BattlerTagType.ENDURING:
return new EnduringTag(sourceMove); return new EnduringTag(sourceMove);
case BattlerTagType.STURDY: case BattlerTagType.STURDY:
return new SturdyTag(sourceMove); return new SturdyTag(sourceMove);
case BattlerTagType.PERISH_SONG: case BattlerTagType.PERISH_SONG:
return new PerishSongTag(turnCount); return new PerishSongTag(turnCount);
case BattlerTagType.CENTER_OF_ATTENTION: case BattlerTagType.CENTER_OF_ATTENTION:
return new CenterOfAttentionTag(sourceMove); return new CenterOfAttentionTag(sourceMove);
case BattlerTagType.TRUANT: case BattlerTagType.TRUANT:
return new TruantTag(); return new TruantTag();
case BattlerTagType.SLOW_START: case BattlerTagType.SLOW_START:
return new SlowStartTag(); return new SlowStartTag();
case BattlerTagType.PROTOSYNTHESIS: case BattlerTagType.PROTOSYNTHESIS:
return new WeatherHighestStatBoostTag(tagType, Abilities.PROTOSYNTHESIS, WeatherType.SUNNY, WeatherType.HARSH_SUN); return new WeatherHighestStatBoostTag(tagType, Abilities.PROTOSYNTHESIS, WeatherType.SUNNY, WeatherType.HARSH_SUN);
case BattlerTagType.QUARK_DRIVE: case BattlerTagType.QUARK_DRIVE:
return new TerrainHighestStatBoostTag(tagType, Abilities.QUARK_DRIVE, TerrainType.ELECTRIC); return new TerrainHighestStatBoostTag(tagType, Abilities.QUARK_DRIVE, TerrainType.ELECTRIC);
case BattlerTagType.FLYING: case BattlerTagType.FLYING:
case BattlerTagType.UNDERGROUND: case BattlerTagType.UNDERGROUND:
case BattlerTagType.UNDERWATER: case BattlerTagType.UNDERWATER:
case BattlerTagType.HIDDEN: case BattlerTagType.HIDDEN:
return new SemiInvulnerableTag(tagType, turnCount, sourceMove); return new SemiInvulnerableTag(tagType, turnCount, sourceMove);
case BattlerTagType.FIRE_BOOST: case BattlerTagType.FIRE_BOOST:
return new TypeBoostTag(tagType, sourceMove, Type.FIRE, 1.5, false); return new TypeBoostTag(tagType, sourceMove, Type.FIRE, 1.5, false);
case BattlerTagType.CRIT_BOOST: case BattlerTagType.CRIT_BOOST:
return new CritBoostTag(tagType, sourceMove); return new CritBoostTag(tagType, sourceMove);
case BattlerTagType.DRAGON_CHEER: case BattlerTagType.DRAGON_CHEER:
return new DragonCheerTag(); return new DragonCheerTag();
case BattlerTagType.ALWAYS_CRIT: case BattlerTagType.ALWAYS_CRIT:
case BattlerTagType.IGNORE_ACCURACY: case BattlerTagType.IGNORE_ACCURACY:
return new BattlerTag(tagType, BattlerTagLapseType.TURN_END, 2, sourceMove); return new BattlerTag(tagType, BattlerTagLapseType.TURN_END, 2, sourceMove);
case BattlerTagType.ALWAYS_GET_HIT: case BattlerTagType.ALWAYS_GET_HIT:
case BattlerTagType.RECEIVE_DOUBLE_DAMAGE: case BattlerTagType.RECEIVE_DOUBLE_DAMAGE:
return new BattlerTag(tagType, BattlerTagLapseType.PRE_MOVE, 1, sourceMove); return new BattlerTag(tagType, BattlerTagLapseType.PRE_MOVE, 1, sourceMove);
case BattlerTagType.BYPASS_SLEEP: case BattlerTagType.BYPASS_SLEEP:
return new BattlerTag(tagType, BattlerTagLapseType.TURN_END, turnCount, sourceMove); return new BattlerTag(tagType, BattlerTagLapseType.TURN_END, turnCount, sourceMove);
case BattlerTagType.IGNORE_FLYING: case BattlerTagType.IGNORE_FLYING:
return new GroundedTag(tagType, BattlerTagLapseType.CUSTOM, sourceMove); return new GroundedTag(tagType, BattlerTagLapseType.CUSTOM, sourceMove);
case BattlerTagType.ROOSTED: case BattlerTagType.ROOSTED:
return new RoostedTag(); return new RoostedTag();
case BattlerTagType.BURNED_UP: case BattlerTagType.BURNED_UP:
return new RemovedTypeTag(tagType, BattlerTagLapseType.CUSTOM, sourceMove); return new RemovedTypeTag(tagType, BattlerTagLapseType.CUSTOM, sourceMove);
case BattlerTagType.DOUBLE_SHOCKED: case BattlerTagType.DOUBLE_SHOCKED:
return new RemovedTypeTag(tagType, BattlerTagLapseType.CUSTOM, sourceMove); return new RemovedTypeTag(tagType, BattlerTagLapseType.CUSTOM, sourceMove);
case BattlerTagType.SALT_CURED: case BattlerTagType.SALT_CURED:
return new SaltCuredTag(sourceId); return new SaltCuredTag(sourceId);
case BattlerTagType.CURSED: case BattlerTagType.CURSED:
return new CursedTag(sourceId); return new CursedTag(sourceId);
case BattlerTagType.CHARGED: case BattlerTagType.CHARGED:
return new TypeBoostTag(tagType, sourceMove, Type.ELECTRIC, 2, true); return new TypeBoostTag(tagType, sourceMove, Type.ELECTRIC, 2, true);
case BattlerTagType.FLOATING: case BattlerTagType.FLOATING:
return new FloatingTag(tagType, sourceMove); return new FloatingTag(tagType, sourceMove);
case BattlerTagType.MINIMIZED: case BattlerTagType.MINIMIZED:
return new MinimizeTag(); return new MinimizeTag();
case BattlerTagType.DESTINY_BOND: case BattlerTagType.DESTINY_BOND:
return new DestinyBondTag(sourceMove, sourceId); return new DestinyBondTag(sourceMove, sourceId);
case BattlerTagType.ICE_FACE: case BattlerTagType.ICE_FACE:
return new IceFaceBlockDamageTag(tagType); return new IceFaceBlockDamageTag(tagType);
case BattlerTagType.DISGUISE: case BattlerTagType.DISGUISE:
return new FormBlockDamageTag(tagType); return new FormBlockDamageTag(tagType);
case BattlerTagType.STOCKPILING: case BattlerTagType.STOCKPILING:
return new StockpilingTag(sourceMove); return new StockpilingTag(sourceMove);
case BattlerTagType.OCTOLOCK: case BattlerTagType.OCTOLOCK:
return new OctolockTag(sourceId); return new OctolockTag(sourceId);
case BattlerTagType.DISABLED: case BattlerTagType.DISABLED:
return new DisabledTag(sourceId); return new DisabledTag(sourceId);
case BattlerTagType.IGNORE_GHOST: case BattlerTagType.IGNORE_GHOST:
return new ExposedTag(tagType, sourceMove, Type.GHOST, [ Type.NORMAL, Type.FIGHTING ]); return new ExposedTag(tagType, sourceMove, Type.GHOST, [ Type.NORMAL, Type.FIGHTING ]);
case BattlerTagType.IGNORE_DARK: case BattlerTagType.IGNORE_DARK:
return new ExposedTag(tagType, sourceMove, Type.DARK, [ Type.PSYCHIC ]); return new ExposedTag(tagType, sourceMove, Type.DARK, [ Type.PSYCHIC ]);
case BattlerTagType.GULP_MISSILE_ARROKUDA: case BattlerTagType.GULP_MISSILE_ARROKUDA:
case BattlerTagType.GULP_MISSILE_PIKACHU: case BattlerTagType.GULP_MISSILE_PIKACHU:
return new GulpMissileTag(tagType, sourceMove); return new GulpMissileTag(tagType, sourceMove);
case BattlerTagType.TAR_SHOT: case BattlerTagType.TAR_SHOT:
return new TarShotTag(); return new TarShotTag();
case BattlerTagType.ELECTRIFIED: case BattlerTagType.ELECTRIFIED:
return new ElectrifiedTag(); return new ElectrifiedTag();
case BattlerTagType.THROAT_CHOPPED: case BattlerTagType.THROAT_CHOPPED:
return new ThroatChoppedTag(); return new ThroatChoppedTag();
case BattlerTagType.GORILLA_TACTICS: case BattlerTagType.GORILLA_TACTICS:
return new GorillaTacticsTag(); return new GorillaTacticsTag();
case BattlerTagType.SUBSTITUTE: case BattlerTagType.SUBSTITUTE:
return new SubstituteTag(sourceMove, sourceId); return new SubstituteTag(sourceMove, sourceId);
case BattlerTagType.AUTOTOMIZED: case BattlerTagType.AUTOTOMIZED:
return new AutotomizedTag(); return new AutotomizedTag();
case BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON: case BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON:
return new MysteryEncounterPostSummonTag(); return new MysteryEncounterPostSummonTag();
case BattlerTagType.HEAL_BLOCK: case BattlerTagType.HEAL_BLOCK:
return new HealBlockTag(turnCount, sourceMove); return new HealBlockTag(turnCount, sourceMove);
case BattlerTagType.TORMENT: case BattlerTagType.TORMENT:
return new TormentTag(sourceId); return new TormentTag(sourceId);
case BattlerTagType.TAUNT: case BattlerTagType.TAUNT:
return new TauntTag(); return new TauntTag();
case BattlerTagType.IMPRISON: case BattlerTagType.IMPRISON:
return new ImprisonTag(sourceId); return new ImprisonTag(sourceId);
case BattlerTagType.SYRUP_BOMB: case BattlerTagType.SYRUP_BOMB:
return new SyrupBombTag(sourceId); return new SyrupBombTag(sourceId);
case BattlerTagType.TELEKINESIS: case BattlerTagType.TELEKINESIS:
return new TelekinesisTag(sourceMove); return new TelekinesisTag(sourceMove);
case BattlerTagType.POWER_TRICK: case BattlerTagType.POWER_TRICK:
return new PowerTrickTag(sourceMove, sourceId); return new PowerTrickTag(sourceMove, sourceId);
case BattlerTagType.NONE: case BattlerTagType.NONE:
default: default:
return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId); return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId);
} }
} }

View File

@ -22,42 +22,42 @@ export type BerryPredicate = (pokemon: Pokemon) => boolean;
export function getBerryPredicate(berryType: BerryType): BerryPredicate { export function getBerryPredicate(berryType: BerryType): BerryPredicate {
switch (berryType) { switch (berryType) {
case BerryType.SITRUS: case BerryType.SITRUS:
return (pokemon: Pokemon) => pokemon.getHpRatio() < 0.5; return (pokemon: Pokemon) => pokemon.getHpRatio() < 0.5;
case BerryType.LUM: case BerryType.LUM:
return (pokemon: Pokemon) => !!pokemon.status || !!pokemon.getTag(BattlerTagType.CONFUSED); return (pokemon: Pokemon) => !!pokemon.status || !!pokemon.getTag(BattlerTagType.CONFUSED);
case BerryType.ENIGMA: case BerryType.ENIGMA:
return (pokemon: Pokemon) => !!pokemon.turnData.attacksReceived.filter(a => a.result === HitResult.SUPER_EFFECTIVE).length; return (pokemon: Pokemon) => !!pokemon.turnData.attacksReceived.filter(a => a.result === HitResult.SUPER_EFFECTIVE).length;
case BerryType.LIECHI: case BerryType.LIECHI:
case BerryType.GANLON: case BerryType.GANLON:
case BerryType.PETAYA: case BerryType.PETAYA:
case BerryType.APICOT: case BerryType.APICOT:
case BerryType.SALAC: case BerryType.SALAC:
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => {
const threshold = new Utils.NumberHolder(0.25); const threshold = new Utils.NumberHolder(0.25);
// Offset BerryType such that LIECHI -> Stat.ATK = 1, GANLON -> Stat.DEF = 2, so on and so forth // Offset BerryType such that LIECHI -> Stat.ATK = 1, GANLON -> Stat.DEF = 2, so on and so forth
const stat: BattleStat = berryType - BerryType.ENIGMA; const stat: BattleStat = berryType - BerryType.ENIGMA;
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold); applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold);
return pokemon.getHpRatio() < threshold.value && pokemon.getStatStage(stat) < 6; return pokemon.getHpRatio() < threshold.value && pokemon.getStatStage(stat) < 6;
}; };
case BerryType.LANSAT: case BerryType.LANSAT:
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => {
const threshold = new Utils.NumberHolder(0.25); const threshold = new Utils.NumberHolder(0.25);
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold); applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold);
return pokemon.getHpRatio() < 0.25 && !pokemon.getTag(BattlerTagType.CRIT_BOOST); return pokemon.getHpRatio() < 0.25 && !pokemon.getTag(BattlerTagType.CRIT_BOOST);
}; };
case BerryType.STARF: case BerryType.STARF:
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => {
const threshold = new Utils.NumberHolder(0.25); const threshold = new Utils.NumberHolder(0.25);
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold); applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold);
return pokemon.getHpRatio() < 0.25; return pokemon.getHpRatio() < 0.25;
}; };
case BerryType.LEPPA: case BerryType.LEPPA:
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => {
const threshold = new Utils.NumberHolder(0.25); const threshold = new Utils.NumberHolder(0.25);
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold); applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold);
return !!pokemon.getMoveset().find(m => !m?.getPpRatio()); return !!pokemon.getMoveset().find(m => !m?.getPpRatio());
}; };
} }
} }
@ -65,70 +65,70 @@ export type BerryEffectFunc = (pokemon: Pokemon) => void;
export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc { export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
switch (berryType) { switch (berryType) {
case BerryType.SITRUS: case BerryType.SITRUS:
case BerryType.ENIGMA: case BerryType.ENIGMA:
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => {
if (pokemon.battleData) { if (pokemon.battleData) {
pokemon.battleData.berriesEaten.push(berryType); pokemon.battleData.berriesEaten.push(berryType);
} }
const hpHealed = new Utils.NumberHolder(Utils.toDmgValue(pokemon.getMaxHp() / 4)); const hpHealed = new Utils.NumberHolder(Utils.toDmgValue(pokemon.getMaxHp() / 4));
applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, hpHealed); applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, hpHealed);
pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.getBattlerIndex(), pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.getBattlerIndex(),
hpHealed.value, i18next.t("battle:hpHealBerry", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), berryName: getBerryName(berryType) }), true)); hpHealed.value, i18next.t("battle:hpHealBerry", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), berryName: getBerryName(berryType) }), true));
}; };
case BerryType.LUM: case BerryType.LUM:
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => {
if (pokemon.battleData) { if (pokemon.battleData) {
pokemon.battleData.berriesEaten.push(berryType); pokemon.battleData.berriesEaten.push(berryType);
} }
if (pokemon.status) { if (pokemon.status) {
pokemon.scene.queueMessage(getStatusEffectHealText(pokemon.status.effect, getPokemonNameWithAffix(pokemon))); pokemon.scene.queueMessage(getStatusEffectHealText(pokemon.status.effect, getPokemonNameWithAffix(pokemon)));
} }
pokemon.resetStatus(true, true); pokemon.resetStatus(true, true);
pokemon.updateInfo(); pokemon.updateInfo();
}; };
case BerryType.LIECHI: case BerryType.LIECHI:
case BerryType.GANLON: case BerryType.GANLON:
case BerryType.PETAYA: case BerryType.PETAYA:
case BerryType.APICOT: case BerryType.APICOT:
case BerryType.SALAC: case BerryType.SALAC:
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => {
if (pokemon.battleData) { if (pokemon.battleData) {
pokemon.battleData.berriesEaten.push(berryType); pokemon.battleData.berriesEaten.push(berryType);
} }
// Offset BerryType such that LIECHI -> Stat.ATK = 1, GANLON -> Stat.DEF = 2, so on and so forth // Offset BerryType such that LIECHI -> Stat.ATK = 1, GANLON -> Stat.DEF = 2, so on and so forth
const stat: BattleStat = berryType - BerryType.ENIGMA; const stat: BattleStat = berryType - BerryType.ENIGMA;
const statStages = new Utils.NumberHolder(1); const statStages = new Utils.NumberHolder(1);
applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, statStages); applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, statStages);
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ stat ], statStages.value)); pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ stat ], statStages.value));
}; };
case BerryType.LANSAT: case BerryType.LANSAT:
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => {
if (pokemon.battleData) { if (pokemon.battleData) {
pokemon.battleData.berriesEaten.push(berryType); pokemon.battleData.berriesEaten.push(berryType);
} }
pokemon.addTag(BattlerTagType.CRIT_BOOST); pokemon.addTag(BattlerTagType.CRIT_BOOST);
}; };
case BerryType.STARF: case BerryType.STARF:
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => {
if (pokemon.battleData) { if (pokemon.battleData) {
pokemon.battleData.berriesEaten.push(berryType); pokemon.battleData.berriesEaten.push(berryType);
} }
const randStat = Utils.randSeedInt(Stat.SPD, Stat.ATK); const randStat = Utils.randSeedInt(Stat.SPD, Stat.ATK);
const stages = new Utils.NumberHolder(2); const stages = new Utils.NumberHolder(2);
applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, stages); applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, stages);
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ randStat ], stages.value)); pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ randStat ], stages.value));
}; };
case BerryType.LEPPA: case BerryType.LEPPA:
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => {
if (pokemon.battleData) { if (pokemon.battleData) {
pokemon.battleData.berriesEaten.push(berryType); pokemon.battleData.berriesEaten.push(berryType);
} }
const ppRestoreMove = pokemon.getMoveset().find(m => !m?.getPpRatio()) ? pokemon.getMoveset().find(m => !m?.getPpRatio()) : pokemon.getMoveset().find(m => m!.getPpRatio() < 1); // TODO: is this bang correct? const ppRestoreMove = pokemon.getMoveset().find(m => !m?.getPpRatio()) ? pokemon.getMoveset().find(m => !m?.getPpRatio()) : pokemon.getMoveset().find(m => m!.getPpRatio() < 1); // TODO: is this bang correct?
if (ppRestoreMove !== undefined) { if (ppRestoreMove !== undefined) {
ppRestoreMove!.ppUsed = Math.max(ppRestoreMove!.ppUsed - 10, 0); ppRestoreMove!.ppUsed = Math.max(ppRestoreMove!.ppUsed - 10, 0);
pokemon.scene.queueMessage(i18next.t("battle:ppHealBerry", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: ppRestoreMove!.getName(), berryName: getBerryName(berryType) })); pokemon.scene.queueMessage(i18next.t("battle:ppHealBerry", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: ppRestoreMove!.getName(), berryName: getBerryName(berryType) }));
} }
}; };
} }
} }

View File

@ -448,21 +448,21 @@ export class SingleGenerationChallenge extends Challenge {
applyFixedBattle(waveIndex: Number, battleConfig: FixedBattleConfig): boolean { applyFixedBattle(waveIndex: Number, battleConfig: FixedBattleConfig): boolean {
let trainerTypes: TrainerType[] = []; let trainerTypes: TrainerType[] = [];
switch (waveIndex) { switch (waveIndex) {
case 182: case 182:
trainerTypes = [ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, Utils.randSeedItem([ TrainerType.HALA, TrainerType.MOLAYNE ]), TrainerType.MARNIE_ELITE, TrainerType.RIKA ]; trainerTypes = [ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, Utils.randSeedItem([ TrainerType.HALA, TrainerType.MOLAYNE ]), TrainerType.MARNIE_ELITE, TrainerType.RIKA ];
break; break;
case 184: case 184:
trainerTypes = [ TrainerType.BRUNO, TrainerType.KOGA, TrainerType.PHOEBE, TrainerType.BERTHA, TrainerType.MARSHAL, TrainerType.SIEBOLD, TrainerType.OLIVIA, TrainerType.NESSA_ELITE, TrainerType.POPPY ]; trainerTypes = [ TrainerType.BRUNO, TrainerType.KOGA, TrainerType.PHOEBE, TrainerType.BERTHA, TrainerType.MARSHAL, TrainerType.SIEBOLD, TrainerType.OLIVIA, TrainerType.NESSA_ELITE, TrainerType.POPPY ];
break; break;
case 186: case 186:
trainerTypes = [ TrainerType.AGATHA, TrainerType.BRUNO, TrainerType.GLACIA, TrainerType.FLINT, TrainerType.GRIMSLEY, TrainerType.WIKSTROM, TrainerType.ACEROLA, Utils.randSeedItem([ TrainerType.BEA_ELITE, TrainerType.ALLISTER_ELITE ]), TrainerType.LARRY_ELITE ]; trainerTypes = [ TrainerType.AGATHA, TrainerType.BRUNO, TrainerType.GLACIA, TrainerType.FLINT, TrainerType.GRIMSLEY, TrainerType.WIKSTROM, TrainerType.ACEROLA, Utils.randSeedItem([ TrainerType.BEA_ELITE, TrainerType.ALLISTER_ELITE ]), TrainerType.LARRY_ELITE ];
break; break;
case 188: case 188:
trainerTypes = [ TrainerType.LANCE, TrainerType.KAREN, TrainerType.DRAKE, TrainerType.LUCIAN, TrainerType.CAITLIN, TrainerType.DRASNA, TrainerType.KAHILI, TrainerType.RAIHAN_ELITE, TrainerType.HASSEL ]; trainerTypes = [ TrainerType.LANCE, TrainerType.KAREN, TrainerType.DRAKE, TrainerType.LUCIAN, TrainerType.CAITLIN, TrainerType.DRASNA, TrainerType.KAHILI, TrainerType.RAIHAN_ELITE, TrainerType.HASSEL ];
break; break;
case 190: case 190:
trainerTypes = [ TrainerType.BLUE, Utils.randSeedItem([ TrainerType.RED, TrainerType.LANCE_CHAMPION ]), Utils.randSeedItem([ TrainerType.STEVEN, TrainerType.WALLACE ]), TrainerType.CYNTHIA, Utils.randSeedItem([ TrainerType.ALDER, TrainerType.IRIS ]), TrainerType.DIANTHA, TrainerType.HAU, TrainerType.LEON, Utils.randSeedItem([ TrainerType.GEETA, TrainerType.NEMONA ]) ]; trainerTypes = [ TrainerType.BLUE, Utils.randSeedItem([ TrainerType.RED, TrainerType.LANCE_CHAMPION ]), Utils.randSeedItem([ TrainerType.STEVEN, TrainerType.WALLACE ]), TrainerType.CYNTHIA, Utils.randSeedItem([ TrainerType.ALDER, TrainerType.IRIS ]), TrainerType.DIANTHA, TrainerType.HAU, TrainerType.LEON, Utils.randSeedItem([ TrainerType.GEETA, TrainerType.NEMONA ]) ];
break; break;
} }
if (trainerTypes.length === 0) { if (trainerTypes.length === 0) {
return false; return false;
@ -891,45 +891,45 @@ export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType
gameMode.challenges.forEach(c => { gameMode.challenges.forEach(c => {
if (c.value !== 0) { if (c.value !== 0) {
switch (challengeType) { switch (challengeType) {
case ChallengeType.STARTER_CHOICE: case ChallengeType.STARTER_CHOICE:
ret ||= c.applyStarterChoice(args[0], args[1], args[2], args[3]); ret ||= c.applyStarterChoice(args[0], args[1], args[2], args[3]);
break; break;
case ChallengeType.STARTER_POINTS: case ChallengeType.STARTER_POINTS:
ret ||= c.applyStarterPoints(args[0]); ret ||= c.applyStarterPoints(args[0]);
break; break;
case ChallengeType.STARTER_COST: case ChallengeType.STARTER_COST:
ret ||= c.applyStarterCost(args[0], args[1]); ret ||= c.applyStarterCost(args[0], args[1]);
break; break;
case ChallengeType.STARTER_MODIFY: case ChallengeType.STARTER_MODIFY:
ret ||= c.applyStarterModify(args[0]); ret ||= c.applyStarterModify(args[0]);
break; break;
case ChallengeType.POKEMON_IN_BATTLE: case ChallengeType.POKEMON_IN_BATTLE:
ret ||= c.applyPokemonInBattle(args[0], args[1]); ret ||= c.applyPokemonInBattle(args[0], args[1]);
break; break;
case ChallengeType.FIXED_BATTLES: case ChallengeType.FIXED_BATTLES:
ret ||= c.applyFixedBattle(args[0], args[1]); ret ||= c.applyFixedBattle(args[0], args[1]);
break; break;
case ChallengeType.TYPE_EFFECTIVENESS: case ChallengeType.TYPE_EFFECTIVENESS:
ret ||= c.applyTypeEffectiveness(args[0]); ret ||= c.applyTypeEffectiveness(args[0]);
break; break;
case ChallengeType.AI_LEVEL: case ChallengeType.AI_LEVEL:
ret ||= c.applyLevelChange(args[0], args[1], args[2], args[3]); ret ||= c.applyLevelChange(args[0], args[1], args[2], args[3]);
break; break;
case ChallengeType.AI_MOVE_SLOTS: case ChallengeType.AI_MOVE_SLOTS:
ret ||= c.applyMoveSlot(args[0], args[1]); ret ||= c.applyMoveSlot(args[0], args[1]);
break; break;
case ChallengeType.PASSIVE_ACCESS: case ChallengeType.PASSIVE_ACCESS:
ret ||= c.applyPassiveAccess(args[0], args[1]); ret ||= c.applyPassiveAccess(args[0], args[1]);
break; break;
case ChallengeType.GAME_MODE_MODIFY: case ChallengeType.GAME_MODE_MODIFY:
ret ||= c.applyGameModeModify(gameMode); ret ||= c.applyGameModeModify(gameMode);
break; break;
case ChallengeType.MOVE_ACCESS: case ChallengeType.MOVE_ACCESS:
ret ||= c.applyMoveAccessLevel(args[0], args[1], args[2], args[3]); ret ||= c.applyMoveAccessLevel(args[0], args[1], args[2], args[3]);
break; break;
case ChallengeType.MOVE_WEIGHT: case ChallengeType.MOVE_WEIGHT:
ret ||= c.applyMoveWeight(args[0], args[1], args[2], args[3]); ret ||= c.applyMoveWeight(args[0], args[1], args[2], args[3]);
break; break;
} }
} }
}); });
@ -943,18 +943,18 @@ export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType
*/ */
export function copyChallenge(source: Challenge | any): Challenge { export function copyChallenge(source: Challenge | any): Challenge {
switch (source.id) { switch (source.id) {
case Challenges.SINGLE_GENERATION: case Challenges.SINGLE_GENERATION:
return SingleGenerationChallenge.loadChallenge(source); return SingleGenerationChallenge.loadChallenge(source);
case Challenges.SINGLE_TYPE: case Challenges.SINGLE_TYPE:
return SingleTypeChallenge.loadChallenge(source); return SingleTypeChallenge.loadChallenge(source);
case Challenges.LOWER_MAX_STARTER_COST: case Challenges.LOWER_MAX_STARTER_COST:
return LowerStarterMaxCostChallenge.loadChallenge(source); return LowerStarterMaxCostChallenge.loadChallenge(source);
case Challenges.LOWER_STARTER_POINTS: case Challenges.LOWER_STARTER_POINTS:
return LowerStarterPointsChallenge.loadChallenge(source); return LowerStarterPointsChallenge.loadChallenge(source);
case Challenges.FRESH_START: case Challenges.FRESH_START:
return FreshStartChallenge.loadChallenge(source); return FreshStartChallenge.loadChallenge(source);
case Challenges.INVERSE_BATTLE: case Challenges.INVERSE_BATTLE:
return InverseBattleChallenge.loadChallenge(source); return InverseBattleChallenge.loadChallenge(source);
} }
throw new Error("Unknown challenge copied"); throw new Error("Unknown challenge copied");
} }

View File

@ -262,14 +262,14 @@ export class Egg {
return "Manaphy"; return "Manaphy";
} }
switch (this.tier) { switch (this.tier) {
case EggTier.RARE: case EggTier.RARE:
return i18next.t("egg:greatTier"); return i18next.t("egg:greatTier");
case EggTier.EPIC: case EggTier.EPIC:
return i18next.t("egg:ultraTier"); return i18next.t("egg:ultraTier");
case EggTier.LEGENDARY: case EggTier.LEGENDARY:
return i18next.t("egg:masterTier"); return i18next.t("egg:masterTier");
default: default:
return i18next.t("egg:defaultTier"); return i18next.t("egg:defaultTier");
} }
} }
@ -288,19 +288,19 @@ export class Egg {
public getEggTypeDescriptor(scene: BattleScene): string { public getEggTypeDescriptor(scene: BattleScene): string {
switch (this.sourceType) { switch (this.sourceType) {
case EggSourceType.SAME_SPECIES_EGG: case EggSourceType.SAME_SPECIES_EGG:
return this._eggDescriptor ?? i18next.t("egg:sameSpeciesEgg", { species: getPokemonSpecies(this._species).getName() }); return this._eggDescriptor ?? i18next.t("egg:sameSpeciesEgg", { species: getPokemonSpecies(this._species).getName() });
case EggSourceType.GACHA_LEGENDARY: case EggSourceType.GACHA_LEGENDARY:
return this._eggDescriptor ?? `${i18next.t("egg:gachaTypeLegendary")} (${getPokemonSpecies(getLegendaryGachaSpeciesForTimestamp(scene, this.timestamp)).getName()})`; return this._eggDescriptor ?? `${i18next.t("egg:gachaTypeLegendary")} (${getPokemonSpecies(getLegendaryGachaSpeciesForTimestamp(scene, this.timestamp)).getName()})`;
case EggSourceType.GACHA_SHINY: case EggSourceType.GACHA_SHINY:
return this._eggDescriptor ?? i18next.t("egg:gachaTypeShiny"); return this._eggDescriptor ?? i18next.t("egg:gachaTypeShiny");
case EggSourceType.GACHA_MOVE: case EggSourceType.GACHA_MOVE:
return this._eggDescriptor ?? i18next.t("egg:gachaTypeMove"); return this._eggDescriptor ?? i18next.t("egg:gachaTypeMove");
case EggSourceType.EVENT: case EggSourceType.EVENT:
return this._eggDescriptor ?? i18next.t("egg:eventType"); return this._eggDescriptor ?? i18next.t("egg:eventType");
default: default:
console.warn("getEggTypeDescriptor case not defined. Returning default empty string"); console.warn("getEggTypeDescriptor case not defined. Returning default empty string");
return ""; return "";
} }
} }
@ -315,14 +315,14 @@ export class Egg {
private rollEggMoveIndex() { private rollEggMoveIndex() {
let baseChance = GACHA_DEFAULT_RARE_EGGMOVE_RATE; let baseChance = GACHA_DEFAULT_RARE_EGGMOVE_RATE;
switch (this._sourceType) { switch (this._sourceType) {
case EggSourceType.SAME_SPECIES_EGG: case EggSourceType.SAME_SPECIES_EGG:
baseChance = SAME_SPECIES_EGG_RARE_EGGMOVE_RATE; baseChance = SAME_SPECIES_EGG_RARE_EGGMOVE_RATE;
break; break;
case EggSourceType.GACHA_MOVE: case EggSourceType.GACHA_MOVE:
baseChance = GACHA_MOVE_UP_RARE_EGGMOVE_RATE; baseChance = GACHA_MOVE_UP_RARE_EGGMOVE_RATE;
break; break;
default: default:
break; break;
} }
const tierMultiplier = this.isManaphyEgg() ? 2 : Math.pow(2, 3 - this.tier); const tierMultiplier = this.isManaphyEgg() ? 2 : Math.pow(2, 3 - this.tier);
@ -335,12 +335,12 @@ export class Egg {
} }
switch (eggTier ?? this._tier) { switch (eggTier ?? this._tier) {
case EggTier.COMMON: case EggTier.COMMON:
return HATCH_WAVES_COMMON_EGG; return HATCH_WAVES_COMMON_EGG;
case EggTier.RARE: case EggTier.RARE:
return HATCH_WAVES_RARE_EGG; return HATCH_WAVES_RARE_EGG;
case EggTier.EPIC: case EggTier.EPIC:
return HATCH_WAVES_EPIC_EGG; return HATCH_WAVES_EPIC_EGG;
} }
return HATCH_WAVES_LEGENDARY_EGG; return HATCH_WAVES_LEGENDARY_EGG;
} }
@ -379,22 +379,22 @@ export class Egg {
let maxStarterValue: integer; let maxStarterValue: integer;
switch (this.tier) { switch (this.tier) {
case EggTier.RARE: case EggTier.RARE:
minStarterValue = 4; minStarterValue = 4;
maxStarterValue = 5; maxStarterValue = 5;
break; break;
case EggTier.EPIC: case EggTier.EPIC:
minStarterValue = 6; minStarterValue = 6;
maxStarterValue = 7; maxStarterValue = 7;
break; break;
case EggTier.LEGENDARY: case EggTier.LEGENDARY:
minStarterValue = 8; minStarterValue = 8;
maxStarterValue = 9; maxStarterValue = 9;
break; break;
default: default:
minStarterValue = 1; minStarterValue = 1;
maxStarterValue = 3; maxStarterValue = 3;
break; break;
} }
const ignoredSpecies = [ Species.PHIONE, Species.MANAPHY, Species.ETERNATUS ]; const ignoredSpecies = [ Species.PHIONE, Species.MANAPHY, Species.ETERNATUS ];
@ -469,14 +469,14 @@ export class Egg {
private rollShiny(): boolean { private rollShiny(): boolean {
let shinyChance = GACHA_DEFAULT_SHINY_RATE; let shinyChance = GACHA_DEFAULT_SHINY_RATE;
switch (this._sourceType) { switch (this._sourceType) {
case EggSourceType.GACHA_SHINY: case EggSourceType.GACHA_SHINY:
shinyChance = GACHA_SHINY_UP_SHINY_RATE; shinyChance = GACHA_SHINY_UP_SHINY_RATE;
break; break;
case EggSourceType.SAME_SPECIES_EGG: case EggSourceType.SAME_SPECIES_EGG:
shinyChance = SAME_SPECIES_EGG_SHINY_RATE; shinyChance = SAME_SPECIES_EGG_SHINY_RATE;
break; break;
default: default:
break; break;
} }
return !Utils.randSeedInt(shinyChance); return !Utils.randSeedInt(shinyChance);
@ -523,15 +523,15 @@ export class Egg {
return; return;
} }
switch (this.tier) { switch (this.tier) {
case EggTier.RARE: case EggTier.RARE:
scene.gameData.gameStats.rareEggsPulled++; scene.gameData.gameStats.rareEggsPulled++;
break; break;
case EggTier.EPIC: case EggTier.EPIC:
scene.gameData.gameStats.epicEggsPulled++; scene.gameData.gameStats.epicEggsPulled++;
break; break;
case EggTier.LEGENDARY: case EggTier.LEGENDARY:
scene.gameData.gameStats.legendaryEggsPulled++; scene.gameData.gameStats.legendaryEggsPulled++;
break; break;
} }
} }

View File

@ -28,24 +28,24 @@ export function getLevelTotalExp(level: integer, growthRate: GrowthRate): intege
let ret: integer; let ret: integer;
switch (growthRate) { switch (growthRate) {
case GrowthRate.ERRATIC: case GrowthRate.ERRATIC:
ret = (Math.pow(level, 4) + (Math.pow(level, 3) * 2000)) / 3500; ret = (Math.pow(level, 4) + (Math.pow(level, 3) * 2000)) / 3500;
break; break;
case GrowthRate.FAST: case GrowthRate.FAST:
ret = Math.pow(level, 3) * 4 / 5; ret = Math.pow(level, 3) * 4 / 5;
break; break;
case GrowthRate.MEDIUM_FAST: case GrowthRate.MEDIUM_FAST:
ret = Math.pow(level, 3); ret = Math.pow(level, 3);
break; break;
case GrowthRate.MEDIUM_SLOW: case GrowthRate.MEDIUM_SLOW:
ret = (Math.pow(level, 3) * 6 / 5) - (15 * Math.pow(level, 2)) + (100 * level) - 140; ret = (Math.pow(level, 3) * 6 / 5) - (15 * Math.pow(level, 2)) + (100 * level) - 140;
break; break;
case GrowthRate.SLOW: case GrowthRate.SLOW:
ret = Math.pow(level, 3) * 5 / 4; ret = Math.pow(level, 3) * 5 / 4;
break; break;
case GrowthRate.FLUCTUATING: case GrowthRate.FLUCTUATING:
ret = (Math.pow(level, 3) * ((level / 2) + 8)) * 4 / (100 + level); ret = (Math.pow(level, 3) * ((level / 2) + 8)) * 4 / (100 + level);
break; break;
} }
if (growthRate !== GrowthRate.MEDIUM_FAST) { if (growthRate !== GrowthRate.MEDIUM_FAST) {
@ -61,17 +61,17 @@ export function getLevelRelExp(level: integer, growthRate: GrowthRate): number {
export function getGrowthRateColor(growthRate: GrowthRate, shadow?: boolean) { export function getGrowthRateColor(growthRate: GrowthRate, shadow?: boolean) {
switch (growthRate) { switch (growthRate) {
case GrowthRate.ERRATIC: case GrowthRate.ERRATIC:
return !shadow ? "#f85888" : "#906060"; return !shadow ? "#f85888" : "#906060";
case GrowthRate.FAST: case GrowthRate.FAST:
return !shadow ? "#f8d030" : "#b8a038"; return !shadow ? "#f8d030" : "#b8a038";
case GrowthRate.MEDIUM_FAST: case GrowthRate.MEDIUM_FAST:
return !shadow ? "#78c850" : "#588040"; return !shadow ? "#78c850" : "#588040";
case GrowthRate.MEDIUM_SLOW: case GrowthRate.MEDIUM_SLOW:
return !shadow ? "#6890f0" : "#807870"; return !shadow ? "#6890f0" : "#807870";
case GrowthRate.SLOW: case GrowthRate.SLOW:
return !shadow ? "#f08030" : "#c03028"; return !shadow ? "#f08030" : "#c03028";
case GrowthRate.FLUCTUATING: case GrowthRate.FLUCTUATING:
return !shadow ? "#a040a0" : "#483850"; return !shadow ? "#a040a0" : "#483850";
} }
} }

View File

@ -6,20 +6,20 @@ export enum Gender {
export function getGenderSymbol(gender: Gender) { export function getGenderSymbol(gender: Gender) {
switch (gender) { switch (gender) {
case Gender.MALE: case Gender.MALE:
return "♂"; return "♂";
case Gender.FEMALE: case Gender.FEMALE:
return "♀"; return "♀";
} }
return ""; return "";
} }
export function getGenderColor(gender: Gender, shadow?: boolean) { export function getGenderColor(gender: Gender, shadow?: boolean) {
switch (gender) { switch (gender) {
case Gender.MALE: case Gender.MALE:
return shadow ? "#006090" : "#40c8f8"; return shadow ? "#006090" : "#40c8f8";
case Gender.FEMALE: case Gender.FEMALE:
return shadow ? "#984038" : "#f89890"; return shadow ? "#984038" : "#f89890";
} }
return "#ffffff"; return "#ffffff";
} }

File diff suppressed because it is too large Load Diff

View File

@ -44,32 +44,32 @@ export const ATrainersTestEncounter: MysteryEncounter =
let spriteKeys; let spriteKeys;
let trainerNameKey: string; let trainerNameKey: string;
switch (randSeedInt(5)) { switch (randSeedInt(5)) {
default: default:
case 0: case 0:
trainerType = TrainerType.BUCK; trainerType = TrainerType.BUCK;
spriteKeys = getSpriteKeysFromSpecies(Species.CLAYDOL); spriteKeys = getSpriteKeysFromSpecies(Species.CLAYDOL);
trainerNameKey = "buck"; trainerNameKey = "buck";
break; break;
case 1: case 1:
trainerType = TrainerType.CHERYL; trainerType = TrainerType.CHERYL;
spriteKeys = getSpriteKeysFromSpecies(Species.BLISSEY); spriteKeys = getSpriteKeysFromSpecies(Species.BLISSEY);
trainerNameKey = "cheryl"; trainerNameKey = "cheryl";
break; break;
case 2: case 2:
trainerType = TrainerType.MARLEY; trainerType = TrainerType.MARLEY;
spriteKeys = getSpriteKeysFromSpecies(Species.ARCANINE); spriteKeys = getSpriteKeysFromSpecies(Species.ARCANINE);
trainerNameKey = "marley"; trainerNameKey = "marley";
break; break;
case 3: case 3:
trainerType = TrainerType.MIRA; trainerType = TrainerType.MIRA;
spriteKeys = getSpriteKeysFromSpecies(Species.ALAKAZAM, false, 1); spriteKeys = getSpriteKeysFromSpecies(Species.ALAKAZAM, false, 1);
trainerNameKey = "mira"; trainerNameKey = "mira";
break; break;
case 4: case 4:
trainerType = TrainerType.RILEY; trainerType = TrainerType.RILEY;
spriteKeys = getSpriteKeysFromSpecies(Species.LUCARIO, false, 1); spriteKeys = getSpriteKeysFromSpecies(Species.LUCARIO, false, 1);
trainerNameKey = "riley"; trainerNameKey = "riley";
break; break;
} }
// Dialogue and tokens for trainer // Dialogue and tokens for trainer

View File

@ -1069,19 +1069,19 @@ export function calculateRareSpawnAggregateStats(scene: BattleScene, luckValue:
const tier = tierValue >= 20 ? BiomePoolTier.BOSS : tierValue >= 6 ? BiomePoolTier.BOSS_RARE : tierValue >= 1 ? BiomePoolTier.BOSS_SUPER_RARE : BiomePoolTier.BOSS_ULTRA_RARE; const tier = tierValue >= 20 ? BiomePoolTier.BOSS : tierValue >= 6 ? BiomePoolTier.BOSS_RARE : tierValue >= 1 ? BiomePoolTier.BOSS_SUPER_RARE : BiomePoolTier.BOSS_ULTRA_RARE;
switch (tier) { switch (tier) {
default: default:
case BiomePoolTier.BOSS: case BiomePoolTier.BOSS:
++bossEncountersByRarity[0]; ++bossEncountersByRarity[0];
break; break;
case BiomePoolTier.BOSS_RARE: case BiomePoolTier.BOSS_RARE:
++bossEncountersByRarity[1]; ++bossEncountersByRarity[1];
break; break;
case BiomePoolTier.BOSS_SUPER_RARE: case BiomePoolTier.BOSS_SUPER_RARE:
++bossEncountersByRarity[2]; ++bossEncountersByRarity[2];
break; break;
case BiomePoolTier.BOSS_ULTRA_RARE: case BiomePoolTier.BOSS_ULTRA_RARE:
++bossEncountersByRarity[3]; ++bossEncountersByRarity[3];
break; break;
} }
} }

View File

@ -37,76 +37,76 @@ export function getNatureName(nature: Nature, includeStatEffects: boolean = fals
export function getNatureStatMultiplier(nature: Nature, stat: Stat): number { export function getNatureStatMultiplier(nature: Nature, stat: Stat): number {
switch (stat) { switch (stat) {
case Stat.ATK: case Stat.ATK:
switch (nature) { switch (nature) {
case Nature.LONELY: case Nature.LONELY:
case Nature.BRAVE: case Nature.BRAVE:
case Nature.ADAMANT: case Nature.ADAMANT:
case Nature.NAUGHTY: case Nature.NAUGHTY:
return 1.1; return 1.1;
case Nature.BOLD: case Nature.BOLD:
case Nature.TIMID: case Nature.TIMID:
case Nature.MODEST: case Nature.MODEST:
case Nature.CALM: case Nature.CALM:
return 0.9; return 0.9;
} }
break; break;
case Stat.DEF: case Stat.DEF:
switch (nature) { switch (nature) {
case Nature.BOLD: case Nature.BOLD:
case Nature.RELAXED: case Nature.RELAXED:
case Nature.IMPISH: case Nature.IMPISH:
case Nature.LAX: case Nature.LAX:
return 1.1; return 1.1;
case Nature.LONELY: case Nature.LONELY:
case Nature.HASTY: case Nature.HASTY:
case Nature.MILD: case Nature.MILD:
case Nature.GENTLE: case Nature.GENTLE:
return 0.9; return 0.9;
} }
break; break;
case Stat.SPATK: case Stat.SPATK:
switch (nature) { switch (nature) {
case Nature.MODEST: case Nature.MODEST:
case Nature.MILD: case Nature.MILD:
case Nature.QUIET: case Nature.QUIET:
case Nature.RASH: case Nature.RASH:
return 1.1; return 1.1;
case Nature.ADAMANT: case Nature.ADAMANT:
case Nature.IMPISH: case Nature.IMPISH:
case Nature.JOLLY: case Nature.JOLLY:
case Nature.CAREFUL: case Nature.CAREFUL:
return 0.9; return 0.9;
} }
break; break;
case Stat.SPDEF: case Stat.SPDEF:
switch (nature) { switch (nature) {
case Nature.CALM: case Nature.CALM:
case Nature.GENTLE: case Nature.GENTLE:
case Nature.SASSY: case Nature.SASSY:
case Nature.CAREFUL: case Nature.CAREFUL:
return 1.1; return 1.1;
case Nature.NAUGHTY: case Nature.NAUGHTY:
case Nature.LAX: case Nature.LAX:
case Nature.NAIVE: case Nature.NAIVE:
case Nature.RASH: case Nature.RASH:
return 0.9; return 0.9;
} }
break; break;
case Stat.SPD: case Stat.SPD:
switch (nature) { switch (nature) {
case Nature.TIMID: case Nature.TIMID:
case Nature.HASTY: case Nature.HASTY:
case Nature.JOLLY: case Nature.JOLLY:
case Nature.NAIVE: case Nature.NAIVE:
return 1.1; return 1.1;
case Nature.BRAVE: case Nature.BRAVE:
case Nature.RELAXED: case Nature.RELAXED:
case Nature.QUIET: case Nature.QUIET:
case Nature.SASSY: case Nature.SASSY:
return 0.9; return 0.9;
} }
break; break;
} }
return 1; return 1;

View File

@ -8,77 +8,77 @@ export const MAX_PER_TYPE_POKEBALLS: integer = 99;
export function getPokeballAtlasKey(type: PokeballType): string { export function getPokeballAtlasKey(type: PokeballType): string {
switch (type) { switch (type) {
case PokeballType.POKEBALL: case PokeballType.POKEBALL:
return "pb"; return "pb";
case PokeballType.GREAT_BALL: case PokeballType.GREAT_BALL:
return "gb"; return "gb";
case PokeballType.ULTRA_BALL: case PokeballType.ULTRA_BALL:
return "ub"; return "ub";
case PokeballType.ROGUE_BALL: case PokeballType.ROGUE_BALL:
return "rb"; return "rb";
case PokeballType.MASTER_BALL: case PokeballType.MASTER_BALL:
return "mb"; return "mb";
case PokeballType.LUXURY_BALL: case PokeballType.LUXURY_BALL:
return "lb"; return "lb";
} }
} }
export function getPokeballName(type: PokeballType): string { export function getPokeballName(type: PokeballType): string {
let ret: string; let ret: string;
switch (type) { switch (type) {
case PokeballType.POKEBALL: case PokeballType.POKEBALL:
ret = i18next.t("pokeball:pokeBall"); ret = i18next.t("pokeball:pokeBall");
break; break;
case PokeballType.GREAT_BALL: case PokeballType.GREAT_BALL:
ret = i18next.t("pokeball:greatBall"); ret = i18next.t("pokeball:greatBall");
break; break;
case PokeballType.ULTRA_BALL: case PokeballType.ULTRA_BALL:
ret = i18next.t("pokeball:ultraBall"); ret = i18next.t("pokeball:ultraBall");
break; break;
case PokeballType.ROGUE_BALL: case PokeballType.ROGUE_BALL:
ret = i18next.t("pokeball:rogueBall"); ret = i18next.t("pokeball:rogueBall");
break; break;
case PokeballType.MASTER_BALL: case PokeballType.MASTER_BALL:
ret = i18next.t("pokeball:masterBall"); ret = i18next.t("pokeball:masterBall");
break; break;
case PokeballType.LUXURY_BALL: case PokeballType.LUXURY_BALL:
ret = i18next.t("pokeball:luxuryBall"); ret = i18next.t("pokeball:luxuryBall");
break; break;
} }
return ret; return ret;
} }
export function getPokeballCatchMultiplier(type: PokeballType): number { export function getPokeballCatchMultiplier(type: PokeballType): number {
switch (type) { switch (type) {
case PokeballType.POKEBALL: case PokeballType.POKEBALL:
return 1; return 1;
case PokeballType.GREAT_BALL: case PokeballType.GREAT_BALL:
return 1.5; return 1.5;
case PokeballType.ULTRA_BALL: case PokeballType.ULTRA_BALL:
return 2; return 2;
case PokeballType.ROGUE_BALL: case PokeballType.ROGUE_BALL:
return 3; return 3;
case PokeballType.MASTER_BALL: case PokeballType.MASTER_BALL:
return -1; return -1;
case PokeballType.LUXURY_BALL: case PokeballType.LUXURY_BALL:
return 1; return 1;
} }
} }
export function getPokeballTintColor(type: PokeballType): number { export function getPokeballTintColor(type: PokeballType): number {
switch (type) { switch (type) {
case PokeballType.POKEBALL: case PokeballType.POKEBALL:
return 0xd52929; return 0xd52929;
case PokeballType.GREAT_BALL: case PokeballType.GREAT_BALL:
return 0x94b4de; return 0x94b4de;
case PokeballType.ULTRA_BALL: case PokeballType.ULTRA_BALL:
return 0xe6cd31; return 0xe6cd31;
case PokeballType.ROGUE_BALL: case PokeballType.ROGUE_BALL:
return 0xd52929; return 0xd52929;
case PokeballType.MASTER_BALL: case PokeballType.MASTER_BALL:
return 0xa441bd; return 0xa441bd;
case PokeballType.LUXURY_BALL: case PokeballType.LUXURY_BALL:
return 0xffde6a; return 0xffde6a;
} }
} }

View File

@ -238,8 +238,8 @@ export abstract class PokemonSpeciesForm {
isRareRegional(): boolean { isRareRegional(): boolean {
switch (this.getRegion()) { switch (this.getRegion()) {
case Region.HISUI: case Region.HISUI:
return true; return true;
} }
return false; return false;
@ -265,14 +265,14 @@ export abstract class PokemonSpeciesForm {
getBaseExp(): number { getBaseExp(): number {
let ret = this.baseExp; let ret = this.baseExp;
switch (this.getFormSpriteKey()) { switch (this.getFormSpriteKey()) {
case SpeciesFormKey.MEGA: case SpeciesFormKey.MEGA:
case SpeciesFormKey.MEGA_X: case SpeciesFormKey.MEGA_X:
case SpeciesFormKey.MEGA_Y: case SpeciesFormKey.MEGA_Y:
case SpeciesFormKey.PRIMAL: case SpeciesFormKey.PRIMAL:
case SpeciesFormKey.GIGANTAMAX: case SpeciesFormKey.GIGANTAMAX:
case SpeciesFormKey.ETERNAMAX: case SpeciesFormKey.ETERNAMAX:
ret *= 1.5; ret *= 1.5;
break; break;
} }
return ret; return ret;
} }
@ -346,29 +346,29 @@ export abstract class PokemonSpeciesForm {
} }
switch (this.speciesId) { switch (this.speciesId) {
case Species.HIPPOPOTAS: case Species.HIPPOPOTAS:
case Species.HIPPOWDON: case Species.HIPPOWDON:
case Species.UNFEZANT: case Species.UNFEZANT:
case Species.FRILLISH: case Species.FRILLISH:
case Species.JELLICENT: case Species.JELLICENT:
case Species.PYROAR: case Species.PYROAR:
ret += female ? "-f" : ""; ret += female ? "-f" : "";
break; break;
} }
let formSpriteKey = this.getFormSpriteKey(formIndex); let formSpriteKey = this.getFormSpriteKey(formIndex);
if (formSpriteKey) { if (formSpriteKey) {
switch (this.speciesId) { switch (this.speciesId) {
case Species.DUDUNSPARCE: case Species.DUDUNSPARCE:
break; break;
case Species.ZACIAN: case Species.ZACIAN:
case Species.ZAMAZENTA: case Species.ZAMAZENTA:
if (formSpriteKey.startsWith("behemoth")) { if (formSpriteKey.startsWith("behemoth")) {
formSpriteKey = "crowned"; formSpriteKey = "crowned";
} }
default: default:
ret += `-${formSpriteKey}`; ret += `-${formSpriteKey}`;
break; break;
} }
} }
@ -383,15 +383,15 @@ export abstract class PokemonSpeciesForm {
let speciesId = this.speciesId; let speciesId = this.speciesId;
if (this.speciesId > 2000) { if (this.speciesId > 2000) {
switch (this.speciesId) { switch (this.speciesId) {
case Species.GALAR_SLOWPOKE: case Species.GALAR_SLOWPOKE:
break; break;
case Species.ETERNAL_FLOETTE: case Species.ETERNAL_FLOETTE:
break; break;
case Species.BLOODMOON_URSALUNA: case Species.BLOODMOON_URSALUNA:
break; break;
default: default:
speciesId = speciesId % 2000; speciesId = speciesId % 2000;
break; break;
} }
} }
let ret = speciesId.toString(); let ret = speciesId.toString();
@ -403,44 +403,44 @@ export abstract class PokemonSpeciesForm {
} }
const formKey = forms[formIndex || 0].formKey; const formKey = forms[formIndex || 0].formKey;
switch (formKey) { switch (formKey) {
case SpeciesFormKey.MEGA: case SpeciesFormKey.MEGA:
case SpeciesFormKey.MEGA_X: case SpeciesFormKey.MEGA_X:
case SpeciesFormKey.MEGA_Y: case SpeciesFormKey.MEGA_Y:
case SpeciesFormKey.GIGANTAMAX: case SpeciesFormKey.GIGANTAMAX:
case SpeciesFormKey.GIGANTAMAX_SINGLE: case SpeciesFormKey.GIGANTAMAX_SINGLE:
case SpeciesFormKey.GIGANTAMAX_RAPID: case SpeciesFormKey.GIGANTAMAX_RAPID:
case "white": case "white":
case "black": case "black":
case "therian": case "therian":
case "sky": case "sky":
case "gorging": case "gorging":
case "gulping": case "gulping":
case "no-ice": case "no-ice":
case "hangry": case "hangry":
case "crowned": case "crowned":
case "eternamax": case "eternamax":
case "four": case "four":
case "droopy": case "droopy":
case "stretchy": case "stretchy":
case "hero": case "hero":
case "roaming": case "roaming":
case "complete": case "complete":
case "10-complete": case "10-complete":
case "10": case "10":
case "10-pc": case "10-pc":
case "super": case "super":
case "unbound": case "unbound":
case "pau": case "pau":
case "pompom": case "pompom":
case "sensu": case "sensu":
case "dusk": case "dusk":
case "midnight": case "midnight":
case "school": case "school":
case "dawn-wings": case "dawn-wings":
case "dusk-mane": case "dusk-mane":
case "ultra": case "ultra":
ret += `-${formKey}`; ret += `-${formKey}`;
break; break;
} }
} }
return ret; return ret;
@ -636,19 +636,19 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
const form = this.forms[formIndex]; const form = this.forms[formIndex];
let key: string | null; let key: string | null;
switch (form.formKey) { switch (form.formKey) {
case SpeciesFormKey.MEGA: case SpeciesFormKey.MEGA:
case SpeciesFormKey.PRIMAL: case SpeciesFormKey.PRIMAL:
case SpeciesFormKey.ETERNAMAX: case SpeciesFormKey.ETERNAMAX:
case SpeciesFormKey.MEGA_X: case SpeciesFormKey.MEGA_X:
case SpeciesFormKey.MEGA_Y: case SpeciesFormKey.MEGA_Y:
key = form.formKey; key = form.formKey;
break; break;
default: default:
if (form.formKey.indexOf(SpeciesFormKey.GIGANTAMAX) > -1) { if (form.formKey.indexOf(SpeciesFormKey.GIGANTAMAX) > -1) {
key = "gigantamax"; key = "gigantamax";
} else { } else {
key = null; key = null;
} }
} }
if (key) { if (key) {
@ -690,18 +690,18 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
*/ */
private getStrengthLevelDiff(strength: PartyMemberStrength): integer { private getStrengthLevelDiff(strength: PartyMemberStrength): integer {
switch (Math.min(strength, PartyMemberStrength.STRONGER)) { switch (Math.min(strength, PartyMemberStrength.STRONGER)) {
case PartyMemberStrength.WEAKEST: case PartyMemberStrength.WEAKEST:
return 60; return 60;
case PartyMemberStrength.WEAKER: case PartyMemberStrength.WEAKER:
return 40; return 40;
case PartyMemberStrength.WEAK: case PartyMemberStrength.WEAK:
return 20; return 20;
case PartyMemberStrength.AVERAGE: case PartyMemberStrength.AVERAGE:
return 8; return 8;
case PartyMemberStrength.STRONG: case PartyMemberStrength.STRONG:
return 4; return 4;
default: default:
return 0; return 0;
} }
} }

View File

@ -26,20 +26,20 @@ export class Status {
function getStatusEffectMessageKey(statusEffect: StatusEffect | undefined): string { function getStatusEffectMessageKey(statusEffect: StatusEffect | undefined): string {
switch (statusEffect) { switch (statusEffect) {
case StatusEffect.POISON: case StatusEffect.POISON:
return "statusEffect:poison"; return "statusEffect:poison";
case StatusEffect.TOXIC: case StatusEffect.TOXIC:
return "statusEffect:toxic"; return "statusEffect:toxic";
case StatusEffect.PARALYSIS: case StatusEffect.PARALYSIS:
return "statusEffect:paralysis"; return "statusEffect:paralysis";
case StatusEffect.SLEEP: case StatusEffect.SLEEP:
return "statusEffect:sleep"; return "statusEffect:sleep";
case StatusEffect.FREEZE: case StatusEffect.FREEZE:
return "statusEffect:freeze"; return "statusEffect:freeze";
case StatusEffect.BURN: case StatusEffect.BURN:
return "statusEffect:burn"; return "statusEffect:burn";
default: default:
return "statusEffect:none"; return "statusEffect:none";
} }
} }
@ -90,14 +90,14 @@ export function getStatusEffectDescriptor(statusEffect: StatusEffect): string {
export function getStatusEffectCatchRateMultiplier(statusEffect: StatusEffect): number { export function getStatusEffectCatchRateMultiplier(statusEffect: StatusEffect): number {
switch (statusEffect) { switch (statusEffect) {
case StatusEffect.POISON: case StatusEffect.POISON:
case StatusEffect.TOXIC: case StatusEffect.TOXIC:
case StatusEffect.PARALYSIS: case StatusEffect.PARALYSIS:
case StatusEffect.BURN: case StatusEffect.BURN:
return 1.5; return 1.5;
case StatusEffect.SLEEP: case StatusEffect.SLEEP:
case StatusEffect.FREEZE: case StatusEffect.FREEZE:
return 2.5; return 2.5;
} }
return 1; return 1;

View File

@ -34,21 +34,21 @@ export class Terrain {
getAttackTypeMultiplier(attackType: Type): number { getAttackTypeMultiplier(attackType: Type): number {
switch (this.terrainType) { switch (this.terrainType) {
case TerrainType.ELECTRIC: case TerrainType.ELECTRIC:
if (attackType === Type.ELECTRIC) { if (attackType === Type.ELECTRIC) {
return 1.3; return 1.3;
} }
break; break;
case TerrainType.GRASSY: case TerrainType.GRASSY:
if (attackType === Type.GRASS) { if (attackType === Type.GRASS) {
return 1.3; return 1.3;
} }
break; break;
case TerrainType.PSYCHIC: case TerrainType.PSYCHIC:
if (attackType === Type.PSYCHIC) { if (attackType === Type.PSYCHIC) {
return 1.3; return 1.3;
} }
break; break;
} }
return 1; return 1;
@ -56,13 +56,13 @@ export class Terrain {
isMoveTerrainCancelled(user: Pokemon, targets: BattlerIndex[], move: Move): boolean { isMoveTerrainCancelled(user: Pokemon, targets: BattlerIndex[], move: Move): boolean {
switch (this.terrainType) { switch (this.terrainType) {
case TerrainType.PSYCHIC: case TerrainType.PSYCHIC:
if (!move.hasAttr(ProtectAttr)) { if (!move.hasAttr(ProtectAttr)) {
const priority = new Utils.IntegerHolder(move.priority); const priority = new Utils.IntegerHolder(move.priority);
applyAbAttrs(ChangeMovePriorityAbAttr, user, null, false, move, priority); applyAbAttrs(ChangeMovePriorityAbAttr, user, null, false, move, priority);
// Cancels move if the move has positive priority and targets a Pokemon grounded on the Psychic Terrain // Cancels move if the move has positive priority and targets a Pokemon grounded on the Psychic Terrain
return priority.value > 0 && user.getOpponents().some(o => targets.includes(o.getBattlerIndex()) && o.isGrounded()); return priority.value > 0 && user.getOpponents().some(o => targets.includes(o.getBattlerIndex()) && o.isGrounded());
} }
} }
return false; return false;
@ -71,14 +71,14 @@ export class Terrain {
export function getTerrainName(terrainType: TerrainType): string { export function getTerrainName(terrainType: TerrainType): string {
switch (terrainType) { switch (terrainType) {
case TerrainType.MISTY: case TerrainType.MISTY:
return i18next.t("terrain:misty"); return i18next.t("terrain:misty");
case TerrainType.ELECTRIC: case TerrainType.ELECTRIC:
return i18next.t("terrain:electric"); return i18next.t("terrain:electric");
case TerrainType.GRASSY: case TerrainType.GRASSY:
return i18next.t("terrain:grassy"); return i18next.t("terrain:grassy");
case TerrainType.PSYCHIC: case TerrainType.PSYCHIC:
return i18next.t("terrain:psychic"); return i18next.t("terrain:psychic");
} }
return ""; return "";
@ -87,14 +87,14 @@ export function getTerrainName(terrainType: TerrainType): string {
export function getTerrainColor(terrainType: TerrainType): [ integer, integer, integer ] { export function getTerrainColor(terrainType: TerrainType): [ integer, integer, integer ] {
switch (terrainType) { switch (terrainType) {
case TerrainType.MISTY: case TerrainType.MISTY:
return [ 232, 136, 200 ]; return [ 232, 136, 200 ];
case TerrainType.ELECTRIC: case TerrainType.ELECTRIC:
return [ 248, 248, 120 ]; return [ 248, 248, 120 ];
case TerrainType.GRASSY: case TerrainType.GRASSY:
return [ 120, 200, 80 ]; return [ 120, 200, 80 ];
case TerrainType.PSYCHIC: case TerrainType.PSYCHIC:
return [ 160, 64, 160 ]; return [ 160, 64, 160 ];
} }
return [ 0, 0, 0 ]; return [ 0, 0, 0 ];

View File

@ -299,65 +299,65 @@ export class TrainerConfig {
getDerivedType(trainerTypeToDeriveFrom: TrainerType | null = null): TrainerType { getDerivedType(trainerTypeToDeriveFrom: TrainerType | null = null): TrainerType {
let trainerType = trainerTypeToDeriveFrom ? trainerTypeToDeriveFrom : this.trainerType; let trainerType = trainerTypeToDeriveFrom ? trainerTypeToDeriveFrom : this.trainerType;
switch (trainerType) { switch (trainerType) {
case TrainerType.RIVAL_2: case TrainerType.RIVAL_2:
case TrainerType.RIVAL_3: case TrainerType.RIVAL_3:
case TrainerType.RIVAL_4: case TrainerType.RIVAL_4:
case TrainerType.RIVAL_5: case TrainerType.RIVAL_5:
case TrainerType.RIVAL_6: case TrainerType.RIVAL_6:
trainerType = TrainerType.RIVAL; trainerType = TrainerType.RIVAL;
break; break;
case TrainerType.LANCE_CHAMPION: case TrainerType.LANCE_CHAMPION:
trainerType = TrainerType.LANCE; trainerType = TrainerType.LANCE;
break; break;
case TrainerType.LARRY_ELITE: case TrainerType.LARRY_ELITE:
trainerType = TrainerType.LARRY; trainerType = TrainerType.LARRY;
break; break;
case TrainerType.ROCKET_BOSS_GIOVANNI_1: case TrainerType.ROCKET_BOSS_GIOVANNI_1:
case TrainerType.ROCKET_BOSS_GIOVANNI_2: case TrainerType.ROCKET_BOSS_GIOVANNI_2:
trainerType = TrainerType.GIOVANNI; trainerType = TrainerType.GIOVANNI;
break; break;
case TrainerType.MAXIE_2: case TrainerType.MAXIE_2:
trainerType = TrainerType.MAXIE; trainerType = TrainerType.MAXIE;
break; break;
case TrainerType.ARCHIE_2: case TrainerType.ARCHIE_2:
trainerType = TrainerType.ARCHIE; trainerType = TrainerType.ARCHIE;
break; break;
case TrainerType.CYRUS_2: case TrainerType.CYRUS_2:
trainerType = TrainerType.CYRUS; trainerType = TrainerType.CYRUS;
break; break;
case TrainerType.GHETSIS_2: case TrainerType.GHETSIS_2:
trainerType = TrainerType.GHETSIS; trainerType = TrainerType.GHETSIS;
break; break;
case TrainerType.LYSANDRE_2: case TrainerType.LYSANDRE_2:
trainerType = TrainerType.LYSANDRE; trainerType = TrainerType.LYSANDRE;
break; break;
case TrainerType.LUSAMINE_2: case TrainerType.LUSAMINE_2:
trainerType = TrainerType.LUSAMINE; trainerType = TrainerType.LUSAMINE;
break; break;
case TrainerType.GUZMA_2: case TrainerType.GUZMA_2:
trainerType = TrainerType.GUZMA; trainerType = TrainerType.GUZMA;
break; break;
case TrainerType.ROSE_2: case TrainerType.ROSE_2:
trainerType = TrainerType.ROSE; trainerType = TrainerType.ROSE;
break; break;
case TrainerType.PENNY_2: case TrainerType.PENNY_2:
trainerType = TrainerType.PENNY; trainerType = TrainerType.PENNY;
break; break;
case TrainerType.MARNIE_ELITE: case TrainerType.MARNIE_ELITE:
trainerType = TrainerType.MARNIE; trainerType = TrainerType.MARNIE;
break; break;
case TrainerType.NESSA_ELITE: case TrainerType.NESSA_ELITE:
trainerType = TrainerType.NESSA; trainerType = TrainerType.NESSA;
break; break;
case TrainerType.BEA_ELITE: case TrainerType.BEA_ELITE:
trainerType = TrainerType.BEA; trainerType = TrainerType.BEA;
break; break;
case TrainerType.ALLISTER_ELITE: case TrainerType.ALLISTER_ELITE:
trainerType = TrainerType.ALLISTER; trainerType = TrainerType.ALLISTER;
break; break;
case TrainerType.RAIHAN_ELITE: case TrainerType.RAIHAN_ELITE:
trainerType = TrainerType.RAIHAN; trainerType = TrainerType.RAIHAN;
break; break;
} }
return trainerType; return trainerType;
@ -564,104 +564,104 @@ export class TrainerConfig {
speciesPoolPerEvilTeamAdmin(team): TrainerTierPools { speciesPoolPerEvilTeamAdmin(team): TrainerTierPools {
team = team.toLowerCase(); team = team.toLowerCase();
switch (team) { switch (team) {
case "rocket": { case "rocket": {
return { return {
[TrainerPoolTier.COMMON]: [ Species.RATTATA, Species.KOFFING, Species.EKANS, Species.ZUBAT, Species.MAGIKARP, Species.HOUNDOUR, Species.ONIX, Species.CUBONE, Species.GROWLITHE, Species.MURKROW, Species.GASTLY, Species.EXEGGCUTE, Species.VOLTORB, Species.DROWZEE, Species.VILEPLUME ], [TrainerPoolTier.COMMON]: [ Species.RATTATA, Species.KOFFING, Species.EKANS, Species.ZUBAT, Species.MAGIKARP, Species.HOUNDOUR, Species.ONIX, Species.CUBONE, Species.GROWLITHE, Species.MURKROW, Species.GASTLY, Species.EXEGGCUTE, Species.VOLTORB, Species.DROWZEE, Species.VILEPLUME ],
[TrainerPoolTier.UNCOMMON]: [ Species.PORYGON, Species.MANKEY, Species.MAGNEMITE, Species.ALOLA_SANDSHREW, Species.ALOLA_MEOWTH, Species.ALOLA_GRIMER, Species.ALOLA_GEODUDE, Species.PALDEA_TAUROS, Species.OMANYTE, Species.KABUTO, Species.MAGBY, Species.ELEKID ], [TrainerPoolTier.UNCOMMON]: [ Species.PORYGON, Species.MANKEY, Species.MAGNEMITE, Species.ALOLA_SANDSHREW, Species.ALOLA_MEOWTH, Species.ALOLA_GRIMER, Species.ALOLA_GEODUDE, Species.PALDEA_TAUROS, Species.OMANYTE, Species.KABUTO, Species.MAGBY, Species.ELEKID ],
[TrainerPoolTier.RARE]: [ Species.DRATINI, Species.LARVITAR ] [TrainerPoolTier.RARE]: [ Species.DRATINI, Species.LARVITAR ]
}; };
} }
case "magma": { case "magma": {
return { return {
[TrainerPoolTier.COMMON]: [ Species.GROWLITHE, Species.SLUGMA, Species.SOLROCK, Species.HIPPOPOTAS, Species.BALTOY, Species.ROLYCOLY, Species.GLIGAR, Species.TORKOAL, Species.HOUNDOUR, Species.MAGBY ], [TrainerPoolTier.COMMON]: [ Species.GROWLITHE, Species.SLUGMA, Species.SOLROCK, Species.HIPPOPOTAS, Species.BALTOY, Species.ROLYCOLY, Species.GLIGAR, Species.TORKOAL, Species.HOUNDOUR, Species.MAGBY ],
[TrainerPoolTier.UNCOMMON]: [ Species.TRAPINCH, Species.SILICOBRA, Species.RHYHORN, Species.ANORITH, Species.LILEEP, Species.HISUI_GROWLITHE, Species.TURTONATOR, Species.ARON, Species.TOEDSCOOL ], [TrainerPoolTier.UNCOMMON]: [ Species.TRAPINCH, Species.SILICOBRA, Species.RHYHORN, Species.ANORITH, Species.LILEEP, Species.HISUI_GROWLITHE, Species.TURTONATOR, Species.ARON, Species.TOEDSCOOL ],
[TrainerPoolTier.RARE]: [ Species.CAPSAKID, Species.CHARCADET ] [TrainerPoolTier.RARE]: [ Species.CAPSAKID, Species.CHARCADET ]
}; };
} }
case "aqua": { case "aqua": {
return { return {
[TrainerPoolTier.COMMON]: [ Species.CORPHISH, Species.SPHEAL, Species.CLAMPERL, Species.CHINCHOU, Species.WOOPER, Species.WINGULL, Species.TENTACOOL, Species.AZURILL, Species.LOTAD, Species.WAILMER, Species.REMORAID, Species.BARBOACH ], [TrainerPoolTier.COMMON]: [ Species.CORPHISH, Species.SPHEAL, Species.CLAMPERL, Species.CHINCHOU, Species.WOOPER, Species.WINGULL, Species.TENTACOOL, Species.AZURILL, Species.LOTAD, Species.WAILMER, Species.REMORAID, Species.BARBOACH ],
[TrainerPoolTier.UNCOMMON]: [ Species.MANTYKE, Species.HISUI_QWILFISH, Species.ARROKUDA, Species.DHELMISE, Species.CLOBBOPUS, Species.FEEBAS, Species.PALDEA_WOOPER, Species.HORSEA, Species.SKRELP ], [TrainerPoolTier.UNCOMMON]: [ Species.MANTYKE, Species.HISUI_QWILFISH, Species.ARROKUDA, Species.DHELMISE, Species.CLOBBOPUS, Species.FEEBAS, Species.PALDEA_WOOPER, Species.HORSEA, Species.SKRELP ],
[TrainerPoolTier.RARE]: [ Species.DONDOZO, Species.BASCULEGION ] [TrainerPoolTier.RARE]: [ Species.DONDOZO, Species.BASCULEGION ]
}; };
} }
case "galactic": { case "galactic": {
return { return {
[TrainerPoolTier.COMMON]: [ Species.BRONZOR, Species.SWINUB, Species.YANMA, Species.LICKITUNG, Species.TANGELA, Species.MAGBY, Species.ELEKID, Species.SKORUPI, Species.ZUBAT, Species.MURKROW, Species.MAGIKARP, Species.VOLTORB ], [TrainerPoolTier.COMMON]: [ Species.BRONZOR, Species.SWINUB, Species.YANMA, Species.LICKITUNG, Species.TANGELA, Species.MAGBY, Species.ELEKID, Species.SKORUPI, Species.ZUBAT, Species.MURKROW, Species.MAGIKARP, Species.VOLTORB ],
[TrainerPoolTier.UNCOMMON]: [ Species.HISUI_GROWLITHE, Species.HISUI_QWILFISH, Species.SNEASEL, Species.DUSKULL, Species.ROTOM, Species.HISUI_VOLTORB, Species.GLIGAR, Species.ABRA ], [TrainerPoolTier.UNCOMMON]: [ Species.HISUI_GROWLITHE, Species.HISUI_QWILFISH, Species.SNEASEL, Species.DUSKULL, Species.ROTOM, Species.HISUI_VOLTORB, Species.GLIGAR, Species.ABRA ],
[TrainerPoolTier.RARE]: [ Species.URSALUNA, Species.HISUI_LILLIGANT, Species.SPIRITOMB, Species.HISUI_SNEASEL ] [TrainerPoolTier.RARE]: [ Species.URSALUNA, Species.HISUI_LILLIGANT, Species.SPIRITOMB, Species.HISUI_SNEASEL ]
}; };
} }
case "plasma": { case "plasma": {
return { return {
[TrainerPoolTier.COMMON]: [ Species.YAMASK, Species.ROGGENROLA, Species.JOLTIK, Species.TYMPOLE, Species.FRILLISH, Species.FERROSEED, Species.SANDILE, Species.TIMBURR, Species.DARUMAKA, Species.FOONGUS, Species.CUBCHOO, Species.VANILLITE ], [TrainerPoolTier.COMMON]: [ Species.YAMASK, Species.ROGGENROLA, Species.JOLTIK, Species.TYMPOLE, Species.FRILLISH, Species.FERROSEED, Species.SANDILE, Species.TIMBURR, Species.DARUMAKA, Species.FOONGUS, Species.CUBCHOO, Species.VANILLITE ],
[TrainerPoolTier.UNCOMMON]: [ Species.PAWNIARD, Species.VULLABY, Species.ZORUA, Species.DRILBUR, Species.KLINK, Species.TYNAMO, Species.GALAR_DARUMAKA, Species.GOLETT, Species.MIENFOO, Species.DURANT, Species.SIGILYPH ], [TrainerPoolTier.UNCOMMON]: [ Species.PAWNIARD, Species.VULLABY, Species.ZORUA, Species.DRILBUR, Species.KLINK, Species.TYNAMO, Species.GALAR_DARUMAKA, Species.GOLETT, Species.MIENFOO, Species.DURANT, Species.SIGILYPH ],
[TrainerPoolTier.RARE]: [ Species.HISUI_ZORUA, Species.AXEW, Species.DEINO, Species.HISUI_BRAVIARY ] [TrainerPoolTier.RARE]: [ Species.HISUI_ZORUA, Species.AXEW, Species.DEINO, Species.HISUI_BRAVIARY ]
}; };
} }
case "flare": { case "flare": {
return { return {
[TrainerPoolTier.COMMON]: [ Species.FLETCHLING, Species.LITLEO, Species.INKAY, Species.FOONGUS, Species.HELIOPTILE, Species.ELECTRIKE, Species.SKORUPI, Species.PURRLOIN, Species.CLAWITZER, Species.PANCHAM, Species.ESPURR, Species.BUNNELBY ], [TrainerPoolTier.COMMON]: [ Species.FLETCHLING, Species.LITLEO, Species.INKAY, Species.FOONGUS, Species.HELIOPTILE, Species.ELECTRIKE, Species.SKORUPI, Species.PURRLOIN, Species.CLAWITZER, Species.PANCHAM, Species.ESPURR, Species.BUNNELBY ],
[TrainerPoolTier.UNCOMMON]: [ Species.LITWICK, Species.SNEASEL, Species.PUMPKABOO, Species.PHANTUMP, Species.HONEDGE, Species.BINACLE, Species.HOUNDOUR, Species.SKRELP, Species.SLIGGOO ], [TrainerPoolTier.UNCOMMON]: [ Species.LITWICK, Species.SNEASEL, Species.PUMPKABOO, Species.PHANTUMP, Species.HONEDGE, Species.BINACLE, Species.HOUNDOUR, Species.SKRELP, Species.SLIGGOO ],
[TrainerPoolTier.RARE]: [ Species.NOIBAT, Species.HISUI_AVALUGG, Species.HISUI_SLIGGOO ] [TrainerPoolTier.RARE]: [ Species.NOIBAT, Species.HISUI_AVALUGG, Species.HISUI_SLIGGOO ]
}; };
} }
case "aether": { case "aether": {
return { return {
[TrainerPoolTier.COMMON]: [ Species.BRUXISH, Species.SLOWPOKE, Species.BALTOY, Species.EXEGGCUTE, Species.ABRA, Species.ALOLA_RAICHU, Species.ELGYEM, Species.NATU, Species.BLIPBUG, Species.GIRAFARIG, Species.ORANGURU ], [TrainerPoolTier.COMMON]: [ Species.BRUXISH, Species.SLOWPOKE, Species.BALTOY, Species.EXEGGCUTE, Species.ABRA, Species.ALOLA_RAICHU, Species.ELGYEM, Species.NATU, Species.BLIPBUG, Species.GIRAFARIG, Species.ORANGURU ],
[TrainerPoolTier.UNCOMMON]: [ Species.GALAR_SLOWPOKE, Species.MEDITITE, Species.BELDUM, Species.HATENNA, Species.INKAY, Species.RALTS, Species.GALAR_MR_MIME ], [TrainerPoolTier.UNCOMMON]: [ Species.GALAR_SLOWPOKE, Species.MEDITITE, Species.BELDUM, Species.HATENNA, Species.INKAY, Species.RALTS, Species.GALAR_MR_MIME ],
[TrainerPoolTier.RARE]: [ Species.ARMAROUGE, Species.HISUI_BRAVIARY, Species.PORYGON ] [TrainerPoolTier.RARE]: [ Species.ARMAROUGE, Species.HISUI_BRAVIARY, Species.PORYGON ]
}; };
} }
case "skull": { case "skull": {
return { return {
[TrainerPoolTier.COMMON]: [ Species.MAREANIE, Species.ALOLA_GRIMER, Species.GASTLY, Species.ZUBAT, Species.FOMANTIS, Species.VENIPEDE, Species.BUDEW, Species.KOFFING, Species.STUNKY, Species.CROAGUNK, Species.NIDORAN_F ], [TrainerPoolTier.COMMON]: [ Species.MAREANIE, Species.ALOLA_GRIMER, Species.GASTLY, Species.ZUBAT, Species.FOMANTIS, Species.VENIPEDE, Species.BUDEW, Species.KOFFING, Species.STUNKY, Species.CROAGUNK, Species.NIDORAN_F ],
[TrainerPoolTier.UNCOMMON]: [ Species.GALAR_SLOWPOKE, Species.SKORUPI, Species.PALDEA_WOOPER, Species.VULLABY, Species.HISUI_QWILFISH, Species.GLIMMET ], [TrainerPoolTier.UNCOMMON]: [ Species.GALAR_SLOWPOKE, Species.SKORUPI, Species.PALDEA_WOOPER, Species.VULLABY, Species.HISUI_QWILFISH, Species.GLIMMET ],
[TrainerPoolTier.RARE]: [ Species.SKRELP, Species.HISUI_SNEASEL ] [TrainerPoolTier.RARE]: [ Species.SKRELP, Species.HISUI_SNEASEL ]
}; };
} }
case "macro": { case "macro": {
return { return {
[TrainerPoolTier.COMMON]: [ Species.HATENNA, Species.FEEBAS, Species.BOUNSWEET, Species.SALANDIT, Species.GALAR_PONYTA, Species.GOTHITA, Species.FROSLASS, Species.VULPIX, Species.FRILLISH, Species.ODDISH, Species.SINISTEA ], [TrainerPoolTier.COMMON]: [ Species.HATENNA, Species.FEEBAS, Species.BOUNSWEET, Species.SALANDIT, Species.GALAR_PONYTA, Species.GOTHITA, Species.FROSLASS, Species.VULPIX, Species.FRILLISH, Species.ODDISH, Species.SINISTEA ],
[TrainerPoolTier.UNCOMMON]: [ Species.VULLABY, Species.MAREANIE, Species.ALOLA_VULPIX, Species.TOGEPI, Species.GALAR_CORSOLA, Species.APPLIN ], [TrainerPoolTier.UNCOMMON]: [ Species.VULLABY, Species.MAREANIE, Species.ALOLA_VULPIX, Species.TOGEPI, Species.GALAR_CORSOLA, Species.APPLIN ],
[TrainerPoolTier.RARE]: [ Species.TINKATINK, Species.HISUI_LILLIGANT ] [TrainerPoolTier.RARE]: [ Species.TINKATINK, Species.HISUI_LILLIGANT ]
}; };
} }
case "star_1": { case "star_1": {
return { return {
[TrainerPoolTier.COMMON]: [ Species.MURKROW, Species.SEEDOT, Species.CACNEA, Species.STUNKY, Species.SANDILE, Species.NYMBLE, Species.MASCHIFF, Species.GALAR_ZIGZAGOON ], [TrainerPoolTier.COMMON]: [ Species.MURKROW, Species.SEEDOT, Species.CACNEA, Species.STUNKY, Species.SANDILE, Species.NYMBLE, Species.MASCHIFF, Species.GALAR_ZIGZAGOON ],
[TrainerPoolTier.UNCOMMON]: [ Species.UMBREON, Species.SNEASEL, Species.CORPHISH, Species.ZORUA, Species.INKAY, Species.BOMBIRDIER ], [TrainerPoolTier.UNCOMMON]: [ Species.UMBREON, Species.SNEASEL, Species.CORPHISH, Species.ZORUA, Species.INKAY, Species.BOMBIRDIER ],
[TrainerPoolTier.RARE]: [ Species.DEINO, Species.SPRIGATITO ] [TrainerPoolTier.RARE]: [ Species.DEINO, Species.SPRIGATITO ]
}; };
} }
case "star_2": { case "star_2": {
return { return {
[TrainerPoolTier.COMMON]: [ Species.GROWLITHE, Species.HOUNDOUR, Species.NUMEL, Species.LITWICK, Species.FLETCHLING, Species.LITLEO, Species.ROLYCOLY, Species.CAPSAKID ], [TrainerPoolTier.COMMON]: [ Species.GROWLITHE, Species.HOUNDOUR, Species.NUMEL, Species.LITWICK, Species.FLETCHLING, Species.LITLEO, Species.ROLYCOLY, Species.CAPSAKID ],
[TrainerPoolTier.UNCOMMON]: [ Species.PONYTA, Species.FLAREON, Species.MAGBY, Species.TORKOAL, Species.SALANDIT, Species.TURTONATOR ], [TrainerPoolTier.UNCOMMON]: [ Species.PONYTA, Species.FLAREON, Species.MAGBY, Species.TORKOAL, Species.SALANDIT, Species.TURTONATOR ],
[TrainerPoolTier.RARE]: [ Species.LARVESTA, Species.FUECOCO ] [TrainerPoolTier.RARE]: [ Species.LARVESTA, Species.FUECOCO ]
}; };
} }
case "star_3": { case "star_3": {
return { return {
[TrainerPoolTier.COMMON]: [ Species.ZUBAT, Species.GRIMER, Species.STUNKY, Species.FOONGUS, Species.MAREANIE, Species.TOXEL, Species.SHROODLE, Species.PALDEA_WOOPER ], [TrainerPoolTier.COMMON]: [ Species.ZUBAT, Species.GRIMER, Species.STUNKY, Species.FOONGUS, Species.MAREANIE, Species.TOXEL, Species.SHROODLE, Species.PALDEA_WOOPER ],
[TrainerPoolTier.UNCOMMON]: [ Species.GASTLY, Species.SEVIPER, Species.SKRELP, Species.ALOLA_GRIMER, Species.GALAR_SLOWPOKE, Species.HISUI_QWILFISH ], [TrainerPoolTier.UNCOMMON]: [ Species.GASTLY, Species.SEVIPER, Species.SKRELP, Species.ALOLA_GRIMER, Species.GALAR_SLOWPOKE, Species.HISUI_QWILFISH ],
[TrainerPoolTier.RARE]: [ Species.GLIMMET, Species.BULBASAUR ] [TrainerPoolTier.RARE]: [ Species.GLIMMET, Species.BULBASAUR ]
}; };
} }
case "star_4": { case "star_4": {
return { return {
[TrainerPoolTier.COMMON]: [ Species.CLEFFA, Species.IGGLYBUFF, Species.AZURILL, Species.COTTONEE, Species.FLABEBE, Species.HATENNA, Species.IMPIDIMP, Species.TINKATINK ], [TrainerPoolTier.COMMON]: [ Species.CLEFFA, Species.IGGLYBUFF, Species.AZURILL, Species.COTTONEE, Species.FLABEBE, Species.HATENNA, Species.IMPIDIMP, Species.TINKATINK ],
[TrainerPoolTier.UNCOMMON]: [ Species.TOGEPI, Species.GARDEVOIR, Species.SYLVEON, Species.KLEFKI, Species.MIMIKYU, Species.ALOLA_VULPIX ], [TrainerPoolTier.UNCOMMON]: [ Species.TOGEPI, Species.GARDEVOIR, Species.SYLVEON, Species.KLEFKI, Species.MIMIKYU, Species.ALOLA_VULPIX ],
[TrainerPoolTier.RARE]: [ Species.GALAR_PONYTA, Species.POPPLIO ] [TrainerPoolTier.RARE]: [ Species.GALAR_PONYTA, Species.POPPLIO ]
}; };
} }
case "star_5": { case "star_5": {
return { return {
[TrainerPoolTier.COMMON]: [ Species.SHROOMISH, Species.MAKUHITA, Species.MEDITITE, Species.CROAGUNK, Species.SCRAGGY, Species.MIENFOO, Species.PAWMI, Species.PALDEA_TAUROS ], [TrainerPoolTier.COMMON]: [ Species.SHROOMISH, Species.MAKUHITA, Species.MEDITITE, Species.CROAGUNK, Species.SCRAGGY, Species.MIENFOO, Species.PAWMI, Species.PALDEA_TAUROS ],
[TrainerPoolTier.UNCOMMON]: [ Species.RIOLU, Species.TIMBURR, Species.HAWLUCHA, Species.PASSIMIAN, Species.FALINKS, Species.FLAMIGO ], [TrainerPoolTier.UNCOMMON]: [ Species.RIOLU, Species.TIMBURR, Species.HAWLUCHA, Species.PASSIMIAN, Species.FALINKS, Species.FLAMIGO ],
[TrainerPoolTier.RARE]: [ Species.JANGMO_O, Species.QUAXLY ] [TrainerPoolTier.RARE]: [ Species.JANGMO_O, Species.QUAXLY ]
}; };
} }
} }
console.warn(`Evil team admin for ${team} not found. Returning empty species pools.`); console.warn(`Evil team admin for ${team} not found. Returning empty species pools.`);

View File

@ -29,260 +29,260 @@ export function getTypeDamageMultiplier(attackType: Type, defType: Type): TypeDa
} }
switch (defType) { switch (defType) {
case Type.NORMAL:
switch (attackType) {
case Type.FIGHTING:
return 2;
case Type.GHOST:
return 0;
default:
return 1;
}
case Type.FIGHTING:
switch (attackType) {
case Type.FLYING:
case Type.PSYCHIC:
case Type.FAIRY:
return 2;
case Type.ROCK:
case Type.BUG:
case Type.DARK:
return 0.5;
default:
return 1;
}
case Type.FLYING:
switch (attackType) {
case Type.ROCK:
case Type.ELECTRIC:
case Type.ICE:
return 2;
case Type.FIGHTING:
case Type.BUG:
case Type.GRASS:
return 0.5;
case Type.GROUND:
return 0;
default:
return 1;
}
case Type.POISON:
switch (attackType) {
case Type.GROUND:
case Type.PSYCHIC:
return 2;
case Type.FIGHTING:
case Type.POISON:
case Type.BUG:
case Type.GRASS:
case Type.FAIRY:
return 0.5;
default:
return 1;
}
case Type.GROUND:
switch (attackType) {
case Type.WATER:
case Type.GRASS:
case Type.ICE:
return 2;
case Type.POISON:
case Type.ROCK:
return 0.5;
case Type.ELECTRIC:
return 0;
default:
return 1;
}
case Type.ROCK:
switch (attackType) {
case Type.FIGHTING:
case Type.GROUND:
case Type.STEEL:
case Type.WATER:
case Type.GRASS:
return 2;
case Type.NORMAL: case Type.NORMAL:
case Type.FLYING: switch (attackType) {
case Type.POISON: case Type.FIGHTING:
case Type.FIRE: return 2;
return 0.5; case Type.GHOST:
default: return 0;
return 1; default:
} return 1;
case Type.BUG: }
switch (attackType) {
case Type.FLYING:
case Type.ROCK:
case Type.FIRE:
return 2;
case Type.FIGHTING: case Type.FIGHTING:
switch (attackType) {
case Type.FLYING:
case Type.PSYCHIC:
case Type.FAIRY:
return 2;
case Type.ROCK:
case Type.BUG:
case Type.DARK:
return 0.5;
default:
return 1;
}
case Type.FLYING:
switch (attackType) {
case Type.ROCK:
case Type.ELECTRIC:
case Type.ICE:
return 2;
case Type.FIGHTING:
case Type.BUG:
case Type.GRASS:
return 0.5;
case Type.GROUND:
return 0;
default:
return 1;
}
case Type.POISON:
switch (attackType) {
case Type.GROUND:
case Type.PSYCHIC:
return 2;
case Type.FIGHTING:
case Type.POISON:
case Type.BUG:
case Type.GRASS:
case Type.FAIRY:
return 0.5;
default:
return 1;
}
case Type.GROUND: case Type.GROUND:
case Type.GRASS: switch (attackType) {
return 0.5; case Type.WATER:
default: case Type.GRASS:
return 1; case Type.ICE:
} return 2;
case Type.GHOST: case Type.POISON:
switch (attackType) { case Type.ROCK:
return 0.5;
case Type.ELECTRIC:
return 0;
default:
return 1;
}
case Type.ROCK:
switch (attackType) {
case Type.FIGHTING:
case Type.GROUND:
case Type.STEEL:
case Type.WATER:
case Type.GRASS:
return 2;
case Type.NORMAL:
case Type.FLYING:
case Type.POISON:
case Type.FIRE:
return 0.5;
default:
return 1;
}
case Type.BUG:
switch (attackType) {
case Type.FLYING:
case Type.ROCK:
case Type.FIRE:
return 2;
case Type.FIGHTING:
case Type.GROUND:
case Type.GRASS:
return 0.5;
default:
return 1;
}
case Type.GHOST: case Type.GHOST:
case Type.DARK: switch (attackType) {
return 2; case Type.GHOST:
case Type.POISON: case Type.DARK:
case Type.BUG: return 2;
return 0.5; case Type.POISON:
case Type.NORMAL: case Type.BUG:
case Type.FIGHTING: return 0.5;
return 0; case Type.NORMAL:
default: case Type.FIGHTING:
return 1; return 0;
} default:
case Type.STEEL: return 1;
switch (attackType) { }
case Type.FIGHTING:
case Type.GROUND:
case Type.FIRE:
return 2;
case Type.NORMAL:
case Type.FLYING:
case Type.ROCK:
case Type.BUG:
case Type.STEEL: case Type.STEEL:
switch (attackType) {
case Type.FIGHTING:
case Type.GROUND:
case Type.FIRE:
return 2;
case Type.NORMAL:
case Type.FLYING:
case Type.ROCK:
case Type.BUG:
case Type.STEEL:
case Type.GRASS:
case Type.PSYCHIC:
case Type.ICE:
case Type.DRAGON:
case Type.FAIRY:
return 0.5;
case Type.POISON:
return 0;
default:
return 1;
}
case Type.FIRE:
switch (attackType) {
case Type.GROUND:
case Type.ROCK:
case Type.WATER:
return 2;
case Type.BUG:
case Type.STEEL:
case Type.FIRE:
case Type.GRASS:
case Type.ICE:
case Type.FAIRY:
return 0.5;
default:
return 1;
}
case Type.WATER:
switch (attackType) {
case Type.GRASS:
case Type.ELECTRIC:
return 2;
case Type.STEEL:
case Type.FIRE:
case Type.WATER:
case Type.ICE:
return 0.5;
default:
return 1;
}
case Type.GRASS: case Type.GRASS:
switch (attackType) {
case Type.FLYING:
case Type.POISON:
case Type.BUG:
case Type.FIRE:
case Type.ICE:
return 2;
case Type.GROUND:
case Type.WATER:
case Type.GRASS:
case Type.ELECTRIC:
return 0.5;
default:
return 1;
}
case Type.ELECTRIC:
switch (attackType) {
case Type.GROUND:
return 2;
case Type.FLYING:
case Type.STEEL:
case Type.ELECTRIC:
return 0.5;
default:
return 1;
}
case Type.PSYCHIC: case Type.PSYCHIC:
switch (attackType) {
case Type.BUG:
case Type.GHOST:
case Type.DARK:
return 2;
case Type.FIGHTING:
case Type.PSYCHIC:
return 0.5;
default:
return 1;
}
case Type.ICE: case Type.ICE:
switch (attackType) {
case Type.FIGHTING:
case Type.ROCK:
case Type.STEEL:
case Type.FIRE:
return 2;
case Type.ICE:
return 0.5;
default:
return 1;
}
case Type.DRAGON: case Type.DRAGON:
case Type.FAIRY: switch (attackType) {
return 0.5; case Type.ICE:
case Type.POISON: case Type.DRAGON:
return 0; case Type.FAIRY:
default: return 2;
return 1; case Type.FIRE:
} case Type.WATER:
case Type.FIRE: case Type.GRASS:
switch (attackType) { case Type.ELECTRIC:
case Type.GROUND: return 0.5;
case Type.ROCK: default:
case Type.WATER: return 1;
return 2; }
case Type.BUG:
case Type.STEEL:
case Type.FIRE:
case Type.GRASS:
case Type.ICE:
case Type.FAIRY:
return 0.5;
default:
return 1;
}
case Type.WATER:
switch (attackType) {
case Type.GRASS:
case Type.ELECTRIC:
return 2;
case Type.STEEL:
case Type.FIRE:
case Type.WATER:
case Type.ICE:
return 0.5;
default:
return 1;
}
case Type.GRASS:
switch (attackType) {
case Type.FLYING:
case Type.POISON:
case Type.BUG:
case Type.FIRE:
case Type.ICE:
return 2;
case Type.GROUND:
case Type.WATER:
case Type.GRASS:
case Type.ELECTRIC:
return 0.5;
default:
return 1;
}
case Type.ELECTRIC:
switch (attackType) {
case Type.GROUND:
return 2;
case Type.FLYING:
case Type.STEEL:
case Type.ELECTRIC:
return 0.5;
default:
return 1;
}
case Type.PSYCHIC:
switch (attackType) {
case Type.BUG:
case Type.GHOST:
case Type.DARK: case Type.DARK:
return 2; switch (attackType) {
case Type.FIGHTING: case Type.FIGHTING:
case Type.PSYCHIC: case Type.BUG:
return 0.5; case Type.FAIRY:
default: return 2;
return 1; case Type.GHOST:
} case Type.DARK:
case Type.ICE: return 0.5;
switch (attackType) { case Type.PSYCHIC:
case Type.FIGHTING: return 0;
case Type.ROCK: default:
case Type.STEEL: return 1;
case Type.FIRE: }
return 2;
case Type.ICE:
return 0.5;
default:
return 1;
}
case Type.DRAGON:
switch (attackType) {
case Type.ICE:
case Type.DRAGON:
case Type.FAIRY: case Type.FAIRY:
return 2; switch (attackType) {
case Type.FIRE: case Type.POISON:
case Type.WATER: case Type.STEEL:
case Type.GRASS: return 2;
case Type.ELECTRIC: case Type.FIGHTING:
return 0.5; case Type.BUG:
default: case Type.DARK:
return 0.5;
case Type.DRAGON:
return 0;
default:
return 1;
}
case Type.STELLAR:
return 1; return 1;
}
case Type.DARK:
switch (attackType) {
case Type.FIGHTING:
case Type.BUG:
case Type.FAIRY:
return 2;
case Type.GHOST:
case Type.DARK:
return 0.5;
case Type.PSYCHIC:
return 0;
default:
return 1;
}
case Type.FAIRY:
switch (attackType) {
case Type.POISON:
case Type.STEEL:
return 2;
case Type.FIGHTING:
case Type.BUG:
case Type.DARK:
return 0.5;
case Type.DRAGON:
return 0;
default:
return 1;
}
case Type.STELLAR:
return 1;
} }
return 1; return 1;
@ -295,86 +295,86 @@ export function getTypeDamageMultiplier(attackType: Type, defType: Type): TypeDa
export function getTypeDamageMultiplierColor(multiplier: TypeDamageMultiplier, side: "defense" | "offense"): string | undefined { export function getTypeDamageMultiplierColor(multiplier: TypeDamageMultiplier, side: "defense" | "offense"): string | undefined {
if (side === "offense") { if (side === "offense") {
switch (multiplier) { switch (multiplier) {
case 0: case 0:
return "#929292"; return "#929292";
case 0.125: case 0.125:
return "#FF5500"; return "#FF5500";
case 0.25: case 0.25:
return "#FF7400"; return "#FF7400";
case 0.5: case 0.5:
return "#FE8E00"; return "#FE8E00";
case 1: case 1:
return undefined; return undefined;
case 2: case 2:
return "#4AA500"; return "#4AA500";
case 4: case 4:
return "#4BB400"; return "#4BB400";
case 8: case 8:
return "#52C200"; return "#52C200";
} }
} else if (side === "defense") { } else if (side === "defense") {
switch (multiplier) { switch (multiplier) {
case 0: case 0:
return "#B1B100"; return "#B1B100";
case 0.125: case 0.125:
return "#2DB4FF"; return "#2DB4FF";
case 0.25: case 0.25:
return "#00A4FF"; return "#00A4FF";
case 0.5: case 0.5:
return "#0093FF"; return "#0093FF";
case 1: case 1:
return undefined; return undefined;
case 2: case 2:
return "#FE8E00"; return "#FE8E00";
case 4: case 4:
return "#FF7400"; return "#FF7400";
case 8: case 8:
return "#FF5500"; return "#FF5500";
} }
} }
} }
export function getTypeRgb(type: Type): [ integer, integer, integer ] { export function getTypeRgb(type: Type): [ integer, integer, integer ] {
switch (type) { switch (type) {
case Type.NORMAL: case Type.NORMAL:
return [ 168, 168, 120 ]; return [ 168, 168, 120 ];
case Type.FIGHTING: case Type.FIGHTING:
return [ 192, 48, 40 ]; return [ 192, 48, 40 ];
case Type.FLYING: case Type.FLYING:
return [ 168, 144, 240 ]; return [ 168, 144, 240 ];
case Type.POISON: case Type.POISON:
return [ 160, 64, 160 ]; return [ 160, 64, 160 ];
case Type.GROUND: case Type.GROUND:
return [ 224, 192, 104 ]; return [ 224, 192, 104 ];
case Type.ROCK: case Type.ROCK:
return [ 184, 160, 56 ]; return [ 184, 160, 56 ];
case Type.BUG: case Type.BUG:
return [ 168, 184, 32 ]; return [ 168, 184, 32 ];
case Type.GHOST: case Type.GHOST:
return [ 112, 88, 152 ]; return [ 112, 88, 152 ];
case Type.STEEL: case Type.STEEL:
return [ 184, 184, 208 ]; return [ 184, 184, 208 ];
case Type.FIRE: case Type.FIRE:
return [ 240, 128, 48 ]; return [ 240, 128, 48 ];
case Type.WATER: case Type.WATER:
return [ 104, 144, 240 ]; return [ 104, 144, 240 ];
case Type.GRASS: case Type.GRASS:
return [ 120, 200, 80 ]; return [ 120, 200, 80 ];
case Type.ELECTRIC: case Type.ELECTRIC:
return [ 248, 208, 48 ]; return [ 248, 208, 48 ];
case Type.PSYCHIC: case Type.PSYCHIC:
return [ 248, 88, 136 ]; return [ 248, 88, 136 ];
case Type.ICE: case Type.ICE:
return [ 152, 216, 216 ]; return [ 152, 216, 216 ];
case Type.DRAGON: case Type.DRAGON:
return [ 112, 56, 248 ]; return [ 112, 56, 248 ];
case Type.DARK: case Type.DARK:
return [ 112, 88, 72 ]; return [ 112, 88, 72 ];
case Type.FAIRY: case Type.FAIRY:
return [ 232, 136, 200 ]; return [ 232, 136, 200 ];
case Type.STELLAR: case Type.STELLAR:
return [ 255, 255, 255 ]; return [ 255, 255, 255 ];
default: default:
return [ 0, 0, 0 ]; return [ 0, 0, 0 ];
} }
} }

View File

@ -10,22 +10,22 @@ export const variantColorCache = {};
export function getVariantTint(variant: Variant): integer { export function getVariantTint(variant: Variant): integer {
switch (variant) { switch (variant) {
case 0: case 0:
return 0xf8c020; return 0xf8c020;
case 1: case 1:
return 0x20f8f0; return 0x20f8f0;
case 2: case 2:
return 0xe81048; return 0xe81048;
} }
} }
export function getVariantIcon(variant: Variant): integer { export function getVariantIcon(variant: Variant): integer {
switch (variant) { switch (variant) {
case 0: case 0:
return VariantTier.STANDARD; return VariantTier.STANDARD;
case 1: case 1:
return VariantTier.RARE; return VariantTier.RARE;
case 2: case 2:
return VariantTier.EPIC; return VariantTier.EPIC;
} }
} }

View File

@ -33,10 +33,10 @@ export class Weather {
isImmutable(): boolean { isImmutable(): boolean {
switch (this.weatherType) { switch (this.weatherType) {
case WeatherType.HEAVY_RAIN: case WeatherType.HEAVY_RAIN:
case WeatherType.HARSH_SUN: case WeatherType.HARSH_SUN:
case WeatherType.STRONG_WINDS: case WeatherType.STRONG_WINDS:
return true; return true;
} }
return false; return false;
@ -44,9 +44,9 @@ export class Weather {
isDamaging(): boolean { isDamaging(): boolean {
switch (this.weatherType) { switch (this.weatherType) {
case WeatherType.SANDSTORM: case WeatherType.SANDSTORM:
case WeatherType.HAIL: case WeatherType.HAIL:
return true; return true;
} }
return false; return false;
@ -54,10 +54,10 @@ export class Weather {
isTypeDamageImmune(type: Type): boolean { isTypeDamageImmune(type: Type): boolean {
switch (this.weatherType) { switch (this.weatherType) {
case WeatherType.SANDSTORM: case WeatherType.SANDSTORM:
return type === Type.GROUND || type === Type.ROCK || type === Type.STEEL; return type === Type.GROUND || type === Type.ROCK || type === Type.STEEL;
case WeatherType.HAIL: case WeatherType.HAIL:
return type === Type.ICE; return type === Type.ICE;
} }
return false; return false;
@ -65,24 +65,24 @@ export class Weather {
getAttackTypeMultiplier(attackType: Type): number { getAttackTypeMultiplier(attackType: Type): number {
switch (this.weatherType) { switch (this.weatherType) {
case WeatherType.SUNNY: case WeatherType.SUNNY:
case WeatherType.HARSH_SUN: case WeatherType.HARSH_SUN:
if (attackType === Type.FIRE) { if (attackType === Type.FIRE) {
return 1.5; return 1.5;
} }
if (attackType === Type.WATER) { if (attackType === Type.WATER) {
return 0.5; return 0.5;
} }
break; break;
case WeatherType.RAIN: case WeatherType.RAIN:
case WeatherType.HEAVY_RAIN: case WeatherType.HEAVY_RAIN:
if (attackType === Type.FIRE) { if (attackType === Type.FIRE) {
return 0.5; return 0.5;
} }
if (attackType === Type.WATER) { if (attackType === Type.WATER) {
return 1.5; return 1.5;
} }
break; break;
} }
return 1; return 1;
@ -92,10 +92,10 @@ export class Weather {
const moveType = user.getMoveType(move); const moveType = user.getMoveType(move);
switch (this.weatherType) { switch (this.weatherType) {
case WeatherType.HARSH_SUN: case WeatherType.HARSH_SUN:
return move instanceof AttackMove && moveType === Type.WATER; return move instanceof AttackMove && moveType === Type.WATER;
case WeatherType.HEAVY_RAIN: case WeatherType.HEAVY_RAIN:
return move instanceof AttackMove && moveType === Type.FIRE; return move instanceof AttackMove && moveType === Type.FIRE;
} }
return false; return false;
@ -120,24 +120,24 @@ export class Weather {
export function getWeatherStartMessage(weatherType: WeatherType): string | null { export function getWeatherStartMessage(weatherType: WeatherType): string | null {
switch (weatherType) { switch (weatherType) {
case WeatherType.SUNNY: case WeatherType.SUNNY:
return i18next.t("weather:sunnyStartMessage"); return i18next.t("weather:sunnyStartMessage");
case WeatherType.RAIN: case WeatherType.RAIN:
return i18next.t("weather:rainStartMessage"); return i18next.t("weather:rainStartMessage");
case WeatherType.SANDSTORM: case WeatherType.SANDSTORM:
return i18next.t("weather:sandstormStartMessage"); return i18next.t("weather:sandstormStartMessage");
case WeatherType.HAIL: case WeatherType.HAIL:
return i18next.t("weather:hailStartMessage"); return i18next.t("weather:hailStartMessage");
case WeatherType.SNOW: case WeatherType.SNOW:
return i18next.t("weather:snowStartMessage"); return i18next.t("weather:snowStartMessage");
case WeatherType.FOG: case WeatherType.FOG:
return i18next.t("weather:fogStartMessage"); return i18next.t("weather:fogStartMessage");
case WeatherType.HEAVY_RAIN: case WeatherType.HEAVY_RAIN:
return i18next.t("weather:heavyRainStartMessage"); return i18next.t("weather:heavyRainStartMessage");
case WeatherType.HARSH_SUN: case WeatherType.HARSH_SUN:
return i18next.t("weather:harshSunStartMessage"); return i18next.t("weather:harshSunStartMessage");
case WeatherType.STRONG_WINDS: case WeatherType.STRONG_WINDS:
return i18next.t("weather:strongWindsStartMessage"); return i18next.t("weather:strongWindsStartMessage");
} }
return null; return null;
@ -145,24 +145,24 @@ export function getWeatherStartMessage(weatherType: WeatherType): string | null
export function getWeatherLapseMessage(weatherType: WeatherType): string | null { export function getWeatherLapseMessage(weatherType: WeatherType): string | null {
switch (weatherType) { switch (weatherType) {
case WeatherType.SUNNY: case WeatherType.SUNNY:
return i18next.t("weather:sunnyLapseMessage"); return i18next.t("weather:sunnyLapseMessage");
case WeatherType.RAIN: case WeatherType.RAIN:
return i18next.t("weather:rainLapseMessage"); return i18next.t("weather:rainLapseMessage");
case WeatherType.SANDSTORM: case WeatherType.SANDSTORM:
return i18next.t("weather:sandstormLapseMessage"); return i18next.t("weather:sandstormLapseMessage");
case WeatherType.HAIL: case WeatherType.HAIL:
return i18next.t("weather:hailLapseMessage"); return i18next.t("weather:hailLapseMessage");
case WeatherType.SNOW: case WeatherType.SNOW:
return i18next.t("weather:snowLapseMessage"); return i18next.t("weather:snowLapseMessage");
case WeatherType.FOG: case WeatherType.FOG:
return i18next.t("weather:fogLapseMessage"); return i18next.t("weather:fogLapseMessage");
case WeatherType.HEAVY_RAIN: case WeatherType.HEAVY_RAIN:
return i18next.t("weather:heavyRainLapseMessage"); return i18next.t("weather:heavyRainLapseMessage");
case WeatherType.HARSH_SUN: case WeatherType.HARSH_SUN:
return i18next.t("weather:harshSunLapseMessage"); return i18next.t("weather:harshSunLapseMessage");
case WeatherType.STRONG_WINDS: case WeatherType.STRONG_WINDS:
return i18next.t("weather:strongWindsLapseMessage"); return i18next.t("weather:strongWindsLapseMessage");
} }
return null; return null;
@ -170,10 +170,10 @@ export function getWeatherLapseMessage(weatherType: WeatherType): string | null
export function getWeatherDamageMessage(weatherType: WeatherType, pokemon: Pokemon): string | null { export function getWeatherDamageMessage(weatherType: WeatherType, pokemon: Pokemon): string | null {
switch (weatherType) { switch (weatherType) {
case WeatherType.SANDSTORM: case WeatherType.SANDSTORM:
return i18next.t("weather:sandstormDamageMessage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }); return i18next.t("weather:sandstormDamageMessage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) });
case WeatherType.HAIL: case WeatherType.HAIL:
return i18next.t("weather:hailDamageMessage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }); return i18next.t("weather:hailDamageMessage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) });
} }
return null; return null;
@ -181,24 +181,24 @@ export function getWeatherDamageMessage(weatherType: WeatherType, pokemon: Pokem
export function getWeatherClearMessage(weatherType: WeatherType): string | null { export function getWeatherClearMessage(weatherType: WeatherType): string | null {
switch (weatherType) { switch (weatherType) {
case WeatherType.SUNNY: case WeatherType.SUNNY:
return i18next.t("weather:sunnyClearMessage"); return i18next.t("weather:sunnyClearMessage");
case WeatherType.RAIN: case WeatherType.RAIN:
return i18next.t("weather:rainClearMessage"); return i18next.t("weather:rainClearMessage");
case WeatherType.SANDSTORM: case WeatherType.SANDSTORM:
return i18next.t("weather:sandstormClearMessage"); return i18next.t("weather:sandstormClearMessage");
case WeatherType.HAIL: case WeatherType.HAIL:
return i18next.t("weather:hailClearMessage"); return i18next.t("weather:hailClearMessage");
case WeatherType.SNOW: case WeatherType.SNOW:
return i18next.t("weather:snowClearMessage"); return i18next.t("weather:snowClearMessage");
case WeatherType.FOG: case WeatherType.FOG:
return i18next.t("weather:fogClearMessage"); return i18next.t("weather:fogClearMessage");
case WeatherType.HEAVY_RAIN: case WeatherType.HEAVY_RAIN:
return i18next.t("weather:heavyRainClearMessage"); return i18next.t("weather:heavyRainClearMessage");
case WeatherType.HARSH_SUN: case WeatherType.HARSH_SUN:
return i18next.t("weather:harshSunClearMessage"); return i18next.t("weather:harshSunClearMessage");
case WeatherType.STRONG_WINDS: case WeatherType.STRONG_WINDS:
return i18next.t("weather:strongWindsClearMessage"); return i18next.t("weather:strongWindsClearMessage");
} }
return null; return null;
@ -206,33 +206,33 @@ export function getWeatherClearMessage(weatherType: WeatherType): string | null
export function getTerrainStartMessage(terrainType: TerrainType): string | null { export function getTerrainStartMessage(terrainType: TerrainType): string | null {
switch (terrainType) { switch (terrainType) {
case TerrainType.MISTY: case TerrainType.MISTY:
return i18next.t("terrain:mistyStartMessage"); return i18next.t("terrain:mistyStartMessage");
case TerrainType.ELECTRIC: case TerrainType.ELECTRIC:
return i18next.t("terrain:electricStartMessage"); return i18next.t("terrain:electricStartMessage");
case TerrainType.GRASSY: case TerrainType.GRASSY:
return i18next.t("terrain:grassyStartMessage"); return i18next.t("terrain:grassyStartMessage");
case TerrainType.PSYCHIC: case TerrainType.PSYCHIC:
return i18next.t("terrain:psychicStartMessage"); return i18next.t("terrain:psychicStartMessage");
default: default:
console.warn("getTerrainStartMessage not defined. Using default null"); console.warn("getTerrainStartMessage not defined. Using default null");
return null; return null;
} }
} }
export function getTerrainClearMessage(terrainType: TerrainType): string | null { export function getTerrainClearMessage(terrainType: TerrainType): string | null {
switch (terrainType) { switch (terrainType) {
case TerrainType.MISTY: case TerrainType.MISTY:
return i18next.t("terrain:mistyClearMessage"); return i18next.t("terrain:mistyClearMessage");
case TerrainType.ELECTRIC: case TerrainType.ELECTRIC:
return i18next.t("terrain:electricClearMessage"); return i18next.t("terrain:electricClearMessage");
case TerrainType.GRASSY: case TerrainType.GRASSY:
return i18next.t("terrain:grassyClearMessage"); return i18next.t("terrain:grassyClearMessage");
case TerrainType.PSYCHIC: case TerrainType.PSYCHIC:
return i18next.t("terrain:psychicClearMessage"); return i18next.t("terrain:psychicClearMessage");
default: default:
console.warn("getTerrainClearMessage not defined. Using default null"); console.warn("getTerrainClearMessage not defined. Using default null");
return null; return null;
} }
} }
@ -252,126 +252,126 @@ export function getRandomWeatherType(arena: any /* Importing from arena causes a
let weatherPool: WeatherPoolEntry[] = []; let weatherPool: WeatherPoolEntry[] = [];
const hasSun = arena.getTimeOfDay() < 2; const hasSun = arena.getTimeOfDay() < 2;
switch (arena.biomeType) { switch (arena.biomeType) {
case Biome.GRASS: case Biome.GRASS:
weatherPool = [ weatherPool = [
{ weatherType: WeatherType.NONE, weight: 7 } { weatherType: WeatherType.NONE, weight: 7 }
]; ];
if (hasSun) { if (hasSun) {
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 3 }); weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 3 });
} }
break; break;
case Biome.TALL_GRASS: case Biome.TALL_GRASS:
weatherPool = [ weatherPool = [
{ weatherType: WeatherType.NONE, weight: 8 }, { weatherType: WeatherType.NONE, weight: 8 },
{ weatherType: WeatherType.RAIN, weight: 5 }, { weatherType: WeatherType.RAIN, weight: 5 },
]; ];
if (hasSun) { if (hasSun) {
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 8 }); weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 8 });
} }
break; break;
case Biome.FOREST: case Biome.FOREST:
weatherPool = [ weatherPool = [
{ weatherType: WeatherType.NONE, weight: 8 }, { weatherType: WeatherType.NONE, weight: 8 },
{ weatherType: WeatherType.RAIN, weight: 5 } { weatherType: WeatherType.RAIN, weight: 5 }
]; ];
break; break;
case Biome.SEA: case Biome.SEA:
weatherPool = [ weatherPool = [
{ weatherType: WeatherType.NONE, weight: 3 }, { weatherType: WeatherType.NONE, weight: 3 },
{ weatherType: WeatherType.RAIN, weight: 12 } { weatherType: WeatherType.RAIN, weight: 12 }
]; ];
break; break;
case Biome.SWAMP: case Biome.SWAMP:
weatherPool = [ weatherPool = [
{ weatherType: WeatherType.NONE, weight: 3 }, { weatherType: WeatherType.NONE, weight: 3 },
{ weatherType: WeatherType.RAIN, weight: 4 }, { weatherType: WeatherType.RAIN, weight: 4 },
{ weatherType: WeatherType.FOG, weight: 1 } { weatherType: WeatherType.FOG, weight: 1 }
]; ];
break; break;
case Biome.BEACH: case Biome.BEACH:
weatherPool = [ weatherPool = [
{ weatherType: WeatherType.NONE, weight: 8 }, { weatherType: WeatherType.NONE, weight: 8 },
{ weatherType: WeatherType.RAIN, weight: 3 } { weatherType: WeatherType.RAIN, weight: 3 }
]; ];
if (hasSun) { if (hasSun) {
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 5 }); weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 5 });
} }
break; break;
case Biome.LAKE: case Biome.LAKE:
weatherPool = [ weatherPool = [
{ weatherType: WeatherType.NONE, weight: 10 }, { weatherType: WeatherType.NONE, weight: 10 },
{ weatherType: WeatherType.RAIN, weight: 5 }, { weatherType: WeatherType.RAIN, weight: 5 },
{ weatherType: WeatherType.FOG, weight: 1 } { weatherType: WeatherType.FOG, weight: 1 }
]; ];
break; break;
case Biome.SEABED: case Biome.SEABED:
weatherPool = [ weatherPool = [
{ weatherType: WeatherType.RAIN, weight: 1 } { weatherType: WeatherType.RAIN, weight: 1 }
]; ];
break; break;
case Biome.BADLANDS: case Biome.BADLANDS:
weatherPool = [ weatherPool = [
{ weatherType: WeatherType.NONE, weight: 8 }, { weatherType: WeatherType.NONE, weight: 8 },
{ weatherType: WeatherType.SANDSTORM, weight: 2 } { weatherType: WeatherType.SANDSTORM, weight: 2 }
]; ];
if (hasSun) { if (hasSun) {
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 5 }); weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 5 });
} }
break; break;
case Biome.DESERT: case Biome.DESERT:
weatherPool = [ weatherPool = [
{ weatherType: WeatherType.SANDSTORM, weight: 2 } { weatherType: WeatherType.SANDSTORM, weight: 2 }
]; ];
if (hasSun) { if (hasSun) {
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 }); weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 });
} }
break; break;
case Biome.ICE_CAVE: case Biome.ICE_CAVE:
weatherPool = [ weatherPool = [
{ weatherType: WeatherType.NONE, weight: 3 }, { weatherType: WeatherType.NONE, weight: 3 },
{ weatherType: WeatherType.SNOW, weight: 4 }, { weatherType: WeatherType.SNOW, weight: 4 },
{ weatherType: WeatherType.HAIL, weight: 1 } { weatherType: WeatherType.HAIL, weight: 1 }
]; ];
break; break;
case Biome.MEADOW: case Biome.MEADOW:
weatherPool = [ weatherPool = [
{ weatherType: WeatherType.NONE, weight: 2 } { weatherType: WeatherType.NONE, weight: 2 }
]; ];
if (hasSun) { if (hasSun) {
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 }); weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 });
} }
case Biome.VOLCANO: case Biome.VOLCANO:
weatherPool = [ weatherPool = [
{ weatherType: hasSun ? WeatherType.SUNNY : WeatherType.NONE, weight: 1 } { weatherType: hasSun ? WeatherType.SUNNY : WeatherType.NONE, weight: 1 }
]; ];
break; break;
case Biome.GRAVEYARD: case Biome.GRAVEYARD:
weatherPool = [ weatherPool = [
{ weatherType: WeatherType.NONE, weight: 3 }, { weatherType: WeatherType.NONE, weight: 3 },
{ weatherType: WeatherType.FOG, weight: 1 } { weatherType: WeatherType.FOG, weight: 1 }
]; ];
break; break;
case Biome.JUNGLE: case Biome.JUNGLE:
weatherPool = [ weatherPool = [
{ weatherType: WeatherType.NONE, weight: 8 }, { weatherType: WeatherType.NONE, weight: 8 },
{ weatherType: WeatherType.RAIN, weight: 2 } { weatherType: WeatherType.RAIN, weight: 2 }
]; ];
break; break;
case Biome.SNOWY_FOREST: case Biome.SNOWY_FOREST:
weatherPool = [ weatherPool = [
{ weatherType: WeatherType.SNOW, weight: 7 }, { weatherType: WeatherType.SNOW, weight: 7 },
{ weatherType: WeatherType.HAIL, weight: 1 } { weatherType: WeatherType.HAIL, weight: 1 }
]; ];
break; break;
case Biome.ISLAND: case Biome.ISLAND:
weatherPool = [ weatherPool = [
{ weatherType: WeatherType.NONE, weight: 5 }, { weatherType: WeatherType.NONE, weight: 5 },
{ weatherType: WeatherType.RAIN, weight: 1 }, { weatherType: WeatherType.RAIN, weight: 1 },
]; ];
if (hasSun) { if (hasSun) {
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 }); weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 });
} }
break; break;
} }
if (weatherPool.length > 1) { if (weatherPool.length > 1) {

View File

@ -4,21 +4,21 @@ import * as Utils from "../utils";
export function addPokeballOpenParticles(scene: BattleScene, x: number, y: number, pokeballType: PokeballType): void { export function addPokeballOpenParticles(scene: BattleScene, x: number, y: number, pokeballType: PokeballType): void {
switch (pokeballType) { switch (pokeballType) {
case PokeballType.POKEBALL: case PokeballType.POKEBALL:
doDefaultPbOpenParticles(scene, x, y, 48); doDefaultPbOpenParticles(scene, x, y, 48);
break; break;
case PokeballType.GREAT_BALL: case PokeballType.GREAT_BALL:
doDefaultPbOpenParticles(scene, x, y, 96); doDefaultPbOpenParticles(scene, x, y, 96);
break; break;
case PokeballType.ULTRA_BALL: case PokeballType.ULTRA_BALL:
doUbOpenParticles(scene, x, y, 8); doUbOpenParticles(scene, x, y, 8);
break; break;
case PokeballType.ROGUE_BALL: case PokeballType.ROGUE_BALL:
doUbOpenParticles(scene, x, y, 10); doUbOpenParticles(scene, x, y, 10);
break; break;
case PokeballType.MASTER_BALL: case PokeballType.MASTER_BALL:
doMbOpenParticles(scene, x, y); doMbOpenParticles(scene, x, y);
break; break;
} }
} }

View File

@ -129,18 +129,18 @@ export class Arena {
if (ret.subLegendary || ret.legendary || ret.mythical) { if (ret.subLegendary || ret.legendary || ret.mythical) {
switch (true) { switch (true) {
case (ret.baseTotal >= 720): case (ret.baseTotal >= 720):
regen = level < 90; regen = level < 90;
break; break;
case (ret.baseTotal >= 670): case (ret.baseTotal >= 670):
regen = level < 70; regen = level < 70;
break; break;
case (ret.baseTotal >= 580): case (ret.baseTotal >= 580):
regen = level < 50; regen = level < 50;
break; break;
default: default:
regen = level < 30; regen = level < 30;
break; break;
} }
} }
} }
@ -177,41 +177,41 @@ export class Arena {
getSpeciesFormIndex(species: PokemonSpecies): integer { getSpeciesFormIndex(species: PokemonSpecies): integer {
switch (species.speciesId) { switch (species.speciesId) {
case Species.BURMY: case Species.BURMY:
case Species.WORMADAM: case Species.WORMADAM:
switch (this.biomeType) { switch (this.biomeType) {
case Biome.BEACH: case Biome.BEACH:
return 1; return 1;
case Biome.SLUM: case Biome.SLUM:
return 2; return 2;
} }
break; break;
case Species.ROTOM: case Species.ROTOM:
switch (this.biomeType) { switch (this.biomeType) {
case Biome.VOLCANO: case Biome.VOLCANO:
return 1; return 1;
case Biome.SEA: case Biome.SEA:
return 2; return 2;
case Biome.ICE_CAVE: case Biome.ICE_CAVE:
return 3; return 3;
case Biome.MOUNTAIN: case Biome.MOUNTAIN:
return 4; return 4;
case Biome.TALL_GRASS: case Biome.TALL_GRASS:
return 5; return 5;
} }
break; break;
case Species.LYCANROC: case Species.LYCANROC:
const timeOfDay = this.getTimeOfDay(); const timeOfDay = this.getTimeOfDay();
switch (timeOfDay) { switch (timeOfDay) {
case TimeOfDay.DAY: case TimeOfDay.DAY:
case TimeOfDay.DAWN: case TimeOfDay.DAWN:
return 0; return 0;
case TimeOfDay.DUSK: case TimeOfDay.DUSK:
return 2; return 2;
case TimeOfDay.NIGHT: case TimeOfDay.NIGHT:
return 1; return 1;
} }
break; break;
} }
return 0; return 0;
@ -219,70 +219,70 @@ export class Arena {
getTypeForBiome() { getTypeForBiome() {
switch (this.biomeType) { switch (this.biomeType) {
case Biome.TOWN: case Biome.TOWN:
case Biome.PLAINS: case Biome.PLAINS:
case Biome.METROPOLIS: case Biome.METROPOLIS:
return Type.NORMAL; return Type.NORMAL;
case Biome.GRASS: case Biome.GRASS:
case Biome.TALL_GRASS: case Biome.TALL_GRASS:
return Type.GRASS; return Type.GRASS;
case Biome.FOREST: case Biome.FOREST:
case Biome.JUNGLE: case Biome.JUNGLE:
return Type.BUG; return Type.BUG;
case Biome.SLUM: case Biome.SLUM:
case Biome.SWAMP: case Biome.SWAMP:
return Type.POISON; return Type.POISON;
case Biome.SEA: case Biome.SEA:
case Biome.BEACH: case Biome.BEACH:
case Biome.LAKE: case Biome.LAKE:
case Biome.SEABED: case Biome.SEABED:
return Type.WATER; return Type.WATER;
case Biome.MOUNTAIN: case Biome.MOUNTAIN:
return Type.FLYING; return Type.FLYING;
case Biome.BADLANDS: case Biome.BADLANDS:
return Type.GROUND; return Type.GROUND;
case Biome.CAVE: case Biome.CAVE:
case Biome.DESERT: case Biome.DESERT:
return Type.ROCK; return Type.ROCK;
case Biome.ICE_CAVE: case Biome.ICE_CAVE:
case Biome.SNOWY_FOREST: case Biome.SNOWY_FOREST:
return Type.ICE; return Type.ICE;
case Biome.MEADOW: case Biome.MEADOW:
case Biome.FAIRY_CAVE: case Biome.FAIRY_CAVE:
case Biome.ISLAND: case Biome.ISLAND:
return Type.FAIRY; return Type.FAIRY;
case Biome.POWER_PLANT: case Biome.POWER_PLANT:
return Type.ELECTRIC; return Type.ELECTRIC;
case Biome.VOLCANO: case Biome.VOLCANO:
return Type.FIRE; return Type.FIRE;
case Biome.GRAVEYARD: case Biome.GRAVEYARD:
case Biome.TEMPLE: case Biome.TEMPLE:
return Type.GHOST; return Type.GHOST;
case Biome.DOJO: case Biome.DOJO:
case Biome.CONSTRUCTION_SITE: case Biome.CONSTRUCTION_SITE:
return Type.FIGHTING; return Type.FIGHTING;
case Biome.FACTORY: case Biome.FACTORY:
case Biome.LABORATORY: case Biome.LABORATORY:
return Type.STEEL; return Type.STEEL;
case Biome.RUINS: case Biome.RUINS:
case Biome.SPACE: case Biome.SPACE:
return Type.PSYCHIC; return Type.PSYCHIC;
case Biome.WASTELAND: case Biome.WASTELAND:
case Biome.END: case Biome.END:
return Type.DRAGON; return Type.DRAGON;
case Biome.ABYSS: case Biome.ABYSS:
return Type.DARK; return Type.DARK;
default: default:
return Type.UNKNOWN; return Type.UNKNOWN;
} }
} }
getBgTerrainColorRatioForBiome(): number { getBgTerrainColorRatioForBiome(): number {
switch (this.biomeType) { switch (this.biomeType) {
case Biome.SPACE: case Biome.SPACE:
return 1; return 1;
case Biome.END: case Biome.END:
return 0; return 0;
} }
return 131 / 180; return 131 / 180;
@ -424,52 +424,52 @@ export class Arena {
*/ */
getTrainerChance(): integer { getTrainerChance(): integer {
switch (this.biomeType) { switch (this.biomeType) {
case Biome.METROPOLIS: case Biome.METROPOLIS:
return 2; return 2;
case Biome.SLUM: case Biome.SLUM:
case Biome.BEACH: case Biome.BEACH:
case Biome.DOJO: case Biome.DOJO:
case Biome.CONSTRUCTION_SITE: case Biome.CONSTRUCTION_SITE:
return 4; return 4;
case Biome.PLAINS: case Biome.PLAINS:
case Biome.GRASS: case Biome.GRASS:
case Biome.LAKE: case Biome.LAKE:
case Biome.CAVE: case Biome.CAVE:
return 6; return 6;
case Biome.TALL_GRASS: case Biome.TALL_GRASS:
case Biome.FOREST: case Biome.FOREST:
case Biome.SEA: case Biome.SEA:
case Biome.SWAMP: case Biome.SWAMP:
case Biome.MOUNTAIN: case Biome.MOUNTAIN:
case Biome.BADLANDS: case Biome.BADLANDS:
case Biome.DESERT: case Biome.DESERT:
case Biome.MEADOW: case Biome.MEADOW:
case Biome.POWER_PLANT: case Biome.POWER_PLANT:
case Biome.GRAVEYARD: case Biome.GRAVEYARD:
case Biome.FACTORY: case Biome.FACTORY:
case Biome.SNOWY_FOREST: case Biome.SNOWY_FOREST:
return 8; return 8;
case Biome.ICE_CAVE: case Biome.ICE_CAVE:
case Biome.VOLCANO: case Biome.VOLCANO:
case Biome.RUINS: case Biome.RUINS:
case Biome.WASTELAND: case Biome.WASTELAND:
case Biome.JUNGLE: case Biome.JUNGLE:
case Biome.FAIRY_CAVE: case Biome.FAIRY_CAVE:
return 12; return 12;
case Biome.SEABED: case Biome.SEABED:
case Biome.ABYSS: case Biome.ABYSS:
case Biome.SPACE: case Biome.SPACE:
case Biome.TEMPLE: case Biome.TEMPLE:
return 16; return 16;
default: default:
return 0; return 0;
} }
} }
getTimeOfDay(): TimeOfDay { getTimeOfDay(): TimeOfDay {
switch (this.biomeType) { switch (this.biomeType) {
case Biome.ABYSS: case Biome.ABYSS:
return TimeOfDay.NIGHT; return TimeOfDay.NIGHT;
} }
const waveCycle = ((this.scene.currentBattle?.waveIndex || 0) + this.scene.waveCycleOffset) % 40; const waveCycle = ((this.scene.currentBattle?.waveIndex || 0) + this.scene.waveCycleOffset) % 40;
@ -491,35 +491,35 @@ export class Arena {
isOutside(): boolean { isOutside(): boolean {
switch (this.biomeType) { switch (this.biomeType) {
case Biome.SEABED: case Biome.SEABED:
case Biome.CAVE: case Biome.CAVE:
case Biome.ICE_CAVE: case Biome.ICE_CAVE:
case Biome.POWER_PLANT: case Biome.POWER_PLANT:
case Biome.DOJO: case Biome.DOJO:
case Biome.FACTORY: case Biome.FACTORY:
case Biome.ABYSS: case Biome.ABYSS:
case Biome.FAIRY_CAVE: case Biome.FAIRY_CAVE:
case Biome.TEMPLE: case Biome.TEMPLE:
case Biome.LABORATORY: case Biome.LABORATORY:
return false; return false;
default: default:
return true; return true;
} }
} }
overrideTint(): [integer, integer, integer] { overrideTint(): [integer, integer, integer] {
switch (Overrides.ARENA_TINT_OVERRIDE) { switch (Overrides.ARENA_TINT_OVERRIDE) {
case TimeOfDay.DUSK: case TimeOfDay.DUSK:
return [ 98, 48, 73 ].map(c => Math.round((c + 128) / 2)) as [integer, integer, integer]; return [ 98, 48, 73 ].map(c => Math.round((c + 128) / 2)) as [integer, integer, integer];
break; break;
case (TimeOfDay.NIGHT): case (TimeOfDay.NIGHT):
return [ 64, 64, 64 ]; return [ 64, 64, 64 ];
break; break;
case TimeOfDay.DAWN: case TimeOfDay.DAWN:
case TimeOfDay.DAY: case TimeOfDay.DAY:
default: default:
return [ 128, 128, 128 ]; return [ 128, 128, 128 ];
break; break;
} }
} }
@ -528,10 +528,10 @@ export class Arena {
return this.overrideTint(); return this.overrideTint();
} }
switch (this.biomeType) { switch (this.biomeType) {
case Biome.ABYSS: case Biome.ABYSS:
return [ 64, 64, 64 ]; return [ 64, 64, 64 ];
default: default:
return [ 128, 128, 128 ]; return [ 128, 128, 128 ];
} }
} }
@ -544,8 +544,8 @@ export class Arena {
} }
switch (this.biomeType) { switch (this.biomeType) {
default: default:
return [ 98, 48, 73 ].map(c => Math.round((c + 128) / 2)) as [integer, integer, integer]; return [ 98, 48, 73 ].map(c => Math.round((c + 128) / 2)) as [integer, integer, integer];
} }
} }
@ -554,10 +554,10 @@ export class Arena {
return this.overrideTint(); return this.overrideTint();
} }
switch (this.biomeType) { switch (this.biomeType) {
case Biome.ABYSS: case Biome.ABYSS:
case Biome.SPACE: case Biome.SPACE:
case Biome.END: case Biome.END:
return this.getDayTint(); return this.getDayTint();
} }
if (!this.isOutside()) { if (!this.isOutside()) {
@ -565,8 +565,8 @@ export class Arena {
} }
switch (this.biomeType) { switch (this.biomeType) {
default: default:
return [ 48, 48, 98 ]; return [ 48, 48, 98 ];
} }
} }
@ -747,77 +747,77 @@ export class Arena {
getBgmLoopPoint(): number { getBgmLoopPoint(): number {
switch (this.biomeType) { switch (this.biomeType) {
case Biome.TOWN: case Biome.TOWN:
return 7.288; return 7.288;
case Biome.PLAINS: case Biome.PLAINS:
return 17.485; return 17.485;
case Biome.GRASS: case Biome.GRASS:
return 1.995; return 1.995;
case Biome.TALL_GRASS: case Biome.TALL_GRASS:
return 9.608; return 9.608;
case Biome.METROPOLIS: case Biome.METROPOLIS:
return 141.470; return 141.470;
case Biome.FOREST: case Biome.FOREST:
return 4.294; return 4.294;
case Biome.SEA: case Biome.SEA:
return 0.024; return 0.024;
case Biome.SWAMP: case Biome.SWAMP:
return 4.461; return 4.461;
case Biome.BEACH: case Biome.BEACH:
return 3.462; return 3.462;
case Biome.LAKE: case Biome.LAKE:
return 7.215; return 7.215;
case Biome.SEABED: case Biome.SEABED:
return 2.600; return 2.600;
case Biome.MOUNTAIN: case Biome.MOUNTAIN:
return 4.018; return 4.018;
case Biome.BADLANDS: case Biome.BADLANDS:
return 17.790; return 17.790;
case Biome.CAVE: case Biome.CAVE:
return 14.240; return 14.240;
case Biome.DESERT: case Biome.DESERT:
return 1.143; return 1.143;
case Biome.ICE_CAVE: case Biome.ICE_CAVE:
return 0.000; return 0.000;
case Biome.MEADOW: case Biome.MEADOW:
return 3.891; return 3.891;
case Biome.POWER_PLANT: case Biome.POWER_PLANT:
return 9.447; return 9.447;
case Biome.VOLCANO: case Biome.VOLCANO:
return 17.637; return 17.637;
case Biome.GRAVEYARD: case Biome.GRAVEYARD:
return 3.232; return 3.232;
case Biome.DOJO: case Biome.DOJO:
return 6.205; return 6.205;
case Biome.FACTORY: case Biome.FACTORY:
return 4.985; return 4.985;
case Biome.RUINS: case Biome.RUINS:
return 0.000; return 0.000;
case Biome.WASTELAND: case Biome.WASTELAND:
return 6.336; return 6.336;
case Biome.ABYSS: case Biome.ABYSS:
return 5.130; return 5.130;
case Biome.SPACE: case Biome.SPACE:
return 20.036; return 20.036;
case Biome.CONSTRUCTION_SITE: case Biome.CONSTRUCTION_SITE:
return 1.222; return 1.222;
case Biome.JUNGLE: case Biome.JUNGLE:
return 0.000; return 0.000;
case Biome.FAIRY_CAVE: case Biome.FAIRY_CAVE:
return 4.542; return 4.542;
case Biome.TEMPLE: case Biome.TEMPLE:
return 2.547; return 2.547;
case Biome.ISLAND: case Biome.ISLAND:
return 2.751; return 2.751;
case Biome.LABORATORY: case Biome.LABORATORY:
return 114.862; return 114.862;
case Biome.SLUM: case Biome.SLUM:
return 0.000; return 0.000;
case Biome.SNOWY_FOREST: case Biome.SNOWY_FOREST:
return 3.047; return 3.047;
default: default:
console.warn(`missing bgm loop-point for biome "${Biome[this.biomeType]}" (=${this.biomeType})`); console.warn(`missing bgm loop-point for biome "${Biome[this.biomeType]}" (=${this.biomeType})`);
return 0; return 0;
} }
} }
} }
@ -828,32 +828,32 @@ export function getBiomeKey(biome: Biome): string {
export function getBiomeHasProps(biomeType: Biome): boolean { export function getBiomeHasProps(biomeType: Biome): boolean {
switch (biomeType) { switch (biomeType) {
case Biome.METROPOLIS: case Biome.METROPOLIS:
case Biome.BEACH: case Biome.BEACH:
case Biome.LAKE: case Biome.LAKE:
case Biome.SEABED: case Biome.SEABED:
case Biome.MOUNTAIN: case Biome.MOUNTAIN:
case Biome.BADLANDS: case Biome.BADLANDS:
case Biome.CAVE: case Biome.CAVE:
case Biome.DESERT: case Biome.DESERT:
case Biome.ICE_CAVE: case Biome.ICE_CAVE:
case Biome.MEADOW: case Biome.MEADOW:
case Biome.POWER_PLANT: case Biome.POWER_PLANT:
case Biome.VOLCANO: case Biome.VOLCANO:
case Biome.GRAVEYARD: case Biome.GRAVEYARD:
case Biome.FACTORY: case Biome.FACTORY:
case Biome.RUINS: case Biome.RUINS:
case Biome.WASTELAND: case Biome.WASTELAND:
case Biome.ABYSS: case Biome.ABYSS:
case Biome.CONSTRUCTION_SITE: case Biome.CONSTRUCTION_SITE:
case Biome.JUNGLE: case Biome.JUNGLE:
case Biome.FAIRY_CAVE: case Biome.FAIRY_CAVE:
case Biome.TEMPLE: case Biome.TEMPLE:
case Biome.SNOWY_FOREST: case Biome.SNOWY_FOREST:
case Biome.ISLAND: case Biome.ISLAND:
case Biome.LABORATORY: case Biome.LABORATORY:
case Biome.END: case Biome.END:
return true; return true;
} }
return false; return false;

View File

@ -29,21 +29,21 @@ export default class DamageNumberHandler {
let [ textColor, shadowColor ] : TextAndShadowArr = [ null, null ]; let [ textColor, shadowColor ] : TextAndShadowArr = [ null, null ];
switch (result) { switch (result) {
case HitResult.SUPER_EFFECTIVE: case HitResult.SUPER_EFFECTIVE:
[ textColor, shadowColor ] = [ "#f8d030", "#b8a038" ]; [ textColor, shadowColor ] = [ "#f8d030", "#b8a038" ];
break; break;
case HitResult.NOT_VERY_EFFECTIVE: case HitResult.NOT_VERY_EFFECTIVE:
[ textColor, shadowColor ] = [ "#f08030", "#c03028" ]; [ textColor, shadowColor ] = [ "#f08030", "#c03028" ];
break; break;
case HitResult.ONE_HIT_KO: case HitResult.ONE_HIT_KO:
[ textColor, shadowColor ] = [ "#a040a0", "#483850" ]; [ textColor, shadowColor ] = [ "#a040a0", "#483850" ];
break; break;
case HitResult.HEAL: case HitResult.HEAL:
[ textColor, shadowColor ] = [ "#78c850", "#588040" ]; [ textColor, shadowColor ] = [ "#78c850", "#588040" ];
break; break;
default: default:
[ textColor, shadowColor ] = [ "#ffffff", "#636363" ]; [ textColor, shadowColor ] = [ "#ffffff", "#636363" ];
break; break;
} }
if (textColor) { if (textColor) {

View File

@ -680,12 +680,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
getFieldPositionOffset(): [ number, number ] { getFieldPositionOffset(): [ number, number ] {
switch (this.fieldPosition) { switch (this.fieldPosition) {
case FieldPosition.CENTER: case FieldPosition.CENTER:
return [ 0, 0 ]; return [ 0, 0 ];
case FieldPosition.LEFT: case FieldPosition.LEFT:
return [ -32, -8 ]; return [ -32, -8 ];
case FieldPosition.RIGHT: case FieldPosition.RIGHT:
return [ 32, 0 ]; return [ 32, 0 ];
} }
} }
@ -917,39 +917,39 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
let ret = statValue.value * this.getStatStageMultiplier(stat, opponent, move, ignoreOppAbility, isCritical, simulated); let ret = statValue.value * this.getStatStageMultiplier(stat, opponent, move, ignoreOppAbility, isCritical, simulated);
switch (stat) { switch (stat) {
case Stat.ATK: case Stat.ATK:
if (this.getTag(BattlerTagType.SLOW_START)) { if (this.getTag(BattlerTagType.SLOW_START)) {
ret >>= 1; ret >>= 1;
} }
break; break;
case Stat.DEF: case Stat.DEF:
if (this.isOfType(Type.ICE) && this.scene.arena.weather?.weatherType === WeatherType.SNOW) { if (this.isOfType(Type.ICE) && this.scene.arena.weather?.weatherType === WeatherType.SNOW) {
ret *= 1.5; ret *= 1.5;
} }
break; break;
case Stat.SPATK: case Stat.SPATK:
break; break;
case Stat.SPDEF: case Stat.SPDEF:
if (this.isOfType(Type.ROCK) && this.scene.arena.weather?.weatherType === WeatherType.SANDSTORM) { if (this.isOfType(Type.ROCK) && this.scene.arena.weather?.weatherType === WeatherType.SANDSTORM) {
ret *= 1.5; ret *= 1.5;
} }
break; break;
case Stat.SPD: case Stat.SPD:
const side = this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; const side = this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY;
if (this.scene.arena.getTagOnSide(ArenaTagType.TAILWIND, side)) { if (this.scene.arena.getTagOnSide(ArenaTagType.TAILWIND, side)) {
ret *= 2; ret *= 2;
} }
if (this.scene.arena.getTagOnSide(ArenaTagType.GRASS_WATER_PLEDGE, side)) { if (this.scene.arena.getTagOnSide(ArenaTagType.GRASS_WATER_PLEDGE, side)) {
ret >>= 2; ret >>= 2;
} }
if (this.getTag(BattlerTagType.SLOW_START)) { if (this.getTag(BattlerTagType.SLOW_START)) {
ret >>= 1; ret >>= 1;
} }
if (this.status && this.status.effect === StatusEffect.PARALYSIS) { if (this.status && this.status.effect === StatusEffect.PARALYSIS) {
ret >>= 1; ret >>= 1;
} }
break; break;
} }
const highestStatBoost = this.findTag(t => t instanceof HighestStatBoostTag && (t as HighestStatBoostTag).stat === stat) as HighestStatBoostTag; const highestStatBoost = this.findTag(t => t instanceof HighestStatBoostTag && (t as HighestStatBoostTag).stat === stat) as HighestStatBoostTag;
@ -2338,14 +2338,14 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
if (opponent) { if (opponent) {
if (isCritical) { if (isCritical) {
switch (stat) { switch (stat) {
case Stat.ATK: case Stat.ATK:
case Stat.SPATK: case Stat.SPATK:
statStage.value = Math.max(statStage.value, 0); statStage.value = Math.max(statStage.value, 0);
break; break;
case Stat.DEF: case Stat.DEF:
case Stat.SPDEF: case Stat.SPDEF:
statStage.value = Math.min(statStage.value, 0); statStage.value = Math.min(statStage.value, 0);
break; break;
} }
} }
if (!ignoreOppAbility) { if (!ignoreOppAbility) {
@ -2795,15 +2795,15 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
// want to include is.Fainted() in case multi hit move ends early, still want to render message // want to include is.Fainted() in case multi hit move ends early, still want to render message
if (source.turnData.hitsLeft === 1 || this.isFainted()) { if (source.turnData.hitsLeft === 1 || this.isFainted()) {
switch (result) { switch (result) {
case HitResult.SUPER_EFFECTIVE: case HitResult.SUPER_EFFECTIVE:
this.scene.queueMessage(i18next.t("battle:hitResultSuperEffective")); this.scene.queueMessage(i18next.t("battle:hitResultSuperEffective"));
break; break;
case HitResult.NOT_VERY_EFFECTIVE: case HitResult.NOT_VERY_EFFECTIVE:
this.scene.queueMessage(i18next.t("battle:hitResultNotVeryEffective")); this.scene.queueMessage(i18next.t("battle:hitResultNotVeryEffective"));
break; break;
case HitResult.ONE_HIT_KO: case HitResult.ONE_HIT_KO:
this.scene.queueMessage(i18next.t("battle:hitResultOneHitKO")); this.scene.queueMessage(i18next.t("battle:hitResultOneHitKO"));
break; break;
} }
} }
@ -3355,53 +3355,53 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
switch (effect) { switch (effect) {
case StatusEffect.POISON: case StatusEffect.POISON:
case StatusEffect.TOXIC: case StatusEffect.TOXIC:
// Check if the Pokemon is immune to Poison/Toxic or if the source pokemon is canceling the immunity // Check if the Pokemon is immune to Poison/Toxic or if the source pokemon is canceling the immunity
const poisonImmunity = types.map(defType => { const poisonImmunity = types.map(defType => {
// Check if the Pokemon is not immune to Poison/Toxic // Check if the Pokemon is not immune to Poison/Toxic
if (defType !== Type.POISON && defType !== Type.STEEL) { if (defType !== Type.POISON && defType !== Type.STEEL) {
return false; return false;
} }
// Check if the source Pokemon has an ability that cancels the Poison/Toxic immunity // Check if the source Pokemon has an ability that cancels the Poison/Toxic immunity
const cancelImmunity = new Utils.BooleanHolder(false); const cancelImmunity = new Utils.BooleanHolder(false);
if (sourcePokemon) { if (sourcePokemon) {
applyAbAttrs(IgnoreTypeStatusEffectImmunityAbAttr, sourcePokemon, cancelImmunity, false, effect, defType); applyAbAttrs(IgnoreTypeStatusEffectImmunityAbAttr, sourcePokemon, cancelImmunity, false, effect, defType);
if (cancelImmunity.value) { if (cancelImmunity.value) {
return false;
}
}
return true;
});
if (this.isOfType(Type.POISON) || this.isOfType(Type.STEEL)) {
if (poisonImmunity.includes(true)) {
return false; return false;
} }
} }
break;
return true; case StatusEffect.PARALYSIS:
}); if (this.isOfType(Type.ELECTRIC)) {
if (this.isOfType(Type.POISON) || this.isOfType(Type.STEEL)) {
if (poisonImmunity.includes(true)) {
return false; return false;
} }
} break;
break; case StatusEffect.SLEEP:
case StatusEffect.PARALYSIS: if (this.isGrounded() && this.scene.arena.terrain?.terrainType === TerrainType.ELECTRIC) {
if (this.isOfType(Type.ELECTRIC)) { return false;
return false; }
} break;
break; case StatusEffect.FREEZE:
case StatusEffect.SLEEP: if (this.isOfType(Type.ICE) || (this.scene?.arena?.weather?.weatherType && [ WeatherType.SUNNY, WeatherType.HARSH_SUN ].includes(this.scene.arena.weather.weatherType))) {
if (this.isGrounded() && this.scene.arena.terrain?.terrainType === TerrainType.ELECTRIC) { return false;
return false; }
} break;
break; case StatusEffect.BURN:
case StatusEffect.FREEZE: if (this.isOfType(Type.FIRE)) {
if (this.isOfType(Type.ICE) || (this.scene?.arena?.weather?.weatherType && [ WeatherType.SUNNY, WeatherType.HARSH_SUN ].includes(this.scene.arena.weather.weatherType))) { return false;
return false; }
} break;
break;
case StatusEffect.BURN:
if (this.isOfType(Type.FIRE)) {
return false;
}
break;
} }
const cancelled = new Utils.BooleanHolder(false); const cancelled = new Utils.BooleanHolder(false);
@ -4501,35 +4501,35 @@ export class EnemyPokemon extends Pokemon {
generateAndPopulateMoveset(formIndex?: integer): void { generateAndPopulateMoveset(formIndex?: integer): void {
switch (true) { switch (true) {
case (this.species.speciesId === Species.SMEARGLE): case (this.species.speciesId === Species.SMEARGLE):
this.moveset = [ this.moveset = [
new PokemonMove(Moves.SKETCH), new PokemonMove(Moves.SKETCH),
new PokemonMove(Moves.SKETCH), new PokemonMove(Moves.SKETCH),
new PokemonMove(Moves.SKETCH), new PokemonMove(Moves.SKETCH),
new PokemonMove(Moves.SKETCH) new PokemonMove(Moves.SKETCH)
];
break;
case (this.species.speciesId === Species.ETERNATUS):
this.moveset = (formIndex !== undefined ? formIndex : this.formIndex)
? [
new PokemonMove(Moves.DYNAMAX_CANNON),
new PokemonMove(Moves.CROSS_POISON),
new PokemonMove(Moves.FLAMETHROWER),
new PokemonMove(Moves.RECOVER, 0, -4)
]
: [
new PokemonMove(Moves.ETERNABEAM),
new PokemonMove(Moves.SLUDGE_BOMB),
new PokemonMove(Moves.FLAMETHROWER),
new PokemonMove(Moves.COSMIC_POWER)
]; ];
if (this.scene.gameMode.hasChallenge(Challenges.INVERSE_BATTLE)) { break;
this.moveset[2] = new PokemonMove(Moves.THUNDERBOLT); case (this.species.speciesId === Species.ETERNATUS):
} this.moveset = (formIndex !== undefined ? formIndex : this.formIndex)
break; ? [
default: new PokemonMove(Moves.DYNAMAX_CANNON),
super.generateAndPopulateMoveset(); new PokemonMove(Moves.CROSS_POISON),
break; new PokemonMove(Moves.FLAMETHROWER),
new PokemonMove(Moves.RECOVER, 0, -4)
]
: [
new PokemonMove(Moves.ETERNABEAM),
new PokemonMove(Moves.SLUDGE_BOMB),
new PokemonMove(Moves.FLAMETHROWER),
new PokemonMove(Moves.COSMIC_POWER)
];
if (this.scene.gameMode.hasChallenge(Challenges.INVERSE_BATTLE)) {
this.moveset[2] = new PokemonMove(Moves.THUNDERBOLT);
}
break;
default:
super.generateAndPopulateMoveset();
break;
} }
} }
@ -4569,135 +4569,135 @@ export class EnemyPokemon extends Pokemon {
} }
} }
switch (this.aiType) { switch (this.aiType) {
case AiType.RANDOM: // No enemy should spawn with this AI type in-game case AiType.RANDOM: // No enemy should spawn with this AI type in-game
const moveId = movePool[this.scene.randBattleSeedInt(movePool.length)]!.moveId; // TODO: is the bang correct? const moveId = movePool[this.scene.randBattleSeedInt(movePool.length)]!.moveId; // TODO: is the bang correct?
return { move: moveId, targets: this.getNextTargets(moveId) }; return { move: moveId, targets: this.getNextTargets(moveId) };
case AiType.SMART_RANDOM: case AiType.SMART_RANDOM:
case AiType.SMART: case AiType.SMART:
/** /**
* Search this Pokemon's move pool for moves that will KO an opposing target. * Search this Pokemon's move pool for moves that will KO an opposing target.
* If there are any moves that can KO an opponent (i.e. a player Pokemon), * If there are any moves that can KO an opponent (i.e. a player Pokemon),
* those moves are the only ones considered for selection on this turn. * those moves are the only ones considered for selection on this turn.
*/ */
const koMoves = movePool.filter(pkmnMove => { const koMoves = movePool.filter(pkmnMove => {
if (!pkmnMove) { if (!pkmnMove) {
return false; return false;
} }
const move = pkmnMove.getMove()!; const move = pkmnMove.getMove()!;
if (move.moveTarget === MoveTarget.ATTACKER) { if (move.moveTarget === MoveTarget.ATTACKER) {
return false; return false;
} }
const fieldPokemon = this.scene.getField(); const fieldPokemon = this.scene.getField();
const moveTargets = getMoveTargets(this, move.id).targets const moveTargets = getMoveTargets(this, move.id).targets
.map(ind => fieldPokemon[ind]) .map(ind => fieldPokemon[ind])
.filter(p => this.isPlayer() !== p.isPlayer()); .filter(p => this.isPlayer() !== p.isPlayer());
// Only considers critical hits for crit-only moves or when this Pokemon is under the effect of Laser Focus // Only considers critical hits for crit-only moves or when this Pokemon is under the effect of Laser Focus
const isCritical = move.hasAttr(CritOnlyAttr) || !!this.getTag(BattlerTagType.ALWAYS_CRIT); const isCritical = move.hasAttr(CritOnlyAttr) || !!this.getTag(BattlerTagType.ALWAYS_CRIT);
return move.category !== MoveCategory.STATUS return move.category !== MoveCategory.STATUS
&& moveTargets.some(p => { && moveTargets.some(p => {
const doesNotFail = move.applyConditions(this, p, move) || [ Moves.SUCKER_PUNCH, Moves.UPPER_HAND, Moves.THUNDERCLAP ].includes(move.id); const doesNotFail = move.applyConditions(this, p, move) || [ Moves.SUCKER_PUNCH, Moves.UPPER_HAND, Moves.THUNDERCLAP ].includes(move.id);
return doesNotFail && p.getAttackDamage(this, move, !p.battleData.abilityRevealed, false, isCritical).damage >= p.hp; return doesNotFail && p.getAttackDamage(this, move, !p.battleData.abilityRevealed, false, isCritical).damage >= p.hp;
}); });
}, this); }, this);
if (koMoves.length > 0) { if (koMoves.length > 0) {
movePool = koMoves; movePool = koMoves;
} }
/** /**
* Move selection is based on the move's calculated "benefit score" against the * Move selection is based on the move's calculated "benefit score" against the
* best possible target(s) (as determined by {@linkcode getNextTargets}). * best possible target(s) (as determined by {@linkcode getNextTargets}).
* For more information on how benefit scores are calculated, see `docs/enemy-ai.md`. * For more information on how benefit scores are calculated, see `docs/enemy-ai.md`.
*/ */
const moveScores = movePool.map(() => 0); const moveScores = movePool.map(() => 0);
const moveTargets = Object.fromEntries(movePool.map(m => [ m!.moveId, this.getNextTargets(m!.moveId) ])); // TODO: are those bangs correct? const moveTargets = Object.fromEntries(movePool.map(m => [ m!.moveId, this.getNextTargets(m!.moveId) ])); // TODO: are those bangs correct?
for (const m in movePool) { for (const m in movePool) {
const pokemonMove = movePool[m]!; // TODO: is the bang correct? const pokemonMove = movePool[m]!; // TODO: is the bang correct?
const move = pokemonMove.getMove(); const move = pokemonMove.getMove();
let moveScore = moveScores[m]; let moveScore = moveScores[m];
const targetScores: integer[] = []; const targetScores: integer[] = [];
for (const mt of moveTargets[move.id]) { for (const mt of moveTargets[move.id]) {
// Prevent a target score from being calculated when the target is whoever attacks the user // Prevent a target score from being calculated when the target is whoever attacks the user
if (mt === BattlerIndex.ATTACKER) { if (mt === BattlerIndex.ATTACKER) {
break; break;
} }
const target = this.scene.getField()[mt]; const target = this.scene.getField()[mt];
/** /**
* The "target score" of a move is given by the move's user benefit score + the move's target benefit score. * The "target score" of a move is given by the move's user benefit score + the move's target benefit score.
* If the target is an ally, the target benefit score is multiplied by -1. * If the target is an ally, the target benefit score is multiplied by -1.
*/ */
let targetScore = move.getUserBenefitScore(this, target, move) + move.getTargetBenefitScore(this, target, move) * (mt < BattlerIndex.ENEMY === this.isPlayer() ? 1 : -1); let targetScore = move.getUserBenefitScore(this, target, move) + move.getTargetBenefitScore(this, target, move) * (mt < BattlerIndex.ENEMY === this.isPlayer() ? 1 : -1);
if (Number.isNaN(targetScore)) { if (Number.isNaN(targetScore)) {
console.error(`Move ${move.name} returned score of NaN`); console.error(`Move ${move.name} returned score of NaN`);
targetScore = 0; targetScore = 0;
} }
/** /**
* If this move is unimplemented, or the move is known to fail when used, set its * If this move is unimplemented, or the move is known to fail when used, set its
* target score to -20 * target score to -20
*/ */
if ((move.name.endsWith(" (N)") || !move.applyConditions(this, target, move)) && ![ Moves.SUCKER_PUNCH, Moves.UPPER_HAND, Moves.THUNDERCLAP ].includes(move.id)) { if ((move.name.endsWith(" (N)") || !move.applyConditions(this, target, move)) && ![ Moves.SUCKER_PUNCH, Moves.UPPER_HAND, Moves.THUNDERCLAP ].includes(move.id)) {
targetScore = -20; targetScore = -20;
} else if (move instanceof AttackMove) { } else if (move instanceof AttackMove) {
/** /**
* Attack moves are given extra multipliers to their base benefit score based on * Attack moves are given extra multipliers to their base benefit score based on
* the move's type effectiveness against the target and whether the move is a STAB move. * the move's type effectiveness against the target and whether the move is a STAB move.
*/ */
const effectiveness = target.getMoveEffectiveness(this, move, !target.battleData?.abilityRevealed); const effectiveness = target.getMoveEffectiveness(this, move, !target.battleData?.abilityRevealed);
if (target.isPlayer() !== this.isPlayer()) { if (target.isPlayer() !== this.isPlayer()) {
targetScore *= effectiveness; targetScore *= effectiveness;
if (this.isOfType(move.type)) { if (this.isOfType(move.type)) {
targetScore *= 1.5; targetScore *= 1.5;
}
} else if (effectiveness) {
targetScore /= effectiveness;
if (this.isOfType(move.type)) {
targetScore /= 1.5;
}
} }
} else if (effectiveness) { /** If a move has a base benefit score of 0, its benefit score is assumed to be unimplemented at this point */
targetScore /= effectiveness; if (!targetScore) {
if (this.isOfType(move.type)) { targetScore = -20;
targetScore /= 1.5;
} }
} }
/** If a move has a base benefit score of 0, its benefit score is assumed to be unimplemented at this point */ targetScores.push(targetScore);
if (!targetScore) {
targetScore = -20;
}
} }
targetScores.push(targetScore); // When a move has multiple targets, its score is equal to the maximum target score across all targets
moveScore += Math.max(...targetScores);
// could make smarter by checking opponent def/spdef
moveScores[m] = moveScore;
} }
// When a move has multiple targets, its score is equal to the maximum target score across all targets
moveScore += Math.max(...targetScores);
// could make smarter by checking opponent def/spdef console.log(moveScores);
moveScores[m] = moveScore;
}
console.log(moveScores); // Sort the move pool in decreasing order of move score
const sortedMovePool = movePool.slice(0);
// Sort the move pool in decreasing order of move score sortedMovePool.sort((a, b) => {
const sortedMovePool = movePool.slice(0); const scoreA = moveScores[movePool.indexOf(a)];
sortedMovePool.sort((a, b) => { const scoreB = moveScores[movePool.indexOf(b)];
const scoreA = moveScores[movePool.indexOf(a)]; return scoreA < scoreB ? 1 : scoreA > scoreB ? -1 : 0;
const scoreB = moveScores[movePool.indexOf(b)]; });
return scoreA < scoreB ? 1 : scoreA > scoreB ? -1 : 0; let r = 0;
}); if (this.aiType === AiType.SMART_RANDOM) {
let r = 0;
if (this.aiType === AiType.SMART_RANDOM) {
// Has a 5/8 chance to select the best move, and a 3/8 chance to advance to the next best move (and repeat this roll) // Has a 5/8 chance to select the best move, and a 3/8 chance to advance to the next best move (and repeat this roll)
while (r < sortedMovePool.length - 1 && this.scene.randBattleSeedInt(8) >= 5) { while (r < sortedMovePool.length - 1 && this.scene.randBattleSeedInt(8) >= 5) {
r++; r++;
} }
} else if (this.aiType === AiType.SMART) { } else if (this.aiType === AiType.SMART) {
// The chance to advance to the next best move increases when the compared moves' scores are closer to each other. // The chance to advance to the next best move increases when the compared moves' scores are closer to each other.
while (r < sortedMovePool.length - 1 && (moveScores[movePool.indexOf(sortedMovePool[r + 1])] / moveScores[movePool.indexOf(sortedMovePool[r])]) >= 0 while (r < sortedMovePool.length - 1 && (moveScores[movePool.indexOf(sortedMovePool[r + 1])] / moveScores[movePool.indexOf(sortedMovePool[r])]) >= 0
&& this.scene.randBattleSeedInt(100) < Math.round((moveScores[movePool.indexOf(sortedMovePool[r + 1])] / moveScores[movePool.indexOf(sortedMovePool[r])]) * 50)) { && this.scene.randBattleSeedInt(100) < Math.round((moveScores[movePool.indexOf(sortedMovePool[r + 1])] / moveScores[movePool.indexOf(sortedMovePool[r])]) * 50)) {
r++; r++;
}
} }
} console.log(movePool.map(m => m!.getName()), moveScores, r, sortedMovePool.map(m => m!.getName())); // TODO: are those bangs correct?
console.log(movePool.map(m => m!.getName()), moveScores, r, sortedMovePool.map(m => m!.getName())); // TODO: are those bangs correct? return { move: sortedMovePool[r]!.moveId, targets: moveTargets[sortedMovePool[r]!.moveId] };
return { move: sortedMovePool[r]!.moveId, targets: moveTargets[sortedMovePool[r]!.moveId] };
} }
} }
@ -4845,10 +4845,10 @@ export class EnemyPokemon extends Pokemon {
} }
switch (this.scene.currentBattle.battleSpec) { switch (this.scene.currentBattle.battleSpec) {
case BattleSpec.FINAL_BOSS: case BattleSpec.FINAL_BOSS:
if (!this.formIndex && this.bossSegmentIndex < 1) { if (!this.formIndex && this.bossSegmentIndex < 1) {
damage = Math.min(damage, this.hp - 1); damage = Math.min(damage, this.hp - 1);
} }
} }
const ret = super.damage(damage, ignoreSegments, preventEndure, ignoreFaintPhase); const ret = super.damage(damage, ignoreSegments, preventEndure, ignoreFaintPhase);

View File

@ -65,16 +65,16 @@ export default class Trainer extends Phaser.GameObjects.Container {
} }
switch (this.variant) { switch (this.variant) {
case TrainerVariant.FEMALE: case TrainerVariant.FEMALE:
if (!this.config.hasGenders) { if (!this.config.hasGenders) {
variant = TrainerVariant.DEFAULT; variant = TrainerVariant.DEFAULT;
} }
break; break;
case TrainerVariant.DOUBLE: case TrainerVariant.DOUBLE:
if (!this.config.hasDouble) { if (!this.config.hasDouble) {
variant = TrainerVariant.DEFAULT; variant = TrainerVariant.DEFAULT;
} }
break; break;
} }
console.log(Object.keys(trainerPartyTemplates)[Object.values(trainerPartyTemplates).indexOf(this.getPartyTemplate())]); console.log(Object.keys(trainerPartyTemplates)[Object.values(trainerPartyTemplates).indexOf(this.getPartyTemplate())]);
@ -229,21 +229,21 @@ export default class Trainer extends Phaser.GameObjects.Container {
const strength = partyTemplate.getStrength(i); const strength = partyTemplate.getStrength(i);
switch (strength) { switch (strength) {
case PartyMemberStrength.WEAKER: case PartyMemberStrength.WEAKER:
multiplier = 0.95; multiplier = 0.95;
break; break;
case PartyMemberStrength.WEAK: case PartyMemberStrength.WEAK:
multiplier = 1.0; multiplier = 1.0;
break; break;
case PartyMemberStrength.AVERAGE: case PartyMemberStrength.AVERAGE:
multiplier = 1.1; multiplier = 1.1;
break; break;
case PartyMemberStrength.STRONG: case PartyMemberStrength.STRONG:
multiplier = 1.2; multiplier = 1.2;
break; break;
case PartyMemberStrength.STRONGER: case PartyMemberStrength.STRONGER:
multiplier = 1.25; multiplier = 1.25;
break; break;
} }
let levelOffset = 0; let levelOffset = 0;
@ -515,19 +515,19 @@ export default class Trainer extends Phaser.GameObjects.Container {
getPartyMemberModifierChanceMultiplier(index: integer): number { getPartyMemberModifierChanceMultiplier(index: integer): number {
switch (this.getPartyTemplate().getStrength(index)) { switch (this.getPartyTemplate().getStrength(index)) {
case PartyMemberStrength.WEAKER: case PartyMemberStrength.WEAKER:
return 0.75; return 0.75;
case PartyMemberStrength.WEAK: case PartyMemberStrength.WEAK:
return 0.675; return 0.675;
case PartyMemberStrength.AVERAGE: case PartyMemberStrength.AVERAGE:
return 0.5625; return 0.5625;
case PartyMemberStrength.STRONG: case PartyMemberStrength.STRONG:
return 0.45; return 0.45;
case PartyMemberStrength.STRONGER: case PartyMemberStrength.STRONGER:
return 0.375; return 0.375;
default: default:
console.warn("getPartyMemberModifierChanceMultiplier not defined. Using default 0"); console.warn("getPartyMemberModifierChanceMultiplier not defined. Using default 0");
return 0; return 0;
} }
} }

View File

@ -92,10 +92,10 @@ export class GameMode implements GameModeConfig {
return Overrides.STARTING_LEVEL_OVERRIDE; return Overrides.STARTING_LEVEL_OVERRIDE;
} }
switch (this.modeId) { switch (this.modeId) {
case GameModes.DAILY: case GameModes.DAILY:
return 20; return 20;
default: default:
return 5; return 5;
} }
} }
@ -117,19 +117,19 @@ export class GameMode implements GameModeConfig {
*/ */
getStartingBiome(scene: BattleScene): Biome { getStartingBiome(scene: BattleScene): Biome {
switch (this.modeId) { switch (this.modeId) {
case GameModes.DAILY: case GameModes.DAILY:
return scene.generateRandomBiome(this.getWaveForDifficulty(1)); return scene.generateRandomBiome(this.getWaveForDifficulty(1));
default: default:
return Overrides.STARTING_BIOME_OVERRIDE || Biome.TOWN; return Overrides.STARTING_BIOME_OVERRIDE || Biome.TOWN;
} }
} }
getWaveForDifficulty(waveIndex: integer, ignoreCurveChanges: boolean = false): integer { getWaveForDifficulty(waveIndex: integer, ignoreCurveChanges: boolean = false): integer {
switch (this.modeId) { switch (this.modeId) {
case GameModes.DAILY: case GameModes.DAILY:
return waveIndex + 30 + (!ignoreCurveChanges ? Math.floor(waveIndex / 5) : 0); return waveIndex + 30 + (!ignoreCurveChanges ? Math.floor(waveIndex / 5) : 0);
default: default:
return waveIndex; return waveIndex;
} }
} }
@ -186,10 +186,10 @@ export class GameMode implements GameModeConfig {
isTrainerBoss(waveIndex: integer, biomeType: Biome, offsetGym: boolean): boolean { isTrainerBoss(waveIndex: integer, biomeType: Biome, offsetGym: boolean): boolean {
switch (this.modeId) { switch (this.modeId) {
case GameModes.DAILY: case GameModes.DAILY:
return waveIndex > 10 && waveIndex < 50 && !(waveIndex % 10); return waveIndex > 10 && waveIndex < 50 && !(waveIndex % 10);
default: default:
return (waveIndex % 30) === (offsetGym ? 0 : 20) && (biomeType !== Biome.END || this.isClassic || this.isWaveFinal(waveIndex)); return (waveIndex % 30) === (offsetGym ? 0 : 20) && (biomeType !== Biome.END || this.isClassic || this.isWaveFinal(waveIndex));
} }
} }
@ -211,14 +211,14 @@ export class GameMode implements GameModeConfig {
*/ */
isWaveFinal(waveIndex: integer, modeId: GameModes = this.modeId): boolean { isWaveFinal(waveIndex: integer, modeId: GameModes = this.modeId): boolean {
switch (modeId) { switch (modeId) {
case GameModes.CLASSIC: case GameModes.CLASSIC:
case GameModes.CHALLENGE: case GameModes.CHALLENGE:
return waveIndex === 200; return waveIndex === 200;
case GameModes.ENDLESS: case GameModes.ENDLESS:
case GameModes.SPLICED_ENDLESS: case GameModes.SPLICED_ENDLESS:
return !(waveIndex % 250); return !(waveIndex % 250);
case GameModes.DAILY: case GameModes.DAILY:
return waveIndex === 50; return waveIndex === 50;
} }
} }
@ -287,40 +287,40 @@ export class GameMode implements GameModeConfig {
getClearScoreBonus(): integer { getClearScoreBonus(): integer {
switch (this.modeId) { switch (this.modeId) {
case GameModes.CLASSIC: case GameModes.CLASSIC:
case GameModes.CHALLENGE: case GameModes.CHALLENGE:
return 5000; return 5000;
case GameModes.DAILY: case GameModes.DAILY:
return 2500; return 2500;
default: default:
return 0; return 0;
} }
} }
getEnemyModifierChance(isBoss: boolean): integer { getEnemyModifierChance(isBoss: boolean): integer {
switch (this.modeId) { switch (this.modeId) {
case GameModes.CLASSIC: case GameModes.CLASSIC:
case GameModes.CHALLENGE: case GameModes.CHALLENGE:
case GameModes.DAILY: case GameModes.DAILY:
return !isBoss ? 18 : 6; return !isBoss ? 18 : 6;
case GameModes.ENDLESS: case GameModes.ENDLESS:
case GameModes.SPLICED_ENDLESS: case GameModes.SPLICED_ENDLESS:
return !isBoss ? 12 : 4; return !isBoss ? 12 : 4;
} }
} }
getName(): string { getName(): string {
switch (this.modeId) { switch (this.modeId) {
case GameModes.CLASSIC: case GameModes.CLASSIC:
return i18next.t("gameMode:classic"); return i18next.t("gameMode:classic");
case GameModes.ENDLESS: case GameModes.ENDLESS:
return i18next.t("gameMode:endless"); return i18next.t("gameMode:endless");
case GameModes.SPLICED_ENDLESS: case GameModes.SPLICED_ENDLESS:
return i18next.t("gameMode:endlessSpliced"); return i18next.t("gameMode:endlessSpliced");
case GameModes.DAILY: case GameModes.DAILY:
return i18next.t("gameMode:dailyRun"); return i18next.t("gameMode:dailyRun");
case GameModes.CHALLENGE: case GameModes.CHALLENGE:
return i18next.t("gameMode:challenge"); return i18next.t("gameMode:challenge");
} }
} }
@ -329,42 +329,42 @@ export class GameMode implements GameModeConfig {
*/ */
getMysteryEncounterLegalWaves(): [number, number] { getMysteryEncounterLegalWaves(): [number, number] {
switch (this.modeId) { switch (this.modeId) {
default: default:
return [ 0, 0 ]; return [ 0, 0 ];
case GameModes.CLASSIC: case GameModes.CLASSIC:
return CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES; return CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES;
case GameModes.CHALLENGE: case GameModes.CHALLENGE:
return CHALLENGE_MODE_MYSTERY_ENCOUNTER_WAVES; return CHALLENGE_MODE_MYSTERY_ENCOUNTER_WAVES;
} }
} }
static getModeName(modeId: GameModes): string { static getModeName(modeId: GameModes): string {
switch (modeId) { switch (modeId) {
case GameModes.CLASSIC: case GameModes.CLASSIC:
return i18next.t("gameMode:classic"); return i18next.t("gameMode:classic");
case GameModes.ENDLESS: case GameModes.ENDLESS:
return i18next.t("gameMode:endless"); return i18next.t("gameMode:endless");
case GameModes.SPLICED_ENDLESS: case GameModes.SPLICED_ENDLESS:
return i18next.t("gameMode:endlessSpliced"); return i18next.t("gameMode:endlessSpliced");
case GameModes.DAILY: case GameModes.DAILY:
return i18next.t("gameMode:dailyRun"); return i18next.t("gameMode:dailyRun");
case GameModes.CHALLENGE: case GameModes.CHALLENGE:
return i18next.t("gameMode:challenge"); return i18next.t("gameMode:challenge");
} }
} }
} }
export function getGameMode(gameMode: GameModes): GameMode { export function getGameMode(gameMode: GameModes): GameMode {
switch (gameMode) { switch (gameMode) {
case GameModes.CLASSIC: case GameModes.CLASSIC:
return new GameMode(GameModes.CLASSIC, { isClassic: true, hasTrainers: true, hasMysteryEncounters: true }, classicFixedBattles); return new GameMode(GameModes.CLASSIC, { isClassic: true, hasTrainers: true, hasMysteryEncounters: true }, classicFixedBattles);
case GameModes.ENDLESS: case GameModes.ENDLESS:
return new GameMode(GameModes.ENDLESS, { isEndless: true, hasShortBiomes: true, hasRandomBosses: true }); return new GameMode(GameModes.ENDLESS, { isEndless: true, hasShortBiomes: true, hasRandomBosses: true });
case GameModes.SPLICED_ENDLESS: case GameModes.SPLICED_ENDLESS:
return new GameMode(GameModes.SPLICED_ENDLESS, { isEndless: true, hasShortBiomes: true, hasRandomBosses: true, isSplicedOnly: true }); return new GameMode(GameModes.SPLICED_ENDLESS, { isEndless: true, hasShortBiomes: true, hasRandomBosses: true, isSplicedOnly: true });
case GameModes.DAILY: case GameModes.DAILY:
return new GameMode(GameModes.DAILY, { isDaily: true, hasTrainers: true, hasNoShop: true }); return new GameMode(GameModes.DAILY, { isDaily: true, hasTrainers: true, hasNoShop: true });
case GameModes.CHALLENGE: case GameModes.CHALLENGE:
return new GameMode(GameModes.CHALLENGE, { isClassic: true, hasTrainers: true, isChallenge: true, hasMysteryEncounters: true }, classicFixedBattles); return new GameMode(GameModes.CHALLENGE, { isClassic: true, hasTrainers: true, isChallenge: true, hasMysteryEncounters: true }, classicFixedBattles);
} }
} }

View File

@ -477,18 +477,18 @@ export class LoadingScene extends SceneBase {
this.load.on(this.LOAD_EVENTS.FILE_COMPLETE, (key: string) => { this.load.on(this.LOAD_EVENTS.FILE_COMPLETE, (key: string) => {
assetText.setText(i18next.t("menu:loadingAsset", { assetName: key })); assetText.setText(i18next.t("menu:loadingAsset", { assetName: key }));
switch (key) { switch (key) {
case "loading_bg": case "loading_bg":
bg.setTexture("loading_bg"); bg.setTexture("loading_bg");
if (mobile) { if (mobile) {
bg.setVisible(true); bg.setVisible(true);
} }
break; break;
case "logo": case "logo":
logo.setTexture("logo"); logo.setTexture("logo");
if (mobile) { if (mobile) {
logo.setVisible(true); logo.setVisible(true);
} }
break; break;
} }
}); });

View File

@ -13,21 +13,21 @@ export function getPokemonNameWithAffix(pokemon: Pokemon | undefined): string {
} }
switch (pokemon.scene.currentBattle.battleSpec) { switch (pokemon.scene.currentBattle.battleSpec) {
case BattleSpec.DEFAULT: case BattleSpec.DEFAULT:
return !pokemon.isPlayer() return !pokemon.isPlayer()
? pokemon.hasTrainer() ? pokemon.hasTrainer()
? i18next.t("battle:foePokemonWithAffix", { ? i18next.t("battle:foePokemonWithAffix", {
pokemonName: pokemon.getNameToRender(), pokemonName: pokemon.getNameToRender(),
}) })
: i18next.t("battle:wildPokemonWithAffix", { : i18next.t("battle:wildPokemonWithAffix", {
pokemonName: pokemon.getNameToRender(), pokemonName: pokemon.getNameToRender(),
}) })
: pokemon.getNameToRender(); : pokemon.getNameToRender();
case BattleSpec.FINAL_BOSS: case BattleSpec.FINAL_BOSS:
return !pokemon.isPlayer() return !pokemon.isPlayer()
? i18next.t("battle:foePokemonWithAffix", { pokemonName: pokemon.getNameToRender() }) ? i18next.t("battle:foePokemonWithAffix", { pokemonName: pokemon.getNameToRender() })
: pokemon.getNameToRender(); : pokemon.getNameToRender();
default: default:
return pokemon.getNameToRender(); return pokemon.getNameToRender();
} }
} }

View File

@ -78,18 +78,18 @@ export class ModifierType {
} }
let poolTypes: ModifierPoolType[]; let poolTypes: ModifierPoolType[];
switch (poolType) { switch (poolType) {
case ModifierPoolType.PLAYER: case ModifierPoolType.PLAYER:
poolTypes = [ poolType, ModifierPoolType.TRAINER, ModifierPoolType.WILD ]; poolTypes = [ poolType, ModifierPoolType.TRAINER, ModifierPoolType.WILD ];
break; break;
case ModifierPoolType.WILD: case ModifierPoolType.WILD:
poolTypes = [ poolType, ModifierPoolType.PLAYER, ModifierPoolType.TRAINER ]; poolTypes = [ poolType, ModifierPoolType.PLAYER, ModifierPoolType.TRAINER ];
break; break;
case ModifierPoolType.TRAINER: case ModifierPoolType.TRAINER:
poolTypes = [ poolType, ModifierPoolType.PLAYER, ModifierPoolType.WILD ]; poolTypes = [ poolType, ModifierPoolType.PLAYER, ModifierPoolType.WILD ];
break; break;
default: default:
poolTypes = [ poolType ]; poolTypes = [ poolType ];
break; break;
} }
// Try multiple pool types in case of stolen items // Try multiple pool types in case of stolen items
for (const type of poolTypes) { for (const type of poolTypes) {
@ -502,42 +502,42 @@ export class BerryModifierType extends PokemonHeldItemModifierType implements Ge
function getAttackTypeBoosterItemName(type: Type) { function getAttackTypeBoosterItemName(type: Type) {
switch (type) { switch (type) {
case Type.NORMAL: case Type.NORMAL:
return "Silk Scarf"; return "Silk Scarf";
case Type.FIGHTING: case Type.FIGHTING:
return "Black Belt"; return "Black Belt";
case Type.FLYING: case Type.FLYING:
return "Sharp Beak"; return "Sharp Beak";
case Type.POISON: case Type.POISON:
return "Poison Barb"; return "Poison Barb";
case Type.GROUND: case Type.GROUND:
return "Soft Sand"; return "Soft Sand";
case Type.ROCK: case Type.ROCK:
return "Hard Stone"; return "Hard Stone";
case Type.BUG: case Type.BUG:
return "Silver Powder"; return "Silver Powder";
case Type.GHOST: case Type.GHOST:
return "Spell Tag"; return "Spell Tag";
case Type.STEEL: case Type.STEEL:
return "Metal Coat"; return "Metal Coat";
case Type.FIRE: case Type.FIRE:
return "Charcoal"; return "Charcoal";
case Type.WATER: case Type.WATER:
return "Mystic Water"; return "Mystic Water";
case Type.GRASS: case Type.GRASS:
return "Miracle Seed"; return "Miracle Seed";
case Type.ELECTRIC: case Type.ELECTRIC:
return "Magnet"; return "Magnet";
case Type.PSYCHIC: case Type.PSYCHIC:
return "Twisted Spoon"; return "Twisted Spoon";
case Type.ICE: case Type.ICE:
return "Never-Melt Ice"; return "Never-Melt Ice";
case Type.DRAGON: case Type.DRAGON:
return "Dragon Fang"; return "Dragon Fang";
case Type.DARK: case Type.DARK:
return "Black Glasses"; return "Black Glasses";
case Type.FAIRY: case Type.FAIRY:
return "Fairy Feather"; return "Fairy Feather";
} }
} }
@ -1149,15 +1149,15 @@ class FormChangeItemModifierTypeGenerator extends ModifierTypeGenerator {
foundN_SOLAR = false; foundN_SOLAR = false;
formChangeItemTriggers.forEach((fc, i) => { formChangeItemTriggers.forEach((fc, i) => {
switch (fc.item) { switch (fc.item) {
case FormChangeItem.ULTRANECROZIUM_Z: case FormChangeItem.ULTRANECROZIUM_Z:
foundULTRA_Z = true; foundULTRA_Z = true;
break; break;
case FormChangeItem.N_LUNARIZER: case FormChangeItem.N_LUNARIZER:
foundN_LUNA = true; foundN_LUNA = true;
break; break;
case FormChangeItem.N_SOLARIZER: case FormChangeItem.N_SOLARIZER:
foundN_SOLAR = true; foundN_SOLAR = true;
break; break;
} }
}); });
if (foundULTRA_Z && foundN_LUNA && foundN_SOLAR) { if (foundULTRA_Z && foundN_LUNA && foundN_SOLAR) {
@ -1975,21 +1975,21 @@ let enemyBuffIgnoredPoolIndexes = {}; // eslint-disable-line @typescript-eslint/
export function getModifierPoolForType(poolType: ModifierPoolType): ModifierPool { export function getModifierPoolForType(poolType: ModifierPoolType): ModifierPool {
let pool: ModifierPool; let pool: ModifierPool;
switch (poolType) { switch (poolType) {
case ModifierPoolType.PLAYER: case ModifierPoolType.PLAYER:
pool = modifierPool; pool = modifierPool;
break; break;
case ModifierPoolType.WILD: case ModifierPoolType.WILD:
pool = wildModifierPool; pool = wildModifierPool;
break; break;
case ModifierPoolType.TRAINER: case ModifierPoolType.TRAINER:
pool = trainerModifierPool; pool = trainerModifierPool;
break; break;
case ModifierPoolType.ENEMY_BUFF: case ModifierPoolType.ENEMY_BUFF:
pool = enemyBuffModifierPool; pool = enemyBuffModifierPool;
break; break;
case ModifierPoolType.DAILY_STARTER: case ModifierPoolType.DAILY_STARTER:
pool = dailyStarterModifierPool; pool = dailyStarterModifierPool;
break; break;
} }
return pool; return pool;
} }
@ -2060,23 +2060,23 @@ export function regenerateModifierPoolThresholds(party: Pokemon[], poolType: Mod
console.table(modifierTableData); console.table(modifierTableData);
} }
switch (poolType) { switch (poolType) {
case ModifierPoolType.PLAYER: case ModifierPoolType.PLAYER:
modifierPoolThresholds = thresholds; modifierPoolThresholds = thresholds;
ignoredPoolIndexes = ignoredIndexes; ignoredPoolIndexes = ignoredIndexes;
break; break;
case ModifierPoolType.WILD: case ModifierPoolType.WILD:
case ModifierPoolType.TRAINER: case ModifierPoolType.TRAINER:
enemyModifierPoolThresholds = thresholds; enemyModifierPoolThresholds = thresholds;
enemyIgnoredPoolIndexes = ignoredIndexes; enemyIgnoredPoolIndexes = ignoredIndexes;
break; break;
case ModifierPoolType.ENEMY_BUFF: case ModifierPoolType.ENEMY_BUFF:
enemyBuffModifierPoolThresholds = thresholds; enemyBuffModifierPoolThresholds = thresholds;
enemyBuffIgnoredPoolIndexes = ignoredIndexes; enemyBuffIgnoredPoolIndexes = ignoredIndexes;
break; break;
case ModifierPoolType.DAILY_STARTER: case ModifierPoolType.DAILY_STARTER:
dailyStarterModifierPoolThresholds = thresholds; dailyStarterModifierPoolThresholds = thresholds;
ignoredDailyStarterPoolIndexes = ignoredIndexes; ignoredDailyStarterPoolIndexes = ignoredIndexes;
break; break;
} }
} }
@ -2247,15 +2247,15 @@ export function getPlayerShopModifierTypeOptionsForWave(waveIndex: integer, base
export function getEnemyBuffModifierForWave(tier: ModifierTier, enemyModifiers: PersistentModifier[], scene: BattleScene): EnemyPersistentModifier { export function getEnemyBuffModifierForWave(tier: ModifierTier, enemyModifiers: PersistentModifier[], scene: BattleScene): EnemyPersistentModifier {
let tierStackCount: number; let tierStackCount: number;
switch (tier) { switch (tier) {
case ModifierTier.ULTRA: case ModifierTier.ULTRA:
tierStackCount = 5; tierStackCount = 5;
break; break;
case ModifierTier.GREAT: case ModifierTier.GREAT:
tierStackCount = 3; tierStackCount = 3;
break; break;
default: default:
tierStackCount = 1; tierStackCount = 1;
break; break;
} }
const retryCount = 50; const retryCount = 50;
@ -2321,21 +2321,21 @@ function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType,
const pool = getModifierPoolForType(poolType); const pool = getModifierPoolForType(poolType);
let thresholds: object; let thresholds: object;
switch (poolType) { switch (poolType) {
case ModifierPoolType.PLAYER: case ModifierPoolType.PLAYER:
thresholds = modifierPoolThresholds; thresholds = modifierPoolThresholds;
break; break;
case ModifierPoolType.WILD: case ModifierPoolType.WILD:
thresholds = enemyModifierPoolThresholds; thresholds = enemyModifierPoolThresholds;
break; break;
case ModifierPoolType.TRAINER: case ModifierPoolType.TRAINER:
thresholds = enemyModifierPoolThresholds; thresholds = enemyModifierPoolThresholds;
break; break;
case ModifierPoolType.ENEMY_BUFF: case ModifierPoolType.ENEMY_BUFF:
thresholds = enemyBuffModifierPoolThresholds; thresholds = enemyBuffModifierPoolThresholds;
break; break;
case ModifierPoolType.DAILY_STARTER: case ModifierPoolType.DAILY_STARTER:
thresholds = dailyStarterModifierPoolThresholds; thresholds = dailyStarterModifierPoolThresholds;
break; break;
} }
if (tier === undefined) { if (tier === undefined) {
const tierValue = randSeedInt(1024); const tierValue = randSeedInt(1024);

View File

@ -1695,12 +1695,12 @@ export class TurnStatusEffectModifier extends PokemonHeldItemModifier {
super(type, pokemonId, stackCount); super(type, pokemonId, stackCount);
switch (type.id) { switch (type.id) {
case "TOXIC_ORB": case "TOXIC_ORB":
this.effect = StatusEffect.TOXIC; this.effect = StatusEffect.TOXIC;
break; break;
case "FLAME_ORB": case "FLAME_ORB":
this.effect = StatusEffect.BURN; this.effect = StatusEffect.BURN;
break; break;
} }
} }
@ -2684,15 +2684,15 @@ export class PokemonMultiHitModifier extends PokemonHeldItemModifier {
count.value *= (this.getStackCount() + 1); count.value *= (this.getStackCount() + 1);
switch (this.getStackCount()) { switch (this.getStackCount()) {
case 1: case 1:
power.value *= 0.4; power.value *= 0.4;
break; break;
case 2: case 2:
power.value *= 0.25; power.value *= 0.25;
break; break;
case 3: case 3:
power.value *= 0.175; power.value *= 0.175;
break; break;
} }
return true; return true;

View File

@ -84,170 +84,170 @@ export class CommandPhase extends FieldPhase {
let success: boolean; let success: boolean;
switch (command) { switch (command) {
case Command.FIGHT: case Command.FIGHT:
let useStruggle = false; let useStruggle = false;
if (cursor === -1 || if (cursor === -1 ||
playerPokemon.trySelectMove(cursor, args[0] as boolean) || playerPokemon.trySelectMove(cursor, args[0] as boolean) ||
(useStruggle = cursor > -1 && !playerPokemon.getMoveset().filter(m => m?.isUsable(playerPokemon)).length)) { (useStruggle = cursor > -1 && !playerPokemon.getMoveset().filter(m => m?.isUsable(playerPokemon)).length)) {
const moveId = !useStruggle ? cursor > -1 ? playerPokemon.getMoveset()[cursor]!.moveId : Moves.NONE : Moves.STRUGGLE; // TODO: is the bang correct? const moveId = !useStruggle ? cursor > -1 ? playerPokemon.getMoveset()[cursor]!.moveId : Moves.NONE : Moves.STRUGGLE; // TODO: is the bang correct?
const turnCommand: TurnCommand = { command: Command.FIGHT, cursor: cursor, move: { move: moveId, targets: [], ignorePP: args[0] }, args: args }; const turnCommand: TurnCommand = { command: Command.FIGHT, cursor: cursor, move: { move: moveId, targets: [], ignorePP: args[0] }, args: args };
const moveTargets: MoveTargetSet = args.length < 3 ? getMoveTargets(playerPokemon, moveId) : args[2]; const moveTargets: MoveTargetSet = args.length < 3 ? getMoveTargets(playerPokemon, moveId) : args[2];
if (!moveId) { if (!moveId) {
turnCommand.targets = [ this.fieldIndex ]; turnCommand.targets = [ this.fieldIndex ];
} }
console.log(moveTargets, getPokemonNameWithAffix(playerPokemon)); console.log(moveTargets, getPokemonNameWithAffix(playerPokemon));
if (moveTargets.targets.length > 1 && moveTargets.multiple) { if (moveTargets.targets.length > 1 && moveTargets.multiple) {
this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex)); this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex));
} }
if (moveTargets.targets.length <= 1 || moveTargets.multiple) { if (moveTargets.targets.length <= 1 || moveTargets.multiple) {
turnCommand.move!.targets = moveTargets.targets; //TODO: is the bang correct here? turnCommand.move!.targets = moveTargets.targets; //TODO: is the bang correct here?
} else if (playerPokemon.getTag(BattlerTagType.CHARGING) && playerPokemon.getMoveQueue().length >= 1) { } else if (playerPokemon.getTag(BattlerTagType.CHARGING) && playerPokemon.getMoveQueue().length >= 1) {
turnCommand.move!.targets = playerPokemon.getMoveQueue()[0].targets; //TODO: is the bang correct here? turnCommand.move!.targets = playerPokemon.getMoveQueue()[0].targets; //TODO: is the bang correct here?
} else { } else {
this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex)); this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex));
} }
this.scene.currentBattle.turnCommands[this.fieldIndex] = turnCommand; this.scene.currentBattle.turnCommands[this.fieldIndex] = turnCommand;
success = true; success = true;
} else if (cursor < playerPokemon.getMoveset().length) { } else if (cursor < playerPokemon.getMoveset().length) {
const move = playerPokemon.getMoveset()[cursor]!; //TODO: is this bang correct? const move = playerPokemon.getMoveset()[cursor]!; //TODO: is this bang correct?
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
// Decides between a Disabled, Not Implemented, or No PP translation message // Decides between a Disabled, Not Implemented, or No PP translation message
const errorMessage = const errorMessage =
playerPokemon.isMoveRestricted(move.moveId, playerPokemon) playerPokemon.isMoveRestricted(move.moveId, playerPokemon)
? playerPokemon.getRestrictingTag(move.moveId, playerPokemon)!.selectionDeniedText(playerPokemon, move.moveId) ? playerPokemon.getRestrictingTag(move.moveId, playerPokemon)!.selectionDeniedText(playerPokemon, move.moveId)
: move.getName().endsWith(" (N)") ? "battle:moveNotImplemented" : "battle:moveNoPP"; : move.getName().endsWith(" (N)") ? "battle:moveNotImplemented" : "battle:moveNoPP";
const moveName = move.getName().replace(" (N)", ""); // Trims off the indicator const moveName = move.getName().replace(" (N)", ""); // Trims off the indicator
this.scene.ui.showText(i18next.t(errorMessage, { moveName: moveName }), null, () => { this.scene.ui.showText(i18next.t(errorMessage, { moveName: moveName }), null, () => {
this.scene.ui.clearText(); this.scene.ui.clearText();
this.scene.ui.setMode(Mode.FIGHT, this.fieldIndex); this.scene.ui.setMode(Mode.FIGHT, this.fieldIndex);
}, null, true); }, null, true);
} }
break; break;
case Command.BALL: case Command.BALL:
const notInDex = (this.scene.getEnemyField().filter(p => p.isActive(true)).some(p => !p.scene.gameData.dexData[p.species.speciesId].caughtAttr) && this.scene.gameData.getStarterCount(d => !!d.caughtAttr) < Object.keys(speciesStarterCosts).length - 1); const notInDex = (this.scene.getEnemyField().filter(p => p.isActive(true)).some(p => !p.scene.gameData.dexData[p.species.speciesId].caughtAttr) && this.scene.gameData.getStarterCount(d => !!d.caughtAttr) < Object.keys(speciesStarterCosts).length - 1);
if (this.scene.arena.biomeType === Biome.END && (!this.scene.gameMode.isClassic || this.scene.gameMode.isFreshStartChallenge() || notInDex )) { if (this.scene.arena.biomeType === Biome.END && (!this.scene.gameMode.isClassic || this.scene.gameMode.isFreshStartChallenge() || notInDex )) {
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(i18next.t("battle:noPokeballForce"), null, () => {
this.scene.ui.showText("", 0);
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
}, null, true);
} else if (this.scene.currentBattle.battleType === BattleType.TRAINER) {
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(i18next.t("battle:noPokeballTrainer"), null, () => {
this.scene.ui.showText("", 0);
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
}, null, true);
} else if (this.scene.currentBattle.isBattleMysteryEncounter() && !this.scene.currentBattle.mysteryEncounter!.catchAllowed) {
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(i18next.t("battle:noPokeballMysteryEncounter"), null, () => {
this.scene.ui.showText("", 0);
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
}, null, true);
} else {
const targets = this.scene.getEnemyField().filter(p => p.isActive(true)).map(p => p.getBattlerIndex());
if (targets.length > 1) {
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(i18next.t("battle:noPokeballMulti"), null, () => { this.scene.ui.showText(i18next.t("battle:noPokeballForce"), null, () => {
this.scene.ui.showText("", 0); this.scene.ui.showText("", 0);
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
}, null, true); }, null, true);
} else if (cursor < 5) { } else if (this.scene.currentBattle.battleType === BattleType.TRAINER) {
const targetPokemon = this.scene.getEnemyField().find(p => p.isActive(true)); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
if (targetPokemon?.isBoss() && targetPokemon?.bossSegmentIndex >= 1 && !targetPokemon?.hasAbility(Abilities.WONDER_GUARD, false, true) && cursor < PokeballType.MASTER_BALL) { this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(i18next.t("battle:noPokeballTrainer"), null, () => {
this.scene.ui.showText("", 0);
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
}, null, true);
} else if (this.scene.currentBattle.isBattleMysteryEncounter() && !this.scene.currentBattle.mysteryEncounter!.catchAllowed) {
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(i18next.t("battle:noPokeballMysteryEncounter"), null, () => {
this.scene.ui.showText("", 0);
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
}, null, true);
} else {
const targets = this.scene.getEnemyField().filter(p => p.isActive(true)).map(p => p.getBattlerIndex());
if (targets.length > 1) {
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(i18next.t("battle:noPokeballStrong"), null, () => { this.scene.ui.showText(i18next.t("battle:noPokeballMulti"), null, () => {
this.scene.ui.showText("", 0); this.scene.ui.showText("", 0);
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
}, null, true); }, null, true);
} else { } else if (cursor < 5) {
this.scene.currentBattle.turnCommands[this.fieldIndex] = { command: Command.BALL, cursor: cursor }; const targetPokemon = this.scene.getEnemyField().find(p => p.isActive(true));
if (targetPokemon?.isBoss() && targetPokemon?.bossSegmentIndex >= 1 && !targetPokemon?.hasAbility(Abilities.WONDER_GUARD, false, true) && cursor < PokeballType.MASTER_BALL) {
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(i18next.t("battle:noPokeballStrong"), null, () => {
this.scene.ui.showText("", 0);
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
}, null, true);
} else {
this.scene.currentBattle.turnCommands[this.fieldIndex] = { command: Command.BALL, cursor: cursor };
this.scene.currentBattle.turnCommands[this.fieldIndex]!.targets = targets; this.scene.currentBattle.turnCommands[this.fieldIndex]!.targets = targets;
if (this.fieldIndex) { if (this.fieldIndex) {
this.scene.currentBattle.turnCommands[this.fieldIndex - 1]!.skip = true; this.scene.currentBattle.turnCommands[this.fieldIndex - 1]!.skip = true;
} }
success = true; success = true;
}
} }
} }
} break;
break; case Command.POKEMON:
case Command.POKEMON: case Command.RUN:
case Command.RUN: const isSwitch = command === Command.POKEMON;
const isSwitch = command === Command.POKEMON; const { currentBattle, arena } = this.scene;
const { currentBattle, arena } = this.scene; const mysteryEncounterFleeAllowed = currentBattle.mysteryEncounter?.fleeAllowed;
const mysteryEncounterFleeAllowed = currentBattle.mysteryEncounter?.fleeAllowed; if (!isSwitch && (arena.biomeType === Biome.END || (!isNullOrUndefined(mysteryEncounterFleeAllowed) && !mysteryEncounterFleeAllowed))) {
if (!isSwitch && (arena.biomeType === Biome.END || (!isNullOrUndefined(mysteryEncounterFleeAllowed) && !mysteryEncounterFleeAllowed))) {
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(i18next.t("battle:noEscapeForce"), null, () => {
this.scene.ui.showText("", 0);
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
}, null, true); this.scene.ui.setMode(Mode.MESSAGE);
} else if (!isSwitch && (currentBattle.battleType === BattleType.TRAINER || currentBattle.mysteryEncounter?.encounterMode === MysteryEncounterMode.TRAINER_BATTLE)) { this.scene.ui.showText(i18next.t("battle:noEscapeForce"), null, () => {
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(i18next.t("battle:noEscapeTrainer"), null, () => {
this.scene.ui.showText("", 0);
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
}, null, true);
} else {
const batonPass = isSwitch && args[0] as boolean;
const trappedAbMessages: string[] = [];
if (batonPass || !playerPokemon.isTrapped(trappedAbMessages)) {
currentBattle.turnCommands[this.fieldIndex] = isSwitch
? { command: Command.POKEMON, cursor: cursor, args: args }
: { command: Command.RUN };
success = true;
if (!isSwitch && this.fieldIndex) {
currentBattle.turnCommands[this.fieldIndex - 1]!.skip = true;
}
} else if (trappedAbMessages.length > 0) {
if (!isSwitch) {
this.scene.ui.setMode(Mode.MESSAGE);
}
this.scene.ui.showText(trappedAbMessages[0], null, () => {
this.scene.ui.showText("", 0); this.scene.ui.showText("", 0);
if (!isSwitch) { this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); }, null, true);
} } else if (!isSwitch && (currentBattle.battleType === BattleType.TRAINER || currentBattle.mysteryEncounter?.encounterMode === MysteryEncounterMode.TRAINER_BATTLE)) {
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(i18next.t("battle:noEscapeTrainer"), null, () => {
this.scene.ui.showText("", 0);
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
}, null, true); }, null, true);
} else { } else {
const trapTag = playerPokemon.getTag(TrappedTag); const batonPass = isSwitch && args[0] as boolean;
const trappedAbMessages: string[] = [];
// trapTag should be defined at this point, but just in case... if (batonPass || !playerPokemon.isTrapped(trappedAbMessages)) {
if (!trapTag) {
currentBattle.turnCommands[this.fieldIndex] = isSwitch currentBattle.turnCommands[this.fieldIndex] = isSwitch
? { command: Command.POKEMON, cursor: cursor, args: args } ? { command: Command.POKEMON, cursor: cursor, args: args }
: { command: Command.RUN }; : { command: Command.RUN };
break; success = true;
} if (!isSwitch && this.fieldIndex) {
currentBattle.turnCommands[this.fieldIndex - 1]!.skip = true;
if (!isSwitch) { }
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); } else if (trappedAbMessages.length > 0) {
this.scene.ui.setMode(Mode.MESSAGE); if (!isSwitch) {
} this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText( }
i18next.t("battle:noEscapePokemon", { this.scene.ui.showText(trappedAbMessages[0], null, () => {
pokemonName: trapTag.sourceId && this.scene.getPokemonById(trapTag.sourceId) ? getPokemonNameWithAffix(this.scene.getPokemonById(trapTag.sourceId)!) : "",
moveName: trapTag.getMoveName(),
escapeVerb: isSwitch ? i18next.t("battle:escapeVerbSwitch") : i18next.t("battle:escapeVerbFlee")
}),
null,
() => {
this.scene.ui.showText("", 0); this.scene.ui.showText("", 0);
if (!isSwitch) { if (!isSwitch) {
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
} }
}, null, true); }, null, true);
} else {
const trapTag = playerPokemon.getTag(TrappedTag);
// trapTag should be defined at this point, but just in case...
if (!trapTag) {
currentBattle.turnCommands[this.fieldIndex] = isSwitch
? { command: Command.POKEMON, cursor: cursor, args: args }
: { command: Command.RUN };
break;
}
if (!isSwitch) {
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
this.scene.ui.setMode(Mode.MESSAGE);
}
this.scene.ui.showText(
i18next.t("battle:noEscapePokemon", {
pokemonName: trapTag.sourceId && this.scene.getPokemonById(trapTag.sourceId) ? getPokemonNameWithAffix(this.scene.getPokemonById(trapTag.sourceId)!) : "",
moveName: trapTag.getMoveName(),
escapeVerb: isSwitch ? i18next.t("battle:escapeVerbSwitch") : i18next.t("battle:escapeVerbFlee")
}),
null,
() => {
this.scene.ui.showText("", 0);
if (!isSwitch) {
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
}
}, null, true);
}
} }
} break;
break;
} }
if (success!) { // TODO: is the bang correct? if (success!) { // TODO: is the bang correct?

View File

@ -41,16 +41,16 @@ export class DamagePhase extends PokemonPhase {
applyDamage() { applyDamage() {
switch (this.damageResult) { switch (this.damageResult) {
case HitResult.EFFECTIVE: case HitResult.EFFECTIVE:
this.scene.playSound("se/hit"); this.scene.playSound("se/hit");
break; break;
case HitResult.SUPER_EFFECTIVE: case HitResult.SUPER_EFFECTIVE:
case HitResult.ONE_HIT_KO: case HitResult.ONE_HIT_KO:
this.scene.playSound("se/hit_strong"); this.scene.playSound("se/hit_strong");
break; break;
case HitResult.NOT_VERY_EFFECTIVE: case HitResult.NOT_VERY_EFFECTIVE:
this.scene.playSound("se/hit_weak"); this.scene.playSound("se/hit_weak");
break; break;
} }
if (this.amount) { if (this.amount) {

View File

@ -494,31 +494,31 @@ export class EncounterPhase extends BattlePhase {
tryOverrideForBattleSpec(): boolean { tryOverrideForBattleSpec(): boolean {
switch (this.scene.currentBattle.battleSpec) { switch (this.scene.currentBattle.battleSpec) {
case BattleSpec.FINAL_BOSS: case BattleSpec.FINAL_BOSS:
const enemy = this.scene.getEnemyPokemon(); const enemy = this.scene.getEnemyPokemon();
this.scene.ui.showText(this.getEncounterMessage(), null, () => { this.scene.ui.showText(this.getEncounterMessage(), null, () => {
const localizationKey = "battleSpecDialogue:encounter"; const localizationKey = "battleSpecDialogue:encounter";
if (this.scene.ui.shouldSkipDialogue(localizationKey)) { if (this.scene.ui.shouldSkipDialogue(localizationKey)) {
// Logging mirrors logging found in dialogue-ui-handler // Logging mirrors logging found in dialogue-ui-handler
console.log(`Dialogue ${localizationKey} skipped`); console.log(`Dialogue ${localizationKey} skipped`);
this.doEncounterCommon(false);
} else {
const count = 5643853 + this.scene.gameData.gameStats.classicSessionsPlayed;
// The line below checks if an English ordinal is necessary or not based on whether an entry for encounterLocalizationKey exists in the language or not.
const ordinalUsed = !i18next.exists(localizationKey, { fallbackLng: []}) || i18next.resolvedLanguage === "en" ? i18next.t("battleSpecDialogue:key", { count: count, ordinal: true }) : "";
const cycleCount = count.toLocaleString() + ordinalUsed;
const genderIndex = this.scene.gameData.gender ?? PlayerGender.UNSET;
const genderStr = PlayerGender[genderIndex].toLowerCase();
const encounterDialogue = i18next.t(localizationKey, { context: genderStr, cycleCount: cycleCount });
if (!this.scene.gameData.getSeenDialogues()[localizationKey]) {
this.scene.gameData.saveSeenDialogue(localizationKey);
}
this.scene.ui.showDialogue(encounterDialogue, enemy?.species.name, null, () => {
this.doEncounterCommon(false); this.doEncounterCommon(false);
}); } else {
} const count = 5643853 + this.scene.gameData.gameStats.classicSessionsPlayed;
}, 1500, true); // The line below checks if an English ordinal is necessary or not based on whether an entry for encounterLocalizationKey exists in the language or not.
return true; const ordinalUsed = !i18next.exists(localizationKey, { fallbackLng: []}) || i18next.resolvedLanguage === "en" ? i18next.t("battleSpecDialogue:key", { count: count, ordinal: true }) : "";
const cycleCount = count.toLocaleString() + ordinalUsed;
const genderIndex = this.scene.gameData.gender ?? PlayerGender.UNSET;
const genderStr = PlayerGender[genderIndex].toLowerCase();
const encounterDialogue = i18next.t(localizationKey, { context: genderStr, cycleCount: cycleCount });
if (!this.scene.gameData.getSeenDialogues()[localizationKey]) {
this.scene.gameData.saveSeenDialogue(localizationKey);
}
this.scene.ui.showDialogue(encounterDialogue, enemy?.species.name, null, () => {
this.doEncounterCommon(false);
});
}
}, 1500, true);
return true;
} }
return false; return false;
} }

View File

@ -179,19 +179,19 @@ export class FaintPhase extends PokemonPhase {
tryOverrideForBattleSpec(): boolean { tryOverrideForBattleSpec(): boolean {
switch (this.scene.currentBattle.battleSpec) { switch (this.scene.currentBattle.battleSpec) {
case BattleSpec.FINAL_BOSS: case BattleSpec.FINAL_BOSS:
if (!this.player) { if (!this.player) {
const enemy = this.getPokemon(); const enemy = this.getPokemon();
if (enemy.formIndex) { if (enemy.formIndex) {
this.scene.ui.showDialogue(battleSpecDialogue[BattleSpec.FINAL_BOSS].secondStageWin, enemy.species.name, null, () => this.doFaint()); this.scene.ui.showDialogue(battleSpecDialogue[BattleSpec.FINAL_BOSS].secondStageWin, enemy.species.name, null, () => this.doFaint());
} else { } else {
// Final boss' HP threshold has been bypassed; cancel faint and force check for 2nd phase // Final boss' HP threshold has been bypassed; cancel faint and force check for 2nd phase
enemy.hp++; enemy.hp++;
this.scene.unshiftPhase(new DamagePhase(this.scene, enemy.getBattlerIndex(), 0, HitResult.OTHER)); this.scene.unshiftPhase(new DamagePhase(this.scene, enemy.getBattlerIndex(), 0, HitResult.OTHER));
this.end(); this.end();
}
return true;
} }
return true;
}
} }
return false; return false;

View File

@ -170,23 +170,23 @@ export class MovePhase extends BattlePhase {
let healed = false; let healed = false;
switch (this.pokemon.status.effect) { switch (this.pokemon.status.effect) {
case StatusEffect.PARALYSIS: case StatusEffect.PARALYSIS:
if (!this.pokemon.randSeedInt(4)) { if (!this.pokemon.randSeedInt(4)) {
activated = true; activated = true;
this.cancelled = true; this.cancelled = true;
} }
break; break;
case StatusEffect.SLEEP: case StatusEffect.SLEEP:
applyMoveAttrs(BypassSleepAttr, this.pokemon, null, this.move.getMove()); applyMoveAttrs(BypassSleepAttr, this.pokemon, null, this.move.getMove());
healed = this.pokemon.status.turnCount === this.pokemon.status.cureTurn; healed = this.pokemon.status.turnCount === this.pokemon.status.cureTurn;
activated = !healed && !this.pokemon.getTag(BattlerTagType.BYPASS_SLEEP); activated = !healed && !this.pokemon.getTag(BattlerTagType.BYPASS_SLEEP);
this.cancelled = activated; this.cancelled = activated;
break; break;
case StatusEffect.FREEZE: case StatusEffect.FREEZE:
healed = !!this.move.getMove().findAttr(attr => attr instanceof HealStatusEffectAttr && attr.selfTarget && attr.isOfEffect(StatusEffect.FREEZE)) || !this.pokemon.randSeedInt(5); healed = !!this.move.getMove().findAttr(attr => attr instanceof HealStatusEffectAttr && attr.selfTarget && attr.isOfEffect(StatusEffect.FREEZE)) || !this.pokemon.randSeedInt(5);
activated = !healed; activated = !healed;
this.cancelled = activated; this.cancelled = activated;
break; break;
} }
if (activated) { if (activated) {

View File

@ -1,13 +0,0 @@
import BattleScene from "#app/battle-scene";
import { Phase } from "#app/phase";
import { Mode } from "#app/ui/ui";
export class OutdatedPhase extends Phase {
constructor(scene: BattleScene) {
super(scene);
}
start(): void {
this.scene.ui.setMode(Mode.OUTDATED);
}
}

View File

@ -25,20 +25,20 @@ export class PokemonAnimPhase extends BattlePhase {
super.start(); super.start();
switch (this.key) { switch (this.key) {
case PokemonAnimType.SUBSTITUTE_ADD: case PokemonAnimType.SUBSTITUTE_ADD:
this.doSubstituteAddAnim(); this.doSubstituteAddAnim();
break; break;
case PokemonAnimType.SUBSTITUTE_PRE_MOVE: case PokemonAnimType.SUBSTITUTE_PRE_MOVE:
this.doSubstitutePreMoveAnim(); this.doSubstitutePreMoveAnim();
break; break;
case PokemonAnimType.SUBSTITUTE_POST_MOVE: case PokemonAnimType.SUBSTITUTE_POST_MOVE:
this.doSubstitutePostMoveAnim(); this.doSubstitutePostMoveAnim();
break; break;
case PokemonAnimType.SUBSTITUTE_REMOVE: case PokemonAnimType.SUBSTITUTE_REMOVE:
this.doSubstituteRemoveAnim(); this.doSubstituteRemoveAnim();
break; break;
default: default:
this.end(); this.end();
} }
} }

View File

@ -26,16 +26,16 @@ export class PostTurnStatusEffectPhase extends PokemonPhase {
this.scene.queueMessage(getStatusEffectActivationText(pokemon.status.effect, getPokemonNameWithAffix(pokemon))); this.scene.queueMessage(getStatusEffectActivationText(pokemon.status.effect, getPokemonNameWithAffix(pokemon)));
const damage = new Utils.NumberHolder(0); const damage = new Utils.NumberHolder(0);
switch (pokemon.status.effect) { switch (pokemon.status.effect) {
case StatusEffect.POISON: case StatusEffect.POISON:
damage.value = Math.max(pokemon.getMaxHp() >> 3, 1); damage.value = Math.max(pokemon.getMaxHp() >> 3, 1);
break; break;
case StatusEffect.TOXIC: case StatusEffect.TOXIC:
damage.value = Math.max(Math.floor((pokemon.getMaxHp() / 16) * pokemon.status.turnCount), 1); damage.value = Math.max(Math.floor((pokemon.getMaxHp() / 16) * pokemon.status.turnCount), 1);
break; break;
case StatusEffect.BURN: case StatusEffect.BURN:
damage.value = Math.max(pokemon.getMaxHp() >> 4, 1); damage.value = Math.max(pokemon.getMaxHp() >> 4, 1);
applyAbAttrs(ReduceBurnDamageAbAttr, pokemon, null, false, damage); applyAbAttrs(ReduceBurnDamageAbAttr, pokemon, null, false, damage);
break; break;
} }
if (damage.value) { if (damage.value) {
// Set preventEndure flag to avoid pokemon surviving thanks to focus band, sturdy, endure ... // Set preventEndure flag to avoid pokemon surviving thanks to focus band, sturdy, endure ...

View File

@ -77,78 +77,78 @@ export class SelectModifierPhase extends BattlePhase {
let cost: integer; let cost: integer;
const rerollCost = this.getRerollCost(this.scene.lockModifierTiers); const rerollCost = this.getRerollCost(this.scene.lockModifierTiers);
switch (rowCursor) { switch (rowCursor) {
case 0:
switch (cursor) {
case 0: case 0:
if (rerollCost < 0 || this.scene.money < rerollCost) { switch (cursor) {
this.scene.ui.playError(); case 0:
return false; if (rerollCost < 0 || this.scene.money < rerollCost) {
} else { this.scene.ui.playError();
this.scene.reroll = true; return false;
this.scene.unshiftPhase(new SelectModifierPhase(this.scene, this.rerollCount + 1, this.typeOptions.map(o => o.type?.tier).filter(t => t !== undefined) as ModifierTier[])); } else {
this.scene.ui.clearText(); this.scene.reroll = true;
this.scene.ui.setMode(Mode.MESSAGE).then(() => super.end()); this.scene.unshiftPhase(new SelectModifierPhase(this.scene, this.rerollCount + 1, this.typeOptions.map(o => o.type?.tier).filter(t => t !== undefined) as ModifierTier[]));
if (!Overrides.WAIVE_ROLL_FEE_OVERRIDE) { this.scene.ui.clearText();
this.scene.money -= rerollCost; this.scene.ui.setMode(Mode.MESSAGE).then(() => super.end());
this.scene.updateMoneyText(); if (!Overrides.WAIVE_ROLL_FEE_OVERRIDE) {
this.scene.animateMoneyChanged(false); this.scene.money -= rerollCost;
} this.scene.updateMoneyText();
this.scene.playSound("se/buy"); this.scene.animateMoneyChanged(false);
} }
break; this.scene.playSound("se/buy");
case 1: }
this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.MODIFIER_TRANSFER, -1, (fromSlotIndex: integer, itemIndex: integer, itemQuantity: integer, toSlotIndex: integer) => { break;
if (toSlotIndex !== undefined && fromSlotIndex < 6 && toSlotIndex < 6 && fromSlotIndex !== toSlotIndex && itemIndex > -1) { case 1:
const itemModifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.MODIFIER_TRANSFER, -1, (fromSlotIndex: integer, itemIndex: integer, itemQuantity: integer, toSlotIndex: integer) => {
if (toSlotIndex !== undefined && fromSlotIndex < 6 && toSlotIndex < 6 && fromSlotIndex !== toSlotIndex && itemIndex > -1) {
const itemModifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier
&& m.isTransferable && m.pokemonId === party[fromSlotIndex].id) as PokemonHeldItemModifier[]; && m.isTransferable && m.pokemonId === party[fromSlotIndex].id) as PokemonHeldItemModifier[];
const itemModifier = itemModifiers[itemIndex]; const itemModifier = itemModifiers[itemIndex];
this.scene.tryTransferHeldItemModifier(itemModifier, party[toSlotIndex], true, itemQuantity); this.scene.tryTransferHeldItemModifier(itemModifier, party[toSlotIndex], true, itemQuantity);
} else { } else {
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), this.typeOptions, modifierSelectCallback, this.getRerollCost(this.scene.lockModifierTiers)); this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), this.typeOptions, modifierSelectCallback, this.getRerollCost(this.scene.lockModifierTiers));
} }
}, PartyUiHandler.FilterItemMaxStacks); }, PartyUiHandler.FilterItemMaxStacks);
break; break;
case 2: case 2:
this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.CHECK, -1, () => { this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.CHECK, -1, () => {
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), this.typeOptions, modifierSelectCallback, this.getRerollCost(this.scene.lockModifierTiers)); this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), this.typeOptions, modifierSelectCallback, this.getRerollCost(this.scene.lockModifierTiers));
}); });
break; break;
case 3: case 3:
if (rerollCost < 0) { if (rerollCost < 0) {
// Reroll lock button is also disabled when reroll is disabled // Reroll lock button is also disabled when reroll is disabled
this.scene.ui.playError(); this.scene.ui.playError();
return false; return false;
}
this.scene.lockModifierTiers = !this.scene.lockModifierTiers;
const uiHandler = this.scene.ui.getHandler() as ModifierSelectUiHandler;
uiHandler.setRerollCost(this.getRerollCost(this.scene.lockModifierTiers));
uiHandler.updateLockRaritiesText();
uiHandler.updateRerollCostText();
return false;
} }
this.scene.lockModifierTiers = !this.scene.lockModifierTiers;
const uiHandler = this.scene.ui.getHandler() as ModifierSelectUiHandler;
uiHandler.setRerollCost(this.getRerollCost(this.scene.lockModifierTiers));
uiHandler.updateLockRaritiesText();
uiHandler.updateRerollCostText();
return false;
}
return true;
case 1:
if (this.typeOptions.length === 0) {
this.scene.ui.clearText();
this.scene.ui.setMode(Mode.MESSAGE);
super.end();
return true; return true;
} case 1:
if (this.typeOptions[cursor].type) { if (this.typeOptions.length === 0) {
modifierType = this.typeOptions[cursor].type; this.scene.ui.clearText();
} this.scene.ui.setMode(Mode.MESSAGE);
break; super.end();
default: return true;
const shopOptions = getPlayerShopModifierTypeOptionsForWave(this.scene.currentBattle.waveIndex, this.scene.getWaveMoneyAmount(1)); }
const shopOption = shopOptions[rowCursor > 2 || shopOptions.length <= SHOP_OPTIONS_ROW_LIMIT ? cursor : cursor + SHOP_OPTIONS_ROW_LIMIT]; if (this.typeOptions[cursor].type) {
if (shopOption.type) { modifierType = this.typeOptions[cursor].type;
modifierType = shopOption.type; }
} break;
// Apply Black Sludge to healing item cost default:
const healingItemCost = new NumberHolder(shopOption.cost); const shopOptions = getPlayerShopModifierTypeOptionsForWave(this.scene.currentBattle.waveIndex, this.scene.getWaveMoneyAmount(1));
this.scene.applyModifier(HealShopCostModifier, true, healingItemCost); const shopOption = shopOptions[rowCursor > 2 || shopOptions.length <= SHOP_OPTIONS_ROW_LIMIT ? cursor : cursor + SHOP_OPTIONS_ROW_LIMIT];
cost = healingItemCost.value; if (shopOption.type) {
break; modifierType = shopOption.type;
}
// Apply Black Sludge to healing item cost
const healingItemCost = new NumberHolder(shopOption.cost);
this.scene.applyModifier(HealShopCostModifier, true, healingItemCost);
cost = healingItemCost.value;
break;
} }
if (cost! && (this.scene.money < cost) && !Overrides.WAIVE_ROLL_FEE_OVERRIDE) { // TODO: is the bang on cost correct? if (cost! && (this.scene.money < cost) && !Overrides.WAIVE_ROLL_FEE_OVERRIDE) { // TODO: is the bang on cost correct?

View File

@ -152,55 +152,55 @@ export class TurnStartPhase extends FieldPhase {
} }
switch (turnCommand?.command) { switch (turnCommand?.command) {
case Command.FIGHT: case Command.FIGHT:
const queuedMove = turnCommand.move; const queuedMove = turnCommand.move;
pokemon.turnData.order = orderIndex++; pokemon.turnData.order = orderIndex++;
if (!queuedMove) { if (!queuedMove) {
continue; continue;
}
const move = pokemon.getMoveset().find(m => m?.moveId === queuedMove.move && m?.ppUsed < m?.getMovePp()) || new PokemonMove(queuedMove.move);
if (move.getMove().hasAttr(MoveHeaderAttr)) {
this.scene.unshiftPhase(new MoveHeaderPhase(this.scene, pokemon, move));
}
if (pokemon.isPlayer()) {
if (turnCommand.cursor === -1) {
this.scene.pushPhase(new MovePhase(this.scene, pokemon, turnCommand.targets || turnCommand.move!.targets, move));//TODO: is the bang correct here?
} else {
const playerPhase = new MovePhase(this.scene, pokemon, turnCommand.targets || turnCommand.move!.targets, move, false, queuedMove.ignorePP);//TODO: is the bang correct here?
this.scene.pushPhase(playerPhase);
} }
} else { const move = pokemon.getMoveset().find(m => m?.moveId === queuedMove.move && m?.ppUsed < m?.getMovePp()) || new PokemonMove(queuedMove.move);
this.scene.pushPhase(new MovePhase(this.scene, pokemon, turnCommand.targets || turnCommand.move!.targets, move, false, queuedMove.ignorePP));//TODO: is the bang correct here? if (move.getMove().hasAttr(MoveHeaderAttr)) {
} this.scene.unshiftPhase(new MoveHeaderPhase(this.scene, pokemon, move));
break; }
case Command.BALL: if (pokemon.isPlayer()) {
this.scene.unshiftPhase(new AttemptCapturePhase(this.scene, turnCommand.targets![0] % 2, turnCommand.cursor!));//TODO: is the bang correct here? if (turnCommand.cursor === -1) {
break; this.scene.pushPhase(new MovePhase(this.scene, pokemon, turnCommand.targets || turnCommand.move!.targets, move));//TODO: is the bang correct here?
case Command.POKEMON:
const switchType = turnCommand.args?.[0] ? SwitchType.BATON_PASS : SwitchType.SWITCH;
this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, switchType, pokemon.getFieldIndex(), turnCommand.cursor!, true, pokemon.isPlayer()));
break;
case Command.RUN:
let runningPokemon = pokemon;
if (this.scene.currentBattle.double) {
const playerActivePokemon = field.filter(pokemon => {
if (!!pokemon) {
return pokemon.isPlayer() && pokemon.isActive();
} else { } else {
return; const playerPhase = new MovePhase(this.scene, pokemon, turnCommand.targets || turnCommand.move!.targets, move, false, queuedMove.ignorePP);//TODO: is the bang correct here?
this.scene.pushPhase(playerPhase);
} }
}); } else {
// if only one pokemon is alive, use that one this.scene.pushPhase(new MovePhase(this.scene, pokemon, turnCommand.targets || turnCommand.move!.targets, move, false, queuedMove.ignorePP));//TODO: is the bang correct here?
if (playerActivePokemon.length > 1) {
// find which active pokemon has faster speed
const fasterPokemon = playerActivePokemon[0].getStat(Stat.SPD) > playerActivePokemon[1].getStat(Stat.SPD) ? playerActivePokemon[0] : playerActivePokemon[1];
// check if either active pokemon has the ability "Run Away"
const hasRunAway = playerActivePokemon.find(p => p.hasAbility(Abilities.RUN_AWAY));
runningPokemon = hasRunAway !== undefined ? hasRunAway : fasterPokemon;
} }
} break;
this.scene.unshiftPhase(new AttemptRunPhase(this.scene, runningPokemon.getFieldIndex())); case Command.BALL:
break; this.scene.unshiftPhase(new AttemptCapturePhase(this.scene, turnCommand.targets![0] % 2, turnCommand.cursor!));//TODO: is the bang correct here?
break;
case Command.POKEMON:
const switchType = turnCommand.args?.[0] ? SwitchType.BATON_PASS : SwitchType.SWITCH;
this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, switchType, pokemon.getFieldIndex(), turnCommand.cursor!, true, pokemon.isPlayer()));
break;
case Command.RUN:
let runningPokemon = pokemon;
if (this.scene.currentBattle.double) {
const playerActivePokemon = field.filter(pokemon => {
if (!!pokemon) {
return pokemon.isPlayer() && pokemon.isActive();
} else {
return;
}
});
// if only one pokemon is alive, use that one
if (playerActivePokemon.length > 1) {
// find which active pokemon has faster speed
const fasterPokemon = playerActivePokemon[0].getStat(Stat.SPD) > playerActivePokemon[1].getStat(Stat.SPD) ? playerActivePokemon[0] : playerActivePokemon[1];
// check if either active pokemon has the ability "Run Away"
const hasRunAway = playerActivePokemon.find(p => p.hasAbility(Abilities.RUN_AWAY));
runningPokemon = hasRunAway !== undefined ? hasRunAway : fasterPokemon;
}
}
this.scene.unshiftPhase(new AttemptRunPhase(this.scene, runningPokemon.getFieldIndex()));
break;
} }
} }

View File

@ -156,133 +156,133 @@ export function getAchievementDescription(localizationKey: string): string {
const genderStr = PlayerGender[genderIndex].toLowerCase(); const genderStr = PlayerGender[genderIndex].toLowerCase();
switch (localizationKey) { switch (localizationKey) {
case "10K_MONEY": case "10K_MONEY":
return i18next.t("achv:MoneyAchv.description", { context: genderStr, "moneyAmount": achvs._10K_MONEY.moneyAmount.toLocaleString("en-US") }); return i18next.t("achv:MoneyAchv.description", { context: genderStr, "moneyAmount": achvs._10K_MONEY.moneyAmount.toLocaleString("en-US") });
case "100K_MONEY": case "100K_MONEY":
return i18next.t("achv:MoneyAchv.description", { context: genderStr, "moneyAmount": achvs._100K_MONEY.moneyAmount.toLocaleString("en-US") }); return i18next.t("achv:MoneyAchv.description", { context: genderStr, "moneyAmount": achvs._100K_MONEY.moneyAmount.toLocaleString("en-US") });
case "1M_MONEY": case "1M_MONEY":
return i18next.t("achv:MoneyAchv.description", { context: genderStr, "moneyAmount": achvs._1M_MONEY.moneyAmount.toLocaleString("en-US") }); return i18next.t("achv:MoneyAchv.description", { context: genderStr, "moneyAmount": achvs._1M_MONEY.moneyAmount.toLocaleString("en-US") });
case "10M_MONEY": case "10M_MONEY":
return i18next.t("achv:MoneyAchv.description", { context: genderStr, "moneyAmount": achvs._10M_MONEY.moneyAmount.toLocaleString("en-US") }); return i18next.t("achv:MoneyAchv.description", { context: genderStr, "moneyAmount": achvs._10M_MONEY.moneyAmount.toLocaleString("en-US") });
case "250_DMG": case "250_DMG":
return i18next.t("achv:DamageAchv.description", { context: genderStr, "damageAmount": achvs._250_DMG.damageAmount.toLocaleString("en-US") }); return i18next.t("achv:DamageAchv.description", { context: genderStr, "damageAmount": achvs._250_DMG.damageAmount.toLocaleString("en-US") });
case "1000_DMG": case "1000_DMG":
return i18next.t("achv:DamageAchv.description", { context: genderStr, "damageAmount": achvs._1000_DMG.damageAmount.toLocaleString("en-US") }); return i18next.t("achv:DamageAchv.description", { context: genderStr, "damageAmount": achvs._1000_DMG.damageAmount.toLocaleString("en-US") });
case "2500_DMG": case "2500_DMG":
return i18next.t("achv:DamageAchv.description", { context: genderStr, "damageAmount": achvs._2500_DMG.damageAmount.toLocaleString("en-US") }); return i18next.t("achv:DamageAchv.description", { context: genderStr, "damageAmount": achvs._2500_DMG.damageAmount.toLocaleString("en-US") });
case "10000_DMG": case "10000_DMG":
return i18next.t("achv:DamageAchv.description", { context: genderStr, "damageAmount": achvs._10000_DMG.damageAmount.toLocaleString("en-US") }); return i18next.t("achv:DamageAchv.description", { context: genderStr, "damageAmount": achvs._10000_DMG.damageAmount.toLocaleString("en-US") });
case "250_HEAL": case "250_HEAL":
return i18next.t("achv:HealAchv.description", { context: genderStr, "healAmount": achvs._250_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t(getShortenedStatKey(Stat.HP)) }); return i18next.t("achv:HealAchv.description", { context: genderStr, "healAmount": achvs._250_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t(getShortenedStatKey(Stat.HP)) });
case "1000_HEAL": case "1000_HEAL":
return i18next.t("achv:HealAchv.description", { context: genderStr, "healAmount": achvs._1000_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t(getShortenedStatKey(Stat.HP)) }); return i18next.t("achv:HealAchv.description", { context: genderStr, "healAmount": achvs._1000_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t(getShortenedStatKey(Stat.HP)) });
case "2500_HEAL": case "2500_HEAL":
return i18next.t("achv:HealAchv.description", { context: genderStr, "healAmount": achvs._2500_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t(getShortenedStatKey(Stat.HP)) }); return i18next.t("achv:HealAchv.description", { context: genderStr, "healAmount": achvs._2500_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t(getShortenedStatKey(Stat.HP)) });
case "10000_HEAL": case "10000_HEAL":
return i18next.t("achv:HealAchv.description", { context: genderStr, "healAmount": achvs._10000_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t(getShortenedStatKey(Stat.HP)) }); return i18next.t("achv:HealAchv.description", { context: genderStr, "healAmount": achvs._10000_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t(getShortenedStatKey(Stat.HP)) });
case "LV_100": case "LV_100":
return i18next.t("achv:LevelAchv.description", { context: genderStr, "level": achvs.LV_100.level }); return i18next.t("achv:LevelAchv.description", { context: genderStr, "level": achvs.LV_100.level });
case "LV_250": case "LV_250":
return i18next.t("achv:LevelAchv.description", { context: genderStr, "level": achvs.LV_250.level }); return i18next.t("achv:LevelAchv.description", { context: genderStr, "level": achvs.LV_250.level });
case "LV_1000": case "LV_1000":
return i18next.t("achv:LevelAchv.description", { context: genderStr, "level": achvs.LV_1000.level }); return i18next.t("achv:LevelAchv.description", { context: genderStr, "level": achvs.LV_1000.level });
case "10_RIBBONS": case "10_RIBBONS":
return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._10_RIBBONS.ribbonAmount.toLocaleString("en-US") }); return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._10_RIBBONS.ribbonAmount.toLocaleString("en-US") });
case "25_RIBBONS": case "25_RIBBONS":
return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._25_RIBBONS.ribbonAmount.toLocaleString("en-US") }); return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._25_RIBBONS.ribbonAmount.toLocaleString("en-US") });
case "50_RIBBONS": case "50_RIBBONS":
return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._50_RIBBONS.ribbonAmount.toLocaleString("en-US") }); return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._50_RIBBONS.ribbonAmount.toLocaleString("en-US") });
case "75_RIBBONS": case "75_RIBBONS":
return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._75_RIBBONS.ribbonAmount.toLocaleString("en-US") }); return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._75_RIBBONS.ribbonAmount.toLocaleString("en-US") });
case "100_RIBBONS": case "100_RIBBONS":
return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._100_RIBBONS.ribbonAmount.toLocaleString("en-US") }); return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._100_RIBBONS.ribbonAmount.toLocaleString("en-US") });
case "TRANSFER_MAX_STAT_STAGE": case "TRANSFER_MAX_STAT_STAGE":
return i18next.t("achv:TRANSFER_MAX_STAT_STAGE.description", { context: genderStr }); return i18next.t("achv:TRANSFER_MAX_STAT_STAGE.description", { context: genderStr });
case "MAX_FRIENDSHIP": case "MAX_FRIENDSHIP":
return i18next.t("achv:MAX_FRIENDSHIP.description", { context: genderStr }); return i18next.t("achv:MAX_FRIENDSHIP.description", { context: genderStr });
case "MEGA_EVOLVE": case "MEGA_EVOLVE":
return i18next.t("achv:MEGA_EVOLVE.description", { context: genderStr }); return i18next.t("achv:MEGA_EVOLVE.description", { context: genderStr });
case "GIGANTAMAX": case "GIGANTAMAX":
return i18next.t("achv:GIGANTAMAX.description", { context: genderStr }); return i18next.t("achv:GIGANTAMAX.description", { context: genderStr });
case "TERASTALLIZE": case "TERASTALLIZE":
return i18next.t("achv:TERASTALLIZE.description", { context: genderStr }); return i18next.t("achv:TERASTALLIZE.description", { context: genderStr });
case "STELLAR_TERASTALLIZE": case "STELLAR_TERASTALLIZE":
return i18next.t("achv:STELLAR_TERASTALLIZE.description", { context: genderStr }); return i18next.t("achv:STELLAR_TERASTALLIZE.description", { context: genderStr });
case "SPLICE": case "SPLICE":
return i18next.t("achv:SPLICE.description", { context: genderStr }); return i18next.t("achv:SPLICE.description", { context: genderStr });
case "MINI_BLACK_HOLE": case "MINI_BLACK_HOLE":
return i18next.t("achv:MINI_BLACK_HOLE.description", { context: genderStr }); return i18next.t("achv:MINI_BLACK_HOLE.description", { context: genderStr });
case "CATCH_MYTHICAL": case "CATCH_MYTHICAL":
return i18next.t("achv:CATCH_MYTHICAL.description", { context: genderStr }); return i18next.t("achv:CATCH_MYTHICAL.description", { context: genderStr });
case "CATCH_SUB_LEGENDARY": case "CATCH_SUB_LEGENDARY":
return i18next.t("achv:CATCH_SUB_LEGENDARY.description", { context: genderStr }); return i18next.t("achv:CATCH_SUB_LEGENDARY.description", { context: genderStr });
case "CATCH_LEGENDARY": case "CATCH_LEGENDARY":
return i18next.t("achv:CATCH_LEGENDARY.description", { context: genderStr }); return i18next.t("achv:CATCH_LEGENDARY.description", { context: genderStr });
case "SEE_SHINY": case "SEE_SHINY":
return i18next.t("achv:SEE_SHINY.description", { context: genderStr }); return i18next.t("achv:SEE_SHINY.description", { context: genderStr });
case "SHINY_PARTY": case "SHINY_PARTY":
return i18next.t("achv:SHINY_PARTY.description", { context: genderStr }); return i18next.t("achv:SHINY_PARTY.description", { context: genderStr });
case "HATCH_MYTHICAL": case "HATCH_MYTHICAL":
return i18next.t("achv:HATCH_MYTHICAL.description", { context: genderStr }); return i18next.t("achv:HATCH_MYTHICAL.description", { context: genderStr });
case "HATCH_SUB_LEGENDARY": case "HATCH_SUB_LEGENDARY":
return i18next.t("achv:HATCH_SUB_LEGENDARY.description", { context: genderStr }); return i18next.t("achv:HATCH_SUB_LEGENDARY.description", { context: genderStr });
case "HATCH_LEGENDARY": case "HATCH_LEGENDARY":
return i18next.t("achv:HATCH_LEGENDARY.description", { context: genderStr }); return i18next.t("achv:HATCH_LEGENDARY.description", { context: genderStr });
case "HATCH_SHINY": case "HATCH_SHINY":
return i18next.t("achv:HATCH_SHINY.description", { context: genderStr }); return i18next.t("achv:HATCH_SHINY.description", { context: genderStr });
case "HIDDEN_ABILITY": case "HIDDEN_ABILITY":
return i18next.t("achv:HIDDEN_ABILITY.description", { context: genderStr }); return i18next.t("achv:HIDDEN_ABILITY.description", { context: genderStr });
case "PERFECT_IVS": case "PERFECT_IVS":
return i18next.t("achv:PERFECT_IVS.description", { context: genderStr }); return i18next.t("achv:PERFECT_IVS.description", { context: genderStr });
case "CLASSIC_VICTORY": case "CLASSIC_VICTORY":
return i18next.t("achv:CLASSIC_VICTORY.description", { context: genderStr }); return i18next.t("achv:CLASSIC_VICTORY.description", { context: genderStr });
case "UNEVOLVED_CLASSIC_VICTORY": case "UNEVOLVED_CLASSIC_VICTORY":
return i18next.t("achv:UNEVOLVED_CLASSIC_VICTORY.description", { context: genderStr }); return i18next.t("achv:UNEVOLVED_CLASSIC_VICTORY.description", { context: genderStr });
case "MONO_GEN_ONE": case "MONO_GEN_ONE":
return i18next.t("achv:MONO_GEN_ONE.description", { context: genderStr }); return i18next.t("achv:MONO_GEN_ONE.description", { context: genderStr });
case "MONO_GEN_TWO": case "MONO_GEN_TWO":
return i18next.t("achv:MONO_GEN_TWO.description", { context: genderStr }); return i18next.t("achv:MONO_GEN_TWO.description", { context: genderStr });
case "MONO_GEN_THREE": case "MONO_GEN_THREE":
return i18next.t("achv:MONO_GEN_THREE.description", { context: genderStr }); return i18next.t("achv:MONO_GEN_THREE.description", { context: genderStr });
case "MONO_GEN_FOUR": case "MONO_GEN_FOUR":
return i18next.t("achv:MONO_GEN_FOUR.description", { context: genderStr }); return i18next.t("achv:MONO_GEN_FOUR.description", { context: genderStr });
case "MONO_GEN_FIVE": case "MONO_GEN_FIVE":
return i18next.t("achv:MONO_GEN_FIVE.description", { context: genderStr }); return i18next.t("achv:MONO_GEN_FIVE.description", { context: genderStr });
case "MONO_GEN_SIX": case "MONO_GEN_SIX":
return i18next.t("achv:MONO_GEN_SIX.description", { context: genderStr }); return i18next.t("achv:MONO_GEN_SIX.description", { context: genderStr });
case "MONO_GEN_SEVEN": case "MONO_GEN_SEVEN":
return i18next.t("achv:MONO_GEN_SEVEN.description", { context: genderStr }); return i18next.t("achv:MONO_GEN_SEVEN.description", { context: genderStr });
case "MONO_GEN_EIGHT": case "MONO_GEN_EIGHT":
return i18next.t("achv:MONO_GEN_EIGHT.description", { context: genderStr }); return i18next.t("achv:MONO_GEN_EIGHT.description", { context: genderStr });
case "MONO_GEN_NINE": case "MONO_GEN_NINE":
return i18next.t("achv:MONO_GEN_NINE.description", { context: genderStr }); return i18next.t("achv:MONO_GEN_NINE.description", { context: genderStr });
case "MONO_NORMAL": case "MONO_NORMAL":
case "MONO_FIGHTING": case "MONO_FIGHTING":
case "MONO_FLYING": case "MONO_FLYING":
case "MONO_POISON": case "MONO_POISON":
case "MONO_GROUND": case "MONO_GROUND":
case "MONO_ROCK": case "MONO_ROCK":
case "MONO_BUG": case "MONO_BUG":
case "MONO_GHOST": case "MONO_GHOST":
case "MONO_STEEL": case "MONO_STEEL":
case "MONO_FIRE": case "MONO_FIRE":
case "MONO_WATER": case "MONO_WATER":
case "MONO_GRASS": case "MONO_GRASS":
case "MONO_ELECTRIC": case "MONO_ELECTRIC":
case "MONO_PSYCHIC": case "MONO_PSYCHIC":
case "MONO_ICE": case "MONO_ICE":
case "MONO_DRAGON": case "MONO_DRAGON":
case "MONO_DARK": case "MONO_DARK":
case "MONO_FAIRY": case "MONO_FAIRY":
return i18next.t("achv:MonoType.description", { context: genderStr, "type": i18next.t(`pokemonInfo:Type.${localizationKey.slice(5)}`) }); return i18next.t("achv:MonoType.description", { context: genderStr, "type": i18next.t(`pokemonInfo:Type.${localizationKey.slice(5)}`) });
case "FRESH_START": case "FRESH_START":
return i18next.t("achv:FRESH_START.description", { context: genderStr }); return i18next.t("achv:FRESH_START.description", { context: genderStr });
case "INVERSE_BATTLE": case "INVERSE_BATTLE":
return i18next.t("achv:INVERSE_BATTLE.description", { context: genderStr }); return i18next.t("achv:INVERSE_BATTLE.description", { context: genderStr });
case "BREEDERS_IN_SPACE": case "BREEDERS_IN_SPACE":
return i18next.t("achv:BREEDERS_IN_SPACE.description", { context: genderStr }); return i18next.t("achv:BREEDERS_IN_SPACE.description", { context: genderStr });
default: default:
return ""; return "";
} }
} }

View File

@ -43,10 +43,9 @@ import { Species } from "#enums/species";
import { applyChallenges, ChallengeType } from "#app/data/challenge"; import { applyChallenges, ChallengeType } from "#app/data/challenge";
import { WeatherType } from "#enums/weather-type"; import { WeatherType } from "#enums/weather-type";
import { TerrainType } from "#app/data/terrain"; import { TerrainType } from "#app/data/terrain";
import { OutdatedPhase } from "#app/phases/outdated-phase";
import { ReloadSessionPhase } from "#app/phases/reload-session-phase"; import { ReloadSessionPhase } from "#app/phases/reload-session-phase";
import { RUN_HISTORY_LIMIT } from "#app/ui/run-history-ui-handler"; import { RUN_HISTORY_LIMIT } from "#app/ui/run-history-ui-handler";
import { applySessionDataPatches, applySettingsDataPatches, applySystemDataPatches } from "#app/system/version-converter"; import { applySessionVersionMigration, applySystemVersionMigration, applySettingsVersionMigration } from "./version_migration/version_converter";
import { MysteryEncounterSaveData } from "#app/data/mystery-encounters/mystery-encounter-save-data"; import { MysteryEncounterSaveData } from "#app/data/mystery-encounters/mystery-encounter-save-data";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { PokerogueApiClearSessionData } from "#app/@types/pokerogue-api"; import { PokerogueApiClearSessionData } from "#app/@types/pokerogue-api";
@ -68,22 +67,22 @@ const saveKey = "x0i2O7WRiANTqPmZ"; // Temporary; secure encryption is not yet n
export function getDataTypeKey(dataType: GameDataType, slotId: integer = 0): string { export function getDataTypeKey(dataType: GameDataType, slotId: integer = 0): string {
switch (dataType) { switch (dataType) {
case GameDataType.SYSTEM: case GameDataType.SYSTEM:
return "data"; return "data";
case GameDataType.SESSION: case GameDataType.SESSION:
let ret = "sessionData"; let ret = "sessionData";
if (slotId) { if (slotId) {
ret += slotId; ret += slotId;
} }
return ret; return ret;
case GameDataType.SETTINGS: case GameDataType.SETTINGS:
return "settings"; return "settings";
case GameDataType.TUTORIALS: case GameDataType.TUTORIALS:
return "tutorials"; return "tutorials";
case GameDataType.SEEN_DIALOGUES: case GameDataType.SEEN_DIALOGUES:
return "seenDialogues"; return "seenDialogues";
case GameDataType.RUN_HISTORY: case GameDataType.RUN_HISTORY:
return "runHistoryData"; return "runHistoryData";
} }
} }
@ -403,10 +402,7 @@ export class GameData {
.then(error => { .then(error => {
this.scene.ui.savingIcon.hide(); this.scene.ui.savingIcon.hide();
if (error) { if (error) {
if (error.startsWith("client version out of date")) { if (error.startsWith("session out of date")) {
this.scene.clearPhaseQueue();
this.scene.unshiftPhase(new OutdatedPhase(this.scene));
} else if (error.startsWith("session out of date")) {
this.scene.clearPhaseQueue(); this.scene.clearPhaseQueue();
this.scene.unshiftPhase(new ReloadSessionPhase(this.scene)); this.scene.unshiftPhase(new ReloadSessionPhase(this.scene));
} }
@ -482,7 +478,7 @@ export class GameData {
localStorage.setItem(lsItemKey, ""); localStorage.setItem(lsItemKey, "");
} }
applySystemDataPatches(systemData); applySystemVersionMigration(systemData);
this.trainerId = systemData.trainerId; this.trainerId = systemData.trainerId;
this.secretId = systemData.secretId; this.secretId = systemData.secretId;
@ -857,7 +853,7 @@ export class GameData {
const settings = JSON.parse(localStorage.getItem("settings")!); // TODO: is this bang correct? const settings = JSON.parse(localStorage.getItem("settings")!); // TODO: is this bang correct?
applySettingsDataPatches(settings); applySettingsVersionMigration(settings);
for (const setting of Object.keys(settings)) { for (const setting of Object.keys(settings)) {
setSetting(this.scene, setting, settings[setting]); setSetting(this.scene, setting, settings[setting]);
@ -1313,7 +1309,7 @@ export class GameData {
return v; return v;
}) as SessionSaveData; }) as SessionSaveData;
applySessionDataPatches(sessionData); applySessionVersionMigration(sessionData);
return sessionData; return sessionData;
} }
@ -1354,10 +1350,7 @@ export class GameData {
this.scene.ui.savingIcon.hide(); this.scene.ui.savingIcon.hide();
} }
if (error) { if (error) {
if (error.startsWith("client version out of date")) { if (error.startsWith("session out of date")) {
this.scene.clearPhaseQueue();
this.scene.unshiftPhase(new OutdatedPhase(this.scene));
} else if (error.startsWith("session out of date")) {
this.scene.clearPhaseQueue(); this.scene.clearPhaseQueue();
this.scene.unshiftPhase(new ReloadSessionPhase(this.scene)); this.scene.unshiftPhase(new ReloadSessionPhase(this.scene));
} }
@ -1381,9 +1374,9 @@ export class GameData {
const dataKey: string = `${getDataTypeKey(dataType, slotId)}_${loggedInUser?.username}`; const dataKey: string = `${getDataTypeKey(dataType, slotId)}_${loggedInUser?.username}`;
const handleData = (dataStr: string) => { const handleData = (dataStr: string) => {
switch (dataType) { switch (dataType) {
case GameDataType.SYSTEM: case GameDataType.SYSTEM:
dataStr = this.convertSystemDataStr(dataStr, true); dataStr = this.convertSystemDataStr(dataStr, true);
break; break;
} }
const encryptedData = AES.encrypt(dataStr, saveKey); const encryptedData = AES.encrypt(dataStr, saveKey);
const blob = new Blob([ encryptedData.toString() ], { type: "text/json" }); const blob = new Blob([ encryptedData.toString() ], { type: "text/json" });
@ -1441,28 +1434,28 @@ export class GameData {
try { try {
dataName = GameDataType[dataType].toLowerCase(); dataName = GameDataType[dataType].toLowerCase();
switch (dataType) { switch (dataType) {
case GameDataType.SYSTEM: case GameDataType.SYSTEM:
dataStr = this.convertSystemDataStr(dataStr); dataStr = this.convertSystemDataStr(dataStr);
const systemData = this.parseSystemData(dataStr); const systemData = this.parseSystemData(dataStr);
valid = !!systemData.dexData && !!systemData.timestamp; valid = !!systemData.dexData && !!systemData.timestamp;
break; break;
case GameDataType.SESSION: case GameDataType.SESSION:
const sessionData = this.parseSessionData(dataStr); const sessionData = this.parseSessionData(dataStr);
valid = !!sessionData.party && !!sessionData.enemyParty && !!sessionData.timestamp; valid = !!sessionData.party && !!sessionData.enemyParty && !!sessionData.timestamp;
break; break;
case GameDataType.RUN_HISTORY: case GameDataType.RUN_HISTORY:
const data = JSON.parse(dataStr); const data = JSON.parse(dataStr);
const keys = Object.keys(data); const keys = Object.keys(data);
dataName = i18next.t("menuUiHandler:RUN_HISTORY").toLowerCase(); dataName = i18next.t("menuUiHandler:RUN_HISTORY").toLowerCase();
keys.forEach((key) => { keys.forEach((key) => {
const entryKeys = Object.keys(data[key]); const entryKeys = Object.keys(data[key]);
valid = [ "isFavorite", "isVictory", "entry" ].every(v => entryKeys.includes(v)) && entryKeys.length === 3; valid = [ "isFavorite", "isVictory", "entry" ].every(v => entryKeys.includes(v)) && entryKeys.length === 3;
}); });
break; break;
case GameDataType.SETTINGS: case GameDataType.SETTINGS:
case GameDataType.TUTORIALS: case GameDataType.TUTORIALS:
valid = true; valid = true;
break; break;
} }
} catch (ex) { } catch (ex) {
console.error(ex); console.error(ex);

View File

@ -82,66 +82,66 @@ export const settingGamepadBlackList = [
export function setSettingGamepad(scene: BattleScene, setting: SettingGamepad, value: integer): boolean { export function setSettingGamepad(scene: BattleScene, setting: SettingGamepad, value: integer): boolean {
switch (setting) { switch (setting) {
case SettingGamepad.Gamepad_Support: case SettingGamepad.Gamepad_Support:
// if we change the value of the gamepad support, we call a method in the inputController to // if we change the value of the gamepad support, we call a method in the inputController to
// activate or deactivate the controller listener // activate or deactivate the controller listener
scene.inputController.setGamepadSupport(settingGamepadOptions[setting][value] !== "Disabled"); scene.inputController.setGamepadSupport(settingGamepadOptions[setting][value] !== "Disabled");
break; break;
case SettingGamepad.Button_Action: case SettingGamepad.Button_Action:
case SettingGamepad.Button_Cancel: case SettingGamepad.Button_Cancel:
case SettingGamepad.Button_Menu: case SettingGamepad.Button_Menu:
case SettingGamepad.Button_Stats: case SettingGamepad.Button_Stats:
case SettingGamepad.Button_Cycle_Shiny: case SettingGamepad.Button_Cycle_Shiny:
case SettingGamepad.Button_Cycle_Form: case SettingGamepad.Button_Cycle_Form:
case SettingGamepad.Button_Cycle_Gender: case SettingGamepad.Button_Cycle_Gender:
case SettingGamepad.Button_Cycle_Ability: case SettingGamepad.Button_Cycle_Ability:
case SettingGamepad.Button_Cycle_Nature: case SettingGamepad.Button_Cycle_Nature:
case SettingGamepad.Button_Cycle_Variant: case SettingGamepad.Button_Cycle_Variant:
case SettingGamepad.Button_Speed_Up: case SettingGamepad.Button_Speed_Up:
case SettingGamepad.Button_Slow_Down: case SettingGamepad.Button_Slow_Down:
case SettingGamepad.Button_Submit: case SettingGamepad.Button_Submit:
if (value) { if (value) {
if (scene.ui) { if (scene.ui) {
const cancelHandler = (success: boolean = false) : boolean => { const cancelHandler = (success: boolean = false) : boolean => {
scene.ui.revertMode(); scene.ui.revertMode();
(scene.ui.getHandler() as SettingsGamepadUiHandler).updateBindings(); (scene.ui.getHandler() as SettingsGamepadUiHandler).updateBindings();
return success; return success;
}; };
scene.ui.setOverlayMode(Mode.GAMEPAD_BINDING, { scene.ui.setOverlayMode(Mode.GAMEPAD_BINDING, {
target: setting, target: setting,
cancelHandler: cancelHandler, cancelHandler: cancelHandler,
}); });
}
} }
} break;
break; case SettingGamepad.Controller:
case SettingGamepad.Controller: if (value) {
if (value) { const gp = scene.inputController.getGamepadsName();
const gp = scene.inputController.getGamepadsName(); if (scene.ui && gp) {
if (scene.ui && gp) { const cancelHandler = () => {
const cancelHandler = () => { scene.ui.revertMode();
scene.ui.revertMode(); (scene.ui.getHandler() as SettingsGamepadUiHandler).setOptionCursor(Object.values(SettingGamepad).indexOf(SettingGamepad.Controller), 0, true);
(scene.ui.getHandler() as SettingsGamepadUiHandler).setOptionCursor(Object.values(SettingGamepad).indexOf(SettingGamepad.Controller), 0, true); (scene.ui.getHandler() as SettingsGamepadUiHandler).updateBindings();
(scene.ui.getHandler() as SettingsGamepadUiHandler).updateBindings(); return false;
};
const changeGamepadHandler = (gamepad: string) => {
scene.inputController.setChosenGamepad(gamepad);
cancelHandler();
return true;
};
scene.ui.setOverlayMode(Mode.OPTION_SELECT, {
options: [ ...gp.map((g: string) => ({
label: truncateString(g, 30), // Truncate the gamepad name for display
handler: () => changeGamepadHandler(g)
})), {
label: "Cancel",
handler: cancelHandler,
}]
});
return false; return false;
}; }
const changeGamepadHandler = (gamepad: string) => {
scene.inputController.setChosenGamepad(gamepad);
cancelHandler();
return true;
};
scene.ui.setOverlayMode(Mode.OPTION_SELECT, {
options: [ ...gp.map((g: string) => ({
label: truncateString(g, 30), // Truncate the gamepad name for display
handler: () => changeGamepadHandler(g)
})), {
label: "Cancel",
handler: cancelHandler,
}]
});
return false;
} }
} break;
break;
} }
return true; return true;

View File

@ -135,53 +135,53 @@ export const settingKeyboardBlackList = [
export function setSettingKeyboard(scene: BattleScene, setting: SettingKeyboard, value: integer): boolean { export function setSettingKeyboard(scene: BattleScene, setting: SettingKeyboard, value: integer): boolean {
switch (setting) { switch (setting) {
case SettingKeyboard.Button_Up: case SettingKeyboard.Button_Up:
case SettingKeyboard.Button_Down: case SettingKeyboard.Button_Down:
case SettingKeyboard.Button_Left: case SettingKeyboard.Button_Left:
case SettingKeyboard.Button_Right: case SettingKeyboard.Button_Right:
case SettingKeyboard.Button_Action: case SettingKeyboard.Button_Action:
case SettingKeyboard.Button_Cancel: case SettingKeyboard.Button_Cancel:
case SettingKeyboard.Button_Menu: case SettingKeyboard.Button_Menu:
case SettingKeyboard.Button_Stats: case SettingKeyboard.Button_Stats:
case SettingKeyboard.Button_Cycle_Shiny: case SettingKeyboard.Button_Cycle_Shiny:
case SettingKeyboard.Button_Cycle_Form: case SettingKeyboard.Button_Cycle_Form:
case SettingKeyboard.Button_Cycle_Gender: case SettingKeyboard.Button_Cycle_Gender:
case SettingKeyboard.Button_Cycle_Ability: case SettingKeyboard.Button_Cycle_Ability:
case SettingKeyboard.Button_Cycle_Nature: case SettingKeyboard.Button_Cycle_Nature:
case SettingKeyboard.Button_Cycle_Variant: case SettingKeyboard.Button_Cycle_Variant:
case SettingKeyboard.Button_Speed_Up: case SettingKeyboard.Button_Speed_Up:
case SettingKeyboard.Button_Slow_Down: case SettingKeyboard.Button_Slow_Down:
case SettingKeyboard.Alt_Button_Up: case SettingKeyboard.Alt_Button_Up:
case SettingKeyboard.Alt_Button_Down: case SettingKeyboard.Alt_Button_Down:
case SettingKeyboard.Alt_Button_Left: case SettingKeyboard.Alt_Button_Left:
case SettingKeyboard.Alt_Button_Right: case SettingKeyboard.Alt_Button_Right:
case SettingKeyboard.Alt_Button_Action: case SettingKeyboard.Alt_Button_Action:
case SettingKeyboard.Alt_Button_Cancel: case SettingKeyboard.Alt_Button_Cancel:
case SettingKeyboard.Alt_Button_Menu: case SettingKeyboard.Alt_Button_Menu:
case SettingKeyboard.Alt_Button_Stats: case SettingKeyboard.Alt_Button_Stats:
case SettingKeyboard.Alt_Button_Cycle_Shiny: case SettingKeyboard.Alt_Button_Cycle_Shiny:
case SettingKeyboard.Alt_Button_Cycle_Form: case SettingKeyboard.Alt_Button_Cycle_Form:
case SettingKeyboard.Alt_Button_Cycle_Gender: case SettingKeyboard.Alt_Button_Cycle_Gender:
case SettingKeyboard.Alt_Button_Cycle_Ability: case SettingKeyboard.Alt_Button_Cycle_Ability:
case SettingKeyboard.Alt_Button_Cycle_Nature: case SettingKeyboard.Alt_Button_Cycle_Nature:
case SettingKeyboard.Alt_Button_Cycle_Variant: case SettingKeyboard.Alt_Button_Cycle_Variant:
case SettingKeyboard.Alt_Button_Speed_Up: case SettingKeyboard.Alt_Button_Speed_Up:
case SettingKeyboard.Alt_Button_Slow_Down: case SettingKeyboard.Alt_Button_Slow_Down:
case SettingKeyboard.Alt_Button_Submit: case SettingKeyboard.Alt_Button_Submit:
if (value) { if (value) {
if (scene.ui) { if (scene.ui) {
const cancelHandler = (success: boolean = false) : boolean => { const cancelHandler = (success: boolean = false) : boolean => {
scene.ui.revertMode(); scene.ui.revertMode();
(scene.ui.getHandler() as SettingsKeyboardUiHandler).updateBindings(); (scene.ui.getHandler() as SettingsKeyboardUiHandler).updateBindings();
return success; return success;
}; };
scene.ui.setOverlayMode(Mode.KEYBOARD_BINDING, { scene.ui.setOverlayMode(Mode.KEYBOARD_BINDING, {
target: setting, target: setting,
cancelHandler: cancelHandler, cancelHandler: cancelHandler,
}); });
}
} }
} break;
break;
// case SettingKeyboard.Default_Layout: // case SettingKeyboard.Default_Layout:
// if (value && scene.ui) { // if (value && scene.ui) {
// const cancelHandler = () => { // const cancelHandler = () => {

View File

@ -76,16 +76,16 @@ const SHOP_CURSOR_TARGET_OPTIONS: SettingOption[] = [
const shopCursorTargetIndexMap = SHOP_CURSOR_TARGET_OPTIONS.map(option => { const shopCursorTargetIndexMap = SHOP_CURSOR_TARGET_OPTIONS.map(option => {
switch (option.value) { switch (option.value) {
case "Rewards": case "Rewards":
return ShopCursorTarget.REWARDS; return ShopCursorTarget.REWARDS;
case "Shop": case "Shop":
return ShopCursorTarget.SHOP; return ShopCursorTarget.SHOP;
case "Reroll": case "Reroll":
return ShopCursorTarget.REROLL; return ShopCursorTarget.REROLL;
case "Check Team": case "Check Team":
return ShopCursorTarget.CHECK_TEAM; return ShopCursorTarget.CHECK_TEAM;
default: default:
throw new Error(`Unknown value: ${option.value}`); throw new Error(`Unknown value: ${option.value}`);
} }
}); });
@ -699,226 +699,226 @@ export function setSetting(scene: BattleScene, setting: string, value: integer):
return false; return false;
} }
switch (Setting[index].key) { switch (Setting[index].key) {
case SettingKeys.Game_Speed: case SettingKeys.Game_Speed:
scene.gameSpeed = parseFloat(Setting[index].options[value].value.replace("x", "")); scene.gameSpeed = parseFloat(Setting[index].options[value].value.replace("x", ""));
break;
case SettingKeys.Master_Volume:
scene.masterVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0;
scene.updateSoundVolume();
break;
case SettingKeys.BGM_Volume:
scene.bgmVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0;
scene.updateSoundVolume();
break;
case SettingKeys.Field_Volume:
scene.fieldVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0;
scene.updateSoundVolume();
break;
case SettingKeys.SE_Volume:
scene.seVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0;
scene.updateSoundVolume();
break;
case SettingKeys.UI_Volume:
scene.uiVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0;
break;
case SettingKeys.Music_Preference:
scene.musicPreference = value;
break;
case SettingKeys.Damage_Numbers:
scene.damageNumbersMode = value;
break;
case SettingKeys.UI_Theme:
scene.uiTheme = value;
break;
case SettingKeys.Window_Type:
updateWindowType(scene, parseInt(Setting[index].options[value].value));
break;
case SettingKeys.Tutorials:
scene.enableTutorials = Setting[index].options[value].value === "On";
break;
case SettingKeys.Move_Info:
scene.enableMoveInfo = Setting[index].options[value].value === "On";
break;
case SettingKeys.Enable_Retries:
scene.enableRetries = Setting[index].options[value].value === "On";
break;
case SettingKeys.Hide_IVs:
scene.hideIvs = Setting[index].options[value].value === "On";
break;
case SettingKeys.Skip_Seen_Dialogues:
scene.skipSeenDialogues = Setting[index].options[value].value === "On";
break;
case SettingKeys.Egg_Skip:
scene.eggSkipPreference = value;
break;
case SettingKeys.Battle_Style:
scene.battleStyle = value;
break;
case SettingKeys.Show_BGM_Bar:
scene.showBgmBar = Setting[index].options[value].value === "On";
break;
case SettingKeys.Candy_Upgrade_Notification:
if (scene.candyUpgradeNotification === value) {
break; break;
} case SettingKeys.Master_Volume:
scene.candyUpgradeNotification = value; scene.masterVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0;
scene.eventTarget.dispatchEvent(new CandyUpgradeNotificationChangedEvent(value)); scene.updateSoundVolume();
break;
case SettingKeys.Candy_Upgrade_Display:
scene.candyUpgradeDisplay = value;
case SettingKeys.Money_Format:
switch (Setting[index].options[value].value) {
case "Normal":
scene.moneyFormat = MoneyFormat.NORMAL;
break; break;
case "Abbreviated": case SettingKeys.BGM_Volume:
scene.moneyFormat = MoneyFormat.ABBREVIATED; scene.bgmVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0;
scene.updateSoundVolume();
break; break;
} case SettingKeys.Field_Volume:
scene.updateMoneyText(false); scene.fieldVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0;
break; scene.updateSoundVolume();
case SettingKeys.Sprite_Set: break;
scene.experimentalSprites = !!value; case SettingKeys.SE_Volume:
if (value) { scene.seVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0;
scene.initExpSprites(); scene.updateSoundVolume();
} break;
break; case SettingKeys.UI_Volume:
case SettingKeys.Move_Animations: scene.uiVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0;
scene.moveAnimations = Setting[index].options[value].value === "On"; break;
break; case SettingKeys.Music_Preference:
case SettingKeys.Show_Moveset_Flyout: scene.musicPreference = value;
scene.showMovesetFlyout = Setting[index].options[value].value === "On"; break;
break; case SettingKeys.Damage_Numbers:
case SettingKeys.Show_Arena_Flyout: scene.damageNumbersMode = value;
scene.showArenaFlyout = Setting[index].options[value].value === "On"; break;
break; case SettingKeys.UI_Theme:
case SettingKeys.Show_Time_Of_Day_Widget: scene.uiTheme = value;
scene.showTimeOfDayWidget = Setting[index].options[value].value === "On"; break;
break; case SettingKeys.Window_Type:
case SettingKeys.Time_Of_Day_Animation: updateWindowType(scene, parseInt(Setting[index].options[value].value));
scene.timeOfDayAnimation = Setting[index].options[value].value === "Bounce" ? EaseType.BOUNCE : EaseType.BACK; break;
break; case SettingKeys.Tutorials:
case SettingKeys.Show_Stats_on_Level_Up: scene.enableTutorials = Setting[index].options[value].value === "On";
scene.showLevelUpStats = Setting[index].options[value].value === "On"; break;
break; case SettingKeys.Move_Info:
case SettingKeys.Shop_Cursor_Target: scene.enableMoveInfo = Setting[index].options[value].value === "On";
const selectedValue = shopCursorTargetIndexMap[value]; break;
scene.shopCursorTarget = selectedValue; case SettingKeys.Enable_Retries:
break; scene.enableRetries = Setting[index].options[value].value === "On";
case SettingKeys.EXP_Gains_Speed: break;
scene.expGainsSpeed = value; case SettingKeys.Hide_IVs:
break; scene.hideIvs = Setting[index].options[value].value === "On";
case SettingKeys.EXP_Party_Display: break;
scene.expParty = value; case SettingKeys.Skip_Seen_Dialogues:
break; scene.skipSeenDialogues = Setting[index].options[value].value === "On";
case SettingKeys.HP_Bar_Speed: break;
scene.hpBarSpeed = value; case SettingKeys.Egg_Skip:
break; scene.eggSkipPreference = value;
case SettingKeys.Fusion_Palette_Swaps: break;
scene.fusionPaletteSwaps = !!value; case SettingKeys.Battle_Style:
break; scene.battleStyle = value;
case SettingKeys.Player_Gender: break;
if (scene.gameData) { case SettingKeys.Show_BGM_Bar:
const female = Setting[index].options[value].value === "Girl"; scene.showBgmBar = Setting[index].options[value].value === "On";
scene.gameData.gender = female ? PlayerGender.FEMALE : PlayerGender.MALE; break;
scene.trainer.setTexture(scene.trainer.texture.key.replace(female ? "m" : "f", female ? "f" : "m")); case SettingKeys.Candy_Upgrade_Notification:
} else { if (scene.candyUpgradeNotification === value) {
return false; break;
} }
break; scene.candyUpgradeNotification = value;
case SettingKeys.Touch_Controls: scene.eventTarget.dispatchEvent(new CandyUpgradeNotificationChangedEvent(value));
scene.enableTouchControls = Setting[index].options[value].value !== "Disabled" && hasTouchscreen(); break;
const touchControls = document.getElementById("touchControls"); case SettingKeys.Candy_Upgrade_Display:
if (touchControls) { scene.candyUpgradeDisplay = value;
touchControls.classList.toggle("visible", scene.enableTouchControls); case SettingKeys.Money_Format:
} switch (Setting[index].options[value].value) {
break; case "Normal":
case SettingKeys.Vibration: scene.moneyFormat = MoneyFormat.NORMAL;
scene.enableVibration = Setting[index].options[value].value !== "Disabled" && hasTouchscreen(); break;
break; case "Abbreviated":
case SettingKeys.Type_Hints: scene.moneyFormat = MoneyFormat.ABBREVIATED;
scene.typeHints = Setting[index].options[value].value === "On"; break;
break; }
case SettingKeys.Language: scene.updateMoneyText(false);
if (value) { break;
if (scene.ui) { case SettingKeys.Sprite_Set:
const cancelHandler = () => { scene.experimentalSprites = !!value;
scene.ui.revertMode(); if (value) {
(scene.ui.getHandler() as SettingsUiHandler).setOptionCursor(0, 0, true); scene.initExpSprites();
}; }
const changeLocaleHandler = (locale: string): boolean => { break;
try { case SettingKeys.Move_Animations:
i18next.changeLanguage(locale); scene.moveAnimations = Setting[index].options[value].value === "On";
localStorage.setItem("prLang", locale); break;
cancelHandler(); case SettingKeys.Show_Moveset_Flyout:
// Reload the whole game to apply the new locale since also some constants are translated scene.showMovesetFlyout = Setting[index].options[value].value === "On";
window.location.reload(); break;
return true; case SettingKeys.Show_Arena_Flyout:
} catch (error) { scene.showArenaFlyout = Setting[index].options[value].value === "On";
console.error("Error changing locale:", error); break;
return false; case SettingKeys.Show_Time_Of_Day_Widget:
} scene.showTimeOfDayWidget = Setting[index].options[value].value === "On";
}; break;
scene.ui.setOverlayMode(Mode.OPTION_SELECT, { case SettingKeys.Time_Of_Day_Animation:
options: [ scene.timeOfDayAnimation = Setting[index].options[value].value === "Bounce" ? EaseType.BOUNCE : EaseType.BACK;
{ break;
label: "English", case SettingKeys.Show_Stats_on_Level_Up:
handler: () => changeLocaleHandler("en") scene.showLevelUpStats = Setting[index].options[value].value === "On";
}, break;
{ case SettingKeys.Shop_Cursor_Target:
label: "Español", const selectedValue = shopCursorTargetIndexMap[value];
handler: () => changeLocaleHandler("es") scene.shopCursorTarget = selectedValue;
}, break;
{ case SettingKeys.EXP_Gains_Speed:
label: "Italiano", scene.expGainsSpeed = value;
handler: () => changeLocaleHandler("it") break;
}, case SettingKeys.EXP_Party_Display:
{ scene.expParty = value;
label: "Français", break;
handler: () => changeLocaleHandler("fr") case SettingKeys.HP_Bar_Speed:
}, scene.hpBarSpeed = value;
{ break;
label: "Deutsch", case SettingKeys.Fusion_Palette_Swaps:
handler: () => changeLocaleHandler("de") scene.fusionPaletteSwaps = !!value;
}, break;
{ case SettingKeys.Player_Gender:
label: "Português (BR)", if (scene.gameData) {
handler: () => changeLocaleHandler("pt-BR") const female = Setting[index].options[value].value === "Girl";
}, scene.gameData.gender = female ? PlayerGender.FEMALE : PlayerGender.MALE;
{ scene.trainer.setTexture(scene.trainer.texture.key.replace(female ? "m" : "f", female ? "f" : "m"));
label: "简体中文", } else {
handler: () => changeLocaleHandler("zh-CN")
},
{
label: "繁體中文",
handler: () => changeLocaleHandler("zh-TW")
},
{
label: "한국어",
handler: () => changeLocaleHandler("ko")
},
{
label: "日本語",
handler: () => changeLocaleHandler("ja")
},
// {
// label: "Català",
// handler: () => changeLocaleHandler("ca-ES")
// },
{
label: i18next.t("settings:back"),
handler: () => cancelHandler()
}
],
maxOptions: 7
});
return false; return false;
} }
} break;
break; case SettingKeys.Touch_Controls:
case SettingKeys.Shop_Overlay_Opacity: scene.enableTouchControls = Setting[index].options[value].value !== "Disabled" && hasTouchscreen();
scene.updateShopOverlayOpacity(parseInt(Setting[index].options[value].value) * .01); const touchControls = document.getElementById("touchControls");
break; if (touchControls) {
touchControls.classList.toggle("visible", scene.enableTouchControls);
}
break;
case SettingKeys.Vibration:
scene.enableVibration = Setting[index].options[value].value !== "Disabled" && hasTouchscreen();
break;
case SettingKeys.Type_Hints:
scene.typeHints = Setting[index].options[value].value === "On";
break;
case SettingKeys.Language:
if (value) {
if (scene.ui) {
const cancelHandler = () => {
scene.ui.revertMode();
(scene.ui.getHandler() as SettingsUiHandler).setOptionCursor(0, 0, true);
};
const changeLocaleHandler = (locale: string): boolean => {
try {
i18next.changeLanguage(locale);
localStorage.setItem("prLang", locale);
cancelHandler();
// Reload the whole game to apply the new locale since also some constants are translated
window.location.reload();
return true;
} catch (error) {
console.error("Error changing locale:", error);
return false;
}
};
scene.ui.setOverlayMode(Mode.OPTION_SELECT, {
options: [
{
label: "English",
handler: () => changeLocaleHandler("en")
},
{
label: "Español",
handler: () => changeLocaleHandler("es")
},
{
label: "Italiano",
handler: () => changeLocaleHandler("it")
},
{
label: "Français",
handler: () => changeLocaleHandler("fr")
},
{
label: "Deutsch",
handler: () => changeLocaleHandler("de")
},
{
label: "Português (BR)",
handler: () => changeLocaleHandler("pt-BR")
},
{
label: "简体中文",
handler: () => changeLocaleHandler("zh-CN")
},
{
label: "繁體中文",
handler: () => changeLocaleHandler("zh-TW")
},
{
label: "한국어",
handler: () => changeLocaleHandler("ko")
},
{
label: "日本語",
handler: () => changeLocaleHandler("ja")
},
// {
// label: "Català",
// handler: () => changeLocaleHandler("ca-ES")
// },
{
label: i18next.t("settings:back"),
handler: () => cancelHandler()
}
],
maxOptions: 7
});
return false;
}
}
break;
case SettingKeys.Shop_Overlay_Opacity:
scene.updateShopOverlayOpacity(parseInt(Setting[index].options[value].value) * .01);
break;
} }
return true; return true;

View File

@ -10,13 +10,13 @@ export enum Unlockables {
export function getUnlockableName(unlockable: Unlockables) { export function getUnlockableName(unlockable: Unlockables) {
switch (unlockable) { switch (unlockable) {
case Unlockables.ENDLESS_MODE: case Unlockables.ENDLESS_MODE:
return `${GameMode.getModeName(GameModes.ENDLESS)} Mode`; return `${GameMode.getModeName(GameModes.ENDLESS)} Mode`;
case Unlockables.MINI_BLACK_HOLE: case Unlockables.MINI_BLACK_HOLE:
return i18next.t("modifierType:ModifierType.MINI_BLACK_HOLE.name"); return i18next.t("modifierType:ModifierType.MINI_BLACK_HOLE.name");
case Unlockables.SPLICED_ENDLESS_MODE: case Unlockables.SPLICED_ENDLESS_MODE:
return `${GameMode.getModeName(GameModes.SPLICED_ENDLESS)} Mode`; return `${GameMode.getModeName(GameModes.SPLICED_ENDLESS)} Mode`;
case Unlockables.EVIOLITE: case Unlockables.EVIOLITE:
return i18next.t("modifierType:ModifierType.EVIOLITE.name"); return i18next.t("modifierType:ModifierType.EVIOLITE.name");
} }
} }

View File

@ -1,157 +0,0 @@
import { allSpecies } from "#app/data/pokemon-species";
import { AbilityAttr, defaultStarterSpecies, DexAttr, SessionSaveData, SystemSaveData } from "./game-data";
import { SettingKeys } from "./settings/settings";
const LATEST_VERSION = "1.0.5";
export function applySessionDataPatches(data: SessionSaveData) {
const curVersion = data.gameVersion;
// Always sanitize money as a safeguard
data.money = Math.floor(data.money);
if (curVersion !== LATEST_VERSION) {
switch (curVersion) {
case "1.0.0":
case "1.0.1":
case "1.0.2":
case "1.0.3":
case "1.0.4":
// --- PATCHES ---
// Fix Battle Items, Vitamins, and Lures
data.modifiers.forEach((m) => {
if (m.className === "PokemonBaseStatModifier") {
m.className = "BaseStatModifier";
} else if (m.className === "PokemonResetNegativeStatStageModifier") {
m.className = "ResetNegativeStatStageModifier";
} else if (m.className === "TempBattleStatBoosterModifier") {
// Dire Hit no longer a part of the TempBattleStatBoosterModifierTypeGenerator
if (m.typeId !== "DIRE_HIT") {
m.className = "TempStatStageBoosterModifier";
m.typeId = "TEMP_STAT_STAGE_BOOSTER";
// Migration from TempBattleStat to Stat
const newStat = m.typePregenArgs[0] + 1;
m.typePregenArgs[0] = newStat;
// From [ stat, battlesLeft ] to [ stat, maxBattles, battleCount ]
m.args = [ newStat, 5, m.args[1] ];
} else {
m.className = "TempCritBoosterModifier";
m.typePregenArgs = [];
// From [ stat, battlesLeft ] to [ maxBattles, battleCount ]
m.args = [ 5, m.args[1] ];
}
} else if (m.className === "DoubleBattleChanceBoosterModifier" && m.args.length === 1) {
let maxBattles: number;
switch (m.typeId) {
case "MAX_LURE":
maxBattles = 30;
break;
case "SUPER_LURE":
maxBattles = 15;
break;
default:
maxBattles = 10;
break;
}
// From [ battlesLeft ] to [ maxBattles, battleCount ]
m.args = [ maxBattles, m.args[0] ];
}
});
data.enemyModifiers.forEach((m) => {
if (m.className === "PokemonBaseStatModifier") {
m.className = "BaseStatModifier";
} else if (m.className === "PokemonResetNegativeStatStageModifier") {
m.className = "ResetNegativeStatStageModifier";
}
});
}
data.gameVersion = LATEST_VERSION;
}
}
export function applySystemDataPatches(data: SystemSaveData) {
const curVersion = data.gameVersion;
if (curVersion !== LATEST_VERSION) {
switch (curVersion) {
case "1.0.0":
case "1.0.1":
case "1.0.2":
case "1.0.3":
case "1.0.4":
// --- LEGACY PATCHES ---
if (data.starterData && data.dexData) {
// Migrate ability starter data if empty for caught species
Object.keys(data.starterData).forEach(sd => {
if (data.dexData[sd]?.caughtAttr && (data.starterData[sd] && !data.starterData[sd].abilityAttr)) {
data.starterData[sd].abilityAttr = 1;
}
});
}
// Fix Legendary Stats
if (data.gameStats && (data.gameStats.legendaryPokemonCaught !== undefined && data.gameStats.subLegendaryPokemonCaught === undefined)) {
data.gameStats.subLegendaryPokemonSeen = 0;
data.gameStats.subLegendaryPokemonCaught = 0;
data.gameStats.subLegendaryPokemonHatched = 0;
allSpecies.filter(s => s.subLegendary).forEach(s => {
const dexEntry = data.dexData[s.speciesId];
data.gameStats.subLegendaryPokemonSeen += dexEntry.seenCount;
data.gameStats.legendaryPokemonSeen = Math.max(data.gameStats.legendaryPokemonSeen - dexEntry.seenCount, 0);
data.gameStats.subLegendaryPokemonCaught += dexEntry.caughtCount;
data.gameStats.legendaryPokemonCaught = Math.max(data.gameStats.legendaryPokemonCaught - dexEntry.caughtCount, 0);
data.gameStats.subLegendaryPokemonHatched += dexEntry.hatchedCount;
data.gameStats.legendaryPokemonHatched = Math.max(data.gameStats.legendaryPokemonHatched - dexEntry.hatchedCount, 0);
});
data.gameStats.subLegendaryPokemonSeen = Math.max(data.gameStats.subLegendaryPokemonSeen, data.gameStats.subLegendaryPokemonCaught);
data.gameStats.legendaryPokemonSeen = Math.max(data.gameStats.legendaryPokemonSeen, data.gameStats.legendaryPokemonCaught);
data.gameStats.mythicalPokemonSeen = Math.max(data.gameStats.mythicalPokemonSeen, data.gameStats.mythicalPokemonCaught);
}
// --- PATCHES ---
// Fix Starter Data
if (data.starterData && data.dexData) {
for (const starterId of defaultStarterSpecies) {
if (data.starterData[starterId]?.abilityAttr) {
data.starterData[starterId].abilityAttr |= AbilityAttr.ABILITY_1;
}
if (data.dexData[starterId]?.caughtAttr) {
data.dexData[starterId].caughtAttr |= DexAttr.FEMALE;
}
}
}
}
data.gameVersion = LATEST_VERSION;
}
}
export function applySettingsDataPatches(settings: Object) {
const curVersion = settings.hasOwnProperty("gameVersion") ? settings["gameVersion"] : "1.0.0";
if (curVersion !== LATEST_VERSION) {
switch (curVersion) {
case "1.0.0":
case "1.0.1":
case "1.0.2":
case "1.0.3":
case "1.0.4":
// --- PATCHES ---
// Fix Reward Cursor Target
if (settings.hasOwnProperty("REROLL_TARGET") && !settings.hasOwnProperty(SettingKeys.Shop_Cursor_Target)) {
settings[SettingKeys.Shop_Cursor_Target] = settings["REROLL_TARGET"];
delete settings["REROLL_TARGET"];
localStorage.setItem("settings", JSON.stringify(settings));
}
}
// Note that the current game version will be written at `saveSettings`
}
}

View File

@ -0,0 +1,182 @@
import { SessionSaveData, SystemSaveData } from "../game-data";
import { version } from "../../../package.json";
// --- v1.0.4 (and below) PATCHES --- //
import * as v1_0_4 from "./versions/v1_0_4";
const LATEST_VERSION = version.split(".").map(value => parseInt(value));
/**
* Converts incoming {@linkcode SystemSaveData} that has a version below the
* current version number listed in `package.json`.
*
* Note that no transforms act on the {@linkcode data} if its version matches
* the current version or if there are no migrations made between its version up
* to the current version.
* @param data {@linkcode SystemSaveData}
* @see {@link SystemVersionConverter}
*/
export function applySystemVersionMigration(data: SystemSaveData) {
const curVersion = data.gameVersion.split(".").map(value => parseInt(value));
if (!curVersion.every((value, index) => value === LATEST_VERSION[index])) {
const converter = new SystemVersionConverter();
converter.applyStaticPreprocessors(data);
converter.applyMigration(data, curVersion);
}
}
/**
* Converts incoming {@linkcode SessionSavaData} that has a version below the
* current version number listed in `package.json`.
*
* Note that no transforms act on the {@linkcode data} if its version matches
* the current version or if there are no migrations made between its version up
* to the current version.
* @param data {@linkcode SessionSaveData}
* @see {@link SessionVersionConverter}
*/
export function applySessionVersionMigration(data: SessionSaveData) {
const curVersion = data.gameVersion.split(".").map(value => parseInt(value));
if (!curVersion.every((value, index) => value === LATEST_VERSION[index])) {
const converter = new SessionVersionConverter();
converter.applyStaticPreprocessors(data);
converter.applyMigration(data, curVersion);
}
}
/**
* Converts incoming settings data that has a version below the
* current version number listed in `package.json`.
*
* Note that no transforms act on the {@linkcode data} if its version matches
* the current version or if there are no migrations made between its version up
* to the current version.
* @param data Settings data object
* @see {@link SettingsVersionConverter}
*/
export function applySettingsVersionMigration(data: Object) {
const gameVersion: string = data.hasOwnProperty("gameVersion") ? data["gameVersion"] : "1.0.0";
const curVersion = gameVersion.split(".").map(value => parseInt(value));
if (!curVersion.every((value, index) => value === LATEST_VERSION[index])) {
const converter = new SettingsVersionConverter();
converter.applyStaticPreprocessors(data);
converter.applyMigration(data, curVersion);
}
}
/**
* Abstract class encapsulating the logic for migrating data from a given version up to
* the current version listed in `package.json`.
*
* Note that, for any version converter, the corresponding `applyMigration`
* function would only need to be changed once when the first migration for a
* given version is introduced. Similarly, a version file (within the `versions`
* folder) would only need to be created for a version once with the appropriate
* array nomenclature.
*/
abstract class VersionConverter {
/**
* Iterates through an array of designated migration functions that are each
* called one by one to transform the data.
* @param data The data to be operated on
* @param migrationArr An array of functions that will transform the incoming data
*/
callMigrators(data: any, migrationArr: readonly any[]) {
for (const migrate of migrationArr) {
migrate(data);
}
}
/**
* Applies any version-agnostic data sanitation as defined within the function
* body.
* @param data The data to be operated on
*/
applyStaticPreprocessors(_data: any): void {
}
/**
* Uses the current version the incoming data to determine the starting point
* of the migration which will cascade up to the latest version, calling the
* necessary migration functions in the process.
* @param data The data to be operated on
* @param curVersion [0] Current major version
* [1] Current minor version
* [2] Current patch version
*/
abstract applyMigration(data: any, curVersion: number[]): void;
}
/**
* Class encapsulating the logic for migrating {@linkcode SessionSaveData} from
* a given version up to the current version listed in `package.json`.
* @extends VersionConverter
*/
class SessionVersionConverter extends VersionConverter {
override applyStaticPreprocessors(data: SessionSaveData): void {
// Always sanitize money as a safeguard
data.money = Math.floor(data.money);
}
override applyMigration(data: SessionSaveData, curVersion: number[]): void {
const [ curMajor, curMinor, curPatch ] = curVersion;
if (curMajor === 1) {
if (curMinor === 0) {
if (curPatch <= 4) {
console.log("Applying v1.0.4 session data migration!");
this.callMigrators(data, v1_0_4.sessionMigrators);
}
}
}
console.log(`Session data successfully migrated to v${version}!`);
}
}
/**
* Class encapsulating the logic for migrating {@linkcode SystemSaveData} from
* a given version up to the current version listed in `package.json`.
* @extends VersionConverter
*/
class SystemVersionConverter extends VersionConverter {
override applyMigration(data: SystemSaveData, curVersion: number[]): void {
const [ curMajor, curMinor, curPatch ] = curVersion;
if (curMajor === 1) {
if (curMinor === 0) {
if (curPatch <= 4) {
console.log("Applying v1.0.4 system data migraton!");
this.callMigrators(data, v1_0_4.systemMigrators);
}
}
}
console.log(`System data successfully migrated to v${version}!`);
}
}
/**
* Class encapsulating the logic for migrating settings data from
* a given version up to the current version listed in `package.json`.
* @extends VersionConverter
*/
class SettingsVersionConverter extends VersionConverter {
override applyMigration(data: Object, curVersion: number[]): void {
const [ curMajor, curMinor, curPatch ] = curVersion;
if (curMajor === 1) {
if (curMinor === 0) {
if (curPatch <= 4) {
console.log("Applying v1.0.4 settings data migraton!");
this.callMigrators(data, v1_0_4.settingsMigrators);
}
}
}
console.log(`System data successfully migrated to v${version}!`);
}
}

View File

@ -0,0 +1,135 @@
import { SettingKeys } from "../../settings/settings";
import { AbilityAttr, defaultStarterSpecies, DexAttr, SystemSaveData, SessionSaveData } from "../../game-data";
import { allSpecies } from "../../../data/pokemon-species";
export const systemMigrators = [
/**
* Migrate ability starter data if empty for caught species.
* @param data {@linkcode SystemSaveData}
*/
function migrateAbilityData(data: SystemSaveData) {
if (data.starterData && data.dexData) {
Object.keys(data.starterData).forEach(sd => {
if (data.dexData[sd]?.caughtAttr && (data.starterData[sd] && !data.starterData[sd].abilityAttr)) {
data.starterData[sd].abilityAttr = 1;
}
});
}
},
/**
* Populate legendary Pokémon statistics if they are missing.
* @param data {@linkcode SystemSaveData}
*/
function fixLegendaryStats(data: SystemSaveData) {
if (data.gameStats && (data.gameStats.legendaryPokemonCaught !== undefined && data.gameStats.subLegendaryPokemonCaught === undefined)) {
data.gameStats.subLegendaryPokemonSeen = 0;
data.gameStats.subLegendaryPokemonCaught = 0;
data.gameStats.subLegendaryPokemonHatched = 0;
allSpecies.filter(s => s.subLegendary).forEach(s => {
const dexEntry = data.dexData[s.speciesId];
data.gameStats.subLegendaryPokemonSeen += dexEntry.seenCount;
data.gameStats.legendaryPokemonSeen = Math.max(data.gameStats.legendaryPokemonSeen - dexEntry.seenCount, 0);
data.gameStats.subLegendaryPokemonCaught += dexEntry.caughtCount;
data.gameStats.legendaryPokemonCaught = Math.max(data.gameStats.legendaryPokemonCaught - dexEntry.caughtCount, 0);
data.gameStats.subLegendaryPokemonHatched += dexEntry.hatchedCount;
data.gameStats.legendaryPokemonHatched = Math.max(data.gameStats.legendaryPokemonHatched - dexEntry.hatchedCount, 0);
});
data.gameStats.subLegendaryPokemonSeen = Math.max(data.gameStats.subLegendaryPokemonSeen, data.gameStats.subLegendaryPokemonCaught);
data.gameStats.legendaryPokemonSeen = Math.max(data.gameStats.legendaryPokemonSeen, data.gameStats.legendaryPokemonCaught);
data.gameStats.mythicalPokemonSeen = Math.max(data.gameStats.mythicalPokemonSeen, data.gameStats.mythicalPokemonCaught);
}
},
/**
* Unlock all starters' first ability and female gender option.
* @param data {@linkcode SystemSaveData}
*/
function fixStarterData(data: SystemSaveData) {
for (const starterId of defaultStarterSpecies) {
if (data.starterData[starterId]?.abilityAttr) {
data.starterData[starterId].abilityAttr |= AbilityAttr.ABILITY_1;
}
if (data.dexData[starterId]?.caughtAttr) {
data.dexData[starterId].caughtAttr |= DexAttr.FEMALE;
}
}
}
] as const;
export const settingsMigrators = [
/**
* Migrate from "REROLL_TARGET" property to {@linkcode
* SettingKeys.Shop_Cursor_Target}.
* @param data the `settings` object
*/
function fixRerollTarget(data: Object) {
if (data.hasOwnProperty("REROLL_TARGET") && !data.hasOwnProperty(SettingKeys.Shop_Cursor_Target)) {
data[SettingKeys.Shop_Cursor_Target] = data["REROLL_TARGET"];
delete data["REROLL_TARGET"];
localStorage.setItem("settings", JSON.stringify(data));
}
}
] as const;
export const sessionMigrators = [
/**
* Converts old lapsing modifiers (battle items, lures, and Dire Hit) and
* other miscellaneous modifiers (vitamins, White Herb) to any new class
* names and/or change in reload arguments.
* @param data {@linkcode SessionSaveData}
*/
function migrateModifiers(data: SessionSaveData) {
data.modifiers.forEach((m) => {
if (m.className === "PokemonBaseStatModifier") {
m.className = "BaseStatModifier";
} else if (m.className === "PokemonResetNegativeStatStageModifier") {
m.className = "ResetNegativeStatStageModifier";
} else if (m.className === "TempBattleStatBoosterModifier") {
const maxBattles = 5;
// Dire Hit no longer a part of the TempBattleStatBoosterModifierTypeGenerator
if (m.typeId !== "DIRE_HIT") {
m.className = "TempStatStageBoosterModifier";
m.typeId = "TEMP_STAT_STAGE_BOOSTER";
// Migration from TempBattleStat to Stat
const newStat = m.typePregenArgs[0] + 1;
m.typePregenArgs[0] = newStat;
// From [ stat, battlesLeft ] to [ stat, maxBattles, battleCount ]
m.args = [ newStat, maxBattles, Math.min(m.args[1], maxBattles) ];
} else {
m.className = "TempCritBoosterModifier";
m.typePregenArgs = [];
// From [ stat, battlesLeft ] to [ maxBattles, battleCount ]
m.args = [ maxBattles, Math.min(m.args[1], maxBattles) ];
}
} else if (m.className === "DoubleBattleChanceBoosterModifier" && m.args.length === 1) {
let maxBattles: number;
switch (m.typeId) {
case "MAX_LURE":
maxBattles = 30;
break;
case "SUPER_LURE":
maxBattles = 15;
break;
default:
maxBattles = 10;
break;
}
// From [ battlesLeft ] to [ maxBattles, battleCount ]
m.args = [ maxBattles, Math.min(m.args[0], maxBattles) ];
}
});
data.enemyModifiers.forEach((m) => {
if (m.className === "PokemonBaseStatModifier") {
m.className = "BaseStatModifier";
} else if (m.className === "PokemonResetNegativeStatStageModifier") {
m.className = "ResetNegativeStatStageModifier";
}
});
}
] as const;

View File

@ -45,41 +45,41 @@ export class Voucher {
getTier(): AchvTier { getTier(): AchvTier {
switch (this.voucherType) { switch (this.voucherType) {
case VoucherType.REGULAR: case VoucherType.REGULAR:
return AchvTier.COMMON; return AchvTier.COMMON;
case VoucherType.PLUS: case VoucherType.PLUS:
return AchvTier.GREAT; return AchvTier.GREAT;
case VoucherType.PREMIUM: case VoucherType.PREMIUM:
return AchvTier.ULTRA; return AchvTier.ULTRA;
case VoucherType.GOLDEN: case VoucherType.GOLDEN:
return AchvTier.ROGUE; return AchvTier.ROGUE;
} }
} }
} }
export function getVoucherTypeName(voucherType: VoucherType): string { export function getVoucherTypeName(voucherType: VoucherType): string {
switch (voucherType) { switch (voucherType) {
case VoucherType.REGULAR: case VoucherType.REGULAR:
return i18next.t("voucher:eggVoucher"); return i18next.t("voucher:eggVoucher");
case VoucherType.PLUS: case VoucherType.PLUS:
return i18next.t("voucher:eggVoucherPlus"); return i18next.t("voucher:eggVoucherPlus");
case VoucherType.PREMIUM: case VoucherType.PREMIUM:
return i18next.t("voucher:eggVoucherPremium"); return i18next.t("voucher:eggVoucherPremium");
case VoucherType.GOLDEN: case VoucherType.GOLDEN:
return i18next.t("voucher:eggVoucherGold"); return i18next.t("voucher:eggVoucherGold");
} }
} }
export function getVoucherTypeIcon(voucherType: VoucherType): string { export function getVoucherTypeIcon(voucherType: VoucherType): string {
switch (voucherType) { switch (voucherType) {
case VoucherType.REGULAR: case VoucherType.REGULAR:
return "coupon"; return "coupon";
case VoucherType.PLUS: case VoucherType.PLUS:
return "pair_of_tickets"; return "pair_of_tickets";
case VoucherType.PREMIUM: case VoucherType.PREMIUM:
return "mystic_ticket"; return "mystic_ticket";
case VoucherType.GOLDEN: case VoucherType.GOLDEN:
return "golden_mystic_ticket"; return "golden_mystic_ticket";
} }
} }

View File

@ -97,20 +97,20 @@ export async function runSelectMysteryEncounterOption(game: GameManager, optionN
uiHandler.unblockInput(); // input are blocked by 1s to prevent accidental input. Tests need to handle that uiHandler.unblockInput(); // input are blocked by 1s to prevent accidental input. Tests need to handle that
switch (optionNo) { switch (optionNo) {
default: default:
case 1: case 1:
// no movement needed. Default cursor position // no movement needed. Default cursor position
break; break;
case 2: case 2:
uiHandler.processInput(Button.RIGHT); uiHandler.processInput(Button.RIGHT);
break; break;
case 3: case 3:
uiHandler.processInput(Button.DOWN); uiHandler.processInput(Button.DOWN);
break; break;
case 4: case 4:
uiHandler.processInput(Button.RIGHT); uiHandler.processInput(Button.RIGHT);
uiHandler.processInput(Button.DOWN); uiHandler.processInput(Button.DOWN);
break; break;
} }
if (!isNullOrUndefined(secondaryOptionSelect?.pokemonNo)) { if (!isNullOrUndefined(secondaryOptionSelect?.pokemonNo)) {

View File

@ -23,6 +23,7 @@ import KeyboardPlugin = Phaser.Input.Keyboard.KeyboardPlugin;
import GamepadPlugin = Phaser.Input.Gamepad.GamepadPlugin; import GamepadPlugin = Phaser.Input.Gamepad.GamepadPlugin;
import EventEmitter = Phaser.Events.EventEmitter; import EventEmitter = Phaser.Events.EventEmitter;
import UpdateList = Phaser.GameObjects.UpdateList; import UpdateList = Phaser.GameObjects.UpdateList;
import { version } from "../../../package.json";
Object.defineProperty(window, "localStorage", { Object.defineProperty(window, "localStorage", {
value: mockLocalStorage(), value: mockLocalStorage(),
@ -101,6 +102,7 @@ export default class GameWrapper {
injectMandatory() { injectMandatory() {
this.game.config = { this.game.config = {
seed: ["test"], seed: ["test"],
gameVersion: version
}; };
this.scene.game = this.game; this.scene.game = this.game;
this.game.renderer = { this.game.renderer = {

View File

@ -122,20 +122,20 @@ export default class TouchControl {
const button = Button[key]; const button = Button[key];
switch (eventType) { switch (eventType) {
case "keydown": case "keydown":
this.events.emit("input_down", { this.events.emit("input_down", {
controller_type: "keyboard", controller_type: "keyboard",
button: button, button: button,
isTouch: true isTouch: true
}); });
break; break;
case "keyup": case "keyup":
this.events.emit("input_up", { this.events.emit("input_up", {
controller_type: "keyboard", controller_type: "keyboard",
button: button, button: button,
isTouch: true isTouch: true
}); });
break; break;
} }
return true; return true;
} }

View File

@ -168,26 +168,26 @@ export class UiInputs {
return; return;
} }
switch (this.scene.ui?.getMode()) { switch (this.scene.ui?.getMode()) {
case Mode.MESSAGE: case Mode.MESSAGE:
const messageHandler = this.scene.ui.getHandler<MessageUiHandler>(); const messageHandler = this.scene.ui.getHandler<MessageUiHandler>();
if (!messageHandler.pendingPrompt || messageHandler.isTextAnimationInProgress()) { if (!messageHandler.pendingPrompt || messageHandler.isTextAnimationInProgress()) {
return;
}
case Mode.TITLE:
case Mode.COMMAND:
case Mode.MODIFIER_SELECT:
case Mode.MYSTERY_ENCOUNTER:
this.scene.ui.setOverlayMode(Mode.MENU);
break;
case Mode.STARTER_SELECT:
this.buttonTouch();
break;
case Mode.MENU:
this.scene.ui.revertMode();
this.scene.playSound("ui/select");
break;
default:
return; return;
}
case Mode.TITLE:
case Mode.COMMAND:
case Mode.MODIFIER_SELECT:
case Mode.MYSTERY_ENCOUNTER:
this.scene.ui.setOverlayMode(Mode.MENU);
break;
case Mode.STARTER_SELECT:
this.buttonTouch();
break;
case Mode.MENU:
this.scene.ui.revertMode();
this.scene.playSound("ui/select");
break;
default:
return;
} }
} }

View File

@ -222,20 +222,20 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
} }
} else { } else {
switch (button) { switch (button) {
case Button.UP: case Button.UP:
if (this.cursor) { if (this.cursor) {
success = this.setCursor(this.cursor - 1); success = this.setCursor(this.cursor - 1);
} else if (this.cursor === 0) { } else if (this.cursor === 0) {
success = this.setCursor(options.length - 1); success = this.setCursor(options.length - 1);
} }
break; break;
case Button.DOWN: case Button.DOWN:
if (this.cursor < options.length - 1) { if (this.cursor < options.length - 1) {
success = this.setCursor(this.cursor + 1); success = this.setCursor(this.cursor + 1);
} else { } else {
success = this.setCursor(0); success = this.setCursor(0);
} }
break; break;
} }
if (this.config?.supportHover) { if (this.config?.supportHover) {
// handle hover code if the element supports hover-handlers and the option has the optional hover-handler set. // handle hover code if the element supports hover-handlers and the option has the optional hover-handler set.

View File

@ -245,51 +245,51 @@ export default class AchvsUiHandler extends MessageUiHandler {
const rowIndex = Math.floor(this.cursor / this.COLS); const rowIndex = Math.floor(this.cursor / this.COLS);
const itemOffset = (this.scrollCursor * this.COLS); const itemOffset = (this.scrollCursor * this.COLS);
switch (button) { switch (button) {
case Button.UP: case Button.UP:
if (this.cursor < this.COLS) { if (this.cursor < this.COLS) {
if (this.scrollCursor) { if (this.scrollCursor) {
success = this.setScrollCursor(this.scrollCursor - 1); success = this.setScrollCursor(this.scrollCursor - 1);
} else { } else {
// Wrap around to the last row // Wrap around to the last row
success = this.setScrollCursor(Math.ceil(this.currentTotal / this.COLS) - this.ROWS); success = this.setScrollCursor(Math.ceil(this.currentTotal / this.COLS) - this.ROWS);
let newCursorIndex = this.cursor + (this.ROWS - 1) * this.COLS; let newCursorIndex = this.cursor + (this.ROWS - 1) * this.COLS;
if (newCursorIndex > this.currentTotal - this.scrollCursor * this.COLS - 1) { if (newCursorIndex > this.currentTotal - this.scrollCursor * this.COLS - 1) {
newCursorIndex -= this.COLS; newCursorIndex -= this.COLS;
}
success = success && this.setCursor(newCursorIndex);
} }
success = success && this.setCursor(newCursorIndex);
}
} else {
success = this.setCursor(this.cursor - this.COLS);
}
break;
case Button.DOWN:
const canMoveDown = itemOffset + 1 < this.currentTotal;
if (rowIndex >= this.ROWS - 1) {
if (this.scrollCursor < Math.ceil(this.currentTotal / this.COLS) - this.ROWS && canMoveDown) {
// scroll down one row
success = this.setScrollCursor(this.scrollCursor + 1);
} else { } else {
// wrap back to the first row success = this.setCursor(this.cursor - this.COLS);
success = this.setScrollCursor(0) && this.setCursor(this.cursor % this.COLS);
} }
} else if (canMoveDown) { break;
success = this.setCursor(Math.min(this.cursor + this.COLS, this.currentTotal - itemOffset - 1)); case Button.DOWN:
} const canMoveDown = itemOffset + 1 < this.currentTotal;
break; if (rowIndex >= this.ROWS - 1) {
case Button.LEFT: if (this.scrollCursor < Math.ceil(this.currentTotal / this.COLS) - this.ROWS && canMoveDown) {
if (this.cursor % this.COLS === 0) { // scroll down one row
success = this.setCursor(Math.min(this.cursor + this.COLS - 1, this.currentTotal - itemOffset - 1)); success = this.setScrollCursor(this.scrollCursor + 1);
} else { } else {
success = this.setCursor(this.cursor - 1); // wrap back to the first row
} success = this.setScrollCursor(0) && this.setCursor(this.cursor % this.COLS);
break; }
case Button.RIGHT: } else if (canMoveDown) {
if ((this.cursor + 1) % this.COLS === 0 || (this.cursor + itemOffset) === (this.currentTotal - 1)) { success = this.setCursor(Math.min(this.cursor + this.COLS, this.currentTotal - itemOffset - 1));
success = this.setCursor(this.cursor - this.cursor % this.COLS); }
} else { break;
success = this.setCursor(this.cursor + 1); case Button.LEFT:
} if (this.cursor % this.COLS === 0) {
break; success = this.setCursor(Math.min(this.cursor + this.COLS - 1, this.currentTotal - itemOffset - 1));
} else {
success = this.setCursor(this.cursor - 1);
}
break;
case Button.RIGHT:
if ((this.cursor + 1) % this.COLS === 0 || (this.cursor + itemOffset) === (this.currentTotal - 1)) {
success = this.setCursor(this.cursor - this.cursor % this.COLS);
} else {
success = this.setCursor(this.cursor + 1);
}
break;
} }
} }
@ -316,22 +316,22 @@ export default class AchvsUiHandler extends MessageUiHandler {
if (update || pageChange) { if (update || pageChange) {
switch (this.currentPage) { switch (this.currentPage) {
case Page.ACHIEVEMENTS: case Page.ACHIEVEMENTS:
if (pageChange) { if (pageChange) {
this.titleBg.width = 174; this.titleBg.width = 174;
this.titleText.x = this.titleBg.width / 2; this.titleText.x = this.titleBg.width / 2;
this.scoreContainer.setVisible(true); this.scoreContainer.setVisible(true);
} }
this.showAchv(achvs[Object.keys(achvs)[cursor + this.scrollCursor * this.COLS]]); this.showAchv(achvs[Object.keys(achvs)[cursor + this.scrollCursor * this.COLS]]);
break; break;
case Page.VOUCHERS: case Page.VOUCHERS:
if (pageChange) { if (pageChange) {
this.titleBg.width = 220; this.titleBg.width = 220;
this.titleText.x = this.titleBg.width / 2; this.titleText.x = this.titleBg.width / 2;
this.scoreContainer.setVisible(false); this.scoreContainer.setVisible(false);
} }
this.showVoucher(vouchers[Object.keys(vouchers)[cursor + this.scrollCursor * this.COLS]]); this.showVoucher(vouchers[Object.keys(vouchers)[cursor + this.scrollCursor * this.COLS]]);
break; break;
} }
} }
return ret; return ret;
@ -358,14 +358,14 @@ export default class AchvsUiHandler extends MessageUiHandler {
} }
switch (this.currentPage) { switch (this.currentPage) {
case Page.ACHIEVEMENTS: case Page.ACHIEVEMENTS:
this.updateAchvIcons(); this.updateAchvIcons();
this.showAchv(achvs[Object.keys(achvs)[this.cursor + this.scrollCursor * this.COLS]]); this.showAchv(achvs[Object.keys(achvs)[this.cursor + this.scrollCursor * this.COLS]]);
break; break;
case Page.VOUCHERS: case Page.VOUCHERS:
this.updateVoucherIcons(); this.updateVoucherIcons();
this.showVoucher(vouchers[Object.keys(vouchers)[this.cursor + this.scrollCursor * this.COLS]]); this.showVoucher(vouchers[Object.keys(vouchers)[this.cursor + this.scrollCursor * this.COLS]]);
break; break;
} }
return true; return true;
} }

View File

@ -215,20 +215,20 @@ export class ArenaFlyout extends Phaser.GameObjects.Container {
// Creates a proxy object to decide which text object needs to be updated // Creates a proxy object to decide which text object needs to be updated
let textObject: Phaser.GameObjects.Text; let textObject: Phaser.GameObjects.Text;
switch (fieldEffectInfo.effecType) { switch (fieldEffectInfo.effecType) {
case ArenaEffectType.PLAYER: case ArenaEffectType.PLAYER:
textObject = this.flyoutTextPlayer; textObject = this.flyoutTextPlayer;
break; break;
case ArenaEffectType.WEATHER: case ArenaEffectType.WEATHER:
case ArenaEffectType.TERRAIN: case ArenaEffectType.TERRAIN:
case ArenaEffectType.FIELD: case ArenaEffectType.FIELD:
textObject = this.flyoutTextField; textObject = this.flyoutTextField;
break; break;
case ArenaEffectType.ENEMY: case ArenaEffectType.ENEMY:
textObject = this.flyoutTextEnemy; textObject = this.flyoutTextEnemy;
break; break;
} }
textObject.text += fieldEffectInfo.name; textObject.text += fieldEffectInfo.name;
@ -253,81 +253,81 @@ export class ArenaFlyout extends Phaser.GameObjects.Container {
let foundIndex: number; let foundIndex: number;
switch (arenaEffectChangedEvent.constructor) { switch (arenaEffectChangedEvent.constructor) {
case TagAddedEvent: case TagAddedEvent:
const tagAddedEvent = arenaEffectChangedEvent as TagAddedEvent; const tagAddedEvent = arenaEffectChangedEvent as TagAddedEvent;
const isArenaTrapTag = this.battleScene.arena.getTag(tagAddedEvent.arenaTagType) instanceof ArenaTrapTag; const isArenaTrapTag = this.battleScene.arena.getTag(tagAddedEvent.arenaTagType) instanceof ArenaTrapTag;
let arenaEffectType: ArenaEffectType; let arenaEffectType: ArenaEffectType;
if (tagAddedEvent.arenaTagSide === ArenaTagSide.BOTH) { if (tagAddedEvent.arenaTagSide === ArenaTagSide.BOTH) {
arenaEffectType = ArenaEffectType.FIELD; arenaEffectType = ArenaEffectType.FIELD;
} else if (tagAddedEvent.arenaTagSide === ArenaTagSide.PLAYER) { } else if (tagAddedEvent.arenaTagSide === ArenaTagSide.PLAYER) {
arenaEffectType = ArenaEffectType.PLAYER; arenaEffectType = ArenaEffectType.PLAYER;
} else { } else {
arenaEffectType = ArenaEffectType.ENEMY; arenaEffectType = ArenaEffectType.ENEMY;
}
const existingTrapTagIndex = isArenaTrapTag ? this.fieldEffectInfo.findIndex(e => tagAddedEvent.arenaTagType === e.tagType && arenaEffectType === e.effecType) : -1;
let name: string = getFieldEffectText(ArenaTagType[tagAddedEvent.arenaTagType]);
if (isArenaTrapTag) {
if (existingTrapTagIndex !== -1) {
const layers = tagAddedEvent.arenaTagMaxLayers > 1 ? ` (${tagAddedEvent.arenaTagLayers})` : "";
this.fieldEffectInfo[existingTrapTagIndex].name = `${name}${layers}`;
break;
} else if (tagAddedEvent.arenaTagMaxLayers > 1) {
name = `${name} (${tagAddedEvent.arenaTagLayers})`;
} }
}
this.fieldEffectInfo.push({ const existingTrapTagIndex = isArenaTrapTag ? this.fieldEffectInfo.findIndex(e => tagAddedEvent.arenaTagType === e.tagType && arenaEffectType === e.effecType) : -1;
name, let name: string = getFieldEffectText(ArenaTagType[tagAddedEvent.arenaTagType]);
effecType: arenaEffectType,
maxDuration: tagAddedEvent.duration,
duration: tagAddedEvent.duration,
tagType: tagAddedEvent.arenaTagType
});
break;
case TagRemovedEvent:
const tagRemovedEvent = arenaEffectChangedEvent as TagRemovedEvent;
foundIndex = this.fieldEffectInfo.findIndex(info => info.tagType === tagRemovedEvent.arenaTagType);
if (foundIndex !== -1) { // If the tag was being tracked, remove it if (isArenaTrapTag) {
this.fieldEffectInfo.splice(foundIndex, 1); if (existingTrapTagIndex !== -1) {
} const layers = tagAddedEvent.arenaTagMaxLayers > 1 ? ` (${tagAddedEvent.arenaTagLayers})` : "";
break; this.fieldEffectInfo[existingTrapTagIndex].name = `${name}${layers}`;
break;
} else if (tagAddedEvent.arenaTagMaxLayers > 1) {
name = `${name} (${tagAddedEvent.arenaTagLayers})`;
}
}
case WeatherChangedEvent: this.fieldEffectInfo.push({
case TerrainChangedEvent: name,
const fieldEffectChangedEvent = arenaEffectChangedEvent as WeatherChangedEvent | TerrainChangedEvent; effecType: arenaEffectType,
maxDuration: tagAddedEvent.duration,
duration: tagAddedEvent.duration,
tagType: tagAddedEvent.arenaTagType
});
break;
case TagRemovedEvent:
const tagRemovedEvent = arenaEffectChangedEvent as TagRemovedEvent;
foundIndex = this.fieldEffectInfo.findIndex(info => info.tagType === tagRemovedEvent.arenaTagType);
// Stores the old Weather/Terrain name in case it's in the array already if (foundIndex !== -1) { // If the tag was being tracked, remove it
const oldName = this.fieldEffectInfo.splice(foundIndex, 1);
}
break;
case WeatherChangedEvent:
case TerrainChangedEvent:
const fieldEffectChangedEvent = arenaEffectChangedEvent as WeatherChangedEvent | TerrainChangedEvent;
// Stores the old Weather/Terrain name in case it's in the array already
const oldName =
getFieldEffectText(fieldEffectChangedEvent instanceof WeatherChangedEvent getFieldEffectText(fieldEffectChangedEvent instanceof WeatherChangedEvent
? WeatherType[fieldEffectChangedEvent.oldWeatherType] ? WeatherType[fieldEffectChangedEvent.oldWeatherType]
: TerrainType[fieldEffectChangedEvent.oldTerrainType]); : TerrainType[fieldEffectChangedEvent.oldTerrainType]);
// Stores the new Weather/Terrain info // Stores the new Weather/Terrain info
const newInfo = { const newInfo = {
name: name:
getFieldEffectText(fieldEffectChangedEvent instanceof WeatherChangedEvent getFieldEffectText(fieldEffectChangedEvent instanceof WeatherChangedEvent
? WeatherType[fieldEffectChangedEvent.newWeatherType] ? WeatherType[fieldEffectChangedEvent.newWeatherType]
: TerrainType[fieldEffectChangedEvent.newTerrainType]), : TerrainType[fieldEffectChangedEvent.newTerrainType]),
effecType: fieldEffectChangedEvent instanceof WeatherChangedEvent effecType: fieldEffectChangedEvent instanceof WeatherChangedEvent
? ArenaEffectType.WEATHER ? ArenaEffectType.WEATHER
: ArenaEffectType.TERRAIN, : ArenaEffectType.TERRAIN,
maxDuration: fieldEffectChangedEvent.duration, maxDuration: fieldEffectChangedEvent.duration,
duration: fieldEffectChangedEvent.duration }; duration: fieldEffectChangedEvent.duration };
foundIndex = this.fieldEffectInfo.findIndex(info => [ newInfo.name, oldName ].includes(info.name)); foundIndex = this.fieldEffectInfo.findIndex(info => [ newInfo.name, oldName ].includes(info.name));
if (foundIndex === -1) { if (foundIndex === -1) {
if (newInfo.name !== undefined) { if (newInfo.name !== undefined) {
this.fieldEffectInfo.push(newInfo); // Adds the info to the array if it doesn't already exist and is defined this.fieldEffectInfo.push(newInfo); // Adds the info to the array if it doesn't already exist and is defined
}
} else if (!newInfo.name) {
this.fieldEffectInfo.splice(foundIndex, 1); // Removes the old info if the new one is undefined
} else {
this.fieldEffectInfo[foundIndex] = newInfo; // Otherwise, replace the old info
} }
} else if (!newInfo.name) { break;
this.fieldEffectInfo.splice(foundIndex, 1); // Removes the old info if the new one is undefined
} else {
this.fieldEffectInfo[foundIndex] = newInfo; // Otherwise, replace the old info
}
break;
} }
this.updateFieldText(); this.updateFieldText();

View File

@ -90,12 +90,12 @@ export default class BallUiHandler extends UiHandler {
} }
} else { } else {
switch (button) { switch (button) {
case Button.UP: case Button.UP:
success = this.setCursor(this.cursor ? this.cursor - 1 : pokeballTypeCount); success = this.setCursor(this.cursor ? this.cursor - 1 : pokeballTypeCount);
break; break;
case Button.DOWN: case Button.DOWN:
success = this.setCursor(this.cursor < pokeballTypeCount ? this.cursor + 1 : 0); success = this.setCursor(this.cursor < pokeballTypeCount ? this.cursor + 1 : 0);
break; break;
} }
} }

View File

@ -376,66 +376,66 @@ export default class GameChallengesUiHandler extends UiHandler {
} else { } else {
if (this.cursorObj?.visible && !this.startCursor.visible) { if (this.cursorObj?.visible && !this.startCursor.visible) {
switch (button) { switch (button) {
case Button.UP: case Button.UP:
if (this.cursor === 0) { if (this.cursor === 0) {
if (this.scrollCursor === 0) { if (this.scrollCursor === 0) {
// When at the top of the menu and pressing UP, move to the bottommost item. // When at the top of the menu and pressing UP, move to the bottommost item.
if (this.scene.gameMode.challenges.length > rowsToDisplay) { // If there are more than 9 challenges, scroll to the bottom if (this.scene.gameMode.challenges.length > rowsToDisplay) { // If there are more than 9 challenges, scroll to the bottom
// First, set the cursor to the last visible element, preparing for the scroll to the end. // First, set the cursor to the last visible element, preparing for the scroll to the end.
const successA = this.setCursor(rowsToDisplay - 1); const successA = this.setCursor(rowsToDisplay - 1);
// Then, adjust the scroll to display the bottommost elements of the menu. // Then, adjust the scroll to display the bottommost elements of the menu.
const successB = this.setScrollCursor(this.scene.gameMode.challenges.length - rowsToDisplay); const successB = this.setScrollCursor(this.scene.gameMode.challenges.length - rowsToDisplay);
success = successA && successB; // success is just there to play the little validation sound effect success = successA && successB; // success is just there to play the little validation sound effect
} else { // If there are 9 or less challenges, just move to the bottom one } else { // If there are 9 or less challenges, just move to the bottom one
success = this.setCursor(this.scene.gameMode.challenges.length - 1); success = this.setCursor(this.scene.gameMode.challenges.length - 1);
}
} else {
success = this.setScrollCursor(this.scrollCursor - 1);
} }
} else { } else {
success = this.setScrollCursor(this.scrollCursor - 1); success = this.setCursor(this.cursor - 1);
} }
} else { if (success) {
success = this.setCursor(this.cursor - 1); this.updateText();
} }
if (success) { break;
this.updateText(); case Button.DOWN:
} if (this.cursor === rowsToDisplay - 1) {
break; if (this.scrollCursor < this.scene.gameMode.challenges.length - rowsToDisplay) {
case Button.DOWN:
if (this.cursor === rowsToDisplay - 1) {
if (this.scrollCursor < this.scene.gameMode.challenges.length - rowsToDisplay) {
// When at the bottom and pressing DOWN, scroll if possible. // When at the bottom and pressing DOWN, scroll if possible.
success = this.setScrollCursor(this.scrollCursor + 1); success = this.setScrollCursor(this.scrollCursor + 1);
} else { } else {
// When at the bottom of a scrolling menu and pressing DOWN, move to the topmost item. // When at the bottom of a scrolling menu and pressing DOWN, move to the topmost item.
// First, set the cursor to the first visible element, preparing for the scroll to the top. // First, set the cursor to the first visible element, preparing for the scroll to the top.
const successA = this.setCursor(0); const successA = this.setCursor(0);
// Then, adjust the scroll to display the topmost elements of the menu. // Then, adjust the scroll to display the topmost elements of the menu.
const successB = this.setScrollCursor(0); const successB = this.setScrollCursor(0);
success = successA && successB; // success is just there to play the little validation sound effect success = successA && successB; // success is just there to play the little validation sound effect
} }
} else if (this.scene.gameMode.challenges.length < rowsToDisplay && this.cursor === this.scene.gameMode.challenges.length - 1) { } else if (this.scene.gameMode.challenges.length < rowsToDisplay && this.cursor === this.scene.gameMode.challenges.length - 1) {
// When at the bottom of a non-scrolling menu and pressing DOWN, move to the topmost item. // When at the bottom of a non-scrolling menu and pressing DOWN, move to the topmost item.
success = this.setCursor(0); success = this.setCursor(0);
} else { } else {
success = this.setCursor(this.cursor + 1); success = this.setCursor(this.cursor + 1);
} }
if (success) { if (success) {
this.updateText(); this.updateText();
} }
break; break;
case Button.LEFT: case Button.LEFT:
// Moves the option cursor left, if possible. // Moves the option cursor left, if possible.
success = this.getActiveChallenge().decreaseValue(); success = this.getActiveChallenge().decreaseValue();
if (success) { if (success) {
this.updateText(); this.updateText();
} }
break; break;
case Button.RIGHT: case Button.RIGHT:
// Moves the option cursor right, if possible. // Moves the option cursor right, if possible.
success = this.getActiveChallenge().increaseValue(); success = this.getActiveChallenge().increaseValue();
if (success) { if (success) {
this.updateText(); this.updateText();
} }
break; break;
} }
} }
} }

View File

@ -89,54 +89,54 @@ export default class CommandUiHandler extends UiHandler {
if (button === Button.ACTION) { if (button === Button.ACTION) {
switch (cursor) { switch (cursor) {
// Fight // Fight
case Command.FIGHT: case Command.FIGHT:
if ((this.scene.getCurrentPhase() as CommandPhase).checkFightOverride()) { if ((this.scene.getCurrentPhase() as CommandPhase).checkFightOverride()) {
return true; return true;
} }
ui.setMode(Mode.FIGHT, (this.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); ui.setMode(Mode.FIGHT, (this.scene.getCurrentPhase() as CommandPhase).getFieldIndex());
success = true; success = true;
break; break;
// Ball // Ball
case Command.BALL: case Command.BALL:
ui.setModeWithoutClear(Mode.BALL); ui.setModeWithoutClear(Mode.BALL);
success = true; success = true;
break; break;
// Pokemon // Pokemon
case Command.POKEMON: case Command.POKEMON:
ui.setMode(Mode.PARTY, PartyUiMode.SWITCH, (this.scene.getCurrentPhase() as CommandPhase).getPokemon().getFieldIndex(), null, PartyUiHandler.FilterNonFainted); ui.setMode(Mode.PARTY, PartyUiMode.SWITCH, (this.scene.getCurrentPhase() as CommandPhase).getPokemon().getFieldIndex(), null, PartyUiHandler.FilterNonFainted);
success = true; success = true;
break; break;
// Run // Run
case Command.RUN: case Command.RUN:
(this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.RUN, 0); (this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.RUN, 0);
success = true; success = true;
break; break;
} }
} else { } else {
(this.scene.getCurrentPhase() as CommandPhase).cancel(); (this.scene.getCurrentPhase() as CommandPhase).cancel();
} }
} else { } else {
switch (button) { switch (button) {
case Button.UP: case Button.UP:
if (cursor >= 2) { if (cursor >= 2) {
success = this.setCursor(cursor - 2); success = this.setCursor(cursor - 2);
} }
break; break;
case Button.DOWN: case Button.DOWN:
if (cursor < 2) { if (cursor < 2) {
success = this.setCursor(cursor + 2); success = this.setCursor(cursor + 2);
} }
break; break;
case Button.LEFT: case Button.LEFT:
if (cursor % 2 === 1) { if (cursor % 2 === 1) {
success = this.setCursor(cursor - 1); success = this.setCursor(cursor - 1);
} }
break; break;
case Button.RIGHT: case Button.RIGHT:
if (cursor % 2 === 0) { if (cursor % 2 === 0) {
success = this.setCursor(cursor + 1); success = this.setCursor(cursor + 1);
} }
break; break;
} }
} }

View File

@ -142,13 +142,13 @@ export class DailyRunScoreboard extends Phaser.GameObjects.Container {
entryContainer.add(scoreLabel); entryContainer.add(scoreLabel);
switch (this.category) { switch (this.category) {
case ScoreboardCategory.DAILY: case ScoreboardCategory.DAILY:
const waveLabel = addTextObject(this.scene, 68, 0, wave, TextStyle.WINDOW, { fontSize: "54px" }); const waveLabel = addTextObject(this.scene, 68, 0, wave, TextStyle.WINDOW, { fontSize: "54px" });
entryContainer.add(waveLabel); entryContainer.add(waveLabel);
break; break;
case ScoreboardCategory.WEEKLY: case ScoreboardCategory.WEEKLY:
scoreLabel.x -= 16; scoreLabel.x -= 16;
break; break;
} }
return entryContainer; return entryContainer;

View File

@ -115,18 +115,18 @@ export class DropDownOption extends Phaser.GameObjects.Container {
*/ */
private updateToggleIconColor(): void { private updateToggleIconColor(): void {
switch (this.state) { switch (this.state) {
case DropDownState.ON: case DropDownState.ON:
this.toggle.setTint(this.onColor); this.toggle.setTint(this.onColor);
break; break;
case DropDownState.OFF: case DropDownState.OFF:
this.toggle.setTint(this.offColor); this.toggle.setTint(this.offColor);
break; break;
case DropDownState.EXCLUDE: case DropDownState.EXCLUDE:
this.toggle.setTint(this.excludeColor); this.toggle.setTint(this.excludeColor);
break; break;
case DropDownState.UNLOCKABLE: case DropDownState.UNLOCKABLE:
this.toggle.setTint(this.unlockableColor); this.toggle.setTint(this.unlockableColor);
break; break;
} }
} }
@ -500,18 +500,18 @@ export class DropDown extends Phaser.GameObjects.Container {
}; };
switch (this.dropDownType) { switch (this.dropDownType) {
case DropDownType.MULTI: case DropDownType.MULTI:
case DropDownType.RADIAL: case DropDownType.RADIAL:
return compareValues([ "val", "state" ]); return compareValues([ "val", "state" ]);
case DropDownType.HYBRID: case DropDownType.HYBRID:
return compareValues([ "val", "state", "cursor" ]); return compareValues([ "val", "state", "cursor" ]);
case DropDownType.SINGLE: case DropDownType.SINGLE:
return compareValues([ "val", "state", "dir" ]); return compareValues([ "val", "state", "dir" ]);
default: default:
return false; return false;
} }
} }

View File

@ -127,47 +127,47 @@ export default class EggGachaUiHandler extends MessageUiHandler {
gachaInfoContainer.add(gachaUpLabel); gachaInfoContainer.add(gachaUpLabel);
switch (gachaType as GachaType) { switch (gachaType as GachaType) {
case GachaType.LEGENDARY: case GachaType.LEGENDARY:
if ([ "de", "es" ].includes(currentLanguage)) { if ([ "de", "es" ].includes(currentLanguage)) {
gachaUpLabel.setAlign("center"); gachaUpLabel.setAlign("center");
gachaUpLabel.setY(0); gachaUpLabel.setY(0);
} }
if ([ "pt-BR" ].includes(currentLanguage)) { if ([ "pt-BR" ].includes(currentLanguage)) {
gachaUpLabel.setX(legendaryLabelX - 2); gachaUpLabel.setX(legendaryLabelX - 2);
} else { } else {
gachaUpLabel.setX(legendaryLabelX); gachaUpLabel.setX(legendaryLabelX);
} }
gachaUpLabel.setY(legendaryLabelY); gachaUpLabel.setY(legendaryLabelY);
const pokemonIcon = this.scene.add.sprite(pokemonIconX, pokemonIconY, "pokemon_icons_0"); const pokemonIcon = this.scene.add.sprite(pokemonIconX, pokemonIconY, "pokemon_icons_0");
if ([ "pt-BR" ].includes(currentLanguage)) { if ([ "pt-BR" ].includes(currentLanguage)) {
pokemonIcon.setX(pokemonIconX - 2); pokemonIcon.setX(pokemonIconX - 2);
} }
pokemonIcon.setScale(0.5); pokemonIcon.setScale(0.5);
pokemonIcon.setOrigin(0, 0.5); pokemonIcon.setOrigin(0, 0.5);
gachaInfoContainer.add(pokemonIcon); gachaInfoContainer.add(pokemonIcon);
break; break;
case GachaType.MOVE: case GachaType.MOVE:
if ([ "de", "es", "fr", "pt-BR" ].includes(currentLanguage)) { if ([ "de", "es", "fr", "pt-BR" ].includes(currentLanguage)) {
gachaUpLabel.setAlign("center"); gachaUpLabel.setAlign("center");
gachaUpLabel.setY(0); gachaUpLabel.setY(0);
} }
gachaUpLabel.setText(i18next.t("egg:moveUPGacha")); gachaUpLabel.setText(i18next.t("egg:moveUPGacha"));
gachaUpLabel.setX(0); gachaUpLabel.setX(0);
gachaUpLabel.setOrigin(0.5, 0); gachaUpLabel.setOrigin(0.5, 0);
break; break;
case GachaType.SHINY: case GachaType.SHINY:
if ([ "de", "fr", "ko" ].includes(currentLanguage)) { if ([ "de", "fr", "ko" ].includes(currentLanguage)) {
gachaUpLabel.setAlign("center"); gachaUpLabel.setAlign("center");
gachaUpLabel.setY(0); gachaUpLabel.setY(0);
} }
gachaUpLabel.setText(i18next.t("egg:shinyUPGacha")); gachaUpLabel.setText(i18next.t("egg:shinyUPGacha"));
gachaUpLabel.setX(0); gachaUpLabel.setX(0);
gachaUpLabel.setOrigin(0.5, 0); gachaUpLabel.setOrigin(0.5, 0);
break; break;
} }
const gachaKnob = this.scene.add.sprite(191, 89, "gacha_knob"); const gachaKnob = this.scene.add.sprite(191, 89, "gacha_knob");
@ -470,12 +470,12 @@ export default class EggGachaUiHandler extends MessageUiHandler {
getGuaranteedEggTierFromPullCount(pullCount: number): EggTier { getGuaranteedEggTierFromPullCount(pullCount: number): EggTier {
switch (pullCount) { switch (pullCount) {
case 10: case 10:
return EggTier.RARE; return EggTier.RARE;
case 25: case 25:
return EggTier.EPIC; return EggTier.EPIC;
default: default:
return EggTier.COMMON; return EggTier.COMMON;
} }
} }
@ -567,11 +567,11 @@ export default class EggGachaUiHandler extends MessageUiHandler {
updateGachaInfo(gachaType: GachaType): void { updateGachaInfo(gachaType: GachaType): void {
const infoContainer = this.gachaInfoContainers[gachaType]; const infoContainer = this.gachaInfoContainers[gachaType];
switch (gachaType as GachaType) { switch (gachaType as GachaType) {
case GachaType.LEGENDARY: case GachaType.LEGENDARY:
const species = getPokemonSpecies(getLegendaryGachaSpeciesForTimestamp(this.scene, new Date().getTime())); const species = getPokemonSpecies(getLegendaryGachaSpeciesForTimestamp(this.scene, new Date().getTime()));
const pokemonIcon = infoContainer.getAt(1) as Phaser.GameObjects.Sprite; const pokemonIcon = infoContainer.getAt(1) as Phaser.GameObjects.Sprite;
pokemonIcon.setTexture(species.getIconAtlasKey(), species.getIconId(false)); pokemonIcon.setTexture(species.getIconAtlasKey(), species.getIconId(false));
break; break;
} }
} }
@ -638,106 +638,106 @@ export default class EggGachaUiHandler extends MessageUiHandler {
} }
} else { } else {
switch (button) { switch (button) {
case Button.ACTION: case Button.ACTION:
switch (this.cursor) { switch (this.cursor) {
case 0: case 0:
if (!this.scene.gameData.voucherCounts[VoucherType.REGULAR] && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) { if (!this.scene.gameData.voucherCounts[VoucherType.REGULAR] && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) {
error = true; error = true;
this.showError(i18next.t("egg:notEnoughVouchers")); this.showError(i18next.t("egg:notEnoughVouchers"));
} else if (this.scene.gameData.eggs.length < 99 || Overrides.UNLIMITED_EGG_COUNT_OVERRIDE) { } else if (this.scene.gameData.eggs.length < 99 || Overrides.UNLIMITED_EGG_COUNT_OVERRIDE) {
if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) { if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) {
this.consumeVouchers(VoucherType.REGULAR, 1); this.consumeVouchers(VoucherType.REGULAR, 1);
} }
this.pull(); this.pull();
success = true; success = true;
} else { } else {
error = true; error = true;
this.showError(i18next.t("egg:tooManyEggs")); this.showError(i18next.t("egg:tooManyEggs"));
} }
break; break;
case 2: case 2:
if (!this.scene.gameData.voucherCounts[VoucherType.PLUS] && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) { if (!this.scene.gameData.voucherCounts[VoucherType.PLUS] && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) {
error = true; error = true;
this.showError(i18next.t("egg:notEnoughVouchers")); this.showError(i18next.t("egg:notEnoughVouchers"));
} else if (this.scene.gameData.eggs.length < 95 || Overrides.UNLIMITED_EGG_COUNT_OVERRIDE) { } else if (this.scene.gameData.eggs.length < 95 || Overrides.UNLIMITED_EGG_COUNT_OVERRIDE) {
if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) { if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) {
this.consumeVouchers(VoucherType.PLUS, 1); this.consumeVouchers(VoucherType.PLUS, 1);
} }
this.pull(5); this.pull(5);
success = true; success = true;
} else { } else {
error = true; error = true;
this.showError(i18next.t("egg:tooManyEggs")); this.showError(i18next.t("egg:tooManyEggs"));
} }
break; break;
case 1: case 1:
case 3: case 3:
if ((this.cursor === 1 && this.scene.gameData.voucherCounts[VoucherType.REGULAR] < 10 && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) if ((this.cursor === 1 && this.scene.gameData.voucherCounts[VoucherType.REGULAR] < 10 && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE)
|| (this.cursor === 3 && !this.scene.gameData.voucherCounts[VoucherType.PREMIUM] && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE)) { || (this.cursor === 3 && !this.scene.gameData.voucherCounts[VoucherType.PREMIUM] && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE)) {
error = true; error = true;
this.showError(i18next.t("egg:notEnoughVouchers")); this.showError(i18next.t("egg:notEnoughVouchers"));
} else if (this.scene.gameData.eggs.length < 90 || Overrides.UNLIMITED_EGG_COUNT_OVERRIDE) { } else if (this.scene.gameData.eggs.length < 90 || Overrides.UNLIMITED_EGG_COUNT_OVERRIDE) {
if (this.cursor === 3) { if (this.cursor === 3) {
if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) { if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) {
this.consumeVouchers(VoucherType.PREMIUM, 1); this.consumeVouchers(VoucherType.PREMIUM, 1);
}
} else {
if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) {
this.consumeVouchers(VoucherType.REGULAR, 10);
}
}
this.pull(10);
success = true;
} else {
error = true;
this.showError(i18next.t("egg:tooManyEggs"));
} }
} else { break;
if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) { case 4:
this.consumeVouchers(VoucherType.REGULAR, 10); if (!this.scene.gameData.voucherCounts[VoucherType.GOLDEN] && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) {
error = true;
this.showError(i18next.t("egg:notEnoughVouchers"));
} else if (this.scene.gameData.eggs.length < 75 || Overrides.UNLIMITED_EGG_COUNT_OVERRIDE) {
if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) {
this.consumeVouchers(VoucherType.GOLDEN, 1);
}
this.pull(25);
success = true;
} else {
error = true;
this.showError(i18next.t("egg:tooManyEggs"));
} }
} break;
this.pull(10); case 5:
success = true; ui.revertMode();
} else { success = true;
error = true; break;
this.showError(i18next.t("egg:tooManyEggs"));
} }
break; break;
case 4: case Button.CANCEL:
if (!this.scene.gameData.voucherCounts[VoucherType.GOLDEN] && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) { this.getUi().revertMode();
error = true;
this.showError(i18next.t("egg:notEnoughVouchers"));
} else if (this.scene.gameData.eggs.length < 75 || Overrides.UNLIMITED_EGG_COUNT_OVERRIDE) {
if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) {
this.consumeVouchers(VoucherType.GOLDEN, 1);
}
this.pull(25);
success = true;
} else {
error = true;
this.showError(i18next.t("egg:tooManyEggs"));
}
break;
case 5:
ui.revertMode();
success = true; success = true;
break; break;
} case Button.UP:
break; if (this.cursor) {
case Button.CANCEL: success = this.setCursor(this.cursor - 1);
this.getUi().revertMode(); }
success = true; break;
break; case Button.DOWN:
case Button.UP: if (this.cursor < 5) {
if (this.cursor) { success = this.setCursor(this.cursor + 1);
success = this.setCursor(this.cursor - 1); }
} break;
break; case Button.LEFT:
case Button.DOWN: if (this.gachaCursor) {
if (this.cursor < 5) { success = this.setGachaCursor(this.gachaCursor - 1);
success = this.setCursor(this.cursor + 1); }
} break;
break; case Button.RIGHT:
case Button.LEFT: if (this.gachaCursor < Utils.getEnumKeys(GachaType).length - 1) {
if (this.gachaCursor) { success = this.setGachaCursor(this.gachaCursor + 1);
success = this.setGachaCursor(this.gachaCursor - 1); }
} break;
break;
case Button.RIGHT:
if (this.gachaCursor < Utils.getEnumKeys(GachaType).length - 1) {
success = this.setGachaCursor(this.gachaCursor + 1);
}
break;
} }
} }
} }

View File

@ -152,26 +152,26 @@ export default class FightUiHandler extends UiHandler implements InfoToggle {
} }
} else { } else {
switch (button) { switch (button) {
case Button.UP: case Button.UP:
if (cursor >= 2) { if (cursor >= 2) {
success = this.setCursor(cursor - 2); success = this.setCursor(cursor - 2);
} }
break; break;
case Button.DOWN: case Button.DOWN:
if (cursor < 2) { if (cursor < 2) {
success = this.setCursor(cursor + 2); success = this.setCursor(cursor + 2);
} }
break; break;
case Button.LEFT: case Button.LEFT:
if (cursor % 2 === 1) { if (cursor % 2 === 1) {
success = this.setCursor(cursor - 1); success = this.setCursor(cursor - 1);
} }
break; break;
case Button.RIGHT: case Button.RIGHT:
if (cursor % 2 === 0) { if (cursor % 2 === 0) {
success = this.setCursor(cursor + 1); success = this.setCursor(cursor + 1);
} }
break; break;
} }
} }

View File

@ -351,16 +351,16 @@ export default class GameStatsUiHandler extends UiHandler {
this.scene.ui.revertMode(); this.scene.ui.revertMode();
} else { } else {
switch (button) { switch (button) {
case Button.UP: case Button.UP:
if (this.cursor) { if (this.cursor) {
success = this.setCursor(this.cursor - 1); success = this.setCursor(this.cursor - 1);
} }
break; break;
case Button.DOWN: case Button.DOWN:
if (this.cursor < Math.ceil((Object.keys(displayStats).length - 18) / 2)) { if (this.cursor < Math.ceil((Object.keys(displayStats).length - 18) / 2)) {
success = this.setCursor(this.cursor + 1); success = this.setCursor(this.cursor + 1);
} }
break; break;
} }
} }

View File

@ -97,18 +97,18 @@ export default class LoginFormUiHandler extends FormModalUiHandler {
error = error.slice(0, colonIndex); error = error.slice(0, colonIndex);
} }
switch (error) { switch (error) {
case this.ERR_USERNAME: case this.ERR_USERNAME:
return i18next.t("menu:invalidLoginUsername"); return i18next.t("menu:invalidLoginUsername");
case this.ERR_PASSWORD: case this.ERR_PASSWORD:
return i18next.t("menu:invalidLoginPassword"); return i18next.t("menu:invalidLoginPassword");
case this.ERR_ACCOUNT_EXIST: case this.ERR_ACCOUNT_EXIST:
return i18next.t("menu:accountNonExistent"); return i18next.t("menu:accountNonExistent");
case this.ERR_PASSWORD_MATCH: case this.ERR_PASSWORD_MATCH:
return i18next.t("menu:unmatchingPassword"); return i18next.t("menu:unmatchingPassword");
case this.ERR_NO_SAVES: case this.ERR_NO_SAVES:
return i18next.t("menu:noSaves"); return i18next.t("menu:noSaves");
case this.ERR_TOO_MANY_SAVES: case this.ERR_TOO_MANY_SAVES:
return i18next.t("menu:tooManySaves"); return i18next.t("menu:tooManySaves");
} }
return super.getReadableErrorMessage(error); return super.getReadableErrorMessage(error);

View File

@ -468,148 +468,148 @@ export default class MenuUiHandler extends MessageUiHandler {
} }
this.showText("", 0); this.showText("", 0);
switch (adjustedCursor) { switch (adjustedCursor) {
case MenuOptions.GAME_SETTINGS: case MenuOptions.GAME_SETTINGS:
ui.setOverlayMode(Mode.SETTINGS); ui.setOverlayMode(Mode.SETTINGS);
success = true; success = true;
break; break;
case MenuOptions.ACHIEVEMENTS: case MenuOptions.ACHIEVEMENTS:
ui.setOverlayMode(Mode.ACHIEVEMENTS); ui.setOverlayMode(Mode.ACHIEVEMENTS);
success = true; success = true;
break; break;
case MenuOptions.STATS: case MenuOptions.STATS:
ui.setOverlayMode(Mode.GAME_STATS); ui.setOverlayMode(Mode.GAME_STATS);
success = true; success = true;
break; break;
case MenuOptions.RUN_HISTORY: case MenuOptions.RUN_HISTORY:
ui.setOverlayMode(Mode.RUN_HISTORY); ui.setOverlayMode(Mode.RUN_HISTORY);
success = true; success = true;
break; break;
case MenuOptions.EGG_LIST: case MenuOptions.EGG_LIST:
if (this.scene.gameData.eggs.length) { if (this.scene.gameData.eggs.length) {
ui.revertMode();
ui.setOverlayMode(Mode.EGG_LIST);
success = true;
} else {
ui.showText(i18next.t("menuUiHandler:noEggs"), null, () => ui.showText(""), Utils.fixedInt(1500));
error = true;
}
break;
case MenuOptions.EGG_GACHA:
ui.revertMode(); ui.revertMode();
ui.setOverlayMode(Mode.EGG_LIST); ui.setOverlayMode(Mode.EGG_GACHA);
success = true; success = true;
} else { break;
ui.showText(i18next.t("menuUiHandler:noEggs"), null, () => ui.showText(""), Utils.fixedInt(1500)); case MenuOptions.MANAGE_DATA:
error = true; if (!bypassLogin && !this.manageDataConfig.options.some(o => o.label === i18next.t("menuUiHandler:linkDiscord") || o.label === i18next.t("menuUiHandler:unlinkDiscord"))) {
} this.manageDataConfig.options.splice(this.manageDataConfig.options.length - 1, 0,
break; {
case MenuOptions.EGG_GACHA: label: loggedInUser?.discordId === "" ? i18next.t("menuUiHandler:linkDiscord") : i18next.t("menuUiHandler:unlinkDiscord"),
ui.revertMode(); handler: () => {
ui.setOverlayMode(Mode.EGG_GACHA); if (loggedInUser?.discordId === "") {
success = true; const token = Utils.getCookie(Utils.sessionIdKey);
break; const redirectUri = encodeURIComponent(`${import.meta.env.VITE_SERVER_URL}/auth/discord/callback`);
case MenuOptions.MANAGE_DATA: const discordId = import.meta.env.VITE_DISCORD_CLIENT_ID;
if (!bypassLogin && !this.manageDataConfig.options.some(o => o.label === i18next.t("menuUiHandler:linkDiscord") || o.label === i18next.t("menuUiHandler:unlinkDiscord"))) { const discordUrl = `https://discord.com/api/oauth2/authorize?client_id=${discordId}&redirect_uri=${redirectUri}&response_type=code&scope=identify&state=${token}&prompt=none`;
this.manageDataConfig.options.splice(this.manageDataConfig.options.length - 1, 0, window.open(discordUrl, "_self");
{ return true;
label: loggedInUser?.discordId === "" ? i18next.t("menuUiHandler:linkDiscord") : i18next.t("menuUiHandler:unlinkDiscord"), } else {
handler: () => { Utils.apiPost("/auth/discord/logout", undefined, undefined, true).then(res => {
if (loggedInUser?.discordId === "") { if (!res.ok) {
const token = Utils.getCookie(Utils.sessionIdKey); console.error(`Unlink failed (${res.status}: ${res.statusText})`);
const redirectUri = encodeURIComponent(`${import.meta.env.VITE_SERVER_URL}/auth/discord/callback`); }
const discordId = import.meta.env.VITE_DISCORD_CLIENT_ID; updateUserInfo().then(() => this.scene.reset(true, true));
const discordUrl = `https://discord.com/api/oauth2/authorize?client_id=${discordId}&redirect_uri=${redirectUri}&response_type=code&scope=identify&state=${token}&prompt=none`; });
window.open(discordUrl, "_self"); return true;
return true; }
} else {
Utils.apiPost("/auth/discord/logout", undefined, undefined, true).then(res => {
if (!res.ok) {
console.error(`Unlink failed (${res.status}: ${res.statusText})`);
}
updateUserInfo().then(() => this.scene.reset(true, true));
});
return true;
} }
} },
}, {
{ label: loggedInUser?.googleId === "" ? i18next.t("menuUiHandler:linkGoogle") : i18next.t("menuUiHandler:unlinkGoogle"),
label: loggedInUser?.googleId === "" ? i18next.t("menuUiHandler:linkGoogle") : i18next.t("menuUiHandler:unlinkGoogle"), handler: () => {
handler: () => { if (loggedInUser?.googleId === "") {
if (loggedInUser?.googleId === "") { const token = Utils.getCookie(Utils.sessionIdKey);
const token = Utils.getCookie(Utils.sessionIdKey); const redirectUri = encodeURIComponent(`${import.meta.env.VITE_SERVER_URL}/auth/google/callback`);
const redirectUri = encodeURIComponent(`${import.meta.env.VITE_SERVER_URL}/auth/google/callback`); const googleId = import.meta.env.VITE_GOOGLE_CLIENT_ID;
const googleId = import.meta.env.VITE_GOOGLE_CLIENT_ID; const googleUrl = `https://accounts.google.com/o/oauth2/auth?client_id=${googleId}&response_type=code&redirect_uri=${redirectUri}&scope=openid&state=${token}`;
const googleUrl = `https://accounts.google.com/o/oauth2/auth?client_id=${googleId}&response_type=code&redirect_uri=${redirectUri}&scope=openid&state=${token}`; window.open(googleUrl, "_self");
window.open(googleUrl, "_self"); return true;
return true; } else {
} else { Utils.apiPost("/auth/google/logout", undefined, undefined, true).then(res => {
Utils.apiPost("/auth/google/logout", undefined, undefined, true).then(res => { if (!res.ok) {
if (!res.ok) { console.error(`Unlink failed (${res.status}: ${res.statusText})`);
console.error(`Unlink failed (${res.status}: ${res.statusText})`); }
} updateUserInfo().then(() => this.scene.reset(true, true));
updateUserInfo().then(() => this.scene.reset(true, true)); });
}); return true;
return true; }
} }
} });
}); }
} ui.setOverlayMode(Mode.MENU_OPTION_SELECT, this.manageDataConfig);
ui.setOverlayMode(Mode.MENU_OPTION_SELECT, this.manageDataConfig);
success = true;
break;
case MenuOptions.COMMUNITY:
ui.setOverlayMode(Mode.MENU_OPTION_SELECT, this.communityConfig);
success = true;
break;
case MenuOptions.SAVE_AND_QUIT:
if (this.scene.currentBattle) {
success = true; success = true;
const doSaveQuit = () => { break;
ui.setMode(Mode.LOADING, { case MenuOptions.COMMUNITY:
buttonActions: [], fadeOut: () => ui.setOverlayMode(Mode.MENU_OPTION_SELECT, this.communityConfig);
this.scene.gameData.saveAll(this.scene, true, true, true, true).then(() => { success = true;
break;
case MenuOptions.SAVE_AND_QUIT:
if (this.scene.currentBattle) {
success = true;
const doSaveQuit = () => {
ui.setMode(Mode.LOADING, {
buttonActions: [], fadeOut: () =>
this.scene.gameData.saveAll(this.scene, true, true, true, true).then(() => {
this.scene.reset(true); this.scene.reset(true);
}) })
});
};
if (this.scene.currentBattle.turn > 1) {
ui.showText(i18next.t("menuUiHandler:losingProgressionWarning"), null, () => {
if (!this.active) {
this.showText("", 0);
return;
}
ui.setOverlayMode(Mode.CONFIRM, doSaveQuit, () => {
ui.revertMode();
this.showText("", 0);
}, false, -98);
});
} else {
doSaveQuit();
}
} else {
error = true;
}
break;
case MenuOptions.LOG_OUT:
success = true;
const doLogout = () => {
ui.setMode(Mode.LOADING, {
buttonActions: [], fadeOut: () => Utils.apiFetch("account/logout", true).then(res => {
if (!res.ok) {
console.error(`Log out failed (${res.status}: ${res.statusText})`);
}
Utils.removeCookie(Utils.sessionIdKey);
updateUserInfo().then(() => this.scene.reset(true, true));
})
}); });
}; };
if (this.scene.currentBattle.turn > 1) { if (this.scene.currentBattle) {
ui.showText(i18next.t("menuUiHandler:losingProgressionWarning"), null, () => { ui.showText(i18next.t("menuUiHandler:losingProgressionWarning"), null, () => {
if (!this.active) { if (!this.active) {
this.showText("", 0); this.showText("", 0);
return; return;
} }
ui.setOverlayMode(Mode.CONFIRM, doSaveQuit, () => { ui.setOverlayMode(Mode.CONFIRM, doLogout, () => {
ui.revertMode(); ui.revertMode();
this.showText("", 0); this.showText("", 0);
}, false, -98); }, false, -98);
}); });
} else { } else {
doSaveQuit(); doLogout();
} }
} else { break;
error = true;
}
break;
case MenuOptions.LOG_OUT:
success = true;
const doLogout = () => {
ui.setMode(Mode.LOADING, {
buttonActions: [], fadeOut: () => Utils.apiFetch("account/logout", true).then(res => {
if (!res.ok) {
console.error(`Log out failed (${res.status}: ${res.statusText})`);
}
Utils.removeCookie(Utils.sessionIdKey);
updateUserInfo().then(() => this.scene.reset(true, true));
})
});
};
if (this.scene.currentBattle) {
ui.showText(i18next.t("menuUiHandler:losingProgressionWarning"), null, () => {
if (!this.active) {
this.showText("", 0);
return;
}
ui.setOverlayMode(Mode.CONFIRM, doLogout, () => {
ui.revertMode();
this.showText("", 0);
}, false, -98);
});
} else {
doLogout();
}
break;
} }
} else if (button === Button.CANCEL) { } else if (button === Button.CANCEL) {
success = true; success = true;
@ -620,20 +620,20 @@ export default class MenuUiHandler extends MessageUiHandler {
}); });
} else { } else {
switch (button) { switch (button) {
case Button.UP: case Button.UP:
if (this.cursor) { if (this.cursor) {
success = this.setCursor(this.cursor - 1); success = this.setCursor(this.cursor - 1);
} else { } else {
success = this.setCursor(this.menuOptions.length - 1); success = this.setCursor(this.menuOptions.length - 1);
} }
break; break;
case Button.DOWN: case Button.DOWN:
if (this.cursor + 1 < this.menuOptions.length) { if (this.cursor + 1 < this.menuOptions.length) {
success = this.setCursor(this.cursor + 1); success = this.setCursor(this.cursor + 1);
} else { } else {
success = this.setCursor(0); success = this.setCursor(0);
} }
break; break;
} }
} }

View File

@ -56,18 +56,18 @@ export default abstract class MessageUiHandler extends AwaitableUiHandler {
let actionMatch: RegExpExecArray | null; let actionMatch: RegExpExecArray | null;
while ((actionMatch = actionPattern.exec(text))) { while ((actionMatch = actionPattern.exec(text))) {
switch (actionMatch[1]) { switch (actionMatch[1]) {
case "c": case "c":
charVarMap.set(actionMatch.index, actionMatch[2]); charVarMap.set(actionMatch.index, actionMatch[2]);
break; break;
case "d": case "d":
delayMap.set(actionMatch.index, parseInt(actionMatch[2])); delayMap.set(actionMatch.index, parseInt(actionMatch[2]));
break; break;
case "s": case "s":
soundMap.set(actionMatch.index, actionMatch[2]); soundMap.set(actionMatch.index, actionMatch[2]);
break; break;
case "f": case "f":
fadeMap.set(actionMatch.index, parseInt(actionMatch[2])); fadeMap.set(actionMatch.index, parseInt(actionMatch[2]));
break; break;
} }
text = text.slice(0, actionMatch.index) + text.slice(actionMatch.index + actionMatch[2].length + 4); text = text.slice(0, actionMatch.index) + text.slice(actionMatch.index + actionMatch[2].length + 4);
} }

View File

@ -17,6 +17,9 @@ import { IntegerHolder } from "./../utils";
import Phaser from "phaser"; import Phaser from "phaser";
export const SHOP_OPTIONS_ROW_LIMIT = 7; export const SHOP_OPTIONS_ROW_LIMIT = 7;
const SINGLE_SHOP_ROW_YOFFSET = 12;
const DOUBLE_SHOP_ROW_YOFFSET = 24;
const OPTION_BUTTON_YPOSITION = -62;
export default class ModifierSelectUiHandler extends AwaitableUiHandler { export default class ModifierSelectUiHandler extends AwaitableUiHandler {
private modifierContainer: Phaser.GameObjects.Container; private modifierContainer: Phaser.GameObjects.Container;
@ -68,7 +71,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
this.checkButtonWidth = context.measureText(i18next.t("modifierSelectUiHandler:checkTeam")).width; this.checkButtonWidth = context.measureText(i18next.t("modifierSelectUiHandler:checkTeam")).width;
} }
this.transferButtonContainer = this.scene.add.container((this.scene.game.canvas.width - this.checkButtonWidth) / 6 - 21, -64); this.transferButtonContainer = this.scene.add.container((this.scene.game.canvas.width - this.checkButtonWidth) / 6 - 21, OPTION_BUTTON_YPOSITION);
this.transferButtonContainer.setName("transfer-btn"); this.transferButtonContainer.setName("transfer-btn");
this.transferButtonContainer.setVisible(false); this.transferButtonContainer.setVisible(false);
ui.add(this.transferButtonContainer); ui.add(this.transferButtonContainer);
@ -78,7 +81,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
transferButtonText.setOrigin(1, 0); transferButtonText.setOrigin(1, 0);
this.transferButtonContainer.add(transferButtonText); this.transferButtonContainer.add(transferButtonText);
this.checkButtonContainer = this.scene.add.container((this.scene.game.canvas.width) / 6 - 1, -64); this.checkButtonContainer = this.scene.add.container((this.scene.game.canvas.width) / 6 - 1, OPTION_BUTTON_YPOSITION);
this.checkButtonContainer.setName("use-btn"); this.checkButtonContainer.setName("use-btn");
this.checkButtonContainer.setVisible(false); this.checkButtonContainer.setVisible(false);
ui.add(this.checkButtonContainer); ui.add(this.checkButtonContainer);
@ -88,7 +91,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
checkButtonText.setOrigin(1, 0); checkButtonText.setOrigin(1, 0);
this.checkButtonContainer.add(checkButtonText); this.checkButtonContainer.add(checkButtonText);
this.rerollButtonContainer = this.scene.add.container(16, -64); this.rerollButtonContainer = this.scene.add.container(16, OPTION_BUTTON_YPOSITION);
this.rerollButtonContainer.setName("reroll-brn"); this.rerollButtonContainer.setName("reroll-brn");
this.rerollButtonContainer.setVisible(false); this.rerollButtonContainer.setVisible(false);
ui.add(this.rerollButtonContainer); ui.add(this.rerollButtonContainer);
@ -104,7 +107,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
this.rerollCostText.setPositionRelative(rerollButtonText, rerollButtonText.displayWidth + 5, 1); this.rerollCostText.setPositionRelative(rerollButtonText, rerollButtonText.displayWidth + 5, 1);
this.rerollButtonContainer.add(this.rerollCostText); this.rerollButtonContainer.add(this.rerollCostText);
this.lockRarityButtonContainer = this.scene.add.container(16, -64); this.lockRarityButtonContainer = this.scene.add.container(16, OPTION_BUTTON_YPOSITION);
this.lockRarityButtonContainer.setVisible(false); this.lockRarityButtonContainer.setVisible(false);
ui.add(this.lockRarityButtonContainer); ui.add(this.lockRarityButtonContainer);
@ -191,7 +194,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
const shopTypeOptions = !removeHealShop const shopTypeOptions = !removeHealShop
? getPlayerShopModifierTypeOptionsForWave(this.scene.currentBattle.waveIndex, baseShopCost.value) ? getPlayerShopModifierTypeOptionsForWave(this.scene.currentBattle.waveIndex, baseShopCost.value)
: []; : [];
const optionsYOffset = shopTypeOptions.length >= SHOP_OPTIONS_ROW_LIMIT ? -8 : -24; const optionsYOffset = shopTypeOptions.length > SHOP_OPTIONS_ROW_LIMIT ? -SINGLE_SHOP_ROW_YOFFSET : -DOUBLE_SHOP_ROW_YOFFSET;
for (let m = 0; m < typeOptions.length; m++) { for (let m = 0; m < typeOptions.length; m++) {
const sliceWidth = (this.scene.game.canvas.width / 6) / (typeOptions.length + 2); const sliceWidth = (this.scene.game.canvas.width / 6) / (typeOptions.length + 2);
@ -212,7 +215,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
const col = m < SHOP_OPTIONS_ROW_LIMIT ? m : m - SHOP_OPTIONS_ROW_LIMIT; const col = m < SHOP_OPTIONS_ROW_LIMIT ? m : m - SHOP_OPTIONS_ROW_LIMIT;
const rowOptions = shopTypeOptions.slice(row ? SHOP_OPTIONS_ROW_LIMIT : 0, row ? undefined : SHOP_OPTIONS_ROW_LIMIT); const rowOptions = shopTypeOptions.slice(row ? SHOP_OPTIONS_ROW_LIMIT : 0, row ? undefined : SHOP_OPTIONS_ROW_LIMIT);
const sliceWidth = (this.scene.game.canvas.width / 6) / (rowOptions.length + 2); const sliceWidth = (this.scene.game.canvas.width / 6) / (rowOptions.length + 2);
const option = new ModifierOption(this.scene, sliceWidth * (col + 1) + (sliceWidth * 0.5), ((-this.scene.game.canvas.height / 12) - (this.scene.game.canvas.height / 32) - (40 - (28 * row - 1))), shopTypeOptions[m]); const option = new ModifierOption(this.scene, sliceWidth * (col + 1) + (sliceWidth * 0.5), ((-this.scene.game.canvas.height / 12) - (this.scene.game.canvas.height / 32) - (42 - (28 * row - 1))), shopTypeOptions[m]);
option.setScale(0.375); option.setScale(0.375);
this.scene.add.existing(option); this.scene.add.existing(option);
this.modifierContainer.add(option); this.modifierContainer.add(option);
@ -354,79 +357,79 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
} }
} else { } else {
switch (button) { switch (button) {
case Button.UP: case Button.UP:
if (this.rowCursor === 0 && this.cursor === 3) { if (this.rowCursor === 0 && this.cursor === 3) {
success = this.setCursor(0); success = this.setCursor(0);
} else if (this.rowCursor < this.shopOptionsRows.length + 1) { } else if (this.rowCursor < this.shopOptionsRows.length + 1) {
success = this.setRowCursor(this.rowCursor + 1); success = this.setRowCursor(this.rowCursor + 1);
}
break;
case Button.DOWN:
if (this.rowCursor) {
success = this.setRowCursor(this.rowCursor - 1);
} else if (this.lockRarityButtonContainer.visible && this.cursor === 0) {
success = this.setCursor(3);
}
break;
case Button.LEFT:
if (!this.rowCursor) {
switch (this.cursor) {
case 0:
success = false;
break;
case 1:
if (this.lockRarityButtonContainer.visible) {
success = this.setCursor(3);
} else {
success = this.rerollButtonContainer.visible && this.setCursor(0);
}
break;
case 2:
if (this.transferButtonContainer.visible) {
success = this.setCursor(1);
} else if (this.rerollButtonContainer.visible) {
success = this.setCursor(0);
} else {
success = false;
}
break;
} }
} else if (this.cursor) { break;
success = this.setCursor(this.cursor - 1); case Button.DOWN:
} else if (this.rowCursor === 1 && this.rerollButtonContainer.visible) { if (this.rowCursor) {
success = this.setRowCursor(0); success = this.setRowCursor(this.rowCursor - 1);
} } else if (this.lockRarityButtonContainer.visible && this.cursor === 0) {
break; success = this.setCursor(3);
case Button.RIGHT:
if (!this.rowCursor) {
switch (this.cursor) {
case 0:
if (this.transferButtonContainer.visible) {
success = this.setCursor(1);
} else {
success = this.setCursor(2);
}
break;
case 1:
success = this.setCursor(2);
break;
case 2:
success = false;
break;
case 3:
if (this.transferButtonContainer.visible) {
success = this.setCursor(1);
} else {
success = this.setCursor(2);
}
break;
} }
} else if (this.cursor < this.getRowItems(this.rowCursor) - 1) { break;
success = this.setCursor(this.cursor + 1); case Button.LEFT:
} else if (this.rowCursor === 1 && this.transferButtonContainer.visible) { if (!this.rowCursor) {
success = this.setRowCursor(0); switch (this.cursor) {
} case 0:
break; success = false;
break;
case 1:
if (this.lockRarityButtonContainer.visible) {
success = this.setCursor(3);
} else {
success = this.rerollButtonContainer.visible && this.setCursor(0);
}
break;
case 2:
if (this.transferButtonContainer.visible) {
success = this.setCursor(1);
} else if (this.rerollButtonContainer.visible) {
success = this.setCursor(0);
} else {
success = false;
}
break;
}
} else if (this.cursor) {
success = this.setCursor(this.cursor - 1);
} else if (this.rowCursor === 1 && this.rerollButtonContainer.visible) {
success = this.setRowCursor(0);
}
break;
case Button.RIGHT:
if (!this.rowCursor) {
switch (this.cursor) {
case 0:
if (this.transferButtonContainer.visible) {
success = this.setCursor(1);
} else {
success = this.setCursor(2);
}
break;
case 1:
success = this.setCursor(2);
break;
case 2:
success = false;
break;
case 3:
if (this.transferButtonContainer.visible) {
success = this.setCursor(1);
} else {
success = this.setCursor(2);
}
break;
}
} else if (this.cursor < this.getRowItems(this.rowCursor) - 1) {
success = this.setCursor(this.cursor + 1);
} else if (this.rowCursor === 1 && this.transferButtonContainer.visible) {
success = this.setRowCursor(0);
}
break;
} }
} }
@ -456,16 +459,18 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
if (this.rowCursor === 1 && options.length === 0) { if (this.rowCursor === 1 && options.length === 0) {
// Continue button when no shop items // Continue button when no shop items
this.cursorObj.setScale(1.25); this.cursorObj.setScale(1.25);
this.cursorObj.setPosition((this.scene.game.canvas.width / 18) + 23, (-this.scene.game.canvas.height / 12) - (this.shopOptionsRows.length > 1 ? 6 : 22)); this.cursorObj.setPosition((this.scene.game.canvas.width / 18) + 23, (-this.scene.game.canvas.height / 12) - (this.shopOptionsRows.length > 1 ? SINGLE_SHOP_ROW_YOFFSET - 2 : DOUBLE_SHOP_ROW_YOFFSET - 2));
ui.showText(i18next.t("modifierSelectUiHandler:continueNextWaveDescription")); ui.showText(i18next.t("modifierSelectUiHandler:continueNextWaveDescription"));
return ret; return ret;
} }
const sliceWidth = (this.scene.game.canvas.width / 6) / (options.length + 2); const sliceWidth = (this.scene.game.canvas.width / 6) / (options.length + 2);
if (this.rowCursor < 2) { if (this.rowCursor < 2) {
this.cursorObj.setPosition(sliceWidth * (cursor + 1) + (sliceWidth * 0.5) - 20, (-this.scene.game.canvas.height / 12) - (this.shopOptionsRows.length > 1 ? 6 : 22)); // Cursor on free items
this.cursorObj.setPosition(sliceWidth * (cursor + 1) + (sliceWidth * 0.5) - 20, (-this.scene.game.canvas.height / 12) - (this.shopOptionsRows.length > 1 ? SINGLE_SHOP_ROW_YOFFSET - 2 : DOUBLE_SHOP_ROW_YOFFSET - 2));
} else { } else {
this.cursorObj.setPosition(sliceWidth * (cursor + 1) + (sliceWidth * 0.5) - 16, (-this.scene.game.canvas.height / 12 - this.scene.game.canvas.height / 32) - (-16 + 28 * (this.rowCursor - (this.shopOptionsRows.length - 1)))); // Cursor on paying items
this.cursorObj.setPosition(sliceWidth * (cursor + 1) + (sliceWidth * 0.5) - 16, (-this.scene.game.canvas.height / 12 - this.scene.game.canvas.height / 32) - (-14 + 28 * (this.rowCursor - (this.shopOptionsRows.length - 1))));
} }
const type = options[this.cursor].modifierTypeOption.type; const type = options[this.cursor].modifierTypeOption.type;
@ -475,16 +480,16 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
this.moveInfoOverlay.show(allMoves[type.moveId]); this.moveInfoOverlay.show(allMoves[type.moveId]);
} }
} else if (cursor === 0) { } else if (cursor === 0) {
this.cursorObj.setPosition(6, this.lockRarityButtonContainer.visible ? -72 : -60); this.cursorObj.setPosition(6, this.lockRarityButtonContainer.visible ? OPTION_BUTTON_YPOSITION - 8 : OPTION_BUTTON_YPOSITION + 4);
ui.showText(i18next.t("modifierSelectUiHandler:rerollDesc")); ui.showText(i18next.t("modifierSelectUiHandler:rerollDesc"));
} else if (cursor === 1) { } else if (cursor === 1) {
this.cursorObj.setPosition((this.scene.game.canvas.width - this.transferButtonWidth - this.checkButtonWidth) / 6 - 30, -60); this.cursorObj.setPosition((this.scene.game.canvas.width - this.transferButtonWidth - this.checkButtonWidth) / 6 - 30, OPTION_BUTTON_YPOSITION + 4);
ui.showText(i18next.t("modifierSelectUiHandler:transferDesc")); ui.showText(i18next.t("modifierSelectUiHandler:transferDesc"));
} else if (cursor === 2) { } else if (cursor === 2) {
this.cursorObj.setPosition((this.scene.game.canvas.width - this.checkButtonWidth) / 6 - 10, -60); this.cursorObj.setPosition((this.scene.game.canvas.width - this.checkButtonWidth) / 6 - 10, OPTION_BUTTON_YPOSITION + 4);
ui.showText(i18next.t("modifierSelectUiHandler:checkTeamDesc")); ui.showText(i18next.t("modifierSelectUiHandler:checkTeamDesc"));
} else { } else {
this.cursorObj.setPosition(6, -60); this.cursorObj.setPosition(6, OPTION_BUTTON_YPOSITION + 4);
ui.showText(i18next.t("modifierSelectUiHandler:lockRaritiesDesc")); ui.showText(i18next.t("modifierSelectUiHandler:lockRaritiesDesc"));
} }
@ -522,12 +527,12 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
private getRowItems(rowCursor: integer): integer { private getRowItems(rowCursor: integer): integer {
switch (rowCursor) { switch (rowCursor) {
case 0: case 0:
return 3; return 3;
case 1: case 1:
return this.options.length; return this.options.length;
default: default:
return this.shopOptionsRows[this.shopOptionsRows.length - (rowCursor - 1)].length; return this.shopOptionsRows[this.shopOptionsRows.length - (rowCursor - 1)].length;
} }
} }

View File

@ -159,16 +159,16 @@ export default class MysteryEncounterUiHandler extends UiHandler {
} }
} else { } else {
switch (this.optionsContainer.getAll()?.length) { switch (this.optionsContainer.getAll()?.length) {
default: default:
case 3: case 3:
success = this.handleTwoOptionMoveInput(button); success = this.handleTwoOptionMoveInput(button);
break; break;
case 4: case 4:
success = this.handleThreeOptionMoveInput(button); success = this.handleThreeOptionMoveInput(button);
break; break;
case 5: case 5:
success = this.handleFourOptionMoveInput(button); success = this.handleFourOptionMoveInput(button);
break; break;
} }
this.displayOptionTooltip(); this.displayOptionTooltip();
@ -185,26 +185,26 @@ export default class MysteryEncounterUiHandler extends UiHandler {
let success = false; let success = false;
const cursor = this.getCursor(); const cursor = this.getCursor();
switch (button) { switch (button) {
case Button.UP: case Button.UP:
if (cursor < this.viewPartyIndex) { if (cursor < this.viewPartyIndex) {
success = this.setCursor(this.viewPartyIndex); success = this.setCursor(this.viewPartyIndex);
} }
break; break;
case Button.DOWN: case Button.DOWN:
if (cursor === this.viewPartyIndex) { if (cursor === this.viewPartyIndex) {
success = this.setCursor(1); success = this.setCursor(1);
} }
break; break;
case Button.LEFT: case Button.LEFT:
if (cursor > 0) { if (cursor > 0) {
success = this.setCursor(cursor - 1); success = this.setCursor(cursor - 1);
} }
break; break;
case Button.RIGHT: case Button.RIGHT:
if (cursor < this.viewPartyIndex) { if (cursor < this.viewPartyIndex) {
success = this.setCursor(cursor + 1); success = this.setCursor(cursor + 1);
} }
break; break;
} }
return success; return success;
@ -214,34 +214,34 @@ export default class MysteryEncounterUiHandler extends UiHandler {
let success = false; let success = false;
const cursor = this.getCursor(); const cursor = this.getCursor();
switch (button) { switch (button) {
case Button.UP: case Button.UP:
if (cursor === 2) { if (cursor === 2) {
success = this.setCursor(cursor - 2); success = this.setCursor(cursor - 2);
} else { } else {
success = this.setCursor(this.viewPartyIndex); success = this.setCursor(this.viewPartyIndex);
} }
break; break;
case Button.DOWN: case Button.DOWN:
if (cursor === this.viewPartyIndex) { if (cursor === this.viewPartyIndex) {
success = this.setCursor(1); success = this.setCursor(1);
} else { } else {
success = this.setCursor(2); success = this.setCursor(2);
} }
break; break;
case Button.LEFT: case Button.LEFT:
if (cursor === this.viewPartyIndex) { if (cursor === this.viewPartyIndex) {
success = this.setCursor(1); success = this.setCursor(1);
} else if (cursor === 1) { } else if (cursor === 1) {
success = this.setCursor(cursor - 1); success = this.setCursor(cursor - 1);
} }
break; break;
case Button.RIGHT: case Button.RIGHT:
if (cursor === 1) { if (cursor === 1) {
success = this.setCursor(this.viewPartyIndex); success = this.setCursor(this.viewPartyIndex);
} else if (cursor < 1) { } else if (cursor < 1) {
success = this.setCursor(cursor + 1); success = this.setCursor(cursor + 1);
} }
break; break;
} }
return success; return success;
@ -251,34 +251,34 @@ export default class MysteryEncounterUiHandler extends UiHandler {
let success = false; let success = false;
const cursor = this.getCursor(); const cursor = this.getCursor();
switch (button) { switch (button) {
case Button.UP: case Button.UP:
if (cursor >= 2 && cursor !== this.viewPartyIndex) { if (cursor >= 2 && cursor !== this.viewPartyIndex) {
success = this.setCursor(cursor - 2); success = this.setCursor(cursor - 2);
} else { } else {
success = this.setCursor(this.viewPartyIndex); success = this.setCursor(this.viewPartyIndex);
} }
break; break;
case Button.DOWN: case Button.DOWN:
if (cursor <= 1) { if (cursor <= 1) {
success = this.setCursor(cursor + 2); success = this.setCursor(cursor + 2);
} else if (cursor === this.viewPartyIndex) { } else if (cursor === this.viewPartyIndex) {
success = this.setCursor(1); success = this.setCursor(1);
} }
break; break;
case Button.LEFT: case Button.LEFT:
if (cursor === this.viewPartyIndex) { if (cursor === this.viewPartyIndex) {
success = this.setCursor(1); success = this.setCursor(1);
} else if (cursor % 2 === 1) { } else if (cursor % 2 === 1) {
success = this.setCursor(cursor - 1); success = this.setCursor(cursor - 1);
} }
break; break;
case Button.RIGHT: case Button.RIGHT:
if (cursor === 1) { if (cursor === 1) {
success = this.setCursor(this.viewPartyIndex); success = this.setCursor(this.viewPartyIndex);
} else if (cursor % 2 === 0 && cursor !== this.viewPartyIndex) { } else if (cursor % 2 === 0 && cursor !== this.viewPartyIndex) {
success = this.setCursor(cursor + 1); success = this.setCursor(cursor + 1);
} }
break; break;
} }
return success; return success;
@ -351,16 +351,16 @@ export default class MysteryEncounterUiHandler extends UiHandler {
let optionText: BBCodeText; let optionText: BBCodeText;
switch (this.encounterOptions.length) { switch (this.encounterOptions.length) {
default: default:
case 2: case 2:
optionText = addBBCodeTextObject(this.scene, i % 2 === 0 ? 0 : 100, 8, "-", TextStyle.WINDOW, { fontSize: "80px", lineSpacing: -8 }); optionText = addBBCodeTextObject(this.scene, i % 2 === 0 ? 0 : 100, 8, "-", TextStyle.WINDOW, { fontSize: "80px", lineSpacing: -8 });
break; break;
case 3: case 3:
optionText = addBBCodeTextObject(this.scene, i % 2 === 0 ? 0 : 100, i < 2 ? 0 : 16, "-", TextStyle.WINDOW, { fontSize: "80px", lineSpacing: -8 }); optionText = addBBCodeTextObject(this.scene, i % 2 === 0 ? 0 : 100, i < 2 ? 0 : 16, "-", TextStyle.WINDOW, { fontSize: "80px", lineSpacing: -8 });
break; break;
case 4: case 4:
optionText = addBBCodeTextObject(this.scene, i % 2 === 0 ? 0 : 100, i < 2 ? 0 : 16, "-", TextStyle.WINDOW, { fontSize: "80px", lineSpacing: -8 }); optionText = addBBCodeTextObject(this.scene, i % 2 === 0 ? 0 : 100, i < 2 ? 0 : 16, "-", TextStyle.WINDOW, { fontSize: "80px", lineSpacing: -8 });
break; break;
} }
this.optionsMeetsReqs.push(option.meetsRequirements(this.scene)); this.optionsMeetsReqs.push(option.meetsRequirements(this.scene));

View File

@ -1,47 +0,0 @@
import BattleScene from "../battle-scene";
import { ModalConfig, ModalUiHandler } from "./modal-ui-handler";
import { addTextObject, TextStyle } from "./text";
import { Mode } from "./ui";
export default class OutdatedModalUiHandler extends ModalUiHandler {
constructor(scene: BattleScene, mode: Mode | null = null) {
super(scene, mode);
}
getModalTitle(): string {
return "";
}
getWidth(): number {
return 160;
}
getHeight(): number {
return 64;
}
getMargin(): [number, number, number, number] {
return [ 0, 0, 48, 0 ];
}
getButtonLabels(): string[] {
return [ ];
}
setup(): void {
super.setup();
const label = addTextObject(this.scene, this.getWidth() / 2, this.getHeight() / 2, "Your client is currently outdated.\nPlease reload to update the game.\n\nIf this error persists, please clear your browser cache.", TextStyle.WINDOW, { fontSize: "48px", align: "center" });
label.setOrigin(0.5, 0.5);
this.modalContainer.add(label);
}
show(args: any[]): boolean {
const config: ModalConfig = {
buttonActions: []
};
return super.show([ config ]);
}
}

View File

@ -539,42 +539,42 @@ export default class PartyUiHandler extends MessageUiHandler {
return true; return true;
} else { } else {
switch (button) { switch (button) {
case Button.LEFT: case Button.LEFT:
/** Decrease quantity for the current item and update UI */ /** Decrease quantity for the current item and update UI */
if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) { if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) {
this.transferQuantities[option] = this.transferQuantities[option] === 1 ? this.transferQuantitiesMax[option] : this.transferQuantities[option] - 1; this.transferQuantities[option] = this.transferQuantities[option] === 1 ? this.transferQuantitiesMax[option] : this.transferQuantities[option] - 1;
this.updateOptions(); this.updateOptions();
success = this.setCursor(this.optionsCursor); /** Place again the cursor at the same position. Necessary, otherwise the cursor disappears */ success = this.setCursor(this.optionsCursor); /** Place again the cursor at the same position. Necessary, otherwise the cursor disappears */
} }
break; break;
case Button.RIGHT: case Button.RIGHT:
/** Increase quantity for the current item and update UI */ /** Increase quantity for the current item and update UI */
if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) { if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) {
this.transferQuantities[option] = this.transferQuantities[option] === this.transferQuantitiesMax[option] ? 1 : this.transferQuantities[option] + 1; this.transferQuantities[option] = this.transferQuantities[option] === this.transferQuantitiesMax[option] ? 1 : this.transferQuantities[option] + 1;
this.updateOptions(); this.updateOptions();
success = this.setCursor(this.optionsCursor); /** Place again the cursor at the same position. Necessary, otherwise the cursor disappears */ success = this.setCursor(this.optionsCursor); /** Place again the cursor at the same position. Necessary, otherwise the cursor disappears */
}
break;
case Button.UP:
/** If currently selecting items to transfer, reset quantity selection */
if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) {
if (option !== PartyOption.ALL) {
this.transferQuantities[option] = this.transferQuantitiesMax[option];
} }
this.updateOptions(); break;
} case Button.UP:
success = this.setCursor(this.optionsCursor ? this.optionsCursor - 1 : this.options.length - 1); /** Move cursor */
break;
case Button.DOWN:
/** If currently selecting items to transfer, reset quantity selection */ /** If currently selecting items to transfer, reset quantity selection */
if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) { if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) {
if (option !== PartyOption.ALL) { if (option !== PartyOption.ALL) {
this.transferQuantities[option] = this.transferQuantitiesMax[option]; this.transferQuantities[option] = this.transferQuantitiesMax[option];
}
this.updateOptions();
} }
this.updateOptions(); success = this.setCursor(this.optionsCursor ? this.optionsCursor - 1 : this.options.length - 1); /** Move cursor */
} break;
success = this.setCursor(this.optionsCursor < this.options.length - 1 ? this.optionsCursor + 1 : 0); /** Move cursor */ case Button.DOWN:
break; /** If currently selecting items to transfer, reset quantity selection */
if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) {
if (option !== PartyOption.ALL) {
this.transferQuantities[option] = this.transferQuantitiesMax[option];
}
this.updateOptions();
}
success = this.setCursor(this.optionsCursor < this.options.length - 1 ? this.optionsCursor + 1 : 0); /** Move cursor */
break;
} }
// show move description // show move description
@ -631,28 +631,28 @@ export default class PartyUiHandler extends MessageUiHandler {
const battlerCount = this.scene.currentBattle.getBattlerCount(); const battlerCount = this.scene.currentBattle.getBattlerCount();
switch (button) { switch (button) {
case Button.UP: case Button.UP:
success = this.setCursor(this.cursor ? this.cursor < 6 ? this.cursor - 1 : slotCount - 1 : 6); success = this.setCursor(this.cursor ? this.cursor < 6 ? this.cursor - 1 : slotCount - 1 : 6);
break;
case Button.DOWN:
success = this.setCursor(this.cursor < 6 ? this.cursor < slotCount - 1 ? this.cursor + 1 : 6 : 0);
break;
case Button.LEFT:
if (this.cursor >= battlerCount && this.cursor <= 6) {
success = this.setCursor(0);
}
break;
case Button.RIGHT:
if (slotCount === battlerCount) {
success = this.setCursor(6);
break; break;
} else if (battlerCount >= 2 && slotCount > battlerCount && this.getCursor() === 0 && this.lastCursor === 1) { case Button.DOWN:
success = this.setCursor(2); success = this.setCursor(this.cursor < 6 ? this.cursor < slotCount - 1 ? this.cursor + 1 : 6 : 0);
break; break;
} else if (slotCount > battlerCount && this.cursor < battlerCount) { case Button.LEFT:
success = this.setCursor(this.lastCursor < 6 ? this.lastCursor || battlerCount : battlerCount); if (this.cursor >= battlerCount && this.cursor <= 6) {
success = this.setCursor(0);
}
break; break;
} case Button.RIGHT:
if (slotCount === battlerCount) {
success = this.setCursor(6);
break;
} else if (battlerCount >= 2 && slotCount > battlerCount && this.getCursor() === 0 && this.lastCursor === 1) {
success = this.setCursor(2);
break;
} else if (slotCount > battlerCount && this.cursor < battlerCount) {
success = this.setCursor(this.lastCursor < 6 ? this.lastCursor || battlerCount : battlerCount);
break;
}
} }
} }
@ -773,19 +773,19 @@ export default class PartyUiHandler extends MessageUiHandler {
let optionsMessage = i18next.t("partyUiHandler:doWhatWithThisPokemon"); let optionsMessage = i18next.t("partyUiHandler:doWhatWithThisPokemon");
switch (this.partyUiMode) { switch (this.partyUiMode) {
case PartyUiMode.MOVE_MODIFIER: case PartyUiMode.MOVE_MODIFIER:
optionsMessage = i18next.t("partyUiHandler:selectAMove"); optionsMessage = i18next.t("partyUiHandler:selectAMove");
break; break;
case PartyUiMode.MODIFIER_TRANSFER: case PartyUiMode.MODIFIER_TRANSFER:
if (!this.transferMode) { if (!this.transferMode) {
optionsMessage = i18next.t("partyUiHandler:changeQuantity"); optionsMessage = i18next.t("partyUiHandler:changeQuantity");
} }
break; break;
case PartyUiMode.SPLICE: case PartyUiMode.SPLICE:
if (!this.transferMode) { if (!this.transferMode) {
optionsMessage = i18next.t("partyUiHandler:selectAnotherPokemonToSplice"); optionsMessage = i18next.t("partyUiHandler:selectAnotherPokemonToSplice");
} }
break; break;
} }
this.showText(optionsMessage, 0); this.showText(optionsMessage, 0);
@ -829,64 +829,64 @@ export default class PartyUiHandler extends MessageUiHandler {
if (this.partyUiMode !== PartyUiMode.MOVE_MODIFIER && this.partyUiMode !== PartyUiMode.REMEMBER_MOVE_MODIFIER && (this.transferMode || this.partyUiMode !== PartyUiMode.MODIFIER_TRANSFER)) { if (this.partyUiMode !== PartyUiMode.MOVE_MODIFIER && this.partyUiMode !== PartyUiMode.REMEMBER_MOVE_MODIFIER && (this.transferMode || this.partyUiMode !== PartyUiMode.MODIFIER_TRANSFER)) {
switch (this.partyUiMode) { switch (this.partyUiMode) {
case PartyUiMode.SWITCH: case PartyUiMode.SWITCH:
case PartyUiMode.FAINT_SWITCH: case PartyUiMode.FAINT_SWITCH:
case PartyUiMode.POST_BATTLE_SWITCH: case PartyUiMode.POST_BATTLE_SWITCH:
if (this.cursor >= this.scene.currentBattle.getBattlerCount()) { if (this.cursor >= this.scene.currentBattle.getBattlerCount()) {
const allowBatonModifierSwitch = const allowBatonModifierSwitch =
this.partyUiMode !== PartyUiMode.FAINT_SWITCH this.partyUiMode !== PartyUiMode.FAINT_SWITCH
&& this.scene.findModifier(m => m instanceof SwitchEffectTransferModifier && this.scene.findModifier(m => m instanceof SwitchEffectTransferModifier
&& (m as SwitchEffectTransferModifier).pokemonId === this.scene.getPlayerField()[this.fieldIndex].id); && (m as SwitchEffectTransferModifier).pokemonId === this.scene.getPlayerField()[this.fieldIndex].id);
const moveHistory = this.scene.getPlayerField()[this.fieldIndex].getMoveHistory(); const moveHistory = this.scene.getPlayerField()[this.fieldIndex].getMoveHistory();
const isBatonPassMove = this.partyUiMode === PartyUiMode.FAINT_SWITCH && moveHistory.length && allMoves[moveHistory[moveHistory.length - 1].move].getAttrs(ForceSwitchOutAttr)[0]?.isBatonPass() && moveHistory[moveHistory.length - 1].result === MoveResult.SUCCESS; const isBatonPassMove = this.partyUiMode === PartyUiMode.FAINT_SWITCH && moveHistory.length && allMoves[moveHistory[moveHistory.length - 1].move].getAttrs(ForceSwitchOutAttr)[0]?.isBatonPass() && moveHistory[moveHistory.length - 1].result === MoveResult.SUCCESS;
// isBatonPassMove and allowBatonModifierSwitch shouldn't ever be true // isBatonPassMove and allowBatonModifierSwitch shouldn't ever be true
// at the same time, because they both explicitly check for a mutually // at the same time, because they both explicitly check for a mutually
// exclusive partyUiMode. But better safe than sorry. // exclusive partyUiMode. But better safe than sorry.
this.options.push(isBatonPassMove && !allowBatonModifierSwitch ? PartyOption.PASS_BATON : PartyOption.SEND_OUT); this.options.push(isBatonPassMove && !allowBatonModifierSwitch ? PartyOption.PASS_BATON : PartyOption.SEND_OUT);
if (allowBatonModifierSwitch && !isBatonPassMove) { if (allowBatonModifierSwitch && !isBatonPassMove) {
// the BATON modifier gives an extra switch option for // the BATON modifier gives an extra switch option for
// pokemon-command switches, allowing buffs to be optionally passed // pokemon-command switches, allowing buffs to be optionally passed
this.options.push(PartyOption.PASS_BATON); this.options.push(PartyOption.PASS_BATON);
}
} }
} break;
break; case PartyUiMode.REVIVAL_BLESSING:
case PartyUiMode.REVIVAL_BLESSING: this.options.push(PartyOption.REVIVE);
this.options.push(PartyOption.REVIVE); break;
break; case PartyUiMode.MODIFIER:
case PartyUiMode.MODIFIER:
this.options.push(PartyOption.APPLY);
break;
case PartyUiMode.TM_MODIFIER:
this.options.push(PartyOption.TEACH);
break;
case PartyUiMode.MODIFIER_TRANSFER:
this.options.push(PartyOption.TRANSFER);
break;
case PartyUiMode.SPLICE:
if (this.transferMode) {
if (this.cursor !== this.transferCursor) {
this.options.push(PartyOption.SPLICE);
}
} else {
this.options.push(PartyOption.APPLY); this.options.push(PartyOption.APPLY);
} break;
break; case PartyUiMode.TM_MODIFIER:
case PartyUiMode.RELEASE: this.options.push(PartyOption.TEACH);
this.options.push(PartyOption.RELEASE); break;
break; case PartyUiMode.MODIFIER_TRANSFER:
case PartyUiMode.CHECK: this.options.push(PartyOption.TRANSFER);
if (this.scene.getCurrentPhase() instanceof SelectModifierPhase) { break;
formChangeItemModifiers = this.getFormChangeItemsModifiers(pokemon); case PartyUiMode.SPLICE:
for (let i = 0; i < formChangeItemModifiers.length; i++) { if (this.transferMode) {
this.options.push(PartyOption.FORM_CHANGE_ITEM + i); if (this.cursor !== this.transferCursor) {
this.options.push(PartyOption.SPLICE);
}
} else {
this.options.push(PartyOption.APPLY);
} }
} break;
break; case PartyUiMode.RELEASE:
case PartyUiMode.SELECT: this.options.push(PartyOption.RELEASE);
this.options.push(PartyOption.SELECT); break;
break; case PartyUiMode.CHECK:
if (this.scene.getCurrentPhase() instanceof SelectModifierPhase) {
formChangeItemModifiers = this.getFormChangeItemsModifiers(pokemon);
for (let i = 0; i < formChangeItemModifiers.length; i++) {
this.options.push(PartyOption.FORM_CHANGE_ITEM + i);
}
}
break;
case PartyUiMode.SELECT:
this.options.push(PartyOption.SELECT);
break;
} }
this.options.push(PartyOption.SUMMARY); this.options.push(PartyOption.SUMMARY);
@ -962,33 +962,33 @@ export default class PartyUiHandler extends MessageUiHandler {
optionName = "↓"; optionName = "↓";
} else if ((this.partyUiMode !== PartyUiMode.REMEMBER_MOVE_MODIFIER && (this.partyUiMode !== PartyUiMode.MODIFIER_TRANSFER || this.transferMode)) || option === PartyOption.CANCEL) { } else if ((this.partyUiMode !== PartyUiMode.REMEMBER_MOVE_MODIFIER && (this.partyUiMode !== PartyUiMode.MODIFIER_TRANSFER || this.transferMode)) || option === PartyOption.CANCEL) {
switch (option) { switch (option) {
case PartyOption.MOVE_1: case PartyOption.MOVE_1:
case PartyOption.MOVE_2: case PartyOption.MOVE_2:
case PartyOption.MOVE_3: case PartyOption.MOVE_3:
case PartyOption.MOVE_4: case PartyOption.MOVE_4:
const move = pokemon.moveset[option - PartyOption.MOVE_1]!; // TODO: is the bang correct? const move = pokemon.moveset[option - PartyOption.MOVE_1]!; // TODO: is the bang correct?
if (this.showMovePp) { if (this.showMovePp) {
const maxPP = move.getMovePp(); const maxPP = move.getMovePp();
const currPP = maxPP - move.ppUsed; const currPP = maxPP - move.ppUsed;
optionName = `${move.getName()} ${currPP}/${maxPP}`; optionName = `${move.getName()} ${currPP}/${maxPP}`;
} else {
optionName = move.getName();
}
break;
default:
if (formChangeItemModifiers && option >= PartyOption.FORM_CHANGE_ITEM) {
const modifier = formChangeItemModifiers[option - PartyOption.FORM_CHANGE_ITEM];
optionName = `${modifier.active ? i18next.t("partyUiHandler:DEACTIVATE") : i18next.t("partyUiHandler:ACTIVATE")} ${modifier.type.name}`;
} else if (option === PartyOption.UNPAUSE_EVOLUTION) {
optionName = `${pokemon.pauseEvolutions ? i18next.t("partyUiHandler:UNPAUSE_EVOLUTION") : i18next.t("partyUiHandler:PAUSE_EVOLUTION")}`;
} else {
if (this.localizedOptions.includes(option)) {
optionName = i18next.t(`partyUiHandler:${PartyOption[option]}`);
} else { } else {
optionName = Utils.toReadableString(PartyOption[option]); optionName = move.getName();
} }
} break;
break; default:
if (formChangeItemModifiers && option >= PartyOption.FORM_CHANGE_ITEM) {
const modifier = formChangeItemModifiers[option - PartyOption.FORM_CHANGE_ITEM];
optionName = `${modifier.active ? i18next.t("partyUiHandler:DEACTIVATE") : i18next.t("partyUiHandler:ACTIVATE")} ${modifier.type.name}`;
} else if (option === PartyOption.UNPAUSE_EVOLUTION) {
optionName = `${pokemon.pauseEvolutions ? i18next.t("partyUiHandler:UNPAUSE_EVOLUTION") : i18next.t("partyUiHandler:PAUSE_EVOLUTION")}`;
} else {
if (this.localizedOptions.includes(option)) {
optionName = i18next.t(`partyUiHandler:${PartyOption[option]}`);
} else {
optionName = Utils.toReadableString(PartyOption[option]);
}
}
break;
} }
} else if (this.partyUiMode === PartyUiMode.REMEMBER_MOVE_MODIFIER) { } else if (this.partyUiMode === PartyUiMode.REMEMBER_MOVE_MODIFIER) {
const move = learnableLevelMoves[option]; const move = learnableLevelMoves[option];

View File

@ -39,12 +39,12 @@ export default class PokemonIconAnimHandler {
getModeYDelta(mode: PokemonIconAnimMode): number { getModeYDelta(mode: PokemonIconAnimMode): number {
switch (mode) { switch (mode) {
case PokemonIconAnimMode.NONE: case PokemonIconAnimMode.NONE:
return 0; return 0;
case PokemonIconAnimMode.PASSIVE: case PokemonIconAnimMode.PASSIVE:
return -1; return -1;
case PokemonIconAnimMode.ACTIVE: case PokemonIconAnimMode.ACTIVE:
return -2; return -2;
} }
} }

View File

@ -50,12 +50,12 @@ export default class RegistrationFormUiHandler extends FormModalUiHandler {
error = error.slice(0, colonIndex); error = error.slice(0, colonIndex);
} }
switch (error) { switch (error) {
case "invalid username": case "invalid username":
return i18next.t("menu:invalidRegisterUsername"); return i18next.t("menu:invalidRegisterUsername");
case "invalid password": case "invalid password":
return i18next.t("menu:invalidRegisterPassword"); return i18next.t("menu:invalidRegisterPassword");
case "failed to add account record": case "failed to add account record":
return i18next.t("menu:usernameAlreadyUsed"); return i18next.t("menu:usernameAlreadyUsed");
} }
return super.getReadableErrorMessage(error); return super.getReadableErrorMessage(error);

View File

@ -118,28 +118,28 @@ export default class RunHistoryUiHandler extends MessageUiHandler {
} }
} else if (this.runs.length > 0) { } else if (this.runs.length > 0) {
switch (button) { switch (button) {
case Button.UP: case Button.UP:
if (this.cursor) { if (this.cursor) {
success = this.setCursor(this.cursor - 1); success = this.setCursor(this.cursor - 1);
} else if (this.scrollCursor) { } else if (this.scrollCursor) {
success = this.setScrollCursor(this.scrollCursor - 1); success = this.setScrollCursor(this.scrollCursor - 1);
} else if (this.runs.length > 1) { } else if (this.runs.length > 1) {
// wrap around to the bottom // wrap around to the bottom
success = this.setCursor(Math.min(this.runs.length - 1, this.maxRows - 1)); success = this.setCursor(Math.min(this.runs.length - 1, this.maxRows - 1));
success = this.setScrollCursor(Math.max(0, this.runs.length - this.maxRows)) || success; success = this.setScrollCursor(Math.max(0, this.runs.length - this.maxRows)) || success;
} }
break; break;
case Button.DOWN: case Button.DOWN:
if (this.cursor < Math.min(this.maxRows - 1, this.runs.length - this.scrollCursor - 1)) { if (this.cursor < Math.min(this.maxRows - 1, this.runs.length - this.scrollCursor - 1)) {
success = this.setCursor(this.cursor + 1); success = this.setCursor(this.cursor + 1);
} else if (this.scrollCursor < this.runs.length - this.maxRows) { } else if (this.scrollCursor < this.runs.length - this.maxRows) {
success = this.setScrollCursor(this.scrollCursor + 1); success = this.setScrollCursor(this.scrollCursor + 1);
} else if (this.runs.length > 1) { } else if (this.runs.length > 1) {
// wrap around to the top // wrap around to the top
success = this.setCursor(0); success = this.setCursor(0);
success = this.setScrollCursor(0) || success; success = this.setScrollCursor(0) || success;
} }
break; break;
} }
} }
@ -333,19 +333,19 @@ class RunEntryContainer extends Phaser.GameObjects.Container {
const gameModeLabel = addTextObject(this.scene, 8, 19, "", TextStyle.WINDOW); const gameModeLabel = addTextObject(this.scene, 8, 19, "", TextStyle.WINDOW);
let mode = ""; let mode = "";
switch (data.gameMode) { switch (data.gameMode) {
case GameModes.DAILY: case GameModes.DAILY:
mode = i18next.t("gameMode:dailyRun"); mode = i18next.t("gameMode:dailyRun");
break; break;
case GameModes.SPLICED_ENDLESS: case GameModes.SPLICED_ENDLESS:
case GameModes.ENDLESS: case GameModes.ENDLESS:
mode = i18next.t("gameMode:endless"); mode = i18next.t("gameMode:endless");
break; break;
case GameModes.CLASSIC: case GameModes.CLASSIC:
mode = i18next.t("gameMode:classic"); mode = i18next.t("gameMode:classic");
break; break;
case GameModes.CHALLENGE: case GameModes.CHALLENGE:
mode = i18next.t("gameMode:challenge"); mode = i18next.t("gameMode:challenge");
break; break;
} }
gameModeLabel.appendText(mode, false); gameModeLabel.appendText(mode, false);
if (data.gameMode === GameModes.SPLICED_ENDLESS) { if (data.gameMode === GameModes.SPLICED_ENDLESS) {

View File

@ -229,14 +229,14 @@ export default class RunInfoUiHandler extends UiHandler {
// Wild - Single and Doubles // Wild - Single and Doubles
if (this.runInfo.battleType === BattleType.WILD || (this.runInfo.battleType === BattleType.MYSTERY_ENCOUNTER && !this.runInfo.trainer)) { if (this.runInfo.battleType === BattleType.WILD || (this.runInfo.battleType === BattleType.MYSTERY_ENCOUNTER && !this.runInfo.trainer)) {
switch (this.runInfo.enemyParty.length) { switch (this.runInfo.enemyParty.length) {
case 1: case 1:
// Wild - Singles // Wild - Singles
this.parseWildSingleDefeat(enemyContainer); this.parseWildSingleDefeat(enemyContainer);
break; break;
case 2: case 2:
//Wild - Doubles //Wild - Doubles
this.parseWildDoubleDefeat(enemyContainer); this.parseWildDoubleDefeat(enemyContainer);
break; break;
} }
} else if (this.runInfo.battleType === BattleType.TRAINER || (this.runInfo.battleType === BattleType.MYSTERY_ENCOUNTER && this.runInfo.trainer)) { } else if (this.runInfo.battleType === BattleType.TRAINER || (this.runInfo.battleType === BattleType.MYSTERY_ENCOUNTER && this.runInfo.trainer)) {
this.parseTrainerDefeat(enemyContainer); this.parseTrainerDefeat(enemyContainer);
@ -474,33 +474,33 @@ export default class RunInfoUiHandler extends UiHandler {
modeText.setPosition(7, 5); modeText.setPosition(7, 5);
modeText.appendText(i18next.t("runHistory:mode") + ": ", false); modeText.appendText(i18next.t("runHistory:mode") + ": ", false);
switch (this.runInfo.gameMode) { switch (this.runInfo.gameMode) {
case GameModes.DAILY: case GameModes.DAILY:
modeText.appendText(`${i18next.t("gameMode:dailyRun")}`, false); modeText.appendText(`${i18next.t("gameMode:dailyRun")}`, false);
break; break;
case GameModes.SPLICED_ENDLESS: case GameModes.SPLICED_ENDLESS:
modeText.appendText(`${i18next.t("gameMode:endlessSpliced")}`, false); modeText.appendText(`${i18next.t("gameMode:endlessSpliced")}`, false);
break; break;
case GameModes.CHALLENGE: case GameModes.CHALLENGE:
modeText.appendText(`${i18next.t("gameMode:challenge")}`, false); modeText.appendText(`${i18next.t("gameMode:challenge")}`, false);
modeText.appendText(`${i18next.t("runHistory:challengeRules")}: `); modeText.appendText(`${i18next.t("runHistory:challengeRules")}: `);
modeText.setWrapMode(1); // wrap by word modeText.setWrapMode(1); // wrap by word
modeText.setWrapWidth(500); modeText.setWrapWidth(500);
const rules: string[] = this.challengeParser(); const rules: string[] = this.challengeParser();
if (rules) { if (rules) {
for (let i = 0; i < rules.length; i++) { for (let i = 0; i < rules.length; i++) {
if (i > 0) { if (i > 0) {
modeText.appendText(" + ", false); modeText.appendText(" + ", false);
}
modeText.appendText(rules[i], false);
} }
modeText.appendText(rules[i], false);
} }
} break;
break; case GameModes.ENDLESS:
case GameModes.ENDLESS: modeText.appendText(`${i18next.t("gameMode:endless")}`, false);
modeText.appendText(`${i18next.t("gameMode:endless")}`, false); break;
break; case GameModes.CLASSIC:
case GameModes.CLASSIC: modeText.appendText(`${i18next.t("gameMode:classic")}`, false);
modeText.appendText(`${i18next.t("gameMode:classic")}`, false); break;
break;
} }
// If the player achieves a personal best in Endless, the mode text will be tinted similarly to SSS luck to celebrate their achievement. // If the player achieves a personal best in Endless, the mode text will be tinted similarly to SSS luck to celebrate their achievement.
@ -577,23 +577,23 @@ export default class RunInfoUiHandler extends UiHandler {
for (let i = 0; i < this.runInfo.challenges.length; i++) { for (let i = 0; i < this.runInfo.challenges.length; i++) {
if (this.runInfo.challenges[i].value !== 0) { if (this.runInfo.challenges[i].value !== 0) {
switch (this.runInfo.challenges[i].id) { switch (this.runInfo.challenges[i].id) {
case Challenges.SINGLE_GENERATION: case Challenges.SINGLE_GENERATION:
rules.push(i18next.t(`runHistory:challengeMonoGen${this.runInfo.challenges[i].value}`)); rules.push(i18next.t(`runHistory:challengeMonoGen${this.runInfo.challenges[i].value}`));
break; break;
case Challenges.SINGLE_TYPE: case Challenges.SINGLE_TYPE:
const typeRule = Type[this.runInfo.challenges[i].value - 1]; const typeRule = Type[this.runInfo.challenges[i].value - 1];
const typeTextColor = `[color=${TypeColor[typeRule]}]`; const typeTextColor = `[color=${TypeColor[typeRule]}]`;
const typeShadowColor = `[shadow=${TypeShadow[typeRule]}]`; const typeShadowColor = `[shadow=${TypeShadow[typeRule]}]`;
const typeText = typeTextColor + typeShadowColor + i18next.t(`pokemonInfo:Type.${typeRule}`)! + "[/color]" + "[/shadow]"; const typeText = typeTextColor + typeShadowColor + i18next.t(`pokemonInfo:Type.${typeRule}`)! + "[/color]" + "[/shadow]";
rules.push(typeText); rules.push(typeText);
break; break;
case Challenges.INVERSE_BATTLE: case Challenges.INVERSE_BATTLE:
rules.push(i18next.t("challenges:inverseBattle.shortName")); rules.push(i18next.t("challenges:inverseBattle.shortName"));
break; break;
default: default:
const localisationKey = Challenges[this.runInfo.challenges[i].id].split("_").map((f, i) => i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()).join(""); const localisationKey = Challenges[this.runInfo.challenges[i].id].split("_").map((f, i) => i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()).join("");
rules.push(i18next.t(`challenges:${localisationKey}.name`)); rules.push(i18next.t(`challenges:${localisationKey}.name`));
break; break;
} }
} }
} }
@ -911,36 +911,36 @@ export default class RunInfoUiHandler extends UiHandler {
const error = false; const error = false;
switch (button) { switch (button) {
case Button.CANCEL: case Button.CANCEL:
success = true; success = true;
if (this.pageMode === RunInfoUiMode.MAIN) { if (this.pageMode === RunInfoUiMode.MAIN) {
this.runInfoContainer.removeAll(true); this.runInfoContainer.removeAll(true);
this.runResultContainer.removeAll(true); this.runResultContainer.removeAll(true);
this.partyContainer.removeAll(true); this.partyContainer.removeAll(true);
this.runContainer.removeAll(true); this.runContainer.removeAll(true);
if (this.isVictory) { if (this.isVictory) {
this.hallofFameContainer.removeAll(true); this.hallofFameContainer.removeAll(true);
}
super.clear();
this.runContainer.setVisible(false);
ui.revertMode();
} else if (this.pageMode === RunInfoUiMode.HALL_OF_FAME) {
this.hallofFameContainer.setVisible(false);
this.pageMode = RunInfoUiMode.MAIN;
} else if (this.pageMode === RunInfoUiMode.ENDING_ART) {
this.endCardContainer.setVisible(false);
this.runContainer.remove(this.endCardContainer);
this.pageMode = RunInfoUiMode.MAIN;
} }
super.clear(); break;
this.runContainer.setVisible(false); case Button.DOWN:
ui.revertMode(); case Button.UP:
} else if (this.pageMode === RunInfoUiMode.HALL_OF_FAME) { break;
this.hallofFameContainer.setVisible(false); case Button.CYCLE_FORM:
this.pageMode = RunInfoUiMode.MAIN; case Button.CYCLE_SHINY:
} else if (this.pageMode === RunInfoUiMode.ENDING_ART) { case Button.CYCLE_ABILITY:
this.endCardContainer.setVisible(false); this.buttonCycleOption(button);
this.runContainer.remove(this.endCardContainer); break;
this.pageMode = RunInfoUiMode.MAIN;
}
break;
case Button.DOWN:
case Button.UP:
break;
case Button.CYCLE_FORM:
case Button.CYCLE_SHINY:
case Button.CYCLE_ABILITY:
this.buttonCycleOption(button);
break;
} }
if (success) { if (success) {
@ -960,40 +960,40 @@ export default class RunInfoUiHandler extends UiHandler {
*/ */
private buttonCycleOption(button: Button) { private buttonCycleOption(button: Button) {
switch (button) { switch (button) {
case Button.CYCLE_FORM: case Button.CYCLE_FORM:
if (this.isVictory && this.pageMode !== RunInfoUiMode.HALL_OF_FAME) { if (this.isVictory && this.pageMode !== RunInfoUiMode.HALL_OF_FAME) {
if (!this.endCardContainer || !this.endCardContainer.visible) { if (!this.endCardContainer || !this.endCardContainer.visible) {
this.createVictorySplash(); this.createVictorySplash();
this.endCardContainer.setVisible(true); this.endCardContainer.setVisible(true);
this.runContainer.add(this.endCardContainer); this.runContainer.add(this.endCardContainer);
this.pageMode = RunInfoUiMode.ENDING_ART; this.pageMode = RunInfoUiMode.ENDING_ART;
} else { } else {
this.endCardContainer.setVisible(false); this.endCardContainer.setVisible(false);
this.runContainer.remove(this.endCardContainer); this.runContainer.remove(this.endCardContainer);
this.pageMode = RunInfoUiMode.MAIN; this.pageMode = RunInfoUiMode.MAIN;
}
} }
} break;
break; case Button.CYCLE_SHINY:
case Button.CYCLE_SHINY: if (this.isVictory && this.pageMode !== RunInfoUiMode.ENDING_ART) {
if (this.isVictory && this.pageMode !== RunInfoUiMode.ENDING_ART) { if (!this.hallofFameContainer.visible) {
if (!this.hallofFameContainer.visible) { this.hallofFameContainer.setVisible(true);
this.hallofFameContainer.setVisible(true); this.pageMode = RunInfoUiMode.HALL_OF_FAME;
this.pageMode = RunInfoUiMode.HALL_OF_FAME; } else {
} else { this.hallofFameContainer.setVisible(false);
this.hallofFameContainer.setVisible(false); this.pageMode = RunInfoUiMode.MAIN;
this.pageMode = RunInfoUiMode.MAIN; }
} }
} break;
break; case Button.CYCLE_ABILITY:
case Button.CYCLE_ABILITY: if (this.runInfo.modifiers.length !== 0 && this.pageMode === RunInfoUiMode.MAIN) {
if (this.runInfo.modifiers.length !== 0 && this.pageMode === RunInfoUiMode.MAIN) { if (this.partyVisibility) {
if (this.partyVisibility) { this.showParty(false);
this.showParty(false); } else {
} else { this.showParty(true);
this.showParty(true); }
} }
} break;
break;
} }
} }
} }

View File

@ -106,40 +106,40 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler {
error = true; error = true;
} else { } else {
switch (this.uiMode) { switch (this.uiMode) {
case SaveSlotUiMode.LOAD: case SaveSlotUiMode.LOAD:
this.saveSlotSelectCallback = null;
originalCallback && originalCallback(cursor);
break;
case SaveSlotUiMode.SAVE:
const saveAndCallback = () => {
const originalCallback = this.saveSlotSelectCallback;
this.saveSlotSelectCallback = null; this.saveSlotSelectCallback = null;
ui.revertMode();
ui.showText("", 0);
ui.setMode(Mode.MESSAGE);
originalCallback && originalCallback(cursor); originalCallback && originalCallback(cursor);
}; break;
if (this.sessionSlots[cursor].hasData) { case SaveSlotUiMode.SAVE:
ui.showText(i18next.t("saveSlotSelectUiHandler:overwriteData"), null, () => { const saveAndCallback = () => {
ui.setOverlayMode(Mode.CONFIRM, () => { const originalCallback = this.saveSlotSelectCallback;
this.scene.gameData.deleteSession(cursor).then(response => { this.saveSlotSelectCallback = null;
if (response === false) { ui.revertMode();
this.scene.reset(true); ui.showText("", 0);
} else { ui.setMode(Mode.MESSAGE);
saveAndCallback(); originalCallback && originalCallback(cursor);
} };
}); if (this.sessionSlots[cursor].hasData) {
}, () => { ui.showText(i18next.t("saveSlotSelectUiHandler:overwriteData"), null, () => {
ui.revertMode(); ui.setOverlayMode(Mode.CONFIRM, () => {
ui.showText("", 0); this.scene.gameData.deleteSession(cursor).then(response => {
}, false, 0, 19, 2000); if (response === false) {
}); this.scene.reset(true);
} else if (this.sessionSlots[cursor].hasData === false) { } else {
saveAndCallback(); saveAndCallback();
} else { }
return false; });
} }, () => {
break; ui.revertMode();
ui.showText("", 0);
}, false, 0, 19, 2000);
});
} else if (this.sessionSlots[cursor].hasData === false) {
saveAndCallback();
} else {
return false;
}
break;
} }
success = true; success = true;
} }
@ -151,26 +151,26 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler {
} else { } else {
const cursorPosition = this.cursor + this.scrollCursor; const cursorPosition = this.cursor + this.scrollCursor;
switch (button) { switch (button) {
case Button.UP: case Button.UP:
if (this.cursor) { if (this.cursor) {
// Check to prevent cursor from accessing a negative index // Check to prevent cursor from accessing a negative index
success = (this.cursor === 0) ? this.setCursor(this.cursor) : this.setCursor(this.cursor - 1, cursorPosition); success = (this.cursor === 0) ? this.setCursor(this.cursor) : this.setCursor(this.cursor - 1, cursorPosition);
} else if (this.scrollCursor) { } else if (this.scrollCursor) {
success = this.setScrollCursor(this.scrollCursor - 1, cursorPosition); success = this.setScrollCursor(this.scrollCursor - 1, cursorPosition);
} }
break; break;
case Button.DOWN: case Button.DOWN:
if (this.cursor < (SLOTS_ON_SCREEN - 1)) { if (this.cursor < (SLOTS_ON_SCREEN - 1)) {
success = this.setCursor(this.cursor + 1, cursorPosition); success = this.setCursor(this.cursor + 1, cursorPosition);
} else if (this.scrollCursor < SESSION_SLOTS_COUNT - SLOTS_ON_SCREEN) { } else if (this.scrollCursor < SESSION_SLOTS_COUNT - SLOTS_ON_SCREEN) {
success = this.setScrollCursor(this.scrollCursor + 1, cursorPosition); success = this.setScrollCursor(this.scrollCursor + 1, cursorPosition);
} }
break; break;
case Button.RIGHT: case Button.RIGHT:
if (this.sessionSlots[cursorPosition].hasData && this.sessionSlots[cursorPosition].saveData) { if (this.sessionSlots[cursorPosition].hasData && this.sessionSlots[cursorPosition].saveData) {
this.scene.ui.setOverlayMode(Mode.RUN_INFO, this.sessionSlots[cursorPosition].saveData, RunDisplayMode.SESSION_PREVIEW); this.scene.ui.setOverlayMode(Mode.RUN_INFO, this.sessionSlots[cursorPosition].saveData, RunDisplayMode.SESSION_PREVIEW);
success = true; success = true;
} }
} }
} }

View File

@ -106,48 +106,48 @@ export default class ScrollableGridUiHandler {
const itemOffset = this.scrollCursor * this.COLUMNS; const itemOffset = this.scrollCursor * this.COLUMNS;
const lastVisibleIndex = Math.min(this.totalElements - 1, this.totalElements - maxScrollCursor * this.COLUMNS - 1); const lastVisibleIndex = Math.min(this.totalElements - 1, this.totalElements - maxScrollCursor * this.COLUMNS - 1);
switch (button) { switch (button) {
case Button.UP: case Button.UP:
if (currentRowIndex > 0) { if (currentRowIndex > 0) {
success = this.setCursor(this.cursor - this.COLUMNS); success = this.setCursor(this.cursor - this.COLUMNS);
} else if (this.scrollCursor > 0) { } else if (this.scrollCursor > 0) {
success = this.setScrollCursor(this.scrollCursor - 1); success = this.setScrollCursor(this.scrollCursor - 1);
} else { } else {
// wrap around to the last row // wrap around to the last row
let newCursor = this.cursor + (onScreenRows - 1) * this.COLUMNS; let newCursor = this.cursor + (onScreenRows - 1) * this.COLUMNS;
if (newCursor > lastVisibleIndex) { if (newCursor > lastVisibleIndex) {
newCursor -= this.COLUMNS; newCursor -= this.COLUMNS;
}
success = this.setScrollCursor(maxScrollCursor, newCursor);
} }
success = this.setScrollCursor(maxScrollCursor, newCursor); break;
} case Button.DOWN:
break; if (currentRowIndex < onScreenRows - 1) {
case Button.DOWN:
if (currentRowIndex < onScreenRows - 1) {
// Go down one row // Go down one row
success = this.setCursor(Math.min(this.cursor + this.COLUMNS, this.totalElements - itemOffset - 1)); success = this.setCursor(Math.min(this.cursor + this.COLUMNS, this.totalElements - itemOffset - 1));
} else if (this.scrollCursor < maxScrollCursor) { } else if (this.scrollCursor < maxScrollCursor) {
// Scroll down one row // Scroll down one row
success = this.setScrollCursor(this.scrollCursor + 1); success = this.setScrollCursor(this.scrollCursor + 1);
} else { } else {
// Wrap around to the top row // Wrap around to the top row
success = this.setScrollCursor(0, this.cursor % this.COLUMNS); success = this.setScrollCursor(0, this.cursor % this.COLUMNS);
} }
break; break;
case Button.LEFT: case Button.LEFT:
if (currentColumnIndex > 0) { if (currentColumnIndex > 0) {
success = this.setCursor(this.cursor - 1); success = this.setCursor(this.cursor - 1);
} else if (this.scrollCursor === maxScrollCursor && currentRowIndex === onScreenRows - 1) { } else if (this.scrollCursor === maxScrollCursor && currentRowIndex === onScreenRows - 1) {
success = this.setCursor(lastVisibleIndex); success = this.setCursor(lastVisibleIndex);
} else { } else {
success = this.setCursor(this.cursor + this.COLUMNS - 1); success = this.setCursor(this.cursor + this.COLUMNS - 1);
} }
break; break;
case Button.RIGHT: case Button.RIGHT:
if (currentColumnIndex < this.COLUMNS - 1 && this.cursor + itemOffset < this.totalElements - 1) { if (currentColumnIndex < this.COLUMNS - 1 && this.cursor + itemOffset < this.totalElements - 1) {
success = this.setCursor(this.cursor + 1); success = this.setCursor(this.cursor + 1);
} else { } else {
success = this.setCursor(this.cursor - currentColumnIndex); success = this.setCursor(this.cursor - currentColumnIndex);
} }
break; break;
} }
return success; return success;
} }

View File

@ -170,22 +170,22 @@ export default abstract class AbstractBindingUiHandler extends UiHandler {
const ui = this.getUi(); const ui = this.getUi();
let success = false; let success = false;
switch (button) { switch (button) {
case Button.LEFT: case Button.LEFT:
case Button.RIGHT: case Button.RIGHT:
// Toggle between action and cancel options. // Toggle between action and cancel options.
const cursor = this.cursor ? 0 : 1; const cursor = this.cursor ? 0 : 1;
success = this.setCursor(cursor); success = this.setCursor(cursor);
break; break;
case Button.ACTION: case Button.ACTION:
// Process actions based on current cursor position. // Process actions based on current cursor position.
if (this.cursor === 0) { if (this.cursor === 0) {
this.cancelFn && this.cancelFn(); this.cancelFn && this.cancelFn();
} else { } else {
success = this.swapAction(); success = this.swapAction();
NavigationManager.getInstance().updateIcons(); NavigationManager.getInstance().updateIcons();
this.cancelFn && this.cancelFn(success); this.cancelFn && this.cancelFn(success);
} }
break; break;
} }
// Plays a select sound effect if an action was successfully processed. // Plays a select sound effect if an action was successfully processed.

View File

@ -449,78 +449,78 @@ export default abstract class AbstractControlSettingsUiHandler extends UiHandler
const cursor = this.cursor + this.scrollCursor; // Calculate the absolute cursor position. const cursor = this.cursor + this.scrollCursor; // Calculate the absolute cursor position.
const setting = this.setting[Object.keys(this.setting)[cursor]]; const setting = this.setting[Object.keys(this.setting)[cursor]];
switch (button) { switch (button) {
case Button.ACTION: case Button.ACTION:
if (!this.optionCursors || !this.optionValueLabels) { if (!this.optionCursors || !this.optionValueLabels) {
return false; // TODO: is false correct as default? (previously was `undefined`) return false; // TODO: is false correct as default? (previously was `undefined`)
}
if (this.settingBlacklisted.includes(setting) || !setting.includes("BUTTON_")) {
success = false;
} else {
success = this.setSetting(this.scene, setting, 1);
}
break;
case Button.UP: // Move up in the menu.
if (!this.optionValueLabels) {
return false;
}
if (cursor) { // If not at the top, move the cursor up.
if (this.cursor) {
success = this.setCursor(this.cursor - 1);
} else {// If at the top of the visible items, scroll up.
success = this.setScrollCursor(this.scrollCursor - 1);
} }
} else { if (this.settingBlacklisted.includes(setting) || !setting.includes("BUTTON_")) {
success = false;
} else {
success = this.setSetting(this.scene, setting, 1);
}
break;
case Button.UP: // Move up in the menu.
if (!this.optionValueLabels) {
return false;
}
if (cursor) { // If not at the top, move the cursor up.
if (this.cursor) {
success = this.setCursor(this.cursor - 1);
} else {// If at the top of the visible items, scroll up.
success = this.setScrollCursor(this.scrollCursor - 1);
}
} else {
// When at the top of the menu and pressing UP, move to the bottommost item. // When at the top of the menu and pressing UP, move to the bottommost item.
// First, set the cursor to the last visible element, preparing for the scroll to the end. // First, set the cursor to the last visible element, preparing for the scroll to the end.
const successA = this.setCursor(this.rowsToDisplay - 1); const successA = this.setCursor(this.rowsToDisplay - 1);
// Then, adjust the scroll to display the bottommost elements of the menu. // Then, adjust the scroll to display the bottommost elements of the menu.
const successB = this.setScrollCursor(this.optionValueLabels.length - this.rowsToDisplay); const successB = this.setScrollCursor(this.optionValueLabels.length - this.rowsToDisplay);
success = successA && successB; // success is just there to play the little validation sound effect success = successA && successB; // success is just there to play the little validation sound effect
}
break;
case Button.DOWN: // Move down in the menu.
if (!this.optionValueLabels) {
return false;
}
if (cursor < this.optionValueLabels.length - 1) {
if (this.cursor < this.rowsToDisplay - 1) {
success = this.setCursor(this.cursor + 1);
} else if (this.scrollCursor < this.optionValueLabels.length - this.rowsToDisplay) {
success = this.setScrollCursor(this.scrollCursor + 1);
} }
} else { break;
case Button.DOWN: // Move down in the menu.
if (!this.optionValueLabels) {
return false;
}
if (cursor < this.optionValueLabels.length - 1) {
if (this.cursor < this.rowsToDisplay - 1) {
success = this.setCursor(this.cursor + 1);
} else if (this.scrollCursor < this.optionValueLabels.length - this.rowsToDisplay) {
success = this.setScrollCursor(this.scrollCursor + 1);
}
} else {
// When at the bottom of the menu and pressing DOWN, move to the topmost item. // When at the bottom of the menu and pressing DOWN, move to the topmost item.
// First, set the cursor to the first visible element, resetting the scroll to the top. // First, set the cursor to the first visible element, resetting the scroll to the top.
const successA = this.setCursor(0); const successA = this.setCursor(0);
// Then, reset the scroll to start from the first element of the menu. // Then, reset the scroll to start from the first element of the menu.
const successB = this.setScrollCursor(0); const successB = this.setScrollCursor(0);
success = successA && successB; // Indicates a successful cursor and scroll adjustment. success = successA && successB; // Indicates a successful cursor and scroll adjustment.
} }
break; break;
case Button.LEFT: // Move selection left within the current option set. case Button.LEFT: // Move selection left within the current option set.
if (!this.optionCursors || !this.optionValueLabels) { if (!this.optionCursors || !this.optionValueLabels) {
return false; // TODO: is false correct as default? (previously was `undefined`) return false; // TODO: is false correct as default? (previously was `undefined`)
} }
if (this.settingBlacklisted.includes(setting) || setting.includes("BUTTON_")) { if (this.settingBlacklisted.includes(setting) || setting.includes("BUTTON_")) {
success = false; success = false;
} else if (this.optionCursors[cursor]) { } else if (this.optionCursors[cursor]) {
success = this.setOptionCursor(cursor, this.optionCursors[cursor] - 1, true); success = this.setOptionCursor(cursor, this.optionCursors[cursor] - 1, true);
} }
break; break;
case Button.RIGHT: // Move selection right within the current option set. case Button.RIGHT: // Move selection right within the current option set.
if (!this.optionCursors || !this.optionValueLabels) { if (!this.optionCursors || !this.optionValueLabels) {
return false; // TODO: is false correct as default? (previously was `undefined`) return false; // TODO: is false correct as default? (previously was `undefined`)
} }
if (this.settingBlacklisted.includes(setting) || setting.includes("BUTTON_")) { if (this.settingBlacklisted.includes(setting) || setting.includes("BUTTON_")) {
success = false; success = false;
} else if (this.optionCursors[cursor] < this.optionValueLabels[cursor].length - 1) { } else if (this.optionCursors[cursor] < this.optionValueLabels[cursor].length - 1) {
success = this.setOptionCursor(cursor, this.optionCursors[cursor] + 1, true); success = this.setOptionCursor(cursor, this.optionCursors[cursor] + 1, true);
} }
break; break;
case Button.CYCLE_FORM: case Button.CYCLE_FORM:
case Button.CYCLE_SHINY: case Button.CYCLE_SHINY:
success = this.navigationContainer.navigate(button); success = this.navigationContainer.navigate(button);
break; break;
} }
} }

View File

@ -224,59 +224,59 @@ export default class AbstractSettingsUiHandler extends UiHandler {
} else { } else {
const cursor = this.cursor + this.scrollCursor; const cursor = this.cursor + this.scrollCursor;
switch (button) { switch (button) {
case Button.UP: case Button.UP:
if (cursor) { if (cursor) {
if (this.cursor) { if (this.cursor) {
success = this.setCursor(this.cursor - 1); success = this.setCursor(this.cursor - 1);
} else {
success = this.setScrollCursor(this.scrollCursor - 1);
}
} else { } else {
success = this.setScrollCursor(this.scrollCursor - 1);
}
} else {
// When at the top of the menu and pressing UP, move to the bottommost item. // When at the top of the menu and pressing UP, move to the bottommost item.
// First, set the cursor to the last visible element, preparing for the scroll to the end. // First, set the cursor to the last visible element, preparing for the scroll to the end.
const successA = this.setCursor(this.rowsToDisplay - 1); const successA = this.setCursor(this.rowsToDisplay - 1);
// Then, adjust the scroll to display the bottommost elements of the menu. // Then, adjust the scroll to display the bottommost elements of the menu.
const successB = this.setScrollCursor(this.optionValueLabels.length - this.rowsToDisplay); const successB = this.setScrollCursor(this.optionValueLabels.length - this.rowsToDisplay);
success = successA && successB; // success is just there to play the little validation sound effect success = successA && successB; // success is just there to play the little validation sound effect
}
break;
case Button.DOWN:
if (cursor < this.optionValueLabels.length - 1) {
if (this.cursor < this.rowsToDisplay - 1) {// if the visual cursor is in the frame of 0 to 8
success = this.setCursor(this.cursor + 1);
} else if (this.scrollCursor < this.optionValueLabels.length - this.rowsToDisplay) {
success = this.setScrollCursor(this.scrollCursor + 1);
} }
} else { break;
case Button.DOWN:
if (cursor < this.optionValueLabels.length - 1) {
if (this.cursor < this.rowsToDisplay - 1) {// if the visual cursor is in the frame of 0 to 8
success = this.setCursor(this.cursor + 1);
} else if (this.scrollCursor < this.optionValueLabels.length - this.rowsToDisplay) {
success = this.setScrollCursor(this.scrollCursor + 1);
}
} else {
// When at the bottom of the menu and pressing DOWN, move to the topmost item. // When at the bottom of the menu and pressing DOWN, move to the topmost item.
// First, set the cursor to the first visible element, resetting the scroll to the top. // First, set the cursor to the first visible element, resetting the scroll to the top.
const successA = this.setCursor(0); const successA = this.setCursor(0);
// Then, reset the scroll to start from the first element of the menu. // Then, reset the scroll to start from the first element of the menu.
const successB = this.setScrollCursor(0); const successB = this.setScrollCursor(0);
success = successA && successB; // Indicates a successful cursor and scroll adjustment. success = successA && successB; // Indicates a successful cursor and scroll adjustment.
} }
break; break;
case Button.LEFT: case Button.LEFT:
if (this.optionCursors[cursor]) {// Moves the option cursor left, if possible. if (this.optionCursors[cursor]) {// Moves the option cursor left, if possible.
success = this.setOptionCursor(cursor, this.optionCursors[cursor] - 1, true); success = this.setOptionCursor(cursor, this.optionCursors[cursor] - 1, true);
} }
break; break;
case Button.RIGHT: case Button.RIGHT:
// Moves the option cursor right, if possible. // Moves the option cursor right, if possible.
if (this.optionCursors[cursor] < this.optionValueLabels[cursor].length - 1) { if (this.optionCursors[cursor] < this.optionValueLabels[cursor].length - 1) {
success = this.setOptionCursor(cursor, this.optionCursors[cursor] + 1, true); success = this.setOptionCursor(cursor, this.optionCursors[cursor] + 1, true);
} }
break; break;
case Button.CYCLE_FORM: case Button.CYCLE_FORM:
case Button.CYCLE_SHINY: case Button.CYCLE_SHINY:
success = this.navigationContainer.navigate(button); success = this.navigationContainer.navigate(button);
break; break;
case Button.ACTION: case Button.ACTION:
const setting: Setting = this.settings[cursor]; const setting: Setting = this.settings[cursor];
if (setting?.activatable) { if (setting?.activatable) {
success = this.activateSetting(setting); success = this.activateSetting(setting);
} }
break; break;
} }
} }
@ -295,9 +295,9 @@ export default class AbstractSettingsUiHandler extends UiHandler {
*/ */
activateSetting(setting: Setting): boolean { activateSetting(setting: Setting): boolean {
switch (setting.key) { switch (setting.key) {
case SettingKeys.Move_Touch_Controls: case SettingKeys.Move_Touch_Controls:
this.scene.inputController.moveTouchControlsHandler.enableConfigurationMode(this.getUi(), this.scene); this.scene.inputController.moveTouchControlsHandler.enableConfigurationMode(this.getUi(), this.scene);
return true; return true;
} }
return false; return false;
} }

View File

@ -198,12 +198,12 @@ export default class NavigationMenu extends Phaser.GameObjects.Container {
navigate(button: Button): boolean { navigate(button: Button): boolean {
const navigationManager = NavigationManager.getInstance(); const navigationManager = NavigationManager.getInstance();
switch (button) { switch (button) {
case Button.CYCLE_FORM: case Button.CYCLE_FORM:
navigationManager.navigate(this.scene, LEFT); navigationManager.navigate(this.scene, LEFT);
return true; return true;
case Button.CYCLE_SHINY: case Button.CYCLE_SHINY:
navigationManager.navigate(this.scene, RIGHT); navigationManager.navigate(this.scene, RIGHT);
return true; return true;
} }
return false; return false;
} }

View File

@ -23,79 +23,79 @@ export default class SettingsDisplayUiHandler extends AbstractSettingsUiHandler
if (languageIndex >= 0) { if (languageIndex >= 0) {
const currentLocale = localStorage.getItem("prLang"); const currentLocale = localStorage.getItem("prLang");
switch (currentLocale) { switch (currentLocale) {
case "en": case "en":
this.settings[languageIndex].options[0] = { this.settings[languageIndex].options[0] = {
value: "English", value: "English",
label: "English", label: "English",
}; };
break; break;
case "es": case "es":
this.settings[languageIndex].options[0] = { this.settings[languageIndex].options[0] = {
value: "Español", value: "Español",
label: "Español", label: "Español",
}; };
break; break;
case "it": case "it":
this.settings[languageIndex].options[0] = { this.settings[languageIndex].options[0] = {
value: "Italiano", value: "Italiano",
label: "Italiano", label: "Italiano",
}; };
break; break;
case "fr": case "fr":
this.settings[languageIndex].options[0] = { this.settings[languageIndex].options[0] = {
value: "Français", value: "Français",
label: "Français", label: "Français",
}; };
break; break;
case "de": case "de":
this.settings[languageIndex].options[0] = { this.settings[languageIndex].options[0] = {
value: "Deutsch", value: "Deutsch",
label: "Deutsch", label: "Deutsch",
}; };
break; break;
case "pt-BR": case "pt-BR":
this.settings[languageIndex].options[0] = { this.settings[languageIndex].options[0] = {
value: "Português (BR)", value: "Português (BR)",
label: "Português (BR)", label: "Português (BR)",
}; };
break; break;
case "zh-CN": case "zh-CN":
this.settings[languageIndex].options[0] = { this.settings[languageIndex].options[0] = {
value: "简体中文", value: "简体中文",
label: "简体中文", label: "简体中文",
}; };
break; break;
case "zh-TW": case "zh-TW":
this.settings[languageIndex].options[0] = { this.settings[languageIndex].options[0] = {
value: "繁體中文", value: "繁體中文",
label: "繁體中文", label: "繁體中文",
}; };
break; break;
case "ko": case "ko":
case "ko-KR": case "ko-KR":
this.settings[languageIndex].options[0] = { this.settings[languageIndex].options[0] = {
value: "한국어", value: "한국어",
label: "한국어", label: "한국어",
}; };
break; break;
case "ja": case "ja":
this.settings[languageIndex].options[0] = { this.settings[languageIndex].options[0] = {
value: "日本語", value: "日本語",
label: "日本語", label: "日本語",
}; };
break; break;
case "ca-ES": case "ca-ES":
this.settings[languageIndex].options[0] = { this.settings[languageIndex].options[0] = {
value: "Català", value: "Català",
label: "Català", label: "Català",
}; };
break; break;
default: default:
this.settings[languageIndex].options[0] = { this.settings[languageIndex].options[0] = {
value: "English", value: "English",
label: "English", label: "English",
}; };
break; break;
} }
} }

View File

@ -1303,119 +1303,119 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
} }
} else if (this.startCursorObj.visible) { // this checks to see if the start button is selected } else if (this.startCursorObj.visible) { // this checks to see if the start button is selected
switch (button) { switch (button) {
case Button.ACTION: case Button.ACTION:
if (this.tryStart(true)) { if (this.tryStart(true)) {
success = true; success = true;
} else { } else {
error = true; error = true;
} }
break; break;
case Button.UP: case Button.UP:
// UP from start button: go to pokemon in team if any, otherwise filter // UP from start button: go to pokemon in team if any, otherwise filter
this.startCursorObj.setVisible(false); this.startCursorObj.setVisible(false);
if (this.starterSpecies.length > 0) { if (this.starterSpecies.length > 0) {
this.starterIconsCursorIndex = this.starterSpecies.length - 1; this.starterIconsCursorIndex = this.starterSpecies.length - 1;
this.moveStarterIconsCursor(this.starterIconsCursorIndex); this.moveStarterIconsCursor(this.starterIconsCursorIndex);
} else { } else {
this.startCursorObj.setVisible(false);
this.filterBarCursor = Math.max(1, this.filterBar.numFilters - 1);
this.setFilterMode(true);
}
success = true;
break;
case Button.DOWN:
// DOWN from start button: Go to filters
this.startCursorObj.setVisible(false); this.startCursorObj.setVisible(false);
this.filterBarCursor = Math.max(1, this.filterBar.numFilters - 1); this.filterBarCursor = Math.max(1, this.filterBar.numFilters - 1);
this.setFilterMode(true); this.setFilterMode(true);
}
success = true;
break;
case Button.DOWN:
// DOWN from start button: Go to filters
this.startCursorObj.setVisible(false);
this.filterBarCursor = Math.max(1, this.filterBar.numFilters - 1);
this.setFilterMode(true);
success = true;
break;
case Button.LEFT:
if (numberOfStarters > 0) {
this.startCursorObj.setVisible(false);
this.cursorObj.setVisible(true);
this.setCursor(onScreenFirstIndex + (onScreenNumberOfRows - 1) * 9 + 8); // set last column
success = true; success = true;
} break;
break; case Button.LEFT:
case Button.RIGHT: if (numberOfStarters > 0) {
if (numberOfStarters > 0) { this.startCursorObj.setVisible(false);
this.startCursorObj.setVisible(false); this.cursorObj.setVisible(true);
this.cursorObj.setVisible(true); this.setCursor(onScreenFirstIndex + (onScreenNumberOfRows - 1) * 9 + 8); // set last column
this.setCursor(onScreenFirstIndex + (onScreenNumberOfRows - 1) * 9); // set first column success = true;
success = true; }
} break;
break; case Button.RIGHT:
if (numberOfStarters > 0) {
this.startCursorObj.setVisible(false);
this.cursorObj.setVisible(true);
this.setCursor(onScreenFirstIndex + (onScreenNumberOfRows - 1) * 9); // set first column
success = true;
}
break;
} }
} else if (this.filterMode) { } else if (this.filterMode) {
switch (button) { switch (button) {
case Button.LEFT: case Button.LEFT:
if (this.filterBarCursor > 0) { if (this.filterBarCursor > 0) {
success = this.setCursor(this.filterBarCursor - 1); success = this.setCursor(this.filterBarCursor - 1);
} else {
success = this.setCursor(this.filterBar.numFilters - 1);
}
break;
case Button.RIGHT:
if (this.filterBarCursor < this.filterBar.numFilters - 1) {
success = this.setCursor(this.filterBarCursor + 1);
} else {
success = this.setCursor(0);
}
break;
case Button.UP:
if (this.filterBar.openDropDown) {
success = this.filterBar.decDropDownCursor();
} else if (this.filterBarCursor === this.filterBar.numFilters - 1 && this.starterSpecies.length > 0) {
// UP from the last filter, move to start button
this.setFilterMode(false);
this.cursorObj.setVisible(false);
this.startCursorObj.setVisible(true);
success = true;
} else if (numberOfStarters > 0) {
// UP from filter bar to bottom of Pokemon list
this.setFilterMode(false);
this.scrollCursor = Math.max(0, numOfRows - 9);
this.updateScroll();
const proportion = (this.filterBarCursor + 0.5) / this.filterBar.numFilters;
const targetCol = Math.min(8, Math.floor(proportion * 11));
if (numberOfStarters % 9 > targetCol) {
this.setCursor(numberOfStarters - (numberOfStarters) % 9 + targetCol);
} else { } else {
this.setCursor(Math.max(numberOfStarters - (numberOfStarters) % 9 + targetCol - 9, 0)); success = this.setCursor(this.filterBar.numFilters - 1);
}
break;
case Button.RIGHT:
if (this.filterBarCursor < this.filterBar.numFilters - 1) {
success = this.setCursor(this.filterBarCursor + 1);
} else {
success = this.setCursor(0);
}
break;
case Button.UP:
if (this.filterBar.openDropDown) {
success = this.filterBar.decDropDownCursor();
} else if (this.filterBarCursor === this.filterBar.numFilters - 1 && this.starterSpecies.length > 0) {
// UP from the last filter, move to start button
this.setFilterMode(false);
this.cursorObj.setVisible(false);
this.startCursorObj.setVisible(true);
success = true;
} else if (numberOfStarters > 0) {
// UP from filter bar to bottom of Pokemon list
this.setFilterMode(false);
this.scrollCursor = Math.max(0, numOfRows - 9);
this.updateScroll();
const proportion = (this.filterBarCursor + 0.5) / this.filterBar.numFilters;
const targetCol = Math.min(8, Math.floor(proportion * 11));
if (numberOfStarters % 9 > targetCol) {
this.setCursor(numberOfStarters - (numberOfStarters) % 9 + targetCol);
} else {
this.setCursor(Math.max(numberOfStarters - (numberOfStarters) % 9 + targetCol - 9, 0));
}
success = true;
}
break;
case Button.DOWN:
if (this.filterBar.openDropDown) {
success = this.filterBar.incDropDownCursor();
} else if (this.filterBarCursor === this.filterBar.numFilters - 1 && this.starterSpecies.length > 0) {
// DOWN from the last filter, move to Pokemon in party if any
this.setFilterMode(false);
this.cursorObj.setVisible(false);
this.starterIconsCursorIndex = 0;
this.moveStarterIconsCursor(this.starterIconsCursorIndex);
success = true;
} else if (numberOfStarters > 0) {
// DOWN from filter bar to top of Pokemon list
this.setFilterMode(false);
this.scrollCursor = 0;
this.updateScroll();
const proportion = this.filterBarCursor / Math.max(1, this.filterBar.numFilters - 1);
const targetCol = Math.min(8, Math.floor(proportion * 11));
this.setCursor(Math.min(targetCol, numberOfStarters));
success = true;
}
break;
case Button.ACTION:
if (!this.filterBar.openDropDown) {
this.filterBar.toggleDropDown(this.filterBarCursor);
} else {
this.filterBar.toggleOptionState();
} }
success = true; success = true;
} break;
break;
case Button.DOWN:
if (this.filterBar.openDropDown) {
success = this.filterBar.incDropDownCursor();
} else if (this.filterBarCursor === this.filterBar.numFilters - 1 && this.starterSpecies.length > 0) {
// DOWN from the last filter, move to Pokemon in party if any
this.setFilterMode(false);
this.cursorObj.setVisible(false);
this.starterIconsCursorIndex = 0;
this.moveStarterIconsCursor(this.starterIconsCursorIndex);
success = true;
} else if (numberOfStarters > 0) {
// DOWN from filter bar to top of Pokemon list
this.setFilterMode(false);
this.scrollCursor = 0;
this.updateScroll();
const proportion = this.filterBarCursor / Math.max(1, this.filterBar.numFilters - 1);
const targetCol = Math.min(8, Math.floor(proportion * 11));
this.setCursor(Math.min(targetCol, numberOfStarters));
success = true;
}
break;
case Button.ACTION:
if (!this.filterBar.openDropDown) {
this.filterBar.toggleDropDown(this.filterBarCursor);
} else {
this.filterBar.toggleOptionState();
}
success = true;
break;
} }
} else { } else {
@ -1856,259 +1856,259 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
} else { } else {
const props = this.scene.gameData.getSpeciesDexAttrProps(this.lastSpecies, this.getCurrentDexProps(this.lastSpecies.speciesId)); const props = this.scene.gameData.getSpeciesDexAttrProps(this.lastSpecies, this.getCurrentDexProps(this.lastSpecies.speciesId));
switch (button) { switch (button) {
case Button.CYCLE_SHINY: case Button.CYCLE_SHINY:
if (this.canCycleShiny) { if (this.canCycleShiny) {
starterAttributes.shiny = starterAttributes.shiny !== undefined ? !starterAttributes.shiny : false; starterAttributes.shiny = starterAttributes.shiny !== undefined ? !starterAttributes.shiny : false;
if (starterAttributes.shiny) { if (starterAttributes.shiny) {
// Change to shiny, we need to get the proper default variant // Change to shiny, we need to get the proper default variant
const newProps = this.scene.gameData.getSpeciesDexAttrProps(this.lastSpecies, this.getCurrentDexProps(this.lastSpecies.speciesId)); const newProps = this.scene.gameData.getSpeciesDexAttrProps(this.lastSpecies, this.getCurrentDexProps(this.lastSpecies.speciesId));
const newVariant = starterAttributes.variant ? starterAttributes.variant as Variant : newProps.variant; const newVariant = starterAttributes.variant ? starterAttributes.variant as Variant : newProps.variant;
this.setSpeciesDetails(this.lastSpecies, true, undefined, undefined, newVariant, undefined, undefined); this.setSpeciesDetails(this.lastSpecies, true, undefined, undefined, newVariant, undefined, undefined);
this.scene.playSound("se/sparkle"); this.scene.playSound("se/sparkle");
// Set the variant label to the shiny tint // Set the variant label to the shiny tint
const tint = getVariantTint(newVariant); const tint = getVariantTint(newVariant);
this.pokemonShinyIcon.setFrame(getVariantIcon(newVariant)); this.pokemonShinyIcon.setFrame(getVariantIcon(newVariant));
this.pokemonShinyIcon.setTint(tint); this.pokemonShinyIcon.setTint(tint);
this.pokemonShinyIcon.setVisible(true); this.pokemonShinyIcon.setVisible(true);
} else { } else {
this.setSpeciesDetails(this.lastSpecies, false, undefined, undefined, 0, undefined, undefined); this.setSpeciesDetails(this.lastSpecies, false, undefined, undefined, 0, undefined, undefined);
this.pokemonShinyIcon.setVisible(false); this.pokemonShinyIcon.setVisible(false);
success = true; success = true;
}
}
break;
case Button.CYCLE_FORM:
if (this.canCycleForm) {
const formCount = this.lastSpecies.forms.length;
let newFormIndex = props.formIndex;
do {
newFormIndex = (newFormIndex + 1) % formCount;
if (this.lastSpecies.forms[newFormIndex].isStarterSelectable && this.speciesStarterDexEntry!.caughtAttr! & this.scene.gameData.getFormAttr(newFormIndex)) { // TODO: are those bangs correct?
break;
} }
} while (newFormIndex !== props.formIndex); }
starterAttributes.form = newFormIndex; // store the selected form break;
this.setSpeciesDetails(this.lastSpecies, undefined, newFormIndex, undefined, undefined, undefined, undefined); case Button.CYCLE_FORM:
success = true; if (this.canCycleForm) {
} const formCount = this.lastSpecies.forms.length;
break; let newFormIndex = props.formIndex;
case Button.CYCLE_GENDER: do {
if (this.canCycleGender) { newFormIndex = (newFormIndex + 1) % formCount;
starterAttributes.female = !props.female; if (this.lastSpecies.forms[newFormIndex].isStarterSelectable && this.speciesStarterDexEntry!.caughtAttr! & this.scene.gameData.getFormAttr(newFormIndex)) { // TODO: are those bangs correct?
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, !props.female, undefined, undefined, undefined);
success = true;
}
break;
case Button.CYCLE_ABILITY:
if (this.canCycleAbility) {
const abilityCount = this.lastSpecies.getAbilityCount();
const abilityAttr = this.scene.gameData.starterData[this.lastSpecies.speciesId].abilityAttr;
const hasAbility1 = abilityAttr & AbilityAttr.ABILITY_1;
let newAbilityIndex = this.abilityCursor;
do {
newAbilityIndex = (newAbilityIndex + 1) % abilityCount;
if (newAbilityIndex === 0) {
if (hasAbility1) {
break; break;
} }
} else if (newAbilityIndex === 1) { } while (newFormIndex !== props.formIndex);
starterAttributes.form = newFormIndex; // store the selected form
this.setSpeciesDetails(this.lastSpecies, undefined, newFormIndex, undefined, undefined, undefined, undefined);
success = true;
}
break;
case Button.CYCLE_GENDER:
if (this.canCycleGender) {
starterAttributes.female = !props.female;
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, !props.female, undefined, undefined, undefined);
success = true;
}
break;
case Button.CYCLE_ABILITY:
if (this.canCycleAbility) {
const abilityCount = this.lastSpecies.getAbilityCount();
const abilityAttr = this.scene.gameData.starterData[this.lastSpecies.speciesId].abilityAttr;
const hasAbility1 = abilityAttr & AbilityAttr.ABILITY_1;
let newAbilityIndex = this.abilityCursor;
do {
newAbilityIndex = (newAbilityIndex + 1) % abilityCount;
if (newAbilityIndex === 0) {
if (hasAbility1) {
break;
}
} else if (newAbilityIndex === 1) {
// If ability 1 and 2 are the same and ability 1 is unlocked, skip over ability 2 // If ability 1 and 2 are the same and ability 1 is unlocked, skip over ability 2
if (this.lastSpecies.ability1 === this.lastSpecies.ability2 && hasAbility1) { if (this.lastSpecies.ability1 === this.lastSpecies.ability2 && hasAbility1) {
newAbilityIndex = (newAbilityIndex + 1) % abilityCount; newAbilityIndex = (newAbilityIndex + 1) % abilityCount;
} }
break;
} else {
if (abilityAttr & AbilityAttr.ABILITY_HIDDEN) {
break; break;
} else {
if (abilityAttr & AbilityAttr.ABILITY_HIDDEN) {
break;
}
} }
} } while (newAbilityIndex !== this.abilityCursor);
} while (newAbilityIndex !== this.abilityCursor); starterAttributes.ability = newAbilityIndex; // store the selected ability
starterAttributes.ability = newAbilityIndex; // store the selected ability
const { visible: tooltipVisible } = this.scene.ui.getTooltip(); const { visible: tooltipVisible } = this.scene.ui.getTooltip();
if (tooltipVisible && this.activeTooltip === "ABILITY") { if (tooltipVisible && this.activeTooltip === "ABILITY") {
const newAbility = allAbilities[this.lastSpecies.getAbility(newAbilityIndex)]; const newAbility = allAbilities[this.lastSpecies.getAbility(newAbilityIndex)];
this.scene.ui.editTooltip(`${newAbility.name}`, `${newAbility.description}`); this.scene.ui.editTooltip(`${newAbility.name}`, `${newAbility.description}`);
} }
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, newAbilityIndex, undefined); this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, newAbilityIndex, undefined);
success = true;
}
break;
case Button.CYCLE_NATURE:
if (this.canCycleNature) {
const natures = this.scene.gameData.getNaturesForAttr(this.speciesStarterDexEntry?.natureAttr);
const natureIndex = natures.indexOf(this.natureCursor);
const newNature = natures[natureIndex < natures.length - 1 ? natureIndex + 1 : 0];
// store cycled nature as default
starterAttributes.nature = newNature as unknown as integer;
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, undefined, newNature, undefined);
success = true;
}
break;
case Button.V:
if (this.canCycleVariant) {
let newVariant = props.variant;
do {
newVariant = (newVariant + 1) % 3;
if (!newVariant) {
if (this.speciesStarterDexEntry!.caughtAttr & DexAttr.DEFAULT_VARIANT) { // TODO: is this bang correct?
break;
}
} else if (newVariant === 1) {
if (this.speciesStarterDexEntry!.caughtAttr & DexAttr.VARIANT_2) { // TODO: is this bang correct?
break;
}
} else {
if (this.speciesStarterDexEntry!.caughtAttr & DexAttr.VARIANT_3) { // TODO: is this bang correct?
break;
}
}
} while (newVariant !== props.variant);
starterAttributes.variant = newVariant; // store the selected variant
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, newVariant as Variant, undefined, undefined);
// Cycle tint based on current sprite tint
const tint = getVariantTint(newVariant as Variant);
this.pokemonShinyIcon.setFrame(getVariantIcon(newVariant as Variant));
this.pokemonShinyIcon.setTint(tint);
success = true;
}
break;
case Button.UP:
if (!this.starterIconsCursorObj.visible) {
if (currentRow > 0) {
if (this.scrollCursor > 0 && currentRow - this.scrollCursor === 0) {
this.scrollCursor--;
this.updateScroll();
}
success = this.setCursor(this.cursor - 9);
} else {
this.filterBarCursor = this.filterBar.getNearestFilter(this.filteredStarterContainers[this.cursor]);
this.setFilterMode(true);
success = true; success = true;
} }
} else { break;
if (this.starterIconsCursorIndex === 0) { case Button.CYCLE_NATURE:
if (this.canCycleNature) {
const natures = this.scene.gameData.getNaturesForAttr(this.speciesStarterDexEntry?.natureAttr);
const natureIndex = natures.indexOf(this.natureCursor);
const newNature = natures[natureIndex < natures.length - 1 ? natureIndex + 1 : 0];
// store cycled nature as default
starterAttributes.nature = newNature as unknown as integer;
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, undefined, newNature, undefined);
success = true;
}
break;
case Button.V:
if (this.canCycleVariant) {
let newVariant = props.variant;
do {
newVariant = (newVariant + 1) % 3;
if (!newVariant) {
if (this.speciesStarterDexEntry!.caughtAttr & DexAttr.DEFAULT_VARIANT) { // TODO: is this bang correct?
break;
}
} else if (newVariant === 1) {
if (this.speciesStarterDexEntry!.caughtAttr & DexAttr.VARIANT_2) { // TODO: is this bang correct?
break;
}
} else {
if (this.speciesStarterDexEntry!.caughtAttr & DexAttr.VARIANT_3) { // TODO: is this bang correct?
break;
}
}
} while (newVariant !== props.variant);
starterAttributes.variant = newVariant; // store the selected variant
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, newVariant as Variant, undefined, undefined);
// Cycle tint based on current sprite tint
const tint = getVariantTint(newVariant as Variant);
this.pokemonShinyIcon.setFrame(getVariantIcon(newVariant as Variant));
this.pokemonShinyIcon.setTint(tint);
success = true;
}
break;
case Button.UP:
if (!this.starterIconsCursorObj.visible) {
if (currentRow > 0) {
if (this.scrollCursor > 0 && currentRow - this.scrollCursor === 0) {
this.scrollCursor--;
this.updateScroll();
}
success = this.setCursor(this.cursor - 9);
} else {
this.filterBarCursor = this.filterBar.getNearestFilter(this.filteredStarterContainers[this.cursor]);
this.setFilterMode(true);
success = true;
}
} else {
if (this.starterIconsCursorIndex === 0) {
// Up from first Pokemon in the team > go to filter // Up from first Pokemon in the team > go to filter
this.starterIconsCursorObj.setVisible(false); this.starterIconsCursorObj.setVisible(false);
this.setSpecies(null); this.setSpecies(null);
this.filterBarCursor = Math.max(1, this.filterBar.numFilters - 1); this.filterBarCursor = Math.max(1, this.filterBar.numFilters - 1);
this.setFilterMode(true); this.setFilterMode(true);
} else { } else {
this.starterIconsCursorIndex--; this.starterIconsCursorIndex--;
this.moveStarterIconsCursor(this.starterIconsCursorIndex); this.moveStarterIconsCursor(this.starterIconsCursorIndex);
}
success = true;
}
break;
case Button.DOWN:
if (!this.starterIconsCursorObj.visible) {
if (currentRow < numOfRows - 1) { // not last row
if (currentRow - this.scrollCursor === 8) { // last row of visible starters
this.scrollCursor++;
} }
success = this.setCursor(this.cursor + 9);
this.updateScroll();
} else if (numOfRows > 1) {
// DOWN from last row of Pokemon > Wrap around to first row
this.scrollCursor = 0;
this.updateScroll();
success = this.setCursor(this.cursor % 9);
} else {
// DOWN from single row of Pokemon > Go to filters
this.filterBarCursor = this.filterBar.getNearestFilter(this.filteredStarterContainers[this.cursor]);
this.setFilterMode(true);
success = true; success = true;
} }
} else { break;
if (this.starterIconsCursorIndex <= this.starterSpecies.length - 2) { case Button.DOWN:
this.starterIconsCursorIndex++; if (!this.starterIconsCursorObj.visible) {
this.moveStarterIconsCursor(this.starterIconsCursorIndex); if (currentRow < numOfRows - 1) { // not last row
if (currentRow - this.scrollCursor === 8) { // last row of visible starters
this.scrollCursor++;
}
success = this.setCursor(this.cursor + 9);
this.updateScroll();
} else if (numOfRows > 1) {
// DOWN from last row of Pokemon > Wrap around to first row
this.scrollCursor = 0;
this.updateScroll();
success = this.setCursor(this.cursor % 9);
} else {
// DOWN from single row of Pokemon > Go to filters
this.filterBarCursor = this.filterBar.getNearestFilter(this.filteredStarterContainers[this.cursor]);
this.setFilterMode(true);
success = true;
}
} else { } else {
this.starterIconsCursorObj.setVisible(false); if (this.starterIconsCursorIndex <= this.starterSpecies.length - 2) {
this.setSpecies(null); this.starterIconsCursorIndex++;
this.startCursorObj.setVisible(true); this.moveStarterIconsCursor(this.starterIconsCursorIndex);
} else {
this.starterIconsCursorObj.setVisible(false);
this.setSpecies(null);
this.startCursorObj.setVisible(true);
}
success = true;
} }
success = true; break;
} case Button.LEFT:
break; if (!this.starterIconsCursorObj.visible) {
case Button.LEFT: if (this.cursor % 9 !== 0) {
if (!this.starterIconsCursorObj.visible) { success = this.setCursor(this.cursor - 1);
if (this.cursor % 9 !== 0) { } else {
success = this.setCursor(this.cursor - 1);
} else {
// LEFT from filtered Pokemon, on the left edge // LEFT from filtered Pokemon, on the left edge
if (this.starterSpecies.length === 0) { if (this.starterSpecies.length === 0) {
// no starter in team > wrap around to the last column // no starter in team > wrap around to the last column
success = this.setCursor(this.cursor + Math.min(8, numberOfStarters - this.cursor)); success = this.setCursor(this.cursor + Math.min(8, numberOfStarters - this.cursor));
} else if (onScreenCurrentRow < 7) { } else if (onScreenCurrentRow < 7) {
// at least one pokemon in team > for the first 7 rows, go to closest starter // at least one pokemon in team > for the first 7 rows, go to closest starter
this.cursorObj.setVisible(false); this.cursorObj.setVisible(false);
this.starterIconsCursorIndex = findClosestStarterIndex(this.cursorObj.y - 1, this.starterSpecies.length); this.starterIconsCursorIndex = findClosestStarterIndex(this.cursorObj.y - 1, this.starterSpecies.length);
this.moveStarterIconsCursor(this.starterIconsCursorIndex); this.moveStarterIconsCursor(this.starterIconsCursorIndex);
} else { } else {
// at least one pokemon in team > from the bottom 2 rows, go to start run button // at least one pokemon in team > from the bottom 2 rows, go to start run button
this.cursorObj.setVisible(false); this.cursorObj.setVisible(false);
this.setSpecies(null); this.setSpecies(null);
this.startCursorObj.setVisible(true); this.startCursorObj.setVisible(true);
}
success = true;
} }
success = true; } else if (numberOfStarters > 0) {
}
} else if (numberOfStarters > 0) {
// LEFT from team > Go to closest filtered Pokemon // LEFT from team > Go to closest filtered Pokemon
const closestRowIndex = findClosestStarterRow(this.starterIconsCursorIndex, onScreenNumberOfRows); const closestRowIndex = findClosestStarterRow(this.starterIconsCursorIndex, onScreenNumberOfRows);
this.starterIconsCursorObj.setVisible(false); this.starterIconsCursorObj.setVisible(false);
this.cursorObj.setVisible(true); this.cursorObj.setVisible(true);
this.setCursor(Math.min(onScreenFirstIndex + closestRowIndex * 9 + 8, onScreenLastIndex)); this.setCursor(Math.min(onScreenFirstIndex + closestRowIndex * 9 + 8, onScreenLastIndex));
success = true;
} else {
// LEFT from team and no Pokemon in filter > do nothing
success = false;
}
break;
case Button.RIGHT:
if (!this.starterIconsCursorObj.visible) {
// is not right edge
if (this.cursor % 9 < (currentRow < numOfRows - 1 ? 8 : (numberOfStarters - 1) % 9)) {
success = this.setCursor(this.cursor + 1);
} else {
// RIGHT from filtered Pokemon, on the right edge
if (this.starterSpecies.length === 0) {
// no selected starter in team > wrap around to the first column
success = this.setCursor(this.cursor - Math.min(8, this.cursor % 9));
} else if (onScreenCurrentRow < 7) {
// at least one pokemon in team > for the first 7 rows, go to closest starter
this.cursorObj.setVisible(false);
this.starterIconsCursorIndex = findClosestStarterIndex(this.cursorObj.y - 1, this.starterSpecies.length);
this.moveStarterIconsCursor(this.starterIconsCursorIndex);
} else {
// at least one pokemon in team > from the bottom 2 rows, go to start run button
this.cursorObj.setVisible(false);
this.setSpecies(null);
this.startCursorObj.setVisible(true);
}
success = true; success = true;
} else {
// LEFT from team and no Pokemon in filter > do nothing
success = false;
} }
} else if (numberOfStarters > 0) { break;
case Button.RIGHT:
if (!this.starterIconsCursorObj.visible) {
// is not right edge
if (this.cursor % 9 < (currentRow < numOfRows - 1 ? 8 : (numberOfStarters - 1) % 9)) {
success = this.setCursor(this.cursor + 1);
} else {
// RIGHT from filtered Pokemon, on the right edge
if (this.starterSpecies.length === 0) {
// no selected starter in team > wrap around to the first column
success = this.setCursor(this.cursor - Math.min(8, this.cursor % 9));
} else if (onScreenCurrentRow < 7) {
// at least one pokemon in team > for the first 7 rows, go to closest starter
this.cursorObj.setVisible(false);
this.starterIconsCursorIndex = findClosestStarterIndex(this.cursorObj.y - 1, this.starterSpecies.length);
this.moveStarterIconsCursor(this.starterIconsCursorIndex);
} else {
// at least one pokemon in team > from the bottom 2 rows, go to start run button
this.cursorObj.setVisible(false);
this.setSpecies(null);
this.startCursorObj.setVisible(true);
}
success = true;
}
} else if (numberOfStarters > 0) {
// RIGHT from team > Go to closest filtered Pokemon // RIGHT from team > Go to closest filtered Pokemon
const closestRowIndex = findClosestStarterRow(this.starterIconsCursorIndex, onScreenNumberOfRows); const closestRowIndex = findClosestStarterRow(this.starterIconsCursorIndex, onScreenNumberOfRows);
this.starterIconsCursorObj.setVisible(false); this.starterIconsCursorObj.setVisible(false);
this.cursorObj.setVisible(true); this.cursorObj.setVisible(true);
this.setCursor(Math.min(onScreenFirstIndex + closestRowIndex * 9, onScreenLastIndex - (onScreenLastIndex % 9))); this.setCursor(Math.min(onScreenFirstIndex + closestRowIndex * 9, onScreenLastIndex - (onScreenLastIndex % 9)));
success = true; success = true;
} else { } else {
// RIGHT from team and no Pokemon in filter > do nothing // RIGHT from team and no Pokemon in filter > do nothing
success = false; success = false;
} }
break; break;
} }
} }
} }
@ -2210,29 +2210,29 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
if (gamepadType === "touch") { if (gamepadType === "touch") {
gamepadType = "keyboard"; gamepadType = "keyboard";
switch (iconSetting) { switch (iconSetting) {
case SettingKeyboard.Button_Cycle_Shiny: case SettingKeyboard.Button_Cycle_Shiny:
iconPath = "R.png"; iconPath = "R.png";
break; break;
case SettingKeyboard.Button_Cycle_Form: case SettingKeyboard.Button_Cycle_Form:
iconPath = "F.png"; iconPath = "F.png";
break; break;
case SettingKeyboard.Button_Cycle_Gender: case SettingKeyboard.Button_Cycle_Gender:
iconPath = "G.png"; iconPath = "G.png";
break; break;
case SettingKeyboard.Button_Cycle_Ability: case SettingKeyboard.Button_Cycle_Ability:
iconPath = "E.png"; iconPath = "E.png";
break; break;
case SettingKeyboard.Button_Cycle_Nature: case SettingKeyboard.Button_Cycle_Nature:
iconPath = "N.png"; iconPath = "N.png";
break; break;
case SettingKeyboard.Button_Cycle_Variant: case SettingKeyboard.Button_Cycle_Variant:
iconPath = "V.png"; iconPath = "V.png";
break; break;
case SettingKeyboard.Button_Stats: case SettingKeyboard.Button_Stats:
iconPath = "C.png"; iconPath = "C.png";
break; break;
default: default:
break; break;
} }
} else { } else {
iconPath = this.scene.inputController?.getIconForLatestInputRecorded(iconSetting); iconPath = this.scene.inputController?.getIconForLatestInputRecorded(iconSetting);
@ -2323,12 +2323,12 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
getValueLimit(): integer { getValueLimit(): integer {
const valueLimit = new Utils.IntegerHolder(0); const valueLimit = new Utils.IntegerHolder(0);
switch (this.scene.gameMode.modeId) { switch (this.scene.gameMode.modeId) {
case GameModes.ENDLESS: case GameModes.ENDLESS:
case GameModes.SPLICED_ENDLESS: case GameModes.SPLICED_ENDLESS:
valueLimit.value = 15; valueLimit.value = 15;
break; break;
default: default:
valueLimit.value = 10; valueLimit.value = 10;
} }
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_POINTS, valueLimit); Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_POINTS, valueLimit);
@ -2532,22 +2532,22 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
const sort = this.filterBar.getVals(DropDownColumn.SORT)[0]; const sort = this.filterBar.getVals(DropDownColumn.SORT)[0];
this.filteredStarterContainers.sort((a, b) => { this.filteredStarterContainers.sort((a, b) => {
switch (sort.val) { switch (sort.val) {
default: default:
break; break;
case SortCriteria.NUMBER: case SortCriteria.NUMBER:
return (a.species.speciesId - b.species.speciesId) * -sort.dir; return (a.species.speciesId - b.species.speciesId) * -sort.dir;
case SortCriteria.COST: case SortCriteria.COST:
return (a.cost - b.cost) * -sort.dir; return (a.cost - b.cost) * -sort.dir;
case SortCriteria.CANDY: case SortCriteria.CANDY:
const candyCountA = this.scene.gameData.starterData[a.species.speciesId].candyCount; const candyCountA = this.scene.gameData.starterData[a.species.speciesId].candyCount;
const candyCountB = this.scene.gameData.starterData[b.species.speciesId].candyCount; const candyCountB = this.scene.gameData.starterData[b.species.speciesId].candyCount;
return (candyCountA - candyCountB) * -sort.dir; return (candyCountA - candyCountB) * -sort.dir;
case SortCriteria.IV: case SortCriteria.IV:
const avgIVsA = this.scene.gameData.dexData[a.species.speciesId].ivs.reduce((a, b) => a + b, 0) / this.scene.gameData.dexData[a.species.speciesId].ivs.length; const avgIVsA = this.scene.gameData.dexData[a.species.speciesId].ivs.reduce((a, b) => a + b, 0) / this.scene.gameData.dexData[a.species.speciesId].ivs.length;
const avgIVsB = this.scene.gameData.dexData[b.species.speciesId].ivs.reduce((a, b) => a + b, 0) / this.scene.gameData.dexData[b.species.speciesId].ivs.length; const avgIVsB = this.scene.gameData.dexData[b.species.speciesId].ivs.reduce((a, b) => a + b, 0) / this.scene.gameData.dexData[b.species.speciesId].ivs.length;
return (avgIVsA - avgIVsB) * -sort.dir; return (avgIVsA - avgIVsB) * -sort.dir;
case SortCriteria.NAME: case SortCriteria.NAME:
return a.species.name.localeCompare(b.species.name) * -sort.dir; return a.species.name.localeCompare(b.species.name) * -sort.dir;
} }
return 0; return 0;
}); });
@ -3362,16 +3362,16 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
starter.label.setText(valueStr); starter.label.setText(valueStr);
let textStyle: TextStyle; let textStyle: TextStyle;
switch (baseStarterValue - starterValue) { switch (baseStarterValue - starterValue) {
case 0: case 0:
textStyle = TextStyle.WINDOW; textStyle = TextStyle.WINDOW;
break; break;
case 1: case 1:
case 0.5: case 0.5:
textStyle = TextStyle.SUMMARY_BLUE; textStyle = TextStyle.SUMMARY_BLUE;
break; break;
default: default:
textStyle = TextStyle.SUMMARY_GOLD; textStyle = TextStyle.SUMMARY_GOLD;
break; break;
} }
if (baseStarterValue - starterValue > 0) { if (baseStarterValue - starterValue > 0) {
starter.label.setColor(this.getTextColor(textStyle)); starter.label.setColor(this.getTextColor(textStyle));

View File

@ -406,22 +406,22 @@ export default class SummaryUiHandler extends UiHandler {
this.genderText.setShadowColor(getGenderColor(this.pokemon.getGender(true), true)); this.genderText.setShadowColor(getGenderColor(this.pokemon.getGender(true), true));
switch (this.summaryUiMode) { switch (this.summaryUiMode) {
case SummaryUiMode.DEFAULT: case SummaryUiMode.DEFAULT:
const page = args.length < 2 ? Page.PROFILE : args[2] as Page; const page = args.length < 2 ? Page.PROFILE : args[2] as Page;
this.hideMoveEffect(true); this.hideMoveEffect(true);
this.setCursor(page); this.setCursor(page);
if (args.length > 3) { if (args.length > 3) {
this.selectCallback = args[3]; this.selectCallback = args[3];
} }
break; break;
case SummaryUiMode.LEARN_MOVE: case SummaryUiMode.LEARN_MOVE:
this.newMove = args[2] as Move; this.newMove = args[2] as Move;
this.moveSelectFunction = args[3] as Function; this.moveSelectFunction = args[3] as Function;
this.showMoveEffect(true); this.showMoveEffect(true);
this.setCursor(Page.MOVES); this.setCursor(Page.MOVES);
this.showMoveSelect(); this.showMoveSelect();
break; break;
} }
const fromSummary = args.length >= 2; const fromSummary = args.length >= 2;
@ -489,25 +489,25 @@ export default class SummaryUiHandler extends UiHandler {
success = true; success = true;
} else { } else {
switch (button) { switch (button) {
case Button.UP: case Button.UP:
success = this.setCursor(this.moveCursor ? this.moveCursor - 1 : 4); success = this.setCursor(this.moveCursor ? this.moveCursor - 1 : 4);
break;
case Button.DOWN:
success = this.setCursor(this.moveCursor < 4 ? this.moveCursor + 1 : 0);
break;
case Button.LEFT:
this.moveSelect = false;
this.setCursor(Page.STATS);
if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) {
this.hideMoveEffect();
this.destroyBlinkCursor();
success = true;
break; break;
} else { case Button.DOWN:
this.hideMoveSelect(); success = this.setCursor(this.moveCursor < 4 ? this.moveCursor + 1 : 0);
success = true;
break; break;
} case Button.LEFT:
this.moveSelect = false;
this.setCursor(Page.STATS);
if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) {
this.hideMoveEffect();
this.destroyBlinkCursor();
success = true;
break;
} else {
this.hideMoveSelect();
success = true;
break;
}
} }
} }
} else { } else {
@ -546,35 +546,35 @@ export default class SummaryUiHandler extends UiHandler {
} else { } else {
const pages = Utils.getEnumValues(Page); const pages = Utils.getEnumValues(Page);
switch (button) { switch (button) {
case Button.UP: case Button.UP:
case Button.DOWN: case Button.DOWN:
if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) { if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) {
break; break;
} else if (!fromPartyMode) { } else if (!fromPartyMode) {
break; break;
}
const isDown = button === Button.DOWN;
const party = this.scene.getParty();
const partyMemberIndex = this.pokemon ? party.indexOf(this.pokemon) : -1;
if ((isDown && partyMemberIndex < party.length - 1) || (!isDown && partyMemberIndex)) {
const page = this.cursor;
this.clear();
this.show([ party[partyMemberIndex + (isDown ? 1 : -1)], this.summaryUiMode, page ]);
}
break;
case Button.LEFT:
if (this.cursor) {
success = this.setCursor(this.cursor - 1);
}
break;
case Button.RIGHT:
if (this.cursor < pages.length - 1) {
success = this.setCursor(this.cursor + 1);
if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE && this.cursor === Page.MOVES) {
this.moveSelect = true;
} }
} const isDown = button === Button.DOWN;
break; const party = this.scene.getParty();
const partyMemberIndex = this.pokemon ? party.indexOf(this.pokemon) : -1;
if ((isDown && partyMemberIndex < party.length - 1) || (!isDown && partyMemberIndex)) {
const page = this.cursor;
this.clear();
this.show([ party[partyMemberIndex + (isDown ? 1 : -1)], this.summaryUiMode, page ]);
}
break;
case Button.LEFT:
if (this.cursor) {
success = this.setCursor(this.cursor - 1);
}
break;
case Button.RIGHT:
if (this.cursor < pages.length - 1) {
success = this.setCursor(this.cursor + 1);
if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE && this.cursor === Page.MOVES) {
this.moveSelect = true;
}
}
break;
} }
} }
} }
@ -730,308 +730,308 @@ export default class SummaryUiHandler extends UiHandler {
} }
switch (page) { switch (page) {
case Page.PROFILE: case Page.PROFILE:
const profileContainer = this.scene.add.container(0, -pageBg.height); const profileContainer = this.scene.add.container(0, -pageBg.height);
pageContainer.add(profileContainer); pageContainer.add(profileContainer);
// TODO: should add field for original trainer name to Pokemon object, to support gift/traded Pokemon from MEs // TODO: should add field for original trainer name to Pokemon object, to support gift/traded Pokemon from MEs
const trainerText = addBBCodeTextObject(this.scene, 7, 12, `${i18next.t("pokemonSummary:ot")}/${getBBCodeFrag(loggedInUser?.username || i18next.t("pokemonSummary:unknown"), this.scene.gameData.gender === PlayerGender.FEMALE ? TextStyle.SUMMARY_PINK : TextStyle.SUMMARY_BLUE)}`, TextStyle.SUMMARY_ALT); const trainerText = addBBCodeTextObject(this.scene, 7, 12, `${i18next.t("pokemonSummary:ot")}/${getBBCodeFrag(loggedInUser?.username || i18next.t("pokemonSummary:unknown"), this.scene.gameData.gender === PlayerGender.FEMALE ? TextStyle.SUMMARY_PINK : TextStyle.SUMMARY_BLUE)}`, TextStyle.SUMMARY_ALT);
trainerText.setOrigin(0, 0); trainerText.setOrigin(0, 0);
profileContainer.add(trainerText); profileContainer.add(trainerText);
const trainerIdText = addTextObject(this.scene, 174, 12, this.scene.gameData.trainerId.toString(), TextStyle.SUMMARY_ALT); const trainerIdText = addTextObject(this.scene, 174, 12, this.scene.gameData.trainerId.toString(), TextStyle.SUMMARY_ALT);
trainerIdText.setOrigin(0, 0); trainerIdText.setOrigin(0, 0);
profileContainer.add(trainerIdText); profileContainer.add(trainerIdText);
const typeLabel = addTextObject(this.scene, 7, 28, `${i18next.t("pokemonSummary:type")}/`, TextStyle.WINDOW_ALT); const typeLabel = addTextObject(this.scene, 7, 28, `${i18next.t("pokemonSummary:type")}/`, TextStyle.WINDOW_ALT);
typeLabel.setOrigin(0, 0); typeLabel.setOrigin(0, 0);
profileContainer.add(typeLabel); profileContainer.add(typeLabel);
const getTypeIcon = (index: integer, type: Type, tera: boolean = false) => { const getTypeIcon = (index: integer, type: Type, tera: boolean = false) => {
const xCoord = typeLabel.width * typeLabel.scale + 9 + 34 * index; const xCoord = typeLabel.width * typeLabel.scale + 9 + 34 * index;
const typeIcon = !tera const typeIcon = !tera
? this.scene.add.sprite(xCoord, 42, Utils.getLocalizedSpriteKey("types"), Type[type].toLowerCase()) ? this.scene.add.sprite(xCoord, 42, Utils.getLocalizedSpriteKey("types"), Type[type].toLowerCase())
: this.scene.add.sprite(xCoord, 42, "type_tera"); : this.scene.add.sprite(xCoord, 42, "type_tera");
if (tera) { if (tera) {
typeIcon.setScale(0.5); typeIcon.setScale(0.5);
const typeRgb = getTypeRgb(type); const typeRgb = getTypeRgb(type);
typeIcon.setTint(Phaser.Display.Color.GetColor(typeRgb[0], typeRgb[1], typeRgb[2])); typeIcon.setTint(Phaser.Display.Color.GetColor(typeRgb[0], typeRgb[1], typeRgb[2]));
}
typeIcon.setOrigin(0, 1);
return typeIcon;
};
const types = this.pokemon?.getTypes(false, false, true)!; // TODO: is this bang correct?
profileContainer.add(getTypeIcon(0, types[0]));
if (types.length > 1) {
profileContainer.add(getTypeIcon(1, types[1]));
}
if (this.pokemon?.isTerastallized()) {
profileContainer.add(getTypeIcon(types.length, this.pokemon.getTeraType(), true));
} }
typeIcon.setOrigin(0, 1);
return typeIcon;
};
const types = this.pokemon?.getTypes(false, false, true)!; // TODO: is this bang correct? if (this.pokemon?.getLuck()) {
profileContainer.add(getTypeIcon(0, types[0])); const luckLabelText = addTextObject(this.scene, 141, 28, i18next.t("common:luckIndicator"), TextStyle.SUMMARY_ALT);
if (types.length > 1) { luckLabelText.setOrigin(0, 0);
profileContainer.add(getTypeIcon(1, types[1])); profileContainer.add(luckLabelText);
}
if (this.pokemon?.isTerastallized()) {
profileContainer.add(getTypeIcon(types.length, this.pokemon.getTeraType(), true));
}
if (this.pokemon?.getLuck()) { const luckText = addTextObject(this.scene, 141 + luckLabelText.displayWidth + 2, 28, this.pokemon.getLuck().toString(), TextStyle.SUMMARY);
const luckLabelText = addTextObject(this.scene, 141, 28, i18next.t("common:luckIndicator"), TextStyle.SUMMARY_ALT); luckText.setOrigin(0, 0);
luckLabelText.setOrigin(0, 0); luckText.setTint(getVariantTint((Math.min(this.pokemon.getLuck() - 1, 2)) as Variant));
profileContainer.add(luckLabelText); profileContainer.add(luckText);
}
const luckText = addTextObject(this.scene, 141 + luckLabelText.displayWidth + 2, 28, this.pokemon.getLuck().toString(), TextStyle.SUMMARY); this.abilityContainer = {
luckText.setOrigin(0, 0); labelImage: this.scene.add.image(0, 0, "summary_profile_ability"),
luckText.setTint(getVariantTint((Math.min(this.pokemon.getLuck() - 1, 2)) as Variant)); ability: this.pokemon?.getAbility(true)!, // TODO: is this bang correct?
profileContainer.add(luckText);
}
this.abilityContainer = {
labelImage: this.scene.add.image(0, 0, "summary_profile_ability"),
ability: this.pokemon?.getAbility(true)!, // TODO: is this bang correct?
nameText: null,
descriptionText: null };
const allAbilityInfo = [ this.abilityContainer ]; // Creates an array to iterate through
// Only add to the array and set up displaying a passive if it's unlocked
if (this.pokemon?.hasPassive()) {
this.passiveContainer = {
labelImage: this.scene.add.image(0, 0, "summary_profile_passive"),
ability: this.pokemon.getPassiveAbility(),
nameText: null, nameText: null,
descriptionText: null }; descriptionText: null };
allAbilityInfo.push(this.passiveContainer);
// Sets up the pixel button prompt image const allAbilityInfo = [ this.abilityContainer ]; // Creates an array to iterate through
this.abilityPrompt = this.scene.add.image(0, 0, !this.scene.inputController?.gamepadSupport ? "summary_profile_prompt_z" : "summary_profile_prompt_a"); // Only add to the array and set up displaying a passive if it's unlocked
this.abilityPrompt.setPosition(8, 43); if (this.pokemon?.hasPassive()) {
this.abilityPrompt.setVisible(true); this.passiveContainer = {
this.abilityPrompt.setOrigin(0, 0); labelImage: this.scene.add.image(0, 0, "summary_profile_passive"),
profileContainer.add(this.abilityPrompt); ability: this.pokemon.getPassiveAbility(),
} nameText: null,
descriptionText: null };
allAbilityInfo.push(this.passiveContainer);
allAbilityInfo.forEach(abilityInfo => { // Sets up the pixel button prompt image
abilityInfo.labelImage.setPosition(17, 43); this.abilityPrompt = this.scene.add.image(0, 0, !this.scene.inputController?.gamepadSupport ? "summary_profile_prompt_z" : "summary_profile_prompt_a");
abilityInfo.labelImage.setVisible(true); this.abilityPrompt.setPosition(8, 43);
abilityInfo.labelImage.setOrigin(0, 0); this.abilityPrompt.setVisible(true);
profileContainer.add(abilityInfo.labelImage); this.abilityPrompt.setOrigin(0, 0);
profileContainer.add(this.abilityPrompt);
abilityInfo.nameText = addTextObject(this.scene, 7, 66, abilityInfo.ability?.name!, TextStyle.SUMMARY_ALT); // TODO: is this bang correct?
abilityInfo.nameText.setOrigin(0, 1);
profileContainer.add(abilityInfo.nameText);
abilityInfo.descriptionText = addTextObject(this.scene, 7, 69, abilityInfo.ability?.description!, TextStyle.WINDOW_ALT, { wordWrap: { width: 1224 }}); // TODO: is this bang correct?
abilityInfo.descriptionText.setOrigin(0, 0);
profileContainer.add(abilityInfo.descriptionText);
// Sets up the mask that hides the description text to give an illusion of scrolling
const descriptionTextMaskRect = this.scene.make.graphics({});
descriptionTextMaskRect.setScale(6);
descriptionTextMaskRect.fillStyle(0xFFFFFF);
descriptionTextMaskRect.beginPath();
descriptionTextMaskRect.fillRect(110, 90.5, 206, 31);
const abilityDescriptionTextMask = descriptionTextMaskRect.createGeometryMask();
abilityInfo.descriptionText.setMask(abilityDescriptionTextMask);
const abilityDescriptionLineCount = Math.floor(abilityInfo.descriptionText.displayHeight / 14.83);
// Animates the description text moving upwards
if (abilityDescriptionLineCount > 2) {
abilityInfo.descriptionText.setY(69);
this.descriptionScrollTween = this.scene.tweens.add({
targets: abilityInfo.descriptionText,
delay: Utils.fixedInt(2000),
loop: -1,
hold: Utils.fixedInt(2000),
duration: Utils.fixedInt((abilityDescriptionLineCount - 2) * 2000),
y: `-=${14.83 * (abilityDescriptionLineCount - 2)}`
});
} }
});
// Turn off visibility of passive info by default
this.passiveContainer?.labelImage.setVisible(false);
this.passiveContainer?.nameText?.setVisible(false);
this.passiveContainer?.descriptionText?.setVisible(false);
const closeFragment = getBBCodeFrag("", TextStyle.WINDOW_ALT); allAbilityInfo.forEach(abilityInfo => {
const rawNature = Utils.toReadableString(Nature[this.pokemon?.getNature()!]); // TODO: is this bang correct? abilityInfo.labelImage.setPosition(17, 43);
const nature = `${getBBCodeFrag(Utils.toReadableString(getNatureName(this.pokemon?.getNature()!)), TextStyle.SUMMARY_RED)}${closeFragment}`; // TODO: is this bang correct? abilityInfo.labelImage.setVisible(true);
abilityInfo.labelImage.setOrigin(0, 0);
profileContainer.add(abilityInfo.labelImage);
const memoString = i18next.t("pokemonSummary:memoString", { abilityInfo.nameText = addTextObject(this.scene, 7, 66, abilityInfo.ability?.name!, TextStyle.SUMMARY_ALT); // TODO: is this bang correct?
metFragment: i18next.t(`pokemonSummary:metFragment.${this.pokemon?.metBiome === -1 ? "apparently" : "normal"}`, { abilityInfo.nameText.setOrigin(0, 1);
biome: `${getBBCodeFrag(getBiomeName(this.pokemon?.metBiome!), TextStyle.SUMMARY_RED)}${closeFragment}`, // TODO: is this bang correct? profileContainer.add(abilityInfo.nameText);
level: `${getBBCodeFrag(this.pokemon?.metLevel.toString()!, TextStyle.SUMMARY_RED)}${closeFragment}`, // TODO: is this bang correct?
wave: `${getBBCodeFrag((this.pokemon?.metWave ? this.pokemon.metWave.toString()! : i18next.t("pokemonSummary:unknownTrainer")), TextStyle.SUMMARY_RED)}${closeFragment}`,
}),
natureFragment: i18next.t(`pokemonSummary:natureFragment.${rawNature}`, { nature: nature })
});
const memoText = addBBCodeTextObject(this.scene, 7, 113, String(memoString), TextStyle.WINDOW_ALT); abilityInfo.descriptionText = addTextObject(this.scene, 7, 69, abilityInfo.ability?.description!, TextStyle.WINDOW_ALT, { wordWrap: { width: 1224 }}); // TODO: is this bang correct?
memoText.setOrigin(0, 0); abilityInfo.descriptionText.setOrigin(0, 0);
profileContainer.add(memoText); profileContainer.add(abilityInfo.descriptionText);
break;
case Page.STATS:
const statsContainer = this.scene.add.container(0, -pageBg.height);
pageContainer.add(statsContainer);
PERMANENT_STATS.forEach((stat, s) => { // Sets up the mask that hides the description text to give an illusion of scrolling
const statName = i18next.t(getStatKey(stat)); const descriptionTextMaskRect = this.scene.make.graphics({});
const rowIndex = s % 3; descriptionTextMaskRect.setScale(6);
const colIndex = Math.floor(s / 3); descriptionTextMaskRect.fillStyle(0xFFFFFF);
descriptionTextMaskRect.beginPath();
descriptionTextMaskRect.fillRect(110, 90.5, 206, 31);
const natureStatMultiplier = getNatureStatMultiplier(this.pokemon?.getNature()!, s); // TODO: is this bang correct? const abilityDescriptionTextMask = descriptionTextMaskRect.createGeometryMask();
const statLabel = addTextObject(this.scene, 27 + 115 * colIndex + (colIndex === 1 ? 5 : 0), 56 + 16 * rowIndex, statName, natureStatMultiplier === 1 ? TextStyle.SUMMARY : natureStatMultiplier > 1 ? TextStyle.SUMMARY_PINK : TextStyle.SUMMARY_BLUE); abilityInfo.descriptionText.setMask(abilityDescriptionTextMask);
statLabel.setOrigin(0.5, 0);
statsContainer.add(statLabel);
const statValueText = stat !== Stat.HP const abilityDescriptionLineCount = Math.floor(abilityInfo.descriptionText.displayHeight / 14.83);
? Utils.formatStat(this.pokemon?.getStat(stat)!) // TODO: is this bang correct?
: `${Utils.formatStat(this.pokemon?.hp!, true)}/${Utils.formatStat(this.pokemon?.getMaxHp()!, true)}`; // TODO: are those bangs correct?
const statValue = addTextObject(this.scene, 120 + 88 * colIndex, 56 + 16 * rowIndex, statValueText, TextStyle.WINDOW_ALT); // Animates the description text moving upwards
statValue.setOrigin(1, 0); if (abilityDescriptionLineCount > 2) {
statsContainer.add(statValue); abilityInfo.descriptionText.setY(69);
}); this.descriptionScrollTween = this.scene.tweens.add({
targets: abilityInfo.descriptionText,
delay: Utils.fixedInt(2000),
loop: -1,
hold: Utils.fixedInt(2000),
duration: Utils.fixedInt((abilityDescriptionLineCount - 2) * 2000),
y: `-=${14.83 * (abilityDescriptionLineCount - 2)}`
});
}
});
// Turn off visibility of passive info by default
this.passiveContainer?.labelImage.setVisible(false);
this.passiveContainer?.nameText?.setVisible(false);
this.passiveContainer?.descriptionText?.setVisible(false);
const itemModifiers = (this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier const closeFragment = getBBCodeFrag("", TextStyle.WINDOW_ALT);
const rawNature = Utils.toReadableString(Nature[this.pokemon?.getNature()!]); // TODO: is this bang correct?
const nature = `${getBBCodeFrag(Utils.toReadableString(getNatureName(this.pokemon?.getNature()!)), TextStyle.SUMMARY_RED)}${closeFragment}`; // TODO: is this bang correct?
const memoString = i18next.t("pokemonSummary:memoString", {
metFragment: i18next.t(`pokemonSummary:metFragment.${this.pokemon?.metBiome === -1 ? "apparently" : "normal"}`, {
biome: `${getBBCodeFrag(getBiomeName(this.pokemon?.metBiome!), TextStyle.SUMMARY_RED)}${closeFragment}`, // TODO: is this bang correct?
level: `${getBBCodeFrag(this.pokemon?.metLevel.toString()!, TextStyle.SUMMARY_RED)}${closeFragment}`, // TODO: is this bang correct?
wave: `${getBBCodeFrag((this.pokemon?.metWave ? this.pokemon.metWave.toString()! : i18next.t("pokemonSummary:unknownTrainer")), TextStyle.SUMMARY_RED)}${closeFragment}`,
}),
natureFragment: i18next.t(`pokemonSummary:natureFragment.${rawNature}`, { nature: nature })
});
const memoText = addBBCodeTextObject(this.scene, 7, 113, String(memoString), TextStyle.WINDOW_ALT);
memoText.setOrigin(0, 0);
profileContainer.add(memoText);
break;
case Page.STATS:
const statsContainer = this.scene.add.container(0, -pageBg.height);
pageContainer.add(statsContainer);
PERMANENT_STATS.forEach((stat, s) => {
const statName = i18next.t(getStatKey(stat));
const rowIndex = s % 3;
const colIndex = Math.floor(s / 3);
const natureStatMultiplier = getNatureStatMultiplier(this.pokemon?.getNature()!, s); // TODO: is this bang correct?
const statLabel = addTextObject(this.scene, 27 + 115 * colIndex + (colIndex === 1 ? 5 : 0), 56 + 16 * rowIndex, statName, natureStatMultiplier === 1 ? TextStyle.SUMMARY : natureStatMultiplier > 1 ? TextStyle.SUMMARY_PINK : TextStyle.SUMMARY_BLUE);
statLabel.setOrigin(0.5, 0);
statsContainer.add(statLabel);
const statValueText = stat !== Stat.HP
? Utils.formatStat(this.pokemon?.getStat(stat)!) // TODO: is this bang correct?
: `${Utils.formatStat(this.pokemon?.hp!, true)}/${Utils.formatStat(this.pokemon?.getMaxHp()!, true)}`; // TODO: are those bangs correct?
const statValue = addTextObject(this.scene, 120 + 88 * colIndex, 56 + 16 * rowIndex, statValueText, TextStyle.WINDOW_ALT);
statValue.setOrigin(1, 0);
statsContainer.add(statValue);
});
const itemModifiers = (this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier
&& m.pokemonId === this.pokemon?.id, this.playerParty) as PokemonHeldItemModifier[]) && m.pokemonId === this.pokemon?.id, this.playerParty) as PokemonHeldItemModifier[])
.sort(modifierSortFunc); .sort(modifierSortFunc);
itemModifiers.forEach((item, i) => { itemModifiers.forEach((item, i) => {
const icon = item.getIcon(this.scene, true); const icon = item.getIcon(this.scene, true);
icon.setPosition((i % 17) * 12 + 3, 14 * Math.floor(i / 17) + 15); icon.setPosition((i % 17) * 12 + 3, 14 * Math.floor(i / 17) + 15);
statsContainer.add(icon); statsContainer.add(icon);
icon.setInteractive(new Phaser.Geom.Rectangle(0, 0, 32, 32), Phaser.Geom.Rectangle.Contains); icon.setInteractive(new Phaser.Geom.Rectangle(0, 0, 32, 32), Phaser.Geom.Rectangle.Contains);
icon.on("pointerover", () => (this.scene as BattleScene).ui.showTooltip(item.type.name, item.type.getDescription(this.scene), true)); icon.on("pointerover", () => (this.scene as BattleScene).ui.showTooltip(item.type.name, item.type.getDescription(this.scene), true));
icon.on("pointerout", () => (this.scene as BattleScene).ui.hideTooltip()); icon.on("pointerout", () => (this.scene as BattleScene).ui.hideTooltip());
}); });
const pkmLvl = this.pokemon?.level!; // TODO: is this bang correct? const pkmLvl = this.pokemon?.level!; // TODO: is this bang correct?
const pkmLvlExp = this.pokemon?.levelExp!; // TODO: is this bang correct? const pkmLvlExp = this.pokemon?.levelExp!; // TODO: is this bang correct?
const pkmExp = this.pokemon?.exp!; // TODO: is this bang correct? const pkmExp = this.pokemon?.exp!; // TODO: is this bang correct?
const pkmSpeciesGrowthRate = this.pokemon?.species.growthRate!; // TODO: is this bang correct? const pkmSpeciesGrowthRate = this.pokemon?.species.growthRate!; // TODO: is this bang correct?
const relLvExp = getLevelRelExp(pkmLvl + 1, pkmSpeciesGrowthRate); const relLvExp = getLevelRelExp(pkmLvl + 1, pkmSpeciesGrowthRate);
const expRatio = pkmLvl < this.scene.getMaxExpLevel() ? pkmLvlExp / relLvExp : 0; const expRatio = pkmLvl < this.scene.getMaxExpLevel() ? pkmLvlExp / relLvExp : 0;
const expLabel = addTextObject(this.scene, 6, 112, i18next.t("pokemonSummary:expPoints"), TextStyle.SUMMARY); const expLabel = addTextObject(this.scene, 6, 112, i18next.t("pokemonSummary:expPoints"), TextStyle.SUMMARY);
expLabel.setOrigin(0, 0); expLabel.setOrigin(0, 0);
statsContainer.add(expLabel); statsContainer.add(expLabel);
const nextLvExpLabel = addTextObject(this.scene, 6, 128, i18next.t("pokemonSummary:nextLv"), TextStyle.SUMMARY); const nextLvExpLabel = addTextObject(this.scene, 6, 128, i18next.t("pokemonSummary:nextLv"), TextStyle.SUMMARY);
nextLvExpLabel.setOrigin(0, 0); nextLvExpLabel.setOrigin(0, 0);
statsContainer.add(nextLvExpLabel); statsContainer.add(nextLvExpLabel);
const expText = addTextObject(this.scene, 208, 112, pkmExp.toString(), TextStyle.WINDOW_ALT); const expText = addTextObject(this.scene, 208, 112, pkmExp.toString(), TextStyle.WINDOW_ALT);
expText.setOrigin(1, 0); expText.setOrigin(1, 0);
statsContainer.add(expText); statsContainer.add(expText);
const nextLvExp = pkmLvl < this.scene.getMaxExpLevel() const nextLvExp = pkmLvl < this.scene.getMaxExpLevel()
? getLevelTotalExp(pkmLvl + 1, pkmSpeciesGrowthRate) - pkmExp ? getLevelTotalExp(pkmLvl + 1, pkmSpeciesGrowthRate) - pkmExp
: 0; : 0;
const nextLvExpText = addTextObject(this.scene, 208, 128, nextLvExp.toString(), TextStyle.WINDOW_ALT); const nextLvExpText = addTextObject(this.scene, 208, 128, nextLvExp.toString(), TextStyle.WINDOW_ALT);
nextLvExpText.setOrigin(1, 0); nextLvExpText.setOrigin(1, 0);
statsContainer.add(nextLvExpText); statsContainer.add(nextLvExpText);
const expOverlay = this.scene.add.image(140, 145, "summary_stats_overlay_exp"); const expOverlay = this.scene.add.image(140, 145, "summary_stats_overlay_exp");
expOverlay.setOrigin(0, 0); expOverlay.setOrigin(0, 0);
statsContainer.add(expOverlay); statsContainer.add(expOverlay);
const expMaskRect = this.scene.make.graphics({}); const expMaskRect = this.scene.make.graphics({});
expMaskRect.setScale(6); expMaskRect.setScale(6);
expMaskRect.fillStyle(0xFFFFFF); expMaskRect.fillStyle(0xFFFFFF);
expMaskRect.beginPath(); expMaskRect.beginPath();
expMaskRect.fillRect(140 + pageContainer.x, 145 + pageContainer.y + 21, Math.floor(expRatio * 64), 3); expMaskRect.fillRect(140 + pageContainer.x, 145 + pageContainer.y + 21, Math.floor(expRatio * 64), 3);
const expMask = expMaskRect.createGeometryMask(); const expMask = expMaskRect.createGeometryMask();
expOverlay.setMask(expMask); expOverlay.setMask(expMask);
break; break;
case Page.MOVES: case Page.MOVES:
this.movesContainer = this.scene.add.container(5, -pageBg.height + 26); this.movesContainer = this.scene.add.container(5, -pageBg.height + 26);
pageContainer.add(this.movesContainer); pageContainer.add(this.movesContainer);
this.extraMoveRowContainer = this.scene.add.container(0, 64); this.extraMoveRowContainer = this.scene.add.container(0, 64);
this.extraMoveRowContainer.setVisible(false); this.extraMoveRowContainer.setVisible(false);
this.movesContainer.add(this.extraMoveRowContainer); this.movesContainer.add(this.extraMoveRowContainer);
const extraRowOverlay = this.scene.add.image(-2, 1, "summary_moves_overlay_row"); const extraRowOverlay = this.scene.add.image(-2, 1, "summary_moves_overlay_row");
extraRowOverlay.setOrigin(0, 1); extraRowOverlay.setOrigin(0, 1);
this.extraMoveRowContainer.add(extraRowOverlay); this.extraMoveRowContainer.add(extraRowOverlay);
const extraRowText = addTextObject(this.scene, 35, 0, this.summaryUiMode === SummaryUiMode.LEARN_MOVE && this.newMove ? this.newMove.name : i18next.t("pokemonSummary:cancel"), const extraRowText = addTextObject(this.scene, 35, 0, this.summaryUiMode === SummaryUiMode.LEARN_MOVE && this.newMove ? this.newMove.name : i18next.t("pokemonSummary:cancel"),
this.summaryUiMode === SummaryUiMode.LEARN_MOVE ? TextStyle.SUMMARY_PINK : TextStyle.SUMMARY); this.summaryUiMode === SummaryUiMode.LEARN_MOVE ? TextStyle.SUMMARY_PINK : TextStyle.SUMMARY);
extraRowText.setOrigin(0, 1); extraRowText.setOrigin(0, 1);
this.extraMoveRowContainer.add(extraRowText); this.extraMoveRowContainer.add(extraRowText);
if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) { if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) {
this.extraMoveRowContainer.setVisible(true); this.extraMoveRowContainer.setVisible(true);
if (this.newMove && this.pokemon) { if (this.newMove && this.pokemon) {
const spriteKey = Utils.getLocalizedSpriteKey("types"); const spriteKey = Utils.getLocalizedSpriteKey("types");
const moveType = this.pokemon.getMoveType(this.newMove); const moveType = this.pokemon.getMoveType(this.newMove);
const newMoveTypeIcon = this.scene.add.sprite(0, 0, spriteKey, Type[moveType].toLowerCase()); const newMoveTypeIcon = this.scene.add.sprite(0, 0, spriteKey, Type[moveType].toLowerCase());
newMoveTypeIcon.setOrigin(0, 1); newMoveTypeIcon.setOrigin(0, 1);
this.extraMoveRowContainer.add(newMoveTypeIcon); this.extraMoveRowContainer.add(newMoveTypeIcon);
} }
const ppOverlay = this.scene.add.image(163, -1, "summary_moves_overlay_pp"); const ppOverlay = this.scene.add.image(163, -1, "summary_moves_overlay_pp");
ppOverlay.setOrigin(0, 1); ppOverlay.setOrigin(0, 1);
this.extraMoveRowContainer.add(ppOverlay); this.extraMoveRowContainer.add(ppOverlay);
const pp = Utils.padInt(this.newMove?.pp!, 2, " "); // TODO: is this bang correct? const pp = Utils.padInt(this.newMove?.pp!, 2, " "); // TODO: is this bang correct?
const ppText = addTextObject(this.scene, 173, 1, `${pp}/${pp}`, TextStyle.WINDOW); const ppText = addTextObject(this.scene, 173, 1, `${pp}/${pp}`, TextStyle.WINDOW);
ppText.setOrigin(0, 1); ppText.setOrigin(0, 1);
this.extraMoveRowContainer.add(ppText); this.extraMoveRowContainer.add(ppText);
}
this.moveRowsContainer = this.scene.add.container(0, 0);
this.movesContainer.add(this.moveRowsContainer);
for (let m = 0; m < 4; m++) {
const move: PokemonMove | null = this.pokemon && this.pokemon.moveset.length > m ? this.pokemon?.moveset[m] : null;
const moveRowContainer = this.scene.add.container(0, 16 * m);
this.moveRowsContainer.add(moveRowContainer);
if (move && this.pokemon) {
const spriteKey = Utils.getLocalizedSpriteKey("types");
const moveType = this.pokemon.getMoveType(move.getMove());
const typeIcon = this.scene.add.sprite(0, 0, spriteKey, Type[moveType].toLowerCase());
typeIcon.setOrigin(0, 1);
moveRowContainer.add(typeIcon);
} }
const moveText = addTextObject(this.scene, 35, 0, move ? move.getName() : "-", TextStyle.SUMMARY); this.moveRowsContainer = this.scene.add.container(0, 0);
moveText.setOrigin(0, 1); this.movesContainer.add(this.moveRowsContainer);
moveRowContainer.add(moveText);
const ppOverlay = this.scene.add.image(163, -1, "summary_moves_overlay_pp"); for (let m = 0; m < 4; m++) {
ppOverlay.setOrigin(0, 1); const move: PokemonMove | null = this.pokemon && this.pokemon.moveset.length > m ? this.pokemon?.moveset[m] : null;
moveRowContainer.add(ppOverlay); const moveRowContainer = this.scene.add.container(0, 16 * m);
this.moveRowsContainer.add(moveRowContainer);
const ppText = addTextObject(this.scene, 173, 1, "--/--", TextStyle.WINDOW); if (move && this.pokemon) {
ppText.setOrigin(0, 1); const spriteKey = Utils.getLocalizedSpriteKey("types");
const moveType = this.pokemon.getMoveType(move.getMove());
const typeIcon = this.scene.add.sprite(0, 0, spriteKey, Type[moveType].toLowerCase());
typeIcon.setOrigin(0, 1);
moveRowContainer.add(typeIcon);
}
if (move) { const moveText = addTextObject(this.scene, 35, 0, move ? move.getName() : "-", TextStyle.SUMMARY);
const maxPP = move.getMovePp(); moveText.setOrigin(0, 1);
const pp = maxPP - move.ppUsed; moveRowContainer.add(moveText);
ppText.setText(`${Utils.padInt(pp, 2, " ")}/${Utils.padInt(maxPP, 2, " ")}`);
const ppOverlay = this.scene.add.image(163, -1, "summary_moves_overlay_pp");
ppOverlay.setOrigin(0, 1);
moveRowContainer.add(ppOverlay);
const ppText = addTextObject(this.scene, 173, 1, "--/--", TextStyle.WINDOW);
ppText.setOrigin(0, 1);
if (move) {
const maxPP = move.getMovePp();
const pp = maxPP - move.ppUsed;
ppText.setText(`${Utils.padInt(pp, 2, " ")}/${Utils.padInt(maxPP, 2, " ")}`);
}
moveRowContainer.add(ppText);
} }
moveRowContainer.add(ppText); this.moveDescriptionText = addTextObject(this.scene, 2, 84, "", TextStyle.WINDOW_ALT, { wordWrap: { width: 1212 }});
} this.movesContainer.add(this.moveDescriptionText);
this.moveDescriptionText = addTextObject(this.scene, 2, 84, "", TextStyle.WINDOW_ALT, { wordWrap: { width: 1212 }}); const moveDescriptionTextMaskRect = this.scene.make.graphics({});
this.movesContainer.add(this.moveDescriptionText); moveDescriptionTextMaskRect.setScale(6);
moveDescriptionTextMaskRect.fillStyle(0xFFFFFF);
moveDescriptionTextMaskRect.beginPath();
moveDescriptionTextMaskRect.fillRect(112, 130, 202, 46);
const moveDescriptionTextMaskRect = this.scene.make.graphics({}); const moveDescriptionTextMask = moveDescriptionTextMaskRect.createGeometryMask();
moveDescriptionTextMaskRect.setScale(6);
moveDescriptionTextMaskRect.fillStyle(0xFFFFFF);
moveDescriptionTextMaskRect.beginPath();
moveDescriptionTextMaskRect.fillRect(112, 130, 202, 46);
const moveDescriptionTextMask = moveDescriptionTextMaskRect.createGeometryMask(); this.moveDescriptionText.setMask(moveDescriptionTextMask);
break;
this.moveDescriptionText.setMask(moveDescriptionTextMask);
break;
} }
} }

View File

@ -71,26 +71,26 @@ export default class TargetSelectUiHandler extends UiHandler {
success = false; success = false;
} else { } else {
switch (button) { switch (button) {
case Button.UP: case Button.UP:
if (this.cursor < BattlerIndex.ENEMY && this.targets.findIndex(t => t >= BattlerIndex.ENEMY) > -1) { if (this.cursor < BattlerIndex.ENEMY && this.targets.findIndex(t => t >= BattlerIndex.ENEMY) > -1) {
success = this.setCursor(this.targets.find(t => t >= BattlerIndex.ENEMY)!); // TODO: is the bang correct here? success = this.setCursor(this.targets.find(t => t >= BattlerIndex.ENEMY)!); // TODO: is the bang correct here?
} }
break; break;
case Button.DOWN: case Button.DOWN:
if (this.cursor >= BattlerIndex.ENEMY && this.targets.findIndex(t => t < BattlerIndex.ENEMY) > -1) { if (this.cursor >= BattlerIndex.ENEMY && this.targets.findIndex(t => t < BattlerIndex.ENEMY) > -1) {
success = this.setCursor(this.targets.find(t => t < BattlerIndex.ENEMY)!); // TODO: is the bang correct here? success = this.setCursor(this.targets.find(t => t < BattlerIndex.ENEMY)!); // TODO: is the bang correct here?
} }
break; break;
case Button.LEFT: case Button.LEFT:
if (this.cursor % 2 && this.targets.findIndex(t => t === this.cursor - 1) > -1) { if (this.cursor % 2 && this.targets.findIndex(t => t === this.cursor - 1) > -1) {
success = this.setCursor(this.cursor - 1); success = this.setCursor(this.cursor - 1);
} }
break; break;
case Button.RIGHT: case Button.RIGHT:
if (!(this.cursor % 2) && this.targets.findIndex(t => t === this.cursor + 1) > -1) { if (!(this.cursor % 2) && this.targets.findIndex(t => t === this.cursor + 1) > -1) {
success = this.setCursor(this.cursor + 1); success = this.setCursor(this.cursor + 1);
} }
break; break;
} }
} }

View File

@ -129,84 +129,84 @@ export function getTextStyleOptions(style: TextStyle, uiTheme: UiTheme, extraSty
} }
switch (style) { switch (style) {
case TextStyle.SUMMARY: case TextStyle.SUMMARY:
case TextStyle.SUMMARY_ALT: case TextStyle.SUMMARY_ALT:
case TextStyle.SUMMARY_BLUE: case TextStyle.SUMMARY_BLUE:
case TextStyle.SUMMARY_RED: case TextStyle.SUMMARY_RED:
case TextStyle.SUMMARY_PINK: case TextStyle.SUMMARY_PINK:
case TextStyle.SUMMARY_GOLD: case TextStyle.SUMMARY_GOLD:
case TextStyle.SUMMARY_GRAY: case TextStyle.SUMMARY_GRAY:
case TextStyle.SUMMARY_GREEN: case TextStyle.SUMMARY_GREEN:
case TextStyle.WINDOW: case TextStyle.WINDOW:
case TextStyle.WINDOW_ALT: case TextStyle.WINDOW_ALT:
shadowXpos = 3;
shadowYpos = 3;
break;
case TextStyle.STATS_LABEL:
let fontSizeLabel = "96px";
switch (lang) {
case "de":
shadowXpos = 3; shadowXpos = 3;
shadowYpos = 3; shadowYpos = 3;
fontSizeLabel = "80px";
break; break;
default: case TextStyle.STATS_LABEL:
fontSizeLabel = "96px"; let fontSizeLabel = "96px";
switch (lang) {
case "de":
shadowXpos = 3;
shadowYpos = 3;
fontSizeLabel = "80px";
break;
default:
fontSizeLabel = "96px";
break;
}
styleOptions.fontSize = fontSizeLabel;
break; break;
} case TextStyle.STATS_VALUE:
styleOptions.fontSize = fontSizeLabel; shadowXpos = 3;
break; shadowYpos = 3;
case TextStyle.STATS_VALUE: let fontSizeValue = "96px";
shadowXpos = 3; switch (lang) {
shadowYpos = 3; case "de":
let fontSizeValue = "96px"; fontSizeValue = "80px";
switch (lang) { break;
case "de": default:
fontSizeValue = "80px"; fontSizeValue = "96px";
break;
}
styleOptions.fontSize = fontSizeValue;
break; break;
default: case TextStyle.MESSAGE:
fontSizeValue = "96px"; case TextStyle.SETTINGS_LABEL:
case TextStyle.SETTINGS_LOCKED:
case TextStyle.SETTINGS_SELECTED:
break;
case TextStyle.BATTLE_INFO:
case TextStyle.MONEY:
case TextStyle.TOOLTIP_TITLE:
styleOptions.fontSize = defaultFontSize - 24;
shadowXpos = 3.5;
shadowYpos = 3.5;
break;
case TextStyle.PARTY:
case TextStyle.PARTY_RED:
styleOptions.fontSize = defaultFontSize - 30;
styleOptions.fontFamily = "pkmnems";
break;
case TextStyle.TOOLTIP_CONTENT:
styleOptions.fontSize = defaultFontSize - 32;
shadowXpos = 3;
shadowYpos = 3;
break;
case TextStyle.MOVE_INFO_CONTENT:
styleOptions.fontSize = defaultFontSize - 40;
shadowXpos = 3;
shadowYpos = 3;
break;
case TextStyle.SMALLER_WINDOW_ALT:
styleOptions.fontSize = defaultFontSize - 36;
shadowXpos = 3;
shadowYpos = 3;
break;
case TextStyle.BGM_BAR:
styleOptions.fontSize = defaultFontSize - 24;
shadowXpos = 3;
shadowYpos = 3;
break; break;
}
styleOptions.fontSize = fontSizeValue;
break;
case TextStyle.MESSAGE:
case TextStyle.SETTINGS_LABEL:
case TextStyle.SETTINGS_LOCKED:
case TextStyle.SETTINGS_SELECTED:
break;
case TextStyle.BATTLE_INFO:
case TextStyle.MONEY:
case TextStyle.TOOLTIP_TITLE:
styleOptions.fontSize = defaultFontSize - 24;
shadowXpos = 3.5;
shadowYpos = 3.5;
break;
case TextStyle.PARTY:
case TextStyle.PARTY_RED:
styleOptions.fontSize = defaultFontSize - 30;
styleOptions.fontFamily = "pkmnems";
break;
case TextStyle.TOOLTIP_CONTENT:
styleOptions.fontSize = defaultFontSize - 32;
shadowXpos = 3;
shadowYpos = 3;
break;
case TextStyle.MOVE_INFO_CONTENT:
styleOptions.fontSize = defaultFontSize - 40;
shadowXpos = 3;
shadowYpos = 3;
break;
case TextStyle.SMALLER_WINDOW_ALT:
styleOptions.fontSize = defaultFontSize - 36;
shadowXpos = 3;
shadowYpos = 3;
break;
case TextStyle.BGM_BAR:
styleOptions.fontSize = defaultFontSize - 24;
shadowXpos = 3;
shadowYpos = 3;
break;
} }
const shadowColor = getTextColor(style, true, uiTheme); const shadowColor = getTextColor(style, true, uiTheme);
@ -257,110 +257,110 @@ export function getTextWithColors(content: string, primaryStyle: TextStyle, uiTh
export function getTextColor(textStyle: TextStyle, shadow?: boolean, uiTheme: UiTheme = UiTheme.DEFAULT): string { export function getTextColor(textStyle: TextStyle, shadow?: boolean, uiTheme: UiTheme = UiTheme.DEFAULT): string {
const isLegacyTheme = uiTheme === UiTheme.LEGACY; const isLegacyTheme = uiTheme === UiTheme.LEGACY;
switch (textStyle) { switch (textStyle) {
case TextStyle.MESSAGE: case TextStyle.MESSAGE:
return !shadow ? "#f8f8f8" : "#6b5a73"; return !shadow ? "#f8f8f8" : "#6b5a73";
case TextStyle.WINDOW: case TextStyle.WINDOW:
case TextStyle.MOVE_INFO_CONTENT: case TextStyle.MOVE_INFO_CONTENT:
case TextStyle.MOVE_PP_FULL: case TextStyle.MOVE_PP_FULL:
case TextStyle.TOOLTIP_CONTENT: case TextStyle.TOOLTIP_CONTENT:
case TextStyle.SETTINGS_VALUE: case TextStyle.SETTINGS_VALUE:
if (isLegacyTheme) { if (isLegacyTheme) {
return !shadow ? "#484848" : "#d0d0c8";
}
return !shadow ? "#f8f8f8" : "#6b5a73";
case TextStyle.MOVE_PP_HALF_FULL:
if (isLegacyTheme) {
return !shadow ? "#a68e17" : "#ebd773";
}
return !shadow ? "#ccbe00" : "#6e672c";
case TextStyle.MOVE_PP_NEAR_EMPTY:
if (isLegacyTheme) {
return !shadow ? "#d64b00" : "#f7b18b";
}
return !shadow ? "#d64b00" : "#69402a";
case TextStyle.MOVE_PP_EMPTY:
if (isLegacyTheme) {
return !shadow ? "#e13d3d" : "#fca2a2";
}
return !shadow ? "#e13d3d" : "#632929";
case TextStyle.WINDOW_ALT:
return !shadow ? "#484848" : "#d0d0c8"; return !shadow ? "#484848" : "#d0d0c8";
} case TextStyle.BATTLE_INFO:
return !shadow ? "#f8f8f8" : "#6b5a73"; if (isLegacyTheme) {
case TextStyle.MOVE_PP_HALF_FULL: return !shadow ? "#404040" : "#ded6b5";
if (isLegacyTheme) { }
return !shadow ? "#a68e17" : "#ebd773"; return !shadow ? "#f8f8f8" : "#6b5a73";
} case TextStyle.PARTY:
return !shadow ? "#ccbe00" : "#6e672c"; return !shadow ? "#f8f8f8" : "#707070";
case TextStyle.MOVE_PP_NEAR_EMPTY: case TextStyle.PARTY_RED:
if (isLegacyTheme) { return !shadow ? "#f89890" : "#984038";
return !shadow ? "#d64b00" : "#f7b18b"; case TextStyle.SUMMARY:
}
return !shadow ? "#d64b00" : "#69402a";
case TextStyle.MOVE_PP_EMPTY:
if (isLegacyTheme) {
return !shadow ? "#e13d3d" : "#fca2a2";
}
return !shadow ? "#e13d3d" : "#632929";
case TextStyle.WINDOW_ALT:
return !shadow ? "#484848" : "#d0d0c8";
case TextStyle.BATTLE_INFO:
if (isLegacyTheme) {
return !shadow ? "#404040" : "#ded6b5";
}
return !shadow ? "#f8f8f8" : "#6b5a73";
case TextStyle.PARTY:
return !shadow ? "#f8f8f8" : "#707070";
case TextStyle.PARTY_RED:
return !shadow ? "#f89890" : "#984038";
case TextStyle.SUMMARY:
return !shadow ? "#f8f8f8" : "#636363";
case TextStyle.SUMMARY_ALT:
if (isLegacyTheme) {
return !shadow ? "#f8f8f8" : "#636363"; return !shadow ? "#f8f8f8" : "#636363";
} case TextStyle.SUMMARY_ALT:
return !shadow ? "#484848" : "#d0d0c8"; if (isLegacyTheme) {
case TextStyle.SUMMARY_RED: return !shadow ? "#f8f8f8" : "#636363";
case TextStyle.TOOLTIP_TITLE: }
return !shadow ? "#e70808" : "#ffbd73";
case TextStyle.SUMMARY_BLUE:
return !shadow ? "#40c8f8" : "#006090";
case TextStyle.SUMMARY_PINK:
return !shadow ? "#f89890" : "#984038";
case TextStyle.SUMMARY_GOLD:
case TextStyle.MONEY:
return !shadow ? "#e8e8a8" : "#a0a060";
case TextStyle.SETTINGS_LOCKED:
case TextStyle.SUMMARY_GRAY:
return !shadow ? "#a0a0a0" : "#636363";
case TextStyle.STATS_LABEL:
return !shadow ? "#f8b050" : "#c07800";
case TextStyle.STATS_VALUE:
if (isLegacyTheme) {
return !shadow ? "#484848" : "#d0d0c8"; return !shadow ? "#484848" : "#d0d0c8";
} case TextStyle.SUMMARY_RED:
return !shadow ? "#f8f8f8" : "#6b5a73"; case TextStyle.TOOLTIP_TITLE:
case TextStyle.SUMMARY_GREEN: return !shadow ? "#e70808" : "#ffbd73";
return !shadow ? "#78c850" : "#306850"; case TextStyle.SUMMARY_BLUE:
case TextStyle.SETTINGS_LABEL: return !shadow ? "#40c8f8" : "#006090";
case TextStyle.PERFECT_IV: case TextStyle.SUMMARY_PINK:
return !shadow ? "#f8b050" : "#c07800"; return !shadow ? "#f89890" : "#984038";
case TextStyle.SETTINGS_SELECTED: case TextStyle.SUMMARY_GOLD:
return !shadow ? "#f88880" : "#f83018"; case TextStyle.MONEY:
case TextStyle.SMALLER_WINDOW_ALT: return !shadow ? "#e8e8a8" : "#a0a060";
return !shadow ? "#484848" : "#d0d0c8"; case TextStyle.SETTINGS_LOCKED:
case TextStyle.BGM_BAR: case TextStyle.SUMMARY_GRAY:
return !shadow ? "#f8f8f8" : "#6b5a73"; return !shadow ? "#a0a0a0" : "#636363";
case TextStyle.STATS_LABEL:
return !shadow ? "#f8b050" : "#c07800";
case TextStyle.STATS_VALUE:
if (isLegacyTheme) {
return !shadow ? "#484848" : "#d0d0c8";
}
return !shadow ? "#f8f8f8" : "#6b5a73";
case TextStyle.SUMMARY_GREEN:
return !shadow ? "#78c850" : "#306850";
case TextStyle.SETTINGS_LABEL:
case TextStyle.PERFECT_IV:
return !shadow ? "#f8b050" : "#c07800";
case TextStyle.SETTINGS_SELECTED:
return !shadow ? "#f88880" : "#f83018";
case TextStyle.SMALLER_WINDOW_ALT:
return !shadow ? "#484848" : "#d0d0c8";
case TextStyle.BGM_BAR:
return !shadow ? "#f8f8f8" : "#6b5a73";
} }
} }
export function getModifierTierTextTint(tier: ModifierTier): integer { export function getModifierTierTextTint(tier: ModifierTier): integer {
switch (tier) { switch (tier) {
case ModifierTier.COMMON: case ModifierTier.COMMON:
return 0xf8f8f8; return 0xf8f8f8;
case ModifierTier.GREAT: case ModifierTier.GREAT:
return 0x4998f8; return 0x4998f8;
case ModifierTier.ULTRA: case ModifierTier.ULTRA:
return 0xf8d038; return 0xf8d038;
case ModifierTier.ROGUE: case ModifierTier.ROGUE:
return 0xdb4343; return 0xdb4343;
case ModifierTier.MASTER: case ModifierTier.MASTER:
return 0xe331c5; return 0xe331c5;
case ModifierTier.LUXURY: case ModifierTier.LUXURY:
return 0xe74c18; return 0xe74c18;
} }
} }
export function getEggTierTextTint(tier: EggTier): integer { export function getEggTierTextTint(tier: EggTier): integer {
switch (tier) { switch (tier) {
case EggTier.COMMON: case EggTier.COMMON:
return getModifierTierTextTint(ModifierTier.COMMON); return getModifierTierTextTint(ModifierTier.COMMON);
case EggTier.RARE: case EggTier.RARE:
return getModifierTierTextTint(ModifierTier.GREAT); return getModifierTierTextTint(ModifierTier.GREAT);
case EggTier.EPIC: case EggTier.EPIC:
return getModifierTierTextTint(ModifierTier.ULTRA); return getModifierTierTextTint(ModifierTier.ULTRA);
case EggTier.LEGENDARY: case EggTier.LEGENDARY:
return getModifierTierTextTint(ModifierTier.MASTER); return getModifierTierTextTint(ModifierTier.MASTER);
} }
} }

View File

@ -10,12 +10,12 @@ export enum WindowVariant {
export function getWindowVariantSuffix(windowVariant: WindowVariant): string { export function getWindowVariantSuffix(windowVariant: WindowVariant): string {
switch (windowVariant) { switch (windowVariant) {
case WindowVariant.THIN: case WindowVariant.THIN:
return "_thin"; return "_thin";
case WindowVariant.XTHIN: case WindowVariant.XTHIN:
return "_xthin"; return "_xthin";
default: default:
return ""; return "";
} }
} }

View File

@ -34,7 +34,6 @@ import SaveSlotSelectUiHandler from "./save-slot-select-ui-handler";
import TitleUiHandler from "./title-ui-handler"; import TitleUiHandler from "./title-ui-handler";
import SavingIconHandler from "./saving-icon-handler"; import SavingIconHandler from "./saving-icon-handler";
import UnavailableModalUiHandler from "./unavailable-modal-ui-handler"; import UnavailableModalUiHandler from "./unavailable-modal-ui-handler";
import OutdatedModalUiHandler from "./outdated-modal-ui-handler";
import SessionReloadModalUiHandler from "./session-reload-modal-ui-handler"; import SessionReloadModalUiHandler from "./session-reload-modal-ui-handler";
import { Button } from "#enums/buttons"; import { Button } from "#enums/buttons";
import i18next from "i18next"; import i18next from "i18next";
@ -90,7 +89,6 @@ export enum Mode {
LOADING, LOADING,
SESSION_RELOAD, SESSION_RELOAD,
UNAVAILABLE, UNAVAILABLE,
OUTDATED,
CHALLENGE_SELECT, CHALLENGE_SELECT,
RENAME_POKEMON, RENAME_POKEMON,
RUN_HISTORY, RUN_HISTORY,
@ -134,7 +132,6 @@ const noTransitionModes = [
Mode.LOADING, Mode.LOADING,
Mode.SESSION_RELOAD, Mode.SESSION_RELOAD,
Mode.UNAVAILABLE, Mode.UNAVAILABLE,
Mode.OUTDATED,
Mode.RENAME_POKEMON, Mode.RENAME_POKEMON,
Mode.TEST_DIALOGUE, Mode.TEST_DIALOGUE,
Mode.AUTO_COMPLETE, Mode.AUTO_COMPLETE,
@ -200,7 +197,6 @@ export default class UI extends Phaser.GameObjects.Container {
new LoadingModalUiHandler(scene), new LoadingModalUiHandler(scene),
new SessionReloadModalUiHandler(scene), new SessionReloadModalUiHandler(scene),
new UnavailableModalUiHandler(scene), new UnavailableModalUiHandler(scene),
new OutdatedModalUiHandler(scene),
new GameChallengesUiHandler(scene), new GameChallengesUiHandler(scene),
new RenameFormUiHandler(scene), new RenameFormUiHandler(scene),
new RunHistoryUiHandler(scene), new RunHistoryUiHandler(scene),

Some files were not shown because too many files have changed in this diff Show More