mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-10-22 04:55:53 +02:00
* Changed how non-BGM are loaded into the game + moved into directories * some leftovers * Apply suggestions from code review Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> * Added setting for Field Volume + rewrote playSound() and updateSoundVolume() functions to reflect the new settings. * Main -> Beta (#3635) * Fixed issue with falsy issue within condition to get a stat for IV scanner * add fix setting code to prevent form/variant bug when default form/variant setting is wrong. in addition, that fix code include gender fix, so i revert old gender fix. update wrong log message. * [Hotfix] Fix Memory Mushroom not showing relearner moves (#3619) * Fix Memory Mushroom not showing relearner moves * Fix rollout test * Rewrite player faint logic in FaintPhase (#3614) * 867 runerigus sprite (#3629) cropped static frames, fixed cropped sprite set runerigus exp to use the shiny exp's animation verified all hex colors are unchanged - fixed ultra necrozma exp front variant swapped arrays. - xatu female eye color fix * [Bug] Preventing the MBH from being stolen in Endless (#3630) * Endless MBH Fix * add import * Revert "add import" This reverts commit814a4059c2
. * Revert "Endless MBH Fix" This reverts commit8eb4481301
. * removed newline --------- Co-authored-by: Frederico Santos <frederico.f.santos@tecnico.ulisboa.pt> Co-authored-by: frutescens <info@laptop> * [Bug] Fix type-hints for immunity (#3620) * enable mock containers to be found by name * enable mock text to be found by name * add test coverage for type-hints Only for "immunity" and "status moves" * fix wrong message key of curse(ghost type) (#3631) Co-authored-by: Frederico Santos <frederico.f.santos@tecnico.ulisboa.pt> * [Hotfix] Steal-able Mini Black Hole Pt 2 (#3632) * Still have no idea where Eternatus is given the MBH.... * typedocs --------- Co-authored-by: frutescens <info@laptop> * [Hotfix] Abilities that prevent ATK drops no longer stop other stat drops (#3624) * Abilities that prevent ATK drops no longer stop other stat drops * Apply suggestions from code review Co-authored-by: Mumble <kimjoanne@protonmail.com> * Add `isNullOrUndefined()` utility function --------- * Grip Claw now shows the proper pokemon nickname (#3634) Co-authored-by: frutescens <info@laptop> --------- Co-authored-by: Opaque02 <66582645+Opaque02@users.noreply.github.com> Co-authored-by: KimJeongSun <leo@atlaslabs.ai> Co-authored-by: Frederico Santos <frederico.f.santos@tecnico.ulisboa.pt> Co-authored-by: innerthunder <168692175+innerthunder@users.noreply.github.com> Co-authored-by: cam <lrlrliwoo@gmail.com> Co-authored-by: Mumble <kimjoanne@protonmail.com> Co-authored-by: frutescens <info@laptop> Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> Co-authored-by: Enoch <enoch.jwsong@gmail.com> Co-authored-by: Mumble <171087428+frutescens@users.noreply.github.com> * [Bug] Preventing the MBH from being stolen in Endless (#3630) * Endless MBH Fix * add import * Revert "add import" This reverts commit814a4059c2
. * Revert "Endless MBH Fix" This reverts commit8eb4481301
. * removed newline --------- Co-authored-by: Frederico Santos <frederico.f.santos@tecnico.ulisboa.pt> Co-authored-by: frutescens <info@laptop> * [Hotfix] Steal-able Mini Black Hole Pt 2 (#3632) * Still have no idea where Eternatus is given the MBH.... * typedocs --------- Co-authored-by: frutescens <info@laptop> * Deleted phases.ts (#3618) * Updated sound terms * Added space for localization * Update src/locales/ko/settings.ts Co-authored-by: Enoch <enoch.jwsong@gmail.com> * Update src/locales/zh_TW/settings.ts Co-authored-by: mercurius-00 <80205689+mercurius-00@users.noreply.github.com> * Update src/locales/pt_BR/settings.ts Co-authored-by: José Ricardo Fleury Oliveira <josefleury@discente.ufg.br> * Update src/locales/zh_CN/settings.ts Co-authored-by: mercurius-00 <80205689+mercurius-00@users.noreply.github.com> * Update src/locales/de/settings.ts Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com> * Update src/locales/ko/settings.ts Co-authored-by: returntoice <dieandbecome@gmail.com> * Update src/locales/fr/settings.ts Co-authored-by: Lugiad' <adrien.grivel@hotmail.fr> * Update src/locales/it/settings.ts Co-authored-by: Niccolò <123510358+NicusPulcis@users.noreply.github.com> * Include sound effects that were loaded in as BGM. * Removed stray placeholder localization --------- Co-authored-by: Frutescens <info@laptop> Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> Co-authored-by: Opaque02 <66582645+Opaque02@users.noreply.github.com> Co-authored-by: KimJeongSun <leo@atlaslabs.ai> Co-authored-by: Frederico Santos <frederico.f.santos@tecnico.ulisboa.pt> Co-authored-by: innerthunder <168692175+innerthunder@users.noreply.github.com> Co-authored-by: cam <lrlrliwoo@gmail.com> Co-authored-by: Enoch <enoch.jwsong@gmail.com> Co-authored-by: mercurius-00 <80205689+mercurius-00@users.noreply.github.com> Co-authored-by: José Ricardo Fleury Oliveira <josefleury@discente.ufg.br> Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com> Co-authored-by: returntoice <dieandbecome@gmail.com> Co-authored-by: Lugiad' <adrien.grivel@hotmail.fr> Co-authored-by: Niccolò <123510358+NicusPulcis@users.noreply.github.com>
172 lines
7.2 KiB
TypeScript
172 lines
7.2 KiB
TypeScript
import BattleScene from "#app/battle-scene.js";
|
|
import { BattlerIndex, BattleType } from "#app/battle.js";
|
|
import { applyPostFaintAbAttrs, PostFaintAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr } from "#app/data/ability.js";
|
|
import { BattlerTagLapseType } from "#app/data/battler-tags.js";
|
|
import { battleSpecDialogue } from "#app/data/dialogue.js";
|
|
import { allMoves, PostVictoryStatChangeAttr } from "#app/data/move.js";
|
|
import { BattleSpec } from "#app/enums/battle-spec.js";
|
|
import { StatusEffect } from "#app/enums/status-effect.js";
|
|
import { PokemonMove, EnemyPokemon, PlayerPokemon, HitResult } from "#app/field/pokemon.js";
|
|
import { getPokemonNameWithAffix } from "#app/messages.js";
|
|
import { PokemonInstantReviveModifier } from "#app/modifier/modifier.js";
|
|
import i18next from "i18next";
|
|
import { DamagePhase } from "./damage-phase";
|
|
import { PokemonPhase } from "./pokemon-phase";
|
|
import { SwitchSummonPhase } from "./switch-summon-phase";
|
|
import { ToggleDoublePositionPhase } from "./toggle-double-position-phase";
|
|
import { GameOverPhase } from "./game-over-phase";
|
|
import { SwitchPhase } from "./switch-phase";
|
|
import { VictoryPhase } from "./victory-phase";
|
|
|
|
export class FaintPhase extends PokemonPhase {
|
|
private preventEndure: boolean;
|
|
|
|
constructor(scene: BattleScene, battlerIndex: BattlerIndex, preventEndure?: boolean) {
|
|
super(scene, battlerIndex);
|
|
|
|
this.preventEndure = preventEndure!; // TODO: is this bang correct?
|
|
}
|
|
|
|
start() {
|
|
super.start();
|
|
|
|
if (!this.preventEndure) {
|
|
const instantReviveModifier = this.scene.applyModifier(PokemonInstantReviveModifier, this.player, this.getPokemon()) as PokemonInstantReviveModifier;
|
|
|
|
if (instantReviveModifier) {
|
|
if (!--instantReviveModifier.stackCount) {
|
|
this.scene.removeModifier(instantReviveModifier);
|
|
}
|
|
this.scene.updateModifiers(this.player);
|
|
return this.end();
|
|
}
|
|
}
|
|
|
|
if (!this.tryOverrideForBattleSpec()) {
|
|
this.doFaint();
|
|
}
|
|
}
|
|
|
|
doFaint(): void {
|
|
const pokemon = this.getPokemon();
|
|
|
|
|
|
// Track total times pokemon have been KO'd for supreme overlord/last respects
|
|
if (pokemon.isPlayer()) {
|
|
this.scene.currentBattle.playerFaints += 1;
|
|
} else {
|
|
this.scene.currentBattle.enemyFaints += 1;
|
|
}
|
|
|
|
this.scene.queueMessage(i18next.t("battle:fainted", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }), null, true);
|
|
|
|
if (pokemon.turnData?.attacksReceived?.length) {
|
|
const lastAttack = pokemon.turnData.attacksReceived[0];
|
|
applyPostFaintAbAttrs(PostFaintAbAttr, pokemon, this.scene.getPokemonById(lastAttack.sourceId)!, new PokemonMove(lastAttack.move).getMove(), lastAttack.result); // TODO: is this bang correct?
|
|
}
|
|
|
|
const alivePlayField = this.scene.getField(true);
|
|
alivePlayField.forEach(p => applyPostKnockOutAbAttrs(PostKnockOutAbAttr, p, pokemon));
|
|
if (pokemon.turnData?.attacksReceived?.length) {
|
|
const defeatSource = this.scene.getPokemonById(pokemon.turnData.attacksReceived[0].sourceId);
|
|
if (defeatSource?.isOnField()) {
|
|
applyPostVictoryAbAttrs(PostVictoryAbAttr, defeatSource);
|
|
const pvmove = allMoves[pokemon.turnData.attacksReceived[0].move];
|
|
const pvattrs = pvmove.getAttrs(PostVictoryStatChangeAttr);
|
|
if (pvattrs.length) {
|
|
for (const pvattr of pvattrs) {
|
|
pvattr.applyPostVictory(defeatSource, defeatSource, pvmove);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (this.player) {
|
|
/** The total number of Pokemon in the player's party that can legally fight */
|
|
const legalPlayerPokemon = this.scene.getParty().filter(p => p.isAllowedInBattle());
|
|
/** The total number of legal player Pokemon that aren't currently on the field */
|
|
const legalPlayerPartyPokemon = legalPlayerPokemon.filter(p => !p.isActive(true));
|
|
if (!legalPlayerPokemon.length) {
|
|
/** If the player doesn't have any legal Pokemon, end the game */
|
|
this.scene.unshiftPhase(new GameOverPhase(this.scene));
|
|
} else if (this.scene.currentBattle.double && legalPlayerPokemon.length === 1 && legalPlayerPartyPokemon.length === 0) {
|
|
/**
|
|
* If the player has exactly one Pokemon in total at this point in a double battle, and that Pokemon
|
|
* is already on the field, unshift a phase that moves that Pokemon to center position.
|
|
*/
|
|
this.scene.unshiftPhase(new ToggleDoublePositionPhase(this.scene, true));
|
|
} else if (legalPlayerPartyPokemon.length > 0) {
|
|
/**
|
|
* If previous conditions weren't met, and the player has at least 1 legal Pokemon off the field,
|
|
* push a phase that prompts the player to summon a Pokemon from their party.
|
|
*/
|
|
this.scene.pushPhase(new SwitchPhase(this.scene, this.fieldIndex, true, false));
|
|
}
|
|
} else {
|
|
this.scene.unshiftPhase(new VictoryPhase(this.scene, this.battlerIndex));
|
|
if (this.scene.currentBattle.battleType === BattleType.TRAINER) {
|
|
const hasReservePartyMember = !!this.scene.getEnemyParty().filter(p => p.isActive() && !p.isOnField() && p.trainerSlot === (pokemon as EnemyPokemon).trainerSlot).length;
|
|
if (hasReservePartyMember) {
|
|
this.scene.pushPhase(new SwitchSummonPhase(this.scene, this.fieldIndex, -1, false, false, false));
|
|
}
|
|
}
|
|
}
|
|
|
|
// in double battles redirect potential moves off fainted pokemon
|
|
if (this.scene.currentBattle.double) {
|
|
const allyPokemon = pokemon.getAlly();
|
|
this.scene.redirectPokemonMoves(pokemon, allyPokemon);
|
|
}
|
|
|
|
pokemon.lapseTags(BattlerTagLapseType.FAINT);
|
|
this.scene.getField(true).filter(p => p !== pokemon).forEach(p => p.removeTagsBySourceId(pokemon.id));
|
|
|
|
pokemon.faintCry(() => {
|
|
if (pokemon instanceof PlayerPokemon) {
|
|
pokemon.addFriendship(-10);
|
|
}
|
|
pokemon.hideInfo();
|
|
this.scene.playSound("se/faint");
|
|
this.scene.tweens.add({
|
|
targets: pokemon,
|
|
duration: 500,
|
|
y: pokemon.y + 150,
|
|
ease: "Sine.easeIn",
|
|
onComplete: () => {
|
|
pokemon.setVisible(false);
|
|
pokemon.y -= 150;
|
|
pokemon.trySetStatus(StatusEffect.FAINT);
|
|
if (pokemon.isPlayer()) {
|
|
this.scene.currentBattle.removeFaintedParticipant(pokemon as PlayerPokemon);
|
|
} else {
|
|
this.scene.addFaintedEnemyScore(pokemon as EnemyPokemon);
|
|
this.scene.currentBattle.addPostBattleLoot(pokemon as EnemyPokemon);
|
|
}
|
|
this.scene.field.remove(pokemon);
|
|
this.end();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
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 {
|
|
// 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();
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|