mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-20 22:39:31 +02:00
Fix indentation, tsdocs, add public
/etc
This commit is contained in:
parent
e17939d47c
commit
8e90a18788
@ -24,10 +24,10 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
super(scene, battlerIndex);
|
super(scene, battlerIndex);
|
||||||
this.move = move;
|
this.move = move;
|
||||||
/**
|
/**
|
||||||
* In double battles, if the right Pokemon selects a spread move and the left Pokemon dies
|
* In double battles, if the right Pokemon selects a spread move and the left Pokemon dies
|
||||||
* with no party members available to switch in, then the right Pokemon takes the index
|
* with no party members available to switch in, then the right Pokemon takes the index
|
||||||
* of the left Pokemon and gets hit unless this is checked.
|
* of the left Pokemon and gets hit unless this is checked.
|
||||||
*/
|
*/
|
||||||
if (targets.includes(battlerIndex) && this.move.getMove().moveTarget === MoveTarget.ALL_NEAR_OTHERS) {
|
if (targets.includes(battlerIndex) && this.move.getMove().moveTarget === MoveTarget.ALL_NEAR_OTHERS) {
|
||||||
const i = targets.indexOf(battlerIndex);
|
const i = targets.indexOf(battlerIndex);
|
||||||
targets.splice(i, i + 1);
|
targets.splice(i, i + 1);
|
||||||
@ -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 */
|
||||||
@ -49,15 +49,15 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does an effect from this move override other effects on this turn?
|
* Does an effect from this move override other effects on this turn?
|
||||||
* e.g. Charging moves (Fly, etc.) on their first turn of use.
|
* e.g. Charging moves (Fly, etc.) on their first turn of use.
|
||||||
*/
|
*/
|
||||||
const overridden = new Utils.BooleanHolder(false);
|
const overridden = new Utils.BooleanHolder(false);
|
||||||
/** The {@linkcode Move} object from {@linkcode allMoves} invoked by this phase */
|
/** The {@linkcode Move} object from {@linkcode allMoves} invoked by this phase */
|
||||||
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();
|
||||||
@ -66,14 +66,14 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
user.lapseTags(BattlerTagLapseType.MOVE_EFFECT);
|
user.lapseTags(BattlerTagLapseType.MOVE_EFFECT);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this phase is for the first hit of the invoked move,
|
* If this phase is for the first hit of the invoked move,
|
||||||
* resolve the move's total hit count. This block combines the
|
* resolve the move's total hit count. This block combines the
|
||||||
* effects of the move itself, Parental Bond, and Multi-Lens to do so.
|
* effects of the move itself, Parental Bond, and Multi-Lens to do so.
|
||||||
*/
|
*/
|
||||||
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
|
||||||
@ -86,16 +86,16 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log to be entered into the user's move history once the move result is resolved.
|
* Log to be entered into the user's move history once the move result is resolved.
|
||||||
* Note that `result` (a {@linkcode MoveResult}) logs whether the move was successfully
|
* Note that `result` (a {@linkcode MoveResult}) logs whether the move was successfully
|
||||||
* used in the sense of "Does it have an effect on the user?".
|
* used in the sense of "Does it have an effect on the user?".
|
||||||
*/
|
*/
|
||||||
const moveHistoryEntry = { move: this.move.moveId, targets: this.targets, result: MoveResult.PENDING, virtual: this.move.virtual };
|
const moveHistoryEntry = { move: this.move.moveId, targets: this.targets, result: MoveResult.PENDING, virtual: this.move.virtual };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores results of hit checks of the invoked move against all targets, organized by battler index.
|
* Stores results of hit checks of the invoked move against all targets, organized by battler index.
|
||||||
* @see {@linkcode hitCheck}
|
* @see {@linkcode hitCheck}
|
||||||
*/
|
*/
|
||||||
const targetHitChecks = Object.fromEntries(targets.map(p => [ p.getBattlerIndex(), this.hitCheck(p) ]));
|
const targetHitChecks = Object.fromEntries(targets.map(p => [ p.getBattlerIndex(), this.hitCheck(p) ]));
|
||||||
const hasActiveTargets = targets.some(t => t.isActive(true));
|
const hasActiveTargets = targets.some(t => t.isActive(true));
|
||||||
|
|
||||||
@ -103,15 +103,14 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
const isImmune = targets[0].hasAbilityWithAttr(TypeImmunityAbAttr) && (targets[0].getAbility()?.getAttrs(TypeImmunityAbAttr)?.[0]?.getImmuneType() === user.getMoveType(move));
|
const isImmune = targets[0].hasAbilityWithAttr(TypeImmunityAbAttr) && (targets[0].getAbility()?.getAttrs(TypeImmunityAbAttr)?.[0]?.getImmuneType() === user.getMoveType(move));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If no targets are left for the move to hit (FAIL), or the invoked move is single-target
|
* If no targets are left for the move to hit (FAIL), or the invoked move is single-target
|
||||||
* (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,17 +143,20 @@ 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));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the move missed a target, stop all future hits against that target
|
* If the move missed a target, stop all future hits against that target
|
||||||
* and move on to the next target (if there is one).
|
* and move on to the next target (if there is one).
|
||||||
*/
|
*/
|
||||||
if (!isImmune && !isProtected && !targetHitChecks[target.getBattlerIndex()]) {
|
if (!isImmune && !isProtected && !targetHitChecks[target.getBattlerIndex()]) {
|
||||||
this.stopMultiHit(target);
|
this.stopMultiHit(target);
|
||||||
this.scene.queueMessage(i18next.t("battle:attackMissed", { pokemonNameWithAffix: getPokemonNameWithAffix(target) }));
|
this.scene.queueMessage(i18next.t("battle:attackMissed", { pokemonNameWithAffix: getPokemonNameWithAffix(target) }));
|
||||||
@ -175,23 +177,23 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Since all fail/miss checks have applied, the move is considered successfully applied.
|
* Since all fail/miss checks have applied, the move is considered successfully applied.
|
||||||
* It's worth noting that if the move has no effect or is protected against, this assignment
|
* It's worth noting that if the move has no effect or is protected against, this assignment
|
||||||
* is overwritten and the move is logged as a FAIL.
|
* is overwritten and the move is logged as a FAIL.
|
||||||
*/
|
*/
|
||||||
moveHistoryEntry.result = MoveResult.SUCCESS;
|
moveHistoryEntry.result = MoveResult.SUCCESS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the result of applying the invoked move to the target.
|
* Stores the result of applying the invoked move to the target.
|
||||||
* If the target is protected, the result is always `NO_EFFECT`.
|
* If the target is protected, the result is always `NO_EFFECT`.
|
||||||
* Otherwise, the hit result is based on type effectiveness, immunities,
|
* Otherwise, the hit result is based on type effectiveness, immunities,
|
||||||
* and other factors that may negate the attack or status application.
|
* and other factors that may negate the attack or status application.
|
||||||
*
|
*
|
||||||
* Internally, the call to {@linkcode Pokemon.apply} is where damage is calculated
|
* Internally, the call to {@linkcode Pokemon.apply} is where damage is calculated
|
||||||
* (for attack moves) and the target's HP is updated. However, this isn't
|
* (for attack moves) and the target's HP is updated. However, this isn't
|
||||||
* made visible to the user until the resulting {@linkcode DamagePhase}
|
* made visible to the user until the resulting {@linkcode DamagePhase}
|
||||||
* is invoked.
|
* is invoked.
|
||||||
*/
|
*/
|
||||||
const hitResult = !isProtected ? target.apply(user, move) : HitResult.NO_EFFECT;
|
const hitResult = !isProtected ? target.apply(user, move) : HitResult.NO_EFFECT;
|
||||||
|
|
||||||
/** Does {@linkcode hitResult} indicate that damage was dealt to the target? */
|
/** Does {@linkcode hitResult} indicate that damage was dealt to the target? */
|
||||||
@ -209,21 +211,21 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the move has no effect on the target (i.e. the target is protected or immune),
|
* If the move has no effect on the target (i.e. the target is protected or immune),
|
||||||
* change the logged move result to FAIL.
|
* change the logged move result to FAIL.
|
||||||
*/
|
*/
|
||||||
if (hitResult === HitResult.NO_EFFECT) {
|
if (hitResult === HitResult.NO_EFFECT) {
|
||||||
moveHistoryEntry.result = MoveResult.FAIL;
|
moveHistoryEntry.result = MoveResult.FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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,
|
||||||
* it only changes forms after the move's last hit
|
* it only changes forms after the move's last hit
|
||||||
* (see Relic Song's interaction with Parental Bond when used by Meloetta).
|
* (see Relic Song's interaction with Parental Bond when used by Meloetta).
|
||||||
*/
|
*/
|
||||||
if (lastHit) {
|
if (lastHit) {
|
||||||
this.scene.triggerPokemonFormChange(user, SpeciesFormChangePostMoveTrigger);
|
this.scene.triggerPokemonFormChange(user, SpeciesFormChangePostMoveTrigger);
|
||||||
}
|
}
|
||||||
@ -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);
|
||||||
@ -528,27 +547,29 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prevents subsequent strikes of this phase's invoked move from occurring
|
* Prevents subsequent strikes of this phase's invoked move from occurring
|
||||||
* @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