Add King's Rock and more berry types

This commit is contained in:
Flashfyre 2023-04-25 01:32:48 -04:00
parent 3753ea73be
commit a148ecab80
19 changed files with 1417 additions and 1104 deletions

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

(image error) Size: 19 KiB

After

(image error) Size: 21 KiB

Binary file not shown.

After

(image error) Size: 290 B

Binary file not shown.

After

(image error) Size: 295 B

Binary file not shown.

After

(image error) Size: 336 B

Binary file not shown.

After

(image error) Size: 322 B

Binary file not shown.

After

(image error) Size: 347 B

Binary file not shown.

After

(image error) Size: 375 B

Binary file not shown.

After

(image error) Size: 345 B

Binary file not shown.

After

(image error) Size: 320 B

@ -5,7 +5,7 @@ import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, HitsTagAttr, Mis
import { Mode } from './ui/ui';
import { Command } from "./ui/command-ui-handler";
import { Stat } from "./data/pokemon-stat";
import { BerryModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, HealingBoosterModifier, HeldItemTransferModifier, HitHealModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, TempBattleStatBoosterModifier, TurnHealModifier } from "./modifier/modifier";
import { BerryModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, HealingBoosterModifier, HeldItemTransferModifier, HitHealModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, TempBattleStatBoosterModifier, TurnHealModifier } from "./modifier/modifier";
import PartyUiHandler, { PartyOption, PartyUiMode } from "./ui/party-ui-handler";
import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./data/pokeball";
import { CommonAnim, CommonBattleAnim, MoveAnim, initMoveAnim, loadMoveAnimAssets } from "./data/battle-anims";
@ -768,7 +768,7 @@ export abstract class MovePhase extends BattlePhase {
}
if (this.cancelled) {
this.pokemon.getMoveHistory().push({ move: Moves.NONE, result: MoveResult.FAILED });
this.pokemon.pushMoveHistory({ move: Moves.NONE, result: MoveResult.FAILED });
this.end();
return;
}
@ -783,7 +783,7 @@ export abstract class MovePhase extends BattlePhase {
if (success)
this.scene.unshiftPhase(this.getEffectPhase());
else {
this.pokemon.getMoveHistory().push({ move: this.move.moveId, result: MoveResult.FAILED, virtual: this.move.virtual });
this.pokemon.pushMoveHistory({ move: this.move.moveId, result: MoveResult.FAILED, virtual: this.move.virtual });
this.scene.queueMessage('But it failed!');
}
@ -900,7 +900,7 @@ abstract class MoveEffectPhase extends PokemonPhase {
if (!this.hitCheck()) {
this.scene.queueMessage(getPokemonMessage(user, '\'s\nattack missed!'));
user.getMoveHistory().push({ move: this.move.moveId, result: MoveResult.MISSED, virtual: this.move.virtual });
user.pushMoveHistory({ move: this.move.moveId, result: MoveResult.MISSED, virtual: this.move.virtual });
applyMoveAttrs(MissEffectAttr, user, target, this.move.getMove());
this.end();
return;
@ -911,9 +911,15 @@ abstract class MoveEffectPhase extends PokemonPhase {
new MoveAnim(this.move.getMove().id as Moves, user, target).play(this.scene, () => {
const result = !isProtected ? target.apply(user, this.move) : MoveResult.NO_EFFECT;
++user.turnData.hitCount;
user.getMoveHistory().push({ move: this.move.moveId, result: result, virtual: this.move.virtual });
user.pushMoveHistory({ move: this.move.moveId, result: result, virtual: this.move.virtual });
if (result !== MoveResult.NO_EFFECT && result !== MoveResult.FAILED) {
applyMoveAttrs(MoveEffectAttr, user, target, this.move.getMove());
if (result < MoveResult.NO_EFFECT) {
const flinched = new Utils.BooleanHolder(false);
user.scene.applyModifiers(FlinchChanceModifier, user.isPlayer(), user, flinched);
if (flinched.value)
target.addTag(BattlerTagType.FLINCHED, undefined, this.move.moveId, user.id);
}
// Charge attribute with charge effect takes all effect attributes and applies them to charge stage, so ignore them if this is present
if (!isProtected && target.hp && !this.move.getMove().getAttrs(ChargeAttr).filter(ca => (ca as ChargeAttr).chargeEffect).length)
applyMoveAttrs(MoveHitEffectAttr, user, target, this.move.getMove());

@ -470,7 +470,7 @@ export default class BattleScene extends Phaser.Scene {
this.arenaBgTransition.setPosition(0, 0);
this.arenaPlayer.setPosition(340, 20);
this.arenaPlayerTransition.setPosition(40, 2);
this.arenaPlayerTransition.setPosition(40, 20);
this.arenaEnemy.setPosition(-240, 13);
this.arenaNextEnemy.setPosition(-240, 13);

@ -5,7 +5,7 @@ import Pokemon from "../pokemon";
import { Stat } from "./pokemon-stat";
import { StatusEffect } from "./status-effect";
import * as Utils from "../utils";
import { Moves, allMoves } from "./move";
import { LapseBattlerTagAttr, Moves, allMoves } from "./move";
import { Type } from "./type";
export enum BattlerTagType {
@ -30,6 +30,7 @@ export enum BattlerTagType {
PROTECTED,
FLYING,
UNDERGROUND,
CRIT_BOOST,
NO_CRIT,
BYPASS_SLEEP,
IGNORE_FLYING
@ -462,6 +463,28 @@ export class HideSpriteTag extends BattlerTag {
}
}
export class CritBoostTag extends BattlerTag {
constructor(tagType: BattlerTagType, sourceMove: Moves) {
super(tagType, BattlerTagLapseType.TURN_END, 1, sourceMove);
}
onAdd(pokemon: Pokemon): void {
super.onAdd(pokemon);
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' is getting\npumped!'));
}
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
return lapseType !== BattlerTagLapseType.CUSTOM || super.lapse(pokemon, lapseType);
}
onRemove(pokemon: Pokemon): void {
super.onRemove(pokemon);
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' relaxed.'));
}
}
export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourceMove: Moves, sourceId: integer): BattlerTag {
switch (tagType) {
case BattlerTagType.RECHARGING:
@ -501,6 +524,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc
case BattlerTagType.FLYING:
case BattlerTagType.UNDERGROUND:
return new HideSpriteTag(tagType, turnCount, sourceMove);
case BattlerTagType.CRIT_BOOST:
return new CritBoostTag(tagType, sourceMove);
case BattlerTagType.NO_CRIT:
return new BattlerTag(tagType, BattlerTagLapseType.AFTER_MOVE, turnCount, sourceMove);
case BattlerTagType.BYPASS_SLEEP:

@ -1,21 +1,26 @@
import { MessagePhase, PokemonHealPhase } from "../battle-phases";
import { PokemonHealPhase, StatChangePhase } from "../battle-phases";
import { getPokemonMessage } from "../messages";
import Pokemon from "../pokemon";
import Pokemon, { MoveResult } from "../pokemon";
import { getBattleStatName } from "./battle-stat";
import { BattleStat } from "./battle-stat";
import { BattlerTagType } from "./battler-tag";
import { getStatusEffectHealText } from "./status-effect";
export enum BerryType {
SITRUS,
LUM
LUM,
ENIGMA,
LIECHI,
GANLON,
SALAC,
PETAYA,
APICOT,
LANSAT,
STARF
}
export function getBerryName(berryType: BerryType) {
switch (berryType) {
case BerryType.SITRUS:
return 'SITRUS BERRY';
case BerryType.LUM:
return 'LUM BERRY';
}
return `${BerryType[berryType]} BERRY`;
}
export function getBerryEffectDescription(berryType: BerryType) {
@ -24,6 +29,19 @@ export function getBerryEffectDescription(berryType: BerryType) {
return 'Restores 25% HP if HP is below 50%';
case BerryType.LUM:
return 'Cures any non-volatile status condition and confusion';
case BerryType.ENIGMA:
return 'Restores 25% HP if hit by a super effective move';
case BerryType.LIECHI:
case BerryType.GANLON:
case BerryType.SALAC:
case BerryType.PETAYA:
case BerryType.APICOT:
const stat = (berryType - BerryType.LIECHI) as BattleStat;
return `Raises ${getBattleStatName(stat)} if HP is below 25%`;
case BerryType.LANSAT:
return 'Raises critical hit ratio if HP is below 25%';
case BerryType.STARF:
return 'Sharply raises a random stat if HP is below 25%';
}
}
@ -35,6 +53,26 @@ export function getBerryPredicate(berryType: BerryType): BerryPredicate {
return (pokemon: Pokemon) => pokemon.getHpRatio() < 0.5;
case BerryType.LUM:
return (pokemon: Pokemon) => !!pokemon.status || !!pokemon.getTag(BattlerTagType.CONFUSED);
case BerryType.ENIGMA:
return (pokemon: Pokemon) => {
const opponent = pokemon.isPlayer() ? pokemon.scene.getEnemyPokemon() : pokemon.scene.getPlayerPokemon();
const opponentLastMove = opponent ? opponent.getLastXMoves(1).find(() => true) : null; // TODO: Update so this works even if opponent has fainted
return opponentLastMove && opponentLastMove.turn === pokemon.scene.currentBattle?.turn - 1 && opponentLastMove.result === MoveResult.SUPER_EFFECTIVE;
};
case BerryType.LIECHI:
case BerryType.GANLON:
case BerryType.SALAC:
case BerryType.PETAYA:
case BerryType.APICOT:
return (pokemon: Pokemon) => {
const battleStat = (berryType - BerryType.LIECHI) as BattleStat;
return pokemon.getHpRatio() < 0.25 && pokemon.summonData.battleStats[battleStat] < 6;
};
case BerryType.LANSAT:
return (pokemon: Pokemon) => pokemon.getHpRatio() < 0.25 && !pokemon.getTag(BattlerTagType.CRIT_BOOST);
case BerryType.STARF:
return (pokemon: Pokemon) => pokemon.getHpRatio() < 0.25;
}
}
@ -43,6 +81,7 @@ export type BerryEffectFunc = (pokemon: Pokemon) => void;
export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
switch (berryType) {
case BerryType.SITRUS:
case BerryType.ENIGMA:
return (pokemon: Pokemon) => {
pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.isPlayer(), Math.floor(pokemon.getMaxHp() / 4), getPokemonMessage(pokemon, `'s ${getBerryName(berryType)}\nrestored its HP!`), true));
};
@ -55,5 +94,20 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
} else if (pokemon.getTag(BattlerTagType.CONFUSED))
pokemon.lapseTag(BattlerTagType.CONFUSED);
};
case BerryType.LIECHI:
case BerryType.GANLON:
case BerryType.SALAC:
case BerryType.PETAYA:
case BerryType.APICOT:
return (pokemon: Pokemon) => {
const battleStat = (berryType - BerryType.LIECHI) as BattleStat;
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.isPlayer(), [ battleStat ], 1));
};
case BerryType.LANSAT:
return (pokemon: Pokemon) => {
pokemon.addTag(BattlerTagType.CRIT_BOOST);
};
case BerryType.STARF:
return (pokemon: Pokemon) => pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.isPlayer(), [ BattleStat.RAND ], 2));
}
}

@ -9,6 +9,7 @@ import { Type } from "./type";
import * as Utils from "../utils";
import { WeatherType } from "./weather";
import { ArenaTagType, ArenaTrapTag } from "./arena-tag";
import { FlinchChanceModifier } from "../modifier/modifier";
export enum MoveCategory {
PHYSICAL,
@ -1037,7 +1038,7 @@ export class ChargeAttr extends OverrideMoveEffectAttr {
user.addTag(this.tagType, 1, move.id, user.id);
if (this.chargeEffect)
applyMoveAttrs(MoveEffectAttr, user, target, move);
user.getMoveHistory().push({ move: move.id, result: MoveResult.OTHER });
user.pushMoveHistory({ move: move.id, result: MoveResult.OTHER });
user.getMoveQueue().push({ move: move.id, ignorePP: true });
resolve(true);
});
@ -1427,7 +1428,8 @@ export class AddBattlerTagAttr extends MoveEffectAttr {
if (!super.apply(user, target, move, args))
return false;
if (move.chance < 0 || move.chance === 100 || Utils.randInt(100) < move.chance) {
const chance = this.getTagChance(user, target, move);
if (chance < 0 || chance === 100 || Utils.randInt(100) < chance) {
(this.selfTarget ? user : target).addTag(this.tagType, this.turnCount, move.id, user.id);
return true;
}
@ -1435,6 +1437,10 @@ export class AddBattlerTagAttr extends MoveEffectAttr {
return false;
}
getTagChance(user: Pokemon, target: Pokemon, move: Move): integer {
return move.chance;
}
getCondition(): MoveCondition {
return this.failOnOverlap
? (user: Pokemon, target: Pokemon, move: Move) => !(this.selfTarget ? user : target).getTag(this.tagType)
@ -1925,7 +1931,8 @@ export const allMoves = [
new SelfStatusMove(Moves.LIGHT_SCREEN, "Light Screen (N)", Type.PSYCHIC, -1, 30, 75, "Halves damage from Special attacks for 5 turns.", -1, 0, 1),
new SelfStatusMove(Moves.HAZE, "Haze (N)", Type.ICE, -1, 30, -1, "Resets all stat changes.", -1, 0, 1),
new SelfStatusMove(Moves.REFLECT, "Reflect (N)", Type.PSYCHIC, -1, 20, 74, "Halves damage from Physical attacks for 5 turns.", -1, 0, 1),
new SelfStatusMove(Moves.FOCUS_ENERGY, "Focus Energy (N)", Type.NORMAL, -1, 30, -1, "Increases critical hit ratio.", -1, 0, 1),
new SelfStatusMove(Moves.FOCUS_ENERGY, "Focus Energy", Type.NORMAL, -1, 30, -1, "Increases critical hit ratio.", -1, 0, 1)
.attr(AddBattlerTagAttr, BattlerTagType.CRIT_BOOST, true, undefined, true),
new AttackMove(Moves.BIDE, "Bide (N)", Type.NORMAL, MoveCategory.PHYSICAL, -1, -1, 10, -1, "User takes damage for two turns then strikes back double.", -1, 0, 1),
new SelfStatusMove(Moves.METRONOME, "Metronome", Type.NORMAL, -1, 10, 80, "User performs almost any move in the game at random.", -1, 0, 1)
.attr(RandomMoveAttr),

@ -1,5 +1,5 @@
import { Gender } from "./gender";
import { AttackTypeBoosterModifier } from "../modifier/modifier";
import { AttackTypeBoosterModifier, FlinchChanceModifier } from "../modifier/modifier";
import { AttackTypeBoosterModifierType } from "../modifier/modifier-type";
import { Moves } from "./move";
import { PokeballType } from "./pokeball";
@ -167,7 +167,7 @@ export const pokemonEvolutions: PokemonEvolutions = {
],
[Species.SLOWPOKE]: [
new SpeciesEvolution(Species.SLOWBRO, 37, null, null),
new SpeciesEvolution(Species.SLOWKING, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition((p: Pokemon) => true /* King's rock*/), SpeciesWildEvolutionDelay.VERY_LONG)
new SpeciesEvolution(Species.SLOWKING, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition((p: Pokemon) => !!p.scene.findModifier(m => (m instanceof FlinchChanceModifier) && (m as FlinchChanceModifier).pokemonId === p.id, true)), SpeciesWildEvolutionDelay.VERY_LONG)
],
[Species.MAGNEMITE]: [
new SpeciesEvolution(Species.MAGNETON, 30, null, null)
@ -779,7 +779,7 @@ export const pokemonEvolutions: PokemonEvolutions = {
],
[Species.POLIWHIRL]: [
new SpeciesEvolution(Species.POLIWRATH, 1, EvolutionItem.WATER_STONE, null, SpeciesWildEvolutionDelay.LONG),
new SpeciesEvolution(Species.POLITOED, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition((p: Pokemon) => true /* King's rock*/), SpeciesWildEvolutionDelay.VERY_LONG)
new SpeciesEvolution(Species.POLITOED, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition((p: Pokemon) => !!p.scene.findModifier(m => (m instanceof FlinchChanceModifier) && (m as FlinchChanceModifier).pokemonId === p.id, true)), SpeciesWildEvolutionDelay.VERY_LONG)
],
[Species.WEEPINBELL]: [
new SpeciesEvolution(Species.VICTREEBEL, 1, EvolutionItem.LEAF_STONE, null, SpeciesWildEvolutionDelay.LONG)

@ -35,7 +35,7 @@ export class ModifierType {
constructor(name: string, description: string, newModifierFunc: NewModifierFunc, iconImage?: string, group?: string, soundName?: string) {
this.name = name;
this.description = description;
this.iconImage = iconImage || name?.replace(/[ \-]/g, '_')?.toLowerCase();
this.iconImage = iconImage || name?.replace(/[ \-]/g, '_')?.replace(/'/g, '')?.toLowerCase();
this.group = group || '';
this.soundName = soundName || 'restore';
this.newModifierFunc = newModifierFunc;
@ -497,7 +497,14 @@ const modifierTypes = {
BERRY: () => new ModifierTypeGenerator((party: Pokemon[]) => {
const berryTypes = Utils.getEnumValues(BerryType);
const randBerryType = berryTypes[Utils.randInt(berryTypes.length)];
let randBerryType;
let rand = Utils.randInt(10);
if (rand < 2)
randBerryType = BerryType.SITRUS;
else if (rand < 4)
randBerryType = BerryType.LUM;
else
randBerryType = berryTypes[Utils.randInt(berryTypes.length - 2) + 2];
return new PokemonHeldItemModifierType(getBerryName(randBerryType), getBerryEffectDescription(randBerryType),
(type, args) => new Modifiers.BerryModifier(type, (args[0] as Pokemon).id, randBerryType),
null, 'berry');
@ -521,6 +528,7 @@ const modifierTypes = {
GOLDEN_EXP_CHARM: () => new ExpBoosterModifierType('GOLDEN EXP CHARM', 100),
LUCKY_EGG: () => new PokemonExpBoosterModifierType('LUCKY EGG', 50),
GOLDEN_EGG: () => new PokemonExpBoosterModifierType('GOLDEN EGG', 200),
HEALING_CHARM: () => new ModifierType('HEALING CHARM', 'Doubles the effectiveness of HP restoring moves and items (excludes revives)',
(type, _args) => new Modifiers.HealingBoosterModifier(type, 2), 'healing_charm'),
@ -536,6 +544,9 @@ const modifierTypes = {
FOCUS_BAND: () => new PokemonHeldItemModifierType('FOCUS BAND', 'Adds a 10% chance to survive with 1 HP after being damaged enough to faint',
(type, args) => new Modifiers.SurviveDamageModifier(type, (args[0] as Pokemon).id)),
KINGS_ROCK: () => new PokemonHeldItemModifierType('KING\'S ROCK', 'Adds a 10% chance an attack move will cause the opponent to flinch',
(type, args) => new Modifiers.FlinchChanceModifier(type, (args[0] as Pokemon).id)),
LEFTOVERS: () => new PokemonHeldItemModifierType('LEFTOVERS', 'Heals 1/16 of a POKéMON\'s maximum HP every turn',
(type, args) => new Modifiers.TurnHealModifier(type, (args[0] as Pokemon).id)),
SHELL_BELL: () => new PokemonHeldItemModifierType('SHELL BELL', 'Heals 1/8 of a POKéMON\'s dealt damage',
@ -570,7 +581,7 @@ const modifierPool = {
return thresholdPartyMemberCount;
}),
new WeightedModifierType(modifierTypes.TEMP_STAT_BOOSTER, 4),
new WeightedModifierType(modifierTypes.BERRY, 2)
new WeightedModifierType(modifierTypes.BERRY, 20)
].map(m => { m.setTier(ModifierTier.COMMON); return m; }),
[ModifierTier.GREAT]: [
new WeightedModifierType(modifierTypes.GREAT_BALL, 6),
@ -617,6 +628,7 @@ const modifierPool = {
//new WeightedModifierType(modifierTypes.OVAL_CHARM, 1),
new WeightedModifierType(modifierTypes.HEALING_CHARM, 1),
new WeightedModifierType(modifierTypes.FOCUS_BAND, 3),
new WeightedModifierType(modifierTypes.KINGS_ROCK, 2),
new WeightedModifierType(modifierTypes.LEFTOVERS, 2),
new WeightedModifierType(modifierTypes.SHELL_BELL, 2),
new WeightedModifierType(modifierTypes.BERRY_POUCH, 3),
@ -644,13 +656,15 @@ const enemyModifierPool = {
new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 1)
].map(m => { m.setTier(ModifierTier.GREAT); return m; }),
[ModifierTier.ULTRA]: [
new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 5),
new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 10),
new WeightedModifierType(modifierTypes.FOCUS_BAND, 2),
new WeightedModifierType(modifierTypes.LUCKY_EGG, 2),
new WeightedModifierType(modifierTypes.LUCKY_EGG, 4),
new WeightedModifierType(modifierTypes.KINGS_ROCK, 1),
new WeightedModifierType(modifierTypes.LEFTOVERS, 1),
new WeightedModifierType(modifierTypes.SHELL_BELL, 1),
].map(m => { m.setTier(ModifierTier.ULTRA); return m; }),
[ModifierTier.MASTER]: [
new WeightedModifierType(modifierTypes.LEFTOVERS, 4),
new WeightedModifierType(modifierTypes.SHELL_BELL, 4),
new WeightedModifierType(modifierTypes.GOLDEN_EGG, 1),
new WeightedModifierType(modifierTypes.MINI_BLACK_HOLE, 1)
].map(m => { m.setTier(ModifierTier.MASTER); return m; })
};

@ -370,7 +370,7 @@ export class SurviveDamageModifier extends PokemonHeldItemModifier {
const pokemon = args[0] as Pokemon;
const surviveDamage = args[1] as Utils.BooleanHolder;
if (!surviveDamage.value && (this.getStackCount() === this.getMaxStackCount() || Utils.randInt(10) < this.getStackCount())) {
if (!surviveDamage.value && Utils.randInt(10) < this.getStackCount()) {
surviveDamage.value = true;
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` hung on\nusing its ${this.type.name}!`));
@ -384,6 +384,37 @@ export class SurviveDamageModifier extends PokemonHeldItemModifier {
}
}
export class FlinchChanceModifier extends PokemonHeldItemModifier {
constructor(type: ModifierType, pokemonId: integer, stackCount?: integer) {
super(type, pokemonId, stackCount);
}
matchType(modifier: Modifier) {
return modifier instanceof FlinchChanceModifier;
}
clone() {
return new FlinchChanceModifier(this.type, this.pokemonId, this.stackCount);
}
shouldApply(args: any[]): boolean {
return super.shouldApply(args) && args.length === 2 && args[1] instanceof Utils.BooleanHolder;
}
apply(args: any[]): boolean {
const flinched = args[1] as Utils.BooleanHolder;
if (!flinched.value && Utils.randInt(10) < this.getStackCount())
flinched.value = true;
return true;
}
getMaxStackCount(): number {
return 3;
}
}
export class TurnHealModifier extends PokemonHeldItemModifier {
constructor(type: ModifierType, pokemonId: integer, stackCount?: integer) {
super(type, pokemonId, stackCount);

@ -491,6 +491,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const critLevel = new Utils.IntegerHolder(0);
applyMoveAttrs(HighCritAttr, source, this, move, critLevel);
this.scene.applyModifiers(TempBattleStatBoosterModifier, source.isPlayer(), TempBattleStat.CRIT, critLevel);
if (source.getTag(BattlerTagType.CRIT_BOOST))
critLevel.value += 2;
const critChance = Math.ceil(16 / Math.pow(2, critLevel.value));
let isCritical = !source.getTag(BattlerTagType.NO_CRIT) && (critChance === 1 || !Utils.randInt(critChance));
const sourceAtk = source.getBattleStat(isPhysical ? Stat.ATK : Stat.SPATK);
@ -642,6 +644,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return this.summonData.moveHistory;
}
pushMoveHistory(turnMove: TurnMove) {
turnMove.turn = this.scene.currentBattle?.turn;
this.getMoveHistory().push(turnMove);
}
getLastXMoves(turnCount?: integer): TurnMove[] {
const moveHistory = this.getMoveHistory();
return moveHistory.slice(turnCount >= 0 ? Math.max(moveHistory.length - (turnCount || 1), 0) : 0, moveHistory.length).reverse();
@ -1035,6 +1042,7 @@ export interface TurnMove {
move: Moves;
result: MoveResult;
virtual?: boolean;
turn?: integer;
}
export interface QueuedMove {