Add redirection logic to Lightning Rod and Storm Drain
parent
60c3c0a008
commit
71e820f149
|
@ -711,13 +711,15 @@ export default class BattleScene extends Phaser.Scene {
|
|||
return party.slice(0, Math.min(party.length, this.currentBattle?.double ? 2 : 1));
|
||||
}
|
||||
|
||||
getField(): Pokemon[] {
|
||||
getField(activeOnly: boolean = false): Pokemon[] {
|
||||
const ret = new Array(4).fill(null);
|
||||
const playerField = this.getPlayerField();
|
||||
const enemyField = this.getEnemyField();
|
||||
ret.splice(0, playerField.length, ...playerField);
|
||||
ret.splice(2, enemyField.length, ...enemyField);
|
||||
return ret;
|
||||
return activeOnly
|
||||
? ret.filter(p => p?.isActive())
|
||||
: ret;
|
||||
}
|
||||
|
||||
getPokemonById(pokemonId: integer): Pokemon {
|
||||
|
@ -935,7 +937,7 @@ export default class BattleScene extends Phaser.Scene {
|
|||
|
||||
updateFieldScale(): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
const fieldScale = Math.floor(Math.pow(1 / this.getField().filter(p => p?.isActive())
|
||||
const fieldScale = Math.floor(Math.pow(1 / this.getField(true)
|
||||
.map(p => p.getSpriteScale())
|
||||
.reduce((highestScale: number, scale: number) => highestScale = Math.max(scale, highestScale), 0), 0.7) * 40
|
||||
) / 40;
|
||||
|
|
|
@ -8,7 +8,7 @@ import { Weather, WeatherType } from "./weather";
|
|||
import { BattlerTag } from "./battler-tags";
|
||||
import { BattlerTagType } from "./enums/battler-tag-type";
|
||||
import { StatusEffect, getStatusEffectDescriptor } from "./status-effect";
|
||||
import Move, { AttackMove, MoveCategory, MoveFlags, RecoilAttr, StatusMoveTypeImmunityAttr } from "./move";
|
||||
import Move, { AttackMove, MoveCategory, MoveFlags, MoveTarget, RecoilAttr, StatusMoveTypeImmunityAttr, allMoves } from "./move";
|
||||
import { ArenaTagType } from "./enums/arena-tag-type";
|
||||
import { Stat } from "./pokemon-stat";
|
||||
import { PokemonHeldItemModifier } from "../modifier/modifier";
|
||||
|
@ -1062,6 +1062,39 @@ export class PostBattleLootAbAttr extends PostBattleAbAttr {
|
|||
}
|
||||
}
|
||||
|
||||
export class RedirectMoveAbAttr extends AbAttr {
|
||||
apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
if (this.canRedirect(args[0] as Moves)) {
|
||||
const target = args[1] as Utils.IntegerHolder;
|
||||
const newTarget = pokemon.getBattlerIndex();
|
||||
if (target.value !== newTarget) {
|
||||
target.value = newTarget;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
canRedirect(moveId: Moves): boolean {
|
||||
const move = allMoves[moveId];
|
||||
return !![ MoveTarget.NEAR_OTHER, MoveTarget.OTHER ].find(t => move.moveTarget === t);
|
||||
}
|
||||
}
|
||||
|
||||
export class RedirectTypeMoveAbAttr extends RedirectMoveAbAttr {
|
||||
public type: Type;
|
||||
|
||||
constructor(type: Type) {
|
||||
super();
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
canRedirect(moveId: Moves): boolean {
|
||||
return super.canRedirect(moveId) && allMoves[moveId].type === this.type;
|
||||
}
|
||||
}
|
||||
|
||||
export class ReduceStatusEffectDurationAbAttr extends AbAttr {
|
||||
private statusEffect: StatusEffect;
|
||||
|
||||
|
@ -1681,6 +1714,7 @@ export function initAbilities() {
|
|||
new Ability(Abilities.NATURAL_CURE, "Natural Cure", "All status conditions heal when the Pokémon switches out.", 3)
|
||||
.attr(PreSwitchOutResetStatusAbAttr),
|
||||
new Ability(Abilities.LIGHTNING_ROD, "Lightning Rod", "The Pokémon draws in all Electric-type moves. Instead of being hit by Electric-type moves, it boosts its Sp. Atk.", 3)
|
||||
.attr(RedirectTypeMoveAbAttr, Type.ELECTRIC)
|
||||
.attr(TypeImmunityStatChangeAbAttr, Type.ELECTRIC, BattleStat.SPATK, 1),
|
||||
new Ability(Abilities.SERENE_GRACE, "Serene Grace (N)", "Boosts the likelihood of additional effects occurring when attacking.", 3),
|
||||
new Ability(Abilities.SWIFT_SWIM, "Swift Swim", "Boosts the Pokémon's Speed stat in rain.", 3)
|
||||
|
@ -1831,6 +1865,7 @@ export function initAbilities() {
|
|||
.attr(PostSummonAddBattlerTagAbAttr, BattlerTagType.SLOW_START, 5),
|
||||
new Ability(Abilities.SCRAPPY, "Scrappy (N)", "The Pokémon can hit Ghost-type Pokémon with Normal- and Fighting-type moves.", 4),
|
||||
new Ability(Abilities.STORM_DRAIN, "Storm Drain", "Draws in all Water-type moves. Instead of being hit by Water-type moves, it boosts its Sp. Atk.", 4)
|
||||
.attr(RedirectTypeMoveAbAttr, Type.WATER)
|
||||
.attr(TypeImmunityStatChangeAbAttr, Type.WATER, BattleStat.SPATK, 1),
|
||||
new Ability(Abilities.ICE_BODY, "Ice Body", "The Pokémon gradually regains HP in a hailstorm.", 4)
|
||||
.attr(PostWeatherLapseHealAbAttr, 1, WeatherType.HAIL),
|
||||
|
|
|
@ -101,7 +101,7 @@ export class Weather {
|
|||
}
|
||||
|
||||
isEffectSuppressed(scene: BattleScene): boolean {
|
||||
const field = scene.getField().filter(p => p);
|
||||
const field = scene.getField(true);
|
||||
|
||||
for (let pokemon of field) {
|
||||
const suppressWeatherEffectAbAttr = pokemon.getAbility().getAttrs(SuppressWeatherEffectAbAttr).find(() => true) as SuppressWeatherEffectAbAttr;
|
||||
|
|
|
@ -2303,7 +2303,7 @@ export class EnemyPokemon extends Pokemon {
|
|||
|
||||
getNextTargets(moveId: Moves): BattlerIndex[] {
|
||||
const moveTargets = getMoveTargets(this, moveId);
|
||||
const targets = this.scene.getField().filter(p => p?.isActive(true) && moveTargets.targets.indexOf(p.getBattlerIndex()) > -1);
|
||||
const targets = this.scene.getField(true).filter(p => moveTargets.targets.indexOf(p.getBattlerIndex()) > -1);
|
||||
if (moveTargets.multiple)
|
||||
return targets.map(p => p.getBattlerIndex());
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ import { Weather, WeatherType, getRandomWeatherType, getWeatherDamageMessage, ge
|
|||
import { TempBattleStat } from "./data/temp-battle-stat";
|
||||
import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag";
|
||||
import { ArenaTagType } from "./data/enums/arena-tag-type";
|
||||
import { Abilities, CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs } from "./data/ability";
|
||||
import { Abilities, CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs } from "./data/ability";
|
||||
import { Unlockables, getUnlockableName } from "./system/unlockables";
|
||||
import { getBiomeKey } from "./field/arena";
|
||||
import { BattleType, BattlerIndex, TurnCommand } from "./battle";
|
||||
|
@ -369,7 +369,7 @@ export abstract class FieldPhase extends BattlePhase {
|
|||
}
|
||||
|
||||
executeForAll(func: PokemonFunc): void {
|
||||
const field = this.scene.getField().filter(p => p?.summonData && p.isActive());
|
||||
const field = this.scene.getField(true).filter(p => p.summonData);
|
||||
field.forEach(pokemon => func(pokemon));
|
||||
}
|
||||
}
|
||||
|
@ -1867,6 +1867,15 @@ export class MovePhase extends BattlePhase {
|
|||
return this.end();
|
||||
}
|
||||
|
||||
// Move redirection abilities (ie. Storm Drain) only support single target moves
|
||||
const moveTarget = this.targets.length === 1
|
||||
? new Utils.IntegerHolder(this.targets[0])
|
||||
: null;
|
||||
if (moveTarget) {
|
||||
this.scene.getField(true).forEach(p => applyAbAttrs(RedirectMoveAbAttr, p, null, this.move.moveId, moveTarget));
|
||||
this.targets[0] = moveTarget.value;
|
||||
}
|
||||
|
||||
if (this.targets.length === 1 && this.targets[0] === BattlerIndex.ATTACKER) {
|
||||
if (this.pokemon.turnData.attacksReceived.length) {
|
||||
const attacker = this.pokemon.turnData.attacksReceived.length ? this.pokemon.scene.getPokemonById(this.pokemon.turnData.attacksReceived[0].sourceId) : null;
|
||||
|
@ -1880,8 +1889,8 @@ export class MovePhase extends BattlePhase {
|
|||
}
|
||||
}
|
||||
|
||||
const targets = this.scene.getField().filter(p => {
|
||||
if (p?.isActive(true) && this.targets.indexOf(p.getBattlerIndex()) > -1) {
|
||||
const targets = this.scene.getField(true).filter(p => {
|
||||
if (this.targets.indexOf(p.getBattlerIndex()) > -1) {
|
||||
const hiddenTag = p.getTag(HiddenTag);
|
||||
if (hiddenTag && !this.move.getMove().getAttrs(HitsTagAttr).filter(hta => (hta as HitsTagAttr).tagType === hiddenTag.tagType).length)
|
||||
return false;
|
||||
|
@ -2197,7 +2206,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||
}
|
||||
|
||||
getTargets(): Pokemon[] {
|
||||
return this.scene.getField().filter(p => p?.isActive(true) && this.targets.indexOf(p.getBattlerIndex()) > -1);
|
||||
return this.scene.getField(true).filter(p => this.targets.indexOf(p.getBattlerIndex()) > -1);
|
||||
}
|
||||
|
||||
getTarget(): Pokemon {
|
||||
|
@ -2690,7 +2699,7 @@ export class FaintPhase extends PokemonPhase {
|
|||
}
|
||||
|
||||
pokemon.lapseTags(BattlerTagLapseType.FAINT);
|
||||
this.scene.getField().filter(p => p !== pokemon && p?.isActive(true)).forEach(p => p.removeTagsBySourceId(pokemon.id));
|
||||
this.scene.getField(true).filter(p => p !== pokemon).forEach(p => p.removeTagsBySourceId(pokemon.id));
|
||||
|
||||
pokemon.faintCry(() => {
|
||||
const friendshipDecrease = new Utils.IntegerHolder(10);
|
||||
|
|
Loading…
Reference in New Issue