Convert apply attribute functions to promises

This commit is contained in:
Flashfyre 2023-12-22 21:42:47 -05:00
parent dd89db29fd
commit 6391e05508
2 changed files with 627 additions and 289 deletions

View File

@ -1739,14 +1739,16 @@ export class MoveEffectPhase extends PokemonPhase {
}
Utils.executeIf(!isProtected && !chargeEffect, () => applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && (attr as MoveEffectAttr).trigger === MoveEffectTrigger.HIT,
user, target, this.move.getMove()).then(() => {
if (!target.isFainted()) {
applyPostDefendAbAttrs(PostDefendAbAttr, target, user, this.move, hitResult);
return Utils.executeIf(!target.isFainted(), () => applyPostDefendAbAttrs(PostDefendAbAttr, target, user, this.move, hitResult).then(() => {
if (!user.isPlayer() && this.move instanceof AttackMove)
user.scene.applyModifiers(EnemyAttackStatusEffectChanceModifier, false, target);
}
applyPostAttackAbAttrs(PostAttackAbAttr, user, target, this.move, hitResult);
})).then(() => {
applyPostAttackAbAttrs(PostAttackAbAttr, user, target, this.move, hitResult).then(() => {
if (this.move instanceof AttackMove)
this.scene.applyModifiers(ContactHeldItemTransferChanceModifier, this.player, user, target.getFieldIndex());
resolve();
});
});
})
).then(() => resolve());
});
@ -1894,6 +1896,8 @@ export class ShowAbilityPhase extends PokemonPhase {
}
start() {
super.start();
this.scene.abilityBar.showAbility(this.getPokemon());
this.end();

View File

@ -60,7 +60,7 @@ export abstract class AbAttr {
this.showAbility = showAbility === undefined || showAbility;
}
apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean {
apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise<boolean> {
return false;
}
@ -100,7 +100,7 @@ export class DoubleBattleChanceAbAttr extends AbAttr {
type PreDefendAbAttrCondition = (pokemon: Pokemon, attacker: Pokemon, move: PokemonMove) => boolean;
export class PreDefendAbAttr extends AbAttr {
applyPreDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean {
applyPreDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise<boolean> {
return false;
}
}
@ -258,7 +258,7 @@ export class NonSuperEffectiveImmunityAbAttr extends TypeImmunityAbAttr {
}
export class PostDefendAbAttr extends AbAttr {
applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean | Promise<boolean> {
return false;
}
}
@ -370,7 +370,7 @@ export class PostDefendCritStatChangeAbAttr extends PostDefendAbAttr {
}
export class PreAttackAbAttr extends AbAttr {
applyPreAttack(pokemon: Pokemon, defender: Pokemon, move: PokemonMove, args: any[]): boolean {
applyPreAttack(pokemon: Pokemon, defender: Pokemon, move: PokemonMove, args: any[]): boolean | Promise<boolean> {
return false;
}
}
@ -449,7 +449,7 @@ export class BattleStatMultiplierAbAttr extends AbAttr {
this.multiplier = multiplier;
}
applyBattleStat(pokemon: Pokemon, battleStat: BattleStat, statValue: Utils.NumberHolder, args: any[]) {
applyBattleStat(pokemon: Pokemon, battleStat: BattleStat, statValue: Utils.NumberHolder, args: any[]): boolean | Promise<boolean> {
if (battleStat === this.battleStat) {
statValue.value *= this.multiplier;
return true;
@ -460,13 +460,14 @@ export class BattleStatMultiplierAbAttr extends AbAttr {
}
export class PostAttackAbAttr extends AbAttr {
applyPostAttack(pokemon: Pokemon, defender: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
applyPostAttack(pokemon: Pokemon, defender: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean | Promise<boolean> {
return false;
}
}
export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr {
applyPostAttack(pokemon: Pokemon, defender: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
applyPostAttack(pokemon: Pokemon, defender: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): Promise<boolean> {
return new Promise<boolean>(resolve => {
if (hitResult < HitResult.NO_EFFECT) {
const heldItems = this.getTargetHeldItems(defender).filter(i => i.getTransferrable(false));
if (heldItems.length) {
@ -475,11 +476,13 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr {
pokemon.scene.tryTransferHeldItemModifier(stolenItem, pokemon, false, false).then(success => {
if (success)
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` stole\n${defender.name}'s ${stolenItem.type.name}!`));
resolve(success);
});
return true;
return;
}
}
return false;
resolve(false);
});
}
getTargetHeldItems(target: Pokemon): PokemonHeldItemModifier[] {
@ -501,7 +504,7 @@ export class IgnoreOpponentStatChangesAbAttr extends AbAttr {
}
export class PostSummonAbAttr extends AbAttr {
applyPostSummon(pokemon: Pokemon, args: any[]) {
applyPostSummon(pokemon: Pokemon, args: any[]): boolean | Promise<boolean> {
return false;
}
}
@ -624,7 +627,7 @@ export class PostSummonTransformAbAttr extends PostSummonAbAttr {
}
export class PreStatChangeAbAttr extends AbAttr {
applyPreStatChange(pokemon: Pokemon, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean {
applyPreStatChange(pokemon: Pokemon, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise<boolean> {
return false;
}
}
@ -653,7 +656,7 @@ export class ProtectStatAbAttr extends PreStatChangeAbAttr {
}
export class PreSetStatusAbAttr extends AbAttr {
applyPreSetStatus(pokemon: Pokemon, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean {
applyPreSetStatus(pokemon: Pokemon, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise<boolean> {
return false;
}
}
@ -682,7 +685,7 @@ export class StatusEffectImmunityAbAttr extends PreSetStatusAbAttr {
}
export class PreApplyBattlerTagAbAttr extends AbAttr {
applyPreApplyBattlerTag(pokemon: Pokemon, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean {
applyPreApplyBattlerTag(pokemon: Pokemon, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise<boolean> {
return false;
}
}
@ -715,7 +718,7 @@ export class BlockCritAbAttr extends AbAttr { }
export class IgnoreContactAbAttr extends AbAttr { }
export class PreWeatherEffectAbAttr extends AbAttr {
applyPreWeatherEffect(pokemon: Pokemon, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): boolean {
applyPreWeatherEffect(pokemon: Pokemon, weather: Weather, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise<boolean> {
return false;
}
}
@ -776,7 +779,7 @@ export class PostWeatherLapseAbAttr extends AbAttr {
this.weatherTypes = weatherTypes;
}
applyPostWeatherLapse(pokemon: Pokemon, weather: Weather, args: any[]): boolean {
applyPostWeatherLapse(pokemon: Pokemon, weather: Weather, args: any[]): boolean | Promise<boolean> {
return false;
}
@ -829,7 +832,7 @@ export class PostWeatherLapseDamageAbAttr extends PostWeatherLapseAbAttr {
}
export class PostTurnAbAttr extends AbAttr {
applyPostTurn(pokemon: Pokemon, args: any[]) {
applyPostTurn(pokemon: Pokemon, args: any[]): boolean | Promise<boolean> {
return false;
}
}
@ -899,7 +902,7 @@ export class RunSuccessAbAttr extends AbAttr {
}
export class CheckTrappedAbAttr extends AbAttr {
applyCheckTrapped(pokemon: Pokemon, trapped: Utils.BooleanHolder, args: any[]): boolean {
applyCheckTrapped(pokemon: Pokemon, trapped: Utils.BooleanHolder, args: any[]): boolean | Promise<boolean> {
return false;
}
}
@ -939,329 +942,660 @@ export class WeightMultiplierAbAttr extends AbAttr {
}
}
export function applyAbAttrs(attrType: { new(...args: any[]): AbAttr }, pokemon: Pokemon, cancelled: Utils.BooleanHolder, ...args: any[]): void {
export function applyAbAttrs(attrType: { new(...args: any[]): AbAttr }, pokemon: Pokemon, cancelled: Utils.BooleanHolder, ...args: any[]): Promise<void> {
return new Promise(resolve => {
if (!pokemon.canApplyAbility())
return;
return resolve();
const ability = pokemon.getAbility();
const attrs = ability.getAttrs(attrType) as AbAttr[];
for (let attr of attrs) {
const clearSpliceQueueAndResolve = () => {
pokemon.scene.clearPhaseQueueSplice();
resolve();
};
const applyNextAbAttr = () => {
if (attrs.length)
applyAbAttr(attrs.shift());
else
clearSpliceQueueAndResolve();
};
const applyAbAttr = (attr: AbAttr) => {
if (!canApplyAttr(pokemon, attr))
continue;
return applyNextAbAttr();
pokemon.scene.setPhaseQueueSplice();
if (attr.apply(pokemon, cancelled, args)) {
const onApplySuccess = () => {
if (attr.showAbility)
queueShowAbility(pokemon);
const message = attr.getTriggerMessage(pokemon);
if (message)
pokemon.scene.queueMessage(message);
};
const result = attr.apply(pokemon, cancelled, args);
if (result instanceof Promise) {
result.then(success => {
if (success)
onApplySuccess();
applyNextAbAttr();
});
} else {
if (result)
onApplySuccess();
applyNextAbAttr();
}
}
pokemon.scene.clearPhaseQueueSplice();
};
applyNextAbAttr();
});
}
export function applyPreDefendAbAttrs(attrType: { new(...args: any[]): PreDefendAbAttr },
pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, ...args: any[]): void {
pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, ...args: any[]): Promise<void> {
return new Promise(resolve => {
if (!pokemon.canApplyAbility())
return;
return resolve();
const ability = pokemon.getAbility();
const attrs = ability.getAttrs(attrType) as PreDefendAbAttr[];
for (let attr of attrs) {
const clearSpliceQueueAndResolve = () => {
pokemon.scene.clearPhaseQueueSplice();
resolve();
};
const applyNextAbAttr = () => {
if (attrs.length)
applyAbAttr(attrs.shift());
else
clearSpliceQueueAndResolve();
};
const applyAbAttr = (attr: PreDefendAbAttr) => {
if (!canApplyAttr(pokemon, attr))
continue;
return applyNextAbAttr();
pokemon.scene.setPhaseQueueSplice();
if (attr.applyPreDefend(pokemon, attacker, move, cancelled, args)) {
const onApplySuccess = () => {
if (attr.showAbility)
queueShowAbility(pokemon);
const message = attr.getTriggerMessage(pokemon, attacker, move);
const message = attr.getTriggerMessage(pokemon);
if (message)
pokemon.scene.queueMessage(message);
};
const result = attr.applyPreDefend(pokemon, attacker, move, cancelled, args);
if (result instanceof Promise) {
result.then(success => {
if (success)
onApplySuccess();
applyNextAbAttr();
});
} else {
if (result)
onApplySuccess();
applyNextAbAttr();
}
}
pokemon.scene.clearPhaseQueueSplice();
};
applyNextAbAttr();
});
}
export function applyPostDefendAbAttrs(attrType: { new(...args: any[]): PostDefendAbAttr },
pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, ...args: any[]): void {
pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, ...args: any[]): Promise<void> {
return new Promise(resolve => {
if (!pokemon.canApplyAbility())
return;
return resolve();
const ability = pokemon.getAbility();
const attrs = ability.getAttrs(attrType) as PostDefendAbAttr[];
for (let attr of attrs) {
const clearSpliceQueueAndResolve = () => {
pokemon.scene.clearPhaseQueueSplice();
resolve();
};
const applyNextAbAttr = () => {
if (attrs.length)
applyAbAttr(attrs.shift());
else
clearSpliceQueueAndResolve();
};
const applyAbAttr = (attr: PostDefendAbAttr) => {
if (!canApplyAttr(pokemon, attr))
continue;
return applyNextAbAttr();
pokemon.scene.setPhaseQueueSplice();
if (attr.applyPostDefend(pokemon, attacker, move, hitResult, args)) {
const onApplySuccess = () => {
if (attr.showAbility)
queueShowAbility(pokemon);
const message = attr.getTriggerMessage(pokemon, attacker, move);
const message = attr.getTriggerMessage(pokemon);
if (message)
pokemon.scene.queueMessage(message);
};
const result = attr.applyPostDefend(pokemon, attacker, move, hitResult, args);
if (result instanceof Promise) {
result.then(success => {
if (success)
onApplySuccess();
applyNextAbAttr();
});
} else {
if (result)
onApplySuccess();
applyNextAbAttr();
}
}
pokemon.scene.clearPhaseQueueSplice();
};
applyNextAbAttr();
});
}
export function applyBattleStatMultiplierAbAttrs(attrType: { new(...args: any[]): BattleStatMultiplierAbAttr },
pokemon: Pokemon, battleStat: BattleStat, statValue: Utils.NumberHolder, ...args: any[]) {
pokemon: Pokemon, battleStat: BattleStat, statValue: Utils.NumberHolder, ...args: any[]): Promise<void> {
return new Promise(resolve => {
if (!pokemon.canApplyAbility())
return;
return resolve();
const ability = pokemon.getAbility();
const attrs = ability.getAttrs(attrType) as BattleStatMultiplierAbAttr[];
for (let attr of attrs) {
if (!canApplyAttr(pokemon, attr))
continue;
pokemon.scene.setPhaseQueueSplice();
if (attr.applyBattleStat(pokemon, battleStat, statValue, args)) {
const message = attr.getTriggerMessage(pokemon);
if (message) {
if (attr.showAbility)
queueShowAbility(pokemon);
pokemon.scene.queueMessage(message);
}
}
}
const clearSpliceQueueAndResolve = () => {
pokemon.scene.clearPhaseQueueSplice();
resolve();
};
const applyNextAbAttr = () => {
if (attrs.length)
applyAbAttr(attrs.shift());
else
clearSpliceQueueAndResolve();
};
const applyAbAttr = (attr: BattleStatMultiplierAbAttr) => {
if (!canApplyAttr(pokemon, attr))
return applyNextAbAttr();
pokemon.scene.setPhaseQueueSplice();
const onApplySuccess = () => {
const message = attr.getTriggerMessage(pokemon);
if (message)
pokemon.scene.queueMessage(message);
};
const result = attr.applyBattleStat(pokemon, battleStat, statValue, args);
if (result instanceof Promise) {
result.then(success => {
if (success)
onApplySuccess();
applyNextAbAttr();
});
} else {
if (result)
onApplySuccess();
applyNextAbAttr();
}
};
applyNextAbAttr();
});
}
export function applyPreAttackAbAttrs(attrType: { new(...args: any[]): PreAttackAbAttr },
pokemon: Pokemon, defender: Pokemon, move: PokemonMove, ...args: any[]): void {
pokemon: Pokemon, defender: Pokemon, move: PokemonMove, ...args: any[]): Promise<void> {
return new Promise(resolve => {
if (!pokemon.canApplyAbility())
return;
return resolve();
const ability = pokemon.getAbility();
const attrs = ability.getAttrs(attrType) as PreAttackAbAttr[];
for (let attr of attrs) {
const clearSpliceQueueAndResolve = () => {
pokemon.scene.clearPhaseQueueSplice();
resolve();
};
const applyNextAbAttr = () => {
if (attrs.length)
applyAbAttr(attrs.shift());
else
clearSpliceQueueAndResolve();
};
const applyAbAttr = (attr: PreAttackAbAttr) => {
if (!canApplyAttr(pokemon, attr))
continue;
return applyNextAbAttr();
pokemon.scene.setPhaseQueueSplice();
if (attr.applyPreAttack(pokemon, defender, move, args)) {
const onApplySuccess = () => {
if (attr.showAbility)
queueShowAbility(pokemon);
const message = attr.getTriggerMessage(pokemon, defender, move);
const message = attr.getTriggerMessage(pokemon);
if (message)
pokemon.scene.queueMessage(message);
};
const result = attr.applyPreAttack(pokemon, defender, move, args);
if (result instanceof Promise) {
result.then(success => {
if (success)
onApplySuccess();
applyNextAbAttr();
});
} else {
if (result)
onApplySuccess();
applyNextAbAttr();
}
}
pokemon.scene.clearPhaseQueueSplice();
};
applyNextAbAttr();
});
}
export function applyPostAttackAbAttrs(attrType: { new(...args: any[]): PostAttackAbAttr },
pokemon: Pokemon, defender: Pokemon, move: PokemonMove, hitResult: HitResult, ...args: any[]): void {
pokemon: Pokemon, defender: Pokemon, move: PokemonMove, hitResult: HitResult, ...args: any[]): Promise<void> {
return new Promise(resolve => {
if (!pokemon.canApplyAbility())
return;
return resolve();
const ability = pokemon.getAbility();
const attrs = ability.getAttrs(attrType) as PostAttackAbAttr[];
for (let attr of attrs) {
const clearSpliceQueueAndResolve = () => {
pokemon.scene.clearPhaseQueueSplice();
resolve();
};
const applyNextAbAttr = () => {
if (attrs.length)
applyAbAttr(attrs.shift());
else
clearSpliceQueueAndResolve();
};
const applyAbAttr = (attr: PostAttackAbAttr) => {
if (!canApplyAttr(pokemon, attr))
continue;
return applyNextAbAttr();
pokemon.scene.setPhaseQueueSplice();
if (attr.applyPostAttack(pokemon, defender, move, hitResult, args)) {
const onApplySuccess = () => {
if (attr.showAbility)
queueShowAbility(pokemon);
const message = attr.getTriggerMessage(pokemon, defender, move);
const message = attr.getTriggerMessage(pokemon);
if (message)
pokemon.scene.queueMessage(message);
};
const result = attr.applyPostAttack(pokemon, defender, move, hitResult, args);
if (result instanceof Promise) {
result.then(success => {
if (success)
onApplySuccess();
applyNextAbAttr();
});
} else {
if (result)
onApplySuccess();
applyNextAbAttr();
}
}
pokemon.scene.clearPhaseQueueSplice();
};
applyNextAbAttr();
});
}
export function applyPostSummonAbAttrs(attrType: { new(...args: any[]): PostSummonAbAttr },
pokemon: Pokemon, ...args: any[]): void {
pokemon: Pokemon, ...args: any[]): Promise<void> {
return new Promise(resolve => {
if (!pokemon.canApplyAbility())
return;
return resolve();
const ability = pokemon.getAbility();
const attrs = ability.getAttrs(attrType) as PostSummonAbAttr[];
for (let attr of attrs) {
const clearSpliceQueueAndResolve = () => {
pokemon.scene.clearPhaseQueueSplice();
resolve();
};
const applyNextAbAttr = () => {
if (attrs.length)
applyAbAttr(attrs.shift());
else
clearSpliceQueueAndResolve();
};
const applyAbAttr = (attr: PostSummonAbAttr) => {
if (!canApplyAttr(pokemon, attr))
continue;
return applyNextAbAttr();
pokemon.scene.setPhaseQueueSplice();
if (attr.applyPostSummon(pokemon, args)) {
const onApplySuccess = () => {
if (attr.showAbility)
queueShowAbility(pokemon);
const message = attr.getTriggerMessage(pokemon);
if (message)
pokemon.scene.queueMessage(message);
};
const result = attr.applyPostSummon(pokemon, args);
if (result instanceof Promise) {
result.then(success => {
if (success)
onApplySuccess();
applyNextAbAttr();
});
} else {
if (result)
onApplySuccess();
applyNextAbAttr();
}
}
pokemon.scene.clearPhaseQueueSplice();
};
applyNextAbAttr();
});
}
export function applyPreStatChangeAbAttrs(attrType: { new(...args: any[]): PreStatChangeAbAttr },
pokemon: Pokemon, stat: BattleStat, cancelled: Utils.BooleanHolder, ...args: any[]): void {
pokemon: Pokemon, stat: BattleStat, cancelled: Utils.BooleanHolder, ...args: any[]): Promise<void> {
return new Promise(resolve => {
if (!pokemon.canApplyAbility())
return;
return resolve();
const ability = pokemon.getAbility();
const attrs = ability.getAttrs(attrType) as PreStatChangeAbAttr[];
for (let attr of attrs) {
if (!canApplyAttr(pokemon, attr))
continue;
pokemon.scene.setPhaseQueueSplice();
if (attr.applyPreStatChange(pokemon, stat, cancelled, args)) {
if (attr.showAbility)
queueShowAbility(pokemon);
const message = attr.getTriggerMessage(pokemon, stat);
if (message)
pokemon.scene.queueMessage(message);
}
}
const clearSpliceQueueAndResolve = () => {
pokemon.scene.clearPhaseQueueSplice();
}
export function applyPreSetStatusAbAttrs(attrType: { new(...args: any[]): PreSetStatusAbAttr },
pokemon: Pokemon, effect: StatusEffect, cancelled: Utils.BooleanHolder, ...args: any[]): void {
if (!pokemon.canApplyAbility())
return;
const ability = pokemon.getAbility();
const attrs = ability.getAttrs(attrType) as PreSetStatusAbAttr[];
for (let attr of attrs) {
resolve();
};
const applyNextAbAttr = () => {
if (attrs.length)
applyAbAttr(attrs.shift());
else
clearSpliceQueueAndResolve();
};
const applyAbAttr = (attr: PreStatChangeAbAttr) => {
if (!canApplyAttr(pokemon, attr))
continue;
return applyNextAbAttr();
pokemon.scene.setPhaseQueueSplice();
if (attr.applyPreSetStatus(pokemon, effect, cancelled, args)) {
if (attr.showAbility)
queueShowAbility(pokemon);
const message = attr.getTriggerMessage(pokemon, effect);
if (message)
pokemon.scene.queueMessage(message);
}
}
pokemon.scene.clearPhaseQueueSplice();
}
export function applyPreApplyBattlerTagAbAttrs(attrType: { new(...args: any[]): PreApplyBattlerTagAbAttr },
pokemon: Pokemon, tag: BattlerTag, cancelled: Utils.BooleanHolder, ...args: any[]): void {
if (!pokemon.canApplyAbility())
return;
const ability = pokemon.getAbility();
const attrs = ability.getAttrs(attrType) as PreApplyBattlerTagAbAttr[];
for (let attr of attrs) {
if (!canApplyAttr(pokemon, attr))
continue;
pokemon.scene.setPhaseQueueSplice();
if (attr.applyPreApplyBattlerTag(pokemon, tag, cancelled, args)) {
if (attr.showAbility)
queueShowAbility(pokemon);
const message = attr.getTriggerMessage(pokemon, tag);
if (message)
pokemon.scene.queueMessage(message);
}
}
pokemon.scene.clearPhaseQueueSplice();
}
export function applyPreWeatherEffectAbAttrs(attrType: { new(...args: any[]): PreWeatherEffectAbAttr },
pokemon: Pokemon, weather: Weather, cancelled: Utils.BooleanHolder, ...args: any[]): void {
if (!pokemon.canApplyAbility())
return;
const ability = pokemon.getAbility();
const attrs = ability.getAttrs(attrType) as PreWeatherEffectAbAttr[];
for (let attr of attrs) {
if (!canApplyAttr(pokemon, attr))
continue;
pokemon.scene.setPhaseQueueSplice();
if (attr.applyPreWeatherEffect(pokemon, weather, cancelled, args)) {
pokemon.scene.abilityBar.showAbility(pokemon);
const message = attr.getTriggerMessage(pokemon, weather);
if (message)
pokemon.scene.queueMessage(message);
}
}
pokemon.scene.clearPhaseQueueSplice();
}
export function applyPostTurnAbAttrs(attrType: { new(...args: any[]): PostTurnAbAttr },
pokemon: Pokemon, ...args: any[]): void {
if (!pokemon.canApplyAbility())
return;
const ability = pokemon.getAbility();
const attrs = ability.getAttrs(attrType) as PostTurnAbAttr[];
for (let attr of attrs) {
if (!canApplyAttr(pokemon, attr))
continue;
pokemon.scene.setPhaseQueueSplice();
if (attr.applyPostTurn(pokemon, args)) {
const onApplySuccess = () => {
if (attr.showAbility)
queueShowAbility(pokemon);
const message = attr.getTriggerMessage(pokemon);
if (message)
pokemon.scene.queueMessage(message);
};
const result = attr.applyPreStatChange(pokemon, stat, cancelled, args);
if (result instanceof Promise) {
result.then(success => {
if (success)
onApplySuccess();
applyNextAbAttr();
});
} else {
if (result)
onApplySuccess();
applyNextAbAttr();
}
};
applyNextAbAttr();
});
}
export function applyPreSetStatusAbAttrs(attrType: { new(...args: any[]): PreSetStatusAbAttr },
pokemon: Pokemon, effect: StatusEffect, cancelled: Utils.BooleanHolder, ...args: any[]): Promise<void> {
return new Promise(resolve => {
if (!pokemon.canApplyAbility())
return resolve();
const ability = pokemon.getAbility();
const attrs = ability.getAttrs(attrType) as PreSetStatusAbAttr[];
const clearSpliceQueueAndResolve = () => {
pokemon.scene.clearPhaseQueueSplice();
resolve();
};
const applyNextAbAttr = () => {
if (attrs.length)
applyAbAttr(attrs.shift());
else
clearSpliceQueueAndResolve();
};
const applyAbAttr = (attr: PreSetStatusAbAttr) => {
if (!canApplyAttr(pokemon, attr))
return applyNextAbAttr();
pokemon.scene.setPhaseQueueSplice();
const onApplySuccess = () => {
if (attr.showAbility)
queueShowAbility(pokemon);
const message = attr.getTriggerMessage(pokemon);
if (message)
pokemon.scene.queueMessage(message);
};
const result = attr.applyPreSetStatus(pokemon, effect, cancelled, args);
if (result instanceof Promise) {
result.then(success => {
if (success)
onApplySuccess();
applyNextAbAttr();
});
} else {
if (result)
onApplySuccess();
applyNextAbAttr();
}
};
applyNextAbAttr();
});
}
export function applyPreApplyBattlerTagAbAttrs(attrType: { new(...args: any[]): PreApplyBattlerTagAbAttr },
pokemon: Pokemon, tag: BattlerTag, cancelled: Utils.BooleanHolder, ...args: any[]): Promise<void> {
return new Promise(resolve => {
if (!pokemon.canApplyAbility())
return resolve();
const ability = pokemon.getAbility();
const attrs = ability.getAttrs(attrType) as PreApplyBattlerTagAbAttr[];
const clearSpliceQueueAndResolve = () => {
pokemon.scene.clearPhaseQueueSplice();
resolve();
};
const applyNextAbAttr = () => {
if (attrs.length)
applyAbAttr(attrs.shift());
else
clearSpliceQueueAndResolve();
};
const applyAbAttr = (attr: PreApplyBattlerTagAbAttr) => {
if (!canApplyAttr(pokemon, attr))
return applyNextAbAttr();
pokemon.scene.setPhaseQueueSplice();
const onApplySuccess = () => {
if (attr.showAbility)
queueShowAbility(pokemon);
const message = attr.getTriggerMessage(pokemon);
if (message)
pokemon.scene.queueMessage(message);
};
const result = attr.applyPreApplyBattlerTag(pokemon, tag, cancelled, args);
if (result instanceof Promise) {
result.then(success => {
if (success)
onApplySuccess();
applyNextAbAttr();
});
} else {
if (result)
onApplySuccess();
applyNextAbAttr();
}
};
applyNextAbAttr();
});
}
export function applyPreWeatherEffectAbAttrs(attrType: { new(...args: any[]): PreWeatherEffectAbAttr },
pokemon: Pokemon, weather: Weather, cancelled: Utils.BooleanHolder, ...args: any[]): Promise<void> {
return new Promise(resolve => {
if (!pokemon.canApplyAbility())
return resolve();
const ability = pokemon.getAbility();
const attrs = ability.getAttrs(attrType) as PreWeatherEffectAbAttr[];
const clearSpliceQueueAndResolve = () => {
pokemon.scene.clearPhaseQueueSplice();
resolve();
};
const applyNextAbAttr = () => {
if (attrs.length)
applyAbAttr(attrs.shift());
else
clearSpliceQueueAndResolve();
};
const applyAbAttr = (attr: PreWeatherEffectAbAttr) => {
if (!canApplyAttr(pokemon, attr))
return applyNextAbAttr();
pokemon.scene.setPhaseQueueSplice();
const onApplySuccess = () => {
pokemon.scene.abilityBar.showAbility(pokemon);
const message = attr.getTriggerMessage(pokemon);
if (message)
pokemon.scene.queueMessage(message);
};
const result = attr.applyPreWeatherEffect(pokemon, weather, cancelled, args);
if (result instanceof Promise) {
result.then(success => {
if (success)
onApplySuccess();
applyNextAbAttr();
});
} else {
if (result)
onApplySuccess();
applyNextAbAttr();
}
};
applyNextAbAttr();
});
}
export function applyPostTurnAbAttrs(attrType: { new(...args: any[]): PostTurnAbAttr },
pokemon: Pokemon, ...args: any[]): Promise<void> {
return new Promise(resolve => {
if (!pokemon.canApplyAbility())
return resolve();
const ability = pokemon.getAbility();
const attrs = ability.getAttrs(attrType) as PostTurnAbAttr[];
const clearSpliceQueueAndResolve = () => {
pokemon.scene.clearPhaseQueueSplice();
resolve();
};
const applyNextAbAttr = () => {
if (attrs.length)
applyAbAttr(attrs.shift());
else
clearSpliceQueueAndResolve();
};
const applyAbAttr = (attr: PostTurnAbAttr) => {
if (!canApplyAttr(pokemon, attr))
return applyNextAbAttr();
pokemon.scene.setPhaseQueueSplice();
const onApplySuccess = () => {
if (attr.showAbility)
queueShowAbility(pokemon);
const message = attr.getTriggerMessage(pokemon);
if (message)
pokemon.scene.queueMessage(message);
};
const result = attr.applyPostTurn(pokemon, args);
if (result instanceof Promise) {
result.then(success => {
if (success)
onApplySuccess();
applyNextAbAttr();
});
} else {
if (result)
onApplySuccess();
applyNextAbAttr();
}
};
applyNextAbAttr();
});
}
export function applyPostWeatherLapseAbAttrs(attrType: { new(...args: any[]): PostWeatherLapseAbAttr },
pokemon: Pokemon, weather: Weather, ...args: any[]): void {
pokemon: Pokemon, weather: Weather, ...args: any[]): Promise<void> {
return new Promise(resolve => {
if (!pokemon.canApplyAbility())
return;
return resolve();
if (weather.isEffectSuppressed(pokemon.scene))
return;
return resolve();
const ability = pokemon.getAbility();
const attrs = ability.getAttrs(attrType) as PostWeatherLapseAbAttr[];
for (let attr of attrs) {
const clearSpliceQueueAndResolve = () => {
pokemon.scene.clearPhaseQueueSplice();
resolve();
};
const applyNextAbAttr = () => {
if (attrs.length)
applyAbAttr(attrs.shift());
else
clearSpliceQueueAndResolve();
};
const applyAbAttr = (attr: PostWeatherLapseAbAttr) => {
if (!canApplyAttr(pokemon, attr))
continue;
return applyNextAbAttr();
pokemon.scene.setPhaseQueueSplice();
if (attr.applyPostWeatherLapse(pokemon, weather, args)) {
const onApplySuccess = () => {
if (attr.showAbility)
queueShowAbility(pokemon);
const message = attr.getTriggerMessage(pokemon, weather);
const message = attr.getTriggerMessage(pokemon);
if (message)
pokemon.scene.queueMessage(message);
};
const result = attr.applyPostWeatherLapse(pokemon, weather, args);
if (result instanceof Promise) {
result.then(success => {
if (success)
onApplySuccess();
applyNextAbAttr();
});
} else {
if (result)
onApplySuccess();
applyNextAbAttr();
}
}
pokemon.scene.clearPhaseQueueSplice();
};
applyNextAbAttr();
});
}
export function applyCheckTrappedAbAttrs(attrType: { new(...args: any[]): CheckTrappedAbAttr },
pokemon: Pokemon, trapped: Utils.BooleanHolder, ...args: any[]): void {
pokemon: Pokemon, trapped: Utils.BooleanHolder, ...args: any[]): Promise<void> {
return new Promise(resolve => {
if (!pokemon.canApplyAbility())
return;
return resolve();
const ability = pokemon.getAbility();
const attrs = ability.getAttrs(attrType) as CheckTrappedAbAttr[];
for (let attr of attrs) {
const clearSpliceQueueAndResolve = () => {
pokemon.scene.clearPhaseQueueSplice();
resolve();
};
const applyNextAbAttr = () => {
if (attrs.length)
applyAbAttr(attrs.shift());
else
clearSpliceQueueAndResolve();
};
const applyAbAttr = (attr: CheckTrappedAbAttr) => {
if (!canApplyAttr(pokemon, attr))
continue;
return applyNextAbAttr();
pokemon.scene.setPhaseQueueSplice();
if (attr.applyCheckTrapped(pokemon, trapped, args)) {
const onApplySuccess = () => {
// Don't show ability bar because this call is asynchronous
const message = attr.getTriggerMessage(pokemon);
if (message)
pokemon.scene.ui.showText(message, null, () => pokemon.scene.ui.showText(null, 0), null, true);
};
const result = attr.applyCheckTrapped(pokemon, trapped, args);
if (result instanceof Promise) {
result.then(success => {
if (success)
onApplySuccess();
applyNextAbAttr();
});
} else {
if (result)
onApplySuccess();
applyNextAbAttr();
}
}
pokemon.scene.clearPhaseQueueSplice();
};
applyNextAbAttr();
});
}
function canApplyAttr(pokemon: Pokemon, attr: AbAttr): boolean {