mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-01 22:12:16 +02:00
Added multi lens and wide lens
This commit is contained in:
parent
ff24aae54b
commit
0b32cfb622
@ -68,10 +68,8 @@ import {
|
|||||||
} from "../abilities/ability";
|
} from "../abilities/ability";
|
||||||
import { allAbilities, allMoves } from "../data-lists";
|
import { allAbilities, allMoves } from "../data-lists";
|
||||||
import {
|
import {
|
||||||
AttackTypeBoosterModifier,
|
|
||||||
BerryModifier,
|
BerryModifier,
|
||||||
PokemonHeldItemModifier,
|
PokemonHeldItemModifier,
|
||||||
PokemonMoveAccuracyBoosterModifier,
|
|
||||||
PokemonMultiHitModifier,
|
PokemonMultiHitModifier,
|
||||||
PreserveBerryModifier,
|
PreserveBerryModifier,
|
||||||
} from "../../modifier/modifier";
|
} from "../../modifier/modifier";
|
||||||
@ -781,7 +779,7 @@ export default class Move implements Localizable {
|
|||||||
const isOhko = this.hasAttr(OneHitKOAccuracyAttr);
|
const isOhko = this.hasAttr(OneHitKOAccuracyAttr);
|
||||||
|
|
||||||
if (!isOhko) {
|
if (!isOhko) {
|
||||||
globalScene.applyModifiers(PokemonMoveAccuracyBoosterModifier, user.isPlayer(), user, moveAccuracy);
|
applyHeldItems(ITEM_EFFECT.ACCURACY_BOOSTER, { pokemon: user, moveAccuracy: moveAccuracy });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (globalScene.arena.weather?.weatherType === WeatherType.FOG) {
|
if (globalScene.arena.weather?.weatherType === WeatherType.FOG) {
|
||||||
|
@ -96,7 +96,6 @@ import {
|
|||||||
PokemonBaseStatTotalModifier,
|
PokemonBaseStatTotalModifier,
|
||||||
PokemonIncrementingStatModifier,
|
PokemonIncrementingStatModifier,
|
||||||
EvoTrackerModifier,
|
EvoTrackerModifier,
|
||||||
PokemonMultiHitModifier,
|
|
||||||
} from "#app/modifier/modifier";
|
} from "#app/modifier/modifier";
|
||||||
import { PokeballType } from "#enums/pokeball";
|
import { PokeballType } from "#enums/pokeball";
|
||||||
import { Gender } from "#app/data/gender";
|
import { Gender } from "#app/data/gender";
|
||||||
@ -3725,14 +3724,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
applyMoveAttrs(FixedDamageAttr, source, this, move, fixedDamage);
|
applyMoveAttrs(FixedDamageAttr, source, this, move, fixedDamage);
|
||||||
if (fixedDamage.value) {
|
if (fixedDamage.value) {
|
||||||
const multiLensMultiplier = new NumberHolder(1);
|
const multiLensMultiplier = new NumberHolder(1);
|
||||||
globalScene.applyModifiers(
|
applyHeldItems(ITEM_EFFECT.MULTI_HIT, {
|
||||||
PokemonMultiHitModifier,
|
pokemon: source,
|
||||||
source.isPlayer(),
|
moveId: move.id,
|
||||||
source,
|
damageMultiplier: multiLensMultiplier,
|
||||||
move.id,
|
});
|
||||||
null,
|
|
||||||
multiLensMultiplier,
|
|
||||||
);
|
|
||||||
fixedDamage.value = toDmgValue(fixedDamage.value * multiLensMultiplier.value);
|
fixedDamage.value = toDmgValue(fixedDamage.value * multiLensMultiplier.value);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -3776,14 +3772,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
|
|
||||||
/** Multiplier for moves enhanced by Multi-Lens and/or Parental Bond */
|
/** Multiplier for moves enhanced by Multi-Lens and/or Parental Bond */
|
||||||
const multiStrikeEnhancementMultiplier = new NumberHolder(1);
|
const multiStrikeEnhancementMultiplier = new NumberHolder(1);
|
||||||
globalScene.applyModifiers(
|
applyHeldItems(ITEM_EFFECT.MULTI_HIT, {
|
||||||
PokemonMultiHitModifier,
|
pokemon: source,
|
||||||
source.isPlayer(),
|
moveId: move.id,
|
||||||
source,
|
damageMultiplier: multiStrikeEnhancementMultiplier,
|
||||||
move.id,
|
});
|
||||||
null,
|
|
||||||
multiStrikeEnhancementMultiplier,
|
|
||||||
);
|
|
||||||
if (!ignoreSourceAbility) {
|
if (!ignoreSourceAbility) {
|
||||||
applyPreAttackAbAttrs(
|
applyPreAttackAbAttrs(
|
||||||
AddSecondStrikeAbAttr,
|
AddSecondStrikeAbAttr,
|
||||||
|
@ -6,6 +6,7 @@ import { SpeciesId } from "#enums/species-id";
|
|||||||
import { Stat, type PermanentStat } from "#enums/stat";
|
import { Stat, type PermanentStat } from "#enums/stat";
|
||||||
import { StatusEffect } from "#enums/status-effect";
|
import { StatusEffect } from "#enums/status-effect";
|
||||||
import { ITEM_EFFECT } from "./held-item";
|
import { ITEM_EFFECT } from "./held-item";
|
||||||
|
import { type ACCURACY_BOOST_PARAMS, AccuracyBoosterHeldItem } from "./held-items/accuracy-booster";
|
||||||
import {
|
import {
|
||||||
type ATTACK_TYPE_BOOST_PARAMS,
|
type ATTACK_TYPE_BOOST_PARAMS,
|
||||||
AttackTypeBoosterHeldItem,
|
AttackTypeBoosterHeldItem,
|
||||||
@ -25,6 +26,7 @@ import { type FLINCH_CHANCE_PARAMS, FlinchChanceHeldItem } from "./held-items/fl
|
|||||||
import { type FRIENDSHIP_BOOST_PARAMS, FriendshipBoosterHeldItem } from "./held-items/friendship-booster";
|
import { type FRIENDSHIP_BOOST_PARAMS, FriendshipBoosterHeldItem } from "./held-items/friendship-booster";
|
||||||
import { type HIT_HEAL_PARAMS, HitHealHeldItem } from "./held-items/hit-heal";
|
import { type HIT_HEAL_PARAMS, HitHealHeldItem } from "./held-items/hit-heal";
|
||||||
import { InstantReviveHeldItem, type INSTANT_REVIVE_PARAMS } from "./held-items/instant-revive";
|
import { InstantReviveHeldItem, type INSTANT_REVIVE_PARAMS } from "./held-items/instant-revive";
|
||||||
|
import { type MULTI_HIT_PARAMS, MultiHitHeldItem } from "./held-items/multi-hit";
|
||||||
import { type NATURE_WEIGHT_BOOST_PARAMS, NatureWeightBoosterHeldItem } from "./held-items/nature-weight-booster";
|
import { type NATURE_WEIGHT_BOOST_PARAMS, NatureWeightBoosterHeldItem } from "./held-items/nature-weight-booster";
|
||||||
import {
|
import {
|
||||||
ResetNegativeStatStageHeldItem,
|
ResetNegativeStatStageHeldItem,
|
||||||
@ -115,6 +117,8 @@ export function initHeldItems() {
|
|||||||
allHeldItems[HeldItemId.KINGS_ROCK] = new FlinchChanceHeldItem(HeldItemId.KINGS_ROCK, 3, 10);
|
allHeldItems[HeldItemId.KINGS_ROCK] = new FlinchChanceHeldItem(HeldItemId.KINGS_ROCK, 3, 10);
|
||||||
allHeldItems[HeldItemId.MYSTICAL_ROCK] = new FieldEffectHeldItem(HeldItemId.MYSTICAL_ROCK, 2);
|
allHeldItems[HeldItemId.MYSTICAL_ROCK] = new FieldEffectHeldItem(HeldItemId.MYSTICAL_ROCK, 2);
|
||||||
allHeldItems[HeldItemId.SOUL_DEW] = new NatureWeightBoosterHeldItem(HeldItemId.SOUL_DEW, 10);
|
allHeldItems[HeldItemId.SOUL_DEW] = new NatureWeightBoosterHeldItem(HeldItemId.SOUL_DEW, 10);
|
||||||
|
allHeldItems[HeldItemId.WIDE_LENS] = new AccuracyBoosterHeldItem(HeldItemId.WIDE_LENS, 3, 5);
|
||||||
|
allHeldItems[HeldItemId.MULTI_LENS] = new MultiHitHeldItem(HeldItemId.MULTI_LENS, 2);
|
||||||
|
|
||||||
allHeldItems[HeldItemId.FLAME_ORB] = new TurnEndStatusHeldItem(HeldItemId.FLAME_ORB, 1, StatusEffect.BURN);
|
allHeldItems[HeldItemId.FLAME_ORB] = new TurnEndStatusHeldItem(HeldItemId.FLAME_ORB, 1, StatusEffect.BURN);
|
||||||
allHeldItems[HeldItemId.TOXIC_ORB] = new TurnEndStatusHeldItem(HeldItemId.TOXIC_ORB, 1, StatusEffect.TOXIC);
|
allHeldItems[HeldItemId.TOXIC_ORB] = new TurnEndStatusHeldItem(HeldItemId.TOXIC_ORB, 1, StatusEffect.TOXIC);
|
||||||
@ -144,6 +148,8 @@ type APPLY_HELD_ITEMS_PARAMS = {
|
|||||||
[ITEM_EFFECT.FIELD_EFFECT]: FIELD_EFFECT_PARAMS;
|
[ITEM_EFFECT.FIELD_EFFECT]: FIELD_EFFECT_PARAMS;
|
||||||
[ITEM_EFFECT.FRIENDSHIP_BOOSTER]: FRIENDSHIP_BOOST_PARAMS;
|
[ITEM_EFFECT.FRIENDSHIP_BOOSTER]: FRIENDSHIP_BOOST_PARAMS;
|
||||||
[ITEM_EFFECT.NATURE_WEIGHT_BOOSTER]: NATURE_WEIGHT_BOOST_PARAMS;
|
[ITEM_EFFECT.NATURE_WEIGHT_BOOSTER]: NATURE_WEIGHT_BOOST_PARAMS;
|
||||||
|
[ITEM_EFFECT.ACCURACY_BOOSTER]: ACCURACY_BOOST_PARAMS;
|
||||||
|
[ITEM_EFFECT.MULTI_HIT]: MULTI_HIT_PARAMS;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function applyHeldItems<T extends ITEM_EFFECT>(effect: T, params: APPLY_HELD_ITEMS_PARAMS[T]) {
|
export function applyHeldItems<T extends ITEM_EFFECT>(effect: T, params: APPLY_HELD_ITEMS_PARAMS[T]) {
|
||||||
|
@ -23,6 +23,8 @@ export const ITEM_EFFECT = {
|
|||||||
FIELD_EFFECT: 15,
|
FIELD_EFFECT: 15,
|
||||||
FRIENDSHIP_BOOSTER: 16,
|
FRIENDSHIP_BOOSTER: 16,
|
||||||
NATURE_WEIGHT_BOOSTER: 17,
|
NATURE_WEIGHT_BOOSTER: 17,
|
||||||
|
ACCURACY_BOOSTER: 18,
|
||||||
|
MULTI_HIT: 19,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export type ITEM_EFFECT = (typeof ITEM_EFFECT)[keyof typeof ITEM_EFFECT];
|
export type ITEM_EFFECT = (typeof ITEM_EFFECT)[keyof typeof ITEM_EFFECT];
|
||||||
|
47
src/items/held-items/accuracy-booster.ts
Normal file
47
src/items/held-items/accuracy-booster.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import type Pokemon from "#app/field/pokemon";
|
||||||
|
import type { NumberHolder } from "#app/utils/common";
|
||||||
|
import type { HeldItemId } from "#enums/held-item-id";
|
||||||
|
import { HeldItem, ITEM_EFFECT } from "../held-item";
|
||||||
|
|
||||||
|
export interface ACCURACY_BOOST_PARAMS {
|
||||||
|
/** The pokemon with the item */
|
||||||
|
pokemon: Pokemon;
|
||||||
|
/** The amount of exp to gain */
|
||||||
|
moveAccuracy: NumberHolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AccuracyBoosterHeldItem extends HeldItem {
|
||||||
|
public effects: ITEM_EFFECT[] = [ITEM_EFFECT.ACCURACY_BOOSTER];
|
||||||
|
|
||||||
|
private accuracyAmount: number;
|
||||||
|
|
||||||
|
constructor(type: HeldItemId, maxStackCount = 1, accuracy: number) {
|
||||||
|
super(type, maxStackCount);
|
||||||
|
this.accuracyAmount = accuracy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if {@linkcode PokemonMoveAccuracyBoosterModifier} should be applied
|
||||||
|
* @param pokemon The {@linkcode Pokemon} to apply the move accuracy boost to
|
||||||
|
* @param moveAccuracy {@linkcode NumberHolder} holding the move accuracy boost
|
||||||
|
* @returns `true` if {@linkcode PokemonMoveAccuracyBoosterModifier} should be applied
|
||||||
|
*/
|
||||||
|
// override shouldApply(pokemon?: Pokemon, moveAccuracy?: NumberHolder): boolean {
|
||||||
|
// return super.shouldApply(pokemon, moveAccuracy) && !!moveAccuracy;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies {@linkcode PokemonMoveAccuracyBoosterModifier}
|
||||||
|
* @param _pokemon The {@linkcode Pokemon} to apply the move accuracy boost to
|
||||||
|
* @param moveAccuracy {@linkcode NumberHolder} holding the move accuracy boost
|
||||||
|
* @returns always `true`
|
||||||
|
*/
|
||||||
|
apply(params: ACCURACY_BOOST_PARAMS): boolean {
|
||||||
|
const pokemon = params.pokemon;
|
||||||
|
const moveAccuracy = params.moveAccuracy;
|
||||||
|
const stackCount = pokemon.heldItemManager.getStack(this.type);
|
||||||
|
moveAccuracy.value = moveAccuracy.value + this.accuracyAmount * stackCount;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
84
src/items/held-items/multi-hit.ts
Normal file
84
src/items/held-items/multi-hit.ts
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import type Pokemon from "#app/field/pokemon";
|
||||||
|
import { HeldItem, ITEM_EFFECT } from "#app/items/held-item";
|
||||||
|
import { isNullOrUndefined, type NumberHolder } from "#app/utils/common";
|
||||||
|
import type { MoveId } from "#enums/move-id";
|
||||||
|
import { allMoves } from "#app/data/data-lists";
|
||||||
|
|
||||||
|
export interface MULTI_HIT_PARAMS {
|
||||||
|
pokemon: Pokemon;
|
||||||
|
moveId: MoveId;
|
||||||
|
count?: NumberHolder;
|
||||||
|
damageMultiplier?: NumberHolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modifier used for held items, namely Toxic Orb and Flame Orb, that apply a
|
||||||
|
* set {@linkcode StatusEffect} at the end of a turn.
|
||||||
|
* @extends PokemonHeldItemModifier
|
||||||
|
* @see {@linkcode apply}
|
||||||
|
*/
|
||||||
|
export class MultiHitHeldItem extends HeldItem {
|
||||||
|
public effects: ITEM_EFFECT[] = [ITEM_EFFECT.MULTI_HIT];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For each stack, converts 25 percent of attack damage into an additional strike.
|
||||||
|
* @param pokemon The {@linkcode Pokemon} using the move
|
||||||
|
* @param moveId The {@linkcode MoveId | identifier} for the move being used
|
||||||
|
* @param count {@linkcode NumberHolder} holding the move's hit count for this turn
|
||||||
|
* @param damageMultiplier {@linkcode NumberHolder} holding a damage multiplier applied to a strike of this move
|
||||||
|
* @returns always `true`
|
||||||
|
*/
|
||||||
|
apply(params: MULTI_HIT_PARAMS): boolean {
|
||||||
|
const pokemon = params.pokemon;
|
||||||
|
const move = allMoves[params.moveId];
|
||||||
|
/**
|
||||||
|
* The move must meet Parental Bond's restrictions for this item
|
||||||
|
* to apply. This means
|
||||||
|
* - Only attacks are boosted
|
||||||
|
* - Multi-strike moves, charge moves, and self-sacrificial moves are not boosted
|
||||||
|
* (though Multi-Lens can still affect moves boosted by Parental Bond)
|
||||||
|
* - Multi-target moves are not boosted *unless* they can only hit a single Pokemon
|
||||||
|
* - Fling, Uproar, Rollout, Ice Ball, and Endeavor are not boosted
|
||||||
|
*/
|
||||||
|
if (!move.canBeMultiStrikeEnhanced(pokemon)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isNullOrUndefined(params.count)) {
|
||||||
|
return this.applyHitCountBoost(pokemon, params.count);
|
||||||
|
}
|
||||||
|
if (!isNullOrUndefined(params.damageMultiplier)) {
|
||||||
|
return this.applyDamageModifier(pokemon, params.damageMultiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adds strikes to a move equal to the number of stacked Multi-Lenses */
|
||||||
|
private applyHitCountBoost(pokemon: Pokemon, count: NumberHolder): boolean {
|
||||||
|
const stackCount = pokemon.heldItemManager.getStack(this.type);
|
||||||
|
count.value += stackCount;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If applied to the first hit of a move, sets the damage multiplier
|
||||||
|
* equal to (1 - the number of stacked Multi-Lenses).
|
||||||
|
* Additional strikes beyond that are given a 0.25x damage multiplier
|
||||||
|
*/
|
||||||
|
private applyDamageModifier(pokemon: Pokemon, damageMultiplier: NumberHolder): boolean {
|
||||||
|
const stackCount = pokemon.heldItemManager.getStack(this.type);
|
||||||
|
if (pokemon.turnData.hitsLeft === pokemon.turnData.hitCount) {
|
||||||
|
// Reduce first hit by 25% for each stack count
|
||||||
|
damageMultiplier.value *= 1 - 0.25 * stackCount;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (pokemon.turnData.hitCount - pokemon.turnData.hitsLeft !== stackCount + 1) {
|
||||||
|
// Deal 25% damage for each remaining Multi Lens hit
|
||||||
|
damageMultiplier.value *= 0.25;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// An extra hit not caused by Multi Lens -- assume it is Parental Bond
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
import { FusionSpeciesFormEvolution, pokemonEvolutions } from "#app/data/balance/pokemon-evolutions";
|
import { FusionSpeciesFormEvolution, pokemonEvolutions } from "#app/data/balance/pokemon-evolutions";
|
||||||
import { getBerryEffectFunc, getBerryPredicate } from "#app/data/berry";
|
import { getBerryEffectFunc, getBerryPredicate } from "#app/data/berry";
|
||||||
import { getLevelTotalExp } from "#app/data/exp";
|
import { getLevelTotalExp } from "#app/data/exp";
|
||||||
import { allMoves } from "#app/data/data-lists";
|
|
||||||
import { MAX_PER_TYPE_POKEBALLS } from "#app/data/pokeball";
|
import { MAX_PER_TYPE_POKEBALLS } from "#app/data/pokeball";
|
||||||
import { type FormChangeItem, SpeciesFormChangeItemTrigger } from "#app/data/pokemon-forms";
|
import { type FormChangeItem, SpeciesFormChangeItemTrigger } from "#app/data/pokemon-forms";
|
||||||
import { getStatusEffectHealText } from "#app/data/status-effect";
|
import { getStatusEffectHealText } from "#app/data/status-effect";
|
||||||
@ -17,7 +16,6 @@ import { addTextObject, TextStyle } from "#app/ui/text";
|
|||||||
import { BooleanHolder, hslToHex, isNullOrUndefined, NumberHolder, toDmgValue } from "#app/utils/common";
|
import { BooleanHolder, hslToHex, isNullOrUndefined, NumberHolder, toDmgValue } from "#app/utils/common";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { BerryType } from "#enums/berry-type";
|
import { BerryType } from "#enums/berry-type";
|
||||||
import type { MoveId } from "#enums/move-id";
|
|
||||||
import type { Nature } from "#enums/nature";
|
import type { Nature } from "#enums/nature";
|
||||||
import type { PokeballType } from "#enums/pokeball";
|
import type { PokeballType } from "#enums/pokeball";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
@ -32,8 +30,6 @@ import {
|
|||||||
type ModifierOverride,
|
type ModifierOverride,
|
||||||
type ModifierType,
|
type ModifierType,
|
||||||
type PokemonBaseStatTotalModifierType,
|
type PokemonBaseStatTotalModifierType,
|
||||||
type PokemonMoveAccuracyBoosterModifierType,
|
|
||||||
type PokemonMultiHitModifierType,
|
|
||||||
type TerastallizeModifierType,
|
type TerastallizeModifierType,
|
||||||
type TmModifierType,
|
type TmModifierType,
|
||||||
getModifierType,
|
getModifierType,
|
||||||
@ -1692,138 +1688,6 @@ export class ExpBalanceModifier extends PersistentModifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PokemonMoveAccuracyBoosterModifier extends PokemonHeldItemModifier {
|
|
||||||
public override type: PokemonMoveAccuracyBoosterModifierType;
|
|
||||||
private accuracyAmount: number;
|
|
||||||
|
|
||||||
constructor(type: PokemonMoveAccuracyBoosterModifierType, pokemonId: number, accuracy: number, stackCount?: number) {
|
|
||||||
super(type, pokemonId, stackCount);
|
|
||||||
this.accuracyAmount = accuracy;
|
|
||||||
}
|
|
||||||
|
|
||||||
matchType(modifier: Modifier): boolean {
|
|
||||||
if (modifier instanceof PokemonMoveAccuracyBoosterModifier) {
|
|
||||||
const pokemonAccuracyBoosterModifier = modifier as PokemonMoveAccuracyBoosterModifier;
|
|
||||||
return pokemonAccuracyBoosterModifier.accuracyAmount === this.accuracyAmount;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
clone(): PersistentModifier {
|
|
||||||
return new PokemonMoveAccuracyBoosterModifier(this.type, this.pokemonId, this.accuracyAmount, this.stackCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
getArgs(): any[] {
|
|
||||||
return super.getArgs().concat(this.accuracyAmount);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if {@linkcode PokemonMoveAccuracyBoosterModifier} should be applied
|
|
||||||
* @param pokemon The {@linkcode Pokemon} to apply the move accuracy boost to
|
|
||||||
* @param moveAccuracy {@linkcode NumberHolder} holding the move accuracy boost
|
|
||||||
* @returns `true` if {@linkcode PokemonMoveAccuracyBoosterModifier} should be applied
|
|
||||||
*/
|
|
||||||
override shouldApply(pokemon?: Pokemon, moveAccuracy?: NumberHolder): boolean {
|
|
||||||
return super.shouldApply(pokemon, moveAccuracy) && !!moveAccuracy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies {@linkcode PokemonMoveAccuracyBoosterModifier}
|
|
||||||
* @param _pokemon The {@linkcode Pokemon} to apply the move accuracy boost to
|
|
||||||
* @param moveAccuracy {@linkcode NumberHolder} holding the move accuracy boost
|
|
||||||
* @returns always `true`
|
|
||||||
*/
|
|
||||||
override apply(_pokemon: Pokemon, moveAccuracy: NumberHolder): boolean {
|
|
||||||
moveAccuracy.value = moveAccuracy.value + this.accuracyAmount * this.getStackCount();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
getMaxHeldItemCount(_pokemon: Pokemon): number {
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PokemonMultiHitModifier extends PokemonHeldItemModifier {
|
|
||||||
public override type: PokemonMultiHitModifierType;
|
|
||||||
|
|
||||||
matchType(modifier: Modifier): boolean {
|
|
||||||
return modifier instanceof PokemonMultiHitModifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
clone(): PersistentModifier {
|
|
||||||
return new PokemonMultiHitModifier(this.type, this.pokemonId, this.stackCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For each stack, converts 25 percent of attack damage into an additional strike.
|
|
||||||
* @param pokemon The {@linkcode Pokemon} using the move
|
|
||||||
* @param moveId The {@linkcode MoveId | identifier} for the move being used
|
|
||||||
* @param count {@linkcode NumberHolder} holding the move's hit count for this turn
|
|
||||||
* @param damageMultiplier {@linkcode NumberHolder} holding a damage multiplier applied to a strike of this move
|
|
||||||
* @returns always `true`
|
|
||||||
*/
|
|
||||||
override apply(
|
|
||||||
pokemon: Pokemon,
|
|
||||||
moveId: MoveId,
|
|
||||||
count: NumberHolder | null = null,
|
|
||||||
damageMultiplier: NumberHolder | null = null,
|
|
||||||
): boolean {
|
|
||||||
const move = allMoves[moveId];
|
|
||||||
/**
|
|
||||||
* The move must meet Parental Bond's restrictions for this item
|
|
||||||
* to apply. This means
|
|
||||||
* - Only attacks are boosted
|
|
||||||
* - Multi-strike moves, charge moves, and self-sacrificial moves are not boosted
|
|
||||||
* (though Multi-Lens can still affect moves boosted by Parental Bond)
|
|
||||||
* - Multi-target moves are not boosted *unless* they can only hit a single Pokemon
|
|
||||||
* - Fling, Uproar, Rollout, Ice Ball, and Endeavor are not boosted
|
|
||||||
*/
|
|
||||||
if (!move.canBeMultiStrikeEnhanced(pokemon)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isNullOrUndefined(count)) {
|
|
||||||
return this.applyHitCountBoost(count);
|
|
||||||
}
|
|
||||||
if (!isNullOrUndefined(damageMultiplier)) {
|
|
||||||
return this.applyDamageModifier(pokemon, damageMultiplier);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Adds strikes to a move equal to the number of stacked Multi-Lenses */
|
|
||||||
private applyHitCountBoost(count: NumberHolder): boolean {
|
|
||||||
count.value += this.getStackCount();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If applied to the first hit of a move, sets the damage multiplier
|
|
||||||
* equal to (1 - the number of stacked Multi-Lenses).
|
|
||||||
* Additional strikes beyond that are given a 0.25x damage multiplier
|
|
||||||
*/
|
|
||||||
private applyDamageModifier(pokemon: Pokemon, damageMultiplier: NumberHolder): boolean {
|
|
||||||
if (pokemon.turnData.hitsLeft === pokemon.turnData.hitCount) {
|
|
||||||
// Reduce first hit by 25% for each stack count
|
|
||||||
damageMultiplier.value *= 1 - 0.25 * this.getStackCount();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (pokemon.turnData.hitCount - pokemon.turnData.hitsLeft !== this.getStackCount() + 1) {
|
|
||||||
// Deal 25% damage for each remaining Multi Lens hit
|
|
||||||
damageMultiplier.value *= 0.25;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// An extra hit not caused by Multi Lens -- assume it is Parental Bond
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
getMaxHeldItemCount(_pokemon: Pokemon): number {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PokemonFormChangeItemModifier extends PokemonHeldItemModifier {
|
export class PokemonFormChangeItemModifier extends PokemonHeldItemModifier {
|
||||||
public override type: FormChangeItemModifierType;
|
public override type: FormChangeItemModifierType;
|
||||||
public formChangeItem: FormChangeItem;
|
public formChangeItem: FormChangeItem;
|
||||||
|
@ -57,7 +57,6 @@ import {
|
|||||||
DamageMoneyRewardModifier,
|
DamageMoneyRewardModifier,
|
||||||
EnemyAttackStatusEffectChanceModifier,
|
EnemyAttackStatusEffectChanceModifier,
|
||||||
EnemyEndureChanceModifier,
|
EnemyEndureChanceModifier,
|
||||||
PokemonMultiHitModifier,
|
|
||||||
} from "#app/modifier/modifier";
|
} from "#app/modifier/modifier";
|
||||||
import { PokemonPhase } from "#app/phases/pokemon-phase";
|
import { PokemonPhase } from "#app/phases/pokemon-phase";
|
||||||
import { BooleanHolder, isNullOrUndefined, NumberHolder } from "#app/utils/common";
|
import { BooleanHolder, isNullOrUndefined, NumberHolder } from "#app/utils/common";
|
||||||
@ -322,7 +321,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
// If Parental Bond is applicable, add another hit
|
// If Parental Bond is applicable, add another hit
|
||||||
applyPreAttackAbAttrs(AddSecondStrikeAbAttr, user, null, move, false, hitCount, null);
|
applyPreAttackAbAttrs(AddSecondStrikeAbAttr, user, null, move, false, hitCount, null);
|
||||||
// If Multi-Lens is applicable, add hits equal to the number of held Multi-Lenses
|
// If Multi-Lens is applicable, add hits equal to the number of held Multi-Lenses
|
||||||
globalScene.applyModifiers(PokemonMultiHitModifier, user.isPlayer(), user, move.id, hitCount);
|
applyHeldItems(ITEM_EFFECT.MULTI_HIT, { pokemon: user, moveId: move.id, count: hitCount });
|
||||||
// Set the user's relevant turnData fields to reflect the final hit count
|
// Set the user's relevant turnData fields to reflect the final hit count
|
||||||
user.turnData.hitCount = hitCount.value;
|
user.turnData.hitCount = hitCount.value;
|
||||||
user.turnData.hitsLeft = hitCount.value;
|
user.turnData.hitsLeft = hitCount.value;
|
||||||
|
Loading…
Reference in New Issue
Block a user