Merge branch 'beta' into assistbug2
|
@ -1,5 +1,5 @@
|
|||
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 importX from 'eslint-plugin-import-x';
|
||||
|
||||
|
@ -16,15 +16,15 @@ export default [
|
|||
'@typescript-eslint': tseslint
|
||||
},
|
||||
rules: {
|
||||
"eqeqeq": ["error", "always"], // Enforces the use of === and !== instead of == and !=
|
||||
"indent": ["error", 2], // Enforces a 2-space indentation
|
||||
"eqeqeq": ["error", "always"], // Enforces the use of `===` and `!==` instead of `==` and `!=`
|
||||
"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
|
||||
"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
|
||||
"no-var": "error", // Disallows the use of `var`, enforcing `let` or `const` instead
|
||||
"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)
|
||||
"@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.
|
||||
"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
|
||||
"@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
|
||||
"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
|
||||
"@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
|
||||
"skipBlankLines": false, // Enforces the rule even on blank lines
|
||||
"ignoreComments": false // Enforces the rule on lines containing comments
|
||||
}],
|
||||
"space-before-blocks": ["error", "always"], // Enforces a space before blocks
|
||||
"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
|
||||
"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
|
||||
|
|
|
@ -3416,12 +3416,12 @@
|
|||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 24,
|
||||
"h": 24
|
||||
"w": 32,
|
||||
"h": 32
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 1,
|
||||
"y": 2,
|
||||
"x": 5,
|
||||
"y": 7,
|
||||
"w": 22,
|
||||
"h": 19
|
||||
},
|
||||
|
@ -8415,6 +8415,6 @@
|
|||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:934ea4080bad980d4fea720cc771f133:ed564bc47b79b15a763de57045178e88:110e074689c9edd2c54833ce2e4d9270$"
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:9ef21166268f7487fc9ff8d0f9b996e4:82658ac7bdd4c2b417e1f59168179262:110e074689c9edd2c54833ce2e4d9270$"
|
||||
}
|
||||
}
|
||||
|
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 285 B |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.4 KiB |
|
@ -86,7 +86,7 @@ import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-ph
|
|||
import { TurnInitPhase } from "#app/phases/turn-init-phase";
|
||||
import { ShopCursorTarget } from "#app/enums/shop-cursor-target";
|
||||
import MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||
import { allMysteryEncounters, ANTI_VARIANCE_WEIGHT_MODIFIER, AVERAGE_ENCOUNTERS_PER_RUN_TARGET, BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT, MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT, mysteryEncountersByBiome, WEIGHT_INCREMENT_ON_SPAWN_MISS } from "#app/data/mystery-encounters/mystery-encounters";
|
||||
import { allMysteryEncounters, ANTI_VARIANCE_WEIGHT_MODIFIER, AVERAGE_ENCOUNTERS_PER_RUN_TARGET, BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT, MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT, mysteryEncountersByBiome } from "#app/data/mystery-encounters/mystery-encounters";
|
||||
import { MysteryEncounterSaveData } from "#app/data/mystery-encounters/mystery-encounter-save-data";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
|
@ -1191,10 +1191,7 @@ export default class BattleScene extends SceneBase {
|
|||
if (trainerConfigs[trainerType].doubleOnly) {
|
||||
doubleTrainer = true;
|
||||
} else if (trainerConfigs[trainerType].hasDouble) {
|
||||
const doubleChance = new Utils.IntegerHolder(newWaveIndex % 10 === 0 ? 32 : 8);
|
||||
this.applyModifiers(DoubleBattleChanceBoosterModifier, true, doubleChance);
|
||||
playerField.forEach(p => applyAbAttrs(DoubleBattleChanceAbAttr, p, null, false, doubleChance));
|
||||
doubleTrainer = !Utils.randSeedInt(doubleChance.value);
|
||||
doubleTrainer = !Utils.randSeedInt(this.getDoubleBattleChance(newWaveIndex, playerField));
|
||||
// Add a check that special trainers can't be double except for tate and liza - they should use the normal double chance
|
||||
if (trainerConfigs[trainerType].trainerTypeDouble && ![ TrainerType.TATE, TrainerType.LIZA ].includes(trainerType)) {
|
||||
doubleTrainer = false;
|
||||
|
@ -1207,12 +1204,10 @@ export default class BattleScene extends SceneBase {
|
|||
|
||||
// Check for mystery encounter
|
||||
// Can only occur in place of a standard (non-boss) wild battle, waves 10-180
|
||||
if (this.isWaveMysteryEncounter(newBattleType, newWaveIndex, mysteryEncounterType) || newBattleType === BattleType.MYSTERY_ENCOUNTER) {
|
||||
if (this.isWaveMysteryEncounter(newBattleType, newWaveIndex) || newBattleType === BattleType.MYSTERY_ENCOUNTER) {
|
||||
newBattleType = BattleType.MYSTERY_ENCOUNTER;
|
||||
// Reset base spawn weight
|
||||
// Reset to base spawn weight
|
||||
this.mysteryEncounterSaveData.encounterSpawnChance = BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT;
|
||||
} else if (newBattleType === BattleType.WILD) {
|
||||
this.mysteryEncounterSaveData.encounterSpawnChance += WEIGHT_INCREMENT_ON_SPAWN_MISS;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1359,69 +1354,69 @@ export default class BattleScene extends SceneBase {
|
|||
}
|
||||
|
||||
switch (species.speciesId) {
|
||||
case Species.UNOWN:
|
||||
case Species.SHELLOS:
|
||||
case Species.GASTRODON:
|
||||
case Species.BASCULIN:
|
||||
case Species.DEERLING:
|
||||
case Species.SAWSBUCK:
|
||||
case Species.FROAKIE:
|
||||
case Species.FROGADIER:
|
||||
case Species.SCATTERBUG:
|
||||
case Species.SPEWPA:
|
||||
case Species.VIVILLON:
|
||||
case Species.FLABEBE:
|
||||
case Species.FLOETTE:
|
||||
case Species.FLORGES:
|
||||
case Species.FURFROU:
|
||||
case Species.PUMPKABOO:
|
||||
case Species.GOURGEIST:
|
||||
case Species.ORICORIO:
|
||||
case Species.MAGEARNA:
|
||||
case Species.ZARUDE:
|
||||
case Species.SQUAWKABILLY:
|
||||
case Species.TATSUGIRI:
|
||||
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 {
|
||||
case Species.UNOWN:
|
||||
case Species.SHELLOS:
|
||||
case Species.GASTRODON:
|
||||
case Species.BASCULIN:
|
||||
case Species.DEERLING:
|
||||
case Species.SAWSBUCK:
|
||||
case Species.FROAKIE:
|
||||
case Species.FROGADIER:
|
||||
case Species.SCATTERBUG:
|
||||
case Species.SPEWPA:
|
||||
case Species.VIVILLON:
|
||||
case Species.FLABEBE:
|
||||
case Species.FLOETTE:
|
||||
case Species.FLORGES:
|
||||
case Species.FURFROU:
|
||||
case Species.PUMPKABOO:
|
||||
case Species.GOURGEIST:
|
||||
case Species.ORICORIO:
|
||||
case Species.MAGEARNA:
|
||||
case Species.ZARUDE:
|
||||
case Species.SQUAWKABILLY:
|
||||
case Species.TATSUGIRI:
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (ignoreArena) {
|
||||
switch (species.speciesId) {
|
||||
case Species.BURMY:
|
||||
case Species.WORMADAM:
|
||||
case Species.ROTOM:
|
||||
case Species.LYCANROC:
|
||||
return Utils.randSeedInt(species.forms.length);
|
||||
case Species.BURMY:
|
||||
case Species.WORMADAM:
|
||||
case Species.ROTOM:
|
||||
case Species.LYCANROC:
|
||||
return Utils.randSeedInt(species.forms.length);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1886,17 +1881,17 @@ export default class BattleScene extends SceneBase {
|
|||
const soundDetails = sound.key.split("/");
|
||||
switch (soundDetails[0]) {
|
||||
|
||||
case "battle_anims":
|
||||
case "cry":
|
||||
if (soundDetails[1].startsWith("PRSFX- ")) {
|
||||
sound.setVolume(this.masterVolume * this.fieldVolume * 0.5);
|
||||
} else {
|
||||
sound.setVolume(this.masterVolume * this.fieldVolume);
|
||||
}
|
||||
break;
|
||||
case "se":
|
||||
case "ui":
|
||||
sound.setVolume(this.masterVolume * this.seVolume);
|
||||
case "battle_anims":
|
||||
case "cry":
|
||||
if (soundDetails[1].startsWith("PRSFX- ")) {
|
||||
sound.setVolume(this.masterVolume * this.fieldVolume * 0.5);
|
||||
} else {
|
||||
sound.setVolume(this.masterVolume * this.fieldVolume);
|
||||
}
|
||||
break;
|
||||
case "se":
|
||||
case "ui":
|
||||
sound.setVolume(this.masterVolume * this.seVolume);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1936,31 +1931,31 @@ export default class BattleScene extends SceneBase {
|
|||
const keyDetails = key.split("/");
|
||||
config["volume"] = config["volume"] ?? 1;
|
||||
switch (keyDetails[0]) {
|
||||
case "level_up_fanfare":
|
||||
case "item_fanfare":
|
||||
case "minor_fanfare":
|
||||
case "heal":
|
||||
case "evolution":
|
||||
case "evolution_fanfare":
|
||||
case "level_up_fanfare":
|
||||
case "item_fanfare":
|
||||
case "minor_fanfare":
|
||||
case "heal":
|
||||
case "evolution":
|
||||
case "evolution_fanfare":
|
||||
// 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()
|
||||
config["volume"] *= (this.masterVolume * this.bgmVolume);
|
||||
break;
|
||||
case "battle_anims":
|
||||
case "cry":
|
||||
config["volume"] *= (this.masterVolume * this.fieldVolume);
|
||||
//PRSFX sound files are unusually loud
|
||||
if (keyDetails[1].startsWith("PRSFX- ")) {
|
||||
config["volume"] *= 0.5;
|
||||
}
|
||||
break;
|
||||
case "ui":
|
||||
config["volume"] *= (this.masterVolume * this.bgmVolume);
|
||||
break;
|
||||
case "battle_anims":
|
||||
case "cry":
|
||||
config["volume"] *= (this.masterVolume * this.fieldVolume);
|
||||
//PRSFX sound files are unusually loud
|
||||
if (keyDetails[1].startsWith("PRSFX- ")) {
|
||||
config["volume"] *= 0.5;
|
||||
}
|
||||
break;
|
||||
case "ui":
|
||||
//As of, right now this applies to the "select", "menu_open", "error" sound effects
|
||||
config["volume"] *= (this.masterVolume * this.uiVolume);
|
||||
break;
|
||||
case "se":
|
||||
config["volume"] *= (this.masterVolume * this.seVolume);
|
||||
break;
|
||||
config["volume"] *= (this.masterVolume * this.uiVolume);
|
||||
break;
|
||||
case "se":
|
||||
config["volume"] *= (this.masterVolume * this.seVolume);
|
||||
break;
|
||||
}
|
||||
this.sound.play(key, config);
|
||||
return this.sound.get(key) as AnySound;
|
||||
|
@ -1989,208 +1984,208 @@ export default class BattleScene extends SceneBase {
|
|||
|
||||
getBgmLoopPoint(bgmName: string): number {
|
||||
switch (bgmName) {
|
||||
case "battle_kanto_champion": //B2W2 Kanto Champion Battle
|
||||
return 13.950;
|
||||
case "battle_johto_champion": //B2W2 Johto Champion Battle
|
||||
return 23.498;
|
||||
case "battle_hoenn_champion_g5": //B2W2 Hoenn Champion Battle
|
||||
return 11.328;
|
||||
case "battle_hoenn_champion_g6": //ORAS Hoenn Champion Battle
|
||||
return 11.762;
|
||||
case "battle_sinnoh_champion": //B2W2 Sinnoh Champion Battle
|
||||
return 12.235;
|
||||
case "battle_champion_alder": //BW Unova Champion Battle
|
||||
return 27.653;
|
||||
case "battle_champion_iris": //B2W2 Unova Champion Battle
|
||||
return 10.145;
|
||||
case "battle_kalos_champion": //XY Kalos Champion Battle
|
||||
return 10.380;
|
||||
case "battle_alola_champion": //USUM Alola Champion Battle
|
||||
return 13.025;
|
||||
case "battle_galar_champion": //SWSH Galar Champion Battle
|
||||
return 61.635;
|
||||
case "battle_champion_geeta": //SV Champion Geeta Battle
|
||||
return 37.447;
|
||||
case "battle_champion_nemona": //SV Champion Nemona Battle
|
||||
return 14.914;
|
||||
case "battle_champion_kieran": //SV Champion Kieran Battle
|
||||
return 7.206;
|
||||
case "battle_hoenn_elite": //ORAS Elite Four Battle
|
||||
return 11.350;
|
||||
case "battle_unova_elite": //BW Elite Four Battle
|
||||
return 17.730;
|
||||
case "battle_kalos_elite": //XY Elite Four Battle
|
||||
return 12.340;
|
||||
case "battle_alola_elite": //SM Elite Four Battle
|
||||
return 19.212;
|
||||
case "battle_galar_elite": //SWSH League Tournament Battle
|
||||
return 164.069;
|
||||
case "battle_paldea_elite": //SV Elite Four Battle
|
||||
return 12.770;
|
||||
case "battle_bb_elite": //SV BB League Elite Four Battle
|
||||
return 19.434;
|
||||
case "battle_final_encounter": //PMD RTDX Rayquaza's Domain
|
||||
return 19.159;
|
||||
case "battle_final": //BW Ghetsis Battle
|
||||
return 16.453;
|
||||
case "battle_kanto_gym": //B2W2 Kanto Gym Battle
|
||||
return 13.857;
|
||||
case "battle_johto_gym": //B2W2 Johto Gym Battle
|
||||
return 12.911;
|
||||
case "battle_hoenn_gym": //B2W2 Hoenn Gym Battle
|
||||
return 12.379;
|
||||
case "battle_sinnoh_gym": //B2W2 Sinnoh Gym Battle
|
||||
return 13.122;
|
||||
case "battle_unova_gym": //BW Unova Gym Battle
|
||||
return 19.145;
|
||||
case "battle_kalos_gym": //XY Kalos Gym Battle
|
||||
return 44.810;
|
||||
case "battle_galar_gym": //SWSH Galar Gym Battle
|
||||
return 171.262;
|
||||
case "battle_paldea_gym": //SV Paldea Gym Battle
|
||||
return 127.489;
|
||||
case "battle_legendary_kanto": //XY Kanto Legendary Battle
|
||||
return 32.966;
|
||||
case "battle_legendary_raikou": //HGSS Raikou Battle
|
||||
return 12.632;
|
||||
case "battle_legendary_entei": //HGSS Entei Battle
|
||||
return 2.905;
|
||||
case "battle_legendary_suicune": //HGSS Suicune Battle
|
||||
return 12.636;
|
||||
case "battle_legendary_lugia": //HGSS Lugia Battle
|
||||
return 19.770;
|
||||
case "battle_legendary_ho_oh": //HGSS Ho-oh Battle
|
||||
return 17.668;
|
||||
case "battle_legendary_regis_g5": //B2W2 Legendary Titan Battle
|
||||
return 49.500;
|
||||
case "battle_legendary_regis_g6": //ORAS Legendary Titan Battle
|
||||
return 21.130;
|
||||
case "battle_legendary_gro_kyo": //ORAS Groudon & Kyogre Battle
|
||||
return 10.547;
|
||||
case "battle_legendary_rayquaza": //ORAS Rayquaza Battle
|
||||
return 10.495;
|
||||
case "battle_legendary_deoxys": //ORAS Deoxys Battle
|
||||
return 13.333;
|
||||
case "battle_legendary_lake_trio": //ORAS Lake Guardians Battle
|
||||
return 16.887;
|
||||
case "battle_legendary_sinnoh": //ORAS Sinnoh Legendary Battle
|
||||
return 22.770;
|
||||
case "battle_legendary_dia_pal": //ORAS Dialga & Palkia Battle
|
||||
return 16.009;
|
||||
case "battle_legendary_origin_forme": //LA Origin Dialga & Palkia Battle
|
||||
return 18.961;
|
||||
case "battle_legendary_giratina": //ORAS Giratina Battle
|
||||
return 10.451;
|
||||
case "battle_legendary_arceus": //HGSS Arceus Battle
|
||||
return 9.595;
|
||||
case "battle_legendary_unova": //BW Unova Legendary Battle
|
||||
return 13.855;
|
||||
case "battle_legendary_kyurem": //BW Kyurem Battle
|
||||
return 18.314;
|
||||
case "battle_legendary_res_zek": //BW Reshiram & Zekrom Battle
|
||||
return 18.329;
|
||||
case "battle_legendary_xern_yvel": //XY Xerneas & Yveltal Battle
|
||||
return 26.468;
|
||||
case "battle_legendary_tapu": //SM Tapu Battle
|
||||
return 0.000;
|
||||
case "battle_legendary_sol_lun": //SM Solgaleo & Lunala Battle
|
||||
return 6.525;
|
||||
case "battle_legendary_ub": //SM Ultra Beast Battle
|
||||
return 9.818;
|
||||
case "battle_legendary_dusk_dawn": //USUM Dusk Mane & Dawn Wings Necrozma Battle
|
||||
return 5.211;
|
||||
case "battle_legendary_ultra_nec": //USUM Ultra Necrozma Battle
|
||||
return 10.344;
|
||||
case "battle_legendary_zac_zam": //SWSH Zacian & Zamazenta Battle
|
||||
return 11.424;
|
||||
case "battle_legendary_glas_spec": //SWSH Glastrier & Spectrier Battle
|
||||
return 12.503;
|
||||
case "battle_legendary_calyrex": //SWSH Calyrex Battle
|
||||
return 50.641;
|
||||
case "battle_legendary_riders": //SWSH Ice & Shadow Rider Calyrex Battle
|
||||
return 18.155;
|
||||
case "battle_legendary_birds_galar": //SWSH Galarian Legendary Birds Battle
|
||||
return 0.175;
|
||||
case "battle_legendary_ruinous": //SV Treasures of Ruin Battle
|
||||
return 6.333;
|
||||
case "battle_legendary_kor_mir": //SV Depths of Area Zero Battle
|
||||
return 6.442;
|
||||
case "battle_legendary_loyal_three": //SV Loyal Three Battle
|
||||
return 6.500;
|
||||
case "battle_legendary_ogerpon": //SV Ogerpon Battle
|
||||
return 14.335;
|
||||
case "battle_legendary_terapagos": //SV Terapagos Battle
|
||||
return 24.377;
|
||||
case "battle_legendary_pecharunt": //SV Pecharunt Battle
|
||||
return 6.508;
|
||||
case "battle_rival": //BW Rival Battle
|
||||
return 14.110;
|
||||
case "battle_rival_2": //BW N Battle
|
||||
return 17.714;
|
||||
case "battle_rival_3": //BW Final N Battle
|
||||
return 17.586;
|
||||
case "battle_trainer": //BW Trainer Battle
|
||||
return 13.686;
|
||||
case "battle_wild": //BW Wild Battle
|
||||
return 12.703;
|
||||
case "battle_wild_strong": //BW Strong Wild Battle
|
||||
return 13.940;
|
||||
case "end_summit": //PMD RTDX Sky Tower Summit
|
||||
return 30.025;
|
||||
case "battle_rocket_grunt": //HGSS Team Rocket Battle
|
||||
return 12.707;
|
||||
case "battle_aqua_magma_grunt": //ORAS Team Aqua & Magma Battle
|
||||
return 12.062;
|
||||
case "battle_galactic_grunt": //BDSP Team Galactic Battle
|
||||
return 13.043;
|
||||
case "battle_plasma_grunt": //BW Team Plasma Battle
|
||||
return 12.974;
|
||||
case "battle_flare_grunt": //XY Team Flare Battle
|
||||
return 4.228;
|
||||
case "battle_aether_grunt": // SM Aether Foundation Battle
|
||||
return 16.00;
|
||||
case "battle_skull_grunt": // SM Team Skull Battle
|
||||
return 20.87;
|
||||
case "battle_macro_grunt": // SWSH Trainer Battle
|
||||
return 11.56;
|
||||
case "battle_star_grunt": //SV Team Star Battle
|
||||
return 133.362;
|
||||
case "battle_galactic_admin": //BDSP Team Galactic Admin Battle
|
||||
return 11.997;
|
||||
case "battle_skull_admin": //SM Team Skull Admin Battle
|
||||
return 15.463;
|
||||
case "battle_oleana": //SWSH Oleana Battle
|
||||
return 14.110;
|
||||
case "battle_star_admin": //SV Team Star Boss Battle
|
||||
return 9.493;
|
||||
case "battle_rocket_boss": //USUM Giovanni Battle
|
||||
return 9.115;
|
||||
case "battle_aqua_magma_boss": //ORAS Archie & Maxie Battle
|
||||
return 14.847;
|
||||
case "battle_galactic_boss": //BDSP Cyrus Battle
|
||||
return 106.962;
|
||||
case "battle_plasma_boss": //B2W2 Ghetsis Battle
|
||||
return 25.624;
|
||||
case "battle_flare_boss": //XY Lysandre Battle
|
||||
return 8.085;
|
||||
case "battle_aether_boss": //SM Lusamine Battle
|
||||
return 11.33;
|
||||
case "battle_skull_boss": //SM Guzma Battle
|
||||
return 13.13;
|
||||
case "battle_macro_boss": //SWSH Rose Battle
|
||||
return 11.42;
|
||||
case "battle_star_boss": //SV Cassiopeia Battle
|
||||
return 25.764;
|
||||
case "mystery_encounter_gen_5_gts": // BW GTS
|
||||
return 8.52;
|
||||
case "mystery_encounter_gen_6_gts": // XY GTS
|
||||
return 9.24;
|
||||
case "mystery_encounter_fun_and_games": // EoS Guildmaster Wigglytuff
|
||||
return 4.78;
|
||||
case "mystery_encounter_weird_dream": // EoS Temporal Spire
|
||||
return 41.42;
|
||||
case "mystery_encounter_delibirdy": // Firel Delibirdy
|
||||
return 82.28;
|
||||
case "battle_kanto_champion": //B2W2 Kanto Champion Battle
|
||||
return 13.950;
|
||||
case "battle_johto_champion": //B2W2 Johto Champion Battle
|
||||
return 23.498;
|
||||
case "battle_hoenn_champion_g5": //B2W2 Hoenn Champion Battle
|
||||
return 11.328;
|
||||
case "battle_hoenn_champion_g6": //ORAS Hoenn Champion Battle
|
||||
return 11.762;
|
||||
case "battle_sinnoh_champion": //B2W2 Sinnoh Champion Battle
|
||||
return 12.235;
|
||||
case "battle_champion_alder": //BW Unova Champion Battle
|
||||
return 27.653;
|
||||
case "battle_champion_iris": //B2W2 Unova Champion Battle
|
||||
return 10.145;
|
||||
case "battle_kalos_champion": //XY Kalos Champion Battle
|
||||
return 10.380;
|
||||
case "battle_alola_champion": //USUM Alola Champion Battle
|
||||
return 13.025;
|
||||
case "battle_galar_champion": //SWSH Galar Champion Battle
|
||||
return 61.635;
|
||||
case "battle_champion_geeta": //SV Champion Geeta Battle
|
||||
return 37.447;
|
||||
case "battle_champion_nemona": //SV Champion Nemona Battle
|
||||
return 14.914;
|
||||
case "battle_champion_kieran": //SV Champion Kieran Battle
|
||||
return 7.206;
|
||||
case "battle_hoenn_elite": //ORAS Elite Four Battle
|
||||
return 11.350;
|
||||
case "battle_unova_elite": //BW Elite Four Battle
|
||||
return 17.730;
|
||||
case "battle_kalos_elite": //XY Elite Four Battle
|
||||
return 12.340;
|
||||
case "battle_alola_elite": //SM Elite Four Battle
|
||||
return 19.212;
|
||||
case "battle_galar_elite": //SWSH League Tournament Battle
|
||||
return 164.069;
|
||||
case "battle_paldea_elite": //SV Elite Four Battle
|
||||
return 12.770;
|
||||
case "battle_bb_elite": //SV BB League Elite Four Battle
|
||||
return 19.434;
|
||||
case "battle_final_encounter": //PMD RTDX Rayquaza's Domain
|
||||
return 19.159;
|
||||
case "battle_final": //BW Ghetsis Battle
|
||||
return 16.453;
|
||||
case "battle_kanto_gym": //B2W2 Kanto Gym Battle
|
||||
return 13.857;
|
||||
case "battle_johto_gym": //B2W2 Johto Gym Battle
|
||||
return 12.911;
|
||||
case "battle_hoenn_gym": //B2W2 Hoenn Gym Battle
|
||||
return 12.379;
|
||||
case "battle_sinnoh_gym": //B2W2 Sinnoh Gym Battle
|
||||
return 13.122;
|
||||
case "battle_unova_gym": //BW Unova Gym Battle
|
||||
return 19.145;
|
||||
case "battle_kalos_gym": //XY Kalos Gym Battle
|
||||
return 44.810;
|
||||
case "battle_galar_gym": //SWSH Galar Gym Battle
|
||||
return 171.262;
|
||||
case "battle_paldea_gym": //SV Paldea Gym Battle
|
||||
return 127.489;
|
||||
case "battle_legendary_kanto": //XY Kanto Legendary Battle
|
||||
return 32.966;
|
||||
case "battle_legendary_raikou": //HGSS Raikou Battle
|
||||
return 12.632;
|
||||
case "battle_legendary_entei": //HGSS Entei Battle
|
||||
return 2.905;
|
||||
case "battle_legendary_suicune": //HGSS Suicune Battle
|
||||
return 12.636;
|
||||
case "battle_legendary_lugia": //HGSS Lugia Battle
|
||||
return 19.770;
|
||||
case "battle_legendary_ho_oh": //HGSS Ho-oh Battle
|
||||
return 17.668;
|
||||
case "battle_legendary_regis_g5": //B2W2 Legendary Titan Battle
|
||||
return 49.500;
|
||||
case "battle_legendary_regis_g6": //ORAS Legendary Titan Battle
|
||||
return 21.130;
|
||||
case "battle_legendary_gro_kyo": //ORAS Groudon & Kyogre Battle
|
||||
return 10.547;
|
||||
case "battle_legendary_rayquaza": //ORAS Rayquaza Battle
|
||||
return 10.495;
|
||||
case "battle_legendary_deoxys": //ORAS Deoxys Battle
|
||||
return 13.333;
|
||||
case "battle_legendary_lake_trio": //ORAS Lake Guardians Battle
|
||||
return 16.887;
|
||||
case "battle_legendary_sinnoh": //ORAS Sinnoh Legendary Battle
|
||||
return 22.770;
|
||||
case "battle_legendary_dia_pal": //ORAS Dialga & Palkia Battle
|
||||
return 16.009;
|
||||
case "battle_legendary_origin_forme": //LA Origin Dialga & Palkia Battle
|
||||
return 18.961;
|
||||
case "battle_legendary_giratina": //ORAS Giratina Battle
|
||||
return 10.451;
|
||||
case "battle_legendary_arceus": //HGSS Arceus Battle
|
||||
return 9.595;
|
||||
case "battle_legendary_unova": //BW Unova Legendary Battle
|
||||
return 13.855;
|
||||
case "battle_legendary_kyurem": //BW Kyurem Battle
|
||||
return 18.314;
|
||||
case "battle_legendary_res_zek": //BW Reshiram & Zekrom Battle
|
||||
return 18.329;
|
||||
case "battle_legendary_xern_yvel": //XY Xerneas & Yveltal Battle
|
||||
return 26.468;
|
||||
case "battle_legendary_tapu": //SM Tapu Battle
|
||||
return 0.000;
|
||||
case "battle_legendary_sol_lun": //SM Solgaleo & Lunala Battle
|
||||
return 6.525;
|
||||
case "battle_legendary_ub": //SM Ultra Beast Battle
|
||||
return 9.818;
|
||||
case "battle_legendary_dusk_dawn": //USUM Dusk Mane & Dawn Wings Necrozma Battle
|
||||
return 5.211;
|
||||
case "battle_legendary_ultra_nec": //USUM Ultra Necrozma Battle
|
||||
return 10.344;
|
||||
case "battle_legendary_zac_zam": //SWSH Zacian & Zamazenta Battle
|
||||
return 11.424;
|
||||
case "battle_legendary_glas_spec": //SWSH Glastrier & Spectrier Battle
|
||||
return 12.503;
|
||||
case "battle_legendary_calyrex": //SWSH Calyrex Battle
|
||||
return 50.641;
|
||||
case "battle_legendary_riders": //SWSH Ice & Shadow Rider Calyrex Battle
|
||||
return 18.155;
|
||||
case "battle_legendary_birds_galar": //SWSH Galarian Legendary Birds Battle
|
||||
return 0.175;
|
||||
case "battle_legendary_ruinous": //SV Treasures of Ruin Battle
|
||||
return 6.333;
|
||||
case "battle_legendary_kor_mir": //SV Depths of Area Zero Battle
|
||||
return 6.442;
|
||||
case "battle_legendary_loyal_three": //SV Loyal Three Battle
|
||||
return 6.500;
|
||||
case "battle_legendary_ogerpon": //SV Ogerpon Battle
|
||||
return 14.335;
|
||||
case "battle_legendary_terapagos": //SV Terapagos Battle
|
||||
return 24.377;
|
||||
case "battle_legendary_pecharunt": //SV Pecharunt Battle
|
||||
return 6.508;
|
||||
case "battle_rival": //BW Rival Battle
|
||||
return 14.110;
|
||||
case "battle_rival_2": //BW N Battle
|
||||
return 17.714;
|
||||
case "battle_rival_3": //BW Final N Battle
|
||||
return 17.586;
|
||||
case "battle_trainer": //BW Trainer Battle
|
||||
return 13.686;
|
||||
case "battle_wild": //BW Wild Battle
|
||||
return 12.703;
|
||||
case "battle_wild_strong": //BW Strong Wild Battle
|
||||
return 13.940;
|
||||
case "end_summit": //PMD RTDX Sky Tower Summit
|
||||
return 30.025;
|
||||
case "battle_rocket_grunt": //HGSS Team Rocket Battle
|
||||
return 12.707;
|
||||
case "battle_aqua_magma_grunt": //ORAS Team Aqua & Magma Battle
|
||||
return 12.062;
|
||||
case "battle_galactic_grunt": //BDSP Team Galactic Battle
|
||||
return 13.043;
|
||||
case "battle_plasma_grunt": //BW Team Plasma Battle
|
||||
return 12.974;
|
||||
case "battle_flare_grunt": //XY Team Flare Battle
|
||||
return 4.228;
|
||||
case "battle_aether_grunt": // SM Aether Foundation Battle
|
||||
return 16.00;
|
||||
case "battle_skull_grunt": // SM Team Skull Battle
|
||||
return 20.87;
|
||||
case "battle_macro_grunt": // SWSH Trainer Battle
|
||||
return 11.56;
|
||||
case "battle_star_grunt": //SV Team Star Battle
|
||||
return 133.362;
|
||||
case "battle_galactic_admin": //BDSP Team Galactic Admin Battle
|
||||
return 11.997;
|
||||
case "battle_skull_admin": //SM Team Skull Admin Battle
|
||||
return 15.463;
|
||||
case "battle_oleana": //SWSH Oleana Battle
|
||||
return 14.110;
|
||||
case "battle_star_admin": //SV Team Star Boss Battle
|
||||
return 9.493;
|
||||
case "battle_rocket_boss": //USUM Giovanni Battle
|
||||
return 9.115;
|
||||
case "battle_aqua_magma_boss": //ORAS Archie & Maxie Battle
|
||||
return 14.847;
|
||||
case "battle_galactic_boss": //BDSP Cyrus Battle
|
||||
return 106.962;
|
||||
case "battle_plasma_boss": //B2W2 Ghetsis Battle
|
||||
return 25.624;
|
||||
case "battle_flare_boss": //XY Lysandre Battle
|
||||
return 8.085;
|
||||
case "battle_aether_boss": //SM Lusamine Battle
|
||||
return 11.33;
|
||||
case "battle_skull_boss": //SM Guzma Battle
|
||||
return 13.13;
|
||||
case "battle_macro_boss": //SWSH Rose Battle
|
||||
return 11.42;
|
||||
case "battle_star_boss": //SV Cassiopeia Battle
|
||||
return 25.764;
|
||||
case "mystery_encounter_gen_5_gts": // BW GTS
|
||||
return 8.52;
|
||||
case "mystery_encounter_gen_6_gts": // XY GTS
|
||||
return 9.24;
|
||||
case "mystery_encounter_fun_and_games": // EoS Guildmaster Wigglytuff
|
||||
return 4.78;
|
||||
case "mystery_encounter_weird_dream": // EoS Temporal Spire
|
||||
return 41.42;
|
||||
case "mystery_encounter_delibirdy": // Firel Delibirdy
|
||||
return 82.28;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -2364,6 +2359,19 @@ export default class BattleScene extends SceneBase {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will search for a specific phase in {@linkcode phaseQueuePrepend} via filter, and remove the first result if a match is found.
|
||||
* @param phaseFilter filter function
|
||||
*/
|
||||
tryRemoveUnshiftedPhase(phaseFilter: (phase: Phase) => boolean): boolean {
|
||||
const phaseIndex = this.phaseQueuePrepend.findIndex(phaseFilter);
|
||||
if (phaseIndex > -1) {
|
||||
this.phaseQueuePrepend.splice(phaseIndex, 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to add the input phase to index before target phase in the phaseQueue, else simply calls unshiftPhase()
|
||||
* @param phase {@linkcode Phase} the phase to be added
|
||||
|
@ -3125,18 +3133,26 @@ export default class BattleScene extends SceneBase {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if a wave COULD spawn a {@linkcode MysteryEncounter}.
|
||||
* Even if returns `true`, does not guarantee that a wave will actually be a ME.
|
||||
* That check is made in {@linkcode BattleScene.isWaveMysteryEncounter} instead.
|
||||
*/
|
||||
isMysteryEncounterValidForWave(battleType: BattleType, waveIndex: number): boolean {
|
||||
const [ lowestMysteryEncounterWave, highestMysteryEncounterWave ] = this.gameMode.getMysteryEncounterLegalWaves();
|
||||
return this.gameMode.hasMysteryEncounters && battleType === BattleType.WILD && !this.gameMode.isBoss(waveIndex) && waveIndex < highestMysteryEncounterWave && waveIndex > lowestMysteryEncounterWave;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a wave should randomly generate a {@linkcode MysteryEncounter}.
|
||||
* Currently, the only modes that MEs are allowed in are Classic and Challenge.
|
||||
* Additionally, MEs cannot spawn outside of waves 10-180 in those modes
|
||||
*
|
||||
* @param newBattleType
|
||||
* @param waveIndex
|
||||
* @param sessionDataEncounterType
|
||||
*/
|
||||
private isWaveMysteryEncounter(newBattleType: BattleType, waveIndex: number, sessionDataEncounterType?: MysteryEncounterType): boolean {
|
||||
private isWaveMysteryEncounter(newBattleType: BattleType, waveIndex: number): boolean {
|
||||
const [ lowestMysteryEncounterWave, highestMysteryEncounterWave ] = this.gameMode.getMysteryEncounterLegalWaves();
|
||||
if (this.gameMode.hasMysteryEncounters && newBattleType === BattleType.WILD && !this.gameMode.isBoss(waveIndex) && waveIndex < highestMysteryEncounterWave && waveIndex > lowestMysteryEncounterWave) {
|
||||
if (this.isMysteryEncounterValidForWave(newBattleType, waveIndex)) {
|
||||
// Base spawn weight is BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT/256, and increases by WEIGHT_INCREMENT_ON_SPAWN_MISS/256 for each missed attempt at spawning an encounter on a valid floor
|
||||
const sessionEncounterRate = this.mysteryEncounterSaveData.encounterSpawnChance;
|
||||
const encounteredEvents = this.mysteryEncounterSaveData.encounteredEvents;
|
||||
|
@ -3177,6 +3193,9 @@ export default class BattleScene extends SceneBase {
|
|||
let encounter: MysteryEncounter | null;
|
||||
if (!isNullOrUndefined(Overrides.MYSTERY_ENCOUNTER_OVERRIDE) && allMysteryEncounters.hasOwnProperty(Overrides.MYSTERY_ENCOUNTER_OVERRIDE)) {
|
||||
encounter = allMysteryEncounters[Overrides.MYSTERY_ENCOUNTER_OVERRIDE];
|
||||
if (canBypass) {
|
||||
return encounter;
|
||||
}
|
||||
} else if (canBypass) {
|
||||
encounter = allMysteryEncounters[encounterType ?? -1];
|
||||
return encounter;
|
||||
|
|
|
@ -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.
|
||||
switch (weatherType) {
|
||||
case (WeatherType.HARSH_SUN):
|
||||
if (pokemon.hasAbility(Abilities.DESOLATE_LAND)
|
||||
case (WeatherType.HARSH_SUN):
|
||||
if (pokemon.hasAbility(Abilities.DESOLATE_LAND)
|
||||
&& pokemon.scene.getField(true).filter(p => p !== pokemon).filter(p => p.hasAbility(Abilities.DESOLATE_LAND)).length === 0) {
|
||||
turnOffWeather = true;
|
||||
}
|
||||
break;
|
||||
case (WeatherType.HEAVY_RAIN):
|
||||
if (pokemon.hasAbility(Abilities.PRIMORDIAL_SEA)
|
||||
turnOffWeather = true;
|
||||
}
|
||||
break;
|
||||
case (WeatherType.HEAVY_RAIN):
|
||||
if (pokemon.hasAbility(Abilities.PRIMORDIAL_SEA)
|
||||
&& pokemon.scene.getField(true).filter(p => p !== pokemon).filter(p => p.hasAbility(Abilities.PRIMORDIAL_SEA)).length === 0) {
|
||||
turnOffWeather = true;
|
||||
}
|
||||
break;
|
||||
case (WeatherType.STRONG_WINDS):
|
||||
if (pokemon.hasAbility(Abilities.DELTA_STREAM)
|
||||
turnOffWeather = true;
|
||||
}
|
||||
break;
|
||||
case (WeatherType.STRONG_WINDS):
|
||||
if (pokemon.hasAbility(Abilities.DELTA_STREAM)
|
||||
&& pokemon.scene.getField(true).filter(p => p !== pokemon).filter(p => p.hasAbility(Abilities.DELTA_STREAM)).length === 0) {
|
||||
turnOffWeather = true;
|
||||
}
|
||||
break;
|
||||
turnOffWeather = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
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.
|
||||
switch (weatherType) {
|
||||
case (WeatherType.HARSH_SUN):
|
||||
if (pokemon.hasAbility(Abilities.DESOLATE_LAND)
|
||||
case (WeatherType.HARSH_SUN):
|
||||
if (pokemon.hasAbility(Abilities.DESOLATE_LAND)
|
||||
&& pokemon.scene.getField(true).filter(p => p.hasAbility(Abilities.DESOLATE_LAND)).length === 0) {
|
||||
turnOffWeather = true;
|
||||
}
|
||||
break;
|
||||
case (WeatherType.HEAVY_RAIN):
|
||||
if (pokemon.hasAbility(Abilities.PRIMORDIAL_SEA)
|
||||
turnOffWeather = true;
|
||||
}
|
||||
break;
|
||||
case (WeatherType.HEAVY_RAIN):
|
||||
if (pokemon.hasAbility(Abilities.PRIMORDIAL_SEA)
|
||||
&& pokemon.scene.getField(true).filter(p => p.hasAbility(Abilities.PRIMORDIAL_SEA)).length === 0) {
|
||||
turnOffWeather = true;
|
||||
}
|
||||
break;
|
||||
case (WeatherType.STRONG_WINDS):
|
||||
if (pokemon.hasAbility(Abilities.DELTA_STREAM)
|
||||
turnOffWeather = true;
|
||||
}
|
||||
break;
|
||||
case (WeatherType.STRONG_WINDS):
|
||||
if (pokemon.hasAbility(Abilities.DELTA_STREAM)
|
||||
&& pokemon.scene.getField(true).filter(p => p.hasAbility(Abilities.DELTA_STREAM)).length === 0) {
|
||||
turnOffWeather = true;
|
||||
}
|
||||
break;
|
||||
turnOffWeather = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (simulated) {
|
||||
|
|
|
@ -88,13 +88,13 @@ export abstract class ArenaTag {
|
|||
*/
|
||||
public getAffectedPokemon(scene: BattleScene): Pokemon[] {
|
||||
switch (this.side) {
|
||||
case ArenaTagSide.PLAYER:
|
||||
return scene.getPlayerField() ?? [];
|
||||
case ArenaTagSide.ENEMY:
|
||||
return scene.getEnemyField() ?? [];
|
||||
case ArenaTagSide.BOTH:
|
||||
default:
|
||||
return scene.getField(true) ?? [];
|
||||
case ArenaTagSide.PLAYER:
|
||||
return scene.getPlayerField() ?? [];
|
||||
case ArenaTagSide.ENEMY:
|
||||
return scene.getEnemyField() ?? [];
|
||||
case ArenaTagSide.BOTH:
|
||||
default:
|
||||
return scene.getField(true) ?? [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -332,11 +332,11 @@ const WideGuardConditionFunc: ProtectConditionFunc = (arena, moveId) : boolean =
|
|||
const move = allMoves[moveId];
|
||||
|
||||
switch (move.moveTarget) {
|
||||
case MoveTarget.ALL_ENEMIES:
|
||||
case MoveTarget.ALL_NEAR_ENEMIES:
|
||||
case MoveTarget.ALL_OTHERS:
|
||||
case MoveTarget.ALL_NEAR_OTHERS:
|
||||
return true;
|
||||
case MoveTarget.ALL_ENEMIES:
|
||||
case MoveTarget.ALL_NEAR_ENEMIES:
|
||||
case MoveTarget.ALL_OTHERS:
|
||||
case MoveTarget.ALL_NEAR_OTHERS:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
@ -626,7 +626,7 @@ export class ArenaTrapTag extends ArenaTag {
|
|||
* @returns `true` if this hazard affects the given Pokemon; `false` otherwise.
|
||||
*/
|
||||
override apply(arena: Arena, simulated: boolean, pokemon: Pokemon): boolean {
|
||||
if (this.sourceId === pokemon.id || (this.side === ArenaTagSide.PLAYER) !== pokemon.isPlayer()) {
|
||||
if ((this.side === ArenaTagSide.PLAYER) !== pokemon.isPlayer()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -807,24 +807,24 @@ class StealthRockTag extends ArenaTrapTag {
|
|||
let damageHpRatio: number = 0;
|
||||
|
||||
switch (effectiveness) {
|
||||
case 0:
|
||||
damageHpRatio = 0;
|
||||
break;
|
||||
case 0.25:
|
||||
damageHpRatio = 0.03125;
|
||||
break;
|
||||
case 0.5:
|
||||
damageHpRatio = 0.0625;
|
||||
break;
|
||||
case 1:
|
||||
damageHpRatio = 0.125;
|
||||
break;
|
||||
case 2:
|
||||
damageHpRatio = 0.25;
|
||||
break;
|
||||
case 4:
|
||||
damageHpRatio = 0.5;
|
||||
break;
|
||||
case 0:
|
||||
damageHpRatio = 0;
|
||||
break;
|
||||
case 0.25:
|
||||
damageHpRatio = 0.03125;
|
||||
break;
|
||||
case 0.5:
|
||||
damageHpRatio = 0.0625;
|
||||
break;
|
||||
case 1:
|
||||
damageHpRatio = 0.125;
|
||||
break;
|
||||
case 2:
|
||||
damageHpRatio = 0.25;
|
||||
break;
|
||||
case 4:
|
||||
damageHpRatio = 0.5;
|
||||
break;
|
||||
}
|
||||
|
||||
return damageHpRatio;
|
||||
|
@ -1185,63 +1185,63 @@ class GrassWaterPledgeTag extends ArenaTag {
|
|||
// 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 {
|
||||
switch (tagType) {
|
||||
case ArenaTagType.MIST:
|
||||
return new MistTag(turnCount, sourceId, side);
|
||||
case ArenaTagType.QUICK_GUARD:
|
||||
return new QuickGuardTag(sourceId, side);
|
||||
case ArenaTagType.WIDE_GUARD:
|
||||
return new WideGuardTag(sourceId, side);
|
||||
case ArenaTagType.MAT_BLOCK:
|
||||
return new MatBlockTag(sourceId, side);
|
||||
case ArenaTagType.CRAFTY_SHIELD:
|
||||
return new CraftyShieldTag(sourceId, side);
|
||||
case ArenaTagType.NO_CRIT:
|
||||
return new NoCritTag(turnCount, sourceMove!, sourceId, side); // TODO: is this bang correct?
|
||||
case ArenaTagType.MUD_SPORT:
|
||||
return new MudSportTag(turnCount, sourceId);
|
||||
case ArenaTagType.WATER_SPORT:
|
||||
return new WaterSportTag(turnCount, sourceId);
|
||||
case ArenaTagType.ION_DELUGE:
|
||||
return new IonDelugeTag(sourceMove);
|
||||
case ArenaTagType.SPIKES:
|
||||
return new SpikesTag(sourceId, side);
|
||||
case ArenaTagType.TOXIC_SPIKES:
|
||||
return new ToxicSpikesTag(sourceId, side);
|
||||
case ArenaTagType.FUTURE_SIGHT:
|
||||
case ArenaTagType.DOOM_DESIRE:
|
||||
return new DelayedAttackTag(tagType, sourceMove, sourceId, targetIndex!); // TODO:questionable bang
|
||||
case ArenaTagType.WISH:
|
||||
return new WishTag(turnCount, sourceId, side);
|
||||
case ArenaTagType.STEALTH_ROCK:
|
||||
return new StealthRockTag(sourceId, side);
|
||||
case ArenaTagType.STICKY_WEB:
|
||||
return new StickyWebTag(sourceId, side);
|
||||
case ArenaTagType.TRICK_ROOM:
|
||||
return new TrickRoomTag(turnCount, sourceId);
|
||||
case ArenaTagType.GRAVITY:
|
||||
return new GravityTag(turnCount);
|
||||
case ArenaTagType.REFLECT:
|
||||
return new ReflectTag(turnCount, sourceId, side);
|
||||
case ArenaTagType.LIGHT_SCREEN:
|
||||
return new LightScreenTag(turnCount, sourceId, side);
|
||||
case ArenaTagType.AURORA_VEIL:
|
||||
return new AuroraVeilTag(turnCount, sourceId, side);
|
||||
case ArenaTagType.TAILWIND:
|
||||
return new TailwindTag(turnCount, sourceId, side);
|
||||
case ArenaTagType.HAPPY_HOUR:
|
||||
return new HappyHourTag(turnCount, sourceId, side);
|
||||
case ArenaTagType.SAFEGUARD:
|
||||
return new SafeguardTag(turnCount, sourceId, side);
|
||||
case ArenaTagType.IMPRISON:
|
||||
return new ImprisonTag(sourceId, side);
|
||||
case ArenaTagType.FIRE_GRASS_PLEDGE:
|
||||
return new FireGrassPledgeTag(sourceId, side);
|
||||
case ArenaTagType.WATER_FIRE_PLEDGE:
|
||||
return new WaterFirePledgeTag(sourceId, side);
|
||||
case ArenaTagType.GRASS_WATER_PLEDGE:
|
||||
return new GrassWaterPledgeTag(sourceId, side);
|
||||
default:
|
||||
return null;
|
||||
case ArenaTagType.MIST:
|
||||
return new MistTag(turnCount, sourceId, side);
|
||||
case ArenaTagType.QUICK_GUARD:
|
||||
return new QuickGuardTag(sourceId, side);
|
||||
case ArenaTagType.WIDE_GUARD:
|
||||
return new WideGuardTag(sourceId, side);
|
||||
case ArenaTagType.MAT_BLOCK:
|
||||
return new MatBlockTag(sourceId, side);
|
||||
case ArenaTagType.CRAFTY_SHIELD:
|
||||
return new CraftyShieldTag(sourceId, side);
|
||||
case ArenaTagType.NO_CRIT:
|
||||
return new NoCritTag(turnCount, sourceMove!, sourceId, side); // TODO: is this bang correct?
|
||||
case ArenaTagType.MUD_SPORT:
|
||||
return new MudSportTag(turnCount, sourceId);
|
||||
case ArenaTagType.WATER_SPORT:
|
||||
return new WaterSportTag(turnCount, sourceId);
|
||||
case ArenaTagType.ION_DELUGE:
|
||||
return new IonDelugeTag(sourceMove);
|
||||
case ArenaTagType.SPIKES:
|
||||
return new SpikesTag(sourceId, side);
|
||||
case ArenaTagType.TOXIC_SPIKES:
|
||||
return new ToxicSpikesTag(sourceId, side);
|
||||
case ArenaTagType.FUTURE_SIGHT:
|
||||
case ArenaTagType.DOOM_DESIRE:
|
||||
return new DelayedAttackTag(tagType, sourceMove, sourceId, targetIndex!); // TODO:questionable bang
|
||||
case ArenaTagType.WISH:
|
||||
return new WishTag(turnCount, sourceId, side);
|
||||
case ArenaTagType.STEALTH_ROCK:
|
||||
return new StealthRockTag(sourceId, side);
|
||||
case ArenaTagType.STICKY_WEB:
|
||||
return new StickyWebTag(sourceId, side);
|
||||
case ArenaTagType.TRICK_ROOM:
|
||||
return new TrickRoomTag(turnCount, sourceId);
|
||||
case ArenaTagType.GRAVITY:
|
||||
return new GravityTag(turnCount);
|
||||
case ArenaTagType.REFLECT:
|
||||
return new ReflectTag(turnCount, sourceId, side);
|
||||
case ArenaTagType.LIGHT_SCREEN:
|
||||
return new LightScreenTag(turnCount, sourceId, side);
|
||||
case ArenaTagType.AURORA_VEIL:
|
||||
return new AuroraVeilTag(turnCount, sourceId, side);
|
||||
case ArenaTagType.TAILWIND:
|
||||
return new TailwindTag(turnCount, sourceId, side);
|
||||
case ArenaTagType.HAPPY_HOUR:
|
||||
return new HappyHourTag(turnCount, sourceId, side);
|
||||
case ArenaTagType.SAFEGUARD:
|
||||
return new SafeguardTag(turnCount, sourceId, side);
|
||||
case ArenaTagType.IMPRISON:
|
||||
return new ImprisonTag(sourceId, side);
|
||||
case ArenaTagType.FIRE_GRASS_PLEDGE:
|
||||
return new FireGrassPledgeTag(sourceId, side);
|
||||
case ArenaTagType.WATER_FIRE_PLEDGE:
|
||||
return new WaterFirePledgeTag(sourceId, side);
|
||||
case ArenaTagType.GRASS_WATER_PLEDGE:
|
||||
return new GrassWaterPledgeTag(sourceId, side);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,14 +13,14 @@ export function getBiomeName(biome: Biome | -1) {
|
|||
return i18next.t("biome:unknownLocation");
|
||||
}
|
||||
switch (biome) {
|
||||
case Biome.GRASS:
|
||||
return i18next.t("biome:GRASS");
|
||||
case Biome.RUINS:
|
||||
return i18next.t("biome:RUINS");
|
||||
case Biome.END:
|
||||
return i18next.t("biome:END");
|
||||
default:
|
||||
return i18next.t(`biome:${Biome[biome].toUpperCase()}`);
|
||||
case Biome.GRASS:
|
||||
return i18next.t("biome:GRASS");
|
||||
case Biome.RUINS:
|
||||
return i18next.t("biome:RUINS");
|
||||
case Biome.END:
|
||||
return i18next.t("biome:END");
|
||||
default:
|
||||
return i18next.t(`biome:${Biome[biome].toUpperCase()}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,25 +15,25 @@ export const FRIENDSHIP_LOSS_FROM_FAINT = 10;
|
|||
*/
|
||||
export function getStarterValueFriendshipCap(starterCost: number): number {
|
||||
switch (starterCost) {
|
||||
case 1:
|
||||
return 20;
|
||||
case 2:
|
||||
return 40;
|
||||
case 3:
|
||||
return 60;
|
||||
case 4:
|
||||
return 100;
|
||||
case 5:
|
||||
return 140;
|
||||
case 6:
|
||||
return 200;
|
||||
case 7:
|
||||
return 280;
|
||||
case 8:
|
||||
case 9:
|
||||
return 450;
|
||||
default:
|
||||
return 600;
|
||||
case 1:
|
||||
return 20;
|
||||
case 2:
|
||||
return 40;
|
||||
case 3:
|
||||
return 60;
|
||||
case 4:
|
||||
return 100;
|
||||
case 5:
|
||||
return 140;
|
||||
case 6:
|
||||
return 200;
|
||||
case 7:
|
||||
return 280;
|
||||
case 8:
|
||||
case 9:
|
||||
return 450;
|
||||
default:
|
||||
return 600;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -134,15 +134,15 @@ export class AnimConfig {
|
|||
for (const te of frameTimedEvents[fte]) {
|
||||
let timedEvent: AnimTimedEvent | undefined;
|
||||
switch (te.eventType) {
|
||||
case "AnimTimedSoundEvent":
|
||||
timedEvent = new AnimTimedSoundEvent(te.frameIndex, te.resourceName, te);
|
||||
break;
|
||||
case "AnimTimedAddBgEvent":
|
||||
timedEvent = new AnimTimedAddBgEvent(te.frameIndex, te.resourceName, te);
|
||||
break;
|
||||
case "AnimTimedUpdateBgEvent":
|
||||
timedEvent = new AnimTimedUpdateBgEvent(te.frameIndex, te.resourceName, te);
|
||||
break;
|
||||
case "AnimTimedSoundEvent":
|
||||
timedEvent = new AnimTimedSoundEvent(te.frameIndex, te.resourceName, te);
|
||||
break;
|
||||
case "AnimTimedAddBgEvent":
|
||||
timedEvent = new AnimTimedAddBgEvent(te.frameIndex, te.resourceName, te);
|
||||
break;
|
||||
case "AnimTimedUpdateBgEvent":
|
||||
timedEvent = new AnimTimedUpdateBgEvent(te.frameIndex, te.resourceName, te);
|
||||
break;
|
||||
}
|
||||
|
||||
timedEvent && timedEvents.push(timedEvent);
|
||||
|
@ -243,12 +243,12 @@ class AnimFrame {
|
|||
if (!init) {
|
||||
let target = AnimFrameTarget.GRAPHIC;
|
||||
switch (pattern) {
|
||||
case -2:
|
||||
target = AnimFrameTarget.TARGET;
|
||||
break;
|
||||
case -1:
|
||||
target = AnimFrameTarget.USER;
|
||||
break;
|
||||
case -2:
|
||||
target = AnimFrameTarget.TARGET;
|
||||
break;
|
||||
case -1:
|
||||
target = AnimFrameTarget.USER;
|
||||
break;
|
||||
}
|
||||
this.target = target;
|
||||
this.graphicFrame = pattern >= 0 ? pattern : 0;
|
||||
|
@ -803,23 +803,23 @@ export abstract class BattleAnim {
|
|||
let scaleX = (frame.zoomX / 100) * (!frame.mirror ? 1 : -1);
|
||||
const scaleY = (frame.zoomY / 100);
|
||||
switch (frame.focus) {
|
||||
case AnimFocus.TARGET:
|
||||
x += targetInitialX - targetFocusX;
|
||||
y += (targetInitialY - targetHalfHeight) - targetFocusY;
|
||||
break;
|
||||
case AnimFocus.USER:
|
||||
x += userInitialX - userFocusX;
|
||||
y += (userInitialY - userHalfHeight) - userFocusY;
|
||||
break;
|
||||
case AnimFocus.USER_TARGET:
|
||||
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);
|
||||
x = point[0];
|
||||
y = point[1];
|
||||
if (frame.target === AnimFrameTarget.GRAPHIC && isReversed(this.srcLine[0], this.srcLine[2], this.dstLine[0], this.dstLine[2])) {
|
||||
scaleX = scaleX * -1;
|
||||
}
|
||||
break;
|
||||
case AnimFocus.TARGET:
|
||||
x += targetInitialX - targetFocusX;
|
||||
y += (targetInitialY - targetHalfHeight) - targetFocusY;
|
||||
break;
|
||||
case AnimFocus.USER:
|
||||
x += userInitialX - userFocusX;
|
||||
y += (userInitialY - userHalfHeight) - userFocusY;
|
||||
break;
|
||||
case AnimFocus.USER_TARGET:
|
||||
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);
|
||||
x = point[0];
|
||||
y = point[1];
|
||||
if (frame.target === AnimFrameTarget.GRAPHIC && isReversed(this.srcLine[0], this.srcLine[2], this.dstLine[0], this.dstLine[2])) {
|
||||
scaleX = scaleX * -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
const angle = -frame.angle;
|
||||
const key = frame.target === AnimFrameTarget.GRAPHIC ? g++ : frame.target === AnimFrameTarget.USER ? u++ : t++;
|
||||
|
@ -993,44 +993,44 @@ export abstract class BattleAnim {
|
|||
spritePriorities[graphicIndex] = frame.priority;
|
||||
const setSpritePriority = (priority: integer) => {
|
||||
switch (priority) {
|
||||
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?
|
||||
break;
|
||||
case 1:
|
||||
scene.field.moveTo(moveSprite, scene.field.getAll().length - 1);
|
||||
break;
|
||||
case 2:
|
||||
switch (frame.focus) {
|
||||
case AnimFocus.USER:
|
||||
if (this.bgSprite) {
|
||||
scene.field.moveAbove(moveSprite as Phaser.GameObjects.GameObject, this.bgSprite);
|
||||
} else {
|
||||
scene.field.moveBelow(moveSprite as Phaser.GameObjects.GameObject, this.user!); // TODO: is this bang correct?
|
||||
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?
|
||||
break;
|
||||
case 1:
|
||||
scene.field.moveTo(moveSprite, scene.field.getAll().length - 1);
|
||||
break;
|
||||
case 2:
|
||||
switch (frame.focus) {
|
||||
case AnimFocus.USER:
|
||||
if (this.bgSprite) {
|
||||
scene.field.moveAbove(moveSprite as Phaser.GameObjects.GameObject, this.bgSprite);
|
||||
} else {
|
||||
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;
|
||||
case AnimFocus.TARGET:
|
||||
scene.field.moveBelow(moveSprite as Phaser.GameObjects.GameObject, this.target!); // TODO: is this bang correct?
|
||||
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);
|
||||
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);
|
||||
|
@ -1396,108 +1396,108 @@ export async function populateAnims() {
|
|||
const fieldName = field.slice(0, field.indexOf(":"));
|
||||
const fieldData = field.slice(fieldName.length + 1, field.lastIndexOf("\n")).trim();
|
||||
switch (fieldName) {
|
||||
case "array":
|
||||
const framesData = fieldData.split(" - - - ").slice(1);
|
||||
for (let fd = 0; fd < framesData.length; fd++) {
|
||||
anim.frames.push([]);
|
||||
const frameData = framesData[fd];
|
||||
const focusFramesData = frameData.split(" - - ");
|
||||
for (let tf = 0; tf < focusFramesData.length; tf++) {
|
||||
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]),
|
||||
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[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);
|
||||
case "array":
|
||||
const framesData = fieldData.split(" - - - ").slice(1);
|
||||
for (let fd = 0; fd < framesData.length; fd++) {
|
||||
anim.frames.push([]);
|
||||
const frameData = framesData[fd];
|
||||
const focusFramesData = frameData.split(" - - ");
|
||||
for (let tf = 0; tf < focusFramesData.length; tf++) {
|
||||
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]),
|
||||
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[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);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "graphic":
|
||||
const graphic = fieldData !== "''" ? fieldData : "";
|
||||
anim.graphic = graphic.indexOf(".") > -1
|
||||
? graphic.slice(0, fieldData.indexOf("."))
|
||||
: graphic;
|
||||
break;
|
||||
case "timing":
|
||||
const timingEntries = fieldData.split("- !ruby/object:PBAnimTiming ").slice(1);
|
||||
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\",")
|
||||
.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?
|
||||
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?
|
||||
let timedEvent: AnimTimedEvent | undefined;
|
||||
switch (timingType) {
|
||||
case 0:
|
||||
if (resourceName && resourceName.indexOf(".") === -1) {
|
||||
let ext: string | undefined;
|
||||
[ "wav", "mp3", "m4a" ].every(e => {
|
||||
if (seNames.indexOf(`${resourceName}.${e}`) > -1) {
|
||||
ext = e;
|
||||
return false;
|
||||
break;
|
||||
case "graphic":
|
||||
const graphic = fieldData !== "''" ? fieldData : "";
|
||||
anim.graphic = graphic.indexOf(".") > -1
|
||||
? graphic.slice(0, fieldData.indexOf("."))
|
||||
: graphic;
|
||||
break;
|
||||
case "timing":
|
||||
const timingEntries = fieldData.split("- !ruby/object:PBAnimTiming ").slice(1);
|
||||
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\",")
|
||||
.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?
|
||||
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?
|
||||
let timedEvent: AnimTimedEvent | undefined;
|
||||
switch (timingType) {
|
||||
case 0:
|
||||
if (resourceName && resourceName.indexOf(".") === -1) {
|
||||
let ext: string | undefined;
|
||||
[ "wav", "mp3", "m4a" ].every(e => {
|
||||
if (seNames.indexOf(`${resourceName}.${e}`) > -1) {
|
||||
ext = e;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
if (!ext) {
|
||||
ext = ".wav";
|
||||
}
|
||||
resourceName += `.${ext}`;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
if (!ext) {
|
||||
ext = ".wav";
|
||||
timedEvent = new AnimTimedSoundEvent(frameIndex, resourceName);
|
||||
break;
|
||||
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;
|
||||
}
|
||||
resourceName += `.${ext}`;
|
||||
}
|
||||
timedEvent = new AnimTimedSoundEvent(frameIndex, resourceName);
|
||||
break;
|
||||
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 (!anim.frameTimedEvents.has(frameIndex)) {
|
||||
anim.frameTimedEvents.set(frameIndex, []);
|
||||
}
|
||||
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?
|
||||
}
|
||||
break;
|
||||
case "position":
|
||||
anim.position = parseInt(fieldData);
|
||||
break;
|
||||
case "hue":
|
||||
anim.hue = parseInt(fieldData);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "position":
|
||||
anim.position = parseInt(fieldData);
|
||||
break;
|
||||
case "hue":
|
||||
anim.hue = parseInt(fieldData);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -919,14 +919,14 @@ export class EncoreTag extends BattlerTag {
|
|||
}
|
||||
|
||||
switch (repeatableMove.move) {
|
||||
case Moves.MIMIC:
|
||||
case Moves.MIRROR_MOVE:
|
||||
case Moves.TRANSFORM:
|
||||
case Moves.STRUGGLE:
|
||||
case Moves.SKETCH:
|
||||
case Moves.SLEEP_TALK:
|
||||
case Moves.ENCORE:
|
||||
return false;
|
||||
case Moves.MIMIC:
|
||||
case Moves.MIRROR_MOVE:
|
||||
case Moves.TRANSFORM:
|
||||
case Moves.STRUGGLE:
|
||||
case Moves.SKETCH:
|
||||
case Moves.SLEEP_TALK:
|
||||
case Moves.ENCORE:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (allMoves[repeatableMove.move].hasAttr(ChargeAttr) && repeatableMove.result === MoveResult.OTHER) {
|
||||
|
@ -1641,12 +1641,12 @@ export class HighestStatBoostTag extends AbilityBattlerTag {
|
|||
this.stat = highestStat;
|
||||
|
||||
switch (this.stat) {
|
||||
case Stat.SPD:
|
||||
this.multiplier = 1.5;
|
||||
break;
|
||||
default:
|
||||
this.multiplier = 1.3;
|
||||
break;
|
||||
case Stat.SPD:
|
||||
this.multiplier = 1.5;
|
||||
break;
|
||||
default:
|
||||
this.multiplier = 1.3;
|
||||
break;
|
||||
}
|
||||
|
||||
pokemon.scene.queueMessage(i18next.t("battlerTags:highestStatBoostOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), statName: i18next.t(getStatKey(highestStat)) }), null, false, null, true);
|
||||
|
@ -2436,15 +2436,15 @@ export class SubstituteTag extends BattlerTag {
|
|||
|
||||
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
|
||||
switch (lapseType) {
|
||||
case BattlerTagLapseType.PRE_MOVE:
|
||||
this.onPreMove(pokemon);
|
||||
break;
|
||||
case BattlerTagLapseType.AFTER_MOVE:
|
||||
this.onAfterMove(pokemon);
|
||||
break;
|
||||
case BattlerTagLapseType.HIT:
|
||||
this.onHit(pokemon);
|
||||
break;
|
||||
case BattlerTagLapseType.PRE_MOVE:
|
||||
this.onPreMove(pokemon);
|
||||
break;
|
||||
case BattlerTagLapseType.AFTER_MOVE:
|
||||
this.onAfterMove(pokemon);
|
||||
break;
|
||||
case BattlerTagLapseType.HIT:
|
||||
this.onHit(pokemon);
|
||||
break;
|
||||
}
|
||||
return lapseType !== BattlerTagLapseType.CUSTOM; // only remove this tag on custom lapse
|
||||
}
|
||||
|
@ -2769,179 +2769,179 @@ export class PowerTrickTag extends BattlerTag {
|
|||
*/
|
||||
export function getBattlerTag(tagType: BattlerTagType, turnCount: number, sourceMove: Moves, sourceId: number): BattlerTag {
|
||||
switch (tagType) {
|
||||
case BattlerTagType.RECHARGING:
|
||||
return new RechargingTag(sourceMove);
|
||||
case BattlerTagType.BEAK_BLAST_CHARGING:
|
||||
return new BeakBlastChargingTag();
|
||||
case BattlerTagType.SHELL_TRAP:
|
||||
return new ShellTrapTag();
|
||||
case BattlerTagType.FLINCHED:
|
||||
return new FlinchedTag(sourceMove);
|
||||
case BattlerTagType.INTERRUPTED:
|
||||
return new InterruptedTag(sourceMove);
|
||||
case BattlerTagType.CONFUSED:
|
||||
return new ConfusedTag(turnCount, sourceMove);
|
||||
case BattlerTagType.INFATUATED:
|
||||
return new InfatuatedTag(sourceMove, sourceId);
|
||||
case BattlerTagType.SEEDED:
|
||||
return new SeedTag(sourceId);
|
||||
case BattlerTagType.NIGHTMARE:
|
||||
return new NightmareTag();
|
||||
case BattlerTagType.FRENZY:
|
||||
return new FrenzyTag(turnCount, sourceMove, sourceId);
|
||||
case BattlerTagType.CHARGING:
|
||||
return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, 1, sourceMove, sourceId);
|
||||
case BattlerTagType.ENCORE:
|
||||
return new EncoreTag(sourceId);
|
||||
case BattlerTagType.HELPING_HAND:
|
||||
return new HelpingHandTag(sourceId);
|
||||
case BattlerTagType.INGRAIN:
|
||||
return new IngrainTag(sourceId);
|
||||
case BattlerTagType.AQUA_RING:
|
||||
return new AquaRingTag();
|
||||
case BattlerTagType.DROWSY:
|
||||
return new DrowsyTag();
|
||||
case BattlerTagType.TRAPPED:
|
||||
return new TrappedTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId);
|
||||
case BattlerTagType.NO_RETREAT:
|
||||
return new NoRetreatTag(sourceId);
|
||||
case BattlerTagType.BIND:
|
||||
return new BindTag(turnCount, sourceId);
|
||||
case BattlerTagType.WRAP:
|
||||
return new WrapTag(turnCount, sourceId);
|
||||
case BattlerTagType.FIRE_SPIN:
|
||||
return new FireSpinTag(turnCount, sourceId);
|
||||
case BattlerTagType.WHIRLPOOL:
|
||||
return new WhirlpoolTag(turnCount, sourceId);
|
||||
case BattlerTagType.CLAMP:
|
||||
return new ClampTag(turnCount, sourceId);
|
||||
case BattlerTagType.SAND_TOMB:
|
||||
return new SandTombTag(turnCount, sourceId);
|
||||
case BattlerTagType.MAGMA_STORM:
|
||||
return new MagmaStormTag(turnCount, sourceId);
|
||||
case BattlerTagType.SNAP_TRAP:
|
||||
return new SnapTrapTag(turnCount, sourceId);
|
||||
case BattlerTagType.THUNDER_CAGE:
|
||||
return new ThunderCageTag(turnCount, sourceId);
|
||||
case BattlerTagType.INFESTATION:
|
||||
return new InfestationTag(turnCount, sourceId);
|
||||
case BattlerTagType.PROTECTED:
|
||||
return new ProtectedTag(sourceMove);
|
||||
case BattlerTagType.SPIKY_SHIELD:
|
||||
return new ContactDamageProtectedTag(sourceMove, 8);
|
||||
case BattlerTagType.KINGS_SHIELD:
|
||||
return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.ATK, -1);
|
||||
case BattlerTagType.OBSTRUCT:
|
||||
return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.DEF, -2);
|
||||
case BattlerTagType.SILK_TRAP:
|
||||
return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.SPD, -1);
|
||||
case BattlerTagType.BANEFUL_BUNKER:
|
||||
return new ContactPoisonProtectedTag(sourceMove);
|
||||
case BattlerTagType.BURNING_BULWARK:
|
||||
return new ContactBurnProtectedTag(sourceMove);
|
||||
case BattlerTagType.ENDURING:
|
||||
return new EnduringTag(sourceMove);
|
||||
case BattlerTagType.STURDY:
|
||||
return new SturdyTag(sourceMove);
|
||||
case BattlerTagType.PERISH_SONG:
|
||||
return new PerishSongTag(turnCount);
|
||||
case BattlerTagType.CENTER_OF_ATTENTION:
|
||||
return new CenterOfAttentionTag(sourceMove);
|
||||
case BattlerTagType.TRUANT:
|
||||
return new TruantTag();
|
||||
case BattlerTagType.SLOW_START:
|
||||
return new SlowStartTag();
|
||||
case BattlerTagType.PROTOSYNTHESIS:
|
||||
return new WeatherHighestStatBoostTag(tagType, Abilities.PROTOSYNTHESIS, WeatherType.SUNNY, WeatherType.HARSH_SUN);
|
||||
case BattlerTagType.QUARK_DRIVE:
|
||||
return new TerrainHighestStatBoostTag(tagType, Abilities.QUARK_DRIVE, TerrainType.ELECTRIC);
|
||||
case BattlerTagType.FLYING:
|
||||
case BattlerTagType.UNDERGROUND:
|
||||
case BattlerTagType.UNDERWATER:
|
||||
case BattlerTagType.HIDDEN:
|
||||
return new SemiInvulnerableTag(tagType, turnCount, sourceMove);
|
||||
case BattlerTagType.FIRE_BOOST:
|
||||
return new TypeBoostTag(tagType, sourceMove, Type.FIRE, 1.5, false);
|
||||
case BattlerTagType.CRIT_BOOST:
|
||||
return new CritBoostTag(tagType, sourceMove);
|
||||
case BattlerTagType.DRAGON_CHEER:
|
||||
return new DragonCheerTag();
|
||||
case BattlerTagType.ALWAYS_CRIT:
|
||||
case BattlerTagType.IGNORE_ACCURACY:
|
||||
return new BattlerTag(tagType, BattlerTagLapseType.TURN_END, 2, sourceMove);
|
||||
case BattlerTagType.ALWAYS_GET_HIT:
|
||||
case BattlerTagType.RECEIVE_DOUBLE_DAMAGE:
|
||||
return new BattlerTag(tagType, BattlerTagLapseType.PRE_MOVE, 1, sourceMove);
|
||||
case BattlerTagType.BYPASS_SLEEP:
|
||||
return new BattlerTag(tagType, BattlerTagLapseType.TURN_END, turnCount, sourceMove);
|
||||
case BattlerTagType.IGNORE_FLYING:
|
||||
return new GroundedTag(tagType, BattlerTagLapseType.CUSTOM, sourceMove);
|
||||
case BattlerTagType.ROOSTED:
|
||||
return new RoostedTag();
|
||||
case BattlerTagType.BURNED_UP:
|
||||
return new RemovedTypeTag(tagType, BattlerTagLapseType.CUSTOM, sourceMove);
|
||||
case BattlerTagType.DOUBLE_SHOCKED:
|
||||
return new RemovedTypeTag(tagType, BattlerTagLapseType.CUSTOM, sourceMove);
|
||||
case BattlerTagType.SALT_CURED:
|
||||
return new SaltCuredTag(sourceId);
|
||||
case BattlerTagType.CURSED:
|
||||
return new CursedTag(sourceId);
|
||||
case BattlerTagType.CHARGED:
|
||||
return new TypeBoostTag(tagType, sourceMove, Type.ELECTRIC, 2, true);
|
||||
case BattlerTagType.FLOATING:
|
||||
return new FloatingTag(tagType, sourceMove);
|
||||
case BattlerTagType.MINIMIZED:
|
||||
return new MinimizeTag();
|
||||
case BattlerTagType.DESTINY_BOND:
|
||||
return new DestinyBondTag(sourceMove, sourceId);
|
||||
case BattlerTagType.ICE_FACE:
|
||||
return new IceFaceBlockDamageTag(tagType);
|
||||
case BattlerTagType.DISGUISE:
|
||||
return new FormBlockDamageTag(tagType);
|
||||
case BattlerTagType.STOCKPILING:
|
||||
return new StockpilingTag(sourceMove);
|
||||
case BattlerTagType.OCTOLOCK:
|
||||
return new OctolockTag(sourceId);
|
||||
case BattlerTagType.DISABLED:
|
||||
return new DisabledTag(sourceId);
|
||||
case BattlerTagType.IGNORE_GHOST:
|
||||
return new ExposedTag(tagType, sourceMove, Type.GHOST, [ Type.NORMAL, Type.FIGHTING ]);
|
||||
case BattlerTagType.IGNORE_DARK:
|
||||
return new ExposedTag(tagType, sourceMove, Type.DARK, [ Type.PSYCHIC ]);
|
||||
case BattlerTagType.GULP_MISSILE_ARROKUDA:
|
||||
case BattlerTagType.GULP_MISSILE_PIKACHU:
|
||||
return new GulpMissileTag(tagType, sourceMove);
|
||||
case BattlerTagType.TAR_SHOT:
|
||||
return new TarShotTag();
|
||||
case BattlerTagType.ELECTRIFIED:
|
||||
return new ElectrifiedTag();
|
||||
case BattlerTagType.THROAT_CHOPPED:
|
||||
return new ThroatChoppedTag();
|
||||
case BattlerTagType.GORILLA_TACTICS:
|
||||
return new GorillaTacticsTag();
|
||||
case BattlerTagType.SUBSTITUTE:
|
||||
return new SubstituteTag(sourceMove, sourceId);
|
||||
case BattlerTagType.AUTOTOMIZED:
|
||||
return new AutotomizedTag();
|
||||
case BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON:
|
||||
return new MysteryEncounterPostSummonTag();
|
||||
case BattlerTagType.HEAL_BLOCK:
|
||||
return new HealBlockTag(turnCount, sourceMove);
|
||||
case BattlerTagType.TORMENT:
|
||||
return new TormentTag(sourceId);
|
||||
case BattlerTagType.TAUNT:
|
||||
return new TauntTag();
|
||||
case BattlerTagType.IMPRISON:
|
||||
return new ImprisonTag(sourceId);
|
||||
case BattlerTagType.SYRUP_BOMB:
|
||||
return new SyrupBombTag(sourceId);
|
||||
case BattlerTagType.TELEKINESIS:
|
||||
return new TelekinesisTag(sourceMove);
|
||||
case BattlerTagType.POWER_TRICK:
|
||||
return new PowerTrickTag(sourceMove, sourceId);
|
||||
case BattlerTagType.NONE:
|
||||
default:
|
||||
return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId);
|
||||
case BattlerTagType.RECHARGING:
|
||||
return new RechargingTag(sourceMove);
|
||||
case BattlerTagType.BEAK_BLAST_CHARGING:
|
||||
return new BeakBlastChargingTag();
|
||||
case BattlerTagType.SHELL_TRAP:
|
||||
return new ShellTrapTag();
|
||||
case BattlerTagType.FLINCHED:
|
||||
return new FlinchedTag(sourceMove);
|
||||
case BattlerTagType.INTERRUPTED:
|
||||
return new InterruptedTag(sourceMove);
|
||||
case BattlerTagType.CONFUSED:
|
||||
return new ConfusedTag(turnCount, sourceMove);
|
||||
case BattlerTagType.INFATUATED:
|
||||
return new InfatuatedTag(sourceMove, sourceId);
|
||||
case BattlerTagType.SEEDED:
|
||||
return new SeedTag(sourceId);
|
||||
case BattlerTagType.NIGHTMARE:
|
||||
return new NightmareTag();
|
||||
case BattlerTagType.FRENZY:
|
||||
return new FrenzyTag(turnCount, sourceMove, sourceId);
|
||||
case BattlerTagType.CHARGING:
|
||||
return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, 1, sourceMove, sourceId);
|
||||
case BattlerTagType.ENCORE:
|
||||
return new EncoreTag(sourceId);
|
||||
case BattlerTagType.HELPING_HAND:
|
||||
return new HelpingHandTag(sourceId);
|
||||
case BattlerTagType.INGRAIN:
|
||||
return new IngrainTag(sourceId);
|
||||
case BattlerTagType.AQUA_RING:
|
||||
return new AquaRingTag();
|
||||
case BattlerTagType.DROWSY:
|
||||
return new DrowsyTag();
|
||||
case BattlerTagType.TRAPPED:
|
||||
return new TrappedTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId);
|
||||
case BattlerTagType.NO_RETREAT:
|
||||
return new NoRetreatTag(sourceId);
|
||||
case BattlerTagType.BIND:
|
||||
return new BindTag(turnCount, sourceId);
|
||||
case BattlerTagType.WRAP:
|
||||
return new WrapTag(turnCount, sourceId);
|
||||
case BattlerTagType.FIRE_SPIN:
|
||||
return new FireSpinTag(turnCount, sourceId);
|
||||
case BattlerTagType.WHIRLPOOL:
|
||||
return new WhirlpoolTag(turnCount, sourceId);
|
||||
case BattlerTagType.CLAMP:
|
||||
return new ClampTag(turnCount, sourceId);
|
||||
case BattlerTagType.SAND_TOMB:
|
||||
return new SandTombTag(turnCount, sourceId);
|
||||
case BattlerTagType.MAGMA_STORM:
|
||||
return new MagmaStormTag(turnCount, sourceId);
|
||||
case BattlerTagType.SNAP_TRAP:
|
||||
return new SnapTrapTag(turnCount, sourceId);
|
||||
case BattlerTagType.THUNDER_CAGE:
|
||||
return new ThunderCageTag(turnCount, sourceId);
|
||||
case BattlerTagType.INFESTATION:
|
||||
return new InfestationTag(turnCount, sourceId);
|
||||
case BattlerTagType.PROTECTED:
|
||||
return new ProtectedTag(sourceMove);
|
||||
case BattlerTagType.SPIKY_SHIELD:
|
||||
return new ContactDamageProtectedTag(sourceMove, 8);
|
||||
case BattlerTagType.KINGS_SHIELD:
|
||||
return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.ATK, -1);
|
||||
case BattlerTagType.OBSTRUCT:
|
||||
return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.DEF, -2);
|
||||
case BattlerTagType.SILK_TRAP:
|
||||
return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.SPD, -1);
|
||||
case BattlerTagType.BANEFUL_BUNKER:
|
||||
return new ContactPoisonProtectedTag(sourceMove);
|
||||
case BattlerTagType.BURNING_BULWARK:
|
||||
return new ContactBurnProtectedTag(sourceMove);
|
||||
case BattlerTagType.ENDURING:
|
||||
return new EnduringTag(sourceMove);
|
||||
case BattlerTagType.STURDY:
|
||||
return new SturdyTag(sourceMove);
|
||||
case BattlerTagType.PERISH_SONG:
|
||||
return new PerishSongTag(turnCount);
|
||||
case BattlerTagType.CENTER_OF_ATTENTION:
|
||||
return new CenterOfAttentionTag(sourceMove);
|
||||
case BattlerTagType.TRUANT:
|
||||
return new TruantTag();
|
||||
case BattlerTagType.SLOW_START:
|
||||
return new SlowStartTag();
|
||||
case BattlerTagType.PROTOSYNTHESIS:
|
||||
return new WeatherHighestStatBoostTag(tagType, Abilities.PROTOSYNTHESIS, WeatherType.SUNNY, WeatherType.HARSH_SUN);
|
||||
case BattlerTagType.QUARK_DRIVE:
|
||||
return new TerrainHighestStatBoostTag(tagType, Abilities.QUARK_DRIVE, TerrainType.ELECTRIC);
|
||||
case BattlerTagType.FLYING:
|
||||
case BattlerTagType.UNDERGROUND:
|
||||
case BattlerTagType.UNDERWATER:
|
||||
case BattlerTagType.HIDDEN:
|
||||
return new SemiInvulnerableTag(tagType, turnCount, sourceMove);
|
||||
case BattlerTagType.FIRE_BOOST:
|
||||
return new TypeBoostTag(tagType, sourceMove, Type.FIRE, 1.5, false);
|
||||
case BattlerTagType.CRIT_BOOST:
|
||||
return new CritBoostTag(tagType, sourceMove);
|
||||
case BattlerTagType.DRAGON_CHEER:
|
||||
return new DragonCheerTag();
|
||||
case BattlerTagType.ALWAYS_CRIT:
|
||||
case BattlerTagType.IGNORE_ACCURACY:
|
||||
return new BattlerTag(tagType, BattlerTagLapseType.TURN_END, 2, sourceMove);
|
||||
case BattlerTagType.ALWAYS_GET_HIT:
|
||||
case BattlerTagType.RECEIVE_DOUBLE_DAMAGE:
|
||||
return new BattlerTag(tagType, BattlerTagLapseType.PRE_MOVE, 1, sourceMove);
|
||||
case BattlerTagType.BYPASS_SLEEP:
|
||||
return new BattlerTag(tagType, BattlerTagLapseType.TURN_END, turnCount, sourceMove);
|
||||
case BattlerTagType.IGNORE_FLYING:
|
||||
return new GroundedTag(tagType, BattlerTagLapseType.CUSTOM, sourceMove);
|
||||
case BattlerTagType.ROOSTED:
|
||||
return new RoostedTag();
|
||||
case BattlerTagType.BURNED_UP:
|
||||
return new RemovedTypeTag(tagType, BattlerTagLapseType.CUSTOM, sourceMove);
|
||||
case BattlerTagType.DOUBLE_SHOCKED:
|
||||
return new RemovedTypeTag(tagType, BattlerTagLapseType.CUSTOM, sourceMove);
|
||||
case BattlerTagType.SALT_CURED:
|
||||
return new SaltCuredTag(sourceId);
|
||||
case BattlerTagType.CURSED:
|
||||
return new CursedTag(sourceId);
|
||||
case BattlerTagType.CHARGED:
|
||||
return new TypeBoostTag(tagType, sourceMove, Type.ELECTRIC, 2, true);
|
||||
case BattlerTagType.FLOATING:
|
||||
return new FloatingTag(tagType, sourceMove);
|
||||
case BattlerTagType.MINIMIZED:
|
||||
return new MinimizeTag();
|
||||
case BattlerTagType.DESTINY_BOND:
|
||||
return new DestinyBondTag(sourceMove, sourceId);
|
||||
case BattlerTagType.ICE_FACE:
|
||||
return new IceFaceBlockDamageTag(tagType);
|
||||
case BattlerTagType.DISGUISE:
|
||||
return new FormBlockDamageTag(tagType);
|
||||
case BattlerTagType.STOCKPILING:
|
||||
return new StockpilingTag(sourceMove);
|
||||
case BattlerTagType.OCTOLOCK:
|
||||
return new OctolockTag(sourceId);
|
||||
case BattlerTagType.DISABLED:
|
||||
return new DisabledTag(sourceId);
|
||||
case BattlerTagType.IGNORE_GHOST:
|
||||
return new ExposedTag(tagType, sourceMove, Type.GHOST, [ Type.NORMAL, Type.FIGHTING ]);
|
||||
case BattlerTagType.IGNORE_DARK:
|
||||
return new ExposedTag(tagType, sourceMove, Type.DARK, [ Type.PSYCHIC ]);
|
||||
case BattlerTagType.GULP_MISSILE_ARROKUDA:
|
||||
case BattlerTagType.GULP_MISSILE_PIKACHU:
|
||||
return new GulpMissileTag(tagType, sourceMove);
|
||||
case BattlerTagType.TAR_SHOT:
|
||||
return new TarShotTag();
|
||||
case BattlerTagType.ELECTRIFIED:
|
||||
return new ElectrifiedTag();
|
||||
case BattlerTagType.THROAT_CHOPPED:
|
||||
return new ThroatChoppedTag();
|
||||
case BattlerTagType.GORILLA_TACTICS:
|
||||
return new GorillaTacticsTag();
|
||||
case BattlerTagType.SUBSTITUTE:
|
||||
return new SubstituteTag(sourceMove, sourceId);
|
||||
case BattlerTagType.AUTOTOMIZED:
|
||||
return new AutotomizedTag();
|
||||
case BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON:
|
||||
return new MysteryEncounterPostSummonTag();
|
||||
case BattlerTagType.HEAL_BLOCK:
|
||||
return new HealBlockTag(turnCount, sourceMove);
|
||||
case BattlerTagType.TORMENT:
|
||||
return new TormentTag(sourceId);
|
||||
case BattlerTagType.TAUNT:
|
||||
return new TauntTag();
|
||||
case BattlerTagType.IMPRISON:
|
||||
return new ImprisonTag(sourceId);
|
||||
case BattlerTagType.SYRUP_BOMB:
|
||||
return new SyrupBombTag(sourceId);
|
||||
case BattlerTagType.TELEKINESIS:
|
||||
return new TelekinesisTag(sourceMove);
|
||||
case BattlerTagType.POWER_TRICK:
|
||||
return new PowerTrickTag(sourceMove, sourceId);
|
||||
case BattlerTagType.NONE:
|
||||
default:
|
||||
return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,42 +22,42 @@ export type BerryPredicate = (pokemon: Pokemon) => boolean;
|
|||
|
||||
export function getBerryPredicate(berryType: BerryType): BerryPredicate {
|
||||
switch (berryType) {
|
||||
case BerryType.SITRUS:
|
||||
return (pokemon: Pokemon) => pokemon.getHpRatio() < 0.5;
|
||||
case BerryType.LUM:
|
||||
return (pokemon: Pokemon) => !!pokemon.status || !!pokemon.getTag(BattlerTagType.CONFUSED);
|
||||
case BerryType.ENIGMA:
|
||||
return (pokemon: Pokemon) => !!pokemon.turnData.attacksReceived.filter(a => a.result === HitResult.SUPER_EFFECTIVE).length;
|
||||
case BerryType.LIECHI:
|
||||
case BerryType.GANLON:
|
||||
case BerryType.PETAYA:
|
||||
case BerryType.APICOT:
|
||||
case BerryType.SALAC:
|
||||
return (pokemon: Pokemon) => {
|
||||
const threshold = new Utils.NumberHolder(0.25);
|
||||
// Offset BerryType such that LIECHI -> Stat.ATK = 1, GANLON -> Stat.DEF = 2, so on and so forth
|
||||
const stat: BattleStat = berryType - BerryType.ENIGMA;
|
||||
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold);
|
||||
return pokemon.getHpRatio() < threshold.value && pokemon.getStatStage(stat) < 6;
|
||||
};
|
||||
case BerryType.LANSAT:
|
||||
return (pokemon: Pokemon) => {
|
||||
const threshold = new Utils.NumberHolder(0.25);
|
||||
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold);
|
||||
return pokemon.getHpRatio() < 0.25 && !pokemon.getTag(BattlerTagType.CRIT_BOOST);
|
||||
};
|
||||
case BerryType.STARF:
|
||||
return (pokemon: Pokemon) => {
|
||||
const threshold = new Utils.NumberHolder(0.25);
|
||||
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold);
|
||||
return pokemon.getHpRatio() < 0.25;
|
||||
};
|
||||
case BerryType.LEPPA:
|
||||
return (pokemon: Pokemon) => {
|
||||
const threshold = new Utils.NumberHolder(0.25);
|
||||
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold);
|
||||
return !!pokemon.getMoveset().find(m => !m?.getPpRatio());
|
||||
};
|
||||
case BerryType.SITRUS:
|
||||
return (pokemon: Pokemon) => pokemon.getHpRatio() < 0.5;
|
||||
case BerryType.LUM:
|
||||
return (pokemon: Pokemon) => !!pokemon.status || !!pokemon.getTag(BattlerTagType.CONFUSED);
|
||||
case BerryType.ENIGMA:
|
||||
return (pokemon: Pokemon) => !!pokemon.turnData.attacksReceived.filter(a => a.result === HitResult.SUPER_EFFECTIVE).length;
|
||||
case BerryType.LIECHI:
|
||||
case BerryType.GANLON:
|
||||
case BerryType.PETAYA:
|
||||
case BerryType.APICOT:
|
||||
case BerryType.SALAC:
|
||||
return (pokemon: Pokemon) => {
|
||||
const threshold = new Utils.NumberHolder(0.25);
|
||||
// Offset BerryType such that LIECHI -> Stat.ATK = 1, GANLON -> Stat.DEF = 2, so on and so forth
|
||||
const stat: BattleStat = berryType - BerryType.ENIGMA;
|
||||
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold);
|
||||
return pokemon.getHpRatio() < threshold.value && pokemon.getStatStage(stat) < 6;
|
||||
};
|
||||
case BerryType.LANSAT:
|
||||
return (pokemon: Pokemon) => {
|
||||
const threshold = new Utils.NumberHolder(0.25);
|
||||
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold);
|
||||
return pokemon.getHpRatio() < 0.25 && !pokemon.getTag(BattlerTagType.CRIT_BOOST);
|
||||
};
|
||||
case BerryType.STARF:
|
||||
return (pokemon: Pokemon) => {
|
||||
const threshold = new Utils.NumberHolder(0.25);
|
||||
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold);
|
||||
return pokemon.getHpRatio() < 0.25;
|
||||
};
|
||||
case BerryType.LEPPA:
|
||||
return (pokemon: Pokemon) => {
|
||||
const threshold = new Utils.NumberHolder(0.25);
|
||||
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold);
|
||||
return !!pokemon.getMoveset().find(m => !m?.getPpRatio());
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,70 +65,70 @@ export type BerryEffectFunc = (pokemon: Pokemon) => void;
|
|||
|
||||
export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
|
||||
switch (berryType) {
|
||||
case BerryType.SITRUS:
|
||||
case BerryType.ENIGMA:
|
||||
return (pokemon: Pokemon) => {
|
||||
if (pokemon.battleData) {
|
||||
pokemon.battleData.berriesEaten.push(berryType);
|
||||
}
|
||||
const hpHealed = new Utils.NumberHolder(Utils.toDmgValue(pokemon.getMaxHp() / 4));
|
||||
applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, hpHealed);
|
||||
pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.getBattlerIndex(),
|
||||
hpHealed.value, i18next.t("battle:hpHealBerry", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), berryName: getBerryName(berryType) }), true));
|
||||
};
|
||||
case BerryType.LUM:
|
||||
return (pokemon: Pokemon) => {
|
||||
if (pokemon.battleData) {
|
||||
pokemon.battleData.berriesEaten.push(berryType);
|
||||
}
|
||||
if (pokemon.status) {
|
||||
pokemon.scene.queueMessage(getStatusEffectHealText(pokemon.status.effect, getPokemonNameWithAffix(pokemon)));
|
||||
}
|
||||
pokemon.resetStatus(true, true);
|
||||
pokemon.updateInfo();
|
||||
};
|
||||
case BerryType.LIECHI:
|
||||
case BerryType.GANLON:
|
||||
case BerryType.PETAYA:
|
||||
case BerryType.APICOT:
|
||||
case BerryType.SALAC:
|
||||
return (pokemon: Pokemon) => {
|
||||
if (pokemon.battleData) {
|
||||
pokemon.battleData.berriesEaten.push(berryType);
|
||||
}
|
||||
// Offset BerryType such that LIECHI -> Stat.ATK = 1, GANLON -> Stat.DEF = 2, so on and so forth
|
||||
const stat: BattleStat = berryType - BerryType.ENIGMA;
|
||||
const statStages = new Utils.NumberHolder(1);
|
||||
applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, statStages);
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ stat ], statStages.value));
|
||||
};
|
||||
case BerryType.LANSAT:
|
||||
return (pokemon: Pokemon) => {
|
||||
if (pokemon.battleData) {
|
||||
pokemon.battleData.berriesEaten.push(berryType);
|
||||
}
|
||||
pokemon.addTag(BattlerTagType.CRIT_BOOST);
|
||||
};
|
||||
case BerryType.STARF:
|
||||
return (pokemon: Pokemon) => {
|
||||
if (pokemon.battleData) {
|
||||
pokemon.battleData.berriesEaten.push(berryType);
|
||||
}
|
||||
const randStat = Utils.randSeedInt(Stat.SPD, Stat.ATK);
|
||||
const stages = new Utils.NumberHolder(2);
|
||||
applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, stages);
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ randStat ], stages.value));
|
||||
};
|
||||
case BerryType.LEPPA:
|
||||
return (pokemon: Pokemon) => {
|
||||
if (pokemon.battleData) {
|
||||
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?
|
||||
if (ppRestoreMove !== undefined) {
|
||||
case BerryType.SITRUS:
|
||||
case BerryType.ENIGMA:
|
||||
return (pokemon: Pokemon) => {
|
||||
if (pokemon.battleData) {
|
||||
pokemon.battleData.berriesEaten.push(berryType);
|
||||
}
|
||||
const hpHealed = new Utils.NumberHolder(Utils.toDmgValue(pokemon.getMaxHp() / 4));
|
||||
applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, hpHealed);
|
||||
pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.getBattlerIndex(),
|
||||
hpHealed.value, i18next.t("battle:hpHealBerry", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), berryName: getBerryName(berryType) }), true));
|
||||
};
|
||||
case BerryType.LUM:
|
||||
return (pokemon: Pokemon) => {
|
||||
if (pokemon.battleData) {
|
||||
pokemon.battleData.berriesEaten.push(berryType);
|
||||
}
|
||||
if (pokemon.status) {
|
||||
pokemon.scene.queueMessage(getStatusEffectHealText(pokemon.status.effect, getPokemonNameWithAffix(pokemon)));
|
||||
}
|
||||
pokemon.resetStatus(true, true);
|
||||
pokemon.updateInfo();
|
||||
};
|
||||
case BerryType.LIECHI:
|
||||
case BerryType.GANLON:
|
||||
case BerryType.PETAYA:
|
||||
case BerryType.APICOT:
|
||||
case BerryType.SALAC:
|
||||
return (pokemon: Pokemon) => {
|
||||
if (pokemon.battleData) {
|
||||
pokemon.battleData.berriesEaten.push(berryType);
|
||||
}
|
||||
// Offset BerryType such that LIECHI -> Stat.ATK = 1, GANLON -> Stat.DEF = 2, so on and so forth
|
||||
const stat: BattleStat = berryType - BerryType.ENIGMA;
|
||||
const statStages = new Utils.NumberHolder(1);
|
||||
applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, statStages);
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ stat ], statStages.value));
|
||||
};
|
||||
case BerryType.LANSAT:
|
||||
return (pokemon: Pokemon) => {
|
||||
if (pokemon.battleData) {
|
||||
pokemon.battleData.berriesEaten.push(berryType);
|
||||
}
|
||||
pokemon.addTag(BattlerTagType.CRIT_BOOST);
|
||||
};
|
||||
case BerryType.STARF:
|
||||
return (pokemon: Pokemon) => {
|
||||
if (pokemon.battleData) {
|
||||
pokemon.battleData.berriesEaten.push(berryType);
|
||||
}
|
||||
const randStat = Utils.randSeedInt(Stat.SPD, Stat.ATK);
|
||||
const stages = new Utils.NumberHolder(2);
|
||||
applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, stages);
|
||||
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ randStat ], stages.value));
|
||||
};
|
||||
case BerryType.LEPPA:
|
||||
return (pokemon: Pokemon) => {
|
||||
if (pokemon.battleData) {
|
||||
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?
|
||||
if (ppRestoreMove !== undefined) {
|
||||
ppRestoreMove!.ppUsed = Math.max(ppRestoreMove!.ppUsed - 10, 0);
|
||||
pokemon.scene.queueMessage(i18next.t("battle:ppHealBerry", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: ppRestoreMove!.getName(), berryName: getBerryName(berryType) }));
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -448,21 +448,21 @@ export class SingleGenerationChallenge extends Challenge {
|
|||
applyFixedBattle(waveIndex: Number, battleConfig: FixedBattleConfig): boolean {
|
||||
let trainerTypes: TrainerType[] = [];
|
||||
switch (waveIndex) {
|
||||
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 ];
|
||||
break;
|
||||
case 184:
|
||||
trainerTypes = [ TrainerType.BRUNO, TrainerType.KOGA, TrainerType.PHOEBE, TrainerType.BERTHA, TrainerType.MARSHAL, TrainerType.SIEBOLD, TrainerType.OLIVIA, TrainerType.NESSA_ELITE, TrainerType.POPPY ];
|
||||
break;
|
||||
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 ];
|
||||
break;
|
||||
case 188:
|
||||
trainerTypes = [ TrainerType.LANCE, TrainerType.KAREN, TrainerType.DRAKE, TrainerType.LUCIAN, TrainerType.CAITLIN, TrainerType.DRASNA, TrainerType.KAHILI, TrainerType.RAIHAN_ELITE, TrainerType.HASSEL ];
|
||||
break;
|
||||
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 ]) ];
|
||||
break;
|
||||
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 ];
|
||||
break;
|
||||
case 184:
|
||||
trainerTypes = [ TrainerType.BRUNO, TrainerType.KOGA, TrainerType.PHOEBE, TrainerType.BERTHA, TrainerType.MARSHAL, TrainerType.SIEBOLD, TrainerType.OLIVIA, TrainerType.NESSA_ELITE, TrainerType.POPPY ];
|
||||
break;
|
||||
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 ];
|
||||
break;
|
||||
case 188:
|
||||
trainerTypes = [ TrainerType.LANCE, TrainerType.KAREN, TrainerType.DRAKE, TrainerType.LUCIAN, TrainerType.CAITLIN, TrainerType.DRASNA, TrainerType.KAHILI, TrainerType.RAIHAN_ELITE, TrainerType.HASSEL ];
|
||||
break;
|
||||
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 ]) ];
|
||||
break;
|
||||
}
|
||||
if (trainerTypes.length === 0) {
|
||||
return false;
|
||||
|
@ -891,45 +891,45 @@ export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType
|
|||
gameMode.challenges.forEach(c => {
|
||||
if (c.value !== 0) {
|
||||
switch (challengeType) {
|
||||
case ChallengeType.STARTER_CHOICE:
|
||||
ret ||= c.applyStarterChoice(args[0], args[1], args[2], args[3]);
|
||||
break;
|
||||
case ChallengeType.STARTER_POINTS:
|
||||
ret ||= c.applyStarterPoints(args[0]);
|
||||
break;
|
||||
case ChallengeType.STARTER_COST:
|
||||
ret ||= c.applyStarterCost(args[0], args[1]);
|
||||
break;
|
||||
case ChallengeType.STARTER_MODIFY:
|
||||
ret ||= c.applyStarterModify(args[0]);
|
||||
break;
|
||||
case ChallengeType.POKEMON_IN_BATTLE:
|
||||
ret ||= c.applyPokemonInBattle(args[0], args[1]);
|
||||
break;
|
||||
case ChallengeType.FIXED_BATTLES:
|
||||
ret ||= c.applyFixedBattle(args[0], args[1]);
|
||||
break;
|
||||
case ChallengeType.TYPE_EFFECTIVENESS:
|
||||
ret ||= c.applyTypeEffectiveness(args[0]);
|
||||
break;
|
||||
case ChallengeType.AI_LEVEL:
|
||||
ret ||= c.applyLevelChange(args[0], args[1], args[2], args[3]);
|
||||
break;
|
||||
case ChallengeType.AI_MOVE_SLOTS:
|
||||
ret ||= c.applyMoveSlot(args[0], args[1]);
|
||||
break;
|
||||
case ChallengeType.PASSIVE_ACCESS:
|
||||
ret ||= c.applyPassiveAccess(args[0], args[1]);
|
||||
break;
|
||||
case ChallengeType.GAME_MODE_MODIFY:
|
||||
ret ||= c.applyGameModeModify(gameMode);
|
||||
break;
|
||||
case ChallengeType.MOVE_ACCESS:
|
||||
ret ||= c.applyMoveAccessLevel(args[0], args[1], args[2], args[3]);
|
||||
break;
|
||||
case ChallengeType.MOVE_WEIGHT:
|
||||
ret ||= c.applyMoveWeight(args[0], args[1], args[2], args[3]);
|
||||
break;
|
||||
case ChallengeType.STARTER_CHOICE:
|
||||
ret ||= c.applyStarterChoice(args[0], args[1], args[2], args[3]);
|
||||
break;
|
||||
case ChallengeType.STARTER_POINTS:
|
||||
ret ||= c.applyStarterPoints(args[0]);
|
||||
break;
|
||||
case ChallengeType.STARTER_COST:
|
||||
ret ||= c.applyStarterCost(args[0], args[1]);
|
||||
break;
|
||||
case ChallengeType.STARTER_MODIFY:
|
||||
ret ||= c.applyStarterModify(args[0]);
|
||||
break;
|
||||
case ChallengeType.POKEMON_IN_BATTLE:
|
||||
ret ||= c.applyPokemonInBattle(args[0], args[1]);
|
||||
break;
|
||||
case ChallengeType.FIXED_BATTLES:
|
||||
ret ||= c.applyFixedBattle(args[0], args[1]);
|
||||
break;
|
||||
case ChallengeType.TYPE_EFFECTIVENESS:
|
||||
ret ||= c.applyTypeEffectiveness(args[0]);
|
||||
break;
|
||||
case ChallengeType.AI_LEVEL:
|
||||
ret ||= c.applyLevelChange(args[0], args[1], args[2], args[3]);
|
||||
break;
|
||||
case ChallengeType.AI_MOVE_SLOTS:
|
||||
ret ||= c.applyMoveSlot(args[0], args[1]);
|
||||
break;
|
||||
case ChallengeType.PASSIVE_ACCESS:
|
||||
ret ||= c.applyPassiveAccess(args[0], args[1]);
|
||||
break;
|
||||
case ChallengeType.GAME_MODE_MODIFY:
|
||||
ret ||= c.applyGameModeModify(gameMode);
|
||||
break;
|
||||
case ChallengeType.MOVE_ACCESS:
|
||||
ret ||= c.applyMoveAccessLevel(args[0], args[1], args[2], args[3]);
|
||||
break;
|
||||
case ChallengeType.MOVE_WEIGHT:
|
||||
ret ||= c.applyMoveWeight(args[0], args[1], args[2], args[3]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -943,18 +943,18 @@ export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType
|
|||
*/
|
||||
export function copyChallenge(source: Challenge | any): Challenge {
|
||||
switch (source.id) {
|
||||
case Challenges.SINGLE_GENERATION:
|
||||
return SingleGenerationChallenge.loadChallenge(source);
|
||||
case Challenges.SINGLE_TYPE:
|
||||
return SingleTypeChallenge.loadChallenge(source);
|
||||
case Challenges.LOWER_MAX_STARTER_COST:
|
||||
return LowerStarterMaxCostChallenge.loadChallenge(source);
|
||||
case Challenges.LOWER_STARTER_POINTS:
|
||||
return LowerStarterPointsChallenge.loadChallenge(source);
|
||||
case Challenges.FRESH_START:
|
||||
return FreshStartChallenge.loadChallenge(source);
|
||||
case Challenges.INVERSE_BATTLE:
|
||||
return InverseBattleChallenge.loadChallenge(source);
|
||||
case Challenges.SINGLE_GENERATION:
|
||||
return SingleGenerationChallenge.loadChallenge(source);
|
||||
case Challenges.SINGLE_TYPE:
|
||||
return SingleTypeChallenge.loadChallenge(source);
|
||||
case Challenges.LOWER_MAX_STARTER_COST:
|
||||
return LowerStarterMaxCostChallenge.loadChallenge(source);
|
||||
case Challenges.LOWER_STARTER_POINTS:
|
||||
return LowerStarterPointsChallenge.loadChallenge(source);
|
||||
case Challenges.FRESH_START:
|
||||
return FreshStartChallenge.loadChallenge(source);
|
||||
case Challenges.INVERSE_BATTLE:
|
||||
return InverseBattleChallenge.loadChallenge(source);
|
||||
}
|
||||
throw new Error("Unknown challenge copied");
|
||||
}
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
import { Abilities } from "#enums/abilities";
|
||||
import { Type } from "#app/data/type";
|
||||
import { isNullOrUndefined } from "#app/utils";
|
||||
import { Nature } from "#enums/nature";
|
||||
|
||||
/**
|
||||
* Data that can customize a Pokemon in non-standard ways from its Species
|
||||
* Currently only used by Mystery Encounters, may need to be renamed if it becomes more widely used
|
||||
* Currently only used by Mystery Encounters and Mints.
|
||||
*/
|
||||
export class MysteryEncounterPokemonData {
|
||||
export class CustomPokemonData {
|
||||
public spriteScale: number;
|
||||
public ability: Abilities | -1;
|
||||
public passive: Abilities | -1;
|
||||
public nature: Nature | -1;
|
||||
public types: Type[];
|
||||
|
||||
constructor(data?: MysteryEncounterPokemonData | Partial<MysteryEncounterPokemonData>) {
|
||||
constructor(data?: CustomPokemonData | Partial<CustomPokemonData>) {
|
||||
if (!isNullOrUndefined(data)) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
|
@ -20,6 +22,7 @@ export class MysteryEncounterPokemonData {
|
|||
this.spriteScale = this.spriteScale ?? -1;
|
||||
this.ability = this.ability ?? -1;
|
||||
this.passive = this.passive ?? -1;
|
||||
this.nature = this.nature ?? -1;
|
||||
this.types = this.types ?? [];
|
||||
}
|
||||
}
|
136
src/data/egg.ts
|
@ -262,14 +262,14 @@ export class Egg {
|
|||
return "Manaphy";
|
||||
}
|
||||
switch (this.tier) {
|
||||
case EggTier.RARE:
|
||||
return i18next.t("egg:greatTier");
|
||||
case EggTier.EPIC:
|
||||
return i18next.t("egg:ultraTier");
|
||||
case EggTier.LEGENDARY:
|
||||
return i18next.t("egg:masterTier");
|
||||
default:
|
||||
return i18next.t("egg:defaultTier");
|
||||
case EggTier.RARE:
|
||||
return i18next.t("egg:greatTier");
|
||||
case EggTier.EPIC:
|
||||
return i18next.t("egg:ultraTier");
|
||||
case EggTier.LEGENDARY:
|
||||
return i18next.t("egg:masterTier");
|
||||
default:
|
||||
return i18next.t("egg:defaultTier");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -288,19 +288,19 @@ export class Egg {
|
|||
|
||||
public getEggTypeDescriptor(scene: BattleScene): string {
|
||||
switch (this.sourceType) {
|
||||
case EggSourceType.SAME_SPECIES_EGG:
|
||||
return this._eggDescriptor ?? i18next.t("egg:sameSpeciesEgg", { species: getPokemonSpecies(this._species).getName() });
|
||||
case EggSourceType.GACHA_LEGENDARY:
|
||||
return this._eggDescriptor ?? `${i18next.t("egg:gachaTypeLegendary")} (${getPokemonSpecies(getLegendaryGachaSpeciesForTimestamp(scene, this.timestamp)).getName()})`;
|
||||
case EggSourceType.GACHA_SHINY:
|
||||
return this._eggDescriptor ?? i18next.t("egg:gachaTypeShiny");
|
||||
case EggSourceType.GACHA_MOVE:
|
||||
return this._eggDescriptor ?? i18next.t("egg:gachaTypeMove");
|
||||
case EggSourceType.EVENT:
|
||||
return this._eggDescriptor ?? i18next.t("egg:eventType");
|
||||
default:
|
||||
console.warn("getEggTypeDescriptor case not defined. Returning default empty string");
|
||||
return "";
|
||||
case EggSourceType.SAME_SPECIES_EGG:
|
||||
return this._eggDescriptor ?? i18next.t("egg:sameSpeciesEgg", { species: getPokemonSpecies(this._species).getName() });
|
||||
case EggSourceType.GACHA_LEGENDARY:
|
||||
return this._eggDescriptor ?? `${i18next.t("egg:gachaTypeLegendary")} (${getPokemonSpecies(getLegendaryGachaSpeciesForTimestamp(scene, this.timestamp)).getName()})`;
|
||||
case EggSourceType.GACHA_SHINY:
|
||||
return this._eggDescriptor ?? i18next.t("egg:gachaTypeShiny");
|
||||
case EggSourceType.GACHA_MOVE:
|
||||
return this._eggDescriptor ?? i18next.t("egg:gachaTypeMove");
|
||||
case EggSourceType.EVENT:
|
||||
return this._eggDescriptor ?? i18next.t("egg:eventType");
|
||||
default:
|
||||
console.warn("getEggTypeDescriptor case not defined. Returning default empty string");
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -315,14 +315,14 @@ export class Egg {
|
|||
private rollEggMoveIndex() {
|
||||
let baseChance = GACHA_DEFAULT_RARE_EGGMOVE_RATE;
|
||||
switch (this._sourceType) {
|
||||
case EggSourceType.SAME_SPECIES_EGG:
|
||||
baseChance = SAME_SPECIES_EGG_RARE_EGGMOVE_RATE;
|
||||
break;
|
||||
case EggSourceType.GACHA_MOVE:
|
||||
baseChance = GACHA_MOVE_UP_RARE_EGGMOVE_RATE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case EggSourceType.SAME_SPECIES_EGG:
|
||||
baseChance = SAME_SPECIES_EGG_RARE_EGGMOVE_RATE;
|
||||
break;
|
||||
case EggSourceType.GACHA_MOVE:
|
||||
baseChance = GACHA_MOVE_UP_RARE_EGGMOVE_RATE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const tierMultiplier = this.isManaphyEgg() ? 2 : Math.pow(2, 3 - this.tier);
|
||||
|
@ -335,12 +335,12 @@ export class Egg {
|
|||
}
|
||||
|
||||
switch (eggTier ?? this._tier) {
|
||||
case EggTier.COMMON:
|
||||
return HATCH_WAVES_COMMON_EGG;
|
||||
case EggTier.RARE:
|
||||
return HATCH_WAVES_RARE_EGG;
|
||||
case EggTier.EPIC:
|
||||
return HATCH_WAVES_EPIC_EGG;
|
||||
case EggTier.COMMON:
|
||||
return HATCH_WAVES_COMMON_EGG;
|
||||
case EggTier.RARE:
|
||||
return HATCH_WAVES_RARE_EGG;
|
||||
case EggTier.EPIC:
|
||||
return HATCH_WAVES_EPIC_EGG;
|
||||
}
|
||||
return HATCH_WAVES_LEGENDARY_EGG;
|
||||
}
|
||||
|
@ -379,22 +379,22 @@ export class Egg {
|
|||
let maxStarterValue: integer;
|
||||
|
||||
switch (this.tier) {
|
||||
case EggTier.RARE:
|
||||
minStarterValue = 4;
|
||||
maxStarterValue = 5;
|
||||
break;
|
||||
case EggTier.EPIC:
|
||||
minStarterValue = 6;
|
||||
maxStarterValue = 7;
|
||||
break;
|
||||
case EggTier.LEGENDARY:
|
||||
minStarterValue = 8;
|
||||
maxStarterValue = 9;
|
||||
break;
|
||||
default:
|
||||
minStarterValue = 1;
|
||||
maxStarterValue = 3;
|
||||
break;
|
||||
case EggTier.RARE:
|
||||
minStarterValue = 4;
|
||||
maxStarterValue = 5;
|
||||
break;
|
||||
case EggTier.EPIC:
|
||||
minStarterValue = 6;
|
||||
maxStarterValue = 7;
|
||||
break;
|
||||
case EggTier.LEGENDARY:
|
||||
minStarterValue = 8;
|
||||
maxStarterValue = 9;
|
||||
break;
|
||||
default:
|
||||
minStarterValue = 1;
|
||||
maxStarterValue = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
const ignoredSpecies = [ Species.PHIONE, Species.MANAPHY, Species.ETERNATUS ];
|
||||
|
@ -469,14 +469,14 @@ export class Egg {
|
|||
private rollShiny(): boolean {
|
||||
let shinyChance = GACHA_DEFAULT_SHINY_RATE;
|
||||
switch (this._sourceType) {
|
||||
case EggSourceType.GACHA_SHINY:
|
||||
shinyChance = GACHA_SHINY_UP_SHINY_RATE;
|
||||
break;
|
||||
case EggSourceType.SAME_SPECIES_EGG:
|
||||
shinyChance = SAME_SPECIES_EGG_SHINY_RATE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case EggSourceType.GACHA_SHINY:
|
||||
shinyChance = GACHA_SHINY_UP_SHINY_RATE;
|
||||
break;
|
||||
case EggSourceType.SAME_SPECIES_EGG:
|
||||
shinyChance = SAME_SPECIES_EGG_SHINY_RATE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return !Utils.randSeedInt(shinyChance);
|
||||
|
@ -523,15 +523,15 @@ export class Egg {
|
|||
return;
|
||||
}
|
||||
switch (this.tier) {
|
||||
case EggTier.RARE:
|
||||
scene.gameData.gameStats.rareEggsPulled++;
|
||||
break;
|
||||
case EggTier.EPIC:
|
||||
scene.gameData.gameStats.epicEggsPulled++;
|
||||
break;
|
||||
case EggTier.LEGENDARY:
|
||||
scene.gameData.gameStats.legendaryEggsPulled++;
|
||||
break;
|
||||
case EggTier.RARE:
|
||||
scene.gameData.gameStats.rareEggsPulled++;
|
||||
break;
|
||||
case EggTier.EPIC:
|
||||
scene.gameData.gameStats.epicEggsPulled++;
|
||||
break;
|
||||
case EggTier.LEGENDARY:
|
||||
scene.gameData.gameStats.legendaryEggsPulled++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,24 +28,24 @@ export function getLevelTotalExp(level: integer, growthRate: GrowthRate): intege
|
|||
let ret: integer;
|
||||
|
||||
switch (growthRate) {
|
||||
case GrowthRate.ERRATIC:
|
||||
ret = (Math.pow(level, 4) + (Math.pow(level, 3) * 2000)) / 3500;
|
||||
break;
|
||||
case GrowthRate.FAST:
|
||||
ret = Math.pow(level, 3) * 4 / 5;
|
||||
break;
|
||||
case GrowthRate.MEDIUM_FAST:
|
||||
ret = Math.pow(level, 3);
|
||||
break;
|
||||
case GrowthRate.MEDIUM_SLOW:
|
||||
ret = (Math.pow(level, 3) * 6 / 5) - (15 * Math.pow(level, 2)) + (100 * level) - 140;
|
||||
break;
|
||||
case GrowthRate.SLOW:
|
||||
ret = Math.pow(level, 3) * 5 / 4;
|
||||
break;
|
||||
case GrowthRate.FLUCTUATING:
|
||||
ret = (Math.pow(level, 3) * ((level / 2) + 8)) * 4 / (100 + level);
|
||||
break;
|
||||
case GrowthRate.ERRATIC:
|
||||
ret = (Math.pow(level, 4) + (Math.pow(level, 3) * 2000)) / 3500;
|
||||
break;
|
||||
case GrowthRate.FAST:
|
||||
ret = Math.pow(level, 3) * 4 / 5;
|
||||
break;
|
||||
case GrowthRate.MEDIUM_FAST:
|
||||
ret = Math.pow(level, 3);
|
||||
break;
|
||||
case GrowthRate.MEDIUM_SLOW:
|
||||
ret = (Math.pow(level, 3) * 6 / 5) - (15 * Math.pow(level, 2)) + (100 * level) - 140;
|
||||
break;
|
||||
case GrowthRate.SLOW:
|
||||
ret = Math.pow(level, 3) * 5 / 4;
|
||||
break;
|
||||
case GrowthRate.FLUCTUATING:
|
||||
ret = (Math.pow(level, 3) * ((level / 2) + 8)) * 4 / (100 + level);
|
||||
break;
|
||||
}
|
||||
|
||||
if (growthRate !== GrowthRate.MEDIUM_FAST) {
|
||||
|
@ -61,17 +61,17 @@ export function getLevelRelExp(level: integer, growthRate: GrowthRate): number {
|
|||
|
||||
export function getGrowthRateColor(growthRate: GrowthRate, shadow?: boolean) {
|
||||
switch (growthRate) {
|
||||
case GrowthRate.ERRATIC:
|
||||
return !shadow ? "#f85888" : "#906060";
|
||||
case GrowthRate.FAST:
|
||||
return !shadow ? "#f8d030" : "#b8a038";
|
||||
case GrowthRate.MEDIUM_FAST:
|
||||
return !shadow ? "#78c850" : "#588040";
|
||||
case GrowthRate.MEDIUM_SLOW:
|
||||
return !shadow ? "#6890f0" : "#807870";
|
||||
case GrowthRate.SLOW:
|
||||
return !shadow ? "#f08030" : "#c03028";
|
||||
case GrowthRate.FLUCTUATING:
|
||||
return !shadow ? "#a040a0" : "#483850";
|
||||
case GrowthRate.ERRATIC:
|
||||
return !shadow ? "#f85888" : "#906060";
|
||||
case GrowthRate.FAST:
|
||||
return !shadow ? "#f8d030" : "#b8a038";
|
||||
case GrowthRate.MEDIUM_FAST:
|
||||
return !shadow ? "#78c850" : "#588040";
|
||||
case GrowthRate.MEDIUM_SLOW:
|
||||
return !shadow ? "#6890f0" : "#807870";
|
||||
case GrowthRate.SLOW:
|
||||
return !shadow ? "#f08030" : "#c03028";
|
||||
case GrowthRate.FLUCTUATING:
|
||||
return !shadow ? "#a040a0" : "#483850";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,20 +6,20 @@ export enum Gender {
|
|||
|
||||
export function getGenderSymbol(gender: Gender) {
|
||||
switch (gender) {
|
||||
case Gender.MALE:
|
||||
return "♂";
|
||||
case Gender.FEMALE:
|
||||
return "♀";
|
||||
case Gender.MALE:
|
||||
return "♂";
|
||||
case Gender.FEMALE:
|
||||
return "♀";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
export function getGenderColor(gender: Gender, shadow?: boolean) {
|
||||
switch (gender) {
|
||||
case Gender.MALE:
|
||||
return shadow ? "#006090" : "#40c8f8";
|
||||
case Gender.FEMALE:
|
||||
return shadow ? "#984038" : "#f89890";
|
||||
case Gender.MALE:
|
||||
return shadow ? "#006090" : "#40c8f8";
|
||||
case Gender.FEMALE:
|
||||
return shadow ? "#984038" : "#f89890";
|
||||
}
|
||||
return "#ffffff";
|
||||
}
|
||||
|
|
1088
src/data/move.ts
|
@ -44,32 +44,32 @@ export const ATrainersTestEncounter: MysteryEncounter =
|
|||
let spriteKeys;
|
||||
let trainerNameKey: string;
|
||||
switch (randSeedInt(5)) {
|
||||
default:
|
||||
case 0:
|
||||
trainerType = TrainerType.BUCK;
|
||||
spriteKeys = getSpriteKeysFromSpecies(Species.CLAYDOL);
|
||||
trainerNameKey = "buck";
|
||||
break;
|
||||
case 1:
|
||||
trainerType = TrainerType.CHERYL;
|
||||
spriteKeys = getSpriteKeysFromSpecies(Species.BLISSEY);
|
||||
trainerNameKey = "cheryl";
|
||||
break;
|
||||
case 2:
|
||||
trainerType = TrainerType.MARLEY;
|
||||
spriteKeys = getSpriteKeysFromSpecies(Species.ARCANINE);
|
||||
trainerNameKey = "marley";
|
||||
break;
|
||||
case 3:
|
||||
trainerType = TrainerType.MIRA;
|
||||
spriteKeys = getSpriteKeysFromSpecies(Species.ALAKAZAM, false, 1);
|
||||
trainerNameKey = "mira";
|
||||
break;
|
||||
case 4:
|
||||
trainerType = TrainerType.RILEY;
|
||||
spriteKeys = getSpriteKeysFromSpecies(Species.LUCARIO, false, 1);
|
||||
trainerNameKey = "riley";
|
||||
break;
|
||||
default:
|
||||
case 0:
|
||||
trainerType = TrainerType.BUCK;
|
||||
spriteKeys = getSpriteKeysFromSpecies(Species.CLAYDOL);
|
||||
trainerNameKey = "buck";
|
||||
break;
|
||||
case 1:
|
||||
trainerType = TrainerType.CHERYL;
|
||||
spriteKeys = getSpriteKeysFromSpecies(Species.BLISSEY);
|
||||
trainerNameKey = "cheryl";
|
||||
break;
|
||||
case 2:
|
||||
trainerType = TrainerType.MARLEY;
|
||||
spriteKeys = getSpriteKeysFromSpecies(Species.ARCANINE);
|
||||
trainerNameKey = "marley";
|
||||
break;
|
||||
case 3:
|
||||
trainerType = TrainerType.MIRA;
|
||||
spriteKeys = getSpriteKeysFromSpecies(Species.ALAKAZAM, false, 1);
|
||||
trainerNameKey = "mira";
|
||||
break;
|
||||
case 4:
|
||||
trainerType = TrainerType.RILEY;
|
||||
spriteKeys = getSpriteKeysFromSpecies(Species.LUCARIO, false, 1);
|
||||
trainerNameKey = "riley";
|
||||
break;
|
||||
}
|
||||
|
||||
// Dialogue and tokens for trainer
|
||||
|
|
|
@ -133,8 +133,8 @@ export const AnOfferYouCantRefuseEncounter: MysteryEncounter =
|
|||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||
.withPrimaryPokemonRequirement(new CombinationPokemonRequirement(
|
||||
new MoveRequirement(EXTORTION_MOVES),
|
||||
new AbilityRequirement(EXTORTION_ABILITIES))
|
||||
new MoveRequirement(EXTORTION_MOVES, true),
|
||||
new AbilityRequirement(EXTORTION_ABILITIES, true))
|
||||
)
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
|
|
|
@ -42,6 +42,8 @@ import {
|
|||
AttackTypeBoosterModifier,
|
||||
BypassSpeedChanceModifier,
|
||||
ContactHeldItemTransferChanceModifier,
|
||||
GigantamaxAccessModifier,
|
||||
MegaEvolutionAccessModifier,
|
||||
PokemonHeldItemModifier
|
||||
} from "#app/modifier/modifier";
|
||||
import i18next from "i18next";
|
||||
|
@ -356,10 +358,17 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
|||
},
|
||||
];
|
||||
} else {
|
||||
// If player has any evolution/form change items that are valid for their party, will spawn one of those items in addition to a Master Ball
|
||||
const modifierOptions: ModifierTypeOption[] = [ generateModifierTypeOption(scene, modifierTypes.MASTER_BALL)!, generateModifierTypeOption(scene, modifierTypes.MAX_LURE)! ];
|
||||
// If the player has any evolution/form change items that are valid for their party,
|
||||
// spawn one of those items in addition to Dynamax Band, Mega Band, and Master Ball
|
||||
const modifierOptions: ModifierTypeOption[] = [ generateModifierTypeOption(scene, modifierTypes.MASTER_BALL)! ];
|
||||
const specialOptions: ModifierTypeOption[] = [];
|
||||
|
||||
if (!scene.findModifier(m => m instanceof MegaEvolutionAccessModifier)) {
|
||||
modifierOptions.push(generateModifierTypeOption(scene, modifierTypes.MEGA_BRACELET)!);
|
||||
}
|
||||
if (!scene.findModifier(m => m instanceof GigantamaxAccessModifier)) {
|
||||
modifierOptions.push(generateModifierTypeOption(scene, modifierTypes.DYNAMAX_BAND)!);
|
||||
}
|
||||
const nonRareEvolutionModifier = generateModifierTypeOption(scene, modifierTypes.EVOLUTION_ITEM);
|
||||
if (nonRareEvolutionModifier) {
|
||||
specialOptions.push(nonRareEvolutionModifier);
|
||||
|
|
|
@ -28,7 +28,7 @@ import { BattlerIndex } from "#app/battle";
|
|||
import { Moves } from "#enums/moves";
|
||||
import { EncounterBattleAnim } from "#app/data/battle-anims";
|
||||
import { MoveCategory } from "#app/data/move";
|
||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
||||
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
import { EncounterAnim } from "#enums/encounter-anims";
|
||||
import { Challenges } from "#enums/challenges";
|
||||
|
@ -133,7 +133,7 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
|||
},
|
||||
{ // Blacephalon has the random ability from pool, and 2 entirely random types to fit with the theme of the encounter
|
||||
species: getPokemonSpecies(Species.BLACEPHALON),
|
||||
mysteryEncounterPokemonData: new MysteryEncounterPokemonData({ ability: ability, types: [ randSeedInt(18), randSeedInt(18) ]}),
|
||||
customPokemonData: new CustomPokemonData({ ability: ability, types: [ randSeedInt(18), randSeedInt(18) ]}),
|
||||
isBoss: true,
|
||||
moveSet: [ Moves.TRICK, Moves.HYPNOSIS, Moves.SHADOW_BALL, Moves.MIND_BLOWN ]
|
||||
},
|
||||
|
@ -353,15 +353,15 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
|||
newTypes.push(secondType);
|
||||
|
||||
// Apply the type changes (to both base and fusion, if pokemon is fused)
|
||||
if (!pokemon.mysteryEncounterPokemonData) {
|
||||
pokemon.mysteryEncounterPokemonData = new MysteryEncounterPokemonData();
|
||||
if (!pokemon.customPokemonData) {
|
||||
pokemon.customPokemonData = new CustomPokemonData();
|
||||
}
|
||||
pokemon.mysteryEncounterPokemonData.types = newTypes;
|
||||
pokemon.customPokemonData.types = newTypes;
|
||||
if (pokemon.isFusion()) {
|
||||
if (!pokemon.fusionMysteryEncounterPokemonData) {
|
||||
pokemon.fusionMysteryEncounterPokemonData = new MysteryEncounterPokemonData();
|
||||
if (!pokemon.fusionCustomPokemonData) {
|
||||
pokemon.fusionCustomPokemonData = new CustomPokemonData();
|
||||
}
|
||||
pokemon.fusionMysteryEncounterPokemonData.types = newTypes;
|
||||
pokemon.fusionCustomPokemonData.types = newTypes;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -426,15 +426,15 @@ function onYesAbilitySwap(scene: BattleScene, resolve) {
|
|||
// Do ability swap
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
if (pokemon.isFusion()) {
|
||||
if (!pokemon.fusionMysteryEncounterPokemonData) {
|
||||
pokemon.fusionMysteryEncounterPokemonData = new MysteryEncounterPokemonData();
|
||||
if (!pokemon.fusionCustomPokemonData) {
|
||||
pokemon.fusionCustomPokemonData = new CustomPokemonData();
|
||||
}
|
||||
pokemon.fusionMysteryEncounterPokemonData.ability = encounter.misc.ability;
|
||||
pokemon.fusionCustomPokemonData.ability = encounter.misc.ability;
|
||||
} else {
|
||||
if (!pokemon.mysteryEncounterPokemonData) {
|
||||
pokemon.mysteryEncounterPokemonData = new MysteryEncounterPokemonData();
|
||||
if (!pokemon.customPokemonData) {
|
||||
pokemon.customPokemonData = new CustomPokemonData();
|
||||
}
|
||||
pokemon.mysteryEncounterPokemonData.ability = encounter.misc.ability;
|
||||
pokemon.customPokemonData.ability = encounter.misc.ability;
|
||||
}
|
||||
encounter.setDialogueToken("chosenPokemon", pokemon.getNameToRender());
|
||||
scene.ui.setMode(Mode.MESSAGE).then(() => resolve(true));
|
||||
|
|
|
@ -236,7 +236,7 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
|||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||
.withPrimaryPokemonRequirement(new MoveRequirement(DANCING_MOVES)) // Will set option3PrimaryName and option3PrimaryMove dialogue tokens automatically
|
||||
.withPrimaryPokemonRequirement(new MoveRequirement(DANCING_MOVES, true)) // Will set option3PrimaryName and option3PrimaryMove dialogue tokens automatically
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||
|
|
|
@ -145,7 +145,7 @@ export const FightOrFlightEncounter: MysteryEncounter =
|
|||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||
.withPrimaryPokemonRequirement(new MoveRequirement(STEALING_MOVES)) // Will set option2PrimaryName and option2PrimaryMove dialogue tokens automatically
|
||||
.withPrimaryPokemonRequirement(new MoveRequirement(STEALING_MOVES, true)) // Will set option2PrimaryName and option2PrimaryMove dialogue tokens automatically
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}:option.2.label`,
|
||||
buttonTooltip: `${namespace}:option.2.tooltip`,
|
||||
|
|
|
@ -227,7 +227,7 @@ export const PartTimerEncounter: MysteryEncounter =
|
|||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||
.withPrimaryPokemonRequirement(new MoveRequirement(CHARMING_MOVES)) // Will set option3PrimaryName and option3PrimaryMove dialogue tokens automatically
|
||||
.withPrimaryPokemonRequirement(new MoveRequirement(CHARMING_MOVES, true)) // Will set option3PrimaryName and option3PrimaryMove dialogue tokens automatically
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||
|
|
|
@ -138,7 +138,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter =
|
|||
newNature = randSeedInt(25) as Nature;
|
||||
}
|
||||
|
||||
chosenPokemon.nature = newNature;
|
||||
chosenPokemon.customPokemonData.nature = newNature;
|
||||
encounter.setDialogueToken("newNature", getNatureName(newNature));
|
||||
queueEncounterMessage(scene, `${namespace}:cheap_side_effects`);
|
||||
setEncounterExp(scene, [ chosenPokemon.id ], 100);
|
||||
|
|
|
@ -18,7 +18,7 @@ import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode
|
|||
import { PartyHealPhase } from "#app/phases/party-heal-phase";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
import { BerryType } from "#enums/berry-type";
|
||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
||||
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||
|
||||
/** i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounters/slumberingSnorlax";
|
||||
|
@ -72,7 +72,7 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter =
|
|||
stackCount: 2
|
||||
},
|
||||
],
|
||||
mysteryEncounterPokemonData: new MysteryEncounterPokemonData({ spriteScale: 1.25 }),
|
||||
customPokemonData: new CustomPokemonData({ spriteScale: 1.25 }),
|
||||
aiType: AiType.SMART // Required to ensure Snorlax uses Sleep Talk while it is asleep
|
||||
};
|
||||
const config: EnemyPartyConfig = {
|
||||
|
@ -143,7 +143,7 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter =
|
|||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||
.withPrimaryPokemonRequirement(new MoveRequirement(STEALING_MOVES))
|
||||
.withPrimaryPokemonRequirement(new MoveRequirement(STEALING_MOVES, true))
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||
|
|
|
@ -25,6 +25,7 @@ import { achvs } from "#app/system/achv";
|
|||
import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
||||
import { Type } from "#app/data/type";
|
||||
import { getPokeballTintColor } from "#app/data/pokeball";
|
||||
import { PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounters/theExpertPokemonBreeder";
|
||||
|
@ -163,7 +164,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
|||
if (pokemon2CommonEggs > 0) {
|
||||
const eggsText = i18next.t(`${namespace}:numEggs`, { count: pokemon2CommonEggs, rarity: i18next.t("egg:defaultTier") });
|
||||
pokemon2Tooltip += i18next.t(`${namespace}:eggs_tooltip`, { eggs: eggsText });
|
||||
encounter.setDialogueToken("pokemon1CommonEggs", eggsText);
|
||||
encounter.setDialogueToken("pokemon2CommonEggs", eggsText);
|
||||
}
|
||||
encounter.options[1].dialogue!.buttonTooltip = pokemon2Tooltip;
|
||||
|
||||
|
@ -221,7 +222,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
|||
encounter.misc.chosenPokemon = pokemon1;
|
||||
encounter.setDialogueToken("chosenPokemon", pokemon1.getNameToRender());
|
||||
const eggOptions = getEggOptions(scene, pokemon1CommonEggs, pokemon1RareEggs);
|
||||
setEncounterRewards(scene, { fillRemaining: true }, eggOptions);
|
||||
setEncounterRewards(scene, { fillRemaining: true }, eggOptions, () => doPostEncounterCleanup(scene));
|
||||
|
||||
// Remove all Pokemon from the party except the chosen Pokemon
|
||||
removePokemonFromPartyAndStoreHeldItems(scene, encounter, pokemon1);
|
||||
|
@ -247,9 +248,6 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
|||
encounter.onGameOver = onGameOver;
|
||||
await initBattleWithEnemyConfig(scene, config);
|
||||
})
|
||||
.withPostOptionPhase(async (scene: BattleScene) => {
|
||||
await doPostEncounterCleanup(scene);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.withOption(
|
||||
|
@ -273,7 +271,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
|||
encounter.misc.chosenPokemon = pokemon2;
|
||||
encounter.setDialogueToken("chosenPokemon", pokemon2.getNameToRender());
|
||||
const eggOptions = getEggOptions(scene, pokemon2CommonEggs, pokemon2RareEggs);
|
||||
setEncounterRewards(scene, { fillRemaining: true }, eggOptions);
|
||||
setEncounterRewards(scene, { fillRemaining: true }, eggOptions, () => doPostEncounterCleanup(scene));
|
||||
|
||||
// Remove all Pokemon from the party except the chosen Pokemon
|
||||
removePokemonFromPartyAndStoreHeldItems(scene, encounter, pokemon2);
|
||||
|
@ -299,9 +297,6 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
|||
encounter.onGameOver = onGameOver;
|
||||
await initBattleWithEnemyConfig(scene, config);
|
||||
})
|
||||
.withPostOptionPhase(async (scene: BattleScene) => {
|
||||
await doPostEncounterCleanup(scene);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.withOption(
|
||||
|
@ -325,7 +320,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
|||
encounter.misc.chosenPokemon = pokemon3;
|
||||
encounter.setDialogueToken("chosenPokemon", pokemon3.getNameToRender());
|
||||
const eggOptions = getEggOptions(scene, pokemon3CommonEggs, pokemon3RareEggs);
|
||||
setEncounterRewards(scene, { fillRemaining: true }, eggOptions);
|
||||
setEncounterRewards(scene, { fillRemaining: true }, eggOptions, () => doPostEncounterCleanup(scene));
|
||||
|
||||
// Remove all Pokemon from the party except the chosen Pokemon
|
||||
removePokemonFromPartyAndStoreHeldItems(scene, encounter, pokemon3);
|
||||
|
@ -351,9 +346,6 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter =
|
|||
encounter.onGameOver = onGameOver;
|
||||
await initBattleWithEnemyConfig(scene, config);
|
||||
})
|
||||
.withPostOptionPhase(async (scene: BattleScene) => {
|
||||
await doPostEncounterCleanup(scene);
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.withOutroDialogue([
|
||||
|
@ -521,19 +513,19 @@ function checkAchievement(scene: BattleScene) {
|
|||
}
|
||||
}
|
||||
|
||||
async function restorePartyAndHeldItems(scene: BattleScene) {
|
||||
function restorePartyAndHeldItems(scene: BattleScene) {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
// Restore original party
|
||||
scene.getParty().push(...encounter.misc.originalParty);
|
||||
|
||||
// Restore held items
|
||||
const originalHeldItems = encounter.misc.originalPartyHeldItems;
|
||||
originalHeldItems.forEach(pokemonHeldItemsList => {
|
||||
originalHeldItems.forEach((pokemonHeldItemsList: PokemonHeldItemModifier[]) => {
|
||||
pokemonHeldItemsList.forEach(heldItem => {
|
||||
scene.addModifier(heldItem, true, false, false, true);
|
||||
});
|
||||
});
|
||||
await scene.updateModifiers(true);
|
||||
scene.updateModifiers(true);
|
||||
}
|
||||
|
||||
function onGameOver(scene: BattleScene) {
|
||||
|
@ -609,13 +601,13 @@ function onGameOver(scene: BattleScene) {
|
|||
return false;
|
||||
}
|
||||
|
||||
async function doPostEncounterCleanup(scene: BattleScene) {
|
||||
function doPostEncounterCleanup(scene: BattleScene) {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
if (!encounter.misc.encounterFailed) {
|
||||
// Give achievement if in Space biome
|
||||
checkAchievement(scene);
|
||||
// Give 20 friendship to the chosen pokemon
|
||||
encounter.misc.chosenPokemon.addFriendship(FRIENDSHIP_ADDED);
|
||||
await restorePartyAndHeldItems(scene);
|
||||
restorePartyAndHeldItems(scene);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import { BattlerIndex } from "#app/battle";
|
|||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { BerryType } from "#enums/berry-type";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
||||
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||
import { Stat } from "#enums/stat";
|
||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
|
@ -79,7 +79,7 @@ export const TheStrongStuffEncounter: MysteryEncounter =
|
|||
species: getPokemonSpecies(Species.SHUCKLE),
|
||||
isBoss: true,
|
||||
bossSegments: 5,
|
||||
mysteryEncounterPokemonData: new MysteryEncounterPokemonData({ spriteScale: 1.25 }),
|
||||
customPokemonData: new CustomPokemonData({ spriteScale: 1.25 }),
|
||||
nature: Nature.BOLD,
|
||||
moveSet: [ Moves.INFESTATION, Moves.SALT_CURE, Moves.GASTRO_ACID, Moves.HEAL_ORDER ],
|
||||
modifierConfigs: [
|
||||
|
|
|
@ -210,7 +210,7 @@ export const UncommonBreedEncounter: MysteryEncounter =
|
|||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||
.withPrimaryPokemonRequirement(new MoveRequirement(CHARMING_MOVES)) // Will set option2PrimaryName and option2PrimaryMove dialogue tokens automatically
|
||||
.withPrimaryPokemonRequirement(new MoveRequirement(CHARMING_MOVES, true)) // Will set option2PrimaryName and option2PrimaryMove dialogue tokens automatically
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}:option.3.label`,
|
||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||
|
|
|
@ -12,7 +12,7 @@ import { IntegerHolder, isNullOrUndefined, randSeedInt, randSeedShuffle } from "
|
|||
import PokemonSpecies, { allSpecies, getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { HiddenAbilityRateBoosterModifier, PokemonFormChangeItemModifier, PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||
import { achvs } from "#app/system/achv";
|
||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
||||
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||
import { showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||
import i18next from "#app/plugins/i18n";
|
||||
|
@ -379,10 +379,10 @@ async function doNewTeamPostProcess(scene: BattleScene, transformations: Pokemon
|
|||
newType = randSeedInt(18) as Type;
|
||||
}
|
||||
newTypes.push(newType);
|
||||
if (!newPokemon.mysteryEncounterPokemonData) {
|
||||
newPokemon.mysteryEncounterPokemonData = new MysteryEncounterPokemonData();
|
||||
if (!newPokemon.customPokemonData) {
|
||||
newPokemon.customPokemonData = new CustomPokemonData();
|
||||
}
|
||||
newPokemon.mysteryEncounterPokemonData.types = newTypes;
|
||||
newPokemon.customPokemonData.types = newTypes;
|
||||
|
||||
for (const item of transformation.heldItems) {
|
||||
item.pokemonId = newPokemon.id;
|
||||
|
|
|
@ -15,6 +15,7 @@ import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
|||
import { AttackTypeBoosterModifier } from "#app/modifier/modifier";
|
||||
import { AttackTypeBoosterModifierType } from "#app/modifier/modifier-type";
|
||||
import { SpeciesFormKey } from "#enums/species-form-key";
|
||||
import { allAbilities } from "#app/data/ability";
|
||||
|
||||
export interface EncounterRequirement {
|
||||
meetsRequirement(scene: BattleScene): boolean; // Boolean to see if a requirement is met
|
||||
|
@ -476,9 +477,11 @@ export class MoveRequirement extends EncounterPokemonRequirement {
|
|||
requiredMoves: Moves[] = [];
|
||||
minNumberOfPokemon: number;
|
||||
invertQuery: boolean;
|
||||
excludeDisallowedPokemon: boolean;
|
||||
|
||||
constructor(moves: Moves | Moves[], minNumberOfPokemon: number = 1, invertQuery: boolean = false) {
|
||||
constructor(moves: Moves | Moves[], excludeDisallowedPokemon: boolean, minNumberOfPokemon: number = 1, invertQuery: boolean = false) {
|
||||
super();
|
||||
this.excludeDisallowedPokemon = excludeDisallowedPokemon;
|
||||
this.minNumberOfPokemon = minNumberOfPokemon;
|
||||
this.invertQuery = invertQuery;
|
||||
this.requiredMoves = Array.isArray(moves) ? moves : [ moves ];
|
||||
|
@ -494,10 +497,15 @@ export class MoveRequirement extends EncounterPokemonRequirement {
|
|||
|
||||
override queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
|
||||
if (!this.invertQuery) {
|
||||
return partyPokemon.filter((pokemon) => this.requiredMoves.filter((reqMove) => pokemon.moveset.filter((move) => move?.moveId === reqMove).length > 0).length > 0);
|
||||
// get the Pokemon with at least one move in the required moves list
|
||||
return partyPokemon.filter((pokemon) =>
|
||||
(!this.excludeDisallowedPokemon || pokemon.isAllowedInBattle())
|
||||
&& pokemon.moveset.some((move) => move?.moveId && this.requiredMoves.includes(move.moveId)));
|
||||
} else {
|
||||
// for an inverted query, we only want to get the pokemon that don't have ANY of the listed moves
|
||||
return partyPokemon.filter((pokemon) => this.requiredMoves.filter((reqMove) => pokemon.moveset.filter((move) => move?.moveId === reqMove).length === 0).length === 0);
|
||||
return partyPokemon.filter((pokemon) =>
|
||||
(!this.excludeDisallowedPokemon || pokemon.isAllowedInBattle())
|
||||
&& !pokemon.moveset.some((move) => move?.moveId && this.requiredMoves.includes(move.moveId)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -559,9 +567,11 @@ export class AbilityRequirement extends EncounterPokemonRequirement {
|
|||
requiredAbilities: Abilities[];
|
||||
minNumberOfPokemon: number;
|
||||
invertQuery: boolean;
|
||||
excludeDisallowedPokemon: boolean;
|
||||
|
||||
constructor(abilities: Abilities | Abilities[], minNumberOfPokemon: number = 1, invertQuery: boolean = false) {
|
||||
constructor(abilities: Abilities | Abilities[], excludeDisallowedPokemon: boolean, minNumberOfPokemon: number = 1, invertQuery: boolean = false) {
|
||||
super();
|
||||
this.excludeDisallowedPokemon = excludeDisallowedPokemon;
|
||||
this.minNumberOfPokemon = minNumberOfPokemon;
|
||||
this.invertQuery = invertQuery;
|
||||
this.requiredAbilities = Array.isArray(abilities) ? abilities : [ abilities ];
|
||||
|
@ -577,16 +587,21 @@ export class AbilityRequirement extends EncounterPokemonRequirement {
|
|||
|
||||
override queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
|
||||
if (!this.invertQuery) {
|
||||
return partyPokemon.filter((pokemon) => this.requiredAbilities.some((ability) => pokemon.getAbility().id === ability));
|
||||
return partyPokemon.filter((pokemon) =>
|
||||
(!this.excludeDisallowedPokemon || pokemon.isAllowedInBattle())
|
||||
&& this.requiredAbilities.some((ability) => pokemon.hasAbility(ability, false)));
|
||||
} else {
|
||||
// for an inverted query, we only want to get the pokemon that don't have ANY of the listed abilitiess
|
||||
return partyPokemon.filter((pokemon) => this.requiredAbilities.filter((ability) => pokemon.getAbility().id === ability).length === 0);
|
||||
// for an inverted query, we only want to get the pokemon that don't have ANY of the listed abilities
|
||||
return partyPokemon.filter((pokemon) =>
|
||||
(!this.excludeDisallowedPokemon || pokemon.isAllowedInBattle())
|
||||
&& this.requiredAbilities.filter((ability) => pokemon.hasAbility(ability, false)).length === 0);
|
||||
}
|
||||
}
|
||||
|
||||
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
if (pokemon?.getAbility().id && this.requiredAbilities.some(a => pokemon.getAbility().id === a)) {
|
||||
return [ "ability", pokemon.getAbility().name ];
|
||||
override getDialogueToken(_scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||
const matchingAbility = this.requiredAbilities.find(a => pokemon?.hasAbility(a, false));
|
||||
if (!isNullOrUndefined(matchingAbility)) {
|
||||
return [ "ability", allAbilities[matchingAbility].name ];
|
||||
}
|
||||
return [ "ability", "" ];
|
||||
}
|
||||
|
|
|
@ -325,7 +325,7 @@ export default class MysteryEncounter implements IMysteryEncounter {
|
|||
if (activeMon.length > 0) {
|
||||
this.primaryPokemon = activeMon[0];
|
||||
} else {
|
||||
this.primaryPokemon = scene.getParty().filter(p => !p.isFainted())[0];
|
||||
this.primaryPokemon = scene.getParty().filter(p => p.isAllowedInBattle())[0];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import { Status, StatusEffect } from "#app/data/status-effect";
|
|||
import { TrainerConfig, trainerConfigs, TrainerSlot } from "#app/data/trainer-config";
|
||||
import PokemonSpecies from "#app/data/pokemon-species";
|
||||
import { Egg, IEggOptions } from "#app/data/egg";
|
||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
||||
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||
import HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
||||
import { MovePhase } from "#app/phases/move-phase";
|
||||
import { EggLapsePhase } from "#app/phases/egg-lapse-phase";
|
||||
|
@ -71,7 +71,7 @@ export interface EnemyPokemonConfig {
|
|||
nickname?: string;
|
||||
bossSegments?: number;
|
||||
bossSegmentModifier?: number; // Additive to the determined segment number
|
||||
mysteryEncounterPokemonData?: MysteryEncounterPokemonData;
|
||||
customPokemonData?: CustomPokemonData;
|
||||
formIndex?: number;
|
||||
abilityIndex?: number;
|
||||
level?: number;
|
||||
|
@ -145,7 +145,7 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
|
|||
newTrainer.setVisible(false);
|
||||
scene.field.add(newTrainer);
|
||||
scene.currentBattle.trainer = newTrainer;
|
||||
loadEnemyAssets.push(newTrainer.loadAssets());
|
||||
loadEnemyAssets.push(newTrainer.loadAssets().then(() => newTrainer.initSprite()));
|
||||
|
||||
battle.enemyLevels = scene.currentBattle.trainer.getPartyLevels(scene.currentBattle.waveIndex);
|
||||
} else {
|
||||
|
@ -250,8 +250,8 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
|
|||
}
|
||||
|
||||
// Set custom mystery encounter data fields (such as sprite scale, custom abilities, types, etc.)
|
||||
if (!isNullOrUndefined(config.mysteryEncounterPokemonData)) {
|
||||
enemyPokemon.mysteryEncounterPokemonData = config.mysteryEncounterPokemonData;
|
||||
if (!isNullOrUndefined(config.customPokemonData)) {
|
||||
enemyPokemon.customPokemonData = config.customPokemonData;
|
||||
}
|
||||
|
||||
// Set Boss
|
||||
|
@ -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;
|
||||
|
||||
switch (tier) {
|
||||
default:
|
||||
case BiomePoolTier.BOSS:
|
||||
++bossEncountersByRarity[0];
|
||||
break;
|
||||
case BiomePoolTier.BOSS_RARE:
|
||||
++bossEncountersByRarity[1];
|
||||
break;
|
||||
case BiomePoolTier.BOSS_SUPER_RARE:
|
||||
++bossEncountersByRarity[2];
|
||||
break;
|
||||
case BiomePoolTier.BOSS_ULTRA_RARE:
|
||||
++bossEncountersByRarity[3];
|
||||
break;
|
||||
default:
|
||||
case BiomePoolTier.BOSS:
|
||||
++bossEncountersByRarity[0];
|
||||
break;
|
||||
case BiomePoolTier.BOSS_RARE:
|
||||
++bossEncountersByRarity[1];
|
||||
break;
|
||||
case BiomePoolTier.BOSS_SUPER_RARE:
|
||||
++bossEncountersByRarity[2];
|
||||
break;
|
||||
case BiomePoolTier.BOSS_ULTRA_RARE:
|
||||
++bossEncountersByRarity[3];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,76 +37,76 @@ export function getNatureName(nature: Nature, includeStatEffects: boolean = fals
|
|||
|
||||
export function getNatureStatMultiplier(nature: Nature, stat: Stat): number {
|
||||
switch (stat) {
|
||||
case Stat.ATK:
|
||||
switch (nature) {
|
||||
case Nature.LONELY:
|
||||
case Nature.BRAVE:
|
||||
case Nature.ADAMANT:
|
||||
case Nature.NAUGHTY:
|
||||
return 1.1;
|
||||
case Nature.BOLD:
|
||||
case Nature.TIMID:
|
||||
case Nature.MODEST:
|
||||
case Nature.CALM:
|
||||
return 0.9;
|
||||
}
|
||||
break;
|
||||
case Stat.DEF:
|
||||
switch (nature) {
|
||||
case Nature.BOLD:
|
||||
case Nature.RELAXED:
|
||||
case Nature.IMPISH:
|
||||
case Nature.LAX:
|
||||
return 1.1;
|
||||
case Nature.LONELY:
|
||||
case Nature.HASTY:
|
||||
case Nature.MILD:
|
||||
case Nature.GENTLE:
|
||||
return 0.9;
|
||||
}
|
||||
break;
|
||||
case Stat.SPATK:
|
||||
switch (nature) {
|
||||
case Nature.MODEST:
|
||||
case Nature.MILD:
|
||||
case Nature.QUIET:
|
||||
case Nature.RASH:
|
||||
return 1.1;
|
||||
case Nature.ADAMANT:
|
||||
case Nature.IMPISH:
|
||||
case Nature.JOLLY:
|
||||
case Nature.CAREFUL:
|
||||
return 0.9;
|
||||
}
|
||||
break;
|
||||
case Stat.SPDEF:
|
||||
switch (nature) {
|
||||
case Nature.CALM:
|
||||
case Nature.GENTLE:
|
||||
case Nature.SASSY:
|
||||
case Nature.CAREFUL:
|
||||
return 1.1;
|
||||
case Nature.NAUGHTY:
|
||||
case Nature.LAX:
|
||||
case Nature.NAIVE:
|
||||
case Nature.RASH:
|
||||
return 0.9;
|
||||
}
|
||||
break;
|
||||
case Stat.SPD:
|
||||
switch (nature) {
|
||||
case Nature.TIMID:
|
||||
case Nature.HASTY:
|
||||
case Nature.JOLLY:
|
||||
case Nature.NAIVE:
|
||||
return 1.1;
|
||||
case Nature.BRAVE:
|
||||
case Nature.RELAXED:
|
||||
case Nature.QUIET:
|
||||
case Nature.SASSY:
|
||||
return 0.9;
|
||||
}
|
||||
break;
|
||||
case Stat.ATK:
|
||||
switch (nature) {
|
||||
case Nature.LONELY:
|
||||
case Nature.BRAVE:
|
||||
case Nature.ADAMANT:
|
||||
case Nature.NAUGHTY:
|
||||
return 1.1;
|
||||
case Nature.BOLD:
|
||||
case Nature.TIMID:
|
||||
case Nature.MODEST:
|
||||
case Nature.CALM:
|
||||
return 0.9;
|
||||
}
|
||||
break;
|
||||
case Stat.DEF:
|
||||
switch (nature) {
|
||||
case Nature.BOLD:
|
||||
case Nature.RELAXED:
|
||||
case Nature.IMPISH:
|
||||
case Nature.LAX:
|
||||
return 1.1;
|
||||
case Nature.LONELY:
|
||||
case Nature.HASTY:
|
||||
case Nature.MILD:
|
||||
case Nature.GENTLE:
|
||||
return 0.9;
|
||||
}
|
||||
break;
|
||||
case Stat.SPATK:
|
||||
switch (nature) {
|
||||
case Nature.MODEST:
|
||||
case Nature.MILD:
|
||||
case Nature.QUIET:
|
||||
case Nature.RASH:
|
||||
return 1.1;
|
||||
case Nature.ADAMANT:
|
||||
case Nature.IMPISH:
|
||||
case Nature.JOLLY:
|
||||
case Nature.CAREFUL:
|
||||
return 0.9;
|
||||
}
|
||||
break;
|
||||
case Stat.SPDEF:
|
||||
switch (nature) {
|
||||
case Nature.CALM:
|
||||
case Nature.GENTLE:
|
||||
case Nature.SASSY:
|
||||
case Nature.CAREFUL:
|
||||
return 1.1;
|
||||
case Nature.NAUGHTY:
|
||||
case Nature.LAX:
|
||||
case Nature.NAIVE:
|
||||
case Nature.RASH:
|
||||
return 0.9;
|
||||
}
|
||||
break;
|
||||
case Stat.SPD:
|
||||
switch (nature) {
|
||||
case Nature.TIMID:
|
||||
case Nature.HASTY:
|
||||
case Nature.JOLLY:
|
||||
case Nature.NAIVE:
|
||||
return 1.1;
|
||||
case Nature.BRAVE:
|
||||
case Nature.RELAXED:
|
||||
case Nature.QUIET:
|
||||
case Nature.SASSY:
|
||||
return 0.9;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
|
|
@ -8,77 +8,77 @@ export const MAX_PER_TYPE_POKEBALLS: integer = 99;
|
|||
|
||||
export function getPokeballAtlasKey(type: PokeballType): string {
|
||||
switch (type) {
|
||||
case PokeballType.POKEBALL:
|
||||
return "pb";
|
||||
case PokeballType.GREAT_BALL:
|
||||
return "gb";
|
||||
case PokeballType.ULTRA_BALL:
|
||||
return "ub";
|
||||
case PokeballType.ROGUE_BALL:
|
||||
return "rb";
|
||||
case PokeballType.MASTER_BALL:
|
||||
return "mb";
|
||||
case PokeballType.LUXURY_BALL:
|
||||
return "lb";
|
||||
case PokeballType.POKEBALL:
|
||||
return "pb";
|
||||
case PokeballType.GREAT_BALL:
|
||||
return "gb";
|
||||
case PokeballType.ULTRA_BALL:
|
||||
return "ub";
|
||||
case PokeballType.ROGUE_BALL:
|
||||
return "rb";
|
||||
case PokeballType.MASTER_BALL:
|
||||
return "mb";
|
||||
case PokeballType.LUXURY_BALL:
|
||||
return "lb";
|
||||
}
|
||||
}
|
||||
|
||||
export function getPokeballName(type: PokeballType): string {
|
||||
let ret: string;
|
||||
switch (type) {
|
||||
case PokeballType.POKEBALL:
|
||||
ret = i18next.t("pokeball:pokeBall");
|
||||
break;
|
||||
case PokeballType.GREAT_BALL:
|
||||
ret = i18next.t("pokeball:greatBall");
|
||||
break;
|
||||
case PokeballType.ULTRA_BALL:
|
||||
ret = i18next.t("pokeball:ultraBall");
|
||||
break;
|
||||
case PokeballType.ROGUE_BALL:
|
||||
ret = i18next.t("pokeball:rogueBall");
|
||||
break;
|
||||
case PokeballType.MASTER_BALL:
|
||||
ret = i18next.t("pokeball:masterBall");
|
||||
break;
|
||||
case PokeballType.LUXURY_BALL:
|
||||
ret = i18next.t("pokeball:luxuryBall");
|
||||
break;
|
||||
case PokeballType.POKEBALL:
|
||||
ret = i18next.t("pokeball:pokeBall");
|
||||
break;
|
||||
case PokeballType.GREAT_BALL:
|
||||
ret = i18next.t("pokeball:greatBall");
|
||||
break;
|
||||
case PokeballType.ULTRA_BALL:
|
||||
ret = i18next.t("pokeball:ultraBall");
|
||||
break;
|
||||
case PokeballType.ROGUE_BALL:
|
||||
ret = i18next.t("pokeball:rogueBall");
|
||||
break;
|
||||
case PokeballType.MASTER_BALL:
|
||||
ret = i18next.t("pokeball:masterBall");
|
||||
break;
|
||||
case PokeballType.LUXURY_BALL:
|
||||
ret = i18next.t("pokeball:luxuryBall");
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
export function getPokeballCatchMultiplier(type: PokeballType): number {
|
||||
switch (type) {
|
||||
case PokeballType.POKEBALL:
|
||||
return 1;
|
||||
case PokeballType.GREAT_BALL:
|
||||
return 1.5;
|
||||
case PokeballType.ULTRA_BALL:
|
||||
return 2;
|
||||
case PokeballType.ROGUE_BALL:
|
||||
return 3;
|
||||
case PokeballType.MASTER_BALL:
|
||||
return -1;
|
||||
case PokeballType.LUXURY_BALL:
|
||||
return 1;
|
||||
case PokeballType.POKEBALL:
|
||||
return 1;
|
||||
case PokeballType.GREAT_BALL:
|
||||
return 1.5;
|
||||
case PokeballType.ULTRA_BALL:
|
||||
return 2;
|
||||
case PokeballType.ROGUE_BALL:
|
||||
return 3;
|
||||
case PokeballType.MASTER_BALL:
|
||||
return -1;
|
||||
case PokeballType.LUXURY_BALL:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
export function getPokeballTintColor(type: PokeballType): number {
|
||||
switch (type) {
|
||||
case PokeballType.POKEBALL:
|
||||
return 0xd52929;
|
||||
case PokeballType.GREAT_BALL:
|
||||
return 0x94b4de;
|
||||
case PokeballType.ULTRA_BALL:
|
||||
return 0xe6cd31;
|
||||
case PokeballType.ROGUE_BALL:
|
||||
return 0xd52929;
|
||||
case PokeballType.MASTER_BALL:
|
||||
return 0xa441bd;
|
||||
case PokeballType.LUXURY_BALL:
|
||||
return 0xffde6a;
|
||||
case PokeballType.POKEBALL:
|
||||
return 0xd52929;
|
||||
case PokeballType.GREAT_BALL:
|
||||
return 0x94b4de;
|
||||
case PokeballType.ULTRA_BALL:
|
||||
return 0xe6cd31;
|
||||
case PokeballType.ROGUE_BALL:
|
||||
return 0xd52929;
|
||||
case PokeballType.MASTER_BALL:
|
||||
return 0xa441bd;
|
||||
case PokeballType.LUXURY_BALL:
|
||||
return 0xffde6a;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -238,8 +238,8 @@ export abstract class PokemonSpeciesForm {
|
|||
|
||||
isRareRegional(): boolean {
|
||||
switch (this.getRegion()) {
|
||||
case Region.HISUI:
|
||||
return true;
|
||||
case Region.HISUI:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -265,14 +265,14 @@ export abstract class PokemonSpeciesForm {
|
|||
getBaseExp(): number {
|
||||
let ret = this.baseExp;
|
||||
switch (this.getFormSpriteKey()) {
|
||||
case SpeciesFormKey.MEGA:
|
||||
case SpeciesFormKey.MEGA_X:
|
||||
case SpeciesFormKey.MEGA_Y:
|
||||
case SpeciesFormKey.PRIMAL:
|
||||
case SpeciesFormKey.GIGANTAMAX:
|
||||
case SpeciesFormKey.ETERNAMAX:
|
||||
ret *= 1.5;
|
||||
break;
|
||||
case SpeciesFormKey.MEGA:
|
||||
case SpeciesFormKey.MEGA_X:
|
||||
case SpeciesFormKey.MEGA_Y:
|
||||
case SpeciesFormKey.PRIMAL:
|
||||
case SpeciesFormKey.GIGANTAMAX:
|
||||
case SpeciesFormKey.ETERNAMAX:
|
||||
ret *= 1.5;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -346,29 +346,29 @@ export abstract class PokemonSpeciesForm {
|
|||
}
|
||||
|
||||
switch (this.speciesId) {
|
||||
case Species.HIPPOPOTAS:
|
||||
case Species.HIPPOWDON:
|
||||
case Species.UNFEZANT:
|
||||
case Species.FRILLISH:
|
||||
case Species.JELLICENT:
|
||||
case Species.PYROAR:
|
||||
ret += female ? "-f" : "";
|
||||
break;
|
||||
case Species.HIPPOPOTAS:
|
||||
case Species.HIPPOWDON:
|
||||
case Species.UNFEZANT:
|
||||
case Species.FRILLISH:
|
||||
case Species.JELLICENT:
|
||||
case Species.PYROAR:
|
||||
ret += female ? "-f" : "";
|
||||
break;
|
||||
}
|
||||
|
||||
let formSpriteKey = this.getFormSpriteKey(formIndex);
|
||||
if (formSpriteKey) {
|
||||
switch (this.speciesId) {
|
||||
case Species.DUDUNSPARCE:
|
||||
break;
|
||||
case Species.ZACIAN:
|
||||
case Species.ZAMAZENTA:
|
||||
if (formSpriteKey.startsWith("behemoth")) {
|
||||
formSpriteKey = "crowned";
|
||||
}
|
||||
default:
|
||||
ret += `-${formSpriteKey}`;
|
||||
break;
|
||||
case Species.DUDUNSPARCE:
|
||||
break;
|
||||
case Species.ZACIAN:
|
||||
case Species.ZAMAZENTA:
|
||||
if (formSpriteKey.startsWith("behemoth")) {
|
||||
formSpriteKey = "crowned";
|
||||
}
|
||||
default:
|
||||
ret += `-${formSpriteKey}`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -383,15 +383,15 @@ export abstract class PokemonSpeciesForm {
|
|||
let speciesId = this.speciesId;
|
||||
if (this.speciesId > 2000) {
|
||||
switch (this.speciesId) {
|
||||
case Species.GALAR_SLOWPOKE:
|
||||
break;
|
||||
case Species.ETERNAL_FLOETTE:
|
||||
break;
|
||||
case Species.BLOODMOON_URSALUNA:
|
||||
break;
|
||||
default:
|
||||
speciesId = speciesId % 2000;
|
||||
break;
|
||||
case Species.GALAR_SLOWPOKE:
|
||||
break;
|
||||
case Species.ETERNAL_FLOETTE:
|
||||
break;
|
||||
case Species.BLOODMOON_URSALUNA:
|
||||
break;
|
||||
default:
|
||||
speciesId = speciesId % 2000;
|
||||
break;
|
||||
}
|
||||
}
|
||||
let ret = speciesId.toString();
|
||||
|
@ -403,44 +403,44 @@ export abstract class PokemonSpeciesForm {
|
|||
}
|
||||
const formKey = forms[formIndex || 0].formKey;
|
||||
switch (formKey) {
|
||||
case SpeciesFormKey.MEGA:
|
||||
case SpeciesFormKey.MEGA_X:
|
||||
case SpeciesFormKey.MEGA_Y:
|
||||
case SpeciesFormKey.GIGANTAMAX:
|
||||
case SpeciesFormKey.GIGANTAMAX_SINGLE:
|
||||
case SpeciesFormKey.GIGANTAMAX_RAPID:
|
||||
case "white":
|
||||
case "black":
|
||||
case "therian":
|
||||
case "sky":
|
||||
case "gorging":
|
||||
case "gulping":
|
||||
case "no-ice":
|
||||
case "hangry":
|
||||
case "crowned":
|
||||
case "eternamax":
|
||||
case "four":
|
||||
case "droopy":
|
||||
case "stretchy":
|
||||
case "hero":
|
||||
case "roaming":
|
||||
case "complete":
|
||||
case "10-complete":
|
||||
case "10":
|
||||
case "10-pc":
|
||||
case "super":
|
||||
case "unbound":
|
||||
case "pau":
|
||||
case "pompom":
|
||||
case "sensu":
|
||||
case "dusk":
|
||||
case "midnight":
|
||||
case "school":
|
||||
case "dawn-wings":
|
||||
case "dusk-mane":
|
||||
case "ultra":
|
||||
ret += `-${formKey}`;
|
||||
break;
|
||||
case SpeciesFormKey.MEGA:
|
||||
case SpeciesFormKey.MEGA_X:
|
||||
case SpeciesFormKey.MEGA_Y:
|
||||
case SpeciesFormKey.GIGANTAMAX:
|
||||
case SpeciesFormKey.GIGANTAMAX_SINGLE:
|
||||
case SpeciesFormKey.GIGANTAMAX_RAPID:
|
||||
case "white":
|
||||
case "black":
|
||||
case "therian":
|
||||
case "sky":
|
||||
case "gorging":
|
||||
case "gulping":
|
||||
case "no-ice":
|
||||
case "hangry":
|
||||
case "crowned":
|
||||
case "eternamax":
|
||||
case "four":
|
||||
case "droopy":
|
||||
case "stretchy":
|
||||
case "hero":
|
||||
case "roaming":
|
||||
case "complete":
|
||||
case "10-complete":
|
||||
case "10":
|
||||
case "10-pc":
|
||||
case "super":
|
||||
case "unbound":
|
||||
case "pau":
|
||||
case "pompom":
|
||||
case "sensu":
|
||||
case "dusk":
|
||||
case "midnight":
|
||||
case "school":
|
||||
case "dawn-wings":
|
||||
case "dusk-mane":
|
||||
case "ultra":
|
||||
ret += `-${formKey}`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
@ -636,19 +636,19 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
|
|||
const form = this.forms[formIndex];
|
||||
let key: string | null;
|
||||
switch (form.formKey) {
|
||||
case SpeciesFormKey.MEGA:
|
||||
case SpeciesFormKey.PRIMAL:
|
||||
case SpeciesFormKey.ETERNAMAX:
|
||||
case SpeciesFormKey.MEGA_X:
|
||||
case SpeciesFormKey.MEGA_Y:
|
||||
key = form.formKey;
|
||||
break;
|
||||
default:
|
||||
if (form.formKey.indexOf(SpeciesFormKey.GIGANTAMAX) > -1) {
|
||||
key = "gigantamax";
|
||||
} else {
|
||||
key = null;
|
||||
}
|
||||
case SpeciesFormKey.MEGA:
|
||||
case SpeciesFormKey.PRIMAL:
|
||||
case SpeciesFormKey.ETERNAMAX:
|
||||
case SpeciesFormKey.MEGA_X:
|
||||
case SpeciesFormKey.MEGA_Y:
|
||||
key = form.formKey;
|
||||
break;
|
||||
default:
|
||||
if (form.formKey.indexOf(SpeciesFormKey.GIGANTAMAX) > -1) {
|
||||
key = "gigantamax";
|
||||
} else {
|
||||
key = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (key) {
|
||||
|
@ -690,18 +690,18 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
|
|||
*/
|
||||
private getStrengthLevelDiff(strength: PartyMemberStrength): integer {
|
||||
switch (Math.min(strength, PartyMemberStrength.STRONGER)) {
|
||||
case PartyMemberStrength.WEAKEST:
|
||||
return 60;
|
||||
case PartyMemberStrength.WEAKER:
|
||||
return 40;
|
||||
case PartyMemberStrength.WEAK:
|
||||
return 20;
|
||||
case PartyMemberStrength.AVERAGE:
|
||||
return 8;
|
||||
case PartyMemberStrength.STRONG:
|
||||
return 4;
|
||||
default:
|
||||
return 0;
|
||||
case PartyMemberStrength.WEAKEST:
|
||||
return 60;
|
||||
case PartyMemberStrength.WEAKER:
|
||||
return 40;
|
||||
case PartyMemberStrength.WEAK:
|
||||
return 20;
|
||||
case PartyMemberStrength.AVERAGE:
|
||||
return 8;
|
||||
case PartyMemberStrength.STRONG:
|
||||
return 4;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,20 +26,20 @@ export class Status {
|
|||
|
||||
function getStatusEffectMessageKey(statusEffect: StatusEffect | undefined): string {
|
||||
switch (statusEffect) {
|
||||
case StatusEffect.POISON:
|
||||
return "statusEffect:poison";
|
||||
case StatusEffect.TOXIC:
|
||||
return "statusEffect:toxic";
|
||||
case StatusEffect.PARALYSIS:
|
||||
return "statusEffect:paralysis";
|
||||
case StatusEffect.SLEEP:
|
||||
return "statusEffect:sleep";
|
||||
case StatusEffect.FREEZE:
|
||||
return "statusEffect:freeze";
|
||||
case StatusEffect.BURN:
|
||||
return "statusEffect:burn";
|
||||
default:
|
||||
return "statusEffect:none";
|
||||
case StatusEffect.POISON:
|
||||
return "statusEffect:poison";
|
||||
case StatusEffect.TOXIC:
|
||||
return "statusEffect:toxic";
|
||||
case StatusEffect.PARALYSIS:
|
||||
return "statusEffect:paralysis";
|
||||
case StatusEffect.SLEEP:
|
||||
return "statusEffect:sleep";
|
||||
case StatusEffect.FREEZE:
|
||||
return "statusEffect:freeze";
|
||||
case StatusEffect.BURN:
|
||||
return "statusEffect:burn";
|
||||
default:
|
||||
return "statusEffect:none";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,14 +90,14 @@ export function getStatusEffectDescriptor(statusEffect: StatusEffect): string {
|
|||
|
||||
export function getStatusEffectCatchRateMultiplier(statusEffect: StatusEffect): number {
|
||||
switch (statusEffect) {
|
||||
case StatusEffect.POISON:
|
||||
case StatusEffect.TOXIC:
|
||||
case StatusEffect.PARALYSIS:
|
||||
case StatusEffect.BURN:
|
||||
return 1.5;
|
||||
case StatusEffect.SLEEP:
|
||||
case StatusEffect.FREEZE:
|
||||
return 2.5;
|
||||
case StatusEffect.POISON:
|
||||
case StatusEffect.TOXIC:
|
||||
case StatusEffect.PARALYSIS:
|
||||
case StatusEffect.BURN:
|
||||
return 1.5;
|
||||
case StatusEffect.SLEEP:
|
||||
case StatusEffect.FREEZE:
|
||||
return 2.5;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
|
|
@ -34,21 +34,21 @@ export class Terrain {
|
|||
|
||||
getAttackTypeMultiplier(attackType: Type): number {
|
||||
switch (this.terrainType) {
|
||||
case TerrainType.ELECTRIC:
|
||||
if (attackType === Type.ELECTRIC) {
|
||||
return 1.3;
|
||||
}
|
||||
break;
|
||||
case TerrainType.GRASSY:
|
||||
if (attackType === Type.GRASS) {
|
||||
return 1.3;
|
||||
}
|
||||
break;
|
||||
case TerrainType.PSYCHIC:
|
||||
if (attackType === Type.PSYCHIC) {
|
||||
return 1.3;
|
||||
}
|
||||
break;
|
||||
case TerrainType.ELECTRIC:
|
||||
if (attackType === Type.ELECTRIC) {
|
||||
return 1.3;
|
||||
}
|
||||
break;
|
||||
case TerrainType.GRASSY:
|
||||
if (attackType === Type.GRASS) {
|
||||
return 1.3;
|
||||
}
|
||||
break;
|
||||
case TerrainType.PSYCHIC:
|
||||
if (attackType === Type.PSYCHIC) {
|
||||
return 1.3;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -56,13 +56,13 @@ export class Terrain {
|
|||
|
||||
isMoveTerrainCancelled(user: Pokemon, targets: BattlerIndex[], move: Move): boolean {
|
||||
switch (this.terrainType) {
|
||||
case TerrainType.PSYCHIC:
|
||||
if (!move.hasAttr(ProtectAttr)) {
|
||||
const priority = new Utils.IntegerHolder(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
|
||||
return priority.value > 0 && user.getOpponents().some(o => targets.includes(o.getBattlerIndex()) && o.isGrounded());
|
||||
}
|
||||
case TerrainType.PSYCHIC:
|
||||
if (!move.hasAttr(ProtectAttr)) {
|
||||
const priority = new Utils.IntegerHolder(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
|
||||
return priority.value > 0 && user.getOpponents().some(o => targets.includes(o.getBattlerIndex()) && o.isGrounded());
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -71,14 +71,14 @@ export class Terrain {
|
|||
|
||||
export function getTerrainName(terrainType: TerrainType): string {
|
||||
switch (terrainType) {
|
||||
case TerrainType.MISTY:
|
||||
return i18next.t("terrain:misty");
|
||||
case TerrainType.ELECTRIC:
|
||||
return i18next.t("terrain:electric");
|
||||
case TerrainType.GRASSY:
|
||||
return i18next.t("terrain:grassy");
|
||||
case TerrainType.PSYCHIC:
|
||||
return i18next.t("terrain:psychic");
|
||||
case TerrainType.MISTY:
|
||||
return i18next.t("terrain:misty");
|
||||
case TerrainType.ELECTRIC:
|
||||
return i18next.t("terrain:electric");
|
||||
case TerrainType.GRASSY:
|
||||
return i18next.t("terrain:grassy");
|
||||
case TerrainType.PSYCHIC:
|
||||
return i18next.t("terrain:psychic");
|
||||
}
|
||||
|
||||
return "";
|
||||
|
@ -87,14 +87,14 @@ export function getTerrainName(terrainType: TerrainType): string {
|
|||
|
||||
export function getTerrainColor(terrainType: TerrainType): [ integer, integer, integer ] {
|
||||
switch (terrainType) {
|
||||
case TerrainType.MISTY:
|
||||
return [ 232, 136, 200 ];
|
||||
case TerrainType.ELECTRIC:
|
||||
return [ 248, 248, 120 ];
|
||||
case TerrainType.GRASSY:
|
||||
return [ 120, 200, 80 ];
|
||||
case TerrainType.PSYCHIC:
|
||||
return [ 160, 64, 160 ];
|
||||
case TerrainType.MISTY:
|
||||
return [ 232, 136, 200 ];
|
||||
case TerrainType.ELECTRIC:
|
||||
return [ 248, 248, 120 ];
|
||||
case TerrainType.GRASSY:
|
||||
return [ 120, 200, 80 ];
|
||||
case TerrainType.PSYCHIC:
|
||||
return [ 160, 64, 160 ];
|
||||
}
|
||||
|
||||
return [ 0, 0, 0 ];
|
||||
|
|
|
@ -299,65 +299,65 @@ export class TrainerConfig {
|
|||
getDerivedType(trainerTypeToDeriveFrom: TrainerType | null = null): TrainerType {
|
||||
let trainerType = trainerTypeToDeriveFrom ? trainerTypeToDeriveFrom : this.trainerType;
|
||||
switch (trainerType) {
|
||||
case TrainerType.RIVAL_2:
|
||||
case TrainerType.RIVAL_3:
|
||||
case TrainerType.RIVAL_4:
|
||||
case TrainerType.RIVAL_5:
|
||||
case TrainerType.RIVAL_6:
|
||||
trainerType = TrainerType.RIVAL;
|
||||
break;
|
||||
case TrainerType.LANCE_CHAMPION:
|
||||
trainerType = TrainerType.LANCE;
|
||||
break;
|
||||
case TrainerType.LARRY_ELITE:
|
||||
trainerType = TrainerType.LARRY;
|
||||
break;
|
||||
case TrainerType.ROCKET_BOSS_GIOVANNI_1:
|
||||
case TrainerType.ROCKET_BOSS_GIOVANNI_2:
|
||||
trainerType = TrainerType.GIOVANNI;
|
||||
break;
|
||||
case TrainerType.MAXIE_2:
|
||||
trainerType = TrainerType.MAXIE;
|
||||
break;
|
||||
case TrainerType.ARCHIE_2:
|
||||
trainerType = TrainerType.ARCHIE;
|
||||
break;
|
||||
case TrainerType.CYRUS_2:
|
||||
trainerType = TrainerType.CYRUS;
|
||||
break;
|
||||
case TrainerType.GHETSIS_2:
|
||||
trainerType = TrainerType.GHETSIS;
|
||||
break;
|
||||
case TrainerType.LYSANDRE_2:
|
||||
trainerType = TrainerType.LYSANDRE;
|
||||
break;
|
||||
case TrainerType.LUSAMINE_2:
|
||||
trainerType = TrainerType.LUSAMINE;
|
||||
break;
|
||||
case TrainerType.GUZMA_2:
|
||||
trainerType = TrainerType.GUZMA;
|
||||
break;
|
||||
case TrainerType.ROSE_2:
|
||||
trainerType = TrainerType.ROSE;
|
||||
break;
|
||||
case TrainerType.PENNY_2:
|
||||
trainerType = TrainerType.PENNY;
|
||||
break;
|
||||
case TrainerType.MARNIE_ELITE:
|
||||
trainerType = TrainerType.MARNIE;
|
||||
break;
|
||||
case TrainerType.NESSA_ELITE:
|
||||
trainerType = TrainerType.NESSA;
|
||||
break;
|
||||
case TrainerType.BEA_ELITE:
|
||||
trainerType = TrainerType.BEA;
|
||||
break;
|
||||
case TrainerType.ALLISTER_ELITE:
|
||||
trainerType = TrainerType.ALLISTER;
|
||||
break;
|
||||
case TrainerType.RAIHAN_ELITE:
|
||||
trainerType = TrainerType.RAIHAN;
|
||||
break;
|
||||
case TrainerType.RIVAL_2:
|
||||
case TrainerType.RIVAL_3:
|
||||
case TrainerType.RIVAL_4:
|
||||
case TrainerType.RIVAL_5:
|
||||
case TrainerType.RIVAL_6:
|
||||
trainerType = TrainerType.RIVAL;
|
||||
break;
|
||||
case TrainerType.LANCE_CHAMPION:
|
||||
trainerType = TrainerType.LANCE;
|
||||
break;
|
||||
case TrainerType.LARRY_ELITE:
|
||||
trainerType = TrainerType.LARRY;
|
||||
break;
|
||||
case TrainerType.ROCKET_BOSS_GIOVANNI_1:
|
||||
case TrainerType.ROCKET_BOSS_GIOVANNI_2:
|
||||
trainerType = TrainerType.GIOVANNI;
|
||||
break;
|
||||
case TrainerType.MAXIE_2:
|
||||
trainerType = TrainerType.MAXIE;
|
||||
break;
|
||||
case TrainerType.ARCHIE_2:
|
||||
trainerType = TrainerType.ARCHIE;
|
||||
break;
|
||||
case TrainerType.CYRUS_2:
|
||||
trainerType = TrainerType.CYRUS;
|
||||
break;
|
||||
case TrainerType.GHETSIS_2:
|
||||
trainerType = TrainerType.GHETSIS;
|
||||
break;
|
||||
case TrainerType.LYSANDRE_2:
|
||||
trainerType = TrainerType.LYSANDRE;
|
||||
break;
|
||||
case TrainerType.LUSAMINE_2:
|
||||
trainerType = TrainerType.LUSAMINE;
|
||||
break;
|
||||
case TrainerType.GUZMA_2:
|
||||
trainerType = TrainerType.GUZMA;
|
||||
break;
|
||||
case TrainerType.ROSE_2:
|
||||
trainerType = TrainerType.ROSE;
|
||||
break;
|
||||
case TrainerType.PENNY_2:
|
||||
trainerType = TrainerType.PENNY;
|
||||
break;
|
||||
case TrainerType.MARNIE_ELITE:
|
||||
trainerType = TrainerType.MARNIE;
|
||||
break;
|
||||
case TrainerType.NESSA_ELITE:
|
||||
trainerType = TrainerType.NESSA;
|
||||
break;
|
||||
case TrainerType.BEA_ELITE:
|
||||
trainerType = TrainerType.BEA;
|
||||
break;
|
||||
case TrainerType.ALLISTER_ELITE:
|
||||
trainerType = TrainerType.ALLISTER;
|
||||
break;
|
||||
case TrainerType.RAIHAN_ELITE:
|
||||
trainerType = TrainerType.RAIHAN;
|
||||
break;
|
||||
}
|
||||
|
||||
return trainerType;
|
||||
|
@ -564,104 +564,104 @@ export class TrainerConfig {
|
|||
speciesPoolPerEvilTeamAdmin(team): TrainerTierPools {
|
||||
team = team.toLowerCase();
|
||||
switch (team) {
|
||||
case "rocket": {
|
||||
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.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 ]
|
||||
};
|
||||
}
|
||||
case "magma": {
|
||||
return {
|
||||
[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.RARE]: [ Species.CAPSAKID, Species.CHARCADET ]
|
||||
};
|
||||
}
|
||||
case "aqua": {
|
||||
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.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 ]
|
||||
};
|
||||
}
|
||||
case "galactic": {
|
||||
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.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 ]
|
||||
};
|
||||
}
|
||||
case "plasma": {
|
||||
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.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 ]
|
||||
};
|
||||
}
|
||||
case "flare": {
|
||||
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.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 ]
|
||||
};
|
||||
}
|
||||
case "aether": {
|
||||
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.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 ]
|
||||
};
|
||||
}
|
||||
case "skull": {
|
||||
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.UNCOMMON]: [ Species.GALAR_SLOWPOKE, Species.SKORUPI, Species.PALDEA_WOOPER, Species.VULLABY, Species.HISUI_QWILFISH, Species.GLIMMET ],
|
||||
[TrainerPoolTier.RARE]: [ Species.SKRELP, Species.HISUI_SNEASEL ]
|
||||
};
|
||||
}
|
||||
case "macro": {
|
||||
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.UNCOMMON]: [ Species.VULLABY, Species.MAREANIE, Species.ALOLA_VULPIX, Species.TOGEPI, Species.GALAR_CORSOLA, Species.APPLIN ],
|
||||
[TrainerPoolTier.RARE]: [ Species.TINKATINK, Species.HISUI_LILLIGANT ]
|
||||
};
|
||||
}
|
||||
case "star_1": {
|
||||
return {
|
||||
[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.RARE]: [ Species.DEINO, Species.SPRIGATITO ]
|
||||
};
|
||||
}
|
||||
case "star_2": {
|
||||
return {
|
||||
[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.RARE]: [ Species.LARVESTA, Species.FUECOCO ]
|
||||
};
|
||||
}
|
||||
case "star_3": {
|
||||
return {
|
||||
[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.RARE]: [ Species.GLIMMET, Species.BULBASAUR ]
|
||||
};
|
||||
}
|
||||
case "star_4": {
|
||||
return {
|
||||
[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.RARE]: [ Species.GALAR_PONYTA, Species.POPPLIO ]
|
||||
};
|
||||
}
|
||||
case "star_5": {
|
||||
return {
|
||||
[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.RARE]: [ Species.JANGMO_O, Species.QUAXLY ]
|
||||
};
|
||||
}
|
||||
case "rocket": {
|
||||
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.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 ]
|
||||
};
|
||||
}
|
||||
case "magma": {
|
||||
return {
|
||||
[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.RARE]: [ Species.CAPSAKID, Species.CHARCADET ]
|
||||
};
|
||||
}
|
||||
case "aqua": {
|
||||
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.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 ]
|
||||
};
|
||||
}
|
||||
case "galactic": {
|
||||
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.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 ]
|
||||
};
|
||||
}
|
||||
case "plasma": {
|
||||
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.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 ]
|
||||
};
|
||||
}
|
||||
case "flare": {
|
||||
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.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 ]
|
||||
};
|
||||
}
|
||||
case "aether": {
|
||||
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.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 ]
|
||||
};
|
||||
}
|
||||
case "skull": {
|
||||
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.UNCOMMON]: [ Species.GALAR_SLOWPOKE, Species.SKORUPI, Species.PALDEA_WOOPER, Species.VULLABY, Species.HISUI_QWILFISH, Species.GLIMMET ],
|
||||
[TrainerPoolTier.RARE]: [ Species.SKRELP, Species.HISUI_SNEASEL ]
|
||||
};
|
||||
}
|
||||
case "macro": {
|
||||
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.UNCOMMON]: [ Species.VULLABY, Species.MAREANIE, Species.ALOLA_VULPIX, Species.TOGEPI, Species.GALAR_CORSOLA, Species.APPLIN ],
|
||||
[TrainerPoolTier.RARE]: [ Species.TINKATINK, Species.HISUI_LILLIGANT ]
|
||||
};
|
||||
}
|
||||
case "star_1": {
|
||||
return {
|
||||
[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.RARE]: [ Species.DEINO, Species.SPRIGATITO ]
|
||||
};
|
||||
}
|
||||
case "star_2": {
|
||||
return {
|
||||
[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.RARE]: [ Species.LARVESTA, Species.FUECOCO ]
|
||||
};
|
||||
}
|
||||
case "star_3": {
|
||||
return {
|
||||
[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.RARE]: [ Species.GLIMMET, Species.BULBASAUR ]
|
||||
};
|
||||
}
|
||||
case "star_4": {
|
||||
return {
|
||||
[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.RARE]: [ Species.GALAR_PONYTA, Species.POPPLIO ]
|
||||
};
|
||||
}
|
||||
case "star_5": {
|
||||
return {
|
||||
[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.RARE]: [ Species.JANGMO_O, Species.QUAXLY ]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
console.warn(`Evil team admin for ${team} not found. Returning empty species pools.`);
|
||||
|
|
628
src/data/type.ts
|
@ -29,260 +29,260 @@ export function getTypeDamageMultiplier(attackType: Type, defType: Type): TypeDa
|
|||
}
|
||||
|
||||
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.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;
|
||||
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:
|
||||
case Type.GRASS:
|
||||
return 0.5;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
case Type.GHOST:
|
||||
switch (attackType) {
|
||||
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.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.DARK:
|
||||
return 2;
|
||||
case Type.POISON:
|
||||
case Type.BUG:
|
||||
return 0.5;
|
||||
case Type.NORMAL:
|
||||
case Type.FIGHTING:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
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:
|
||||
switch (attackType) {
|
||||
case Type.GHOST:
|
||||
case Type.DARK:
|
||||
return 2;
|
||||
case Type.POISON:
|
||||
case Type.BUG:
|
||||
return 0.5;
|
||||
case Type.NORMAL:
|
||||
case Type.FIGHTING:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
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:
|
||||
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:
|
||||
return 2;
|
||||
case Type.FIGHTING:
|
||||
case Type.PSYCHIC:
|
||||
return 0.5;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
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.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:
|
||||
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:
|
||||
switch (attackType) {
|
||||
case Type.ICE:
|
||||
case Type.DRAGON:
|
||||
case Type.FAIRY:
|
||||
return 2;
|
||||
case Type.FIRE:
|
||||
case Type.WATER:
|
||||
case Type.GRASS:
|
||||
case Type.ELECTRIC:
|
||||
return 0.5;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
case Type.DARK:
|
||||
return 2;
|
||||
case Type.FIGHTING:
|
||||
case Type.PSYCHIC:
|
||||
return 0.5;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
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:
|
||||
switch (attackType) {
|
||||
case Type.ICE:
|
||||
case Type.DRAGON:
|
||||
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:
|
||||
return 2;
|
||||
case Type.FIRE:
|
||||
case Type.WATER:
|
||||
case Type.GRASS:
|
||||
case Type.ELECTRIC:
|
||||
return 0.5;
|
||||
default:
|
||||
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;
|
||||
}
|
||||
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;
|
||||
|
@ -295,86 +295,86 @@ export function getTypeDamageMultiplier(attackType: Type, defType: Type): TypeDa
|
|||
export function getTypeDamageMultiplierColor(multiplier: TypeDamageMultiplier, side: "defense" | "offense"): string | undefined {
|
||||
if (side === "offense") {
|
||||
switch (multiplier) {
|
||||
case 0:
|
||||
return "#929292";
|
||||
case 0.125:
|
||||
return "#FF5500";
|
||||
case 0.25:
|
||||
return "#FF7400";
|
||||
case 0.5:
|
||||
return "#FE8E00";
|
||||
case 1:
|
||||
return undefined;
|
||||
case 2:
|
||||
return "#4AA500";
|
||||
case 4:
|
||||
return "#4BB400";
|
||||
case 8:
|
||||
return "#52C200";
|
||||
case 0:
|
||||
return "#929292";
|
||||
case 0.125:
|
||||
return "#FF5500";
|
||||
case 0.25:
|
||||
return "#FF7400";
|
||||
case 0.5:
|
||||
return "#FE8E00";
|
||||
case 1:
|
||||
return undefined;
|
||||
case 2:
|
||||
return "#4AA500";
|
||||
case 4:
|
||||
return "#4BB400";
|
||||
case 8:
|
||||
return "#52C200";
|
||||
}
|
||||
} else if (side === "defense") {
|
||||
switch (multiplier) {
|
||||
case 0:
|
||||
return "#B1B100";
|
||||
case 0.125:
|
||||
return "#2DB4FF";
|
||||
case 0.25:
|
||||
return "#00A4FF";
|
||||
case 0.5:
|
||||
return "#0093FF";
|
||||
case 1:
|
||||
return undefined;
|
||||
case 2:
|
||||
return "#FE8E00";
|
||||
case 4:
|
||||
return "#FF7400";
|
||||
case 8:
|
||||
return "#FF5500";
|
||||
case 0:
|
||||
return "#B1B100";
|
||||
case 0.125:
|
||||
return "#2DB4FF";
|
||||
case 0.25:
|
||||
return "#00A4FF";
|
||||
case 0.5:
|
||||
return "#0093FF";
|
||||
case 1:
|
||||
return undefined;
|
||||
case 2:
|
||||
return "#FE8E00";
|
||||
case 4:
|
||||
return "#FF7400";
|
||||
case 8:
|
||||
return "#FF5500";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getTypeRgb(type: Type): [ integer, integer, integer ] {
|
||||
switch (type) {
|
||||
case Type.NORMAL:
|
||||
return [ 168, 168, 120 ];
|
||||
case Type.FIGHTING:
|
||||
return [ 192, 48, 40 ];
|
||||
case Type.FLYING:
|
||||
return [ 168, 144, 240 ];
|
||||
case Type.POISON:
|
||||
return [ 160, 64, 160 ];
|
||||
case Type.GROUND:
|
||||
return [ 224, 192, 104 ];
|
||||
case Type.ROCK:
|
||||
return [ 184, 160, 56 ];
|
||||
case Type.BUG:
|
||||
return [ 168, 184, 32 ];
|
||||
case Type.GHOST:
|
||||
return [ 112, 88, 152 ];
|
||||
case Type.STEEL:
|
||||
return [ 184, 184, 208 ];
|
||||
case Type.FIRE:
|
||||
return [ 240, 128, 48 ];
|
||||
case Type.WATER:
|
||||
return [ 104, 144, 240 ];
|
||||
case Type.GRASS:
|
||||
return [ 120, 200, 80 ];
|
||||
case Type.ELECTRIC:
|
||||
return [ 248, 208, 48 ];
|
||||
case Type.PSYCHIC:
|
||||
return [ 248, 88, 136 ];
|
||||
case Type.ICE:
|
||||
return [ 152, 216, 216 ];
|
||||
case Type.DRAGON:
|
||||
return [ 112, 56, 248 ];
|
||||
case Type.DARK:
|
||||
return [ 112, 88, 72 ];
|
||||
case Type.FAIRY:
|
||||
return [ 232, 136, 200 ];
|
||||
case Type.STELLAR:
|
||||
return [ 255, 255, 255 ];
|
||||
default:
|
||||
return [ 0, 0, 0 ];
|
||||
case Type.NORMAL:
|
||||
return [ 168, 168, 120 ];
|
||||
case Type.FIGHTING:
|
||||
return [ 192, 48, 40 ];
|
||||
case Type.FLYING:
|
||||
return [ 168, 144, 240 ];
|
||||
case Type.POISON:
|
||||
return [ 160, 64, 160 ];
|
||||
case Type.GROUND:
|
||||
return [ 224, 192, 104 ];
|
||||
case Type.ROCK:
|
||||
return [ 184, 160, 56 ];
|
||||
case Type.BUG:
|
||||
return [ 168, 184, 32 ];
|
||||
case Type.GHOST:
|
||||
return [ 112, 88, 152 ];
|
||||
case Type.STEEL:
|
||||
return [ 184, 184, 208 ];
|
||||
case Type.FIRE:
|
||||
return [ 240, 128, 48 ];
|
||||
case Type.WATER:
|
||||
return [ 104, 144, 240 ];
|
||||
case Type.GRASS:
|
||||
return [ 120, 200, 80 ];
|
||||
case Type.ELECTRIC:
|
||||
return [ 248, 208, 48 ];
|
||||
case Type.PSYCHIC:
|
||||
return [ 248, 88, 136 ];
|
||||
case Type.ICE:
|
||||
return [ 152, 216, 216 ];
|
||||
case Type.DRAGON:
|
||||
return [ 112, 56, 248 ];
|
||||
case Type.DARK:
|
||||
return [ 112, 88, 72 ];
|
||||
case Type.FAIRY:
|
||||
return [ 232, 136, 200 ];
|
||||
case Type.STELLAR:
|
||||
return [ 255, 255, 255 ];
|
||||
default:
|
||||
return [ 0, 0, 0 ];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,22 +10,22 @@ export const variantColorCache = {};
|
|||
|
||||
export function getVariantTint(variant: Variant): integer {
|
||||
switch (variant) {
|
||||
case 0:
|
||||
return 0xf8c020;
|
||||
case 1:
|
||||
return 0x20f8f0;
|
||||
case 2:
|
||||
return 0xe81048;
|
||||
case 0:
|
||||
return 0xf8c020;
|
||||
case 1:
|
||||
return 0x20f8f0;
|
||||
case 2:
|
||||
return 0xe81048;
|
||||
}
|
||||
}
|
||||
|
||||
export function getVariantIcon(variant: Variant): integer {
|
||||
switch (variant) {
|
||||
case 0:
|
||||
return VariantTier.STANDARD;
|
||||
case 1:
|
||||
return VariantTier.RARE;
|
||||
case 2:
|
||||
return VariantTier.EPIC;
|
||||
case 0:
|
||||
return VariantTier.STANDARD;
|
||||
case 1:
|
||||
return VariantTier.RARE;
|
||||
case 2:
|
||||
return VariantTier.EPIC;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,10 +33,10 @@ export class Weather {
|
|||
|
||||
isImmutable(): boolean {
|
||||
switch (this.weatherType) {
|
||||
case WeatherType.HEAVY_RAIN:
|
||||
case WeatherType.HARSH_SUN:
|
||||
case WeatherType.STRONG_WINDS:
|
||||
return true;
|
||||
case WeatherType.HEAVY_RAIN:
|
||||
case WeatherType.HARSH_SUN:
|
||||
case WeatherType.STRONG_WINDS:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -44,9 +44,9 @@ export class Weather {
|
|||
|
||||
isDamaging(): boolean {
|
||||
switch (this.weatherType) {
|
||||
case WeatherType.SANDSTORM:
|
||||
case WeatherType.HAIL:
|
||||
return true;
|
||||
case WeatherType.SANDSTORM:
|
||||
case WeatherType.HAIL:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -54,10 +54,10 @@ export class Weather {
|
|||
|
||||
isTypeDamageImmune(type: Type): boolean {
|
||||
switch (this.weatherType) {
|
||||
case WeatherType.SANDSTORM:
|
||||
return type === Type.GROUND || type === Type.ROCK || type === Type.STEEL;
|
||||
case WeatherType.HAIL:
|
||||
return type === Type.ICE;
|
||||
case WeatherType.SANDSTORM:
|
||||
return type === Type.GROUND || type === Type.ROCK || type === Type.STEEL;
|
||||
case WeatherType.HAIL:
|
||||
return type === Type.ICE;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -65,24 +65,24 @@ export class Weather {
|
|||
|
||||
getAttackTypeMultiplier(attackType: Type): number {
|
||||
switch (this.weatherType) {
|
||||
case WeatherType.SUNNY:
|
||||
case WeatherType.HARSH_SUN:
|
||||
if (attackType === Type.FIRE) {
|
||||
return 1.5;
|
||||
}
|
||||
if (attackType === Type.WATER) {
|
||||
return 0.5;
|
||||
}
|
||||
break;
|
||||
case WeatherType.RAIN:
|
||||
case WeatherType.HEAVY_RAIN:
|
||||
if (attackType === Type.FIRE) {
|
||||
return 0.5;
|
||||
}
|
||||
if (attackType === Type.WATER) {
|
||||
return 1.5;
|
||||
}
|
||||
break;
|
||||
case WeatherType.SUNNY:
|
||||
case WeatherType.HARSH_SUN:
|
||||
if (attackType === Type.FIRE) {
|
||||
return 1.5;
|
||||
}
|
||||
if (attackType === Type.WATER) {
|
||||
return 0.5;
|
||||
}
|
||||
break;
|
||||
case WeatherType.RAIN:
|
||||
case WeatherType.HEAVY_RAIN:
|
||||
if (attackType === Type.FIRE) {
|
||||
return 0.5;
|
||||
}
|
||||
if (attackType === Type.WATER) {
|
||||
return 1.5;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -92,10 +92,10 @@ export class Weather {
|
|||
const moveType = user.getMoveType(move);
|
||||
|
||||
switch (this.weatherType) {
|
||||
case WeatherType.HARSH_SUN:
|
||||
return move instanceof AttackMove && moveType === Type.WATER;
|
||||
case WeatherType.HEAVY_RAIN:
|
||||
return move instanceof AttackMove && moveType === Type.FIRE;
|
||||
case WeatherType.HARSH_SUN:
|
||||
return move instanceof AttackMove && moveType === Type.WATER;
|
||||
case WeatherType.HEAVY_RAIN:
|
||||
return move instanceof AttackMove && moveType === Type.FIRE;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -120,24 +120,24 @@ export class Weather {
|
|||
|
||||
export function getWeatherStartMessage(weatherType: WeatherType): string | null {
|
||||
switch (weatherType) {
|
||||
case WeatherType.SUNNY:
|
||||
return i18next.t("weather:sunnyStartMessage");
|
||||
case WeatherType.RAIN:
|
||||
return i18next.t("weather:rainStartMessage");
|
||||
case WeatherType.SANDSTORM:
|
||||
return i18next.t("weather:sandstormStartMessage");
|
||||
case WeatherType.HAIL:
|
||||
return i18next.t("weather:hailStartMessage");
|
||||
case WeatherType.SNOW:
|
||||
return i18next.t("weather:snowStartMessage");
|
||||
case WeatherType.FOG:
|
||||
return i18next.t("weather:fogStartMessage");
|
||||
case WeatherType.HEAVY_RAIN:
|
||||
return i18next.t("weather:heavyRainStartMessage");
|
||||
case WeatherType.HARSH_SUN:
|
||||
return i18next.t("weather:harshSunStartMessage");
|
||||
case WeatherType.STRONG_WINDS:
|
||||
return i18next.t("weather:strongWindsStartMessage");
|
||||
case WeatherType.SUNNY:
|
||||
return i18next.t("weather:sunnyStartMessage");
|
||||
case WeatherType.RAIN:
|
||||
return i18next.t("weather:rainStartMessage");
|
||||
case WeatherType.SANDSTORM:
|
||||
return i18next.t("weather:sandstormStartMessage");
|
||||
case WeatherType.HAIL:
|
||||
return i18next.t("weather:hailStartMessage");
|
||||
case WeatherType.SNOW:
|
||||
return i18next.t("weather:snowStartMessage");
|
||||
case WeatherType.FOG:
|
||||
return i18next.t("weather:fogStartMessage");
|
||||
case WeatherType.HEAVY_RAIN:
|
||||
return i18next.t("weather:heavyRainStartMessage");
|
||||
case WeatherType.HARSH_SUN:
|
||||
return i18next.t("weather:harshSunStartMessage");
|
||||
case WeatherType.STRONG_WINDS:
|
||||
return i18next.t("weather:strongWindsStartMessage");
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -145,24 +145,24 @@ export function getWeatherStartMessage(weatherType: WeatherType): string | null
|
|||
|
||||
export function getWeatherLapseMessage(weatherType: WeatherType): string | null {
|
||||
switch (weatherType) {
|
||||
case WeatherType.SUNNY:
|
||||
return i18next.t("weather:sunnyLapseMessage");
|
||||
case WeatherType.RAIN:
|
||||
return i18next.t("weather:rainLapseMessage");
|
||||
case WeatherType.SANDSTORM:
|
||||
return i18next.t("weather:sandstormLapseMessage");
|
||||
case WeatherType.HAIL:
|
||||
return i18next.t("weather:hailLapseMessage");
|
||||
case WeatherType.SNOW:
|
||||
return i18next.t("weather:snowLapseMessage");
|
||||
case WeatherType.FOG:
|
||||
return i18next.t("weather:fogLapseMessage");
|
||||
case WeatherType.HEAVY_RAIN:
|
||||
return i18next.t("weather:heavyRainLapseMessage");
|
||||
case WeatherType.HARSH_SUN:
|
||||
return i18next.t("weather:harshSunLapseMessage");
|
||||
case WeatherType.STRONG_WINDS:
|
||||
return i18next.t("weather:strongWindsLapseMessage");
|
||||
case WeatherType.SUNNY:
|
||||
return i18next.t("weather:sunnyLapseMessage");
|
||||
case WeatherType.RAIN:
|
||||
return i18next.t("weather:rainLapseMessage");
|
||||
case WeatherType.SANDSTORM:
|
||||
return i18next.t("weather:sandstormLapseMessage");
|
||||
case WeatherType.HAIL:
|
||||
return i18next.t("weather:hailLapseMessage");
|
||||
case WeatherType.SNOW:
|
||||
return i18next.t("weather:snowLapseMessage");
|
||||
case WeatherType.FOG:
|
||||
return i18next.t("weather:fogLapseMessage");
|
||||
case WeatherType.HEAVY_RAIN:
|
||||
return i18next.t("weather:heavyRainLapseMessage");
|
||||
case WeatherType.HARSH_SUN:
|
||||
return i18next.t("weather:harshSunLapseMessage");
|
||||
case WeatherType.STRONG_WINDS:
|
||||
return i18next.t("weather:strongWindsLapseMessage");
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -170,10 +170,10 @@ export function getWeatherLapseMessage(weatherType: WeatherType): string | null
|
|||
|
||||
export function getWeatherDamageMessage(weatherType: WeatherType, pokemon: Pokemon): string | null {
|
||||
switch (weatherType) {
|
||||
case WeatherType.SANDSTORM:
|
||||
return i18next.t("weather:sandstormDamageMessage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) });
|
||||
case WeatherType.HAIL:
|
||||
return i18next.t("weather:hailDamageMessage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) });
|
||||
case WeatherType.SANDSTORM:
|
||||
return i18next.t("weather:sandstormDamageMessage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) });
|
||||
case WeatherType.HAIL:
|
||||
return i18next.t("weather:hailDamageMessage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) });
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -181,24 +181,24 @@ export function getWeatherDamageMessage(weatherType: WeatherType, pokemon: Pokem
|
|||
|
||||
export function getWeatherClearMessage(weatherType: WeatherType): string | null {
|
||||
switch (weatherType) {
|
||||
case WeatherType.SUNNY:
|
||||
return i18next.t("weather:sunnyClearMessage");
|
||||
case WeatherType.RAIN:
|
||||
return i18next.t("weather:rainClearMessage");
|
||||
case WeatherType.SANDSTORM:
|
||||
return i18next.t("weather:sandstormClearMessage");
|
||||
case WeatherType.HAIL:
|
||||
return i18next.t("weather:hailClearMessage");
|
||||
case WeatherType.SNOW:
|
||||
return i18next.t("weather:snowClearMessage");
|
||||
case WeatherType.FOG:
|
||||
return i18next.t("weather:fogClearMessage");
|
||||
case WeatherType.HEAVY_RAIN:
|
||||
return i18next.t("weather:heavyRainClearMessage");
|
||||
case WeatherType.HARSH_SUN:
|
||||
return i18next.t("weather:harshSunClearMessage");
|
||||
case WeatherType.STRONG_WINDS:
|
||||
return i18next.t("weather:strongWindsClearMessage");
|
||||
case WeatherType.SUNNY:
|
||||
return i18next.t("weather:sunnyClearMessage");
|
||||
case WeatherType.RAIN:
|
||||
return i18next.t("weather:rainClearMessage");
|
||||
case WeatherType.SANDSTORM:
|
||||
return i18next.t("weather:sandstormClearMessage");
|
||||
case WeatherType.HAIL:
|
||||
return i18next.t("weather:hailClearMessage");
|
||||
case WeatherType.SNOW:
|
||||
return i18next.t("weather:snowClearMessage");
|
||||
case WeatherType.FOG:
|
||||
return i18next.t("weather:fogClearMessage");
|
||||
case WeatherType.HEAVY_RAIN:
|
||||
return i18next.t("weather:heavyRainClearMessage");
|
||||
case WeatherType.HARSH_SUN:
|
||||
return i18next.t("weather:harshSunClearMessage");
|
||||
case WeatherType.STRONG_WINDS:
|
||||
return i18next.t("weather:strongWindsClearMessage");
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -206,33 +206,33 @@ export function getWeatherClearMessage(weatherType: WeatherType): string | null
|
|||
|
||||
export function getTerrainStartMessage(terrainType: TerrainType): string | null {
|
||||
switch (terrainType) {
|
||||
case TerrainType.MISTY:
|
||||
return i18next.t("terrain:mistyStartMessage");
|
||||
case TerrainType.ELECTRIC:
|
||||
return i18next.t("terrain:electricStartMessage");
|
||||
case TerrainType.GRASSY:
|
||||
return i18next.t("terrain:grassyStartMessage");
|
||||
case TerrainType.PSYCHIC:
|
||||
return i18next.t("terrain:psychicStartMessage");
|
||||
default:
|
||||
console.warn("getTerrainStartMessage not defined. Using default null");
|
||||
return null;
|
||||
case TerrainType.MISTY:
|
||||
return i18next.t("terrain:mistyStartMessage");
|
||||
case TerrainType.ELECTRIC:
|
||||
return i18next.t("terrain:electricStartMessage");
|
||||
case TerrainType.GRASSY:
|
||||
return i18next.t("terrain:grassyStartMessage");
|
||||
case TerrainType.PSYCHIC:
|
||||
return i18next.t("terrain:psychicStartMessage");
|
||||
default:
|
||||
console.warn("getTerrainStartMessage not defined. Using default null");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function getTerrainClearMessage(terrainType: TerrainType): string | null {
|
||||
switch (terrainType) {
|
||||
case TerrainType.MISTY:
|
||||
return i18next.t("terrain:mistyClearMessage");
|
||||
case TerrainType.ELECTRIC:
|
||||
return i18next.t("terrain:electricClearMessage");
|
||||
case TerrainType.GRASSY:
|
||||
return i18next.t("terrain:grassyClearMessage");
|
||||
case TerrainType.PSYCHIC:
|
||||
return i18next.t("terrain:psychicClearMessage");
|
||||
default:
|
||||
console.warn("getTerrainClearMessage not defined. Using default null");
|
||||
return null;
|
||||
case TerrainType.MISTY:
|
||||
return i18next.t("terrain:mistyClearMessage");
|
||||
case TerrainType.ELECTRIC:
|
||||
return i18next.t("terrain:electricClearMessage");
|
||||
case TerrainType.GRASSY:
|
||||
return i18next.t("terrain:grassyClearMessage");
|
||||
case TerrainType.PSYCHIC:
|
||||
return i18next.t("terrain:psychicClearMessage");
|
||||
default:
|
||||
console.warn("getTerrainClearMessage not defined. Using default null");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -252,126 +252,126 @@ export function getRandomWeatherType(arena: any /* Importing from arena causes a
|
|||
let weatherPool: WeatherPoolEntry[] = [];
|
||||
const hasSun = arena.getTimeOfDay() < 2;
|
||||
switch (arena.biomeType) {
|
||||
case Biome.GRASS:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 7 }
|
||||
];
|
||||
if (hasSun) {
|
||||
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 3 });
|
||||
}
|
||||
break;
|
||||
case Biome.TALL_GRASS:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 8 },
|
||||
{ weatherType: WeatherType.RAIN, weight: 5 },
|
||||
];
|
||||
if (hasSun) {
|
||||
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 8 });
|
||||
}
|
||||
break;
|
||||
case Biome.FOREST:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 8 },
|
||||
{ weatherType: WeatherType.RAIN, weight: 5 }
|
||||
];
|
||||
break;
|
||||
case Biome.SEA:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 3 },
|
||||
{ weatherType: WeatherType.RAIN, weight: 12 }
|
||||
];
|
||||
break;
|
||||
case Biome.SWAMP:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 3 },
|
||||
{ weatherType: WeatherType.RAIN, weight: 4 },
|
||||
{ weatherType: WeatherType.FOG, weight: 1 }
|
||||
];
|
||||
break;
|
||||
case Biome.BEACH:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 8 },
|
||||
{ weatherType: WeatherType.RAIN, weight: 3 }
|
||||
];
|
||||
if (hasSun) {
|
||||
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 5 });
|
||||
}
|
||||
break;
|
||||
case Biome.LAKE:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 10 },
|
||||
{ weatherType: WeatherType.RAIN, weight: 5 },
|
||||
{ weatherType: WeatherType.FOG, weight: 1 }
|
||||
];
|
||||
break;
|
||||
case Biome.SEABED:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.RAIN, weight: 1 }
|
||||
];
|
||||
break;
|
||||
case Biome.BADLANDS:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 8 },
|
||||
{ weatherType: WeatherType.SANDSTORM, weight: 2 }
|
||||
];
|
||||
if (hasSun) {
|
||||
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 5 });
|
||||
}
|
||||
break;
|
||||
case Biome.DESERT:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.SANDSTORM, weight: 2 }
|
||||
];
|
||||
if (hasSun) {
|
||||
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 });
|
||||
}
|
||||
break;
|
||||
case Biome.ICE_CAVE:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 3 },
|
||||
{ weatherType: WeatherType.SNOW, weight: 4 },
|
||||
{ weatherType: WeatherType.HAIL, weight: 1 }
|
||||
];
|
||||
break;
|
||||
case Biome.MEADOW:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 2 }
|
||||
];
|
||||
if (hasSun) {
|
||||
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 });
|
||||
}
|
||||
case Biome.VOLCANO:
|
||||
weatherPool = [
|
||||
{ weatherType: hasSun ? WeatherType.SUNNY : WeatherType.NONE, weight: 1 }
|
||||
];
|
||||
break;
|
||||
case Biome.GRAVEYARD:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 3 },
|
||||
{ weatherType: WeatherType.FOG, weight: 1 }
|
||||
];
|
||||
break;
|
||||
case Biome.JUNGLE:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 8 },
|
||||
{ weatherType: WeatherType.RAIN, weight: 2 }
|
||||
];
|
||||
break;
|
||||
case Biome.SNOWY_FOREST:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.SNOW, weight: 7 },
|
||||
{ weatherType: WeatherType.HAIL, weight: 1 }
|
||||
];
|
||||
break;
|
||||
case Biome.ISLAND:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 5 },
|
||||
{ weatherType: WeatherType.RAIN, weight: 1 },
|
||||
];
|
||||
if (hasSun) {
|
||||
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 });
|
||||
}
|
||||
break;
|
||||
case Biome.GRASS:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 7 }
|
||||
];
|
||||
if (hasSun) {
|
||||
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 3 });
|
||||
}
|
||||
break;
|
||||
case Biome.TALL_GRASS:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 8 },
|
||||
{ weatherType: WeatherType.RAIN, weight: 5 },
|
||||
];
|
||||
if (hasSun) {
|
||||
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 8 });
|
||||
}
|
||||
break;
|
||||
case Biome.FOREST:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 8 },
|
||||
{ weatherType: WeatherType.RAIN, weight: 5 }
|
||||
];
|
||||
break;
|
||||
case Biome.SEA:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 3 },
|
||||
{ weatherType: WeatherType.RAIN, weight: 12 }
|
||||
];
|
||||
break;
|
||||
case Biome.SWAMP:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 3 },
|
||||
{ weatherType: WeatherType.RAIN, weight: 4 },
|
||||
{ weatherType: WeatherType.FOG, weight: 1 }
|
||||
];
|
||||
break;
|
||||
case Biome.BEACH:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 8 },
|
||||
{ weatherType: WeatherType.RAIN, weight: 3 }
|
||||
];
|
||||
if (hasSun) {
|
||||
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 5 });
|
||||
}
|
||||
break;
|
||||
case Biome.LAKE:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 10 },
|
||||
{ weatherType: WeatherType.RAIN, weight: 5 },
|
||||
{ weatherType: WeatherType.FOG, weight: 1 }
|
||||
];
|
||||
break;
|
||||
case Biome.SEABED:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.RAIN, weight: 1 }
|
||||
];
|
||||
break;
|
||||
case Biome.BADLANDS:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 8 },
|
||||
{ weatherType: WeatherType.SANDSTORM, weight: 2 }
|
||||
];
|
||||
if (hasSun) {
|
||||
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 5 });
|
||||
}
|
||||
break;
|
||||
case Biome.DESERT:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.SANDSTORM, weight: 2 }
|
||||
];
|
||||
if (hasSun) {
|
||||
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 });
|
||||
}
|
||||
break;
|
||||
case Biome.ICE_CAVE:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 3 },
|
||||
{ weatherType: WeatherType.SNOW, weight: 4 },
|
||||
{ weatherType: WeatherType.HAIL, weight: 1 }
|
||||
];
|
||||
break;
|
||||
case Biome.MEADOW:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 2 }
|
||||
];
|
||||
if (hasSun) {
|
||||
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 });
|
||||
}
|
||||
case Biome.VOLCANO:
|
||||
weatherPool = [
|
||||
{ weatherType: hasSun ? WeatherType.SUNNY : WeatherType.NONE, weight: 1 }
|
||||
];
|
||||
break;
|
||||
case Biome.GRAVEYARD:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 3 },
|
||||
{ weatherType: WeatherType.FOG, weight: 1 }
|
||||
];
|
||||
break;
|
||||
case Biome.JUNGLE:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 8 },
|
||||
{ weatherType: WeatherType.RAIN, weight: 2 }
|
||||
];
|
||||
break;
|
||||
case Biome.SNOWY_FOREST:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.SNOW, weight: 7 },
|
||||
{ weatherType: WeatherType.HAIL, weight: 1 }
|
||||
];
|
||||
break;
|
||||
case Biome.ISLAND:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 5 },
|
||||
{ weatherType: WeatherType.RAIN, weight: 1 },
|
||||
];
|
||||
if (hasSun) {
|
||||
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 });
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (weatherPool.length > 1) {
|
||||
|
|
|
@ -4,21 +4,21 @@ import * as Utils from "../utils";
|
|||
|
||||
export function addPokeballOpenParticles(scene: BattleScene, x: number, y: number, pokeballType: PokeballType): void {
|
||||
switch (pokeballType) {
|
||||
case PokeballType.POKEBALL:
|
||||
doDefaultPbOpenParticles(scene, x, y, 48);
|
||||
break;
|
||||
case PokeballType.GREAT_BALL:
|
||||
doDefaultPbOpenParticles(scene, x, y, 96);
|
||||
break;
|
||||
case PokeballType.ULTRA_BALL:
|
||||
doUbOpenParticles(scene, x, y, 8);
|
||||
break;
|
||||
case PokeballType.ROGUE_BALL:
|
||||
doUbOpenParticles(scene, x, y, 10);
|
||||
break;
|
||||
case PokeballType.MASTER_BALL:
|
||||
doMbOpenParticles(scene, x, y);
|
||||
break;
|
||||
case PokeballType.POKEBALL:
|
||||
doDefaultPbOpenParticles(scene, x, y, 48);
|
||||
break;
|
||||
case PokeballType.GREAT_BALL:
|
||||
doDefaultPbOpenParticles(scene, x, y, 96);
|
||||
break;
|
||||
case PokeballType.ULTRA_BALL:
|
||||
doUbOpenParticles(scene, x, y, 8);
|
||||
break;
|
||||
case PokeballType.ROGUE_BALL:
|
||||
doUbOpenParticles(scene, x, y, 10);
|
||||
break;
|
||||
case PokeballType.MASTER_BALL:
|
||||
doMbOpenParticles(scene, x, y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -129,18 +129,18 @@ export class Arena {
|
|||
|
||||
if (ret.subLegendary || ret.legendary || ret.mythical) {
|
||||
switch (true) {
|
||||
case (ret.baseTotal >= 720):
|
||||
regen = level < 90;
|
||||
break;
|
||||
case (ret.baseTotal >= 670):
|
||||
regen = level < 70;
|
||||
break;
|
||||
case (ret.baseTotal >= 580):
|
||||
regen = level < 50;
|
||||
break;
|
||||
default:
|
||||
regen = level < 30;
|
||||
break;
|
||||
case (ret.baseTotal >= 720):
|
||||
regen = level < 90;
|
||||
break;
|
||||
case (ret.baseTotal >= 670):
|
||||
regen = level < 70;
|
||||
break;
|
||||
case (ret.baseTotal >= 580):
|
||||
regen = level < 50;
|
||||
break;
|
||||
default:
|
||||
regen = level < 30;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -177,41 +177,41 @@ export class Arena {
|
|||
|
||||
getSpeciesFormIndex(species: PokemonSpecies): integer {
|
||||
switch (species.speciesId) {
|
||||
case Species.BURMY:
|
||||
case Species.WORMADAM:
|
||||
switch (this.biomeType) {
|
||||
case Biome.BEACH:
|
||||
return 1;
|
||||
case Biome.SLUM:
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
case Species.ROTOM:
|
||||
switch (this.biomeType) {
|
||||
case Biome.VOLCANO:
|
||||
return 1;
|
||||
case Biome.SEA:
|
||||
return 2;
|
||||
case Biome.ICE_CAVE:
|
||||
return 3;
|
||||
case Biome.MOUNTAIN:
|
||||
return 4;
|
||||
case Biome.TALL_GRASS:
|
||||
return 5;
|
||||
}
|
||||
break;
|
||||
case Species.LYCANROC:
|
||||
const timeOfDay = this.getTimeOfDay();
|
||||
switch (timeOfDay) {
|
||||
case TimeOfDay.DAY:
|
||||
case TimeOfDay.DAWN:
|
||||
return 0;
|
||||
case TimeOfDay.DUSK:
|
||||
return 2;
|
||||
case TimeOfDay.NIGHT:
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case Species.BURMY:
|
||||
case Species.WORMADAM:
|
||||
switch (this.biomeType) {
|
||||
case Biome.BEACH:
|
||||
return 1;
|
||||
case Biome.SLUM:
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
case Species.ROTOM:
|
||||
switch (this.biomeType) {
|
||||
case Biome.VOLCANO:
|
||||
return 1;
|
||||
case Biome.SEA:
|
||||
return 2;
|
||||
case Biome.ICE_CAVE:
|
||||
return 3;
|
||||
case Biome.MOUNTAIN:
|
||||
return 4;
|
||||
case Biome.TALL_GRASS:
|
||||
return 5;
|
||||
}
|
||||
break;
|
||||
case Species.LYCANROC:
|
||||
const timeOfDay = this.getTimeOfDay();
|
||||
switch (timeOfDay) {
|
||||
case TimeOfDay.DAY:
|
||||
case TimeOfDay.DAWN:
|
||||
return 0;
|
||||
case TimeOfDay.DUSK:
|
||||
return 2;
|
||||
case TimeOfDay.NIGHT:
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -219,70 +219,70 @@ export class Arena {
|
|||
|
||||
getTypeForBiome() {
|
||||
switch (this.biomeType) {
|
||||
case Biome.TOWN:
|
||||
case Biome.PLAINS:
|
||||
case Biome.METROPOLIS:
|
||||
return Type.NORMAL;
|
||||
case Biome.GRASS:
|
||||
case Biome.TALL_GRASS:
|
||||
return Type.GRASS;
|
||||
case Biome.FOREST:
|
||||
case Biome.JUNGLE:
|
||||
return Type.BUG;
|
||||
case Biome.SLUM:
|
||||
case Biome.SWAMP:
|
||||
return Type.POISON;
|
||||
case Biome.SEA:
|
||||
case Biome.BEACH:
|
||||
case Biome.LAKE:
|
||||
case Biome.SEABED:
|
||||
return Type.WATER;
|
||||
case Biome.MOUNTAIN:
|
||||
return Type.FLYING;
|
||||
case Biome.BADLANDS:
|
||||
return Type.GROUND;
|
||||
case Biome.CAVE:
|
||||
case Biome.DESERT:
|
||||
return Type.ROCK;
|
||||
case Biome.ICE_CAVE:
|
||||
case Biome.SNOWY_FOREST:
|
||||
return Type.ICE;
|
||||
case Biome.MEADOW:
|
||||
case Biome.FAIRY_CAVE:
|
||||
case Biome.ISLAND:
|
||||
return Type.FAIRY;
|
||||
case Biome.POWER_PLANT:
|
||||
return Type.ELECTRIC;
|
||||
case Biome.VOLCANO:
|
||||
return Type.FIRE;
|
||||
case Biome.GRAVEYARD:
|
||||
case Biome.TEMPLE:
|
||||
return Type.GHOST;
|
||||
case Biome.DOJO:
|
||||
case Biome.CONSTRUCTION_SITE:
|
||||
return Type.FIGHTING;
|
||||
case Biome.FACTORY:
|
||||
case Biome.LABORATORY:
|
||||
return Type.STEEL;
|
||||
case Biome.RUINS:
|
||||
case Biome.SPACE:
|
||||
return Type.PSYCHIC;
|
||||
case Biome.WASTELAND:
|
||||
case Biome.END:
|
||||
return Type.DRAGON;
|
||||
case Biome.ABYSS:
|
||||
return Type.DARK;
|
||||
default:
|
||||
return Type.UNKNOWN;
|
||||
case Biome.TOWN:
|
||||
case Biome.PLAINS:
|
||||
case Biome.METROPOLIS:
|
||||
return Type.NORMAL;
|
||||
case Biome.GRASS:
|
||||
case Biome.TALL_GRASS:
|
||||
return Type.GRASS;
|
||||
case Biome.FOREST:
|
||||
case Biome.JUNGLE:
|
||||
return Type.BUG;
|
||||
case Biome.SLUM:
|
||||
case Biome.SWAMP:
|
||||
return Type.POISON;
|
||||
case Biome.SEA:
|
||||
case Biome.BEACH:
|
||||
case Biome.LAKE:
|
||||
case Biome.SEABED:
|
||||
return Type.WATER;
|
||||
case Biome.MOUNTAIN:
|
||||
return Type.FLYING;
|
||||
case Biome.BADLANDS:
|
||||
return Type.GROUND;
|
||||
case Biome.CAVE:
|
||||
case Biome.DESERT:
|
||||
return Type.ROCK;
|
||||
case Biome.ICE_CAVE:
|
||||
case Biome.SNOWY_FOREST:
|
||||
return Type.ICE;
|
||||
case Biome.MEADOW:
|
||||
case Biome.FAIRY_CAVE:
|
||||
case Biome.ISLAND:
|
||||
return Type.FAIRY;
|
||||
case Biome.POWER_PLANT:
|
||||
return Type.ELECTRIC;
|
||||
case Biome.VOLCANO:
|
||||
return Type.FIRE;
|
||||
case Biome.GRAVEYARD:
|
||||
case Biome.TEMPLE:
|
||||
return Type.GHOST;
|
||||
case Biome.DOJO:
|
||||
case Biome.CONSTRUCTION_SITE:
|
||||
return Type.FIGHTING;
|
||||
case Biome.FACTORY:
|
||||
case Biome.LABORATORY:
|
||||
return Type.STEEL;
|
||||
case Biome.RUINS:
|
||||
case Biome.SPACE:
|
||||
return Type.PSYCHIC;
|
||||
case Biome.WASTELAND:
|
||||
case Biome.END:
|
||||
return Type.DRAGON;
|
||||
case Biome.ABYSS:
|
||||
return Type.DARK;
|
||||
default:
|
||||
return Type.UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
getBgTerrainColorRatioForBiome(): number {
|
||||
switch (this.biomeType) {
|
||||
case Biome.SPACE:
|
||||
return 1;
|
||||
case Biome.END:
|
||||
return 0;
|
||||
case Biome.SPACE:
|
||||
return 1;
|
||||
case Biome.END:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 131 / 180;
|
||||
|
@ -424,52 +424,52 @@ export class Arena {
|
|||
*/
|
||||
getTrainerChance(): integer {
|
||||
switch (this.biomeType) {
|
||||
case Biome.METROPOLIS:
|
||||
return 2;
|
||||
case Biome.SLUM:
|
||||
case Biome.BEACH:
|
||||
case Biome.DOJO:
|
||||
case Biome.CONSTRUCTION_SITE:
|
||||
return 4;
|
||||
case Biome.PLAINS:
|
||||
case Biome.GRASS:
|
||||
case Biome.LAKE:
|
||||
case Biome.CAVE:
|
||||
return 6;
|
||||
case Biome.TALL_GRASS:
|
||||
case Biome.FOREST:
|
||||
case Biome.SEA:
|
||||
case Biome.SWAMP:
|
||||
case Biome.MOUNTAIN:
|
||||
case Biome.BADLANDS:
|
||||
case Biome.DESERT:
|
||||
case Biome.MEADOW:
|
||||
case Biome.POWER_PLANT:
|
||||
case Biome.GRAVEYARD:
|
||||
case Biome.FACTORY:
|
||||
case Biome.SNOWY_FOREST:
|
||||
return 8;
|
||||
case Biome.ICE_CAVE:
|
||||
case Biome.VOLCANO:
|
||||
case Biome.RUINS:
|
||||
case Biome.WASTELAND:
|
||||
case Biome.JUNGLE:
|
||||
case Biome.FAIRY_CAVE:
|
||||
return 12;
|
||||
case Biome.SEABED:
|
||||
case Biome.ABYSS:
|
||||
case Biome.SPACE:
|
||||
case Biome.TEMPLE:
|
||||
return 16;
|
||||
default:
|
||||
return 0;
|
||||
case Biome.METROPOLIS:
|
||||
return 2;
|
||||
case Biome.SLUM:
|
||||
case Biome.BEACH:
|
||||
case Biome.DOJO:
|
||||
case Biome.CONSTRUCTION_SITE:
|
||||
return 4;
|
||||
case Biome.PLAINS:
|
||||
case Biome.GRASS:
|
||||
case Biome.LAKE:
|
||||
case Biome.CAVE:
|
||||
return 6;
|
||||
case Biome.TALL_GRASS:
|
||||
case Biome.FOREST:
|
||||
case Biome.SEA:
|
||||
case Biome.SWAMP:
|
||||
case Biome.MOUNTAIN:
|
||||
case Biome.BADLANDS:
|
||||
case Biome.DESERT:
|
||||
case Biome.MEADOW:
|
||||
case Biome.POWER_PLANT:
|
||||
case Biome.GRAVEYARD:
|
||||
case Biome.FACTORY:
|
||||
case Biome.SNOWY_FOREST:
|
||||
return 8;
|
||||
case Biome.ICE_CAVE:
|
||||
case Biome.VOLCANO:
|
||||
case Biome.RUINS:
|
||||
case Biome.WASTELAND:
|
||||
case Biome.JUNGLE:
|
||||
case Biome.FAIRY_CAVE:
|
||||
return 12;
|
||||
case Biome.SEABED:
|
||||
case Biome.ABYSS:
|
||||
case Biome.SPACE:
|
||||
case Biome.TEMPLE:
|
||||
return 16;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
getTimeOfDay(): TimeOfDay {
|
||||
switch (this.biomeType) {
|
||||
case Biome.ABYSS:
|
||||
return TimeOfDay.NIGHT;
|
||||
case Biome.ABYSS:
|
||||
return TimeOfDay.NIGHT;
|
||||
}
|
||||
|
||||
const waveCycle = ((this.scene.currentBattle?.waveIndex || 0) + this.scene.waveCycleOffset) % 40;
|
||||
|
@ -491,35 +491,35 @@ export class Arena {
|
|||
|
||||
isOutside(): boolean {
|
||||
switch (this.biomeType) {
|
||||
case Biome.SEABED:
|
||||
case Biome.CAVE:
|
||||
case Biome.ICE_CAVE:
|
||||
case Biome.POWER_PLANT:
|
||||
case Biome.DOJO:
|
||||
case Biome.FACTORY:
|
||||
case Biome.ABYSS:
|
||||
case Biome.FAIRY_CAVE:
|
||||
case Biome.TEMPLE:
|
||||
case Biome.LABORATORY:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
case Biome.SEABED:
|
||||
case Biome.CAVE:
|
||||
case Biome.ICE_CAVE:
|
||||
case Biome.POWER_PLANT:
|
||||
case Biome.DOJO:
|
||||
case Biome.FACTORY:
|
||||
case Biome.ABYSS:
|
||||
case Biome.FAIRY_CAVE:
|
||||
case Biome.TEMPLE:
|
||||
case Biome.LABORATORY:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
overrideTint(): [integer, integer, integer] {
|
||||
switch (Overrides.ARENA_TINT_OVERRIDE) {
|
||||
case TimeOfDay.DUSK:
|
||||
return [ 98, 48, 73 ].map(c => Math.round((c + 128) / 2)) as [integer, integer, integer];
|
||||
break;
|
||||
case (TimeOfDay.NIGHT):
|
||||
return [ 64, 64, 64 ];
|
||||
break;
|
||||
case TimeOfDay.DAWN:
|
||||
case TimeOfDay.DAY:
|
||||
default:
|
||||
return [ 128, 128, 128 ];
|
||||
break;
|
||||
case TimeOfDay.DUSK:
|
||||
return [ 98, 48, 73 ].map(c => Math.round((c + 128) / 2)) as [integer, integer, integer];
|
||||
break;
|
||||
case (TimeOfDay.NIGHT):
|
||||
return [ 64, 64, 64 ];
|
||||
break;
|
||||
case TimeOfDay.DAWN:
|
||||
case TimeOfDay.DAY:
|
||||
default:
|
||||
return [ 128, 128, 128 ];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -528,10 +528,10 @@ export class Arena {
|
|||
return this.overrideTint();
|
||||
}
|
||||
switch (this.biomeType) {
|
||||
case Biome.ABYSS:
|
||||
return [ 64, 64, 64 ];
|
||||
default:
|
||||
return [ 128, 128, 128 ];
|
||||
case Biome.ABYSS:
|
||||
return [ 64, 64, 64 ];
|
||||
default:
|
||||
return [ 128, 128, 128 ];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -544,8 +544,8 @@ export class Arena {
|
|||
}
|
||||
|
||||
switch (this.biomeType) {
|
||||
default:
|
||||
return [ 98, 48, 73 ].map(c => Math.round((c + 128) / 2)) as [integer, integer, integer];
|
||||
default:
|
||||
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();
|
||||
}
|
||||
switch (this.biomeType) {
|
||||
case Biome.ABYSS:
|
||||
case Biome.SPACE:
|
||||
case Biome.END:
|
||||
return this.getDayTint();
|
||||
case Biome.ABYSS:
|
||||
case Biome.SPACE:
|
||||
case Biome.END:
|
||||
return this.getDayTint();
|
||||
}
|
||||
|
||||
if (!this.isOutside()) {
|
||||
|
@ -565,8 +565,8 @@ export class Arena {
|
|||
}
|
||||
|
||||
switch (this.biomeType) {
|
||||
default:
|
||||
return [ 48, 48, 98 ];
|
||||
default:
|
||||
return [ 48, 48, 98 ];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -747,77 +747,77 @@ export class Arena {
|
|||
|
||||
getBgmLoopPoint(): number {
|
||||
switch (this.biomeType) {
|
||||
case Biome.TOWN:
|
||||
return 7.288;
|
||||
case Biome.PLAINS:
|
||||
return 17.485;
|
||||
case Biome.GRASS:
|
||||
return 1.995;
|
||||
case Biome.TALL_GRASS:
|
||||
return 9.608;
|
||||
case Biome.METROPOLIS:
|
||||
return 141.470;
|
||||
case Biome.FOREST:
|
||||
return 4.294;
|
||||
case Biome.SEA:
|
||||
return 0.024;
|
||||
case Biome.SWAMP:
|
||||
return 4.461;
|
||||
case Biome.BEACH:
|
||||
return 3.462;
|
||||
case Biome.LAKE:
|
||||
return 7.215;
|
||||
case Biome.SEABED:
|
||||
return 2.600;
|
||||
case Biome.MOUNTAIN:
|
||||
return 4.018;
|
||||
case Biome.BADLANDS:
|
||||
return 17.790;
|
||||
case Biome.CAVE:
|
||||
return 14.240;
|
||||
case Biome.DESERT:
|
||||
return 1.143;
|
||||
case Biome.ICE_CAVE:
|
||||
return 0.000;
|
||||
case Biome.MEADOW:
|
||||
return 3.891;
|
||||
case Biome.POWER_PLANT:
|
||||
return 9.447;
|
||||
case Biome.VOLCANO:
|
||||
return 17.637;
|
||||
case Biome.GRAVEYARD:
|
||||
return 3.232;
|
||||
case Biome.DOJO:
|
||||
return 6.205;
|
||||
case Biome.FACTORY:
|
||||
return 4.985;
|
||||
case Biome.RUINS:
|
||||
return 0.000;
|
||||
case Biome.WASTELAND:
|
||||
return 6.336;
|
||||
case Biome.ABYSS:
|
||||
return 5.130;
|
||||
case Biome.SPACE:
|
||||
return 20.036;
|
||||
case Biome.CONSTRUCTION_SITE:
|
||||
return 1.222;
|
||||
case Biome.JUNGLE:
|
||||
return 0.000;
|
||||
case Biome.FAIRY_CAVE:
|
||||
return 4.542;
|
||||
case Biome.TEMPLE:
|
||||
return 2.547;
|
||||
case Biome.ISLAND:
|
||||
return 2.751;
|
||||
case Biome.LABORATORY:
|
||||
return 114.862;
|
||||
case Biome.SLUM:
|
||||
return 0.000;
|
||||
case Biome.SNOWY_FOREST:
|
||||
return 3.047;
|
||||
default:
|
||||
console.warn(`missing bgm loop-point for biome "${Biome[this.biomeType]}" (=${this.biomeType})`);
|
||||
return 0;
|
||||
case Biome.TOWN:
|
||||
return 7.288;
|
||||
case Biome.PLAINS:
|
||||
return 17.485;
|
||||
case Biome.GRASS:
|
||||
return 1.995;
|
||||
case Biome.TALL_GRASS:
|
||||
return 9.608;
|
||||
case Biome.METROPOLIS:
|
||||
return 141.470;
|
||||
case Biome.FOREST:
|
||||
return 4.294;
|
||||
case Biome.SEA:
|
||||
return 0.024;
|
||||
case Biome.SWAMP:
|
||||
return 4.461;
|
||||
case Biome.BEACH:
|
||||
return 3.462;
|
||||
case Biome.LAKE:
|
||||
return 7.215;
|
||||
case Biome.SEABED:
|
||||
return 2.600;
|
||||
case Biome.MOUNTAIN:
|
||||
return 4.018;
|
||||
case Biome.BADLANDS:
|
||||
return 17.790;
|
||||
case Biome.CAVE:
|
||||
return 14.240;
|
||||
case Biome.DESERT:
|
||||
return 1.143;
|
||||
case Biome.ICE_CAVE:
|
||||
return 0.000;
|
||||
case Biome.MEADOW:
|
||||
return 3.891;
|
||||
case Biome.POWER_PLANT:
|
||||
return 9.447;
|
||||
case Biome.VOLCANO:
|
||||
return 17.637;
|
||||
case Biome.GRAVEYARD:
|
||||
return 3.232;
|
||||
case Biome.DOJO:
|
||||
return 6.205;
|
||||
case Biome.FACTORY:
|
||||
return 4.985;
|
||||
case Biome.RUINS:
|
||||
return 0.000;
|
||||
case Biome.WASTELAND:
|
||||
return 6.336;
|
||||
case Biome.ABYSS:
|
||||
return 5.130;
|
||||
case Biome.SPACE:
|
||||
return 20.036;
|
||||
case Biome.CONSTRUCTION_SITE:
|
||||
return 1.222;
|
||||
case Biome.JUNGLE:
|
||||
return 0.000;
|
||||
case Biome.FAIRY_CAVE:
|
||||
return 4.542;
|
||||
case Biome.TEMPLE:
|
||||
return 2.547;
|
||||
case Biome.ISLAND:
|
||||
return 2.751;
|
||||
case Biome.LABORATORY:
|
||||
return 114.862;
|
||||
case Biome.SLUM:
|
||||
return 0.000;
|
||||
case Biome.SNOWY_FOREST:
|
||||
return 3.047;
|
||||
default:
|
||||
console.warn(`missing bgm loop-point for biome "${Biome[this.biomeType]}" (=${this.biomeType})`);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -828,32 +828,32 @@ export function getBiomeKey(biome: Biome): string {
|
|||
|
||||
export function getBiomeHasProps(biomeType: Biome): boolean {
|
||||
switch (biomeType) {
|
||||
case Biome.METROPOLIS:
|
||||
case Biome.BEACH:
|
||||
case Biome.LAKE:
|
||||
case Biome.SEABED:
|
||||
case Biome.MOUNTAIN:
|
||||
case Biome.BADLANDS:
|
||||
case Biome.CAVE:
|
||||
case Biome.DESERT:
|
||||
case Biome.ICE_CAVE:
|
||||
case Biome.MEADOW:
|
||||
case Biome.POWER_PLANT:
|
||||
case Biome.VOLCANO:
|
||||
case Biome.GRAVEYARD:
|
||||
case Biome.FACTORY:
|
||||
case Biome.RUINS:
|
||||
case Biome.WASTELAND:
|
||||
case Biome.ABYSS:
|
||||
case Biome.CONSTRUCTION_SITE:
|
||||
case Biome.JUNGLE:
|
||||
case Biome.FAIRY_CAVE:
|
||||
case Biome.TEMPLE:
|
||||
case Biome.SNOWY_FOREST:
|
||||
case Biome.ISLAND:
|
||||
case Biome.LABORATORY:
|
||||
case Biome.END:
|
||||
return true;
|
||||
case Biome.METROPOLIS:
|
||||
case Biome.BEACH:
|
||||
case Biome.LAKE:
|
||||
case Biome.SEABED:
|
||||
case Biome.MOUNTAIN:
|
||||
case Biome.BADLANDS:
|
||||
case Biome.CAVE:
|
||||
case Biome.DESERT:
|
||||
case Biome.ICE_CAVE:
|
||||
case Biome.MEADOW:
|
||||
case Biome.POWER_PLANT:
|
||||
case Biome.VOLCANO:
|
||||
case Biome.GRAVEYARD:
|
||||
case Biome.FACTORY:
|
||||
case Biome.RUINS:
|
||||
case Biome.WASTELAND:
|
||||
case Biome.ABYSS:
|
||||
case Biome.CONSTRUCTION_SITE:
|
||||
case Biome.JUNGLE:
|
||||
case Biome.FAIRY_CAVE:
|
||||
case Biome.TEMPLE:
|
||||
case Biome.SNOWY_FOREST:
|
||||
case Biome.ISLAND:
|
||||
case Biome.LABORATORY:
|
||||
case Biome.END:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -29,21 +29,21 @@ export default class DamageNumberHandler {
|
|||
let [ textColor, shadowColor ] : TextAndShadowArr = [ null, null ];
|
||||
|
||||
switch (result) {
|
||||
case HitResult.SUPER_EFFECTIVE:
|
||||
[ textColor, shadowColor ] = [ "#f8d030", "#b8a038" ];
|
||||
break;
|
||||
case HitResult.NOT_VERY_EFFECTIVE:
|
||||
[ textColor, shadowColor ] = [ "#f08030", "#c03028" ];
|
||||
break;
|
||||
case HitResult.ONE_HIT_KO:
|
||||
[ textColor, shadowColor ] = [ "#a040a0", "#483850" ];
|
||||
break;
|
||||
case HitResult.HEAL:
|
||||
[ textColor, shadowColor ] = [ "#78c850", "#588040" ];
|
||||
break;
|
||||
default:
|
||||
[ textColor, shadowColor ] = [ "#ffffff", "#636363" ];
|
||||
break;
|
||||
case HitResult.SUPER_EFFECTIVE:
|
||||
[ textColor, shadowColor ] = [ "#f8d030", "#b8a038" ];
|
||||
break;
|
||||
case HitResult.NOT_VERY_EFFECTIVE:
|
||||
[ textColor, shadowColor ] = [ "#f08030", "#c03028" ];
|
||||
break;
|
||||
case HitResult.ONE_HIT_KO:
|
||||
[ textColor, shadowColor ] = [ "#a040a0", "#483850" ];
|
||||
break;
|
||||
case HitResult.HEAL:
|
||||
[ textColor, shadowColor ] = [ "#78c850", "#588040" ];
|
||||
break;
|
||||
default:
|
||||
[ textColor, shadowColor ] = [ "#ffffff", "#636363" ];
|
||||
break;
|
||||
}
|
||||
|
||||
if (textColor) {
|
||||
|
|
|
@ -62,7 +62,7 @@ import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-ph
|
|||
import { Challenges } from "#enums/challenges";
|
||||
import { PokemonAnimType } from "#enums/pokemon-anim-type";
|
||||
import { PLAYER_PARTY_MAX_SIZE } from "#app/constants";
|
||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
||||
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||
import { SwitchType } from "#enums/switch-type";
|
||||
import { SpeciesFormKey } from "#enums/species-form-key";
|
||||
import { BASE_HIDDEN_ABILITY_CHANCE, BASE_SHINY_CHANCE, SHINY_EPIC_CHANCE, SHINY_VARIANT_CHANCE } from "#app/data/balance/rates";
|
||||
|
@ -114,7 +114,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
public fusionVariant: Variant;
|
||||
public fusionGender: Gender;
|
||||
public fusionLuck: integer;
|
||||
public fusionMysteryEncounterPokemonData: MysteryEncounterPokemonData | null;
|
||||
public fusionCustomPokemonData: CustomPokemonData | null;
|
||||
|
||||
private summonDataPrimer: PokemonSummonData | null;
|
||||
|
||||
|
@ -122,7 +122,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
public battleData: PokemonBattleData;
|
||||
public battleSummonData: PokemonBattleSummonData;
|
||||
public turnData: PokemonTurnData;
|
||||
public mysteryEncounterPokemonData: MysteryEncounterPokemonData;
|
||||
public customPokemonData: CustomPokemonData;
|
||||
|
||||
/** Used by Mystery Encounters to execute pokemon-specific logic (such as stat boosts) at start of battle */
|
||||
public mysteryEncounterBattleEffects?: (pokemon: Pokemon) => void;
|
||||
|
@ -193,7 +193,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
}
|
||||
this.nature = dataSource.nature || 0 as Nature;
|
||||
this.nickname = dataSource.nickname;
|
||||
this.natureOverride = dataSource.natureOverride !== undefined ? dataSource.natureOverride : -1;
|
||||
this.moveset = dataSource.moveset;
|
||||
this.status = dataSource.status!; // TODO: is this bang correct?
|
||||
this.friendship = dataSource.friendship !== undefined ? dataSource.friendship : this.species.baseFriendship;
|
||||
|
@ -212,9 +211,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
this.fusionVariant = dataSource.fusionVariant || 0;
|
||||
this.fusionGender = dataSource.fusionGender;
|
||||
this.fusionLuck = dataSource.fusionLuck;
|
||||
this.fusionMysteryEncounterPokemonData = dataSource.fusionMysteryEncounterPokemonData;
|
||||
this.fusionCustomPokemonData = dataSource.fusionCustomPokemonData;
|
||||
this.usedTMs = dataSource.usedTMs ?? [];
|
||||
this.mysteryEncounterPokemonData = new MysteryEncounterPokemonData(dataSource.mysteryEncounterPokemonData);
|
||||
this.customPokemonData = new CustomPokemonData(dataSource.customPokemonData);
|
||||
} else {
|
||||
this.id = Utils.randSeedInt(4294967296);
|
||||
this.ivs = ivs || Utils.getIvsFromId(this.id);
|
||||
|
@ -235,7 +234,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
this.variant = this.shiny ? this.generateVariant() : 0;
|
||||
}
|
||||
|
||||
this.mysteryEncounterPokemonData = new MysteryEncounterPokemonData();
|
||||
this.customPokemonData = new CustomPokemonData();
|
||||
|
||||
if (nature !== undefined) {
|
||||
this.setNature(nature);
|
||||
|
@ -243,8 +242,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
this.generateNature();
|
||||
}
|
||||
|
||||
this.natureOverride = -1;
|
||||
|
||||
this.friendship = species.baseFriendship;
|
||||
this.metLevel = level;
|
||||
this.metBiome = scene.currentBattle ? scene.arena.biomeType : -1;
|
||||
|
@ -593,8 +590,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
const formKey = this.getFormKey();
|
||||
if (this.isMax() === true || formKey === "segin-starmobile" || formKey === "schedar-starmobile" || formKey === "navi-starmobile" || formKey === "ruchbah-starmobile" || formKey === "caph-starmobile") {
|
||||
return 1.5;
|
||||
} else if (this.mysteryEncounterPokemonData.spriteScale > 0) {
|
||||
return this.mysteryEncounterPokemonData.spriteScale;
|
||||
} else if (this.customPokemonData.spriteScale > 0) {
|
||||
return this.customPokemonData.spriteScale;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -680,12 +677,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
|
||||
getFieldPositionOffset(): [ number, number ] {
|
||||
switch (this.fieldPosition) {
|
||||
case FieldPosition.CENTER:
|
||||
return [ 0, 0 ];
|
||||
case FieldPosition.LEFT:
|
||||
return [ -32, -8 ];
|
||||
case FieldPosition.RIGHT:
|
||||
return [ 32, 0 ];
|
||||
case FieldPosition.CENTER:
|
||||
return [ 0, 0 ];
|
||||
case FieldPosition.LEFT:
|
||||
return [ -32, -8 ];
|
||||
case FieldPosition.RIGHT:
|
||||
return [ 32, 0 ];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -917,39 +914,39 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
let ret = statValue.value * this.getStatStageMultiplier(stat, opponent, move, ignoreOppAbility, isCritical, simulated);
|
||||
|
||||
switch (stat) {
|
||||
case Stat.ATK:
|
||||
if (this.getTag(BattlerTagType.SLOW_START)) {
|
||||
ret >>= 1;
|
||||
}
|
||||
break;
|
||||
case Stat.DEF:
|
||||
if (this.isOfType(Type.ICE) && this.scene.arena.weather?.weatherType === WeatherType.SNOW) {
|
||||
ret *= 1.5;
|
||||
}
|
||||
break;
|
||||
case Stat.SPATK:
|
||||
break;
|
||||
case Stat.SPDEF:
|
||||
if (this.isOfType(Type.ROCK) && this.scene.arena.weather?.weatherType === WeatherType.SANDSTORM) {
|
||||
ret *= 1.5;
|
||||
}
|
||||
break;
|
||||
case Stat.SPD:
|
||||
const side = this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY;
|
||||
if (this.scene.arena.getTagOnSide(ArenaTagType.TAILWIND, side)) {
|
||||
ret *= 2;
|
||||
}
|
||||
if (this.scene.arena.getTagOnSide(ArenaTagType.GRASS_WATER_PLEDGE, side)) {
|
||||
ret >>= 2;
|
||||
}
|
||||
case Stat.ATK:
|
||||
if (this.getTag(BattlerTagType.SLOW_START)) {
|
||||
ret >>= 1;
|
||||
}
|
||||
break;
|
||||
case Stat.DEF:
|
||||
if (this.isOfType(Type.ICE) && this.scene.arena.weather?.weatherType === WeatherType.SNOW) {
|
||||
ret *= 1.5;
|
||||
}
|
||||
break;
|
||||
case Stat.SPATK:
|
||||
break;
|
||||
case Stat.SPDEF:
|
||||
if (this.isOfType(Type.ROCK) && this.scene.arena.weather?.weatherType === WeatherType.SANDSTORM) {
|
||||
ret *= 1.5;
|
||||
}
|
||||
break;
|
||||
case Stat.SPD:
|
||||
const side = this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY;
|
||||
if (this.scene.arena.getTagOnSide(ArenaTagType.TAILWIND, side)) {
|
||||
ret *= 2;
|
||||
}
|
||||
if (this.scene.arena.getTagOnSide(ArenaTagType.GRASS_WATER_PLEDGE, side)) {
|
||||
ret >>= 2;
|
||||
}
|
||||
|
||||
if (this.getTag(BattlerTagType.SLOW_START)) {
|
||||
ret >>= 1;
|
||||
}
|
||||
if (this.status && this.status.effect === StatusEffect.PARALYSIS) {
|
||||
ret >>= 1;
|
||||
}
|
||||
break;
|
||||
if (this.getTag(BattlerTagType.SLOW_START)) {
|
||||
ret >>= 1;
|
||||
}
|
||||
if (this.status && this.status.effect === StatusEffect.PARALYSIS) {
|
||||
ret >>= 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
const highestStatBoost = this.findTag(t => t instanceof HighestStatBoostTag && (t as HighestStatBoostTag).stat === stat) as HighestStatBoostTag;
|
||||
|
@ -1023,7 +1020,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
}
|
||||
|
||||
getNature(): Nature {
|
||||
return this.natureOverride !== -1 ? this.natureOverride : this.nature;
|
||||
return this.customPokemonData.nature !== -1 ? this.customPokemonData.nature : this.nature;
|
||||
}
|
||||
|
||||
setNature(nature: Nature): void {
|
||||
|
@ -1198,15 +1195,15 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
if (!types.length || !includeTeraType) {
|
||||
if (!ignoreOverride && this.summonData?.types && this.summonData.types.length > 0) {
|
||||
this.summonData.types.forEach(t => types.push(t));
|
||||
} else if (this.mysteryEncounterPokemonData.types && this.mysteryEncounterPokemonData.types.length > 0) {
|
||||
} else if (this.customPokemonData.types && this.customPokemonData.types.length > 0) {
|
||||
// "Permanent" override for a Pokemon's normal types, currently only used by Mystery Encounters
|
||||
types.push(this.mysteryEncounterPokemonData.types[0]);
|
||||
types.push(this.customPokemonData.types[0]);
|
||||
|
||||
// Fusing a Pokemon onto something with "permanently changed" types will still apply the fusion's types as normal
|
||||
const fusionSpeciesForm = this.getFusionSpeciesForm(ignoreOverride);
|
||||
if (fusionSpeciesForm) {
|
||||
// Check if the fusion Pokemon also had "permanently changed" types
|
||||
const fusionMETypes = this.fusionMysteryEncounterPokemonData?.types;
|
||||
const fusionMETypes = this.fusionCustomPokemonData?.types;
|
||||
if (fusionMETypes && fusionMETypes.length >= 2 && fusionMETypes[1] !== types[0]) {
|
||||
types.push(fusionMETypes[1]);
|
||||
} else if (fusionMETypes && fusionMETypes.length === 1 && fusionMETypes[0] !== types[0]) {
|
||||
|
@ -1218,8 +1215,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
}
|
||||
}
|
||||
|
||||
if (types.length === 1 && this.mysteryEncounterPokemonData.types.length >= 2) {
|
||||
types.push(this.mysteryEncounterPokemonData.types[1]);
|
||||
if (types.length === 1 && this.customPokemonData.types.length >= 2) {
|
||||
types.push(this.customPokemonData.types[1]);
|
||||
}
|
||||
} else {
|
||||
const speciesForm = this.getSpeciesForm(ignoreOverride);
|
||||
|
@ -1230,7 +1227,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
if (fusionSpeciesForm) {
|
||||
// Check if the fusion Pokemon also had "permanently changed" types
|
||||
// Otherwise, use standard fusion type logic
|
||||
const fusionMETypes = this.fusionMysteryEncounterPokemonData?.types;
|
||||
const fusionMETypes = this.fusionCustomPokemonData?.types;
|
||||
if (fusionMETypes && fusionMETypes.length >= 2 && fusionMETypes[1] !== types[0]) {
|
||||
types.push(fusionMETypes[1]);
|
||||
} else if (fusionMETypes && fusionMETypes.length === 1 && fusionMETypes[0] !== types[0]) {
|
||||
|
@ -1262,6 +1259,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
}
|
||||
}
|
||||
|
||||
// If both types are the same (can happen in weird custom typing scenarios), reduce to single type
|
||||
if (types.length > 1 && types[0] === types[1]) {
|
||||
types.splice(0, 1);
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
|
@ -1288,14 +1290,14 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
return allAbilities[Overrides.OPP_ABILITY_OVERRIDE];
|
||||
}
|
||||
if (this.isFusion()) {
|
||||
if (!isNullOrUndefined(this.fusionMysteryEncounterPokemonData?.ability) && this.fusionMysteryEncounterPokemonData.ability !== -1) {
|
||||
return allAbilities[this.fusionMysteryEncounterPokemonData.ability];
|
||||
if (!isNullOrUndefined(this.fusionCustomPokemonData?.ability) && this.fusionCustomPokemonData.ability !== -1) {
|
||||
return allAbilities[this.fusionCustomPokemonData.ability];
|
||||
} else {
|
||||
return allAbilities[this.getFusionSpeciesForm(ignoreOverride).getAbility(this.fusionAbilityIndex)];
|
||||
}
|
||||
}
|
||||
if (!isNullOrUndefined(this.mysteryEncounterPokemonData.ability) && this.mysteryEncounterPokemonData.ability !== -1) {
|
||||
return allAbilities[this.mysteryEncounterPokemonData.ability];
|
||||
if (!isNullOrUndefined(this.customPokemonData.ability) && this.customPokemonData.ability !== -1) {
|
||||
return allAbilities[this.customPokemonData.ability];
|
||||
}
|
||||
let abilityId = this.getSpeciesForm(ignoreOverride).getAbility(this.abilityIndex);
|
||||
if (abilityId === Abilities.NONE) {
|
||||
|
@ -1318,8 +1320,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
if (Overrides.OPP_PASSIVE_ABILITY_OVERRIDE && !this.isPlayer()) {
|
||||
return allAbilities[Overrides.OPP_PASSIVE_ABILITY_OVERRIDE];
|
||||
}
|
||||
if (!isNullOrUndefined(this.mysteryEncounterPokemonData.passive) && this.mysteryEncounterPokemonData.passive !== -1) {
|
||||
return allAbilities[this.mysteryEncounterPokemonData.passive];
|
||||
if (!isNullOrUndefined(this.customPokemonData.passive) && this.customPokemonData.passive !== -1) {
|
||||
return allAbilities[this.customPokemonData.passive];
|
||||
}
|
||||
|
||||
let starterSpeciesId = this.species.speciesId;
|
||||
|
@ -2018,7 +2020,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
this.fusionVariant = 0;
|
||||
this.fusionGender = 0;
|
||||
this.fusionLuck = 0;
|
||||
this.fusionMysteryEncounterPokemonData = null;
|
||||
this.fusionCustomPokemonData = null;
|
||||
|
||||
this.generateName();
|
||||
this.calculateStats();
|
||||
|
@ -2187,7 +2189,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
this.moveset.push(new PokemonMove(movePool[index][0], 0, 0));
|
||||
}
|
||||
|
||||
this.scene.triggerPokemonFormChange(this, SpeciesFormChangeMoveLearnedTrigger);
|
||||
// Trigger FormChange, except for enemy Pokemon during Mystery Encounters, to avoid crashes
|
||||
if (this.isPlayer() || !this.scene.currentBattle?.isBattleMysteryEncounter() || !this.scene.currentBattle?.mysteryEncounter) {
|
||||
this.scene.triggerPokemonFormChange(this, SpeciesFormChangeMoveLearnedTrigger);
|
||||
}
|
||||
}
|
||||
|
||||
trySelectMove(moveIndex: integer, ignorePp?: boolean): boolean {
|
||||
|
@ -2338,14 +2343,14 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
if (opponent) {
|
||||
if (isCritical) {
|
||||
switch (stat) {
|
||||
case Stat.ATK:
|
||||
case Stat.SPATK:
|
||||
statStage.value = Math.max(statStage.value, 0);
|
||||
break;
|
||||
case Stat.DEF:
|
||||
case Stat.SPDEF:
|
||||
statStage.value = Math.min(statStage.value, 0);
|
||||
break;
|
||||
case Stat.ATK:
|
||||
case Stat.SPATK:
|
||||
statStage.value = Math.max(statStage.value, 0);
|
||||
break;
|
||||
case Stat.DEF:
|
||||
case Stat.SPDEF:
|
||||
statStage.value = Math.min(statStage.value, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ignoreOppAbility) {
|
||||
|
@ -2795,15 +2800,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
|
||||
if (source.turnData.hitsLeft === 1 || this.isFainted()) {
|
||||
switch (result) {
|
||||
case HitResult.SUPER_EFFECTIVE:
|
||||
this.scene.queueMessage(i18next.t("battle:hitResultSuperEffective"));
|
||||
break;
|
||||
case HitResult.NOT_VERY_EFFECTIVE:
|
||||
this.scene.queueMessage(i18next.t("battle:hitResultNotVeryEffective"));
|
||||
break;
|
||||
case HitResult.ONE_HIT_KO:
|
||||
this.scene.queueMessage(i18next.t("battle:hitResultOneHitKO"));
|
||||
break;
|
||||
case HitResult.SUPER_EFFECTIVE:
|
||||
this.scene.queueMessage(i18next.t("battle:hitResultSuperEffective"));
|
||||
break;
|
||||
case HitResult.NOT_VERY_EFFECTIVE:
|
||||
this.scene.queueMessage(i18next.t("battle:hitResultNotVeryEffective"));
|
||||
break;
|
||||
case HitResult.ONE_HIT_KO:
|
||||
this.scene.queueMessage(i18next.t("battle:hitResultOneHitKO"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3355,53 +3360,53 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
}
|
||||
|
||||
switch (effect) {
|
||||
case StatusEffect.POISON:
|
||||
case StatusEffect.TOXIC:
|
||||
case StatusEffect.POISON:
|
||||
case StatusEffect.TOXIC:
|
||||
// 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
|
||||
if (defType !== Type.POISON && defType !== Type.STEEL) {
|
||||
return false;
|
||||
}
|
||||
if (defType !== Type.POISON && defType !== Type.STEEL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the source Pokemon has an ability that cancels the Poison/Toxic immunity
|
||||
const cancelImmunity = new Utils.BooleanHolder(false);
|
||||
if (sourcePokemon) {
|
||||
applyAbAttrs(IgnoreTypeStatusEffectImmunityAbAttr, sourcePokemon, cancelImmunity, false, effect, defType);
|
||||
if (cancelImmunity.value) {
|
||||
// Check if the source Pokemon has an ability that cancels the Poison/Toxic immunity
|
||||
const cancelImmunity = new Utils.BooleanHolder(false);
|
||||
if (sourcePokemon) {
|
||||
applyAbAttrs(IgnoreTypeStatusEffectImmunityAbAttr, sourcePokemon, cancelImmunity, false, effect, defType);
|
||||
if (cancelImmunity.value) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
if (this.isOfType(Type.POISON) || this.isOfType(Type.STEEL)) {
|
||||
if (poisonImmunity.includes(true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
if (this.isOfType(Type.POISON) || this.isOfType(Type.STEEL)) {
|
||||
if (poisonImmunity.includes(true)) {
|
||||
break;
|
||||
case StatusEffect.PARALYSIS:
|
||||
if (this.isOfType(Type.ELECTRIC)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case StatusEffect.PARALYSIS:
|
||||
if (this.isOfType(Type.ELECTRIC)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case StatusEffect.SLEEP:
|
||||
if (this.isGrounded() && this.scene.arena.terrain?.terrainType === TerrainType.ELECTRIC) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case StatusEffect.FREEZE:
|
||||
if (this.isOfType(Type.ICE) || (this.scene?.arena?.weather?.weatherType && [ WeatherType.SUNNY, WeatherType.HARSH_SUN ].includes(this.scene.arena.weather.weatherType))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case StatusEffect.BURN:
|
||||
if (this.isOfType(Type.FIRE)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case StatusEffect.SLEEP:
|
||||
if (this.isGrounded() && this.scene.arena.terrain?.terrainType === TerrainType.ELECTRIC) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case StatusEffect.FREEZE:
|
||||
if (this.isOfType(Type.ICE) || (this.scene?.arena?.weather?.weatherType && [ WeatherType.SUNNY, WeatherType.HARSH_SUN ].includes(this.scene.arena.weather.weatherType))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case StatusEffect.BURN:
|
||||
if (this.isOfType(Type.FIRE)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
const cancelled = new Utils.BooleanHolder(false);
|
||||
|
@ -3977,10 +3982,14 @@ export class PlayerPokemon extends Pokemon {
|
|||
if (Overrides.SHINY_OVERRIDE) {
|
||||
this.shiny = true;
|
||||
this.initShinySparkle();
|
||||
if (Overrides.VARIANT_OVERRIDE) {
|
||||
this.variant = Overrides.VARIANT_OVERRIDE;
|
||||
}
|
||||
} else if (Overrides.SHINY_OVERRIDE === false) {
|
||||
this.shiny = false;
|
||||
}
|
||||
|
||||
if (Overrides.VARIANT_OVERRIDE !== null && this.shiny) {
|
||||
this.variant = Overrides.VARIANT_OVERRIDE;
|
||||
}
|
||||
|
||||
if (!dataSource) {
|
||||
if (this.scene.gameMode.isDaily) {
|
||||
this.generateAndPopulateMoveset();
|
||||
|
@ -4292,12 +4301,33 @@ export class PlayerPokemon extends Pokemon {
|
|||
|
||||
changeForm(formChange: SpeciesFormChange): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
const previousFormIndex = this.formIndex;
|
||||
this.formIndex = Math.max(this.species.forms.findIndex(f => f.formKey === formChange.formKey), 0);
|
||||
this.generateName();
|
||||
const abilityCount = this.getSpeciesForm().getAbilityCount();
|
||||
if (this.abilityIndex >= abilityCount) { // Shouldn't happen
|
||||
this.abilityIndex = abilityCount - 1;
|
||||
}
|
||||
|
||||
// In cases where a form change updates the type of a Pokemon from its previous form (Arceus, Silvally, Castform, etc.),
|
||||
// persist that type change in customPokemonData if necessary
|
||||
const baseForm = this.species.forms[previousFormIndex];
|
||||
const baseFormTypes = [ baseForm.type1, baseForm.type2 ];
|
||||
if (this.customPokemonData.types.length > 0) {
|
||||
if (this.getSpeciesForm().type1 !== baseFormTypes[0]) {
|
||||
this.customPokemonData.types[0] = this.getSpeciesForm().type1;
|
||||
}
|
||||
|
||||
const type2 = this.getSpeciesForm().type2;
|
||||
if (!isNullOrUndefined(type2) && type2 !== baseFormTypes[1]) {
|
||||
if (this.customPokemonData.types.length > 1) {
|
||||
this.customPokemonData.types[1] = type2;
|
||||
} else {
|
||||
this.customPokemonData.types.push(type2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.compatibleTms.splice(0, this.compatibleTms.length);
|
||||
this.generateCompatibleTms();
|
||||
const updateAndResolve = () => {
|
||||
|
@ -4334,7 +4364,7 @@ export class PlayerPokemon extends Pokemon {
|
|||
this.fusionVariant = pokemon.variant;
|
||||
this.fusionGender = pokemon.gender;
|
||||
this.fusionLuck = pokemon.luck;
|
||||
this.fusionMysteryEncounterPokemonData = pokemon.mysteryEncounterPokemonData;
|
||||
this.fusionCustomPokemonData = pokemon.customPokemonData;
|
||||
if ((pokemon.pauseEvolutions) || (this.pauseEvolutions)) {
|
||||
this.pauseEvolutions = true;
|
||||
}
|
||||
|
@ -4448,10 +4478,13 @@ export class EnemyPokemon extends Pokemon {
|
|||
if (Overrides.OPP_SHINY_OVERRIDE) {
|
||||
this.shiny = true;
|
||||
this.initShinySparkle();
|
||||
} else if (Overrides.OPP_SHINY_OVERRIDE === false) {
|
||||
this.shiny = false;
|
||||
}
|
||||
|
||||
if (this.shiny) {
|
||||
this.variant = this.generateVariant();
|
||||
if (Overrides.OPP_VARIANT_OVERRIDE) {
|
||||
if (Overrides.OPP_VARIANT_OVERRIDE !== null) {
|
||||
this.variant = Overrides.OPP_VARIANT_OVERRIDE;
|
||||
}
|
||||
}
|
||||
|
@ -4501,35 +4534,35 @@ export class EnemyPokemon extends Pokemon {
|
|||
|
||||
generateAndPopulateMoveset(formIndex?: integer): void {
|
||||
switch (true) {
|
||||
case (this.species.speciesId === Species.SMEARGLE):
|
||||
this.moveset = [
|
||||
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)
|
||||
case (this.species.speciesId === Species.SMEARGLE):
|
||||
this.moveset = [
|
||||
new PokemonMove(Moves.SKETCH),
|
||||
new PokemonMove(Moves.SKETCH),
|
||||
new PokemonMove(Moves.SKETCH),
|
||||
new PokemonMove(Moves.SKETCH)
|
||||
];
|
||||
if (this.scene.gameMode.hasChallenge(Challenges.INVERSE_BATTLE)) {
|
||||
this.moveset[2] = new PokemonMove(Moves.THUNDERBOLT);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
super.generateAndPopulateMoveset();
|
||||
break;
|
||||
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)) {
|
||||
this.moveset[2] = new PokemonMove(Moves.THUNDERBOLT);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
super.generateAndPopulateMoveset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4571,135 +4604,135 @@ export class EnemyPokemon extends Pokemon {
|
|||
}
|
||||
}
|
||||
switch (this.aiType) {
|
||||
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?
|
||||
return { move: moveId, targets: this.getNextTargets(moveId) };
|
||||
case AiType.SMART_RANDOM:
|
||||
case AiType.SMART:
|
||||
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?
|
||||
return { move: moveId, targets: this.getNextTargets(moveId) };
|
||||
case AiType.SMART_RANDOM:
|
||||
case AiType.SMART:
|
||||
/**
|
||||
* 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),
|
||||
* those moves are the only ones considered for selection on this turn.
|
||||
*/
|
||||
const koMoves = movePool.filter(pkmnMove => {
|
||||
if (!pkmnMove) {
|
||||
return false;
|
||||
}
|
||||
const koMoves = movePool.filter(pkmnMove => {
|
||||
if (!pkmnMove) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const move = pkmnMove.getMove()!;
|
||||
if (move.moveTarget === MoveTarget.ATTACKER) {
|
||||
return false;
|
||||
}
|
||||
const move = pkmnMove.getMove()!;
|
||||
if (move.moveTarget === MoveTarget.ATTACKER) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const fieldPokemon = this.scene.getField();
|
||||
const moveTargets = getMoveTargets(this, move.id).targets
|
||||
.map(ind => fieldPokemon[ind])
|
||||
.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
|
||||
const isCritical = move.hasAttr(CritOnlyAttr) || !!this.getTag(BattlerTagType.ALWAYS_CRIT);
|
||||
const fieldPokemon = this.scene.getField();
|
||||
const moveTargets = getMoveTargets(this, move.id).targets
|
||||
.map(ind => fieldPokemon[ind])
|
||||
.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
|
||||
const isCritical = move.hasAttr(CritOnlyAttr) || !!this.getTag(BattlerTagType.ALWAYS_CRIT);
|
||||
|
||||
return move.category !== MoveCategory.STATUS
|
||||
return move.category !== MoveCategory.STATUS
|
||||
&& moveTargets.some(p => {
|
||||
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;
|
||||
});
|
||||
}, this);
|
||||
}, this);
|
||||
|
||||
if (koMoves.length > 0) {
|
||||
movePool = koMoves;
|
||||
}
|
||||
if (koMoves.length > 0) {
|
||||
movePool = koMoves;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Move selection is based on the move's calculated "benefit score" against the
|
||||
* best possible target(s) (as determined by {@linkcode getNextTargets}).
|
||||
* For more information on how benefit scores are calculated, see `docs/enemy-ai.md`.
|
||||
*/
|
||||
const moveScores = movePool.map(() => 0);
|
||||
const moveTargets = Object.fromEntries(movePool.map(m => [ m!.moveId, this.getNextTargets(m!.moveId) ])); // TODO: are those bangs correct?
|
||||
for (const m in movePool) {
|
||||
const pokemonMove = movePool[m]!; // TODO: is the bang correct?
|
||||
const move = pokemonMove.getMove();
|
||||
const moveScores = movePool.map(() => 0);
|
||||
const moveTargets = Object.fromEntries(movePool.map(m => [ m!.moveId, this.getNextTargets(m!.moveId) ])); // TODO: are those bangs correct?
|
||||
for (const m in movePool) {
|
||||
const pokemonMove = movePool[m]!; // TODO: is the bang correct?
|
||||
const move = pokemonMove.getMove();
|
||||
|
||||
let moveScore = moveScores[m];
|
||||
const targetScores: integer[] = [];
|
||||
let moveScore = moveScores[m];
|
||||
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
|
||||
if (mt === BattlerIndex.ATTACKER) {
|
||||
break;
|
||||
}
|
||||
if (mt === BattlerIndex.ATTACKER) {
|
||||
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.
|
||||
* 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);
|
||||
if (Number.isNaN(targetScore)) {
|
||||
console.error(`Move ${move.name} returned score of NaN`);
|
||||
targetScore = 0;
|
||||
}
|
||||
/**
|
||||
let targetScore = move.getUserBenefitScore(this, target, move) + move.getTargetBenefitScore(this, target, move) * (mt < BattlerIndex.ENEMY === this.isPlayer() ? 1 : -1);
|
||||
if (Number.isNaN(targetScore)) {
|
||||
console.error(`Move ${move.name} returned score of NaN`);
|
||||
targetScore = 0;
|
||||
}
|
||||
/**
|
||||
* If this move is unimplemented, or the move is known to fail when used, set its
|
||||
* 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)) {
|
||||
targetScore = -20;
|
||||
} else if (move instanceof AttackMove) {
|
||||
if ((move.name.endsWith(" (N)") || !move.applyConditions(this, target, move)) && ![ Moves.SUCKER_PUNCH, Moves.UPPER_HAND, Moves.THUNDERCLAP ].includes(move.id)) {
|
||||
targetScore = -20;
|
||||
} else if (move instanceof AttackMove) {
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
const effectiveness = target.getMoveEffectiveness(this, move, !target.battleData?.abilityRevealed);
|
||||
if (target.isPlayer() !== this.isPlayer()) {
|
||||
targetScore *= effectiveness;
|
||||
if (this.isOfType(move.type)) {
|
||||
targetScore *= 1.5;
|
||||
const effectiveness = target.getMoveEffectiveness(this, move, !target.battleData?.abilityRevealed);
|
||||
if (target.isPlayer() !== this.isPlayer()) {
|
||||
targetScore *= effectiveness;
|
||||
if (this.isOfType(move.type)) {
|
||||
targetScore *= 1.5;
|
||||
}
|
||||
} else if (effectiveness) {
|
||||
targetScore /= effectiveness;
|
||||
if (this.isOfType(move.type)) {
|
||||
targetScore /= 1.5;
|
||||
}
|
||||
}
|
||||
} else if (effectiveness) {
|
||||
targetScore /= effectiveness;
|
||||
if (this.isOfType(move.type)) {
|
||||
targetScore /= 1.5;
|
||||
/** If a move has a base benefit score of 0, its benefit score is assumed to be unimplemented at this point */
|
||||
if (!targetScore) {
|
||||
targetScore = -20;
|
||||
}
|
||||
}
|
||||
/** If a move has a base benefit score of 0, its benefit score is assumed to be unimplemented at this point */
|
||||
if (!targetScore) {
|
||||
targetScore = -20;
|
||||
}
|
||||
targetScores.push(targetScore);
|
||||
}
|
||||
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
|
||||
moveScores[m] = moveScore;
|
||||
}
|
||||
console.log(moveScores);
|
||||
|
||||
console.log(moveScores);
|
||||
|
||||
// Sort the move pool in decreasing order of move score
|
||||
const sortedMovePool = movePool.slice(0);
|
||||
sortedMovePool.sort((a, b) => {
|
||||
const scoreA = moveScores[movePool.indexOf(a)];
|
||||
const scoreB = moveScores[movePool.indexOf(b)];
|
||||
return scoreA < scoreB ? 1 : scoreA > scoreB ? -1 : 0;
|
||||
});
|
||||
let r = 0;
|
||||
if (this.aiType === AiType.SMART_RANDOM) {
|
||||
// Sort the move pool in decreasing order of move score
|
||||
const sortedMovePool = movePool.slice(0);
|
||||
sortedMovePool.sort((a, b) => {
|
||||
const scoreA = moveScores[movePool.indexOf(a)];
|
||||
const scoreB = moveScores[movePool.indexOf(b)];
|
||||
return scoreA < scoreB ? 1 : scoreA > scoreB ? -1 : 0;
|
||||
});
|
||||
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)
|
||||
while (r < sortedMovePool.length - 1 && this.scene.randBattleSeedInt(8) >= 5) {
|
||||
r++;
|
||||
}
|
||||
} else if (this.aiType === AiType.SMART) {
|
||||
while (r < sortedMovePool.length - 1 && this.scene.randBattleSeedInt(8) >= 5) {
|
||||
r++;
|
||||
}
|
||||
} 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.
|
||||
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)) {
|
||||
r++;
|
||||
r++;
|
||||
}
|
||||
}
|
||||
}
|
||||
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] };
|
||||
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] };
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4847,10 +4880,10 @@ export class EnemyPokemon extends Pokemon {
|
|||
}
|
||||
|
||||
switch (this.scene.currentBattle.battleSpec) {
|
||||
case BattleSpec.FINAL_BOSS:
|
||||
if (!this.formIndex && this.bossSegmentIndex < 1) {
|
||||
damage = Math.min(damage, this.hp - 1);
|
||||
}
|
||||
case BattleSpec.FINAL_BOSS:
|
||||
if (!this.formIndex && this.bossSegmentIndex < 1) {
|
||||
damage = Math.min(damage, this.hp - 1);
|
||||
}
|
||||
}
|
||||
|
||||
const ret = super.damage(damage, ignoreSegments, preventEndure, ignoreFaintPhase);
|
||||
|
|
|
@ -65,16 +65,16 @@ export default class Trainer extends Phaser.GameObjects.Container {
|
|||
}
|
||||
|
||||
switch (this.variant) {
|
||||
case TrainerVariant.FEMALE:
|
||||
if (!this.config.hasGenders) {
|
||||
variant = TrainerVariant.DEFAULT;
|
||||
}
|
||||
break;
|
||||
case TrainerVariant.DOUBLE:
|
||||
if (!this.config.hasDouble) {
|
||||
variant = TrainerVariant.DEFAULT;
|
||||
}
|
||||
break;
|
||||
case TrainerVariant.FEMALE:
|
||||
if (!this.config.hasGenders) {
|
||||
variant = TrainerVariant.DEFAULT;
|
||||
}
|
||||
break;
|
||||
case TrainerVariant.DOUBLE:
|
||||
if (!this.config.hasDouble) {
|
||||
variant = TrainerVariant.DEFAULT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
switch (strength) {
|
||||
case PartyMemberStrength.WEAKER:
|
||||
multiplier = 0.95;
|
||||
break;
|
||||
case PartyMemberStrength.WEAK:
|
||||
multiplier = 1.0;
|
||||
break;
|
||||
case PartyMemberStrength.AVERAGE:
|
||||
multiplier = 1.1;
|
||||
break;
|
||||
case PartyMemberStrength.STRONG:
|
||||
multiplier = 1.2;
|
||||
break;
|
||||
case PartyMemberStrength.STRONGER:
|
||||
multiplier = 1.25;
|
||||
break;
|
||||
case PartyMemberStrength.WEAKER:
|
||||
multiplier = 0.95;
|
||||
break;
|
||||
case PartyMemberStrength.WEAK:
|
||||
multiplier = 1.0;
|
||||
break;
|
||||
case PartyMemberStrength.AVERAGE:
|
||||
multiplier = 1.1;
|
||||
break;
|
||||
case PartyMemberStrength.STRONG:
|
||||
multiplier = 1.2;
|
||||
break;
|
||||
case PartyMemberStrength.STRONGER:
|
||||
multiplier = 1.25;
|
||||
break;
|
||||
}
|
||||
|
||||
let levelOffset = 0;
|
||||
|
@ -515,19 +515,19 @@ export default class Trainer extends Phaser.GameObjects.Container {
|
|||
|
||||
getPartyMemberModifierChanceMultiplier(index: integer): number {
|
||||
switch (this.getPartyTemplate().getStrength(index)) {
|
||||
case PartyMemberStrength.WEAKER:
|
||||
return 0.75;
|
||||
case PartyMemberStrength.WEAK:
|
||||
return 0.675;
|
||||
case PartyMemberStrength.AVERAGE:
|
||||
return 0.5625;
|
||||
case PartyMemberStrength.STRONG:
|
||||
return 0.45;
|
||||
case PartyMemberStrength.STRONGER:
|
||||
return 0.375;
|
||||
default:
|
||||
console.warn("getPartyMemberModifierChanceMultiplier not defined. Using default 0");
|
||||
return 0;
|
||||
case PartyMemberStrength.WEAKER:
|
||||
return 0.75;
|
||||
case PartyMemberStrength.WEAK:
|
||||
return 0.675;
|
||||
case PartyMemberStrength.AVERAGE:
|
||||
return 0.5625;
|
||||
case PartyMemberStrength.STRONG:
|
||||
return 0.45;
|
||||
case PartyMemberStrength.STRONGER:
|
||||
return 0.375;
|
||||
default:
|
||||
console.warn("getPartyMemberModifierChanceMultiplier not defined. Using default 0");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
148
src/game-mode.ts
|
@ -92,10 +92,10 @@ export class GameMode implements GameModeConfig {
|
|||
return Overrides.STARTING_LEVEL_OVERRIDE;
|
||||
}
|
||||
switch (this.modeId) {
|
||||
case GameModes.DAILY:
|
||||
return 20;
|
||||
default:
|
||||
return 5;
|
||||
case GameModes.DAILY:
|
||||
return 20;
|
||||
default:
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,19 +117,19 @@ export class GameMode implements GameModeConfig {
|
|||
*/
|
||||
getStartingBiome(scene: BattleScene): Biome {
|
||||
switch (this.modeId) {
|
||||
case GameModes.DAILY:
|
||||
return scene.generateRandomBiome(this.getWaveForDifficulty(1));
|
||||
default:
|
||||
return Overrides.STARTING_BIOME_OVERRIDE || Biome.TOWN;
|
||||
case GameModes.DAILY:
|
||||
return scene.generateRandomBiome(this.getWaveForDifficulty(1));
|
||||
default:
|
||||
return Overrides.STARTING_BIOME_OVERRIDE || Biome.TOWN;
|
||||
}
|
||||
}
|
||||
|
||||
getWaveForDifficulty(waveIndex: integer, ignoreCurveChanges: boolean = false): integer {
|
||||
switch (this.modeId) {
|
||||
case GameModes.DAILY:
|
||||
return waveIndex + 30 + (!ignoreCurveChanges ? Math.floor(waveIndex / 5) : 0);
|
||||
default:
|
||||
return waveIndex;
|
||||
case GameModes.DAILY:
|
||||
return waveIndex + 30 + (!ignoreCurveChanges ? Math.floor(waveIndex / 5) : 0);
|
||||
default:
|
||||
return waveIndex;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,10 +186,10 @@ export class GameMode implements GameModeConfig {
|
|||
|
||||
isTrainerBoss(waveIndex: integer, biomeType: Biome, offsetGym: boolean): boolean {
|
||||
switch (this.modeId) {
|
||||
case GameModes.DAILY:
|
||||
return waveIndex > 10 && waveIndex < 50 && !(waveIndex % 10);
|
||||
default:
|
||||
return (waveIndex % 30) === (offsetGym ? 0 : 20) && (biomeType !== Biome.END || this.isClassic || this.isWaveFinal(waveIndex));
|
||||
case GameModes.DAILY:
|
||||
return waveIndex > 10 && waveIndex < 50 && !(waveIndex % 10);
|
||||
default:
|
||||
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 {
|
||||
switch (modeId) {
|
||||
case GameModes.CLASSIC:
|
||||
case GameModes.CHALLENGE:
|
||||
return waveIndex === 200;
|
||||
case GameModes.ENDLESS:
|
||||
case GameModes.SPLICED_ENDLESS:
|
||||
return !(waveIndex % 250);
|
||||
case GameModes.DAILY:
|
||||
return waveIndex === 50;
|
||||
case GameModes.CLASSIC:
|
||||
case GameModes.CHALLENGE:
|
||||
return waveIndex === 200;
|
||||
case GameModes.ENDLESS:
|
||||
case GameModes.SPLICED_ENDLESS:
|
||||
return !(waveIndex % 250);
|
||||
case GameModes.DAILY:
|
||||
return waveIndex === 50;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -287,40 +287,40 @@ export class GameMode implements GameModeConfig {
|
|||
|
||||
getClearScoreBonus(): integer {
|
||||
switch (this.modeId) {
|
||||
case GameModes.CLASSIC:
|
||||
case GameModes.CHALLENGE:
|
||||
return 5000;
|
||||
case GameModes.DAILY:
|
||||
return 2500;
|
||||
default:
|
||||
return 0;
|
||||
case GameModes.CLASSIC:
|
||||
case GameModes.CHALLENGE:
|
||||
return 5000;
|
||||
case GameModes.DAILY:
|
||||
return 2500;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
getEnemyModifierChance(isBoss: boolean): integer {
|
||||
switch (this.modeId) {
|
||||
case GameModes.CLASSIC:
|
||||
case GameModes.CHALLENGE:
|
||||
case GameModes.DAILY:
|
||||
return !isBoss ? 18 : 6;
|
||||
case GameModes.ENDLESS:
|
||||
case GameModes.SPLICED_ENDLESS:
|
||||
return !isBoss ? 12 : 4;
|
||||
case GameModes.CLASSIC:
|
||||
case GameModes.CHALLENGE:
|
||||
case GameModes.DAILY:
|
||||
return !isBoss ? 18 : 6;
|
||||
case GameModes.ENDLESS:
|
||||
case GameModes.SPLICED_ENDLESS:
|
||||
return !isBoss ? 12 : 4;
|
||||
}
|
||||
}
|
||||
|
||||
getName(): string {
|
||||
switch (this.modeId) {
|
||||
case GameModes.CLASSIC:
|
||||
return i18next.t("gameMode:classic");
|
||||
case GameModes.ENDLESS:
|
||||
return i18next.t("gameMode:endless");
|
||||
case GameModes.SPLICED_ENDLESS:
|
||||
return i18next.t("gameMode:endlessSpliced");
|
||||
case GameModes.DAILY:
|
||||
return i18next.t("gameMode:dailyRun");
|
||||
case GameModes.CHALLENGE:
|
||||
return i18next.t("gameMode:challenge");
|
||||
case GameModes.CLASSIC:
|
||||
return i18next.t("gameMode:classic");
|
||||
case GameModes.ENDLESS:
|
||||
return i18next.t("gameMode:endless");
|
||||
case GameModes.SPLICED_ENDLESS:
|
||||
return i18next.t("gameMode:endlessSpliced");
|
||||
case GameModes.DAILY:
|
||||
return i18next.t("gameMode:dailyRun");
|
||||
case GameModes.CHALLENGE:
|
||||
return i18next.t("gameMode:challenge");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -329,42 +329,42 @@ export class GameMode implements GameModeConfig {
|
|||
*/
|
||||
getMysteryEncounterLegalWaves(): [number, number] {
|
||||
switch (this.modeId) {
|
||||
default:
|
||||
return [ 0, 0 ];
|
||||
case GameModes.CLASSIC:
|
||||
return CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES;
|
||||
case GameModes.CHALLENGE:
|
||||
return CHALLENGE_MODE_MYSTERY_ENCOUNTER_WAVES;
|
||||
default:
|
||||
return [ 0, 0 ];
|
||||
case GameModes.CLASSIC:
|
||||
return CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES;
|
||||
case GameModes.CHALLENGE:
|
||||
return CHALLENGE_MODE_MYSTERY_ENCOUNTER_WAVES;
|
||||
}
|
||||
}
|
||||
|
||||
static getModeName(modeId: GameModes): string {
|
||||
switch (modeId) {
|
||||
case GameModes.CLASSIC:
|
||||
return i18next.t("gameMode:classic");
|
||||
case GameModes.ENDLESS:
|
||||
return i18next.t("gameMode:endless");
|
||||
case GameModes.SPLICED_ENDLESS:
|
||||
return i18next.t("gameMode:endlessSpliced");
|
||||
case GameModes.DAILY:
|
||||
return i18next.t("gameMode:dailyRun");
|
||||
case GameModes.CHALLENGE:
|
||||
return i18next.t("gameMode:challenge");
|
||||
case GameModes.CLASSIC:
|
||||
return i18next.t("gameMode:classic");
|
||||
case GameModes.ENDLESS:
|
||||
return i18next.t("gameMode:endless");
|
||||
case GameModes.SPLICED_ENDLESS:
|
||||
return i18next.t("gameMode:endlessSpliced");
|
||||
case GameModes.DAILY:
|
||||
return i18next.t("gameMode:dailyRun");
|
||||
case GameModes.CHALLENGE:
|
||||
return i18next.t("gameMode:challenge");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getGameMode(gameMode: GameModes): GameMode {
|
||||
switch (gameMode) {
|
||||
case GameModes.CLASSIC:
|
||||
return new GameMode(GameModes.CLASSIC, { isClassic: true, hasTrainers: true, hasMysteryEncounters: true }, classicFixedBattles);
|
||||
case GameModes.ENDLESS:
|
||||
return new GameMode(GameModes.ENDLESS, { isEndless: true, hasShortBiomes: true, hasRandomBosses: true });
|
||||
case GameModes.SPLICED_ENDLESS:
|
||||
return new GameMode(GameModes.SPLICED_ENDLESS, { isEndless: true, hasShortBiomes: true, hasRandomBosses: true, isSplicedOnly: true });
|
||||
case GameModes.DAILY:
|
||||
return new GameMode(GameModes.DAILY, { isDaily: true, hasTrainers: true, hasNoShop: true });
|
||||
case GameModes.CHALLENGE:
|
||||
return new GameMode(GameModes.CHALLENGE, { isClassic: true, hasTrainers: true, isChallenge: true, hasMysteryEncounters: true }, classicFixedBattles);
|
||||
case GameModes.CLASSIC:
|
||||
return new GameMode(GameModes.CLASSIC, { isClassic: true, hasTrainers: true, hasMysteryEncounters: true }, classicFixedBattles);
|
||||
case GameModes.ENDLESS:
|
||||
return new GameMode(GameModes.ENDLESS, { isEndless: true, hasShortBiomes: true, hasRandomBosses: true });
|
||||
case GameModes.SPLICED_ENDLESS:
|
||||
return new GameMode(GameModes.SPLICED_ENDLESS, { isEndless: true, hasShortBiomes: true, hasRandomBosses: true, isSplicedOnly: true });
|
||||
case GameModes.DAILY:
|
||||
return new GameMode(GameModes.DAILY, { isDaily: true, hasTrainers: true, hasNoShop: true });
|
||||
case GameModes.CHALLENGE:
|
||||
return new GameMode(GameModes.CHALLENGE, { isClassic: true, hasTrainers: true, isChallenge: true, hasMysteryEncounters: true }, classicFixedBattles);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -477,18 +477,18 @@ export class LoadingScene extends SceneBase {
|
|||
this.load.on(this.LOAD_EVENTS.FILE_COMPLETE, (key: string) => {
|
||||
assetText.setText(i18next.t("menu:loadingAsset", { assetName: key }));
|
||||
switch (key) {
|
||||
case "loading_bg":
|
||||
bg.setTexture("loading_bg");
|
||||
if (mobile) {
|
||||
bg.setVisible(true);
|
||||
}
|
||||
break;
|
||||
case "logo":
|
||||
logo.setTexture("logo");
|
||||
if (mobile) {
|
||||
logo.setVisible(true);
|
||||
}
|
||||
break;
|
||||
case "loading_bg":
|
||||
bg.setTexture("loading_bg");
|
||||
if (mobile) {
|
||||
bg.setVisible(true);
|
||||
}
|
||||
break;
|
||||
case "logo":
|
||||
logo.setTexture("logo");
|
||||
if (mobile) {
|
||||
logo.setVisible(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -13,21 +13,21 @@ export function getPokemonNameWithAffix(pokemon: Pokemon | undefined): string {
|
|||
}
|
||||
|
||||
switch (pokemon.scene.currentBattle.battleSpec) {
|
||||
case BattleSpec.DEFAULT:
|
||||
return !pokemon.isPlayer()
|
||||
? pokemon.hasTrainer()
|
||||
? i18next.t("battle:foePokemonWithAffix", {
|
||||
pokemonName: pokemon.getNameToRender(),
|
||||
})
|
||||
: i18next.t("battle:wildPokemonWithAffix", {
|
||||
pokemonName: pokemon.getNameToRender(),
|
||||
})
|
||||
: pokemon.getNameToRender();
|
||||
case BattleSpec.FINAL_BOSS:
|
||||
return !pokemon.isPlayer()
|
||||
? i18next.t("battle:foePokemonWithAffix", { pokemonName: pokemon.getNameToRender() })
|
||||
: pokemon.getNameToRender();
|
||||
default:
|
||||
return pokemon.getNameToRender();
|
||||
case BattleSpec.DEFAULT:
|
||||
return !pokemon.isPlayer()
|
||||
? pokemon.hasTrainer()
|
||||
? i18next.t("battle:foePokemonWithAffix", {
|
||||
pokemonName: pokemon.getNameToRender(),
|
||||
})
|
||||
: i18next.t("battle:wildPokemonWithAffix", {
|
||||
pokemonName: pokemon.getNameToRender(),
|
||||
})
|
||||
: pokemon.getNameToRender();
|
||||
case BattleSpec.FINAL_BOSS:
|
||||
return !pokemon.isPlayer()
|
||||
? i18next.t("battle:foePokemonWithAffix", { pokemonName: pokemon.getNameToRender() })
|
||||
: pokemon.getNameToRender();
|
||||
default:
|
||||
return pokemon.getNameToRender();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,18 +78,18 @@ export class ModifierType {
|
|||
}
|
||||
let poolTypes: ModifierPoolType[];
|
||||
switch (poolType) {
|
||||
case ModifierPoolType.PLAYER:
|
||||
poolTypes = [ poolType, ModifierPoolType.TRAINER, ModifierPoolType.WILD ];
|
||||
break;
|
||||
case ModifierPoolType.WILD:
|
||||
poolTypes = [ poolType, ModifierPoolType.PLAYER, ModifierPoolType.TRAINER ];
|
||||
break;
|
||||
case ModifierPoolType.TRAINER:
|
||||
poolTypes = [ poolType, ModifierPoolType.PLAYER, ModifierPoolType.WILD ];
|
||||
break;
|
||||
default:
|
||||
poolTypes = [ poolType ];
|
||||
break;
|
||||
case ModifierPoolType.PLAYER:
|
||||
poolTypes = [ poolType, ModifierPoolType.TRAINER, ModifierPoolType.WILD ];
|
||||
break;
|
||||
case ModifierPoolType.WILD:
|
||||
poolTypes = [ poolType, ModifierPoolType.PLAYER, ModifierPoolType.TRAINER ];
|
||||
break;
|
||||
case ModifierPoolType.TRAINER:
|
||||
poolTypes = [ poolType, ModifierPoolType.PLAYER, ModifierPoolType.WILD ];
|
||||
break;
|
||||
default:
|
||||
poolTypes = [ poolType ];
|
||||
break;
|
||||
}
|
||||
// Try multiple pool types in case of stolen items
|
||||
for (const type of poolTypes) {
|
||||
|
@ -502,42 +502,42 @@ export class BerryModifierType extends PokemonHeldItemModifierType implements Ge
|
|||
|
||||
function getAttackTypeBoosterItemName(type: Type) {
|
||||
switch (type) {
|
||||
case Type.NORMAL:
|
||||
return "Silk Scarf";
|
||||
case Type.FIGHTING:
|
||||
return "Black Belt";
|
||||
case Type.FLYING:
|
||||
return "Sharp Beak";
|
||||
case Type.POISON:
|
||||
return "Poison Barb";
|
||||
case Type.GROUND:
|
||||
return "Soft Sand";
|
||||
case Type.ROCK:
|
||||
return "Hard Stone";
|
||||
case Type.BUG:
|
||||
return "Silver Powder";
|
||||
case Type.GHOST:
|
||||
return "Spell Tag";
|
||||
case Type.STEEL:
|
||||
return "Metal Coat";
|
||||
case Type.FIRE:
|
||||
return "Charcoal";
|
||||
case Type.WATER:
|
||||
return "Mystic Water";
|
||||
case Type.GRASS:
|
||||
return "Miracle Seed";
|
||||
case Type.ELECTRIC:
|
||||
return "Magnet";
|
||||
case Type.PSYCHIC:
|
||||
return "Twisted Spoon";
|
||||
case Type.ICE:
|
||||
return "Never-Melt Ice";
|
||||
case Type.DRAGON:
|
||||
return "Dragon Fang";
|
||||
case Type.DARK:
|
||||
return "Black Glasses";
|
||||
case Type.FAIRY:
|
||||
return "Fairy Feather";
|
||||
case Type.NORMAL:
|
||||
return "Silk Scarf";
|
||||
case Type.FIGHTING:
|
||||
return "Black Belt";
|
||||
case Type.FLYING:
|
||||
return "Sharp Beak";
|
||||
case Type.POISON:
|
||||
return "Poison Barb";
|
||||
case Type.GROUND:
|
||||
return "Soft Sand";
|
||||
case Type.ROCK:
|
||||
return "Hard Stone";
|
||||
case Type.BUG:
|
||||
return "Silver Powder";
|
||||
case Type.GHOST:
|
||||
return "Spell Tag";
|
||||
case Type.STEEL:
|
||||
return "Metal Coat";
|
||||
case Type.FIRE:
|
||||
return "Charcoal";
|
||||
case Type.WATER:
|
||||
return "Mystic Water";
|
||||
case Type.GRASS:
|
||||
return "Miracle Seed";
|
||||
case Type.ELECTRIC:
|
||||
return "Magnet";
|
||||
case Type.PSYCHIC:
|
||||
return "Twisted Spoon";
|
||||
case Type.ICE:
|
||||
return "Never-Melt Ice";
|
||||
case Type.DRAGON:
|
||||
return "Dragon Fang";
|
||||
case Type.DARK:
|
||||
return "Black Glasses";
|
||||
case Type.FAIRY:
|
||||
return "Fairy Feather";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1126,7 +1126,7 @@ class EvolutionItemModifierTypeGenerator extends ModifierTypeGenerator {
|
|||
}
|
||||
|
||||
class FormChangeItemModifierTypeGenerator extends ModifierTypeGenerator {
|
||||
constructor(rare: boolean) {
|
||||
constructor(isRareFormChangeItem: boolean) {
|
||||
super((party: Pokemon[], pregenArgs?: any[]) => {
|
||||
if (pregenArgs && (pregenArgs.length === 1) && (pregenArgs[0] in FormChangeItem)) {
|
||||
return new FormChangeItemModifierType(pregenArgs[0] as FormChangeItem);
|
||||
|
@ -1149,15 +1149,15 @@ class FormChangeItemModifierTypeGenerator extends ModifierTypeGenerator {
|
|||
foundN_SOLAR = false;
|
||||
formChangeItemTriggers.forEach((fc, i) => {
|
||||
switch (fc.item) {
|
||||
case FormChangeItem.ULTRANECROZIUM_Z:
|
||||
foundULTRA_Z = true;
|
||||
break;
|
||||
case FormChangeItem.N_LUNARIZER:
|
||||
foundN_LUNA = true;
|
||||
break;
|
||||
case FormChangeItem.N_SOLARIZER:
|
||||
foundN_SOLAR = true;
|
||||
break;
|
||||
case FormChangeItem.ULTRANECROZIUM_Z:
|
||||
foundULTRA_Z = true;
|
||||
break;
|
||||
case FormChangeItem.N_LUNARIZER:
|
||||
foundN_LUNA = true;
|
||||
break;
|
||||
case FormChangeItem.N_SOLARIZER:
|
||||
foundN_SOLAR = true;
|
||||
break;
|
||||
}
|
||||
});
|
||||
if (foundULTRA_Z && foundN_LUNA && foundN_SOLAR) {
|
||||
|
@ -1167,7 +1167,7 @@ class FormChangeItemModifierTypeGenerator extends ModifierTypeGenerator {
|
|||
}
|
||||
return formChangeItemTriggers;
|
||||
}).flat())
|
||||
].flat().flatMap(fc => fc.item).filter(i => (i && i < 100) === rare);
|
||||
].flat().flatMap(fc => fc.item).filter(i => (i && i < 100) === isRareFormChangeItem);
|
||||
// convert it into a set to remove duplicate values, which can appear when the same species with a potential form change is in the party.
|
||||
|
||||
if (!formChangeItemPool.length) {
|
||||
|
@ -1975,21 +1975,21 @@ let enemyBuffIgnoredPoolIndexes = {}; // eslint-disable-line @typescript-eslint/
|
|||
export function getModifierPoolForType(poolType: ModifierPoolType): ModifierPool {
|
||||
let pool: ModifierPool;
|
||||
switch (poolType) {
|
||||
case ModifierPoolType.PLAYER:
|
||||
pool = modifierPool;
|
||||
break;
|
||||
case ModifierPoolType.WILD:
|
||||
pool = wildModifierPool;
|
||||
break;
|
||||
case ModifierPoolType.TRAINER:
|
||||
pool = trainerModifierPool;
|
||||
break;
|
||||
case ModifierPoolType.ENEMY_BUFF:
|
||||
pool = enemyBuffModifierPool;
|
||||
break;
|
||||
case ModifierPoolType.DAILY_STARTER:
|
||||
pool = dailyStarterModifierPool;
|
||||
break;
|
||||
case ModifierPoolType.PLAYER:
|
||||
pool = modifierPool;
|
||||
break;
|
||||
case ModifierPoolType.WILD:
|
||||
pool = wildModifierPool;
|
||||
break;
|
||||
case ModifierPoolType.TRAINER:
|
||||
pool = trainerModifierPool;
|
||||
break;
|
||||
case ModifierPoolType.ENEMY_BUFF:
|
||||
pool = enemyBuffModifierPool;
|
||||
break;
|
||||
case ModifierPoolType.DAILY_STARTER:
|
||||
pool = dailyStarterModifierPool;
|
||||
break;
|
||||
}
|
||||
return pool;
|
||||
}
|
||||
|
@ -2060,23 +2060,23 @@ export function regenerateModifierPoolThresholds(party: Pokemon[], poolType: Mod
|
|||
console.table(modifierTableData);
|
||||
}
|
||||
switch (poolType) {
|
||||
case ModifierPoolType.PLAYER:
|
||||
modifierPoolThresholds = thresholds;
|
||||
ignoredPoolIndexes = ignoredIndexes;
|
||||
break;
|
||||
case ModifierPoolType.WILD:
|
||||
case ModifierPoolType.TRAINER:
|
||||
enemyModifierPoolThresholds = thresholds;
|
||||
enemyIgnoredPoolIndexes = ignoredIndexes;
|
||||
break;
|
||||
case ModifierPoolType.ENEMY_BUFF:
|
||||
enemyBuffModifierPoolThresholds = thresholds;
|
||||
enemyBuffIgnoredPoolIndexes = ignoredIndexes;
|
||||
break;
|
||||
case ModifierPoolType.DAILY_STARTER:
|
||||
dailyStarterModifierPoolThresholds = thresholds;
|
||||
ignoredDailyStarterPoolIndexes = ignoredIndexes;
|
||||
break;
|
||||
case ModifierPoolType.PLAYER:
|
||||
modifierPoolThresholds = thresholds;
|
||||
ignoredPoolIndexes = ignoredIndexes;
|
||||
break;
|
||||
case ModifierPoolType.WILD:
|
||||
case ModifierPoolType.TRAINER:
|
||||
enemyModifierPoolThresholds = thresholds;
|
||||
enemyIgnoredPoolIndexes = ignoredIndexes;
|
||||
break;
|
||||
case ModifierPoolType.ENEMY_BUFF:
|
||||
enemyBuffModifierPoolThresholds = thresholds;
|
||||
enemyBuffIgnoredPoolIndexes = ignoredIndexes;
|
||||
break;
|
||||
case ModifierPoolType.DAILY_STARTER:
|
||||
dailyStarterModifierPoolThresholds = thresholds;
|
||||
ignoredDailyStarterPoolIndexes = ignoredIndexes;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2247,15 +2247,15 @@ export function getPlayerShopModifierTypeOptionsForWave(waveIndex: integer, base
|
|||
export function getEnemyBuffModifierForWave(tier: ModifierTier, enemyModifiers: PersistentModifier[], scene: BattleScene): EnemyPersistentModifier {
|
||||
let tierStackCount: number;
|
||||
switch (tier) {
|
||||
case ModifierTier.ULTRA:
|
||||
tierStackCount = 5;
|
||||
break;
|
||||
case ModifierTier.GREAT:
|
||||
tierStackCount = 3;
|
||||
break;
|
||||
default:
|
||||
tierStackCount = 1;
|
||||
break;
|
||||
case ModifierTier.ULTRA:
|
||||
tierStackCount = 5;
|
||||
break;
|
||||
case ModifierTier.GREAT:
|
||||
tierStackCount = 3;
|
||||
break;
|
||||
default:
|
||||
tierStackCount = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
const retryCount = 50;
|
||||
|
@ -2321,21 +2321,21 @@ function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType,
|
|||
const pool = getModifierPoolForType(poolType);
|
||||
let thresholds: object;
|
||||
switch (poolType) {
|
||||
case ModifierPoolType.PLAYER:
|
||||
thresholds = modifierPoolThresholds;
|
||||
break;
|
||||
case ModifierPoolType.WILD:
|
||||
thresholds = enemyModifierPoolThresholds;
|
||||
break;
|
||||
case ModifierPoolType.TRAINER:
|
||||
thresholds = enemyModifierPoolThresholds;
|
||||
break;
|
||||
case ModifierPoolType.ENEMY_BUFF:
|
||||
thresholds = enemyBuffModifierPoolThresholds;
|
||||
break;
|
||||
case ModifierPoolType.DAILY_STARTER:
|
||||
thresholds = dailyStarterModifierPoolThresholds;
|
||||
break;
|
||||
case ModifierPoolType.PLAYER:
|
||||
thresholds = modifierPoolThresholds;
|
||||
break;
|
||||
case ModifierPoolType.WILD:
|
||||
thresholds = enemyModifierPoolThresholds;
|
||||
break;
|
||||
case ModifierPoolType.TRAINER:
|
||||
thresholds = enemyModifierPoolThresholds;
|
||||
break;
|
||||
case ModifierPoolType.ENEMY_BUFF:
|
||||
thresholds = enemyBuffModifierPoolThresholds;
|
||||
break;
|
||||
case ModifierPoolType.DAILY_STARTER:
|
||||
thresholds = dailyStarterModifierPoolThresholds;
|
||||
break;
|
||||
}
|
||||
if (tier === undefined) {
|
||||
const tierValue = randSeedInt(1024);
|
||||
|
|
|
@ -1695,12 +1695,12 @@ export class TurnStatusEffectModifier extends PokemonHeldItemModifier {
|
|||
super(type, pokemonId, stackCount);
|
||||
|
||||
switch (type.id) {
|
||||
case "TOXIC_ORB":
|
||||
this.effect = StatusEffect.TOXIC;
|
||||
break;
|
||||
case "FLAME_ORB":
|
||||
this.effect = StatusEffect.BURN;
|
||||
break;
|
||||
case "TOXIC_ORB":
|
||||
this.effect = StatusEffect.TOXIC;
|
||||
break;
|
||||
case "FLAME_ORB":
|
||||
this.effect = StatusEffect.BURN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2181,7 +2181,7 @@ export class PokemonNatureChangeModifier extends ConsumablePokemonModifier {
|
|||
* @returns
|
||||
*/
|
||||
override apply(playerPokemon: PlayerPokemon): boolean {
|
||||
playerPokemon.natureOverride = this.nature;
|
||||
playerPokemon.customPokemonData.nature = this.nature;
|
||||
let speciesId = playerPokemon.species.speciesId;
|
||||
playerPokemon.scene.gameData.dexData[speciesId].natureAttr |= 1 << (this.nature + 1);
|
||||
|
||||
|
@ -2684,15 +2684,15 @@ export class PokemonMultiHitModifier extends PokemonHeldItemModifier {
|
|||
count.value *= (this.getStackCount() + 1);
|
||||
|
||||
switch (this.getStackCount()) {
|
||||
case 1:
|
||||
power.value *= 0.4;
|
||||
break;
|
||||
case 2:
|
||||
power.value *= 0.25;
|
||||
break;
|
||||
case 3:
|
||||
power.value *= 0.175;
|
||||
break;
|
||||
case 1:
|
||||
power.value *= 0.4;
|
||||
break;
|
||||
case 2:
|
||||
power.value *= 0.25;
|
||||
break;
|
||||
case 3:
|
||||
power.value *= 0.175;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -113,8 +113,8 @@ class DefaultOverrides {
|
|||
readonly STATUS_OVERRIDE: StatusEffect = StatusEffect.NONE;
|
||||
readonly GENDER_OVERRIDE: Gender | null = null;
|
||||
readonly MOVESET_OVERRIDE: Moves | Array<Moves> = [];
|
||||
readonly SHINY_OVERRIDE: boolean = false;
|
||||
readonly VARIANT_OVERRIDE: Variant = 0;
|
||||
readonly SHINY_OVERRIDE: boolean | null = null;
|
||||
readonly VARIANT_OVERRIDE: Variant | null = null;
|
||||
|
||||
// --------------------------
|
||||
// OPPONENT / ENEMY OVERRIDES
|
||||
|
@ -134,8 +134,8 @@ class DefaultOverrides {
|
|||
readonly OPP_STATUS_OVERRIDE: StatusEffect = StatusEffect.NONE;
|
||||
readonly OPP_GENDER_OVERRIDE: Gender | null = null;
|
||||
readonly OPP_MOVESET_OVERRIDE: Moves | Array<Moves> = [];
|
||||
readonly OPP_SHINY_OVERRIDE: boolean = false;
|
||||
readonly OPP_VARIANT_OVERRIDE: Variant = 0;
|
||||
readonly OPP_SHINY_OVERRIDE: boolean | null = null;
|
||||
readonly OPP_VARIANT_OVERRIDE: Variant | null = null;
|
||||
readonly OPP_IVS_OVERRIDE: number | number[] = [];
|
||||
readonly OPP_FORM_OVERRIDES: Partial<Record<Species, number>> = {};
|
||||
/**
|
||||
|
|
|
@ -84,182 +84,182 @@ export class CommandPhase extends FieldPhase {
|
|||
let success: boolean;
|
||||
|
||||
switch (command) {
|
||||
case Command.FIGHT:
|
||||
let useStruggle = false;
|
||||
const turnMove: TurnMove | undefined = (args.length === 2 ? (args[1] as TurnMove) : undefined);
|
||||
if (cursor === -1 ||
|
||||
case Command.FIGHT:
|
||||
let useStruggle = false;
|
||||
const turnMove: TurnMove | undefined = (args.length === 2 ? (args[1] as TurnMove) : undefined);
|
||||
if (cursor === -1 ||
|
||||
playerPokemon.trySelectMove(cursor, args[0] as boolean) ||
|
||||
(useStruggle = cursor > -1 && !playerPokemon.getMoveset().filter(m => m?.isUsable(playerPokemon)).length)) {
|
||||
|
||||
let moveId: Moves;
|
||||
if (useStruggle) {
|
||||
moveId = Moves.STRUGGLE;
|
||||
} else if (turnMove !== undefined) {
|
||||
moveId = turnMove.move;
|
||||
} else if (cursor > -1) {
|
||||
moveId = playerPokemon.getMoveset()[cursor]!.moveId;
|
||||
} else {
|
||||
moveId = Moves.NONE;
|
||||
}
|
||||
let moveId: Moves;
|
||||
if (useStruggle) {
|
||||
moveId = Moves.STRUGGLE;
|
||||
} else if (turnMove !== undefined) {
|
||||
moveId = turnMove.move;
|
||||
} else if (cursor > -1) {
|
||||
moveId = playerPokemon.getMoveset()[cursor]!.moveId;
|
||||
} else {
|
||||
moveId = Moves.NONE;
|
||||
}
|
||||
|
||||
const turnCommand: TurnCommand = { command: Command.FIGHT, cursor: cursor, move: { move: moveId, targets: [], ignorePP: args[0] }, args: args };
|
||||
const moveTargets: MoveTargetSet = turnMove === undefined ? getMoveTargets(playerPokemon, moveId) : { targets: turnMove.targets, multiple: turnMove.targets.length > 1 };
|
||||
if (!moveId) {
|
||||
turnCommand.targets = [ this.fieldIndex ];
|
||||
}
|
||||
console.log(moveTargets, getPokemonNameWithAffix(playerPokemon));
|
||||
if (moveTargets.targets.length > 1 && moveTargets.multiple) {
|
||||
this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex));
|
||||
}
|
||||
if (moveTargets.targets.length <= 1 || moveTargets.multiple) {
|
||||
const turnCommand: TurnCommand = { command: Command.FIGHT, cursor: cursor, move: { move: moveId, targets: [], ignorePP: args[0] }, args: args };
|
||||
const moveTargets: MoveTargetSet = turnMove === undefined ? getMoveTargets(playerPokemon, moveId) : { targets: turnMove.targets, multiple: turnMove.targets.length > 1 };
|
||||
if (!moveId) {
|
||||
turnCommand.targets = [ this.fieldIndex ];
|
||||
}
|
||||
console.log(moveTargets, getPokemonNameWithAffix(playerPokemon));
|
||||
if (moveTargets.targets.length > 1 && moveTargets.multiple) {
|
||||
this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex));
|
||||
}
|
||||
if (moveTargets.targets.length <= 1 || moveTargets.multiple) {
|
||||
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?
|
||||
} else {
|
||||
this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex));
|
||||
}
|
||||
this.scene.currentBattle.turnCommands[this.fieldIndex] = turnCommand;
|
||||
success = true;
|
||||
} else if (cursor < playerPokemon.getMoveset().length) {
|
||||
const move = playerPokemon.getMoveset()[cursor]!; //TODO: is this bang correct?
|
||||
this.scene.ui.setMode(Mode.MESSAGE);
|
||||
} else {
|
||||
this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex));
|
||||
}
|
||||
this.scene.currentBattle.turnCommands[this.fieldIndex] = turnCommand;
|
||||
success = true;
|
||||
} else if (cursor < playerPokemon.getMoveset().length) {
|
||||
const move = playerPokemon.getMoveset()[cursor]!; //TODO: is this bang correct?
|
||||
this.scene.ui.setMode(Mode.MESSAGE);
|
||||
|
||||
// Decides between a Disabled, Not Implemented, or No PP translation message
|
||||
const errorMessage =
|
||||
// Decides between a Disabled, Not Implemented, or No PP translation message
|
||||
const errorMessage =
|
||||
playerPokemon.isMoveRestricted(move.moveId, playerPokemon)
|
||||
? playerPokemon.getRestrictingTag(move.moveId, playerPokemon)!.selectionDeniedText(playerPokemon, move.moveId)
|
||||
: 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.clearText();
|
||||
this.scene.ui.setMode(Mode.FIGHT, this.fieldIndex);
|
||||
}, null, true);
|
||||
}
|
||||
break;
|
||||
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);
|
||||
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.showText(i18next.t(errorMessage, { moveName: moveName }), null, () => {
|
||||
this.scene.ui.clearText();
|
||||
this.scene.ui.setMode(Mode.FIGHT, this.fieldIndex);
|
||||
}, null, true);
|
||||
}
|
||||
break;
|
||||
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);
|
||||
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:noPokeballMulti"), null, () => {
|
||||
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 (cursor < 5) {
|
||||
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) {
|
||||
} 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.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.setMode(Mode.COMMAND, this.fieldIndex);
|
||||
}, null, true);
|
||||
} else {
|
||||
this.scene.currentBattle.turnCommands[this.fieldIndex] = { command: Command.BALL, cursor: cursor };
|
||||
} else if (cursor < 5) {
|
||||
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;
|
||||
if (this.fieldIndex) {
|
||||
this.scene.currentBattle.turnCommands[this.fieldIndex - 1]!.skip = true;
|
||||
}
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Command.POKEMON:
|
||||
case Command.RUN:
|
||||
const isSwitch = command === Command.POKEMON;
|
||||
const { currentBattle, arena } = this.scene;
|
||||
const mysteryEncounterFleeAllowed = currentBattle.mysteryEncounter?.fleeAllowed;
|
||||
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);
|
||||
break;
|
||||
case Command.POKEMON:
|
||||
case Command.RUN:
|
||||
const isSwitch = command === Command.POKEMON;
|
||||
const { currentBattle, arena } = this.scene;
|
||||
const mysteryEncounterFleeAllowed = currentBattle.mysteryEncounter?.fleeAllowed;
|
||||
if (!isSwitch && (arena.biomeType === Biome.END || (!isNullOrUndefined(mysteryEncounterFleeAllowed) && !mysteryEncounterFleeAllowed))) {
|
||||
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);
|
||||
} 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.setMode(Mode.MESSAGE);
|
||||
this.scene.ui.showText(i18next.t("battle:noEscapeForce"), null, () => {
|
||||
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);
|
||||
} else {
|
||||
const trapTag = playerPokemon.getTag(TrappedTag);
|
||||
|
||||
// trapTag should be defined at this point, but just in case...
|
||||
if (!trapTag) {
|
||||
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 };
|
||||
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,
|
||||
() => {
|
||||
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);
|
||||
if (!isSwitch) {
|
||||
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
|
||||
}
|
||||
}, 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?
|
||||
|
|
|
@ -41,16 +41,16 @@ export class DamagePhase extends PokemonPhase {
|
|||
|
||||
applyDamage() {
|
||||
switch (this.damageResult) {
|
||||
case HitResult.EFFECTIVE:
|
||||
this.scene.playSound("se/hit");
|
||||
break;
|
||||
case HitResult.SUPER_EFFECTIVE:
|
||||
case HitResult.ONE_HIT_KO:
|
||||
this.scene.playSound("se/hit_strong");
|
||||
break;
|
||||
case HitResult.NOT_VERY_EFFECTIVE:
|
||||
this.scene.playSound("se/hit_weak");
|
||||
break;
|
||||
case HitResult.EFFECTIVE:
|
||||
this.scene.playSound("se/hit");
|
||||
break;
|
||||
case HitResult.SUPER_EFFECTIVE:
|
||||
case HitResult.ONE_HIT_KO:
|
||||
this.scene.playSound("se/hit_strong");
|
||||
break;
|
||||
case HitResult.NOT_VERY_EFFECTIVE:
|
||||
this.scene.playSound("se/hit_weak");
|
||||
break;
|
||||
}
|
||||
|
||||
if (this.amount) {
|
||||
|
|
|
@ -35,6 +35,7 @@ import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-d
|
|||
import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases";
|
||||
import { getGoldenBugNetSpecies } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
import { Biome } from "#enums/biome";
|
||||
import { WEIGHT_INCREMENT_ON_SPAWN_MISS } from "#app/data/mystery-encounters/mystery-encounters";
|
||||
|
||||
export class EncounterPhase extends BattlePhase {
|
||||
private loaded: boolean;
|
||||
|
@ -68,7 +69,7 @@ export class EncounterPhase extends BattlePhase {
|
|||
this.scene.executeWithSeedOffset(() => {
|
||||
const currentSessionEncounterType = battle.mysteryEncounterType;
|
||||
battle.mysteryEncounter = this.scene.getMysteryEncounter(currentSessionEncounterType);
|
||||
}, battle.waveIndex << 4);
|
||||
}, battle.waveIndex * 16);
|
||||
}
|
||||
const mysteryEncounter = battle.mysteryEncounter;
|
||||
if (mysteryEncounter) {
|
||||
|
@ -251,6 +252,13 @@ export class EncounterPhase extends BattlePhase {
|
|||
this.scene.updateModifiers(true);
|
||||
}*/
|
||||
|
||||
const { battleType, waveIndex } = this.scene.currentBattle;
|
||||
if (this.scene.isMysteryEncounterValidForWave(battleType, waveIndex) && !this.scene.currentBattle.isBattleMysteryEncounter()) {
|
||||
// Increment ME spawn chance if an ME could have spawned but did not
|
||||
// Only do this AFTER session has been saved to avoid duplicating increments
|
||||
this.scene.mysteryEncounterSaveData.encounterSpawnChance += WEIGHT_INCREMENT_ON_SPAWN_MISS;
|
||||
}
|
||||
|
||||
for (const pokemon of this.scene.getParty()) {
|
||||
if (pokemon) {
|
||||
pokemon.resetBattleData();
|
||||
|
@ -494,31 +502,31 @@ export class EncounterPhase extends BattlePhase {
|
|||
|
||||
tryOverrideForBattleSpec(): boolean {
|
||||
switch (this.scene.currentBattle.battleSpec) {
|
||||
case BattleSpec.FINAL_BOSS:
|
||||
const enemy = this.scene.getEnemyPokemon();
|
||||
this.scene.ui.showText(this.getEncounterMessage(), null, () => {
|
||||
const localizationKey = "battleSpecDialogue:encounter";
|
||||
if (this.scene.ui.shouldSkipDialogue(localizationKey)) {
|
||||
case BattleSpec.FINAL_BOSS:
|
||||
const enemy = this.scene.getEnemyPokemon();
|
||||
this.scene.ui.showText(this.getEncounterMessage(), null, () => {
|
||||
const localizationKey = "battleSpecDialogue:encounter";
|
||||
if (this.scene.ui.shouldSkipDialogue(localizationKey)) {
|
||||
// Logging mirrors logging found in dialogue-ui-handler
|
||||
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, () => {
|
||||
console.log(`Dialogue ${localizationKey} skipped`);
|
||||
this.doEncounterCommon(false);
|
||||
});
|
||||
}
|
||||
}, 1500, true);
|
||||
return true;
|
||||
} 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);
|
||||
});
|
||||
}
|
||||
}, 1500, true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -179,19 +179,19 @@ export class FaintPhase extends PokemonPhase {
|
|||
|
||||
tryOverrideForBattleSpec(): boolean {
|
||||
switch (this.scene.currentBattle.battleSpec) {
|
||||
case BattleSpec.FINAL_BOSS:
|
||||
if (!this.player) {
|
||||
const enemy = this.getPokemon();
|
||||
if (enemy.formIndex) {
|
||||
this.scene.ui.showDialogue(battleSpecDialogue[BattleSpec.FINAL_BOSS].secondStageWin, enemy.species.name, null, () => this.doFaint());
|
||||
} else {
|
||||
case BattleSpec.FINAL_BOSS:
|
||||
if (!this.player) {
|
||||
const enemy = this.getPokemon();
|
||||
if (enemy.formIndex) {
|
||||
this.scene.ui.showDialogue(battleSpecDialogue[BattleSpec.FINAL_BOSS].secondStageWin, enemy.species.name, null, () => this.doFaint());
|
||||
} else {
|
||||
// Final boss' HP threshold has been bypassed; cancel faint and force check for 2nd phase
|
||||
enemy.hp++;
|
||||
this.scene.unshiftPhase(new DamagePhase(this.scene, enemy.getBattlerIndex(), 0, HitResult.OTHER));
|
||||
this.end();
|
||||
enemy.hp++;
|
||||
this.scene.unshiftPhase(new DamagePhase(this.scene, enemy.getBattlerIndex(), 0, HitResult.OTHER));
|
||||
this.end();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -170,13 +170,16 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
|
|||
pokemon.setMove(index, this.moveId);
|
||||
initMoveAnim(this.scene, this.moveId).then(() => {
|
||||
loadMoveAnimAssets(this.scene, [ this.moveId ], true);
|
||||
this.scene.playSound("level_up_fanfare"); // Sound loaded into game as is
|
||||
});
|
||||
this.scene.ui.setMode(this.messageMode);
|
||||
const learnMoveText = i18next.t("battle:learnMove", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name });
|
||||
textMessage = textMessage ? textMessage + "$" + learnMoveText : learnMoveText;
|
||||
await this.scene.ui.showTextPromise(textMessage, this.messageMode === Mode.EVOLUTION_SCENE ? 1000 : undefined, true);
|
||||
this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeMoveLearnedTrigger, true);
|
||||
this.end();
|
||||
if (textMessage) {
|
||||
await this.scene.ui.showTextPromise(textMessage);
|
||||
}
|
||||
this.scene.playSound("level_up_fanfare"); // Sound loaded into game as is
|
||||
this.scene.ui.showText(learnMoveText, null, () => {
|
||||
this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeMoveLearnedTrigger, true);
|
||||
this.end();
|
||||
}, this.messageMode === Mode.EVOLUTION_SCENE ? 1000 : undefined, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -167,23 +167,23 @@ export class MovePhase extends BattlePhase {
|
|||
let healed = false;
|
||||
|
||||
switch (this.pokemon.status.effect) {
|
||||
case StatusEffect.PARALYSIS:
|
||||
if (!this.pokemon.randSeedInt(4)) {
|
||||
activated = true;
|
||||
this.cancelled = true;
|
||||
}
|
||||
break;
|
||||
case StatusEffect.SLEEP:
|
||||
applyMoveAttrs(BypassSleepAttr, this.pokemon, null, this.move.getMove());
|
||||
healed = this.pokemon.status.turnCount === this.pokemon.status.cureTurn;
|
||||
activated = !healed && !this.pokemon.getTag(BattlerTagType.BYPASS_SLEEP);
|
||||
this.cancelled = activated;
|
||||
break;
|
||||
case StatusEffect.FREEZE:
|
||||
healed = !!this.move.getMove().findAttr(attr => attr instanceof HealStatusEffectAttr && attr.selfTarget && attr.isOfEffect(StatusEffect.FREEZE)) || !this.pokemon.randSeedInt(5);
|
||||
activated = !healed;
|
||||
this.cancelled = activated;
|
||||
break;
|
||||
case StatusEffect.PARALYSIS:
|
||||
if (!this.pokemon.randSeedInt(4)) {
|
||||
activated = true;
|
||||
this.cancelled = true;
|
||||
}
|
||||
break;
|
||||
case StatusEffect.SLEEP:
|
||||
applyMoveAttrs(BypassSleepAttr, this.pokemon, null, this.move.getMove());
|
||||
healed = this.pokemon.status.turnCount === this.pokemon.status.cureTurn;
|
||||
activated = !healed && !this.pokemon.getTag(BattlerTagType.BYPASS_SLEEP);
|
||||
this.cancelled = activated;
|
||||
break;
|
||||
case StatusEffect.FREEZE:
|
||||
healed = !!this.move.getMove().findAttr(attr => attr instanceof HealStatusEffectAttr && attr.selfTarget && attr.isOfEffect(StatusEffect.FREEZE)) || !this.pokemon.randSeedInt(5);
|
||||
activated = !healed;
|
||||
this.cancelled = activated;
|
||||
break;
|
||||
}
|
||||
|
||||
if (activated) {
|
||||
|
|
|
@ -402,7 +402,7 @@ export class MysteryEncounterBattlePhase extends Phase {
|
|||
}
|
||||
}
|
||||
|
||||
const availablePartyMembers = scene.getParty().filter(p => !p.isFainted());
|
||||
const availablePartyMembers = scene.getParty().filter(p => p.isAllowedInBattle());
|
||||
|
||||
if (!availablePartyMembers[0].isOnField()) {
|
||||
scene.pushPhase(new SummonPhase(scene, 0));
|
||||
|
|
|
@ -25,20 +25,20 @@ export class PokemonAnimPhase extends BattlePhase {
|
|||
super.start();
|
||||
|
||||
switch (this.key) {
|
||||
case PokemonAnimType.SUBSTITUTE_ADD:
|
||||
this.doSubstituteAddAnim();
|
||||
break;
|
||||
case PokemonAnimType.SUBSTITUTE_PRE_MOVE:
|
||||
this.doSubstitutePreMoveAnim();
|
||||
break;
|
||||
case PokemonAnimType.SUBSTITUTE_POST_MOVE:
|
||||
this.doSubstitutePostMoveAnim();
|
||||
break;
|
||||
case PokemonAnimType.SUBSTITUTE_REMOVE:
|
||||
this.doSubstituteRemoveAnim();
|
||||
break;
|
||||
default:
|
||||
this.end();
|
||||
case PokemonAnimType.SUBSTITUTE_ADD:
|
||||
this.doSubstituteAddAnim();
|
||||
break;
|
||||
case PokemonAnimType.SUBSTITUTE_PRE_MOVE:
|
||||
this.doSubstitutePreMoveAnim();
|
||||
break;
|
||||
case PokemonAnimType.SUBSTITUTE_POST_MOVE:
|
||||
this.doSubstitutePostMoveAnim();
|
||||
break;
|
||||
case PokemonAnimType.SUBSTITUTE_REMOVE:
|
||||
this.doSubstituteRemoveAnim();
|
||||
break;
|
||||
default:
|
||||
this.end();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,16 +26,16 @@ export class PostTurnStatusEffectPhase extends PokemonPhase {
|
|||
this.scene.queueMessage(getStatusEffectActivationText(pokemon.status.effect, getPokemonNameWithAffix(pokemon)));
|
||||
const damage = new Utils.NumberHolder(0);
|
||||
switch (pokemon.status.effect) {
|
||||
case StatusEffect.POISON:
|
||||
damage.value = Math.max(pokemon.getMaxHp() >> 3, 1);
|
||||
break;
|
||||
case StatusEffect.TOXIC:
|
||||
damage.value = Math.max(Math.floor((pokemon.getMaxHp() / 16) * pokemon.status.turnCount), 1);
|
||||
break;
|
||||
case StatusEffect.BURN:
|
||||
damage.value = Math.max(pokemon.getMaxHp() >> 4, 1);
|
||||
applyAbAttrs(ReduceBurnDamageAbAttr, pokemon, null, false, damage);
|
||||
break;
|
||||
case StatusEffect.POISON:
|
||||
damage.value = Math.max(pokemon.getMaxHp() >> 3, 1);
|
||||
break;
|
||||
case StatusEffect.TOXIC:
|
||||
damage.value = Math.max(Math.floor((pokemon.getMaxHp() / 16) * pokemon.status.turnCount), 1);
|
||||
break;
|
||||
case StatusEffect.BURN:
|
||||
damage.value = Math.max(pokemon.getMaxHp() >> 4, 1);
|
||||
applyAbAttrs(ReduceBurnDamageAbAttr, pokemon, null, false, damage);
|
||||
break;
|
||||
}
|
||||
if (damage.value) {
|
||||
// Set preventEndure flag to avoid pokemon surviving thanks to focus band, sturdy, endure ...
|
||||
|
|
|
@ -77,78 +77,78 @@ export class SelectModifierPhase extends BattlePhase {
|
|||
let cost: integer;
|
||||
const rerollCost = this.getRerollCost(this.scene.lockModifierTiers);
|
||||
switch (rowCursor) {
|
||||
case 0:
|
||||
switch (cursor) {
|
||||
case 0:
|
||||
if (rerollCost < 0 || this.scene.money < rerollCost) {
|
||||
this.scene.ui.playError();
|
||||
return false;
|
||||
} else {
|
||||
this.scene.reroll = true;
|
||||
this.scene.unshiftPhase(new SelectModifierPhase(this.scene, this.rerollCount + 1, this.typeOptions.map(o => o.type?.tier).filter(t => t !== undefined) as ModifierTier[]));
|
||||
this.scene.ui.clearText();
|
||||
this.scene.ui.setMode(Mode.MESSAGE).then(() => super.end());
|
||||
if (!Overrides.WAIVE_ROLL_FEE_OVERRIDE) {
|
||||
this.scene.money -= rerollCost;
|
||||
this.scene.updateMoneyText();
|
||||
this.scene.animateMoneyChanged(false);
|
||||
}
|
||||
this.scene.playSound("se/buy");
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
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
|
||||
switch (cursor) {
|
||||
case 0:
|
||||
if (rerollCost < 0 || this.scene.money < rerollCost) {
|
||||
this.scene.ui.playError();
|
||||
return false;
|
||||
} else {
|
||||
this.scene.reroll = true;
|
||||
this.scene.unshiftPhase(new SelectModifierPhase(this.scene, this.rerollCount + 1, this.typeOptions.map(o => o.type?.tier).filter(t => t !== undefined) as ModifierTier[]));
|
||||
this.scene.ui.clearText();
|
||||
this.scene.ui.setMode(Mode.MESSAGE).then(() => super.end());
|
||||
if (!Overrides.WAIVE_ROLL_FEE_OVERRIDE) {
|
||||
this.scene.money -= rerollCost;
|
||||
this.scene.updateMoneyText();
|
||||
this.scene.animateMoneyChanged(false);
|
||||
}
|
||||
this.scene.playSound("se/buy");
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
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[];
|
||||
const itemModifier = itemModifiers[itemIndex];
|
||||
this.scene.tryTransferHeldItemModifier(itemModifier, party[toSlotIndex], true, itemQuantity);
|
||||
} else {
|
||||
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), this.typeOptions, modifierSelectCallback, this.getRerollCost(this.scene.lockModifierTiers));
|
||||
}
|
||||
}, PartyUiHandler.FilterItemMaxStacks);
|
||||
break;
|
||||
case 2:
|
||||
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));
|
||||
});
|
||||
break;
|
||||
case 3:
|
||||
if (rerollCost < 0) {
|
||||
// Reroll lock button is also disabled when reroll is disabled
|
||||
this.scene.ui.playError();
|
||||
return false;
|
||||
const itemModifier = itemModifiers[itemIndex];
|
||||
this.scene.tryTransferHeldItemModifier(itemModifier, party[toSlotIndex], true, itemQuantity);
|
||||
} else {
|
||||
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), this.typeOptions, modifierSelectCallback, this.getRerollCost(this.scene.lockModifierTiers));
|
||||
}
|
||||
}, PartyUiHandler.FilterItemMaxStacks);
|
||||
break;
|
||||
case 2:
|
||||
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));
|
||||
});
|
||||
break;
|
||||
case 3:
|
||||
if (rerollCost < 0) {
|
||||
// Reroll lock button is also disabled when reroll is disabled
|
||||
this.scene.ui.playError();
|
||||
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;
|
||||
}
|
||||
if (this.typeOptions[cursor].type) {
|
||||
modifierType = this.typeOptions[cursor].type;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
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 (shopOption.type) {
|
||||
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;
|
||||
case 1:
|
||||
if (this.typeOptions.length === 0) {
|
||||
this.scene.ui.clearText();
|
||||
this.scene.ui.setMode(Mode.MESSAGE);
|
||||
super.end();
|
||||
return true;
|
||||
}
|
||||
if (this.typeOptions[cursor].type) {
|
||||
modifierType = this.typeOptions[cursor].type;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
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 (shopOption.type) {
|
||||
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?
|
||||
|
|
|
@ -152,55 +152,55 @@ export class TurnStartPhase extends FieldPhase {
|
|||
}
|
||||
|
||||
switch (turnCommand?.command) {
|
||||
case Command.FIGHT:
|
||||
const queuedMove = turnCommand.move;
|
||||
pokemon.turnData.order = orderIndex++;
|
||||
if (!queuedMove) {
|
||||
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);
|
||||
case Command.FIGHT:
|
||||
const queuedMove = turnCommand.move;
|
||||
pokemon.turnData.order = orderIndex++;
|
||||
if (!queuedMove) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
this.scene.pushPhase(new MovePhase(this.scene, pokemon, turnCommand.targets || turnCommand.move!.targets, move, false, queuedMove.ignorePP));//TODO: is the bang correct here?
|
||||
}
|
||||
break;
|
||||
case Command.BALL:
|
||||
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();
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
});
|
||||
// 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;
|
||||
} else {
|
||||
this.scene.pushPhase(new MovePhase(this.scene, pokemon, turnCommand.targets || turnCommand.move!.targets, move, false, queuedMove.ignorePP));//TODO: is the bang correct here?
|
||||
}
|
||||
}
|
||||
this.scene.unshiftPhase(new AttemptRunPhase(this.scene, runningPokemon.getFieldIndex()));
|
||||
break;
|
||||
break;
|
||||
case Command.BALL:
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -156,133 +156,133 @@ export function getAchievementDescription(localizationKey: string): string {
|
|||
const genderStr = PlayerGender[genderIndex].toLowerCase();
|
||||
|
||||
switch (localizationKey) {
|
||||
case "10K_MONEY":
|
||||
return i18next.t("achv:MoneyAchv.description", { context: genderStr, "moneyAmount": achvs._10K_MONEY.moneyAmount.toLocaleString("en-US") });
|
||||
case "100K_MONEY":
|
||||
return i18next.t("achv:MoneyAchv.description", { context: genderStr, "moneyAmount": achvs._100K_MONEY.moneyAmount.toLocaleString("en-US") });
|
||||
case "1M_MONEY":
|
||||
return i18next.t("achv:MoneyAchv.description", { context: genderStr, "moneyAmount": achvs._1M_MONEY.moneyAmount.toLocaleString("en-US") });
|
||||
case "10M_MONEY":
|
||||
return i18next.t("achv:MoneyAchv.description", { context: genderStr, "moneyAmount": achvs._10M_MONEY.moneyAmount.toLocaleString("en-US") });
|
||||
case "250_DMG":
|
||||
return i18next.t("achv:DamageAchv.description", { context: genderStr, "damageAmount": achvs._250_DMG.damageAmount.toLocaleString("en-US") });
|
||||
case "1000_DMG":
|
||||
return i18next.t("achv:DamageAchv.description", { context: genderStr, "damageAmount": achvs._1000_DMG.damageAmount.toLocaleString("en-US") });
|
||||
case "2500_DMG":
|
||||
return i18next.t("achv:DamageAchv.description", { context: genderStr, "damageAmount": achvs._2500_DMG.damageAmount.toLocaleString("en-US") });
|
||||
case "10000_DMG":
|
||||
return i18next.t("achv:DamageAchv.description", { context: genderStr, "damageAmount": achvs._10000_DMG.damageAmount.toLocaleString("en-US") });
|
||||
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)) });
|
||||
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)) });
|
||||
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)) });
|
||||
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)) });
|
||||
case "LV_100":
|
||||
return i18next.t("achv:LevelAchv.description", { context: genderStr, "level": achvs.LV_100.level });
|
||||
case "LV_250":
|
||||
return i18next.t("achv:LevelAchv.description", { context: genderStr, "level": achvs.LV_250.level });
|
||||
case "LV_1000":
|
||||
return i18next.t("achv:LevelAchv.description", { context: genderStr, "level": achvs.LV_1000.level });
|
||||
case "10_RIBBONS":
|
||||
return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._10_RIBBONS.ribbonAmount.toLocaleString("en-US") });
|
||||
case "25_RIBBONS":
|
||||
return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._25_RIBBONS.ribbonAmount.toLocaleString("en-US") });
|
||||
case "50_RIBBONS":
|
||||
return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._50_RIBBONS.ribbonAmount.toLocaleString("en-US") });
|
||||
case "75_RIBBONS":
|
||||
return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._75_RIBBONS.ribbonAmount.toLocaleString("en-US") });
|
||||
case "100_RIBBONS":
|
||||
return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._100_RIBBONS.ribbonAmount.toLocaleString("en-US") });
|
||||
case "TRANSFER_MAX_STAT_STAGE":
|
||||
return i18next.t("achv:TRANSFER_MAX_STAT_STAGE.description", { context: genderStr });
|
||||
case "MAX_FRIENDSHIP":
|
||||
return i18next.t("achv:MAX_FRIENDSHIP.description", { context: genderStr });
|
||||
case "MEGA_EVOLVE":
|
||||
return i18next.t("achv:MEGA_EVOLVE.description", { context: genderStr });
|
||||
case "GIGANTAMAX":
|
||||
return i18next.t("achv:GIGANTAMAX.description", { context: genderStr });
|
||||
case "TERASTALLIZE":
|
||||
return i18next.t("achv:TERASTALLIZE.description", { context: genderStr });
|
||||
case "STELLAR_TERASTALLIZE":
|
||||
return i18next.t("achv:STELLAR_TERASTALLIZE.description", { context: genderStr });
|
||||
case "SPLICE":
|
||||
return i18next.t("achv:SPLICE.description", { context: genderStr });
|
||||
case "MINI_BLACK_HOLE":
|
||||
return i18next.t("achv:MINI_BLACK_HOLE.description", { context: genderStr });
|
||||
case "CATCH_MYTHICAL":
|
||||
return i18next.t("achv:CATCH_MYTHICAL.description", { context: genderStr });
|
||||
case "CATCH_SUB_LEGENDARY":
|
||||
return i18next.t("achv:CATCH_SUB_LEGENDARY.description", { context: genderStr });
|
||||
case "CATCH_LEGENDARY":
|
||||
return i18next.t("achv:CATCH_LEGENDARY.description", { context: genderStr });
|
||||
case "SEE_SHINY":
|
||||
return i18next.t("achv:SEE_SHINY.description", { context: genderStr });
|
||||
case "SHINY_PARTY":
|
||||
return i18next.t("achv:SHINY_PARTY.description", { context: genderStr });
|
||||
case "HATCH_MYTHICAL":
|
||||
return i18next.t("achv:HATCH_MYTHICAL.description", { context: genderStr });
|
||||
case "HATCH_SUB_LEGENDARY":
|
||||
return i18next.t("achv:HATCH_SUB_LEGENDARY.description", { context: genderStr });
|
||||
case "HATCH_LEGENDARY":
|
||||
return i18next.t("achv:HATCH_LEGENDARY.description", { context: genderStr });
|
||||
case "HATCH_SHINY":
|
||||
return i18next.t("achv:HATCH_SHINY.description", { context: genderStr });
|
||||
case "HIDDEN_ABILITY":
|
||||
return i18next.t("achv:HIDDEN_ABILITY.description", { context: genderStr });
|
||||
case "PERFECT_IVS":
|
||||
return i18next.t("achv:PERFECT_IVS.description", { context: genderStr });
|
||||
case "CLASSIC_VICTORY":
|
||||
return i18next.t("achv:CLASSIC_VICTORY.description", { context: genderStr });
|
||||
case "UNEVOLVED_CLASSIC_VICTORY":
|
||||
return i18next.t("achv:UNEVOLVED_CLASSIC_VICTORY.description", { context: genderStr });
|
||||
case "MONO_GEN_ONE":
|
||||
return i18next.t("achv:MONO_GEN_ONE.description", { context: genderStr });
|
||||
case "MONO_GEN_TWO":
|
||||
return i18next.t("achv:MONO_GEN_TWO.description", { context: genderStr });
|
||||
case "MONO_GEN_THREE":
|
||||
return i18next.t("achv:MONO_GEN_THREE.description", { context: genderStr });
|
||||
case "MONO_GEN_FOUR":
|
||||
return i18next.t("achv:MONO_GEN_FOUR.description", { context: genderStr });
|
||||
case "MONO_GEN_FIVE":
|
||||
return i18next.t("achv:MONO_GEN_FIVE.description", { context: genderStr });
|
||||
case "MONO_GEN_SIX":
|
||||
return i18next.t("achv:MONO_GEN_SIX.description", { context: genderStr });
|
||||
case "MONO_GEN_SEVEN":
|
||||
return i18next.t("achv:MONO_GEN_SEVEN.description", { context: genderStr });
|
||||
case "MONO_GEN_EIGHT":
|
||||
return i18next.t("achv:MONO_GEN_EIGHT.description", { context: genderStr });
|
||||
case "MONO_GEN_NINE":
|
||||
return i18next.t("achv:MONO_GEN_NINE.description", { context: genderStr });
|
||||
case "MONO_NORMAL":
|
||||
case "MONO_FIGHTING":
|
||||
case "MONO_FLYING":
|
||||
case "MONO_POISON":
|
||||
case "MONO_GROUND":
|
||||
case "MONO_ROCK":
|
||||
case "MONO_BUG":
|
||||
case "MONO_GHOST":
|
||||
case "MONO_STEEL":
|
||||
case "MONO_FIRE":
|
||||
case "MONO_WATER":
|
||||
case "MONO_GRASS":
|
||||
case "MONO_ELECTRIC":
|
||||
case "MONO_PSYCHIC":
|
||||
case "MONO_ICE":
|
||||
case "MONO_DRAGON":
|
||||
case "MONO_DARK":
|
||||
case "MONO_FAIRY":
|
||||
return i18next.t("achv:MonoType.description", { context: genderStr, "type": i18next.t(`pokemonInfo:Type.${localizationKey.slice(5)}`) });
|
||||
case "FRESH_START":
|
||||
return i18next.t("achv:FRESH_START.description", { context: genderStr });
|
||||
case "INVERSE_BATTLE":
|
||||
return i18next.t("achv:INVERSE_BATTLE.description", { context: genderStr });
|
||||
case "BREEDERS_IN_SPACE":
|
||||
return i18next.t("achv:BREEDERS_IN_SPACE.description", { context: genderStr });
|
||||
default:
|
||||
return "";
|
||||
case "10K_MONEY":
|
||||
return i18next.t("achv:MoneyAchv.description", { context: genderStr, "moneyAmount": achvs._10K_MONEY.moneyAmount.toLocaleString("en-US") });
|
||||
case "100K_MONEY":
|
||||
return i18next.t("achv:MoneyAchv.description", { context: genderStr, "moneyAmount": achvs._100K_MONEY.moneyAmount.toLocaleString("en-US") });
|
||||
case "1M_MONEY":
|
||||
return i18next.t("achv:MoneyAchv.description", { context: genderStr, "moneyAmount": achvs._1M_MONEY.moneyAmount.toLocaleString("en-US") });
|
||||
case "10M_MONEY":
|
||||
return i18next.t("achv:MoneyAchv.description", { context: genderStr, "moneyAmount": achvs._10M_MONEY.moneyAmount.toLocaleString("en-US") });
|
||||
case "250_DMG":
|
||||
return i18next.t("achv:DamageAchv.description", { context: genderStr, "damageAmount": achvs._250_DMG.damageAmount.toLocaleString("en-US") });
|
||||
case "1000_DMG":
|
||||
return i18next.t("achv:DamageAchv.description", { context: genderStr, "damageAmount": achvs._1000_DMG.damageAmount.toLocaleString("en-US") });
|
||||
case "2500_DMG":
|
||||
return i18next.t("achv:DamageAchv.description", { context: genderStr, "damageAmount": achvs._2500_DMG.damageAmount.toLocaleString("en-US") });
|
||||
case "10000_DMG":
|
||||
return i18next.t("achv:DamageAchv.description", { context: genderStr, "damageAmount": achvs._10000_DMG.damageAmount.toLocaleString("en-US") });
|
||||
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)) });
|
||||
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)) });
|
||||
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)) });
|
||||
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)) });
|
||||
case "LV_100":
|
||||
return i18next.t("achv:LevelAchv.description", { context: genderStr, "level": achvs.LV_100.level });
|
||||
case "LV_250":
|
||||
return i18next.t("achv:LevelAchv.description", { context: genderStr, "level": achvs.LV_250.level });
|
||||
case "LV_1000":
|
||||
return i18next.t("achv:LevelAchv.description", { context: genderStr, "level": achvs.LV_1000.level });
|
||||
case "10_RIBBONS":
|
||||
return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._10_RIBBONS.ribbonAmount.toLocaleString("en-US") });
|
||||
case "25_RIBBONS":
|
||||
return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._25_RIBBONS.ribbonAmount.toLocaleString("en-US") });
|
||||
case "50_RIBBONS":
|
||||
return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._50_RIBBONS.ribbonAmount.toLocaleString("en-US") });
|
||||
case "75_RIBBONS":
|
||||
return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._75_RIBBONS.ribbonAmount.toLocaleString("en-US") });
|
||||
case "100_RIBBONS":
|
||||
return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._100_RIBBONS.ribbonAmount.toLocaleString("en-US") });
|
||||
case "TRANSFER_MAX_STAT_STAGE":
|
||||
return i18next.t("achv:TRANSFER_MAX_STAT_STAGE.description", { context: genderStr });
|
||||
case "MAX_FRIENDSHIP":
|
||||
return i18next.t("achv:MAX_FRIENDSHIP.description", { context: genderStr });
|
||||
case "MEGA_EVOLVE":
|
||||
return i18next.t("achv:MEGA_EVOLVE.description", { context: genderStr });
|
||||
case "GIGANTAMAX":
|
||||
return i18next.t("achv:GIGANTAMAX.description", { context: genderStr });
|
||||
case "TERASTALLIZE":
|
||||
return i18next.t("achv:TERASTALLIZE.description", { context: genderStr });
|
||||
case "STELLAR_TERASTALLIZE":
|
||||
return i18next.t("achv:STELLAR_TERASTALLIZE.description", { context: genderStr });
|
||||
case "SPLICE":
|
||||
return i18next.t("achv:SPLICE.description", { context: genderStr });
|
||||
case "MINI_BLACK_HOLE":
|
||||
return i18next.t("achv:MINI_BLACK_HOLE.description", { context: genderStr });
|
||||
case "CATCH_MYTHICAL":
|
||||
return i18next.t("achv:CATCH_MYTHICAL.description", { context: genderStr });
|
||||
case "CATCH_SUB_LEGENDARY":
|
||||
return i18next.t("achv:CATCH_SUB_LEGENDARY.description", { context: genderStr });
|
||||
case "CATCH_LEGENDARY":
|
||||
return i18next.t("achv:CATCH_LEGENDARY.description", { context: genderStr });
|
||||
case "SEE_SHINY":
|
||||
return i18next.t("achv:SEE_SHINY.description", { context: genderStr });
|
||||
case "SHINY_PARTY":
|
||||
return i18next.t("achv:SHINY_PARTY.description", { context: genderStr });
|
||||
case "HATCH_MYTHICAL":
|
||||
return i18next.t("achv:HATCH_MYTHICAL.description", { context: genderStr });
|
||||
case "HATCH_SUB_LEGENDARY":
|
||||
return i18next.t("achv:HATCH_SUB_LEGENDARY.description", { context: genderStr });
|
||||
case "HATCH_LEGENDARY":
|
||||
return i18next.t("achv:HATCH_LEGENDARY.description", { context: genderStr });
|
||||
case "HATCH_SHINY":
|
||||
return i18next.t("achv:HATCH_SHINY.description", { context: genderStr });
|
||||
case "HIDDEN_ABILITY":
|
||||
return i18next.t("achv:HIDDEN_ABILITY.description", { context: genderStr });
|
||||
case "PERFECT_IVS":
|
||||
return i18next.t("achv:PERFECT_IVS.description", { context: genderStr });
|
||||
case "CLASSIC_VICTORY":
|
||||
return i18next.t("achv:CLASSIC_VICTORY.description", { context: genderStr });
|
||||
case "UNEVOLVED_CLASSIC_VICTORY":
|
||||
return i18next.t("achv:UNEVOLVED_CLASSIC_VICTORY.description", { context: genderStr });
|
||||
case "MONO_GEN_ONE":
|
||||
return i18next.t("achv:MONO_GEN_ONE.description", { context: genderStr });
|
||||
case "MONO_GEN_TWO":
|
||||
return i18next.t("achv:MONO_GEN_TWO.description", { context: genderStr });
|
||||
case "MONO_GEN_THREE":
|
||||
return i18next.t("achv:MONO_GEN_THREE.description", { context: genderStr });
|
||||
case "MONO_GEN_FOUR":
|
||||
return i18next.t("achv:MONO_GEN_FOUR.description", { context: genderStr });
|
||||
case "MONO_GEN_FIVE":
|
||||
return i18next.t("achv:MONO_GEN_FIVE.description", { context: genderStr });
|
||||
case "MONO_GEN_SIX":
|
||||
return i18next.t("achv:MONO_GEN_SIX.description", { context: genderStr });
|
||||
case "MONO_GEN_SEVEN":
|
||||
return i18next.t("achv:MONO_GEN_SEVEN.description", { context: genderStr });
|
||||
case "MONO_GEN_EIGHT":
|
||||
return i18next.t("achv:MONO_GEN_EIGHT.description", { context: genderStr });
|
||||
case "MONO_GEN_NINE":
|
||||
return i18next.t("achv:MONO_GEN_NINE.description", { context: genderStr });
|
||||
case "MONO_NORMAL":
|
||||
case "MONO_FIGHTING":
|
||||
case "MONO_FLYING":
|
||||
case "MONO_POISON":
|
||||
case "MONO_GROUND":
|
||||
case "MONO_ROCK":
|
||||
case "MONO_BUG":
|
||||
case "MONO_GHOST":
|
||||
case "MONO_STEEL":
|
||||
case "MONO_FIRE":
|
||||
case "MONO_WATER":
|
||||
case "MONO_GRASS":
|
||||
case "MONO_ELECTRIC":
|
||||
case "MONO_PSYCHIC":
|
||||
case "MONO_ICE":
|
||||
case "MONO_DRAGON":
|
||||
case "MONO_DARK":
|
||||
case "MONO_FAIRY":
|
||||
return i18next.t("achv:MonoType.description", { context: genderStr, "type": i18next.t(`pokemonInfo:Type.${localizationKey.slice(5)}`) });
|
||||
case "FRESH_START":
|
||||
return i18next.t("achv:FRESH_START.description", { context: genderStr });
|
||||
case "INVERSE_BATTLE":
|
||||
return i18next.t("achv:INVERSE_BATTLE.description", { context: genderStr });
|
||||
case "BREEDERS_IN_SPACE":
|
||||
return i18next.t("achv:BREEDERS_IN_SPACE.description", { context: genderStr });
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -67,22 +67,22 @@ const saveKey = "x0i2O7WRiANTqPmZ"; // Temporary; secure encryption is not yet n
|
|||
|
||||
export function getDataTypeKey(dataType: GameDataType, slotId: integer = 0): string {
|
||||
switch (dataType) {
|
||||
case GameDataType.SYSTEM:
|
||||
return "data";
|
||||
case GameDataType.SESSION:
|
||||
let ret = "sessionData";
|
||||
if (slotId) {
|
||||
ret += slotId;
|
||||
}
|
||||
return ret;
|
||||
case GameDataType.SETTINGS:
|
||||
return "settings";
|
||||
case GameDataType.TUTORIALS:
|
||||
return "tutorials";
|
||||
case GameDataType.SEEN_DIALOGUES:
|
||||
return "seenDialogues";
|
||||
case GameDataType.RUN_HISTORY:
|
||||
return "runHistoryData";
|
||||
case GameDataType.SYSTEM:
|
||||
return "data";
|
||||
case GameDataType.SESSION:
|
||||
let ret = "sessionData";
|
||||
if (slotId) {
|
||||
ret += slotId;
|
||||
}
|
||||
return ret;
|
||||
case GameDataType.SETTINGS:
|
||||
return "settings";
|
||||
case GameDataType.TUTORIALS:
|
||||
return "tutorials";
|
||||
case GameDataType.SEEN_DIALOGUES:
|
||||
return "seenDialogues";
|
||||
case GameDataType.RUN_HISTORY:
|
||||
return "runHistoryData";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1374,9 +1374,9 @@ export class GameData {
|
|||
const dataKey: string = `${getDataTypeKey(dataType, slotId)}_${loggedInUser?.username}`;
|
||||
const handleData = (dataStr: string) => {
|
||||
switch (dataType) {
|
||||
case GameDataType.SYSTEM:
|
||||
dataStr = this.convertSystemDataStr(dataStr, true);
|
||||
break;
|
||||
case GameDataType.SYSTEM:
|
||||
dataStr = this.convertSystemDataStr(dataStr, true);
|
||||
break;
|
||||
}
|
||||
const encryptedData = AES.encrypt(dataStr, saveKey);
|
||||
const blob = new Blob([ encryptedData.toString() ], { type: "text/json" });
|
||||
|
@ -1434,28 +1434,28 @@ export class GameData {
|
|||
try {
|
||||
dataName = GameDataType[dataType].toLowerCase();
|
||||
switch (dataType) {
|
||||
case GameDataType.SYSTEM:
|
||||
dataStr = this.convertSystemDataStr(dataStr);
|
||||
const systemData = this.parseSystemData(dataStr);
|
||||
valid = !!systemData.dexData && !!systemData.timestamp;
|
||||
break;
|
||||
case GameDataType.SESSION:
|
||||
const sessionData = this.parseSessionData(dataStr);
|
||||
valid = !!sessionData.party && !!sessionData.enemyParty && !!sessionData.timestamp;
|
||||
break;
|
||||
case GameDataType.RUN_HISTORY:
|
||||
const data = JSON.parse(dataStr);
|
||||
const keys = Object.keys(data);
|
||||
dataName = i18next.t("menuUiHandler:RUN_HISTORY").toLowerCase();
|
||||
keys.forEach((key) => {
|
||||
const entryKeys = Object.keys(data[key]);
|
||||
valid = [ "isFavorite", "isVictory", "entry" ].every(v => entryKeys.includes(v)) && entryKeys.length === 3;
|
||||
});
|
||||
break;
|
||||
case GameDataType.SETTINGS:
|
||||
case GameDataType.TUTORIALS:
|
||||
valid = true;
|
||||
break;
|
||||
case GameDataType.SYSTEM:
|
||||
dataStr = this.convertSystemDataStr(dataStr);
|
||||
const systemData = this.parseSystemData(dataStr);
|
||||
valid = !!systemData.dexData && !!systemData.timestamp;
|
||||
break;
|
||||
case GameDataType.SESSION:
|
||||
const sessionData = this.parseSessionData(dataStr);
|
||||
valid = !!sessionData.party && !!sessionData.enemyParty && !!sessionData.timestamp;
|
||||
break;
|
||||
case GameDataType.RUN_HISTORY:
|
||||
const data = JSON.parse(dataStr);
|
||||
const keys = Object.keys(data);
|
||||
dataName = i18next.t("menuUiHandler:RUN_HISTORY").toLowerCase();
|
||||
keys.forEach((key) => {
|
||||
const entryKeys = Object.keys(data[key]);
|
||||
valid = [ "isFavorite", "isVictory", "entry" ].every(v => entryKeys.includes(v)) && entryKeys.length === 3;
|
||||
});
|
||||
break;
|
||||
case GameDataType.SETTINGS:
|
||||
case GameDataType.TUTORIALS:
|
||||
valid = true;
|
||||
break;
|
||||
}
|
||||
} catch (ex) {
|
||||
console.error(ex);
|
||||
|
|
|
@ -12,7 +12,7 @@ import { loadBattlerTag } from "../data/battler-tags";
|
|||
import { Biome } from "#enums/biome";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
||||
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||
|
||||
export default class PokemonData {
|
||||
public id: integer;
|
||||
|
@ -33,7 +33,6 @@ export default class PokemonData {
|
|||
public stats: integer[];
|
||||
public ivs: integer[];
|
||||
public nature: Nature;
|
||||
public natureOverride: Nature | -1;
|
||||
public moveset: (PokemonMove | null)[];
|
||||
public status: Status | null;
|
||||
public friendship: integer;
|
||||
|
@ -54,14 +53,20 @@ export default class PokemonData {
|
|||
public fusionVariant: Variant;
|
||||
public fusionGender: Gender;
|
||||
public fusionLuck: integer;
|
||||
public fusionMysteryEncounterPokemonData: MysteryEncounterPokemonData;
|
||||
|
||||
public boss: boolean;
|
||||
public bossSegments?: integer;
|
||||
|
||||
public summonData: PokemonSummonData;
|
||||
|
||||
/** Data that can customize a Pokemon in non-standard ways from its Species */
|
||||
public mysteryEncounterPokemonData: MysteryEncounterPokemonData;
|
||||
public customPokemonData: CustomPokemonData;
|
||||
public fusionCustomPokemonData: CustomPokemonData;
|
||||
|
||||
// Deprecated attributes, needed for now to allow SessionData migration (see PR#4619 comments)
|
||||
public natureOverride: Nature | -1;
|
||||
public mysteryEncounterPokemonData: CustomPokemonData | null;
|
||||
public fusionMysteryEncounterPokemonData: CustomPokemonData | null;
|
||||
|
||||
constructor(source: Pokemon | any, forHistory: boolean = false) {
|
||||
const sourcePokemon = source instanceof Pokemon ? source : null;
|
||||
|
@ -107,9 +112,13 @@ export default class PokemonData {
|
|||
this.fusionVariant = source.fusionVariant;
|
||||
this.fusionGender = source.fusionGender;
|
||||
this.fusionLuck = source.fusionLuck !== undefined ? source.fusionLuck : (source.fusionShiny ? source.fusionVariant + 1 : 0);
|
||||
this.fusionCustomPokemonData = new CustomPokemonData(source.fusionCustomPokemonData);
|
||||
this.usedTMs = source.usedTMs ?? [];
|
||||
|
||||
this.mysteryEncounterPokemonData = new MysteryEncounterPokemonData(source.mysteryEncounterPokemonData);
|
||||
this.customPokemonData = new CustomPokemonData(source.customPokemonData);
|
||||
|
||||
this.mysteryEncounterPokemonData = new CustomPokemonData(source.mysteryEncounterPokemonData);
|
||||
this.fusionMysteryEncounterPokemonData = new CustomPokemonData(source.fusionMysteryEncounterPokemonData);
|
||||
|
||||
if (!forHistory) {
|
||||
this.boss = (source instanceof EnemyPokemon && !!source.bossSegments) || (!this.player && !!source.boss);
|
||||
|
|
|
@ -82,66 +82,66 @@ export const settingGamepadBlackList = [
|
|||
|
||||
export function setSettingGamepad(scene: BattleScene, setting: SettingGamepad, value: integer): boolean {
|
||||
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
|
||||
// activate or deactivate the controller listener
|
||||
scene.inputController.setGamepadSupport(settingGamepadOptions[setting][value] !== "Disabled");
|
||||
break;
|
||||
case SettingGamepad.Button_Action:
|
||||
case SettingGamepad.Button_Cancel:
|
||||
case SettingGamepad.Button_Menu:
|
||||
case SettingGamepad.Button_Stats:
|
||||
case SettingGamepad.Button_Cycle_Shiny:
|
||||
case SettingGamepad.Button_Cycle_Form:
|
||||
case SettingGamepad.Button_Cycle_Gender:
|
||||
case SettingGamepad.Button_Cycle_Ability:
|
||||
case SettingGamepad.Button_Cycle_Nature:
|
||||
case SettingGamepad.Button_Cycle_Variant:
|
||||
case SettingGamepad.Button_Speed_Up:
|
||||
case SettingGamepad.Button_Slow_Down:
|
||||
case SettingGamepad.Button_Submit:
|
||||
if (value) {
|
||||
if (scene.ui) {
|
||||
const cancelHandler = (success: boolean = false) : boolean => {
|
||||
scene.ui.revertMode();
|
||||
(scene.ui.getHandler() as SettingsGamepadUiHandler).updateBindings();
|
||||
return success;
|
||||
};
|
||||
scene.ui.setOverlayMode(Mode.GAMEPAD_BINDING, {
|
||||
target: setting,
|
||||
cancelHandler: cancelHandler,
|
||||
});
|
||||
scene.inputController.setGamepadSupport(settingGamepadOptions[setting][value] !== "Disabled");
|
||||
break;
|
||||
case SettingGamepad.Button_Action:
|
||||
case SettingGamepad.Button_Cancel:
|
||||
case SettingGamepad.Button_Menu:
|
||||
case SettingGamepad.Button_Stats:
|
||||
case SettingGamepad.Button_Cycle_Shiny:
|
||||
case SettingGamepad.Button_Cycle_Form:
|
||||
case SettingGamepad.Button_Cycle_Gender:
|
||||
case SettingGamepad.Button_Cycle_Ability:
|
||||
case SettingGamepad.Button_Cycle_Nature:
|
||||
case SettingGamepad.Button_Cycle_Variant:
|
||||
case SettingGamepad.Button_Speed_Up:
|
||||
case SettingGamepad.Button_Slow_Down:
|
||||
case SettingGamepad.Button_Submit:
|
||||
if (value) {
|
||||
if (scene.ui) {
|
||||
const cancelHandler = (success: boolean = false) : boolean => {
|
||||
scene.ui.revertMode();
|
||||
(scene.ui.getHandler() as SettingsGamepadUiHandler).updateBindings();
|
||||
return success;
|
||||
};
|
||||
scene.ui.setOverlayMode(Mode.GAMEPAD_BINDING, {
|
||||
target: setting,
|
||||
cancelHandler: cancelHandler,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SettingGamepad.Controller:
|
||||
if (value) {
|
||||
const gp = scene.inputController.getGamepadsName();
|
||||
if (scene.ui && gp) {
|
||||
const cancelHandler = () => {
|
||||
scene.ui.revertMode();
|
||||
(scene.ui.getHandler() as SettingsGamepadUiHandler).setOptionCursor(Object.values(SettingGamepad).indexOf(SettingGamepad.Controller), 0, true);
|
||||
(scene.ui.getHandler() as SettingsGamepadUiHandler).updateBindings();
|
||||
break;
|
||||
case SettingGamepad.Controller:
|
||||
if (value) {
|
||||
const gp = scene.inputController.getGamepadsName();
|
||||
if (scene.ui && gp) {
|
||||
const cancelHandler = () => {
|
||||
scene.ui.revertMode();
|
||||
(scene.ui.getHandler() as SettingsGamepadUiHandler).setOptionCursor(Object.values(SettingGamepad).indexOf(SettingGamepad.Controller), 0, true);
|
||||
(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;
|
||||
};
|
||||
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;
|
||||
|
|
|
@ -135,53 +135,53 @@ export const settingKeyboardBlackList = [
|
|||
|
||||
export function setSettingKeyboard(scene: BattleScene, setting: SettingKeyboard, value: integer): boolean {
|
||||
switch (setting) {
|
||||
case SettingKeyboard.Button_Up:
|
||||
case SettingKeyboard.Button_Down:
|
||||
case SettingKeyboard.Button_Left:
|
||||
case SettingKeyboard.Button_Right:
|
||||
case SettingKeyboard.Button_Action:
|
||||
case SettingKeyboard.Button_Cancel:
|
||||
case SettingKeyboard.Button_Menu:
|
||||
case SettingKeyboard.Button_Stats:
|
||||
case SettingKeyboard.Button_Cycle_Shiny:
|
||||
case SettingKeyboard.Button_Cycle_Form:
|
||||
case SettingKeyboard.Button_Cycle_Gender:
|
||||
case SettingKeyboard.Button_Cycle_Ability:
|
||||
case SettingKeyboard.Button_Cycle_Nature:
|
||||
case SettingKeyboard.Button_Cycle_Variant:
|
||||
case SettingKeyboard.Button_Speed_Up:
|
||||
case SettingKeyboard.Button_Slow_Down:
|
||||
case SettingKeyboard.Alt_Button_Up:
|
||||
case SettingKeyboard.Alt_Button_Down:
|
||||
case SettingKeyboard.Alt_Button_Left:
|
||||
case SettingKeyboard.Alt_Button_Right:
|
||||
case SettingKeyboard.Alt_Button_Action:
|
||||
case SettingKeyboard.Alt_Button_Cancel:
|
||||
case SettingKeyboard.Alt_Button_Menu:
|
||||
case SettingKeyboard.Alt_Button_Stats:
|
||||
case SettingKeyboard.Alt_Button_Cycle_Shiny:
|
||||
case SettingKeyboard.Alt_Button_Cycle_Form:
|
||||
case SettingKeyboard.Alt_Button_Cycle_Gender:
|
||||
case SettingKeyboard.Alt_Button_Cycle_Ability:
|
||||
case SettingKeyboard.Alt_Button_Cycle_Nature:
|
||||
case SettingKeyboard.Alt_Button_Cycle_Variant:
|
||||
case SettingKeyboard.Alt_Button_Speed_Up:
|
||||
case SettingKeyboard.Alt_Button_Slow_Down:
|
||||
case SettingKeyboard.Alt_Button_Submit:
|
||||
if (value) {
|
||||
if (scene.ui) {
|
||||
const cancelHandler = (success: boolean = false) : boolean => {
|
||||
scene.ui.revertMode();
|
||||
(scene.ui.getHandler() as SettingsKeyboardUiHandler).updateBindings();
|
||||
return success;
|
||||
};
|
||||
scene.ui.setOverlayMode(Mode.KEYBOARD_BINDING, {
|
||||
target: setting,
|
||||
cancelHandler: cancelHandler,
|
||||
});
|
||||
case SettingKeyboard.Button_Up:
|
||||
case SettingKeyboard.Button_Down:
|
||||
case SettingKeyboard.Button_Left:
|
||||
case SettingKeyboard.Button_Right:
|
||||
case SettingKeyboard.Button_Action:
|
||||
case SettingKeyboard.Button_Cancel:
|
||||
case SettingKeyboard.Button_Menu:
|
||||
case SettingKeyboard.Button_Stats:
|
||||
case SettingKeyboard.Button_Cycle_Shiny:
|
||||
case SettingKeyboard.Button_Cycle_Form:
|
||||
case SettingKeyboard.Button_Cycle_Gender:
|
||||
case SettingKeyboard.Button_Cycle_Ability:
|
||||
case SettingKeyboard.Button_Cycle_Nature:
|
||||
case SettingKeyboard.Button_Cycle_Variant:
|
||||
case SettingKeyboard.Button_Speed_Up:
|
||||
case SettingKeyboard.Button_Slow_Down:
|
||||
case SettingKeyboard.Alt_Button_Up:
|
||||
case SettingKeyboard.Alt_Button_Down:
|
||||
case SettingKeyboard.Alt_Button_Left:
|
||||
case SettingKeyboard.Alt_Button_Right:
|
||||
case SettingKeyboard.Alt_Button_Action:
|
||||
case SettingKeyboard.Alt_Button_Cancel:
|
||||
case SettingKeyboard.Alt_Button_Menu:
|
||||
case SettingKeyboard.Alt_Button_Stats:
|
||||
case SettingKeyboard.Alt_Button_Cycle_Shiny:
|
||||
case SettingKeyboard.Alt_Button_Cycle_Form:
|
||||
case SettingKeyboard.Alt_Button_Cycle_Gender:
|
||||
case SettingKeyboard.Alt_Button_Cycle_Ability:
|
||||
case SettingKeyboard.Alt_Button_Cycle_Nature:
|
||||
case SettingKeyboard.Alt_Button_Cycle_Variant:
|
||||
case SettingKeyboard.Alt_Button_Speed_Up:
|
||||
case SettingKeyboard.Alt_Button_Slow_Down:
|
||||
case SettingKeyboard.Alt_Button_Submit:
|
||||
if (value) {
|
||||
if (scene.ui) {
|
||||
const cancelHandler = (success: boolean = false) : boolean => {
|
||||
scene.ui.revertMode();
|
||||
(scene.ui.getHandler() as SettingsKeyboardUiHandler).updateBindings();
|
||||
return success;
|
||||
};
|
||||
scene.ui.setOverlayMode(Mode.KEYBOARD_BINDING, {
|
||||
target: setting,
|
||||
cancelHandler: cancelHandler,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
// case SettingKeyboard.Default_Layout:
|
||||
// if (value && scene.ui) {
|
||||
// const cancelHandler = () => {
|
||||
|
|
|
@ -76,16 +76,16 @@ const SHOP_CURSOR_TARGET_OPTIONS: SettingOption[] = [
|
|||
|
||||
const shopCursorTargetIndexMap = SHOP_CURSOR_TARGET_OPTIONS.map(option => {
|
||||
switch (option.value) {
|
||||
case "Rewards":
|
||||
return ShopCursorTarget.REWARDS;
|
||||
case "Shop":
|
||||
return ShopCursorTarget.SHOP;
|
||||
case "Reroll":
|
||||
return ShopCursorTarget.REROLL;
|
||||
case "Check Team":
|
||||
return ShopCursorTarget.CHECK_TEAM;
|
||||
default:
|
||||
throw new Error(`Unknown value: ${option.value}`);
|
||||
case "Rewards":
|
||||
return ShopCursorTarget.REWARDS;
|
||||
case "Shop":
|
||||
return ShopCursorTarget.SHOP;
|
||||
case "Reroll":
|
||||
return ShopCursorTarget.REROLL;
|
||||
case "Check Team":
|
||||
return ShopCursorTarget.CHECK_TEAM;
|
||||
default:
|
||||
throw new Error(`Unknown value: ${option.value}`);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -699,226 +699,226 @@ export function setSetting(scene: BattleScene, setting: string, value: integer):
|
|||
return false;
|
||||
}
|
||||
switch (Setting[index].key) {
|
||||
case SettingKeys.Game_Speed:
|
||||
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) {
|
||||
case SettingKeys.Game_Speed:
|
||||
scene.gameSpeed = parseFloat(Setting[index].options[value].value.replace("x", ""));
|
||||
break;
|
||||
}
|
||||
scene.candyUpgradeNotification = value;
|
||||
scene.eventTarget.dispatchEvent(new CandyUpgradeNotificationChangedEvent(value));
|
||||
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;
|
||||
case SettingKeys.Master_Volume:
|
||||
scene.masterVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0;
|
||||
scene.updateSoundVolume();
|
||||
break;
|
||||
case "Abbreviated":
|
||||
scene.moneyFormat = MoneyFormat.ABBREVIATED;
|
||||
case SettingKeys.BGM_Volume:
|
||||
scene.bgmVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0;
|
||||
scene.updateSoundVolume();
|
||||
break;
|
||||
}
|
||||
scene.updateMoneyText(false);
|
||||
break;
|
||||
case SettingKeys.Sprite_Set:
|
||||
scene.experimentalSprites = !!value;
|
||||
if (value) {
|
||||
scene.initExpSprites();
|
||||
}
|
||||
break;
|
||||
case SettingKeys.Move_Animations:
|
||||
scene.moveAnimations = Setting[index].options[value].value === "On";
|
||||
break;
|
||||
case SettingKeys.Show_Moveset_Flyout:
|
||||
scene.showMovesetFlyout = Setting[index].options[value].value === "On";
|
||||
break;
|
||||
case SettingKeys.Show_Arena_Flyout:
|
||||
scene.showArenaFlyout = Setting[index].options[value].value === "On";
|
||||
break;
|
||||
case SettingKeys.Show_Time_Of_Day_Widget:
|
||||
scene.showTimeOfDayWidget = Setting[index].options[value].value === "On";
|
||||
break;
|
||||
case SettingKeys.Time_Of_Day_Animation:
|
||||
scene.timeOfDayAnimation = Setting[index].options[value].value === "Bounce" ? EaseType.BOUNCE : EaseType.BACK;
|
||||
break;
|
||||
case SettingKeys.Show_Stats_on_Level_Up:
|
||||
scene.showLevelUpStats = Setting[index].options[value].value === "On";
|
||||
break;
|
||||
case SettingKeys.Shop_Cursor_Target:
|
||||
const selectedValue = shopCursorTargetIndexMap[value];
|
||||
scene.shopCursorTarget = selectedValue;
|
||||
break;
|
||||
case SettingKeys.EXP_Gains_Speed:
|
||||
scene.expGainsSpeed = value;
|
||||
break;
|
||||
case SettingKeys.EXP_Party_Display:
|
||||
scene.expParty = value;
|
||||
break;
|
||||
case SettingKeys.HP_Bar_Speed:
|
||||
scene.hpBarSpeed = value;
|
||||
break;
|
||||
case SettingKeys.Fusion_Palette_Swaps:
|
||||
scene.fusionPaletteSwaps = !!value;
|
||||
break;
|
||||
case SettingKeys.Player_Gender:
|
||||
if (scene.gameData) {
|
||||
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"));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case SettingKeys.Touch_Controls:
|
||||
scene.enableTouchControls = Setting[index].options[value].value !== "Disabled" && hasTouchscreen();
|
||||
const touchControls = document.getElementById("touchControls");
|
||||
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
|
||||
});
|
||||
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;
|
||||
}
|
||||
scene.candyUpgradeNotification = value;
|
||||
scene.eventTarget.dispatchEvent(new CandyUpgradeNotificationChangedEvent(value));
|
||||
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;
|
||||
case "Abbreviated":
|
||||
scene.moneyFormat = MoneyFormat.ABBREVIATED;
|
||||
break;
|
||||
}
|
||||
scene.updateMoneyText(false);
|
||||
break;
|
||||
case SettingKeys.Sprite_Set:
|
||||
scene.experimentalSprites = !!value;
|
||||
if (value) {
|
||||
scene.initExpSprites();
|
||||
}
|
||||
break;
|
||||
case SettingKeys.Move_Animations:
|
||||
scene.moveAnimations = Setting[index].options[value].value === "On";
|
||||
break;
|
||||
case SettingKeys.Show_Moveset_Flyout:
|
||||
scene.showMovesetFlyout = Setting[index].options[value].value === "On";
|
||||
break;
|
||||
case SettingKeys.Show_Arena_Flyout:
|
||||
scene.showArenaFlyout = Setting[index].options[value].value === "On";
|
||||
break;
|
||||
case SettingKeys.Show_Time_Of_Day_Widget:
|
||||
scene.showTimeOfDayWidget = Setting[index].options[value].value === "On";
|
||||
break;
|
||||
case SettingKeys.Time_Of_Day_Animation:
|
||||
scene.timeOfDayAnimation = Setting[index].options[value].value === "Bounce" ? EaseType.BOUNCE : EaseType.BACK;
|
||||
break;
|
||||
case SettingKeys.Show_Stats_on_Level_Up:
|
||||
scene.showLevelUpStats = Setting[index].options[value].value === "On";
|
||||
break;
|
||||
case SettingKeys.Shop_Cursor_Target:
|
||||
const selectedValue = shopCursorTargetIndexMap[value];
|
||||
scene.shopCursorTarget = selectedValue;
|
||||
break;
|
||||
case SettingKeys.EXP_Gains_Speed:
|
||||
scene.expGainsSpeed = value;
|
||||
break;
|
||||
case SettingKeys.EXP_Party_Display:
|
||||
scene.expParty = value;
|
||||
break;
|
||||
case SettingKeys.HP_Bar_Speed:
|
||||
scene.hpBarSpeed = value;
|
||||
break;
|
||||
case SettingKeys.Fusion_Palette_Swaps:
|
||||
scene.fusionPaletteSwaps = !!value;
|
||||
break;
|
||||
case SettingKeys.Player_Gender:
|
||||
if (scene.gameData) {
|
||||
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"));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SettingKeys.Shop_Overlay_Opacity:
|
||||
scene.updateShopOverlayOpacity(parseInt(Setting[index].options[value].value) * .01);
|
||||
break;
|
||||
break;
|
||||
case SettingKeys.Touch_Controls:
|
||||
scene.enableTouchControls = Setting[index].options[value].value !== "Disabled" && hasTouchscreen();
|
||||
const touchControls = document.getElementById("touchControls");
|
||||
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;
|
||||
|
|
|
@ -10,13 +10,13 @@ export enum Unlockables {
|
|||
|
||||
export function getUnlockableName(unlockable: Unlockables) {
|
||||
switch (unlockable) {
|
||||
case Unlockables.ENDLESS_MODE:
|
||||
return `${GameMode.getModeName(GameModes.ENDLESS)} Mode`;
|
||||
case Unlockables.MINI_BLACK_HOLE:
|
||||
return i18next.t("modifierType:ModifierType.MINI_BLACK_HOLE.name");
|
||||
case Unlockables.SPLICED_ENDLESS_MODE:
|
||||
return `${GameMode.getModeName(GameModes.SPLICED_ENDLESS)} Mode`;
|
||||
case Unlockables.EVIOLITE:
|
||||
return i18next.t("modifierType:ModifierType.EVIOLITE.name");
|
||||
case Unlockables.ENDLESS_MODE:
|
||||
return `${GameMode.getModeName(GameModes.ENDLESS)} Mode`;
|
||||
case Unlockables.MINI_BLACK_HOLE:
|
||||
return i18next.t("modifierType:ModifierType.MINI_BLACK_HOLE.name");
|
||||
case Unlockables.SPLICED_ENDLESS_MODE:
|
||||
return `${GameMode.getModeName(GameModes.SPLICED_ENDLESS)} Mode`;
|
||||
case Unlockables.EVIOLITE:
|
||||
return i18next.t("modifierType:ModifierType.EVIOLITE.name");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,9 @@ import { version } from "../../../package.json";
|
|||
// --- v1.0.4 (and below) PATCHES --- //
|
||||
import * as v1_0_4 from "./versions/v1_0_4";
|
||||
|
||||
// --- v1.1.0 PATCHES --- //
|
||||
import * as v1_1_0 from "./versions/v1_1_0";
|
||||
|
||||
const LATEST_VERSION = version.split(".").map(value => parseInt(value));
|
||||
|
||||
/**
|
||||
|
@ -131,6 +134,10 @@ class SessionVersionConverter extends VersionConverter {
|
|||
this.callMigrators(data, v1_0_4.sessionMigrators);
|
||||
}
|
||||
}
|
||||
if (curMinor <= 1) {
|
||||
console.log("Applying v1.1.0 session data migration!");
|
||||
this.callMigrators(data, v1_1_0.sessionMigrators);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Session data successfully migrated to v${version}!`);
|
||||
|
@ -153,6 +160,10 @@ class SystemVersionConverter extends VersionConverter {
|
|||
this.callMigrators(data, v1_0_4.systemMigrators);
|
||||
}
|
||||
}
|
||||
if (curMinor <= 1) {
|
||||
console.log("Applying v1.1.0 system data migraton!");
|
||||
this.callMigrators(data, v1_1_0.systemMigrators);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`System data successfully migrated to v${version}!`);
|
||||
|
@ -175,6 +186,10 @@ class SettingsVersionConverter extends VersionConverter {
|
|||
this.callMigrators(data, v1_0_4.settingsMigrators);
|
||||
}
|
||||
}
|
||||
if (curMinor <= 1) {
|
||||
console.log("Applying v1.1.0 settings data migraton!");
|
||||
this.callMigrators(data, v1_1_0.settingsMigrators);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`System data successfully migrated to v${version}!`);
|
||||
|
|
|
@ -108,15 +108,15 @@ export const sessionMigrators = [
|
|||
} 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;
|
||||
case "MAX_LURE":
|
||||
maxBattles = 30;
|
||||
break;
|
||||
case "SUPER_LURE":
|
||||
maxBattles = 15;
|
||||
break;
|
||||
default:
|
||||
maxBattles = 10;
|
||||
break;
|
||||
}
|
||||
|
||||
// From [ battlesLeft ] to [ maxBattles, battleCount ]
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
import { SessionSaveData } from "../../game-data";
|
||||
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||
|
||||
export const systemMigrators = [] as const;
|
||||
|
||||
export const settingsMigrators = [] as const;
|
||||
|
||||
export const sessionMigrators = [
|
||||
/**
|
||||
* Converts old Pokemon natureOverride and mysteryEncounterData
|
||||
* to use the new conjoined {@linkcode Pokemon.customPokemonData} structure instead.
|
||||
* @param data {@linkcode SessionSaveData}
|
||||
*/
|
||||
function migrateCustomPokemonDataAndNatureOverrides(data: SessionSaveData) {
|
||||
// Fix Pokemon nature overrides and custom data migration
|
||||
data.party.forEach(pokemon => {
|
||||
if (pokemon["mysteryEncounterPokemonData"]) {
|
||||
pokemon.customPokemonData = new CustomPokemonData(pokemon["mysteryEncounterPokemonData"]);
|
||||
pokemon["mysteryEncounterPokemonData"] = null;
|
||||
}
|
||||
if (pokemon["fusionMysteryEncounterPokemonData"]) {
|
||||
pokemon.fusionCustomPokemonData = new CustomPokemonData(pokemon["fusionMysteryEncounterPokemonData"]);
|
||||
pokemon["fusionMysteryEncounterPokemonData"] = null;
|
||||
}
|
||||
pokemon.customPokemonData = pokemon.customPokemonData ?? new CustomPokemonData();
|
||||
if (pokemon["natureOverride"] && pokemon["natureOverride"] >= 0) {
|
||||
pokemon.customPokemonData.nature = pokemon["natureOverride"];
|
||||
pokemon["natureOverride"] = -1;
|
||||
}
|
||||
});
|
||||
}
|
||||
] as const;
|
|
@ -45,41 +45,41 @@ export class Voucher {
|
|||
|
||||
getTier(): AchvTier {
|
||||
switch (this.voucherType) {
|
||||
case VoucherType.REGULAR:
|
||||
return AchvTier.COMMON;
|
||||
case VoucherType.PLUS:
|
||||
return AchvTier.GREAT;
|
||||
case VoucherType.PREMIUM:
|
||||
return AchvTier.ULTRA;
|
||||
case VoucherType.GOLDEN:
|
||||
return AchvTier.ROGUE;
|
||||
case VoucherType.REGULAR:
|
||||
return AchvTier.COMMON;
|
||||
case VoucherType.PLUS:
|
||||
return AchvTier.GREAT;
|
||||
case VoucherType.PREMIUM:
|
||||
return AchvTier.ULTRA;
|
||||
case VoucherType.GOLDEN:
|
||||
return AchvTier.ROGUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getVoucherTypeName(voucherType: VoucherType): string {
|
||||
switch (voucherType) {
|
||||
case VoucherType.REGULAR:
|
||||
return i18next.t("voucher:eggVoucher");
|
||||
case VoucherType.PLUS:
|
||||
return i18next.t("voucher:eggVoucherPlus");
|
||||
case VoucherType.PREMIUM:
|
||||
return i18next.t("voucher:eggVoucherPremium");
|
||||
case VoucherType.GOLDEN:
|
||||
return i18next.t("voucher:eggVoucherGold");
|
||||
case VoucherType.REGULAR:
|
||||
return i18next.t("voucher:eggVoucher");
|
||||
case VoucherType.PLUS:
|
||||
return i18next.t("voucher:eggVoucherPlus");
|
||||
case VoucherType.PREMIUM:
|
||||
return i18next.t("voucher:eggVoucherPremium");
|
||||
case VoucherType.GOLDEN:
|
||||
return i18next.t("voucher:eggVoucherGold");
|
||||
}
|
||||
}
|
||||
|
||||
export function getVoucherTypeIcon(voucherType: VoucherType): string {
|
||||
switch (voucherType) {
|
||||
case VoucherType.REGULAR:
|
||||
return "coupon";
|
||||
case VoucherType.PLUS:
|
||||
return "pair_of_tickets";
|
||||
case VoucherType.PREMIUM:
|
||||
return "mystic_ticket";
|
||||
case VoucherType.GOLDEN:
|
||||
return "golden_mystic_ticket";
|
||||
case VoucherType.REGULAR:
|
||||
return "coupon";
|
||||
case VoucherType.PLUS:
|
||||
return "pair_of_tickets";
|
||||
case VoucherType.PREMIUM:
|
||||
return "mystic_ticket";
|
||||
case VoucherType.GOLDEN:
|
||||
return "golden_mystic_ticket";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,8 +9,6 @@ import GameManager from "#test/utils/gameManager";
|
|||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||
|
||||
const TIMEOUT = 20 * 1000;
|
||||
|
||||
describe("Moves - Toxic Spikes", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
@ -34,10 +32,10 @@ describe("Moves - Toxic Spikes", () => {
|
|||
.enemyAbility(Abilities.BALL_FETCH)
|
||||
.ability(Abilities.BALL_FETCH)
|
||||
.enemyMoveset(Moves.SPLASH)
|
||||
.moveset([ Moves.TOXIC_SPIKES, Moves.SPLASH, Moves.ROAR ]);
|
||||
.moveset([ Moves.TOXIC_SPIKES, Moves.SPLASH, Moves.ROAR, Moves.COURT_CHANGE ]);
|
||||
});
|
||||
|
||||
it("should not affect the opponent if they do not switch", async() => {
|
||||
it("should not affect the opponent if they do not switch", async () => {
|
||||
await game.classicMode.runToSummon([ Species.MIGHTYENA, Species.POOCHYENA ]);
|
||||
|
||||
const enemy = game.scene.getEnemyField()[0];
|
||||
|
@ -51,9 +49,9 @@ describe("Moves - Toxic Spikes", () => {
|
|||
|
||||
expect(enemy.hp).toBe(enemy.getMaxHp());
|
||||
expect(enemy.status?.effect).toBeUndefined();
|
||||
}, TIMEOUT);
|
||||
});
|
||||
|
||||
it("should poison the opponent if they switch into 1 layer", async() => {
|
||||
it("should poison the opponent if they switch into 1 layer", async () => {
|
||||
await game.classicMode.runToSummon([ Species.MIGHTYENA ]);
|
||||
|
||||
game.move.select(Moves.TOXIC_SPIKES);
|
||||
|
@ -65,9 +63,9 @@ describe("Moves - Toxic Spikes", () => {
|
|||
|
||||
expect(enemy.hp).toBeLessThan(enemy.getMaxHp());
|
||||
expect(enemy.status?.effect).toBe(StatusEffect.POISON);
|
||||
}, TIMEOUT);
|
||||
});
|
||||
|
||||
it("should badly poison the opponent if they switch into 2 layers", async() => {
|
||||
it("should badly poison the opponent if they switch into 2 layers", async () => {
|
||||
await game.classicMode.runToSummon([ Species.MIGHTYENA ]);
|
||||
|
||||
game.move.select(Moves.TOXIC_SPIKES);
|
||||
|
@ -80,27 +78,32 @@ describe("Moves - Toxic Spikes", () => {
|
|||
const enemy = game.scene.getEnemyField()[0];
|
||||
expect(enemy.hp).toBeLessThan(enemy.getMaxHp());
|
||||
expect(enemy.status?.effect).toBe(StatusEffect.TOXIC);
|
||||
}, TIMEOUT);
|
||||
});
|
||||
|
||||
it("should be removed if a grounded poison pokemon switches in", async() => {
|
||||
game.override.enemySpecies(Species.GRIMER);
|
||||
await game.classicMode.runToSummon([ Species.MIGHTYENA ]);
|
||||
it("should be removed if a grounded poison pokemon switches in", async () => {
|
||||
await game.classicMode.runToSummon([ Species.MUK, Species.PIDGEY ]);
|
||||
|
||||
const muk = game.scene.getPlayerPokemon()!;
|
||||
|
||||
game.move.select(Moves.TOXIC_SPIKES);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
game.move.select(Moves.TOXIC_SPIKES);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
game.move.select(Moves.ROAR);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
const enemy = game.scene.getEnemyField()[0];
|
||||
expect(enemy.hp).toBe(enemy.getMaxHp());
|
||||
expect(enemy.status?.effect).toBeUndefined();
|
||||
await game.toNextTurn();
|
||||
// also make sure the toxic spikes are removed even if the pokemon
|
||||
// that set them up is the one switching in (https://github.com/pagefaultgames/pokerogue/issues/935)
|
||||
game.move.select(Moves.COURT_CHANGE);
|
||||
await game.toNextTurn();
|
||||
game.doSwitchPokemon(1);
|
||||
await game.toNextTurn();
|
||||
game.doSwitchPokemon(1);
|
||||
await game.toNextTurn();
|
||||
game.move.select(Moves.SPLASH);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(muk.isFullHp()).toBe(true);
|
||||
expect(muk.status?.effect).toBeUndefined();
|
||||
expect(game.scene.arena.tags.length).toBe(0);
|
||||
}, TIMEOUT);
|
||||
});
|
||||
|
||||
it("shouldn't create multiple layers per use in doubles", async() => {
|
||||
it("shouldn't create multiple layers per use in doubles", async () => {
|
||||
await game.classicMode.runToSummon([ Species.MIGHTYENA, Species.POOCHYENA ]);
|
||||
|
||||
game.move.select(Moves.TOXIC_SPIKES);
|
||||
|
@ -109,9 +112,9 @@ describe("Moves - Toxic Spikes", () => {
|
|||
const arenaTags = (game.scene.arena.getTagOnSide(ArenaTagType.TOXIC_SPIKES, ArenaTagSide.ENEMY) as ArenaTrapTag);
|
||||
expect(arenaTags.tagType).toBe(ArenaTagType.TOXIC_SPIKES);
|
||||
expect(arenaTags.layers).toBe(1);
|
||||
}, TIMEOUT);
|
||||
});
|
||||
|
||||
it("should persist through reload", async() => {
|
||||
it("should persist through reload", async () => {
|
||||
game.override.startingWave(1);
|
||||
const scene = game.scene;
|
||||
const gameData = new GameData(scene);
|
||||
|
@ -132,5 +135,5 @@ describe("Moves - Toxic Spikes", () => {
|
|||
|
||||
expect(sessionData.arena.tags).toEqual(recoveredData.arena.tags);
|
||||
localStorage.removeItem("sessionTestData");
|
||||
}, TIMEOUT);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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
|
||||
|
||||
switch (optionNo) {
|
||||
default:
|
||||
case 1:
|
||||
default:
|
||||
case 1:
|
||||
// no movement needed. Default cursor position
|
||||
break;
|
||||
case 2:
|
||||
uiHandler.processInput(Button.RIGHT);
|
||||
break;
|
||||
case 3:
|
||||
uiHandler.processInput(Button.DOWN);
|
||||
break;
|
||||
case 4:
|
||||
uiHandler.processInput(Button.RIGHT);
|
||||
uiHandler.processInput(Button.DOWN);
|
||||
break;
|
||||
break;
|
||||
case 2:
|
||||
uiHandler.processInput(Button.RIGHT);
|
||||
break;
|
||||
case 3:
|
||||
uiHandler.processInput(Button.DOWN);
|
||||
break;
|
||||
case 4:
|
||||
uiHandler.processInput(Button.RIGHT);
|
||||
uiHandler.processInput(Button.DOWN);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!isNullOrUndefined(secondaryOptionSelect?.pokemonNo)) {
|
||||
|
|
|
@ -476,10 +476,11 @@ describe("Bug-Type Superfan - Mystery Encounter", () => {
|
|||
|
||||
expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT);
|
||||
const modifierSelectHandler = scene.ui.handlers.find(h => h instanceof ModifierSelectUiHandler) as ModifierSelectUiHandler;
|
||||
expect(modifierSelectHandler.options.length).toEqual(3);
|
||||
expect(modifierSelectHandler.options.length).toEqual(4);
|
||||
expect(modifierSelectHandler.options[0].modifierTypeOption.type.id).toBe("MASTER_BALL");
|
||||
expect(modifierSelectHandler.options[1].modifierTypeOption.type.id).toBe("MAX_LURE");
|
||||
expect(modifierSelectHandler.options[2].modifierTypeOption.type.id).toBe("FORM_CHANGE_ITEM");
|
||||
expect(modifierSelectHandler.options[1].modifierTypeOption.type.id).toBe("MEGA_BRACELET");
|
||||
expect(modifierSelectHandler.options[2].modifierTypeOption.type.id).toBe("DYNAMAX_BAND");
|
||||
expect(modifierSelectHandler.options[3].modifierTypeOption.type.id).toBe("FORM_CHANGE_ITEM");
|
||||
});
|
||||
|
||||
it("should leave encounter without battle", async () => {
|
||||
|
|
|
@ -118,11 +118,11 @@ describe("Clowning Around - Mystery Encounter", () => {
|
|||
});
|
||||
expect(config.pokemonConfigs?.[1]).toEqual({
|
||||
species: getPokemonSpecies(Species.BLACEPHALON),
|
||||
mysteryEncounterPokemonData: expect.anything(),
|
||||
customPokemonData: expect.anything(),
|
||||
isBoss: true,
|
||||
moveSet: [ Moves.TRICK, Moves.HYPNOSIS, Moves.SHADOW_BALL, Moves.MIND_BLOWN ]
|
||||
});
|
||||
expect(config.pokemonConfigs?.[1].mysteryEncounterPokemonData?.types.length).toBe(2);
|
||||
expect(config.pokemonConfigs?.[1].customPokemonData?.types.length).toBe(2);
|
||||
expect([
|
||||
Abilities.STURDY,
|
||||
Abilities.PICKUP,
|
||||
|
@ -139,8 +139,8 @@ describe("Clowning Around - Mystery Encounter", () => {
|
|||
Abilities.MAGICIAN,
|
||||
Abilities.SHEER_FORCE,
|
||||
Abilities.PRANKSTER
|
||||
]).toContain(config.pokemonConfigs?.[1].mysteryEncounterPokemonData?.ability);
|
||||
expect(ClowningAroundEncounter.misc.ability).toBe(config.pokemonConfigs?.[1].mysteryEncounterPokemonData?.ability);
|
||||
]).toContain(config.pokemonConfigs?.[1].customPokemonData?.ability);
|
||||
expect(ClowningAroundEncounter.misc.ability).toBe(config.pokemonConfigs?.[1].customPokemonData?.ability);
|
||||
await vi.waitFor(() => expect(moveInitSpy).toHaveBeenCalled());
|
||||
await vi.waitFor(() => expect(moveLoadSpy).toHaveBeenCalled());
|
||||
expect(onInitResult).toBe(true);
|
||||
|
@ -219,7 +219,7 @@ describe("Clowning Around - Mystery Encounter", () => {
|
|||
await game.phaseInterceptor.to(NewBattlePhase, false);
|
||||
|
||||
const leadPokemon = scene.getParty()[0];
|
||||
expect(leadPokemon.mysteryEncounterPokemonData?.ability).toBe(abilityToTrain);
|
||||
expect(leadPokemon.customPokemonData?.ability).toBe(abilityToTrain);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -340,9 +340,9 @@ describe("Clowning Around - Mystery Encounter", () => {
|
|||
scene.getParty()[2].moveset = [];
|
||||
await runMysteryEncounterToEnd(game, 3);
|
||||
|
||||
const leadTypesAfter = scene.getParty()[0].mysteryEncounterPokemonData?.types;
|
||||
const secondaryTypesAfter = scene.getParty()[1].mysteryEncounterPokemonData?.types;
|
||||
const thirdTypesAfter = scene.getParty()[2].mysteryEncounterPokemonData?.types;
|
||||
const leadTypesAfter = scene.getParty()[0].customPokemonData?.types;
|
||||
const secondaryTypesAfter = scene.getParty()[1].customPokemonData?.types;
|
||||
const thirdTypesAfter = scene.getParty()[2].customPokemonData?.types;
|
||||
|
||||
expect(leadTypesAfter.length).toBe(2);
|
||||
expect(leadTypesAfter[0]).toBe(Type.WATER);
|
||||
|
|
|
@ -21,7 +21,7 @@ import { BerryModifier, PokemonBaseStatTotalModifier } from "#app/modifier/modif
|
|||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { initSceneWithoutEncounterPhase } from "#test/utils/gameManagerUtils";
|
||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
||||
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||
import { CommandPhase } from "#app/phases/command-phase";
|
||||
import { MovePhase } from "#app/phases/move-phase";
|
||||
import { SelectModifierPhase } from "#app/phases/select-modifier-phase";
|
||||
|
@ -109,7 +109,7 @@ describe("The Strong Stuff - Mystery Encounter", () => {
|
|||
species: getPokemonSpecies(Species.SHUCKLE),
|
||||
isBoss: true,
|
||||
bossSegments: 5,
|
||||
mysteryEncounterPokemonData: new MysteryEncounterPokemonData({ spriteScale: 1.25 }),
|
||||
customPokemonData: new CustomPokemonData({ spriteScale: 1.25 }),
|
||||
nature: Nature.BOLD,
|
||||
moveSet: [ Moves.INFESTATION, Moves.SALT_CURE, Moves.GASTRO_ACID, Moves.HEAL_ORDER ],
|
||||
modifierConfigs: expect.any(Array),
|
||||
|
|
|
@ -122,7 +122,7 @@ describe("Weird Dream - Mystery Encounter", () => {
|
|||
for (let i = 0; i < pokemonAfter.length; i++) {
|
||||
const newPokemon = pokemonAfter[i];
|
||||
expect(newPokemon.getSpeciesForm().speciesId).not.toBe(pokemonPrior[i].getSpeciesForm().speciesId);
|
||||
expect(newPokemon.mysteryEncounterPokemonData?.types.length).toBe(2);
|
||||
expect(newPokemon.customPokemonData?.types.length).toBe(2);
|
||||
}
|
||||
|
||||
const plus90To110 = bstDiff.filter(bst => bst > 80);
|
||||
|
|
|
@ -38,6 +38,10 @@ export class ChallengeModeHelper extends GameManagerHelper {
|
|||
async runToSummon(species?: Species[]) {
|
||||
await this.game.runToTitle();
|
||||
|
||||
if (this.game.override.disableShinies) {
|
||||
this.game.override.shiny(false).enemyShiny(false);
|
||||
}
|
||||
|
||||
this.game.onNextPrompt("TitlePhase", Mode.TITLE, () => {
|
||||
this.game.scene.gameMode.challenges = this.challenges;
|
||||
const starters = generateStarter(this.game.scene, species);
|
||||
|
@ -47,7 +51,7 @@ export class ChallengeModeHelper extends GameManagerHelper {
|
|||
});
|
||||
|
||||
await this.game.phaseInterceptor.run(EncounterPhase);
|
||||
if (overrides.OPP_HELD_ITEMS_OVERRIDE.length === 0) {
|
||||
if (overrides.OPP_HELD_ITEMS_OVERRIDE.length === 0 && this.game.override.removeEnemyStartingItems) {
|
||||
this.game.removeEnemyHeldItems();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,9 +20,13 @@ export class ClassicModeHelper extends GameManagerHelper {
|
|||
* @param species - Optional array of species to summon.
|
||||
* @returns A promise that resolves when the summon phase is reached.
|
||||
*/
|
||||
async runToSummon(species?: Species[]) {
|
||||
async runToSummon(species?: Species[]): Promise<void> {
|
||||
await this.game.runToTitle();
|
||||
|
||||
if (this.game.override.disableShinies) {
|
||||
this.game.override.shiny(false).enemyShiny(false);
|
||||
}
|
||||
|
||||
this.game.onNextPrompt("TitlePhase", Mode.TITLE, () => {
|
||||
this.game.scene.gameMode = getGameMode(GameModes.CLASSIC);
|
||||
const starters = generateStarter(this.game.scene, species);
|
||||
|
@ -32,7 +36,7 @@ export class ClassicModeHelper extends GameManagerHelper {
|
|||
});
|
||||
|
||||
await this.game.phaseInterceptor.run(EncounterPhase);
|
||||
if (overrides.OPP_HELD_ITEMS_OVERRIDE.length === 0) {
|
||||
if (overrides.OPP_HELD_ITEMS_OVERRIDE.length === 0 && this.game.override.removeEnemyStartingItems) {
|
||||
this.game.removeEnemyHeldItems();
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +46,7 @@ export class ClassicModeHelper extends GameManagerHelper {
|
|||
* @param species - Optional array of species to start the battle with.
|
||||
* @returns A promise that resolves when the battle is started.
|
||||
*/
|
||||
async startBattle(species?: Species[]) {
|
||||
async startBattle(species?: Species[]): Promise<void> {
|
||||
await this.runToSummon(species);
|
||||
|
||||
if (this.game.scene.battleStyle === BattleStyle.SWITCH) {
|
||||
|
|
|
@ -21,6 +21,10 @@ export class DailyModeHelper extends GameManagerHelper {
|
|||
async runToSummon() {
|
||||
await this.game.runToTitle();
|
||||
|
||||
if (this.game.override.disableShinies) {
|
||||
this.game.override.shiny(false).enemyShiny(false);
|
||||
}
|
||||
|
||||
this.game.onNextPrompt("TitlePhase", Mode.TITLE, () => {
|
||||
const titlePhase = new TitlePhase(this.game.scene);
|
||||
titlePhase.initDailyRun();
|
||||
|
@ -33,7 +37,7 @@ export class DailyModeHelper extends GameManagerHelper {
|
|||
|
||||
await this.game.phaseInterceptor.to(EncounterPhase);
|
||||
|
||||
if (overrides.OPP_HELD_ITEMS_OVERRIDE.length === 0) {
|
||||
if (overrides.OPP_HELD_ITEMS_OVERRIDE.length === 0 && this.game.override.removeEnemyStartingItems) {
|
||||
this.game.removeEnemyHeldItems();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,11 @@ import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
|||
* Helper to handle overrides in tests
|
||||
*/
|
||||
export class OverridesHelper extends GameManagerHelper {
|
||||
/** If `true`, removes the starting items from enemies at the start of each test; default `true` */
|
||||
public removeEnemyStartingItems: boolean = true;
|
||||
/** If `true`, sets the shiny overrides to disable shinies at the start of each test; default `true` */
|
||||
public disableShinies: boolean = true;
|
||||
|
||||
/**
|
||||
* Override the starting biome
|
||||
* @warning Any event listeners that are attached to [NewArenaEvent](events\battle-scene.ts) may need to be handled down the line
|
||||
|
@ -368,23 +373,50 @@ export class OverridesHelper extends GameManagerHelper {
|
|||
|
||||
/**
|
||||
* Override player shininess
|
||||
* @param shininess Whether the player's Pokemon should be shiny.
|
||||
* @param shininess - `true` or `false` to force the player's pokemon to be shiny or not shiny,
|
||||
* `null` to disable the override and re-enable RNG shinies.
|
||||
*/
|
||||
shinyLevel(shininess: boolean): this {
|
||||
shiny(shininess: boolean | null): this {
|
||||
vi.spyOn(Overrides, "SHINY_OVERRIDE", "get").mockReturnValue(shininess);
|
||||
this.log(`Set player Pokemon as ${shininess ? "" : "not "}shiny!`);
|
||||
if (shininess === null) {
|
||||
this.log("Disabled player Pokemon shiny override!");
|
||||
} else {
|
||||
this.log(`Set player Pokemon to be ${shininess ? "" : "not "}shiny!`);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override player shiny variant
|
||||
* @param variant The player's shiny variant.
|
||||
* @param variant - The player's shiny variant.
|
||||
*/
|
||||
variantLevel(variant: Variant): this {
|
||||
shinyVariant(variant: Variant): this {
|
||||
vi.spyOn(Overrides, "VARIANT_OVERRIDE", "get").mockReturnValue(variant);
|
||||
this.log(`Set player Pokemon's shiny variant to ${variant}!`);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override enemy shininess
|
||||
* @param shininess - `true` or `false` to force the enemy's pokemon to be shiny or not shiny,
|
||||
* `null` to disable the override and re-enable RNG shinies.
|
||||
* @param variant - (Optional) The enemy's shiny {@linkcode Variant}.
|
||||
*/
|
||||
enemyShiny(shininess: boolean | null, variant?: Variant): this {
|
||||
vi.spyOn(Overrides, "OPP_SHINY_OVERRIDE", "get").mockReturnValue(shininess);
|
||||
if (shininess === null) {
|
||||
this.log("Disabled enemy Pokemon shiny override!");
|
||||
} else {
|
||||
this.log(`Set enemy Pokemon to be ${shininess ? "" : "not "}shiny!`);
|
||||
}
|
||||
|
||||
if (variant !== undefined) {
|
||||
vi.spyOn(Overrides, "OPP_VARIANT_OVERRIDE", "get").mockReturnValue(variant);
|
||||
this.log(`Set enemy shiny variant to be ${variant}!`);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the enemy (Pokemon) to have the given amount of health segments
|
||||
* @param healthSegments the number of segments to give
|
||||
|
|
|
@ -122,20 +122,20 @@ export default class TouchControl {
|
|||
const button = Button[key];
|
||||
|
||||
switch (eventType) {
|
||||
case "keydown":
|
||||
this.events.emit("input_down", {
|
||||
controller_type: "keyboard",
|
||||
button: button,
|
||||
isTouch: true
|
||||
});
|
||||
break;
|
||||
case "keyup":
|
||||
this.events.emit("input_up", {
|
||||
controller_type: "keyboard",
|
||||
button: button,
|
||||
isTouch: true
|
||||
});
|
||||
break;
|
||||
case "keydown":
|
||||
this.events.emit("input_down", {
|
||||
controller_type: "keyboard",
|
||||
button: button,
|
||||
isTouch: true
|
||||
});
|
||||
break;
|
||||
case "keyup":
|
||||
this.events.emit("input_up", {
|
||||
controller_type: "keyboard",
|
||||
button: button,
|
||||
isTouch: true
|
||||
});
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -168,26 +168,26 @@ export class UiInputs {
|
|||
return;
|
||||
}
|
||||
switch (this.scene.ui?.getMode()) {
|
||||
case Mode.MESSAGE:
|
||||
const messageHandler = this.scene.ui.getHandler<MessageUiHandler>();
|
||||
if (!messageHandler.pendingPrompt || messageHandler.isTextAnimationInProgress()) {
|
||||
case Mode.MESSAGE:
|
||||
const messageHandler = this.scene.ui.getHandler<MessageUiHandler>();
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -222,20 +222,20 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
|
|||
}
|
||||
} else {
|
||||
switch (button) {
|
||||
case Button.UP:
|
||||
if (this.cursor) {
|
||||
success = this.setCursor(this.cursor - 1);
|
||||
} else if (this.cursor === 0) {
|
||||
success = this.setCursor(options.length - 1);
|
||||
}
|
||||
break;
|
||||
case Button.DOWN:
|
||||
if (this.cursor < options.length - 1) {
|
||||
success = this.setCursor(this.cursor + 1);
|
||||
} else {
|
||||
success = this.setCursor(0);
|
||||
}
|
||||
break;
|
||||
case Button.UP:
|
||||
if (this.cursor) {
|
||||
success = this.setCursor(this.cursor - 1);
|
||||
} else if (this.cursor === 0) {
|
||||
success = this.setCursor(options.length - 1);
|
||||
}
|
||||
break;
|
||||
case Button.DOWN:
|
||||
if (this.cursor < options.length - 1) {
|
||||
success = this.setCursor(this.cursor + 1);
|
||||
} else {
|
||||
success = this.setCursor(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (this.config?.supportHover) {
|
||||
// handle hover code if the element supports hover-handlers and the option has the optional hover-handler set.
|
||||
|
|
|
@ -245,51 +245,51 @@ export default class AchvsUiHandler extends MessageUiHandler {
|
|||
const rowIndex = Math.floor(this.cursor / this.COLS);
|
||||
const itemOffset = (this.scrollCursor * this.COLS);
|
||||
switch (button) {
|
||||
case Button.UP:
|
||||
if (this.cursor < this.COLS) {
|
||||
if (this.scrollCursor) {
|
||||
success = this.setScrollCursor(this.scrollCursor - 1);
|
||||
} else {
|
||||
case Button.UP:
|
||||
if (this.cursor < this.COLS) {
|
||||
if (this.scrollCursor) {
|
||||
success = this.setScrollCursor(this.scrollCursor - 1);
|
||||
} else {
|
||||
// Wrap around to the last row
|
||||
success = this.setScrollCursor(Math.ceil(this.currentTotal / this.COLS) - this.ROWS);
|
||||
let newCursorIndex = this.cursor + (this.ROWS - 1) * this.COLS;
|
||||
if (newCursorIndex > this.currentTotal - this.scrollCursor * this.COLS - 1) {
|
||||
newCursorIndex -= this.COLS;
|
||||
success = this.setScrollCursor(Math.ceil(this.currentTotal / this.COLS) - this.ROWS);
|
||||
let newCursorIndex = this.cursor + (this.ROWS - 1) * this.COLS;
|
||||
if (newCursorIndex > this.currentTotal - this.scrollCursor * this.COLS - 1) {
|
||||
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 {
|
||||
// wrap back to the first row
|
||||
success = this.setScrollCursor(0) && this.setCursor(this.cursor % this.COLS);
|
||||
success = this.setCursor(this.cursor - this.COLS);
|
||||
}
|
||||
} else if (canMoveDown) {
|
||||
success = this.setCursor(Math.min(this.cursor + this.COLS, this.currentTotal - itemOffset - 1));
|
||||
}
|
||||
break;
|
||||
case Button.LEFT:
|
||||
if (this.cursor % this.COLS === 0) {
|
||||
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;
|
||||
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 {
|
||||
// wrap back to the first row
|
||||
success = this.setScrollCursor(0) && this.setCursor(this.cursor % this.COLS);
|
||||
}
|
||||
} else if (canMoveDown) {
|
||||
success = this.setCursor(Math.min(this.cursor + this.COLS, this.currentTotal - itemOffset - 1));
|
||||
}
|
||||
break;
|
||||
case Button.LEFT:
|
||||
if (this.cursor % this.COLS === 0) {
|
||||
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) {
|
||||
switch (this.currentPage) {
|
||||
case Page.ACHIEVEMENTS:
|
||||
if (pageChange) {
|
||||
this.titleBg.width = 174;
|
||||
this.titleText.x = this.titleBg.width / 2;
|
||||
this.scoreContainer.setVisible(true);
|
||||
}
|
||||
this.showAchv(achvs[Object.keys(achvs)[cursor + this.scrollCursor * this.COLS]]);
|
||||
break;
|
||||
case Page.VOUCHERS:
|
||||
if (pageChange) {
|
||||
this.titleBg.width = 220;
|
||||
this.titleText.x = this.titleBg.width / 2;
|
||||
this.scoreContainer.setVisible(false);
|
||||
}
|
||||
this.showVoucher(vouchers[Object.keys(vouchers)[cursor + this.scrollCursor * this.COLS]]);
|
||||
break;
|
||||
case Page.ACHIEVEMENTS:
|
||||
if (pageChange) {
|
||||
this.titleBg.width = 174;
|
||||
this.titleText.x = this.titleBg.width / 2;
|
||||
this.scoreContainer.setVisible(true);
|
||||
}
|
||||
this.showAchv(achvs[Object.keys(achvs)[cursor + this.scrollCursor * this.COLS]]);
|
||||
break;
|
||||
case Page.VOUCHERS:
|
||||
if (pageChange) {
|
||||
this.titleBg.width = 220;
|
||||
this.titleText.x = this.titleBg.width / 2;
|
||||
this.scoreContainer.setVisible(false);
|
||||
}
|
||||
this.showVoucher(vouchers[Object.keys(vouchers)[cursor + this.scrollCursor * this.COLS]]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
@ -358,14 +358,14 @@ export default class AchvsUiHandler extends MessageUiHandler {
|
|||
}
|
||||
|
||||
switch (this.currentPage) {
|
||||
case Page.ACHIEVEMENTS:
|
||||
this.updateAchvIcons();
|
||||
this.showAchv(achvs[Object.keys(achvs)[this.cursor + this.scrollCursor * this.COLS]]);
|
||||
break;
|
||||
case Page.VOUCHERS:
|
||||
this.updateVoucherIcons();
|
||||
this.showVoucher(vouchers[Object.keys(vouchers)[this.cursor + this.scrollCursor * this.COLS]]);
|
||||
break;
|
||||
case Page.ACHIEVEMENTS:
|
||||
this.updateAchvIcons();
|
||||
this.showAchv(achvs[Object.keys(achvs)[this.cursor + this.scrollCursor * this.COLS]]);
|
||||
break;
|
||||
case Page.VOUCHERS:
|
||||
this.updateVoucherIcons();
|
||||
this.showVoucher(vouchers[Object.keys(vouchers)[this.cursor + this.scrollCursor * this.COLS]]);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -215,20 +215,20 @@ export class ArenaFlyout extends Phaser.GameObjects.Container {
|
|||
// Creates a proxy object to decide which text object needs to be updated
|
||||
let textObject: Phaser.GameObjects.Text;
|
||||
switch (fieldEffectInfo.effecType) {
|
||||
case ArenaEffectType.PLAYER:
|
||||
textObject = this.flyoutTextPlayer;
|
||||
break;
|
||||
case ArenaEffectType.PLAYER:
|
||||
textObject = this.flyoutTextPlayer;
|
||||
break;
|
||||
|
||||
case ArenaEffectType.WEATHER:
|
||||
case ArenaEffectType.TERRAIN:
|
||||
case ArenaEffectType.FIELD:
|
||||
textObject = this.flyoutTextField;
|
||||
case ArenaEffectType.WEATHER:
|
||||
case ArenaEffectType.TERRAIN:
|
||||
case ArenaEffectType.FIELD:
|
||||
textObject = this.flyoutTextField;
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case ArenaEffectType.ENEMY:
|
||||
textObject = this.flyoutTextEnemy;
|
||||
break;
|
||||
case ArenaEffectType.ENEMY:
|
||||
textObject = this.flyoutTextEnemy;
|
||||
break;
|
||||
}
|
||||
|
||||
textObject.text += fieldEffectInfo.name;
|
||||
|
@ -253,81 +253,81 @@ export class ArenaFlyout extends Phaser.GameObjects.Container {
|
|||
|
||||
let foundIndex: number;
|
||||
switch (arenaEffectChangedEvent.constructor) {
|
||||
case TagAddedEvent:
|
||||
const tagAddedEvent = arenaEffectChangedEvent as TagAddedEvent;
|
||||
const isArenaTrapTag = this.battleScene.arena.getTag(tagAddedEvent.arenaTagType) instanceof ArenaTrapTag;
|
||||
let arenaEffectType: ArenaEffectType;
|
||||
case TagAddedEvent:
|
||||
const tagAddedEvent = arenaEffectChangedEvent as TagAddedEvent;
|
||||
const isArenaTrapTag = this.battleScene.arena.getTag(tagAddedEvent.arenaTagType) instanceof ArenaTrapTag;
|
||||
let arenaEffectType: ArenaEffectType;
|
||||
|
||||
if (tagAddedEvent.arenaTagSide === ArenaTagSide.BOTH) {
|
||||
arenaEffectType = ArenaEffectType.FIELD;
|
||||
} else if (tagAddedEvent.arenaTagSide === ArenaTagSide.PLAYER) {
|
||||
arenaEffectType = ArenaEffectType.PLAYER;
|
||||
} else {
|
||||
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})`;
|
||||
if (tagAddedEvent.arenaTagSide === ArenaTagSide.BOTH) {
|
||||
arenaEffectType = ArenaEffectType.FIELD;
|
||||
} else if (tagAddedEvent.arenaTagSide === ArenaTagSide.PLAYER) {
|
||||
arenaEffectType = ArenaEffectType.PLAYER;
|
||||
} else {
|
||||
arenaEffectType = ArenaEffectType.ENEMY;
|
||||
}
|
||||
}
|
||||
|
||||
this.fieldEffectInfo.push({
|
||||
name,
|
||||
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);
|
||||
const existingTrapTagIndex = isArenaTrapTag ? this.fieldEffectInfo.findIndex(e => tagAddedEvent.arenaTagType === e.tagType && arenaEffectType === e.effecType) : -1;
|
||||
let name: string = getFieldEffectText(ArenaTagType[tagAddedEvent.arenaTagType]);
|
||||
|
||||
if (foundIndex !== -1) { // If the tag was being tracked, remove it
|
||||
this.fieldEffectInfo.splice(foundIndex, 1);
|
||||
}
|
||||
break;
|
||||
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})`;
|
||||
}
|
||||
}
|
||||
|
||||
case WeatherChangedEvent:
|
||||
case TerrainChangedEvent:
|
||||
const fieldEffectChangedEvent = arenaEffectChangedEvent as WeatherChangedEvent | TerrainChangedEvent;
|
||||
this.fieldEffectInfo.push({
|
||||
name,
|
||||
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
|
||||
const oldName =
|
||||
if (foundIndex !== -1) { // If the tag was being tracked, remove it
|
||||
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
|
||||
? WeatherType[fieldEffectChangedEvent.oldWeatherType]
|
||||
: TerrainType[fieldEffectChangedEvent.oldTerrainType]);
|
||||
// Stores the new Weather/Terrain info
|
||||
const newInfo = {
|
||||
name:
|
||||
// Stores the new Weather/Terrain info
|
||||
const newInfo = {
|
||||
name:
|
||||
getFieldEffectText(fieldEffectChangedEvent instanceof WeatherChangedEvent
|
||||
? WeatherType[fieldEffectChangedEvent.newWeatherType]
|
||||
: TerrainType[fieldEffectChangedEvent.newTerrainType]),
|
||||
effecType: fieldEffectChangedEvent instanceof WeatherChangedEvent
|
||||
? ArenaEffectType.WEATHER
|
||||
: ArenaEffectType.TERRAIN,
|
||||
maxDuration: fieldEffectChangedEvent.duration,
|
||||
duration: fieldEffectChangedEvent.duration };
|
||||
effecType: fieldEffectChangedEvent instanceof WeatherChangedEvent
|
||||
? ArenaEffectType.WEATHER
|
||||
: ArenaEffectType.TERRAIN,
|
||||
maxDuration: fieldEffectChangedEvent.duration,
|
||||
duration: fieldEffectChangedEvent.duration };
|
||||
|
||||
foundIndex = this.fieldEffectInfo.findIndex(info => [ newInfo.name, oldName ].includes(info.name));
|
||||
if (foundIndex === -1) {
|
||||
if (newInfo.name !== undefined) {
|
||||
this.fieldEffectInfo.push(newInfo); // Adds the info to the array if it doesn't already exist and is defined
|
||||
foundIndex = this.fieldEffectInfo.findIndex(info => [ newInfo.name, oldName ].includes(info.name));
|
||||
if (foundIndex === -1) {
|
||||
if (newInfo.name !== undefined) {
|
||||
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) {
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
||||
this.updateFieldText();
|
||||
|
|
|
@ -90,12 +90,12 @@ export default class BallUiHandler extends UiHandler {
|
|||
}
|
||||
} else {
|
||||
switch (button) {
|
||||
case Button.UP:
|
||||
success = this.setCursor(this.cursor ? this.cursor - 1 : pokeballTypeCount);
|
||||
break;
|
||||
case Button.DOWN:
|
||||
success = this.setCursor(this.cursor < pokeballTypeCount ? this.cursor + 1 : 0);
|
||||
break;
|
||||
case Button.UP:
|
||||
success = this.setCursor(this.cursor ? this.cursor - 1 : pokeballTypeCount);
|
||||
break;
|
||||
case Button.DOWN:
|
||||
success = this.setCursor(this.cursor < pokeballTypeCount ? this.cursor + 1 : 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -376,66 +376,66 @@ export default class GameChallengesUiHandler extends UiHandler {
|
|||
} else {
|
||||
if (this.cursorObj?.visible && !this.startCursor.visible) {
|
||||
switch (button) {
|
||||
case Button.UP:
|
||||
if (this.cursor === 0) {
|
||||
if (this.scrollCursor === 0) {
|
||||
case Button.UP:
|
||||
if (this.cursor === 0) {
|
||||
if (this.scrollCursor === 0) {
|
||||
// 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.
|
||||
const successA = this.setCursor(rowsToDisplay - 1);
|
||||
// Then, adjust the scroll to display the bottommost elements of the menu.
|
||||
const successB = this.setScrollCursor(this.scene.gameMode.challenges.length - rowsToDisplay);
|
||||
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
|
||||
success = this.setCursor(this.scene.gameMode.challenges.length - 1);
|
||||
const successA = this.setCursor(rowsToDisplay - 1);
|
||||
// Then, adjust the scroll to display the bottommost elements of the menu.
|
||||
const successB = this.setScrollCursor(this.scene.gameMode.challenges.length - rowsToDisplay);
|
||||
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
|
||||
success = this.setCursor(this.scene.gameMode.challenges.length - 1);
|
||||
}
|
||||
} else {
|
||||
success = this.setScrollCursor(this.scrollCursor - 1);
|
||||
}
|
||||
} else {
|
||||
success = this.setScrollCursor(this.scrollCursor - 1);
|
||||
success = this.setCursor(this.cursor - 1);
|
||||
}
|
||||
} else {
|
||||
success = this.setCursor(this.cursor - 1);
|
||||
}
|
||||
if (success) {
|
||||
this.updateText();
|
||||
}
|
||||
break;
|
||||
case Button.DOWN:
|
||||
if (this.cursor === rowsToDisplay - 1) {
|
||||
if (this.scrollCursor < this.scene.gameMode.challenges.length - rowsToDisplay) {
|
||||
if (success) {
|
||||
this.updateText();
|
||||
}
|
||||
break;
|
||||
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.
|
||||
success = this.setScrollCursor(this.scrollCursor + 1);
|
||||
} else {
|
||||
success = this.setScrollCursor(this.scrollCursor + 1);
|
||||
} else {
|
||||
// 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.
|
||||
const successA = this.setCursor(0);
|
||||
// Then, adjust the scroll to display the topmost elements of the menu.
|
||||
const successB = this.setScrollCursor(0);
|
||||
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) {
|
||||
const successA = this.setCursor(0);
|
||||
// Then, adjust the scroll to display the topmost elements of the menu.
|
||||
const successB = this.setScrollCursor(0);
|
||||
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) {
|
||||
// When at the bottom of a non-scrolling menu and pressing DOWN, move to the topmost item.
|
||||
success = this.setCursor(0);
|
||||
} else {
|
||||
success = this.setCursor(this.cursor + 1);
|
||||
}
|
||||
if (success) {
|
||||
this.updateText();
|
||||
}
|
||||
break;
|
||||
case Button.LEFT:
|
||||
success = this.setCursor(0);
|
||||
} else {
|
||||
success = this.setCursor(this.cursor + 1);
|
||||
}
|
||||
if (success) {
|
||||
this.updateText();
|
||||
}
|
||||
break;
|
||||
case Button.LEFT:
|
||||
// Moves the option cursor left, if possible.
|
||||
success = this.getActiveChallenge().decreaseValue();
|
||||
if (success) {
|
||||
this.updateText();
|
||||
}
|
||||
break;
|
||||
case Button.RIGHT:
|
||||
success = this.getActiveChallenge().decreaseValue();
|
||||
if (success) {
|
||||
this.updateText();
|
||||
}
|
||||
break;
|
||||
case Button.RIGHT:
|
||||
// Moves the option cursor right, if possible.
|
||||
success = this.getActiveChallenge().increaseValue();
|
||||
if (success) {
|
||||
this.updateText();
|
||||
}
|
||||
break;
|
||||
success = this.getActiveChallenge().increaseValue();
|
||||
if (success) {
|
||||
this.updateText();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,54 +89,54 @@ export default class CommandUiHandler extends UiHandler {
|
|||
if (button === Button.ACTION) {
|
||||
switch (cursor) {
|
||||
// Fight
|
||||
case Command.FIGHT:
|
||||
if ((this.scene.getCurrentPhase() as CommandPhase).checkFightOverride()) {
|
||||
return true;
|
||||
}
|
||||
ui.setMode(Mode.FIGHT, (this.scene.getCurrentPhase() as CommandPhase).getFieldIndex());
|
||||
success = true;
|
||||
break;
|
||||
case Command.FIGHT:
|
||||
if ((this.scene.getCurrentPhase() as CommandPhase).checkFightOverride()) {
|
||||
return true;
|
||||
}
|
||||
ui.setMode(Mode.FIGHT, (this.scene.getCurrentPhase() as CommandPhase).getFieldIndex());
|
||||
success = true;
|
||||
break;
|
||||
// Ball
|
||||
case Command.BALL:
|
||||
ui.setModeWithoutClear(Mode.BALL);
|
||||
success = true;
|
||||
break;
|
||||
case Command.BALL:
|
||||
ui.setModeWithoutClear(Mode.BALL);
|
||||
success = true;
|
||||
break;
|
||||
// Pokemon
|
||||
case Command.POKEMON:
|
||||
ui.setMode(Mode.PARTY, PartyUiMode.SWITCH, (this.scene.getCurrentPhase() as CommandPhase).getPokemon().getFieldIndex(), null, PartyUiHandler.FilterNonFainted);
|
||||
success = true;
|
||||
break;
|
||||
case Command.POKEMON:
|
||||
ui.setMode(Mode.PARTY, PartyUiMode.SWITCH, (this.scene.getCurrentPhase() as CommandPhase).getPokemon().getFieldIndex(), null, PartyUiHandler.FilterNonFainted);
|
||||
success = true;
|
||||
break;
|
||||
// Run
|
||||
case Command.RUN:
|
||||
(this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.RUN, 0);
|
||||
success = true;
|
||||
break;
|
||||
case Command.RUN:
|
||||
(this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.RUN, 0);
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
(this.scene.getCurrentPhase() as CommandPhase).cancel();
|
||||
}
|
||||
} else {
|
||||
switch (button) {
|
||||
case Button.UP:
|
||||
if (cursor >= 2) {
|
||||
success = this.setCursor(cursor - 2);
|
||||
}
|
||||
break;
|
||||
case Button.DOWN:
|
||||
if (cursor < 2) {
|
||||
success = this.setCursor(cursor + 2);
|
||||
}
|
||||
break;
|
||||
case Button.LEFT:
|
||||
if (cursor % 2 === 1) {
|
||||
success = this.setCursor(cursor - 1);
|
||||
}
|
||||
break;
|
||||
case Button.RIGHT:
|
||||
if (cursor % 2 === 0) {
|
||||
success = this.setCursor(cursor + 1);
|
||||
}
|
||||
break;
|
||||
case Button.UP:
|
||||
if (cursor >= 2) {
|
||||
success = this.setCursor(cursor - 2);
|
||||
}
|
||||
break;
|
||||
case Button.DOWN:
|
||||
if (cursor < 2) {
|
||||
success = this.setCursor(cursor + 2);
|
||||
}
|
||||
break;
|
||||
case Button.LEFT:
|
||||
if (cursor % 2 === 1) {
|
||||
success = this.setCursor(cursor - 1);
|
||||
}
|
||||
break;
|
||||
case Button.RIGHT:
|
||||
if (cursor % 2 === 0) {
|
||||
success = this.setCursor(cursor + 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -142,13 +142,13 @@ export class DailyRunScoreboard extends Phaser.GameObjects.Container {
|
|||
entryContainer.add(scoreLabel);
|
||||
|
||||
switch (this.category) {
|
||||
case ScoreboardCategory.DAILY:
|
||||
const waveLabel = addTextObject(this.scene, 68, 0, wave, TextStyle.WINDOW, { fontSize: "54px" });
|
||||
entryContainer.add(waveLabel);
|
||||
break;
|
||||
case ScoreboardCategory.WEEKLY:
|
||||
scoreLabel.x -= 16;
|
||||
break;
|
||||
case ScoreboardCategory.DAILY:
|
||||
const waveLabel = addTextObject(this.scene, 68, 0, wave, TextStyle.WINDOW, { fontSize: "54px" });
|
||||
entryContainer.add(waveLabel);
|
||||
break;
|
||||
case ScoreboardCategory.WEEKLY:
|
||||
scoreLabel.x -= 16;
|
||||
break;
|
||||
}
|
||||
|
||||
return entryContainer;
|
||||
|
|