[Ability] Implement Ice Face (#1755)
* implement ice face ability * remove showing ability bar * fixes * add documentations * move code out of phases.ts * add hardcoded eiscue check, localization * add KO locale * remove unnecessary constructor * use && instead of || to specify ice form on eiscue
This commit is contained in:
parent
ba66f2c916
commit
8d6a0bb0a1
|
@ -59,6 +59,7 @@ import {InputsController} from "./inputs-controller";
|
|||
import {UiInputs} from "./ui-inputs";
|
||||
import { MoneyFormat } from "./enums/money-format";
|
||||
import { NewArenaEvent } from "./battle-scene-events";
|
||||
import { Abilities } from "./data/enums/abilities";
|
||||
import ArenaFlyout from "./ui/arena-flyout";
|
||||
import { EaseType } from "./ui/enums/ease-type";
|
||||
|
||||
|
@ -1048,6 +1049,12 @@ export default class BattleScene extends SceneBase {
|
|||
if (resetArenaState) {
|
||||
this.arena.removeAllTags();
|
||||
playerField.forEach((_, p) => this.unshiftPhase(new ReturnPhase(this, p)));
|
||||
|
||||
for (const pokemon of this.getParty()) {
|
||||
if (pokemon.hasAbility(Abilities.ICE_FACE)) {
|
||||
pokemon.formIndex = 0;
|
||||
}
|
||||
}
|
||||
this.unshiftPhase(new ShowTrainerPhase(this));
|
||||
}
|
||||
for (const pokemon of this.getParty()) {
|
||||
|
|
|
@ -3344,6 +3344,48 @@ export class PostSummonStatChangeOnArenaAbAttr extends PostSummonStatChangeAbAtt
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies immunity to physical moves.
|
||||
* This is used in Ice Face ability.
|
||||
*/
|
||||
export class IceFaceMoveImmunityAbAttr extends MoveImmunityAbAttr {
|
||||
/**
|
||||
* Applies the Ice Face pre-defense ability to the Pokémon.
|
||||
* Removes BattlerTagType.ICE_FACE hit by physical attack and is in Ice Face form.
|
||||
*
|
||||
* @param {Pokemon} pokemon - The Pokémon with the Ice Face ability.
|
||||
* @param {boolean} passive - Whether the ability is passive.
|
||||
* @param {Pokemon} attacker - The attacking Pokémon.
|
||||
* @param {PokemonMove} move - The move being used.
|
||||
* @param {Utils.BooleanHolder} cancelled - A holder for whether the move was cancelled.
|
||||
* @param {any[]} args - Additional arguments.
|
||||
* @returns {boolean} - Whether the immunity was applied.
|
||||
*/
|
||||
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
const isImmune = super.applyPreDefend(pokemon, passive, attacker, move, cancelled, args);
|
||||
|
||||
if (isImmune) {
|
||||
const simulated = args.length > 1 && args[1];
|
||||
if (!simulated) {
|
||||
pokemon.removeTag(BattlerTagType.ICE_FACE);
|
||||
}
|
||||
}
|
||||
|
||||
return isImmune;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the message triggered when the Pokémon avoids damage using the Ice Face ability.
|
||||
* @param {Pokemon} pokemon - The Pokémon with the Ice Face ability.
|
||||
* @param {string} abilityName - The name of the ability.
|
||||
* @param {...any} args - Additional arguments.
|
||||
* @returns {string} - The trigger message.
|
||||
*/
|
||||
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
|
||||
return i18next.t("abilityTriggers:iceFaceAvoidedDamage", { pokemonName: pokemon.name, abilityName: abilityName });
|
||||
}
|
||||
}
|
||||
|
||||
function applyAbAttrsInternal<TAttr extends AbAttr>(attrType: { new(...args: any[]): TAttr },
|
||||
pokemon: Pokemon, applyFunc: AbAttrApplyFunc<TAttr>, args: any[], isAsync: boolean = false, showAbilityInstant: boolean = false, quiet: boolean = false, passive: boolean = false): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
|
@ -4330,8 +4372,14 @@ export function initAbilities() {
|
|||
.attr(UnsuppressableAbilityAbAttr)
|
||||
.attr(NoTransformAbilityAbAttr)
|
||||
.attr(NoFusionAbilityAbAttr)
|
||||
.ignorable()
|
||||
.unimplemented(),
|
||||
// Add BattlerTagType.ICE_FACE if the pokemon is in ice face form
|
||||
.conditionalAttr(pokemon => pokemon.formIndex === 0, PostSummonAddBattlerTagAbAttr, BattlerTagType.ICE_FACE, 0, false)
|
||||
// When summoned with active HAIL or SNOW, add BattlerTagType.ICE_FACE
|
||||
.conditionalAttr(getWeatherCondition(WeatherType.HAIL, WeatherType.SNOW), PostSummonAddBattlerTagAbAttr, BattlerTagType.ICE_FACE, 0)
|
||||
// When weather changes to HAIL or SNOW while pokemon is fielded, add BattlerTagType.ICE_FACE
|
||||
.attr(PostWeatherChangeAddBattlerTagAttr, BattlerTagType.ICE_FACE, 0, WeatherType.HAIL, WeatherType.SNOW)
|
||||
.attr(IceFaceMoveImmunityAbAttr, (target, user, move) => move.getMove().category === MoveCategory.PHYSICAL && !!target.getTag(BattlerTagType.ICE_FACE))
|
||||
.ignorable(),
|
||||
new Ability(Abilities.POWER_SPOT, 8)
|
||||
.unimplemented(),
|
||||
new Ability(Abilities.MIMICRY, 8)
|
||||
|
|
|
@ -15,6 +15,8 @@ import { TerrainType } from "./terrain";
|
|||
import { WeatherType } from "./weather";
|
||||
import { BattleStat } from "./battle-stat";
|
||||
import { allAbilities } from "./ability";
|
||||
import { SpeciesFormChangeManualTrigger } from "./pokemon-forms";
|
||||
import { Species } from "./enums/species";
|
||||
|
||||
export enum BattlerTagLapseType {
|
||||
FAINT,
|
||||
|
@ -1354,6 +1356,57 @@ export class CursedTag extends BattlerTag {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the Ice Face ability's effects.
|
||||
*/
|
||||
export class IceFaceTag extends BattlerTag {
|
||||
constructor(sourceMove: Moves) {
|
||||
super(BattlerTagType.ICE_FACE, BattlerTagLapseType.CUSTOM, 1, sourceMove);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the Ice Face tag can be added to the Pokémon.
|
||||
* @param {Pokemon} pokemon - The Pokémon to which the tag might be added.
|
||||
* @returns {boolean} - True if the tag can be added, false otherwise.
|
||||
*/
|
||||
canAdd(pokemon: Pokemon): boolean {
|
||||
const weatherType = pokemon.scene.arena.weather?.weatherType;
|
||||
const isWeatherSnowOrHail = weatherType === WeatherType.HAIL || weatherType === WeatherType.SNOW;
|
||||
const isFormIceFace = pokemon.formIndex === 0;
|
||||
|
||||
|
||||
// Hard code Eiscue for now, this is to prevent the game from crashing if fused pokemon has Ice Face
|
||||
if ((pokemon.species.speciesId === Species.EISCUE && isFormIceFace) || isWeatherSnowOrHail) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the Ice Face tag to the Pokémon.
|
||||
* Triggers a form change to Ice Face if the Pokémon is not in its Ice Face form.
|
||||
* @param {Pokemon} pokemon - The Pokémon to which the tag is added.
|
||||
*/
|
||||
onAdd(pokemon: Pokemon): void {
|
||||
super.onAdd(pokemon);
|
||||
|
||||
if (pokemon.formIndex !== 0) {
|
||||
pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the Ice Face tag from the Pokémon.
|
||||
* Triggers a form change to Noice when the tag is removed.
|
||||
* @param {Pokemon} pokemon - The Pokémon from which the tag is removed.
|
||||
*/
|
||||
onRemove(pokemon: Pokemon): void {
|
||||
super.onRemove(pokemon);
|
||||
|
||||
pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger);
|
||||
}
|
||||
}
|
||||
|
||||
export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourceMove: Moves, sourceId: integer): BattlerTag {
|
||||
switch (tagType) {
|
||||
case BattlerTagType.RECHARGING:
|
||||
|
@ -1467,6 +1520,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc
|
|||
return new MinimizeTag();
|
||||
case BattlerTagType.DESTINY_BOND:
|
||||
return new DestinyBondTag(sourceMove, sourceId);
|
||||
case BattlerTagType.ICE_FACE:
|
||||
return new IceFaceTag(sourceMove);
|
||||
case BattlerTagType.NONE:
|
||||
default:
|
||||
return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId);
|
||||
|
|
|
@ -57,5 +57,6 @@ export enum BattlerTagType {
|
|||
GROUNDED = "GROUNDED",
|
||||
MAGNET_RISEN = "MAGNET_RISEN",
|
||||
MINIMIZED = "MINIMIZED",
|
||||
DESTINY_BOND = "DESTINY_BOND"
|
||||
DESTINY_BOND = "DESTINY_BOND",
|
||||
ICE_FACE = "ICE_FACE"
|
||||
}
|
||||
|
|
|
@ -730,6 +730,10 @@ export const pokemonFormChanges: PokemonFormChanges = {
|
|||
[Species.GALAR_DARMANITAN]: [
|
||||
new SpeciesFormChange(Species.GALAR_DARMANITAN, "", "zen", new SpeciesFormChangeManualTrigger(), true),
|
||||
new SpeciesFormChange(Species.GALAR_DARMANITAN, "zen", "", new SpeciesFormChangeManualTrigger(), true)
|
||||
],
|
||||
[Species.EISCUE]: [
|
||||
new SpeciesFormChange(Species.EISCUE, "", "no-ice", new SpeciesFormChangeManualTrigger(), true),
|
||||
new SpeciesFormChange(Species.EISCUE, "no-ice", "", new SpeciesFormChangeManualTrigger(), true),
|
||||
]
|
||||
};
|
||||
|
||||
|
|
|
@ -4,4 +4,5 @@ export const abilityTriggers: SimpleTranslationEntries = {
|
|||
"blockRecoilDamage" : "{{pokemonName}} wurde durch {{abilityName}}\nvor Rückstoß geschützt!",
|
||||
"badDreams": "{{pokemonName}} ist in einem Alptraum gefangen!",
|
||||
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!",
|
||||
"iceFaceAvoidedDamage": "{{pokemonName}} avoided\ndamage with {{abilityName}}!"
|
||||
} as const;
|
||||
|
|
|
@ -5,5 +5,6 @@ export const abilityTriggers: SimpleTranslationEntries = {
|
|||
"badDreams": "{{pokemonName}} is tormented!",
|
||||
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!",
|
||||
"perishBody": "{{pokemonName}}'s {{abilityName}}\nwill faint both pokemon in 3 turns!",
|
||||
"poisonHeal": "{{pokemonName}}'s {{abilityName}}\nrestored its HP a little!"
|
||||
"poisonHeal": "{{pokemonName}}'s {{abilityName}}\nrestored its HP a little!",
|
||||
"iceFaceAvoidedDamage": "{{pokemonName}} avoided\ndamage with {{abilityName}}!"
|
||||
} as const;
|
||||
|
|
|
@ -4,4 +4,5 @@ export const abilityTriggers: SimpleTranslationEntries = {
|
|||
"blockRecoilDamage" : "¡{{abilityName}} de {{pokemonName}}\nlo protegió del daño de retroceso!",
|
||||
"badDreams": "¡{{pokemonName}} está atormentado!",
|
||||
"windPowerCharged": "¡{{pokemonName}} se ha cargado de electricidad gracias a {{moveName}}!",
|
||||
"iceFaceAvoidedDamage": "{{pokemonName}} avoided\ndamage with {{abilityName}}!"
|
||||
} as const;
|
||||
|
|
|
@ -3,5 +3,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
|
|||
export const abilityTriggers: SimpleTranslationEntries = {
|
||||
"blockRecoilDamage" : "{{abilityName}}\nde {{pokemonName}} le protège du contrecoup !",
|
||||
"badDreams": "{{pokemonName}} a le sommeil agité !",
|
||||
"windPowerCharged": "{{pokemonName}} a été touché par la capacité {{moveName}} et se charge en électricité !"
|
||||
"windPowerCharged": "{{pokemonName}} a été touché par la capacité {{moveName}} et se charge en électricité !",
|
||||
"iceFaceAvoidedDamage": "{{pokemonName}} avoided\ndamage with {{abilityName}}!"
|
||||
} as const;
|
||||
|
|
|
@ -4,4 +4,5 @@ export const abilityTriggers: SimpleTranslationEntries = {
|
|||
"blockRecoilDamage" : "{{abilityName}} di {{pokemonName}}\nl'ha protetto dal contraccolpo!",
|
||||
"badDreams": "{{pokemonName}} è tormentato!",
|
||||
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!",
|
||||
"iceFaceAvoidedDamage": "{{pokemonName}} avoided\ndamage with {{abilityName}}!"
|
||||
} as const;
|
||||
|
|
|
@ -3,4 +3,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
|
|||
export const abilityTriggers: SimpleTranslationEntries = {
|
||||
"blockRecoilDamage" : "{{pokemonName}}[[는]] {{abilityName}} 때문에\n반동 데미지를 받지 않는다!",
|
||||
"badDreams": "{{pokemonName}}[[는]]\n나이트메어 때문에 시달리고 있다!",
|
||||
"iceFaceAvoidedDamage": "{{pokemonName}} avoided\ndamage with {{abilityName}}!"
|
||||
} as const;
|
||||
|
|
|
@ -3,5 +3,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
|
|||
export const abilityTriggers: SimpleTranslationEntries = {
|
||||
"blockRecoilDamage" : "{{abilityName}} de {{pokemonName}}\nprotegeu-o do dano de recuo!",
|
||||
"badDreams": "{{pokemonName}} está tendo pesadelos!",
|
||||
"windPowerCharged": "Ser atingido por {{moveName}} carregou {{pokemonName}} com poder!"
|
||||
"windPowerCharged": "Ser atingido por {{moveName}} carregou {{pokemonName}} com poder!",
|
||||
"iceFaceAvoidedDamage": "{{pokemonName}} avoided\ndamage with {{abilityName}}!"
|
||||
} as const;
|
||||
|
|
|
@ -3,5 +3,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
|
|||
export const abilityTriggers: SimpleTranslationEntries = {
|
||||
"blockRecoilDamage" : "{{pokemonName}} 的 {{abilityName}}\n抵消了反作用力!",
|
||||
"badDreams": "{{pokemonName}} 被折磨着!",
|
||||
"windPowerCharged": "受 {{moveName}} 的影响, {{pokemonName}} 提升了能力!"
|
||||
"windPowerCharged": "受 {{moveName}} 的影响, {{pokemonName}} 提升了能力!",
|
||||
"iceFaceAvoidedDamage": "{{pokemonName}} avoided\ndamage with {{abilityName}}!"
|
||||
} as const;
|
||||
|
|
|
@ -3,5 +3,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
|
|||
export const abilityTriggers: SimpleTranslationEntries = {
|
||||
"blockRecoilDamage" : "{{pokemonName}} 的 {{abilityName}}\n抵消了反作用力!",
|
||||
"badDreams": "{{pokemonName}} 被折磨着!",
|
||||
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!"
|
||||
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!",
|
||||
"iceFaceAvoidedDamage": "{{pokemonName}} avoided\ndamage with {{abilityName}}!"
|
||||
} as const;
|
||||
|
|
Loading…
Reference in New Issue