Implement randomFoe and foePokemonLeft

This commit is contained in:
Guangcong Luo 2021-03-31 19:36:36 -07:00
parent e5d52bb33c
commit f6ec932e8d
7 changed files with 61 additions and 64 deletions

View File

@ -276,7 +276,7 @@ export const Abilities: {[abilityid: string]: AbilityData} = {
if (effect?.effectType !== 'Move') {
return;
}
if (source.species.id === 'greninja' && source.hp && !source.transformed && source.side.foe.pokemonLeft) {
if (source.species.id === 'greninja' && source.hp && !source.transformed && source.side.foePokemonLeft()) {
this.add('-activate', source, 'ability: Battle Bond');
source.formeChange('Greninja-Ash', this.effect, true);
}
@ -3154,19 +3154,14 @@ export const Abilities: {[abilityid: string]: AbilityData} = {
onStart(pokemon) {
let activated = false;
for (const sideCondition of ['reflect', 'lightscreen', 'auroraveil']) {
if (pokemon.side.getSideCondition(sideCondition)) {
if (!activated) {
this.add('-activate', pokemon, 'ability: Screen Cleaner');
activated = true;
for (const side of [pokemon.side, ...pokemon.side.foeSidesWithConditions()]) {
if (side.getSideCondition(sideCondition)) {
if (!activated) {
this.add('-activate', pokemon, 'ability: Screen Cleaner');
activated = true;
}
side.removeSideCondition(sideCondition);
}
pokemon.side.removeSideCondition(sideCondition);
}
if (pokemon.side.foe.getSideCondition(sideCondition)) {
if (!activated) {
this.add('-activate', pokemon, 'ability: Screen Cleaner');
activated = true;
}
pokemon.side.foe.removeSideCondition(sideCondition);
}
}
},

View File

@ -152,7 +152,7 @@ export const Abilities: {[k: string]: ModdedAbilityData} = {
inherit: true,
onUpdate(pokemon) {
if (!pokemon.isStarted) return;
const target = pokemon.side.foe.randomAlly();
const target = pokemon.side.randomFoe();
if (!target || target.fainted) return;
const ability = target.getAbility();
const bannedAbilities = ['forecast', 'multitype', 'trace'];

View File

@ -454,7 +454,7 @@ export const Abilities: {[k: string]: ModdedAbilityData} = {
inherit: true,
onUpdate(pokemon) {
if (!pokemon.isStarted) return;
const target = pokemon.side.foe.randomAlly();
const target = pokemon.side.randomFoe();
if (!target || target.fainted) return;
const ability = target.getAbility();
const bannedAbilities = ['forecast', 'multitype', 'trace'];

View File

@ -19,7 +19,7 @@ export const Abilities: {[k: string]: ModdedAbilityData} = {
frisk: {
inherit: true,
onStart(pokemon) {
const target = pokemon.side.foe.randomAlly();
const target = pokemon.side.randomFoe();
if (target?.item) {
this.add('-item', target, target.getItem().name, '[from] ability: Frisk', '[of] ' + pokemon);
}

View File

@ -4877,20 +4877,16 @@ export const Moves: {[moveid: string]: MoveData} = {
this.add('-sidestart', targetSide, 'Fire Pledge');
},
onEnd(targetSide) {
for (const pokemon of targetSide.activeTeam()) {
if (pokemon && !pokemon.hasType('Fire')) {
this.damage(pokemon.baseMaxhp / 8, pokemon);
}
for (const pokemon of targetSide.allies()) {
if (!pokemon.hasType('Fire')) this.damage(pokemon.baseMaxhp / 8, pokemon);
}
this.add('-sideend', targetSide, 'Fire Pledge');
},
onResidualOrder: 5,
onResidualSubOrder: 1,
onResidual(side) {
for (const pokemon of side.activeTeam()) {
if (pokemon && !pokemon.hasType('Fire')) {
this.damage(pokemon.baseMaxhp / 8, pokemon);
}
for (const pokemon of side.allies()) {
if (!pokemon.hasType('Fire')) this.damage(pokemon.baseMaxhp / 8, pokemon);
}
},
},
@ -5944,15 +5940,10 @@ export const Moves: {[moveid: string]: MoveData} = {
priority: 0,
flags: {snatch: 1, authentic: 1},
onHitSide(side, source, move) {
const targets = [];
for (const pokemon of side.activeTeam()) {
if (
pokemon.hasAbility(['plus', 'minus']) &&
(!pokemon.volatiles['maxguard'] || this.runEvent('TryHit', pokemon, source, move))
) {
targets.push(pokemon);
}
}
const targets = side.allies().filter(target => (
target.hasAbility(['plus', 'minus']) &&
(!target.volatiles['maxguard'] || this.runEvent('TryHit', target, source, move))
));
if (!targets.length) return false;
let didSomething = false;
for (const target of targets) {
@ -6187,13 +6178,13 @@ export const Moves: {[moveid: string]: MoveData} = {
onResidualOrder: 5,
onResidualSubOrder: 1.1,
onResidual(targetSide) {
for (const pokemon of targetSide.activeTeam()) {
if (!pokemon.hasType('Water')) this.damage(pokemon.baseMaxhp / 6, pokemon);
for (const target of targetSide.allies()) {
if (!target.hasType('Water')) this.damage(target.baseMaxhp / 6, target);
}
},
onEnd(targetSide) {
for (const pokemon of targetSide.activeTeam()) {
if (!pokemon.hasType('Water')) this.damage(pokemon.baseMaxhp / 6, pokemon);
for (const target of targetSide.allies()) {
if (!target.hasType('Water')) this.damage(target.baseMaxhp / 6, target);
}
this.add('-sideend', targetSide, 'G-Max Cannonade');
},
@ -6839,13 +6830,13 @@ export const Moves: {[moveid: string]: MoveData} = {
onResidualOrder: 5,
onResidualSubOrder: 1.1,
onResidual(targetSide) {
for (const pokemon of targetSide.activeTeam()) {
if (!pokemon.hasType('Grass')) this.damage(pokemon.baseMaxhp / 6, pokemon);
for (const target of targetSide.allies()) {
if (!target.hasType('Grass')) this.damage(target.baseMaxhp / 6, target);
}
},
onEnd(targetSide) {
for (const pokemon of targetSide.activeTeam()) {
if (!pokemon.hasType('Grass')) this.damage(pokemon.baseMaxhp / 6, pokemon);
for (const target of targetSide.allies()) {
if (!target.hasType('Grass')) this.damage(target.baseMaxhp / 6, target);
}
this.add('-sideend', targetSide, 'G-Max Vine Lash');
},
@ -6879,13 +6870,13 @@ export const Moves: {[moveid: string]: MoveData} = {
onResidualOrder: 5,
onResidualSubOrder: 1.1,
onResidual(targetSide) {
for (const pokemon of targetSide.activeTeam()) {
if (!pokemon.hasType('Rock')) this.damage(pokemon.baseMaxhp / 6, pokemon);
for (const target of targetSide.allies()) {
if (!target.hasType('Rock')) this.damage(target.baseMaxhp / 6, target);
}
},
onEnd(targetSide) {
for (const pokemon of targetSide.activeTeam()) {
if (!pokemon.hasType('Rock')) this.damage(pokemon.baseMaxhp / 6, pokemon);
for (const target of targetSide.allies()) {
if (!target.hasType('Rock')) this.damage(target.baseMaxhp / 6, target);
}
this.add('-sideend', targetSide, 'G-Max Volcalith');
},
@ -6942,13 +6933,13 @@ export const Moves: {[moveid: string]: MoveData} = {
onResidualOrder: 5,
onResidualSubOrder: 1.1,
onResidual(targetSide) {
for (const pokemon of targetSide.activeTeam()) {
if (!pokemon.hasType('Fire')) this.damage(pokemon.baseMaxhp / 6, pokemon);
for (const target of targetSide.allies()) {
if (!target.hasType('Fire')) this.damage(target.baseMaxhp / 6, target);
}
},
onEnd(targetSide) {
for (const pokemon of targetSide.activeTeam()) {
if (!pokemon.hasType('Fire')) this.damage(pokemon.baseMaxhp / 6, pokemon);
for (const target of targetSide.allies()) {
if (!target.hasType('Fire')) this.damage(target.baseMaxhp / 6, target);
}
this.add('-sideend', targetSide, 'G-Max Wildfire');
},
@ -10106,16 +10097,12 @@ export const Moves: {[moveid: string]: MoveData} = {
priority: 0,
flags: {snatch: 1, distance: 1, authentic: 1},
onHitSide(side, source, move) {
const targets = [];
for (const pokemon of side.activeTeam()) {
if (
pokemon.hasAbility(['plus', 'minus']) &&
(!pokemon.volatiles['maxguard'] || this.runEvent('TryHit', pokemon, source, move))
) {
targets.push(pokemon);
}
}
const targets = side.allies().filter(ally => (
ally.hasAbility(['plus', 'minus']) &&
(!ally.volatiles['maxguard'] || this.runEvent('TryHit', ally, source, move))
));
if (!targets.length) return false;
let didSomething = false;
for (const target of targets) {
didSomething = this.boost({def: 1, spd: 1}, target, source, move, false, true) || didSomething;

View File

@ -1414,7 +1414,7 @@ export class Battle {
if (this.maybeTriggerEndlessBattleClause(trappedBySide, stalenessBySide)) return;
if (this.gameType === 'triples' && !this.sides.filter(side => side.pokemonLeft > 1).length) {
if (this.gameType === 'triples' && this.sides.every(side => side.pokemonLeft === 1)) {
// If both sides have one Pokemon left in triples and they are not adjacent, they are both moved to the center.
const actives = this.getAllActive();
if (actives.length > 1 && !actives[0].isAdjacent(actives[1])) {
@ -1594,7 +1594,7 @@ export class Battle {
}
if (!target?.hp) return 0;
if (!target.isActive) return false;
if (this.gen > 5 && !target.side.foe.pokemonLeft) return false;
if (this.gen > 5 && !target.side.foePokemonLeft()) return false;
boost = this.runEvent('Boost', target, source, effect, {...boost});
let success = null;
let boosted = isSecondary;
@ -2062,7 +2062,7 @@ export class Battle {
return foeActives[frontPosition];
}
}
return pokemon.side.foe.randomAlly() || pokemon.side.foe.active[0];
return pokemon.side.randomFoe() || pokemon.side.foe.active[0];
}
checkFainted() {

View File

@ -204,12 +204,27 @@ export class Side {
return data;
}
randomAlly() {
const actives = this.allies();
randomFoe() {
const actives = this.foes();
if (!actives.length) return null;
return this.battle.sample(actives);
}
/** Intended as a way to iterate through all foe side conditions - do not use for anything else. */
foeSidesWithConditions() {
if (this.battle.gameType === 'multi') return this.battle.sides.filter(side => side !== this);
return [this.foe];
}
foePokemonLeft() {
if (this.battle.gameType === 'multi') {
return this.battle.sides.filter(side => side !== this).map(side => side.pokemonLeft).reduce((a, b) => a + b);
}
if (this.foe.allySide) return this.foe.pokemonLeft + this.foe.allySide.pokemonLeft;
return this.foe.pokemonLeft;
}
allies() {
// called during the first switch-in, so `active` can still contain nulls at this point
return this.activeTeam().filter(ally => ally && !ally.fainted);
@ -217,7 +232,7 @@ export class Side {
foes() {
if (this.battle.gameType === 'free-for-all') {
return this.battle.sides.map(side => side.active[0])
.filter(pokemon => pokemon.side !== this && pokemon && !pokemon.fainted);
.filter(pokemon => pokemon && pokemon.side !== this && !pokemon.fainted);
}
return this.foe.allies();
}