mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-21 06:49:35 +02:00
Fix indentation, tsdocs, add public
/etc
This commit is contained in:
parent
e17939d47c
commit
8e90a18788
@ -35,7 +35,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
this.targets = targets;
|
this.targets = targets;
|
||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
public start(): void {
|
||||||
super.start();
|
super.start();
|
||||||
|
|
||||||
/** The Pokemon using this phase's invoked move */
|
/** The Pokemon using this phase's invoked move */
|
||||||
@ -57,7 +57,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
const move = this.move.getMove();
|
const move = this.move.getMove();
|
||||||
|
|
||||||
// Assume single target for override
|
// Assume single target for override
|
||||||
applyMoveAttrs(OverrideMoveEffectAttr, user, this.getTarget() ?? null, move, overridden, this.move.virtual).then(() => {
|
applyMoveAttrs(OverrideMoveEffectAttr, user, this.getFirstTarget() ?? null, move, overridden, this.move.virtual).then(() => {
|
||||||
// If other effects were overriden, stop this phase before they can be applied
|
// If other effects were overriden, stop this phase before they can be applied
|
||||||
if (overridden.value) {
|
if (overridden.value) {
|
||||||
return this.end();
|
return this.end();
|
||||||
@ -73,7 +73,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
if (user.turnData.hitsLeft === -1) {
|
if (user.turnData.hitsLeft === -1) {
|
||||||
const hitCount = new Utils.IntegerHolder(1);
|
const hitCount = new Utils.IntegerHolder(1);
|
||||||
// Assume single target for multi hit
|
// Assume single target for multi hit
|
||||||
applyMoveAttrs(MultiHitAttr, user, this.getTarget() ?? null, move, hitCount);
|
applyMoveAttrs(MultiHitAttr, user, this.getFirstTarget() ?? null, move, hitCount);
|
||||||
// If Parental Bond is applicable, double the hit count
|
// If Parental Bond is applicable, double the hit count
|
||||||
applyPreAttackAbAttrs(AddSecondStrikeAbAttr, user, null, move, false, targets.length, hitCount, new Utils.IntegerHolder(0));
|
applyPreAttackAbAttrs(AddSecondStrikeAbAttr, user, null, move, false, targets.length, hitCount, new Utils.IntegerHolder(0));
|
||||||
// If Multi-Lens is applicable, multiply the hit count by 1 + the number of Multi-Lenses held by the user
|
// If Multi-Lens is applicable, multiply the hit count by 1 + the number of Multi-Lenses held by the user
|
||||||
@ -107,11 +107,10 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
* (and not random target) and failed the hit check against its target (MISS), log the move
|
* (and not random target) and failed the hit check against its target (MISS), log the move
|
||||||
* as FAILed or MISSed (depending on the conditions above) and end this phase.
|
* as FAILed or MISSed (depending on the conditions above) and end this phase.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!hasActiveTargets || (!move.hasAttr(VariableTargetAttr) && !move.isMultiTarget() && !targetHitChecks[this.targets[0]] && !targets[0].getTag(ProtectedTag) && !isImmune)) {
|
if (!hasActiveTargets || (!move.hasAttr(VariableTargetAttr) && !move.isMultiTarget() && !targetHitChecks[this.targets[0]] && !targets[0].getTag(ProtectedTag) && !isImmune)) {
|
||||||
this.stopMultiHit();
|
this.stopMultiHit();
|
||||||
if (hasActiveTargets) {
|
if (hasActiveTargets) {
|
||||||
this.scene.queueMessage(i18next.t("battle:attackMissed", { pokemonNameWithAffix: this.getTarget() ? getPokemonNameWithAffix(this.getTarget()!) : "" }));
|
this.scene.queueMessage(i18next.t("battle:attackMissed", { pokemonNameWithAffix: this.getFirstTarget() ? getPokemonNameWithAffix(this.getFirstTarget()!) : "" }));
|
||||||
moveHistoryEntry.result = MoveResult.MISS;
|
moveHistoryEntry.result = MoveResult.MISS;
|
||||||
applyMoveAttrs(MissEffectAttr, user, null, move);
|
applyMoveAttrs(MissEffectAttr, user, null, move);
|
||||||
} else {
|
} else {
|
||||||
@ -127,7 +126,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
|
|
||||||
const playOnEmptyField = this.scene.currentBattle?.mysteryEncounter?.hasBattleAnimationsWithoutTargets ?? false;
|
const playOnEmptyField = this.scene.currentBattle?.mysteryEncounter?.hasBattleAnimationsWithoutTargets ?? false;
|
||||||
// Move animation only needs one target
|
// Move animation only needs one target
|
||||||
new MoveAnim(move.id as Moves, user, this.getTarget()!.getBattlerIndex()!, playOnEmptyField).play(this.scene, move.hitsSubstitute(user, this.getTarget()!), () => {
|
new MoveAnim(move.id as Moves, user, this.getFirstTarget()!.getBattlerIndex()!, playOnEmptyField).play(this.scene, move.hitsSubstitute(user, this.getFirstTarget()!), () => {
|
||||||
/** Has the move successfully hit a target (for damage) yet? */
|
/** Has the move successfully hit a target (for damage) yet? */
|
||||||
let hasHit: boolean = false;
|
let hasHit: boolean = false;
|
||||||
for (const target of targets) {
|
for (const target of targets) {
|
||||||
@ -144,9 +143,12 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Is the target protected by Protect, etc. or a relevant conditional protection effect? */
|
/** Is the target protected by Protect, etc. or a relevant conditional protection effect? */
|
||||||
const isProtected = (bypassIgnoreProtect.value || !this.move.getMove().checkFlag(MoveFlags.IGNORE_PROTECT, user, target))
|
const isProtected = (bypassIgnoreProtect.value
|
||||||
&& (hasConditionalProtectApplied.value || (!target.findTags(t => t instanceof DamageProtectedTag).length && target.findTags(t => t instanceof ProtectedTag).find(t => target.lapseTag(t.tagType)))
|
|| !this.move.getMove().checkFlag(MoveFlags.IGNORE_PROTECT, user, target))
|
||||||
|| (this.move.getMove().category !== MoveCategory.STATUS && target.findTags(t => t instanceof DamageProtectedTag).find(t => target.lapseTag(t.tagType))));
|
&& (hasConditionalProtectApplied.value || (!target.findTags(t => t instanceof DamageProtectedTag).length
|
||||||
|
&& target.findTags(t => t instanceof ProtectedTag).find(t => target.lapseTag(t.tagType)))
|
||||||
|
|| (this.move.getMove().category !== MoveCategory.STATUS
|
||||||
|
&& target.findTags(t => t instanceof DamageProtectedTag).find(t => target.lapseTag(t.tagType))));
|
||||||
|
|
||||||
/** Is the pokemon immune due to an ablility? */
|
/** Is the pokemon immune due to an ablility? */
|
||||||
const isImmune = target.hasAbilityWithAttr(TypeImmunityAbAttr) && (target.getAbility()?.getAttrs(TypeImmunityAbAttr)?.[0]?.getImmuneType() === user.getMoveType(move));
|
const isImmune = target.hasAbilityWithAttr(TypeImmunityAbAttr) && (target.getAbility()?.getAttrs(TypeImmunityAbAttr)?.[0]?.getImmuneType() === user.getMoveType(move));
|
||||||
@ -217,7 +219,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Does this phase represent the invoked move's last strike? */
|
/** Does this phase represent the invoked move's last strike? */
|
||||||
const lastHit = (user.turnData.hitsLeft === 1 || !this.getTarget()?.isActive());
|
const lastHit = (user.turnData.hitsLeft === 1 || !this.getFirstTarget()?.isActive());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the user can change forms by using the invoked move,
|
* If the user can change forms by using the invoked move,
|
||||||
@ -235,15 +237,19 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
*/
|
*/
|
||||||
const k = new Promise<void>((resolve) => {
|
const k = new Promise<void>((resolve) => {
|
||||||
//Start promise chain and apply PRE_APPLY move attributes
|
//Start promise chain and apply PRE_APPLY move attributes
|
||||||
let promiseChain : Promise<void | null> = applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && attr.trigger === MoveEffectTrigger.PRE_APPLY && (!attr.firstHitOnly || firstHit) && (!attr.lastHitOnly || lastHit) && hitResult !== HitResult.NO_EFFECT, user, target, move);
|
let promiseChain: Promise<void | null> = applyFilteredMoveAttrs((attr: MoveAttr) =>
|
||||||
|
attr instanceof MoveEffectAttr
|
||||||
|
&& attr.trigger === MoveEffectTrigger.PRE_APPLY
|
||||||
|
&& (!attr.firstHitOnly || firstHit)
|
||||||
|
&& (!attr.lastHitOnly || lastHit)
|
||||||
|
&& hitResult !== HitResult.NO_EFFECT, user, target, move);
|
||||||
|
|
||||||
/** Is the user on turn one of a two turn move? */
|
/** Is the user on turn one of a two turn move? */
|
||||||
const chargeEffect = !!move.getAttrs(ChargeAttr).find(ca => ca.usedChargeEffect(user, target ?? null, move));
|
const chargeEffect = !!move.getAttrs(ChargeAttr).find(ca => ca.usedChargeEffect(user, target ?? null, move));
|
||||||
|
|
||||||
/** Don't complete if the move failed */
|
/** Don't complete if the move failed */
|
||||||
if (hitResult === HitResult.FAIL) {
|
if (hitResult === HitResult.FAIL) {
|
||||||
resolve();
|
return resolve();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Apply Move/Ability Effects in correct order */
|
/** Apply Move/Ability Effects in correct order */
|
||||||
@ -254,7 +260,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
promiseChain
|
promiseChain
|
||||||
.then(this.applyPostApplyEffects(user, target, firstHit, lastHit))
|
.then(this.applyPostApplyEffects(user, target, firstHit, lastHit))
|
||||||
.then(this.applyHeldItemFlinchCheck(user, target, dealsDamage))
|
.then(this.applyHeldItemFlinchCheck(user, target, dealsDamage))
|
||||||
.then(this.applySuccessfulAttkEffects(user, target, firstHit, lastHit, !!isProtected, hitResult, firstTarget, chargeEffect))
|
.then(this.applySuccessfulAttackEffects(user, target, firstHit, lastHit, !!isProtected, hitResult, firstTarget, chargeEffect))
|
||||||
.then(() => resolve());
|
.then(() => resolve());
|
||||||
} else {
|
} else {
|
||||||
promiseChain
|
promiseChain
|
||||||
@ -267,13 +273,13 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply the move's POST_TARGET effects on the move's last hit, after all targeted effects have resolved
|
// Apply the move's POST_TARGET effects on the move's last hit, after all targeted effects have resolved
|
||||||
const postTarget = (user.turnData.hitsLeft === 1 || !this.getTarget()?.isActive()) ?
|
const postTarget = (user.turnData.hitsLeft === 1 || !this.getFirstTarget()?.isActive()) ?
|
||||||
applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && attr.trigger === MoveEffectTrigger.POST_TARGET, user, null, move) :
|
applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && attr.trigger === MoveEffectTrigger.POST_TARGET, user, null, move) :
|
||||||
null;
|
null;
|
||||||
|
|
||||||
if (!!postTarget) {
|
if (postTarget) {
|
||||||
if (applyAttrs.length) { // If there is a pending asynchronous move effect, do this after
|
if (applyAttrs.length) { // If there is a pending asynchronous move effect, do this after
|
||||||
applyAttrs[applyAttrs.length - 1]?.then(() => postTarget);
|
applyAttrs[applyAttrs.length - 1].then(() => postTarget);
|
||||||
} else { // Otherwise, push a new asynchronous move effect
|
} else { // Otherwise, push a new asynchronous move effect
|
||||||
applyAttrs.push(postTarget);
|
applyAttrs.push(postTarget);
|
||||||
}
|
}
|
||||||
@ -288,7 +294,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
*/
|
*/
|
||||||
targets.forEach(target => {
|
targets.forEach(target => {
|
||||||
const substitute = target.getTag(SubstituteTag);
|
const substitute = target.getTag(SubstituteTag);
|
||||||
if (!!substitute && substitute.hp <= 0) {
|
if (substitute && substitute.hp <= 0) {
|
||||||
target.lapseTag(BattlerTagType.SUBSTITUTE);
|
target.lapseTag(BattlerTagType.SUBSTITUTE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -298,7 +304,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
end() {
|
public end(): void {
|
||||||
const user = this.getUserPokemon();
|
const user = this.getUserPokemon();
|
||||||
/**
|
/**
|
||||||
* If this phase isn't for the invoked move's last strike,
|
* If this phase isn't for the invoked move's last strike,
|
||||||
@ -308,7 +314,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
* to the user.
|
* to the user.
|
||||||
*/
|
*/
|
||||||
if (user) {
|
if (user) {
|
||||||
if (user.turnData.hitsLeft && --user.turnData.hitsLeft >= 1 && this.getTarget()?.isActive()) {
|
if (user.turnData.hitsLeft && --user.turnData.hitsLeft >= 1 && this.getFirstTarget()?.isActive()) {
|
||||||
this.scene.unshiftPhase(this.getNewHitPhase());
|
this.scene.unshiftPhase(this.getNewHitPhase());
|
||||||
} else {
|
} else {
|
||||||
// Queue message for number of hits made by multi-move
|
// Queue message for number of hits made by multi-move
|
||||||
@ -328,57 +334,70 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply self-targeted effects that trigger POST_APPLY
|
* Apply self-targeted effects that trigger `POST_APPLY`
|
||||||
*
|
*
|
||||||
* @param user {@linkcode Pokemon} the Pokemon using this phases invoked move
|
* @param user - The {@linkcode Pokemon} using this phase's invoked move
|
||||||
* @param target {@linkcode Pokemon} the current target of this phases invoked move
|
* @param target - {@linkcode Pokemon} the current target of this phase's invoked move
|
||||||
* @param firstHit {@linkcode boolean} whether or not this is the first hit in a multi-hit attack
|
* @param firstHit - `true` if this is the first hit in a multi-hit attack
|
||||||
* @param lastHit {@linkcode boolean} whether or not this is the last hit in a multi-hit attack
|
* @param lastHit - `true` if this is the last hit in a multi-hit attack
|
||||||
* @param chargeEffect {@linkcode boolean} whether or not this is turn 1 of a 2 turn move.
|
* @param chargeEffect - `true` if this is turn 1 of a 2 turn move.
|
||||||
* @return a function intended to pass into a then() call.
|
* @returns a function intended to be passed into a `then()` call.
|
||||||
*/
|
*/
|
||||||
applySelfTargetEffects(user: Pokemon, target: Pokemon, firstHit: boolean, lastHit: boolean, chargeEffect: boolean) : () => Promise<void | null> {
|
protected applySelfTargetEffects(user: Pokemon, target: Pokemon, firstHit: boolean, lastHit: boolean, chargeEffect: boolean): () => Promise<void | null> {
|
||||||
return () => Utils.executeIf(!chargeEffect, () => applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && attr.trigger === MoveEffectTrigger.POST_APPLY
|
return () => Utils.executeIf(!chargeEffect, () => applyFilteredMoveAttrs((attr: MoveAttr) =>
|
||||||
&& attr.selfTarget && (!attr.firstHitOnly || firstHit) && (!attr.lastHitOnly || lastHit), user, target, this.move.getMove()));
|
attr instanceof MoveEffectAttr
|
||||||
|
&& attr.trigger === MoveEffectTrigger.POST_APPLY
|
||||||
|
&& attr.selfTarget
|
||||||
|
&& (!attr.firstHitOnly || firstHit)
|
||||||
|
&& (!attr.lastHitOnly || lastHit), user, target, this.move.getMove()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies non-self-targeted effects that trigger POST_APPLY
|
* Applies non-self-targeted effects that trigger `POST_APPLY`
|
||||||
* (i.e. Smelling Salts curing Paralysis, and the forced switch from U-Turn, Dragon Tail, etc)
|
* (i.e. Smelling Salts curing Paralysis, and the forced switch from U-Turn, Dragon Tail, etc)
|
||||||
* @param user {@linkcode Pokemon} the Pokemon using this phases invoked move
|
* @param user - The {@linkcode Pokemon} using this phase's invoked move
|
||||||
* @param target {@linkcode Pokemon} the current target of this phases invoked move
|
* @param target - {@linkcode Pokemon} the current target of this phase's invoked move
|
||||||
* @param firstHit {@linkcode boolean} whether or not this is the first hit in a multi-hit attack
|
* @param firstHit - `true` if this is the first hit in a multi-hit attack
|
||||||
* @param lastHit {@linkcode boolean} whether or not this is the last hit in a multi-hit attack
|
* @param lastHit - `true` if this is the last hit in a multi-hit attack
|
||||||
* @return a function intended to pass into a then() call.
|
* @returns a function intended to be passed into a `then()` call.
|
||||||
*/
|
*/
|
||||||
applyPostApplyEffects( user: Pokemon, target: Pokemon, firstHit: boolean, lastHit: boolean) : () => Promise<void | null> {
|
protected applyPostApplyEffects(user: Pokemon, target: Pokemon, firstHit: boolean, lastHit: boolean): () => Promise<void | null> {
|
||||||
return () => applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && (attr as MoveEffectAttr).trigger === MoveEffectTrigger.POST_APPLY && !(attr as MoveEffectAttr).selfTarget && (!attr.firstHitOnly || firstHit) && (!attr.lastHitOnly || lastHit), user, target, this.move.getMove());
|
return () => applyFilteredMoveAttrs((attr: MoveAttr) =>
|
||||||
|
attr instanceof MoveEffectAttr
|
||||||
|
&& attr.trigger === MoveEffectTrigger.POST_APPLY
|
||||||
|
&& !attr.selfTarget
|
||||||
|
&& (!attr.firstHitOnly || firstHit)
|
||||||
|
&& (!attr.lastHitOnly || lastHit), user, target, this.move.getMove());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies effects that trigger on HIT
|
* Applies effects that trigger on HIT
|
||||||
* (i.e. Final Gambit, Power-Up Punch, Drain Punch)
|
* (i.e. Final Gambit, Power-Up Punch, Drain Punch)
|
||||||
* @param user {@linkcode Pokemon} the Pokemon using this phases invoked move
|
* @param user - The {@linkcode Pokemon} using this phase's invoked move
|
||||||
* @param target {@linkcode Pokemon} the current target of this phases invoked move
|
* @param target - {@linkcode Pokemon} the current target of this phase's invoked move
|
||||||
* @param firstHit {@linkcode boolean} whether or not this is the first hit in a multi-hit attack
|
* @param firstHit - `true` if this is the first hit in a multi-hit attack
|
||||||
* @param lastHit {@linkcode boolean} whether or not this is the last hit in a multi-hit attack
|
* @param lastHit - `true` if this is the last hit in a multi-hit attack
|
||||||
* @param firstTarget {@linkcode boolean} whether {@linkcode target} is the first target hit by this strike of {@linkcode move}
|
* @param firstTarget - `true` if {@linkcode target} is the first target hit by this strike of {@linkcode move}
|
||||||
* @return a Promise, intended to pass into a then() call.
|
* @returns a function intended to be passed into a `then()` call.
|
||||||
*/
|
*/
|
||||||
applyOnHitEffects(user: Pokemon, target: Pokemon, firstHit : boolean, lastHit: boolean, firstTarget: boolean): Promise<void> {
|
protected applyOnHitEffects(user: Pokemon, target: Pokemon, firstHit : boolean, lastHit: boolean, firstTarget: boolean): Promise<void> {
|
||||||
return applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && (attr as MoveEffectAttr).trigger === MoveEffectTrigger.HIT
|
return applyFilteredMoveAttrs((attr: MoveAttr) =>
|
||||||
&& (!attr.firstHitOnly || firstHit) && (!attr.lastHitOnly || lastHit) && (!attr.firstTargetOnly || firstTarget), user, target, this.move.getMove());
|
attr instanceof MoveEffectAttr
|
||||||
|
&& attr.trigger === MoveEffectTrigger.HIT
|
||||||
|
&& (!attr.firstHitOnly || firstHit)
|
||||||
|
&& (!attr.lastHitOnly || lastHit)
|
||||||
|
&& (!attr.firstTargetOnly || firstTarget), user, target, this.move.getMove());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies reactive effects that occur when a Pokémon is hit.
|
* Applies reactive effects that occur when a Pokémon is hit.
|
||||||
* (i.e. Effect Spore, Disguise, Liquid Ooze, Beak Blast)
|
* (i.e. Effect Spore, Disguise, Liquid Ooze, Beak Blast)
|
||||||
* @param user {@linkcode Pokemon} the Pokemon using this phases invoked move
|
* @param user - The {@linkcode Pokemon} using this phase's invoked move
|
||||||
* @param target {@linkcode Pokemon} the current target of this phases invoked move
|
* @param target - {@linkcode Pokemon} the current target of this phase's invoked move
|
||||||
* @param hitResult {@linkcode HitResult} the result of the attempted move
|
* @param hitResult - The {@linkcode HitResult} of the attempted move
|
||||||
* @return a Promise, intended to pass into a then() call.
|
* @returns a `Promise` intended to be passed into a `then()` call.
|
||||||
*/
|
*/
|
||||||
applyOnGetHitAbEffects(user: Pokemon, target: Pokemon, hitResult: HitResult) : Promise<void | null> {
|
protected applyOnGetHitAbEffects(user: Pokemon, target: Pokemon, hitResult: HitResult): Promise<void | null> {
|
||||||
return Utils.executeIf(!target.isFainted() || target.canApplyAbility(), () =>
|
return Utils.executeIf(!target.isFainted() || target.canApplyAbility(), () =>
|
||||||
applyPostDefendAbAttrs(PostDefendAbAttr, target, user, this.move.getMove(), hitResult)
|
applyPostDefendAbAttrs(PostDefendAbAttr, target, user, this.move.getMove(), hitResult)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@ -401,17 +420,17 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
/**
|
/**
|
||||||
* Applies all effects and attributes that require a move to connect with a target,
|
* Applies all effects and attributes that require a move to connect with a target,
|
||||||
* namely reactive effects like Weak Armor, on-hit effects like that of Power-Up Punch, and item stealing effects
|
* namely reactive effects like Weak Armor, on-hit effects like that of Power-Up Punch, and item stealing effects
|
||||||
* @param user {@linkcode Pokemon} the Pokemon using this phase's invoked move
|
* @param user - The {@linkcode Pokemon} using this phase's invoked move
|
||||||
* @param target {@linkcode Pokemon} the current target of this phase's invoked move
|
* @param target - {@linkcode Pokemon} the current target of this phase's invoked move
|
||||||
* @param firstHit {@linkcode boolean} whether or not this is the first hit in a multi-hit attack
|
* @param firstHit - `true` if this is the first hit in a multi-hit attack
|
||||||
* @param lastHit {@linkcode boolean} whether or not this is the last hit in a multi-hit attack
|
* @param lastHit - `true` if this is the last hit in a multi-hit attack
|
||||||
* @param isProtected {@linkcode boolean} whether or not the target is protected by effects such as Protect
|
* @param isProtected - `true` if the target is protected by effects such as Protect
|
||||||
* @param hitResult {@linkcode HitResult} the result of the attempted move
|
* @param hitResult - The {@linkcode HitResult} of the attempted move
|
||||||
* @param firstTarget {@linkcode boolean} whether {@linkcode target} is the first target hit by this strike of {@linkcode move}
|
* @param firstTarget - `true` if {@linkcode target} is the first target hit by this strike of {@linkcode move}
|
||||||
* @param chargeEffect {@linkcode boolean} whether or not this is turn 1 of a two turn move
|
* @param chargeEffect - `true` if this is turn 1 of a 2 turn move.
|
||||||
* @return a function to pass into a then() call.
|
* @returns a function intended to be passed into a `then()` call.
|
||||||
*/
|
*/
|
||||||
applySuccessfulAttkEffects(user: Pokemon, target: Pokemon, firstHit : boolean, lastHit: boolean, isProtected : boolean, hitResult: HitResult, firstTarget: boolean, chargeEffect: boolean) : () => Promise<void | null> {
|
protected applySuccessfulAttackEffects(user: Pokemon, target: Pokemon, firstHit : boolean, lastHit: boolean, isProtected : boolean, hitResult: HitResult, firstTarget: boolean, chargeEffect: boolean) : () => Promise<void | null> {
|
||||||
return () => Utils.executeIf(!isProtected && !chargeEffect, () =>
|
return () => Utils.executeIf(!isProtected && !chargeEffect, () =>
|
||||||
this.applyOnHitEffects(user, target, firstHit, lastHit, firstTarget).then(() =>
|
this.applyOnHitEffects(user, target, firstHit, lastHit, firstTarget).then(() =>
|
||||||
this.applyOnGetHitAbEffects(user, target, hitResult)).then(() =>
|
this.applyOnGetHitAbEffects(user, target, hitResult)).then(() =>
|
||||||
@ -426,12 +445,12 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles checking for and applying Flinches
|
* Handles checking for and applying Flinches
|
||||||
* @param user {@linkcode Pokemon} the Pokemon using this phases invoked move
|
* @param user - The {@linkcode Pokemon} using this phase's invoked move
|
||||||
* @param target {@linkcode Pokemon} the current target of this phases invoked move
|
* @param target - {@linkcode Pokemon} the current target of this phase's invoked move
|
||||||
* @param dealsDamage {@linkcode boolean} if the attempted move successfully dealt damage
|
* @param dealsDamage - `true` if the attempted move successfully dealt damage
|
||||||
* @returns a function to be passed into a then() call
|
* @returns a function intended to be passed into a `then()` call.
|
||||||
*/
|
*/
|
||||||
applyHeldItemFlinchCheck(user: Pokemon, target: Pokemon, dealsDamage: boolean) : () => void {
|
protected applyHeldItemFlinchCheck(user: Pokemon, target: Pokemon, dealsDamage: boolean) : () => void {
|
||||||
return () => {
|
return () => {
|
||||||
if (dealsDamage && !target.hasAbilityWithAttr(IgnoreMoveEffectsAbAttr) && !this.move.getMove().hitsSubstitute(user, target)) {
|
if (dealsDamage && !target.hasAbilityWithAttr(IgnoreMoveEffectsAbAttr) && !this.move.getMove().hitsSubstitute(user, target)) {
|
||||||
const flinched = new Utils.BooleanHolder(false);
|
const flinched = new Utils.BooleanHolder(false);
|
||||||
@ -444,11 +463,11 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves whether this phase's invoked move hits or misses the given target
|
* Resolves whether this phase's invoked move hits the given target
|
||||||
* @param target {@linkcode Pokemon} the Pokemon targeted by the invoked move
|
* @param target - The {@linkcode Pokemon} targeted by the invoked move
|
||||||
* @returns `true` if the move does not miss the target; `false` otherwise
|
* @returns `true` if the move hits the target
|
||||||
*/
|
*/
|
||||||
hitCheck(target: Pokemon): boolean {
|
public hitCheck(target: Pokemon): boolean {
|
||||||
// Moves targeting the user and entry hazards can't miss
|
// Moves targeting the user and entry hazards can't miss
|
||||||
if ([ MoveTarget.USER, MoveTarget.ENEMY_SIDE ].includes(this.move.getMove().moveTarget)) {
|
if ([ MoveTarget.USER, MoveTarget.ENEMY_SIDE ].includes(this.move.getMove().moveTarget)) {
|
||||||
return true;
|
return true;
|
||||||
@ -498,29 +517,29 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
return rand < (moveAccuracy * accuracyMultiplier);
|
return rand < (moveAccuracy * accuracyMultiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the {@linkcode Pokemon} using this phase's invoked move */
|
/** @returns The {@linkcode Pokemon} using this phase's invoked move */
|
||||||
getUserPokemon(): Pokemon | undefined {
|
public getUserPokemon(): Pokemon | undefined {
|
||||||
if (this.battlerIndex > BattlerIndex.ENEMY_2) {
|
if (this.battlerIndex > BattlerIndex.ENEMY_2) {
|
||||||
return this.scene.getPokemonById(this.battlerIndex) ?? undefined;
|
return this.scene.getPokemonById(this.battlerIndex) ?? undefined;
|
||||||
}
|
}
|
||||||
return (this.player ? this.scene.getPlayerField() : this.scene.getEnemyField())[this.fieldIndex];
|
return (this.player ? this.scene.getPlayerField() : this.scene.getEnemyField())[this.fieldIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns an array of all {@linkcode Pokemon} targeted by this phase's invoked move */
|
/** @returns An array of all {@linkcode Pokemon} targeted by this phase's invoked move */
|
||||||
getTargets(): Pokemon[] {
|
public getTargets(): Pokemon[] {
|
||||||
return this.scene.getField(true).filter(p => this.targets.indexOf(p.getBattlerIndex()) > -1);
|
return this.scene.getField(true).filter(p => this.targets.indexOf(p.getBattlerIndex()) > -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the first target of this phase's invoked move */
|
/** @returns The first target of this phase's invoked move */
|
||||||
getTarget(): Pokemon | undefined {
|
public getFirstTarget(): Pokemon | undefined {
|
||||||
return this.getTargets()[0];
|
return this.getTargets()[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the given {@linkcode Pokemon} from this phase's target list
|
* Removes the given {@linkcode Pokemon} from this phase's target list
|
||||||
* @param target {@linkcode Pokemon} the Pokemon to be removed
|
* @param target - The {@linkcode Pokemon} to be removed
|
||||||
*/
|
*/
|
||||||
removeTarget(target: Pokemon): void {
|
protected removeTarget(target: Pokemon): void {
|
||||||
const targetIndex = this.targets.findIndex(ind => ind === target.getBattlerIndex());
|
const targetIndex = this.targets.findIndex(ind => ind === target.getBattlerIndex());
|
||||||
if (targetIndex !== -1) {
|
if (targetIndex !== -1) {
|
||||||
this.targets.splice(this.targets.findIndex(ind => ind === target.getBattlerIndex()), 1);
|
this.targets.splice(this.targets.findIndex(ind => ind === target.getBattlerIndex()), 1);
|
||||||
@ -532,23 +551,25 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
* @param target {@linkcode Pokemon} if defined, only stop subsequent
|
* @param target {@linkcode Pokemon} if defined, only stop subsequent
|
||||||
* strikes against this Pokemon
|
* strikes against this Pokemon
|
||||||
*/
|
*/
|
||||||
stopMultiHit(target?: Pokemon): void {
|
public stopMultiHit(target?: Pokemon): void {
|
||||||
/** If given a specific target, remove the target from subsequent strikes */
|
// If given a specific target, remove the target from subsequent strikes
|
||||||
if (target) {
|
if (target) {
|
||||||
this.removeTarget(target);
|
this.removeTarget(target);
|
||||||
}
|
}
|
||||||
/**
|
const user = this.getUserPokemon();
|
||||||
* If no target specified, or the specified target was the last of this move's
|
if (!user) {
|
||||||
* targets, completely cancel all subsequent strikes.
|
return;
|
||||||
*/
|
}
|
||||||
|
// If no target specified, or the specified target was the last of this move's
|
||||||
|
// targets, completely cancel all subsequent strikes.
|
||||||
if (!target || this.targets.length === 0 ) {
|
if (!target || this.targets.length === 0 ) {
|
||||||
this.getUserPokemon()!.turnData.hitCount = 1; // TODO: is the bang correct here?
|
user.turnData.hitCount = 1;
|
||||||
this.getUserPokemon()!.turnData.hitsLeft = 1; // TODO: is the bang correct here?
|
user.turnData.hitsLeft = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a new MoveEffectPhase with the same properties as this phase */
|
/** @returns A new `MoveEffectPhase` with the same properties as this phase */
|
||||||
getNewHitPhase() {
|
protected getNewHitPhase(): MoveEffectPhase {
|
||||||
return new MoveEffectPhase(this.scene, this.battlerIndex, this.targets, this.move);
|
return new MoveEffectPhase(this.scene, this.battlerIndex, this.targets, this.move);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ describe("Abilities - Serene Grace", () => {
|
|||||||
|
|
||||||
const chance = new Utils.IntegerHolder(move.chance);
|
const chance = new Utils.IntegerHolder(move.chance);
|
||||||
console.log(move.chance + " Their ability is " + phase.getUserPokemon()!.getAbility().name);
|
console.log(move.chance + " Their ability is " + phase.getUserPokemon()!.getAbility().name);
|
||||||
applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, false, chance, move, phase.getTarget(), false);
|
applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, false, chance, move, phase.getFirstTarget(), false);
|
||||||
expect(chance.value).toBe(30);
|
expect(chance.value).toBe(30);
|
||||||
|
|
||||||
}, 20000);
|
}, 20000);
|
||||||
@ -83,7 +83,7 @@ describe("Abilities - Serene Grace", () => {
|
|||||||
expect(move.id).toBe(Moves.AIR_SLASH);
|
expect(move.id).toBe(Moves.AIR_SLASH);
|
||||||
|
|
||||||
const chance = new Utils.IntegerHolder(move.chance);
|
const chance = new Utils.IntegerHolder(move.chance);
|
||||||
applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, false, chance, move, phase.getTarget(), false);
|
applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, false, chance, move, phase.getFirstTarget(), false);
|
||||||
expect(chance.value).toBe(60);
|
expect(chance.value).toBe(60);
|
||||||
|
|
||||||
}, 20000);
|
}, 20000);
|
||||||
|
@ -60,8 +60,8 @@ describe("Abilities - Sheer Force", () => {
|
|||||||
const power = new Utils.IntegerHolder(move.power);
|
const power = new Utils.IntegerHolder(move.power);
|
||||||
const chance = new Utils.IntegerHolder(move.chance);
|
const chance = new Utils.IntegerHolder(move.chance);
|
||||||
|
|
||||||
applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, false, chance, move, phase.getTarget(), false);
|
applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, false, chance, move, phase.getFirstTarget(), false);
|
||||||
applyPreAttackAbAttrs(MovePowerBoostAbAttr, phase.getUserPokemon()!, phase.getTarget()!, move, false, power);
|
applyPreAttackAbAttrs(MovePowerBoostAbAttr, phase.getUserPokemon()!, phase.getFirstTarget()!, move, false, power);
|
||||||
|
|
||||||
expect(chance.value).toBe(0);
|
expect(chance.value).toBe(0);
|
||||||
expect(power.value).toBe(move.power * 5461 / 4096);
|
expect(power.value).toBe(move.power * 5461 / 4096);
|
||||||
@ -93,8 +93,8 @@ describe("Abilities - Sheer Force", () => {
|
|||||||
const power = new Utils.IntegerHolder(move.power);
|
const power = new Utils.IntegerHolder(move.power);
|
||||||
const chance = new Utils.IntegerHolder(move.chance);
|
const chance = new Utils.IntegerHolder(move.chance);
|
||||||
|
|
||||||
applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, false, chance, move, phase.getTarget(), false);
|
applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, false, chance, move, phase.getFirstTarget(), false);
|
||||||
applyPreAttackAbAttrs(MovePowerBoostAbAttr, phase.getUserPokemon()!, phase.getTarget()!, move, false, power);
|
applyPreAttackAbAttrs(MovePowerBoostAbAttr, phase.getUserPokemon()!, phase.getFirstTarget()!, move, false, power);
|
||||||
|
|
||||||
expect(chance.value).toBe(-1);
|
expect(chance.value).toBe(-1);
|
||||||
expect(power.value).toBe(move.power);
|
expect(power.value).toBe(move.power);
|
||||||
@ -126,8 +126,8 @@ describe("Abilities - Sheer Force", () => {
|
|||||||
const power = new Utils.IntegerHolder(move.power);
|
const power = new Utils.IntegerHolder(move.power);
|
||||||
const chance = new Utils.IntegerHolder(move.chance);
|
const chance = new Utils.IntegerHolder(move.chance);
|
||||||
|
|
||||||
applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, false, chance, move, phase.getTarget(), false);
|
applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, false, chance, move, phase.getFirstTarget(), false);
|
||||||
applyPreAttackAbAttrs(MovePowerBoostAbAttr, phase.getUserPokemon()!, phase.getTarget()!, move, false, power);
|
applyPreAttackAbAttrs(MovePowerBoostAbAttr, phase.getUserPokemon()!, phase.getFirstTarget()!, move, false, power);
|
||||||
|
|
||||||
expect(chance.value).toBe(-1);
|
expect(chance.value).toBe(-1);
|
||||||
expect(power.value).toBe(move.power);
|
expect(power.value).toBe(move.power);
|
||||||
@ -161,7 +161,7 @@ describe("Abilities - Sheer Force", () => {
|
|||||||
const power = new Utils.IntegerHolder(move.power);
|
const power = new Utils.IntegerHolder(move.power);
|
||||||
const chance = new Utils.IntegerHolder(move.chance);
|
const chance = new Utils.IntegerHolder(move.chance);
|
||||||
const user = phase.getUserPokemon()!;
|
const user = phase.getUserPokemon()!;
|
||||||
const target = phase.getTarget()!;
|
const target = phase.getFirstTarget()!;
|
||||||
const opponentType = target.getTypes()[0];
|
const opponentType = target.getTypes()[0];
|
||||||
|
|
||||||
applyAbAttrs(MoveEffectChanceMultiplierAbAttr, user, null, false, chance, move, target, false);
|
applyAbAttrs(MoveEffectChanceMultiplierAbAttr, user, null, false, chance, move, target, false);
|
||||||
|
@ -57,8 +57,8 @@ describe("Abilities - Shield Dust", () => {
|
|||||||
expect(move.id).toBe(Moves.AIR_SLASH);
|
expect(move.id).toBe(Moves.AIR_SLASH);
|
||||||
|
|
||||||
const chance = new Utils.IntegerHolder(move.chance);
|
const chance = new Utils.IntegerHolder(move.chance);
|
||||||
applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, false, chance, move, phase.getTarget(), false);
|
applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon()!, null, false, chance, move, phase.getFirstTarget(), false);
|
||||||
applyPreDefendAbAttrs(IgnoreMoveEffectsAbAttr, phase.getTarget()!, phase.getUserPokemon()!, null, null, false, chance);
|
applyPreDefendAbAttrs(IgnoreMoveEffectsAbAttr, phase.getFirstTarget()!, phase.getUserPokemon()!, null, null, false, chance);
|
||||||
expect(chance.value).toBe(0);
|
expect(chance.value).toBe(0);
|
||||||
|
|
||||||
}, 20000);
|
}, 20000);
|
||||||
|
@ -81,7 +81,7 @@ describe("Moves - Dynamax Cannon", () => {
|
|||||||
const phase = game.scene.getCurrentPhase() as MoveEffectPhase;
|
const phase = game.scene.getCurrentPhase() as MoveEffectPhase;
|
||||||
expect(phase.move.moveId).toBe(dynamaxCannon.id);
|
expect(phase.move.moveId).toBe(dynamaxCannon.id);
|
||||||
// Force level cap to be 100
|
// Force level cap to be 100
|
||||||
vi.spyOn(phase.getTarget()!.scene, "getMaxExpLevel").mockReturnValue(100);
|
vi.spyOn(phase.getFirstTarget()!.scene, "getMaxExpLevel").mockReturnValue(100);
|
||||||
await game.phaseInterceptor.to(DamagePhase, false);
|
await game.phaseInterceptor.to(DamagePhase, false);
|
||||||
expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(120);
|
expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(120);
|
||||||
}, 20000);
|
}, 20000);
|
||||||
@ -98,7 +98,7 @@ describe("Moves - Dynamax Cannon", () => {
|
|||||||
const phase = game.scene.getCurrentPhase() as MoveEffectPhase;
|
const phase = game.scene.getCurrentPhase() as MoveEffectPhase;
|
||||||
expect(phase.move.moveId).toBe(dynamaxCannon.id);
|
expect(phase.move.moveId).toBe(dynamaxCannon.id);
|
||||||
// Force level cap to be 100
|
// Force level cap to be 100
|
||||||
vi.spyOn(phase.getTarget()!.scene, "getMaxExpLevel").mockReturnValue(100);
|
vi.spyOn(phase.getFirstTarget()!.scene, "getMaxExpLevel").mockReturnValue(100);
|
||||||
await game.phaseInterceptor.to(DamagePhase, false);
|
await game.phaseInterceptor.to(DamagePhase, false);
|
||||||
expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(140);
|
expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(140);
|
||||||
}, 20000);
|
}, 20000);
|
||||||
@ -115,7 +115,7 @@ describe("Moves - Dynamax Cannon", () => {
|
|||||||
const phase = game.scene.getCurrentPhase() as MoveEffectPhase;
|
const phase = game.scene.getCurrentPhase() as MoveEffectPhase;
|
||||||
expect(phase.move.moveId).toBe(dynamaxCannon.id);
|
expect(phase.move.moveId).toBe(dynamaxCannon.id);
|
||||||
// Force level cap to be 100
|
// Force level cap to be 100
|
||||||
vi.spyOn(phase.getTarget()!.scene, "getMaxExpLevel").mockReturnValue(100);
|
vi.spyOn(phase.getFirstTarget()!.scene, "getMaxExpLevel").mockReturnValue(100);
|
||||||
await game.phaseInterceptor.to(DamagePhase, false);
|
await game.phaseInterceptor.to(DamagePhase, false);
|
||||||
expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(160);
|
expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(160);
|
||||||
}, 20000);
|
}, 20000);
|
||||||
@ -132,7 +132,7 @@ describe("Moves - Dynamax Cannon", () => {
|
|||||||
const phase = game.scene.getCurrentPhase() as MoveEffectPhase;
|
const phase = game.scene.getCurrentPhase() as MoveEffectPhase;
|
||||||
expect(phase.move.moveId).toBe(dynamaxCannon.id);
|
expect(phase.move.moveId).toBe(dynamaxCannon.id);
|
||||||
// Force level cap to be 100
|
// Force level cap to be 100
|
||||||
vi.spyOn(phase.getTarget()!.scene, "getMaxExpLevel").mockReturnValue(100);
|
vi.spyOn(phase.getFirstTarget()!.scene, "getMaxExpLevel").mockReturnValue(100);
|
||||||
await game.phaseInterceptor.to(DamagePhase, false);
|
await game.phaseInterceptor.to(DamagePhase, false);
|
||||||
expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(180);
|
expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(180);
|
||||||
}, 20000);
|
}, 20000);
|
||||||
@ -149,7 +149,7 @@ describe("Moves - Dynamax Cannon", () => {
|
|||||||
const phase = game.scene.getCurrentPhase() as MoveEffectPhase;
|
const phase = game.scene.getCurrentPhase() as MoveEffectPhase;
|
||||||
expect(phase.move.moveId).toBe(dynamaxCannon.id);
|
expect(phase.move.moveId).toBe(dynamaxCannon.id);
|
||||||
// Force level cap to be 100
|
// Force level cap to be 100
|
||||||
vi.spyOn(phase.getTarget()!.scene, "getMaxExpLevel").mockReturnValue(100);
|
vi.spyOn(phase.getFirstTarget()!.scene, "getMaxExpLevel").mockReturnValue(100);
|
||||||
await game.phaseInterceptor.to(DamagePhase, false);
|
await game.phaseInterceptor.to(DamagePhase, false);
|
||||||
expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(200);
|
expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(200);
|
||||||
}, 20000);
|
}, 20000);
|
||||||
|
Loading…
Reference in New Issue
Block a user