mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-04 15:32:18 +02:00
Merge branch 'pagefaultgames:main' into main
This commit is contained in:
commit
cd135fef83
@ -55,6 +55,9 @@ Check out our [Trello Board](https://trello.com/b/z10B703R/pokerogue-board) to s
|
|||||||
- GAMEFREAK
|
- GAMEFREAK
|
||||||
- LJ Birdman
|
- LJ Birdman
|
||||||
|
|
||||||
|
### 🎨 Pagefault Games Intro
|
||||||
|
- Spectremint
|
||||||
|
|
||||||
### 🎨 Game Logo
|
### 🎨 Game Logo
|
||||||
- Gonstar (Paid Commission)
|
- Gonstar (Paid Commission)
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "pokemon-rogue-battle",
|
"name": "pokemon-rogue-battle",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "vite",
|
"start": "vite",
|
||||||
|
2477
public/battle-anims/common-snow.json
Normal file
2477
public/battle-anims/common-snow.json
Normal file
File diff suppressed because it is too large
Load Diff
BIN
public/images/intro_dark.mp4
Normal file
BIN
public/images/intro_dark.mp4
Normal file
Binary file not shown.
@ -128,6 +128,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
public moveAnimations: boolean = true;
|
public moveAnimations: boolean = true;
|
||||||
public hpBarSpeed: integer = 0;
|
public hpBarSpeed: integer = 0;
|
||||||
public fusionPaletteSwaps: boolean = true;
|
public fusionPaletteSwaps: boolean = true;
|
||||||
|
public gamepadSupport: boolean = true;
|
||||||
public enableTouchControls: boolean = false;
|
public enableTouchControls: boolean = false;
|
||||||
public enableVibration: boolean = false;
|
public enableVibration: boolean = false;
|
||||||
|
|
||||||
@ -198,6 +199,26 @@ export default class BattleScene extends SceneBase {
|
|||||||
// (i.e. by holding down a button) at a time
|
// (i.e. by holding down a button) at a time
|
||||||
private movementButtonLock: Button;
|
private movementButtonLock: Button;
|
||||||
|
|
||||||
|
// using a dualshock controller as a map
|
||||||
|
private gamepadKeyConfig = {
|
||||||
|
[Button.UP]: 12, // up
|
||||||
|
[Button.DOWN]: 13, // down
|
||||||
|
[Button.LEFT]: 14, // left
|
||||||
|
[Button.RIGHT]: 15, // right
|
||||||
|
[Button.SUBMIT]: 17, // touchpad
|
||||||
|
[Button.ACTION]: 0, // X
|
||||||
|
[Button.CANCEL]: 1, // O
|
||||||
|
[Button.MENU]: 9, // options
|
||||||
|
[Button.CYCLE_SHINY]: 5, // RB
|
||||||
|
[Button.CYCLE_FORM]: 4, // LB
|
||||||
|
[Button.CYCLE_GENDER]: 6, // LT
|
||||||
|
[Button.CYCLE_ABILITY]: 7, // RT
|
||||||
|
[Button.CYCLE_NATURE]: 2, // square
|
||||||
|
[Button.SPEED_UP]: 10, // L3
|
||||||
|
[Button.SLOW_DOWN]: 11 // R3
|
||||||
|
};
|
||||||
|
public gamepadButtonStates: boolean[] = new Array(17).fill(false);
|
||||||
|
|
||||||
public rngCounter: integer = 0;
|
public rngCounter: integer = 0;
|
||||||
public rngSeedOverride: string = '';
|
public rngSeedOverride: string = '';
|
||||||
public rngOffset: integer = 0;
|
public rngOffset: integer = 0;
|
||||||
@ -936,6 +957,8 @@ export default class BattleScene extends SceneBase {
|
|||||||
case Species.TATSUGIRI:
|
case Species.TATSUGIRI:
|
||||||
case Species.PALDEA_TAUROS:
|
case Species.PALDEA_TAUROS:
|
||||||
return Utils.randSeedInt(species.forms.length);
|
return Utils.randSeedInt(species.forms.length);
|
||||||
|
case Species.MINIOR:
|
||||||
|
return Utils.randSeedInt(6);
|
||||||
case Species.MEOWSTIC:
|
case Species.MEOWSTIC:
|
||||||
case Species.INDEEDEE:
|
case Species.INDEEDEE:
|
||||||
case Species.BASCULEGION:
|
case Species.BASCULEGION:
|
||||||
@ -1243,14 +1266,19 @@ export default class BattleScene extends SceneBase {
|
|||||||
} else if (this.ui?.getHandler() instanceof StarterSelectUiHandler) {
|
} else if (this.ui?.getHandler() instanceof StarterSelectUiHandler) {
|
||||||
if (this.buttonJustPressed(Button.CYCLE_SHINY)) {
|
if (this.buttonJustPressed(Button.CYCLE_SHINY)) {
|
||||||
inputSuccess = this.ui.processInput(Button.CYCLE_SHINY);
|
inputSuccess = this.ui.processInput(Button.CYCLE_SHINY);
|
||||||
|
this.setLastProcessedMovementTime(Button.CYCLE_SHINY);
|
||||||
} else if (this.buttonJustPressed(Button.CYCLE_FORM)) {
|
} else if (this.buttonJustPressed(Button.CYCLE_FORM)) {
|
||||||
inputSuccess = this.ui.processInput(Button.CYCLE_FORM);
|
inputSuccess = this.ui.processInput(Button.CYCLE_FORM);
|
||||||
|
this.setLastProcessedMovementTime(Button.CYCLE_FORM);
|
||||||
} else if (this.buttonJustPressed(Button.CYCLE_GENDER)) {
|
} else if (this.buttonJustPressed(Button.CYCLE_GENDER)) {
|
||||||
inputSuccess = this.ui.processInput(Button.CYCLE_GENDER);
|
inputSuccess = this.ui.processInput(Button.CYCLE_GENDER);
|
||||||
|
this.setLastProcessedMovementTime(Button.CYCLE_GENDER);
|
||||||
} else if (this.buttonJustPressed(Button.CYCLE_ABILITY)) {
|
} else if (this.buttonJustPressed(Button.CYCLE_ABILITY)) {
|
||||||
inputSuccess = this.ui.processInput(Button.CYCLE_ABILITY);
|
inputSuccess = this.ui.processInput(Button.CYCLE_ABILITY);
|
||||||
|
this.setLastProcessedMovementTime(Button.CYCLE_ABILITY);
|
||||||
} else if (this.buttonJustPressed(Button.CYCLE_NATURE)) {
|
} else if (this.buttonJustPressed(Button.CYCLE_NATURE)) {
|
||||||
inputSuccess = this.ui.processInput(Button.CYCLE_NATURE);
|
inputSuccess = this.ui.processInput(Button.CYCLE_NATURE);
|
||||||
|
this.setLastProcessedMovementTime(Button.CYCLE_NATURE);
|
||||||
} else
|
} else
|
||||||
return;
|
return;
|
||||||
} else if (this.buttonJustPressed(Button.SPEED_UP)) {
|
} else if (this.buttonJustPressed(Button.SPEED_UP)) {
|
||||||
@ -1271,8 +1299,29 @@ export default class BattleScene extends SceneBase {
|
|||||||
navigator.vibrate(vibrationLength || 10);
|
navigator.vibrate(vibrationLength || 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gamepadButtonJustDown returns true if @param button has just been pressed down
|
||||||
|
* or not. It will only return true once, until the key is released and pressed down
|
||||||
|
* again.
|
||||||
|
*/
|
||||||
|
gamepadButtonJustDown(button: Phaser.Input.Gamepad.Button) : boolean {
|
||||||
|
if (!button || !this.gamepadSupport)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
let ret = false;
|
||||||
|
if (button.pressed) {
|
||||||
|
if (!this.gamepadButtonStates[button.index])
|
||||||
|
ret = true;
|
||||||
|
this.gamepadButtonStates[button.index] = true;
|
||||||
|
} else
|
||||||
|
this.gamepadButtonStates[button.index] = false;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
buttonJustPressed(button: Button): boolean {
|
buttonJustPressed(button: Button): boolean {
|
||||||
return this.buttonKeys[button].some(k => Phaser.Input.Keyboard.JustDown(k));
|
const gamepad = this.input.gamepad?.gamepads[0];
|
||||||
|
return this.buttonKeys[button].some(k => Phaser.Input.Keyboard.JustDown(k)) || this.gamepadButtonJustDown(gamepad?.buttons[this.gamepadKeyConfig[button]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1284,7 +1333,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
if (this.movementButtonLock !== null && this.movementButtonLock !== button) {
|
if (this.movementButtonLock !== null && this.movementButtonLock !== button) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (this.buttonKeys[button].every(k => k.isUp)) {
|
if (this.buttonKeys[button].every(k => k.isUp) && this.gamepadButtonStates.every(b => b == false)) {
|
||||||
this.movementButtonLock = null;
|
this.movementButtonLock = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1935,4 +1984,4 @@ export default class BattleScene extends SceneBase {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -386,6 +386,20 @@ export class PostDefendAbAttr extends AbAttr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class FieldPriorityMoveImmunityAbAttr extends PreDefendAbAttr {
|
||||||
|
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||||
|
const attackPriority = new Utils.IntegerHolder(move.getMove().priority);
|
||||||
|
applyAbAttrs(IncrementMovePriorityAbAttr, attacker, null, move.getMove(), attackPriority);
|
||||||
|
|
||||||
|
if(attackPriority.value > 0 && !move.getMove().isMultiTarget()) {
|
||||||
|
cancelled.value = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class PostStatChangeAbAttr extends AbAttr {
|
export class PostStatChangeAbAttr extends AbAttr {
|
||||||
applyPostStatChange(pokemon: Pokemon, statsChanged: BattleStat[], levelChanged: integer, selfTarget: boolean, args: any[]): boolean | Promise<boolean> {
|
applyPostStatChange(pokemon: Pokemon, statsChanged: BattleStat[], levelChanged: integer, selfTarget: boolean, args: any[]): boolean | Promise<boolean> {
|
||||||
return false;
|
return false;
|
||||||
@ -1141,6 +1155,8 @@ export class PostSummonFormChangeAbAttr extends PostSummonAbAttr {
|
|||||||
export class TraceAbAttr extends PostSummonAbAttr {
|
export class TraceAbAttr extends PostSummonAbAttr {
|
||||||
applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean {
|
applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean {
|
||||||
const targets = pokemon.getOpponents();
|
const targets = pokemon.getOpponents();
|
||||||
|
if (!targets.length)
|
||||||
|
return false;
|
||||||
let target: Pokemon;
|
let target: Pokemon;
|
||||||
if (targets.length > 1)
|
if (targets.length > 1)
|
||||||
pokemon.scene.executeWithSeedOffset(() => target = Utils.randSeedItem(targets), pokemon.scene.currentBattle.waveIndex);
|
pokemon.scene.executeWithSeedOffset(() => target = Utils.randSeedItem(targets), pokemon.scene.currentBattle.waveIndex);
|
||||||
@ -2343,10 +2359,10 @@ export function initAbilities() {
|
|||||||
.attr(MovePowerBoostAbAttr, (user, target, move) => user.gender !== Gender.GENDERLESS && target.gender !== Gender.GENDERLESS && user.gender !== target.gender, 0.75),
|
.attr(MovePowerBoostAbAttr, (user, target, move) => user.gender !== Gender.GENDERLESS && target.gender !== Gender.GENDERLESS && user.gender !== target.gender, 0.75),
|
||||||
new Ability(Abilities.STEADFAST, "Steadfast", "The Pokémon's determination boosts the Speed stat each time the Pokémon flinches.", 4)
|
new Ability(Abilities.STEADFAST, "Steadfast", "The Pokémon's determination boosts the Speed stat each time the Pokémon flinches.", 4)
|
||||||
.attr(FlinchStatChangeAbAttr, BattleStat.SPD, 1),
|
.attr(FlinchStatChangeAbAttr, BattleStat.SPD, 1),
|
||||||
new Ability(Abilities.SNOW_CLOAK, "Snow Cloak", "Boosts evasiveness in a hailstorm.", 4)
|
new Ability(Abilities.SNOW_CLOAK, "Snow Cloak", "Boosts the Pokémon's evasiveness in snow.", 4)
|
||||||
.attr(BattleStatMultiplierAbAttr, BattleStat.EVA, 1.2)
|
.attr(BattleStatMultiplierAbAttr, BattleStat.EVA, 1.2)
|
||||||
.attr(BlockWeatherDamageAttr, WeatherType.HAIL)
|
.attr(BlockWeatherDamageAttr, WeatherType.HAIL)
|
||||||
.condition(getWeatherCondition(WeatherType.HAIL))
|
.condition(getWeatherCondition(WeatherType.HAIL, WeatherType.SNOW))
|
||||||
.ignorable(),
|
.ignorable(),
|
||||||
new Ability(Abilities.GLUTTONY, "Gluttony", "Makes the Pokémon eat a held Berry when its HP drops to half or less, which is sooner than usual.", 4)
|
new Ability(Abilities.GLUTTONY, "Gluttony", "Makes the Pokémon eat a held Berry when its HP drops to half or less, which is sooner than usual.", 4)
|
||||||
.attr(ReduceBerryUseThresholdAbAttr),
|
.attr(ReduceBerryUseThresholdAbAttr),
|
||||||
@ -2424,14 +2440,15 @@ export function initAbilities() {
|
|||||||
.attr(RedirectTypeMoveAbAttr, Type.WATER)
|
.attr(RedirectTypeMoveAbAttr, Type.WATER)
|
||||||
.attr(TypeImmunityStatChangeAbAttr, Type.WATER, BattleStat.SPATK, 1)
|
.attr(TypeImmunityStatChangeAbAttr, Type.WATER, BattleStat.SPATK, 1)
|
||||||
.ignorable(),
|
.ignorable(),
|
||||||
new Ability(Abilities.ICE_BODY, "Ice Body", "The Pokémon gradually regains HP in a hailstorm.", 4)
|
new Ability(Abilities.ICE_BODY, "Ice Body", "The Pokémon gradually regains HP in snow.", 4)
|
||||||
.attr(PostWeatherLapseHealAbAttr, 1, WeatherType.HAIL),
|
.attr(BlockWeatherDamageAttr, WeatherType.HAIL)
|
||||||
|
.attr(PostWeatherLapseHealAbAttr, 1, WeatherType.HAIL, WeatherType.SNOW),
|
||||||
new Ability(Abilities.SOLID_ROCK, "Solid Rock", "Reduces the power of supereffective attacks taken.", 4)
|
new Ability(Abilities.SOLID_ROCK, "Solid Rock", "Reduces the power of supereffective attacks taken.", 4)
|
||||||
.attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getAttackTypeEffectiveness(move.type) >= 2, 0.75)
|
.attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getAttackTypeEffectiveness(move.type) >= 2, 0.75)
|
||||||
.ignorable(),
|
.ignorable(),
|
||||||
new Ability(Abilities.SNOW_WARNING, "Snow Warning", "The Pokémon summons a hailstorm when it enters a battle.", 4)
|
new Ability(Abilities.SNOW_WARNING, "Snow Warning", "The Pokémon makes it snow when it enters a battle.", 4)
|
||||||
.attr(PostSummonWeatherChangeAbAttr, WeatherType.HAIL)
|
.attr(PostSummonWeatherChangeAbAttr, WeatherType.SNOW)
|
||||||
.attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.HAIL),
|
.attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.SNOW),
|
||||||
new Ability(Abilities.HONEY_GATHER, "Honey Gather (N)", "The Pokémon may gather Honey after a battle.", 4),
|
new Ability(Abilities.HONEY_GATHER, "Honey Gather (N)", "The Pokémon may gather Honey after a battle.", 4),
|
||||||
new Ability(Abilities.FRISK, "Frisk (N)", "When it enters a battle, the Pokémon can check an opposing Pokémon's held item.", 4),
|
new Ability(Abilities.FRISK, "Frisk (N)", "When it enters a battle, the Pokémon can check an opposing Pokémon's held item.", 4),
|
||||||
new Ability(Abilities.RECKLESS, "Reckless", "Powers up moves that have recoil damage.", 4)
|
new Ability(Abilities.RECKLESS, "Reckless", "Powers up moves that have recoil damage.", 4)
|
||||||
@ -2536,9 +2553,9 @@ export function initAbilities() {
|
|||||||
.attr(PostDefendContactDamageAbAttr, 8)
|
.attr(PostDefendContactDamageAbAttr, 8)
|
||||||
.bypassFaint(),
|
.bypassFaint(),
|
||||||
new Ability(Abilities.ZEN_MODE, "Zen Mode", "Changes the Pokémon's shape when HP is half or less.", 5)
|
new Ability(Abilities.ZEN_MODE, "Zen Mode", "Changes the Pokémon's shape when HP is half or less.", 5)
|
||||||
.attr(PostBattleInitFormChangeAbAttr, p => p.getHpRatio() >= 0.5 ? 0 : 1)
|
.attr(PostBattleInitFormChangeAbAttr, p => p.getHpRatio() <= 0.5 ? 1 : 0)
|
||||||
.attr(PostSummonFormChangeAbAttr, p => p.getHpRatio() >= 0.5 ? 0 : 1)
|
.attr(PostSummonFormChangeAbAttr, p => p.getHpRatio() <= 0.5 ? 1 : 0)
|
||||||
.attr(PostTurnFormChangeAbAttr, p => p.getHpRatio() >= 0.5 ? 0 : 1)
|
.attr(PostTurnFormChangeAbAttr, p => p.getHpRatio() <= 0.5 ? 1 : 0)
|
||||||
.attr(UncopiableAbilityAbAttr)
|
.attr(UncopiableAbilityAbAttr)
|
||||||
.attr(UnswappableAbilityAbAttr)
|
.attr(UnswappableAbilityAbAttr)
|
||||||
.attr(UnsuppressableAbilityAbAttr),
|
.attr(UnsuppressableAbilityAbAttr),
|
||||||
@ -2616,7 +2633,10 @@ export function initAbilities() {
|
|||||||
new Ability(Abilities.WATER_COMPACTION, "Water Compaction", "Boosts the Pokémon's Defense stat sharply when hit by a Water-type move.", 7)
|
new Ability(Abilities.WATER_COMPACTION, "Water Compaction", "Boosts the Pokémon's Defense stat sharply when hit by a Water-type move.", 7)
|
||||||
.attr(PostDefendStatChangeAbAttr, (target, user, move) => move.type === Type.WATER, BattleStat.DEF, 2),
|
.attr(PostDefendStatChangeAbAttr, (target, user, move) => move.type === Type.WATER, BattleStat.DEF, 2),
|
||||||
new Ability(Abilities.MERCILESS, "Merciless (N)", "The Pokémon's attacks become critical hits if the target is poisoned.", 7),
|
new Ability(Abilities.MERCILESS, "Merciless (N)", "The Pokémon's attacks become critical hits if the target is poisoned.", 7),
|
||||||
new Ability(Abilities.SHIELDS_DOWN, "Shields Down (N)", "When its HP becomes half or less, the Pokémon's shell breaks and it becomes aggressive.", 7)
|
new Ability(Abilities.SHIELDS_DOWN, "Shields Down (P)", "When its HP becomes half or less, the Pokémon's shell breaks and it becomes aggressive.", 7)
|
||||||
|
.attr(PostBattleInitFormChangeAbAttr, p => p.formIndex % 7 + (p.getHpRatio() <= 0.5 ? 7 : 0))
|
||||||
|
.attr(PostSummonFormChangeAbAttr, p => p.formIndex % 7 + (p.getHpRatio() <= 0.5 ? 7 : 0))
|
||||||
|
.attr(PostTurnFormChangeAbAttr, p => p.formIndex % 7 + (p.getHpRatio() <= 0.5 ? 7 : 0))
|
||||||
.attr(UncopiableAbilityAbAttr)
|
.attr(UncopiableAbilityAbAttr)
|
||||||
.attr(UnswappableAbilityAbAttr)
|
.attr(UnswappableAbilityAbAttr)
|
||||||
.attr(UnsuppressableAbilityAbAttr),
|
.attr(UnsuppressableAbilityAbAttr),
|
||||||
@ -2629,9 +2649,9 @@ export function initAbilities() {
|
|||||||
new Ability(Abilities.STEELWORKER, "Steelworker", "Powers up Steel-type moves.", 7)
|
new Ability(Abilities.STEELWORKER, "Steelworker", "Powers up Steel-type moves.", 7)
|
||||||
.attr(MoveTypePowerBoostAbAttr, Type.STEEL),
|
.attr(MoveTypePowerBoostAbAttr, Type.STEEL),
|
||||||
new Ability(Abilities.BERSERK, "Berserk (N)", "Boosts the Pokémon's Sp. Atk stat when it takes a hit that causes its HP to become half or less.", 7),
|
new Ability(Abilities.BERSERK, "Berserk (N)", "Boosts the Pokémon's Sp. Atk stat when it takes a hit that causes its HP to become half or less.", 7),
|
||||||
new Ability(Abilities.SLUSH_RUSH, "Slush Rush", "Boosts the Pokémon's Speed stat in a hailstorm.", 7)
|
new Ability(Abilities.SLUSH_RUSH, "Slush Rush", "Boosts the Pokémon's Speed stat in snow.", 7)
|
||||||
.attr(BattleStatMultiplierAbAttr, BattleStat.SPD, 2)
|
.attr(BattleStatMultiplierAbAttr, BattleStat.SPD, 2)
|
||||||
.condition(getWeatherCondition(WeatherType.HAIL)),
|
.condition(getWeatherCondition(WeatherType.HAIL, WeatherType.SNOW)),
|
||||||
new Ability(Abilities.LONG_REACH, "Long Reach", "The Pokémon uses its moves without making contact with the target.", 7)
|
new Ability(Abilities.LONG_REACH, "Long Reach", "The Pokémon uses its moves without making contact with the target.", 7)
|
||||||
.attr(IgnoreContactAbAttr),
|
.attr(IgnoreContactAbAttr),
|
||||||
new Ability(Abilities.LIQUID_VOICE, "Liquid Voice", "All sound-based moves become Water-type moves.", 7)
|
new Ability(Abilities.LIQUID_VOICE, "Liquid Voice", "All sound-based moves become Water-type moves.", 7)
|
||||||
@ -2668,7 +2688,8 @@ export function initAbilities() {
|
|||||||
.attr(UncopiableAbilityAbAttr)
|
.attr(UncopiableAbilityAbAttr)
|
||||||
.attr(UnswappableAbilityAbAttr)
|
.attr(UnswappableAbilityAbAttr)
|
||||||
.attr(UnsuppressableAbilityAbAttr),
|
.attr(UnsuppressableAbilityAbAttr),
|
||||||
new Ability(Abilities.QUEENLY_MAJESTY, "Queenly Majesty (N)", "Its majesty pressures the opposing Pokémon, making it unable to attack using priority moves.", 7)
|
new Ability(Abilities.QUEENLY_MAJESTY, "Queenly Majesty", "Its majesty pressures the opposing Pokémon, making it unable to attack using priority moves.", 7)
|
||||||
|
.attr(FieldPriorityMoveImmunityAbAttr)
|
||||||
.ignorable(),
|
.ignorable(),
|
||||||
new Ability(Abilities.INNARDS_OUT, "Innards Out (N)", "Damages the attacker landing the finishing hit by the amount equal to its last HP.", 7),
|
new Ability(Abilities.INNARDS_OUT, "Innards Out (N)", "Damages the attacker landing the finishing hit by the amount equal to its last HP.", 7),
|
||||||
new Ability(Abilities.DANCER, "Dancer (N)", "When another Pokémon uses a dance move, it can use a dance move following it regardless of its Speed.", 7),
|
new Ability(Abilities.DANCER, "Dancer (N)", "When another Pokémon uses a dance move, it can use a dance move following it regardless of its Speed.", 7),
|
||||||
@ -2677,7 +2698,8 @@ export function initAbilities() {
|
|||||||
.attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => move.hasFlag(MoveFlags.MAKES_CONTACT), 0.5)
|
.attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => move.hasFlag(MoveFlags.MAKES_CONTACT), 0.5)
|
||||||
.attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => move.type === Type.FIRE, 2)
|
.attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => move.type === Type.FIRE, 2)
|
||||||
.ignorable(),
|
.ignorable(),
|
||||||
new Ability(Abilities.DAZZLING, "Dazzling (N)", "Surprises the opposing Pokémon, making it unable to attack using priority moves.", 7)
|
new Ability(Abilities.DAZZLING, "Dazzling", "Surprises the opposing Pokémon, making it unable to attack using priority moves.", 7)
|
||||||
|
.attr(FieldPriorityMoveImmunityAbAttr)
|
||||||
.ignorable(),
|
.ignorable(),
|
||||||
new Ability(Abilities.SOUL_HEART, "Soul-Heart", "Boosts its Sp. Atk stat every time a Pokémon faints.", 7)
|
new Ability(Abilities.SOUL_HEART, "Soul-Heart", "Boosts its Sp. Atk stat every time a Pokémon faints.", 7)
|
||||||
.attr(PostKnockOutStatChangeAbAttr, BattleStat.SPATK, 1),
|
.attr(PostKnockOutStatChangeAbAttr, BattleStat.SPATK, 1),
|
||||||
@ -2810,7 +2832,8 @@ export function initAbilities() {
|
|||||||
.bypassFaint(),
|
.bypassFaint(),
|
||||||
new Ability(Abilities.SEED_SOWER, "Seed Sower", "Turns the ground into Grassy Terrain when the Pokémon is hit by an attack.", 9)
|
new Ability(Abilities.SEED_SOWER, "Seed Sower", "Turns the ground into Grassy Terrain when the Pokémon is hit by an attack.", 9)
|
||||||
.attr(PostDefendTerrainChangeAbAttr, TerrainType.GRASSY),
|
.attr(PostDefendTerrainChangeAbAttr, TerrainType.GRASSY),
|
||||||
new Ability(Abilities.THERMAL_EXCHANGE, "Thermal Exchange (P)", "Boosts the Attack stat when the Pokémon is hit by a Fire-type move. The Pokémon also cannot be burned.", 9)
|
new Ability(Abilities.THERMAL_EXCHANGE, "Thermal Exchange", "Boosts the Attack stat when the Pokémon is hit by a Fire-type move. The Pokémon also cannot be burned.", 9)
|
||||||
|
.attr(PostDefendStatChangeAbAttr, (target, user, move) => move.type === Type.FIRE, BattleStat.ATK, 1)
|
||||||
.attr(StatusEffectImmunityAbAttr, StatusEffect.BURN)
|
.attr(StatusEffectImmunityAbAttr, StatusEffect.BURN)
|
||||||
.ignorable(),
|
.ignorable(),
|
||||||
new Ability(Abilities.ANGER_SHELL, "Anger Shell (N)", "When an attack causes its HP to drop to half or less, the Pokémon gets angry. This lowers its Defense and Sp. Def stats but boosts its Attack, Sp. Atk, and Speed stats.", 9),
|
new Ability(Abilities.ANGER_SHELL, "Anger Shell (N)", "When an attack causes its HP to drop to half or less, the Pokémon gets angry. This lowers its Defense and Sp. Def stats but boosts its Attack, Sp. Atk, and Speed stats.", 9),
|
||||||
@ -2875,7 +2898,8 @@ export function initAbilities() {
|
|||||||
new Ability(Abilities.SUPREME_OVERLORD, "Supreme Overlord (N)", "When the Pokémon enters a battle, its Attack and Sp. Atk stats are slightly boosted for each of the allies in its party that have already been defeated.", 9),
|
new Ability(Abilities.SUPREME_OVERLORD, "Supreme Overlord (N)", "When the Pokémon enters a battle, its Attack and Sp. Atk stats are slightly boosted for each of the allies in its party that have already been defeated.", 9),
|
||||||
new Ability(Abilities.COSTAR, "Costar (N)", "When the Pokémon enters a battle, it copies an ally's stat changes.", 9),
|
new Ability(Abilities.COSTAR, "Costar (N)", "When the Pokémon enters a battle, it copies an ally's stat changes.", 9),
|
||||||
new Ability(Abilities.TOXIC_DEBRIS, "Toxic Debris (N)", "Scatters poison spikes at the feet of the opposing team when the Pokémon takes damage from physical moves.", 9),
|
new Ability(Abilities.TOXIC_DEBRIS, "Toxic Debris (N)", "Scatters poison spikes at the feet of the opposing team when the Pokémon takes damage from physical moves.", 9),
|
||||||
new Ability(Abilities.ARMOR_TAIL, "Armor Tail (N)", "The mysterious tail covering the Pokémon's head makes opponents unable to use priority moves against the Pokémon or its allies.", 9)
|
new Ability(Abilities.ARMOR_TAIL, "Armor Tail", "The mysterious tail covering the Pokémon's head makes opponents unable to use priority moves against the Pokémon or its allies.", 9)
|
||||||
|
.attr(FieldPriorityMoveImmunityAbAttr)
|
||||||
.ignorable(),
|
.ignorable(),
|
||||||
new Ability(Abilities.EARTH_EATER, "Earth Eater", "If hit by a Ground-type move, the Pokémon has its HP restored instead of taking damage.", 9)
|
new Ability(Abilities.EARTH_EATER, "Earth Eater", "If hit by a Ground-type move, the Pokémon has its HP restored instead of taking damage.", 9)
|
||||||
.attr(TypeImmunityHealAbAttr, Type.GROUND)
|
.attr(TypeImmunityHealAbAttr, Type.GROUND)
|
||||||
|
@ -89,6 +89,7 @@ export enum CommonAnim {
|
|||||||
RAIN,
|
RAIN,
|
||||||
SANDSTORM,
|
SANDSTORM,
|
||||||
HAIL,
|
HAIL,
|
||||||
|
SNOW,
|
||||||
WIND,
|
WIND,
|
||||||
HEAVY_RAIN,
|
HEAVY_RAIN,
|
||||||
HARSH_SUN,
|
HARSH_SUN,
|
||||||
|
@ -799,7 +799,7 @@ export class TruantTag extends AbilityBattlerTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
|
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
|
||||||
if ((!pokemon.canApplyAbility() || pokemon.getAbility().id !== Abilities.TRUANT) && (!pokemon.canApplyAbility(true) || pokemon.getPassiveAbility().id !== Abilities.TRUANT))
|
if (!pokemon.hasAbility(Abilities.TRUANT))
|
||||||
return super.lapse(pokemon, lapseType);
|
return super.lapse(pokemon, lapseType);
|
||||||
const passive = pokemon.getAbility().id !== Abilities.TRUANT;
|
const passive = pokemon.getAbility().id !== Abilities.TRUANT;
|
||||||
|
|
||||||
@ -827,7 +827,7 @@ export class SlowStartTag extends AbilityBattlerTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
|
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
|
||||||
if ((!pokemon.canApplyAbility() || pokemon.getAbility().id !== this.ability) && (!pokemon.canApplyAbility(true) || pokemon.getPassiveAbility().id !== this.ability))
|
if (!pokemon.hasAbility(this.ability))
|
||||||
this.turnCount = 1;
|
this.turnCount = 1;
|
||||||
|
|
||||||
return super.lapse(pokemon, lapseType);
|
return super.lapse(pokemon, lapseType);
|
||||||
@ -1077,6 +1077,7 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc
|
|||||||
return new TerrainHighestStatBoostTag(tagType, Abilities.QUARK_DRIVE, TerrainType.ELECTRIC);
|
return new TerrainHighestStatBoostTag(tagType, Abilities.QUARK_DRIVE, TerrainType.ELECTRIC);
|
||||||
case BattlerTagType.FLYING:
|
case BattlerTagType.FLYING:
|
||||||
case BattlerTagType.UNDERGROUND:
|
case BattlerTagType.UNDERGROUND:
|
||||||
|
case BattlerTagType.UNDERWATER:
|
||||||
case BattlerTagType.HIDDEN:
|
case BattlerTagType.HIDDEN:
|
||||||
return new HideSpriteTag(tagType, turnCount, sourceMove);
|
return new HideSpriteTag(tagType, turnCount, sourceMove);
|
||||||
case BattlerTagType.FIRE_BOOST:
|
case BattlerTagType.FIRE_BOOST:
|
||||||
|
@ -38,6 +38,7 @@ export enum BattlerTagType {
|
|||||||
QUARK_DRIVE = "QUARK_DRIVE",
|
QUARK_DRIVE = "QUARK_DRIVE",
|
||||||
FLYING = "FLYING",
|
FLYING = "FLYING",
|
||||||
UNDERGROUND = "UNDERGROUND",
|
UNDERGROUND = "UNDERGROUND",
|
||||||
|
UNDERWATER = "UNDERWATER",
|
||||||
HIDDEN = "HIDDEN",
|
HIDDEN = "HIDDEN",
|
||||||
FIRE_BOOST = "FIRE_BOOST",
|
FIRE_BOOST = "FIRE_BOOST",
|
||||||
CRIT_BOOST = "CRIT_BOOST",
|
CRIT_BOOST = "CRIT_BOOST",
|
||||||
|
257
src/data/move.ts
257
src/data/move.ts
@ -23,6 +23,7 @@ import { SpeciesFormChangeActiveTrigger } from "./pokemon-forms";
|
|||||||
import { Species } from "./enums/species";
|
import { Species } from "./enums/species";
|
||||||
import { ModifierPoolType } from "#app/modifier/modifier-type";
|
import { ModifierPoolType } from "#app/modifier/modifier-type";
|
||||||
import { Command } from "../ui/command-ui-handler";
|
import { Command } from "../ui/command-ui-handler";
|
||||||
|
import { Biome } from "./enums/biome";
|
||||||
|
|
||||||
export enum MoveCategory {
|
export enum MoveCategory {
|
||||||
PHYSICAL,
|
PHYSICAL,
|
||||||
@ -274,7 +275,7 @@ export default class Move {
|
|||||||
checkFlag(flag: MoveFlags, user: Pokemon, target: Pokemon): boolean {
|
checkFlag(flag: MoveFlags, user: Pokemon, target: Pokemon): boolean {
|
||||||
switch (flag) {
|
switch (flag) {
|
||||||
case MoveFlags.MAKES_CONTACT:
|
case MoveFlags.MAKES_CONTACT:
|
||||||
if ((user.canApplyAbility() && user.getAbility().hasAttr(IgnoreContactAbAttr)) || (user.canApplyAbility(true) && user.getPassiveAbility().hasAttr(IgnoreContactAbAttr)))
|
if (user.hasAbilityWithAttr(IgnoreContactAbAttr))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -776,6 +777,7 @@ export class PlantHealAttr extends WeatherHealAttr {
|
|||||||
case WeatherType.RAIN:
|
case WeatherType.RAIN:
|
||||||
case WeatherType.SANDSTORM:
|
case WeatherType.SANDSTORM:
|
||||||
case WeatherType.HAIL:
|
case WeatherType.HAIL:
|
||||||
|
case WeatherType.SNOW:
|
||||||
case WeatherType.HEAVY_RAIN:
|
case WeatherType.HEAVY_RAIN:
|
||||||
return 0.25;
|
return 0.25;
|
||||||
default:
|
default:
|
||||||
@ -1755,6 +1757,7 @@ export class AntiSunlightPowerDecreaseAttr extends VariablePowerAttr {
|
|||||||
case WeatherType.RAIN:
|
case WeatherType.RAIN:
|
||||||
case WeatherType.SANDSTORM:
|
case WeatherType.SANDSTORM:
|
||||||
case WeatherType.HAIL:
|
case WeatherType.HAIL:
|
||||||
|
case WeatherType.SNOW:
|
||||||
case WeatherType.HEAVY_RAIN:
|
case WeatherType.HEAVY_RAIN:
|
||||||
power.value *= 0.5;
|
power.value *= 0.5;
|
||||||
return true;
|
return true;
|
||||||
@ -1804,6 +1807,28 @@ export class StatChangeCountPowerAttr extends VariablePowerAttr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class PresentPowerAttr extends VariablePowerAttr {
|
||||||
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
|
|
||||||
|
const powerSeed = Utils.randSeedInt(100);
|
||||||
|
if (powerSeed <= 40) {
|
||||||
|
(args[0] as Utils.NumberHolder).value = 40;
|
||||||
|
}
|
||||||
|
else if (40 < powerSeed && powerSeed <= 70) {
|
||||||
|
(args[0] as Utils.NumberHolder).value = 80;
|
||||||
|
}
|
||||||
|
else if (70 < powerSeed && powerSeed <= 80) {
|
||||||
|
(args[0] as Utils.NumberHolder).value = 120;
|
||||||
|
}
|
||||||
|
else if (80 < powerSeed && powerSeed <= 100) {
|
||||||
|
target.scene.unshiftPhase(new PokemonHealPhase(target.scene, target.getBattlerIndex(),
|
||||||
|
Math.max(Math.floor(target.getMaxHp() / 4), 1), getPokemonMessage(target, ' regained\nhealth!'), true));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class VariableAtkAttr extends MoveAttr {
|
export class VariableAtkAttr extends MoveAttr {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -1904,7 +1929,7 @@ export class BlizzardAccuracyAttr extends VariableAccuracyAttr {
|
|||||||
if (!user.scene.arena.weather?.isEffectSuppressed(user.scene)) {
|
if (!user.scene.arena.weather?.isEffectSuppressed(user.scene)) {
|
||||||
const accuracy = args[0] as Utils.NumberHolder;
|
const accuracy = args[0] as Utils.NumberHolder;
|
||||||
const weatherType = user.scene.arena.weather?.weatherType || WeatherType.NONE;
|
const weatherType = user.scene.arena.weather?.weatherType || WeatherType.NONE;
|
||||||
if (weatherType === WeatherType.HAIL) {
|
if (weatherType === WeatherType.HAIL || weatherType === WeatherType.SNOW) {
|
||||||
accuracy.value = -1;
|
accuracy.value = -1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2016,6 +2041,45 @@ export class RagingBullTypeAttr extends VariableMoveTypeAttr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class IvyCudgelTypeAttr extends VariableMoveTypeAttr {
|
||||||
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
|
if ([user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.OGERPON)) {
|
||||||
|
const form = user.species.speciesId === Species.OGERPON ? user.formIndex : user.fusionSpecies.formIndex;
|
||||||
|
const type = (args[0] as Utils.IntegerHolder);
|
||||||
|
|
||||||
|
switch (form) {
|
||||||
|
case 1: // Wellspring Mask
|
||||||
|
type.value = Type.WATER;
|
||||||
|
break;
|
||||||
|
case 2: // Hearthflame Mask
|
||||||
|
type.value = Type.FIRE;
|
||||||
|
break;
|
||||||
|
case 3: // Cornerstone Mask
|
||||||
|
type.value = Type.ROCK;
|
||||||
|
break;
|
||||||
|
case 4: // Teal Mask Tera
|
||||||
|
type.value = Type.GRASS;
|
||||||
|
break;
|
||||||
|
case 5: // Wellspring Mask Tera
|
||||||
|
type.value = Type.WATER;
|
||||||
|
break;
|
||||||
|
case 6: // Hearthflame Mask Tera
|
||||||
|
type.value = Type.FIRE;
|
||||||
|
break;
|
||||||
|
case 7: // Cornerstone Mask Tera
|
||||||
|
type.value = Type.ROCK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
type.value = Type.GRASS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class WeatherBallTypeAttr extends VariableMoveTypeAttr {
|
export class WeatherBallTypeAttr extends VariableMoveTypeAttr {
|
||||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
if (!user.scene.arena.weather?.isEffectSuppressed(user.scene)) {
|
if (!user.scene.arena.weather?.isEffectSuppressed(user.scene)) {
|
||||||
@ -2034,6 +2098,7 @@ export class WeatherBallTypeAttr extends VariableMoveTypeAttr {
|
|||||||
type.value = Type.ROCK;
|
type.value = Type.ROCK;
|
||||||
break;
|
break;
|
||||||
case WeatherType.HAIL:
|
case WeatherType.HAIL:
|
||||||
|
case WeatherType.SNOW:
|
||||||
type.value = Type.ICE;
|
type.value = Type.ICE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -2779,6 +2844,149 @@ export class RandomMoveAttr extends OverrideMoveEffectAttr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class NaturePowerAttr extends OverrideMoveEffectAttr {
|
||||||
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise<boolean> {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
var moveId;
|
||||||
|
switch (user.scene.arena.getTerrainType()) {
|
||||||
|
// this allows terrains to 'override' the biome move
|
||||||
|
case TerrainType.NONE:
|
||||||
|
switch (user.scene.arena.biomeType) {
|
||||||
|
case Biome.TOWN:
|
||||||
|
moveId = Moves.ROUND;
|
||||||
|
break;
|
||||||
|
case Biome.METROPOLIS:
|
||||||
|
moveId = Moves.TRI_ATTACK;
|
||||||
|
break;
|
||||||
|
case Biome.SLUM:
|
||||||
|
moveId = Moves.SLUDGE_BOMB;
|
||||||
|
break;
|
||||||
|
case Biome.PLAINS:
|
||||||
|
moveId = Moves.SILVER_WIND;
|
||||||
|
break;
|
||||||
|
case Biome.GRASS:
|
||||||
|
moveId = Moves.GRASS_KNOT;
|
||||||
|
break;
|
||||||
|
case Biome.TALL_GRASS:
|
||||||
|
moveId = Moves.POLLEN_PUFF;
|
||||||
|
break;
|
||||||
|
case Biome.MEADOW:
|
||||||
|
moveId = Moves.GIGA_DRAIN;
|
||||||
|
break;
|
||||||
|
case Biome.FOREST:
|
||||||
|
moveId = Moves.BUG_BUZZ;
|
||||||
|
break;
|
||||||
|
case Biome.JUNGLE:
|
||||||
|
moveId = Moves.LEAF_STORM;
|
||||||
|
break;
|
||||||
|
case Biome.SEA:
|
||||||
|
moveId = Moves.HYDRO_PUMP;
|
||||||
|
break;
|
||||||
|
case Biome.SWAMP:
|
||||||
|
moveId = Moves.MUD_BOMB;
|
||||||
|
break;
|
||||||
|
case Biome.BEACH:
|
||||||
|
moveId = Moves.SCALD;
|
||||||
|
break;
|
||||||
|
case Biome.LAKE:
|
||||||
|
moveId = Moves.BUBBLE_BEAM;
|
||||||
|
break;
|
||||||
|
case Biome.SEABED:
|
||||||
|
moveId = Moves.BRINE;
|
||||||
|
break;
|
||||||
|
case Biome.ISLAND:
|
||||||
|
moveId = Moves.LEAF_TORNADO;
|
||||||
|
break;
|
||||||
|
case Biome.MOUNTAIN:
|
||||||
|
moveId = Moves.AIR_SLASH;
|
||||||
|
break;
|
||||||
|
case Biome.BADLANDS:
|
||||||
|
moveId = Moves.EARTH_POWER;
|
||||||
|
break;
|
||||||
|
case Biome.DESERT:
|
||||||
|
moveId = Moves.SCORCHING_SANDS;
|
||||||
|
break;
|
||||||
|
case Biome.WASTELAND:
|
||||||
|
moveId = Moves.DRAGON_PULSE;
|
||||||
|
break;
|
||||||
|
case Biome.CONSTRUCTION_SITE:
|
||||||
|
moveId = Moves.STEEL_BEAM;
|
||||||
|
break;
|
||||||
|
case Biome.CAVE:
|
||||||
|
moveId = Moves.POWER_GEM;
|
||||||
|
break;
|
||||||
|
case Biome.ICE_CAVE:
|
||||||
|
moveId = Moves.ICE_BEAM;
|
||||||
|
break;
|
||||||
|
case Biome.SNOWY_FOREST:
|
||||||
|
moveId = Moves.FROST_BREATH;
|
||||||
|
break;
|
||||||
|
case Biome.VOLCANO:
|
||||||
|
moveId = Moves.LAVA_PLUME;
|
||||||
|
break;
|
||||||
|
case Biome.GRAVEYARD:
|
||||||
|
moveId = Moves.SHADOW_BALL;
|
||||||
|
break;
|
||||||
|
case Biome.RUINS:
|
||||||
|
moveId = Moves.ANCIENT_POWER;
|
||||||
|
break;
|
||||||
|
case Biome.TEMPLE:
|
||||||
|
moveId = Moves.EXTRASENSORY;
|
||||||
|
break;
|
||||||
|
case Biome.DOJO:
|
||||||
|
moveId = Moves.FOCUS_BLAST;
|
||||||
|
break;
|
||||||
|
case Biome.FAIRY_CAVE:
|
||||||
|
moveId = Moves.ALLURING_VOICE;
|
||||||
|
break;
|
||||||
|
case Biome.ABYSS:
|
||||||
|
moveId = Moves.OMINOUS_WIND;
|
||||||
|
break;
|
||||||
|
case Biome.SPACE:
|
||||||
|
moveId = Moves.DRACO_METEOR;
|
||||||
|
break;
|
||||||
|
case Biome.FACTORY:
|
||||||
|
moveId = Moves.FLASH_CANNON;
|
||||||
|
break;
|
||||||
|
case Biome.LABORATORY:
|
||||||
|
moveId = Moves.ZAP_CANNON;
|
||||||
|
break;
|
||||||
|
case Biome.POWER_PLANT:
|
||||||
|
moveId = Moves.CHARGE_BEAM;
|
||||||
|
break;
|
||||||
|
case Biome.END:
|
||||||
|
moveId = Moves.ETERNABEAM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TerrainType.MISTY:
|
||||||
|
moveId = Moves.MOONBLAST;
|
||||||
|
break;
|
||||||
|
case TerrainType.ELECTRIC:
|
||||||
|
moveId = Moves.THUNDERBOLT;
|
||||||
|
break;
|
||||||
|
case TerrainType.GRASSY:
|
||||||
|
moveId = Moves.ENERGY_BALL;
|
||||||
|
break;
|
||||||
|
case TerrainType.PSYCHIC:
|
||||||
|
moveId = Moves.PSYCHIC;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Just in case there's no match
|
||||||
|
moveId = Moves.TRI_ATTACK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
user.getMoveQueue().push({ move: moveId, targets: [target.getBattlerIndex()], ignorePP: true });
|
||||||
|
user.scene.unshiftPhase(new MovePhase(user.scene, user, [target.getBattlerIndex()], new PokemonMove(moveId, 0, 0, true), true));
|
||||||
|
initMoveAnim(moveId).then(() => {
|
||||||
|
loadMoveAnimAssets(user.scene, [ moveId ], true)
|
||||||
|
.then(() => resolve(true));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const lastMoveCopiableCondition: MoveConditionFunc = (user, target, move) => {
|
const lastMoveCopiableCondition: MoveConditionFunc = (user, target, move) => {
|
||||||
const copiableMove = user.scene.currentBattle.lastMove;
|
const copiableMove = user.scene.currentBattle.lastMove;
|
||||||
|
|
||||||
@ -3263,6 +3471,7 @@ export function initMoves() {
|
|||||||
new AttackMove(Moves.WING_ATTACK, "Wing Attack", Type.FLYING, MoveCategory.PHYSICAL, 60, 100, 35, "The target is struck with large, imposing wings spread wide to inflict damage.", -1, 0, 1),
|
new AttackMove(Moves.WING_ATTACK, "Wing Attack", Type.FLYING, MoveCategory.PHYSICAL, 60, 100, 35, "The target is struck with large, imposing wings spread wide to inflict damage.", -1, 0, 1),
|
||||||
new StatusMove(Moves.WHIRLWIND, "Whirlwind", Type.NORMAL, -1, 20, "The target is blown away, and a different Pokémon is dragged out. In the wild, this ends a battle against a single Pokémon.", -1, -6, 1)
|
new StatusMove(Moves.WHIRLWIND, "Whirlwind", Type.NORMAL, -1, 20, "The target is blown away, and a different Pokémon is dragged out. In the wild, this ends a battle against a single Pokémon.", -1, -6, 1)
|
||||||
.attr(ForceSwitchOutAttr)
|
.attr(ForceSwitchOutAttr)
|
||||||
|
.attr(HitsTagAttr, BattlerTagType.FLYING, false)
|
||||||
.hidesTarget()
|
.hidesTarget()
|
||||||
.windMove(),
|
.windMove(),
|
||||||
new AttackMove(Moves.FLY, "Fly", Type.FLYING, MoveCategory.PHYSICAL, 90, 95, 15, "The user flies up into the sky and then strikes its target on the next turn.", -1, 0, 1)
|
new AttackMove(Moves.FLY, "Fly", Type.FLYING, MoveCategory.PHYSICAL, 90, 95, 15, "The user flies up into the sky and then strikes its target on the next turn.", -1, 0, 1)
|
||||||
@ -3357,7 +3566,8 @@ export function initMoves() {
|
|||||||
new AttackMove(Moves.WATER_GUN, "Water Gun", Type.WATER, MoveCategory.SPECIAL, 40, 100, 25, "The target is blasted with a forceful shot of water.", -1, 0, 1),
|
new AttackMove(Moves.WATER_GUN, "Water Gun", Type.WATER, MoveCategory.SPECIAL, 40, 100, 25, "The target is blasted with a forceful shot of water.", -1, 0, 1),
|
||||||
new AttackMove(Moves.HYDRO_PUMP, "Hydro Pump", Type.WATER, MoveCategory.SPECIAL, 110, 80, 5, "The target is blasted by a huge volume of water launched under great pressure.", -1, 0, 1),
|
new AttackMove(Moves.HYDRO_PUMP, "Hydro Pump", Type.WATER, MoveCategory.SPECIAL, 110, 80, 5, "The target is blasted by a huge volume of water launched under great pressure.", -1, 0, 1),
|
||||||
new AttackMove(Moves.SURF, "Surf", Type.WATER, MoveCategory.SPECIAL, 90, 100, 15, "The user attacks everything around it by swamping its surroundings with a giant wave.", -1, 0, 1)
|
new AttackMove(Moves.SURF, "Surf", Type.WATER, MoveCategory.SPECIAL, 90, 100, 15, "The user attacks everything around it by swamping its surroundings with a giant wave.", -1, 0, 1)
|
||||||
.target(MoveTarget.ALL_NEAR_OTHERS),
|
.target(MoveTarget.ALL_NEAR_OTHERS)
|
||||||
|
.attr(HitsTagAttr, BattlerTagType.UNDERWATER, true),
|
||||||
new AttackMove(Moves.ICE_BEAM, "Ice Beam", Type.ICE, MoveCategory.SPECIAL, 90, 100, 10, "The target is struck with an icy-cold beam of energy. This may also leave the target frozen.", 10, 0, 1)
|
new AttackMove(Moves.ICE_BEAM, "Ice Beam", Type.ICE, MoveCategory.SPECIAL, 90, 100, 10, "The target is struck with an icy-cold beam of energy. This may also leave the target frozen.", 10, 0, 1)
|
||||||
.attr(StatusEffectAttr, StatusEffect.FREEZE),
|
.attr(StatusEffectAttr, StatusEffect.FREEZE),
|
||||||
new AttackMove(Moves.BLIZZARD, "Blizzard", Type.ICE, MoveCategory.SPECIAL, 110, 70, 5, "A howling blizzard is summoned to strike opposing Pokémon. This may also leave the opposing Pokémon frozen.", 10, 0, 1)
|
new AttackMove(Moves.BLIZZARD, "Blizzard", Type.ICE, MoveCategory.SPECIAL, 110, 70, 5, "A howling blizzard is summoned to strike opposing Pokémon. This may also leave the opposing Pokémon frozen.", 10, 0, 1)
|
||||||
@ -3436,7 +3646,8 @@ export function initMoves() {
|
|||||||
.attr(StatusMoveTypeImmunityAttr, Type.GROUND),
|
.attr(StatusMoveTypeImmunityAttr, Type.GROUND),
|
||||||
new AttackMove(Moves.THUNDER, "Thunder", Type.ELECTRIC, MoveCategory.SPECIAL, 110, 70, 10, "A wicked thunderbolt is dropped on the target to inflict damage. This may also leave the target with paralysis.", 30, 0, 1)
|
new AttackMove(Moves.THUNDER, "Thunder", Type.ELECTRIC, MoveCategory.SPECIAL, 110, 70, 10, "A wicked thunderbolt is dropped on the target to inflict damage. This may also leave the target with paralysis.", 30, 0, 1)
|
||||||
.attr(StatusEffectAttr, StatusEffect.PARALYSIS)
|
.attr(StatusEffectAttr, StatusEffect.PARALYSIS)
|
||||||
.attr(ThunderAccuracyAttr),
|
.attr(ThunderAccuracyAttr)
|
||||||
|
.attr(HitsTagAttr, BattlerTagType.FLYING, false),
|
||||||
new AttackMove(Moves.ROCK_THROW, "Rock Throw", Type.ROCK, MoveCategory.PHYSICAL, 50, 90, 15, "The user picks up and throws a small rock at the target to attack.", -1, 0, 1)
|
new AttackMove(Moves.ROCK_THROW, "Rock Throw", Type.ROCK, MoveCategory.PHYSICAL, 50, 90, 15, "The user picks up and throws a small rock at the target to attack.", -1, 0, 1)
|
||||||
.makesContact(false),
|
.makesContact(false),
|
||||||
new AttackMove(Moves.EARTHQUAKE, "Earthquake", Type.GROUND, MoveCategory.PHYSICAL, 100, 100, 10, "The user sets off an earthquake that strikes every Pokémon around it.", -1, 0, 1)
|
new AttackMove(Moves.EARTHQUAKE, "Earthquake", Type.GROUND, MoveCategory.PHYSICAL, 100, 100, 10, "The user sets off an earthquake that strikes every Pokémon around it.", -1, 0, 1)
|
||||||
@ -3446,6 +3657,7 @@ export function initMoves() {
|
|||||||
new AttackMove(Moves.FISSURE, "Fissure", Type.GROUND, MoveCategory.PHYSICAL, -1, 30, 5, "The user opens up a fissure in the ground and drops the target in. The target faints instantly if this attack hits.", -1, 0, 1)
|
new AttackMove(Moves.FISSURE, "Fissure", Type.GROUND, MoveCategory.PHYSICAL, -1, 30, 5, "The user opens up a fissure in the ground and drops the target in. The target faints instantly if this attack hits.", -1, 0, 1)
|
||||||
.attr(OneHitKOAttr)
|
.attr(OneHitKOAttr)
|
||||||
.attr(OneHitKOAccuracyAttr)
|
.attr(OneHitKOAccuracyAttr)
|
||||||
|
.attr(HitsTagAttr, BattlerTagType.UNDERGROUND, false)
|
||||||
.makesContact(false),
|
.makesContact(false),
|
||||||
new AttackMove(Moves.DIG, "Dig", Type.GROUND, MoveCategory.PHYSICAL, 80, 100, 10, "The user burrows into the ground, then attacks on the next turn.", -1, 0, 1)
|
new AttackMove(Moves.DIG, "Dig", Type.GROUND, MoveCategory.PHYSICAL, 80, 100, 10, "The user burrows into the ground, then attacks on the next turn.", -1, 0, 1)
|
||||||
.attr(ChargeAttr, ChargeAnim.DIG_CHARGING, 'dug a hole!', BattlerTagType.UNDERGROUND)
|
.attr(ChargeAttr, ChargeAnim.DIG_CHARGING, 'dug a hole!', BattlerTagType.UNDERGROUND)
|
||||||
@ -3783,7 +3995,8 @@ export function initMoves() {
|
|||||||
.target(MoveTarget.USER_AND_ALLIES),
|
.target(MoveTarget.USER_AND_ALLIES),
|
||||||
new AttackMove(Moves.RETURN, "Return", Type.NORMAL, MoveCategory.PHYSICAL, -1, 100, 20, "This full-power attack grows more powerful the more the user likes its Trainer.", -1, 0, 2)
|
new AttackMove(Moves.RETURN, "Return", Type.NORMAL, MoveCategory.PHYSICAL, -1, 100, 20, "This full-power attack grows more powerful the more the user likes its Trainer.", -1, 0, 2)
|
||||||
.attr(FriendshipPowerAttr),
|
.attr(FriendshipPowerAttr),
|
||||||
new AttackMove(Moves.PRESENT, "Present (N)", Type.NORMAL, MoveCategory.PHYSICAL, -1, 90, 15, "The user attacks by giving the target a gift with a hidden trap. It restores HP sometimes, however.", -1, 0, 2)
|
new AttackMove(Moves.PRESENT, "Present", Type.NORMAL, MoveCategory.PHYSICAL, -1, 90, 15, "The user attacks by giving the target a gift with a hidden trap. It restores HP sometimes, however.", -1, 0, 2)
|
||||||
|
.attr(PresentPowerAttr)
|
||||||
.makesContact(false),
|
.makesContact(false),
|
||||||
new AttackMove(Moves.FRUSTRATION, "Frustration", Type.NORMAL, MoveCategory.PHYSICAL, -1, 100, 20, "This full-power attack grows more powerful the less the user likes its Trainer.", -1, 0, 2)
|
new AttackMove(Moves.FRUSTRATION, "Frustration", Type.NORMAL, MoveCategory.PHYSICAL, -1, 100, 20, "This full-power attack grows more powerful the less the user likes its Trainer.", -1, 0, 2)
|
||||||
.attr(FriendshipPowerAttr, true),
|
.attr(FriendshipPowerAttr, true),
|
||||||
@ -3799,6 +4012,7 @@ export function initMoves() {
|
|||||||
new AttackMove(Moves.MAGNITUDE, "Magnitude", Type.GROUND, MoveCategory.PHYSICAL, -1, 100, 30, "The user attacks everything around it with a ground-shaking quake. Its power varies.", -1, 0, 2)
|
new AttackMove(Moves.MAGNITUDE, "Magnitude", Type.GROUND, MoveCategory.PHYSICAL, -1, 100, 30, "The user attacks everything around it with a ground-shaking quake. Its power varies.", -1, 0, 2)
|
||||||
.attr(PreMoveMessageAttr, magnitudeMessageFunc)
|
.attr(PreMoveMessageAttr, magnitudeMessageFunc)
|
||||||
.attr(MagnitudePowerAttr)
|
.attr(MagnitudePowerAttr)
|
||||||
|
.attr(HitsTagAttr, BattlerTagType.UNDERGROUND, true)
|
||||||
.makesContact(false)
|
.makesContact(false)
|
||||||
.target(MoveTarget.ALL_NEAR_OTHERS),
|
.target(MoveTarget.ALL_NEAR_OTHERS),
|
||||||
new AttackMove(Moves.DYNAMIC_PUNCH, "Dynamic Punch", Type.FIGHTING, MoveCategory.PHYSICAL, 100, 50, 5, "The user punches the target with full, concentrated power. This confuses the target if it hits.", 100, 0, 2)
|
new AttackMove(Moves.DYNAMIC_PUNCH, "Dynamic Punch", Type.FIGHTING, MoveCategory.PHYSICAL, 100, 50, 5, "The user punches the target with full, concentrated power. This confuses the target if it hits.", 100, 0, 2)
|
||||||
@ -3867,7 +4081,8 @@ export function initMoves() {
|
|||||||
new AttackMove(Moves.ROCK_SMASH, "Rock Smash", Type.FIGHTING, MoveCategory.PHYSICAL, 40, 100, 15, "The user attacks with a punch. This may also lower the target's Defense stat.", 50, 0, 2)
|
new AttackMove(Moves.ROCK_SMASH, "Rock Smash", Type.FIGHTING, MoveCategory.PHYSICAL, 40, 100, 15, "The user attacks with a punch. This may also lower the target's Defense stat.", 50, 0, 2)
|
||||||
.attr(StatChangeAttr, BattleStat.DEF, -1),
|
.attr(StatChangeAttr, BattleStat.DEF, -1),
|
||||||
new AttackMove(Moves.WHIRLPOOL, "Whirlpool", Type.WATER, MoveCategory.SPECIAL, 35, 85, 15, "The user traps the target in a violent swirling whirlpool for four to five turns.", 100, 0, 2)
|
new AttackMove(Moves.WHIRLPOOL, "Whirlpool", Type.WATER, MoveCategory.SPECIAL, 35, 85, 15, "The user traps the target in a violent swirling whirlpool for four to five turns.", 100, 0, 2)
|
||||||
.attr(TrapAttr, BattlerTagType.WHIRLPOOL),
|
.attr(TrapAttr, BattlerTagType.WHIRLPOOL)
|
||||||
|
.attr(HitsTagAttr, BattlerTagType.UNDERWATER, true),
|
||||||
new AttackMove(Moves.BEAT_UP, "Beat Up (N)", Type.DARK, MoveCategory.PHYSICAL, -1, 100, 10, "The user gets all party Pokémon to attack the target. The more party Pokémon, the greater the number of attacks.", -1, 0, 2)
|
new AttackMove(Moves.BEAT_UP, "Beat Up (N)", Type.DARK, MoveCategory.PHYSICAL, -1, 100, 10, "The user gets all party Pokémon to attack the target. The more party Pokémon, the greater the number of attacks.", -1, 0, 2)
|
||||||
.makesContact(false),
|
.makesContact(false),
|
||||||
new AttackMove(Moves.FAKE_OUT, "Fake Out", Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 10, "This attack hits first and makes the target flinch. It only works the first turn each time the user enters battle.", 100, 3, 3)
|
new AttackMove(Moves.FAKE_OUT, "Fake Out", Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 10, "This attack hits first and makes the target flinch. It only works the first turn each time the user enters battle.", 100, 3, 3)
|
||||||
@ -3909,7 +4124,9 @@ export function initMoves() {
|
|||||||
.attr(MovePowerMultiplierAttr, (user, target, move) => target.status?.effect === StatusEffect.PARALYSIS ? 2 : 1)
|
.attr(MovePowerMultiplierAttr, (user, target, move) => target.status?.effect === StatusEffect.PARALYSIS ? 2 : 1)
|
||||||
.attr(HealStatusEffectAttr, true, StatusEffect.PARALYSIS),
|
.attr(HealStatusEffectAttr, true, StatusEffect.PARALYSIS),
|
||||||
new SelfStatusMove(Moves.FOLLOW_ME, "Follow Me (N)", Type.NORMAL, -1, 20, "The user draws attention to itself, making all targets take aim only at the user.", -1, 2, 3),
|
new SelfStatusMove(Moves.FOLLOW_ME, "Follow Me (N)", Type.NORMAL, -1, 20, "The user draws attention to itself, making all targets take aim only at the user.", -1, 2, 3),
|
||||||
new StatusMove(Moves.NATURE_POWER, "Nature Power (N)", Type.NORMAL, -1, 20, "This attack makes use of nature's power. Its effects vary depending on the user's environment.", -1, 0, 3),
|
new StatusMove(Moves.NATURE_POWER, "Nature Power", Type.NORMAL, -1, 20, "This attack makes use of nature's power. Its effects vary depending on the user's environment.", -1, 0, 3)
|
||||||
|
.attr(NaturePowerAttr)
|
||||||
|
.ignoresVirtual(),
|
||||||
new SelfStatusMove(Moves.CHARGE, "Charge (P)", Type.ELECTRIC, -1, 20, "The user boosts the power of the Electric move it uses on the next turn. This also raises the user's Sp. Def stat.", -1, 0, 3)
|
new SelfStatusMove(Moves.CHARGE, "Charge (P)", Type.ELECTRIC, -1, 20, "The user boosts the power of the Electric move it uses on the next turn. This also raises the user's Sp. Def stat.", -1, 0, 3)
|
||||||
.attr(StatChangeAttr, BattleStat.SPDEF, 1, true),
|
.attr(StatChangeAttr, BattleStat.SPDEF, 1, true),
|
||||||
new StatusMove(Moves.TAUNT, "Taunt (N)", Type.DARK, 100, 20, "The target is taunted into a rage that allows it to use only attack moves for three turns.", -1, 0, 3),
|
new StatusMove(Moves.TAUNT, "Taunt (N)", Type.DARK, 100, 20, "The target is taunted into a rage that allows it to use only attack moves for three turns.", -1, 0, 3),
|
||||||
@ -3955,7 +4172,7 @@ export function initMoves() {
|
|||||||
new AttackMove(Moves.SECRET_POWER, "Secret Power (P)", Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 20, "The additional effects of this attack depend upon where it was used.", 30, 0, 3)
|
new AttackMove(Moves.SECRET_POWER, "Secret Power (P)", Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 20, "The additional effects of this attack depend upon where it was used.", 30, 0, 3)
|
||||||
.makesContact(false),
|
.makesContact(false),
|
||||||
new AttackMove(Moves.DIVE, "Dive", Type.WATER, MoveCategory.PHYSICAL, 80, 100, 10, "Diving on the first turn, the user floats up and attacks on the next turn.", -1, 0, 3)
|
new AttackMove(Moves.DIVE, "Dive", Type.WATER, MoveCategory.PHYSICAL, 80, 100, 10, "Diving on the first turn, the user floats up and attacks on the next turn.", -1, 0, 3)
|
||||||
.attr(ChargeAttr, ChargeAnim.DIVE_CHARGING, 'hid\nunderwater!', BattlerTagType.UNDERGROUND)
|
.attr(ChargeAttr, ChargeAnim.DIVE_CHARGING, 'hid\nunderwater!', BattlerTagType.UNDERWATER)
|
||||||
.ignoresVirtual(),
|
.ignoresVirtual(),
|
||||||
new AttackMove(Moves.ARM_THRUST, "Arm Thrust", Type.FIGHTING, MoveCategory.PHYSICAL, 15, 100, 20, "The user lets loose a flurry of open-palmed arm thrusts that hit two to five times in a row.", -1, 0, 3)
|
new AttackMove(Moves.ARM_THRUST, "Arm Thrust", Type.FIGHTING, MoveCategory.PHYSICAL, 15, 100, 20, "The user lets loose a flurry of open-palmed arm thrusts that hit two to five times in a row.", -1, 0, 3)
|
||||||
.attr(MultiHitAttr),
|
.attr(MultiHitAttr),
|
||||||
@ -4008,7 +4225,7 @@ export function initMoves() {
|
|||||||
.attr(FlinchAttr),
|
.attr(FlinchAttr),
|
||||||
new AttackMove(Moves.WEATHER_BALL, "Weather Ball", Type.NORMAL, MoveCategory.SPECIAL, 50, 100, 10, "This attack move varies in power and type depending on the weather.", -1, 0, 3)
|
new AttackMove(Moves.WEATHER_BALL, "Weather Ball", Type.NORMAL, MoveCategory.SPECIAL, 50, 100, 10, "This attack move varies in power and type depending on the weather.", -1, 0, 3)
|
||||||
.attr(WeatherBallTypeAttr)
|
.attr(WeatherBallTypeAttr)
|
||||||
.attr(MovePowerMultiplierAttr, (user, target, move) => [WeatherType.SUNNY, WeatherType.RAIN, WeatherType.SANDSTORM, WeatherType.HAIL, WeatherType.FOG, WeatherType.HEAVY_RAIN, WeatherType.HARSH_SUN].includes(user.scene.arena.weather?.weatherType) && !user.scene.arena.weather?.isEffectSuppressed(user.scene) ? 2 : 1)
|
.attr(MovePowerMultiplierAttr, (user, target, move) => [WeatherType.SUNNY, WeatherType.RAIN, WeatherType.SANDSTORM, WeatherType.HAIL, WeatherType.SNOW, WeatherType.FOG, WeatherType.HEAVY_RAIN, WeatherType.HARSH_SUN].includes(user.scene.arena.weather?.weatherType) && !user.scene.arena.weather?.isEffectSuppressed(user.scene) ? 2 : 1)
|
||||||
.ballBombMove(),
|
.ballBombMove(),
|
||||||
new StatusMove(Moves.AROMATHERAPY, "Aromatherapy (N)", Type.GRASS, -1, 5, "The user releases a soothing scent that heals all status conditions affecting the user's party.", -1, 0, 3)
|
new StatusMove(Moves.AROMATHERAPY, "Aromatherapy (N)", Type.GRASS, -1, 5, "The user releases a soothing scent that heals all status conditions affecting the user's party.", -1, 0, 3)
|
||||||
.target(MoveTarget.USER_AND_ALLIES),
|
.target(MoveTarget.USER_AND_ALLIES),
|
||||||
@ -4425,6 +4642,7 @@ export function initMoves() {
|
|||||||
.target(MoveTarget.BOTH_SIDES),
|
.target(MoveTarget.BOTH_SIDES),
|
||||||
new AttackMove(Moves.SMACK_DOWN, "Smack Down", Type.ROCK, MoveCategory.PHYSICAL, 50, 100, 15, "The user throws a stone or similar projectile to attack the target. A flying Pokémon will fall to the ground when it's hit.", 100, 0, 5)
|
new AttackMove(Moves.SMACK_DOWN, "Smack Down", Type.ROCK, MoveCategory.PHYSICAL, 50, 100, 15, "The user throws a stone or similar projectile to attack the target. A flying Pokémon will fall to the ground when it's hit.", 100, 0, 5)
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.IGNORE_FLYING, false, false, 5)
|
.attr(AddBattlerTagAttr, BattlerTagType.IGNORE_FLYING, false, false, 5)
|
||||||
|
.attr(HitsTagAttr, BattlerTagType.FLYING, false)
|
||||||
.makesContact(false),
|
.makesContact(false),
|
||||||
new AttackMove(Moves.STORM_THROW, "Storm Throw", Type.FIGHTING, MoveCategory.PHYSICAL, 60, 100, 10, "The user strikes the target with a fierce blow. This attack always results in a critical hit.", -1, 0, 5)
|
new AttackMove(Moves.STORM_THROW, "Storm Throw", Type.FIGHTING, MoveCategory.PHYSICAL, 60, 100, 10, "The user strikes the target with a fierce blow. This attack always results in a critical hit.", -1, 0, 5)
|
||||||
.attr(CritOnlyAttr),
|
.attr(CritOnlyAttr),
|
||||||
@ -4565,6 +4783,7 @@ export function initMoves() {
|
|||||||
new AttackMove(Moves.HURRICANE, "Hurricane", Type.FLYING, MoveCategory.SPECIAL, 110, 70, 10, "The user attacks by wrapping its opponent in a fierce wind that flies up into the sky. This may also confuse the target.", 30, 0, 5)
|
new AttackMove(Moves.HURRICANE, "Hurricane", Type.FLYING, MoveCategory.SPECIAL, 110, 70, 10, "The user attacks by wrapping its opponent in a fierce wind that flies up into the sky. This may also confuse the target.", 30, 0, 5)
|
||||||
.attr(ThunderAccuracyAttr)
|
.attr(ThunderAccuracyAttr)
|
||||||
.attr(ConfuseAttr)
|
.attr(ConfuseAttr)
|
||||||
|
.attr(HitsTagAttr, BattlerTagType.FLYING, false)
|
||||||
.windMove(),
|
.windMove(),
|
||||||
new AttackMove(Moves.HEAD_CHARGE, "Head Charge", Type.NORMAL, MoveCategory.PHYSICAL, 120, 100, 15, "The user charges its head into its target, using its powerful guard hair. This also damages the user a little.", -1, 0, 5)
|
new AttackMove(Moves.HEAD_CHARGE, "Head Charge", Type.NORMAL, MoveCategory.PHYSICAL, 120, 100, 15, "The user charges its head into its target, using its powerful guard hair. This also damages the user a little.", -1, 0, 5)
|
||||||
.attr(RecoilAttr),
|
.attr(RecoilAttr),
|
||||||
@ -4715,9 +4934,9 @@ export function initMoves() {
|
|||||||
.attr(StatChangeAttr, [ BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD ], 2, true)
|
.attr(StatChangeAttr, [ BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD ], 2, true)
|
||||||
.ignoresVirtual(),
|
.ignoresVirtual(),
|
||||||
new StatusMove(Moves.MAGNETIC_FLUX, "Magnetic Flux", Type.ELECTRIC, -1, 20, "The user manipulates magnetic fields, which raises the Defense and Sp. Def stats of ally Pokémon with the Plus or Minus Ability.", -1, 0, 6)
|
new StatusMove(Moves.MAGNETIC_FLUX, "Magnetic Flux", Type.ELECTRIC, -1, 20, "The user manipulates magnetic fields, which raises the Defense and Sp. Def stats of ally Pokémon with the Plus or Minus Ability.", -1, 0, 6)
|
||||||
.attr(StatChangeAttr, [ BattleStat.DEF, BattleStat.SPDEF ], 1, false, (user, target, move) => !![ Abilities.PLUS, Abilities.MINUS].find(a => a === user.getAbility().id || (user.canApplyPassive() && a === user.getPassiveAbility().id)))
|
.attr(StatChangeAttr, [ BattleStat.DEF, BattleStat.SPDEF ], 1, false, (user, target, move) => !![ Abilities.PLUS, Abilities.MINUS].find(a => target.hasAbility(a, false)))
|
||||||
.target(MoveTarget.USER_AND_ALLIES)
|
.target(MoveTarget.USER_AND_ALLIES)
|
||||||
.condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS].find(a => a === p.getAbility().id || (user.canApplyPassive() && a === user.getPassiveAbility().id)))),
|
.condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS].find(a => p.hasAbility(a, false)))),
|
||||||
new StatusMove(Moves.HAPPY_HOUR, "Happy Hour (N)", Type.NORMAL, -1, 30, "Using Happy Hour doubles the amount of prize money received after battle.", -1, 0, 6) // No animation
|
new StatusMove(Moves.HAPPY_HOUR, "Happy Hour (N)", Type.NORMAL, -1, 30, "Using Happy Hour doubles the amount of prize money received after battle.", -1, 0, 6) // No animation
|
||||||
.target(MoveTarget.USER_SIDE),
|
.target(MoveTarget.USER_SIDE),
|
||||||
new StatusMove(Moves.ELECTRIC_TERRAIN, "Electric Terrain", Type.ELECTRIC, -1, 10, "The user electrifies the ground for five turns, powering up Electric-type moves. Pokémon on the ground no longer fall asleep.", -1, 0, 6)
|
new StatusMove(Moves.ELECTRIC_TERRAIN, "Electric Terrain", Type.ELECTRIC, -1, 10, "The user electrifies the ground for five turns, powering up Electric-type moves. Pokémon on the ground no longer fall asleep.", -1, 0, 6)
|
||||||
@ -4744,6 +4963,7 @@ export function initMoves() {
|
|||||||
.triageMove(),
|
.triageMove(),
|
||||||
new AttackMove(Moves.THOUSAND_ARROWS, "Thousand Arrows", Type.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, "This move also hits opposing Pokémon that are in the air. Those Pokémon are knocked down to the ground.", 100, 0, 6)
|
new AttackMove(Moves.THOUSAND_ARROWS, "Thousand Arrows", Type.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, "This move also hits opposing Pokémon that are in the air. Those Pokémon are knocked down to the ground.", 100, 0, 6)
|
||||||
.attr(NeutralDamageAgainstFlyingTypeMultiplierAttr)
|
.attr(NeutralDamageAgainstFlyingTypeMultiplierAttr)
|
||||||
|
.attr(HitsTagAttr, BattlerTagType.FLYING, false)
|
||||||
.makesContact(false)
|
.makesContact(false)
|
||||||
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
||||||
new AttackMove(Moves.THOUSAND_WAVES, "Thousand Waves", Type.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, "The user attacks with a wave that crawls along the ground. Those it hits can't flee from battle.", -1, 0, 6)
|
new AttackMove(Moves.THOUSAND_WAVES, "Thousand Waves", Type.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, "The user attacks with a wave that crawls along the ground. Those it hits can't flee from battle.", -1, 0, 6)
|
||||||
@ -4845,9 +5065,9 @@ export function initMoves() {
|
|||||||
new SelfStatusMove(Moves.LASER_FOCUS, "Laser Focus", Type.NORMAL, -1, 30, "The user concentrates intensely. The attack on the next turn always results in a critical hit.", -1, 0, 7)
|
new SelfStatusMove(Moves.LASER_FOCUS, "Laser Focus", Type.NORMAL, -1, 30, "The user concentrates intensely. The attack on the next turn always results in a critical hit.", -1, 0, 7)
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.ALWAYS_CRIT, true, false),
|
.attr(AddBattlerTagAttr, BattlerTagType.ALWAYS_CRIT, true, false),
|
||||||
new StatusMove(Moves.GEAR_UP, "Gear Up", Type.STEEL, -1, 20, "The user engages its gears to raise the Attack and Sp. Atk stats of ally Pokémon with the Plus or Minus Ability.", -1, 0, 7)
|
new StatusMove(Moves.GEAR_UP, "Gear Up", Type.STEEL, -1, 20, "The user engages its gears to raise the Attack and Sp. Atk stats of ally Pokémon with the Plus or Minus Ability.", -1, 0, 7)
|
||||||
.attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK ], 1, false, (user, target, move) => [ Abilities.PLUS, Abilities.MINUS ].includes(target.getAbility().id) || (target.canApplyPassive() && [ Abilities.PLUS, Abilities.MINUS ].includes(target.getPassiveAbility().id)))
|
.attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK ], 1, false, (user, target, move) => !![ Abilities.PLUS, Abilities.MINUS].find(a => target.hasAbility(a, false)))
|
||||||
.target(MoveTarget.USER_AND_ALLIES)
|
.target(MoveTarget.USER_AND_ALLIES)
|
||||||
.condition((user, target, move) => !![ user, user.getAlly() ].find(p => p && [ Abilities.PLUS, Abilities.MINUS ].includes(p.getAbility().id) || (target.canApplyPassive() && [ Abilities.PLUS, Abilities.MINUS ].includes(target.getPassiveAbility().id)))),
|
.condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS].find(a => p.hasAbility(a, false)))),
|
||||||
new AttackMove(Moves.THROAT_CHOP, "Throat Chop (P)", Type.DARK, MoveCategory.PHYSICAL, 80, 100, 15, "The user attacks the target's throat, and the resultant suffering prevents the target from using moves that emit sound for two turns.", 100, 0, 7),
|
new AttackMove(Moves.THROAT_CHOP, "Throat Chop (P)", Type.DARK, MoveCategory.PHYSICAL, 80, 100, 15, "The user attacks the target's throat, and the resultant suffering prevents the target from using moves that emit sound for two turns.", 100, 0, 7),
|
||||||
new AttackMove(Moves.POLLEN_PUFF, "Pollen Puff (P)", Type.BUG, MoveCategory.SPECIAL, 90, 100, 15, "The user attacks the enemy with a pollen puff that explodes. If the target is an ally, it gives the ally a pollen puff that restores its HP instead.", -1, 0, 7)
|
new AttackMove(Moves.POLLEN_PUFF, "Pollen Puff (P)", Type.BUG, MoveCategory.SPECIAL, 90, 100, 15, "The user attacks the enemy with a pollen puff that explodes. If the target is an ally, it gives the ally a pollen puff that restores its HP instead.", -1, 0, 7)
|
||||||
.ballBombMove(),
|
.ballBombMove(),
|
||||||
@ -4886,8 +5106,8 @@ export function initMoves() {
|
|||||||
new AttackMove(Moves.DRAGON_HAMMER, "Dragon Hammer", Type.DRAGON, MoveCategory.PHYSICAL, 90, 100, 15, "The user uses its body like a hammer to attack the target and inflict damage.", -1, 0, 7),
|
new AttackMove(Moves.DRAGON_HAMMER, "Dragon Hammer", Type.DRAGON, MoveCategory.PHYSICAL, 90, 100, 15, "The user uses its body like a hammer to attack the target and inflict damage.", -1, 0, 7),
|
||||||
new AttackMove(Moves.BRUTAL_SWING, "Brutal Swing", Type.DARK, MoveCategory.PHYSICAL, 60, 100, 20, "The user swings its body around violently to inflict damage on everything in its vicinity.", -1, 0, 7)
|
new AttackMove(Moves.BRUTAL_SWING, "Brutal Swing", Type.DARK, MoveCategory.PHYSICAL, 60, 100, 20, "The user swings its body around violently to inflict damage on everything in its vicinity.", -1, 0, 7)
|
||||||
.target(MoveTarget.ALL_NEAR_OTHERS),
|
.target(MoveTarget.ALL_NEAR_OTHERS),
|
||||||
new StatusMove(Moves.AURORA_VEIL, "Aurora Veil", Type.ICE, -1, 20, "This move reduces damage from physical and special moves for five turns. This can be used only in a hailstorm.", -1, 0, 7)
|
new StatusMove(Moves.AURORA_VEIL, "Aurora Veil", Type.ICE, -1, 20, "This move reduces damage from physical and special moves for five turns. This can be used only when it is snowing.", -1, 0, 7)
|
||||||
.condition((user, target, move) => user.scene.arena.weather?.weatherType === WeatherType.HAIL && !user.scene.arena.weather?.isEffectSuppressed(user.scene))
|
.condition((user, target, move) => (user.scene.arena.weather?.weatherType === WeatherType.HAIL || user.scene.arena.weather?.weatherType === WeatherType.SNOW) && !user.scene.arena.weather?.isEffectSuppressed(user.scene))
|
||||||
.attr(AddArenaTagAttr, ArenaTagType.AURORA_VEIL, 5, true)
|
.attr(AddArenaTagAttr, ArenaTagType.AURORA_VEIL, 5, true)
|
||||||
.target(MoveTarget.USER_SIDE),
|
.target(MoveTarget.USER_SIDE),
|
||||||
/* Unused */
|
/* Unused */
|
||||||
@ -5407,13 +5627,13 @@ export function initMoves() {
|
|||||||
.makesContact(),
|
.makesContact(),
|
||||||
new SelfStatusMove(Moves.SHED_TAIL, "Shed Tail (N)", Type.NORMAL, -1, 10, "The user creates a substitute for itself using its own HP before switching places with a party Pokémon in waiting.", -1, 0, 9),
|
new SelfStatusMove(Moves.SHED_TAIL, "Shed Tail (N)", Type.NORMAL, -1, 10, "The user creates a substitute for itself using its own HP before switching places with a party Pokémon in waiting.", -1, 0, 9),
|
||||||
new StatusMove(Moves.CHILLY_RECEPTION, "Chilly Reception", Type.ICE, -1, 10, "The user tells a chillingly bad joke before switching places with a party Pokémon in waiting. This summons a snowstorm lasting five turns.", -1, 0, 9)
|
new StatusMove(Moves.CHILLY_RECEPTION, "Chilly Reception", Type.ICE, -1, 10, "The user tells a chillingly bad joke before switching places with a party Pokémon in waiting. This summons a snowstorm lasting five turns.", -1, 0, 9)
|
||||||
.attr(WeatherChangeAttr, WeatherType.HAIL) // Set to Hail for now, if Snow is added in the future, change this
|
.attr(WeatherChangeAttr, WeatherType.SNOW)
|
||||||
.attr(ForceSwitchOutAttr, true, false)
|
.attr(ForceSwitchOutAttr, true, false)
|
||||||
.target(MoveTarget.BOTH_SIDES),
|
.target(MoveTarget.BOTH_SIDES),
|
||||||
new SelfStatusMove(Moves.TIDY_UP, "Tidy Up (P)", Type.NORMAL, -1, 10, "The user tidies up and removes the effects of Spikes, Stealth Rock, Sticky Web, Toxic Spikes, and Substitute. This also boosts the user's Attack and Speed stats.", 100, 0, 9)
|
new SelfStatusMove(Moves.TIDY_UP, "Tidy Up (P)", Type.NORMAL, -1, 10, "The user tidies up and removes the effects of Spikes, Stealth Rock, Sticky Web, Toxic Spikes, and Substitute. This also boosts the user's Attack and Speed stats.", 100, 0, 9)
|
||||||
.attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPD ], 1, true),
|
.attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPD ], 1, true),
|
||||||
new StatusMove(Moves.SNOWSCAPE, "Snowscape", Type.ICE, -1, 10, "The user summons a snowstorm lasting five turns. This boosts the Defense stats of Ice types.", -1, 0, 9)
|
new StatusMove(Moves.SNOWSCAPE, "Snowscape", Type.ICE, -1, 10, "The user summons a snowstorm lasting five turns. This boosts the Defense stats of Ice types.", -1, 0, 9)
|
||||||
.attr(WeatherChangeAttr, WeatherType.HAIL) // Set to Hail for now, if Snow is added in the future, change this
|
.attr(WeatherChangeAttr, WeatherType.SNOW)
|
||||||
.target(MoveTarget.BOTH_SIDES),
|
.target(MoveTarget.BOTH_SIDES),
|
||||||
new AttackMove(Moves.POUNCE, "Pounce", Type.BUG, MoveCategory.PHYSICAL, 50, 100, 20, "The user attacks by pouncing on the target. This also lowers the target's Speed stat.", 100, 0, 9)
|
new AttackMove(Moves.POUNCE, "Pounce", Type.BUG, MoveCategory.PHYSICAL, 50, 100, 20, "The user attacks by pouncing on the target. This also lowers the target's Speed stat.", 100, 0, 9)
|
||||||
.attr(StatChangeAttr, BattleStat.SPD, -1),
|
.attr(StatChangeAttr, BattleStat.SPD, -1),
|
||||||
@ -5477,7 +5697,8 @@ export function initMoves() {
|
|||||||
new AttackMove(Moves.SYRUP_BOMB, "Syrup Bomb (P)", Type.GRASS, MoveCategory.SPECIAL, 60, 85, 10, "The user sets off an explosion of sticky candy syrup, which coats the target and causes the target's Speed stat to drop each turn for three turns.", -1, 0, 9)
|
new AttackMove(Moves.SYRUP_BOMB, "Syrup Bomb (P)", Type.GRASS, MoveCategory.SPECIAL, 60, 85, 10, "The user sets off an explosion of sticky candy syrup, which coats the target and causes the target's Speed stat to drop each turn for three turns.", -1, 0, 9)
|
||||||
.attr(StatChangeAttr, BattleStat.SPD, -1) //Temporary
|
.attr(StatChangeAttr, BattleStat.SPD, -1) //Temporary
|
||||||
.ballBombMove(),
|
.ballBombMove(),
|
||||||
new AttackMove(Moves.IVY_CUDGEL, "Ivy Cudgel (P)", Type.GRASS, MoveCategory.PHYSICAL, 100, 100, 10, "The user strikes with an ivy-wrapped cudgel. This move's type changes depending on the mask worn by the user, and it has a heightened chance of landing a critical hit.", -1, 0, 9)
|
new AttackMove(Moves.IVY_CUDGEL, "Ivy Cudgel", Type.GRASS, MoveCategory.PHYSICAL, 100, 100, 10, "The user strikes with an ivy-wrapped cudgel. This move's type changes depending on the mask worn by the user, and it has a heightened chance of landing a critical hit.", -1, 0, 9)
|
||||||
|
.attr(IvyCudgelTypeAttr)
|
||||||
.attr(HighCritAttr)
|
.attr(HighCritAttr)
|
||||||
.makesContact(false),
|
.makesContact(false),
|
||||||
new AttackMove(Moves.ELECTRO_SHOT, "Electro Shot", Type.ELECTRIC, MoveCategory.SPECIAL, 130, 100, 10, "The user gathers electricity on the first turn, boosting its Sp. Atk stat, then fires a high-voltage shot on the next turn. The shot will be fired immediately in rain.", 100, 0, 9)
|
new AttackMove(Moves.ELECTRO_SHOT, "Electro Shot", Type.ELECTRIC, MoveCategory.SPECIAL, 130, 100, 10, "The user gathers electricity on the first turn, boosting its Sp. Atk stat, then fires a high-voltage shot on the next turn. The shot will be fired immediately in rain.", 100, 0, 9)
|
||||||
|
@ -968,8 +968,8 @@ export const pokemonEvolutions: PokemonEvolutions = {
|
|||||||
new SpeciesEvolution(Species.COSMOEM, 43, null, null)
|
new SpeciesEvolution(Species.COSMOEM, 43, null, null)
|
||||||
],
|
],
|
||||||
[Species.COSMOEM]: [
|
[Species.COSMOEM]: [
|
||||||
new SpeciesEvolution(Species.SOLGALEO, 53, null, new SpeciesEvolutionCondition(p => p.scene.arena.biomeType !== Biome.SPACE && p.scene.arena.getTimeOfDay() === TimeOfDay.DAY), null),
|
new SpeciesEvolution(Species.SOLGALEO, 53, null, new SpeciesEvolutionCondition(p => p.scene.arena.getTimeOfDay() === TimeOfDay.DAY), null),
|
||||||
new SpeciesEvolution(Species.LUNALA, 53, null, new SpeciesEvolutionCondition(p => p.scene.arena.biomeType !== Biome.SPACE && p.scene.arena.getTimeOfDay() === TimeOfDay.NIGHT), null)
|
new SpeciesEvolution(Species.LUNALA, 53, null, new SpeciesEvolutionCondition(p => p.scene.arena.getTimeOfDay() === TimeOfDay.NIGHT), null)
|
||||||
],
|
],
|
||||||
[Species.MELTAN]: [
|
[Species.MELTAN]: [
|
||||||
new SpeciesEvolution(Species.MELMETAL, 48, null, null)
|
new SpeciesEvolution(Species.MELMETAL, 48, null, null)
|
||||||
|
@ -535,8 +535,8 @@ export const pokemonFormChanges: PokemonFormChanges = {
|
|||||||
new SpeciesFormChange(Species.MELOETTA, 'pirouette', 'aria', new SpeciesFormChangeActiveTrigger(false), true)
|
new SpeciesFormChange(Species.MELOETTA, 'pirouette', 'aria', new SpeciesFormChangeActiveTrigger(false), true)
|
||||||
],
|
],
|
||||||
[Species.AEGISLASH]: [
|
[Species.AEGISLASH]: [
|
||||||
new SpeciesFormChange(Species.AEGISLASH, 'blade', 'shield', new SpeciesFormChangePreMoveTrigger(Moves.KINGS_SHIELD), true, new SpeciesFormChangeCondition(p => p.getAbility().id === Abilities.STANCE_CHANGE)),
|
new SpeciesFormChange(Species.AEGISLASH, 'blade', 'shield', new SpeciesFormChangePreMoveTrigger(Moves.KINGS_SHIELD), true, new SpeciesFormChangeCondition(p => p.hasAbility(Abilities.STANCE_CHANGE))),
|
||||||
new SpeciesFormChange(Species.AEGISLASH, 'shield', 'blade', new SpeciesFormChangePreMoveTrigger(m => allMoves[m].category !== MoveCategory.STATUS), true, new SpeciesFormChangeCondition(p => p.getAbility().id === Abilities.STANCE_CHANGE)),
|
new SpeciesFormChange(Species.AEGISLASH, 'shield', 'blade', new SpeciesFormChangePreMoveTrigger(m => allMoves[m].category !== MoveCategory.STATUS), true, new SpeciesFormChangeCondition(p => p.hasAbility(Abilities.STANCE_CHANGE))),
|
||||||
new SpeciesFormChange(Species.AEGISLASH, 'blade', 'shield', new SpeciesFormChangeActiveTrigger(false), true)
|
new SpeciesFormChange(Species.AEGISLASH, 'blade', 'shield', new SpeciesFormChangeActiveTrigger(false), true)
|
||||||
],
|
],
|
||||||
[Species.DIANCIE]: [
|
[Species.DIANCIE]: [
|
||||||
@ -549,6 +549,22 @@ export const pokemonFormChanges: PokemonFormChanges = {
|
|||||||
new SpeciesFormChange(Species.WISHIWASHI, '', 'school', new SpeciesFormChangeManualTrigger(), true),
|
new SpeciesFormChange(Species.WISHIWASHI, '', 'school', new SpeciesFormChangeManualTrigger(), true),
|
||||||
new SpeciesFormChange(Species.WISHIWASHI, 'school', '', new SpeciesFormChangeManualTrigger(), true)
|
new SpeciesFormChange(Species.WISHIWASHI, 'school', '', new SpeciesFormChangeManualTrigger(), true)
|
||||||
],
|
],
|
||||||
|
[Species.MINIOR]: [
|
||||||
|
new SpeciesFormChange(Species.MINIOR, 'red-meteor', 'red', new SpeciesFormChangeManualTrigger(), true),
|
||||||
|
new SpeciesFormChange(Species.MINIOR, 'red', 'red-meteor', new SpeciesFormChangeManualTrigger(), true),
|
||||||
|
new SpeciesFormChange(Species.MINIOR, 'orange-meteor', 'orange', new SpeciesFormChangeManualTrigger(), true),
|
||||||
|
new SpeciesFormChange(Species.MINIOR, 'orange', 'orange-meteor', new SpeciesFormChangeManualTrigger(), true),
|
||||||
|
new SpeciesFormChange(Species.MINIOR, 'yellow-meteor', 'yellow', new SpeciesFormChangeManualTrigger(), true),
|
||||||
|
new SpeciesFormChange(Species.MINIOR, 'yellow', 'yellow-meteor', new SpeciesFormChangeManualTrigger(), true),
|
||||||
|
new SpeciesFormChange(Species.MINIOR, 'green-meteor', 'green', new SpeciesFormChangeManualTrigger(), true),
|
||||||
|
new SpeciesFormChange(Species.MINIOR, 'green', 'green-meteor', new SpeciesFormChangeManualTrigger(), true),
|
||||||
|
new SpeciesFormChange(Species.MINIOR, 'blue-meteor', 'blue', new SpeciesFormChangeManualTrigger(), true),
|
||||||
|
new SpeciesFormChange(Species.MINIOR, 'blue', 'blue-meteor', new SpeciesFormChangeManualTrigger(), true),
|
||||||
|
new SpeciesFormChange(Species.MINIOR, 'indigo-meteor', 'indigo', new SpeciesFormChangeManualTrigger(), true),
|
||||||
|
new SpeciesFormChange(Species.MINIOR, 'indigo', 'indigo-meteor', new SpeciesFormChangeManualTrigger(), true),
|
||||||
|
new SpeciesFormChange(Species.MINIOR, 'violet-meteor', 'violet', new SpeciesFormChangeManualTrigger(), true),
|
||||||
|
new SpeciesFormChange(Species.MINIOR, 'violet', 'violet-meteor', new SpeciesFormChangeManualTrigger(), true)
|
||||||
|
],
|
||||||
[Species.NECROZMA]: [
|
[Species.NECROZMA]: [
|
||||||
new SpeciesFormChange(Species.NECROZMA, '', 'dawn-wings', new SpeciesFormChangeItemTrigger(FormChangeItem.N_LUNARIZER)),
|
new SpeciesFormChange(Species.NECROZMA, '', 'dawn-wings', new SpeciesFormChangeItemTrigger(FormChangeItem.N_LUNARIZER)),
|
||||||
new SpeciesFormChange(Species.NECROZMA, '', 'dusk-mane', new SpeciesFormChangeItemTrigger(FormChangeItem.N_SOLARIZER))
|
new SpeciesFormChange(Species.NECROZMA, '', 'dusk-mane', new SpeciesFormChangeItemTrigger(FormChangeItem.N_SOLARIZER))
|
||||||
|
@ -15,6 +15,7 @@ splashMessages.push(...[
|
|||||||
'Now with 33% More Salt!',
|
'Now with 33% More Salt!',
|
||||||
'Infinite Fusion at Home!',
|
'Infinite Fusion at Home!',
|
||||||
'Broken Egg Moves!',
|
'Broken Egg Moves!',
|
||||||
|
'Magnificent!',
|
||||||
'Mubstitute!',
|
'Mubstitute!',
|
||||||
'That\'s Crazy!',
|
'That\'s Crazy!',
|
||||||
'Orance Juice!',
|
'Orance Juice!',
|
||||||
|
@ -79,7 +79,7 @@ export const trainerNamePools = {
|
|||||||
[TrainerType.BEAUTY]: ["Cassie","Julia","Olivia","Samantha","Valerie","Victoria","Bridget","Connie","Jessica","Johanna","Melissa","Sheila","Shirley","Tiffany","Namiko","Thalia","Grace","Lola","Lori","Maura","Tamia","Cyndy","Devon","Gabriella","Harley","Lindsay","Nicola","Callie","Charlotte","Kassandra","December","Fleming","Nikola","Aimee","Anais","Brigitte","Cassandra","Andrea","Brittney","Carolyn","Krystal","Alexis","Alice","Aina","Anya","Arianna","Aubrey","Beverly","Camille","Beauty","Evette","Hansol","Haruka","Jill","Jo","Lana","Lois","Lucy","Mai","Nickie","Nicole","Prita","Rose","Shelly","Suzy","Tessa","Anita","Alissa","Rita","Cudsy","Eloff","Miru","Minot","Nevah","Niven","Ogoin"],
|
[TrainerType.BEAUTY]: ["Cassie","Julia","Olivia","Samantha","Valerie","Victoria","Bridget","Connie","Jessica","Johanna","Melissa","Sheila","Shirley","Tiffany","Namiko","Thalia","Grace","Lola","Lori","Maura","Tamia","Cyndy","Devon","Gabriella","Harley","Lindsay","Nicola","Callie","Charlotte","Kassandra","December","Fleming","Nikola","Aimee","Anais","Brigitte","Cassandra","Andrea","Brittney","Carolyn","Krystal","Alexis","Alice","Aina","Anya","Arianna","Aubrey","Beverly","Camille","Beauty","Evette","Hansol","Haruka","Jill","Jo","Lana","Lois","Lucy","Mai","Nickie","Nicole","Prita","Rose","Shelly","Suzy","Tessa","Anita","Alissa","Rita","Cudsy","Eloff","Miru","Minot","Nevah","Niven","Ogoin"],
|
||||||
[TrainerType.BIKER]: ["Charles","Dwayne","Glenn","Harris","Joel","Riley","Zeke","Alex","Billy","Ernest","Gerald","Hideo","Isaac","Jared","Jaren","Jaxon","Jordy","Lao","Lukas","Malik","Nikolas","Ricardo","Ruben","Virgil","William","Aiden","Dale","Dan","Jacob","Markey","Reese","Teddy","Theron","Jeremy","Morgann","Phillip","Philip","Stanley","Dillon"],
|
[TrainerType.BIKER]: ["Charles","Dwayne","Glenn","Harris","Joel","Riley","Zeke","Alex","Billy","Ernest","Gerald","Hideo","Isaac","Jared","Jaren","Jaxon","Jordy","Lao","Lukas","Malik","Nikolas","Ricardo","Ruben","Virgil","William","Aiden","Dale","Dan","Jacob","Markey","Reese","Teddy","Theron","Jeremy","Morgann","Phillip","Philip","Stanley","Dillon"],
|
||||||
[TrainerType.BLACK_BELT]: [["Kenji","Lao","Lung","Nob","Wai","Yoshi","Atsushi","Daisuke","Hideki","Hitoshi","Kiyo","Koichi","Koji","Yuji","Cristian","Rhett","Takao","Theodore","Zander","Aaron","Hugh","Mike","Nicolas","Shea","Takashi","Adam","Carl","Colby","Darren","David","Davon","Derek","Eddie","Gregory","Griffin","Jarrett","Jeffery","Kendal","Kyle","Luke","Miles","Nathaniel","Philip","Rafael","Ray","Ricky","Sean","Willie","Ander","Manford","Benjamin","Corey","Edward","Grant","Jay","Kendrew","Kentaro","Ryder","Teppei","Thomas","Tyrone","Andrey","Donny","Drago","Gordon","Grigor","Jeriel","Kenneth","Martell","Mathis","Rich","Rocky","Rodrigo","Wesley","Zachery","Alonzo","Cadoc","Gunnar","Igor","Killian","Markus","Ricardo","Yanis","Banting","Clayton","Duane","Earl","Greg","Roy","Terry","Tracy","Walter","Alvaro","Curtis","Francis","Ross","Brice","Cheng","Dudley","Eric","Kano","Masahiro","Randy","Ryuji","Steve","Tadashi","Wong","Yuen","Brian","Carter","Reece","Nick","Yang"],["Cora","Cyndy","Jill","Laura","Sadie","Tessa","Vivian","Aisha","Callie","Danielle","Helene","Jocelyn","Lilith","Paula","Reyna","Helen","Kelsey","Tyler","Amy","Chandra","Hillary","Janie","Lee","Maggie","Mikiko","Miriam","Sharon","Susie","Xiao","Alize","Azra","Brenda","Chalina","Chan","Glinda","Maki","Tia","Tiffany","Wendy","Andrea","Gabrielle","Gerardine","Hailey","Hedvig","Justine","Kinsey","Sigrid","Veronique","Tess"]],
|
[TrainerType.BLACK_BELT]: [["Kenji","Lao","Lung","Nob","Wai","Yoshi","Atsushi","Daisuke","Hideki","Hitoshi","Kiyo","Koichi","Koji","Yuji","Cristian","Rhett","Takao","Theodore","Zander","Aaron","Hugh","Mike","Nicolas","Shea","Takashi","Adam","Carl","Colby","Darren","David","Davon","Derek","Eddie","Gregory","Griffin","Jarrett","Jeffery","Kendal","Kyle","Luke","Miles","Nathaniel","Philip","Rafael","Ray","Ricky","Sean","Willie","Ander","Manford","Benjamin","Corey","Edward","Grant","Jay","Kendrew","Kentaro","Ryder","Teppei","Thomas","Tyrone","Andrey","Donny","Drago","Gordon","Grigor","Jeriel","Kenneth","Martell","Mathis","Rich","Rocky","Rodrigo","Wesley","Zachery","Alonzo","Cadoc","Gunnar","Igor","Killian","Markus","Ricardo","Yanis","Banting","Clayton","Duane","Earl","Greg","Roy","Terry","Tracy","Walter","Alvaro","Curtis","Francis","Ross","Brice","Cheng","Dudley","Eric","Kano","Masahiro","Randy","Ryuji","Steve","Tadashi","Wong","Yuen","Brian","Carter","Reece","Nick","Yang"],["Cora","Cyndy","Jill","Laura","Sadie","Tessa","Vivian","Aisha","Callie","Danielle","Helene","Jocelyn","Lilith","Paula","Reyna","Helen","Kelsey","Tyler","Amy","Chandra","Hillary","Janie","Lee","Maggie","Mikiko","Miriam","Sharon","Susie","Xiao","Alize","Azra","Brenda","Chalina","Chan","Glinda","Maki","Tia","Tiffany","Wendy","Andrea","Gabrielle","Gerardine","Hailey","Hedvig","Justine","Kinsey","Sigrid","Veronique","Tess"]],
|
||||||
[TrainerType.BREEDER]: [["Isaac","Myles","Salvadore","Allison","Alize","Bethany","Lily","Albert","Kahlil","Eustace","Galen","Owen","Addison","Marcus","Foster","Cory","Glenn","Jay","Wesley","William","Adrian","Bradley","Jaime"],["Lydia","Gabrielle","Jayden","Pat","Veronica","Amber","Jennifer","Kaylee","Adelaide","Brooke","Ethel","April","Irene","Magnolia","Amala","Mercy","Amanda","Ikue","Savannah","Yuka","Chloe","Debra","Denise","Elena"]],
|
[TrainerType.BREEDER]: [["Isaac","Myles","Salvadore","Albert","Kahlil","Eustace","Galen","Owen","Addison","Marcus","Foster","Cory","Glenn","Jay","Wesley","William","Adrian","Bradley","Jaime"],["Allison","Alize","Bethany","Lily","Lydia","Gabrielle","Jayden","Pat","Veronica","Amber","Jennifer","Kaylee","Adelaide","Brooke","Ethel","April","Irene","Magnolia","Amala","Mercy","Amanda","Ikue","Savannah","Yuka","Chloe","Debra","Denise","Elena"]],
|
||||||
[TrainerType.CLERK]: [["Chaz","Clemens","Doug","Fredric","Ivan","Isaac","Nelson","Wade","Warren","Augustin","Gilligan","Cody","Jeremy","Shane","Dugal","Royce","Ronald"],["Alberta","Ingrid","Katie","Piper","Trisha","Wren","Britney","Lana","Jessica","Kristen","Michelle","Gabrielle"]],
|
[TrainerType.CLERK]: [["Chaz","Clemens","Doug","Fredric","Ivan","Isaac","Nelson","Wade","Warren","Augustin","Gilligan","Cody","Jeremy","Shane","Dugal","Royce","Ronald"],["Alberta","Ingrid","Katie","Piper","Trisha","Wren","Britney","Lana","Jessica","Kristen","Michelle","Gabrielle"]],
|
||||||
[TrainerType.CYCLIST]: [["Axel","James","John","Ryan","Hector","Jeremiah"],["Kayla","Megan","Nicole","Rachel","Krissa","Adelaide"]],
|
[TrainerType.CYCLIST]: [["Axel","James","John","Ryan","Hector","Jeremiah"],["Kayla","Megan","Nicole","Rachel","Krissa","Adelaide"]],
|
||||||
[TrainerType.DANCER]: ["Brian","Davey","Dirk","Edmond","Mickey","Raymond","Cara","Julia","Maika","Mireille","Ronda","Zoe"],
|
[TrainerType.DANCER]: ["Brian","Davey","Dirk","Edmond","Mickey","Raymond","Cara","Julia","Maika","Mireille","Ronda","Zoe"],
|
||||||
|
@ -14,6 +14,7 @@ export enum WeatherType {
|
|||||||
RAIN,
|
RAIN,
|
||||||
SANDSTORM,
|
SANDSTORM,
|
||||||
HAIL,
|
HAIL,
|
||||||
|
SNOW,
|
||||||
FOG,
|
FOG,
|
||||||
HEAVY_RAIN,
|
HEAVY_RAIN,
|
||||||
HARSH_SUN,
|
HARSH_SUN,
|
||||||
@ -108,7 +109,7 @@ export class Weather {
|
|||||||
for (let pokemon of field) {
|
for (let pokemon of field) {
|
||||||
let suppressWeatherEffectAbAttr = pokemon.getAbility().getAttrs(SuppressWeatherEffectAbAttr).find(() => true) as SuppressWeatherEffectAbAttr;
|
let suppressWeatherEffectAbAttr = pokemon.getAbility().getAttrs(SuppressWeatherEffectAbAttr).find(() => true) as SuppressWeatherEffectAbAttr;
|
||||||
if (!suppressWeatherEffectAbAttr)
|
if (!suppressWeatherEffectAbAttr)
|
||||||
suppressWeatherEffectAbAttr = pokemon.canApplyPassive() ? pokemon.getPassiveAbility().getAttrs(SuppressWeatherEffectAbAttr).find(() => true) as SuppressWeatherEffectAbAttr : null;
|
suppressWeatherEffectAbAttr = pokemon.hasPassive() ? pokemon.getPassiveAbility().getAttrs(SuppressWeatherEffectAbAttr).find(() => true) as SuppressWeatherEffectAbAttr : null;
|
||||||
if (suppressWeatherEffectAbAttr && (!this.isImmutable() || suppressWeatherEffectAbAttr.affectsImmutable))
|
if (suppressWeatherEffectAbAttr && (!this.isImmutable() || suppressWeatherEffectAbAttr.affectsImmutable))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -127,6 +128,8 @@ export function getWeatherStartMessage(weatherType: WeatherType): string {
|
|||||||
return 'A sandstorm brewed!';
|
return 'A sandstorm brewed!';
|
||||||
case WeatherType.HAIL:
|
case WeatherType.HAIL:
|
||||||
return 'It started to hail!';
|
return 'It started to hail!';
|
||||||
|
case WeatherType.SNOW:
|
||||||
|
return 'It started to snow!';
|
||||||
case WeatherType.FOG:
|
case WeatherType.FOG:
|
||||||
return 'A thick fog emerged!'
|
return 'A thick fog emerged!'
|
||||||
case WeatherType.HEAVY_RAIN:
|
case WeatherType.HEAVY_RAIN:
|
||||||
@ -150,6 +153,8 @@ export function getWeatherLapseMessage(weatherType: WeatherType): string {
|
|||||||
return 'The sandstorm rages.';
|
return 'The sandstorm rages.';
|
||||||
case WeatherType.HAIL:
|
case WeatherType.HAIL:
|
||||||
return 'Hail continues to fall.';
|
return 'Hail continues to fall.';
|
||||||
|
case WeatherType.SNOW:
|
||||||
|
return 'The snow is falling down.';
|
||||||
case WeatherType.FOG:
|
case WeatherType.FOG:
|
||||||
return 'The fog continues.';
|
return 'The fog continues.';
|
||||||
case WeatherType.HEAVY_RAIN:
|
case WeatherType.HEAVY_RAIN:
|
||||||
@ -184,6 +189,8 @@ export function getWeatherClearMessage(weatherType: WeatherType): string {
|
|||||||
return 'The sandstorm subsided.';
|
return 'The sandstorm subsided.';
|
||||||
case WeatherType.HAIL:
|
case WeatherType.HAIL:
|
||||||
return 'The hail stopped.';
|
return 'The hail stopped.';
|
||||||
|
case WeatherType.SNOW:
|
||||||
|
return 'The snow stopped.';
|
||||||
case WeatherType.FOG:
|
case WeatherType.FOG:
|
||||||
return 'The fog disappeared.'
|
return 'The fog disappeared.'
|
||||||
case WeatherType.HEAVY_RAIN:
|
case WeatherType.HEAVY_RAIN:
|
||||||
@ -292,11 +299,6 @@ export function getRandomWeatherType(arena: any /* Importing from arena causes a
|
|||||||
{ weatherType: WeatherType.RAIN, weight: 1 }
|
{ weatherType: WeatherType.RAIN, weight: 1 }
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
case Biome.MOUNTAIN:
|
|
||||||
weatherPool = [
|
|
||||||
{ weatherType: WeatherType.NONE, weight: 1 }
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
case Biome.BADLANDS:
|
case Biome.BADLANDS:
|
||||||
weatherPool = [
|
weatherPool = [
|
||||||
{ weatherType: WeatherType.NONE, weight: 8 },
|
{ weatherType: WeatherType.NONE, weight: 8 },
|
||||||
@ -314,6 +316,8 @@ export function getRandomWeatherType(arena: any /* Importing from arena causes a
|
|||||||
break;
|
break;
|
||||||
case Biome.ICE_CAVE:
|
case Biome.ICE_CAVE:
|
||||||
weatherPool = [
|
weatherPool = [
|
||||||
|
{ weatherType: WeatherType.NONE, weight: 3 },
|
||||||
|
{ weatherType: WeatherType.SNOW, weight: 4 },
|
||||||
{ weatherType: WeatherType.HAIL, weight: 1 }
|
{ weatherType: WeatherType.HAIL, weight: 1 }
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
@ -334,20 +338,25 @@ export function getRandomWeatherType(arena: any /* Importing from arena causes a
|
|||||||
{ weatherType: WeatherType.FOG, weight: 1 }
|
{ weatherType: WeatherType.FOG, weight: 1 }
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
case Biome.RUINS:
|
case Biome.JUNGLE:
|
||||||
weatherPool = [
|
weatherPool = [
|
||||||
{ weatherType: WeatherType.NONE, weight: 4 }
|
{ weatherType: WeatherType.NONE, weight: 8 },
|
||||||
|
{ weatherType: WeatherType.RAIN, weight: 2 }
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
case Biome.WASTELAND:
|
case Biome.SNOWY_FOREST:
|
||||||
weatherPool = [
|
weatherPool = [
|
||||||
{ weatherType: WeatherType.NONE, weight: 4 }
|
{ weatherType: WeatherType.SNOW, weight: 7 },
|
||||||
|
{ weatherType: WeatherType.HAIL, weight: 1 }
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
case Biome.ABYSS:
|
case Biome.ISLAND:
|
||||||
weatherPool = [
|
weatherPool = [
|
||||||
{ weatherType: WeatherType.NONE, weight: 4 }
|
{ weatherType: WeatherType.NONE, weight: 5 },
|
||||||
|
{ weatherType: WeatherType.RAIN, weight: 1 },
|
||||||
];
|
];
|
||||||
|
if (hasSun)
|
||||||
|
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,6 +166,20 @@ export class Arena {
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case Species.ROTOM:
|
||||||
|
switch (this.biomeType) {
|
||||||
|
case Biome.VOLCANO:
|
||||||
|
return 1;
|
||||||
|
case Biome.SEA:
|
||||||
|
return 2;
|
||||||
|
case Biome.ICE_CAVE:
|
||||||
|
return 3;
|
||||||
|
case Biome.MOUNTAIN:
|
||||||
|
return 4;
|
||||||
|
case Biome.TALL_GRASS:
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case Species.SCATTERBUG:
|
case Species.SCATTERBUG:
|
||||||
case Species.SPEWPA:
|
case Species.SPEWPA:
|
||||||
case Species.VIVILLON:
|
case Species.VIVILLON:
|
||||||
|
@ -25,7 +25,7 @@ import { TempBattleStat } from '../data/temp-battle-stat';
|
|||||||
import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from '../data/arena-tag';
|
import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from '../data/arena-tag';
|
||||||
import { ArenaTagType } from "../data/enums/arena-tag-type";
|
import { ArenaTagType } from "../data/enums/arena-tag-type";
|
||||||
import { Biome } from "../data/enums/biome";
|
import { Biome } from "../data/enums/biome";
|
||||||
import { Ability, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs } from '../data/ability';
|
import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs } from '../data/ability';
|
||||||
import { Abilities } from "#app/data/enums/abilities";
|
import { Abilities } from "#app/data/enums/abilities";
|
||||||
import PokemonData from '../system/pokemon-data';
|
import PokemonData from '../system/pokemon-data';
|
||||||
import { BattlerIndex } from '../battle';
|
import { BattlerIndex } from '../battle';
|
||||||
@ -523,6 +523,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
ret >>= 1;
|
ret >>= 1;
|
||||||
break;
|
break;
|
||||||
case Stat.DEF:
|
case Stat.DEF:
|
||||||
|
if (this.isOfType(Type.ICE) && this.scene.arena.weather?.weatherType === WeatherType.SNOW)
|
||||||
|
ret *= 1.5;
|
||||||
break;
|
break;
|
||||||
case Stat.SPATK:
|
case Stat.SPATK:
|
||||||
break;
|
break;
|
||||||
@ -561,7 +563,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
let value = Math.floor(((2 * baseStat + this.ivs[s]) * this.level) * 0.01);
|
let value = Math.floor(((2 * baseStat + this.ivs[s]) * this.level) * 0.01);
|
||||||
if (isHp) {
|
if (isHp) {
|
||||||
value = value + this.level + 10;
|
value = value + this.level + 10;
|
||||||
if ((this.canApplyAbility() && this.getAbility().hasAttr(NonSuperEffectiveImmunityAbAttr)) || (this.canApplyAbility(true) && this.getPassiveAbility().hasAttr(NonSuperEffectiveImmunityAbAttr)))
|
if (this.hasAbility(Abilities.WONDER_GUARD, false, true))
|
||||||
value = 1;
|
value = 1;
|
||||||
if (this.hp > value || this.hp === undefined)
|
if (this.hp > value || this.hp === undefined)
|
||||||
this.hp = value;
|
this.hp = value;
|
||||||
@ -730,12 +732,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
return allAbilities[starterPassiveAbilities[starterSpeciesId]];
|
return allAbilities[starterPassiveAbilities[starterSpeciesId]];
|
||||||
}
|
}
|
||||||
|
|
||||||
canApplyPassive(): boolean {
|
hasPassive(): boolean {
|
||||||
return this.passive || this.isBoss();
|
return this.passive || this.isBoss();
|
||||||
}
|
}
|
||||||
|
|
||||||
canApplyAbility(passive: boolean = false): boolean {
|
canApplyAbility(passive: boolean = false): boolean {
|
||||||
if (passive && !this.canApplyPassive())
|
if (passive && !this.hasPassive())
|
||||||
return false;
|
return false;
|
||||||
const ability = (!passive ? this.getAbility() : this.getPassiveAbility());
|
const ability = (!passive ? this.getAbility() : this.getPassiveAbility());
|
||||||
if (ability.isIgnorable && this.scene.arena.ignoreAbilities)
|
if (ability.isIgnorable && this.scene.arena.ignoreAbilities)
|
||||||
@ -743,6 +745,22 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
return (this.hp || ability.isBypassFaint) && !ability.conditions.find(condition => !condition(this));
|
return (this.hp || ability.isBypassFaint) && !ability.conditions.find(condition => !condition(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hasAbility(ability: Abilities, canApply: boolean = true, ignoreOverride?: boolean): boolean {
|
||||||
|
if ((!canApply || this.canApplyAbility()) && this.getAbility(ignoreOverride).id === ability)
|
||||||
|
return true;
|
||||||
|
if (this.hasPassive() && (!canApply || this.canApplyAbility(true)) && this.getPassiveAbility().id === ability)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasAbilityWithAttr(attrType: { new(...args: any[]): AbAttr }, canApply: boolean = true, ignoreOverride?: boolean): boolean {
|
||||||
|
if ((!canApply || this.canApplyAbility()) && this.getAbility(ignoreOverride).hasAttr(attrType))
|
||||||
|
return true;
|
||||||
|
if (this.hasPassive() && (!canApply || this.canApplyAbility(true)) && this.getPassiveAbility().hasAttr(attrType))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
getWeight(): number {
|
getWeight(): number {
|
||||||
const weight = new Utils.NumberHolder(this.species.weight);
|
const weight = new Utils.NumberHolder(this.species.weight);
|
||||||
// This will trigger the ability overlay so only call this function when necessary
|
// This will trigger the ability overlay so only call this function when necessary
|
||||||
@ -850,10 +868,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
} else
|
} else
|
||||||
levelMoves = this.getSpeciesForm().getLevelMoves();
|
levelMoves = this.getSpeciesForm(true).getLevelMoves();
|
||||||
if (this.fusionSpecies) {
|
if (this.fusionSpecies) {
|
||||||
const evolutionLevelMoves = levelMoves.slice(0, Math.max(levelMoves.findIndex(lm => !!lm[0]), 0));
|
const evolutionLevelMoves = levelMoves.slice(0, Math.max(levelMoves.findIndex(lm => !!lm[0]), 0));
|
||||||
const fusionLevelMoves = this.getFusionSpeciesForm().getLevelMoves();
|
const fusionLevelMoves = this.getFusionSpeciesForm(true).getLevelMoves();
|
||||||
const newLevelMoves: LevelMoves = [];
|
const newLevelMoves: LevelMoves = [];
|
||||||
while (levelMoves.length && levelMoves[0][0] < startingLevel)
|
while (levelMoves.length && levelMoves[0][0] < startingLevel)
|
||||||
levelMoves.shift();
|
levelMoves.shift();
|
||||||
@ -1114,7 +1132,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
let result: HitResult;
|
let result: HitResult;
|
||||||
const move = battlerMove.getMove();
|
const move = battlerMove.getMove();
|
||||||
let damage = new Utils.NumberHolder(0);
|
let damage = new Utils.NumberHolder(0);
|
||||||
|
const defendingSidePlayField = this.isPlayer() ? this.scene.getPlayerField() : this.scene.getEnemyField();
|
||||||
|
|
||||||
const variableCategory = new Utils.IntegerHolder(move.category);
|
const variableCategory = new Utils.IntegerHolder(move.category);
|
||||||
applyMoveAttrs(VariableMoveCategoryAttr, source, this, move, variableCategory);
|
applyMoveAttrs(VariableMoveCategoryAttr, source, this, move, variableCategory);
|
||||||
const moveCategory = variableCategory.value as MoveCategory;
|
const moveCategory = variableCategory.value as MoveCategory;
|
||||||
@ -1156,8 +1175,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
|
|
||||||
if (!typeless)
|
if (!typeless)
|
||||||
applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, battlerMove, cancelled, typeMultiplier);
|
applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, battlerMove, cancelled, typeMultiplier);
|
||||||
if (!cancelled.value)
|
if (!cancelled.value) {
|
||||||
applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, battlerMove, cancelled, typeMultiplier);
|
applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, battlerMove, cancelled, typeMultiplier);
|
||||||
|
defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, battlerMove, cancelled, typeMultiplier));
|
||||||
|
}
|
||||||
|
|
||||||
if (cancelled.value)
|
if (cancelled.value)
|
||||||
result = HitResult.NO_EFFECT;
|
result = HitResult.NO_EFFECT;
|
||||||
@ -1186,7 +1207,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
applyMoveAttrs(HighCritAttr, source, this, move, critLevel);
|
applyMoveAttrs(HighCritAttr, source, this, move, critLevel);
|
||||||
this.scene.applyModifiers(TempBattleStatBoosterModifier, source.isPlayer(), TempBattleStat.CRIT, critLevel);
|
this.scene.applyModifiers(TempBattleStatBoosterModifier, source.isPlayer(), TempBattleStat.CRIT, critLevel);
|
||||||
const bonusCrit = new Utils.BooleanHolder(false);
|
const bonusCrit = new Utils.BooleanHolder(false);
|
||||||
if (applyAbAttrs(BonusCritAbAttr, this, null, bonusCrit)) {
|
if (applyAbAttrs(BonusCritAbAttr, source, null, bonusCrit)) {
|
||||||
if (bonusCrit.value)
|
if (bonusCrit.value)
|
||||||
critLevel.value += 1;
|
critLevel.value += 1;
|
||||||
}
|
}
|
||||||
@ -1278,6 +1299,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
|
|
||||||
applyMoveAttrs(ModifiedDamageAttr, source, this, move, damage);
|
applyMoveAttrs(ModifiedDamageAttr, source, this, move, damage);
|
||||||
|
|
||||||
|
if (power.value === 0) {
|
||||||
|
damage.value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
console.log('damage', damage.value, move.name, power.value, sourceAtk, targetDef);
|
console.log('damage', damage.value, move.name, power.value, sourceAtk, targetDef);
|
||||||
|
|
||||||
if (damage.value) {
|
if (damage.value) {
|
||||||
@ -1328,8 +1353,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
case MoveCategory.STATUS:
|
case MoveCategory.STATUS:
|
||||||
if (!typeless)
|
if (!typeless)
|
||||||
applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, battlerMove, cancelled, typeMultiplier);
|
applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, battlerMove, cancelled, typeMultiplier);
|
||||||
if (!cancelled.value)
|
if (!cancelled.value) {
|
||||||
applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, battlerMove, cancelled, typeMultiplier);
|
applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, battlerMove, cancelled, typeMultiplier);
|
||||||
|
defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, battlerMove, cancelled, typeMultiplier));
|
||||||
|
}
|
||||||
if (!typeMultiplier.value)
|
if (!typeMultiplier.value)
|
||||||
this.scene.queueMessage(`It doesn\'t affect ${this.name}!`);
|
this.scene.queueMessage(`It doesn\'t affect ${this.name}!`);
|
||||||
result = cancelled.value || !typeMultiplier.value ? HitResult.NO_EFFECT : HitResult.STATUS;
|
result = cancelled.value || !typeMultiplier.value ? HitResult.NO_EFFECT : HitResult.STATUS;
|
||||||
@ -2260,6 +2287,7 @@ export class PlayerPokemon extends Pokemon {
|
|||||||
if (newEvolution.condition.predicate(this)) {
|
if (newEvolution.condition.predicate(this)) {
|
||||||
const newPokemon = this.scene.addPlayerPokemon(this.species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this.ivs, this.nature);
|
const newPokemon = this.scene.addPlayerPokemon(this.species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this.ivs, this.nature);
|
||||||
newPokemon.natureOverride = this.natureOverride;
|
newPokemon.natureOverride = this.natureOverride;
|
||||||
|
newPokemon.moveset = this.moveset.slice();
|
||||||
newPokemon.fusionSpecies = this.fusionSpecies;
|
newPokemon.fusionSpecies = this.fusionSpecies;
|
||||||
newPokemon.fusionFormIndex = this.fusionFormIndex;
|
newPokemon.fusionFormIndex = this.fusionFormIndex;
|
||||||
newPokemon.fusionAbilityIndex = this.fusionAbilityIndex;
|
newPokemon.fusionAbilityIndex = this.fusionAbilityIndex;
|
||||||
|
@ -6,6 +6,7 @@ import { getBiomeHasProps } from "./field/arena";
|
|||||||
import CacheBustedLoaderPlugin from "./plugins/cache-busted-loader-plugin";
|
import CacheBustedLoaderPlugin from "./plugins/cache-busted-loader-plugin";
|
||||||
import { SceneBase } from "./scene-base";
|
import { SceneBase } from "./scene-base";
|
||||||
import { WindowVariant, getWindowVariantSuffix } from "./ui/ui-theme";
|
import { WindowVariant, getWindowVariantSuffix } from "./ui/ui-theme";
|
||||||
|
import { isMobile } from "./touch-controls";
|
||||||
import * as Utils from "./utils";
|
import * as Utils from "./utils";
|
||||||
|
|
||||||
export class LoadingScene extends SceneBase {
|
export class LoadingScene extends SceneBase {
|
||||||
@ -23,6 +24,9 @@ export class LoadingScene extends SceneBase {
|
|||||||
this.load['cacheBuster'] = buildIdMatch[1];
|
this.load['cacheBuster'] = buildIdMatch[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isMobile())
|
||||||
|
this.load.video('intro_dark', 'images/intro_dark.mp4', true);
|
||||||
|
|
||||||
this.loadImage('loading_bg', 'arenas');
|
this.loadImage('loading_bg', 'arenas');
|
||||||
this.loadImage('logo', '');
|
this.loadImage('logo', '');
|
||||||
|
|
||||||
@ -250,6 +254,10 @@ export class LoadingScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loadLoadingScreen() {
|
loadLoadingScreen() {
|
||||||
|
const mobile = isMobile();
|
||||||
|
|
||||||
|
const loadingGraphics: any[] = [];
|
||||||
|
|
||||||
const bg = this.add.image(0, 0, '');
|
const bg = this.add.image(0, 0, '');
|
||||||
bg.setOrigin(0, 0);
|
bg.setOrigin(0, 0);
|
||||||
bg.setScale(6);
|
bg.setScale(6);
|
||||||
@ -294,6 +302,10 @@ export class LoadingScene extends SceneBase {
|
|||||||
});
|
});
|
||||||
assetText.setOrigin(0.5, 0.5);
|
assetText.setOrigin(0.5, 0.5);
|
||||||
|
|
||||||
|
const intro = this.add.video(0, 0);
|
||||||
|
intro.setOrigin(0, 0);
|
||||||
|
intro.setScale(3);
|
||||||
|
|
||||||
this.load.on("progress", (value: string) => {
|
this.load.on("progress", (value: string) => {
|
||||||
const parsedValue = parseFloat(value);
|
const parsedValue = parseFloat(value);
|
||||||
percentText.setText(`${Math.floor(parsedValue * 100)}%`);
|
percentText.setText(`${Math.floor(parsedValue * 100)}%`);
|
||||||
@ -305,28 +317,51 @@ export class LoadingScene extends SceneBase {
|
|||||||
this.load.on("fileprogress", file => {
|
this.load.on("fileprogress", file => {
|
||||||
assetText.setText(`Loading asset: ${file.key}`);
|
assetText.setText(`Loading asset: ${file.key}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
loadingGraphics.push(bg, graphics, progressBar, progressBox, logo, percentText, assetText);
|
||||||
|
|
||||||
this.load.on('filecomplete', key => {
|
if (!mobile)
|
||||||
switch (key) {
|
loadingGraphics.map(g => g.setVisible(false));
|
||||||
case 'loading_bg':
|
|
||||||
bg.setVisible(true);
|
|
||||||
bg.setTexture('loading_bg');
|
|
||||||
break;
|
|
||||||
case 'logo':
|
|
||||||
logo.setVisible(true);
|
|
||||||
logo.setTexture('logo');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.load.on("complete", () => {
|
const destroyLoadingAssets = () => {
|
||||||
|
intro.destroy();
|
||||||
bg.destroy();
|
bg.destroy();
|
||||||
logo.destroy();
|
logo.destroy();
|
||||||
progressBar.destroy();
|
progressBar.destroy();
|
||||||
progressBox.destroy();
|
progressBox.destroy();
|
||||||
percentText.destroy();
|
percentText.destroy();
|
||||||
assetText.destroy();
|
assetText.destroy();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.load.on('filecomplete', key => {
|
||||||
|
switch (key) {
|
||||||
|
case 'intro_dark':
|
||||||
|
intro.load('intro_dark');
|
||||||
|
intro.on('complete', () => {
|
||||||
|
this.tweens.add({
|
||||||
|
targets: intro,
|
||||||
|
duration: 500,
|
||||||
|
alpha: 0,
|
||||||
|
ease: 'Sine.easeIn'
|
||||||
|
});
|
||||||
|
loadingGraphics.map(g => g.setVisible(true));
|
||||||
|
});
|
||||||
|
intro.play();
|
||||||
|
break;
|
||||||
|
case 'loading_bg':
|
||||||
|
bg.setTexture('loading_bg');
|
||||||
|
if (mobile)
|
||||||
|
bg.setVisible(true);
|
||||||
|
break;
|
||||||
|
case 'logo':
|
||||||
|
logo.setTexture('logo');
|
||||||
|
if (mobile)
|
||||||
|
logo.setVisible(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.load.on("complete", () => destroyLoadingAssets());
|
||||||
}
|
}
|
||||||
|
|
||||||
get gameHeight() {
|
get gameHeight() {
|
||||||
|
@ -44,6 +44,7 @@ const config: Phaser.Types.Core.GameConfig = {
|
|||||||
touch: {
|
touch: {
|
||||||
target: 'app'
|
target: 'app'
|
||||||
},
|
},
|
||||||
|
gamepad: true
|
||||||
},
|
},
|
||||||
dom: {
|
dom: {
|
||||||
createContainer: true
|
createContainer: true
|
||||||
@ -78,4 +79,4 @@ document.fonts.load('16px emerald').then(() => document.fonts.load('10px pkmnems
|
|||||||
const game = new Phaser.Game(config);
|
const game = new Phaser.Game(config);
|
||||||
game.sound.pauseOnBlur = false;
|
game.sound.pauseOnBlur = false;
|
||||||
|
|
||||||
export default game;
|
export default game;
|
||||||
|
@ -1341,7 +1341,7 @@ export function getPlayerShopModifierTypeOptionsForWave(waveIndex: integer, base
|
|||||||
new ModifierTypeOption(modifierTypes.FULL_RESTORE(), 0, baseCost * 2.25)
|
new ModifierTypeOption(modifierTypes.FULL_RESTORE(), 0, baseCost * 2.25)
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
new ModifierTypeOption(modifierTypes.SACRED_ASH(), 0, baseCost * 12)
|
new ModifierTypeOption(modifierTypes.SACRED_ASH(), 0, baseCost * 10)
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
return options.slice(0, Math.ceil(Math.max(waveIndex + 10, 0) / 30)).flat();
|
return options.slice(0, Math.ceil(Math.max(waveIndex + 10, 0) / 30)).flat();
|
||||||
|
@ -379,6 +379,16 @@ export class UnavailablePhase extends Phase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class OutdatedPhase extends Phase {
|
||||||
|
constructor(scene: BattleScene) {
|
||||||
|
super(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
start(): void {
|
||||||
|
this.scene.ui.setMode(Mode.OUTDATED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class SelectGenderPhase extends Phase {
|
export class SelectGenderPhase extends Phase {
|
||||||
constructor(scene: BattleScene) {
|
constructor(scene: BattleScene) {
|
||||||
super(scene);
|
super(scene);
|
||||||
@ -2190,7 +2200,7 @@ export class MovePhase extends BattlePhase {
|
|||||||
for (let opponent of targetedOpponents) {
|
for (let opponent of targetedOpponents) {
|
||||||
if (this.move.ppUsed === this.move.getMove().pp)
|
if (this.move.ppUsed === this.move.getMove().pp)
|
||||||
break;
|
break;
|
||||||
if ((opponent.canApplyAbility() && opponent.getAbility().hasAttr(IncreasePpAbAttr)) || (opponent.canApplyAbility(true) && opponent.getPassiveAbility().hasAttr(IncreasePpAbAttr)))
|
if (opponent.hasAbilityWithAttr(IncreasePpAbAttr))
|
||||||
this.move.ppUsed = Math.min(this.move.ppUsed + 1, this.move.getMovePp());
|
this.move.ppUsed = Math.min(this.move.ppUsed + 1, this.move.getMovePp());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2389,7 +2399,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
}
|
}
|
||||||
Utils.executeIf(!isProtected && !chargeEffect, () => applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && (attr as MoveEffectAttr).trigger === MoveEffectTrigger.HIT && (!attr.firstHitOnly || firstHit),
|
Utils.executeIf(!isProtected && !chargeEffect, () => applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && (attr as MoveEffectAttr).trigger === MoveEffectTrigger.HIT && (!attr.firstHitOnly || firstHit),
|
||||||
user, target, this.move.getMove()).then(() => {
|
user, target, this.move.getMove()).then(() => {
|
||||||
return Utils.executeIf(!target.isFainted(), () => applyPostDefendAbAttrs(PostDefendAbAttr, target, user, this.move, hitResult).then(() => {
|
return Utils.executeIf(!target.isFainted() || target.canApplyAbility(), () => applyPostDefendAbAttrs(PostDefendAbAttr, target, user, this.move, hitResult).then(() => {
|
||||||
if (!user.isPlayer() && this.move.getMove() instanceof AttackMove)
|
if (!user.isPlayer() && this.move.getMove() instanceof AttackMove)
|
||||||
user.scene.applyModifiers(EnemyAttackStatusEffectChanceModifier, false, target);
|
user.scene.applyModifiers(EnemyAttackStatusEffectChanceModifier, false, target);
|
||||||
})).then(() => {
|
})).then(() => {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
let cacheBuster = '';
|
let cacheBuster = '';
|
||||||
|
|
||||||
|
const ignoredFiles = [ 'intro_dark' ];
|
||||||
|
|
||||||
export default class CacheBustedLoaderPlugin extends Phaser.Loader.LoaderPlugin {
|
export default class CacheBustedLoaderPlugin extends Phaser.Loader.LoaderPlugin {
|
||||||
constructor(scene: Phaser.Scene) {
|
constructor(scene: Phaser.Scene) {
|
||||||
super(scene)
|
super(scene)
|
||||||
@ -15,9 +17,9 @@ export default class CacheBustedLoaderPlugin extends Phaser.Loader.LoaderPlugin
|
|||||||
|
|
||||||
addFile(file): void {
|
addFile(file): void {
|
||||||
if (!Array.isArray(file))
|
if (!Array.isArray(file))
|
||||||
file = [ file ]
|
file = [ file ];
|
||||||
|
|
||||||
if (cacheBuster)
|
if (!ignoredFiles.includes(file?.key) && cacheBuster)
|
||||||
file.forEach(item => item.url += '?v=' + cacheBuster);
|
file.forEach(item => item.url += '?v=' + cacheBuster);
|
||||||
|
|
||||||
super.addFile(file);
|
super.addFile(file);
|
||||||
|
@ -27,6 +27,7 @@ import { Moves } from "../data/enums/moves";
|
|||||||
import { speciesEggMoves } from "../data/egg-moves";
|
import { speciesEggMoves } from "../data/egg-moves";
|
||||||
import { allMoves } from "../data/move";
|
import { allMoves } from "../data/move";
|
||||||
import { TrainerVariant } from "../field/trainer";
|
import { TrainerVariant } from "../field/trainer";
|
||||||
|
import { OutdatedPhase, UnavailablePhase } from "#app/phases";
|
||||||
|
|
||||||
const saveKey = 'x0i2O7WRiANTqPmZ'; // Temporary; secure encryption is not yet necessary
|
const saveKey = 'x0i2O7WRiANTqPmZ'; // Temporary; secure encryption is not yet necessary
|
||||||
|
|
||||||
@ -183,7 +184,7 @@ const systemShortKeys = {
|
|||||||
ivs: '$i',
|
ivs: '$i',
|
||||||
moveset: '$m',
|
moveset: '$m',
|
||||||
eggMoves: '$em',
|
eggMoves: '$em',
|
||||||
candyCount: '$cc',
|
candyCount: '$x',
|
||||||
passive: '$p',
|
passive: '$p',
|
||||||
valueReduction: '$vr'
|
valueReduction: '$vr'
|
||||||
};
|
};
|
||||||
@ -269,6 +270,10 @@ export class GameData {
|
|||||||
.then(error => {
|
.then(error => {
|
||||||
this.scene.ui.savingIcon.hide();
|
this.scene.ui.savingIcon.hide();
|
||||||
if (error) {
|
if (error) {
|
||||||
|
if (error.startsWith('client version out of date')) {
|
||||||
|
this.scene.clearPhaseQueue();
|
||||||
|
this.scene.unshiftPhase(new OutdatedPhase(this.scene));
|
||||||
|
}
|
||||||
console.error(error);
|
console.error(error);
|
||||||
return resolve(false);
|
return resolve(false);
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ export enum Setting {
|
|||||||
HP_Bar_Speed = "HP_BAR_SPEED",
|
HP_Bar_Speed = "HP_BAR_SPEED",
|
||||||
Fusion_Palette_Swaps = "FUSION_PALETTE_SWAPS",
|
Fusion_Palette_Swaps = "FUSION_PALETTE_SWAPS",
|
||||||
Player_Gender = "PLAYER_GENDER",
|
Player_Gender = "PLAYER_GENDER",
|
||||||
|
Gamepad_Support = "GAMEPAD_SUPPORT",
|
||||||
Touch_Controls = "TOUCH_CONTROLS",
|
Touch_Controls = "TOUCH_CONTROLS",
|
||||||
Vibration = "VIBRATION"
|
Vibration = "VIBRATION"
|
||||||
}
|
}
|
||||||
@ -47,6 +48,7 @@ export const settingOptions: SettingOptions = {
|
|||||||
[Setting.HP_Bar_Speed]: [ 'Normal', 'Fast', 'Faster', 'Instant' ],
|
[Setting.HP_Bar_Speed]: [ 'Normal', 'Fast', 'Faster', 'Instant' ],
|
||||||
[Setting.Fusion_Palette_Swaps]: [ 'Off', 'On' ],
|
[Setting.Fusion_Palette_Swaps]: [ 'Off', 'On' ],
|
||||||
[Setting.Player_Gender]: [ 'Boy', 'Girl' ],
|
[Setting.Player_Gender]: [ 'Boy', 'Girl' ],
|
||||||
|
[Setting.Gamepad_Support]: [ 'Auto', 'Disabled' ],
|
||||||
[Setting.Touch_Controls]: [ 'Auto', 'Disabled' ],
|
[Setting.Touch_Controls]: [ 'Auto', 'Disabled' ],
|
||||||
[Setting.Vibration]: [ 'Auto', 'Disabled' ]
|
[Setting.Vibration]: [ 'Auto', 'Disabled' ]
|
||||||
};
|
};
|
||||||
@ -67,6 +69,7 @@ export const settingDefaults: SettingDefaults = {
|
|||||||
[Setting.HP_Bar_Speed]: 0,
|
[Setting.HP_Bar_Speed]: 0,
|
||||||
[Setting.Fusion_Palette_Swaps]: 1,
|
[Setting.Fusion_Palette_Swaps]: 1,
|
||||||
[Setting.Player_Gender]: 0,
|
[Setting.Player_Gender]: 0,
|
||||||
|
[Setting.Gamepad_Support]: 0,
|
||||||
[Setting.Touch_Controls]: 0,
|
[Setting.Touch_Controls]: 0,
|
||||||
[Setting.Vibration]: 0
|
[Setting.Vibration]: 0
|
||||||
};
|
};
|
||||||
@ -130,6 +133,9 @@ export function setSetting(scene: BattleScene, setting: Setting, value: integer)
|
|||||||
} else
|
} else
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
case Setting.Gamepad_Support:
|
||||||
|
scene.gamepadSupport = settingOptions[setting][value] !== 'Disabled';
|
||||||
|
break;
|
||||||
case Setting.Touch_Controls:
|
case Setting.Touch_Controls:
|
||||||
scene.enableTouchControls = settingOptions[setting][value] !== 'Disabled' && hasTouchscreen();
|
scene.enableTouchControls = settingOptions[setting][value] !== 'Disabled' && hasTouchscreen();
|
||||||
const touchControls = document.getElementById('touchControls');
|
const touchControls = document.getElementById('touchControls');
|
||||||
|
47
src/ui/outdated-modal-ui-handler.ts
Normal file
47
src/ui/outdated-modal-ui-handler.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import BattleScene from "../battle-scene";
|
||||||
|
import { ModalConfig, ModalUiHandler } from "./modal-ui-handler";
|
||||||
|
import { addTextObject, TextStyle } from "./text";
|
||||||
|
import { Mode } from "./ui";
|
||||||
|
|
||||||
|
export default class OutdatedModalUiHandler extends ModalUiHandler {
|
||||||
|
constructor(scene: BattleScene, mode?: Mode) {
|
||||||
|
super(scene, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
getModalTitle(): string {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
getWidth(): number {
|
||||||
|
return 160;
|
||||||
|
}
|
||||||
|
|
||||||
|
getHeight(): number {
|
||||||
|
return 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
getMargin(): [number, number, number, number] {
|
||||||
|
return [ 0, 0, 48, 0 ];
|
||||||
|
}
|
||||||
|
|
||||||
|
getButtonLabels(): string[] {
|
||||||
|
return [ ];
|
||||||
|
}
|
||||||
|
|
||||||
|
setup(): void {
|
||||||
|
super.setup();
|
||||||
|
|
||||||
|
const label = addTextObject(this.scene, this.getWidth() / 2, this.getHeight() / 2, 'Your client is currently outdated.\nPlease reload to update the game.\n\nIf this error persists, please clear your browser cache.', TextStyle.WINDOW, { fontSize: '48px', align: 'center' });
|
||||||
|
label.setOrigin(0.5, 0.5);
|
||||||
|
|
||||||
|
this.modalContainer.add(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
show(args: any[]): boolean {
|
||||||
|
const config: ModalConfig = {
|
||||||
|
buttonActions: []
|
||||||
|
};
|
||||||
|
|
||||||
|
return super.show([ config ]);
|
||||||
|
}
|
||||||
|
}
|
@ -114,8 +114,10 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler {
|
|||||||
ui.showText(null, 0);
|
ui.showText(null, 0);
|
||||||
}, false, 0, 19, 2000);
|
}, false, 0, 19, 2000);
|
||||||
});
|
});
|
||||||
} else
|
} else if (this.sessionSlots[this.cursor].hasData === false)
|
||||||
saveAndCallback();
|
saveAndCallback();
|
||||||
|
else
|
||||||
|
return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
success = true;
|
success = true;
|
||||||
@ -210,7 +212,6 @@ class SessionSlot extends Phaser.GameObjects.Container {
|
|||||||
super(scene, 0, slotId * 56);
|
super(scene, 0, slotId * 56);
|
||||||
|
|
||||||
this.slotId = slotId;
|
this.slotId = slotId;
|
||||||
this.hasData = false;
|
|
||||||
|
|
||||||
this.setup();
|
this.setup();
|
||||||
}
|
}
|
||||||
@ -282,6 +283,7 @@ class SessionSlot extends Phaser.GameObjects.Container {
|
|||||||
return new Promise<boolean>(resolve => {
|
return new Promise<boolean>(resolve => {
|
||||||
this.scene.gameData.getSession(this.slotId).then(async sessionData => {
|
this.scene.gameData.getSession(this.slotId).then(async sessionData => {
|
||||||
if (!sessionData) {
|
if (!sessionData) {
|
||||||
|
this.hasData = false;
|
||||||
this.loadingLabel.setText('Empty');
|
this.loadingLabel.setText('Empty');
|
||||||
resolve(false);
|
resolve(false);
|
||||||
return;
|
return;
|
||||||
|
@ -1304,6 +1304,13 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
this.dexAttrCursor = 0n;
|
this.dexAttrCursor = 0n;
|
||||||
this.natureCursor = -1;
|
this.natureCursor = -1;
|
||||||
|
|
||||||
|
if (species?.forms?.find(f => f.formKey === 'female')) {
|
||||||
|
if (female !== undefined)
|
||||||
|
formIndex = female ? 1 : 0;
|
||||||
|
else if (formIndex !== undefined)
|
||||||
|
female = formIndex === 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (species) {
|
if (species) {
|
||||||
this.dexAttrCursor |= (shiny !== undefined ? !shiny : !(shiny = oldProps.shiny)) ? DexAttr.NON_SHINY : DexAttr.SHINY;
|
this.dexAttrCursor |= (shiny !== undefined ? !shiny : !(shiny = oldProps.shiny)) ? DexAttr.NON_SHINY : DexAttr.SHINY;
|
||||||
this.dexAttrCursor |= (female !== undefined ? !female : !(female = oldProps.female)) ? DexAttr.MALE : DexAttr.FEMALE;
|
this.dexAttrCursor |= (female !== undefined ? !female : !(female = oldProps.female)) ? DexAttr.MALE : DexAttr.FEMALE;
|
||||||
|
10
src/ui/ui.ts
10
src/ui/ui.ts
@ -34,6 +34,7 @@ import SaveSlotSelectUiHandler from './save-slot-select-ui-handler';
|
|||||||
import TitleUiHandler from './title-ui-handler';
|
import TitleUiHandler from './title-ui-handler';
|
||||||
import SavingIconHandler from './saving-icon-handler';
|
import SavingIconHandler from './saving-icon-handler';
|
||||||
import UnavailableModalUiHandler from './unavailable-modal-ui-handler';
|
import UnavailableModalUiHandler from './unavailable-modal-ui-handler';
|
||||||
|
import OutdatedModalUiHandler from './outdated-modal-ui-handler';
|
||||||
|
|
||||||
export enum Mode {
|
export enum Mode {
|
||||||
MESSAGE,
|
MESSAGE,
|
||||||
@ -63,7 +64,8 @@ export enum Mode {
|
|||||||
LOGIN_FORM,
|
LOGIN_FORM,
|
||||||
REGISTRATION_FORM,
|
REGISTRATION_FORM,
|
||||||
LOADING,
|
LOADING,
|
||||||
UNAVAILABLE
|
UNAVAILABLE,
|
||||||
|
OUTDATED
|
||||||
};
|
};
|
||||||
|
|
||||||
const transitionModes = [
|
const transitionModes = [
|
||||||
@ -90,7 +92,8 @@ const noTransitionModes = [
|
|||||||
Mode.LOGIN_FORM,
|
Mode.LOGIN_FORM,
|
||||||
Mode.REGISTRATION_FORM,
|
Mode.REGISTRATION_FORM,
|
||||||
Mode.LOADING,
|
Mode.LOADING,
|
||||||
Mode.UNAVAILABLE
|
Mode.UNAVAILABLE,
|
||||||
|
Mode.OUTDATED
|
||||||
];
|
];
|
||||||
|
|
||||||
export default class UI extends Phaser.GameObjects.Container {
|
export default class UI extends Phaser.GameObjects.Container {
|
||||||
@ -141,7 +144,8 @@ export default class UI extends Phaser.GameObjects.Container {
|
|||||||
new LoginFormUiHandler(scene),
|
new LoginFormUiHandler(scene),
|
||||||
new RegistrationFormUiHandler(scene),
|
new RegistrationFormUiHandler(scene),
|
||||||
new LoadingModalUiHandler(scene),
|
new LoadingModalUiHandler(scene),
|
||||||
new UnavailableModalUiHandler(scene)
|
new UnavailableModalUiHandler(scene),
|
||||||
|
new OutdatedModalUiHandler(scene)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user