Skip to content

Commit

Permalink
Dragon Tail now properly respects abilities like Suction Cups
Browse files Browse the repository at this point in the history
  • Loading branch information
DayKev committed Sep 14, 2024
1 parent 783b9d8 commit 3cc560a
Show file tree
Hide file tree
Showing 2 changed files with 171 additions and 153 deletions.
92 changes: 48 additions & 44 deletions src/data/move.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5158,31 +5158,29 @@ export class RevivalBlessingAttr extends MoveEffectAttr {
}

export class ForceSwitchOutAttr extends MoveEffectAttr {
private user: boolean;
private batonPass: boolean;

constructor(user?: boolean, batonPass?: boolean) {
constructor(
private selfSwitch: boolean = false,
private batonPass: boolean = false
) {
super(false, MoveEffectTrigger.POST_APPLY, false, true);
this.user = !!user;
this.batonPass = !!batonPass;
}

isBatonPass() {
return this.batonPass;
}

// TODO: Why is this a Promise?
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise<boolean> {
return new Promise(resolve => {

// Check if the move category is not STATUS or if the switch out condition is not met
if (!this.getSwitchOutCondition()(user, target, move)) {
return resolve(false);
}

// Move the switch out logic inside the conditional block
// This ensures that the switch out only happens when the conditions are met
const switchOutTarget = this.user ? user : target;
if (switchOutTarget instanceof PlayerPokemon) {
// Move the switch out logic inside the conditional block
// This ensures that the switch out only happens when the conditions are met
const switchOutTarget = this.selfSwitch ? user : target;
if (switchOutTarget instanceof PlayerPokemon) {
switchOutTarget.leaveField(!this.batonPass);

if (switchOutTarget.hp > 0) {
Expand All @@ -5191,42 +5189,44 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
} else {
resolve(false);
}
return;
} else if (user.scene.currentBattle.battleType !== BattleType.WILD) {
// Switch out logic for trainer battles
return;
} else if (user.scene.currentBattle.battleType !== BattleType.WILD) {
// Switch out logic for trainer battles
switchOutTarget.leaveField(!this.batonPass);

if (switchOutTarget.hp > 0) {
// for opponent switching out
user.scene.prependToPhase(new SwitchSummonPhase(user.scene, switchOutTarget.getFieldIndex(), (user.scene.currentBattle.trainer ? user.scene.currentBattle.trainer.getNextSummonIndex((switchOutTarget as EnemyPokemon).trainerSlot) : 0), false, this.batonPass, false), MoveEndPhase);
if (switchOutTarget.hp > 0) {
// for opponent switching out
user.scene.prependToPhase(new SwitchSummonPhase(user.scene, switchOutTarget.getFieldIndex(),
(user.scene.currentBattle.trainer ? user.scene.currentBattle.trainer.getNextSummonIndex((switchOutTarget as EnemyPokemon).trainerSlot) : 0),
false, this.batonPass, false), MoveEndPhase);
}
} else {
// Switch out logic for everything else (eg: WILD battles)
switchOutTarget.leaveField(false);
} else {
// Switch out logic for everything else (eg: WILD battles)
switchOutTarget.leaveField(false);

if (switchOutTarget.hp) {
if (switchOutTarget.hp) {
switchOutTarget.setWildFlee(true);
user.scene.queueMessage(i18next.t("moveTriggers:fled", {pokemonName: getPokemonNameWithAffix(switchOutTarget)}), null, true, 500);
user.scene.queueMessage(i18next.t("moveTriggers:fled", {pokemonName: getPokemonNameWithAffix(switchOutTarget)}), null, true, 500);

// in double battles redirect potential moves off fled pokemon
if (switchOutTarget.scene.currentBattle.double) {
const allyPokemon = switchOutTarget.getAlly();
switchOutTarget.scene.redirectPokemonMoves(switchOutTarget, allyPokemon);
}
}
}

if (!switchOutTarget.getAlly()?.isActive(true)) {
user.scene.clearEnemyHeldItemModifiers();
if (!switchOutTarget.getAlly()?.isActive(true)) {
user.scene.clearEnemyHeldItemModifiers();

if (switchOutTarget.hp) {
user.scene.pushPhase(new BattleEndPhase(user.scene));
user.scene.pushPhase(new NewBattlePhase(user.scene));
}
}
}
if (switchOutTarget.hp) {
user.scene.pushPhase(new BattleEndPhase(user.scene));
user.scene.pushPhase(new NewBattlePhase(user.scene));
}
}
}

resolve(true);
});
resolve(true);
});
}

getCondition(): MoveConditionFunc {
Expand All @@ -5241,38 +5241,42 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {

getSwitchOutCondition(): MoveConditionFunc {
return (user, target, move) => {
const switchOutTarget = (this.user ? user : target);
const switchOutTarget = (this.selfSwitch ? user : target);
const player = switchOutTarget instanceof PlayerPokemon;

if (!this.user && move.hitsSubstitute(user, target)) {
return false;
}
if (!this.selfSwitch) {
if (move.hitsSubstitute(user, target)) {
return false;
}

if (!this.user && move.category === MoveCategory.STATUS && (target.hasAbilityWithAttr(ForceSwitchOutImmunityAbAttr))) {
return false;
const blockedByAbility = new Utils.BooleanHolder(false);
applyAbAttrs(ForceSwitchOutImmunityAbAttr, target, blockedByAbility);
return !blockedByAbility.value;
}

if (!player && !user.scene.currentBattle.battleType) {
if (!player && user.scene.currentBattle.battleType === BattleType.WILD) {
if (this.batonPass) {
return false;
}
// Don't allow wild opponents to flee on the boss stage since it can ruin a run early on
if (!(user.scene.currentBattle.waveIndex % 10)) {
if (user.scene.currentBattle.waveIndex % 10 === 0) {
return false;
}
}

const party = player ? user.scene.getParty() : user.scene.getEnemyParty();
return (!player && !user.scene.currentBattle.battleType) || party.filter(p => p.isAllowedInBattle() && (player || (p as EnemyPokemon).trainerSlot === (switchOutTarget as EnemyPokemon).trainerSlot)).length > user.scene.currentBattle.getBattlerCount();
return (!player && !user.scene.currentBattle.battleType)
|| party.filter(p => p.isAllowedInBattle()
&& (player || (p as EnemyPokemon).trainerSlot === (switchOutTarget as EnemyPokemon).trainerSlot)).length > user.scene.currentBattle.getBattlerCount();
};
}

getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer {
if (!user.scene.getEnemyParty().find(p => p.isActive() && !p.isOnField())) {
return -20;
}
let ret = this.user ? Math.floor((1 - user.getHpRatio()) * 20) : super.getUserBenefitScore(user, target, move);
if (this.user && this.batonPass) {
let ret = this.selfSwitch ? Math.floor((1 - user.getHpRatio()) * 20) : super.getUserBenefitScore(user, target, move);
if (this.selfSwitch && this.batonPass) {
const statStageTotal = user.getStatStages().reduce((s: integer, total: integer) => total += s, 0);
ret = ret / 2 + (Phaser.Tweens.Builders.GetEaseFunction("Sine.easeOut")(Math.min(Math.abs(statStageTotal), 10) / 10) * (statStageTotal >= 0 ? 10 : -10));
}
Expand Down
Loading

0 comments on commit 3cc560a

Please sign in to comment.