implement Cheek Pouch ability (#987)

* Partially implement Cheek Pouch ability

* add cheek pouch trigger to EatBerryAttr class

* Partially implement Cheek Pouch ability

* add cheek pouch trigger to EatBerryAttr class

* add cheek pouch trigger to new berry phase, remove partial tag

* run auto formatter because I forgot

* hotfix berries triggering before status effects

* Revert "hotfix berries triggering before status effects"

This reverts commit 3fbbc9a165.

* add partial tags to abilities that would be blocked by Heal Block
This commit is contained in:
Dmitriy K 2024-05-28 13:19:03 -04:00 committed by GitHub
parent e7cef039c3
commit 9893c21a7e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 54 additions and 7 deletions

View File

@ -2662,6 +2662,38 @@ export class PreventBerryUseAbAttr extends AbAttr {
}
}
/**
* A Pokemon with this ability heals by a percentage of their maximum hp after eating a berry
* @param healPercent - Percent of Max HP to heal
* @see {@linkcode apply()} for implementation
*/
export class HealFromBerryUseAbAttr extends AbAttr {
/** Percent of Max HP to heal */
private healPercent: number;
constructor(healPercent: number) {
super();
// Clamp healPercent so its between [0,1].
this.healPercent = Math.max(Math.min(healPercent, 1), 0);
}
apply(pokemon: Pokemon, passive: boolean, ...args: [Utils.BooleanHolder, any[]]): boolean {
const { name: abilityName } = passive ? pokemon.getPassiveAbility() : pokemon.getAbility();
pokemon.scene.unshiftPhase(
new PokemonHealPhase(
pokemon.scene,
pokemon.getBattlerIndex(),
Math.max(Math.floor(pokemon.getMaxHp() * this.healPercent), 1),
getPokemonMessage(pokemon, `'s ${abilityName}\nrestored its HP!`),
true
)
);
return true;
}
}
export class RunSuccessAbAttr extends AbAttr {
apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
(args[0] as Utils.IntegerHolder).value = 256;
@ -3308,9 +3340,11 @@ export function initAbilities() {
.bypassFaint(),
new Ability(Abilities.VOLT_ABSORB, 3)
.attr(TypeImmunityHealAbAttr, Type.ELECTRIC)
.partial() // Healing not blocked by Heal Block
.ignorable(),
new Ability(Abilities.WATER_ABSORB, 3)
.attr(TypeImmunityHealAbAttr, Type.WATER)
.partial() // Healing not blocked by Heal Block
.ignorable(),
new Ability(Abilities.OBLIVIOUS, 3)
.attr(BattlerTagImmunityAbAttr, BattlerTagType.INFATUATED)
@ -3409,7 +3443,8 @@ export function initAbilities() {
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.getMove().hasFlag(MoveFlags.SOUND_BASED))
.ignorable(),
new Ability(Abilities.RAIN_DISH, 3)
.attr(PostWeatherLapseHealAbAttr, 1, WeatherType.RAIN, WeatherType.HEAVY_RAIN),
.attr(PostWeatherLapseHealAbAttr, 1, WeatherType.RAIN, WeatherType.HEAVY_RAIN)
.partial(), // Healing not blocked by Heal Block
new Ability(Abilities.SAND_STREAM, 3)
.attr(PostSummonWeatherChangeAbAttr, WeatherType.SANDSTORM)
.attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.SANDSTORM),
@ -3530,6 +3565,7 @@ export function initAbilities() {
.attr(PostWeatherLapseHealAbAttr, 2, WeatherType.RAIN, WeatherType.HEAVY_RAIN)
.attr(ReceivedTypeDamageMultiplierAbAttr, Type.FIRE, 1.25)
.attr(TypeImmunityHealAbAttr, Type.WATER)
.partial() // Healing not blocked by Heal Block
.ignorable(),
new Ability(Abilities.DOWNLOAD, 4)
.attr(DownloadAbAttr),
@ -3607,7 +3643,8 @@ export function initAbilities() {
.ignorable(),
new Ability(Abilities.ICE_BODY, 4)
.attr(BlockWeatherDamageAttr, WeatherType.HAIL)
.attr(PostWeatherLapseHealAbAttr, 1, WeatherType.HAIL, WeatherType.SNOW),
.attr(PostWeatherLapseHealAbAttr, 1, WeatherType.HAIL, WeatherType.SNOW)
.partial(), // Healing not blocked by Heal Block
new Ability(Abilities.SOLID_ROCK, 4)
.attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getAttackTypeEffectiveness(move.type, user) >= 2, 0.75)
.ignorable(),
@ -3768,7 +3805,8 @@ export function initAbilities() {
.ignorable()
.unimplemented(),
new Ability(Abilities.CHEEK_POUCH, 6)
.unimplemented(),
.attr(HealFromBerryUseAbAttr, 1/3)
.partial(), // Healing not blocked by Heal Block
new Ability(Abilities.PROTEAN, 6)
.unimplemented(),
new Ability(Abilities.FUR_COAT, 6)
@ -4201,6 +4239,7 @@ export function initAbilities() {
.ignorable(),
new Ability(Abilities.EARTH_EATER, 9)
.attr(TypeImmunityHealAbAttr, Type.GROUND)
.partial() // Healing not blocked by Heal Block
.ignorable(),
new Ability(Abilities.MYCELIUM_MIGHT, 9)
.attr(MoveAbilityBypassAbAttr, (pokemon, move: Move) => move.category === MoveCategory.STATUS)
@ -4214,7 +4253,8 @@ export function initAbilities() {
.attr(PostSummonStatChangeAbAttr, BattleStat.EVA, -1)
.condition(getOncePerBattleCondition(Abilities.SUPERSWEET_SYRUP)),
new Ability(Abilities.HOSPITALITY, 9)
.attr(PostSummonAllyHealAbAttr, 4, true),
.attr(PostSummonAllyHealAbAttr, 4, true)
.partial(), // Healing not blocked by Heal Block
new Ability(Abilities.TOXIC_CHAIN, 9)
.attr(PostAttackApplyStatusEffectAbAttr, false, 30, StatusEffect.TOXIC),
new Ability(Abilities.EMBODY_ASPECT_TEAL, 9)

View File

@ -12,7 +12,7 @@ import * as Utils from "../utils";
import { WeatherType } from "./weather";
import { ArenaTagSide, ArenaTrapTag } from "./arena-tag";
import { ArenaTagType } from "./enums/arena-tag-type";
import { UnswappableAbilityAbAttr, UncopiableAbilityAbAttr, UnsuppressableAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPreSwitchOutAbAttrs, PreSwitchOutAbAttr, applyPostDefendAbAttrs, PostDefendContactApplyStatusEffectAbAttr, MoveAbilityBypassAbAttr, ReverseDrainAbAttr, FieldPreventExplosiveMovesAbAttr, ForceSwitchOutImmunityAbAttr, BlockItemTheftAbAttr, applyPostAttackAbAttrs, ConfusionOnStatusEffectAbAttr } from "./ability";
import { UnswappableAbilityAbAttr, UncopiableAbilityAbAttr, UnsuppressableAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPreSwitchOutAbAttrs, PreSwitchOutAbAttr, applyPostDefendAbAttrs, PostDefendContactApplyStatusEffectAbAttr, MoveAbilityBypassAbAttr, ReverseDrainAbAttr, FieldPreventExplosiveMovesAbAttr, ForceSwitchOutImmunityAbAttr, BlockItemTheftAbAttr, applyPostAttackAbAttrs, ConfusionOnStatusEffectAbAttr, HealFromBerryUseAbAttr } from "./ability";
import { Abilities } from "./enums/abilities";
import { allAbilities } from "./ability";
import { PokemonHeldItemModifier, BerryModifier, PreserveBerryModifier } from "../modifier/modifier";
@ -1577,8 +1577,11 @@ export class EatBerryAttr extends MoveEffectAttr {
}
target.scene.updateModifiers(target.isPlayer());
}
this.chosenBerry = undefined;
applyAbAttrs(HealFromBerryUseAbAttr, target, new Utils.BooleanHolder(false));
return true;
}

View File

@ -30,7 +30,7 @@ import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, get
import { TempBattleStat } from "./data/temp-battle-stat";
import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag";
import { ArenaTagType } from "./data/enums/arena-tag-type";
import { CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, IgnoreOpponentEvasionAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr, applyPostMoveUsedAbAttrs, PostMoveUsedAbAttr } from "./data/ability";
import { CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, IgnoreOpponentEvasionAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr, applyPostMoveUsedAbAttrs, PostMoveUsedAbAttr, HealFromBerryUseAbAttr } from "./data/ability";
import { Unlockables, getUnlockableName } from "./system/unlockables";
import { getBiomeKey } from "./field/arena";
import { BattleType, BattlerIndex, TurnCommand } from "./battle";
@ -2221,7 +2221,9 @@ export class BerryPhase extends FieldPhase {
if (cancelled.value) {
pokemon.scene.queueMessage(getPokemonMessage(pokemon, " is too\nnervous to eat berries!"));
} else {
this.scene.unshiftPhase(new CommonAnimPhase(this.scene, pokemon.getBattlerIndex(), pokemon.getBattlerIndex(), CommonAnim.USE_ITEM));
this.scene.unshiftPhase(
new CommonAnimPhase(this.scene, pokemon.getBattlerIndex(), pokemon.getBattlerIndex(), CommonAnim.USE_ITEM)
);
for (const berryModifier of this.scene.applyModifiers(BerryModifier, pokemon.isPlayer(), pokemon) as BerryModifier[]) {
if (berryModifier.consumed) {
@ -2234,6 +2236,8 @@ export class BerryPhase extends FieldPhase {
}
this.scene.updateModifiers(pokemon.isPlayer());
applyAbAttrs(HealFromBerryUseAbAttr, pokemon, new Utils.BooleanHolder(false));
}
}
});