mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-01 05:52:17 +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";
|
||||
import { allAbilities, allMoves } from "../data-lists";
|
||||
import {
|
||||
AttackTypeBoosterModifier,
|
||||
BerryModifier,
|
||||
PokemonHeldItemModifier,
|
||||
PokemonMoveAccuracyBoosterModifier,
|
||||
PokemonMultiHitModifier,
|
||||
PreserveBerryModifier,
|
||||
} from "../../modifier/modifier";
|
||||
@ -781,7 +779,7 @@ export default class Move implements Localizable {
|
||||
const isOhko = this.hasAttr(OneHitKOAccuracyAttr);
|
||||
|
||||
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) {
|
||||
|
@ -96,7 +96,6 @@ import {
|
||||
PokemonBaseStatTotalModifier,
|
||||
PokemonIncrementingStatModifier,
|
||||
EvoTrackerModifier,
|
||||
PokemonMultiHitModifier,
|
||||
} from "#app/modifier/modifier";
|
||||
import { PokeballType } from "#enums/pokeball";
|
||||
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);
|
||||
if (fixedDamage.value) {
|
||||
const multiLensMultiplier = new NumberHolder(1);
|
||||
globalScene.applyModifiers(
|
||||
PokemonMultiHitModifier,
|
||||
source.isPlayer(),
|
||||
source,
|
||||
move.id,
|
||||
null,
|
||||
multiLensMultiplier,
|
||||
);
|
||||
applyHeldItems(ITEM_EFFECT.MULTI_HIT, {
|
||||
pokemon: source,
|
||||
moveId: move.id,
|
||||
damageMultiplier: multiLensMultiplier,
|
||||
});
|
||||
fixedDamage.value = toDmgValue(fixedDamage.value * multiLensMultiplier.value);
|
||||
|
||||
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 */
|
||||
const multiStrikeEnhancementMultiplier = new NumberHolder(1);
|
||||
globalScene.applyModifiers(
|
||||
PokemonMultiHitModifier,
|
||||
source.isPlayer(),
|
||||
source,
|
||||
move.id,
|
||||
null,
|
||||
multiStrikeEnhancementMultiplier,
|
||||
);
|
||||
applyHeldItems(ITEM_EFFECT.MULTI_HIT, {
|
||||
pokemon: source,
|
||||
moveId: move.id,
|
||||
damageMultiplier: multiStrikeEnhancementMultiplier,
|
||||
});
|
||||
if (!ignoreSourceAbility) {
|
||||
applyPreAttackAbAttrs(
|
||||
AddSecondStrikeAbAttr,
|
||||
|
@ -6,6 +6,7 @@ import { SpeciesId } from "#enums/species-id";
|
||||
import { Stat, type PermanentStat } from "#enums/stat";
|
||||
import { StatusEffect } from "#enums/status-effect";
|
||||
import { ITEM_EFFECT } from "./held-item";
|
||||
import { type ACCURACY_BOOST_PARAMS, AccuracyBoosterHeldItem } from "./held-items/accuracy-booster";
|
||||
import {
|
||||
type ATTACK_TYPE_BOOST_PARAMS,
|
||||
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 HIT_HEAL_PARAMS, HitHealHeldItem } from "./held-items/hit-heal";
|
||||
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 {
|
||||
ResetNegativeStatStageHeldItem,
|
||||
@ -115,6 +117,8 @@ export function initHeldItems() {
|
||||
allHeldItems[HeldItemId.KINGS_ROCK] = new FlinchChanceHeldItem(HeldItemId.KINGS_ROCK, 3, 10);
|
||||
allHeldItems[HeldItemId.MYSTICAL_ROCK] = new FieldEffectHeldItem(HeldItemId.MYSTICAL_ROCK, 2);
|
||||
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.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.FRIENDSHIP_BOOSTER]: FRIENDSHIP_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]) {
|
||||
|
@ -23,6 +23,8 @@ export const ITEM_EFFECT = {
|
||||
FIELD_EFFECT: 15,
|
||||
FRIENDSHIP_BOOSTER: 16,
|
||||
NATURE_WEIGHT_BOOSTER: 17,
|
||||
ACCURACY_BOOSTER: 18,
|
||||
MULTI_HIT: 19,
|
||||
} as const;
|
||||
|
||||
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 { getBerryEffectFunc, getBerryPredicate } from "#app/data/berry";
|
||||
import { getLevelTotalExp } from "#app/data/exp";
|
||||
import { allMoves } from "#app/data/data-lists";
|
||||
import { MAX_PER_TYPE_POKEBALLS } from "#app/data/pokeball";
|
||||
import { type FormChangeItem, SpeciesFormChangeItemTrigger } from "#app/data/pokemon-forms";
|
||||
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 { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { BerryType } from "#enums/berry-type";
|
||||
import type { MoveId } from "#enums/move-id";
|
||||
import type { Nature } from "#enums/nature";
|
||||
import type { PokeballType } from "#enums/pokeball";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
@ -32,8 +30,6 @@ import {
|
||||
type ModifierOverride,
|
||||
type ModifierType,
|
||||
type PokemonBaseStatTotalModifierType,
|
||||
type PokemonMoveAccuracyBoosterModifierType,
|
||||
type PokemonMultiHitModifierType,
|
||||
type TerastallizeModifierType,
|
||||
type TmModifierType,
|
||||
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 {
|
||||
public override type: FormChangeItemModifierType;
|
||||
public formChangeItem: FormChangeItem;
|
||||
|
@ -57,7 +57,6 @@ import {
|
||||
DamageMoneyRewardModifier,
|
||||
EnemyAttackStatusEffectChanceModifier,
|
||||
EnemyEndureChanceModifier,
|
||||
PokemonMultiHitModifier,
|
||||
} from "#app/modifier/modifier";
|
||||
import { PokemonPhase } from "#app/phases/pokemon-phase";
|
||||
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
|
||||
applyPreAttackAbAttrs(AddSecondStrikeAbAttr, user, null, move, false, hitCount, null);
|
||||
// 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
|
||||
user.turnData.hitCount = hitCount.value;
|
||||
user.turnData.hitsLeft = hitCount.value;
|
||||
|
Loading…
Reference in New Issue
Block a user