mirror of
https://github.com/smogon/pokemon-showdown.git
synced 2026-03-21 17:25:10 -05:00
Properly implement Chloroblast recoil (#9648)
This commit is contained in:
parent
d947b82322
commit
e218cb9dbb
|
|
@ -302,7 +302,7 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
}
|
||||
|
||||
if (move.recoil && move.totalDamage) {
|
||||
this.battle.damage(this.calcRecoilDamage(move.totalDamage, move), pokemon, target, 'recoil');
|
||||
this.battle.damage(this.calcRecoilDamage(move.totalDamage, move, pokemon), pokemon, target, 'recoil');
|
||||
}
|
||||
return damage;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
// If a pokemon caused the other to faint with a recoil move and only one pokemon remains on both sides,
|
||||
// recoil damage will not be taken.
|
||||
if (move.recoil && move.totalDamage && (pokemon.side.pokemonLeft > 1 || target.side.pokemonLeft > 1 || target.hp)) {
|
||||
this.battle.damage(this.calcRecoilDamage(move.totalDamage, move), pokemon, target, 'recoil');
|
||||
this.battle.damage(this.calcRecoilDamage(move.totalDamage, move, pokemon), pokemon, target, 'recoil');
|
||||
}
|
||||
return damage;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -451,7 +451,7 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
}
|
||||
|
||||
if (move.recoil && move.totalDamage) {
|
||||
this.battle.damage(this.calcRecoilDamage(move.totalDamage, move), pokemon, target, 'recoil');
|
||||
this.battle.damage(this.calcRecoilDamage(move.totalDamage, move, pokemon), pokemon, target, 'recoil');
|
||||
}
|
||||
|
||||
if (target && pokemon !== target) target.gotAttacked(move, damage, pokemon);
|
||||
|
|
|
|||
|
|
@ -1513,7 +1513,7 @@ export const Moves: {[k: string]: ModdedMoveData} = {
|
|||
this.add('-activate', target, 'Substitute', '[damage]');
|
||||
}
|
||||
if (move.recoil && damage) {
|
||||
this.damage(this.actions.calcRecoilDamage(damage, move), source, target, 'recoil');
|
||||
this.damage(this.actions.calcRecoilDamage(damage, move, source), source, target, 'recoil');
|
||||
}
|
||||
if (move.drain) {
|
||||
this.heal(Math.ceil(damage * move.drain[0] / move.drain[1]), source, target, 'drain');
|
||||
|
|
|
|||
|
|
@ -890,7 +890,7 @@ export const Moves: {[k: string]: ModdedMoveData} = {
|
|||
this.add('-activate', target, 'Substitute', '[damage]');
|
||||
}
|
||||
if (move.recoil && damage) {
|
||||
this.damage(this.actions.calcRecoilDamage(damage, move), source, target, 'recoil');
|
||||
this.damage(this.actions.calcRecoilDamage(damage, move, source), source, target, 'recoil');
|
||||
}
|
||||
if (move.drain) {
|
||||
this.heal(Math.ceil(damage * move.drain[0] / move.drain[1]), source, target, 'drain');
|
||||
|
|
|
|||
|
|
@ -527,7 +527,7 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
}
|
||||
|
||||
if (move.recoil && move.totalDamage) {
|
||||
this.battle.damage(this.calcRecoilDamage(move.totalDamage, move), pokemon, pokemon, 'recoil');
|
||||
this.battle.damage(this.calcRecoilDamage(move.totalDamage, move, pokemon), pokemon, pokemon, 'recoil');
|
||||
}
|
||||
|
||||
if (move.struggleRecoil) {
|
||||
|
|
|
|||
|
|
@ -2396,16 +2396,7 @@ export const Moves: {[moveid: string]: MoveData} = {
|
|||
pp: 5,
|
||||
priority: 0,
|
||||
flags: {protect: 1, mirror: 1},
|
||||
mindBlownRecoil: true,
|
||||
onAfterMove(pokemon, target, move) {
|
||||
if (move.mindBlownRecoil && !move.multihit) {
|
||||
const hpBeforeRecoil = pokemon.hp;
|
||||
this.damage(Math.round(pokemon.maxhp / 2), pokemon, pokemon, this.dex.conditions.get('Chloroblast'), true);
|
||||
if (pokemon.hp <= pokemon.maxhp / 2 && hpBeforeRecoil > pokemon.maxhp / 2) {
|
||||
this.runEvent('EmergencyExit', pokemon, pokemon);
|
||||
}
|
||||
}
|
||||
},
|
||||
// Recoil implemented in battle-actions.ts
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
type: "Grass",
|
||||
|
|
@ -18788,8 +18779,8 @@ export const Moves: {[moveid: string]: MoveData} = {
|
|||
} else {
|
||||
this.add('-activate', target, 'move: Substitute', '[damage]');
|
||||
}
|
||||
if (move.recoil) {
|
||||
this.damage(this.actions.calcRecoilDamage(damage, move), source, target, 'recoil');
|
||||
if (move.recoil || move.id === 'chloroblast') {
|
||||
this.damage(this.actions.calcRecoilDamage(damage, move, source), source, target, 'recoil');
|
||||
}
|
||||
if (move.drain) {
|
||||
this.heal(Math.ceil(damage * move.drain[0] / move.drain[1]), source, target, 'drain');
|
||||
|
|
|
|||
|
|
@ -945,9 +945,9 @@ export class BattleActions {
|
|||
this.battle.add('-hitcount', targets[0], hit - 1);
|
||||
}
|
||||
|
||||
if (move.recoil && move.totalDamage) {
|
||||
if ((move.recoil || move.id === 'chloroblast') && move.totalDamage) {
|
||||
const hpBeforeRecoil = pokemon.hp;
|
||||
this.battle.damage(this.calcRecoilDamage(move.totalDamage, move), pokemon, pokemon, 'recoil');
|
||||
this.battle.damage(this.calcRecoilDamage(move.totalDamage, move, pokemon), pokemon, pokemon, 'recoil');
|
||||
if (pokemon.hp <= pokemon.maxhp / 2 && hpBeforeRecoil > pokemon.maxhp / 2) {
|
||||
this.battle.runEvent('EmergencyExit', pokemon, pokemon);
|
||||
}
|
||||
|
|
@ -1359,7 +1359,8 @@ export class BattleActions {
|
|||
return retVal === true ? undefined : retVal;
|
||||
}
|
||||
|
||||
calcRecoilDamage(damageDealt: number, move: Move): number {
|
||||
calcRecoilDamage(damageDealt: number, move: Move, pokemon: Pokemon): number {
|
||||
if (move.id === 'chloroblast') return Math.round(pokemon.maxhp / 2);
|
||||
return this.battle.clampIntRange(Math.round(damageDealt * move.recoil![0] / move.recoil![1]), 1);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -214,7 +214,7 @@ interface BattleScriptsData {
|
|||
interface ModdedBattleActions {
|
||||
inherit?: true;
|
||||
afterMoveSecondaryEvent?: (this: BattleActions, targets: Pokemon[], pokemon: Pokemon, move: ActiveMove) => undefined;
|
||||
calcRecoilDamage?: (this: BattleActions, damageDealt: number, move: Move) => number;
|
||||
calcRecoilDamage?: (this: BattleActions, damageDealt: number, move: Move, pokemon: Pokemon) => number;
|
||||
canMegaEvo?: (this: BattleActions, pokemon: Pokemon) => string | undefined | null;
|
||||
canUltraBurst?: (this: BattleActions, pokemon: Pokemon) => string | null;
|
||||
canZMove?: (this: BattleActions, pokemon: Pokemon) => ZMoveOptions | void;
|
||||
|
|
|
|||
54
test/sim/moves/chloroblast.js
Normal file
54
test/sim/moves/chloroblast.js
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
'use strict';
|
||||
|
||||
const assert = require('./../../assert');
|
||||
const common = require('./../../common');
|
||||
|
||||
let battle;
|
||||
|
||||
describe('Chloroblast', function () {
|
||||
afterEach(function () {
|
||||
battle.destroy();
|
||||
});
|
||||
|
||||
it('should deal recoil damage to the user equal to half its max HP, rounded up', function () {
|
||||
battle = common.createBattle([[
|
||||
{species: "Electrode-Hisui", item: 'widelens', moves: ['chloroblast']},
|
||||
], [
|
||||
{species: "Blissey", moves: ['sleeptalk']},
|
||||
]]);
|
||||
assert.hurtsBy(battle.p1.active[0], Math.round(battle.p1.active[0].maxhp / 2), () => battle.makeChoices());
|
||||
});
|
||||
|
||||
it('should not deal recoil damage to the user if it misses or is blocked by Protect', function () {
|
||||
battle = common.createBattle([[
|
||||
{species: "Electrode-Hisui", item: 'widelens', moves: ['chloroblast', 'protect']},
|
||||
], [
|
||||
{species: "Talonflame", ability: 'galewings', moves: ['fly', 'protect']},
|
||||
]]);
|
||||
battle.makeChoices('move chloroblast', 'move fly');
|
||||
battle.makeChoices('move protect', 'auto');
|
||||
battle.makeChoices('move chloroblast', 'move protect');
|
||||
assert.fullHP(battle.p1.active[0]);
|
||||
});
|
||||
|
||||
it('should have its recoil damage negated by Rock Head', function () {
|
||||
battle = common.createBattle([[
|
||||
{species: "Electrode-Hisui", ability: 'rockhead', item: 'widelens', moves: ['chloroblast']},
|
||||
], [
|
||||
{species: "Blissey", moves: ['sleeptalk']},
|
||||
]]);
|
||||
battle.makeChoices();
|
||||
assert.fullHP(battle.p1.active[0]);
|
||||
});
|
||||
|
||||
it('should not have its base power boosted by Reckless', function () {
|
||||
battle = common.createBattle([[
|
||||
{species: "Electrode-Hisui", ability: 'reckless', item: 'widelens', moves: ['chloroblast']},
|
||||
], [
|
||||
{species: "Blissey", ability: 'shellarmor', moves: ['sleeptalk']},
|
||||
]]);
|
||||
battle.makeChoices();
|
||||
const damage = battle.p2.active[0].maxhp - battle.p2.active[0].hp;
|
||||
assert.bounded(damage, [103, 123]);
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user