mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-06-21 00:52:47 +02:00
* Refactor evo conditions and descriptions * Fix test * Fix Shedinja * Simplify Gimmighoul evolution * Primeape and Stantler evolve by using their move 10 times * Basculin white stripe evolves by taking 294 recoil damage * Primeape and Stantler use modifiers for tracking * Basculin uses modifier too * Remove evo count from pokemon data * No more evo counter data, Gallade/Froslass * Fix allmoves import * Clamperl * Struggle shouldn't count for Basc recoil * Change to nicer type * Apply Benjie's suggestions Co-authored-by: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> * Address formatting * Undo new evolution changes * Remove unused imports * Fix speciesid * Fixed up descriptions a little * Change a key name * Fix Gimmighoul * Apply Biome * Apply Biome unsafe fixes * Review suggestions - Convert `EvoCondKey` enum to `const` object - Use early returns in `SpeciesEvolutionCondition#description` and `SpeciesFormEvolution#description` - Replace `!!x.find` with `x.some` and `y.indexOf() > -1` with `y.includes()` - Implement `coerceArray` - Fix Shelmet evolution condition checking for Shelmet and not Karrablast - Remove unnecessary type casting in `battle-scene.ts` * Remove leftover enforce func loop * Fix circular imports issue - `getPokemonSpecies` moved to `src/utils/pokemon-utils.ts` - `allSpecies` moved to `src/data/data-lists.ts` --------- Co-authored-by: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
234 lines
8.3 KiB
TypeScript
234 lines
8.3 KiB
TypeScript
import type { EnemyPartyConfig } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
|
import {
|
|
initBattleWithEnemyConfig,
|
|
loadCustomMovesForEncounter,
|
|
leaveEncounterWithoutBattle,
|
|
setEncounterRewards,
|
|
transitionMysteryEncounterIntroVisuals,
|
|
generateModifierType,
|
|
} from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
|
import type { PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
|
import { modifierTypes } from "#app/data/data-lists";
|
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
|
import { globalScene } from "#app/global-scene";
|
|
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
|
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
|
import { getPokemonSpecies } from "#app/utils/pokemon-utils";
|
|
import { SpeciesId } from "#enums/species-id";
|
|
import { Nature } from "#enums/nature";
|
|
import type Pokemon from "#app/field/pokemon";
|
|
import { PokemonMove } from "#app/data/moves/pokemon-move";
|
|
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
|
import { modifyPlayerPokemonBST } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
|
import { MoveId } from "#enums/move-id";
|
|
import { BattlerIndex } from "#enums/battler-index";
|
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
|
import { BerryType } from "#enums/berry-type";
|
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
|
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
|
import { Stat } from "#enums/stat";
|
|
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
|
import { MoveUseMode } from "#enums/move-use-mode";
|
|
|
|
/** the i18n namespace for the encounter */
|
|
const namespace = "mysteryEncounters/theStrongStuff";
|
|
|
|
// Halved for HP stat
|
|
const HIGH_BST_REDUCTION_VALUE = 15;
|
|
const BST_INCREASE_VALUE = 10;
|
|
|
|
/**
|
|
* The Strong Stuff encounter.
|
|
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/3803 | GitHub Issue #3803}
|
|
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
|
*/
|
|
export const TheStrongStuffEncounter: MysteryEncounter = MysteryEncounterBuilder.withEncounterType(
|
|
MysteryEncounterType.THE_STRONG_STUFF,
|
|
)
|
|
.withEncounterTier(MysteryEncounterTier.COMMON)
|
|
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
|
.withScenePartySizeRequirement(3, 6) // Must have at least 3 pokemon in party
|
|
.withMaxAllowedEncounters(1)
|
|
.withHideWildIntroMessage(true)
|
|
.withAutoHideIntroVisuals(false)
|
|
.withFleeAllowed(false)
|
|
.withIntroSpriteConfigs([
|
|
{
|
|
spriteKey: "berry_juice",
|
|
fileRoot: "items",
|
|
hasShadow: true,
|
|
isItem: true,
|
|
scale: 1.25,
|
|
x: -15,
|
|
y: 3,
|
|
disableAnimation: true,
|
|
},
|
|
{
|
|
spriteKey: SpeciesId.SHUCKLE.toString(),
|
|
fileRoot: "pokemon",
|
|
hasShadow: true,
|
|
repeat: true,
|
|
scale: 1.25,
|
|
x: 20,
|
|
y: 10,
|
|
yShadow: 7,
|
|
},
|
|
]) // Set in onInit()
|
|
.withIntroDialogue([
|
|
{
|
|
text: `${namespace}:intro`,
|
|
},
|
|
])
|
|
.withOnInit(() => {
|
|
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
|
|
|
// Calculate boss mon
|
|
const config: EnemyPartyConfig = {
|
|
levelAdditiveModifier: 1,
|
|
disableSwitch: true,
|
|
pokemonConfigs: [
|
|
{
|
|
species: getPokemonSpecies(SpeciesId.SHUCKLE),
|
|
isBoss: true,
|
|
bossSegments: 5,
|
|
shiny: false, // Shiny lock because shiny is rolled only if the battle option is picked
|
|
customPokemonData: new CustomPokemonData({ spriteScale: 1.25 }),
|
|
nature: Nature.HARDY,
|
|
moveSet: [MoveId.INFESTATION, MoveId.SALT_CURE, MoveId.GASTRO_ACID, MoveId.HEAL_ORDER],
|
|
modifierConfigs: [
|
|
{
|
|
modifier: generateModifierType(modifierTypes.BERRY, [BerryType.SITRUS]) as PokemonHeldItemModifierType,
|
|
},
|
|
{
|
|
modifier: generateModifierType(modifierTypes.BERRY, [BerryType.ENIGMA]) as PokemonHeldItemModifierType,
|
|
},
|
|
{
|
|
modifier: generateModifierType(modifierTypes.BERRY, [BerryType.APICOT]) as PokemonHeldItemModifierType,
|
|
},
|
|
{
|
|
modifier: generateModifierType(modifierTypes.BERRY, [BerryType.GANLON]) as PokemonHeldItemModifierType,
|
|
},
|
|
{
|
|
modifier: generateModifierType(modifierTypes.BERRY, [BerryType.LUM]) as PokemonHeldItemModifierType,
|
|
stackCount: 2,
|
|
},
|
|
],
|
|
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
|
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
|
queueEncounterMessage(`${namespace}:option.2.stat_boost`);
|
|
globalScene.phaseManager.unshiftNew(
|
|
"StatStageChangePhase",
|
|
pokemon.getBattlerIndex(),
|
|
true,
|
|
[Stat.DEF, Stat.SPDEF],
|
|
1,
|
|
);
|
|
},
|
|
},
|
|
],
|
|
};
|
|
|
|
encounter.enemyPartyConfigs = [config];
|
|
|
|
loadCustomMovesForEncounter([MoveId.GASTRO_ACID, MoveId.STEALTH_ROCK]);
|
|
|
|
encounter.setDialogueToken("shuckleName", getPokemonSpecies(SpeciesId.SHUCKLE).getName());
|
|
|
|
return true;
|
|
})
|
|
.setLocalizationKey(`${namespace}`)
|
|
.withTitle(`${namespace}:title`)
|
|
.withDescription(`${namespace}:description`)
|
|
.withQuery(`${namespace}:query`)
|
|
.withSimpleOption(
|
|
{
|
|
buttonLabel: `${namespace}:option.1.label`,
|
|
buttonTooltip: `${namespace}:option.1.tooltip`,
|
|
selected: [
|
|
{
|
|
text: `${namespace}:option.1.selected`,
|
|
},
|
|
],
|
|
},
|
|
async () => {
|
|
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
|
// Do blackout and hide intro visuals during blackout
|
|
globalScene.time.delayedCall(750, () => {
|
|
transitionMysteryEncounterIntroVisuals(true, true, 50);
|
|
});
|
|
|
|
// -15 to all base stats of highest BST (halved for HP), +10 to all base stats of rest of party (halved for HP)
|
|
// Sort party by bst
|
|
const sortedParty = globalScene
|
|
.getPlayerParty()
|
|
.slice(0)
|
|
.sort((pokemon1, pokemon2) => {
|
|
const pokemon1Bst = pokemon1.getSpeciesForm().getBaseStatTotal();
|
|
const pokemon2Bst = pokemon2.getSpeciesForm().getBaseStatTotal();
|
|
return pokemon2Bst - pokemon1Bst;
|
|
});
|
|
|
|
sortedParty.forEach((pokemon, index) => {
|
|
if (index < 2) {
|
|
// -15 to the two highest BST mons
|
|
modifyPlayerPokemonBST(pokemon, -HIGH_BST_REDUCTION_VALUE);
|
|
encounter.setDialogueToken("highBstPokemon" + (index + 1), pokemon.getNameToRender());
|
|
} else {
|
|
// +10 for the rest
|
|
modifyPlayerPokemonBST(pokemon, BST_INCREASE_VALUE);
|
|
}
|
|
});
|
|
|
|
encounter.setDialogueToken("reductionValue", HIGH_BST_REDUCTION_VALUE.toString());
|
|
encounter.setDialogueToken("increaseValue", BST_INCREASE_VALUE.toString());
|
|
await showEncounterText(`${namespace}:option.1.selected_2`, null, undefined, true);
|
|
|
|
encounter.dialogue.outro = [
|
|
{
|
|
text: `${namespace}:outro`,
|
|
},
|
|
];
|
|
setEncounterRewards({ fillRemaining: true });
|
|
leaveEncounterWithoutBattle(true);
|
|
return true;
|
|
},
|
|
)
|
|
.withSimpleOption(
|
|
{
|
|
buttonLabel: `${namespace}:option.2.label`,
|
|
buttonTooltip: `${namespace}:option.2.tooltip`,
|
|
selected: [
|
|
{
|
|
text: `${namespace}:option.2.selected`,
|
|
},
|
|
],
|
|
},
|
|
async () => {
|
|
// Pick battle
|
|
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
|
setEncounterRewards({
|
|
guaranteedModifierTypeFuncs: [modifierTypes.SOUL_DEW],
|
|
fillRemaining: true,
|
|
});
|
|
encounter.startOfBattleEffects.push(
|
|
{
|
|
sourceBattlerIndex: BattlerIndex.ENEMY,
|
|
targets: [BattlerIndex.PLAYER],
|
|
move: new PokemonMove(MoveId.GASTRO_ACID),
|
|
useMode: MoveUseMode.IGNORE_PP,
|
|
},
|
|
{
|
|
sourceBattlerIndex: BattlerIndex.ENEMY,
|
|
targets: [BattlerIndex.PLAYER],
|
|
move: new PokemonMove(MoveId.STEALTH_ROCK),
|
|
useMode: MoveUseMode.IGNORE_PP,
|
|
},
|
|
);
|
|
|
|
encounter.dialogue.outro = [];
|
|
await transitionMysteryEncounterIntroVisuals(true, true, 500);
|
|
await initBattleWithEnemyConfig(encounter.enemyPartyConfigs[0]);
|
|
},
|
|
)
|
|
.build();
|