Damage-related fixes and changes

Apply damage numbers to all damage and heal; fix some damage-related bugs
This commit is contained in:
Flashfyre 2024-03-01 09:35:36 -05:00
parent 716d8853a3
commit 1f6a6f4621
7 changed files with 103 additions and 65 deletions

View File

@ -905,8 +905,8 @@ export class PostWeatherLapseDamageAbAttr extends PostWeatherLapseAbAttr {
if (pokemon.getHpRatio() < 1) {
const scene = pokemon.scene;
scene.queueMessage(getPokemonMessage(pokemon, ` is hurt\nby its ${pokemon.getAbility()}!`));
scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.getBattlerIndex(), HitResult.OTHER));
pokemon.damage(Math.ceil(pokemon.getMaxHp() / (16 / this.damageFactor)));
const damage = pokemon.damage(Math.ceil(pokemon.getMaxHp() / (16 / this.damageFactor)));
scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.getBattlerIndex(), damage, HitResult.OTHER));
return true;
}

View File

@ -170,10 +170,10 @@ class SpikesTag extends ArenaTrapTag {
activateTrap(pokemon: Pokemon): boolean {
if ((!pokemon.isOfType(Type.FLYING) || pokemon.getTag(BattlerTagType.IGNORE_FLYING) || pokemon.scene.arena.getTag(ArenaTagType.GRAVITY))) {
const damageHpRatio = 1 / (10 - 2 * this.layers);
const damage = Math.ceil(pokemon.getMaxHp() * damageHpRatio);
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' is hurt\nby the spikes!'));
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.getBattlerIndex(), HitResult.OTHER));
pokemon.damage(Math.ceil(pokemon.getMaxHp() * damageHpRatio));
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.getBattlerIndex(), pokemon.damage(damage), HitResult.OTHER));
return true;
}
@ -266,9 +266,9 @@ class StealthRockTag extends ArenaTrapTag {
}
if (damageHpRatio) {
const damage = Math.ceil(pokemon.getMaxHp() * damageHpRatio);
pokemon.scene.queueMessage(`Pointed stones dug into\n${pokemon.name}!`);
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.getBattlerIndex(), HitResult.OTHER));
pokemon.damage(Math.ceil(pokemon.getMaxHp() * damageHpRatio));
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.getBattlerIndex(), pokemon.damage(damage), HitResult.OTHER));
}
return false;

View File

@ -179,8 +179,7 @@ export class ConfusedTag extends BattlerTag {
const def = pokemon.getBattleStat(Stat.DEF);
const damage = Math.ceil(((((2 * pokemon.level / 5 + 2) * 40 * atk / def) / 50) + 2) * (pokemon.randSeedInt(15, 85) / 100));
pokemon.scene.queueMessage('It hurt itself in its\nconfusion!');
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.getBattlerIndex()));
pokemon.damage(damage);
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.getBattlerIndex(), pokemon.damage(damage)));
pokemon.battleData.hitCount++;
(pokemon.scene.getCurrentPhase() as MovePhase).cancel();
}
@ -264,9 +263,9 @@ export class SeedTag extends BattlerTag {
if (source) {
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, source.getBattlerIndex(), pokemon.getBattlerIndex(), CommonAnim.LEECH_SEED));
const damage = Math.max(Math.floor(pokemon.getMaxHp() / 8), 1);
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.getBattlerIndex()));
pokemon.damage(damage);
const damage = pokemon.damage(Math.max(Math.floor(pokemon.getMaxHp() / 8), 1));
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.getBattlerIndex(), damage));
pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, source.getBattlerIndex(), damage, getPokemonMessage(pokemon, '\'s health is\nsapped by Leech Seed!'), false, true));
}
}
@ -304,8 +303,7 @@ export class NightmareTag extends BattlerTag {
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.getBattlerIndex(), undefined, CommonAnim.CURSE)); // TODO: Update animation type
const damage = Math.ceil(pokemon.getMaxHp() / 4);
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.getBattlerIndex()));
pokemon.damage(damage);
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.getBattlerIndex(), pokemon.damage(damage)));
}
return ret;
@ -473,8 +471,7 @@ export abstract class DamagingTrapTag extends TrappedTag {
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.getBattlerIndex(), undefined, this.commonAnim));
const damage = Math.ceil(pokemon.getMaxHp() / 8);
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.getBattlerIndex()));
pokemon.damage(damage);
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.getBattlerIndex(), pokemon.damage(damage)));
}
return ret;
@ -617,10 +614,8 @@ export class PerishSongTag extends BattlerTag {
if (ret)
pokemon.scene.queueMessage(getPokemonMessage(pokemon, `\'s perish count fell to ${this.turnCount}.`));
else {
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.getBattlerIndex(), HitResult.ONE_HIT_KO));
pokemon.damage(pokemon.hp, true, true);
}
else
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.getBattlerIndex(), pokemon.damage(pokemon.hp, true, true), HitResult.ONE_HIT_KO));
return ret;
}

View File

@ -532,9 +532,8 @@ export class RecoilAttr extends MoveEffectAttr {
if (!recoilDamage)
return false;
user.scene.unshiftPhase(new DamagePhase(user.scene, user.getBattlerIndex(), HitResult.OTHER));
user.scene.unshiftPhase(new DamagePhase(user.scene, user.getBattlerIndex(), user.damage(recoilDamage, true), HitResult.OTHER));
user.scene.queueMessage(getPokemonMessage(user, ' is hit\nwith recoil!'));
user.damage(recoilDamage, true);
return true;
}
@ -553,8 +552,7 @@ export class SacrificialAttr extends MoveEffectAttr {
if (!super.apply(user, target, move, args))
return false;
user.scene.unshiftPhase(new DamagePhase(user.scene, user.getBattlerIndex(), HitResult.OTHER));
user.damage(user.getMaxHp(), true, true);
user.scene.unshiftPhase(new DamagePhase(user.scene, user.getBattlerIndex(), user.damage(user.hp, true, true), HitResult.OTHER));
return true;
}
@ -1085,7 +1083,9 @@ export class HalfHpStatMaxAttr extends StatChangeAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise<boolean> {
return new Promise<boolean>(resolve => {
user.damage(Math.floor(user.getMaxHp() / 2));
const damage = user.damage(Math.floor(user.getMaxHp() / 2), true);
if (damage)
user.scene.damageNumberHandler.add(user, damage);
user.updateInfo().then(() => {
const ret = super.apply(user, target, move, args);
user.scene.queueMessage(getPokemonMessage(user, ` cut its own hp\nand maximized its ${getBattleStatName(this.stats[0])}!`));
@ -1106,7 +1106,9 @@ export class CutHpStatBoostAttr extends StatChangeAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise<boolean> {
return new Promise<boolean>(resolve => {
user.damage(Math.floor(user.getMaxHp() / 3));
const damage = user.damage(Math.floor(user.getMaxHp() / 3), true);
if (damage)
user.scene.damageNumberHandler.add(user, damage);
user.updateInfo().then(() => {
const ret = super.apply(user, target, move, args);
resolve(ret);
@ -1128,16 +1130,26 @@ export class HpSplitAttr extends MoveEffectAttr {
const infoUpdates = [];
const hpValue = Math.floor((target.hp + user.hp) / 2);
if (user.hp < hpValue)
user.heal(hpValue - user.hp);
else if (user.hp > hpValue)
user.damage(user.hp - hpValue, true);
if (user.hp < hpValue) {
const healing = user.heal(hpValue - user.hp);
if (healing)
user.scene.damageNumberHandler.add(user, healing, HitResult.HEAL);
} else if (user.hp > hpValue) {
const damage = user.damage(user.hp - hpValue, true);
if (damage)
user.scene.damageNumberHandler.add(user, damage);
}
infoUpdates.push(user.updateInfo());
if (target.hp < hpValue)
target.heal(hpValue - target.hp);
else if (target.hp > hpValue)
target.damage(target.hp - hpValue, true);
if (target.hp < hpValue) {
const healing = target.heal(hpValue - target.hp);
if (healing)
user.scene.damageNumberHandler.add(user, healing, HitResult.HEAL);
} else if (target.hp > hpValue) {
const damage = target.damage(target.hp - hpValue, true);
if (damage)
target.scene.damageNumberHandler.add(target, damage);
}
infoUpdates.push(target.updateInfo());
return Promise.all(infoUpdates).then(() => resolve(true));
@ -1397,6 +1409,13 @@ export class MissEffectAttr extends MoveAttr {
}
}
const halveHpMissEffectFunc = (user: Pokemon, move: Move) => {
const damage = user.damage(Math.floor(user.getMaxHp() / 2));
if (damage)
user.scene.damageNumberHandler.add(user, damage, HitResult.OTHER);
return true;
};
export class TypelessAttr extends MoveAttr { }
export class DisableMoveAttr extends MoveEffectAttr {
@ -2280,7 +2299,7 @@ export function initMoves() {
.attr(MultiHitAttr, MultiHitType._2),
new AttackMove(Moves.MEGA_KICK, "Mega Kick", Type.NORMAL, MoveCategory.PHYSICAL, 120, 75, 5, -1, "The target is attacked by a kick launched with muscle-packed power.", -1, 0, 1),
new AttackMove(Moves.JUMP_KICK, "Jump Kick", Type.FIGHTING, MoveCategory.PHYSICAL, 100, 95, 10, -1, "The user jumps up high, then strikes with a kick. If the kick misses, the user hurts itself.", -1, 0, 1)
.attr(MissEffectAttr, (user: Pokemon, move: Move) => { user.damage(Math.floor(user.getMaxHp() / 2)); return true; })
.attr(MissEffectAttr, halveHpMissEffectFunc)
.condition(failOnGravityCondition),
new AttackMove(Moves.ROLLING_KICK, "Rolling Kick", Type.FIGHTING, MoveCategory.PHYSICAL, 60, 85, 15, -1, "The user lashes out with a quick, spinning kick. This may also make the target flinch.", 30, 0, 1)
.attr(FlinchAttr),
@ -2547,7 +2566,7 @@ export function initMoves() {
new SelfStatusMove(Moves.SOFT_BOILED, "Soft-Boiled", Type.NORMAL, -1, 5, -1, "The user restores its own HP by up to half of its max HP.", -1, 0, 1)
.attr(HealAttr, 0.5),
new AttackMove(Moves.HIGH_JUMP_KICK, "High Jump Kick", Type.FIGHTING, MoveCategory.PHYSICAL, 130, 90, 10, -1, "The target is attacked with a knee kick from a jump. If it misses, the user is hurt instead.", -1, 0, 1)
.attr(MissEffectAttr, (user: Pokemon, move: Move) => { user.damage(Math.floor(user.getMaxHp() / 2)); return true; })
.attr(MissEffectAttr, halveHpMissEffectFunc)
.condition(failOnGravityCondition),
new StatusMove(Moves.GLARE, "Glare", Type.NORMAL, 100, 30, -1, "The user intimidates the target with the pattern on its belly to cause paralysis.", -1, 0, 1)
.attr(StatusEffectAttr, StatusEffect.PARALYSIS),
@ -4120,7 +4139,7 @@ export function initMoves() {
new AttackMove(Moves.TERA_BLAST, "Tera Blast (P)", Type.NORMAL, MoveCategory.SPECIAL, 80, 100, 10, -1, "If the user has Terastallized, it unleashes energy of its Tera Type. This move inflicts damage using the Attack or Sp. Atk stat-whichever is higher for the user.", -1, 0, 9),
new SelfStatusMove(Moves.SILK_TRAP, "Silk Trap (N)", Type.BUG, -1, 10, -1, "The user spins a silken trap, protecting itself from damage while lowering the Speed stat of any attacker that makes direct contact.", -1, 4, 9),
new AttackMove(Moves.AXE_KICK, "Axe Kick", Type.FIGHTING, MoveCategory.PHYSICAL, 120, 90, 10, -1, "The user attacks by kicking up into the air and slamming its heel down upon the target. This may also confuse the target. If it misses, the user takes damage instead.", 30, 0, 9)
.attr(MissEffectAttr, (user: Pokemon, move: Move) => { user.damage(Math.floor(user.getMaxHp() / 2)); return true; })
.attr(MissEffectAttr, halveHpMissEffectFunc)
.attr(ConfuseAttr),
new AttackMove(Moves.LAST_RESPECTS, "Last Respects (P)", Type.GHOST, MoveCategory.PHYSICAL, 50, 100, 10, -1, "The user attacks to avenge its allies. The more defeated allies there are in the user's party, the greater the move's power.", -1, 0, 9),
new AttackMove(Moves.LUMINA_CRASH, "Lumina Crash", Type.PSYCHIC, MoveCategory.SPECIAL, 80, 100, 10, -1, "The user attacks by unleashing a peculiar light that even affects the mind. This also harshly lowers the target's Sp. Def stat.", 100, 0, 9)
@ -4250,7 +4269,7 @@ export function initMoves() {
new AttackMove(Moves.ALLURING_VOICE, "Alluring Voice (P)", Type.FAIRY, MoveCategory.SPECIAL, 80, 100, 10, -1, "The user attacks the target using its angelic voice. This also confuses the target if its stats have been boosted during the turn.", -1, 0, 9),
new AttackMove(Moves.TEMPER_FLARE, "Temper Flare (P)", Type.FIRE, MoveCategory.PHYSICAL, 75, 100, 10, -1, "Spurred by desperation, the user attacks the target. This move's power is doubled if the user's previous move failed.", -1, 0, 9),
new AttackMove(Moves.SUPERCELL_SLAM, "Supercell Slam", Type.ELECTRIC, MoveCategory.PHYSICAL, 100, 95, 15, -1, "The user electrifies its body and drops onto the target to inflict damage. If this move misses, the user takes damage instead.", -1, 0, 9)
.attr(MissEffectAttr, (user: Pokemon, move: Move) => { user.damage(Math.floor(user.getMaxHp() / 2)); return true; }),
.attr(MissEffectAttr, halveHpMissEffectFunc),
new AttackMove(Moves.PSYCHIC_NOISE, "Psychic Noise (P)", Type.PSYCHIC, MoveCategory.SPECIAL, 75, 100, 10, -1, "The user attacks the target with unpleasant sound waves. For two turns, the target is prevented from recovering HP through moves, Abilities, or held items.", -1, 0, 9)
.soundBased(),
new AttackMove(Moves.UPPER_HAND, "Upper Hand (P)", Type.FIGHTING, MoveCategory.PHYSICAL, 65, 100, 15, -1, "The user reacts to the target's movement and strikes with the heel of its palm, making the target flinch. This move fails if the target is not readying a priority move.", -1, 0, 9),

View File

@ -1,5 +1,5 @@
import { TextStyle, addTextObject } from "../ui/text";
import Pokemon, { AttackMoveResult, HitResult } from "./pokemon";
import Pokemon, { DamageResult, HitResult } from "./pokemon";
import * as Utils from "../utils";
import { BattlerIndex } from "../battle";
@ -10,17 +10,21 @@ export default class DamageNumberHandler {
this.damageNumbers = new Map();
}
add(target: Pokemon, result: AttackMoveResult): void {
add(target: Pokemon, amount: integer, result: DamageResult | HitResult.HEAL = HitResult.EFFECTIVE, critical: boolean = false): void {
const scene = target.scene;
if (!scene.damageNumbersMode)
return;
const battlerIndex = target.getBattlerIndex();
const baseScale = target.getSpriteScale() / 6;
const damageNumber = addTextObject(scene, target.x, -(scene.game.canvas.height / 6) + target.y - target.getSprite().height / 2, Utils.formatStat(result.damage, true), TextStyle.SUMMARY);
const damageNumber = addTextObject(scene, target.x, -(scene.game.canvas.height / 6) + target.y - target.getSprite().height / 2, Utils.formatStat(amount, true), TextStyle.SUMMARY);
damageNumber.setOrigin(0.5, 1);
damageNumber.setScale(baseScale);
let [ textColor, shadowColor ] = [ null, null ];
switch (result.result) {
switch (result) {
case HitResult.SUPER_EFFECTIVE:
[ textColor, shadowColor ] = [ '#f8d030', '#b8a038' ];
break;
@ -30,6 +34,9 @@ export default class DamageNumberHandler {
case HitResult.ONE_HIT_KO:
[ textColor, shadowColor ] = [ '#a040a0', '#483850' ];
break;
case HitResult.HEAL:
[ textColor, shadowColor ] = [ '#78c850', '#588040' ];
break;
default:
[ textColor, shadowColor ] = [ '#ffffff', '#636363' ];
break;
@ -38,7 +45,7 @@ export default class DamageNumberHandler {
if (textColor)
damageNumber.setColor(textColor);
if (shadowColor) {
if (result.critical) {
if (critical) {
damageNumber.setShadowOffset(0, 0);
damageNumber.setStroke(shadowColor, 12);
} else

View File

@ -1123,11 +1123,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
this.scene.applyModifiers(EnemyDamageReducerModifier, false, damage);
if (damage) {
this.scene.unshiftPhase(new DamagePhase(this.scene, this.getBattlerIndex(), result as DamageResult));
damage.value = this.damage(damage.value);
this.scene.unshiftPhase(new DamagePhase(this.scene, this.getBattlerIndex(), damage.value, result as DamageResult, isCritical));
if (isCritical)
this.scene.queueMessage('A critical hit!');
this.scene.setPhaseQueueSplice();
damage.value = this.damage(damage.value);
if (source.isPlayer()) {
this.scene.validateAchvs(DamageAchv, damage);
if (damage.value > this.scene.gameData.gameStats.highestDamage)
@ -1137,8 +1137,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
this.battleData.hitCount++;
const attackResult = { move: move.id, result: result as DamageResult, damage: damage.value, critical: isCritical, sourceId: source.id };
this.turnData.attacksReceived.unshift(attackResult);
if (damage.value && this.scene.damageNumbersMode)
this.scene.damageNumberHandler.add(this, attackResult);
if (source.isPlayer() && !this.isPlayer())
this.scene.applyModifiers(DamageMoneyRewardModifier, true, source, damage)
}
@ -2344,7 +2342,7 @@ export class EnemyPokemon extends Pokemon {
const hpThreshold = segmentSize * s;
const roundedHpThreshold = Math.round(hpThreshold);
if (this.hp >= roundedHpThreshold) {
if (this.hp - damage < roundedHpThreshold) {
if (this.hp - damage <= roundedHpThreshold) {
const hpRemainder = this.hp - roundedHpThreshold;
let segmentsBypassed = 0;
while (this.canBypassBossSegments(segmentsBypassed + 1) && (damage - hpRemainder) >= Math.round(segmentSize * Math.pow(2, segmentsBypassed + 1))) {
@ -2536,6 +2534,7 @@ export enum HitResult {
ONE_HIT_KO,
NO_EFFECT,
STATUS,
HEAL,
FAIL,
MISS,
OTHER

View File

@ -2394,9 +2394,10 @@ export class WeatherEffectPhase extends CommonAnimPhase {
if (cancelled.value)
return;
const damage = Math.ceil(pokemon.getMaxHp() / 16);
this.scene.queueMessage(getWeatherDamageMessage(this.weather.weatherType, pokemon));
this.scene.unshiftPhase(new DamagePhase(this.scene, pokemon.getBattlerIndex()));
pokemon.damage(Math.ceil(pokemon.getMaxHp() / 16));
this.scene.unshiftPhase(new DamagePhase(this.scene, pokemon.getBattlerIndex(), pokemon.damage(damage)));
};
this.executeForAll((pokemon: Pokemon) => {
@ -2458,19 +2459,22 @@ export class PostTurnStatusEffectPhase extends PokemonPhase {
const pokemon = this.getPokemon();
if (pokemon?.isActive(true) && pokemon.status && pokemon.status.isPostTurn()) {
pokemon.status.incrementTurn();
new CommonBattleAnim(CommonAnim.POISON + (pokemon.status.effect - 1), pokemon).play(this.scene, () => {
this.scene.queueMessage(getPokemonMessage(pokemon, getStatusEffectActivationText(pokemon.status.effect)));
switch (pokemon.status.effect) {
case StatusEffect.POISON:
case StatusEffect.BURN:
pokemon.damage(Math.max(pokemon.getMaxHp() >> 3, 1));
break;
case StatusEffect.TOXIC:
pokemon.damage(Math.max(Math.floor((pokemon.getMaxHp() / 16) * pokemon.status.turnCount), 1));
break;
}
pokemon.updateInfo().then(() => this.end());
});
this.scene.queueMessage(getPokemonMessage(pokemon, getStatusEffectActivationText(pokemon.status.effect)));
let damage: integer = 0;
switch (pokemon.status.effect) {
case StatusEffect.POISON:
case StatusEffect.BURN:
damage = Math.max(pokemon.getMaxHp() >> 3, 1);
break;
case StatusEffect.TOXIC:
damage = Math.max(Math.floor((pokemon.getMaxHp() / 16) * pokemon.status.turnCount), 1);
break;
}
if (damage) {
this.scene.damageNumberHandler.add(this.getPokemon(), pokemon.damage(damage));
pokemon.updateInfo();
}
new CommonBattleAnim(CommonAnim.POISON + (pokemon.status.effect - 1), pokemon).play(this.scene, () => this.end());
} else
this.end();
}
@ -2512,12 +2516,16 @@ export class MessagePhase extends Phase {
}
export class DamagePhase extends PokemonPhase {
private amount: integer;
private damageResult: DamageResult;
private critical: boolean;
constructor(scene: BattleScene, battlerIndex: BattlerIndex, damageResult?: DamageResult) {
constructor(scene: BattleScene, battlerIndex: BattlerIndex, amount: integer, damageResult?: DamageResult, critical: boolean = false) {
super(scene, battlerIndex);
this.amount = amount;
this.damageResult = damageResult || HitResult.EFFECTIVE;
this.critical = critical;
}
start() {
@ -2549,6 +2557,9 @@ export class DamagePhase extends PokemonPhase {
break;
}
if (this.amount)
this.scene.damageNumberHandler.add(this.getPokemon(), this.amount, this.damageResult, this.critical);
if (this.damageResult !== HitResult.OTHER) {
const flashTimer = this.scene.time.addEvent({
delay: 100,
@ -2685,10 +2696,15 @@ export class FaintPhase extends PokemonPhase {
case BattleSpec.FINAL_BOSS:
if (!this.player) {
const enemy = this.getPokemon();
if (enemy.formIndex) {
if (enemy.formIndex)
this.scene.ui.showDialogue(battleSpecDialogue[BattleSpec.FINAL_BOSS].secondStageWin, enemy.species.name, null, () => this.doFaint());
return true;
else {
// Final boss' HP threshold has been bypassed; cancel faint and force check for 2nd phase
enemy.hp++;
this.scene.unshiftPhase(new DamagePhase(this.scene, enemy.getBattlerIndex(), 0, HitResult.OTHER));
this.end();
}
return true;
}
}
@ -3310,6 +3326,8 @@ export class PokemonHealPhase extends CommonAnimPhase {
this.scene.applyModifiers(HealingBoosterModifier, this.player, hpRestoreMultiplier);
const healAmount = new Utils.NumberHolder(Math.floor(this.hpHealed * hpRestoreMultiplier.value));
healAmount.value = pokemon.heal(healAmount.value);
if (healAmount.value)
this.scene.damageNumberHandler.add(pokemon, healAmount.value, HitResult.HEAL);
if (pokemon.isPlayer()) {
this.scene.validateAchvs(HealAchv, healAmount);
if (healAmount.value > this.scene.gameData.gameStats.highestHeal)