Skip to content

Commit

Permalink
[Ability] Refactor Gulp Missile and make it trigger when Cramorant fa…
Browse files Browse the repository at this point in the history
…ints (#4428)

* reimplement gulp missile

* cleanup + docs

* more cleanup

* add override

* update paths
  • Loading branch information
torranx authored Sep 30, 2024
1 parent d620b5c commit 4c327e9
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 96 deletions.
57 changes: 8 additions & 49 deletions src/data/ability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Constructor } from "#app/utils";
import * as Utils from "../utils";
import { getPokemonNameWithAffix } from "../messages";
import { Weather, WeatherType } from "./weather";
import { BattlerTag, GroundedTag, GulpMissileTag, SemiInvulnerableTag } from "./battler-tags";
import { BattlerTag, GroundedTag } from "./battler-tags";
import { StatusEffect, getNonVolatileStatusEffects, getStatusEffectDescriptor, getStatusEffectHealText } from "./status-effect";
import { Gender } from "./gender";
import Move, { AttackMove, MoveCategory, MoveFlags, MoveTarget, FlinchAttr, OneHitKOAttr, HitHealAttr, allMoves, StatusMove, SelfStatusMove, VariablePowerAttr, applyMoveAttrs, IncrementMovePriorityAttr, VariableMoveTypeAttr, RandomMovesetMoveAttr, RandomMoveAttr, NaturePowerAttr, CopyMoveAttr, MoveAttr, MultiHitAttr, ChargeAttr, SacrificialAttr, SacrificialAttrOnHit, NeutralDamageAgainstFlyingTypeMultiplierAttr, FixedDamageAttr } from "./move";
Expand Down Expand Up @@ -536,53 +536,6 @@ export class PostDefendAbAttr extends AbAttr {
}
}

/**
* Applies the effects of Gulp Missile when the user is hit by an attack.
* @extends PostDefendAbAttr
*/
export class PostDefendGulpMissileAbAttr extends PostDefendAbAttr {
constructor() {
super(true);
}

/**
* Damages the attacker and triggers the secondary effect based on the form or the BattlerTagType.
* @param {Pokemon} pokemon - The defending Pokemon.
* @param passive - n/a
* @param {Pokemon} attacker - The attacking Pokemon.
* @param {Move} move - The move being used.
* @param {HitResult} hitResult - n/a
* @param {any[]} args - n/a
* @returns Whether the effects of the ability are applied.
*/
applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean | Promise<boolean> {
const battlerTag = pokemon.getTag(GulpMissileTag);
if (!battlerTag || move.category === MoveCategory.STATUS || pokemon.getTag(SemiInvulnerableTag)) {
return false;
}

if (simulated) {
return true;
}

const cancelled = new Utils.BooleanHolder(false);
applyAbAttrs(BlockNonDirectDamageAbAttr, attacker, cancelled);

if (!cancelled.value) {
attacker.damageAndUpdate(Math.max(1, Math.floor(attacker.getMaxHp() / 4)), HitResult.OTHER);
}

if (battlerTag.tagType === BattlerTagType.GULP_MISSILE_ARROKUDA) {
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, attacker.getBattlerIndex(), false, [ Stat.DEF ], -1));
} else {
attacker.trySetStatus(StatusEffect.PARALYSIS, true, pokemon);
}

pokemon.removeTag(battlerTag.tagType);
return true;
}
}

export class FieldPriorityMoveImmunityAbAttr extends PreDefendAbAttr {
applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean {
const attackPriority = new Utils.IntegerHolder(move.priority);
Expand Down Expand Up @@ -5668,13 +5621,19 @@ export function initAbilities() {
new Ability(Abilities.MIRROR_ARMOR, 8)
.ignorable()
.unimplemented(),
/**
* Right now, the logic is attached to Surf and Dive moves. Ideally, the post-defend/hit should be an
* ability attribute but the current implementation of move effects for BattlerTag does not support this- in the case
* where Cramorant is fainted.
* @see {@linkcode GulpMissileTagAttr} and {@linkcode GulpMissileTag} for Gulp Missile implementation
*/
new Ability(Abilities.GULP_MISSILE, 8)
.attr(UnsuppressableAbilityAbAttr)
.attr(NoTransformAbilityAbAttr)
.attr(NoFusionAbilityAbAttr)
.attr(UncopiableAbilityAbAttr)
.attr(UnswappableAbilityAbAttr)
.attr(PostDefendGulpMissileAbAttr),
.bypassFaint(),
new Ability(Abilities.STALWART, 8)
.attr(BlockRedirectAbAttr),
new Ability(Abilities.STEAM_ENGINE, 8)
Expand Down
31 changes: 30 additions & 1 deletion src/data/battler-tags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2123,7 +2123,36 @@ export class StockpilingTag extends BattlerTag {
*/
export class GulpMissileTag extends BattlerTag {
constructor(tagType: BattlerTagType, sourceMove: Moves) {
super(tagType, BattlerTagLapseType.CUSTOM, 0, sourceMove);
super(tagType, BattlerTagLapseType.HIT, 0, sourceMove);
}

override lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
if (pokemon.getTag(BattlerTagType.UNDERWATER)) {
return true;
}

const moveEffectPhase = pokemon.scene.getCurrentPhase();
if (moveEffectPhase instanceof MoveEffectPhase) {
const attacker = moveEffectPhase.getUserPokemon();

if (!attacker) {
return false;
}

const cancelled = new Utils.BooleanHolder(false);
applyAbAttrs(BlockNonDirectDamageAbAttr, attacker, cancelled);

if (!cancelled.value) {
attacker.damageAndUpdate(Math.max(1, Math.floor(attacker.getMaxHp() / 4)), HitResult.OTHER);
}

if (this.tagType === BattlerTagType.GULP_MISSILE_ARROKUDA) {
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, attacker.getBattlerIndex(), false, [ Stat.DEF ], -1));
} else {
attacker.trySetStatus(StatusEffect.PARALYSIS, true, pokemon);
}
}
return false;
}

/**
Expand Down
Loading

0 comments on commit 4c327e9

Please sign in to comment.