diff --git a/public/images/pokemon/icons/778-busted.png b/public/images/pokemon/icons/778-busted.png new file mode 100644 index 000000000..6f66946e1 Binary files /dev/null and b/public/images/pokemon/icons/778-busted.png differ diff --git a/public/images/pokemon/icons/778s-busted.png b/public/images/pokemon/icons/778s-busted.png new file mode 100644 index 000000000..40260efb6 Binary files /dev/null and b/public/images/pokemon/icons/778s-busted.png differ diff --git a/public/images/pokemon_icons_7.json b/public/images/pokemon_icons_7.json index 0bfbc8173..7cea5c316 100644 --- a/public/images/pokemon_icons_7.json +++ b/public/images/pokemon_icons_7.json @@ -4923,6 +4923,48 @@ "h": 22 } }, + { + "filename": "778-busted", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 5, + "w": 17, + "h": 22 + }, + "frame": { + "x": 156, + "y": 443, + "w": 17, + "h": 22 + } + }, + { + "filename": "778s-busted", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 40, + "h": 30 + }, + "spriteSourceSize": { + "x": 13, + "y": 5, + "w": 17, + "h": 22 + }, + "frame": { + "x": 217, + "y": 367, + "w": 17, + "h": 22 + } + }, { "filename": "741s-pompom", "rotated": false, diff --git a/src/data/ability.ts b/src/data/ability.ts index 7eecc4f26..b30104e4b 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -202,6 +202,25 @@ export class PreDefendAbAttr extends AbAttr { } } +export class PreDefendFormChangeAbAttr extends PreDefendAbAttr { + private formFunc: (p: Pokemon) => integer; + + constructor(formFunc: ((p: Pokemon) => integer)) { + super(true); + + this.formFunc = formFunc; + } + + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + const formIndex = this.formFunc(pokemon); + if (formIndex !== pokemon.formIndex) { + pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); + return true; + } + + return false; + } +} export class PreDefendFullHpEndureAbAttr extends PreDefendAbAttr { applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { if (pokemon.getHpRatio() < 1 || (args[0] as Utils.NumberHolder).value < pokemon.hp) @@ -235,7 +254,7 @@ export class StabBoostAbAttr extends AbAttr { } export class ReceivedMoveDamageMultiplierAbAttr extends PreDefendAbAttr { - private condition: PokemonDefendCondition; + protected condition: PokemonDefendCondition; private powerMultiplier: number; constructor(condition: PokemonDefendCondition, powerMultiplier: number) { @@ -261,6 +280,21 @@ export class ReceivedTypeDamageMultiplierAbAttr extends ReceivedMoveDamageMultip } } +export class PreDefendMovePowerToOneAbAttr extends ReceivedMoveDamageMultiplierAbAttr { + constructor(condition: PokemonDefendCondition) { + super(condition, 1); + } + + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { + if (this.condition(pokemon, attacker, move.getMove())) { + (args[0] as Utils.NumberHolder).value = 1; + return true; + } + + return false; + } +} + export class TypeImmunityAbAttr extends PreDefendAbAttr { private immuneType: Type; private condition: AbAttrCondition; @@ -386,6 +420,43 @@ export class PostDefendAbAttr extends AbAttr { } } +export class PostDefendDisguiseAbAttr extends PostDefendAbAttr { + + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + if (pokemon.formIndex == 0 && pokemon.battleData.hitCount != 0 && (move.getMove().category == MoveCategory.SPECIAL || move.getMove().category == MoveCategory.PHYSICAL)) { + + const recoilDamage = Math.ceil((pokemon.getMaxHp() / 8) - attacker.turnData.damageDealt); + if (!recoilDamage) + return false; + pokemon.damageAndUpdate(recoilDamage, HitResult.OTHER); + pokemon.scene.queueMessage(getPokemonMessage(pokemon, '\'s disguise was busted!')); + return true; + } + + return false; + } +} + +export class PostDefendFormChangeAbAttr extends PostDefendAbAttr { + private formFunc: (p: Pokemon) => integer; + + constructor(formFunc: ((p: Pokemon) => integer)) { + super(true); + + this.formFunc = formFunc; + } + + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + const formIndex = this.formFunc(pokemon); + if (formIndex !== pokemon.formIndex) { + pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); + return true; + } + + return false; + } +} + export class FieldPriorityMoveImmunityAbAttr extends PreDefendAbAttr { applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { const attackPriority = new Utils.IntegerHolder(move.getMove().priority); @@ -2437,7 +2508,7 @@ export function initAbilities() { .attr(BattleStatMultiplierAbAttr, BattleStat.SPATK, 1.5) .condition(getWeatherCondition(WeatherType.SUNNY, WeatherType.HARSH_SUN)), new Ability(Abilities.QUICK_FEET, "Quick Feet", "Boosts the Speed stat if the Pokémon has a status condition.", 4) - .conditionalAttr(pokemon => pokemon.status.effect === StatusEffect.PARALYSIS, BattleStatMultiplierAbAttr, BattleStat.SPD, 2) + .conditionalAttr(pokemon => pokemon.status ? pokemon.status.effect === StatusEffect.PARALYSIS : false, BattleStatMultiplierAbAttr, BattleStat.SPD, 2) .conditionalAttr(pokemon => !!pokemon.status, BattleStatMultiplierAbAttr, BattleStat.SPD, 1.5), new Ability(Abilities.NORMALIZE, "Normalize", "All the Pokémon's moves become Normal type. The power of those moves is boosted a little.", 4) .attr(MoveTypeChangeAttr, Type.NORMAL, 1.2, (user, target, move) => move.id !== Moves.HIDDEN_POWER && move.id !== Moves.WEATHER_BALL && @@ -2713,7 +2784,13 @@ export function initAbilities() { .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(UnsuppressableAbilityAbAttr), - new Ability(Abilities.DISGUISE, "Disguise (N)", "Once per battle, the shroud that covers the Pokémon can protect it from an attack.", 7) + new Ability(Abilities.DISGUISE, "Disguise (P)", "Once per battle, the shroud that covers the Pokémon can protect it from an attack.", 7) + .attr(PreDefendMovePowerToOneAbAttr, (target, user, move) => target.formIndex == 0 && target.getAttackTypeEffectiveness(move.type) > 0) + .attr(PostSummonFormChangeAbAttr, p => p.battleData.hitCount === 0 ? 0 : 1) + .attr(PostBattleInitFormChangeAbAttr, p => p.battleData.hitCount === 0 ? 0 : 1) + .attr(PostDefendFormChangeAbAttr, p => p.battleData.hitCount === 0 ? 0 : 1) + .attr(PreDefendFormChangeAbAttr, p => p.battleData.hitCount === 0 ? 0 : 1) + .attr(PostDefendDisguiseAbAttr) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(UnsuppressableAbilityAbAttr) diff --git a/src/data/pokemon-forms.ts b/src/data/pokemon-forms.ts index bb22f9859..4bf7b7ac8 100644 --- a/src/data/pokemon-forms.ts +++ b/src/data/pokemon-forms.ts @@ -565,6 +565,10 @@ export const pokemonFormChanges: PokemonFormChanges = { new SpeciesFormChange(Species.MINIOR, 'violet-meteor', 'violet', new SpeciesFormChangeManualTrigger(), true), new SpeciesFormChange(Species.MINIOR, 'violet', 'violet-meteor', new SpeciesFormChangeManualTrigger(), true) ], + [Species.MIMIKYU]: [ + new SpeciesFormChange(Species.MIMIKYU, 'disguised', 'busted', new SpeciesFormChangeManualTrigger(), true), + new SpeciesFormChange(Species.MIMIKYU, 'busted', 'disguised', new SpeciesFormChangeManualTrigger(), true) + ], [Species.NECROZMA]: [ new SpeciesFormChange(Species.NECROZMA, '', 'dawn-wings', new SpeciesFormChangeItemTrigger(FormChangeItem.N_LUNARIZER)), new SpeciesFormChange(Species.NECROZMA, '', 'dusk-mane', new SpeciesFormChangeItemTrigger(FormChangeItem.N_SOLARIZER))