Convert apply attribute functions to promises

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

View File

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