mirror of
https://github.com/smogon/pokemon-showdown.git
synced 2026-06-02 22:08:36 -05:00
Merge branch 'master' into magician-tests
This commit is contained in:
commit
52f2273e71
6
.github/workflows/publish.yml
vendored
6
.github/workflows/publish.yml
vendored
|
|
@ -15,7 +15,7 @@ jobs:
|
|||
last_version: ${{ steps.last_version.outputs.version }}
|
||||
token_exists: ${{ steps.check_token.outputs.token }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 50
|
||||
# Check if the package.json version field has changed since the last push
|
||||
|
|
@ -40,8 +40,8 @@ jobs:
|
|||
# We only want to publish if the package.json version field has changed
|
||||
if: needs.get-version.outputs.current_version != needs.get-version.outputs.last_version && needs.get-version.outputs.token_exists == 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 18
|
||||
cache: 'npm'
|
||||
|
|
|
|||
8
.github/workflows/test.yml
vendored
8
.github/workflows/test.yml
vendored
|
|
@ -28,12 +28,12 @@ jobs:
|
|||
node-version: ['18.x']
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 100 # assumes PR/push to master is no larger than 100 commits. Other solutions are needlessly complex.
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
|
|
@ -43,7 +43,7 @@ jobs:
|
|||
- name: Determine which files to lint (if pull request)
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v35
|
||||
uses: tj-actions/changed-files@v47
|
||||
with:
|
||||
files: |
|
||||
./config/*.ts
|
||||
|
|
@ -66,7 +66,7 @@ jobs:
|
|||
- name: Determine whether test/sim or test/random-battles need to run (if pull request)
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
id: changed-directories
|
||||
uses: tj-actions/changed-files@v35
|
||||
uses: tj-actions/changed-files@v47
|
||||
with:
|
||||
files: |
|
||||
config/formats.ts
|
||||
|
|
|
|||
6
.github/workflows/update_version.yml
vendored
6
.github/workflows/update_version.yml
vendored
|
|
@ -21,9 +21,9 @@ jobs:
|
|||
update_version:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 18
|
||||
cache: 'npm'
|
||||
|
|
@ -34,7 +34,7 @@ jobs:
|
|||
npm version ${{ github.event.inputs.version }} --no-git-tag-version
|
||||
echo "new_version=$(jq -r .version package.json)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- uses: peter-evans/create-pull-request@v7
|
||||
- uses: peter-evans/create-pull-request@v8
|
||||
with:
|
||||
title: Bump package.json version to v${{ steps.bump_version.outputs.new_version }}
|
||||
body: |
|
||||
|
|
|
|||
2
LICENSE
2
LICENSE
|
|
@ -1,6 +1,6 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2011-2024 Guangcong Luo and other contributors http://pokemonshowdown.com/
|
||||
Copyright (c) 2011-2026 Guangcong Luo and other contributors http://pokemonshowdown.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ Pokémon Showdown is implemented in SockJS. SockJS is a compatibility
|
|||
layer over raw WebSocket, so you can actually connect to Pokémon
|
||||
Showdown directly using WebSocket:
|
||||
|
||||
ws://sim.smogon.com:8000/showdown/websocket
|
||||
or
|
||||
wss://sim3.psim.us/showdown/websocket
|
||||
or
|
||||
ws://sim3.psim.us:8000/showdown/websocket
|
||||
|
||||
Client implementations you might want to look at for reference include:
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,15 @@ exports.bindaddress = '0.0.0.0';
|
|||
*/
|
||||
exports.wsdeflate = null;
|
||||
|
||||
/**
|
||||
* lazysockets - disables eager initialization of network services
|
||||
* Turn this on if you'd prefer to manually connect Showdown to the network,
|
||||
* or you intend to run it offline.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
exports.lazysockets = false;
|
||||
|
||||
/*
|
||||
// example:
|
||||
exports.wsdeflate = {
|
||||
|
|
|
|||
2231
config/formats.ts
2231
config/formats.ts
File diff suppressed because it is too large
Load Diff
|
|
@ -1003,6 +1003,28 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
|
|||
rating: 3.5,
|
||||
num: 88,
|
||||
},
|
||||
dragonize: {
|
||||
isNonstandard: "Future",
|
||||
onModifyTypePriority: -1,
|
||||
onModifyType(move, pokemon) {
|
||||
const noModifyType = [
|
||||
'judgment', 'multiattack', 'naturalgift', 'revelationdance', 'technoblast', 'terrainpulse', 'weatherball',
|
||||
];
|
||||
if (move.type === 'Normal' && (!noModifyType.includes(move.id) || this.activeMove?.isMax) &&
|
||||
!(move.isZ && move.category !== 'Status') && !(move.name === 'Tera Blast' && pokemon.terastallized)) {
|
||||
move.type = 'Dragon';
|
||||
move.typeChangerBoosted = this.effect;
|
||||
}
|
||||
},
|
||||
onBasePowerPriority: 23,
|
||||
onBasePower(basePower, pokemon, target, move) {
|
||||
if (move.typeChangerBoosted === this.effect) return this.chainModify([4915, 4096]);
|
||||
},
|
||||
flags: {},
|
||||
name: "Dragonize",
|
||||
rating: 4,
|
||||
num: 312,
|
||||
},
|
||||
dragonsmaw: {
|
||||
onModifyAtkPriority: 5,
|
||||
onModifyAtk(atk, attacker, defender, move) {
|
||||
|
|
@ -1059,7 +1081,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
|
|||
}
|
||||
},
|
||||
onWeather(target, source, effect) {
|
||||
if (target.hasItem('utilityumbrella')) return;
|
||||
if (target.effectiveWeather() !== effect.id) return;
|
||||
if (effect.id === 'raindance' || effect.id === 'primordialsea') {
|
||||
this.heal(target.baseMaxhp / 8);
|
||||
} else if (effect.id === 'sunnyday' || effect.id === 'desolateland') {
|
||||
|
|
@ -1094,14 +1116,14 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
|
|||
},
|
||||
effectspore: {
|
||||
onDamagingHit(damage, target, source, move) {
|
||||
if (this.checkMoveMakesContact(move, source, target) && !source.status && source.runStatusImmunity('powder')) {
|
||||
if (this.checkMoveMakesContact(move, source, target) && source.runStatusImmunity('powder')) {
|
||||
const r = this.random(100);
|
||||
if (r < 11) {
|
||||
source.setStatus('slp', target);
|
||||
source.trySetStatus('slp', target);
|
||||
} else if (r < 21) {
|
||||
source.setStatus('par', target);
|
||||
source.trySetStatus('par', target);
|
||||
} else if (r < 30) {
|
||||
source.setStatus('psn', target);
|
||||
source.trySetStatus('psn', target);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -1987,7 +2009,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
|
|||
}
|
||||
},
|
||||
onEnd(pokemon) {
|
||||
if (pokemon.illusion) {
|
||||
if (pokemon.illusion && !pokemon.beingCalledBack) {
|
||||
this.debug('illusion cleared');
|
||||
pokemon.illusion = null;
|
||||
const details = pokemon.getUpdatedDetails();
|
||||
|
|
@ -2303,10 +2325,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
|
|||
return;
|
||||
}
|
||||
if (this.checkMoveMakesContact(move, source, target, !source.isAlly(target))) {
|
||||
const oldAbility = source.setAbility('lingeringaroma', target);
|
||||
if (oldAbility) {
|
||||
this.add('-activate', target, 'ability: Lingering Aroma', this.dex.abilities.get(oldAbility).name, `[of] ${source}`);
|
||||
}
|
||||
source.setAbility('lingeringaroma', target);
|
||||
}
|
||||
},
|
||||
flags: {},
|
||||
|
|
@ -2474,6 +2493,20 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
|
|||
rating: 3,
|
||||
num: 178,
|
||||
},
|
||||
megasol: {
|
||||
isNonstandard: "Future",
|
||||
onWeatherModifyDamage(damage, attacker, defender, move) {
|
||||
if (this.field.weather !== 'sunnyday') {
|
||||
(this.dex.conditions.getByID('sunnyday' as ID) as any).onWeatherModifyDamage
|
||||
.call(this, damage, attacker, defender, move);
|
||||
}
|
||||
},
|
||||
flags: {},
|
||||
name: "Mega Sol",
|
||||
rating: 3,
|
||||
num: 315,
|
||||
// Partially implemented in Pokemon.effectiveWeather() in sim/pokemon.ts
|
||||
},
|
||||
merciless: {
|
||||
onModifyCritRatio(critRatio, source, target) {
|
||||
if (target && ['psn', 'tox'].includes(target.status)) return 5;
|
||||
|
|
@ -2688,10 +2721,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
|
|||
return;
|
||||
}
|
||||
if (this.checkMoveMakesContact(move, source, target, !source.isAlly(target))) {
|
||||
const oldAbility = source.setAbility('mummy', target);
|
||||
if (oldAbility) {
|
||||
this.add('-activate', target, 'ability: Mummy', this.dex.abilities.get(oldAbility).name, `[of] ${source}`);
|
||||
}
|
||||
source.setAbility('mummy', target);
|
||||
}
|
||||
},
|
||||
flags: {},
|
||||
|
|
@ -3187,6 +3217,20 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
|
|||
rating: 0.5,
|
||||
num: 53,
|
||||
},
|
||||
piercingdrill: {
|
||||
isNonstandard: "Future",
|
||||
onHitProtect(source, target, move) {
|
||||
if (move.flags['contact']) {
|
||||
target.getMoveHitData(move).bypassProtect = this.effect;
|
||||
return false;
|
||||
}
|
||||
},
|
||||
// breaking protect handled in Battle#checkMoveBypassesProtect()
|
||||
flags: {},
|
||||
name: "Piercing Drill",
|
||||
rating: 1,
|
||||
num: 311,
|
||||
},
|
||||
pixilate: {
|
||||
onModifyTypePriority: -1,
|
||||
onModifyType(move, pokemon) {
|
||||
|
|
@ -3652,7 +3696,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
|
|||
},
|
||||
raindish: {
|
||||
onWeather(target, source, effect) {
|
||||
if (target.hasItem('utilityumbrella')) return;
|
||||
if (target.effectiveWeather() !== effect.id) return;
|
||||
if (effect.id === 'raindance' || effect.id === 'primordialsea') {
|
||||
this.heal(target.baseMaxhp / 16);
|
||||
}
|
||||
|
|
@ -4095,7 +4139,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
|
|||
},
|
||||
sheerforce: {
|
||||
onModifyMove(move, pokemon) {
|
||||
if (move.secondaries) {
|
||||
if (move.secondaries && !move.hasSheerForceBoost) {
|
||||
delete move.secondaries;
|
||||
// Technically not a secondary effect, but it is negated
|
||||
delete move.self;
|
||||
|
|
@ -4106,7 +4150,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
|
|||
},
|
||||
onBasePowerPriority: 21,
|
||||
onBasePower(basePower, pokemon, target, move) {
|
||||
if (move.hasSheerForce) return this.chainModify([5325, 4096]);
|
||||
if (move.hasSheerForce || move.hasSheerForceBoost) return this.chainModify([5325, 4096]);
|
||||
},
|
||||
flags: {},
|
||||
name: "Sheer Force",
|
||||
|
|
@ -4229,6 +4273,10 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
|
|||
return this.chainModify(0.5);
|
||||
}
|
||||
},
|
||||
onEnd(pokemon) {
|
||||
if (pokemon.beingCalledBack) return;
|
||||
this.add('-end', pokemon, 'Slow Start', '[silent]');
|
||||
},
|
||||
flags: {},
|
||||
name: "Slow Start",
|
||||
rating: -1,
|
||||
|
|
@ -4291,7 +4339,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
|
|||
}
|
||||
},
|
||||
onWeather(target, source, effect) {
|
||||
if (target.hasItem('utilityumbrella')) return;
|
||||
if (target.effectiveWeather() !== effect.id) return;
|
||||
if (effect.id === 'sunnyday' || effect.id === 'desolateland') {
|
||||
this.damage(target.baseMaxhp / 8, target, target);
|
||||
}
|
||||
|
|
@ -4353,6 +4401,16 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
|
|||
rating: 4.5,
|
||||
num: 3,
|
||||
},
|
||||
spicyspray: {
|
||||
isNonstandard: "Future",
|
||||
onDamagingHit(damage, target, source, move) {
|
||||
source.trySetStatus('brn', target);
|
||||
},
|
||||
flags: {},
|
||||
name: "Spicy Spray",
|
||||
rating: 3,
|
||||
num: 318,
|
||||
},
|
||||
stakeout: {
|
||||
onModifyAtkPriority: 5,
|
||||
onModifyAtk(atk, attacker, defender) {
|
||||
|
|
@ -5240,20 +5298,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
|
|||
},
|
||||
wanderingspirit: {
|
||||
onDamagingHit(damage, target, source, move) {
|
||||
if (source.getAbility().flags['failskillswap'] || target.volatiles['dynamax']) return;
|
||||
|
||||
if (this.checkMoveMakesContact(move, source, target)) {
|
||||
const targetCanBeSet = this.runEvent('SetAbility', target, source, this.effect, source.ability);
|
||||
if (!targetCanBeSet) return targetCanBeSet;
|
||||
const sourceAbility = source.setAbility('wanderingspirit', target);
|
||||
if (!sourceAbility) return;
|
||||
if (target.isAlly(source)) {
|
||||
this.add('-activate', target, 'Skill Swap', '', '', `[of] ${source}`);
|
||||
} else {
|
||||
this.add('-activate', target, 'ability: Wandering Spirit', this.dex.abilities.get(sourceAbility).name, 'Wandering Spirit', `[of] ${source}`);
|
||||
}
|
||||
target.setAbility(sourceAbility);
|
||||
}
|
||||
if (this.checkMoveMakesContact(move, source, target)) this.skillSwap(source, target);
|
||||
},
|
||||
flags: {},
|
||||
name: "Wandering Spirit",
|
||||
|
|
|
|||
|
|
@ -15,9 +15,11 @@ export const Aliases: import('../sim/dex').AliasesTable = {
|
|||
zeroused: "[Gen 9] ZU",
|
||||
mono: "[Gen 9] Monotype",
|
||||
ag: "[Gen 9] Anything Goes",
|
||||
bss: "[Gen 9] BSS Reg J",
|
||||
vgc: "[Gen 9] VGC 2026 Reg F",
|
||||
bsd: "[Gen 9] VGC 2026 Reg F",
|
||||
champsou: "[Gen 9 Champions] OU",
|
||||
cou: "[Gen 9 Champions] OU",
|
||||
bss: "[Gen 9 Champions] BSS Reg M-A",
|
||||
vgc: "[Gen 9 Champions] VGC 2026 Reg M-A",
|
||||
bsd: "[Gen 9 Champions] VGC 2026 Reg M-A",
|
||||
randdubs: "[Gen 9] Random Doubles Battle",
|
||||
doubles: "[Gen 9] Doubles OU",
|
||||
dou: "[Gen 9] Doubles OU",
|
||||
|
|
@ -91,8 +93,10 @@ export const Aliases: import('../sim/dex').AliasesTable = {
|
|||
zaou: "[Gen 9] Legends Z-A OU",
|
||||
legendsou: "[Gen 9] Legends Z-A OU",
|
||||
plzaou: "[Gen 9] Legends Z-A OU",
|
||||
omotm: "[Gen 9] Pokebilities",
|
||||
lcotm: "[Gen 9] Tera Override",
|
||||
omotm: "[Gen 9] Alphabet Cup",
|
||||
lcotm: "[Gen 9] Cross Evolution",
|
||||
ommotm: "[Gen 9] STAAABmons",
|
||||
ommspotlight: "[Gen 9] STAAABmons",
|
||||
|
||||
// mega evos --- 1st ordered alphabetically by species, 2nd by alias
|
||||
megasnow: "Abomasnow-Mega",
|
||||
|
|
|
|||
|
|
@ -484,7 +484,7 @@ export const Conditions: import('../sim/dex-conditions').ConditionDataTable = {
|
|||
return 5;
|
||||
},
|
||||
onWeatherModifyDamage(damage, attacker, defender, move) {
|
||||
if (defender.hasItem('utilityumbrella')) return;
|
||||
if (defender.effectiveWeather() !== 'raindance') return;
|
||||
if (move.type === 'Water') {
|
||||
this.debug('rain water boost');
|
||||
return this.chainModify(1.5);
|
||||
|
|
@ -525,7 +525,7 @@ export const Conditions: import('../sim/dex-conditions').ConditionDataTable = {
|
|||
}
|
||||
},
|
||||
onWeatherModifyDamage(damage, attacker, defender, move) {
|
||||
if (defender.hasItem('utilityumbrella')) return;
|
||||
if (defender.effectiveWeather() !== 'primordialsea') return;
|
||||
if (move.type === 'Water') {
|
||||
this.debug('Rain water boost');
|
||||
return this.chainModify(1.5);
|
||||
|
|
@ -554,11 +554,11 @@ export const Conditions: import('../sim/dex-conditions').ConditionDataTable = {
|
|||
return 5;
|
||||
},
|
||||
onWeatherModifyDamage(damage, attacker, defender, move) {
|
||||
if (move.id === 'hydrosteam' && !attacker.hasItem('utilityumbrella')) {
|
||||
if (move.id === 'hydrosteam' && attacker.effectiveWeather() === 'sunnyday') {
|
||||
this.debug('Sunny Day Hydro Steam boost');
|
||||
return this.chainModify(1.5);
|
||||
}
|
||||
if (defender.hasItem('utilityumbrella')) return;
|
||||
if (defender.effectiveWeather() !== 'sunnyday') return;
|
||||
if (move.type === 'Fire') {
|
||||
this.debug('Sunny Day fire boost');
|
||||
return this.chainModify(1.5);
|
||||
|
|
@ -577,7 +577,7 @@ export const Conditions: import('../sim/dex-conditions').ConditionDataTable = {
|
|||
}
|
||||
},
|
||||
onImmunity(type, pokemon) {
|
||||
if (pokemon.hasItem('utilityumbrella')) return;
|
||||
if (pokemon.effectiveWeather() !== 'sunnyday') return;
|
||||
if (type === 'frz') return false;
|
||||
},
|
||||
onFieldResidualOrder: 1,
|
||||
|
|
@ -603,9 +603,9 @@ export const Conditions: import('../sim/dex-conditions').ConditionDataTable = {
|
|||
}
|
||||
},
|
||||
onWeatherModifyDamage(damage, attacker, defender, move) {
|
||||
if (defender.hasItem('utilityumbrella')) return;
|
||||
if (defender.effectiveWeather() !== 'desolateland') return;
|
||||
if (move.type === 'Fire') {
|
||||
this.debug('Sunny Day fire boost');
|
||||
this.debug('Desolate Land fire boost');
|
||||
return this.chainModify(1.5);
|
||||
}
|
||||
},
|
||||
|
|
@ -613,7 +613,7 @@ export const Conditions: import('../sim/dex-conditions').ConditionDataTable = {
|
|||
this.add('-weather', 'DesolateLand', '[from] ability: ' + effect.name, `[of] ${source}`);
|
||||
},
|
||||
onImmunity(type, pokemon) {
|
||||
if (pokemon.hasItem('utilityumbrella')) return;
|
||||
if (pokemon.effectiveWeather() !== 'desolateland') return;
|
||||
if (type === 'frz') return false;
|
||||
},
|
||||
onFieldResidualOrder: 1,
|
||||
|
|
@ -879,6 +879,67 @@ export const Conditions: import('../sim/dex-conditions').ConditionDataTable = {
|
|||
return [type];
|
||||
},
|
||||
},
|
||||
zacian: {
|
||||
name: 'Zacian',
|
||||
onBattleStart(pokemon) {
|
||||
if (pokemon.item !== 'rustedsword') return;
|
||||
const rawSpecies = this.dex.species.get('Zacian-Crowned');
|
||||
const species = pokemon.setSpecies(rawSpecies);
|
||||
if (!species) return;
|
||||
pokemon.baseSpecies = rawSpecies;
|
||||
pokemon.details = pokemon.getUpdatedDetails();
|
||||
pokemon.setAbility(species.abilities['0'], null, null, true);
|
||||
pokemon.baseAbility = pokemon.ability;
|
||||
|
||||
const ironHeadIndex = pokemon.baseMoves.indexOf('ironhead');
|
||||
if (ironHeadIndex >= 0) {
|
||||
const move = this.dex.moves.get('behemothblade');
|
||||
const pp = this.calculatePP(move, pokemon.ppUps[ironHeadIndex]);
|
||||
pokemon.baseMoveSlots[ironHeadIndex] = {
|
||||
move: move.name,
|
||||
id: move.id,
|
||||
pp,
|
||||
maxpp: pp,
|
||||
target: move.target,
|
||||
disabled: false,
|
||||
disabledSource: '',
|
||||
used: false,
|
||||
};
|
||||
pokemon.moveSlots = pokemon.baseMoveSlots.slice();
|
||||
}
|
||||
},
|
||||
},
|
||||
zamazenta: {
|
||||
name: 'Zamazenta',
|
||||
onBattleStart(pokemon) {
|
||||
if (pokemon.item !== 'rustedshield') return;
|
||||
const rawSpecies = this.dex.species.get('Zamazenta-Crowned');
|
||||
const species = pokemon.setSpecies(rawSpecies);
|
||||
if (!species) return;
|
||||
pokemon.baseSpecies = rawSpecies;
|
||||
pokemon.details = pokemon.getUpdatedDetails();
|
||||
pokemon.setAbility(species.abilities['0'], null, null, true);
|
||||
pokemon.baseAbility = pokemon.ability;
|
||||
|
||||
const ironHeadIndex = pokemon.baseMoves.indexOf('ironhead');
|
||||
if (ironHeadIndex >= 0) {
|
||||
const move = this.dex.moves.get('behemothbash');
|
||||
const pp = this.calculatePP(move, pokemon.ppUps[ironHeadIndex]);
|
||||
pokemon.baseMoveSlots[ironHeadIndex] = {
|
||||
move: move.name,
|
||||
id: move.id,
|
||||
pp,
|
||||
maxpp: pp,
|
||||
target: move.target,
|
||||
disabled: false,
|
||||
disabledSource: '',
|
||||
used: false,
|
||||
};
|
||||
pokemon.moveSlots = pokemon.baseMoveSlots.slice();
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
rolloutstorage: {
|
||||
name: 'rolloutstorage',
|
||||
duration: 2,
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
beedrillmega: {
|
||||
isNonstandard: "Past",
|
||||
tier: "Illegal",
|
||||
natDexTier: "UU",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
pidgey: {
|
||||
isNonstandard: "Past",
|
||||
|
|
@ -381,7 +381,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
tier: "NFE",
|
||||
},
|
||||
vileplume: {
|
||||
tier: "NU",
|
||||
tier: "PU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
|
|
@ -464,7 +464,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
tier: "LC",
|
||||
},
|
||||
primeape: {
|
||||
tier: "ZU",
|
||||
tier: "NFE",
|
||||
doublesTier: "NFE",
|
||||
natDexTier: "NFE",
|
||||
},
|
||||
|
|
@ -475,7 +475,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
tier: "LC",
|
||||
},
|
||||
arcanine: {
|
||||
tier: "PU",
|
||||
tier: "NU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
|
|
@ -560,7 +560,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
tentacruel: {
|
||||
tier: "NU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "UU",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
geodude: {
|
||||
tier: "LC",
|
||||
|
|
@ -613,7 +613,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
slowbro: {
|
||||
tier: "RU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "UU",
|
||||
natDexTier: "OU",
|
||||
},
|
||||
slowbromega: {
|
||||
isNonstandard: "Past",
|
||||
|
|
@ -621,7 +621,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
natDexTier: "RUBL",
|
||||
},
|
||||
slowbrogalar: {
|
||||
tier: "NU",
|
||||
tier: "PU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
|
|
@ -696,7 +696,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
natDexTier: "RU",
|
||||
},
|
||||
shellder: {
|
||||
tier: "LC",
|
||||
tier: "NFE",
|
||||
},
|
||||
cloyster: {
|
||||
tier: "NUBL",
|
||||
|
|
@ -1116,7 +1116,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
tier: "NFE",
|
||||
},
|
||||
porygon2: {
|
||||
tier: "ZUBL",
|
||||
tier: "PU",
|
||||
doublesTier: "DUU",
|
||||
natDexTier: "NFE",
|
||||
},
|
||||
|
|
@ -1159,7 +1159,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
tier: "LC",
|
||||
},
|
||||
snorlax: {
|
||||
tier: "ZU",
|
||||
tier: "PU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
|
|
@ -1194,7 +1194,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
},
|
||||
moltresgalar: {
|
||||
tier: "UUBL",
|
||||
doublesTier: "DUU",
|
||||
doublesTier: "DOU",
|
||||
natDexTier: "RUBL",
|
||||
},
|
||||
dratini: {
|
||||
|
|
@ -1228,7 +1228,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
natDexTier: "Uber",
|
||||
},
|
||||
mew: {
|
||||
tier: "RU",
|
||||
tier: "UU",
|
||||
doublesTier: "DUU",
|
||||
natDexTier: "UU",
|
||||
},
|
||||
|
|
@ -1316,7 +1316,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
tier: "LC",
|
||||
},
|
||||
lanturn: {
|
||||
tier: "ZU",
|
||||
tier: "PU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
|
|
@ -1521,17 +1521,19 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
natDexTier: "RU",
|
||||
},
|
||||
heracross: {
|
||||
tier: "PUBL",
|
||||
tier: "PU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
heracrossmega: {
|
||||
isNonstandard: "Past",
|
||||
tier: "Illegal",
|
||||
natDexTier: "UU",
|
||||
natDexTier: "RUBL",
|
||||
},
|
||||
sneasel: {
|
||||
tier: "NFE",
|
||||
tier: "ZU",
|
||||
doublesTier: "NFE",
|
||||
natDexTier: "NFE",
|
||||
},
|
||||
sneaselhisui: {
|
||||
tier: "ZU",
|
||||
|
|
@ -1557,7 +1559,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
ursaluna: {
|
||||
tier: "UUBL",
|
||||
doublesTier: "DOU",
|
||||
natDexTier: "UU",
|
||||
natDexTier: "RUBL",
|
||||
},
|
||||
ursalunabloodmoon: {
|
||||
tier: "Uber",
|
||||
|
|
@ -1579,7 +1581,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
tier: "NFE",
|
||||
},
|
||||
mamoswine: {
|
||||
tier: "RUBL",
|
||||
tier: "UU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "RUBL",
|
||||
},
|
||||
|
|
@ -1700,7 +1702,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
tyranitarmega: {
|
||||
isNonstandard: "Past",
|
||||
tier: "Illegal",
|
||||
natDexTier: "UUBL",
|
||||
natDexTier: "OU",
|
||||
},
|
||||
lugia: {
|
||||
tier: "Uber",
|
||||
|
|
@ -1758,7 +1760,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
swampert: {
|
||||
tier: "NU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "RU",
|
||||
natDexTier: "UU",
|
||||
},
|
||||
swampertmega: {
|
||||
isNonstandard: "Past",
|
||||
|
|
@ -1877,11 +1879,11 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
gardevoirmega: {
|
||||
isNonstandard: "Past",
|
||||
tier: "Illegal",
|
||||
natDexTier: "RUBL",
|
||||
natDexTier: "UU",
|
||||
},
|
||||
gallade: {
|
||||
tier: "RU",
|
||||
doublesTier: "(DUU)",
|
||||
doublesTier: "DUU",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
gallademega: {
|
||||
|
|
@ -1980,7 +1982,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
sableyemega: {
|
||||
isNonstandard: "Past",
|
||||
tier: "Illegal",
|
||||
natDexTier: "RUBL",
|
||||
natDexTier: "UU",
|
||||
},
|
||||
mawile: {
|
||||
isNonstandard: "Past",
|
||||
|
|
@ -2096,7 +2098,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
sharpedomega: {
|
||||
isNonstandard: "Past",
|
||||
tier: "Illegal",
|
||||
natDexTier: "RU",
|
||||
natDexTier: "RUBL",
|
||||
},
|
||||
wailmer: {
|
||||
isNonstandard: "Past",
|
||||
|
|
@ -2701,7 +2703,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
tier: "LC",
|
||||
},
|
||||
skuntank: {
|
||||
tier: "PU",
|
||||
tier: "ZU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
|
|
@ -2838,12 +2840,12 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
natDexTier: "RU",
|
||||
},
|
||||
rotommow: {
|
||||
tier: "ZU",
|
||||
tier: "PU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
uxie: {
|
||||
tier: "PU",
|
||||
tier: "NU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
|
|
@ -2926,7 +2928,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
tier: "Illegal",
|
||||
},
|
||||
shaymin: {
|
||||
tier: "ZU",
|
||||
tier: "PU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
|
|
@ -3136,7 +3138,9 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
tier: "LC",
|
||||
},
|
||||
gurdurr: {
|
||||
tier: "NFE",
|
||||
tier: "ZU",
|
||||
doublesTier: "NFE",
|
||||
natDexTier: "NFE",
|
||||
},
|
||||
conkeldurr: {
|
||||
tier: "UU",
|
||||
|
|
@ -3290,7 +3294,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
tier: "NFE",
|
||||
},
|
||||
scrafty: {
|
||||
tier: "NU",
|
||||
tier: "PU",
|
||||
doublesTier: "DUU",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
|
|
@ -3646,7 +3650,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
mandibuzz: {
|
||||
tier: "UU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "UU",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
heatmor: {
|
||||
isNonstandard: "Past",
|
||||
|
|
@ -3665,7 +3669,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
tier: "NFE",
|
||||
},
|
||||
hydreigon: {
|
||||
tier: "RUBL",
|
||||
tier: "UU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "UU",
|
||||
},
|
||||
|
|
@ -3683,7 +3687,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
natDexTier: "RU",
|
||||
},
|
||||
terrakion: {
|
||||
tier: "NUBL",
|
||||
tier: "RU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "RUBL",
|
||||
},
|
||||
|
|
@ -3848,7 +3852,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
tier: "NFE",
|
||||
},
|
||||
talonflame: {
|
||||
tier: "RU",
|
||||
tier: "UU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
|
|
@ -4197,7 +4201,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
},
|
||||
hoopaunbound: {
|
||||
tier: "UUBL",
|
||||
doublesTier: "(DUU)",
|
||||
doublesTier: "DUU",
|
||||
natDexTier: "UUBL",
|
||||
},
|
||||
volcanion: {
|
||||
|
|
@ -4241,7 +4245,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
primarina: {
|
||||
tier: "OU",
|
||||
doublesTier: "DOU",
|
||||
natDexTier: "UU",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
pikipek: {
|
||||
tier: "LC",
|
||||
|
|
@ -4294,7 +4298,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
tier: "Illegal",
|
||||
},
|
||||
oricorio: {
|
||||
tier: "ZU",
|
||||
tier: "ZUBL",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
|
|
@ -4304,7 +4308,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
natDexTier: "RU",
|
||||
},
|
||||
oricoriopau: {
|
||||
tier: "ZU",
|
||||
tier: "ZUBL",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
|
|
@ -4342,7 +4346,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
natDexTier: "RU",
|
||||
},
|
||||
lycanrocdusk: {
|
||||
tier: "RU",
|
||||
tier: "NUBL",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
|
|
@ -4448,7 +4452,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
natDexTier: "RU",
|
||||
},
|
||||
passimian: {
|
||||
tier: "ZU",
|
||||
tier: "PU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
|
|
@ -4460,7 +4464,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
golisopod: {
|
||||
isNonstandard: "Past",
|
||||
tier: "Illegal",
|
||||
natDexTier: "UU",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
golisopodmega: {
|
||||
isNonstandard: "Future",
|
||||
|
|
@ -4717,7 +4721,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
natDexTier: "RU",
|
||||
},
|
||||
necrozma: {
|
||||
tier: "NUBL",
|
||||
tier: "RU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
|
|
@ -4777,7 +4781,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
zeraora: {
|
||||
isNonstandard: "Past",
|
||||
tier: "Illegal",
|
||||
natDexTier: "RU",
|
||||
natDexTier: "UU",
|
||||
},
|
||||
zeraoramega: {
|
||||
isNonstandard: "Future",
|
||||
|
|
@ -4808,7 +4812,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
rillaboom: {
|
||||
tier: "OU",
|
||||
doublesTier: "DOU",
|
||||
natDexTier: "UU",
|
||||
natDexTier: "OU",
|
||||
},
|
||||
rillaboomgmax: {
|
||||
isNonstandard: "Past",
|
||||
|
|
@ -4998,7 +5002,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
tier: "LC",
|
||||
},
|
||||
barraskewda: {
|
||||
tier: "NU",
|
||||
tier: "RU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
|
|
@ -5006,7 +5010,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
tier: "LC",
|
||||
},
|
||||
toxtricity: {
|
||||
tier: "NU",
|
||||
tier: "RU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
|
|
@ -5154,7 +5158,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
dracozolt: {
|
||||
isNonstandard: "Past",
|
||||
tier: "Illegal",
|
||||
natDexTier: "UU",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
arctozolt: {
|
||||
isNonstandard: "Past",
|
||||
|
|
@ -5322,7 +5326,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
quaquaval: {
|
||||
tier: "UUBL",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "UU",
|
||||
natDexTier: "RUBL",
|
||||
},
|
||||
lechonk: {
|
||||
tier: "LC",
|
||||
|
|
@ -5351,7 +5355,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
lokix: {
|
||||
tier: "UU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "UU",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
rellor: {
|
||||
tier: "LC",
|
||||
|
|
@ -5548,7 +5552,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
garganacl: {
|
||||
tier: "OU",
|
||||
doublesTier: "DUU",
|
||||
natDexTier: "UU",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
glimmet: {
|
||||
tier: "LC",
|
||||
|
|
@ -5556,7 +5560,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
glimmora: {
|
||||
tier: "OU",
|
||||
doublesTier: "DOU",
|
||||
natDexTier: "RU",
|
||||
natDexTier: "UU",
|
||||
},
|
||||
glimmoramega: {
|
||||
isNonstandard: "Future",
|
||||
|
|
@ -5686,7 +5690,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
natDexTier: "Uber",
|
||||
},
|
||||
wochien: {
|
||||
tier: "NU",
|
||||
tier: "PU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
|
|
@ -5727,7 +5731,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
ceruledge: {
|
||||
tier: "OU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "UUBL",
|
||||
natDexTier: "OU",
|
||||
},
|
||||
toedscool: {
|
||||
tier: "LC",
|
||||
|
|
@ -5772,8 +5776,8 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
},
|
||||
okidogi: {
|
||||
tier: "UUBL",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "RUBL",
|
||||
doublesTier: "DOU",
|
||||
natDexTier: "UUBL",
|
||||
},
|
||||
munkidori: {
|
||||
tier: "NU",
|
||||
|
|
@ -5786,7 +5790,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
natDexTier: "RU",
|
||||
},
|
||||
ogerpon: {
|
||||
tier: "UU",
|
||||
tier: "OU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "RU",
|
||||
},
|
||||
|
|
@ -5828,7 +5832,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
ironboulder: {
|
||||
tier: "UUBL",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "UU",
|
||||
natDexTier: "RUBL",
|
||||
},
|
||||
ironcrown: {
|
||||
tier: "OU",
|
||||
|
|
@ -5848,7 +5852,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
pecharunt: {
|
||||
tier: "OU",
|
||||
doublesTier: "(DUU)",
|
||||
natDexTier: "UU",
|
||||
natDexTier: "UUBL",
|
||||
},
|
||||
missingno: {
|
||||
isNonstandard: "Custom",
|
||||
|
|
@ -6162,6 +6166,10 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable =
|
|||
isNonstandard: "CAP",
|
||||
tier: "CAP",
|
||||
},
|
||||
flox: {
|
||||
isNonstandard: "CAP",
|
||||
tier: "CAP LC",
|
||||
},
|
||||
shox: {
|
||||
isNonstandard: "CAP",
|
||||
tier: "CAP",
|
||||
|
|
|
|||
618
data/items.ts
618
data/items.ts
File diff suppressed because it is too large
Load Diff
|
|
@ -32244,18 +32244,22 @@ export const Learnsets: import('../sim/dex-species').LearnsetDataTable = {
|
|||
smeargle: {
|
||||
learnset: {
|
||||
captivate: ["5D"],
|
||||
falseswipe: ["5S1"],
|
||||
flamethrower: ["6S2"],
|
||||
furyswipes: ["6S2"],
|
||||
meanlook: ["5S1"],
|
||||
odorsleuth: ["5S1"],
|
||||
seismictoss: ["6S2"],
|
||||
sketch: ["9L1", "7L1", "7V", "6L1", "6S2", "5L1", "5D", "4L1", "3L1", "3S0"],
|
||||
doubleslap: ["3S1"],
|
||||
falseswipe: ["5S2"],
|
||||
flamethrower: ["6S3"],
|
||||
furyswipes: ["6S3"],
|
||||
irontail: ["3S1"],
|
||||
meanlook: ["5S2"],
|
||||
odorsleuth: ["5S2"],
|
||||
seismictoss: ["6S3"],
|
||||
sketch: ["9L1", "7L1", "7V", "6L1", "6S3", "5L1", "5D", "4L1", "3L1", "3S1", "3S0"],
|
||||
sleeptalk: ["5D"],
|
||||
spore: ["5S1"],
|
||||
spore: ["5S2"],
|
||||
tailwhip: ["3S1"],
|
||||
},
|
||||
eventData: [
|
||||
{generation: 3, level: 10, gender: "M", abilities: ["owntempo"], moves: ["sketch"], pokeball: "pokeball"},
|
||||
{generation: 3, level: 45, abilities: ["owntempo"], moves: ["sketch", "tailwhip", "doubleslap", "irontail"]},
|
||||
{generation: 5, level: 50, gender: "F", nature: "Jolly", ivs: {atk: 31, spe: 31}, abilities: ["technician"], moves: ["falseswipe", "spore", "odorsleuth", "meanlook"], pokeball: "cherishball"},
|
||||
{generation: 6, level: 40, gender: "M", nature: "Jolly", abilities: ["owntempo"], moves: ["sketch", "furyswipes", "seismictoss", "flamethrower"], pokeball: "cherishball"},
|
||||
],
|
||||
|
|
@ -49730,12 +49734,85 @@ export const Learnsets: import('../sim/dex-species').LearnsetDataTable = {
|
|||
},
|
||||
gastrodoneast: {
|
||||
learnset: {
|
||||
earthpower: ["9S3", "9S2", "8S1", "8S0"],
|
||||
icebeam: ["9S2", "8S1", "8S0"],
|
||||
icywind: ["9S3"],
|
||||
protect: ["9S3", "9S2", "8S1", "8S0"],
|
||||
surf: ["8S0"],
|
||||
yawn: ["9S3", "9S2", "8S1"],
|
||||
amnesia: ["9M", "8M"],
|
||||
ancientpower: ["9L20", "8L20", "4T"],
|
||||
attract: ["8M", "7M", "6M", "5M", "4M"],
|
||||
blizzard: ["9M", "8M", "7M", "6M", "5M", "4M"],
|
||||
block: ["7T", "6T", "5T", "4T"],
|
||||
bodyslam: ["9M", "9L25", "8M", "8L25", "7L29", "6L29", "5L29", "4L29"],
|
||||
brine: ["8M", "4M"],
|
||||
bulldoze: ["9M", "8M", "7M", "6M", "5M"],
|
||||
captivate: ["4M"],
|
||||
chillingwater: ["9M"],
|
||||
confide: ["7M", "6M"],
|
||||
curse: ["9M"],
|
||||
dig: ["9M", "8M", "6M", "5M", "4M"],
|
||||
dive: ["8M", "6M", "5M", "4T"],
|
||||
doubleteam: ["7M", "6M", "5M", "4M"],
|
||||
earthpower: ["9M", "9L39", "9S2", "9S3", "8M", "8L39", "8S0", "8S1", "7T", "6T", "5T", "4T"],
|
||||
earthquake: ["9M", "8M", "7M", "6M", "5M", "4M"],
|
||||
endure: ["9M", "8M", "4M"],
|
||||
facade: ["9M", "8M", "7M", "6M", "5M", "4M"],
|
||||
flash: ["6M", "5M", "4M"],
|
||||
frustration: ["7M", "6M", "5M", "4M"],
|
||||
gigaimpact: ["9M", "8M", "7M", "6M", "5M", "4M"],
|
||||
hail: ["8M", "7M", "6M", "5M", "4M"],
|
||||
harden: ["9L1", "8L1", "7L1", "6L1", "5L1", "4L1"],
|
||||
headbutt: ["4T"],
|
||||
helpinghand: ["9M"],
|
||||
hiddenpower: ["7M", "7L16", "6M", "6L16", "5M", "5L16", "4M", "4L16"],
|
||||
hydropump: ["9M", "8M"],
|
||||
hyperbeam: ["9M", "8M", "7M", "6M", "5M", "4M"],
|
||||
icebeam: ["9M", "9S2", "8M", "8S0", "8S1", "7M", "6M", "5M", "4M"],
|
||||
icywind: ["9M", "9S3", "8M", "7T", "6T", "5T", "4T"],
|
||||
infestation: ["7M", "6M"],
|
||||
liquidation: ["9M"],
|
||||
memento: ["9L53", "8L53"],
|
||||
mudbomb: ["7L11", "6L11", "5L11", "4L11"],
|
||||
muddywater: ["9M", "9L33", "8M", "8L33", "7L41", "6L41", "5L41", "4L41"],
|
||||
mudshot: ["9M", "8M"],
|
||||
mudslap: ["9M", "9L1", "8L1", "7L1", "6L1", "5L1", "4T", "4L1"],
|
||||
mudsport: ["7L1", "6L1", "5L1", "4L1"],
|
||||
naturalgift: ["4M"],
|
||||
painsplit: ["9M", "7T", "6T", "5T", "4T"],
|
||||
protect: ["9M", "9S2", "9S3", "8M", "8S0", "8S1", "7M", "6M", "5M", "4M"],
|
||||
raindance: ["9M", "9L46", "8M", "8L46", "7M", "7L22", "6M", "6L22", "5M", "5L22", "4M", "4L22"],
|
||||
recover: ["9L1", "8L1", "7L54", "6L54", "5L54", "4L54"],
|
||||
rest: ["9M", "8M", "7M", "6M", "5M", "4M"],
|
||||
return: ["7M", "6M", "5M", "4M"],
|
||||
rockblast: ["9M"],
|
||||
rockslide: ["9M", "8M", "7M", "6M", "5M", "4M"],
|
||||
rocksmash: ["6M", "5M", "4M"],
|
||||
rocktomb: ["9M", "8M", "7M", "6M", "5M", "4M"],
|
||||
round: ["8M", "7M", "6M", "5M"],
|
||||
sandstorm: ["9M", "8M", "7M", "6M", "5M", "4M"],
|
||||
sandtomb: ["9M", "8M"],
|
||||
scald: ["8M", "7M", "6M", "5M"],
|
||||
secretpower: ["6M", "4M"],
|
||||
skittersmack: ["9M", "8T"],
|
||||
sleeptalk: ["9M", "8M", "7M", "6M", "5T", "4M"],
|
||||
sludgebomb: ["9M", "8M", "7M", "6M", "5M", "4M"],
|
||||
sludgewave: ["9M", "8M", "7M", "6M", "5M"],
|
||||
snore: ["8M", "7T", "6T", "5T", "4T"],
|
||||
snowscape: ["9M"],
|
||||
spikes: ["9M"],
|
||||
stealthrock: ["9M"],
|
||||
stompingtantrum: ["9M", "8M", "7T"],
|
||||
stoneedge: ["9M", "8M", "7M", "6M", "5M", "4M"],
|
||||
strength: ["6M", "5M", "4M"],
|
||||
stringshot: ["4T"],
|
||||
substitute: ["9M", "8M", "7M", "6M", "5M", "4M"],
|
||||
surf: ["9M", "8M", "8S0", "7M", "6M", "5M", "4M"],
|
||||
swagger: ["7M", "6M", "5M", "4M"],
|
||||
takedown: ["9M"],
|
||||
terablast: ["9M"],
|
||||
toxic: ["7M", "6M", "5M", "4M"],
|
||||
waterfall: ["9M", "8M", "7M", "6M", "5M", "4M"],
|
||||
watergun: ["9L1", "8L1"],
|
||||
waterpulse: ["9M", "9L15", "8L15", "7T", "7L1", "6T", "6L1", "5L1", "4M", "4L1"],
|
||||
weatherball: ["9M", "8M"],
|
||||
whirlpool: ["9M", "8M", "4M"],
|
||||
yawn: ["9S2", "9S3", "8S1"],
|
||||
},
|
||||
eventData: [
|
||||
{generation: 8, level: 50, gender: "F", nature: "Quiet", abilities: ["stormdrain"], ivs: {hp: 31, atk: 2, def: 31, spa: 31, spd: 31, spe: 0}, moves: ["protect", "surf", "icebeam", "earthpower"], pokeball: "cherishball"},
|
||||
|
|
@ -53582,7 +53659,7 @@ export const Learnsets: import('../sim/dex-species').LearnsetDataTable = {
|
|||
{generation: 6, level: 1, moves: ["tailglow", "bubble", "watersport", "heartswap"], pokeball: "cherishball"},
|
||||
{generation: 6, level: 100, moves: ["tailglow", "bubble", "watersport"], pokeball: "cherishball"},
|
||||
{generation: 7, level: 15, moves: ["tailglow", "waterpulse", "aquaring", "heartswap"], pokeball: "cherishball"},
|
||||
{generation: 8, moves: ['tailglow', 'watergun'], pokeball: 'pokeball', source: "gen8bdsp"},
|
||||
{generation: 8, level: 1, moves: ['tailglow', 'watergun'], pokeball: 'pokeball', source: "gen8bdsp"},
|
||||
{generation: 8, level: 50, moves: ["waterpulse", "zenheadbutt", "moonblast", "bubble"], source: "gen8legends"},
|
||||
{generation: 9, level: 50, shiny: true, nature: "Calm", ivs: {hp: 31, atk: 20, def: 31, spa: 20, spd: 31, spe: 20}, moves: ["bubblebeam", "acidarmor", "whirlpool", "waterpulse"], pokeball: "cherishball"},
|
||||
],
|
||||
|
|
@ -72938,10 +73015,79 @@ export const Learnsets: import('../sim/dex-species').LearnsetDataTable = {
|
|||
},
|
||||
pumpkaboosuper: {
|
||||
learnset: {
|
||||
astonish: ["6S0"],
|
||||
scaryface: ["6S0"],
|
||||
shadowsneak: ["6S0"],
|
||||
trickortreat: ["6S0"],
|
||||
allyswitch: ["8M", "7T"],
|
||||
astonish: ["8L1", "7L1", "6L1", "6S0"],
|
||||
attract: ["8M", "7M", "6M"],
|
||||
bestow: ["7E", "6E"],
|
||||
bulletseed: ["8M", "8L20", "7L26", "6L26"],
|
||||
chargebeam: ["7M", "6M"],
|
||||
confide: ["7M", "6M"],
|
||||
confuseray: ["8L8", "7L1", "6L1"],
|
||||
curse: ["8E", "7E"],
|
||||
darkpulse: ["8M", "7M", "6M"],
|
||||
destinybond: ["8E", "7E", "6E"],
|
||||
disable: ["8E", "7E", "6E"],
|
||||
doubleteam: ["7M", "6M"],
|
||||
dreameater: ["7M", "6M"],
|
||||
endure: ["8M"],
|
||||
energyball: ["8M", "7M", "6M"],
|
||||
explosion: ["7M", "6M"],
|
||||
facade: ["8M", "7M", "6M"],
|
||||
fireblast: ["8M", "7M", "6M"],
|
||||
flamecharge: ["7M", "6M"],
|
||||
flamethrower: ["8M", "7M", "6M"],
|
||||
flash: ["6M"],
|
||||
foulplay: ["8M", "7T", "6T"],
|
||||
frustration: ["7M", "6M"],
|
||||
gigadrain: ["8M", "7T", "6T"],
|
||||
grassknot: ["8M", "7M", "6M"],
|
||||
grassyglide: ["8T"],
|
||||
gyroball: ["8M", "7M", "6M"],
|
||||
hex: ["8M"],
|
||||
hiddenpower: ["7M", "6M"],
|
||||
imprison: ["8M"],
|
||||
incinerate: ["6M"],
|
||||
leechseed: ["8L16", "7L20", "6L20"],
|
||||
lightscreen: ["8M", "7M", "6M"],
|
||||
magiccoat: ["7T", "6T"],
|
||||
mysticalfire: ["8M"],
|
||||
naturepower: ["7M", "6M"],
|
||||
painsplit: ["8L44", "7T", "7L42", "6T", "6L42"],
|
||||
poltergeist: ["8T"],
|
||||
protect: ["8M", "7M", "6M"],
|
||||
psychic: ["8M", "7M", "6M"],
|
||||
razorleaf: ["8L12", "7L16", "6L16"],
|
||||
rest: ["8M", "7M", "6M"],
|
||||
return: ["7M", "6M"],
|
||||
rockslide: ["8M", "7M", "6M"],
|
||||
rocksmash: ["6M"],
|
||||
roleplay: ["7T", "6T"],
|
||||
round: ["8M", "7M", "6M"],
|
||||
safeguard: ["8M", "7M", "6M"],
|
||||
scaryface: ["8M", "8L24", "7L4", "6L4", "6S0"],
|
||||
secretpower: ["6M"],
|
||||
seedbomb: ["8M", "8L32", "7T", "7L48", "6T", "6L48"],
|
||||
shadowball: ["8M", "8L36", "7M", "7L36", "6M", "6L36"],
|
||||
shadowsneak: ["8L4", "7L30", "6L30", "6S0"],
|
||||
skillswap: ["8M", "7T", "6T"],
|
||||
skittersmack: ["8T"],
|
||||
sleeptalk: ["8M", "7M", "6M"],
|
||||
sludgebomb: ["8M", "7M", "6M"],
|
||||
snore: ["8M"],
|
||||
solarbeam: ["8M", "7M", "6M"],
|
||||
spite: ["7T", "6T"],
|
||||
substitute: ["8M", "7M", "6M"],
|
||||
sunnyday: ["8M", "7M", "6M"],
|
||||
swagger: ["7M", "6M"],
|
||||
synthesis: ["7T", "6T"],
|
||||
telekinesis: ["7T"],
|
||||
thief: ["8M", "7M", "6M"],
|
||||
toxic: ["7M", "6M"],
|
||||
trick: ["8M", "8L40", "7T", "7L1", "6T", "6L1"],
|
||||
trickortreat: ["8L1", "7L23", "6L6", "6S0"],
|
||||
trickroom: ["8M", "7M", "6M"],
|
||||
willowisp: ["8M", "7M", "6M"],
|
||||
worryseed: ["8L28", "7T", "7L11", "6T", "6L11"],
|
||||
},
|
||||
eventData: [
|
||||
{generation: 6, level: 50, moves: ["trickortreat", "astonish", "scaryface", "shadowsneak"], pokeball: "cherishball"},
|
||||
|
|
@ -73028,6 +73174,87 @@ export const Learnsets: import('../sim/dex-species').LearnsetDataTable = {
|
|||
worryseed: ["8L28", "7T", "7L11", "6T", "6L11"],
|
||||
},
|
||||
},
|
||||
gourgeistsuper: {
|
||||
learnset: {
|
||||
allyswitch: ["8M", "7T"],
|
||||
astonish: ["8L1", "7L1", "6L1"],
|
||||
attract: ["8M", "7M", "6M"],
|
||||
brutalswing: ["8M"],
|
||||
bulletseed: ["8M", "8L20", "7L26", "6L26"],
|
||||
chargebeam: ["7M", "6M"],
|
||||
confide: ["7M", "6M"],
|
||||
confuseray: ["8L1", "7L1", "6L1"],
|
||||
darkpulse: ["8M", "7M", "6M"],
|
||||
doubleteam: ["7M", "6M"],
|
||||
dreameater: ["7M", "6M"],
|
||||
endure: ["8M"],
|
||||
energyball: ["8M", "7M", "6M"],
|
||||
explosion: ["8L1", "7M", "7L1", "6M", "6L1"],
|
||||
facade: ["8M", "7M", "6M"],
|
||||
fireblast: ["8M", "7M", "6M"],
|
||||
flamecharge: ["7M", "6M"],
|
||||
flamethrower: ["8M", "7M", "6M"],
|
||||
flash: ["6M"],
|
||||
focusblast: ["8M", "7M", "6M"],
|
||||
foulplay: ["8M", "7T", "6T"],
|
||||
frustration: ["7M", "6M"],
|
||||
gigadrain: ["8M", "7T", "6T"],
|
||||
gigaimpact: ["8M", "7M", "6M"],
|
||||
grassknot: ["8M", "7M", "6M"],
|
||||
grassyglide: ["8T"],
|
||||
gyroball: ["8M", "7M", "6M"],
|
||||
hex: ["8M"],
|
||||
hiddenpower: ["7M", "6M"],
|
||||
hyperbeam: ["8M", "7M", "6M"],
|
||||
imprison: ["8M"],
|
||||
incinerate: ["6M"],
|
||||
leechseed: ["8L16", "7L20", "6L20"],
|
||||
lightscreen: ["8M", "7M", "6M"],
|
||||
magiccoat: ["7T", "6T"],
|
||||
moonblast: ["8L1"],
|
||||
mysticalfire: ["8M"],
|
||||
nastyplot: ["8M"],
|
||||
naturepower: ["7M", "6M"],
|
||||
painsplit: ["8L44", "7T", "7L42", "6T", "6L42"],
|
||||
phantomforce: ["8M", "8L48", "7L1", "6L1"],
|
||||
poltergeist: ["8T"],
|
||||
powerwhip: ["8M"],
|
||||
protect: ["8M", "7M", "6M"],
|
||||
psychic: ["8M", "7M", "6M"],
|
||||
razorleaf: ["8L12", "7L16", "6L16"],
|
||||
rest: ["8M", "7M", "6M"],
|
||||
return: ["7M", "6M"],
|
||||
rockslide: ["8M", "7M", "6M"],
|
||||
rocksmash: ["6M"],
|
||||
roleplay: ["7T", "6T"],
|
||||
round: ["8M", "7M", "6M"],
|
||||
safeguard: ["8M", "7M", "6M"],
|
||||
scaryface: ["8M", "8L24", "7L1", "6L4"],
|
||||
secretpower: ["6M"],
|
||||
seedbomb: ["8M", "8L32", "7T", "7L48", "6T", "6L48"],
|
||||
shadowball: ["8M", "8L36", "7M", "7L36", "6M", "6L36"],
|
||||
shadowsneak: ["8L1", "7L30", "6L30"],
|
||||
skillswap: ["8M", "7T", "6T"],
|
||||
skittersmack: ["8T"],
|
||||
sleeptalk: ["8M", "7M", "6M"],
|
||||
sludgebomb: ["8M", "7M", "6M"],
|
||||
snore: ["8M"],
|
||||
solarbeam: ["8M", "7M", "6M"],
|
||||
spite: ["7T", "6T"],
|
||||
substitute: ["8M", "7M", "6M"],
|
||||
sunnyday: ["8M", "7M", "6M"],
|
||||
swagger: ["7M", "6M"],
|
||||
synthesis: ["7T", "6T"],
|
||||
telekinesis: ["7T"],
|
||||
thief: ["8M", "7M", "6M"],
|
||||
toxic: ["7M", "6M"],
|
||||
trick: ["8M", "8L40", "7T", "7L1", "6T", "6L1"],
|
||||
trickortreat: ["8L1", "7L23", "6L6"],
|
||||
trickroom: ["8M", "7M", "6M"],
|
||||
willowisp: ["8M", "7M", "6M"],
|
||||
worryseed: ["8L28", "7T", "7L11", "6T", "6L11"],
|
||||
},
|
||||
},
|
||||
bergmite: {
|
||||
learnset: {
|
||||
afteryou: ["7T", "6T"],
|
||||
|
|
@ -84106,49 +84333,53 @@ export const Learnsets: import('../sim/dex-species').LearnsetDataTable = {
|
|||
},
|
||||
sinisteaantique: {
|
||||
learnset: {
|
||||
allyswitch: ["9E"],
|
||||
aromatherapy: ["8S0"],
|
||||
aromaticmist: ["9L6"],
|
||||
astonish: ["9L1"],
|
||||
batonpass: ["9M"],
|
||||
allyswitch: ["9E", "8M"],
|
||||
aromatherapy: ["8L30", "8S0"],
|
||||
aromaticmist: ["9L6", "8L6"],
|
||||
astonish: ["9L1", "8L1"],
|
||||
batonpass: ["9M", "8M"],
|
||||
calmmind: ["9M"],
|
||||
celebrate: ["8S0"],
|
||||
confuseray: ["9M"],
|
||||
curse: ["9M"],
|
||||
darkpulse: ["9M"],
|
||||
endure: ["9M"],
|
||||
facade: ["9M"],
|
||||
foulplay: ["9M"],
|
||||
gigadrain: ["9M", "9L36"],
|
||||
hex: ["9M"],
|
||||
imprison: ["9M"],
|
||||
darkpulse: ["9M", "8M"],
|
||||
endure: ["9M", "8M"],
|
||||
facade: ["9M", "8M"],
|
||||
foulplay: ["9M", "8M"],
|
||||
gigadrain: ["9M", "9L36", "8M", "8L36"],
|
||||
hex: ["9M", "8M"],
|
||||
imprison: ["9M", "8M"],
|
||||
magicalleaf: ["9M"],
|
||||
megadrain: ["9L12"],
|
||||
memento: ["9L54", "8S0"],
|
||||
metronome: ["9M", "8S0"],
|
||||
nastyplot: ["9M", "9L42"],
|
||||
megadrain: ["9L12", "8L12"],
|
||||
memento: ["9L54", "8L54", "8S0"],
|
||||
metronome: ["9M", "8M", "8S0"],
|
||||
nastyplot: ["9M", "9L42", "8M", "8L42"],
|
||||
nightshade: ["9M"],
|
||||
phantomforce: ["9M"],
|
||||
poltergeist: ["9M"],
|
||||
protect: ["9M"],
|
||||
payback: ["8M"],
|
||||
phantomforce: ["9M", "8M"],
|
||||
poltergeist: ["9M", "8T"],
|
||||
protect: ["9M", "8M", "8L18"],
|
||||
psybeam: ["9M"],
|
||||
psychic: ["9M"],
|
||||
psyshock: ["9M"],
|
||||
rest: ["9M"],
|
||||
shadowball: ["9M", "9L48"],
|
||||
shellsmash: ["9L60"],
|
||||
psychic: ["9M", "8M"],
|
||||
psyshock: ["9M", "8M"],
|
||||
rest: ["9M", "8M"],
|
||||
round: ["8M"],
|
||||
shadowball: ["9M", "9L48", "8M", "8L48"],
|
||||
shellsmash: ["9L60", "8L60"],
|
||||
skillswap: ["9M"],
|
||||
sleeptalk: ["9M"],
|
||||
sleeptalk: ["9M", "8M"],
|
||||
snore: ["8M"],
|
||||
spite: ["9M"],
|
||||
storedpower: ["9M"],
|
||||
substitute: ["9M"],
|
||||
suckerpunch: ["9L24"],
|
||||
storedpower: ["9M", "8M"],
|
||||
substitute: ["9M", "8M"],
|
||||
suckerpunch: ["9L24", "8L24"],
|
||||
sweetscent: ["9L30"],
|
||||
terablast: ["9M"],
|
||||
trick: ["9M"],
|
||||
trick: ["9M", "8M"],
|
||||
trickroom: ["9M"],
|
||||
willowisp: ["9M"],
|
||||
withdraw: ["9L1"],
|
||||
willowisp: ["9M", "8M"],
|
||||
withdraw: ["9L1", "8L1"],
|
||||
wonderroom: ["8M"],
|
||||
},
|
||||
eventData: [
|
||||
{generation: 8, level: 50, isHidden: true, moves: ["memento", "metronome", "aromatherapy", "celebrate"], pokeball: "cherishball"},
|
||||
|
|
@ -84212,6 +84443,64 @@ export const Learnsets: import('../sim/dex-species').LearnsetDataTable = {
|
|||
wonderroom: ["8M"],
|
||||
},
|
||||
},
|
||||
polteageistantique: {
|
||||
learnset: {
|
||||
allyswitch: ["8M"],
|
||||
aromatherapy: ["8L30"],
|
||||
aromaticmist: ["9L1", "8L1"],
|
||||
astonish: ["9L1", "8L1"],
|
||||
batonpass: ["9M", "8M"],
|
||||
calmmind: ["9M"],
|
||||
confuseray: ["9M"],
|
||||
curse: ["9M", "9L66", "8L66"],
|
||||
darkpulse: ["9M", "8M"],
|
||||
endure: ["9M", "8M"],
|
||||
facade: ["9M", "8M"],
|
||||
foulplay: ["9M", "8M"],
|
||||
gigadrain: ["9M", "9L36", "8M", "8L36"],
|
||||
gigaimpact: ["9M", "8M"],
|
||||
hex: ["9M", "8M"],
|
||||
hyperbeam: ["9M", "8M"],
|
||||
imprison: ["9M", "8M"],
|
||||
lightscreen: ["9M", "8M"],
|
||||
magicalleaf: ["9M"],
|
||||
megadrain: ["9L1", "8L1"],
|
||||
memento: ["9L54", "8L54"],
|
||||
metronome: ["9M", "8M"],
|
||||
nastyplot: ["9M", "9L42", "8M", "8L42"],
|
||||
nightshade: ["9M"],
|
||||
painsplit: ["9M"],
|
||||
payback: ["8M"],
|
||||
phantomforce: ["9M", "8M"],
|
||||
poltergeist: ["9M", "8T"],
|
||||
protect: ["9M", "9L18", "8M", "8L18"],
|
||||
psybeam: ["9M"],
|
||||
psychic: ["9M", "8M"],
|
||||
psyshock: ["9M", "8M"],
|
||||
reflect: ["9M", "8M"],
|
||||
rest: ["9M", "8M"],
|
||||
round: ["8M"],
|
||||
selfdestruct: ["8M"],
|
||||
shadowball: ["9M", "9L48", "8M", "8L48"],
|
||||
shellsmash: ["9L60", "8L60"],
|
||||
skillswap: ["9M"],
|
||||
sleeptalk: ["9M", "8M"],
|
||||
snore: ["8M"],
|
||||
spite: ["9M"],
|
||||
storedpower: ["9M", "8M"],
|
||||
strengthsap: ["9L1", "8L1"],
|
||||
substitute: ["9M", "8M"],
|
||||
suckerpunch: ["9L24", "8L24"],
|
||||
sweetscent: ["9L30"],
|
||||
teatime: ["9L0", "8L0"],
|
||||
terablast: ["9M"],
|
||||
trick: ["9M", "8M"],
|
||||
trickroom: ["9M"],
|
||||
willowisp: ["9M", "8M"],
|
||||
withdraw: ["9L1", "8L1"],
|
||||
wonderroom: ["8M"],
|
||||
},
|
||||
},
|
||||
hatenna: {
|
||||
learnset: {
|
||||
afteryou: ["9E", "8E"],
|
||||
|
|
@ -89284,7 +89573,7 @@ export const Learnsets: import('../sim/dex-species').LearnsetDataTable = {
|
|||
waterpulse: ["9M"],
|
||||
},
|
||||
eventData: [
|
||||
{generation: 9, moves: ["bodyslam", "amnesia", "icespinner", "doubleedge"]},
|
||||
{generation: 9, level: 50, moves: ["bodyslam", "amnesia", "icespinner", "doubleedge"]},
|
||||
],
|
||||
},
|
||||
frigibax: {
|
||||
|
|
@ -89471,10 +89760,43 @@ export const Learnsets: import('../sim/dex-species').LearnsetDataTable = {
|
|||
},
|
||||
tatsugiristretchy: {
|
||||
learnset: {
|
||||
batonpass: ["9M", "9E"],
|
||||
celebrate: ["9S0"],
|
||||
dracometeor: ["9S0"],
|
||||
helpinghand: ["9S0"],
|
||||
muddywater: ["9S0"],
|
||||
chillingwater: ["9M"],
|
||||
counter: ["9E"],
|
||||
dracometeor: ["9M", "9S0"],
|
||||
dragoncheer: ["9M"],
|
||||
dragondance: ["9M"],
|
||||
dragonpulse: ["9M", "9L52"],
|
||||
endure: ["9M"],
|
||||
facade: ["9M"],
|
||||
gigaimpact: ["9M"],
|
||||
harden: ["9L6"],
|
||||
helpinghand: ["9M", "9L12", "9S0"],
|
||||
hydropump: ["9M"],
|
||||
hyperbeam: ["9M"],
|
||||
icywind: ["9M"],
|
||||
lunge: ["9M"],
|
||||
memento: ["9L34"],
|
||||
mirrorcoat: ["9L47"],
|
||||
muddywater: ["9M", "9L39", "9S0"],
|
||||
nastyplot: ["9M", "9L43"],
|
||||
outrage: ["9M"],
|
||||
protect: ["9M"],
|
||||
raindance: ["9M"],
|
||||
rapidspin: ["9E"],
|
||||
rest: ["9M"],
|
||||
sleeptalk: ["9M"],
|
||||
soak: ["9L23"],
|
||||
splash: ["9L1"],
|
||||
substitute: ["9M"],
|
||||
surf: ["9M"],
|
||||
takedown: ["9M"],
|
||||
taunt: ["9M", "9L28"],
|
||||
terablast: ["9M"],
|
||||
watergun: ["9L1"],
|
||||
waterpulse: ["9M", "9L17"],
|
||||
whirlpool: ["9M"],
|
||||
},
|
||||
eventData: [
|
||||
{generation: 9, level: 50, moves: ["dracometeor", "muddywater", "helpinghand", "celebrate"], pokeball: "cherishball"},
|
||||
|
|
@ -99770,6 +100092,67 @@ export const Learnsets: import('../sim/dex-species').LearnsetDataTable = {
|
|||
{generation: 9, level: 50, shiny: true, abilities: ["armortail"], moves: ["celebrate", "dragontail", "sludgebomb", "dragondance"], pokeball: "cherishball"},
|
||||
],
|
||||
},
|
||||
flox: {
|
||||
learnset: {
|
||||
blizzard: ["9M"],
|
||||
bodyslam: ["9M"],
|
||||
bulldoze: ["9M"],
|
||||
charge: ["9M", "9L15"],
|
||||
chargebeam: ["9M"],
|
||||
charm: ["9M", "9L15"],
|
||||
dig: ["9M"],
|
||||
disarmingvoice: ["9M"],
|
||||
discharge: ["9L40"],
|
||||
doubleedge: ["9M", "9L50"],
|
||||
eerieimpulse: ["9M"],
|
||||
electricterrain: ["9M"],
|
||||
electroball: ["9M"],
|
||||
electroweb: ["9M"],
|
||||
endeavor: ["9M", "9E"],
|
||||
endure: ["9M"],
|
||||
facade: ["9M"],
|
||||
glare: ["9E"],
|
||||
growl: ["9L1"],
|
||||
headbutt: ["9L20"],
|
||||
helpinghand: ["9M"],
|
||||
hypervoice: ["9M"],
|
||||
icebeam: ["9M"],
|
||||
icywind: ["9M"],
|
||||
ironhead: ["9M"],
|
||||
milkdrink: ["9L30"],
|
||||
mudshot: ["9M"],
|
||||
mudslap: ["9M"],
|
||||
nuzzle: ["9E"],
|
||||
playrough: ["9M"],
|
||||
protect: ["9M"],
|
||||
raindance: ["9M"],
|
||||
rest: ["9M"],
|
||||
seedbomb: ["9M"],
|
||||
sleeptalk: ["9M"],
|
||||
spark: ["9L25"],
|
||||
spitup: ["9E"],
|
||||
stockpile: ["9E"],
|
||||
stompingtantrum: ["9M"],
|
||||
substitute: ["9M"],
|
||||
sunnyday: ["9M"],
|
||||
superfang: ["9M"],
|
||||
swallow: ["9E"],
|
||||
tackle: ["9L1"],
|
||||
takedown: ["9M", "9L35"],
|
||||
terablast: ["9M"],
|
||||
thief: ["9M"],
|
||||
thunder: ["9M"],
|
||||
thundershock: ["9L10"],
|
||||
thunderwave: ["9M", "9L5"],
|
||||
thunderbolt: ["9M"],
|
||||
trailblaze: ["9M"],
|
||||
uproar: ["9M"],
|
||||
voltswitch: ["9M"],
|
||||
wildcharge: ["9M"],
|
||||
zapcannon: ["9L55"],
|
||||
zenheadbutt: ["9M"],
|
||||
},
|
||||
},
|
||||
shox: {
|
||||
learnset: {
|
||||
blizzard: ["9M"],
|
||||
|
|
|
|||
231
data/mods/afd/abilities.ts
Normal file
231
data/mods/afd/abilities.ts
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTable = {
|
||||
chaossaliva: {
|
||||
onSourceDamagingHit(damage, target, source, move) {
|
||||
// Despite not being a secondary, Shield Dust / Covert Cloak block Poison Touch's effect
|
||||
if (target.hasAbility('shielddust') || target.hasItem('covertcloak')) return;
|
||||
if (this.checkMoveMakesContact(move, target, source)) {
|
||||
if (this.randomChance(2, 10)) {
|
||||
target.trySetStatus('par', source);
|
||||
}
|
||||
if (this.randomChance(2, 10)) {
|
||||
target.addVolatile('confusion', source);
|
||||
}
|
||||
}
|
||||
},
|
||||
flags: {},
|
||||
name: "Chaos Saliva",
|
||||
gen: 9,
|
||||
shortDesc: "Contact moves have a 20% chance to paralyze and a 20% chance to confuse.",
|
||||
},
|
||||
faststart: {
|
||||
onStart(pokemon) {
|
||||
this.add('-start', pokemon, 'ability: Fast Start');
|
||||
this.effectState.counter = 5;
|
||||
},
|
||||
onResidualOrder: 28,
|
||||
onResidualSubOrder: 2,
|
||||
onResidual(pokemon) {
|
||||
if (pokemon.activeTurns && this.effectState.counter) {
|
||||
this.effectState.counter--;
|
||||
if (!this.effectState.counter) {
|
||||
this.add('-end', pokemon, 'Fast Start');
|
||||
delete this.effectState.counter;
|
||||
}
|
||||
}
|
||||
},
|
||||
onModifyAtkPriority: 5,
|
||||
onModifyAtk(atk, pokemon) {
|
||||
if (this.effectState.counter) {
|
||||
return this.chainModify(2);
|
||||
}
|
||||
},
|
||||
onModifySpe(spe, pokemon) {
|
||||
if (this.effectState.counter) {
|
||||
return this.chainModify(2);
|
||||
}
|
||||
},
|
||||
onEnd(pokemon) {
|
||||
if (pokemon.beingCalledBack) return;
|
||||
this.add('-end', pokemon, 'Fast Start', '[silent]');
|
||||
},
|
||||
flags: {},
|
||||
name: "Fast Start",
|
||||
rating: -1,
|
||||
gen: 9,
|
||||
},
|
||||
ironfist: {
|
||||
inherit: true,
|
||||
onBasePower(basePower, attacker, defender, move) {
|
||||
if (move.flags['punch']) {
|
||||
this.debug('Iron Fist boost');
|
||||
return this.chainModify([8192, 4096]);
|
||||
}
|
||||
},
|
||||
},
|
||||
supermegalauncher: {
|
||||
onBasePowerPriority: 19,
|
||||
onBasePower(basePower, attacker, defender, move) {
|
||||
if (move.flags['pulse']) {
|
||||
return this.chainModify(4);
|
||||
}
|
||||
},
|
||||
flags: {},
|
||||
name: "Mega Launcher",
|
||||
desc: "This Pokemon's pulse moves have their power multiplied by 4. Heal Pulse restores 8/4 of a target's maximum HP, rounded half down.",
|
||||
shortDesc: "This Pokemon's pulse moves have 4x power. Heal Pulse heals 8/4 target's max HP.",
|
||||
rating: 3,
|
||||
gen: 9,
|
||||
},
|
||||
discourage: {
|
||||
onStart(pokemon) {
|
||||
let activated = false;
|
||||
for (const target of pokemon.adjacentFoes()) {
|
||||
if (!activated) {
|
||||
this.add('-ability', pokemon, 'Discourage', 'boost');
|
||||
activated = true;
|
||||
}
|
||||
if (target.volatiles['substitute']) {
|
||||
this.add('-immune', target);
|
||||
} else {
|
||||
this.boost({ spa: -1 }, target, pokemon, null, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
flags: {},
|
||||
name: "Discourage",
|
||||
rating: 3.5,
|
||||
num: 999,
|
||||
gen: 9,
|
||||
},
|
||||
adaptability: {
|
||||
inherit: true,
|
||||
onModifySTAB(stab, source, target, move) {
|
||||
if (move.forceSTAB || source.hasType(move.type)) {
|
||||
const types = source.getTypes();
|
||||
if (types[0] === move.type) return 2.3;
|
||||
if (types[1] && types[1] === move.type) return 1.6;
|
||||
if (stab === 2.3) {
|
||||
return 2.55;
|
||||
}
|
||||
return 2.7;
|
||||
}
|
||||
},
|
||||
},
|
||||
icebody: {
|
||||
inherit: true,
|
||||
onDamagingHit(damage, target, source, move) {
|
||||
if (this.checkMoveMakesContact(move, source, target)) {
|
||||
if (this.randomChance(1, 10)) {
|
||||
source.trySetStatus('frz', target);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
noretreat: {
|
||||
onStart(target) {
|
||||
this.add('-start', target, 'move: No Retreat');
|
||||
},
|
||||
onFoeBeforeSwitchOut(pokemon) {
|
||||
if (!pokemon || pokemon.fainted || pokemon.hp <= 0 || pokemon.hasAbility('noretreat')) return;
|
||||
const success = !!this.damage(pokemon.maxhp / 4, pokemon, this.effectState.target);
|
||||
if (success) {
|
||||
pokemon.tryTrap();
|
||||
}
|
||||
},
|
||||
name: "No Retreat",
|
||||
flags: { breakable: 1 },
|
||||
},
|
||||
itsexcadrillintime: {
|
||||
onModifySpe(spe, pokemon) {
|
||||
if (this.field.isWeather('sandstorm')) {
|
||||
return this.chainModify(2);
|
||||
}
|
||||
},
|
||||
onImmunity(type, pokemon) {
|
||||
if (type === 'sandstorm') return false;
|
||||
},
|
||||
onBasePowerPriority: 21,
|
||||
onBasePower(basePower, attacker, defender, move) {
|
||||
if (this.field.isWeather('sandstorm')) {
|
||||
if (move.type === 'Rock' || move.type === 'Ground' || move.type === 'Steel') {
|
||||
this.debug('Sand Force boost');
|
||||
return this.chainModify([5325, 4096]);
|
||||
}
|
||||
}
|
||||
},
|
||||
name: "It's Excadrillin' Time!",
|
||||
flags: {},
|
||||
},
|
||||
goodasgold: {
|
||||
inherit: true,
|
||||
onTryHit(target, source, move) {
|
||||
if (move.category !== 'Special' && target !== source) {
|
||||
this.add('-immune', target, '[from] ability: Good as Gold');
|
||||
return null;
|
||||
}
|
||||
},
|
||||
},
|
||||
intimidate2: {
|
||||
onStart(pokemon) {
|
||||
let activated = false;
|
||||
let timesActivated = 0;
|
||||
for (const target of pokemon.adjacentFoes()) {
|
||||
if (!activated) {
|
||||
this.add('-ability', pokemon, 'Intimidate 2', 'boost');
|
||||
activated = true;
|
||||
}
|
||||
if (target.volatiles['substitute']) {
|
||||
this.add('-immune', target);
|
||||
} else {
|
||||
this.boost({ atk: -1 }, target, pokemon, null, true);
|
||||
timesActivated++;
|
||||
}
|
||||
}
|
||||
if (timesActivated > 0) {
|
||||
for (let i = 0; i < timesActivated; i++) {
|
||||
this.boost({ atk: 1 }, pokemon, pokemon, null, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
flags: {},
|
||||
name: "Intimidate 2",
|
||||
rating: 3.5,
|
||||
num: 22,
|
||||
},
|
||||
asonemonarch: {
|
||||
onSwitchInPriority: 1,
|
||||
onStart(pokemon) {
|
||||
if (this.effectState.unnerved) return;
|
||||
this.add('-ability', pokemon, 'As One');
|
||||
this.add('-ability', pokemon, 'Unnerve');
|
||||
this.effectState.unnerved = true;
|
||||
},
|
||||
onEnd() {
|
||||
this.effectState.unnerved = false;
|
||||
},
|
||||
onFoeTryEatItem() {
|
||||
return !this.effectState.unnerved;
|
||||
},
|
||||
flags: { failroleplay: 1, noreceiver: 1, noentrain: 1, notrace: 1, failskillswap: 1, cantsuppress: 1 },
|
||||
name: "As One (Monarch)",
|
||||
rating: 3.5,
|
||||
num: 266,
|
||||
},
|
||||
intimidate: {
|
||||
inherit: true,
|
||||
onStart(pokemon) {
|
||||
let activated = false;
|
||||
for (const target of pokemon.adjacentFoes()) {
|
||||
if (!activated) {
|
||||
this.add('-ability', pokemon, 'Intimidate', 'boost');
|
||||
activated = true;
|
||||
}
|
||||
if (target.volatiles['substitute']) {
|
||||
this.add('-immune', target);
|
||||
} else {
|
||||
this.boost({ atk: -2 }, target, pokemon, null, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
22
data/mods/afd/conditions.ts
Normal file
22
data/mods/afd/conditions.ts
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
export const Conditions: import('../../../sim/dex-conditions').ModdedConditionDataTable = {
|
||||
sandstorm: {
|
||||
inherit: true,
|
||||
onWeatherModifyDamage(damage, attacker, defender, move) {
|
||||
if (defender.hasItem('utilityumbrella')) return;
|
||||
if (move.type === 'Rock') {
|
||||
this.debug('Sandstorm rock boost');
|
||||
return this.chainModify(1.5);
|
||||
}
|
||||
},
|
||||
},
|
||||
snowscape: {
|
||||
inherit: true,
|
||||
onModifySpePriority: 10,
|
||||
onModifySpe(spe, pokemon) {
|
||||
if (!pokemon.getTypes(false, true).includes('Ice') && !pokemon.getTypes(false, true).includes('Steel') &&
|
||||
!pokemon.hasAbility(['slushrush', 'snowcloak', 'iceface', 'icebody']) && pokemon.effectiveWeather() === 'snowscape') {
|
||||
return this.modify(spe, 0.5);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
93
data/mods/afd/items.ts
Normal file
93
data/mods/afd/items.ts
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
||||
hoots: {
|
||||
name: "Hoots",
|
||||
spritenum: 715,
|
||||
fling: {
|
||||
basePower: 80,
|
||||
},
|
||||
num: 1120,
|
||||
gen: 8,
|
||||
// Hazard Immunity implemented in moves.ts
|
||||
},
|
||||
luckycharm: {
|
||||
name: "Lucky Charm",
|
||||
onModifyMovePriority: -2,
|
||||
onModifyMove(move, pokemon, target) {
|
||||
let trigger = false;
|
||||
if (move.secondaries) {
|
||||
this.debug('doubling secondary chance');
|
||||
for (const secondary of move.secondaries) {
|
||||
if (secondary.chance && secondary.chance < 100) {
|
||||
secondary.chance = 100;
|
||||
if (!trigger) trigger = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (move.self?.chance) {
|
||||
move.self.chance = 100;
|
||||
trigger = true;
|
||||
}
|
||||
if (trigger) {
|
||||
pokemon.useItem();
|
||||
}
|
||||
},
|
||||
spritenum: 707,
|
||||
fling: {
|
||||
basePower: 120,
|
||||
},
|
||||
num: 9999,
|
||||
gen: 9,
|
||||
},
|
||||
onikaburger: {
|
||||
name: "Onika Burger",
|
||||
desc: "PP and damage of every move is halved. Gain 25% max HP at the end of each turn.",
|
||||
shortDesc: "PP and damage of every move is halved. Gain 25% max HP at the end of each turn.",
|
||||
onStart(target) {
|
||||
if (target.m.onikaBurger) return;
|
||||
target.m.onikaBurger = true;
|
||||
for (const moveSlot of target.moveSlots) {
|
||||
const deductPP = target.deductPP(moveSlot.id, moveSlot.maxpp / 2, target);
|
||||
if (!deductPP) continue;
|
||||
this.add('-activate', target, 'item: Onika Burger', moveSlot.move, deductPP);
|
||||
}
|
||||
},
|
||||
onModifyDamage() {
|
||||
return this.chainModify(0.5);
|
||||
},
|
||||
onResidualOrder: 5,
|
||||
onResidualSubOrder: 4,
|
||||
onResidual(pokemon) {
|
||||
this.heal(pokemon.baseMaxhp / 4);
|
||||
},
|
||||
},
|
||||
wardtag: {
|
||||
name: "Ward Tag",
|
||||
desc: "Reflects back 125% of the damage that would've been dealt. One-time use.",
|
||||
shortDesc: "Reflects back 125% of the damage that would've been dealt. One-time use.",
|
||||
onDamage(damage, target, source, effect) {
|
||||
if (source && target !== source && effect?.effectType === 'Move' && target.useItem()) {
|
||||
this.add('-activate', target, 'item: Ward Tag');
|
||||
this.damage(damage * 5 / 4, source, target);
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
},
|
||||
strengthpolicy: {
|
||||
name: "Strength Policy",
|
||||
spritenum: 609,
|
||||
fling: {
|
||||
basePower: 80,
|
||||
},
|
||||
onDamagingHit(damage, target, source, move) {
|
||||
if (!move.damage && !move.damageCallback && target.getMoveHitData(move).typeMod < 0) {
|
||||
target.useItem();
|
||||
}
|
||||
},
|
||||
boosts: {
|
||||
def: 2,
|
||||
spd: 2,
|
||||
},
|
||||
num: 639,
|
||||
gen: 6,
|
||||
},
|
||||
};
|
||||
599
data/mods/afd/moves.ts
Normal file
599
data/mods/afd/moves.ts
Normal file
|
|
@ -0,0 +1,599 @@
|
|||
export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
||||
banefulbunker: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
inherit: true,
|
||||
onTryHit(target, source, move) {
|
||||
if (this.checkMoveBypassesProtect(move, source, target)) return;
|
||||
if (move.smartTarget) {
|
||||
move.smartTarget = false;
|
||||
} else {
|
||||
if (!this.randomChance(2, 10)) {
|
||||
this.add('-activate', target, 'move: Protect');
|
||||
if (move.basePower >= 100) {
|
||||
this.add('message', '**BWUAHAAUAAAANGGGGGG**');
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const lockedmove = source.getVolatile('lockedmove');
|
||||
if (lockedmove) {
|
||||
// Outrage counter is reset
|
||||
if (source.volatiles['lockedmove'].duration === 2) {
|
||||
delete source.volatiles['lockedmove'];
|
||||
}
|
||||
}
|
||||
if (this.checkMoveMakesContact(move, source, target)) {
|
||||
source.trySetStatus('psn', target);
|
||||
}
|
||||
return this.NOT_FAIL;
|
||||
},
|
||||
},
|
||||
},
|
||||
burningbulwark: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
inherit: true,
|
||||
onTryHit(target, source, move) {
|
||||
if (this.checkMoveBypassesProtect(move, source, target, false)) return;
|
||||
if (move.smartTarget) {
|
||||
move.smartTarget = false;
|
||||
} else {
|
||||
if (!this.randomChance(2, 10)) {
|
||||
this.add('-activate', target, 'move: Protect');
|
||||
if (move.basePower >= 100) {
|
||||
this.add('message', '**BWUAHAAUAAAANGGGGGG**');
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const lockedmove = source.getVolatile('lockedmove');
|
||||
if (lockedmove) {
|
||||
// Outrage counter is reset
|
||||
if (source.volatiles['lockedmove'].duration === 2) {
|
||||
delete source.volatiles['lockedmove'];
|
||||
}
|
||||
}
|
||||
if (this.checkMoveMakesContact(move, source, target)) {
|
||||
source.trySetStatus('brn', target);
|
||||
}
|
||||
return this.NOT_FAIL;
|
||||
},
|
||||
},
|
||||
},
|
||||
kingsshield: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
inherit: true,
|
||||
onTryHit(target, source, move) {
|
||||
if (this.checkMoveBypassesProtect(move, source, target, false)) return;
|
||||
if (move.smartTarget) {
|
||||
move.smartTarget = false;
|
||||
} else {
|
||||
if (!this.randomChance(2, 10)) {
|
||||
this.add('-activate', target, 'move: Protect');
|
||||
if (move.basePower >= 100) {
|
||||
this.add('message', '**BWUAHAAUAAAANGGGGGG**');
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const lockedmove = source.getVolatile('lockedmove');
|
||||
if (lockedmove) {
|
||||
// Outrage counter is reset
|
||||
if (source.volatiles['lockedmove'].duration === 2) {
|
||||
delete source.volatiles['lockedmove'];
|
||||
}
|
||||
}
|
||||
if (this.checkMoveMakesContact(move, source, target)) {
|
||||
this.boost({ atk: -1 }, source, target, this.dex.getActiveMove("King's Shield"));
|
||||
}
|
||||
return this.NOT_FAIL;
|
||||
},
|
||||
},
|
||||
},
|
||||
maxguard: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
inherit: true,
|
||||
onTryHit(target, source, move) {
|
||||
const bypassesMaxGuard = [
|
||||
'acupressure', 'afteryou', 'allyswitch', 'aromatherapy', 'aromaticmist', 'coaching', 'confide', 'copycat', 'curse', 'decorate', 'doomdesire', 'feint', 'futuresight', 'gmaxoneblow', 'gmaxrapidflow', 'healbell', 'holdhands', 'howl', 'junglehealing', 'lifedew', 'meanlook', 'perishsong', 'playnice', 'powertrick', 'roar', 'roleplay', 'tearfullook',
|
||||
];
|
||||
if (bypassesMaxGuard.includes(move.id)) return;
|
||||
if (move.smartTarget) {
|
||||
move.smartTarget = false;
|
||||
} else {
|
||||
if (!this.randomChance(2, 10)) {
|
||||
this.add('-activate', target, 'move: Protect');
|
||||
if (move.basePower >= 100) {
|
||||
this.add('message', '**BWUAHAAUAAAANGGGGGG**');
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const lockedmove = source.getVolatile('lockedmove');
|
||||
if (lockedmove) {
|
||||
// Outrage counter is reset
|
||||
if (source.volatiles['lockedmove'].duration === 2) {
|
||||
delete source.volatiles['lockedmove'];
|
||||
}
|
||||
}
|
||||
return this.NOT_FAIL;
|
||||
},
|
||||
},
|
||||
},
|
||||
meteorbeam: {
|
||||
inherit: true,
|
||||
onTryMove(attacker, defender, move) {
|
||||
if (attacker.removeVolatile(move.id)) {
|
||||
return;
|
||||
}
|
||||
this.add('-prepare', attacker, move.name);
|
||||
this.boost({ spa: 1 }, attacker, attacker, move);
|
||||
if (['sandstorm'].includes(attacker.effectiveWeather())) {
|
||||
this.attrLastMove('[still]');
|
||||
this.addMove('-anim', attacker, move.name, defender);
|
||||
return;
|
||||
}
|
||||
if (!this.runEvent('ChargeMove', attacker, defender, move)) {
|
||||
return;
|
||||
}
|
||||
attacker.addVolatile('twoturnmove', defender);
|
||||
return null;
|
||||
},
|
||||
},
|
||||
obstruct: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
inherit: true,
|
||||
onTryHit(target, source, move) {
|
||||
if (this.checkMoveBypassesProtect(move, source, target, false)) return;
|
||||
if (move.smartTarget) {
|
||||
move.smartTarget = false;
|
||||
} else {
|
||||
if (!this.randomChance(2, 10)) {
|
||||
this.add('-activate', target, 'move: Protect');
|
||||
if (move.basePower >= 100) {
|
||||
this.add('message', '**BWUAHAAUAAAANGGGGGG**');
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const lockedmove = source.getVolatile('lockedmove');
|
||||
if (lockedmove) {
|
||||
// Outrage counter is reset
|
||||
if (source.volatiles['lockedmove'].duration === 2) {
|
||||
delete source.volatiles['lockedmove'];
|
||||
}
|
||||
}
|
||||
if (this.checkMoveMakesContact(move, source, target)) {
|
||||
this.boost({ def: -2 }, source, target, this.dex.getActiveMove("Obstruct"));
|
||||
}
|
||||
return this.NOT_FAIL;
|
||||
},
|
||||
},
|
||||
},
|
||||
protect: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
inherit: true,
|
||||
onTryHit(target, source, move) {
|
||||
if (this.checkMoveBypassesProtect(move, source, target)) return;
|
||||
if (move.smartTarget) {
|
||||
move.smartTarget = false;
|
||||
} else {
|
||||
if (!this.randomChance(2, 10)) {
|
||||
this.add('-activate', target, 'move: Protect');
|
||||
if (move.basePower >= 100) {
|
||||
this.add('message', '**BWUAHAAUAAAANGGGGGG**');
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const lockedmove = source.getVolatile('lockedmove');
|
||||
if (lockedmove) {
|
||||
// Outrage counter is reset
|
||||
if (source.volatiles['lockedmove'].duration === 2) {
|
||||
delete source.volatiles['lockedmove'];
|
||||
}
|
||||
}
|
||||
return this.NOT_FAIL;
|
||||
},
|
||||
},
|
||||
},
|
||||
silktrap: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
inherit: true,
|
||||
onTryHit(target, source, move) {
|
||||
if (this.checkMoveBypassesProtect(move, source, target, false)) return;
|
||||
if (move.smartTarget) {
|
||||
move.smartTarget = false;
|
||||
} else {
|
||||
if (!this.randomChance(2, 10)) {
|
||||
this.add('-activate', target, 'move: Protect');
|
||||
if (move.basePower >= 100) {
|
||||
this.add('message', '**BWUAHAAUAAAANGGGGGG**');
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const lockedmove = source.getVolatile('lockedmove');
|
||||
if (lockedmove) {
|
||||
// Outrage counter is reset
|
||||
if (source.volatiles['lockedmove'].duration === 2) {
|
||||
delete source.volatiles['lockedmove'];
|
||||
}
|
||||
}
|
||||
if (this.checkMoveMakesContact(move, source, target)) {
|
||||
this.boost({ spe: -1 }, source, target, this.dex.getActiveMove("Silk Trap"));
|
||||
}
|
||||
return this.NOT_FAIL;
|
||||
},
|
||||
},
|
||||
},
|
||||
spikyshield: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
inherit: true,
|
||||
onTryHit(target, source, move) {
|
||||
if (this.checkMoveBypassesProtect(move, source, target)) return;
|
||||
if (move.smartTarget) {
|
||||
move.smartTarget = false;
|
||||
} else {
|
||||
if (!this.randomChance(2, 10)) {
|
||||
this.add('-activate', target, 'move: Protect');
|
||||
if (move.basePower >= 100) {
|
||||
this.add('message', '**BWUAHAAUAAAANGGGGGG**');
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const lockedmove = source.getVolatile('lockedmove');
|
||||
if (lockedmove) {
|
||||
// Outrage counter is reset
|
||||
if (source.volatiles['lockedmove'].duration === 2) {
|
||||
delete source.volatiles['lockedmove'];
|
||||
}
|
||||
}
|
||||
if (this.checkMoveMakesContact(move, source, target)) {
|
||||
this.damage(source.baseMaxhp / 8, source, target);
|
||||
}
|
||||
return this.NOT_FAIL;
|
||||
},
|
||||
},
|
||||
},
|
||||
stealthrock: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
onSideStart(side) {
|
||||
this.add('-sidestart', side, 'Stealth Rock');
|
||||
this.effectState.layers = 1;
|
||||
},
|
||||
onSideRestart(side) {
|
||||
if (this.effectState.layers >= 5) return false;
|
||||
this.add('-sidestart', side, 'Stealth Rock');
|
||||
this.effectState.layers++;
|
||||
},
|
||||
onSwitchIn(pokemon) {
|
||||
if (pokemon.hasItem(['heavydutyboots', 'hoots'])) return;
|
||||
const typeMod = this.clampIntRange(pokemon.runEffectiveness(this.dex.getActiveMove('stealthrock')), -6, 6);
|
||||
const damageAmounts = [0, 1, 2, 3, 4, 5]; // 2 ** typeMod / 8
|
||||
this.damage((damageAmounts[this.effectState.layers] / 5) * pokemon.maxhp * ((2 ** typeMod) / 8));
|
||||
},
|
||||
},
|
||||
},
|
||||
gmaxsteelsurge: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
onSideStart(side) {
|
||||
this.add('-sidestart', side, 'G-Max Steelsurge');
|
||||
this.effectState.layers = 1;
|
||||
},
|
||||
onSideRestart(side) {
|
||||
if (this.effectState.layers >= 5) return false;
|
||||
this.add('-sidestart', side, 'G-Max Steelsurge');
|
||||
this.effectState.layers++;
|
||||
},
|
||||
onSwitchIn(pokemon) {
|
||||
if (pokemon.hasItem(['heavydutyboots', 'hoots'])) return;
|
||||
const steelHazard = this.dex.getActiveMove('Stealth Rock');
|
||||
steelHazard.type = 'Steel';
|
||||
const typeMod = this.clampIntRange(pokemon.runEffectiveness(steelHazard), -6, 6);
|
||||
const damageAmounts = [0, 1, 2, 3, 4, 5]; // 2 ** typeMod / 8
|
||||
this.damage((damageAmounts[this.effectState.layers] / 5) * pokemon.maxhp * ((2 ** typeMod) / 8));
|
||||
},
|
||||
},
|
||||
},
|
||||
spikes: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
inherit: true,
|
||||
onSwitchIn(pokemon) {
|
||||
if (!pokemon.isGrounded() || pokemon.hasItem(['heavydutyboots', 'hoots'])) return;
|
||||
const damageAmounts = [0, 3, 4, 6]; // 1/8, 1/6, 1/4
|
||||
this.damage(damageAmounts[this.effectState.layers] * pokemon.maxhp / 24);
|
||||
},
|
||||
},
|
||||
},
|
||||
stickyweb: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
inherit: true,
|
||||
onSwitchIn(pokemon) {
|
||||
if (!pokemon.isGrounded() || pokemon.hasItem(['heavydutyboots', 'hoots'])) return;
|
||||
this.add('-activate', pokemon, 'move: Sticky Web');
|
||||
this.boost({ spe: -1 }, pokemon, pokemon.side.foe.active[0], this.dex.getActiveMove('stickyweb'));
|
||||
},
|
||||
},
|
||||
},
|
||||
toxicspikes: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
inherit: true,
|
||||
onSwitchIn(pokemon) {
|
||||
if (!pokemon.isGrounded()) return;
|
||||
if (pokemon.hasType('Poison')) {
|
||||
this.add('-sideend', pokemon.side, 'move: Toxic Spikes', `[of] ${pokemon}`);
|
||||
pokemon.side.removeSideCondition('toxicspikes');
|
||||
} else if (pokemon.hasType('Steel') || pokemon.hasItem(['heavydutyboots', 'hoots'])) {
|
||||
// do nothing
|
||||
} else if (this.effectState.layers >= 2) {
|
||||
pokemon.trySetStatus('tox', pokemon.side.foe.active[0]);
|
||||
} else {
|
||||
pokemon.trySetStatus('psn', pokemon.side.foe.active[0]);
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
suckerpunch: {
|
||||
inherit: true,
|
||||
onTry() { },
|
||||
onModifyPriority(priority, source, target, move) {
|
||||
if (!target) return priority - 1;
|
||||
const action = this.queue.willMove(target);
|
||||
const aMove = action?.choice === 'move' ? action.move : null;
|
||||
if (!aMove || (aMove.category === 'Status' && aMove.id !== 'mefirst') || target.volatiles['mustrecharge']) {
|
||||
return priority - 1;
|
||||
}
|
||||
return priority;
|
||||
},
|
||||
},
|
||||
thousandarrows: {
|
||||
inherit: true,
|
||||
basePower: 120,
|
||||
},
|
||||
healpulse: {
|
||||
inherit: true,
|
||||
onHit(target, source) {
|
||||
let success = false;
|
||||
if (source.hasAbility('supermegalauncher')) {
|
||||
success = !!this.heal(this.modify(target.baseMaxhp, 2));
|
||||
} else if (source.hasAbility('megalauncher')) {
|
||||
success = !!this.heal(this.modify(target.baseMaxhp, 0.75));
|
||||
} else {
|
||||
success = !!this.heal(Math.ceil(target.baseMaxhp * 0.5));
|
||||
}
|
||||
if (success && !target.isAlly(source)) {
|
||||
target.staleness = 'external';
|
||||
}
|
||||
if (!success) {
|
||||
this.add('-fail', target, 'heal');
|
||||
return this.NOT_FAIL;
|
||||
}
|
||||
return success;
|
||||
},
|
||||
},
|
||||
headsmash: {
|
||||
inherit: true,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1, heal: 1 },
|
||||
secondary: {
|
||||
chance: 100,
|
||||
onHit(target, source, move) {
|
||||
if (!this.heal(this.modify(target.baseMaxhp, 0.25))) {
|
||||
return this.NOT_FAIL;
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
knockoff: {
|
||||
inherit: true,
|
||||
accuracy: 90,
|
||||
},
|
||||
shitpulse: {
|
||||
num: -400,
|
||||
gen: 9,
|
||||
accuracy: 100,
|
||||
basePower: 75,
|
||||
category: "Special",
|
||||
name: "Shit Pulse",
|
||||
pp: 15,
|
||||
priority: 0,
|
||||
flags: { protect: 1, mirror: 1, distance: 1, metronome: 1, pulse: 1 },
|
||||
secondary: {
|
||||
chance: 30,
|
||||
boosts: {
|
||||
accuracy: -2,
|
||||
},
|
||||
},
|
||||
target: "any",
|
||||
type: "Poison",
|
||||
shortDesc: "30% chance to lower foe's accuracy by 2.",
|
||||
},
|
||||
solarflare: {
|
||||
num: -4324534,
|
||||
gen: 9,
|
||||
accuracy: 100,
|
||||
basePower: 75,
|
||||
category: "Special",
|
||||
name: "Solar Flare",
|
||||
pp: 15,
|
||||
priority: 0,
|
||||
flags: { protect: 1, mirror: 1, metronome: 1 },
|
||||
secondary: {
|
||||
chance: 50,
|
||||
onHit(target, source, move) {
|
||||
if (!['sunnyday', 'desolateland'].includes(target.effectiveWeather())) return;
|
||||
target.trySetStatus('brn', source, move);
|
||||
},
|
||||
},
|
||||
target: "normal",
|
||||
type: "Fire",
|
||||
shortDesc: "Sun active: 50% chance to burn.",
|
||||
},
|
||||
onslaught: {
|
||||
num: -3023,
|
||||
gen: 9,
|
||||
accuracy: 100,
|
||||
basePower: 100,
|
||||
category: "Physical",
|
||||
name: "Onslaught",
|
||||
pp: 5,
|
||||
priority: 0,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 },
|
||||
self: {
|
||||
boosts: {
|
||||
atk: -1,
|
||||
def: -1,
|
||||
},
|
||||
},
|
||||
target: "normal",
|
||||
type: "Dark",
|
||||
},
|
||||
scald: {
|
||||
inherit: true,
|
||||
onEffectiveness(typeMod, target, type) {
|
||||
if (type === 'Steel') return 1;
|
||||
},
|
||||
secondary: undefined,
|
||||
secondaries: [{
|
||||
chance: 30,
|
||||
status: 'brn',
|
||||
}, {
|
||||
chance: 100,
|
||||
onHit(target, source, move) {
|
||||
if (target.hasType(['Normal', 'Fairy'])) {
|
||||
target.trySetStatus('brn', source, move);
|
||||
}
|
||||
},
|
||||
}],
|
||||
},
|
||||
explosion: {
|
||||
inherit: true,
|
||||
onAfterMove(pokemon, target, move) {
|
||||
if (target && target.hp <= 0) {
|
||||
delete move.selfdestruct;
|
||||
return;
|
||||
}
|
||||
},
|
||||
},
|
||||
selfdestruct: {
|
||||
inherit: true,
|
||||
onAfterMove(pokemon, target, move) {
|
||||
if (target && target.hp <= 0) {
|
||||
delete move.selfdestruct;
|
||||
return;
|
||||
}
|
||||
},
|
||||
},
|
||||
mistyexplosion: {
|
||||
inherit: true,
|
||||
onAfterMove(pokemon, target, move) {
|
||||
if (target && target.hp <= 0) {
|
||||
delete move.selfdestruct;
|
||||
return;
|
||||
}
|
||||
},
|
||||
},
|
||||
moonblast: {
|
||||
inherit: true,
|
||||
basePower: 90,
|
||||
accuracy: 90,
|
||||
secondary: {
|
||||
chance: 10,
|
||||
boosts: {
|
||||
atk: -1,
|
||||
},
|
||||
},
|
||||
category: "Physical",
|
||||
},
|
||||
noretreat: {
|
||||
name: "No Retreat",
|
||||
// @ts-expect-error
|
||||
exists: false,
|
||||
},
|
||||
blastiodon: {
|
||||
num: -306345534534523,
|
||||
gen: 9,
|
||||
accuracy: 100,
|
||||
basePower: 0,
|
||||
basePowerCallback(pokemon, target) {
|
||||
const targetDef = target.getStat('def', false, true);
|
||||
const pokemonDef = pokemon.getStat('def', false, true);
|
||||
let bp;
|
||||
if (pokemonDef >= targetDef * 5) {
|
||||
bp = 150;
|
||||
} else if (pokemonDef >= targetDef * 4) {
|
||||
bp = 125;
|
||||
} else if (pokemonDef >= targetDef * 3) {
|
||||
bp = 100;
|
||||
} else if (pokemonDef >= targetDef * 2) {
|
||||
bp = 75;
|
||||
} else {
|
||||
bp = 50;
|
||||
}
|
||||
this.debug(`BP: ${bp}`);
|
||||
return bp;
|
||||
},
|
||||
category: "Physical",
|
||||
name: "Blastiodon",
|
||||
pp: 15,
|
||||
priority: 0,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 },
|
||||
overrideOffensiveStat: 'def',
|
||||
secondary: {
|
||||
chance: 50,
|
||||
boosts: {
|
||||
def: -1,
|
||||
},
|
||||
},
|
||||
target: "normal",
|
||||
type: "Rock",
|
||||
shortDesc: "Higher user Def than target Def = higher BP.",
|
||||
},
|
||||
focusblast: {
|
||||
inherit: true,
|
||||
accuracy: 100,
|
||||
recoil: [1, 4],
|
||||
category: "Physical",
|
||||
},
|
||||
darkvoid: {
|
||||
inherit: true,
|
||||
onModifyMove(move, pokemon, target) {
|
||||
if (pokemon.species.baseSpecies === 'Calyrex') {
|
||||
move.accuracy = 80;
|
||||
}
|
||||
},
|
||||
onTry(source, target, move) {
|
||||
if (source.species.baseSpecies === 'Darkrai' || source.species.baseSpecies === 'Calyrex' || move.hasBounced) {
|
||||
return;
|
||||
}
|
||||
this.add('-fail', source, 'move: Dark Void');
|
||||
this.hint("Only a Pokemon whose form is Darkrai can use this move.");
|
||||
return null;
|
||||
},
|
||||
},
|
||||
rapidspin: {
|
||||
inherit: true,
|
||||
type: "Dark",
|
||||
},
|
||||
};
|
||||
329
data/mods/afd/pokedex.ts
Normal file
329
data/mods/afd/pokedex.ts
Normal file
|
|
@ -0,0 +1,329 @@
|
|||
export const Pokedex: import('../../../sim/dex-species').ModdedSpeciesDataTable = {
|
||||
seaking: {
|
||||
inherit: true,
|
||||
baseStats: { hp: 80, atk: 92, def: 65, spa: 65, spd: 80, spe: 98 },
|
||||
},
|
||||
clefablemega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Regenerator" },
|
||||
},
|
||||
victreebelmega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Regenerator" },
|
||||
},
|
||||
starmiemega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Huge Power" },
|
||||
},
|
||||
skarmorymega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Huge Power" },
|
||||
},
|
||||
scolipedemega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Huge Power" },
|
||||
},
|
||||
scraftymega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Huge Power" },
|
||||
},
|
||||
emboarmega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Regenerator" },
|
||||
},
|
||||
eelektrossmega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Regenerator" },
|
||||
},
|
||||
chesnaughtmega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Regenerator" },
|
||||
},
|
||||
delphoxmega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Regenerator" },
|
||||
},
|
||||
greninjamega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Regenerator" },
|
||||
},
|
||||
pyroarmega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Regenerator" },
|
||||
},
|
||||
barbaraclemega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Huge Power" },
|
||||
},
|
||||
hawluchamega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Huge Power" },
|
||||
},
|
||||
raichumegax: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Huge Power" },
|
||||
},
|
||||
chimechomega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Regenerator" },
|
||||
},
|
||||
baxcaliburmega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Huge Power" },
|
||||
},
|
||||
zeraoramega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Huge Power" },
|
||||
},
|
||||
absolmegaz: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Huge Power" },
|
||||
},
|
||||
staraptormega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Huge Power" },
|
||||
},
|
||||
golisopodmega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Huge Power" },
|
||||
},
|
||||
meowsticfmega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Regenerator" },
|
||||
},
|
||||
crabominablemega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Huge Power" },
|
||||
},
|
||||
golurkmega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Huge Power" },
|
||||
},
|
||||
garchompmegaz: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Huge Power" },
|
||||
},
|
||||
lucariomegaz: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Regenerator" },
|
||||
},
|
||||
raichumegay: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Regenerator" },
|
||||
},
|
||||
falinksmega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "No Retreat" },
|
||||
},
|
||||
drampamega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Regenerator" },
|
||||
},
|
||||
zygardemega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Regenerator" },
|
||||
},
|
||||
dragalgemega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Regenerator" },
|
||||
},
|
||||
darkraimega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Regenerator" },
|
||||
},
|
||||
heatranmega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Regenerator" },
|
||||
},
|
||||
floettemega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Regenerator" },
|
||||
},
|
||||
chandeluremega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Shadow Tag" },
|
||||
},
|
||||
lickitung: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Own Tempo", 1: "Oblivious", H: "Chaos Saliva" },
|
||||
},
|
||||
mewtwo: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Pressure", 1: "Neuroforce", H: "Unnerve" },
|
||||
},
|
||||
scovillainmega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Contrary" },
|
||||
},
|
||||
mew: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Synchronize", 1: "Neuroforce" },
|
||||
},
|
||||
smeargle: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Own Tempo", 1: "Prankster", H: "Moody" },
|
||||
},
|
||||
swampert: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Torrent", 1: "Sap Sipper", H: "Damp" },
|
||||
},
|
||||
bibarel: {
|
||||
inherit: true,
|
||||
baseStats: { hp: 159, atk: 85, def: 60, spa: 55, spd: 60, spe: 151 },
|
||||
},
|
||||
skuntank: {
|
||||
inherit: true,
|
||||
baseStats: { hp: 103, atk: 93, def: 67, spa: 106, spd: 61, spe: 84 },
|
||||
abilities: { 0: "Stench", 1: "Aftermath", H: "Mega Launcher" },
|
||||
},
|
||||
rampardos: {
|
||||
inherit: true,
|
||||
baseStats: { hp: 97, atk: 225, def: 30, spa: 65, spd: 30, spe: 58 },
|
||||
abilities: { 0: "Rocky Payload", H: "Sheer Force" },
|
||||
},
|
||||
gallademega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Sharpness" },
|
||||
},
|
||||
garchompmega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Sand Rush" },
|
||||
},
|
||||
dusknoir: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Damp" },
|
||||
},
|
||||
lickilicky: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Own Tempo", 1: "Oblivious", H: "Chaos Saliva" },
|
||||
},
|
||||
regigigas: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Slow Start", H: "Fast Start" },
|
||||
},
|
||||
serperior: {
|
||||
inherit: true,
|
||||
types: ['Grass', 'Dragon'],
|
||||
baseStats: { hp: 75, atk: 75, def: 95, spa: 105, spd: 95, spe: 113 },
|
||||
},
|
||||
simisage: {
|
||||
inherit: true,
|
||||
baseStats: { hp: 120, atk: 120, def: 120, spa: 120, spd: 120, spe: 120 },
|
||||
},
|
||||
excadrillmega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "It's Excadrillin' Time!" },
|
||||
},
|
||||
chandelure: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Flash Fire", 1: "Flame Body", H: "Shadow Tag" },
|
||||
},
|
||||
delphox: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Blaze", H: "Discourage" },
|
||||
},
|
||||
clawitzer: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Super Mega Launcher" },
|
||||
},
|
||||
malamar: {
|
||||
inherit: true,
|
||||
baseStats: { hp: 101, atk: 112, def: 88, spa: 68, spd: 75, spe: 73 },
|
||||
},
|
||||
malamarmega: {
|
||||
inherit: true,
|
||||
baseStats: { hp: 101, atk: 122, def: 88, spa: 98, spd: 120, spe: 88 },
|
||||
abilities: { 0: "Contrary" },
|
||||
},
|
||||
incineroar: {
|
||||
inherit: true,
|
||||
types: ['Fire', 'Fighting'],
|
||||
},
|
||||
incineroar2: {
|
||||
num: 2000,
|
||||
name: "Incineroar 2",
|
||||
types: ["Ghost", "Steel"],
|
||||
genderRatio: { M: 0.875, F: 0.125 },
|
||||
baseStats: { hp: 95, atk: 115, def: 90, spa: 80, spd: 90, spe: 60 },
|
||||
abilities: { 0: "Intimidate 2" },
|
||||
heightm: 1.8,
|
||||
weightkg: 83,
|
||||
color: "Red",
|
||||
eggGroups: ["Field"],
|
||||
},
|
||||
celesteela: {
|
||||
inherit: true,
|
||||
baseStats: { hp: 5, atk: 5, def: 5, spa: 5, spd: 5, spe: 5 },
|
||||
},
|
||||
hatterene: {
|
||||
inherit: true,
|
||||
types: ['Psychic', 'Dark'],
|
||||
},
|
||||
glimmora: {
|
||||
inherit: true,
|
||||
baseStats: { hp: 106, atk: 150, def: 70, spa: 194, spd: 120, spe: 140 },
|
||||
},
|
||||
glimmoramega: {
|
||||
inherit: true,
|
||||
baseStats: { hp: 106, atk: 185, def: 85, spa: 214, spd: 145, spe: 155 },
|
||||
abilities: { 0: "Regenerator" },
|
||||
},
|
||||
tatsugiri: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Commander", 1: "Parental Bond", H: "Storm Drain" },
|
||||
},
|
||||
tatsugiridroopy: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Commander", 1: "Parental Bond", H: "Storm Drain" },
|
||||
},
|
||||
tatsugiristretchy: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Commander", 1: "Parental Bond", H: "Storm Drain" },
|
||||
},
|
||||
tatsugiricurlymega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Parental Bond" },
|
||||
},
|
||||
tatsugiridroopymega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Parental Bond" },
|
||||
},
|
||||
tatsugiristretchymega: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Parental Bond" },
|
||||
},
|
||||
calyrex: {
|
||||
num: 898,
|
||||
name: "Calyrex",
|
||||
types: ["Psychic", "Grass"],
|
||||
gender: "N",
|
||||
baseStats: { hp: 100, atk: 80, def: 80, spa: 80, spd: 80, spe: 80 },
|
||||
abilities: { 0: "Unnerve" },
|
||||
heightm: 1.1,
|
||||
weightkg: 7.7,
|
||||
color: "Green",
|
||||
eggGroups: ["Undiscovered"],
|
||||
tags: ["Restricted Legendary"],
|
||||
otherFormes: ["Calyrex-Ice", "Calyrex-Shadow", "Calyrex-Monarch"],
|
||||
formeOrder: ["Calyrex", "Calyrex-Ice", "Calyrex-Shadow", "Calyrex-Monarch"],
|
||||
},
|
||||
calyrexmonarch: {
|
||||
num: 898,
|
||||
name: "Calyrex-Monarch",
|
||||
baseSpecies: "Calyrex",
|
||||
forme: "Monarch",
|
||||
types: ["Psychic", "Grass"],
|
||||
gender: "N",
|
||||
baseStats: { hp: 200, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 },
|
||||
abilities: { 0: "As One (Calyrex)" },
|
||||
heightm: 2.2,
|
||||
weightkg: 15.4,
|
||||
color: "Green",
|
||||
eggGroups: ["Undiscovered"],
|
||||
changesFrom: "Calyrex",
|
||||
},
|
||||
spidops: {
|
||||
inherit: true,
|
||||
baseStats: { hp: 100, atk: 100, def: 100, spa: 100, spd: 100, spe: 0 },
|
||||
},
|
||||
};
|
||||
788
data/mods/afd/random-teams.ts
Normal file
788
data/mods/afd/random-teams.ts
Normal file
|
|
@ -0,0 +1,788 @@
|
|||
import { Utils } from '../../../lib';
|
||||
import RandomTeams from '../../random-battles/gen9/teams';
|
||||
import { toID } from '../../../sim/dex';
|
||||
|
||||
export interface TeamData {
|
||||
typeCount: { [k: string]: number };
|
||||
typeComboCount: { [k: string]: number };
|
||||
baseFormes: { [k: string]: number };
|
||||
megaCount?: number;
|
||||
zCount?: number;
|
||||
wantsTeraCount?: number;
|
||||
has: { [k: string]: number };
|
||||
forceResult: boolean;
|
||||
weaknesses: { [k: string]: number };
|
||||
resistances: { [k: string]: number };
|
||||
weather?: string;
|
||||
eeveeLimCount?: number;
|
||||
gigantamax?: boolean;
|
||||
}
|
||||
export interface BattleFactorySpecies {
|
||||
sets: BattleFactorySet[];
|
||||
weight: number;
|
||||
}
|
||||
interface BattleFactorySet {
|
||||
species: string;
|
||||
weight: number;
|
||||
item: string[];
|
||||
ability: string[];
|
||||
nature: string[];
|
||||
moves: string[][];
|
||||
teraType: string[];
|
||||
gender?: string;
|
||||
wantsTera?: boolean;
|
||||
evs?: Partial<StatsTable>;
|
||||
ivs?: Partial<StatsTable>;
|
||||
shiny?: boolean;
|
||||
level?: number;
|
||||
}
|
||||
export class MoveCounter extends Utils.Multiset<string> {
|
||||
damagingMoves: Set<Move>;
|
||||
basePowerMoves: Set<Move>;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.damagingMoves = new Set();
|
||||
this.basePowerMoves = new Set();
|
||||
}
|
||||
}
|
||||
// Moves that switch the user out
|
||||
const PIVOT_MOVES = [
|
||||
'chillyreception', 'flipturn', 'partingshot', 'shedtail', 'teleport', 'uturn', 'voltswitch',
|
||||
];
|
||||
|
||||
/** Pokemon who should never be in the lead slot */
|
||||
const NO_LEAD_POKEMON = [
|
||||
'Zacian', 'Zamazenta',
|
||||
];
|
||||
|
||||
const DEFENSIVE_TERA_BLAST_USERS = [
|
||||
'alcremie', 'bellossom', 'comfey', 'fezandipiti', 'florges',
|
||||
];
|
||||
|
||||
export class RandomAFDTeams extends RandomTeams {
|
||||
override shouldCullAbility(
|
||||
ability: string,
|
||||
types: string[],
|
||||
moves: Set<string>,
|
||||
abilities: string[],
|
||||
counter: MoveCounter,
|
||||
teamDetails: RandomTeamsTypes.TeamDetails,
|
||||
species: Species,
|
||||
isLead: boolean,
|
||||
isDoubles: boolean,
|
||||
teraType: string,
|
||||
role: RandomTeamsTypes.Role,
|
||||
): boolean {
|
||||
switch (ability) {
|
||||
// Abilities which are primarily useful for certain moves or with team support
|
||||
case 'Chlorophyll': case 'Solar Power':
|
||||
return !teamDetails.sun;
|
||||
case 'Defiant':
|
||||
return (species.id === 'thundurus' && !!counter.get('Status'));
|
||||
case 'Hydration': case 'Swift Swim':
|
||||
return !teamDetails.rain;
|
||||
case 'Iron Fist': case 'Skill Link':
|
||||
return !counter.get(toID(ability));
|
||||
case 'Overgrow':
|
||||
return !counter.get('Grass');
|
||||
case 'Prankster':
|
||||
return !counter.get('Status');
|
||||
case 'Sand Force': case 'Sand Rush': case 'It\'s Excadrillin\' Time!':
|
||||
return !teamDetails.sand;
|
||||
case 'Slush Rush':
|
||||
return !teamDetails.snow;
|
||||
case 'Swarm':
|
||||
return !counter.get('Bug');
|
||||
case 'Torrent':
|
||||
return (!counter.get('Water') && !moves.has('flipturn'));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
override getAbility(
|
||||
types: string[],
|
||||
moves: Set<string>,
|
||||
abilities: string[],
|
||||
counter: MoveCounter,
|
||||
teamDetails: RandomTeamsTypes.TeamDetails,
|
||||
species: Species,
|
||||
isLead: boolean,
|
||||
isDoubles: boolean,
|
||||
teraType: string,
|
||||
role: RandomTeamsTypes.Role,
|
||||
): string {
|
||||
if (abilities.length <= 1) return abilities[0];
|
||||
|
||||
// Hard-code abilities here
|
||||
if (species.id === 'drifblim') return moves.has('defog') ? 'Aftermath' : 'Unburden';
|
||||
if (abilities.includes('Flash Fire') && this.dex.getEffectiveness('Fire', teraType) >= 1) return 'Flash Fire';
|
||||
if ((species.id === 'thundurus' || species.id === 'tornadus') && !counter.get('Physical')) return 'Prankster';
|
||||
if (species.id === 'toucannon' && counter.get('skilllink')) return 'Skill Link';
|
||||
if (abilities.includes('Slush Rush') && moves.has('snowscape')) return 'Slush Rush';
|
||||
if (species.id === 'golduck' && teamDetails.rain) return 'Swift Swim';
|
||||
|
||||
const abilityAllowed: string[] = [];
|
||||
// Obtain a list of abilities that are allowed (not culled)
|
||||
for (const ability of abilities) {
|
||||
if (!this.shouldCullAbility(
|
||||
ability, types, moves, abilities, counter, teamDetails, species, isLead, isDoubles, teraType, role
|
||||
)) {
|
||||
abilityAllowed.push(ability);
|
||||
}
|
||||
}
|
||||
|
||||
// Pick a random allowed ability
|
||||
if (abilityAllowed.length >= 1) return this.sample(abilityAllowed);
|
||||
|
||||
// If all abilities are rejected, prioritize weather abilities over non-weather abilities
|
||||
if (!abilityAllowed.length) {
|
||||
const weatherAbilities = abilities.filter(
|
||||
a => ['Chlorophyll', 'Hydration', 'Sand Force', 'Sand Rush', 'Slush Rush', 'Solar Power', 'Swift Swim'].includes(a)
|
||||
);
|
||||
if (weatherAbilities.length) return this.sample(weatherAbilities);
|
||||
}
|
||||
|
||||
// Pick a random ability
|
||||
return this.sample(abilities);
|
||||
}
|
||||
|
||||
override getPriorityItem(
|
||||
ability: string,
|
||||
types: string[],
|
||||
moves: Set<string>,
|
||||
counter: MoveCounter,
|
||||
teamDetails: RandomTeamsTypes.TeamDetails,
|
||||
species: Species,
|
||||
isLead: boolean,
|
||||
isDoubles: boolean,
|
||||
teraType: string,
|
||||
role: RandomTeamsTypes.Role,
|
||||
) {
|
||||
if (role === 'Fast Bulky Setup' && (ability === 'Quark Drive' || ability === 'Protosynthesis')) {
|
||||
return 'Booster Energy';
|
||||
}
|
||||
if (species.id === 'lokix') {
|
||||
return (role === 'Fast Attacker') ? 'Silver Powder' : 'Life Orb';
|
||||
}
|
||||
if (species.requiredItems && species.baseSpecies !== 'Magearna') {
|
||||
// Z-Crystals aren't available in Gen 9, so require Plates
|
||||
if (species.baseSpecies === 'Arceus') {
|
||||
return species.requiredItems[0];
|
||||
}
|
||||
return this.sample(species.requiredItems);
|
||||
}
|
||||
if (species.id === 'pikachu') return 'Light Ball';
|
||||
if (role === 'AV Pivot') return 'Assault Vest';
|
||||
if (species.id === 'regieleki') return 'Magnet';
|
||||
if (types.includes('Normal') && moves.has('doubleedge') && moves.has('fakeout')) return 'Silk Scarf';
|
||||
if (
|
||||
species.id === 'froslass' || moves.has('populationbomb') ||
|
||||
(ability === 'Hustle' && counter.get('setup') && !isDoubles && this.randomChance(1, 2))
|
||||
) return 'Wide Lens';
|
||||
if (species.id === 'smeargle') return 'Focus Sash';
|
||||
if (moves.has('clangoroussoul') || (species.id === 'toxtricity' && moves.has('shiftgear'))) return 'Throat Spray';
|
||||
if (
|
||||
(species.baseSpecies === 'Magearna' && role === 'Tera Blast user') ||
|
||||
((species.id === 'calyrexice' || species.id === 'necrozmaduskmane') && isDoubles)
|
||||
) return 'Weakness Policy';
|
||||
if (['dragonenergy', 'lastrespects', 'waterspout'].some(m => moves.has(m))) return 'Choice Scarf';
|
||||
if (
|
||||
!isDoubles && (ability === 'Imposter' || (species.id === 'magnezone' && role === 'Fast Attacker'))
|
||||
) return 'Choice Scarf';
|
||||
if (species.id === 'rampardos' && (role === 'Fast Attacker' || isDoubles)) return 'Choice Scarf';
|
||||
if (species.id === 'palkia' && counter.get('Status')) return 'Lustrous Orb';
|
||||
if (
|
||||
moves.has('courtchange') ||
|
||||
!isDoubles && (species.id === 'luvdisc' || (species.id === 'terapagos' && !moves.has('rest')))
|
||||
) return 'Hoots';
|
||||
if (['Cheek Pouch', 'Cud Chew', 'Harvest', 'Ripen'].some(m => ability === m)) {
|
||||
return 'Sitrus Berry';
|
||||
}
|
||||
if (moves.has('bellydrum') || moves.has('filletaway')) return 'Ward Tag';
|
||||
if (['healingwish', 'switcheroo', 'trick'].some(m => moves.has(m))) {
|
||||
if (
|
||||
species.baseStats.spe >= 60 && species.baseStats.spe <= 108 &&
|
||||
role !== 'Wallbreaker' && role !== 'Doubles Wallbreaker' && !counter.get('priority')
|
||||
) {
|
||||
return 'Choice Scarf';
|
||||
} else {
|
||||
return (counter.get('Physical') > counter.get('Special')) ? 'Choice Band' : 'Choice Specs';
|
||||
}
|
||||
}
|
||||
if (counter.get('Status') && (species.name === 'Latias' || species.name === 'Latios')) return 'Soul Dew';
|
||||
if (species.id === 'scyther' && !isDoubles) return (isLead && !moves.has('uturn')) ? 'Eviolite' : 'Hoots';
|
||||
if (ability === 'Poison Heal' || ability === 'Quick Feet') return 'Toxic Orb';
|
||||
if (species.nfe) return 'Eviolite';
|
||||
if ((ability === 'Guts' || moves.has('facade')) && !moves.has('sleeptalk')) {
|
||||
return (types.includes('Fire') || ability === 'Toxic Boost') ? 'Toxic Orb' : 'Flame Orb';
|
||||
}
|
||||
if (ability === 'Magic Guard' || (ability === 'Sheer Force' && counter.get('sheerforce'))) return 'Life Orb';
|
||||
if (ability === 'Anger Shell') return this.sample(['Expert Belt', 'Lum Berry', 'Scope Lens', 'Sitrus Berry']);
|
||||
if (moves.has('dragondance') && isDoubles) return 'Clear Amulet';
|
||||
if (counter.get('skilllink') && ability !== 'Skill Link' && species.id !== 'breloom') return 'Loaded Dice';
|
||||
if (ability === 'Unburden') {
|
||||
return (moves.has('closecombat') || moves.has('leafstorm')) ? 'White Herb' : 'Sitrus Berry';
|
||||
}
|
||||
if (moves.has('shellsmash') && ability !== 'Weak Armor') return 'White Herb';
|
||||
if (moves.has('meteorbeam') || (moves.has('electroshot') && !teamDetails.rain)) return 'Power Herb';
|
||||
if (moves.has('acrobatics') && ability !== 'Protosynthesis') return '';
|
||||
if (moves.has('auroraveil') || moves.has('lightscreen') && moves.has('reflect')) return 'Light Clay';
|
||||
if (ability === 'Gluttony') return `${this.sample(['Aguav', 'Figy', 'Iapapa', 'Mago', 'Wiki'])} Berry`;
|
||||
if (species.id === 'giratina' && !isDoubles && moves.has('rest') && !moves.has('sleeptalk')) return 'Leftovers';
|
||||
if (
|
||||
moves.has('rest') && !moves.has('sleeptalk') &&
|
||||
ability !== 'Natural Cure' && ability !== 'Shed Skin'
|
||||
) {
|
||||
return 'Chesto Berry';
|
||||
}
|
||||
if (
|
||||
species.id !== 'yanmega' &&
|
||||
this.dex.getEffectiveness('Rock', species) >= 2 && (!types.includes('Flying') || !isDoubles)
|
||||
) return 'Hoots';
|
||||
}
|
||||
|
||||
override getItem(
|
||||
ability: string,
|
||||
types: string[],
|
||||
moves: Set<string>,
|
||||
counter: MoveCounter,
|
||||
teamDetails: RandomTeamsTypes.TeamDetails,
|
||||
species: Species,
|
||||
isLead: boolean,
|
||||
teraType: string,
|
||||
role: RandomTeamsTypes.Role,
|
||||
): string {
|
||||
const lifeOrbReqs = ['flamecharge', 'nuzzle', 'rapidspin'].every(m => !moves.has(m));
|
||||
|
||||
if (
|
||||
species.id !== 'jirachi' && (counter.get('Physical') >= moves.size) &&
|
||||
['dragontail', 'fakeout', 'firstimpression', 'flamecharge', 'rapidspin', 'trailblaze'].every(m => !moves.has(m))
|
||||
) {
|
||||
const scarfReqs = (
|
||||
role !== 'Wallbreaker' &&
|
||||
(species.baseStats.atk >= 100 || ability === 'Huge Power' || ability === 'Pure Power') &&
|
||||
species.baseStats.spe >= 60 && species.baseStats.spe <= 108 &&
|
||||
ability !== 'Speed Boost' && !counter.get('priority')
|
||||
);
|
||||
return (scarfReqs && this.randomChance(1, 2)) ? 'Choice Scarf' : 'Choice Band';
|
||||
}
|
||||
if (
|
||||
(counter.get('Special') >= moves.size) ||
|
||||
(counter.get('Special') >= moves.size - 1 && ['flipturn', 'uturn'].some(m => moves.has(m)))
|
||||
) {
|
||||
const scarfReqs = (
|
||||
role !== 'Wallbreaker' &&
|
||||
species.baseStats.spa >= 100 &&
|
||||
species.baseStats.spe >= 60 && species.baseStats.spe <= 108 &&
|
||||
ability !== 'Speed Boost' && ability !== 'Tinted Lens' && !moves.has('uturn') && !counter.get('priority')
|
||||
);
|
||||
return (scarfReqs && this.randomChance(1, 2)) ? 'Choice Scarf' : 'Choice Specs';
|
||||
}
|
||||
if (counter.get('speedsetup') && !counter.get('physicalsetup') && role === 'Bulky Setup') return 'Weakness Policy';
|
||||
if (
|
||||
!counter.get('Status') &&
|
||||
!['Fast Attacker', 'Wallbreaker', 'Tera Blast user'].includes(role)
|
||||
) {
|
||||
return 'Assault Vest';
|
||||
}
|
||||
if (species.id === 'golem') return (counter.get('speedsetup')) ? 'Weakness Policy' : 'Custap Berry';
|
||||
if (moves.has('substitute')) return 'Leftovers';
|
||||
if (
|
||||
moves.has('stickyweb') && isLead &&
|
||||
(species.baseStats.hp + species.baseStats.def + species.baseStats.spd) <= 235
|
||||
) return 'Focus Sash';
|
||||
if (this.dex.getEffectiveness('Rock', species) >= 1) return 'Hoots';
|
||||
if (
|
||||
(moves.has('chillyreception') || (
|
||||
role === 'Fast Support' &&
|
||||
[...PIVOT_MOVES, 'defog', 'mortalspin', 'rapidspin'].some(m => moves.has(m)) &&
|
||||
!types.includes('Flying') && ability !== 'Levitate'
|
||||
))
|
||||
) return 'Hoots';
|
||||
|
||||
// Low Priority
|
||||
if (moves.has('dragondance') && role === 'Bulky Setup') return 'Weakness Policy';
|
||||
if (
|
||||
ability === 'Rough Skin' || (
|
||||
ability === 'Regenerator' && (role === 'Bulky Support' || role === 'Bulky Attacker') &&
|
||||
(species.baseStats.hp + species.baseStats.def) >= 180 && this.randomChance(1, 2)
|
||||
) || (
|
||||
ability !== 'Regenerator' && !counter.get('setup') && counter.get('recovery') &&
|
||||
this.dex.getEffectiveness('Fighting', species) < 1 &&
|
||||
(species.baseStats.hp + species.baseStats.def) > 200 && this.randomChance(1, 2)
|
||||
)
|
||||
) return 'Rocky Helmet';
|
||||
if (role === 'Bulky Support') return 'Onika Burger';
|
||||
if (moves.has('outrage') && counter.get('setup')) return 'Lum Berry';
|
||||
if (moves.has('protect') && ability !== 'Speed Boost') return 'Leftovers';
|
||||
if (
|
||||
role === 'Fast Support' && isLead && !counter.get('recovery') && !counter.get('recoil') &&
|
||||
(counter.get('hazards') || counter.get('setup')) &&
|
||||
(species.baseStats.hp + species.baseStats.def + species.baseStats.spd) < 258
|
||||
) return 'Focus Sash';
|
||||
if (
|
||||
!counter.get('setup') && ability !== 'Levitate' && this.dex.getEffectiveness('Ground', species) >= 2
|
||||
) return 'Air Balloon';
|
||||
if (['Bulky Attacker', 'Bulky Setup'].some(m => role === (m))) return 'Leftovers';
|
||||
if (species.id === 'pawmot' && moves.has('nuzzle')) return 'Leppa Berry';
|
||||
if (role === 'Fast Support' || role === 'Fast Bulky Setup') {
|
||||
return (
|
||||
counter.get('Physical') + counter.get('Special') > counter.get('Status') && lifeOrbReqs
|
||||
) ? 'Life Orb' : 'Leftovers';
|
||||
}
|
||||
if (role === 'Tera Blast user' && DEFENSIVE_TERA_BLAST_USERS.includes(species.id)) return 'Leftovers';
|
||||
if (
|
||||
lifeOrbReqs && ['Fast Attacker', 'Setup Sweeper', 'Tera Blast user', 'Wallbreaker'].some(m => role === (m))
|
||||
) return 'Life Orb';
|
||||
return 'Leftovers';
|
||||
}
|
||||
|
||||
override getLevel(species: Species): number {
|
||||
if (this.adjustLevel) return this.adjustLevel;
|
||||
const file = this.randomAFDSets[species.id] || this.randomSets[species.id];
|
||||
if (file["level"]) return file["level"];
|
||||
// Default to tier-based levelling
|
||||
const tier = species.tier;
|
||||
const tierScale: Partial<Record<Species['tier'], number>> = {
|
||||
Uber: 76,
|
||||
OU: 80,
|
||||
UUBL: 81,
|
||||
UU: 82,
|
||||
RUBL: 83,
|
||||
RU: 84,
|
||||
NUBL: 85,
|
||||
NU: 86,
|
||||
PUBL: 87,
|
||||
PU: 88, "(PU)": 88, NFE: 88,
|
||||
};
|
||||
return tierScale[tier] || 80;
|
||||
}
|
||||
|
||||
override getForme(species: Species): string {
|
||||
if (typeof species.battleOnly === 'string') {
|
||||
// Only change the forme. The species has custom moves, and may have different typing and requirements.
|
||||
return species.battleOnly;
|
||||
}
|
||||
if (species.cosmeticFormes) return this.sample([species.name].concat(species.cosmeticFormes));
|
||||
|
||||
// Consolidate mostly-cosmetic formes, at least for the purposes of Random Battles
|
||||
if (['Dudunsparce', 'Maushold', 'Polteageist', 'Sinistcha', 'Zarude'].includes(species.baseSpecies)) {
|
||||
return this.sample([species.name].concat(species.otherFormes!));
|
||||
}
|
||||
if (species.baseSpecies === 'Basculin') return 'Basculin' + this.sample(['', '-Blue-Striped']);
|
||||
if (species.baseSpecies === 'Magearna') return 'Magearna' + this.sample(['', '-Original']);
|
||||
if (species.baseSpecies === 'Pikachu') {
|
||||
return 'Pikachu' + this.sample(
|
||||
['', '-Original', '-Hoenn', '-Sinnoh', '-Unova', '-Kalos', '-Alola', '-Partner', '-World']
|
||||
);
|
||||
}
|
||||
return species.name;
|
||||
}
|
||||
|
||||
randomAFDSet(
|
||||
s: string | Species,
|
||||
teamDetails: RandomTeamsTypes.TeamDetails = {},
|
||||
isLead = false,
|
||||
isDoubles = false
|
||||
): RandomTeamsTypes.RandomSet {
|
||||
const species = this.dex.species.get(s);
|
||||
const forme = this.getForme(species);
|
||||
if (!this.randomAFDSets[species.id]) return this.randomSet(species, teamDetails, isLead, isDoubles);
|
||||
const sets = this.randomAFDSets[species.id]["sets"];
|
||||
const possibleSets: RandomTeamsTypes.RandomSetData[] = [];
|
||||
|
||||
const ruleTable = this.dex.formats.getRuleTable(this.format);
|
||||
|
||||
for (const set of sets) {
|
||||
// Prevent Fast Bulky Setup on lead Paradox Pokemon, since it generates Booster Energy.
|
||||
const abilities = set.abilities!;
|
||||
if (
|
||||
isLead && (abilities.includes('Protosynthesis') || abilities.includes('Quark Drive')) &&
|
||||
set.role === 'Fast Bulky Setup'
|
||||
) continue;
|
||||
// Prevent Tera Blast user if the team already has one, or if Terastallizion is prevented.
|
||||
if ((teamDetails.teraBlast || ruleTable.has('terastalclause')) && set.role === 'Tera Blast user') {
|
||||
continue;
|
||||
}
|
||||
possibleSets.push(set);
|
||||
}
|
||||
const set = this.sampleIfArray(possibleSets);
|
||||
const role = set.role;
|
||||
const movePool: string[] = [];
|
||||
for (const movename of set.movepool) {
|
||||
movePool.push(this.dex.moves.get(movename).id);
|
||||
}
|
||||
const teraTypes = set.teraTypes!;
|
||||
let teraType = this.sampleIfArray(teraTypes);
|
||||
|
||||
let ability = '';
|
||||
let item = undefined;
|
||||
|
||||
const evs = { hp: 85, atk: 85, def: 85, spa: 85, spd: 85, spe: 85 };
|
||||
const ivs = { hp: 31, atk: 31, def: 31, spa: 31, spd: 31, spe: 31 };
|
||||
|
||||
const types = species.types;
|
||||
const abilities = set.abilities!;
|
||||
|
||||
// Get moves
|
||||
const moves = this.randomMoveset(types, abilities, teamDetails, species, isLead, isDoubles, movePool, teraType, role);
|
||||
const counter = this.queryMoves(moves, species, teraType, abilities);
|
||||
|
||||
// Get ability
|
||||
ability = this.getAbility(types, moves, abilities, counter, teamDetails, species, isLead, isDoubles, teraType, role);
|
||||
|
||||
// Get items
|
||||
// First, the priority items
|
||||
item = this.getPriorityItem(ability, types, moves, counter, teamDetails, species, isLead, isDoubles, teraType, role);
|
||||
if (item === undefined) {
|
||||
item = this.getItem(ability, types, moves, counter, teamDetails, species, isLead, teraType, role);
|
||||
}
|
||||
|
||||
// Get level
|
||||
const level = this.getLevel(species);
|
||||
|
||||
// Prepare optimal HP
|
||||
const srImmunity = ability === 'Magic Guard' || item === 'Heavy-Duty Boots' || item === 'Hoots';
|
||||
let srWeakness = srImmunity ? 0 : this.dex.getEffectiveness('Rock', species);
|
||||
// Crash damage move users want an odd HP to survive two misses
|
||||
if (['axekick', 'highjumpkick', 'jumpkick', 'supercellslam'].some(m => moves.has(m))) srWeakness = 2;
|
||||
while (evs.hp > 1) {
|
||||
const hp = Math.floor(Math.floor(2 * species.baseStats.hp + ivs.hp + Math.floor(evs.hp / 4) + 100) * level / 100 + 10);
|
||||
if ((moves.has('substitute') && ['Sitrus Berry'].includes(item)) || species.id === 'minior') {
|
||||
// Two Substitutes should activate Sitrus Berry. Two switch-ins to Stealth Rock should activate Shields Down on Minior.
|
||||
if (hp % 4 === 0) break;
|
||||
} else if (
|
||||
(moves.has('bellydrum') || moves.has('filletaway') || moves.has('shedtail')) &&
|
||||
(item === 'Sitrus Berry' || ability === 'Gluttony')
|
||||
) {
|
||||
// Belly Drum should activate Sitrus Berry
|
||||
if (hp % 2 === 0) break;
|
||||
} else if (moves.has('substitute') && moves.has('endeavor')) {
|
||||
// Luvdisc should be able to Substitute down to very low HP
|
||||
if (hp % 4 > 0) break;
|
||||
} else {
|
||||
// Maximize number of Stealth Rock switch-ins in singles
|
||||
if (isDoubles) break;
|
||||
if (srWeakness <= 0 || ability === 'Regenerator' || ['Leftovers', 'Life Orb'].includes(item)) break;
|
||||
if (item !== 'Sitrus Berry' && hp % (4 / srWeakness) > 0) break;
|
||||
// Minimise number of Stealth Rock switch-ins to activate Sitrus Berry
|
||||
if (item === 'Sitrus Berry' && hp % (4 / srWeakness) === 0) break;
|
||||
}
|
||||
evs.hp -= 4;
|
||||
}
|
||||
|
||||
// Minimize confusion damage
|
||||
const noAttackStatMoves = [...moves].every(m => {
|
||||
const move = this.dex.moves.get(m);
|
||||
if (move.damageCallback || move.damage) return true;
|
||||
if (move.id === 'shellsidearm') return false;
|
||||
// Physical Tera Blast
|
||||
if (
|
||||
move.id === 'terablast' && (species.id === 'porygon2' || ['Contrary', 'Defiant'].includes(ability) ||
|
||||
moves.has('shiftgear') || species.baseStats.atk > species.baseStats.spa)
|
||||
) return false;
|
||||
return move.category !== 'Physical' || move.id === 'bodypress' || move.id === 'foulplay';
|
||||
});
|
||||
if (
|
||||
noAttackStatMoves && !moves.has('transform') && this.format.mod !== 'partnersincrime' &&
|
||||
!ruleTable.has('forceofthefallenmod')
|
||||
) {
|
||||
evs.atk = 0;
|
||||
ivs.atk = 0;
|
||||
}
|
||||
|
||||
if (moves.has('gyroball') || moves.has('trickroom')) {
|
||||
evs.spe = 0;
|
||||
ivs.spe = 0;
|
||||
}
|
||||
|
||||
// Enforce Tera Type after all set generation is done to prevent infinite generation
|
||||
if (this.forceTeraType) teraType = this.forceTeraType;
|
||||
|
||||
// shuffle moves to add more randomness to camomons
|
||||
const shuffledMoves = Array.from(moves);
|
||||
this.prng.shuffle(shuffledMoves);
|
||||
let name = species.baseSpecies;
|
||||
if (name === "Bruxish") name = "Brux";
|
||||
return {
|
||||
name,
|
||||
species: forme,
|
||||
speciesId: species.id,
|
||||
gender: species.baseSpecies === 'Greninja' ? 'M' : (species.gender || (this.random(2) ? 'F' : 'M')),
|
||||
shiny: this.randomChance(1, 1024),
|
||||
level,
|
||||
moves: shuffledMoves,
|
||||
ability,
|
||||
evs,
|
||||
ivs,
|
||||
item,
|
||||
teraType,
|
||||
role,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the new species is compatible with the other mons currently on the team.
|
||||
*/
|
||||
override getPokemonCompatibility(
|
||||
species: Species,
|
||||
pokemon: RandomTeamsTypes.RandomSet[]
|
||||
): boolean {
|
||||
const webSetters = [
|
||||
'ariados', 'smeargle', 'masquerain', 'kricketune', 'leavanny', 'galvantula', 'vikavolt', 'ribombee', 'araquanid', 'spidops',
|
||||
];
|
||||
const screenSetters = ['meowstic', 'grimmsnarl', 'ninetalesalola', 'abomasnow'];
|
||||
|
||||
const sunSetters = ['ninetales', 'torkoal', 'groudon', 'koraidon'];
|
||||
|
||||
const incompatiblePokemon = [
|
||||
// These Pokemon with support roles are considered too similar to each other.
|
||||
['blissey', 'chansey'],
|
||||
['illumise', 'volbeat'],
|
||||
|
||||
// These combinations are prevented to avoid double webs or screens.
|
||||
[webSetters, webSetters],
|
||||
[screenSetters, screenSetters],
|
||||
|
||||
// These Pokemon are incompatible because the presence of one actively harms the other.
|
||||
// Prevent Dry Skin + sun setting ability
|
||||
['toxicroak', sunSetters],
|
||||
];
|
||||
|
||||
const incompatibilityList = incompatiblePokemon;
|
||||
for (const pair of incompatibilityList) {
|
||||
const monsArrayA = (Array.isArray(pair[0])) ? pair[0] : [pair[0]];
|
||||
const monsArrayB = (Array.isArray(pair[1])) ? pair[1] : [pair[1]];
|
||||
if (monsArrayB.includes(species.id)) {
|
||||
if (pokemon.some(m => monsArrayA.includes(m.speciesId!))) return false;
|
||||
}
|
||||
if (monsArrayA.includes(species.id)) {
|
||||
if (pokemon.some(m => monsArrayB.includes(m.speciesId!))) return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
randomAFDSets: { [species: string]: RandomTeamsTypes.RandomSpeciesData } = require('./sets.json');
|
||||
|
||||
override randomTeam() {
|
||||
this.enforceNoDirectCustomBanlistChanges();
|
||||
|
||||
const seed = this.prng.getSeed();
|
||||
const ruleTable = this.dex.formats.getRuleTable(this.format);
|
||||
const pokemon: RandomTeamsTypes.RandomSet[] = [];
|
||||
|
||||
// PotD stuff
|
||||
const usePotD = global.Config && Config.potd && ruleTable.has('potd');
|
||||
const potd = usePotD ? this.dex.species.get(Config.potd) : null;
|
||||
|
||||
const baseFormes: { [k: string]: number } = {};
|
||||
|
||||
const typeCount: { [k: string]: number } = {};
|
||||
const typeComboCount: { [k: string]: number } = {};
|
||||
const typeWeaknesses: { [k: string]: number } = {};
|
||||
const typeDoubleWeaknesses: { [k: string]: number } = {};
|
||||
const teamDetails: RandomTeamsTypes.TeamDetails = {};
|
||||
let numMaxLevelPokemon = 0;
|
||||
|
||||
const pokemonList = Object.keys(this.randomSets);
|
||||
const afdList = Object.keys(this.randomAFDSets);
|
||||
const zaMegaList = Object.keys(this.randomAFDSets).filter(x => (
|
||||
this.dex.species.get(x).isMega && this.dex.species.get(x).gen === 9
|
||||
));
|
||||
const [pokemonPool, baseSpeciesPool] = this.getPokemonPool('', pokemon, false, pokemonList);
|
||||
const [afdPool, baseAfdPool] = this.getPokemonPool('', pokemon, false, afdList);
|
||||
const [zaMegaPool, zaBaseMegaPool] = this.getPokemonPool('', pokemon, false, zaMegaList);
|
||||
|
||||
let leadsRemaining = this.format.gameType === 'doubles' ? 2 : 1;
|
||||
while (baseSpeciesPool.length && pokemon.length < this.maxTeamSize) {
|
||||
let baseSpecies, species;
|
||||
if (pokemon.length === 0) {
|
||||
baseSpecies = this.sampleNoReplace(zaBaseMegaPool);
|
||||
species = this.dex.species.get(this.sample(zaMegaPool[baseSpecies]));
|
||||
} else if (this.randomChance(1, 5)) {
|
||||
baseSpecies = this.sampleNoReplace(baseAfdPool);
|
||||
species = this.dex.species.get(this.sample(afdPool[baseSpecies]));
|
||||
} else {
|
||||
baseSpecies = this.sampleNoReplace(baseSpeciesPool);
|
||||
species = this.dex.species.get(this.sample(pokemonPool[baseSpecies]));
|
||||
}
|
||||
if (!species.exists) continue;
|
||||
|
||||
// Limit to one of each species (Species Clause)
|
||||
if (baseFormes[species.baseSpecies]) continue;
|
||||
|
||||
// Treat Ogerpon formes and Terapagos like the Tera Blast user role; reject if team has one already
|
||||
if (['ogerpon', 'ogerponhearthflame', 'terapagos'].includes(species.id) && teamDetails.teraBlast) continue;
|
||||
|
||||
// Illusion shouldn't be on the last slot
|
||||
if (species.baseSpecies === 'Zoroark' && pokemon.length >= (this.maxTeamSize - 1)) continue;
|
||||
|
||||
const types = species.types;
|
||||
const typeCombo = types.slice().sort().join();
|
||||
const weakToFreezeDry = (
|
||||
this.dex.getEffectiveness('Ice', species) > 0 ||
|
||||
(this.dex.getEffectiveness('Ice', species) > -2 && types.includes('Water'))
|
||||
);
|
||||
const weakToScald = (
|
||||
this.dex.getEffectiveness('Water', species) > 0 ||
|
||||
(this.dex.getEffectiveness('Water', species) > -2 && types.includes('Steel'))
|
||||
);
|
||||
// Dynamically scale limits for different team sizes. The default and minimum value is 1.
|
||||
const limitFactor = Math.round(this.maxTeamSize / 6) || 1;
|
||||
|
||||
let skip = false;
|
||||
|
||||
// Limit two of any type
|
||||
for (const typeName of types) {
|
||||
if (typeCount[typeName] >= 2 * limitFactor) {
|
||||
skip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (skip) continue;
|
||||
|
||||
// Limit three weak to any type, and one double weak to any type
|
||||
for (const typeName of this.dex.types.names()) {
|
||||
// it's weak to the type
|
||||
if (this.dex.getEffectiveness(typeName, species) > 0) {
|
||||
if (!typeWeaknesses[typeName]) typeWeaknesses[typeName] = 0;
|
||||
if (typeWeaknesses[typeName] >= 3 * limitFactor) {
|
||||
skip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (this.dex.getEffectiveness(typeName, species) > 1) {
|
||||
if (!typeDoubleWeaknesses[typeName]) typeDoubleWeaknesses[typeName] = 0;
|
||||
if (typeDoubleWeaknesses[typeName] >= limitFactor) {
|
||||
skip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (skip) continue;
|
||||
|
||||
// Count Dry Skin/Fluffy as Fire weaknesses
|
||||
if (
|
||||
this.dex.getEffectiveness('Fire', species) === 0 &&
|
||||
Object.values(species.abilities).filter(a => ['Dry Skin', 'Fluffy'].includes(a)).length
|
||||
) {
|
||||
if (!typeWeaknesses['Fire']) typeWeaknesses['Fire'] = 0;
|
||||
if (typeWeaknesses['Fire'] >= 3 * limitFactor) continue;
|
||||
}
|
||||
|
||||
// Limit four weak to Freeze-Dry
|
||||
if (weakToFreezeDry) {
|
||||
if (!typeWeaknesses['Freeze-Dry']) typeWeaknesses['Freeze-Dry'] = 0;
|
||||
if (typeWeaknesses['Freeze-Dry'] >= 4 * limitFactor) continue;
|
||||
}
|
||||
if (weakToScald) {
|
||||
if (!typeWeaknesses['Scald']) typeWeaknesses['Scald'] = 0;
|
||||
if (typeWeaknesses['Scald'] >= 4 * limitFactor) continue;
|
||||
}
|
||||
|
||||
// Limit one level 100 Pokemon
|
||||
if (!this.adjustLevel && (this.getLevel(species) === 100) && numMaxLevelPokemon >= limitFactor) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check compatibility with team
|
||||
if (!this.getPokemonCompatibility(species, pokemon)) continue;
|
||||
|
||||
// The Pokemon of the Day
|
||||
if (potd?.exists && (pokemon.length === 1 || this.maxTeamSize === 1)) species = potd;
|
||||
|
||||
let set: RandomTeamsTypes.RandomSet;
|
||||
|
||||
if (leadsRemaining) {
|
||||
if (NO_LEAD_POKEMON.includes(species.baseSpecies)) {
|
||||
if (pokemon.length + leadsRemaining === this.maxTeamSize) continue;
|
||||
set = this.randomAFDSet(species, teamDetails, false);
|
||||
pokemon.push(set);
|
||||
} else {
|
||||
set = this.randomAFDSet(species, teamDetails, true);
|
||||
pokemon.unshift(set);
|
||||
leadsRemaining--;
|
||||
}
|
||||
} else {
|
||||
set = this.randomAFDSet(species, teamDetails, false);
|
||||
pokemon.push(set);
|
||||
}
|
||||
|
||||
// Don't bother tracking details for the last Pokemon
|
||||
if (pokemon.length === this.maxTeamSize) break;
|
||||
|
||||
// Now that our Pokemon has passed all checks, we can increment our counters
|
||||
baseFormes[species.baseSpecies] = 1;
|
||||
|
||||
// Increment type counters
|
||||
for (const typeName of types) {
|
||||
if (typeName in typeCount) {
|
||||
typeCount[typeName]++;
|
||||
} else {
|
||||
typeCount[typeName] = 1;
|
||||
}
|
||||
}
|
||||
if (typeCombo in typeComboCount) {
|
||||
typeComboCount[typeCombo]++;
|
||||
} else {
|
||||
typeComboCount[typeCombo] = 1;
|
||||
}
|
||||
|
||||
// Increment weakness counter
|
||||
for (const typeName of this.dex.types.names()) {
|
||||
// it's weak to the type
|
||||
if (this.dex.getEffectiveness(typeName, species) > 0) {
|
||||
typeWeaknesses[typeName]++;
|
||||
}
|
||||
if (this.dex.getEffectiveness(typeName, species) > 1) {
|
||||
typeDoubleWeaknesses[typeName]++;
|
||||
}
|
||||
}
|
||||
// Count Dry Skin/Fluffy as Fire weaknesses
|
||||
if (['Dry Skin', 'Fluffy'].includes(set.ability) && this.dex.getEffectiveness('Fire', species) === 0) {
|
||||
typeWeaknesses['Fire']++;
|
||||
}
|
||||
if (weakToFreezeDry) typeWeaknesses['Freeze-Dry']++;
|
||||
if (weakToScald) typeWeaknesses['Scald']++;
|
||||
|
||||
// Increment level 100 counter
|
||||
if (set.level === 100) numMaxLevelPokemon++;
|
||||
|
||||
// Track what the team has
|
||||
if (set.ability === 'Drizzle' || set.moves.includes('raindance')) teamDetails.rain = 1;
|
||||
if (set.ability === 'Drought' || set.ability === 'Orichalcum Pulse' || set.moves.includes('sunnyday')) {
|
||||
teamDetails.sun = 1;
|
||||
}
|
||||
if (set.ability === 'Sand Stream') teamDetails.sand = 1;
|
||||
if (set.ability === 'Snow Warning' || set.moves.includes('snowscape') || set.moves.includes('chillyreception')) {
|
||||
teamDetails.snow = 1;
|
||||
}
|
||||
if (set.moves.includes('healbell')) teamDetails.statusCure = 1;
|
||||
if (set.moves.includes('spikes') || set.moves.includes('ceaselessedge')) {
|
||||
teamDetails.spikes = (teamDetails.spikes || 0) + 1;
|
||||
}
|
||||
if (set.moves.includes('toxicspikes') || set.ability === 'Toxic Debris') teamDetails.toxicSpikes = 1;
|
||||
if (set.moves.includes('stealthrock') || set.moves.includes('stoneaxe')) teamDetails.stealthRock = 1;
|
||||
if (set.moves.includes('stickyweb')) teamDetails.stickyWeb = 1;
|
||||
if (set.moves.includes('defog')) teamDetails.defog = 1;
|
||||
if (set.moves.includes('rapidspin') || set.moves.includes('mortalspin')) teamDetails.rapidSpin = 1;
|
||||
if (set.moves.includes('auroraveil') || (set.moves.includes('reflect') && set.moves.includes('lightscreen'))) {
|
||||
teamDetails.screens = 1;
|
||||
}
|
||||
if (set.role === 'Tera Blast user' || ['ogerpon', 'ogerponhearthflame', 'terapagos'].includes(species.id)) {
|
||||
teamDetails.teraBlast = 1;
|
||||
}
|
||||
}
|
||||
if (pokemon.length < this.maxTeamSize && pokemon.length < 12) { // large teams sometimes cannot be built
|
||||
throw new Error(`Could not build a random team for ${this.format} (seed=${seed})`);
|
||||
}
|
||||
|
||||
return pokemon;
|
||||
}
|
||||
}
|
||||
|
||||
export default RandomAFDTeams;
|
||||
626
data/mods/afd/scripts.ts
Normal file
626
data/mods/afd/scripts.ts
Normal file
|
|
@ -0,0 +1,626 @@
|
|||
export const Scripts: ModdedBattleScriptsData = {
|
||||
gen: 9,
|
||||
init() {
|
||||
for (const id in this.data.Pokedex) {
|
||||
const species = this.data.Pokedex[id];
|
||||
if (species.isCosmeticForme) continue;
|
||||
if (species.types.includes('Ground')) {
|
||||
if (this.data.Learnsets[id]?.learnset) this.modData('Learnsets', id).learnset.thousandarrows = ['9L1'];
|
||||
}
|
||||
if (species.types.includes('Grass') && !species.types.includes('Fire')) {
|
||||
if (this.data.Learnsets[id]?.learnset) this.modData('Learnsets', id).learnset.solarflare = ['9L1'];
|
||||
}
|
||||
const abilities = this.modData('Pokedex', id, true).abilities;
|
||||
if (species.baseStats['atk'] >= 130) {
|
||||
const hasHP = Object.values(abilities).includes('Huge Power') ||
|
||||
Object.values(abilities).includes('Pure Power');
|
||||
if (!hasHP) {
|
||||
const slot = !abilities['1'] ? '1' : !abilities['H'] ? 'H' : 'S';
|
||||
abilities[slot] ||= 'Huge Power';
|
||||
}
|
||||
}
|
||||
const hasRegen = Object.values(abilities).includes('Regenerator');
|
||||
if (!hasRegen) {
|
||||
const slot = !abilities['1'] ? '1' : !abilities['H'] ? 'H' : 'S';
|
||||
abilities[slot] ||= 'Regenerator';
|
||||
}
|
||||
}
|
||||
this.modData('Learnsets', 'tyranitar').learnset.shoreup = ['9L1'];
|
||||
this.modData('Learnsets', 'bastiodon').learnset.blastiodon = ['9L1'];
|
||||
this.modData('Learnsets', 'seaking').learnset.boltbeak = ['9L1'];
|
||||
this.modData('Learnsets', 'seaking').learnset.fishiousrend = ['9L1'];
|
||||
this.modData('Learnsets', 'ampharos').learnset.tailglow = ['9L1'];
|
||||
this.modData('Learnsets', 'ampharos').learnset.dracometeor = ['9L1'];
|
||||
this.modData('Learnsets', 'serperior').learnset.dracometeor = ['9L1'];
|
||||
this.modData('Learnsets', 'serperior').learnset.overheat = ['9L1'];
|
||||
this.modData('Learnsets', 'serperior').learnset.makeitrain = ['9L1'];
|
||||
this.modData('Learnsets', 'rampardos').learnset.accelerock = ['9L1'];
|
||||
this.modData('Learnsets', 'bibarel').learnset.bellydrum = ['9L1'];
|
||||
this.modData('Learnsets', 'bibarel').learnset.storedpower = ['9L1'];
|
||||
this.modData('Learnsets', 'bibarel').learnset.powertrip = ['9L1'];
|
||||
this.modData('Learnsets', 'golisopod').learnset.bellydrum = ['9L1'];
|
||||
this.modData('Learnsets', 'skuntank').learnset.shitpulse = ['9L1'];
|
||||
this.modData('Learnsets', 'dusknoir').learnset = { explosion: ['9L1'] };
|
||||
for (const move of this.moves.all()) {
|
||||
if (move.flags['bite']) {
|
||||
this.modData('Learnsets', 'bruxish').learnset[move.id] = ['9L1'];
|
||||
}
|
||||
}
|
||||
for (const moveid in this.data.Learnsets['incineroar'].learnset) {
|
||||
if (this.moves.get(moveid).type === 'Dark') {
|
||||
delete this.modData('Learnsets', 'incineroar').learnset[moveid];
|
||||
}
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
runMegaEvo(pokemon: Pokemon) {
|
||||
const speciesid = pokemon.canMegaEvo || pokemon.canUltraBurst;
|
||||
if (!speciesid) return false;
|
||||
|
||||
pokemon.formeChange(speciesid, pokemon.getItem(), true);
|
||||
|
||||
// Limit one mega evolution
|
||||
pokemon.canMegaEvo = null;
|
||||
|
||||
this.battle.runEvent('AfterMega', pokemon);
|
||||
return true;
|
||||
},
|
||||
switchIn(pokemon, pos, sourceEffect = null, isDrag) {
|
||||
if (!pokemon || pokemon.isActive) {
|
||||
this.battle.hint("A switch failed because the Pokémon trying to switch in is already in.");
|
||||
return false;
|
||||
}
|
||||
|
||||
const side = pokemon.side;
|
||||
if (pos >= side.active.length) {
|
||||
throw new Error(`Invalid switch position ${pos} / ${side.active.length}`);
|
||||
}
|
||||
const oldActive = side.active[pos];
|
||||
const unfaintedActive = oldActive?.hp ? oldActive : null;
|
||||
if (unfaintedActive) {
|
||||
oldActive.beingCalledBack = true;
|
||||
let switchCopyFlag: 'copyvolatile' | 'shedtail' | boolean = false;
|
||||
if (sourceEffect && typeof (sourceEffect as Move).selfSwitch === 'string') {
|
||||
switchCopyFlag = (sourceEffect as Move).selfSwitch!;
|
||||
}
|
||||
if (!oldActive.skipBeforeSwitchOutEventFlag && !isDrag) {
|
||||
this.battle.runEvent('BeforeSwitchOut', oldActive);
|
||||
if (this.battle.gen >= 5) {
|
||||
this.battle.eachEvent('Update');
|
||||
}
|
||||
}
|
||||
oldActive.skipBeforeSwitchOutEventFlag = false;
|
||||
if (!this.battle.runEvent('SwitchOut', oldActive)) {
|
||||
// Warning: DO NOT interrupt a switch-out if you just want to trap a pokemon.
|
||||
// To trap a pokemon and prevent it from switching out, (e.g. Mean Look, Magnet Pull)
|
||||
// use the 'trapped' flag instead.
|
||||
|
||||
// Note: Nothing in the real games can interrupt a switch-out (except Pursuit KOing,
|
||||
// which is handled elsewhere); this is just for custom formats.
|
||||
return false;
|
||||
}
|
||||
if (!oldActive.hp) {
|
||||
// a pokemon fainted from Pursuit before it could switch
|
||||
return 'pursuitfaint';
|
||||
}
|
||||
|
||||
// will definitely switch out at this point
|
||||
|
||||
this.battle.singleEvent('End', oldActive.getAbility(), oldActive.abilityState, oldActive);
|
||||
this.battle.singleEvent('End', oldActive.getItem(), oldActive.itemState, oldActive);
|
||||
|
||||
// if a pokemon is forced out by Whirlwind/etc or Eject Button/Pack, it can't use its chosen move
|
||||
this.battle.queue.cancelAction(oldActive);
|
||||
|
||||
let newMove = null;
|
||||
if (this.battle.gen === 4 && sourceEffect) {
|
||||
newMove = oldActive.lastMove;
|
||||
}
|
||||
if (switchCopyFlag) {
|
||||
pokemon.copyVolatileFrom(oldActive, switchCopyFlag);
|
||||
}
|
||||
if (newMove) pokemon.lastMove = newMove;
|
||||
oldActive.clearVolatile();
|
||||
}
|
||||
if (oldActive) {
|
||||
oldActive.isActive = false;
|
||||
oldActive.isStarted = false;
|
||||
oldActive.usedItemThisTurn = false;
|
||||
oldActive.statsRaisedThisTurn = false;
|
||||
oldActive.statsLoweredThisTurn = false;
|
||||
oldActive.position = pokemon.position;
|
||||
if (oldActive.fainted) oldActive.status = '';
|
||||
if (this.battle.gen <= 4) {
|
||||
pokemon.lastItem = oldActive.lastItem;
|
||||
oldActive.lastItem = '';
|
||||
}
|
||||
pokemon.position = pos;
|
||||
side.pokemon[pokemon.position] = pokemon;
|
||||
side.pokemon[oldActive.position] = oldActive;
|
||||
}
|
||||
pokemon.isActive = true;
|
||||
side.active[pos] = pokemon;
|
||||
pokemon.activeTurns = 0;
|
||||
pokemon.activeMoveActions = 0;
|
||||
for (const moveSlot of pokemon.moveSlots) {
|
||||
moveSlot.used = false;
|
||||
}
|
||||
pokemon.abilityState = this.battle.initEffectState({ id: pokemon.ability, target: pokemon });
|
||||
pokemon.itemState = this.battle.initEffectState({ id: pokemon.item, target: pokemon });
|
||||
this.battle.runEvent('BeforeSwitchIn', pokemon);
|
||||
if (sourceEffect) {
|
||||
this.battle.add(isDrag ? 'drag' : 'switch', pokemon, pokemon.getFullDetails, `[from] ${sourceEffect}`);
|
||||
} else {
|
||||
this.battle.add(isDrag ? 'drag' : 'switch', pokemon, pokemon.getFullDetails);
|
||||
}
|
||||
if (isDrag && this.battle.gen === 2) pokemon.draggedIn = this.battle.turn;
|
||||
pokemon.previouslySwitchedIn++;
|
||||
|
||||
if (isDrag && this.battle.gen >= 5) {
|
||||
// runSwitch happens immediately so that Mold Breaker can make hazards bypass Clear Body and Levitate
|
||||
this.runSwitch(pokemon);
|
||||
} else {
|
||||
this.battle.queue.insertChoice({ choice: 'runSwitch', pokemon });
|
||||
}
|
||||
|
||||
if (pokemon.hasType('Flying')) {
|
||||
this.battle.field.addPseudoWeather('Tailwind', pokemon);
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
useMoveInner(moveOrMoveName, pokemon, options) {
|
||||
let target = options?.target;
|
||||
let sourceEffect = options?.sourceEffect;
|
||||
const zMove = options?.zMove;
|
||||
const maxMove = options?.maxMove;
|
||||
if (!sourceEffect && this.battle.effect.id) sourceEffect = this.battle.effect;
|
||||
if (sourceEffect && ['instruct', 'custapberry'].includes(sourceEffect.id)) sourceEffect = null;
|
||||
|
||||
let move = this.dex.getActiveMove(moveOrMoveName);
|
||||
pokemon.lastMoveUsed = move;
|
||||
if (move.id === 'weatherball' && zMove) {
|
||||
// Z-Weather Ball only changes types if it's used directly,
|
||||
// not if it's called by Z-Sleep Talk or something.
|
||||
this.battle.singleEvent('ModifyType', move, null, pokemon, target, move, move);
|
||||
if (move.type !== 'Normal') sourceEffect = move;
|
||||
}
|
||||
if (zMove || (move.category !== 'Status' && sourceEffect && (sourceEffect as ActiveMove).isZ)) {
|
||||
move = this.getActiveZMove(move, pokemon);
|
||||
}
|
||||
if (maxMove && move.category !== 'Status') {
|
||||
// Max move outcome is dependent on the move type after type modifications from ability and the move itself
|
||||
this.battle.singleEvent('ModifyType', move, null, pokemon, target, move, move);
|
||||
this.battle.runEvent('ModifyType', pokemon, target, move, move);
|
||||
}
|
||||
if (maxMove || (move.category !== 'Status' && sourceEffect && (sourceEffect as ActiveMove).isMax)) {
|
||||
move = this.getActiveMaxMove(move, pokemon);
|
||||
}
|
||||
|
||||
if (this.battle.activeMove) {
|
||||
move.priority = this.battle.activeMove.priority;
|
||||
if (!move.hasBounced) move.pranksterBoosted = this.battle.activeMove.pranksterBoosted;
|
||||
}
|
||||
const baseTarget = move.target;
|
||||
let targetRelayVar = { target };
|
||||
targetRelayVar = this.battle.runEvent('ModifyTarget', pokemon, target, move, targetRelayVar, true);
|
||||
if (targetRelayVar.target !== undefined) target = targetRelayVar.target;
|
||||
if (target === undefined) target = this.battle.getRandomTarget(pokemon, move);
|
||||
if (move.target === 'self' || move.target === 'allies') {
|
||||
target = pokemon;
|
||||
}
|
||||
if (sourceEffect) {
|
||||
move.sourceEffect = sourceEffect.id;
|
||||
move.ignoreAbility = (sourceEffect as ActiveMove).ignoreAbility;
|
||||
}
|
||||
let moveResult = false;
|
||||
|
||||
this.battle.setActiveMove(move, pokemon, target);
|
||||
|
||||
this.battle.singleEvent('ModifyType', move, null, pokemon, target, move, move);
|
||||
this.battle.singleEvent('ModifyMove', move, null, pokemon, target, move, move);
|
||||
if (baseTarget !== move.target) {
|
||||
// Target changed in ModifyMove, so we must adjust it here
|
||||
// Adjust before the next event so the correct target is passed to the
|
||||
// event
|
||||
target = this.battle.getRandomTarget(pokemon, move);
|
||||
}
|
||||
move = this.battle.runEvent('ModifyType', pokemon, target, move, move);
|
||||
move = this.battle.runEvent('ModifyMove', pokemon, target, move, move);
|
||||
if (baseTarget !== move.target) {
|
||||
// Adjust again
|
||||
target = this.battle.getRandomTarget(pokemon, move);
|
||||
}
|
||||
if (!move || pokemon.fainted) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let attrs = '';
|
||||
|
||||
let movename = move.name;
|
||||
if (move.id === 'hiddenpower') movename = 'Hidden Power';
|
||||
if (sourceEffect) attrs += `|[from] ${sourceEffect.fullname}`;
|
||||
if (zMove && move.isZ === true) {
|
||||
attrs = `|[anim]${movename}${attrs}`;
|
||||
movename = `Z-${movename}`;
|
||||
}
|
||||
this.battle.addMove('move', pokemon, movename, `${target}${attrs}`);
|
||||
|
||||
if (zMove) this.runZPower(move, pokemon);
|
||||
|
||||
if (!target) {
|
||||
this.battle.attrLastMove('[notarget]');
|
||||
this.battle.add(this.battle.gen >= 5 ? '-fail' : '-notarget', pokemon);
|
||||
return false;
|
||||
}
|
||||
|
||||
const { targets, pressureTargets } = pokemon.getMoveTargets(move, target);
|
||||
if (targets.length) {
|
||||
target = targets[targets.length - 1]; // in case of redirection
|
||||
}
|
||||
|
||||
const callerMoveForPressure = sourceEffect && (sourceEffect as ActiveMove).pp ? sourceEffect as ActiveMove : null;
|
||||
if (!sourceEffect || callerMoveForPressure || sourceEffect.id === 'pursuit') {
|
||||
let extraPP = 0;
|
||||
for (const source of pressureTargets) {
|
||||
const ppDrop = this.battle.runEvent('DeductPP', source, pokemon, move);
|
||||
if (ppDrop !== true) {
|
||||
extraPP += ppDrop || 0;
|
||||
}
|
||||
}
|
||||
if (extraPP > 0) {
|
||||
pokemon.deductPP(callerMoveForPressure || moveOrMoveName, extraPP);
|
||||
}
|
||||
}
|
||||
|
||||
let tryMoveResult = this.battle.singleEvent('TryMove', move, null, pokemon, target, move);
|
||||
if (tryMoveResult) {
|
||||
tryMoveResult = this.battle.runEvent('TryMove', pokemon, target, move);
|
||||
}
|
||||
if (!tryMoveResult) {
|
||||
move.mindBlownRecoil = false;
|
||||
return tryMoveResult;
|
||||
}
|
||||
|
||||
this.battle.singleEvent('UseMoveMessage', move, null, pokemon, target, move);
|
||||
|
||||
if (move.ignoreImmunity === undefined) {
|
||||
move.ignoreImmunity = (move.category === 'Status');
|
||||
}
|
||||
|
||||
if (this.battle.gen !== 4 && move.selfdestruct === 'always') {
|
||||
this.battle.faint(pokemon, pokemon, move);
|
||||
}
|
||||
|
||||
let damage: number | false | undefined | '' = false;
|
||||
if (move.target === 'all' || move.target === 'foeSide' || move.target === 'allySide' || move.target === 'allyTeam') {
|
||||
damage = this.tryMoveHit(targets, pokemon, move);
|
||||
if (damage === this.battle.NOT_FAIL) pokemon.moveThisTurnResult = null;
|
||||
if (damage || damage === 0 || damage === undefined) moveResult = true;
|
||||
} else {
|
||||
if (!targets.length) {
|
||||
this.battle.attrLastMove('[notarget]');
|
||||
this.battle.add(this.battle.gen >= 5 ? '-fail' : '-notarget', pokemon);
|
||||
return false;
|
||||
}
|
||||
if (this.battle.gen === 4 && move.selfdestruct === 'always') {
|
||||
this.battle.faint(pokemon, pokemon, move);
|
||||
}
|
||||
moveResult = this.trySpreadMoveHit(targets, pokemon, move);
|
||||
}
|
||||
if (move.selfBoost && moveResult) this.moveHit(pokemon, pokemon, move, move.selfBoost, false, true);
|
||||
if (!pokemon.hp) {
|
||||
this.battle.faint(pokemon, pokemon, move);
|
||||
}
|
||||
|
||||
if (!moveResult) {
|
||||
this.battle.singleEvent('MoveFail', move, null, target, pokemon, move);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(move.hasSheerForce && pokemon.hasAbility('sheerforce')) && !move.flags['futuremove']) {
|
||||
const originalHp = pokemon.hp;
|
||||
this.battle.singleEvent('AfterMoveSecondarySelf', move, null, pokemon, target, move);
|
||||
this.battle.runEvent('AfterMoveSecondarySelf', pokemon, target, move);
|
||||
if (pokemon && pokemon !== target && move.category !== 'Status') {
|
||||
if (pokemon.hp <= pokemon.maxhp / 2 && originalHp > pokemon.maxhp / 2) {
|
||||
this.battle.runEvent('EmergencyExit', pokemon, pokemon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
canTerastallize(pokemon: Pokemon) {
|
||||
if (this.dex.gen !== 9) {
|
||||
return null;
|
||||
}
|
||||
return pokemon.teraType;
|
||||
},
|
||||
canMegaEvo(pokemon) {
|
||||
const species = pokemon.baseSpecies;
|
||||
const altForme = species.otherFormes && this.dex.species.get(species.otherFormes[0]);
|
||||
const item = pokemon.getItem();
|
||||
// Mega Rayquaza
|
||||
if ((this.battle.gen <= 7 || this.battle.ruleTable.has('+pokemontag:past') ||
|
||||
this.battle.ruleTable.has('+pokemontag:future')) &&
|
||||
altForme?.isMega && altForme?.requiredMove &&
|
||||
pokemon.baseMoves.includes(this.battle.toID(altForme.requiredMove)) && !item.zMove) {
|
||||
return altForme.name;
|
||||
}
|
||||
if (species.baseSpecies === 'Magearna' && !species.isMega) {
|
||||
return species.name.includes('Original') ? 'Magearna-Original-Mega' : 'Magearna-Mega';
|
||||
}
|
||||
if (!item.megaStone) return null;
|
||||
return item.megaStone[species.name];
|
||||
},
|
||||
modifyDamage(baseDamage, pokemon, target, move, suppressMessages = false) {
|
||||
const tr = this.battle.trunc;
|
||||
if (!move.type) move.type = '???';
|
||||
const type = move.type;
|
||||
|
||||
baseDamage += 2;
|
||||
|
||||
if (move.spreadHit) {
|
||||
// multi-target modifier (doubles only)
|
||||
const spreadModifier = this.battle.gameType === 'freeforall' ? 0.5 : 0.75;
|
||||
this.battle.debug(`Spread modifier: ${spreadModifier}`);
|
||||
baseDamage = this.battle.modify(baseDamage, spreadModifier);
|
||||
} else if (move.multihitType === 'parentalbond' && move.hit > 1) {
|
||||
// Parental Bond modifier
|
||||
const bondModifier = this.battle.gen > 6 ? 0.25 : 0.5;
|
||||
this.battle.debug(`Parental Bond modifier: ${bondModifier}`);
|
||||
baseDamage = this.battle.modify(baseDamage, bondModifier);
|
||||
}
|
||||
|
||||
// weather modifier
|
||||
baseDamage = this.battle.runEvent('WeatherModifyDamage', pokemon, target, move, baseDamage);
|
||||
|
||||
// crit - not a modifier
|
||||
const isCrit = target.getMoveHitData(move).crit;
|
||||
if (isCrit) {
|
||||
baseDamage = tr(baseDamage * (move.critModifier || (this.battle.gen >= 6 ? 1.5 : 2)));
|
||||
}
|
||||
|
||||
// random factor - also not a modifier
|
||||
baseDamage = this.battle.randomizer(baseDamage);
|
||||
|
||||
// STAB
|
||||
// The "???" type never gets STAB
|
||||
// Not even if you Roost in Gen 4 and somehow manage to use
|
||||
// Struggle in the same turn.
|
||||
// (On second thought, it might be easier to get a MissingNo.)
|
||||
if (type !== '???') {
|
||||
let stab: number | [number, number] = 1;
|
||||
|
||||
const pokeTypes = pokemon.getTypes(false, true);
|
||||
const isPrimarySTAB = move.forceSTAB || (pokemon.hasType(type) && pokeTypes[0] === type);
|
||||
const isSecondarySTAB = move.forceSTAB || (pokemon.hasType(type) && pokeTypes.length > 1 && pokeTypes[1] === type);
|
||||
const isSTAB = move.forceSTAB || pokemon.hasType(type) || pokemon.getTypes(false, true).includes(type);
|
||||
if (isPrimarySTAB) {
|
||||
stab = 1.7;
|
||||
}
|
||||
if (isSecondarySTAB) {
|
||||
stab = 1.2;
|
||||
}
|
||||
|
||||
// The Stellar tera type makes this incredibly confusing
|
||||
// If the move's type does not match one of the user's base types,
|
||||
// the Stellar tera type applies a one-time 1.2x damage boost for that type.
|
||||
//
|
||||
// If the move's type does match one of the user's base types,
|
||||
// then the Stellar tera type applies a one-time 2x STAB boost for that type,
|
||||
// and then goes back to using the regular 1.5x STAB boost for those types.
|
||||
if (pokemon.terastallized === 'Stellar') {
|
||||
if (!pokemon.stellarBoostedTypes.includes(type) || move.stellarBoosted) {
|
||||
stab = isSTAB ? 2.3 : [4915, 4096];
|
||||
move.stellarBoosted = true;
|
||||
if (pokemon.species.name !== 'Terapagos-Stellar') {
|
||||
pokemon.stellarBoostedTypes.push(type);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (pokemon.terastallized === type && pokeTypes.includes(type)) {
|
||||
stab = 2.3;
|
||||
}
|
||||
stab = this.battle.runEvent('ModifySTAB', pokemon, target, move, stab);
|
||||
}
|
||||
|
||||
baseDamage = this.battle.modify(baseDamage, stab);
|
||||
}
|
||||
|
||||
// types
|
||||
let typeMod = target.runEffectiveness(move);
|
||||
typeMod = this.battle.clampIntRange(typeMod, -6, 6);
|
||||
target.getMoveHitData(move).typeMod = typeMod;
|
||||
if (typeMod > 0) {
|
||||
if (!suppressMessages) this.battle.add('-supereffective', target);
|
||||
|
||||
for (let i = 0; i < typeMod; i++) {
|
||||
baseDamage *= 2;
|
||||
}
|
||||
}
|
||||
if (typeMod < 0) {
|
||||
if (!suppressMessages) this.battle.add('-resisted', target);
|
||||
|
||||
for (let i = 0; i > typeMod; i--) {
|
||||
baseDamage = tr(baseDamage / 2);
|
||||
}
|
||||
}
|
||||
|
||||
if (isCrit && !suppressMessages) this.battle.add('-crit', target);
|
||||
|
||||
if (pokemon.status === 'brn' && move.category === 'Physical' && !pokemon.hasAbility('guts')) {
|
||||
if (this.battle.gen < 6 || move.id !== 'facade') {
|
||||
baseDamage = this.battle.modify(baseDamage, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
if (pokemon.status === 'psn' && move.category === 'Special') {
|
||||
if (this.battle.gen < 6 || move.id !== 'facade') {
|
||||
baseDamage = this.battle.modify(baseDamage, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
// Generation 5, but nothing later, sets damage to 1 before the final damage modifiers
|
||||
if (this.battle.gen === 5 && !baseDamage) baseDamage = 1;
|
||||
|
||||
// Final modifier. Modifiers that modify damage after min damage check, such as Life Orb.
|
||||
baseDamage = this.battle.runEvent('ModifyDamage', pokemon, target, move, baseDamage);
|
||||
|
||||
const bypassProtect = target.getMoveHitData(move).bypassProtect;
|
||||
if (bypassProtect) {
|
||||
baseDamage = this.battle.modify(baseDamage, 0.25);
|
||||
if (bypassProtect !== true && bypassProtect.effectType === 'Ability') {
|
||||
this.battle.add('-ability', pokemon, bypassProtect.name);
|
||||
}
|
||||
this.battle.add('-zbroken', target);
|
||||
}
|
||||
|
||||
// Generation 6-7 moves the check for minimum 1 damage after the final modifier...
|
||||
if (this.battle.gen !== 5 && !baseDamage) return 1;
|
||||
|
||||
// ...but 16-bit truncation happens even later, and can truncate to 0
|
||||
return tr(baseDamage, 16);
|
||||
},
|
||||
getDamage(source, target, move, suppressMessages = false) {
|
||||
if (typeof move === 'string') move = this.dex.getActiveMove(move);
|
||||
|
||||
if (typeof move === 'number') {
|
||||
const basePower = move;
|
||||
move = new Dex.Move({
|
||||
basePower,
|
||||
type: '???',
|
||||
category: 'Physical',
|
||||
willCrit: false,
|
||||
}) as ActiveMove;
|
||||
move.hit = 0;
|
||||
}
|
||||
|
||||
if (!target.runImmunity(move, !suppressMessages)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (move.ohko) return this.battle.gen === 3 ? target.hp : target.maxhp;
|
||||
if (move.damageCallback) return move.damageCallback.call(this.battle, source, target);
|
||||
if (move.damage === 'level') {
|
||||
return source.level;
|
||||
} else if (move.damage) {
|
||||
return move.damage;
|
||||
}
|
||||
|
||||
let category = this.battle.getCategory(move);
|
||||
|
||||
let basePower: number | false | null = move.basePower;
|
||||
if (move.basePowerCallback) {
|
||||
basePower = move.basePowerCallback.call(this.battle, source, target, move);
|
||||
}
|
||||
if (!basePower) return basePower === 0 ? undefined : basePower;
|
||||
basePower = this.battle.clampIntRange(basePower, 1);
|
||||
if (move.type === 'Electric' && move.category === 'Physical') {
|
||||
basePower += 15;
|
||||
category = 'Special';
|
||||
}
|
||||
|
||||
let critMult;
|
||||
let critRatio = this.battle.runEvent('ModifyCritRatio', source, target, move, move.critRatio || 0);
|
||||
if (this.battle.gen <= 5) {
|
||||
critRatio = this.battle.clampIntRange(critRatio, 0, 5);
|
||||
critMult = [0, 16, 8, 4, 3, 2];
|
||||
} else {
|
||||
critRatio = this.battle.clampIntRange(critRatio, 0, 4);
|
||||
if (this.battle.gen === 6) {
|
||||
critMult = [0, 16, 8, 2, 1];
|
||||
} else {
|
||||
critMult = [0, 24, 8, 2, 1];
|
||||
}
|
||||
}
|
||||
|
||||
const moveHit = target.getMoveHitData(move);
|
||||
moveHit.crit = move.willCrit || false;
|
||||
if (move.willCrit === undefined) {
|
||||
if (critRatio) {
|
||||
moveHit.crit = this.battle.randomChance(1, critMult[critRatio]);
|
||||
}
|
||||
}
|
||||
|
||||
if (moveHit.crit) {
|
||||
moveHit.crit = this.battle.runEvent('CriticalHit', target, null, move);
|
||||
}
|
||||
|
||||
// happens after crit calculation
|
||||
basePower = this.battle.runEvent('BasePower', source, target, move, basePower, true);
|
||||
|
||||
if (!basePower) return 0;
|
||||
basePower = this.battle.clampIntRange(basePower, 1);
|
||||
// Hacked Max Moves have 0 base power, even if you Dynamax
|
||||
if ((!source.volatiles['dynamax'] && move.isMax) || (move.isMax && this.dex.moves.get(move.baseMove).isMax)) {
|
||||
basePower = 0;
|
||||
}
|
||||
|
||||
const dexMove = this.dex.moves.get(move.id);
|
||||
if (source.terastallized && (source.terastallized === 'Stellar' ?
|
||||
!source.stellarBoostedTypes.includes(move.type) : source.hasType(move.type)) &&
|
||||
basePower < 60 && dexMove.priority <= 0 && !dexMove.multihit &&
|
||||
// Hard move.basePower check for moves like Dragon Energy that have variable BP
|
||||
!((move.basePower === 0 || move.basePower === 150) && move.basePowerCallback)
|
||||
) {
|
||||
basePower = 60;
|
||||
}
|
||||
|
||||
const level = source.level;
|
||||
|
||||
const attacker = move.overrideOffensivePokemon === 'target' ? target : source;
|
||||
const defender = move.overrideDefensivePokemon === 'source' ? source : target;
|
||||
|
||||
const isPhysical = move.category === 'Physical';
|
||||
let attackStat: StatIDExceptHP = move.overrideOffensiveStat || (isPhysical ? 'atk' : 'spa');
|
||||
const defenseStat: StatIDExceptHP = move.overrideDefensiveStat || (isPhysical ? 'def' : 'spd');
|
||||
|
||||
const statTable = { atk: 'Atk', def: 'Def', spa: 'SpA', spd: 'SpD', spe: 'Spe' };
|
||||
|
||||
let atkBoosts = attacker.boosts[attackStat];
|
||||
let defBoosts = defender.boosts[defenseStat];
|
||||
|
||||
let ignoreNegativeOffensive = !!move.ignoreNegativeOffensive;
|
||||
let ignorePositiveDefensive = !!move.ignorePositiveDefensive;
|
||||
|
||||
if (moveHit.crit) {
|
||||
ignoreNegativeOffensive = true;
|
||||
ignorePositiveDefensive = true;
|
||||
}
|
||||
const ignoreOffensive = !!(move.ignoreOffensive || (ignoreNegativeOffensive && atkBoosts < 0));
|
||||
const ignoreDefensive = !!(move.ignoreDefensive || (ignorePositiveDefensive && defBoosts > 0));
|
||||
|
||||
if (ignoreOffensive) {
|
||||
this.battle.debug('Negating (sp)atk boost/penalty.');
|
||||
atkBoosts = 0;
|
||||
}
|
||||
if (ignoreDefensive) {
|
||||
this.battle.debug('Negating (sp)def boost/penalty.');
|
||||
defBoosts = 0;
|
||||
}
|
||||
|
||||
let attack = attacker.calculateStat(attackStat, atkBoosts, 1, source);
|
||||
let defense = defender.calculateStat(defenseStat, defBoosts, 1, target);
|
||||
|
||||
attackStat = (category === 'Physical' ? 'atk' : 'spa');
|
||||
|
||||
// Apply Stat Modifiers
|
||||
attack = this.battle.runEvent('Modify' + statTable[attackStat], source, target, move, attack);
|
||||
defense = this.battle.runEvent('Modify' + statTable[defenseStat], target, source, move, defense);
|
||||
|
||||
if (this.battle.gen <= 4 && ['explosion', 'selfdestruct'].includes(move.id) && defenseStat === 'def') {
|
||||
defense = this.battle.clampIntRange(Math.floor(defense / 2), 1);
|
||||
}
|
||||
|
||||
const tr = this.battle.trunc;
|
||||
|
||||
// int(int(int(2 * L / 5 + 2) * A * P / D) / 50);
|
||||
const baseDamage = tr(tr(tr(tr(2 * level / 5 + 2) * basePower * attack) / defense) / 50);
|
||||
|
||||
// Calculate damage modifiers separately (order differs between generations)
|
||||
return this.modifyDamage(baseDamage, source, target, move, suppressMessages);
|
||||
},
|
||||
},
|
||||
};
|
||||
1052
data/mods/afd/sets.json
Normal file
1052
data/mods/afd/sets.json
Normal file
File diff suppressed because it is too large
Load Diff
49
data/mods/afd/typechart.ts
Normal file
49
data/mods/afd/typechart.ts
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
export const TypeChart: import('../../../sim/dex-data').ModdedTypeDataTable = {
|
||||
fairy: {
|
||||
damageTaken: {
|
||||
Bug: 2,
|
||||
Dark: 2,
|
||||
Dragon: 3,
|
||||
Electric: 0,
|
||||
Fairy: 0,
|
||||
Fighting: 2,
|
||||
Fire: 0,
|
||||
Flying: 0,
|
||||
Ghost: 0,
|
||||
Grass: 0,
|
||||
Ground: 0,
|
||||
Ice: 0,
|
||||
Normal: 1,
|
||||
Poison: 1,
|
||||
Psychic: 0,
|
||||
Rock: 0,
|
||||
Steel: 1,
|
||||
Stellar: 0,
|
||||
Water: 0,
|
||||
},
|
||||
},
|
||||
ghost: {
|
||||
inherit: true,
|
||||
damageTaken: {
|
||||
Bug: 3,
|
||||
Dark: 1,
|
||||
Dragon: 1,
|
||||
Electric: 1,
|
||||
Fairy: 3,
|
||||
Fighting: 3,
|
||||
Fire: 1,
|
||||
Flying: 3,
|
||||
Ghost: 3,
|
||||
Grass: 1,
|
||||
Ground: 3,
|
||||
Ice: 1,
|
||||
Normal: 3,
|
||||
Poison: 3,
|
||||
Psychic: 1,
|
||||
Rock: 3,
|
||||
Steel: 3,
|
||||
Stellar: 0,
|
||||
Water: 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -185,17 +185,20 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
(pokemon.m.scrambled.abilities as { thing: string, inSlot: string }[]).findIndex(e =>
|
||||
this.toID(e.thing) === 'trace' && e.inSlot === 'Move'), 1);
|
||||
this.add('-ability', pokemon, move.name, 'Trace');
|
||||
const ppUps = move.noPPBoosts ? 0 : 3;
|
||||
const basePP = this.calculatePP(move, ppUps);
|
||||
const newMove = {
|
||||
move: move.name,
|
||||
id: move.id,
|
||||
pp: move.noPPBoosts ? move.pp : move.pp * 8 / 5,
|
||||
maxpp: move.noPPBoosts ? move.pp : move.pp * 8 / 5,
|
||||
pp: basePP,
|
||||
maxpp: basePP,
|
||||
target: move.target,
|
||||
disabled: false,
|
||||
used: false,
|
||||
};
|
||||
pokemon.baseMoveSlots.push(newMove);
|
||||
pokemon.moveSlots.push(newMove);
|
||||
pokemon.ppUps.push(ppUps);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -223,6 +223,24 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
skillswap: {
|
||||
inherit: true,
|
||||
onTryHit(target, source) {
|
||||
const targetAbility = target.getAbility();
|
||||
const sourceAbility = source.getAbility();
|
||||
if (sourceAbility.flags['failskillswap'] || targetAbility.flags['failskillswap'] || target.volatiles['dynamax']) {
|
||||
return false;
|
||||
}
|
||||
let sourceCanBeSet = this.runEvent('SetAbility', source, source, this.effect, targetAbility);
|
||||
if (!this.dex.abilities.get(sourceAbility).exists && this.dex.items.get(sourceAbility.id).exists) {
|
||||
sourceCanBeSet = this.runEvent('TakeItem', source, source, this.effect, this.dex.items.get(sourceAbility.id));
|
||||
}
|
||||
|
||||
if (!sourceCanBeSet) return sourceCanBeSet;
|
||||
let targetCanBeSet = this.runEvent('SetAbility', target, source, this.effect, sourceAbility);
|
||||
if (!this.dex.abilities.get(targetAbility).exists && this.dex.items.get(targetAbility.id).exists) {
|
||||
targetCanBeSet = this.runEvent('TakeItem', target, source, this.effect, this.dex.items.get(targetAbility.id));
|
||||
}
|
||||
if (!targetCanBeSet) return targetCanBeSet;
|
||||
},
|
||||
onHit(target, source, move) {
|
||||
const targetAbility = target.getAbility();
|
||||
const sourceAbility = source.getAbility();
|
||||
|
|
@ -280,17 +298,20 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
} else {
|
||||
source.m.scrambled.moves.push({ thing: targetAbility.id, inSlot: 'Ability' });
|
||||
const bmmMove = Dex.moves.get(targetAbility.id);
|
||||
const ppUps = move.noPPBoosts ? 0 : 3;
|
||||
const basePP = this.calculatePP(move, ppUps);
|
||||
const newMove = {
|
||||
move: bmmMove.name,
|
||||
id: bmmMove.id,
|
||||
pp: bmmMove.noPPBoosts ? bmmMove.pp : bmmMove.pp * 8 / 5,
|
||||
maxpp: bmmMove.noPPBoosts ? bmmMove.pp : bmmMove.pp * 8 / 5,
|
||||
pp: basePP,
|
||||
maxpp: basePP,
|
||||
target: bmmMove.target,
|
||||
disabled: false,
|
||||
used: false,
|
||||
};
|
||||
source.baseMoveSlots.push(newMove);
|
||||
source.moveSlots.push(newMove);
|
||||
source.ppUps.push(ppUps);
|
||||
}
|
||||
}
|
||||
this.singleEvent('Start', sourceAbility, target.abilityState, target);
|
||||
|
|
@ -303,17 +324,20 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
} else {
|
||||
target.m.scrambled.moves.push({ thing: sourceAbility.id, inSlot: 'Ability' });
|
||||
const bmmMove = Dex.moves.get(sourceAbility.id);
|
||||
const ppUps = move.noPPBoosts ? 0 : 3;
|
||||
const basePP = this.calculatePP(move, ppUps);
|
||||
const newMove = {
|
||||
move: bmmMove.name,
|
||||
id: bmmMove.id,
|
||||
pp: bmmMove.noPPBoosts ? bmmMove.pp : bmmMove.pp * 8 / 5,
|
||||
maxpp: bmmMove.noPPBoosts ? bmmMove.pp : bmmMove.pp * 8 / 5,
|
||||
pp: basePP,
|
||||
maxpp: basePP,
|
||||
target: bmmMove.target,
|
||||
disabled: false,
|
||||
used: false,
|
||||
};
|
||||
target.baseMoveSlots.push(newMove);
|
||||
target.moveSlots.push(newMove);
|
||||
target.ppUps.push(ppUps);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -63,10 +63,16 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
);
|
||||
},
|
||||
setAbility(ability, source, sourceEffect, isFromFormeChange = false, isTransform = false) {
|
||||
const allThings = new Set([
|
||||
...(this.m.scrambled.abilities as { thing: string }[]).map(e => e.thing),
|
||||
...(this.m.scrambled.items as { thing: string }[]).map(e => e.thing),
|
||||
...(this.m.scrambled.moves as { thing: string }[]).map(e => e.thing),
|
||||
this.ability, ...this.moveSlots.map(e => e.move), this.item,
|
||||
].map(this.battle.toID));
|
||||
|
||||
let isBMMAbil = false;
|
||||
let isOldBMMAbil = false;
|
||||
if (!this.hp) return false;
|
||||
if (!this.battle.dex.abilities.get(ability).exists) isBMMAbil = true;
|
||||
if (typeof ability === 'string') {
|
||||
if (this.battle.dex.abilities.get(ability).exists) {
|
||||
ability = this.battle.dex.abilities.get(ability);
|
||||
|
|
@ -85,13 +91,18 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
} as Ability;
|
||||
}
|
||||
}
|
||||
if (ability.name.length && !this.battle.dex.abilities.get(ability).exists) isBMMAbil = true;
|
||||
if (!sourceEffect && this.battle.effect) sourceEffect = this.battle.effect;
|
||||
let oldAbility;
|
||||
if (this.battle.dex.abilities.get(this.ability).exists) {
|
||||
oldAbility = this.battle.dex.abilities.get(this.ability);
|
||||
} else {
|
||||
let abil = this.battle.dex.items.getByID(this.ability) as Item | Move;
|
||||
if (!abil.exists) abil = this.battle.dex.moves.getByID(this.ability);
|
||||
if (!abil.exists) {
|
||||
abil = this.battle.dex.moves.getByID(this.ability);
|
||||
} else {
|
||||
if (!this.battle.runEvent('TakeItem', this, source, null, abil as Item)) return false;
|
||||
}
|
||||
oldAbility = {
|
||||
id: this.ability,
|
||||
name: abil.name || this.ability,
|
||||
|
|
@ -103,6 +114,9 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
} as Ability;
|
||||
isOldBMMAbil = true;
|
||||
}
|
||||
|
||||
if (allThings.has(ability.id)) return false;
|
||||
|
||||
if (!isFromFormeChange) {
|
||||
if (ability.flags['cantsuppress'] || this.getAbility().flags['cantsuppress']) return false;
|
||||
}
|
||||
|
|
@ -153,11 +167,13 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
} else {
|
||||
this.m.scrambled.moves.push({ thing: ability.id, inSlot: 'Ability' });
|
||||
const move = Dex.moves.get(ability.id);
|
||||
const ppUps = move.noPPBoosts ? 0 : 3;
|
||||
const basePP = this.battle.calculatePP(move, ppUps);
|
||||
const newMove = {
|
||||
move: move.name,
|
||||
id: move.id,
|
||||
pp: move.noPPBoosts ? move.pp : move.pp * 8 / 5,
|
||||
maxpp: move.noPPBoosts ? move.pp : move.pp * 8 / 5,
|
||||
pp: basePP,
|
||||
maxpp: basePP,
|
||||
target: move.target,
|
||||
disabled: false,
|
||||
used: false,
|
||||
|
|
@ -165,6 +181,7 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
if (!isTransform) {
|
||||
this.baseMoveSlots.push(newMove);
|
||||
this.moveSlots.push(newMove);
|
||||
this.ppUps.push(ppUps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -195,14 +212,22 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
if (!source) source = this;
|
||||
if (this.battle.gen <= 4) {
|
||||
if (source.itemKnockedOff) return false;
|
||||
if (this.battle.toID(this.ability) === 'multitype') return false;
|
||||
if (this.battle.toID(source.ability) === 'multitype') return false;
|
||||
if (this.battle.toID(this.ability) === 'multitype' || (this.m.scrambled.abilities as { thing: string }[])
|
||||
.findIndex(e => this.battle.toID(e.thing) === 'multitype') >= 0) {
|
||||
return false;
|
||||
}
|
||||
if (this.battle.toID(source.ability) === 'multitype' || (source.m.scrambled.abilities as { thing: string }[])
|
||||
.findIndex(e => this.battle.toID(e.thing) === 'multitype') >= 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const item = this.getItem();
|
||||
if (this.battle.runEvent('TakeItem', this, source, null, item)) {
|
||||
this.item = '';
|
||||
let wrongSlot = (this.m.scrambled.abilities as { inSlot: string }[]).findIndex(e => e.inSlot === 'Item');
|
||||
if (wrongSlot >= 0) {
|
||||
const dexAbil = this.battle.dex.abilities.get(this.m.scrambled.abilities[wrongSlot].thing);
|
||||
if (dexAbil.flags['failskillswap']) return false;
|
||||
this.removeVolatile('ability:' + this.battle.toID(this.m.scrambled.abilities[wrongSlot].thing));
|
||||
this.m.scrambled.abilities.splice(wrongSlot, 1);
|
||||
} else if ((this.m.scrambled.moves as { inSlot: string }[]).findIndex(e => e.inSlot === 'Item') >= 0) {
|
||||
|
|
@ -225,17 +250,27 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
return false;
|
||||
},
|
||||
setItem(item, source, effect) {
|
||||
const allThings = new Set([
|
||||
...(this.m.scrambled.abilities as { thing: string }[]).map(e => e.thing),
|
||||
...(this.m.scrambled.items as { thing: string }[]).map(e => e.thing),
|
||||
...(this.m.scrambled.moves as { thing: string }[]).map(e => e.thing),
|
||||
this.ability, ...this.moveSlots.map(e => e.move), this.item,
|
||||
].map(this.battle.toID));
|
||||
|
||||
let isBMMItem = false;
|
||||
let isOldBMMItem = false;
|
||||
if (!this.hp || !this.isActive) return false;
|
||||
if (!this.battle.dex.items.get(item).exists) isBMMItem = true;
|
||||
if (typeof item === 'string') {
|
||||
if (this.battle.dex.items.get(item).exists) {
|
||||
if (!item.length || this.battle.dex.items.get(item).exists) {
|
||||
item = this.battle.dex.items.get(item);
|
||||
} else {
|
||||
const itemString = item;
|
||||
let newData = this.battle.dex.abilities.get(itemString) as Ability | Move;
|
||||
if (!newData.exists) newData = this.battle.dex.moves.get(itemString);
|
||||
if (!newData.exists) {
|
||||
newData = this.battle.dex.moves.get(itemString);
|
||||
} else {
|
||||
if ((newData as Ability).flags['failskillswap']) return false;
|
||||
}
|
||||
item = {
|
||||
id: newData.id || itemString,
|
||||
name: newData.name || itemString,
|
||||
|
|
@ -246,6 +281,8 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
} as Item;
|
||||
}
|
||||
}
|
||||
if (item.name.length && !this.battle.dex.items.get(item).exists) isBMMItem = true;
|
||||
if (allThings.has(item.id)) return false;
|
||||
const effectid = this.battle.effect ? this.battle.effect.id : '';
|
||||
if (RESTORATIVE_BERRIES.has('leppaberry' as ID)) {
|
||||
const inflicted = ['trick', 'switcheroo'].includes(effectid);
|
||||
|
|
@ -288,17 +325,20 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
} else {
|
||||
this.m.scrambled.moves.push({ thing: item.id, inSlot: 'Item' });
|
||||
const move = Dex.moves.get(item.id);
|
||||
const ppUps = move.noPPBoosts ? 0 : 3;
|
||||
const basePP = this.battle.calculatePP(move, ppUps);
|
||||
const newMove = {
|
||||
move: move.name,
|
||||
id: move.id,
|
||||
pp: move.noPPBoosts ? move.pp : move.pp * 8 / 5,
|
||||
maxpp: move.noPPBoosts ? move.pp : move.pp * 8 / 5,
|
||||
pp: basePP,
|
||||
maxpp: basePP,
|
||||
target: move.target,
|
||||
disabled: false,
|
||||
used: false,
|
||||
};
|
||||
this.baseMoveSlots.push(newMove);
|
||||
this.moveSlots.push(newMove);
|
||||
this.ppUps.push(ppUps);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
@ -340,9 +380,11 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
|
||||
const isBMM = this.volatiles[item.id]?.inSlot;
|
||||
if (isBMM) {
|
||||
const dexItem = this.battle.dex.items.get(item.name);
|
||||
this.removeVolatile(item.id);
|
||||
this.m.scrambled.items.splice((this.m.scrambled.items as { thing: string, inSlot: string }[]).findIndex(e =>
|
||||
e.thing === this.battle.toID(item.name) && e.inSlot === isBMM), 1);
|
||||
const itemIndex = (this.m.scrambled.items as { thing: string, inSlot: string }[]).findIndex(e =>
|
||||
this.battle.toID(e.thing) === dexItem.id && e.inSlot === isBMM);
|
||||
if (itemIndex >= 0) this.m.scrambled.items.splice(itemIndex, 1);
|
||||
if (isBMM === 'Ability') this.setAbility('No Ability');
|
||||
} else {
|
||||
this.lastItem = this.item;
|
||||
|
|
@ -391,9 +433,11 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
|
||||
const isBMM = this.volatiles[item.id]?.inSlot;
|
||||
if (isBMM) {
|
||||
const dexItem = this.battle.dex.items.get(item.name);
|
||||
this.removeVolatile(item.id);
|
||||
this.m.scrambled.items.splice((this.m.scrambled.items as { thing: string, inSlot: string }[]).findIndex(e =>
|
||||
e.thing === this.battle.toID(item.name) && e.inSlot === isBMM), 1);
|
||||
const itemIndex = (this.m.scrambled.items as { thing: string, inSlot: string }[]).findIndex(e =>
|
||||
this.battle.toID(e.thing) === dexItem.id && e.inSlot === isBMM);
|
||||
if (itemIndex >= 0) this.m.scrambled.items.splice(itemIndex, 1);
|
||||
if (isBMM === 'Ability') this.setAbility('No Ability');
|
||||
} else {
|
||||
this.lastItem = this.item;
|
||||
|
|
@ -445,16 +489,17 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
this.hpType = (this.battle.gen >= 5 ? this.hpType : pokemon.hpType);
|
||||
this.hpPower = (this.battle.gen >= 5 ? this.hpPower : pokemon.hpPower);
|
||||
this.timesAttacked = pokemon.timesAttacked;
|
||||
for (const moveSlot of pokemon.moveSlots) {
|
||||
for (const [i, moveSlot] of pokemon.moveSlots.entries()) {
|
||||
let moveName = moveSlot.move;
|
||||
if (moveSlot.id === 'hiddenpower') {
|
||||
moveName = 'Hidden Power ' + this.hpType;
|
||||
}
|
||||
const move = this.battle.dex.moves.get(moveSlot.id);
|
||||
this.moveSlots.push({
|
||||
move: moveName,
|
||||
id: moveSlot.id,
|
||||
pp: moveSlot.maxpp === 1 ? 1 : 5,
|
||||
maxpp: this.battle.gen >= 5 ? (moveSlot.maxpp === 1 ? 1 : 5) : moveSlot.maxpp,
|
||||
pp: Math.min(5, move.pp),
|
||||
maxpp: this.battle.gen >= 5 ? Math.min(5, move.pp) : moveSlot.maxpp,
|
||||
target: moveSlot.target,
|
||||
disabled: false,
|
||||
used: false,
|
||||
|
|
|
|||
66
data/mods/champions/abilities.ts
Normal file
66
data/mods/champions/abilities.ts
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTable = {
|
||||
angershell: {
|
||||
inherit: true,
|
||||
onDamage(damage, target, source, effect) {
|
||||
this.effectState.checkedAngerShell = !(effect.effectType === "Move" && !effect.multihit);
|
||||
},
|
||||
},
|
||||
berserk: {
|
||||
inherit: true,
|
||||
onDamage(damage, target, source, effect) {
|
||||
this.effectState.checkedBerserk = !(effect.effectType === "Move" && !effect.multihit);
|
||||
},
|
||||
},
|
||||
dragonize: {
|
||||
inherit: true,
|
||||
isNonstandard: null,
|
||||
},
|
||||
healer: {
|
||||
inherit: true,
|
||||
onResidual(pokemon) {
|
||||
for (const allyActive of pokemon.adjacentAllies()) {
|
||||
if (allyActive.status && this.randomChance(1, 2)) {
|
||||
this.add('-activate', pokemon, 'ability: Healer');
|
||||
allyActive.cureStatus();
|
||||
}
|
||||
}
|
||||
},
|
||||
desc: "50% chance this Pokemon's ally has its non-volatile status condition cured at the end of each turn.",
|
||||
shortDesc: "50% chance this Pokemon's ally has its status cured at the end of each turn.",
|
||||
},
|
||||
megasol: {
|
||||
inherit: true,
|
||||
isNonstandard: null,
|
||||
},
|
||||
piercingdrill: {
|
||||
inherit: true,
|
||||
isNonstandard: null,
|
||||
},
|
||||
shedskin: {
|
||||
inherit: true,
|
||||
onResidual(pokemon) {
|
||||
if (pokemon.hp && pokemon.status && this.randomChance(3, 10)) {
|
||||
this.debug('shed skin');
|
||||
this.add('-activate', pokemon, 'ability: Shed Skin');
|
||||
pokemon.cureStatus();
|
||||
}
|
||||
},
|
||||
desc: "This Pokemon has a 30% chance to have its non-volatile status condition cured at the end of each turn.",
|
||||
shortDesc: "This Pokemon has a 30% chance to have its status cured at the end of each turn.",
|
||||
},
|
||||
spicyspray: {
|
||||
inherit: true,
|
||||
isNonstandard: null,
|
||||
},
|
||||
unseenfist: {
|
||||
onModifyMove: undefined, // no inherit
|
||||
onHitProtect(source, target, move) {
|
||||
if (move.flags['contact']) {
|
||||
target.getMoveHitData(move).bypassProtect = this.effect;
|
||||
return false;
|
||||
}
|
||||
},
|
||||
inherit: true,
|
||||
shortDesc: "This Pokemon's contact moves ignore a target's protection and deal 1/4 the usual damage.",
|
||||
},
|
||||
};
|
||||
136
data/mods/champions/conditions.ts
Normal file
136
data/mods/champions/conditions.ts
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
export const Conditions: import('../../../sim/dex-conditions').ModdedConditionDataTable = {
|
||||
par: {
|
||||
inherit: true,
|
||||
onBeforeMove(pokemon) {
|
||||
if (this.randomChance(1, 8)) {
|
||||
this.add('cant', pokemon, 'par');
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
slp: {
|
||||
inherit: true,
|
||||
onStart(target, source, sourceEffect) {
|
||||
if (sourceEffect && sourceEffect.effectType === 'Ability') {
|
||||
this.add('-status', target, 'slp', '[from] ability: ' + sourceEffect.name, `[of] ${source}`);
|
||||
} else if (sourceEffect && sourceEffect.effectType === 'Move') {
|
||||
this.add('-status', target, 'slp', `[from] move: ${sourceEffect.name}`);
|
||||
} else {
|
||||
this.add('-status', target, 'slp');
|
||||
}
|
||||
|
||||
// 1/3 chance for a Pokemon to wake up on turn 2
|
||||
this.effectState.startTime = this.sample([2, 3, 3]);
|
||||
this.effectState.time = this.effectState.startTime;
|
||||
|
||||
if (target.removeVolatile('nightmare')) {
|
||||
this.add('-end', target, 'Nightmare', '[silent]');
|
||||
}
|
||||
},
|
||||
},
|
||||
frz: {
|
||||
inherit: true,
|
||||
onStart(target, source, sourceEffect) {
|
||||
if (sourceEffect && sourceEffect.effectType === 'Ability') {
|
||||
this.add('-status', target, 'frz', '[from] ability: ' + sourceEffect.name, `[of] ${source}`);
|
||||
} else {
|
||||
this.add('-status', target, 'frz');
|
||||
}
|
||||
if (target.species.name === 'Shaymin-Sky' && target.baseSpecies.baseSpecies === 'Shaymin') {
|
||||
target.formeChange('Shaymin', this.effect, true);
|
||||
}
|
||||
|
||||
this.effectState.startTime = 3;
|
||||
this.effectState.time = this.effectState.startTime;
|
||||
},
|
||||
onBeforeMove(pokemon, target, move) {
|
||||
if (move.flags['defrost'] && !(move.id === 'burnup' && !pokemon.hasType('Fire'))) return;
|
||||
pokemon.statusState.time--;
|
||||
if (pokemon.statusState.time <= 0 || this.randomChance(1, 4)) {
|
||||
pokemon.cureStatus();
|
||||
return;
|
||||
}
|
||||
this.add('cant', pokemon, 'frz');
|
||||
return false;
|
||||
},
|
||||
},
|
||||
|
||||
raindance: {
|
||||
inherit: true,
|
||||
onWeatherModifyDamage(damage, attacker, defender, move) {
|
||||
if (attacker.effectiveWeather() !== 'raindance') return;
|
||||
if (move.type === 'Water') {
|
||||
this.debug('rain water boost');
|
||||
return this.chainModify(1.5);
|
||||
}
|
||||
if (move.type === 'Fire') {
|
||||
this.debug('rain fire suppress');
|
||||
return this.chainModify(0.5);
|
||||
}
|
||||
},
|
||||
},
|
||||
primordialsea: {
|
||||
inherit: true,
|
||||
onWeatherModifyDamage(damage, attacker, defender, move) {
|
||||
if (attacker.effectiveWeather() !== 'primordialsea') return;
|
||||
if (move.type === 'Water') {
|
||||
this.debug('Rain water boost');
|
||||
return this.chainModify(1.5);
|
||||
}
|
||||
},
|
||||
},
|
||||
sunnyday: {
|
||||
inherit: true,
|
||||
onWeatherModifyDamage(damage, attacker, defender, move) {
|
||||
if (attacker.effectiveWeather() !== 'sunnyday') return;
|
||||
if (move.id === 'hydrosteam') {
|
||||
this.debug('Sunny Day Hydro Steam boost');
|
||||
return this.chainModify(1.5);
|
||||
}
|
||||
if (move.type === 'Fire') {
|
||||
this.debug('Sunny Day fire boost');
|
||||
return this.chainModify(1.5);
|
||||
}
|
||||
if (move.type === 'Water') {
|
||||
this.debug('Sunny Day water suppress');
|
||||
return this.chainModify(0.5);
|
||||
}
|
||||
},
|
||||
},
|
||||
desolateland: {
|
||||
inherit: true,
|
||||
onWeatherModifyDamage(damage, attacker, defender, move) {
|
||||
if (attacker.effectiveWeather() !== 'desolateland') return;
|
||||
if (move.type === 'Fire') {
|
||||
this.debug('Desolate Land fire boost');
|
||||
return this.chainModify(1.5);
|
||||
}
|
||||
},
|
||||
},
|
||||
sandstorm: {
|
||||
inherit: true,
|
||||
onModifySpD(spd, target, source) {
|
||||
if (target.hasType('Rock') && source.effectiveWeather() === 'sandstorm') {
|
||||
return this.modify(spd, 1.5);
|
||||
}
|
||||
},
|
||||
},
|
||||
snowscape: {
|
||||
inherit: true,
|
||||
onModifyDef(def, target, source) {
|
||||
if (target.hasType('Ice') && source.effectiveWeather() === 'snowscape') {
|
||||
return this.modify(def, 1.5);
|
||||
}
|
||||
},
|
||||
},
|
||||
// TODO: check Mega Sol's interaction with Deltastream
|
||||
// deltastream: {
|
||||
// inherit: true,
|
||||
// onEffectiveness(typeMod, target, type, move) {
|
||||
// if (move && move.effectType === 'Move' && move.category !== 'Status' && type === 'Flying' && typeMod > 0) {
|
||||
// this.add('-fieldactivate', 'Delta Stream');
|
||||
// return 0;
|
||||
// }
|
||||
// },
|
||||
// },
|
||||
};
|
||||
5039
data/mods/champions/formats-data.ts
Normal file
5039
data/mods/champions/formats-data.ts
Normal file
File diff suppressed because it is too large
Load Diff
1053
data/mods/champions/items.ts
Normal file
1053
data/mods/champions/items.ts
Normal file
File diff suppressed because it is too large
Load Diff
13451
data/mods/champions/learnsets.ts
Normal file
13451
data/mods/champions/learnsets.ts
Normal file
File diff suppressed because it is too large
Load Diff
1109
data/mods/champions/moves.ts
Normal file
1109
data/mods/champions/moves.ts
Normal file
File diff suppressed because it is too large
Load Diff
40
data/mods/champions/rulesets.ts
Normal file
40
data/mods/champions/rulesets.ts
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
|
||||
standardag: {
|
||||
inherit: true,
|
||||
ruleset: [
|
||||
'Obtainable', 'Team Preview', 'Cancel Mod', 'Endless Battle Clause',
|
||||
'Adjust Level = 50', 'Species Clause', 'Item Clause = 1',
|
||||
],
|
||||
onBegin() {
|
||||
this.reportPercentages = true;
|
||||
},
|
||||
},
|
||||
standard: {
|
||||
inherit: true,
|
||||
ruleset: [
|
||||
'Standard AG',
|
||||
'Sleep Moves Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Moves Clause',
|
||||
],
|
||||
},
|
||||
standarddraft: {
|
||||
inherit: true,
|
||||
ruleset: [
|
||||
'Standard AG',
|
||||
'Nickname Clause', 'Beat Up Nicknames Mod', 'Sleep Clause Mod', 'OHKO Clause', 'Evasion Clause',
|
||||
'!Item Clause',
|
||||
],
|
||||
onBegin() {
|
||||
this.reportPercentages = true;
|
||||
},
|
||||
// timer: {starting: 60 * 60, grace: 0, addPerTurn: 10, maxPerTurn: 100, timeoutAutoChoose: true},
|
||||
},
|
||||
flatrules: {
|
||||
inherit: true,
|
||||
desc: "The in-game Flat Rules: Adjust Level 50, Species Clause, Item Clause = 1, -Mythical, -Restricted Legendary, Bring 6 Pick 3-6 depending on game type.",
|
||||
ruleset: ['Obtainable', 'Team Preview', 'Species Clause', 'Nickname Clause', 'Item Clause = 1', 'Adjust Level = 50', 'Picked Team Size = Auto', 'Cancel Mod'],
|
||||
banlist: ['Mythical', 'Restricted Legendary'],
|
||||
onBegin() {
|
||||
this.reportPercentages = true;
|
||||
},
|
||||
},
|
||||
};
|
||||
505
data/mods/champions/scripts.ts
Normal file
505
data/mods/champions/scripts.ts
Normal file
|
|
@ -0,0 +1,505 @@
|
|||
export const Scripts: ModdedBattleScriptsData = {
|
||||
gen: 9,
|
||||
init() {
|
||||
for (const i in this.data.Moves) {
|
||||
if (this.data.Moves[i].pp > 20) {
|
||||
this.modData('Moves', i).pp = 20;
|
||||
}
|
||||
}
|
||||
},
|
||||
statModify(baseStats, set, statName) {
|
||||
const tr = this.trunc;
|
||||
let stat = baseStats[statName];
|
||||
const evs = set.evs[statName];
|
||||
if (statName === 'hp') {
|
||||
return stat + evs + 75;
|
||||
}
|
||||
stat = stat + evs + 20;
|
||||
const nature = this.dex.natures.get(set.nature);
|
||||
// Natures are calculated with 16-bit truncation.
|
||||
// This only affects Eternatus-Eternamax in Pure Hackmons.
|
||||
if (nature.plus === statName) {
|
||||
stat = this.ruleTable.has('overflowstatmod') ? Math.min(stat, 595) : stat;
|
||||
stat = tr(tr(stat * 110, 16) / 100);
|
||||
} else if (nature.minus === statName) {
|
||||
stat = this.ruleTable.has('overflowstatmod') ? Math.min(stat, 728) : stat;
|
||||
stat = tr(tr(stat * 90, 16) / 100);
|
||||
}
|
||||
return stat;
|
||||
},
|
||||
calculatePP(move, ppUps) {
|
||||
return move.noPPBoosts ? move.pp : (move.pp / 5 + 1) * 4;
|
||||
},
|
||||
pokemon: {
|
||||
// Remove Trick Room underflow
|
||||
getActionSpeed() {
|
||||
let speed = this.getStat('spe', false, false);
|
||||
const trickRoomCheck = this.battle.ruleTable.has('twisteddimensionmod') ?
|
||||
!this.battle.field.getPseudoWeather('trickroom') : this.battle.field.getPseudoWeather('trickroom');
|
||||
if (trickRoomCheck) {
|
||||
speed = -speed;
|
||||
}
|
||||
return speed;
|
||||
},
|
||||
// Don't revert Mega Evolutions after fainting
|
||||
// TODO: confirm interaction with Revival Blessing
|
||||
formeChange(speciesId, source, isPermanent, abilitySlot = '0', message) {
|
||||
const rawSpecies = this.battle.dex.species.get(speciesId);
|
||||
|
||||
const species = this.setSpecies(rawSpecies, source);
|
||||
if (!species) return false;
|
||||
|
||||
if (this.battle.gen <= 2) return true;
|
||||
|
||||
// The species the opponent sees
|
||||
const apparentSpecies =
|
||||
this.illusion ? this.illusion.species.name : species.baseSpecies;
|
||||
if (isPermanent) {
|
||||
this.baseSpecies = rawSpecies;
|
||||
this.details = this.getUpdatedDetails();
|
||||
let details = (this.illusion || this).details;
|
||||
if (this.terastallized) details += `, tera:${this.terastallized}`;
|
||||
this.battle.add('detailschange', this, details);
|
||||
this.updateMaxHp();
|
||||
if (!source) {
|
||||
// Tera forme
|
||||
// Ogerpon/Terapagos text goes here
|
||||
this.formeRegression = true;
|
||||
} else if (source.effectType === 'Item') {
|
||||
this.canTerastallize = null; // National Dex behavior
|
||||
if (source.zMove) {
|
||||
this.battle.add('-burst', this, apparentSpecies, species.requiredItem);
|
||||
this.moveThisTurnResult = true; // Ultra Burst counts as an action for Truant
|
||||
} else if (source.isPrimalOrb) {
|
||||
if (this.illusion) {
|
||||
this.ability = '';
|
||||
this.battle.add('-primal', this.illusion, species.requiredItem);
|
||||
} else {
|
||||
this.battle.add('-primal', this, species.requiredItem);
|
||||
}
|
||||
} else {
|
||||
this.battle.add('-mega', this, apparentSpecies, species.requiredItem);
|
||||
this.moveThisTurnResult = true; // Mega Evolution counts as an action for Truant
|
||||
}
|
||||
} else if (source.effectType === 'Status') {
|
||||
// Shaymin-Sky -> Shaymin
|
||||
this.battle.add('-formechange', this, species.name, message);
|
||||
}
|
||||
} else {
|
||||
if (source?.effectType === 'Ability') {
|
||||
this.battle.add('-formechange', this, species.name, message, `[from] ability: ${source.name}`);
|
||||
} else {
|
||||
this.battle.add('-formechange', this, this.illusion ? this.illusion.species.name : species.name, message);
|
||||
}
|
||||
}
|
||||
if (isPermanent && (!source || !['disguise', 'iceface'].includes(source.id))) {
|
||||
if (this.illusion && source) {
|
||||
// Tera forme by Ogerpon or Terapagos breaks the Illusion
|
||||
this.ability = ''; // Don't allow Illusion to wear off
|
||||
}
|
||||
const ability = species.abilities[abilitySlot] || species.abilities['0'];
|
||||
// Ogerpon's forme change doesn't override permanent abilities
|
||||
if (source || !this.getAbility().flags['cantsuppress']) this.setAbility(ability, null, null, true);
|
||||
// However, its ability does reset upon switching out
|
||||
this.baseAbility = this.battle.toID(ability);
|
||||
}
|
||||
if (this.terastallized) {
|
||||
this.knownType = true;
|
||||
this.apparentType = this.terastallized;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
// Announce status immunities from abilities without revealing the ability
|
||||
// TODO: check if this happens to other abilities besides Spicy Spray (Static, Poison Touch, etc.)
|
||||
setStatus(status, source, sourceEffect, ignoreImmunities) {
|
||||
if (!this.hp) return false;
|
||||
status = this.battle.dex.conditions.get(status);
|
||||
if (this.battle.event) {
|
||||
if (!source) source = this.battle.event.source;
|
||||
if (!sourceEffect) sourceEffect = this.battle.effect;
|
||||
}
|
||||
if (!source) source = this;
|
||||
|
||||
if (this.status === status.id) {
|
||||
if ((sourceEffect as Move)?.status === this.status) {
|
||||
this.battle.add('-fail', this, this.status);
|
||||
} else if ((sourceEffect as Move)?.status) {
|
||||
this.battle.add('-fail', source);
|
||||
this.battle.attrLastMove('[still]');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
!ignoreImmunities && status.id && !(source?.hasAbility('corrosion') && ['tox', 'psn'].includes(status.id))
|
||||
) {
|
||||
// the game currently never ignores immunities
|
||||
if (!this.runStatusImmunity(status.id === 'tox' ? 'psn' : status.id)) {
|
||||
this.battle.debug('immune to status');
|
||||
if ((sourceEffect as Move)?.status || sourceEffect?.effectType === 'Ability') {
|
||||
this.battle.add('-immune', this);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const prevStatus = this.status;
|
||||
const prevStatusState = this.statusState;
|
||||
if (status.id) {
|
||||
const result: boolean = this.battle.runEvent('SetStatus', this, source, sourceEffect, status);
|
||||
if (!result) {
|
||||
this.battle.debug('set status [' + status.id + '] interrupted');
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
this.status = status.id;
|
||||
this.statusState = this.battle.initEffectState({ id: status.id, target: this });
|
||||
if (source) this.statusState.source = source;
|
||||
if (status.duration) this.statusState.duration = status.duration;
|
||||
if (status.durationCallback) {
|
||||
this.statusState.duration = status.durationCallback.call(this.battle, this, source, sourceEffect);
|
||||
}
|
||||
|
||||
if (status.id && !this.battle.singleEvent('Start', status, this.statusState, this, source, sourceEffect)) {
|
||||
this.battle.debug('status start [' + status.id + '] interrupted');
|
||||
// cancel the setstatus
|
||||
this.status = prevStatus;
|
||||
this.statusState = prevStatusState;
|
||||
return false;
|
||||
}
|
||||
if (status.id && !this.battle.runEvent('AfterSetStatus', this, source, sourceEffect, status)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
// Disable Fake Out if the user has already acted since switching in
|
||||
getMoves(lockedMove, restrictData) {
|
||||
if (lockedMove) {
|
||||
lockedMove = this.battle.toID(lockedMove);
|
||||
if (lockedMove === 'recharge') {
|
||||
return [{
|
||||
move: 'Recharge',
|
||||
id: 'recharge' as ID,
|
||||
}];
|
||||
}
|
||||
for (const moveSlot of this.moveSlots) {
|
||||
if (moveSlot.id !== lockedMove) continue;
|
||||
return [{
|
||||
move: moveSlot.move,
|
||||
id: moveSlot.id,
|
||||
}];
|
||||
}
|
||||
// does this happen?
|
||||
return [{
|
||||
move: this.battle.dex.moves.get(lockedMove).name,
|
||||
id: lockedMove,
|
||||
}];
|
||||
}
|
||||
const moves = [];
|
||||
let hasValidMove = false;
|
||||
for (const moveSlot of this.moveSlots) {
|
||||
let moveName = moveSlot.move;
|
||||
if (moveSlot.id === 'hiddenpower') {
|
||||
moveName = `Hidden Power ${this.hpType}`;
|
||||
if (this.battle.gen < 6) moveName += ` ${this.hpPower}`;
|
||||
} else if (moveSlot.id === 'return' || moveSlot.id === 'frustration') {
|
||||
const basePowerCallback = this.battle.dex.moves.get(moveSlot.id).basePowerCallback as (pokemon: Pokemon) => number;
|
||||
moveName += ` ${basePowerCallback(this)}`;
|
||||
}
|
||||
let target = moveSlot.target;
|
||||
switch (moveSlot.id) {
|
||||
case 'curse':
|
||||
if (!this.hasType('Ghost')) {
|
||||
target = this.battle.dex.moves.get('curse').nonGhostTarget;
|
||||
}
|
||||
break;
|
||||
case 'pollenpuff':
|
||||
// Heal Block only prevents Pollen Puff from targeting an ally when the user has Heal Block
|
||||
if (this.volatiles['healblock']) {
|
||||
target = 'adjacentFoe';
|
||||
}
|
||||
break;
|
||||
case 'terastarstorm':
|
||||
if (this.species.name === 'Terapagos-Stellar') {
|
||||
target = 'allAdjacentFoes';
|
||||
}
|
||||
break;
|
||||
}
|
||||
let disabled = moveSlot.disabled;
|
||||
if (this.volatiles['dynamax']) {
|
||||
// if each of a Pokemon's base moves are disabled by one of these effects, it will Struggle
|
||||
const canCauseStruggle = ['Encore', 'Disable', 'Taunt', 'Assault Vest', 'Belch', 'Stuff Cheeks'];
|
||||
disabled = this.maxMoveDisabled(moveSlot.id) || disabled && canCauseStruggle.includes(moveSlot.disabledSource!);
|
||||
} else if (moveSlot.pp <= 0 || (moveSlot.id === 'fakeout' && this.activeMoveActions > 0)) {
|
||||
disabled = true;
|
||||
}
|
||||
|
||||
if (disabled === 'hidden') {
|
||||
disabled = !restrictData;
|
||||
}
|
||||
if (!disabled) {
|
||||
hasValidMove = true;
|
||||
}
|
||||
|
||||
moves.push({
|
||||
move: moveName,
|
||||
id: moveSlot.id,
|
||||
pp: moveSlot.pp,
|
||||
maxpp: moveSlot.maxpp,
|
||||
target,
|
||||
disabled,
|
||||
});
|
||||
}
|
||||
return hasValidMove ? moves : [];
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
canTerastallize(pokemon) {
|
||||
return null;
|
||||
},
|
||||
canMegaEvo(pokemon: Pokemon) {
|
||||
const species = pokemon.baseSpecies;
|
||||
const altForme = species.otherFormes && this.dex.species.get(species.otherFormes[0]);
|
||||
const item = pokemon.getItem();
|
||||
// Mega Rayquaza
|
||||
if ((this.battle.gen <= 7 || this.battle.ruleTable.has('+pokemontag:past') ||
|
||||
this.battle.ruleTable.has('+pokemontag:future')) &&
|
||||
altForme?.isMega && altForme?.requiredMove &&
|
||||
pokemon.baseMoves.includes(toID(altForme.requiredMove)) && !item.zMove) {
|
||||
return altForme.name;
|
||||
}
|
||||
return item.megaStone?.[species.name] || null;
|
||||
},
|
||||
// Announce 4x and 0.25x effectiveness
|
||||
modifyDamage(baseDamage, pokemon, target, move, suppressMessages) {
|
||||
const tr = this.battle.trunc;
|
||||
if (!move.type) move.type = '???';
|
||||
const type = move.type;
|
||||
|
||||
baseDamage += 2;
|
||||
|
||||
if (move.spreadHit) {
|
||||
// multi-target modifier (doubles only)
|
||||
const spreadModifier = this.battle.gameType === 'freeforall' ? 0.5 : 0.75;
|
||||
this.battle.debug(`Spread modifier: ${spreadModifier}`);
|
||||
baseDamage = this.battle.modify(baseDamage, spreadModifier);
|
||||
} else if (move.multihitType === 'parentalbond' && move.hit > 1) {
|
||||
// Parental Bond modifier
|
||||
const bondModifier = this.battle.gen > 6 ? 0.25 : 0.5;
|
||||
this.battle.debug(`Parental Bond modifier: ${bondModifier}`);
|
||||
baseDamage = this.battle.modify(baseDamage, bondModifier);
|
||||
}
|
||||
|
||||
// weather modifier
|
||||
baseDamage = this.battle.runEvent('WeatherModifyDamage', pokemon, target, move, baseDamage);
|
||||
|
||||
// crit - not a modifier
|
||||
const isCrit = target.getMoveHitData(move).crit;
|
||||
if (isCrit) {
|
||||
baseDamage = tr(baseDamage * (move.critModifier || (this.battle.gen >= 6 ? 1.5 : 2)));
|
||||
}
|
||||
|
||||
// random factor - also not a modifier
|
||||
baseDamage = this.battle.randomizer(baseDamage);
|
||||
|
||||
// STAB
|
||||
// The "???" type never gets STAB
|
||||
// Not even if you Roost in Gen 4 and somehow manage to use
|
||||
// Struggle in the same turn.
|
||||
// (On second thought, it might be easier to get a MissingNo.)
|
||||
if (type !== '???') {
|
||||
let stab: number | [number, number] = 1;
|
||||
|
||||
const isSTAB = move.forceSTAB || pokemon.hasType(type) || pokemon.getTypes(false, true).includes(type);
|
||||
if (isSTAB) {
|
||||
stab = 1.5;
|
||||
}
|
||||
|
||||
// The Stellar tera type makes this incredibly confusing
|
||||
// If the move's type does not match one of the user's base types,
|
||||
// the Stellar tera type applies a one-time 1.2x damage boost for that type.
|
||||
//
|
||||
// If the move's type does match one of the user's base types,
|
||||
// then the Stellar tera type applies a one-time 2x STAB boost for that type,
|
||||
// and then goes back to using the regular 1.5x STAB boost for those types.
|
||||
if (pokemon.terastallized === 'Stellar') {
|
||||
if (!pokemon.stellarBoostedTypes.includes(type) || move.stellarBoosted) {
|
||||
stab = isSTAB ? 2 : [4915, 4096];
|
||||
move.stellarBoosted = true;
|
||||
if (pokemon.species.name !== 'Terapagos-Stellar') {
|
||||
pokemon.stellarBoostedTypes.push(type);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (pokemon.terastallized === type && pokemon.getTypes(false, true).includes(type)) {
|
||||
stab = 2;
|
||||
}
|
||||
stab = this.battle.runEvent('ModifySTAB', pokemon, target, move, stab);
|
||||
}
|
||||
|
||||
baseDamage = this.battle.modify(baseDamage, stab);
|
||||
}
|
||||
|
||||
// types
|
||||
let typeMod = target.runEffectiveness(move);
|
||||
typeMod = this.battle.clampIntRange(typeMod, -6, 6);
|
||||
target.getMoveHitData(move).typeMod = typeMod;
|
||||
if (typeMod > 0) {
|
||||
if (!suppressMessages) this.battle.add('-supereffective', target, Math.min(typeMod, 2));
|
||||
|
||||
for (let i = 0; i < typeMod; i++) {
|
||||
baseDamage *= 2;
|
||||
}
|
||||
}
|
||||
if (typeMod < 0) {
|
||||
if (!suppressMessages) this.battle.add('-resisted', target, Math.min(-typeMod, 2));
|
||||
|
||||
for (let i = 0; i > typeMod; i--) {
|
||||
baseDamage = tr(baseDamage / 2);
|
||||
}
|
||||
}
|
||||
|
||||
if (isCrit && !suppressMessages) this.battle.add('-crit', target);
|
||||
|
||||
if (pokemon.status === 'brn' && move.category === 'Physical' && !pokemon.hasAbility('guts')) {
|
||||
if (this.battle.gen < 6 || move.id !== 'facade') {
|
||||
baseDamage = this.battle.modify(baseDamage, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
// Generation 5, but nothing later, sets damage to 1 before the final damage modifiers
|
||||
if (this.battle.gen === 5 && !baseDamage) baseDamage = 1;
|
||||
|
||||
// Final modifier. Modifiers that modify damage after min damage check, such as Life Orb.
|
||||
baseDamage = this.battle.runEvent('ModifyDamage', pokemon, target, move, baseDamage);
|
||||
|
||||
const bypassProtect = target.getMoveHitData(move).bypassProtect;
|
||||
if (bypassProtect) {
|
||||
baseDamage = this.battle.modify(baseDamage, 0.25);
|
||||
if (bypassProtect !== true && bypassProtect.effectType === 'Ability') {
|
||||
this.battle.add('-ability', pokemon, bypassProtect.name);
|
||||
}
|
||||
this.battle.add('-zbroken', target);
|
||||
}
|
||||
|
||||
// Generation 6-7 moves the check for minimum 1 damage after the final modifier...
|
||||
if (this.battle.gen !== 5 && !baseDamage) return 1;
|
||||
|
||||
// ...but 16-bit truncation happens even later, and can truncate to 0
|
||||
return tr(baseDamage, 16);
|
||||
},
|
||||
// Run `AfterHit` events even if the source fainted
|
||||
spreadMoveHit(targets, pokemon, moveOrMoveName, hitEffect?, isSecondary?, isSelf?) {
|
||||
// Hardcoded for single-target purposes
|
||||
// (no spread moves have any kind of onTryHit handler)
|
||||
const target = targets[0];
|
||||
let damage: (number | boolean | undefined)[] = [];
|
||||
for (const i of targets.keys()) {
|
||||
damage[i] = true;
|
||||
}
|
||||
const move = this.dex.getActiveMove(moveOrMoveName);
|
||||
let hitResult: boolean | number | null = true;
|
||||
let moveData = hitEffect!;
|
||||
if (!moveData) moveData = move;
|
||||
if (!moveData.flags) moveData.flags = {};
|
||||
if (move.target === 'all' && !isSelf) {
|
||||
hitResult = this.battle.singleEvent('TryHitField', moveData, {}, target || null, pokemon, move);
|
||||
} else if ((move.target === 'foeSide' || move.target === 'allySide' || move.target === 'allyTeam') && !isSelf) {
|
||||
hitResult = this.battle.singleEvent('TryHitSide', moveData, {}, target || null, pokemon, move);
|
||||
} else if (target) {
|
||||
hitResult = this.battle.singleEvent('TryHit', moveData, {}, target, pokemon, move);
|
||||
}
|
||||
if (!hitResult) {
|
||||
if (hitResult === false) {
|
||||
this.battle.add('-fail', pokemon);
|
||||
this.battle.attrLastMove('[still]');
|
||||
}
|
||||
return [[false], targets]; // single-target only
|
||||
}
|
||||
|
||||
// 0. check for substitute
|
||||
if (!isSecondary && !isSelf) {
|
||||
if (move.target !== 'all' && move.target !== 'allyTeam' && move.target !== 'allySide' && move.target !== 'foeSide') {
|
||||
damage = this.tryPrimaryHitEvent(damage, targets, pokemon, move, moveData, isSecondary);
|
||||
}
|
||||
}
|
||||
|
||||
for (const i of targets.keys()) {
|
||||
if (damage[i] === this.battle.HIT_SUBSTITUTE) {
|
||||
damage[i] = true;
|
||||
targets[i] = null;
|
||||
}
|
||||
if (targets[i] && isSecondary && !moveData.self) {
|
||||
damage[i] = true;
|
||||
}
|
||||
if (!damage[i]) targets[i] = false;
|
||||
}
|
||||
// 1. call to this.battle.getDamage
|
||||
damage = this.getSpreadDamage(damage, targets, pokemon, move, moveData, isSecondary, isSelf);
|
||||
|
||||
for (const i of targets.keys()) {
|
||||
if (damage[i] === false) targets[i] = false;
|
||||
}
|
||||
|
||||
// 2. call to this.battle.spreadDamage
|
||||
damage = this.battle.spreadDamage(damage, targets, pokemon, move);
|
||||
|
||||
for (const i of targets.keys()) {
|
||||
if (damage[i] === false) targets[i] = false;
|
||||
}
|
||||
|
||||
// 3. onHit event happens here
|
||||
damage = this.runMoveEffects(damage, targets, pokemon, move, moveData, isSecondary, isSelf);
|
||||
|
||||
for (const i of targets.keys()) {
|
||||
if (!damage[i] && damage[i] !== 0) targets[i] = false;
|
||||
}
|
||||
|
||||
// steps 4 and 5 can mess with this.battle.activeTarget, which needs to be preserved for Dancer
|
||||
const activeTarget = this.battle.activeTarget;
|
||||
|
||||
// 4. self drops (start checking for targets[i] === false here)
|
||||
if (moveData.self && !move.selfDropped) this.selfDrops(targets, pokemon, move, moveData, isSecondary);
|
||||
|
||||
// 5. secondary effects
|
||||
if (moveData.secondaries) this.secondaries(targets, pokemon, move, moveData, isSelf);
|
||||
|
||||
this.battle.activeTarget = activeTarget;
|
||||
|
||||
// 6. force switch
|
||||
if (moveData.forceSwitch) damage = this.forceSwitch(damage, targets, pokemon, move);
|
||||
|
||||
for (const i of targets.keys()) {
|
||||
if (!damage[i] && damage[i] !== 0) targets[i] = false;
|
||||
}
|
||||
|
||||
const damagedTargets: Pokemon[] = [];
|
||||
const damagedDamage = [];
|
||||
for (const [i, t] of targets.entries()) {
|
||||
if (typeof damage[i] === 'number' && t) {
|
||||
damagedTargets.push(t);
|
||||
damagedDamage.push(damage[i]);
|
||||
}
|
||||
}
|
||||
const pokemonOriginalHP = pokemon.hp;
|
||||
if (damagedDamage.length && !isSecondary && !isSelf) {
|
||||
if (this.battle.gen >= 5) {
|
||||
this.battle.runEvent('DamagingHit', damagedTargets, pokemon, move, damagedDamage);
|
||||
}
|
||||
if (moveData.onAfterHit) {
|
||||
for (const t of damagedTargets) {
|
||||
this.battle.singleEvent('AfterHit', moveData, {}, t, pokemon, move);
|
||||
}
|
||||
}
|
||||
if (this.battle.gen < 5) {
|
||||
this.battle.runEvent('DamagingHit', damagedTargets, pokemon, move, damagedDamage);
|
||||
}
|
||||
if (pokemon.hp && pokemon.hp <= pokemon.maxhp / 2 && pokemonOriginalHP > pokemon.maxhp / 2) {
|
||||
this.battle.runEvent('EmergencyExit', pokemon);
|
||||
}
|
||||
}
|
||||
|
||||
return [damage, targets];
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -953,4 +953,41 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
},
|
||||
shortDesc: "This Pokemon can poison a Pokemon regardless of its typing and hit them with Poison moves.",
|
||||
},
|
||||
jellobody: {
|
||||
onTryHit(pokemon, target, move) {
|
||||
if (move.selfSwitch) {
|
||||
this.add('-immune', pokemon, '[from] ability: Jello Body');
|
||||
this.heal(target.baseMaxhp / 2);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
onModifyMove(move, source, target) {
|
||||
move.drain = [1, 2];
|
||||
},
|
||||
flags: { breakable: 1 },
|
||||
name: "Jello Body",
|
||||
rating: 5,
|
||||
num: -122,
|
||||
shortDesc: "Immune to pivot moves, heals 50% HP when hit by one. All moves drain 50%.",
|
||||
},
|
||||
nibblenibble: {
|
||||
onPrepareHit(source, target, move) {
|
||||
if (move.category === 'Status' || move.multihit || move.flags['noparentalbond'] || move.flags['charge'] ||
|
||||
move.flags['futuremove'] || move.spreadHit || move.isZ || move.isMax || !move.flags['bite']) return;
|
||||
move.multihit = 2;
|
||||
move.multihitType = 'parentalbond';
|
||||
},
|
||||
// Damage modifier implemented in BattleActions#modifyDamage()
|
||||
onSourceModifySecondaries(secondaries, target, source, move) {
|
||||
if (move.multihitType === 'parentalbond' && move.id === 'secretpower' && move.hit < 2) {
|
||||
// hack to prevent accidentally suppressing King's Rock/Razor Fang
|
||||
return secondaries.filter(effect => effect.volatileStatus === 'flinch');
|
||||
}
|
||||
},
|
||||
flags: {},
|
||||
name: "Nibble Nibble",
|
||||
rating: 5,
|
||||
num: -123,
|
||||
shortDesc: "Parental Bond but for Bite moves.",
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,12 +13,10 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
masquerainite: {
|
||||
name: "Masquerainite",
|
||||
spritenum: 1,
|
||||
megaStone: "Masquerain-Mega",
|
||||
megaEvolves: "Masquerain",
|
||||
megaStone: { "Masquerain": "Masquerain-Mega" },
|
||||
itemUser: ["Masquerain"],
|
||||
onTakeItem(item, source) {
|
||||
if (item.megaEvolves === source.baseSpecies.baseSpecies) return false;
|
||||
return true;
|
||||
return !item.megaStone?.[source.baseSpecies.baseSpecies];
|
||||
},
|
||||
num: -1,
|
||||
gen: 9,
|
||||
|
|
@ -59,12 +57,10 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
typhlosionite: {
|
||||
name: "Typhlosionite",
|
||||
spritenum: 1,
|
||||
megaStone: "Typhlosion-Mega",
|
||||
megaEvolves: "Typhlosion",
|
||||
megaStone: { "Typhlosion": "Typhlosion-Mega" },
|
||||
itemUser: ["Typhlosion"],
|
||||
onTakeItem(item, source) {
|
||||
if (item.megaEvolves === source.baseSpecies.baseSpecies) return false;
|
||||
return true;
|
||||
return !item.megaStone?.[source.baseSpecies.baseSpecies];
|
||||
},
|
||||
num: -2,
|
||||
gen: 9,
|
||||
|
|
@ -127,14 +123,28 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
onDamagePriority: -40,
|
||||
onDamage(damage, target, source, effect) {
|
||||
const chance = Math.max(Math.floor(target.hp / target.maxhp), 10);
|
||||
const chance = Math.max(Math.floor(100 - (target.maxhp - target.hp)), 10);
|
||||
if (this.randomChance(chance, 100) && damage >= target.hp && effect && effect.effectType === 'Move') {
|
||||
this.add("-activate", target, "item: Focus Band");
|
||||
return target.hp - 1;
|
||||
} else {
|
||||
return damage;
|
||||
}
|
||||
},
|
||||
num: 230,
|
||||
gen: 2,
|
||||
desc: "Chance to survive attack equal to percentage of remaining HP, minimum 10%.",
|
||||
},
|
||||
raticite: {
|
||||
name: "Raticite",
|
||||
spritenum: 1,
|
||||
megaStone: { "Raticate": "Raticate-Mega" },
|
||||
itemUser: ["Raticate"],
|
||||
onTakeItem(item, source) {
|
||||
return !item.megaStone?.[source.baseSpecies.baseSpecies];
|
||||
},
|
||||
num: -3,
|
||||
gen: 9,
|
||||
desc: "If held by a Raticate, this item allows it to Mega Evolve in battle.",
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
ancientpower: {
|
||||
inherit: true,
|
||||
category: "Physical",
|
||||
secondary: null,
|
||||
secondary: undefined, // no inherit
|
||||
// Ancient Power is physical and boosts on-kill
|
||||
onAfterMoveSecondarySelf(pokemon, target, move) {
|
||||
if (!target || target.fainted || target.hp <= 0) {
|
||||
|
|
@ -44,7 +44,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
this.add('-anim', source, 'Crunch', target);
|
||||
this.add('-anim', source, 'Rock Slide', target);
|
||||
},
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
type: "Rock",
|
||||
contestType: "Clever",
|
||||
|
|
@ -60,7 +59,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
pp: 10,
|
||||
priority: 0,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 },
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
type: "Poison",
|
||||
contestType: "Tough",
|
||||
|
|
@ -197,7 +195,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
this.field.setWeather('snowscape');
|
||||
},
|
||||
},
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
type: "Ice",
|
||||
contestType: "Clever",
|
||||
|
|
@ -254,7 +251,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
onAfterSubDamage(damage, target, source, move) {
|
||||
if (!source.isAlly(target)) this.hint(move.category + " Geyser");
|
||||
},
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
type: "Water",
|
||||
desc: "This move is Special + no contact if it would be stronger.",
|
||||
|
|
@ -281,7 +277,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
target.addVolatile('encore');
|
||||
},
|
||||
weather: 'raindance',
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
type: "Water",
|
||||
zMove: { boost: { spe: 1 } },
|
||||
|
|
@ -343,7 +338,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
this.add('-anim', source, 'Ivy Cudgel Rock', target);
|
||||
this.add('-anim', source, 'Splash');
|
||||
},
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
type: "Rock",
|
||||
contestType: "Beautiful",
|
||||
|
|
@ -366,7 +360,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
onPrepareHit(target, source, move) {
|
||||
this.add('-anim', source, 'Metal Claw', target);
|
||||
},
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
type: "Steel",
|
||||
contestType: "Beautiful",
|
||||
|
|
@ -395,7 +388,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
thunderouskick: {
|
||||
inherit: true,
|
||||
secondary: null,
|
||||
secondary: undefined, // no inherit
|
||||
onHit(target, source, move) {
|
||||
// random # 0 or 1
|
||||
const randomNum = this.random(2);
|
||||
|
|
@ -444,7 +437,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
},
|
||||
},
|
||||
secondary: null,
|
||||
target: "foeSide",
|
||||
type: "Rock",
|
||||
zMove: { boost: { def: 1 } },
|
||||
|
|
@ -487,7 +479,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
},
|
||||
},
|
||||
secondary: null,
|
||||
target: "foeSide",
|
||||
type: "Ground",
|
||||
zMove: { boost: { def: 1 } },
|
||||
|
|
@ -584,8 +575,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
source.switchFlag = true;
|
||||
},
|
||||
secondary: null,
|
||||
hasSheerForce: true,
|
||||
hasSheerForceBoost: true,
|
||||
target: "normal",
|
||||
type: "Dragon",
|
||||
desc: "Dondozo eats a mon on the user's team, KOing it. Dondozo then gains a stat boost depending on the eaten mon's highest stat: +3 Attack for Atk/SpA, +2 Def/+2 SpD for Def/SpD, and +3 Speed for Speed.",
|
||||
|
|
@ -658,7 +648,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
this.add('-anim', source, 'Spirit Shackle', target);
|
||||
},
|
||||
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 },
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
type: "Ghost",
|
||||
contestType: "Clever",
|
||||
|
|
@ -687,7 +676,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
},
|
||||
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 },
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
type: "Fighting",
|
||||
contestType: "Clever",
|
||||
|
|
@ -833,7 +821,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
return success;
|
||||
},
|
||||
flags: { protect: 1, mirror: 1, metronome: 1, wind: 1 },
|
||||
secondary: null,
|
||||
target: "allAdjacentFoes",
|
||||
type: "Dragon",
|
||||
contestType: "Cool",
|
||||
|
|
@ -853,7 +840,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
this.add('-start', target, 'typechange', 'Steel');
|
||||
},
|
||||
flags: { protect: 1, mirror: 1, metronome: 1, bullet: 1 },
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
type: "Steel",
|
||||
contestType: "Cool",
|
||||
|
|
@ -890,7 +876,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
this.add('-anim', source, 'Extreme Speed', target);
|
||||
this.add('-anim', source, 'Thunder', target);
|
||||
},
|
||||
secondary: null,
|
||||
secondary: undefined, // no inherit
|
||||
desc: "Nearly always goes first.",
|
||||
shortDesc: "Nearly always goes first.",
|
||||
},
|
||||
|
|
@ -938,7 +924,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 },
|
||||
selfSwitch: true,
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
type: "Fire",
|
||||
contestType: "Cute",
|
||||
|
|
@ -1078,7 +1063,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
pp: 10,
|
||||
priority: 0,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 },
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
type: "Rock",
|
||||
contestType: "Tough",
|
||||
|
|
@ -1122,10 +1106,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
onTryHitPriority: 3,
|
||||
onTryHit(target, source, move) {
|
||||
if (!move.flags['protect'] || move.category === 'Status') {
|
||||
if (move.isZ || move.isMax) target.getMoveHitData(move).zBrokeProtect = true;
|
||||
return;
|
||||
}
|
||||
if (this.checkMoveBypassesProtect(move, source, target, false)) return;
|
||||
if (move.smartTarget) {
|
||||
move.smartTarget = false;
|
||||
} else {
|
||||
|
|
@ -1174,7 +1155,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
priority: 0,
|
||||
flags: { protect: 1, mirror: 1, metronome: 1 },
|
||||
drain: [1, 2],
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
type: "Fire",
|
||||
zMove: { basePower: 160 },
|
||||
|
|
@ -1209,7 +1189,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
pp: 10,
|
||||
priority: 0,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 },
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
type: "Grass",
|
||||
contestType: "Tough",
|
||||
|
|
@ -1275,7 +1254,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
},
|
||||
},
|
||||
secondary: null,
|
||||
target: "self",
|
||||
type: "Normal",
|
||||
zMove: { effect: 'clearnegativeboost' },
|
||||
|
|
@ -1311,10 +1289,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
this.add('-fail', source, 'move: Crowverload');
|
||||
return this.NOT_FAIL;
|
||||
}
|
||||
if (source.hp <= source.maxhp / 4) {
|
||||
this.add('-fail', source, 'move: Substitute', '[weak]');
|
||||
return this.NOT_FAIL;
|
||||
}
|
||||
},
|
||||
onAfterMove(source, target, move) {
|
||||
this.actions.useMove('substitute', source, { });
|
||||
|
|
@ -1323,7 +1297,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
flags: { protect: 1, mirror: 1, metronome: 1 },
|
||||
multihit: [10, 10],
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
type: "Dark",
|
||||
zMove: { basePower: 140 },
|
||||
|
|
@ -1372,7 +1345,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
return null;
|
||||
},
|
||||
callsMove: true,
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
type: "Normal",
|
||||
contestType: "Beautiful",
|
||||
|
|
@ -1399,7 +1371,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
return priority + 1;
|
||||
}
|
||||
},
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
type: "Fairy",
|
||||
contestType: "Cool",
|
||||
|
|
@ -1426,7 +1397,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
return priority + 1;
|
||||
}
|
||||
},
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
type: "Electric",
|
||||
contestType: "Cool",
|
||||
|
|
@ -1454,7 +1424,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
this.boost({ spe: 1 }, source, source);
|
||||
}
|
||||
},
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
type: "Psychic",
|
||||
contestType: "Cool",
|
||||
|
|
@ -1532,16 +1501,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
return false;
|
||||
}
|
||||
},
|
||||
onTryHeal(damage, target, source, effect) {
|
||||
if (effect && (effect.id === 'zpower' || (effect as Move).isZ)) return damage;
|
||||
if (source && target !== source && target.hp !== target.maxhp && effect.name === "Pollen Puff") {
|
||||
this.attrLastMove('[still]');
|
||||
// FIXME: Wrong error message, correct one not supported yet
|
||||
this.add('cant', source, 'move: Electric Terrain', effect);
|
||||
return null;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
onFieldResidualOrder: 27,
|
||||
onFieldResidualSubOrder: 7,
|
||||
onFieldEnd() {
|
||||
|
|
@ -1631,10 +1590,10 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
this.add('-anim', source, 'Explosion', target);
|
||||
this.add('-anim', source, 'Mind Blown', target);
|
||||
},
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
type: "Normal",
|
||||
contestType: "Cute",
|
||||
shortDesc: "Present but better.",
|
||||
},
|
||||
sinisterarrows: {
|
||||
num: -1016,
|
||||
|
|
@ -1708,13 +1667,56 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
},
|
||||
},
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
type: "Ghost",
|
||||
contestType: "Clever",
|
||||
shortDesc: "Hits for 4 turns, even if user switches out.",
|
||||
},
|
||||
mortalspin: {
|
||||
inherit: true,
|
||||
category: "Special",
|
||||
},
|
||||
lastbreakfast: {
|
||||
num: -1020,
|
||||
accuracy: 100,
|
||||
basePower: 80,
|
||||
category: "Physical",
|
||||
name: "Last Breakfast",
|
||||
pp: 15,
|
||||
priority: 0,
|
||||
flags: { protect: 1, mirror: 1, metronome: 1, contact: 1, bite: 1 },
|
||||
onHit(target, source, move) {
|
||||
const numberBerries = 0 + 1 * Number(source.side.totalFainted);
|
||||
for (let i = 0; i < numberBerries; i++) {
|
||||
const possibleBerries = ['aguavberry', 'apicotberry', 'enigmaberry', 'figyberry', 'ganlonberry', 'iapapaberry',
|
||||
'keeberry', 'lansatberry', 'leppaberry', 'liechiberry', 'lumberry', 'magoberry',
|
||||
'marangaberry', 'micleberry',
|
||||
'oranberry', 'petayaberry', 'salacberry', 'sitrusberry', 'starfberry', 'wikiberry',
|
||||
'aspearberry', 'cheriberry', 'chestoberry', 'lumberry', 'pechaberry', 'rawstberry', 'persimberry'];
|
||||
const chosenBerry = this.sample(possibleBerries);
|
||||
const berry = this.dex.items.get(chosenBerry);
|
||||
if (source.hp && berry.isBerry) {
|
||||
if (this.singleEvent('Eat', berry, null, source, source, move)) {
|
||||
this.runEvent('EatItem', source, source, move, berry);
|
||||
}
|
||||
if (berry.onEat) source.ateBerry = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
onTryMove() {
|
||||
this.attrLastMove('[still]');
|
||||
},
|
||||
onPrepareHit(target, source) {
|
||||
this.add('-anim', source, 'Curse', target);
|
||||
this.add('-anim', source, 'Bug Bite', target);
|
||||
},
|
||||
target: "normal",
|
||||
type: "Ghost",
|
||||
contestType: "Cute",
|
||||
shortDesc: "Eats X random berries, where X is fainted teammates.",
|
||||
},
|
||||
superfang: {
|
||||
inherit: true,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1, bite: 1 },
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -482,10 +482,33 @@ export const Pokedex: import('../../../sim/dex-species').ModdedSpeciesDataTable
|
|||
ogerponcornerstone: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Solid Rock" },
|
||||
types: ["Psychic", "Normal"],
|
||||
},
|
||||
glimmora: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Corrosion" },
|
||||
},
|
||||
wobbuffet: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Jello Body" },
|
||||
},
|
||||
raticate: {
|
||||
inherit: true,
|
||||
abilities: { 0: "Hustle" },
|
||||
baseStats: { hp: 90, atk: 81, def: 60, spa: 50, spd: 70, spe: 97 },
|
||||
},
|
||||
raticatemega: {
|
||||
num: -977,
|
||||
name: "Raticate-Mega",
|
||||
baseSpecies: "Raticate",
|
||||
forme: "Mega",
|
||||
types: ["Normal", "Ghost"],
|
||||
genderRatio: { M: 0.5, F: 0.5 },
|
||||
baseStats: { hp: 90, atk: 105, def: 60, spa: 50, spd: 70, spe: 173 },
|
||||
abilities: { 0: "Nibble Nibble" },
|
||||
heightm: 0.7,
|
||||
weightkg: 5,
|
||||
color: "Black",
|
||||
eggGroups: ["Field"],
|
||||
requiredItem: "Raticite",
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -294,5 +294,11 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
|
||||
this.modData('Learnsets', 'glimmora').learnset.icebeam = ['9L1'];
|
||||
this.modData('Learnsets', 'glimmora').learnset.malignantchain = ['9L1'];
|
||||
|
||||
this.modData('Learnsets', 'wobbuffet').learnset.nightshade = ['9L1'];
|
||||
this.modData('Learnsets', 'wobbuffet').learnset.guillotine = ['9L1'];
|
||||
this.modData('Learnsets', 'wobbuffet').learnset.shedtail = ['9L1'];
|
||||
|
||||
this.modData('Learnsets', 'raticate').learnset.lastbreakfast = ['9L1'];
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -80,6 +80,9 @@ export const Conditions: import('../../../sim/dex-conditions').ModdedConditionDa
|
|||
onAfterMoveSelf(pokemon) {
|
||||
if (pokemon.statusState.time <= 0) pokemon.cureStatus();
|
||||
},
|
||||
onDisableMove(target) {
|
||||
target.maybeLocked = false; // the player knows it is locked
|
||||
},
|
||||
},
|
||||
frz: {
|
||||
name: 'frz',
|
||||
|
|
@ -98,6 +101,9 @@ export const Conditions: import('../../../sim/dex-conditions').ModdedConditionDa
|
|||
target.cureStatus();
|
||||
}
|
||||
},
|
||||
onDisableMove(target) {
|
||||
target.maybeLocked = false; // the player knows it is locked
|
||||
},
|
||||
},
|
||||
psn: {
|
||||
name: 'psn',
|
||||
|
|
@ -202,12 +208,11 @@ export const Conditions: import('../../../sim/dex-conditions').ModdedConditionDa
|
|||
onAccuracy(accuracy, target, source, move) {
|
||||
if (source === this.effectState.source) return true;
|
||||
},
|
||||
onLockMove() {
|
||||
// exact move doesn't matter, no move is ever actually used
|
||||
return 'struggle';
|
||||
},
|
||||
onDisableMovePriority: 1, // higher priority so it gets undone by frz, slp or Bide
|
||||
onDisableMove(target) {
|
||||
target.maybeLocked = true;
|
||||
if (this.effectState.maybeLocked) {
|
||||
target.maybeLocked = true;
|
||||
}
|
||||
},
|
||||
},
|
||||
fakepartiallytrapped: {
|
||||
|
|
@ -215,6 +220,7 @@ export const Conditions: import('../../../sim/dex-conditions').ModdedConditionDa
|
|||
// Wrap ended this turn, but you don't know that
|
||||
// until you try to use an attack
|
||||
duration: 2,
|
||||
onDisableMovePriority: 1, // higher priority so it gets undone by frz, slp or Bide
|
||||
onDisableMove(target) {
|
||||
target.maybeLocked = true;
|
||||
},
|
||||
|
|
@ -234,9 +240,6 @@ export const Conditions: import('../../../sim/dex-conditions').ModdedConditionDa
|
|||
this.effectState.locked = foe;
|
||||
foe.addVolatile('partiallytrapped', target, effect);
|
||||
},
|
||||
onOverrideAction(pokemon, target, move) {
|
||||
return this.effectState.move;
|
||||
},
|
||||
onBeforeMove(pokemon, target, move) {
|
||||
if (target !== this.effectState.locked) {
|
||||
pokemon.removeVolatile('partialtrappinglock');
|
||||
|
|
@ -256,20 +259,25 @@ export const Conditions: import('../../../sim/dex-conditions').ModdedConditionDa
|
|||
}
|
||||
} else {
|
||||
target.addVolatile('partiallytrapped', pokemon, move);
|
||||
if (this.effectState.totalDuration - this.effectState.duration! > 0) {
|
||||
target.volatiles['partiallytrapped'].maybeLocked = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
onLockMove() {
|
||||
onSemiLockMove() {
|
||||
return this.effectState.move;
|
||||
},
|
||||
onDisableMove(pokemon) {
|
||||
pokemon.maybeLocked = true;
|
||||
if (this.effectState.totalDuration - this.effectState.duration! > 1) {
|
||||
pokemon.maybeLocked = true;
|
||||
}
|
||||
},
|
||||
},
|
||||
mustrecharge: {
|
||||
inherit: true,
|
||||
duration: 0,
|
||||
onBeforeMovePriority: 7,
|
||||
onStart() {},
|
||||
onStart: undefined, // no inherit
|
||||
onAfterMove(pokemon, target, move) {
|
||||
if (target && target.hp <= 0) {
|
||||
delete pokemon.volatiles['mustrecharge'];
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
bide: {
|
||||
inherit: true,
|
||||
priority: 0,
|
||||
accuracy: true,
|
||||
condition: {
|
||||
onStart(pokemon) {
|
||||
|
|
@ -60,15 +59,9 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
this.add('-activate', pokemon, 'Bide');
|
||||
return false;
|
||||
},
|
||||
onDisableMove(pokemon) {
|
||||
if (!pokemon.hasMove('bide')) {
|
||||
return;
|
||||
}
|
||||
for (const moveSlot of pokemon.moveSlots) {
|
||||
if (moveSlot.id !== 'bide') {
|
||||
pokemon.disableMove(moveSlot.id);
|
||||
}
|
||||
}
|
||||
onSemiLockMove: 'bide',
|
||||
onDisableMove(target) {
|
||||
target.maybeLocked = false; // the player knows it is locked
|
||||
},
|
||||
},
|
||||
type: "???", // Will look as Normal but it's STAB-less
|
||||
|
|
@ -162,14 +155,14 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
// - if Counter is used by the opponent, it will succeed if the player's last selected move is Counterable
|
||||
// - (Counter will thus desync if the target's last used move is not as counterable as the target's last selected move)
|
||||
// - if Counter succeeds it will deal twice the last move damage dealt in battle (even if it's from a different pokemon because of a switch)
|
||||
const isCounterable = (move: Move | null) => move && move.basePower > 0 &&
|
||||
['Normal', 'Fighting'].includes(move.type) && move.id !== 'counter';
|
||||
|
||||
const lastMove = target.side.lastMove && this.dex.moves.get(target.side.lastMove.id);
|
||||
const lastMoveIsCounterable = lastMove && lastMove.basePower > 0 &&
|
||||
['Normal', 'Fighting'].includes(lastMove.type) && lastMove.id !== 'counter';
|
||||
const lastMoveIsCounterable = isCounterable(lastMove);
|
||||
|
||||
const lastSelectedMove = target.side.lastSelectedMove && this.dex.moves.get(target.side.lastSelectedMove);
|
||||
const lastSelectedMoveIsCounterable = lastSelectedMove && lastSelectedMove.basePower > 0 &&
|
||||
['Normal', 'Fighting'].includes(lastSelectedMove.type) && lastSelectedMove.id !== 'counter';
|
||||
const lastSelectedMoveIsCounterable = isCounterable(lastSelectedMove || null);
|
||||
|
||||
if (!lastMoveIsCounterable && !lastSelectedMoveIsCounterable) {
|
||||
this.debug("Gen 1 Counter: last move was not Counterable");
|
||||
|
|
@ -211,33 +204,23 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
},
|
||||
disable: {
|
||||
num: 50,
|
||||
accuracy: 55,
|
||||
basePower: 0,
|
||||
category: "Status",
|
||||
name: "Disable",
|
||||
pp: 20,
|
||||
priority: 0,
|
||||
flags: { protect: 1, mirror: 1, bypasssub: 1, metronome: 1 },
|
||||
volatileStatus: 'disable',
|
||||
inherit: true,
|
||||
onTryHit(target) {
|
||||
// This function should not return if the checks are met. Adding && undefined ensures this happens.
|
||||
return target.moveSlots.some(ms => ms.pp > 0) &&
|
||||
!('disable' in target.volatiles) &&
|
||||
undefined;
|
||||
return target.moveSlots.some(ms => ms.pp > 0);
|
||||
},
|
||||
condition: {
|
||||
inherit: true,
|
||||
durationCallback: undefined, // no inherit
|
||||
onStart(pokemon) {
|
||||
// disable can only select moves that have pp > 0, hence the onTryHit modification
|
||||
const moveSlot = this.sample(pokemon.moveSlots.filter(ms => ms.pp > 0));
|
||||
const [slotIndex, moveSlot] = this.sample(Array.from(pokemon.moveSlots.entries()).filter(([i, ms]) => ms.pp > 0));
|
||||
this.debug(`Disable: disabling move ${moveSlot.move} in slot ${slotIndex}`);
|
||||
this.add('-start', pokemon, 'Disable', moveSlot.move);
|
||||
this.effectState.move = moveSlot.id;
|
||||
this.effectState.slotIndex = slotIndex;
|
||||
// 1-8 turns (which will in effect translate to 0-7 missed turns for the target)
|
||||
this.effectState.time = this.random(1, 9);
|
||||
},
|
||||
onEnd(pokemon) {
|
||||
this.add('-end', pokemon, 'Disable');
|
||||
},
|
||||
onBeforeMovePriority: 6,
|
||||
onBeforeMove(pokemon, target, move) {
|
||||
pokemon.volatiles['disable'].time--;
|
||||
|
|
@ -253,20 +236,17 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
},
|
||||
onDisableMove(pokemon) {
|
||||
for (const moveSlot of pokemon.moveSlots) {
|
||||
if (moveSlot.id === this.effectState.move) {
|
||||
pokemon.disableMove(moveSlot.id);
|
||||
}
|
||||
// disable the move slot
|
||||
if (pokemon.moveSlots.length > this.effectState.slotIndex) {
|
||||
pokemon.moveSlots[this.effectState.slotIndex].disabled = true;
|
||||
pokemon.moveSlots[this.effectState.slotIndex].disabledSource = this.effect.name;
|
||||
}
|
||||
},
|
||||
},
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
type: "Normal",
|
||||
},
|
||||
dizzypunch: {
|
||||
inherit: true,
|
||||
secondary: null,
|
||||
secondary: undefined, // no inherit
|
||||
},
|
||||
doubleedge: {
|
||||
inherit: true,
|
||||
|
|
@ -319,11 +299,9 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
focusenergy: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
onStart(pokemon) {
|
||||
this.add('-start', pokemon, 'move: Focus Energy');
|
||||
},
|
||||
inherit: true,
|
||||
// This does nothing as it's dealt with on critical hit calculation.
|
||||
onModifyMove() {},
|
||||
onModifyCritRatio: undefined, // no inherit
|
||||
},
|
||||
},
|
||||
glare: {
|
||||
|
|
@ -349,6 +327,12 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
for (const pokemon of this.getAllActive()) {
|
||||
pokemon.clearBoosts();
|
||||
if (pokemon !== source) {
|
||||
if (['frz', 'slp'].includes(pokemon.status)) {
|
||||
pokemon.side.lastSelectedMove = 'cannotmove' as ID;
|
||||
if (this.queue.willMove(pokemon)) {
|
||||
this.queue.changeAction(pokemon, { choice: 'move', pokemon, moveid: 'cannotmove' });
|
||||
}
|
||||
}
|
||||
pokemon.cureStatus(true);
|
||||
}
|
||||
if (pokemon.status === 'tox') {
|
||||
|
|
@ -406,11 +390,9 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
leechseed: {
|
||||
inherit: true,
|
||||
onHit() {},
|
||||
onHit: undefined, // no inherit
|
||||
condition: {
|
||||
onStart(target) {
|
||||
this.add('-start', target, 'move: Leech Seed');
|
||||
},
|
||||
inherit: true,
|
||||
onAfterMoveSelfPriority: 1,
|
||||
onAfterMoveSelf(pokemon) {
|
||||
const leecher = this.getAtSlot(pokemon.volatiles['leechseed'].sourceSlot);
|
||||
|
|
@ -436,15 +418,9 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
},
|
||||
lightscreen: {
|
||||
num: 113,
|
||||
accuracy: true,
|
||||
basePower: 0,
|
||||
category: "Status",
|
||||
name: "Light Screen",
|
||||
pp: 30,
|
||||
priority: 0,
|
||||
flags: { metronome: 1 },
|
||||
inherit: true,
|
||||
volatileStatus: 'lightscreen',
|
||||
sideCondition: undefined, // no inherit
|
||||
onTryHit(pokemon) {
|
||||
if (pokemon.volatiles['lightscreen']) {
|
||||
return false;
|
||||
|
|
@ -456,14 +432,28 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
},
|
||||
target: "self",
|
||||
type: "Psychic",
|
||||
},
|
||||
metronome: {
|
||||
inherit: true,
|
||||
onHit(pokemon) {
|
||||
const moves = this.dex.moves.all().filter(move => (
|
||||
(!move.isNonstandard || move.isNonstandard === 'Unobtainable') && move.flags['metronome']
|
||||
));
|
||||
let randomMove = '';
|
||||
if (moves.length) {
|
||||
moves.sort((a, b) => a.num - b.num);
|
||||
randomMove = this.sample(moves).id;
|
||||
}
|
||||
if (!randomMove) return false;
|
||||
pokemon.side.lastSelectedMove = this.toID(randomMove);
|
||||
this.actions.useMove(randomMove, pokemon);
|
||||
},
|
||||
},
|
||||
mimic: {
|
||||
inherit: true,
|
||||
flags: { protect: 1, bypasssub: 1, metronome: 1 },
|
||||
onHit(target, source) {
|
||||
const moveslot = source.moves.indexOf('mimic');
|
||||
if (moveslot < 0) return false;
|
||||
const moveslot = source.side.lastSelectedMoveSlot;
|
||||
const moves = target.moves;
|
||||
const moveid = this.sample(moves);
|
||||
if (!moveid) return false;
|
||||
|
|
@ -472,7 +462,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
move: move.name,
|
||||
id: move.id,
|
||||
pp: source.moveSlots[moveslot].pp,
|
||||
maxpp: move.pp * 8 / 5,
|
||||
maxpp: this.calculatePP(move, source.ppUps[moveslot] || 0),
|
||||
target: move.target,
|
||||
disabled: false,
|
||||
used: false,
|
||||
|
|
@ -481,6 +471,13 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
this.add('-start', source, 'Mimic', move.name);
|
||||
},
|
||||
},
|
||||
minimize: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
inherit: true,
|
||||
onSourceModifyDamage: undefined, // no inherit
|
||||
},
|
||||
},
|
||||
mirrormove: {
|
||||
inherit: true,
|
||||
onHit(pokemon) {
|
||||
|
|
@ -495,9 +492,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
mist: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
onStart(pokemon) {
|
||||
this.add('-start', pokemon, 'Mist');
|
||||
},
|
||||
inherit: true,
|
||||
onTryBoost(boost, target, source, effect) {
|
||||
if (effect.effectType === 'Move' && effect.category !== 'Status') return;
|
||||
if (source && target !== source) {
|
||||
|
|
@ -523,7 +518,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
petaldance: {
|
||||
inherit: true,
|
||||
onMoveFail() {},
|
||||
onMoveFail: undefined, // no inherit
|
||||
},
|
||||
poisonsting: {
|
||||
inherit: true,
|
||||
|
|
@ -546,9 +541,15 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
basePower: 1,
|
||||
damageCallback(pokemon) {
|
||||
if ([0, 1, 171].includes(pokemon.level)) {
|
||||
this.hint("Desync Clause Mod activated!");
|
||||
this.hint("In Gen 1, if a Pokémon at level 0, 1 or 171 uses Psywave, the game softlocks.");
|
||||
return false;
|
||||
}
|
||||
const psywaveDamage = (this.random(0, this.trunc(1.5 * pokemon.level)));
|
||||
if (psywaveDamage <= 0) {
|
||||
this.hint("Desync Clause Mod activated!");
|
||||
this.hint("In Gen 1, Psywave can roll 0 damage.");
|
||||
return false;
|
||||
}
|
||||
return psywaveDamage;
|
||||
|
|
@ -595,7 +596,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
recover: {
|
||||
inherit: true,
|
||||
heal: null,
|
||||
heal: undefined, // no inherit
|
||||
onHit(target) {
|
||||
if (target.hp === target.maxhp) return false;
|
||||
// Fail when health is 255 or 511 less than max, unless it is divisible by 256
|
||||
|
|
@ -613,15 +614,9 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
},
|
||||
reflect: {
|
||||
num: 115,
|
||||
accuracy: true,
|
||||
basePower: 0,
|
||||
category: "Status",
|
||||
name: "Reflect",
|
||||
pp: 20,
|
||||
priority: 0,
|
||||
flags: { metronome: 1 },
|
||||
inherit: true,
|
||||
volatileStatus: 'reflect',
|
||||
sideCondition: undefined, // no inherit
|
||||
onTryHit(pokemon) {
|
||||
if (pokemon.volatiles['reflect']) {
|
||||
return false;
|
||||
|
|
@ -632,13 +627,11 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
this.add('-start', pokemon, 'Reflect');
|
||||
},
|
||||
},
|
||||
secondary: null,
|
||||
target: "self",
|
||||
type: "Psychic",
|
||||
},
|
||||
rest: {
|
||||
inherit: true,
|
||||
onTry() {},
|
||||
onTry: undefined, // no inherit
|
||||
onHit(target, source, move) {
|
||||
if (target.hp === target.maxhp) return false;
|
||||
// Fail when health is 255 or 511 less than max, unless it is divisible by 256
|
||||
|
|
@ -661,12 +654,12 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
roar: {
|
||||
inherit: true,
|
||||
forceSwitch: false,
|
||||
onTryHit() {},
|
||||
onTryHit: undefined, // no inherit
|
||||
priority: 0,
|
||||
},
|
||||
rockslide: {
|
||||
inherit: true,
|
||||
secondary: null,
|
||||
secondary: undefined, // no inherit
|
||||
target: "normal",
|
||||
},
|
||||
rockthrow: {
|
||||
|
|
@ -742,7 +735,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
softboiled: {
|
||||
inherit: true,
|
||||
heal: null,
|
||||
heal: undefined, // no inherit
|
||||
onHit(target) {
|
||||
if (target.hp === target.maxhp) return false;
|
||||
// Fail when health is 255 or 511 less than max, unless it is divisible by 256
|
||||
|
|
@ -763,18 +756,10 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
pp: 10,
|
||||
recoil: [1, 2],
|
||||
onModifyMove() {},
|
||||
onModifyMove: undefined, // no inherit
|
||||
},
|
||||
substitute: {
|
||||
num: 164,
|
||||
accuracy: true,
|
||||
basePower: 0,
|
||||
category: "Status",
|
||||
name: "Substitute",
|
||||
pp: 10,
|
||||
priority: 0,
|
||||
flags: { metronome: 1 },
|
||||
volatileStatus: 'substitute',
|
||||
inherit: true,
|
||||
onTryHit(target) {
|
||||
if (target.volatiles['substitute']) {
|
||||
this.add('-fail', target, 'move: Substitute');
|
||||
|
|
@ -794,11 +779,16 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
},
|
||||
condition: {
|
||||
inherit: true,
|
||||
onStart(target) {
|
||||
this.add('-start', target, 'Substitute');
|
||||
this.effectState.hp = Math.floor(target.maxhp / 4) + 1;
|
||||
delete target.volatiles['partiallytrapped'];
|
||||
if (target.volatiles['partiallytrapped']) {
|
||||
this.add('-end', target, target.volatiles['partiallytrapped'].sourceEffect, '[partiallytrapped]', '[silent]');
|
||||
delete target.volatiles['partiallytrapped'];
|
||||
}
|
||||
},
|
||||
onTryPrimaryHit: undefined, // no inherit
|
||||
onTryHitPriority: -1,
|
||||
onTryHit(target, source, move) {
|
||||
if (move.category === 'Status') {
|
||||
|
|
@ -862,13 +852,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
return 0;
|
||||
},
|
||||
onEnd(target) {
|
||||
this.add('-end', target, 'Substitute');
|
||||
},
|
||||
},
|
||||
secondary: null,
|
||||
target: "self",
|
||||
type: "Normal",
|
||||
},
|
||||
superfang: {
|
||||
inherit: true,
|
||||
|
|
@ -877,7 +861,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
thrash: {
|
||||
inherit: true,
|
||||
onMoveFail() {},
|
||||
onMoveFail: undefined, // no inherit
|
||||
},
|
||||
thunder: {
|
||||
inherit: true,
|
||||
|
|
@ -888,14 +872,14 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
triattack: {
|
||||
inherit: true,
|
||||
onHit() {},
|
||||
secondary: null,
|
||||
onHit: undefined, // no inherit
|
||||
secondary: undefined, // no inherit
|
||||
},
|
||||
whirlwind: {
|
||||
inherit: true,
|
||||
accuracy: 85,
|
||||
forceSwitch: false,
|
||||
onTryHit() {},
|
||||
onTryHit: undefined, // no inherit
|
||||
priority: 0,
|
||||
},
|
||||
wingattack: {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,17 @@
|
|||
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
|
||||
standardag: {
|
||||
inherit: true,
|
||||
ruleset: [
|
||||
'Obtainable', 'Desync Clause Mod', 'HP Percentage Mod', 'Cancel Mod', 'Endless Battle Clause',
|
||||
],
|
||||
},
|
||||
standard: {
|
||||
effectType: 'ValidatorRule',
|
||||
name: 'Standard',
|
||||
ruleset: ['Obtainable', 'Desync Clause Mod', 'Sleep Clause Mod', 'Freeze Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Moves Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod'],
|
||||
ruleset: [
|
||||
'Standard AG',
|
||||
'Sleep Clause Mod', 'Freeze Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Moves Clause',
|
||||
],
|
||||
banlist: ['Dig', 'Fly'],
|
||||
},
|
||||
'350cupmod': {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,27 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
// BattlePokemon scripts.
|
||||
pokemon: {
|
||||
inherit: true,
|
||||
deductPP(move, amount) {
|
||||
// deduct PP based on side.lastSelectedMoveSlot
|
||||
const ppData = this.getMoveSlot(this.side.lastSelectedMoveSlot);
|
||||
if (!ppData) return 0;
|
||||
ppData.used = true;
|
||||
|
||||
if (!amount) amount = 1;
|
||||
ppData.pp -= amount;
|
||||
|
||||
if (ppData.pp < 0) {
|
||||
this.battle.hint("In Gen 1, if a Pokémon is forced to use a move with 0 PP, the move will underflow to have 63 PP.");
|
||||
}
|
||||
ppData.pp = ((ppData.pp % 64) + 64) % 64;
|
||||
|
||||
if (ppData.virtual && !this.transformed) {
|
||||
// sync PP from Mimic's slot, or Metronome/Mirror Move that called Mimic
|
||||
this.baseMoveSlots[this.side.lastSelectedMoveSlot].pp = ppData.pp;
|
||||
}
|
||||
|
||||
return amount;
|
||||
},
|
||||
getStat(statName, unmodified) {
|
||||
// @ts-expect-error type checking prevents 'hp' from being passed, but we're paranoid
|
||||
if (statName === 'hp') throw new Error("Please read `maxhp` directly");
|
||||
|
|
@ -136,12 +157,30 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
}
|
||||
}
|
||||
|
||||
// If a faster partial trapping move misses against a user of Hyper Beam during a recharge turn,
|
||||
// the user of Hyper Beam will automatically use Hyper Beam during that turn.
|
||||
if (move.id === 'recharge' && !pokemon.volatiles['mustrecharge'] && !pokemon.volatiles['partiallytrapped']) {
|
||||
move = this.battle.dex.getActiveMove('hyperbeam');
|
||||
this.battle.hint(`In Gen 1, partial trapping moves like Wrap remove Hyper Beam recharges. ` +
|
||||
`If the target would have recharged, it will automatically use Hyper Beam instead.`, true);
|
||||
const abortMove = () => {
|
||||
this.battle.clearActiveMove(true);
|
||||
this.battle.runEvent('AfterMoveSelf', pokemon, target, move);
|
||||
};
|
||||
|
||||
if (move.id === 'cannotmove') {
|
||||
if (pokemon.status === 'slp') {
|
||||
this.battle.hint(
|
||||
"In Gen 1, if a Pokémon spends a turn partially trapped and switches to a Pokémon that is asleep, " +
|
||||
"the sleep counter will not decrease until you select a move with a different Pokémon."
|
||||
);
|
||||
} else if (pokemon.getLockedMove()) {
|
||||
this.battle.hint(
|
||||
"In Gen 1, when Haze cures the sleep/freeze status of a Pokémon during a multi-turn move, " +
|
||||
"that Pokémon will become soft-locked."
|
||||
);
|
||||
} else if (pokemon.getSemiLockedMove()) {
|
||||
this.battle.hint(
|
||||
"In Gen 1, when Haze cures the sleep/freeze status of a Pokémon during Bide, " +
|
||||
"the move execution will never resolve."
|
||||
);
|
||||
}
|
||||
abortMove();
|
||||
return;
|
||||
}
|
||||
|
||||
if (target?.subFainted) target.subFainted = null;
|
||||
|
|
@ -149,37 +188,36 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
this.battle.setActiveMove(move, pokemon, target);
|
||||
|
||||
if (pokemon.moveThisTurn || !this.battle.runEvent('BeforeMove', pokemon, target, move)) {
|
||||
this.battle.clearActiveMove(true);
|
||||
// This is only run for sleep.
|
||||
this.battle.runEvent('AfterMoveSelf', pokemon, target, move);
|
||||
abortMove();
|
||||
return;
|
||||
}
|
||||
if (move.beforeMoveCallback?.call(this.battle, pokemon, target, move)) {
|
||||
this.battle.clearActiveMove(true);
|
||||
abortMove();
|
||||
return;
|
||||
}
|
||||
|
||||
const lockedMove = pokemon.getLockedMove();
|
||||
if (lockedMove) sourceEffect = move;
|
||||
if (move.id !== 'struggle') {
|
||||
const lockedMove = pokemon.getLockedMove() || pokemon.getSemiLockedMove();
|
||||
if (lockedMove) sourceEffect = move;
|
||||
|
||||
// Locked moves don't deduct PP
|
||||
// Two-turn moves like Sky Attack deduct PP on their second turn.
|
||||
if (!lockedMove || pokemon.volatiles['twoturnmove']) {
|
||||
const ppMove = pokemon.volatiles['twoturnmove']?.ppMove || move.id;
|
||||
pokemon.deductPP(ppMove, null, target);
|
||||
const moveSlot = pokemon.getMoveData(ppMove);
|
||||
if (moveSlot && moveSlot.pp < 0) {
|
||||
moveSlot.pp += 64;
|
||||
this.battle.hint("In Gen 1, if a pokemon is forced to use a move with 0 PP, the move will underflow to have 63 PP.");
|
||||
// Locked moves don't deduct PP
|
||||
// Two-turn moves like Sky Attack deduct PP on their second turn.
|
||||
if ((!lockedMove && !TWO_TURN_MOVES.includes(move.id)) || pokemon.volatiles['twoturnmove']) {
|
||||
const moveSlot = pokemon.getMoveSlot(pokemon.side.lastSelectedMoveSlot);
|
||||
if (moveSlot) pokemon.deductPP(moveSlot.id, null, target);
|
||||
}
|
||||
|
||||
if (!lockedMove && move.id !== pokemon.getMoveSlot(pokemon.side.lastSelectedMoveSlot)?.id) {
|
||||
this.battle.hint("Desync Clause Mod activated!");
|
||||
this.battle.hint(
|
||||
"In Gen 1, a Pokémon might default to using a move that doesn't match the move of the slot it last selected.",
|
||||
);
|
||||
abortMove();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.useMove(move, pokemon, { target, sourceEffect });
|
||||
|
||||
if (pokemon.volatiles['twoturnmove']) {
|
||||
pokemon.deductPP(move, -1, target);
|
||||
pokemon.volatiles['twoturnmove'].ppMove = move.id;
|
||||
}
|
||||
},
|
||||
// This function deals with AfterMoveSelf events.
|
||||
// This leads with partial trapping moves shenanigans after the move has been used.
|
||||
|
|
@ -195,6 +233,19 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
}
|
||||
if (sourceEffect) move.sourceEffect = sourceEffect.id;
|
||||
|
||||
if (sourceEffect?.id === 'metronome' || sourceEffect?.id === 'mirrormove') {
|
||||
if (TWO_TURN_MOVES.includes(move.id)) {
|
||||
const moveSlot = pokemon.getMoveSlot(pokemon.side.lastSelectedMoveSlot);
|
||||
if (moveSlot) pokemon.deductPP(moveSlot.id, -1, target);
|
||||
}
|
||||
// FIXME: this should happen even if the slot was empty before Transform
|
||||
// https://bulbapedia.bulbagarden.net/wiki/List_of_Transform_glitches#Transform_.2B_Mirror_Move.2FMetronome_PP_error
|
||||
if (pokemon.transformed && pokemon.side.lastSelectedMoveSlot < pokemon.baseMoveSlots.length) {
|
||||
pokemon.baseMoveSlots[pokemon.side.lastSelectedMoveSlot].pp += 1;
|
||||
pokemon.baseMoveSlots[pokemon.side.lastSelectedMoveSlot].pp %= 64;
|
||||
}
|
||||
}
|
||||
|
||||
this.battle.singleEvent('ModifyMove', move, null, pokemon, target, move, move);
|
||||
if (baseMove.target !== move.target) {
|
||||
// Target changed in ModifyMove, so we must adjust it here
|
||||
|
|
@ -414,7 +465,7 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
let i: number;
|
||||
for (i = 0; i < hits && target.hp && pokemon.hp; i++) {
|
||||
move.hit = i + 1;
|
||||
if (move.hit === hits) move.lastHit = true;
|
||||
move.lastHit = move.hit === hits;
|
||||
moveDamage = this.moveHit(target, pokemon, move);
|
||||
if (moveDamage === false) break;
|
||||
damage = (moveDamage || 0);
|
||||
|
|
|
|||
|
|
@ -13,12 +13,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
substitute: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
onStart(target) {
|
||||
this.add('-start', target, 'Substitute');
|
||||
this.effectState.hp = Math.floor(target.maxhp / 4) + 1;
|
||||
delete target.volatiles['partiallytrapped'];
|
||||
},
|
||||
onTryHitPriority: -1,
|
||||
inherit: true,
|
||||
onTryHit(target, source, move) {
|
||||
if (move.drain) {
|
||||
this.add('-miss', source);
|
||||
|
|
@ -76,9 +71,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
return accuracy;
|
||||
},
|
||||
onEnd(target) {
|
||||
this.add('-end', target, 'Substitute');
|
||||
},
|
||||
},
|
||||
},
|
||||
swift: {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,10 @@ export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable
|
|||
standard: {
|
||||
effectType: 'ValidatorRule',
|
||||
name: 'Standard',
|
||||
ruleset: ['Obtainable', 'Desync Clause Mod', 'Sleep Clause Mod', 'Freeze Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Moves Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod'],
|
||||
ruleset: [
|
||||
'Standard AG',
|
||||
'Sleep Clause Mod', 'Freeze Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Moves Clause',
|
||||
],
|
||||
banlist: ['Dig', 'Fly'],
|
||||
},
|
||||
nc1997movelegality: {
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ export const Conditions: import('../../../sim/dex-conditions').ModdedConditionDa
|
|||
},
|
||||
flinch: {
|
||||
inherit: true,
|
||||
onStart() {},
|
||||
onStart: undefined, // no inherit
|
||||
},
|
||||
partiallytrapped: {
|
||||
name: 'partiallytrapped',
|
||||
|
|
|
|||
|
|
@ -160,11 +160,11 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
volatileStatus: 'rage',
|
||||
},
|
||||
condition: {
|
||||
inherit: true,
|
||||
// Rage lock
|
||||
onStart(target, source, effect) {
|
||||
this.effectState.move = 'rage';
|
||||
},
|
||||
onLockMove: 'rage',
|
||||
onHit(target, source, move) {
|
||||
if (target.boosts.atk < 6 && (move.category !== 'Status' || move.id === 'disable')) {
|
||||
this.boost({ atk: 1 });
|
||||
|
|
@ -174,7 +174,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
recover: {
|
||||
inherit: true,
|
||||
heal: null,
|
||||
onHit(target) {
|
||||
if (target.hp === target.maxhp) {
|
||||
return false;
|
||||
|
|
@ -197,7 +196,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
softboiled: {
|
||||
inherit: true,
|
||||
heal: null,
|
||||
onHit(target) {
|
||||
// Fail when health is 255 or 511 less than max
|
||||
if (target.hp === target.maxhp) {
|
||||
|
|
@ -220,12 +218,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
},
|
||||
condition: {
|
||||
onStart(target) {
|
||||
this.add('-start', target, 'Substitute');
|
||||
this.effectState.hp = Math.floor(target.maxhp / 4);
|
||||
delete target.volatiles['partiallytrapped'];
|
||||
},
|
||||
onTryHitPriority: -1,
|
||||
inherit: true,
|
||||
onTryHit(target, source, move) {
|
||||
if (target === source) {
|
||||
this.debug('sub bypass: self hit');
|
||||
|
|
@ -275,11 +268,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
return 0;
|
||||
},
|
||||
onEnd(target) {
|
||||
this.add('-end', target, 'Substitute');
|
||||
},
|
||||
},
|
||||
secondary: null,
|
||||
target: "self",
|
||||
type: "Normal",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,7 +1,763 @@
|
|||
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
|
||||
standardag: {
|
||||
inherit: true,
|
||||
ruleset: [
|
||||
'Obtainable', 'Exact HP Mod', 'Cancel Mod',
|
||||
],
|
||||
},
|
||||
standard: {
|
||||
effectType: 'ValidatorRule',
|
||||
name: 'Standard',
|
||||
ruleset: ['Obtainable', 'Stadium Sleep Clause', 'Freeze Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Moves Clause', 'Exact HP Mod', 'Cancel Mod'],
|
||||
ruleset: [
|
||||
'Standard AG',
|
||||
'Stadium Sleep Clause', 'Freeze Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Moves Clause',
|
||||
],
|
||||
},
|
||||
stadiumpokecuprentals: {
|
||||
inherit: true,
|
||||
onChangeSet(set, format, setHas, teamHas) {
|
||||
set.level = 50;
|
||||
switch (this.dex.species.get(set.species).name) {
|
||||
case 'Bulbasaur':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Leech Seed', 'Toxic', 'Body Slam', 'Razor Leaf'];
|
||||
break;
|
||||
case 'Ivysaur':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Razor Leaf', 'Sleep Powder', 'Growth', 'Double-Edge'];
|
||||
break;
|
||||
case 'Venusaur':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Psychic', 'Seismic Toss', 'Reflect', 'Thunder Wave'];
|
||||
break;
|
||||
case 'Charmander':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Flamethrower', 'Slash', 'Dig', 'Fire Spin'];
|
||||
break;
|
||||
case 'Charmeleon':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Flamethrower', 'Counter', 'Seismic Toss', 'Strength'];
|
||||
break;
|
||||
case 'Charizard':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Fly', 'Swords Dance', 'Fire Spin', 'Fire Blast'];
|
||||
break;
|
||||
case 'Squirtle':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Surf', 'Blizzard', 'Body Slam', 'Dig'];
|
||||
break;
|
||||
case 'Wartortle':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Surf', 'Strength', 'Rest', 'Ice Beam'];
|
||||
break;
|
||||
case 'Blastoise':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Hydro Pump', 'Skull Bash', 'Withdraw', 'Seismic Toss'];
|
||||
break;
|
||||
case 'Caterpie':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['String Shot', 'Tackle'];
|
||||
break;
|
||||
case 'Metapod':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['String Shot', 'Tackle'];
|
||||
break;
|
||||
case 'Butterfree':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Psychic', 'Supersonic', 'Mega Drain', 'Stun Spore'];
|
||||
break;
|
||||
case 'Weedle':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['String Shot', 'Poison Sting'];
|
||||
break;
|
||||
case 'Kakuna':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['String Shot', 'Poison Sting'];
|
||||
break;
|
||||
case 'Beedrill':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Twineedle', 'Hyper Beam', 'Toxic', 'Focus Energy'];
|
||||
break;
|
||||
case 'Pidgey':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Fly', 'Toxic', 'Double-Edge', 'Double Team'];
|
||||
break;
|
||||
case 'Pidgeotto':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Fly', 'Quick Attack', 'Sand Attack', 'Take Down'];
|
||||
break;
|
||||
case 'Pidgeot':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Mirror Move', 'Fly', 'Quick Attack', 'Sand Attack'];
|
||||
break;
|
||||
case 'Rattata':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Super Fang', 'Blizzard', 'Quick Attack', 'Hyper Fang'];
|
||||
break;
|
||||
case 'Raticate':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Hyper Fang', 'Hyper Beam', 'Focus Energy', 'Thunder'];
|
||||
break;
|
||||
case 'Spearow':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Drill Peck', 'Mirror Move', 'Double Team', 'Double-Edge'];
|
||||
break;
|
||||
case 'Fearow':
|
||||
set.evs = { hp: 121, atk: 120, def: 120, spa: 120, spd: 120, spe: 120 };
|
||||
set.ivs = { hp: 6, atk: 8, def: 8, spa: 6, spd: 6, spe: 6 };
|
||||
set.moves = ['Drill Peck', 'Mirror Move', 'Fury Attack', 'Swift'];
|
||||
break;
|
||||
case 'Ekans':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Earthquake', 'Acid', 'Screech', 'Body Slam'];
|
||||
break;
|
||||
case 'Arbok':
|
||||
set.evs = { hp: 121, atk: 120, def: 120, spa: 120, spd: 120, spe: 120 };
|
||||
set.ivs = { hp: 6, atk: 8, def: 8, spa: 6, spd: 6, spe: 6 };
|
||||
set.moves = ['Glare', 'Wrap', 'Dig', 'Strength'];
|
||||
break;
|
||||
case 'Pikachu':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Thunderbolt', 'Slam', 'Thunder Wave', 'Seismic Toss'];
|
||||
break;
|
||||
case 'Raichu':
|
||||
set.evs = { hp: 121, atk: 120, def: 120, spa: 120, spd: 120, spe: 120 };
|
||||
set.ivs = { hp: 6, atk: 8, def: 8, spa: 6, spd: 6, spe: 6 };
|
||||
set.moves = ['Thunder', 'Thunder Wave', 'Flash', 'Mega Kick'];
|
||||
break;
|
||||
case 'Sandshrew':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Earthquake', 'Slash', 'Seismic Toss', 'Sand Attack'];
|
||||
break;
|
||||
case 'Sandslash':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Dig', 'Swift', 'Seismic Toss', 'Sand Attack'];
|
||||
break;
|
||||
case 'Nidoran-F':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Toxic', 'Thunderbolt', 'Body Slam', 'Blizzard'];
|
||||
break;
|
||||
case 'Nidorina':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Toxic', 'Thunder', 'Double-Edge', 'Ice Beam'];
|
||||
break;
|
||||
case 'Nidoqueen':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Toxic', 'Double Kick', 'Bite', 'Earthquake'];
|
||||
break;
|
||||
case 'Nidoran-M':
|
||||
set.evs = { hp: 177, atk: 176, def: 176, spa: 176, spd: 176, spe: 176 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Blizzard', 'Body Slam', 'Thunderbolt', 'Focus Energy'];
|
||||
break;
|
||||
case 'Nidorino':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Double-Edge', 'Horn Drill', 'Focus Energy', 'Thunder'];
|
||||
break;
|
||||
case 'Nidoking':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Earthquake', 'Horn Drill', 'Rage', 'Substitute'];
|
||||
break;
|
||||
case 'Clefairy':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Thunderbolt', 'Psychic', 'Body Slam', 'Blizzard'];
|
||||
break;
|
||||
case 'Clefable':
|
||||
set.evs = { hp: 121, atk: 120, def: 120, spa: 120, spd: 120, spe: 120 };
|
||||
set.ivs = { hp: 6, atk: 8, def: 8, spa: 6, spd: 6, spe: 6 };
|
||||
set.moves = ['Sing', 'Tri Attack', 'Minimize', 'Ice Beam'];
|
||||
break;
|
||||
case 'Vulpix':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Flamethrower', 'Dig', 'Confuse Ray', 'Double-Edge'];
|
||||
break;
|
||||
case 'Ninetales':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Fire Blast', 'Skull Bash', 'Confuse Ray', 'Tail Whip'];
|
||||
break;
|
||||
case 'Jigglypuff':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Sing', 'Body Slam', 'Seismic Toss', 'Psychic'];
|
||||
break;
|
||||
case 'Wigglytuff':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Sing', 'Double-Edge', 'Submission', 'Thunderbolt'];
|
||||
break;
|
||||
case 'Zubat':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Confuse Ray', 'Mega Drain', 'Toxic', 'Double-Edge'];
|
||||
break;
|
||||
case 'Golbat':
|
||||
set.evs = { hp: 121, atk: 120, def: 120, spa: 120, spd: 120, spe: 120 };
|
||||
set.ivs = { hp: 6, atk: 8, def: 8, spa: 6, spd: 6, spe: 6 };
|
||||
set.moves = ['Confuse Ray', 'Mega Drain', 'Bite', 'Haze'];
|
||||
break;
|
||||
case 'Oddish':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Petal Dance', 'Toxic', 'Mega Drain', 'Double-Edge'];
|
||||
break;
|
||||
case 'Gloom':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Petal Dance', 'Take Down', 'Mega Drain', 'Stun Spore'];
|
||||
break;
|
||||
case 'Vileplume':
|
||||
set.evs = { hp: 121, atk: 120, def: 120, spa: 120, spd: 120, spe: 120 };
|
||||
set.ivs = { hp: 6, atk: 8, def: 8, spa: 6, spd: 6, spe: 6 };
|
||||
set.moves = ['Petal Dance', 'Sleep Powder', 'Acid', 'Cut'];
|
||||
break;
|
||||
case 'Paras':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Spore', 'Slash', 'Dig', 'Mega Drain'];
|
||||
break;
|
||||
case 'Parasect':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Spore', 'Take Down', 'Dig', 'Solar Beam'];
|
||||
break;
|
||||
case 'Venonat':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Psychic', 'Mega Drain', 'Double-Edge', 'Stun Spore'];
|
||||
break;
|
||||
case 'Venomoth':
|
||||
set.evs = { hp: 121, atk: 120, def: 120, spa: 120, spd: 120, spe: 120 };
|
||||
set.ivs = { hp: 6, atk: 8, def: 8, spa: 6, spd: 6, spe: 6 };
|
||||
set.moves = ['Psychic', 'Supersonic', 'Solar Beam', 'Swift'];
|
||||
break;
|
||||
case 'Diglett':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Earthquake', 'Slash', 'Sand Attack', 'Rock Slide'];
|
||||
break;
|
||||
case 'Dugtrio':
|
||||
set.evs = { hp: 121, atk: 120, def: 120, spa: 120, spd: 120, spe: 120 };
|
||||
set.ivs = { hp: 6, atk: 8, def: 8, spa: 6, spd: 6, spe: 6 };
|
||||
set.moves = ['Dig', 'Sand Attack', 'Toxic', 'Hyper Beam'];
|
||||
break;
|
||||
case 'Meowth':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Slash', 'Thunderbolt', 'Swift', 'Double Team'];
|
||||
break;
|
||||
case 'Persian':
|
||||
set.evs = { hp: 121, atk: 120, def: 120, spa: 120, spd: 120, spe: 120 };
|
||||
set.ivs = { hp: 6, atk: 8, def: 8, spa: 6, spd: 6, spe: 6 };
|
||||
set.moves = ['Slash', 'Bubble Beam', 'Mimic', 'Growl'];
|
||||
break;
|
||||
case 'Psyduck':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Surf', 'Confusion', 'Dig', 'Blizzard'];
|
||||
break;
|
||||
case 'Golduck':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Ice Beam', 'Surf', 'Toxic', 'Disable'];
|
||||
break;
|
||||
case 'Mankey':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Submission', 'Rock Slide', 'Seismic Toss', 'Screech'];
|
||||
break;
|
||||
case 'Primeape':
|
||||
set.evs = { hp: 121, atk: 120, def: 120, spa: 120, spd: 120, spe: 120 };
|
||||
set.ivs = { hp: 6, atk: 8, def: 8, spa: 6, spd: 6, spe: 6 };
|
||||
set.moves = ['Fury Swipes', 'Rock Slide', 'Low Kick', 'Screech'];
|
||||
break;
|
||||
case 'Growlithe':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Flamethrower', 'Body Slam', 'Reflect', 'Dig'];
|
||||
break;
|
||||
case 'Arcanine':
|
||||
set.evs = { hp: 105, atk: 104, def: 104, spa: 104, spd: 104, spe: 104 };
|
||||
set.ivs = { hp: 0, atk: 0, def: 0, spa: 0, spd: 0, spe: 0 };
|
||||
set.moves = ['Fire Blast', 'Take Down', 'Dragon Rage', 'Substitute'];
|
||||
break;
|
||||
case 'Poliwag':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Body Slam', 'Blizzard', 'Surf', 'Amnesia'];
|
||||
break;
|
||||
case 'Poliwhirl':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Hypnosis', 'Surf', 'Ice Beam', 'Earthquake'];
|
||||
break;
|
||||
case 'Poliwrath':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Hypnosis', 'Submission', 'Counter', 'Hydro Pump'];
|
||||
break;
|
||||
case 'Abra':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Psychic', 'Seismic Toss', 'Reflect', 'Thunder Wave'];
|
||||
break;
|
||||
case 'Kadabra':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Psychic', 'Counter', 'Recover', 'Dig'];
|
||||
break;
|
||||
case 'Alakazam':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Psybeam', 'Metronome', 'Disable', 'Tri Attack'];
|
||||
break;
|
||||
case 'Machop':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Submission', 'Rock Slide', 'Earthquake', 'Focus Energy'];
|
||||
break;
|
||||
case 'Machoke':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Submission', 'Strength', 'Rock Slide', 'Focus Energy'];
|
||||
break;
|
||||
case 'Machamp':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Low Kick', 'Strength', 'Counter', 'Focus Energy'];
|
||||
break;
|
||||
case 'Bellsprout':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Razor Leaf', 'Growth', 'Mega Drain', 'Stun Spore'];
|
||||
break;
|
||||
case 'Weepinbell':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Razor Leaf', 'Acid', 'Wrap', 'Toxic'];
|
||||
break;
|
||||
case 'Victreebel':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Solar Beam', 'Acid', 'Reflect', 'Slam'];
|
||||
break;
|
||||
case 'Tentacool':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Surf', 'Supersonic', 'Mega Drain', 'Blizzard'];
|
||||
break;
|
||||
case 'Tentacruel':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Acid', 'Supersonic', 'Hydro Pump', 'Cut'];
|
||||
break;
|
||||
case 'Geodude':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Earthquake', 'Seismic Toss', 'Rock Slide', 'Explosion'];
|
||||
break;
|
||||
case 'Graveler':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Earthquake', 'Seismic Toss', 'Strength', 'Self-Destruct'];
|
||||
break;
|
||||
case 'Golem':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Dig', 'Seismic Toss', 'Fire Blast', 'Metronome'];
|
||||
break;
|
||||
case 'Ponyta':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Fire Blast', 'Agility', 'Horn Drill', 'Body Slam'];
|
||||
break;
|
||||
case 'Rapidash':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Fire Blast', 'Stomp', 'Toxic', 'Fire Spin'];
|
||||
break;
|
||||
case 'Slowpoke':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Surf', 'Psychic', 'Thunder Wave', 'Amnesia'];
|
||||
break;
|
||||
case 'Slowbro':
|
||||
set.evs = { hp: 121, atk: 120, def: 120, spa: 120, spd: 120, spe: 120 };
|
||||
set.ivs = { hp: 6, atk: 8, def: 8, spa: 6, spd: 6, spe: 6 };
|
||||
set.moves = ['Surf', 'Psychic', 'Disable', 'Withdraw'];
|
||||
break;
|
||||
case 'Magnemite':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Thunderbolt', 'Thunder Wave', 'Supersonic', 'Double-Edge'];
|
||||
break;
|
||||
case 'Magneton':
|
||||
set.evs = { hp: 121, atk: 120, def: 120, spa: 120, spd: 120, spe: 120 };
|
||||
set.ivs = { hp: 6, atk: 8, def: 8, spa: 6, spd: 6, spe: 6 };
|
||||
set.moves = ['Thunderbolt', 'Screech', 'Supersonic', 'Swift'];
|
||||
break;
|
||||
case 'Farfetch\u2019d':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Slash', 'Sand Attack', 'Toxic', 'Fly'];
|
||||
break;
|
||||
case 'Doduo':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Drill Peck', 'Tri Attack', 'Double Team', 'Reflect'];
|
||||
break;
|
||||
case 'Dodrio':
|
||||
set.evs = { hp: 121, atk: 120, def: 120, spa: 120, spd: 120, spe: 120 };
|
||||
set.ivs = { hp: 6, atk: 8, def: 8, spa: 6, spd: 6, spe: 6 };
|
||||
set.moves = ['Fly', 'Tri Attack', 'Agility', 'Reflect'];
|
||||
break;
|
||||
case 'Seel':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Ice Beam', 'Body Slam', 'Horn Drill', 'Surf'];
|
||||
break;
|
||||
case 'Dewgong':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Aurora Beam', 'Heabutt', 'Rest', 'Surf'];
|
||||
break;
|
||||
case 'Grimer':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Sludge', 'Body Slam', 'Explosion', 'Screech'];
|
||||
break;
|
||||
case 'Muk':
|
||||
set.evs = { hp: 121, atk: 120, def: 120, spa: 120, spd: 120, spe: 120 };
|
||||
set.ivs = { hp: 6, atk: 8, def: 8, spa: 6, spd: 6, spe: 6 };
|
||||
set.moves = ['Sludge', 'Thunderbolt', 'Hyper Beam', 'Self-Destruct'];
|
||||
break;
|
||||
case 'Shellder':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Surf', 'Explosion', 'Blizzard', 'Tri Attack'];
|
||||
break;
|
||||
case 'Cloyster':
|
||||
set.evs = { hp: 105, atk: 104, def: 104, spa: 104, spd: 104, spe: 104 };
|
||||
set.ivs = { hp: 0, atk: 0, def: 0, spa: 0, spd: 0, spe: 0 };
|
||||
set.moves = ['Clamp', 'Spike Cannon', 'Ice Beam', 'Supersonic'];
|
||||
break;
|
||||
case 'Gastly':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Hypnosis', 'Dream Eater', 'Psychic', 'Confuse Ray'];
|
||||
break;
|
||||
case 'Haunter':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Mega Drain', 'Psychic', 'Explosion', 'Confuse Ray'];
|
||||
break;
|
||||
case 'Gengar':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Thunderbolt', 'Night Shade', 'Hypnosis', 'Confuse Ray'];
|
||||
break;
|
||||
case 'Onix':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Earthquake', 'Rock Slide', 'Strength', 'Explosion'];
|
||||
break;
|
||||
case 'Drowzee':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Hypnois', 'Dream Eater', 'Psychic', 'Tri Attack'];
|
||||
break;
|
||||
case 'Hypno':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Hypnosis', 'Headbutt', 'Dream Eater', 'Meditate'];
|
||||
break;
|
||||
case 'Krabby':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Crabhammer', 'Guillotine', 'Double-Edge', 'Blizzard'];
|
||||
break;
|
||||
case 'Kingler':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Crabhammer', 'Guillotine', 'Stomp', 'Substitute'];
|
||||
break;
|
||||
case 'Voltorb':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Thunderbolt', 'Thunder Wave', 'Swift', 'Explosion'];
|
||||
break;
|
||||
case 'Electrode':
|
||||
set.evs = { hp: 121, atk: 120, def: 120, spa: 120, spd: 120, spe: 120 };
|
||||
set.ivs = { hp: 6, atk: 8, def: 8, spa: 6, spd: 6, spe: 6 };
|
||||
set.moves = ['Thunder', 'Thunder Wave', 'Swift', 'Self-Destruct'];
|
||||
break;
|
||||
case 'Exeggcute':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Psychic', 'Explosion', 'Leech Seed', 'Toxic'];
|
||||
break;
|
||||
case 'Exeggutor':
|
||||
set.evs = { hp: 105, atk: 104, def: 104, spa: 104, spd: 104, spe: 104 };
|
||||
set.ivs = { hp: 0, atk: 0, def: 0, spa: 0, spd: 0, spe: 0 };
|
||||
set.moves = ['Mega Drain', 'Stun Spore', 'Leech Seed', 'Egg Bomb'];
|
||||
break;
|
||||
case 'Cubone':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Earthquake', 'Submission', 'Blizzard', 'Strength'];
|
||||
break;
|
||||
case 'Marowak':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Bonemerang', 'Thrash', 'Fire Blast', 'Focus Energy'];
|
||||
break;
|
||||
case 'Hitmonlee':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['High Jump Kick', 'Mega Kick', 'Metronome', 'Seismic Toss'];
|
||||
break;
|
||||
case 'Hitmonchan':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Submission', 'Thunder Punch', 'Ice Punch', 'Strength'];
|
||||
break;
|
||||
case 'Lickitung':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Strength', 'Blizzard', 'Thunder', 'Fire Blast'];
|
||||
break;
|
||||
case 'Koffing':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Sludge', 'Toxic', 'Thunderbolt', 'Explosion'];
|
||||
break;
|
||||
case 'Weezing':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Sludge', 'Hyper Beam', 'Fire Blast', 'Self-Destruct'];
|
||||
break;
|
||||
case 'Rhyhorn':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Earthquake', 'Body Slam', 'Rock Slide', 'Fire Blast'];
|
||||
break;
|
||||
case 'Rhydon':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Dig', 'Strength', 'Thunder', 'Surf'];
|
||||
break;
|
||||
case 'Chansey':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Thunder', 'Fire Blast', 'Minimize', 'Rest'];
|
||||
break;
|
||||
case 'Tangela':
|
||||
set.evs = { hp: 121, atk: 120, def: 120, spa: 120, spd: 120, spe: 120 };
|
||||
set.ivs = { hp: 6, atk: 8, def: 8, spa: 6, spd: 6, spe: 6 };
|
||||
set.moves = ['Mega Drain', 'Growth', 'Toxic', 'Double-Edge'];
|
||||
break;
|
||||
case 'Kangaskhan':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Dizzy Punch', 'Rock Slide', 'Surf', 'Thunderbolt'];
|
||||
break;
|
||||
case 'Horsea':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Hydro Pump', 'Toxic', 'Smokescreen', 'Ice Beam'];
|
||||
break;
|
||||
case 'Seadra':
|
||||
set.evs = { hp: 121, atk: 120, def: 120, spa: 120, spd: 120, spe: 120 };
|
||||
set.ivs = { hp: 6, atk: 8, def: 8, spa: 6, spd: 6, spe: 6 };
|
||||
set.moves = ['Surf', 'Toxic', 'Smokescreen', 'Swift'];
|
||||
break;
|
||||
case 'Goldeen':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Surf', 'Supersonic', 'Horn Drill', 'Blizzard'];
|
||||
break;
|
||||
case 'Seaking':
|
||||
set.evs = { hp: 121, atk: 120, def: 120, spa: 120, spd: 120, spe: 120 };
|
||||
set.ivs = { hp: 6, atk: 8, def: 8, spa: 6, spd: 6, spe: 6 };
|
||||
set.moves = ['Waterfall', 'Supersonic', 'Horn Attack', 'Ice Beam'];
|
||||
break;
|
||||
case 'Staryu':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Hydro Pump', 'Recover', 'Thunderbolt', 'Psychic'];
|
||||
break;
|
||||
case 'Starmie':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Surf', 'Thunder', 'Swift', 'Harden'];
|
||||
break;
|
||||
case 'Mr. Mime':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Barrier', 'Psychic', 'Metronome', 'Seismic Toss'];
|
||||
break;
|
||||
case 'Scyther':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Slash', 'Wing Attack', 'Leer', 'Double Team'];
|
||||
break;
|
||||
case 'Jynx':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Ice Punch', 'Mega Punch', 'Psychic', 'Lovely Kiss'];
|
||||
break;
|
||||
case 'Electabuzz':
|
||||
set.evs = { hp: 121, atk: 120, def: 120, spa: 120, spd: 120, spe: 120 };
|
||||
set.ivs = { hp: 6, atk: 8, def: 8, spa: 6, spd: 6, spe: 6 };
|
||||
set.moves = ['Thunder Punch', 'Mega Punch', 'Psychic', 'Thunder Wave'];
|
||||
break;
|
||||
case 'Magmar':
|
||||
set.evs = { hp: 121, atk: 120, def: 120, spa: 120, spd: 120, spe: 120 };
|
||||
set.ivs = { hp: 6, atk: 8, def: 8, spa: 6, spd: 6, spe: 6 };
|
||||
set.moves = ['Fire Punch', 'Mega Punch', 'Psychic', 'Smokescreen'];
|
||||
break;
|
||||
case 'Pinsir':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Strength', 'Harden', 'Seismic Toss', 'Guillotine'];
|
||||
break;
|
||||
case 'Tauros':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Double-Edge', 'Fire Blast', 'Tail Whip', 'Bide'];
|
||||
break;
|
||||
case 'Magikarp':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Splash', 'Tackle'];
|
||||
break;
|
||||
case 'Gyarados':
|
||||
set.evs = { hp: 105, atk: 104, def: 104, spa: 104, spd: 104, spe: 104 };
|
||||
set.ivs = { hp: 0, atk: 0, def: 0, spa: 0, spd: 0, spe: 0 };
|
||||
set.moves = ['Surf', 'Dragon Rage', 'Bite', 'Fire Blast'];
|
||||
break;
|
||||
case 'Lapras':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Ice Beam', 'Solar Beam', 'Body Slam', 'Sing'];
|
||||
break;
|
||||
case 'Ditto':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Transform'];
|
||||
break;
|
||||
case 'Eevee':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Body Slam', 'Swift', 'Sand Attack', 'Toxic'];
|
||||
break;
|
||||
case 'Vaporeon':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Surf', 'Quick Attack', 'Sand Attack', 'Acid Armor'];
|
||||
break;
|
||||
case 'Jolteon':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Thunderbolt', 'Pin Missile', 'Toxic', 'Sand Attack'];
|
||||
break;
|
||||
case 'Flareon':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Fire Blast', 'Take Down', 'Smog', 'Sand Attack'];
|
||||
break;
|
||||
case 'Omanyte':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Surf', 'Ice Beam', 'Double Edge', 'Double Team'];
|
||||
break;
|
||||
case 'Omastar':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Hydro Pump', 'Submission', 'Spike Cannon', 'Withdraw'];
|
||||
break;
|
||||
case 'Kabuto':
|
||||
set.evs = { hp: 145, atk: 144, def: 144, spa: 144, spd: 144, spe: 144 };
|
||||
set.ivs = { hp: 12, atk: 12, def: 10, spa: 12, spd: 12, spe: 10 };
|
||||
set.moves = ['Hydro Pump', 'Blizzard', 'Slash', 'Double Team'];
|
||||
break;
|
||||
case 'Kabutops':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Surf', 'Swords Dance', 'Mega Kick', 'Submission'];
|
||||
break;
|
||||
case 'Aerodactyl':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Fly', 'Hyper Beam', 'Supersonic', 'Dragon Rage'];
|
||||
break;
|
||||
case 'Snorlax':
|
||||
set.evs = { hp: 113, atk: 112, def: 112, spa: 112, spd: 112, spe: 112 };
|
||||
set.ivs = { hp: 4, atk: 4, def: 4, spa: 4, spd: 4, spe: 6 };
|
||||
set.moves = ['Mega Kick', 'Rock Slide', 'Metronome', 'Rest'];
|
||||
break;
|
||||
case 'Articuno':
|
||||
set.evs = { hp: 97, atk: 96, def: 96, spa: 96, spd: 96, spe: 96 };
|
||||
set.ivs = { hp: 0, atk: 0, def: 0, spa: 0, spd: 0, spe: 0 };
|
||||
set.moves = ['Ice Beam', 'Sky Attack', 'Razor Wind', 'Substitute'];
|
||||
break;
|
||||
case 'Zapdos':
|
||||
set.evs = { hp: 97, atk: 96, def: 96, spa: 96, spd: 96, spe: 96 };
|
||||
set.ivs = { hp: 0, atk: 0, def: 0, spa: 0, spd: 0, spe: 0 };
|
||||
set.moves = ['Thunderbolt', 'Sky Attack', 'Thunder Wave', 'Flash'];
|
||||
break;
|
||||
case 'Moltres':
|
||||
set.evs = { hp: 97, atk: 96, def: 96, spa: 96, spd: 96, spe: 96 };
|
||||
set.ivs = { hp: 0, atk: 0, def: 0, spa: 0, spd: 0, spe: 0 };
|
||||
set.moves = ['Fire Blast', 'Fly', 'Swift', 'Substitute'];
|
||||
break;
|
||||
case 'Dratini':
|
||||
set.evs = { hp: 161, atk: 160, def: 160, spa: 160, spd: 160, spe: 160 };
|
||||
set.ivs = { hp: 14, atk: 12, def: 14, spa: 14, spd: 14, spe: 14 };
|
||||
set.moves = ['Hyper Beam', 'Body Slam', 'Thunderbolt', 'Thunder Wave'];
|
||||
break;
|
||||
case 'Dragonair':
|
||||
set.evs = { hp: 129, atk: 128, def: 128, spa: 128, spd: 128, spe: 128 };
|
||||
set.ivs = { hp: 10, atk: 8, def: 10, spa: 10, spd: 10, spe: 8 };
|
||||
set.moves = ['Hyper Beam', 'Swift', 'Ice Beam', 'Thunder Wave'];
|
||||
break;
|
||||
case 'Dragonite':
|
||||
set.evs = { hp: 97, atk: 96, def: 96, spa: 96, spd: 96, spe: 96 };
|
||||
set.ivs = { hp: 0, atk: 0, def: 0, spa: 0, spd: 0, spe: 0 };
|
||||
set.moves = ['Slam', 'Dragon Rage', 'Thunder', 'Agility'];
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -93,8 +93,7 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
return;
|
||||
}
|
||||
}
|
||||
let lockedMove = this.battle.runEvent('LockMove', pokemon);
|
||||
if (lockedMove === true) lockedMove = false;
|
||||
const lockedMove = pokemon.getLockedMove() || pokemon.getSemiLockedMove();
|
||||
if (
|
||||
!lockedMove &&
|
||||
(!pokemon.volatiles['partialtrappinglock'] || pokemon.volatiles['partialtrappinglock'].locked !== target)
|
||||
|
|
@ -332,7 +331,7 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
let i: number;
|
||||
for (i = 0; i < hits && target.hp && pokemon.hp; i++) {
|
||||
move.hit = i + 1;
|
||||
if (move.hit === hits) move.lastHit = true;
|
||||
move.lastHit = move.hit === hits;
|
||||
moveDamage = this.moveHit(target, pokemon, move);
|
||||
if (moveDamage === false) break;
|
||||
damage = (moveDamage || 0);
|
||||
|
|
|
|||
|
|
@ -62,8 +62,8 @@ export const Conditions: import('../../../sim/dex-conditions').ModdedConditionDa
|
|||
this.add('cant', pokemon, 'frz');
|
||||
return false;
|
||||
},
|
||||
onModifyMove() {},
|
||||
onDamagingHit() {},
|
||||
onModifyMove: undefined, // no inherit
|
||||
onDamagingHit: undefined, // no inherit
|
||||
onAfterMoveSecondary(target, source, move) {
|
||||
if ((move.secondary && move.secondary.status === 'brn') || move.statusRoll === 'brn') {
|
||||
target.cureStatus();
|
||||
|
|
@ -187,7 +187,7 @@ export const Conditions: import('../../../sim/dex-conditions').ModdedConditionDa
|
|||
delete target.volatiles['confusion'];
|
||||
if (!target.side.getSideCondition('safeguard')) target.addVolatile('confusion');
|
||||
},
|
||||
onLockMove(pokemon) {
|
||||
onLockMove() {
|
||||
return this.effectState.move;
|
||||
},
|
||||
onMoveAborted(pokemon) {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
|
|||
tier: "LC",
|
||||
},
|
||||
charmeleon: {
|
||||
tier: "ZU",
|
||||
tier: "ZUBL",
|
||||
},
|
||||
charizard: {
|
||||
tier: "UUBL",
|
||||
|
|
@ -57,7 +57,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
|
|||
tier: "LC",
|
||||
},
|
||||
raticate: {
|
||||
tier: "NU",
|
||||
tier: "PU",
|
||||
},
|
||||
spearow: {
|
||||
tier: "LC",
|
||||
|
|
@ -69,7 +69,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
|
|||
tier: "LC",
|
||||
},
|
||||
arbok: {
|
||||
tier: "NU",
|
||||
tier: "PU",
|
||||
},
|
||||
pichu: {
|
||||
tier: "LC",
|
||||
|
|
@ -267,7 +267,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
|
|||
tier: "UU",
|
||||
},
|
||||
farfetchd: {
|
||||
tier: "NU",
|
||||
tier: "PU",
|
||||
},
|
||||
doduo: {
|
||||
tier: "ZU",
|
||||
|
|
@ -345,10 +345,10 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
|
|||
tier: "NU",
|
||||
},
|
||||
hitmonchan: {
|
||||
tier: "PUBL",
|
||||
tier: "PU",
|
||||
},
|
||||
hitmontop: {
|
||||
tier: "PU",
|
||||
tier: "NU",
|
||||
},
|
||||
lickitung: {
|
||||
tier: "NU",
|
||||
|
|
@ -540,7 +540,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
|
|||
tier: "LC",
|
||||
},
|
||||
furret: {
|
||||
tier: "PUBL",
|
||||
tier: "PU",
|
||||
},
|
||||
hoothoot: {
|
||||
tier: "LC",
|
||||
|
|
@ -558,7 +558,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
|
|||
tier: "LC",
|
||||
},
|
||||
ariados: {
|
||||
tier: "ZU",
|
||||
tier: "ZUBL",
|
||||
},
|
||||
chinchou: {
|
||||
tier: "NU",
|
||||
|
|
@ -591,7 +591,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
|
|||
tier: "LC",
|
||||
},
|
||||
azumarill: {
|
||||
tier: "NU",
|
||||
tier: "PU",
|
||||
},
|
||||
sudowoodo: {
|
||||
tier: "NU",
|
||||
|
|
@ -645,7 +645,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
|
|||
tier: "OU",
|
||||
},
|
||||
dunsparce: {
|
||||
tier: "NU",
|
||||
tier: "PU",
|
||||
},
|
||||
gligar: {
|
||||
tier: "UU",
|
||||
|
|
@ -705,7 +705,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
|
|||
tier: "OU",
|
||||
},
|
||||
houndour: {
|
||||
tier: "NU",
|
||||
tier: "PU",
|
||||
},
|
||||
houndoom: {
|
||||
tier: "UUBL",
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
blackbelt: {
|
||||
inherit: true,
|
||||
onModifyAtk() {},
|
||||
onModifyAtk: undefined, // no inherit
|
||||
onModifyDamage(damage, source, target, move) {
|
||||
if (move?.type === 'Fighting') {
|
||||
return damage * 1.1;
|
||||
|
|
@ -14,7 +14,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
blackglasses: {
|
||||
inherit: true,
|
||||
onModifySpA() {},
|
||||
onModifySpA: undefined, // no inherit
|
||||
onModifyDamage(damage, source, target, move) {
|
||||
if (move?.type === 'Dark') {
|
||||
return damage * 1.1;
|
||||
|
|
@ -31,7 +31,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
charcoal: {
|
||||
inherit: true,
|
||||
onModifySpA() {},
|
||||
onModifySpA: undefined, // no inherit
|
||||
onModifyDamage(damage, source, target, move) {
|
||||
if (move?.type === 'Fire') {
|
||||
return damage * 1.1;
|
||||
|
|
@ -40,7 +40,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
dragonfang: {
|
||||
inherit: true,
|
||||
onModifySpA() {},
|
||||
onModifySpA: undefined, // no inherit
|
||||
},
|
||||
dragonscale: {
|
||||
inherit: true,
|
||||
|
|
@ -65,7 +65,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
hardstone: {
|
||||
inherit: true,
|
||||
onModifyAtk() {},
|
||||
onModifyAtk: undefined, // no inherit
|
||||
onModifyDamage(damage, source, target, move) {
|
||||
if (move?.type === 'Rock') {
|
||||
return damage * 1.1;
|
||||
|
|
@ -106,7 +106,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
lightball: {
|
||||
inherit: true,
|
||||
// In Gen 2 this happens in stat calculation directly.
|
||||
onModifySpA() {},
|
||||
onModifySpA: undefined, // no inherit
|
||||
},
|
||||
loveball: {
|
||||
inherit: true,
|
||||
|
|
@ -127,7 +127,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
magnet: {
|
||||
inherit: true,
|
||||
onModifySpA() {},
|
||||
onModifySpA: undefined, // no inherit
|
||||
onModifyDamage(damage, source, target, move) {
|
||||
if (move?.type === 'Electric') {
|
||||
return damage * 1.1;
|
||||
|
|
@ -136,7 +136,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
metalcoat: {
|
||||
inherit: true,
|
||||
onModifyAtk() {},
|
||||
onModifyAtk: undefined, // no inherit
|
||||
onModifyDamage(damage, source, target, move) {
|
||||
if (move?.type === 'Steel') {
|
||||
return damage * 1.1;
|
||||
|
|
@ -146,12 +146,12 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
metalpowder: {
|
||||
inherit: true,
|
||||
// In Gen 2 this happens in stat calculation directly.
|
||||
onModifyDef() {},
|
||||
onModifySpD() {},
|
||||
onModifyDef: undefined, // no inherit
|
||||
onModifySpD: undefined, // no inherit
|
||||
},
|
||||
miracleseed: {
|
||||
inherit: true,
|
||||
onModifySpA() {},
|
||||
onModifySpA: undefined, // no inherit
|
||||
onModifyDamage(damage, source, target, move) {
|
||||
if (move?.type === 'Grass') {
|
||||
return damage * 1.1;
|
||||
|
|
@ -164,7 +164,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
mysticwater: {
|
||||
inherit: true,
|
||||
onModifySpA() {},
|
||||
onModifySpA: undefined, // no inherit
|
||||
onModifyDamage(damage, source, target, move) {
|
||||
if (move?.type === 'Water') {
|
||||
return damage * 1.1;
|
||||
|
|
@ -173,7 +173,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
nevermeltice: {
|
||||
inherit: true,
|
||||
onModifySpA() {},
|
||||
onModifySpA: undefined, // no inherit
|
||||
onModifyDamage(damage, source, target, move) {
|
||||
if (move?.type === 'Ice') {
|
||||
return damage * 1.1;
|
||||
|
|
@ -182,7 +182,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
poisonbarb: {
|
||||
inherit: true,
|
||||
onModifyAtk() {},
|
||||
onModifyAtk: undefined, // no inherit
|
||||
onModifyDamage(damage, source, target, move) {
|
||||
if (move?.type === 'Poison') {
|
||||
return damage * 1.1;
|
||||
|
|
@ -191,7 +191,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
sharpbeak: {
|
||||
inherit: true,
|
||||
onModifyAtk() {},
|
||||
onModifyAtk: undefined, // no inherit
|
||||
onModifyDamage(damage, source, target, move) {
|
||||
if (move?.type === 'Flying') {
|
||||
return damage * 1.1;
|
||||
|
|
@ -200,7 +200,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
silverpowder: {
|
||||
inherit: true,
|
||||
onModifyAtk() {},
|
||||
onModifyAtk: undefined, // no inherit
|
||||
onModifyDamage(damage, source, target, move) {
|
||||
if (move?.type === 'Bug') {
|
||||
return damage * 1.1;
|
||||
|
|
@ -209,7 +209,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
softsand: {
|
||||
inherit: true,
|
||||
onModifyAtk() {},
|
||||
onModifyAtk: undefined, // no inherit
|
||||
onModifyDamage(damage, source, target, move) {
|
||||
if (move?.type === 'Ground') {
|
||||
return damage * 1.1;
|
||||
|
|
@ -218,7 +218,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
spelltag: {
|
||||
inherit: true,
|
||||
onModifyAtk() {},
|
||||
onModifyAtk: undefined, // no inherit
|
||||
onModifyDamage(damage, source, target, move) {
|
||||
if (move?.type === 'Ghost') {
|
||||
return damage * 1.1;
|
||||
|
|
@ -241,11 +241,11 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
thickclub: {
|
||||
inherit: true,
|
||||
// In Gen 2 this happens in stat calculation directly.
|
||||
onModifyAtk() {},
|
||||
onModifyAtk: undefined, // no inherit
|
||||
},
|
||||
twistedspoon: {
|
||||
inherit: true,
|
||||
onModifySpA() {},
|
||||
onModifySpA: undefined, // no inherit
|
||||
onModifyDamage(damage, source, target, move) {
|
||||
if (move?.type === 'Psychic') {
|
||||
return damage * 1.1;
|
||||
|
|
@ -290,7 +290,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
pinkbow: {
|
||||
inherit: true,
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
onModifyDamage(damage, source, target, move) {
|
||||
if (move?.type === 'Normal') {
|
||||
return damage * 1.1;
|
||||
|
|
@ -300,7 +300,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
polkadotbow: {
|
||||
inherit: true,
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
onModifyDamage(damage, source, target, move) {
|
||||
if (move?.type === 'Normal') {
|
||||
return damage * 1.1;
|
||||
|
|
|
|||
|
|
@ -51,64 +51,12 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
bide: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 3,
|
||||
inherit: true,
|
||||
durationCallback(target, source, effect) {
|
||||
return this.random(3, 5);
|
||||
},
|
||||
onLockMove: 'bide',
|
||||
onStart(pokemon) {
|
||||
this.effectState.totalDamage = 0;
|
||||
this.add('-start', pokemon, 'move: Bide');
|
||||
},
|
||||
onDamagePriority: -101,
|
||||
onDamage(damage, target, source, move) {
|
||||
if (!move || move.effectType !== 'Move' || !source) return;
|
||||
this.effectState.totalDamage += damage;
|
||||
this.effectState.lastDamageSource = source;
|
||||
},
|
||||
onBeforeMove(pokemon, target, move) {
|
||||
if (this.effectState.duration === 1) {
|
||||
this.add('-end', pokemon, 'move: Bide');
|
||||
if (!this.effectState.totalDamage) {
|
||||
this.add('-fail', pokemon);
|
||||
return false;
|
||||
}
|
||||
target = this.effectState.lastDamageSource;
|
||||
if (!target) {
|
||||
this.add('-fail', pokemon);
|
||||
return false;
|
||||
}
|
||||
if (!target.isActive) {
|
||||
const possibleTarget = this.getRandomTarget(pokemon, this.dex.moves.get('pound'));
|
||||
if (!possibleTarget) {
|
||||
this.add('-miss', pokemon);
|
||||
return false;
|
||||
}
|
||||
target = possibleTarget;
|
||||
}
|
||||
const moveData = {
|
||||
id: 'bide',
|
||||
name: "Bide",
|
||||
accuracy: 100,
|
||||
damage: this.effectState.totalDamage * 2,
|
||||
category: "Physical",
|
||||
priority: 0,
|
||||
flags: { contact: 1, protect: 1 },
|
||||
effectType: 'Move',
|
||||
type: 'Normal',
|
||||
} as unknown as ActiveMove;
|
||||
this.actions.tryMoveHit(target, pokemon, moveData);
|
||||
pokemon.removeVolatile('bide');
|
||||
return false;
|
||||
}
|
||||
this.add('-activate', pokemon, 'move: Bide');
|
||||
},
|
||||
onMoveAborted(pokemon) {
|
||||
pokemon.removeVolatile('bide');
|
||||
},
|
||||
onEnd(pokemon) {
|
||||
this.add('-end', pokemon, 'move: Bide', '[silent]');
|
||||
},
|
||||
onLockMove: undefined, // no inherit
|
||||
onSemiLockMove: 'bide',
|
||||
},
|
||||
},
|
||||
counter: {
|
||||
|
|
@ -123,8 +71,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
return false;
|
||||
},
|
||||
beforeTurnCallback() {},
|
||||
onTry() {},
|
||||
beforeTurnCallback: undefined, // no inherit
|
||||
onTry: undefined, // no inherit
|
||||
condition: {},
|
||||
priority: -1,
|
||||
},
|
||||
|
|
@ -139,12 +87,12 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
curse: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
onStart(pokemon, source) {
|
||||
this.add('-start', pokemon, 'Curse', `[of] ${source}`);
|
||||
},
|
||||
inherit: true,
|
||||
onAfterMoveSelfPriority: 0, // explicit
|
||||
onAfterMoveSelf(pokemon) {
|
||||
this.damage(pokemon.baseMaxhp / 4);
|
||||
},
|
||||
onResidual: undefined, // no inherit
|
||||
},
|
||||
},
|
||||
detect: {
|
||||
|
|
@ -157,10 +105,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
return source.status !== 'slp';
|
||||
},
|
||||
condition: {
|
||||
duration: 2,
|
||||
onImmunity(type, pokemon) {
|
||||
if (type === 'sandstorm') return false;
|
||||
},
|
||||
inherit: true,
|
||||
onInvulnerability(target, source, move) {
|
||||
if (move.id === 'earthquake' || move.id === 'magnitude' || move.id === 'fissure') {
|
||||
return;
|
||||
|
|
@ -172,6 +117,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
if (source.volatiles['lockon'] && target === source.volatiles['lockon'].source) return;
|
||||
return false;
|
||||
},
|
||||
onSourceModifyDamage: undefined, // no inherit
|
||||
onSourceBasePower(basePower, target, source, move) {
|
||||
if (move.id === 'earthquake' || move.id === 'magnitude') {
|
||||
return this.chainModify(2);
|
||||
|
|
@ -186,9 +132,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
encore: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
durationCallback() {
|
||||
return this.random(3, 7);
|
||||
},
|
||||
inherit: true,
|
||||
onStart(target) {
|
||||
const lockedMove = target.lastMoveEncore?.id || '';
|
||||
const moveSlot = lockedMove ? target.getMoveData(lockedMove) : null;
|
||||
|
|
@ -199,30 +143,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
this.effectState.move = lockedMove;
|
||||
this.add('-start', target, 'Encore');
|
||||
},
|
||||
onOverrideAction(pokemon) {
|
||||
return this.effectState.move;
|
||||
},
|
||||
onResidualOrder: 13,
|
||||
onResidual(target) {
|
||||
const lockedMoveSlot = target.getMoveData(this.effectState.move);
|
||||
if (lockedMoveSlot && lockedMoveSlot.pp <= 0) {
|
||||
// early termination if you run out of PP
|
||||
target.removeVolatile('encore');
|
||||
}
|
||||
},
|
||||
onEnd(target) {
|
||||
this.add('-end', target, 'Encore');
|
||||
},
|
||||
onDisableMove(pokemon) {
|
||||
if (!this.effectState.move || !pokemon.hasMove(this.effectState.move)) {
|
||||
return;
|
||||
}
|
||||
for (const moveSlot of pokemon.moveSlots) {
|
||||
if (moveSlot.id !== this.effectState.move) {
|
||||
pokemon.disableMove(moveSlot.id);
|
||||
}
|
||||
}
|
||||
},
|
||||
onResidualSubOrder: undefined, // no inherit
|
||||
},
|
||||
},
|
||||
endure: {
|
||||
|
|
@ -244,7 +166,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
return source.status !== 'slp';
|
||||
},
|
||||
condition: {
|
||||
duration: 2,
|
||||
inherit: true,
|
||||
onInvulnerability(target, source, move) {
|
||||
if (move.id === 'gust' || move.id === 'twister' || move.id === 'thunder' || move.id === 'whirlwind') {
|
||||
return;
|
||||
|
|
@ -260,6 +182,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
if (source.volatiles['lockon'] && target === source.volatiles['lockon'].source) return;
|
||||
return false;
|
||||
},
|
||||
onSourceModifyDamage: undefined, // no inherit
|
||||
onSourceBasePower(basePower, target, source, move) {
|
||||
if (move.id === 'gust' || move.id === 'twister') {
|
||||
return this.chainModify(2);
|
||||
|
|
@ -270,9 +193,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
focusenergy: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
onStart(pokemon) {
|
||||
this.add('-start', pokemon, 'move: Focus Energy');
|
||||
},
|
||||
inherit: true,
|
||||
onModifyCritRatio(critRatio) {
|
||||
return critRatio + 1;
|
||||
},
|
||||
|
|
@ -284,17 +205,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
if (target.volatiles['foresight']) return false;
|
||||
},
|
||||
condition: {
|
||||
onStart(pokemon) {
|
||||
this.add('-start', pokemon, 'Foresight');
|
||||
},
|
||||
onNegateImmunity(pokemon, type) {
|
||||
if (pokemon.hasType('Ghost') && ['Normal', 'Fighting'].includes(type)) return false;
|
||||
},
|
||||
onModifyBoost(boosts) {
|
||||
if (boosts.evasion && boosts.evasion > 0) {
|
||||
boosts.evasion = 0;
|
||||
}
|
||||
},
|
||||
inherit: true,
|
||||
noCopy: false,
|
||||
},
|
||||
},
|
||||
frustration: {
|
||||
|
|
@ -338,11 +250,10 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
leechseed: {
|
||||
inherit: true,
|
||||
onHit() {},
|
||||
onHit: undefined, // no inherit
|
||||
condition: {
|
||||
onStart(target) {
|
||||
this.add('-start', target, 'move: Leech Seed');
|
||||
},
|
||||
inherit: true,
|
||||
onResidual: undefined, // no inherit
|
||||
onAfterMoveSelfPriority: 2,
|
||||
onAfterMoveSelf(pokemon) {
|
||||
if (!pokemon.hp) return;
|
||||
|
|
@ -378,19 +289,15 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
if (target.volatiles['foresight'] || target.volatiles['lockon']) return false;
|
||||
},
|
||||
condition: {
|
||||
duration: 2,
|
||||
onSourceAccuracy(accuracy, target, source, move) {
|
||||
if (move && source === this.effectState.target && target === this.effectState.source) return true;
|
||||
},
|
||||
inherit: true,
|
||||
onSourceInvulnerability: undefined, // no inherit
|
||||
},
|
||||
},
|
||||
lowkick: {
|
||||
inherit: true,
|
||||
accuracy: 90,
|
||||
basePower: 50,
|
||||
basePowerCallback() {
|
||||
return 50;
|
||||
},
|
||||
basePowerCallback: undefined, // no inherit
|
||||
secondary: {
|
||||
chance: 30,
|
||||
volatileStatus: 'flinch',
|
||||
|
|
@ -427,8 +334,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
return false;
|
||||
},
|
||||
beforeTurnCallback() {},
|
||||
onTry() {},
|
||||
beforeTurnCallback: undefined, // no inherit
|
||||
onTry: undefined, // no inherit
|
||||
condition: {},
|
||||
priority: -1,
|
||||
},
|
||||
|
|
@ -449,15 +356,9 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
},
|
||||
mist: {
|
||||
num: 54,
|
||||
accuracy: true,
|
||||
basePower: 0,
|
||||
category: "Status",
|
||||
name: "Mist",
|
||||
pp: 30,
|
||||
priority: 0,
|
||||
flags: { metronome: 1 },
|
||||
inherit: true,
|
||||
volatileStatus: 'mist',
|
||||
sideCondition: undefined, // no inherit
|
||||
condition: {
|
||||
onStart(pokemon) {
|
||||
this.add('-start', pokemon, 'Mist');
|
||||
|
|
@ -478,9 +379,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
},
|
||||
},
|
||||
secondary: null,
|
||||
target: "self",
|
||||
type: "Ice",
|
||||
},
|
||||
moonlight: {
|
||||
inherit: true,
|
||||
|
|
@ -509,13 +408,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
nightmare: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
noCopy: true,
|
||||
onStart(pokemon) {
|
||||
if (pokemon.status !== 'slp') {
|
||||
return false;
|
||||
}
|
||||
this.add('-start', pokemon, 'Nightmare');
|
||||
},
|
||||
inherit: true,
|
||||
onResidual: undefined, // no inherit
|
||||
onAfterMoveSelfPriority: 1,
|
||||
onAfterMoveSelf(pokemon) {
|
||||
if (pokemon.status === 'slp') this.damage(pokemon.baseMaxhp / 4);
|
||||
|
|
@ -535,16 +429,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
perishsong: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 4,
|
||||
onEnd(target) {
|
||||
this.add('-start', target, 'perish0');
|
||||
target.faint();
|
||||
},
|
||||
inherit: true,
|
||||
onResidualOrder: 4,
|
||||
onResidual(pokemon) {
|
||||
const duration = pokemon.volatiles['perishsong'].duration;
|
||||
this.add('-start', pokemon, `perish${duration}`);
|
||||
},
|
||||
},
|
||||
},
|
||||
petaldance: {
|
||||
|
|
@ -573,9 +459,18 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
pursuit: {
|
||||
inherit: true,
|
||||
onModifyMove() {},
|
||||
beforeTurnCallback(pokemon, target) {
|
||||
if (pokemon.isAlly(target)) return;
|
||||
target.addVolatile('pursuit');
|
||||
const data = target.volatiles['pursuit'];
|
||||
if (!data.sources) {
|
||||
data.sources = [];
|
||||
}
|
||||
data.sources.push(pokemon);
|
||||
},
|
||||
onModifyMove: undefined, // no inherit
|
||||
condition: {
|
||||
duration: 1,
|
||||
inherit: true,
|
||||
onBeforeSwitchOut(pokemon) {
|
||||
this.debug('Pursuit start');
|
||||
let alreadyAdded = false;
|
||||
|
|
@ -649,7 +544,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
target.statusState.source = target;
|
||||
this.heal(target.maxhp);
|
||||
},
|
||||
secondary: null,
|
||||
},
|
||||
return: {
|
||||
inherit: true,
|
||||
|
|
@ -675,41 +569,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
safeguard: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 5,
|
||||
durationCallback(target, source, effect) {
|
||||
if (source?.hasAbility('persistent')) {
|
||||
this.add('-activate', source, 'ability: Persistent', effect);
|
||||
return 7;
|
||||
}
|
||||
return 5;
|
||||
},
|
||||
onSetStatus(status, target, source, effect) {
|
||||
if (!effect || !source) return;
|
||||
if (effect.id === 'yawn') return;
|
||||
if (effect.effectType === 'Move' && effect.infiltrates && !target.isAlly(source)) return;
|
||||
if (target !== source) {
|
||||
this.debug('interrupting setStatus');
|
||||
if (effect.id === 'synchronize' || (effect.effectType === 'Move' && !effect.secondaries)) {
|
||||
this.add('-activate', target, 'move: Safeguard');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
},
|
||||
onTryAddVolatile(status, target, source, effect) {
|
||||
if (!effect || !source) return;
|
||||
if (effect.effectType === 'Move' && effect.infiltrates && !target.isAlly(source)) return;
|
||||
if ((status.id === 'confusion' || status.id === 'yawn') && target !== source) {
|
||||
if (effect.effectType === 'Move' && !effect.secondaries) this.add('-activate', target, 'move: Safeguard');
|
||||
return null;
|
||||
}
|
||||
},
|
||||
onSideStart(side) {
|
||||
this.add('-sidestart', side, 'Safeguard');
|
||||
},
|
||||
inherit: true,
|
||||
onSideResidualOrder: 8,
|
||||
onSideEnd(side) {
|
||||
this.add('-sideend', side, 'Safeguard');
|
||||
},
|
||||
},
|
||||
},
|
||||
selfdestruct: {
|
||||
|
|
@ -736,7 +597,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
onPrepareHit(target, source) {
|
||||
return source.status !== 'slp';
|
||||
},
|
||||
secondary: null,
|
||||
secondary: undefined, // no inherit
|
||||
},
|
||||
slash: {
|
||||
inherit: true,
|
||||
|
|
@ -766,7 +627,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
return source.status !== 'slp';
|
||||
},
|
||||
// Rain weakening done directly in the damage formula
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
},
|
||||
spiderweb: {
|
||||
inherit: true,
|
||||
|
|
@ -775,31 +636,14 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
spikes: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
// this is a side condition
|
||||
onSideStart(side) {
|
||||
if (!this.effectState.layers || this.effectState.layers === 0) {
|
||||
this.add('-sidestart', side, 'Spikes');
|
||||
this.effectState.layers = 1;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
onSwitchIn(pokemon) {
|
||||
if (!pokemon.runImmunity('Ground')) return;
|
||||
const damageAmounts = [0, 3];
|
||||
this.damage(damageAmounts[this.effectState.layers] * pokemon.maxhp / 24);
|
||||
},
|
||||
inherit: true,
|
||||
onSideRestart: undefined, // no inherit
|
||||
},
|
||||
},
|
||||
substitute: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
onStart(target) {
|
||||
this.add('-start', target, 'Substitute');
|
||||
this.effectState.hp = Math.floor(target.maxhp / 4);
|
||||
delete target.volatiles['partiallytrapped'];
|
||||
},
|
||||
onTryPrimaryHitPriority: -1,
|
||||
inherit: true,
|
||||
onTryPrimaryHit(target, source, move) {
|
||||
if (move.stallingMove) {
|
||||
this.add('-fail', source);
|
||||
|
|
@ -852,9 +696,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
this.runEvent('AfterSubDamage', target, source, move, damage);
|
||||
return this.HIT_SUBSTITUTE;
|
||||
},
|
||||
onEnd(target) {
|
||||
this.add('-end', target, 'Substitute');
|
||||
},
|
||||
},
|
||||
},
|
||||
swagger: {
|
||||
|
|
@ -880,7 +721,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
thief: {
|
||||
inherit: true,
|
||||
onAfterHit() {},
|
||||
onAfterHit: undefined, // no inherit
|
||||
secondary: {
|
||||
chance: 100,
|
||||
onHit(target, source) {
|
||||
|
|
@ -916,7 +757,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
triattack: {
|
||||
inherit: true,
|
||||
onHit(target, source, move) {
|
||||
move.statusRoll = ['par', 'frz', 'brn'][this.random(3)];
|
||||
move.statusRoll = this.sample(['par', 'frz', 'brn']);
|
||||
},
|
||||
secondary: {
|
||||
chance: 20,
|
||||
|
|
|
|||
|
|
@ -28,7 +28,10 @@ export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable
|
|||
standard: {
|
||||
effectType: 'ValidatorRule',
|
||||
name: 'Standard',
|
||||
ruleset: ['Obtainable', 'Sleep Clause Mod', 'Freeze Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Items Clause', 'Evasion Moves Clause', 'Endless battle Clause', 'HP Percentage Mod', 'Cancel Mod'],
|
||||
ruleset: [
|
||||
'Standard AG',
|
||||
'Sleep Clause Mod', 'Freeze Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Items Clause', 'Evasion Moves Clause',
|
||||
],
|
||||
banlist: [
|
||||
'Hypnosis + Mean Look',
|
||||
'Hypnosis + Spider Web',
|
||||
|
|
|
|||
|
|
@ -125,8 +125,7 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
}
|
||||
}
|
||||
pokemon.lastDamage = 0;
|
||||
let lockedMove = this.battle.runEvent('LockMove', pokemon);
|
||||
if (lockedMove === true) lockedMove = false;
|
||||
const lockedMove = pokemon.getLockedMove() || pokemon.getSemiLockedMove();
|
||||
if (!lockedMove) {
|
||||
if (!pokemon.deductPP(move, null, target) && (move.id !== 'struggle')) {
|
||||
this.battle.add('cant', pokemon, 'nopp', move);
|
||||
|
|
@ -273,7 +272,7 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
for (i = 0; i < hits && target.hp && pokemon.hp; i++) {
|
||||
if (pokemon.status === 'slp' && !isSleepUsable) break;
|
||||
move.hit = i + 1;
|
||||
if (move.hit === hits) move.lastHit = true;
|
||||
move.lastHit = move.hit === hits;
|
||||
moveDamage = this.moveHit(target, pokemon, move);
|
||||
if (moveDamage === false) break;
|
||||
if (nullDamage && (moveDamage || moveDamage === 0 || moveDamage === undefined)) nullDamage = false;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,6 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
dragonscale: {
|
||||
inherit: true,
|
||||
onModifyDamage() {},
|
||||
onModifyDamage: undefined, // no inherit
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,8 +1,17 @@
|
|||
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
|
||||
standardag: {
|
||||
inherit: true,
|
||||
ruleset: [
|
||||
'Obtainable', 'Team Preview', 'Exact HP Mod', 'Cancel Mod', 'Beat Up Nicknames Mod',
|
||||
],
|
||||
},
|
||||
standard: {
|
||||
effectType: 'ValidatorRule',
|
||||
name: 'Standard',
|
||||
ruleset: ['Obtainable', 'Team Preview', 'Stadium Sleep Clause', 'Freeze Clause Mod', 'Self-KO Clause', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Moves Clause', 'Exact HP Mod', 'Cancel Mod', 'Stadium Items Clause'],
|
||||
ruleset: [
|
||||
'Standard AG',
|
||||
'Stadium Sleep Clause', 'Freeze Clause Mod', 'Self-KO Clause', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Moves Clause', 'Stadium Items Clause',
|
||||
],
|
||||
},
|
||||
selfkoclause: {
|
||||
effectType: 'Rule',
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
for (i = 0; i < hits && target.hp && pokemon.hp; i++) {
|
||||
if (pokemon.status === 'slp' && !isSleepUsable) break;
|
||||
move.hit = i + 1;
|
||||
if (move.hit === hits) move.lastHit = true;
|
||||
move.lastHit = move.hit === hits;
|
||||
moveDamage = this.moveHit(target, pokemon, move);
|
||||
if (moveDamage === false) break;
|
||||
if (nullDamage && (moveDamage || moveDamage === 0 || moveDamage === undefined)) nullDamage = false;
|
||||
|
|
|
|||
|
|
@ -12,15 +12,9 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
effectspore: {
|
||||
inherit: true,
|
||||
onDamagingHit(damage, target, source, move) {
|
||||
if (damage && move.flags['contact'] && !source.status) {
|
||||
const r = this.random(300);
|
||||
if (r < 10) {
|
||||
source.setStatus('slp', target);
|
||||
} else if (r < 20) {
|
||||
source.setStatus('par', target);
|
||||
} else if (r < 30) {
|
||||
source.setStatus('psn', target);
|
||||
}
|
||||
if (damage && move.flags['contact'] && this.randomChance(1, 10)) {
|
||||
const status = this.sample(['slp', 'par', 'psn']);
|
||||
source.trySetStatus(status, target);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
@ -91,6 +85,8 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
},
|
||||
},
|
||||
lightningrod: {
|
||||
inherit: true,
|
||||
onAnyRedirectTarget: undefined, // no inherit
|
||||
onFoeRedirectTarget(target, source, source2, move) {
|
||||
// don't count Hidden Power as Electric-type
|
||||
if (this.dex.moves.get(move.id).type !== 'Electric') return;
|
||||
|
|
@ -98,15 +94,11 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
return this.effectState.target;
|
||||
}
|
||||
},
|
||||
flags: { breakable: 1 },
|
||||
name: "Lightning Rod",
|
||||
rating: 0,
|
||||
num: 32,
|
||||
},
|
||||
magnetpull: {
|
||||
inherit: true,
|
||||
onFoeTrapPokemon() {},
|
||||
onFoeMaybeTrapPokemon() {},
|
||||
onFoeTrapPokemon: undefined, // no inherit
|
||||
onFoeMaybeTrapPokemon: undefined, // no inherit
|
||||
onAnyTrapPokemon(pokemon) {
|
||||
if (pokemon.hasType('Steel') && pokemon.isAdjacent(this.effectState.target)) {
|
||||
pokemon.tryTrap(true);
|
||||
|
|
@ -158,7 +150,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
},
|
||||
raindish: {
|
||||
inherit: true,
|
||||
onWeather() {},
|
||||
onWeather: undefined, // no inherit
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 3,
|
||||
onResidual(pokemon) {
|
||||
|
|
@ -193,7 +185,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
},
|
||||
trace: {
|
||||
inherit: true,
|
||||
onUpdate() {},
|
||||
onUpdate: undefined, // no inherit
|
||||
onStart(pokemon) {
|
||||
const target = pokemon.side.randomFoe();
|
||||
if (!target || target.fainted) return;
|
||||
|
|
@ -204,7 +196,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
},
|
||||
truant: {
|
||||
inherit: true,
|
||||
onStart() {},
|
||||
onStart: undefined, // no inherit
|
||||
onSwitchIn(pokemon) {
|
||||
pokemon.truantTurn = this.turn !== 0;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -51,6 +51,6 @@ export const Conditions: import('../../../sim/dex-conditions').ModdedConditionDa
|
|||
},
|
||||
sandstorm: {
|
||||
inherit: true,
|
||||
onModifySpD() {},
|
||||
onModifySpD: undefined, // no inherit
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
|
|||
tier: "LC",
|
||||
},
|
||||
fearow: {
|
||||
tier: "UU",
|
||||
tier: "RUBL",
|
||||
},
|
||||
ekans: {
|
||||
tier: "LC",
|
||||
|
|
@ -312,7 +312,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
|
|||
tier: "ZU",
|
||||
},
|
||||
hypno: {
|
||||
tier: "UU",
|
||||
tier: "RU",
|
||||
},
|
||||
krabby: {
|
||||
tier: "LC",
|
||||
|
|
@ -930,7 +930,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
|
|||
tier: "LC",
|
||||
},
|
||||
manectric: {
|
||||
tier: "UU",
|
||||
tier: "RU",
|
||||
},
|
||||
plusle: {
|
||||
tier: "NU",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
||||
aguavberry: {
|
||||
inherit: true,
|
||||
onUpdate() {},
|
||||
onUpdate: undefined, // no inherit
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 4,
|
||||
onResidual(pokemon) {
|
||||
|
|
@ -12,7 +12,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
apicotberry: {
|
||||
inherit: true,
|
||||
onUpdate() {},
|
||||
onUpdate: undefined, // no inherit
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 4,
|
||||
onResidual(pokemon) {
|
||||
|
|
@ -23,7 +23,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
berryjuice: {
|
||||
inherit: true,
|
||||
onUpdate() {},
|
||||
onUpdate: undefined, // no inherit
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 4,
|
||||
onResidual(pokemon) {
|
||||
|
|
@ -37,7 +37,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
blackbelt: {
|
||||
inherit: true,
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
onModifyAtkPriority: 1,
|
||||
onModifyAtk(atk, user, target, move) {
|
||||
if (move?.type === 'Fighting') {
|
||||
|
|
@ -47,7 +47,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
blackglasses: {
|
||||
inherit: true,
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
onModifySpAPriority: 1,
|
||||
onModifySpA(spa, user, target, move) {
|
||||
if (move?.type === 'Dark') {
|
||||
|
|
@ -57,7 +57,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
charcoal: {
|
||||
inherit: true,
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
onModifySpAPriority: 1,
|
||||
onModifySpA(spa, user, target, move) {
|
||||
if (move?.type === 'Fire') {
|
||||
|
|
@ -67,7 +67,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
dragonfang: {
|
||||
inherit: true,
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
onModifySpAPriority: 1,
|
||||
onModifySpA(spa, user, target, move) {
|
||||
if (move?.type === 'Dragon') {
|
||||
|
|
@ -82,6 +82,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
num: 208,
|
||||
gen: 3,
|
||||
isNonstandard: "Unobtainable",
|
||||
// No competitive use
|
||||
},
|
||||
fastball: {
|
||||
inherit: true,
|
||||
|
|
@ -89,7 +90,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
figyberry: {
|
||||
inherit: true,
|
||||
onUpdate() {},
|
||||
onUpdate: undefined, // no inherit
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 4,
|
||||
onResidual(pokemon) {
|
||||
|
|
@ -100,7 +101,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
ganlonberry: {
|
||||
inherit: true,
|
||||
onUpdate() {},
|
||||
onUpdate: undefined, // no inherit
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 4,
|
||||
onResidual(pokemon) {
|
||||
|
|
@ -111,7 +112,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
hardstone: {
|
||||
inherit: true,
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
onModifyAtkPriority: 1,
|
||||
onModifyAtk(atk, user, target, move) {
|
||||
if (move?.type === 'Rock') {
|
||||
|
|
@ -125,7 +126,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
iapapaberry: {
|
||||
inherit: true,
|
||||
onUpdate() {},
|
||||
onUpdate: undefined, // no inherit
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 4,
|
||||
onResidual(pokemon) {
|
||||
|
|
@ -151,7 +152,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
lansatberry: {
|
||||
inherit: true,
|
||||
onUpdate() {},
|
||||
onUpdate: undefined, // no inherit
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 4,
|
||||
onResidual(pokemon) {
|
||||
|
|
@ -174,7 +175,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
liechiberry: {
|
||||
inherit: true,
|
||||
onUpdate() {},
|
||||
onUpdate: undefined, // no inherit
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 4,
|
||||
onResidual(pokemon) {
|
||||
|
|
@ -190,7 +191,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
return this.chainModify(2);
|
||||
}
|
||||
},
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
},
|
||||
loveball: {
|
||||
inherit: true,
|
||||
|
|
@ -202,7 +203,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
magnet: {
|
||||
inherit: true,
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
onModifySpAPriority: 1,
|
||||
onModifySpA(spa, user, target, move) {
|
||||
if (move?.type === 'Electric') {
|
||||
|
|
@ -212,7 +213,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
magoberry: {
|
||||
inherit: true,
|
||||
onUpdate() {},
|
||||
onUpdate: undefined, // no inherit
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 4,
|
||||
onResidual(pokemon) {
|
||||
|
|
@ -223,7 +224,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
metalcoat: {
|
||||
inherit: true,
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
onModifyAtkPriority: 1,
|
||||
onModifyAtk(atk, user, target, move) {
|
||||
if (move?.type === 'Steel') {
|
||||
|
|
@ -233,7 +234,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
miracleseed: {
|
||||
inherit: true,
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
onModifySpAPriority: 1,
|
||||
onModifySpA(spa, user, target, move) {
|
||||
if (move?.type === 'Grass') {
|
||||
|
|
@ -247,7 +248,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
mysticwater: {
|
||||
inherit: true,
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
onModifySpAPriority: 1,
|
||||
onModifySpA(spa, user, target, move) {
|
||||
if (move?.type === 'Water') {
|
||||
|
|
@ -257,7 +258,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
nevermeltice: {
|
||||
inherit: true,
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
onModifySpAPriority: 1,
|
||||
onModifySpA(spa, user, target, move) {
|
||||
if (move?.type === 'Ice') {
|
||||
|
|
@ -267,7 +268,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
oranberry: {
|
||||
inherit: true,
|
||||
onUpdate() {},
|
||||
onUpdate: undefined, // no inherit
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 4,
|
||||
onResidual(pokemon) {
|
||||
|
|
@ -278,7 +279,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
petayaberry: {
|
||||
inherit: true,
|
||||
onUpdate() {},
|
||||
onUpdate: undefined, // no inherit
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 4,
|
||||
onResidual(pokemon) {
|
||||
|
|
@ -289,7 +290,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
poisonbarb: {
|
||||
inherit: true,
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
onModifyAtkPriority: 1,
|
||||
onModifyAtk(atk, user, target, move) {
|
||||
if (move?.type === 'Poison') {
|
||||
|
|
@ -299,12 +300,12 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
quickclaw: {
|
||||
inherit: true,
|
||||
onFractionalPriority() {},
|
||||
onFractionalPriority: undefined, // no inherit
|
||||
// implemented in Pokemon#getActionSpeed()
|
||||
},
|
||||
salacberry: {
|
||||
inherit: true,
|
||||
onUpdate() {},
|
||||
onUpdate: undefined, // no inherit
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 4,
|
||||
onResidual(pokemon) {
|
||||
|
|
@ -315,7 +316,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
seaincense: {
|
||||
inherit: true,
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
onModifySpAPriority: 1,
|
||||
onModifySpA(spa, user, target, move) {
|
||||
if (move?.type === 'Water') {
|
||||
|
|
@ -325,7 +326,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
sharpbeak: {
|
||||
inherit: true,
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
onModifyAtkPriority: 1,
|
||||
onModifyAtk(atk, user, target, move) {
|
||||
if (move?.type === 'Flying') {
|
||||
|
|
@ -335,7 +336,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
silkscarf: {
|
||||
inherit: true,
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
onModifyAtkPriority: 1,
|
||||
onModifyAtk(atk, user, target, move) {
|
||||
if (move?.type === 'Normal') {
|
||||
|
|
@ -345,7 +346,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
silverpowder: {
|
||||
inherit: true,
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
onModifyAtkPriority: 1,
|
||||
onModifyAtk(atk, user, target, move) {
|
||||
if (move?.type === 'Bug') {
|
||||
|
|
@ -355,7 +356,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
sitrusberry: {
|
||||
inherit: true,
|
||||
onUpdate() {},
|
||||
onUpdate: undefined, // no inherit
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 4,
|
||||
onResidual(pokemon) {
|
||||
|
|
@ -369,7 +370,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
softsand: {
|
||||
inherit: true,
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
onModifyAtkPriority: 1,
|
||||
onModifyAtk(atk, user, target, move) {
|
||||
if (move?.type === 'Ground') {
|
||||
|
|
@ -379,7 +380,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
spelltag: {
|
||||
inherit: true,
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
onModifyAtkPriority: 1,
|
||||
onModifyAtk(atk, user, target, move) {
|
||||
if (move?.type === 'Ghost') {
|
||||
|
|
@ -393,7 +394,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
starfberry: {
|
||||
inherit: true,
|
||||
onUpdate() {},
|
||||
onUpdate: undefined, // no inherit
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 4,
|
||||
onResidual(pokemon) {
|
||||
|
|
@ -404,7 +405,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
twistedspoon: {
|
||||
inherit: true,
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
onModifySpAPriority: 1,
|
||||
onModifySpA(spa, user, target, move) {
|
||||
if (move?.type === 'Psychic') {
|
||||
|
|
@ -414,7 +415,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
wikiberry: {
|
||||
inherit: true,
|
||||
onUpdate() {},
|
||||
onUpdate: undefined, // no inherit
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 4,
|
||||
onResidual(pokemon) {
|
||||
|
|
|
|||
|
|
@ -26,10 +26,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
astonish: {
|
||||
inherit: true,
|
||||
basePowerCallback(pokemon, target) {
|
||||
if (target.volatiles['minimize']) return 60;
|
||||
return 30;
|
||||
},
|
||||
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1, minimize: 1 },
|
||||
},
|
||||
beatup: {
|
||||
inherit: true,
|
||||
|
|
@ -44,8 +41,9 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
duration: 1,
|
||||
onModifySpAPriority: -101,
|
||||
onModifySpA(atk, pokemon, defender, move) {
|
||||
// https://www.smogon.com/forums/posts/8992145/
|
||||
// this.add('-activate', pokemon, 'move: Beat Up', '[of] ' + move.allies![0].name);
|
||||
if (!this.ruleTable.has('beatupnicknamesmod')) {
|
||||
this.add('-activate', pokemon, 'move: Beat Up', '[of] ' + move.allies![0].name);
|
||||
}
|
||||
this.event.modifier = 1;
|
||||
return this.dex.species.get(move.allies!.shift()!.set.species).baseStats.atk;
|
||||
},
|
||||
|
|
@ -61,18 +59,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
accuracy: 100,
|
||||
priority: 0,
|
||||
condition: {
|
||||
duration: 3,
|
||||
onLockMove: 'bide',
|
||||
onStart(pokemon) {
|
||||
this.effectState.totalDamage = 0;
|
||||
this.add('-start', pokemon, 'move: Bide');
|
||||
},
|
||||
onDamagePriority: -101,
|
||||
onDamage(damage, target, source, move) {
|
||||
if (!move || move.effectType !== 'Move' || !source) return;
|
||||
this.effectState.totalDamage += damage;
|
||||
this.effectState.lastDamageSource = source;
|
||||
},
|
||||
inherit: true,
|
||||
onAfterSetStatus: undefined, // no inherit
|
||||
onBeforeMove(pokemon, target, move) {
|
||||
if (this.effectState.duration === 1) {
|
||||
this.add('-end', pokemon, 'move: Bide');
|
||||
|
|
@ -110,17 +98,11 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
this.add('-activate', pokemon, 'move: Bide');
|
||||
},
|
||||
onMoveAborted(pokemon) {
|
||||
pokemon.removeVolatile('bide');
|
||||
},
|
||||
onEnd(pokemon) {
|
||||
this.add('-end', pokemon, 'move: Bide', '[silent]');
|
||||
},
|
||||
},
|
||||
},
|
||||
blizzard: {
|
||||
inherit: true,
|
||||
onModifyMove() { },
|
||||
onModifyMove: undefined, // no inherit
|
||||
},
|
||||
brickbreak: {
|
||||
inherit: true,
|
||||
|
|
@ -133,7 +115,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
charge: {
|
||||
inherit: true,
|
||||
boosts: null,
|
||||
boosts: undefined, // no inherit
|
||||
},
|
||||
conversion: {
|
||||
inherit: true,
|
||||
|
|
@ -181,17 +163,12 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
counter: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 1,
|
||||
noCopy: true,
|
||||
onStart(target, source, move) {
|
||||
this.effectState.slot = null;
|
||||
this.effectState.damage = 0;
|
||||
},
|
||||
onRedirectTargetPriority: -1,
|
||||
inherit: true,
|
||||
onRedirectTarget(target, source, source2) {
|
||||
if (source !== this.effectState.target || !this.effectState.slot) return;
|
||||
return this.getAtSlot(this.effectState.slot);
|
||||
},
|
||||
onDamagingHit: undefined, // no inherit
|
||||
onDamagePriority: -101,
|
||||
onDamage(damage, target, source, effect) {
|
||||
if (
|
||||
|
|
@ -225,48 +202,13 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
accuracy: 55,
|
||||
flags: { protect: 1, mirror: 1, bypasssub: 1, metronome: 1 },
|
||||
volatileStatus: 'disable',
|
||||
condition: {
|
||||
inherit: true,
|
||||
durationCallback() {
|
||||
return this.random(2, 6);
|
||||
},
|
||||
noCopy: true,
|
||||
onStart(pokemon) {
|
||||
if (!this.queue.willMove(pokemon)) {
|
||||
this.effectState.duration!++;
|
||||
}
|
||||
if (!pokemon.lastMove) {
|
||||
return false;
|
||||
}
|
||||
for (const moveSlot of pokemon.moveSlots) {
|
||||
if (moveSlot.id === pokemon.lastMove.id) {
|
||||
if (!moveSlot.pp) {
|
||||
return false;
|
||||
} else {
|
||||
this.add('-start', pokemon, 'Disable', moveSlot.move);
|
||||
this.effectState.move = pokemon.lastMove.id;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
onEnd(pokemon) {
|
||||
this.add('-end', pokemon, 'move: Disable');
|
||||
},
|
||||
onBeforeMove(attacker, defender, move) {
|
||||
if (move.id === this.effectState.move) {
|
||||
this.add('cant', attacker, 'Disable', move);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
onDisableMove(pokemon) {
|
||||
for (const moveSlot of pokemon.moveSlots) {
|
||||
if (moveSlot.id === this.effectState.move) {
|
||||
pokemon.disableMove(moveSlot.id);
|
||||
}
|
||||
}
|
||||
},
|
||||
"onResidualOrder": undefined, // no inherit
|
||||
"onResidualSubOrder": undefined, // no inherit
|
||||
},
|
||||
},
|
||||
dive: {
|
||||
|
|
@ -310,51 +252,15 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
volatileStatus: 'encore',
|
||||
condition: {
|
||||
inherit: true,
|
||||
durationCallback() {
|
||||
return this.random(3, 7);
|
||||
},
|
||||
onStart(target, source) {
|
||||
const moveSlot = target.lastMove ? target.getMoveData(target.lastMove.id) : null;
|
||||
if (!target.lastMove || target.lastMove.flags['failencore'] || !moveSlot || moveSlot.pp <= 0) {
|
||||
// it failed
|
||||
return false;
|
||||
}
|
||||
this.effectState.move = target.lastMove.id;
|
||||
this.add('-start', target, 'Encore');
|
||||
},
|
||||
onOverrideAction(pokemon) {
|
||||
return this.effectState.move;
|
||||
},
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 14,
|
||||
onResidual(target) {
|
||||
const moveSlot = target.getMoveData(this.effectState.move);
|
||||
if (moveSlot && moveSlot.pp <= 0) {
|
||||
// early termination if you run out of PP
|
||||
target.removeVolatile('encore');
|
||||
}
|
||||
},
|
||||
onEnd(target) {
|
||||
this.add('-end', target, 'Encore');
|
||||
},
|
||||
onDisableMove(pokemon) {
|
||||
if (!this.effectState.move || !pokemon.hasMove(this.effectState.move)) {
|
||||
return;
|
||||
}
|
||||
for (const moveSlot of pokemon.moveSlots) {
|
||||
if (moveSlot.id !== this.effectState.move) {
|
||||
pokemon.disableMove(moveSlot.id);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
extrasensory: {
|
||||
inherit: true,
|
||||
basePowerCallback(pokemon, target) {
|
||||
if (target.volatiles['minimize']) return 160;
|
||||
return 80;
|
||||
},
|
||||
flags: { protect: 1, mirror: 1, metronome: 1, minimize: 1 },
|
||||
},
|
||||
fakeout: {
|
||||
inherit: true,
|
||||
|
|
@ -396,15 +302,14 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
followme: {
|
||||
inherit: true,
|
||||
volatileStatus: undefined,
|
||||
volatileStatus: undefined, // no inherit
|
||||
slotCondition: 'followme',
|
||||
condition: {
|
||||
duration: 1,
|
||||
inherit: true,
|
||||
onStart(target, source, effect) {
|
||||
this.add('-singleturn', target, 'move: Follow Me');
|
||||
this.effectState.slot = target.getSlot();
|
||||
},
|
||||
onFoeRedirectTargetPriority: 1,
|
||||
onFoeRedirectTarget(target, source, source2, move) {
|
||||
const userSlot = this.getAtSlot(this.effectState.slot);
|
||||
if (this.validTarget(userSlot, source, move.target)) {
|
||||
|
|
@ -502,17 +407,12 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
mirrorcoat: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 1,
|
||||
noCopy: true,
|
||||
onStart(target, source, move) {
|
||||
this.effectState.slot = null;
|
||||
this.effectState.damage = 0;
|
||||
},
|
||||
onRedirectTargetPriority: -1,
|
||||
inherit: true,
|
||||
onRedirectTarget(target, source, source2) {
|
||||
if (source !== this.effectState.target || !this.effectState.slot) return;
|
||||
return this.getAtSlot(this.effectState.slot);
|
||||
},
|
||||
onDamagingHit: undefined, // no inherit
|
||||
onDamagePriority: -101,
|
||||
onDamage(damage, target, source, effect) {
|
||||
if (
|
||||
|
|
@ -528,7 +428,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
mirrormove: {
|
||||
inherit: true,
|
||||
flags: { metronome: 1, failencore: 1, nosleeptalk: 1, noassist: 1 },
|
||||
onTryHit() { },
|
||||
onTryHit: undefined, // no inherit
|
||||
onHit(pokemon) {
|
||||
const noMirror = [
|
||||
'assist', 'curse', 'doomdesire', 'focuspunch', 'futuresight', 'magiccoat', 'metronome', 'mimic', 'mirrormove', 'naturepower', 'psychup', 'roleplay', 'sketch', 'sleeptalk', 'spikes', 'spitup', 'taunt', 'teeterdance', 'transform',
|
||||
|
|
@ -553,10 +453,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
needlearm: {
|
||||
inherit: true,
|
||||
basePowerCallback(pokemon, target) {
|
||||
if (target.volatiles['minimize']) return 120;
|
||||
return 60;
|
||||
},
|
||||
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1, minimize: 1 },
|
||||
},
|
||||
nightmare: {
|
||||
inherit: true,
|
||||
|
|
@ -578,6 +475,20 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
basePower: 70,
|
||||
},
|
||||
pursuit: {
|
||||
inherit: true,
|
||||
beforeTurnCallback(pokemon, target) {
|
||||
if (['frz', 'slp'].includes(pokemon.status) ||
|
||||
(pokemon.hasAbility('truant') && pokemon.truantTurn)) return;
|
||||
if (pokemon.isAlly(target)) return;
|
||||
target.addVolatile('pursuit');
|
||||
const data = target.volatiles['pursuit'];
|
||||
if (!data.sources) {
|
||||
data.sources = [];
|
||||
}
|
||||
data.sources.push(pokemon);
|
||||
},
|
||||
},
|
||||
recover: {
|
||||
inherit: true,
|
||||
pp: 20,
|
||||
|
|
@ -681,28 +592,13 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
flags: { protect: 1, bypasssub: 1, metronome: 1 },
|
||||
condition: {
|
||||
inherit: true,
|
||||
duration: 2,
|
||||
onStart(target) {
|
||||
this.add('-start', target, 'move: Taunt');
|
||||
},
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 15,
|
||||
durationCallback: undefined, // no inherit
|
||||
onEnd(target) {
|
||||
this.add('-end', target, 'move: Taunt', '[silent]');
|
||||
},
|
||||
onDisableMove(pokemon) {
|
||||
for (const moveSlot of pokemon.moveSlots) {
|
||||
if (this.dex.moves.get(moveSlot.move).category === 'Status') {
|
||||
pokemon.disableMove(moveSlot.id);
|
||||
}
|
||||
}
|
||||
},
|
||||
onBeforeMove(attacker, defender, move) {
|
||||
if (move.category === 'Status') {
|
||||
this.add('cant', attacker, 'move: Taunt', move);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
onBeforeMovePriority: undefined, // no inherit
|
||||
},
|
||||
},
|
||||
teeterdance: {
|
||||
|
|
@ -716,37 +612,9 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
uproar: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
onStart(target) {
|
||||
this.add('-start', target, 'Uproar');
|
||||
// 2-5 turns
|
||||
this.effectState.duration = this.random(2, 6);
|
||||
},
|
||||
onResidual(target) {
|
||||
if (target.volatiles['throatchop']) {
|
||||
target.removeVolatile('uproar');
|
||||
return;
|
||||
}
|
||||
if (target.lastMove && target.lastMove.id === 'struggle') {
|
||||
// don't lock
|
||||
delete target.volatiles['uproar'];
|
||||
}
|
||||
this.add('-start', target, 'Uproar', '[upkeep]');
|
||||
},
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 11,
|
||||
onEnd(target) {
|
||||
this.add('-end', target, 'Uproar');
|
||||
},
|
||||
onLockMove: 'uproar',
|
||||
onAnySetStatus(status, pokemon) {
|
||||
if (status.id === 'slp') {
|
||||
if (pokemon === this.effectState.target) {
|
||||
this.add('-fail', pokemon, 'slp', '[from] Uproar', '[msg]');
|
||||
} else {
|
||||
this.add('-fail', pokemon, 'slp', '[from] Uproar');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
inherit: true,
|
||||
durationCallback() {
|
||||
return this.random(2, 6);
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -756,11 +624,11 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
volttackle: {
|
||||
inherit: true,
|
||||
secondary: null,
|
||||
secondary: undefined, // no inherit
|
||||
},
|
||||
waterfall: {
|
||||
inherit: true,
|
||||
secondary: null,
|
||||
secondary: undefined, // no inherit
|
||||
},
|
||||
weatherball: {
|
||||
inherit: true,
|
||||
|
|
|
|||
|
|
@ -3,14 +3,17 @@ export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable
|
|||
effectType: 'ValidatorRule',
|
||||
name: 'Standard',
|
||||
desc: "The standard ruleset for all official Smogon singles tiers (Ubers, OU, etc.)",
|
||||
ruleset: ['Obtainable', 'Sleep Clause Mod', 'Switch Priority Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Items Clause', 'Evasion Moves Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod'],
|
||||
ruleset: [
|
||||
'Standard AG',
|
||||
'Sleep Clause Mod', 'Switch Priority Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Items Clause', 'Evasion Moves Clause',
|
||||
],
|
||||
},
|
||||
standarddraft: {
|
||||
effectType: 'ValidatorRule',
|
||||
name: 'Standard Draft',
|
||||
desc: "The custom Draft League ruleset",
|
||||
ruleset: [
|
||||
'Obtainable', 'Nickname Clause', '+Unreleased', 'Sleep Clause Mod', 'OHKO Clause', 'Evasion Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod',
|
||||
'Obtainable', 'Nickname Clause', 'Beat Up Nicknames Mod', '+Unreleased', 'Sleep Clause Mod', 'OHKO Clause', 'Evasion Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod',
|
||||
'One Boost Passer Clause', 'Freeze Clause Mod', 'Accuracy Moves Clause', 'Baton Pass Trap Clause',
|
||||
],
|
||||
banlist: [
|
||||
|
|
|
|||
|
|
@ -409,6 +409,7 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
for (i = 0; i < hits && target.hp && pokemon.hp; i++) {
|
||||
if (pokemon.status === 'slp' && !isSleepUsable) break;
|
||||
move.hit = i + 1;
|
||||
move.lastHit = move.hit === hits;
|
||||
|
||||
if (move.multiaccuracy && i > 0) {
|
||||
accuracy = move.accuracy;
|
||||
|
|
|
|||
|
|
@ -5,30 +5,20 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
perishsong: {
|
||||
inherit: true,
|
||||
onTryMove(attacker, defender, move) {
|
||||
let immuneMon = false;
|
||||
|
||||
for (const mon of attacker.side.active) {
|
||||
if (this.runEvent('Immunity', mon, attacker, move)) {
|
||||
immuneMon = true;
|
||||
}
|
||||
if (attacker.side.pokemonLeft === 1) {
|
||||
this.add('-fail', attacker, 'move: Perish Song');
|
||||
this.hint("Self KO Clause: The last pokemon on a team cannot use moves that force fainting");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const mon of attacker.side.foe.active) {
|
||||
if (this.runEvent('Immunity', mon, attacker, move)) {
|
||||
immuneMon = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (immuneMon) return;
|
||||
|
||||
if (this.format.gameType === 'singles') {
|
||||
if (attacker.side.pokemonLeft === 1 && attacker.side.foe.pokemonLeft === 1) {
|
||||
return false;
|
||||
}
|
||||
} else if (this.format.gameType === 'doubles') {
|
||||
if (attacker.side.pokemonLeft === 2 && attacker.side.foe.pokemonLeft === 2) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
destinybond: {
|
||||
inherit: true,
|
||||
onTryMove(attacker, defender, move) {
|
||||
if (attacker.side.pokemonLeft === 1) {
|
||||
this.add('-fail', attacker, 'move: Perish Song');
|
||||
this.hint("Self KO Clause: The last pokemon on a team cannot use moves that force fainting");
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -4,8 +4,18 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
|
||||
checkWin(faintData?: Battle['faintQueue'][0]) {
|
||||
if (this.sides.every(side => !side.pokemonLeft)) {
|
||||
this.win(faintData ? faintData.target.side : null);
|
||||
return true;
|
||||
let isSelfKo = false;
|
||||
if (faintData?.effect) {
|
||||
isSelfKo = isSelfKo || this.dex.moves.getByID(faintData?.effect?.id).selfdestruct !== undefined;
|
||||
isSelfKo = isSelfKo || this.dex.moves.getByID(faintData?.effect?.id).recoil !== undefined;
|
||||
}
|
||||
if (isSelfKo) {
|
||||
this.win(faintData ? faintData.target.side : null);
|
||||
return true;
|
||||
} else {
|
||||
this.win(undefined);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (const side of this.sides) {
|
||||
if (!side.foePokemonLeft()) {
|
||||
|
|
|
|||
63
data/mods/gen3frlg/abilities.ts
Normal file
63
data/mods/gen3frlg/abilities.ts
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
function attemptStatuses(battle: Battle, target: Pokemon, source: Pokemon, move: ActiveMove, status: string) {
|
||||
const attackerStatused = source.trySetStatus(status, target);
|
||||
if (move.multihit && move.id !== 'triplekick' &&
|
||||
(move.lastHit || (attackerStatused && status === 'slp')) &&
|
||||
battle.randomChance(1, 100)) {
|
||||
const defenderStatused = target.trySetStatus(status, target, move);
|
||||
if (defenderStatused) {
|
||||
battle.hint("In Pokemon Ruby, Sapphire, FireRed, LeafGreen, and Colosseum, if the final hit of a multihit move (except for Triple Kick) that makes contact triggers an ability that inflicts status, then there is a 1% chance that the defender is afflicted by the same status.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTable = {
|
||||
effectspore: {
|
||||
inherit: true,
|
||||
onDamagingHit(damage, target, source, move) {
|
||||
if (damage && move.flags['contact'] && !source.status) {
|
||||
const r = this.random(300);
|
||||
let status = null;
|
||||
if (r < 10) {
|
||||
status = 'slp';
|
||||
} else if (r < 20) {
|
||||
status = 'par';
|
||||
} else if (r < 30) {
|
||||
status = 'psn';
|
||||
}
|
||||
if (status) {
|
||||
attemptStatuses(this, target, source, move, status);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
flamebody: {
|
||||
inherit: true,
|
||||
onDamagingHit(damage, target, source, move) {
|
||||
if (damage && move.flags['contact']) {
|
||||
if (this.randomChance(1, 3)) {
|
||||
attemptStatuses(this, target, source, move, 'brn');
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
poisonpoint: {
|
||||
inherit: true,
|
||||
onDamagingHit(damage, target, source, move) {
|
||||
if (damage && move.flags['contact']) {
|
||||
if (this.randomChance(1, 3)) {
|
||||
attemptStatuses(this, target, source, move, 'psn');
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
static: {
|
||||
inherit: true,
|
||||
onDamagingHit(damage, target, source, move) {
|
||||
if (damage && move.flags['contact']) {
|
||||
if (this.randomChance(1, 3)) {
|
||||
attemptStatuses(this, target, source, move, 'par');
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
1354
data/mods/gen3frlg/formats-data.ts
Normal file
1354
data/mods/gen3frlg/formats-data.ts
Normal file
File diff suppressed because it is too large
Load Diff
146
data/mods/gen3frlg/items.ts
Normal file
146
data/mods/gen3frlg/items.ts
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
||||
aguavberry: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
apicotberry: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
brightpowder: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
choiceband: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
clawfossil: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
cornnberry: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
deepseascale: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
deepseatooth: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
diveball: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
enigmaberry: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
figyberry: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
ganlonberry: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
grepaberry: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
hondewberry: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
kelpsyberry: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
lansatberry: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
liechiberry: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
lightball: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
magoberry: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
magostberry: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
mentalherb: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
nomelberry: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
petayaberry: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
pomegberry: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
premierball: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
qualotberry: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
rabutaberry: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
rootfossil: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
salacberry: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
scopelens: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
shellbell: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
souldew: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
starfberry: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
tamatoberry: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
whiteherb: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
wikiberry: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
};
|
||||
9336
data/mods/gen3frlg/learnsets.ts
Normal file
9336
data/mods/gen3frlg/learnsets.ts
Normal file
File diff suppressed because it is too large
Load Diff
40
data/mods/gen3frlg/rulesets.ts
Normal file
40
data/mods/gen3frlg/rulesets.ts
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
|
||||
standard: {
|
||||
effectType: 'ValidatorRule',
|
||||
name: 'Standard',
|
||||
desc: "The standard ruleset for all official Smogon singles tiers (Ubers, OU, etc.)",
|
||||
ruleset: [
|
||||
'Standard AG',
|
||||
'Sleep Clause Mod', 'Switch Priority Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Items Clause', 'Evasion Moves Clause',
|
||||
],
|
||||
},
|
||||
standarddraft: {
|
||||
effectType: 'ValidatorRule',
|
||||
name: 'Standard Draft',
|
||||
desc: "The custom Draft League ruleset",
|
||||
ruleset: [
|
||||
'Obtainable', 'Nickname Clause', 'Beat Up Nicknames Mod', '+Unreleased', 'Sleep Clause Mod', 'OHKO Clause', 'Evasion Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod',
|
||||
'One Boost Passer Clause', 'Freeze Clause Mod', 'Accuracy Moves Clause', 'Baton Pass Trap Clause',
|
||||
],
|
||||
banlist: [
|
||||
'Uber', 'Smeargle + Ingrain', 'Swagger', 'Focus Band', 'King\'s Rock', 'Quick Claw', 'Baton Pass + Ancient Power', 'Baton Pass + Silver Wind',
|
||||
],
|
||||
// timer: {starting: 60 * 60, grace: 0, addPerTurn: 10, maxPerTurn: 100, timeoutAutoChoose: true},
|
||||
},
|
||||
obtainable: {
|
||||
inherit: true,
|
||||
onValidateSet(set) {
|
||||
const species = this.dex.species.get(set.species);
|
||||
if (['entei', 'raikou', 'suicune'].includes(species.id)) {
|
||||
if (!set.ivs) set.ivs = { hp: 31, atk: 31, def: 31, spa: 31, spd: 31, spe: 31 };
|
||||
for (const stat in set.ivs) {
|
||||
if ((stat === 'atk' && set.ivs[stat] > 7) || (stat !== 'hp' && set.ivs[stat as 'def'] > 0)) {
|
||||
return [
|
||||
`${set.name} must have 7 or fewer Attack IVs and 0 IVs in all other stats except HP, due to the Roaming IVs glitch.`,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
export const Scripts: ModdedBattleScriptsData = {
|
||||
gen: 9,
|
||||
inherit: 'gen3',
|
||||
};
|
||||
63
data/mods/gen3rs/abilities.ts
Normal file
63
data/mods/gen3rs/abilities.ts
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
function attemptStatuses(battle: Battle, target: Pokemon, source: Pokemon, move: ActiveMove, status: string) {
|
||||
const attackerStatused = source.trySetStatus(status, target);
|
||||
if (move.multihit && move.id !== 'triplekick' &&
|
||||
(move.lastHit || (attackerStatused && status === 'slp')) &&
|
||||
battle.randomChance(1, 100)) {
|
||||
const defenderStatused = target.trySetStatus(status, target, move);
|
||||
if (defenderStatused) {
|
||||
battle.hint("In Pokemon Ruby, Sapphire, FireRed, LeafGreen, and Colosseum, if the final hit of a multihit move (except for Triple Kick) that makes contact triggers an ability that inflicts status, then there is a 1% chance that the defender is afflicted by the same status.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTable = {
|
||||
effectspore: {
|
||||
inherit: true,
|
||||
onDamagingHit(damage, target, source, move) {
|
||||
if (damage && move.flags['contact'] && !source.status) {
|
||||
const r = this.random(300);
|
||||
let status = null;
|
||||
if (r < 10) {
|
||||
status = 'slp';
|
||||
} else if (r < 20) {
|
||||
status = 'par';
|
||||
} else if (r < 30) {
|
||||
status = 'psn';
|
||||
}
|
||||
if (status) {
|
||||
attemptStatuses(this, target, source, move, status);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
flamebody: {
|
||||
inherit: true,
|
||||
onDamagingHit(damage, target, source, move) {
|
||||
if (damage && move.flags['contact']) {
|
||||
if (this.randomChance(1, 3)) {
|
||||
attemptStatuses(this, target, source, move, 'brn');
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
poisonpoint: {
|
||||
inherit: true,
|
||||
onDamagingHit(damage, target, source, move) {
|
||||
if (damage && move.flags['contact']) {
|
||||
if (this.randomChance(1, 3)) {
|
||||
attemptStatuses(this, target, source, move, 'psn');
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
static: {
|
||||
inherit: true,
|
||||
onDamagingHit(damage, target, source, move) {
|
||||
if (damage && move.flags['contact']) {
|
||||
if (this.randomChance(1, 3)) {
|
||||
attemptStatuses(this, target, source, move, 'par');
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -7,10 +7,6 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
enigmaberry: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
fastball: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
|
|
|
|||
|
|
@ -4356,6 +4356,7 @@ export const Learnsets: import('../../../sim/dex-species').ModdedLearnsetDataTab
|
|||
toxic: ["3M"],
|
||||
uproar: ["3E"],
|
||||
waterpulse: ["3M"],
|
||||
wish: ["3E"],
|
||||
},
|
||||
},
|
||||
delcatty: {
|
||||
|
|
@ -4813,6 +4814,7 @@ export const Learnsets: import('../../../sim/dex-species').ModdedLearnsetDataTab
|
|||
thunderbolt: ["3M"],
|
||||
thunderwave: ["3L4"],
|
||||
toxic: ["3M"],
|
||||
wish: ["3E"],
|
||||
},
|
||||
},
|
||||
minun: {
|
||||
|
|
@ -4846,6 +4848,7 @@ export const Learnsets: import('../../../sim/dex-species').ModdedLearnsetDataTab
|
|||
thunderbolt: ["3M"],
|
||||
thunderwave: ["3L4"],
|
||||
toxic: ["3M"],
|
||||
wish: ["3E"],
|
||||
},
|
||||
},
|
||||
volbeat: {
|
||||
|
|
@ -5462,6 +5465,7 @@ export const Learnsets: import('../../../sim/dex-species').ModdedLearnsetDataTab
|
|||
trick: ["3E"],
|
||||
uproar: ["3L5"],
|
||||
waterpulse: ["3M"],
|
||||
wish: ["3E"],
|
||||
},
|
||||
},
|
||||
trapinch: {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTable = {
|
||||
airlock: {
|
||||
inherit: true,
|
||||
onSwitchIn() {},
|
||||
onSwitchIn: undefined, // no inherit
|
||||
onStart(pokemon) {
|
||||
pokemon.abilityState.ending = false;
|
||||
},
|
||||
|
|
@ -23,6 +23,9 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
onResidualSubOrder: 10,
|
||||
},
|
||||
blaze: {
|
||||
inherit: true,
|
||||
onModifyAtk: undefined, // no inherit
|
||||
onModifySpA: undefined, // no inherit
|
||||
onBasePowerPriority: 2,
|
||||
onBasePower(basePower, attacker, defender, move) {
|
||||
if (move.type === 'Fire' && attacker.hp <= attacker.maxhp / 3) {
|
||||
|
|
@ -30,13 +33,10 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
return this.chainModify(1.5);
|
||||
}
|
||||
},
|
||||
name: "Blaze",
|
||||
rating: 2,
|
||||
num: 66,
|
||||
},
|
||||
cloudnine: {
|
||||
inherit: true,
|
||||
onSwitchIn() {},
|
||||
onSwitchIn: undefined, // no inherit
|
||||
onStart(pokemon) {
|
||||
pokemon.abilityState.ending = false;
|
||||
},
|
||||
|
|
@ -51,14 +51,14 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
this.add('-start', target, 'typechange', type, '[from] ability: Color Change');
|
||||
}
|
||||
},
|
||||
onAfterMoveSecondary() {},
|
||||
onAfterMoveSecondary: undefined, // no inherit
|
||||
},
|
||||
compoundeyes: {
|
||||
onSourceModifyAccuracyPriority: 9,
|
||||
onSourceModifyAccuracy(accuracy) {
|
||||
if (typeof accuracy !== 'number') return;
|
||||
this.debug('compoundeyes - enhancing accuracy');
|
||||
return accuracy * 1.3;
|
||||
return this.chainModify(1.3);
|
||||
},
|
||||
inherit: true,
|
||||
},
|
||||
|
|
@ -92,15 +92,9 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
effectspore: {
|
||||
inherit: true,
|
||||
onDamagingHit(damage, target, source, move) {
|
||||
if (damage && move.flags['contact'] && !source.status) {
|
||||
const r = this.random(100);
|
||||
if (r < 10) {
|
||||
source.setStatus('slp', target);
|
||||
} else if (r < 20) {
|
||||
source.setStatus('par', target);
|
||||
} else if (r < 30) {
|
||||
source.setStatus('psn', target);
|
||||
}
|
||||
if (damage && move.flags['contact'] && this.randomChance(3, 10)) {
|
||||
const status = this.sample(['slp', 'par', 'psn']);
|
||||
source.trySetStatus(status, target);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
@ -128,19 +122,15 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
}
|
||||
},
|
||||
condition: {
|
||||
noCopy: true, // doesn't get copied by Baton Pass
|
||||
onStart(target) {
|
||||
this.add('-start', target, 'ability: Flash Fire');
|
||||
},
|
||||
inherit: true,
|
||||
onModifyAtk: undefined, // no inherit
|
||||
onModifySpA: undefined, // no inherit
|
||||
onModifyDamagePhase1(atk, attacker, defender, move) {
|
||||
if (move.type === 'Fire') {
|
||||
this.debug('Flash Fire boost');
|
||||
return this.chainModify(1.5);
|
||||
}
|
||||
},
|
||||
onEnd(target) {
|
||||
this.add('-end', target, 'ability: Flash Fire', '[silent]');
|
||||
},
|
||||
},
|
||||
},
|
||||
flowergift: {
|
||||
|
|
@ -200,20 +190,19 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
onSourceModifyAccuracyPriority: 7,
|
||||
onSourceModifyAccuracy(accuracy, target, source, move) {
|
||||
if (move.category === 'Physical' && typeof accuracy === 'number') {
|
||||
return accuracy * 0.8;
|
||||
return this.chainModify(0.8);
|
||||
}
|
||||
},
|
||||
},
|
||||
hydration: {
|
||||
inherit: true,
|
||||
onResidual: undefined, // no inherit
|
||||
onWeather(target, source, effect) {
|
||||
if (effect.id === 'raindance' && target.status) {
|
||||
this.add('-activate', target, 'ability: Hydration');
|
||||
target.cureStatus();
|
||||
}
|
||||
},
|
||||
name: "Hydration",
|
||||
rating: 1.5,
|
||||
num: 93,
|
||||
},
|
||||
insomnia: {
|
||||
inherit: true,
|
||||
|
|
@ -255,7 +244,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
},
|
||||
lightningrod: {
|
||||
inherit: true,
|
||||
onTryHit() {},
|
||||
onTryHit: undefined, // no inherit
|
||||
rating: 0,
|
||||
},
|
||||
liquidooze: {
|
||||
|
|
@ -270,35 +259,33 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
},
|
||||
},
|
||||
magicguard: {
|
||||
onDamage(damage, target, source, effect) {
|
||||
if (effect.effectType !== 'Move') {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
inherit: true,
|
||||
onSetStatus(status, target, source, effect) {
|
||||
if (effect && effect.id === 'toxicspikes') {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
name: "Magic Guard",
|
||||
rating: 4.5,
|
||||
num: 98,
|
||||
},
|
||||
minus: {
|
||||
inherit: true,
|
||||
onModifySpAPriority: undefined, // no inherit
|
||||
onModifySpA(spa, pokemon) {
|
||||
for (const ally of pokemon.allies()) {
|
||||
if (ally.ability === 'plus') {
|
||||
return spa * 1.5;
|
||||
for (const allyActive of pokemon.allies()) {
|
||||
if (allyActive.hasAbility('plus')) {
|
||||
return this.chainModify(1.5);
|
||||
}
|
||||
}
|
||||
},
|
||||
name: "Minus",
|
||||
rating: 0,
|
||||
num: 58,
|
||||
},
|
||||
multitype: {
|
||||
inherit: true,
|
||||
onTakeItem: false,
|
||||
onSetAbility: false, // redundant but hardcoded
|
||||
},
|
||||
naturalcure: {
|
||||
inherit: true,
|
||||
onCheckShow(pokemon) {},
|
||||
onCheckShow: undefined, // no inherit
|
||||
onSwitchOut(pokemon) {
|
||||
if (!pokemon.status || pokemon.status === 'fnt') return;
|
||||
|
||||
|
|
@ -318,6 +305,9 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
},
|
||||
},
|
||||
overgrow: {
|
||||
inherit: true,
|
||||
onModifyAtk: undefined, // no inherit
|
||||
onModifySpA: undefined, // no inherit
|
||||
onBasePowerPriority: 2,
|
||||
onBasePower(basePower, attacker, defender, move) {
|
||||
if (move.type === 'Grass' && attacker.hp <= attacker.maxhp / 3) {
|
||||
|
|
@ -325,26 +315,23 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
return this.chainModify(1.5);
|
||||
}
|
||||
},
|
||||
name: "Overgrow",
|
||||
rating: 2,
|
||||
num: 65,
|
||||
},
|
||||
pickup: {
|
||||
name: "Pickup",
|
||||
inherit: true,
|
||||
onResidual: undefined, // no inherit
|
||||
rating: 0,
|
||||
num: 53,
|
||||
// No competitive use
|
||||
},
|
||||
plus: {
|
||||
inherit: true,
|
||||
onModifySpAPriority: undefined, // no inherit
|
||||
onModifySpA(spa, pokemon) {
|
||||
for (const ally of pokemon.allies()) {
|
||||
if (ally.ability === 'minus') {
|
||||
return spa * 1.5;
|
||||
for (const allyActive of pokemon.allies()) {
|
||||
if (allyActive.hasAbility('minus')) {
|
||||
return this.chainModify(1.5);
|
||||
}
|
||||
}
|
||||
},
|
||||
name: "Plus",
|
||||
rating: 0,
|
||||
num: 57,
|
||||
},
|
||||
poisonpoint: {
|
||||
inherit: true,
|
||||
|
|
@ -357,16 +344,12 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
},
|
||||
},
|
||||
pressure: {
|
||||
onStart(pokemon) {
|
||||
this.add('-ability', pokemon, 'Pressure');
|
||||
},
|
||||
inherit: true,
|
||||
onDeductPP(target, source) {
|
||||
if (target === source) return;
|
||||
return 1;
|
||||
},
|
||||
name: "Pressure",
|
||||
rating: 1.5,
|
||||
num: 46,
|
||||
},
|
||||
roughskin: {
|
||||
inherit: true,
|
||||
|
|
@ -383,7 +366,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
if (typeof accuracy !== 'number') return;
|
||||
if (this.field.isWeather('sandstorm')) {
|
||||
this.debug('Sand Veil - decreasing accuracy');
|
||||
return accuracy * 0.8;
|
||||
return this.chainModify(0.8);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
@ -404,16 +387,14 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
onResidualSubOrder: 3,
|
||||
},
|
||||
simple: {
|
||||
inherit: true,
|
||||
onChangeBoost: undefined, // no inherit
|
||||
onModifyBoost(boosts) {
|
||||
let key: BoostID;
|
||||
for (key in boosts) {
|
||||
boosts[key]! *= 2;
|
||||
}
|
||||
},
|
||||
flags: { breakable: 1 },
|
||||
name: "Simple",
|
||||
rating: 4,
|
||||
num: 86,
|
||||
},
|
||||
snowcloak: {
|
||||
inherit: true,
|
||||
|
|
@ -422,7 +403,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
if (typeof accuracy !== 'number') return;
|
||||
if (this.field.isWeather('hail')) {
|
||||
this.debug('Snow Cloak - decreasing accuracy');
|
||||
return accuracy * 0.8;
|
||||
return this.chainModify(0.8);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
@ -431,6 +412,13 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 3,
|
||||
},
|
||||
stall: {
|
||||
inherit: true,
|
||||
onFractionalPriority(priority, pokemon) {
|
||||
// don't override Lagging Tail and Full Incense's -0.2 fractional priority
|
||||
if (priority >= 0) return -0.1;
|
||||
},
|
||||
},
|
||||
static: {
|
||||
inherit: true,
|
||||
onDamagingHit(damage, target, source, move) {
|
||||
|
|
@ -442,9 +430,10 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
},
|
||||
},
|
||||
stench: {
|
||||
name: "Stench",
|
||||
inherit: true,
|
||||
onModifyMove: undefined, // no inherit
|
||||
rating: 0,
|
||||
num: 1,
|
||||
// No competitive use
|
||||
},
|
||||
stickyhold: {
|
||||
inherit: true,
|
||||
|
|
@ -457,15 +446,18 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
},
|
||||
stormdrain: {
|
||||
inherit: true,
|
||||
onTryHit() {},
|
||||
onTryHit: undefined, // no inherit
|
||||
rating: 0,
|
||||
},
|
||||
sturdy: {
|
||||
inherit: true,
|
||||
onDamage() {},
|
||||
onDamage: undefined, // no inherit
|
||||
rating: 0,
|
||||
},
|
||||
swarm: {
|
||||
inherit: true,
|
||||
onModifyAtk: undefined, // no inherit
|
||||
onModifySpA: undefined, // no inherit
|
||||
onBasePowerPriority: 2,
|
||||
onBasePower(basePower, attacker, defender, move) {
|
||||
if (move.type === 'Bug' && attacker.hp <= attacker.maxhp / 3) {
|
||||
|
|
@ -473,9 +465,6 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
return this.chainModify(1.5);
|
||||
}
|
||||
},
|
||||
name: "Swarm",
|
||||
rating: 2,
|
||||
num: 68,
|
||||
},
|
||||
synchronize: {
|
||||
inherit: true,
|
||||
|
|
@ -495,23 +484,25 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
if (typeof accuracy !== 'number') return;
|
||||
if (target?.volatiles['confusion']) {
|
||||
this.debug('Tangled Feet - decreasing accuracy');
|
||||
return accuracy * 0.5;
|
||||
return this.chainModify(0.5);
|
||||
}
|
||||
},
|
||||
},
|
||||
thickfat: {
|
||||
inherit: true,
|
||||
onSourceModifyAtk: undefined, // no inherit
|
||||
onSourceModifySpA: undefined, // no inherit
|
||||
onSourceBasePowerPriority: 1,
|
||||
onSourceBasePower(basePower, attacker, defender, move) {
|
||||
if (move.type === 'Ice' || move.type === 'Fire') {
|
||||
return this.chainModify(0.5);
|
||||
}
|
||||
},
|
||||
flags: { breakable: 1 },
|
||||
name: "Thick Fat",
|
||||
rating: 3.5,
|
||||
num: 47,
|
||||
},
|
||||
torrent: {
|
||||
inherit: true,
|
||||
onModifyAtk: undefined, // no inherit
|
||||
onModifySpA: undefined, // no inherit
|
||||
onBasePowerPriority: 2,
|
||||
onBasePower(basePower, attacker, defender, move) {
|
||||
if (move.type === 'Water' && attacker.hp <= attacker.maxhp / 3) {
|
||||
|
|
@ -519,9 +510,6 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
return this.chainModify(1.5);
|
||||
}
|
||||
},
|
||||
name: "Torrent",
|
||||
rating: 2,
|
||||
num: 67,
|
||||
},
|
||||
trace: {
|
||||
inherit: true,
|
||||
|
|
@ -530,10 +518,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
const target = pokemon.side.randomFoe();
|
||||
if (!target || target.fainted) return;
|
||||
const ability = target.getAbility();
|
||||
const bannedAbilities = ['forecast', 'multitype', 'trace'];
|
||||
if (bannedAbilities.includes(target.ability)) {
|
||||
return;
|
||||
}
|
||||
if (ability.flags['notrace']) return;
|
||||
pokemon.setAbility(ability, target);
|
||||
},
|
||||
flags: { notrace: 1 },
|
||||
|
|
@ -559,6 +544,6 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
},
|
||||
rebound: {
|
||||
inherit: true,
|
||||
onTryHitSide() {},
|
||||
onTryHitSide: undefined, // no inherit
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ export const Conditions: import('../../../sim/dex-conditions').ModdedConditionDa
|
|||
},
|
||||
lockedmove: {
|
||||
inherit: true,
|
||||
onAfterMove() {},
|
||||
onAfterMove: undefined, // no inherit
|
||||
},
|
||||
choicelock: {
|
||||
inherit: true,
|
||||
|
|
|
|||
|
|
@ -32,24 +32,24 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
choiceband: {
|
||||
inherit: true,
|
||||
onStart() {},
|
||||
onModifyMove() {},
|
||||
onStart: undefined, // no inherit
|
||||
onModifyMove: undefined, // no inherit
|
||||
onAfterMove(pokemon) {
|
||||
pokemon.addVolatile('choicelock');
|
||||
},
|
||||
},
|
||||
choicescarf: {
|
||||
inherit: true,
|
||||
onStart() {},
|
||||
onModifyMove() {},
|
||||
onStart: undefined, // no inherit
|
||||
onModifyMove: undefined, // no inherit
|
||||
onAfterMove(pokemon) {
|
||||
pokemon.addVolatile('choicelock');
|
||||
},
|
||||
},
|
||||
choicespecs: {
|
||||
inherit: true,
|
||||
onStart() {},
|
||||
onModifyMove() {},
|
||||
onStart: undefined, // no inherit
|
||||
onModifyMove: undefined, // no inherit
|
||||
onAfterMove(pokemon) {
|
||||
pokemon.addVolatile('choicelock');
|
||||
},
|
||||
|
|
@ -72,7 +72,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
custapberry: {
|
||||
inherit: true,
|
||||
onFractionalPriority() {},
|
||||
onFractionalPriority: undefined, // no inherit
|
||||
onBeforeTurn(pokemon) {
|
||||
if (pokemon.hp <= pokemon.maxhp / 4 || (pokemon.hp <= pokemon.maxhp / 2 && pokemon.ability === 'gluttony')) {
|
||||
const action = this.queue.willMove(pokemon);
|
||||
|
|
@ -144,7 +144,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
focussash: {
|
||||
inherit: true,
|
||||
onDamage() { },
|
||||
onDamage: undefined, // no inherit
|
||||
onTryHit(target, source, move) {
|
||||
if (target !== source && target.hp === target.maxhp) {
|
||||
target.addVolatile('focussash');
|
||||
|
|
@ -164,6 +164,11 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
},
|
||||
},
|
||||
fullincense: {
|
||||
inherit: true,
|
||||
onFractionalPriorityPriority: 1,
|
||||
onFractionalPriority: -0.2,
|
||||
},
|
||||
griseousorb: {
|
||||
inherit: true,
|
||||
onBasePower(basePower, user, target, move) {
|
||||
|
|
@ -171,6 +176,8 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
return this.chainModify(1.2);
|
||||
}
|
||||
},
|
||||
onTakeItem: false,
|
||||
onSetAbility: false,
|
||||
},
|
||||
heavyball: {
|
||||
inherit: true,
|
||||
|
|
@ -186,7 +193,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
ironball: {
|
||||
inherit: true,
|
||||
onEffectiveness() {},
|
||||
onEffectiveness: undefined, // no inherit
|
||||
},
|
||||
ironplate: {
|
||||
inherit: true,
|
||||
|
|
@ -207,6 +214,11 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
}
|
||||
},
|
||||
},
|
||||
laggingtail: {
|
||||
inherit: true,
|
||||
onFractionalPriorityPriority: 1,
|
||||
onFractionalPriority: -0.2,
|
||||
},
|
||||
laxincense: {
|
||||
inherit: true,
|
||||
onModifyAccuracyPriority: 5,
|
||||
|
|
@ -227,8 +239,8 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
lifeorb: {
|
||||
inherit: true,
|
||||
onModifyDamage() {},
|
||||
onAfterMoveSecondarySelf() {},
|
||||
onModifyDamage: undefined, // no inherit
|
||||
onAfterMoveSecondarySelf: undefined, // no inherit
|
||||
onBasePower(basePower, user, target) {
|
||||
if (!target.volatiles['substitute']) {
|
||||
user.addVolatile('lifeorb');
|
||||
|
|
@ -250,8 +262,8 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
lightball: {
|
||||
inherit: true,
|
||||
onModifyAtk() {},
|
||||
onModifySpA() {},
|
||||
onModifyAtk: undefined, // no inherit
|
||||
onModifySpA: undefined, // no inherit
|
||||
onBasePower(basePower, pokemon) {
|
||||
if (pokemon.species.name === 'Pikachu') {
|
||||
return this.chainModify(2);
|
||||
|
|
@ -306,11 +318,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
metronome: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
onStart(pokemon) {
|
||||
this.effectState.numConsecutive = 0;
|
||||
this.effectState.lastMove = '';
|
||||
},
|
||||
onTryMovePriority: -2,
|
||||
inherit: true,
|
||||
onTryMove(pokemon, target, move) {
|
||||
if (!pokemon.hasItem('metronome')) {
|
||||
pokemon.removeVolatile('metronome');
|
||||
|
|
@ -323,6 +331,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
}
|
||||
this.effectState.lastMove = move.id;
|
||||
},
|
||||
onModifyDamage: undefined, // no inherit
|
||||
onModifyDamagePhase2(damage, source, target, move) {
|
||||
return damage * (1 + (this.effectState.numConsecutive / 10));
|
||||
},
|
||||
|
|
@ -331,7 +340,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
micleberry: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 2,
|
||||
inherit: true,
|
||||
onSourceModifyAccuracyPriority: 3,
|
||||
onSourceModifyAccuracy(accuracy, target, source) {
|
||||
this.add('-enditem', source, 'Micle Berry');
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,7 +1,16 @@
|
|||
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
|
||||
standardag: {
|
||||
inherit: true,
|
||||
ruleset: [
|
||||
'Obtainable', 'HP Percentage Mod', 'Cancel Mod', 'Beat Up Nicknames Mod', 'Endless Battle Clause',
|
||||
],
|
||||
},
|
||||
standard: {
|
||||
inherit: true,
|
||||
ruleset: ['Obtainable', 'Sleep Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Items Clause', 'Evasion Moves Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod'],
|
||||
ruleset: [
|
||||
'Standard AG',
|
||||
'Sleep Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Items Clause', 'Evasion Moves Clause',
|
||||
],
|
||||
},
|
||||
flatrules: {
|
||||
inherit: true,
|
||||
|
|
@ -21,26 +30,4 @@ export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable
|
|||
this.makeRequest('teampreview');
|
||||
},
|
||||
},
|
||||
validatestats: {
|
||||
inherit: true,
|
||||
onValidateSet(set) {
|
||||
const species = this.dex.species.get(set.species);
|
||||
const item = this.dex.items.get(set.item);
|
||||
if (item && item.id === 'griseousorb' && species.num !== 487) {
|
||||
return ['Griseous Orb can only be held by Giratina in Generation 4.'];
|
||||
}
|
||||
if (species.num === 493 && set.evs) {
|
||||
const isEventArceus = set.moves.includes('roaroftime') || set.moves.includes('shadowforce') ||
|
||||
set.moves.includes('spacialrend');
|
||||
if (isEventArceus) {
|
||||
let stat: StatID;
|
||||
for (stat in set.evs) {
|
||||
if (set.evs[stat] > 100) {
|
||||
return ["Event Arceus may not have more than 100 of any EVs in Generation 4."];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,18 @@
|
|||
export const Scripts: ModdedBattleScriptsData = {
|
||||
inherit: 'gen5',
|
||||
gen: 4,
|
||||
|
||||
pokemon: {
|
||||
inherit: true,
|
||||
getActionSpeed() {
|
||||
let speed = this.getStat('spe', false, false);
|
||||
const trickRoomCheck = this.battle.ruleTable.has('twisteddimensionmod') ?
|
||||
!this.battle.field.getPseudoWeather('trickroom') : this.battle.field.getPseudoWeather('trickroom');
|
||||
if (trickRoomCheck) {
|
||||
speed = -speed;
|
||||
}
|
||||
return speed;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
inherit: true,
|
||||
runSwitch(pokemon) {
|
||||
|
|
@ -12,6 +23,16 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
if (this.battle.gen <= 2) {
|
||||
// pokemon.lastMove is reset for all Pokemon on the field after a switch. This affects Mirror Move.
|
||||
for (const poke of this.battle.getAllActive()) poke.lastMove = null;
|
||||
if (this.battle.gen === 1) pokemon.side.lastSelectedMoveSlot = 0;
|
||||
for (const poke of pokemon.foes()) {
|
||||
if (poke.volatiles['partialtrappinglock'] && poke.moveSlots[poke.side.lastSelectedMoveSlot].id === 'metronome') {
|
||||
// this is not done for Mirror Move, potentially resulting in a desync
|
||||
poke.side.lastSelectedMove = 'metronome' as ID;
|
||||
if (this.battle.queue.willMove(poke)) {
|
||||
this.battle.queue.changeAction(poke, { choice: 'move', poke, moveid: 'metronome' });
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!pokemon.side.faintedThisTurn && pokemon.draggedIn !== this.battle.turn) {
|
||||
this.battle.runEvent('AfterSwitchInSelf', pokemon);
|
||||
}
|
||||
|
|
@ -55,10 +76,6 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
// Weather
|
||||
baseDamage = this.battle.runEvent('WeatherModifyDamage', pokemon, target, move, baseDamage);
|
||||
|
||||
if (this.battle.gen === 3 && move.category === 'Physical' && !Math.floor(baseDamage)) {
|
||||
baseDamage = 1;
|
||||
}
|
||||
|
||||
baseDamage += 2;
|
||||
|
||||
const isCrit = target.getMoveHitData(move).crit;
|
||||
|
|
|
|||
|
|
@ -1475,7 +1475,6 @@ export const Learnsets: import('../../../sim/dex-species').ModdedLearnsetDataTab
|
|||
hiddenpower: ["4M", "3M"],
|
||||
irontail: ["4M", "4S21", "3M"],
|
||||
knockoff: ["4T"],
|
||||
lastresort: ["4S18"],
|
||||
lightscreen: ["4M", "4L42", "4S11", "3M", "3L50", "3S0", "3S6", "3S7", "3S8"],
|
||||
magnetrise: ["4T"],
|
||||
megakick: ["3T"],
|
||||
|
|
@ -2916,7 +2915,6 @@ export const Learnsets: import('../../../sim/dex-species').ModdedLearnsetDataTab
|
|||
steelwing: ["4M", "3M"],
|
||||
substitute: ["4M", "3T"],
|
||||
sunnyday: ["4M", "3M"],
|
||||
superfang: ["4S0"],
|
||||
supersonic: ["4L1", "3L1"],
|
||||
swagger: ["4M", "3T"],
|
||||
swift: ["4T", "3T"],
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
},
|
||||
keeneye: {
|
||||
inherit: true,
|
||||
onModifyMove() {},
|
||||
onModifyMove: undefined, // no inherit
|
||||
},
|
||||
magicbounce: {
|
||||
inherit: true,
|
||||
|
|
@ -68,13 +68,13 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
onImmunity(type, pokemon) {
|
||||
if (type === 'sandstorm' || type === 'hail') return false;
|
||||
},
|
||||
onTryHit() {},
|
||||
onTryHit: undefined, // no inherit
|
||||
flags: {},
|
||||
rating: 0.5,
|
||||
},
|
||||
sapsipper: {
|
||||
inherit: true,
|
||||
onAllyTryHitSide() {},
|
||||
onAllyTryHitSide: undefined, // no inherit
|
||||
},
|
||||
serenegrace: {
|
||||
inherit: true,
|
||||
|
|
@ -89,7 +89,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
},
|
||||
soundproof: {
|
||||
inherit: true,
|
||||
onAllyTryHitSide() {},
|
||||
onAllyTryHitSide: undefined, // no inherit
|
||||
},
|
||||
rebound: {
|
||||
inherit: true,
|
||||
|
|
|
|||
|
|
@ -36,8 +36,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
autotomize: {
|
||||
inherit: true,
|
||||
volatileStatus: 'autotomize',
|
||||
onHit(pokemon) {
|
||||
},
|
||||
onHit: undefined, // no inherit
|
||||
condition: {
|
||||
noCopy: true, // doesn't get copied by Baton Pass
|
||||
onStart(pokemon) {
|
||||
|
|
@ -78,6 +77,10 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
flags: { protect: 1, reflectable: 1, mirror: 1, metronome: 1 },
|
||||
},
|
||||
bodyslam: {
|
||||
inherit: true,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, nonsky: 1, metronome: 1 },
|
||||
},
|
||||
bounce: {
|
||||
inherit: true,
|
||||
flags: { contact: 1, charge: 1, protect: 1, mirror: 1, gravity: 1, distance: 1, metronome: 1, nosleeptalk: 1 },
|
||||
|
|
@ -149,7 +152,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
cottonspore: {
|
||||
inherit: true,
|
||||
onTryHit() {},
|
||||
onTryHit: undefined, // no inherit
|
||||
target: "normal",
|
||||
},
|
||||
covet: {
|
||||
|
|
@ -192,6 +195,10 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, punch: 1, metronome: 1 },
|
||||
},
|
||||
dragonrush: {
|
||||
inherit: true,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 },
|
||||
},
|
||||
dreameater: {
|
||||
inherit: true,
|
||||
flags: { protect: 1, mirror: 1, metronome: 1 },
|
||||
|
|
@ -260,10 +267,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
basePower: 20,
|
||||
condition: {
|
||||
duration: 2,
|
||||
onStart() {
|
||||
this.effectState.multiplier = 1;
|
||||
},
|
||||
inherit: true,
|
||||
onRestart() {
|
||||
if (this.effectState.multiplier < 8) {
|
||||
this.effectState.multiplier <<= 1;
|
||||
|
|
@ -363,6 +367,10 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
return success;
|
||||
},
|
||||
},
|
||||
heatcrash: {
|
||||
inherit: true,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, nonsky: 1, metronome: 1 },
|
||||
},
|
||||
heatwave: {
|
||||
inherit: true,
|
||||
basePower: 100,
|
||||
|
|
@ -477,7 +485,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
knockoff: {
|
||||
inherit: true,
|
||||
basePower: 20,
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
},
|
||||
leafstorm: {
|
||||
inherit: true,
|
||||
|
|
@ -494,13 +502,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
lightscreen: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 5,
|
||||
durationCallback(target, source, effect) {
|
||||
if (source?.hasItem('lightclay')) {
|
||||
return 8;
|
||||
}
|
||||
return 5;
|
||||
},
|
||||
inherit: true,
|
||||
onAnyModifyDamage(damage, source, target, move) {
|
||||
if (target !== source && this.effectState.target.hasAlly(target) && this.getCategory(move) === 'Special') {
|
||||
if (!target.getMoveHitData(move).crit && !move.infiltrates) {
|
||||
|
|
@ -510,14 +512,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
}
|
||||
},
|
||||
onSideStart(side) {
|
||||
this.add('-sidestart', side, 'move: Light Screen');
|
||||
},
|
||||
onSideResidualOrder: 26,
|
||||
onSideResidualSubOrder: 2,
|
||||
onSideEnd(side) {
|
||||
this.add('-sideend', side, 'move: Light Screen');
|
||||
},
|
||||
},
|
||||
},
|
||||
lowsweep: {
|
||||
|
|
@ -527,24 +521,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
magiccoat: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 1,
|
||||
onStart(target, source, effect) {
|
||||
this.add('-singleturn', target, 'move: Magic Coat');
|
||||
if (effect?.effectType === 'Move') {
|
||||
this.effectState.pranksterBoosted = effect.pranksterBoosted;
|
||||
}
|
||||
},
|
||||
onTryHitPriority: 2,
|
||||
onTryHit(target, source, move) {
|
||||
if (target === source || move.hasBounced || !move.flags['reflectable'] || target.isSemiInvulnerable()) {
|
||||
return;
|
||||
}
|
||||
const newMove = this.dex.getActiveMove(move.id);
|
||||
newMove.hasBounced = true;
|
||||
newMove.pranksterBoosted = this.effectState.pranksterBoosted;
|
||||
this.actions.useMove(newMove, target, { target: source });
|
||||
return null;
|
||||
},
|
||||
inherit: true,
|
||||
onAllyTryHitSide(target, source, move) {
|
||||
if (target.isAlly(source) || move.hasBounced || !move.flags['reflectable']) {
|
||||
return;
|
||||
|
|
@ -587,12 +564,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
pp: 20,
|
||||
condition: {
|
||||
noCopy: true,
|
||||
onSourceModifyDamage(damage, source, target, move) {
|
||||
if (['stomp', 'steamroller'].includes(move.id)) {
|
||||
return this.chainModify(2);
|
||||
}
|
||||
},
|
||||
inherit: true,
|
||||
onAccuracy: undefined, // no inherit
|
||||
},
|
||||
},
|
||||
moonlight: {
|
||||
|
|
@ -605,7 +578,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
mudsport: {
|
||||
inherit: true,
|
||||
pseudoWeather: undefined,
|
||||
pseudoWeather: undefined, // no inherit
|
||||
volatileStatus: 'mudsport',
|
||||
condition: {
|
||||
noCopy: true,
|
||||
|
|
@ -623,7 +596,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
naturepower: {
|
||||
inherit: true,
|
||||
onTryHit() {},
|
||||
onTryHit: undefined, // no inherit
|
||||
onHit(pokemon) {
|
||||
this.actions.useMove('earthquake', pokemon);
|
||||
},
|
||||
|
|
@ -655,7 +628,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
poisonpowder: {
|
||||
inherit: true,
|
||||
onTryHit() {},
|
||||
onTryHit: undefined, // no inherit
|
||||
},
|
||||
powergem: {
|
||||
inherit: true,
|
||||
|
|
@ -689,17 +662,14 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
source.addVolatile('stall');
|
||||
},
|
||||
condition: {
|
||||
duration: 1,
|
||||
onSideStart(target, source) {
|
||||
this.add('-singleturn', source, 'Quick Guard');
|
||||
},
|
||||
onTryHitPriority: 4,
|
||||
onTryHit(target, source, effect) {
|
||||
inherit: true,
|
||||
onTryHit(target, source, move) {
|
||||
// Quick Guard only blocks moves with a natural positive priority
|
||||
// (e.g. it doesn't block 0 priority moves boosted by Prankster)
|
||||
if (effect && (effect.id === 'feint' || this.dex.moves.get(effect.id).priority <= 0)) {
|
||||
if (move.id === 'feint' || this.dex.moves.get(move.id).priority <= 0) {
|
||||
return;
|
||||
}
|
||||
if (this.checkMoveBypassesProtect(move, source, target)) return;
|
||||
this.add('-activate', target, 'Quick Guard');
|
||||
const lockedmove = source.getVolatile('lockedmove');
|
||||
if (lockedmove) {
|
||||
|
|
@ -716,17 +686,24 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
priority: 3,
|
||||
flags: { noassist: 1, failcopycat: 1 },
|
||||
condition: {
|
||||
inherit: true,
|
||||
onFoeRedirectTarget(target, source, source2, move) {
|
||||
const ragePowderUser = this.effectState.target;
|
||||
if (ragePowderUser.isSkyDropped()) return;
|
||||
|
||||
if (this.validTarget(ragePowderUser, source, move.target)) {
|
||||
if (move.smartTarget) move.smartTarget = false;
|
||||
this.debug("Rage Powder redirected target of move");
|
||||
return ragePowderUser;
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
reflect: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 5,
|
||||
durationCallback(target, source, effect) {
|
||||
if (source?.hasItem('lightclay')) {
|
||||
return 8;
|
||||
}
|
||||
return 5;
|
||||
},
|
||||
inherit: true,
|
||||
onAnyModifyDamage(damage, source, target, move) {
|
||||
if (target !== source && this.effectState.target.hasAlly(target) && this.getCategory(move) === 'Physical') {
|
||||
if (!target.getMoveHitData(move).crit && !move.infiltrates) {
|
||||
|
|
@ -736,14 +713,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
}
|
||||
},
|
||||
onSideStart(side) {
|
||||
this.add('-sidestart', side, 'Reflect');
|
||||
},
|
||||
onSideResidualOrder: 26,
|
||||
onSideResidualSubOrder: 1,
|
||||
onSideEnd(side) {
|
||||
this.add('-sideend', side, 'Reflect');
|
||||
},
|
||||
},
|
||||
},
|
||||
relicsong: {
|
||||
|
|
@ -794,19 +763,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
flags: { protect: 1, reflectable: 1, mirror: 1, sound: 1, metronome: 1 },
|
||||
},
|
||||
skillswap: {
|
||||
inherit: true,
|
||||
onHit(target, source) {
|
||||
const targetAbility = target.ability;
|
||||
const sourceAbility = source.ability;
|
||||
if (targetAbility === sourceAbility) {
|
||||
return false;
|
||||
}
|
||||
this.add('-activate', source, 'move: Skill Swap', this.dex.abilities.get(targetAbility), this.dex.abilities.get(sourceAbility), `[of] ${target}`);
|
||||
source.setAbility(targetAbility);
|
||||
target.setAbility(sourceAbility);
|
||||
},
|
||||
},
|
||||
skullbash: {
|
||||
inherit: true,
|
||||
basePower: 100,
|
||||
|
|
@ -838,7 +794,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
sleeppowder: {
|
||||
inherit: true,
|
||||
onTryHit() {},
|
||||
onTryHit: undefined, // no inherit
|
||||
},
|
||||
smellingsalts: {
|
||||
inherit: true,
|
||||
|
|
@ -871,7 +827,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
spore: {
|
||||
inherit: true,
|
||||
onTryHit() {},
|
||||
onTryHit: undefined, // no inherit
|
||||
},
|
||||
stormthrow: {
|
||||
inherit: true,
|
||||
|
|
@ -889,17 +845,12 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
stunspore: {
|
||||
inherit: true,
|
||||
onTryHit() {},
|
||||
onTryHit: undefined, // no inherit
|
||||
},
|
||||
substitute: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
onStart(target) {
|
||||
this.add('-start', target, 'Substitute');
|
||||
this.effectState.hp = Math.floor(target.maxhp / 4);
|
||||
delete target.volatiles['partiallytrapped'];
|
||||
},
|
||||
onTryPrimaryHitPriority: -1,
|
||||
inherit: true,
|
||||
onTryPrimaryHit(target, source, move) {
|
||||
if (target === source || move.flags['bypasssub']) {
|
||||
return;
|
||||
|
|
@ -931,9 +882,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
this.runEvent('AfterSubDamage', target, source, move, damage);
|
||||
return this.HIT_SUBSTITUTE;
|
||||
},
|
||||
onEnd(target) {
|
||||
this.add('-end', target, 'Substitute');
|
||||
},
|
||||
},
|
||||
},
|
||||
submission: {
|
||||
|
|
@ -990,7 +938,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
toxic: {
|
||||
inherit: true,
|
||||
onPrepareHit() {},
|
||||
onPrepareHit: undefined, // no inherit
|
||||
},
|
||||
uproar: {
|
||||
inherit: true,
|
||||
|
|
@ -1018,7 +966,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
watersport: {
|
||||
inherit: true,
|
||||
pseudoWeather: undefined,
|
||||
pseudoWeather: undefined, // no inherit
|
||||
volatileStatus: 'watersport',
|
||||
condition: {
|
||||
noCopy: true,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable
|
|||
standard: {
|
||||
inherit: true,
|
||||
ruleset: [
|
||||
'Obtainable', 'Team Preview', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Moody Clause', 'Evasion Items Clause', 'Evasion Moves Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod',
|
||||
'Standard AG',
|
||||
'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Items Clause', 'Evasion Moves Clause',
|
||||
],
|
||||
},
|
||||
obtainablemoves: {
|
||||
|
|
|
|||
|
|
@ -1,117 +0,0 @@
|
|||
export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTable = {
|
||||
mummy: {
|
||||
inherit: true,
|
||||
onDamagingHit(damage, target, source, move) {
|
||||
if (target.ability === 'mummy') {
|
||||
const sourceAbility = source.getAbility();
|
||||
if (sourceAbility.flags['cantsuppress'] || sourceAbility.id === 'mummy') {
|
||||
return;
|
||||
}
|
||||
if (this.checkMoveMakesContact(move, source, target, !source.isAlly(target))) {
|
||||
const oldAbility = source.setAbility('mummy', target);
|
||||
if (oldAbility) {
|
||||
this.add('-activate', target, 'ability: Mummy', this.dex.abilities.get(oldAbility).name, `[of] ${source}`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const possibleAbilities = [source.ability, ...(source.m.innates || [])]
|
||||
.filter(val => !this.dex.abilities.get(val).flags['cantsuppress'] && val !== 'mummy');
|
||||
if (!possibleAbilities.length) return;
|
||||
if (this.checkMoveMakesContact(move, source, target, !source.isAlly(target))) {
|
||||
const abil = this.sample(possibleAbilities);
|
||||
if (abil === source.ability) {
|
||||
const oldAbility = source.setAbility('mummy', target);
|
||||
if (oldAbility) {
|
||||
this.add('-activate', target, 'ability: Mummy', this.dex.abilities.get(oldAbility).name, `[of] ${source}`);
|
||||
}
|
||||
} else {
|
||||
source.removeVolatile('ability:' + abil);
|
||||
source.addVolatile('ability:mummy', source);
|
||||
if (abil) {
|
||||
this.add('-activate', target, 'ability: Mummy', this.dex.abilities.get(abil).name, `[of] ${source}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
powerofalchemy: {
|
||||
inherit: true,
|
||||
onAllyFaint(ally) {
|
||||
const pokemon = this.effectState.target;
|
||||
if (!pokemon.hp) return;
|
||||
const isAbility = pokemon.ability === 'powerofalchemy';
|
||||
let possibleAbilities = [ally.ability];
|
||||
if (ally.m.innates) possibleAbilities.push(...ally.m.innates);
|
||||
const additionalBannedAbilities = [pokemon.ability, ...(pokemon.m.innates || [])];
|
||||
possibleAbilities = possibleAbilities
|
||||
.filter(val => !this.dex.abilities.get(val).flags['noreceiver'] && !additionalBannedAbilities.includes(val));
|
||||
if (!possibleAbilities.length) return;
|
||||
const ability = this.dex.abilities.get(possibleAbilities[this.random(possibleAbilities.length)]);
|
||||
this.add('-ability', pokemon, ability, '[from] ability: Power of Alchemy', `[of] ${ally}`);
|
||||
if (isAbility) {
|
||||
pokemon.setAbility(ability);
|
||||
} else {
|
||||
pokemon.removeVolatile("ability:powerofalchemy");
|
||||
pokemon.addVolatile(`ability:${ability}`, pokemon);
|
||||
}
|
||||
},
|
||||
},
|
||||
receiver: {
|
||||
inherit: true,
|
||||
onAllyFaint(ally) {
|
||||
const pokemon = this.effectState.target;
|
||||
if (!pokemon.hp) return;
|
||||
const isAbility = pokemon.ability === 'receiver';
|
||||
let possibleAbilities = [ally.ability];
|
||||
if (ally.m.innates) possibleAbilities.push(...ally.m.innates);
|
||||
const additionalBannedAbilities = [pokemon.ability, ...(pokemon.m.innates || [])];
|
||||
possibleAbilities = possibleAbilities
|
||||
.filter(val => !this.dex.abilities.get(val).flags['noreceiver'] && !additionalBannedAbilities.includes(val));
|
||||
if (!possibleAbilities.length) return;
|
||||
const ability = this.dex.abilities.get(possibleAbilities[this.random(possibleAbilities.length)]);
|
||||
this.add('-ability', pokemon, ability, '[from] ability: Receiver', `[of] ${ally}`);
|
||||
if (isAbility) {
|
||||
pokemon.setAbility(ability);
|
||||
} else {
|
||||
pokemon.removeVolatile("ability:receiver");
|
||||
pokemon.addVolatile(`ability:${ability}`, pokemon);
|
||||
}
|
||||
},
|
||||
},
|
||||
trace: {
|
||||
inherit: true,
|
||||
onUpdate(pokemon) {
|
||||
if (!this.effectState.seek) return;
|
||||
const isAbility = pokemon.ability === 'trace';
|
||||
const possibleTargets: Pokemon[] = [];
|
||||
for (const target of pokemon.side.foe.active) {
|
||||
if (target && !target.fainted) {
|
||||
possibleTargets.push(target);
|
||||
}
|
||||
}
|
||||
while (possibleTargets.length) {
|
||||
const rand = this.random(possibleTargets.length);
|
||||
const target = possibleTargets[rand];
|
||||
let possibleAbilities = [target.ability];
|
||||
if (target.m.innates) possibleAbilities.push(...target.m.innates);
|
||||
const additionalBannedAbilities = [pokemon.ability, ...(pokemon.m.innates || [])];
|
||||
possibleAbilities = possibleAbilities
|
||||
.filter(val => !this.dex.abilities.get(val).flags['notrace'] && !additionalBannedAbilities.includes(val));
|
||||
if (!possibleAbilities.length) {
|
||||
possibleTargets.splice(rand, 1);
|
||||
continue;
|
||||
}
|
||||
const ability = this.dex.abilities.get(this.sample(possibleAbilities));
|
||||
this.add('-ability', pokemon, ability, '[from] ability: Trace', `[of] ${target}`);
|
||||
if (isAbility) {
|
||||
pokemon.setAbility(ability);
|
||||
} else {
|
||||
pokemon.removeVolatile("ability:trace");
|
||||
pokemon.addVolatile(`ability:${ability}`, pokemon);
|
||||
}
|
||||
return;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
||||
gastroacid: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
// Ability suppression implemented in Pokemon.ignoringAbility() within sim/pokemon.js
|
||||
onStart(pokemon) {
|
||||
this.add('-endability', pokemon);
|
||||
this.singleEvent('End', pokemon.getAbility(), pokemon.abilityState, pokemon, pokemon, 'gastroacid');
|
||||
if (pokemon.m.innates) {
|
||||
for (const innate of pokemon.m.innates) {
|
||||
pokemon.removeVolatile("ability" + innate);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -1,215 +0,0 @@
|
|||
export const Scripts: ModdedBattleScriptsData = {
|
||||
inherit: 'gen5',
|
||||
field: {
|
||||
suppressingWeather() {
|
||||
for (const pokemon of this.battle.getAllActive()) {
|
||||
if (pokemon && !pokemon.fainted && !pokemon.ignoringAbility() &&
|
||||
(pokemon.getAbility().suppressWeather ||
|
||||
pokemon.m.innates?.some((k: string) => this.battle.dex.abilities.get(k).suppressWeather))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
},
|
||||
pokemon: {
|
||||
ignoringAbility() {
|
||||
// Check if any active pokemon have the ability Neutralizing Gas
|
||||
let neutralizinggas = false;
|
||||
for (const pokemon of this.battle.getAllActive()) {
|
||||
// can't use hasAbility because it would lead to infinite recursion
|
||||
if (
|
||||
(pokemon.ability === ('neutralizinggas' as ID) || pokemon.m.innates?.some((k: string) => k === 'neutralizinggas')) &&
|
||||
!pokemon.volatiles['gastroacid'] && !pokemon.abilityState.ending
|
||||
) {
|
||||
neutralizinggas = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return !!(
|
||||
(this.battle.gen >= 5 && !this.isActive) ||
|
||||
((this.volatiles['gastroacid'] ||
|
||||
(neutralizinggas && (this.ability !== ('neutralizinggas' as ID) ||
|
||||
this.m.innates?.some((k: string) => k === 'neutralizinggas'))
|
||||
)) && !this.getAbility().flags['cantsuppress']
|
||||
)
|
||||
);
|
||||
},
|
||||
hasAbility(ability) {
|
||||
if (this.ignoringAbility()) return false;
|
||||
if (Array.isArray(ability)) return ability.some(abil => this.hasAbility(abil));
|
||||
ability = this.battle.toID(ability);
|
||||
return this.ability === ability || !!this.volatiles['ability:' + ability];
|
||||
},
|
||||
transformInto(pokemon, effect) {
|
||||
const species = pokemon.species;
|
||||
if (pokemon.fainted || this.illusion || pokemon.illusion || (pokemon.volatiles['substitute'] && this.battle.gen >= 5) ||
|
||||
(pokemon.transformed && this.battle.gen >= 2) || (this.transformed && this.battle.gen >= 5) ||
|
||||
species.name === 'Eternatus-Eternamax') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.setSpecies(species, effect, true)) return false;
|
||||
|
||||
this.transformed = true;
|
||||
this.weighthg = pokemon.weighthg;
|
||||
|
||||
const types = pokemon.getTypes(true, true);
|
||||
this.setType(pokemon.volatiles['roost'] ? pokemon.volatiles['roost'].typeWas : types, true);
|
||||
this.addedType = pokemon.addedType;
|
||||
this.knownType = this.isAlly(pokemon) && pokemon.knownType;
|
||||
this.apparentType = pokemon.apparentType;
|
||||
|
||||
let statName: StatIDExceptHP;
|
||||
for (statName in this.storedStats) {
|
||||
this.storedStats[statName] = pokemon.storedStats[statName];
|
||||
if (this.modifiedStats) this.modifiedStats[statName] = pokemon.modifiedStats![statName]; // Gen 1: Copy modified stats.
|
||||
}
|
||||
this.moveSlots = [];
|
||||
this.set.ivs = (this.battle.gen >= 5 ? this.set.ivs : pokemon.set.ivs);
|
||||
this.hpType = (this.battle.gen >= 5 ? this.hpType : pokemon.hpType);
|
||||
this.hpPower = (this.battle.gen >= 5 ? this.hpPower : pokemon.hpPower);
|
||||
this.timesAttacked = pokemon.timesAttacked;
|
||||
for (const moveSlot of pokemon.moveSlots) {
|
||||
let moveName = moveSlot.move;
|
||||
if (moveSlot.id === 'hiddenpower') {
|
||||
moveName = 'Hidden Power ' + this.hpType;
|
||||
}
|
||||
this.moveSlots.push({
|
||||
move: moveName,
|
||||
id: moveSlot.id,
|
||||
pp: moveSlot.maxpp === 1 ? 1 : 5,
|
||||
maxpp: this.battle.gen >= 5 ? (moveSlot.maxpp === 1 ? 1 : 5) : moveSlot.maxpp,
|
||||
target: moveSlot.target,
|
||||
disabled: false,
|
||||
used: false,
|
||||
virtual: true,
|
||||
});
|
||||
}
|
||||
let boostName: BoostID;
|
||||
for (boostName in pokemon.boosts) {
|
||||
this.boosts[boostName] = pokemon.boosts[boostName];
|
||||
}
|
||||
if (this.battle.gen >= 6) {
|
||||
// we need to be sure to remove all the overlapping crit volatiles before trying to add any of them
|
||||
const volatilesToCopy = ['dragoncheer', 'focusenergy', 'gmaxchistrike', 'laserfocus'];
|
||||
for (const volatile of volatilesToCopy) this.removeVolatile(volatile);
|
||||
for (const volatile of volatilesToCopy) {
|
||||
if (pokemon.volatiles[volatile]) {
|
||||
this.addVolatile(volatile);
|
||||
if (volatile === 'gmaxchistrike') this.volatiles[volatile].layers = pokemon.volatiles[volatile].layers;
|
||||
if (volatile === 'dragoncheer') this.volatiles[volatile].hasDragonType = pokemon.volatiles[volatile].hasDragonType;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (effect) {
|
||||
this.battle.add('-transform', this, pokemon, '[from] ' + effect.fullname);
|
||||
} else {
|
||||
this.battle.add('-transform', this, pokemon);
|
||||
}
|
||||
if (this.terastallized && this.terastallized !== this.apparentType) {
|
||||
this.battle.add('-start', this, 'typechange', this.terastallized, '[silent]');
|
||||
this.apparentType = this.terastallized;
|
||||
}
|
||||
if (this.battle.gen > 2) {
|
||||
this.setAbility(pokemon.ability, this, null, true);
|
||||
if (this.m.innates) {
|
||||
for (const innate of this.m.innates) {
|
||||
this.removeVolatile('ability:' + innate);
|
||||
}
|
||||
}
|
||||
if (pokemon.m.innates) {
|
||||
for (const innate of pokemon.m.innates) {
|
||||
this.addVolatile('ability:' + innate, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Change formes based on held items (for Transform)
|
||||
// Only ever relevant in Generation 4 since Generation 3 didn't have item-based forme changes
|
||||
if (this.battle.gen === 4) {
|
||||
if (this.species.num === 487) {
|
||||
// Giratina formes
|
||||
if (this.species.name === 'Giratina' && this.item === 'griseousorb') {
|
||||
this.formeChange('Giratina-Origin');
|
||||
} else if (this.species.name === 'Giratina-Origin' && this.item !== 'griseousorb') {
|
||||
this.formeChange('Giratina');
|
||||
}
|
||||
}
|
||||
if (this.species.num === 493) {
|
||||
// Arceus formes
|
||||
const item = this.getItem();
|
||||
const targetForme = (item?.onPlate ? 'Arceus-' + item.onPlate : 'Arceus');
|
||||
if (this.species.name !== targetForme) {
|
||||
this.formeChange(targetForme);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
/**
|
||||
* Changes this Pokemon's forme to match the given speciesId (or species).
|
||||
* This function handles all changes to stats, ability, type, species, etc.
|
||||
* as well as sending all relevant messages sent to the client.
|
||||
*/
|
||||
formeChange(speciesId, source, isPermanent, message) {
|
||||
if (!source) source = this.battle.effect;
|
||||
|
||||
const rawSpecies = this.battle.dex.species.get(speciesId);
|
||||
|
||||
const species = this.setSpecies(rawSpecies, source);
|
||||
if (!species) return false;
|
||||
|
||||
if (this.battle.gen <= 2) return true;
|
||||
|
||||
// The species the opponent sees
|
||||
const apparentSpecies =
|
||||
this.illusion ? this.illusion.species.name : species.baseSpecies;
|
||||
if (isPermanent) {
|
||||
this.baseSpecies = rawSpecies;
|
||||
this.details = this.getUpdatedDetails();
|
||||
this.battle.add('detailschange', this, (this.illusion || this).details);
|
||||
if (source.effectType === 'Item') {
|
||||
this.canTerastallize = null; // National Dex behavior
|
||||
if (source.zMove) {
|
||||
this.battle.add('-burst', this, apparentSpecies, species.requiredItem);
|
||||
this.moveThisTurnResult = true; // Ultra Burst counts as an action for Truant
|
||||
} else if (source.isPrimalOrb) {
|
||||
if (this.illusion) {
|
||||
this.ability = '';
|
||||
this.battle.add('-primal', this.illusion);
|
||||
} else {
|
||||
this.battle.add('-primal', this);
|
||||
}
|
||||
} else {
|
||||
this.battle.add('-mega', this, apparentSpecies, species.requiredItem);
|
||||
this.moveThisTurnResult = true; // Mega Evolution counts as an action for Truant
|
||||
}
|
||||
} else if (source.effectType === 'Status') {
|
||||
// Shaymin-Sky -> Shaymin
|
||||
this.battle.add('-formechange', this, species.name, message);
|
||||
}
|
||||
} else {
|
||||
if (source.effectType === 'Ability') {
|
||||
this.battle.add('-formechange', this, species.name, message, `[from] ability: ${source.name}`);
|
||||
} else {
|
||||
this.battle.add('-formechange', this, this.illusion ? this.illusion.species.name : species.name, message);
|
||||
}
|
||||
}
|
||||
if (isPermanent && !['disguise', 'iceface', 'ability:disguise', 'ability:iceface'].includes(source.id)) {
|
||||
if (this.illusion) {
|
||||
this.ability = ''; // Don't allow Illusion to wear off
|
||||
}
|
||||
this.setAbility(species.abilities['0'], null, null, true);
|
||||
this.baseAbility = this.ability;
|
||||
}
|
||||
if (this.terastallized && this.terastallized !== this.apparentType) {
|
||||
this.battle.add('-start', this, 'typechange', this.terastallized, '[silent]');
|
||||
this.apparentType = this.terastallized;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -54,7 +54,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
move.type = 'Normal';
|
||||
}
|
||||
},
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
rating: -1,
|
||||
},
|
||||
parentalbond: {
|
||||
|
|
@ -93,7 +93,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
const targetForme = (move.id === 'kingsshield' ? 'Aegislash' : 'Aegislash-Blade');
|
||||
if (attacker.species.name !== targetForme) attacker.formeChange(targetForme);
|
||||
},
|
||||
onModifyMove() {},
|
||||
onModifyMove: undefined, // no inherit
|
||||
},
|
||||
symbiosis: {
|
||||
inherit: true,
|
||||
|
|
|
|||
|
|
@ -40,6 +40,6 @@ export const Conditions: import('../../../sim/dex-conditions').ModdedConditionDa
|
|||
},
|
||||
choicelock: {
|
||||
inherit: true,
|
||||
onBeforeMove() {},
|
||||
onBeforeMove: undefined, // no inherit
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1678,7 +1678,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
|
|||
doublesTier: "DUber",
|
||||
},
|
||||
jirachi: {
|
||||
tier: "OU",
|
||||
tier: "(OU)",
|
||||
doublesTier: "DUber",
|
||||
},
|
||||
deoxys: {
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
souldew: {
|
||||
inherit: true,
|
||||
onBasePower() {},
|
||||
onBasePower: undefined, // no inherit
|
||||
onModifySpAPriority: 1,
|
||||
onModifySpA(spa, pokemon) {
|
||||
if (pokemon.baseSpecies.num === 380 || pokemon.baseSpecies.num === 381) {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
darkvoid: {
|
||||
inherit: true,
|
||||
accuracy: 80,
|
||||
onTry() {},
|
||||
onTry: undefined, // no inherit
|
||||
},
|
||||
destinybond: {
|
||||
inherit: true,
|
||||
|
|
@ -24,7 +24,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
diamondstorm: {
|
||||
inherit: true,
|
||||
self: null,
|
||||
self: undefined, // no inherit
|
||||
secondary: {
|
||||
chance: 50,
|
||||
self: {
|
||||
|
|
@ -34,48 +34,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
},
|
||||
},
|
||||
encore: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 3,
|
||||
onStart(target) {
|
||||
const moveSlot = target.lastMove ? target.getMoveData(target.lastMove.id) : null;
|
||||
if (!target.lastMove || target.lastMove.flags['failencore'] || !moveSlot || moveSlot.pp <= 0) {
|
||||
// it failed
|
||||
return false;
|
||||
}
|
||||
this.effectState.move = target.lastMove.id;
|
||||
this.add('-start', target, 'Encore');
|
||||
if (!this.queue.willMove(target)) {
|
||||
this.effectState.duration!++;
|
||||
}
|
||||
},
|
||||
onOverrideAction(pokemon, target, move) {
|
||||
if (move.id !== this.effectState.move) return this.effectState.move;
|
||||
},
|
||||
onResidualOrder: 16,
|
||||
onResidual(target) {
|
||||
const lockedMoveSlot = target.getMoveData(this.effectState.move);
|
||||
if (lockedMoveSlot && lockedMoveSlot.pp <= 0) {
|
||||
// Encore ends early if you run out of PP
|
||||
target.removeVolatile('encore');
|
||||
}
|
||||
},
|
||||
onEnd(target) {
|
||||
this.add('-end', target, 'Encore');
|
||||
},
|
||||
onDisableMove(pokemon) {
|
||||
if (!this.effectState.move || !pokemon.hasMove(this.effectState.move)) {
|
||||
return;
|
||||
}
|
||||
for (const moveSlot of pokemon.moveSlots) {
|
||||
if (moveSlot.id !== this.effectState.move) {
|
||||
pokemon.disableMove(moveSlot.id);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
fellstinger: {
|
||||
inherit: true,
|
||||
basePower: 30,
|
||||
|
|
@ -87,6 +45,10 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
basePower: 80,
|
||||
},
|
||||
heavyslam: {
|
||||
inherit: true,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, nonsky: 1, metronome: 1 },
|
||||
},
|
||||
leechlife: {
|
||||
inherit: true,
|
||||
basePower: 20,
|
||||
|
|
@ -96,29 +58,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
flags: { protect: 1, bypasssub: 1, noassist: 1, failcopycat: 1, failmefirst: 1, nosleeptalk: 1 },
|
||||
},
|
||||
minimize: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
noCopy: true,
|
||||
onSourceModifyDamage(damage, source, target, move) {
|
||||
const boostedMoves = [
|
||||
'stomp', 'steamroller', 'bodyslam', 'flyingpress', 'dragonrush', 'phantomforce', 'heatcrash', 'shadowforce',
|
||||
];
|
||||
if (boostedMoves.includes(move.id)) {
|
||||
return this.chainModify(2);
|
||||
}
|
||||
},
|
||||
onAccuracy(accuracy, target, source, move) {
|
||||
const boostedMoves = [
|
||||
'stomp', 'steamroller', 'bodyslam', 'flyingpress', 'dragonrush', 'phantomforce', 'heatcrash', 'shadowforce',
|
||||
];
|
||||
if (boostedMoves.includes(move.id)) {
|
||||
return true;
|
||||
}
|
||||
return accuracy;
|
||||
},
|
||||
},
|
||||
},
|
||||
metronome: {
|
||||
inherit: true,
|
||||
flags: { noassist: 1, failcopycat: 1, nosleeptalk: 1 },
|
||||
|
|
@ -126,39 +65,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
mistyterrain: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
effectType: 'Terrain',
|
||||
duration: 5,
|
||||
durationCallback(source, effect) {
|
||||
if (source?.hasItem('terrainextender')) {
|
||||
return 8;
|
||||
}
|
||||
return 5;
|
||||
},
|
||||
onSetStatus(status, target, source, effect) {
|
||||
if (!target.isGrounded() || target.isSemiInvulnerable()) return;
|
||||
if (effect && ((effect as Move).status || effect.id === 'yawn')) {
|
||||
this.add('-activate', target, 'move: Misty Terrain');
|
||||
}
|
||||
return false;
|
||||
},
|
||||
onBasePower(basePower, attacker, defender, move) {
|
||||
if (move.type === 'Dragon' && defender.isGrounded() && !defender.isSemiInvulnerable()) {
|
||||
this.debug('misty terrain weaken');
|
||||
return this.chainModify(0.5);
|
||||
}
|
||||
},
|
||||
onFieldStart(field, source, effect) {
|
||||
if (effect?.effectType === 'Ability') {
|
||||
this.add('-fieldstart', 'move: Misty Terrain', `[from] ability: ${effect}`, `[of] ${source}`);
|
||||
} else {
|
||||
this.add('-fieldstart', 'move: Misty Terrain');
|
||||
}
|
||||
},
|
||||
onFieldResidualOrder: 27,
|
||||
onFieldResidualSubOrder: 7,
|
||||
onFieldEnd() {
|
||||
this.add('-fieldend', 'Misty Terrain');
|
||||
},
|
||||
inherit: true,
|
||||
onTryAddVolatile: undefined, // no inherit
|
||||
},
|
||||
},
|
||||
mysticalfire: {
|
||||
|
|
@ -179,28 +87,25 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
this.boost({ atk: -1, spa: -1 }, target, source);
|
||||
},
|
||||
},
|
||||
phantomforce: {
|
||||
inherit: true,
|
||||
flags: { contact: 1, charge: 1, mirror: 1, metronome: 1, nosleeptalk: 1, noassist: 1, failinstruct: 1, minimize: 1 },
|
||||
},
|
||||
powder: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 1,
|
||||
onStart(target) {
|
||||
this.add('-singleturn', target, 'Powder');
|
||||
},
|
||||
inherit: true,
|
||||
onTryMovePriority: 1,
|
||||
onTryMove(pokemon, target, move) {
|
||||
if (move.type === 'Fire') {
|
||||
this.add('-activate', pokemon, 'move: Powder');
|
||||
this.damage(this.clampIntRange(Math.round(pokemon.maxhp / 4), 1));
|
||||
this.attrLastMove('[still]');
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
rockblast: {
|
||||
inherit: true,
|
||||
flags: { protect: 1, mirror: 1, metronome: 1 },
|
||||
},
|
||||
shadowforce: {
|
||||
inherit: true,
|
||||
flags: { contact: 1, charge: 1, mirror: 1, metronome: 1, nosleeptalk: 1, noassist: 1, failinstruct: 1, minimize: 1 },
|
||||
},
|
||||
sheercold: {
|
||||
inherit: true,
|
||||
ohko: true,
|
||||
|
|
@ -263,19 +168,13 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
wideguard: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 1,
|
||||
onSideStart(target, source) {
|
||||
this.add('-singleturn', source, 'Wide Guard');
|
||||
},
|
||||
onTryHitPriority: 4,
|
||||
onTryHit(target, source, effect) {
|
||||
inherit: true,
|
||||
onTryHit(target, source, move) {
|
||||
// Wide Guard blocks damaging spread moves
|
||||
if (
|
||||
effect &&
|
||||
(effect.category === 'Status' || (effect.target !== 'allAdjacent' && effect.target !== 'allAdjacentFoes'))
|
||||
) {
|
||||
if (move.category === 'Status' || (move?.target !== 'allAdjacent' && move.target !== 'allAdjacentFoes')) {
|
||||
return;
|
||||
}
|
||||
if (this.checkMoveBypassesProtect(move, source, target, false)) return;
|
||||
this.add('-activate', target, 'move: Wide Guard');
|
||||
const lockedmove = source.getVolatile('lockedmove');
|
||||
if (lockedmove) {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
innerfocus: {
|
||||
inherit: true,
|
||||
rating: 1,
|
||||
onTryBoost() {},
|
||||
onTryBoost: undefined, // no inherit
|
||||
},
|
||||
moody: {
|
||||
inherit: true,
|
||||
|
|
@ -65,25 +65,19 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
},
|
||||
oblivious: {
|
||||
inherit: true,
|
||||
onTryBoost() {},
|
||||
onTryBoost: undefined, // no inherit
|
||||
},
|
||||
owntempo: {
|
||||
inherit: true,
|
||||
onTryBoost() {},
|
||||
onTryBoost: undefined, // no inherit
|
||||
},
|
||||
rattled: {
|
||||
onDamagingHit(damage, target, source, move) {
|
||||
if (['Dark', 'Bug', 'Ghost'].includes(move.type)) {
|
||||
this.boost({ spe: 1 });
|
||||
}
|
||||
},
|
||||
name: "Rattled",
|
||||
rating: 1.5,
|
||||
num: 155,
|
||||
inherit: true,
|
||||
onAfterBoost: undefined, // no inherit
|
||||
},
|
||||
scrappy: {
|
||||
inherit: true,
|
||||
onTryBoost() {},
|
||||
onTryBoost: undefined, // no inherit
|
||||
},
|
||||
slowstart: {
|
||||
inherit: true,
|
||||
|
|
|
|||
|
|
@ -592,7 +592,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
|
|||
doublesTier: "NFE",
|
||||
},
|
||||
tangrowth: {
|
||||
tier: "OU",
|
||||
tier: "(OU)",
|
||||
doublesTier: "(DUU)",
|
||||
},
|
||||
kangaskhan: {
|
||||
|
|
|
|||
|
|
@ -182,47 +182,13 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
electricterrain: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
effectType: 'Terrain',
|
||||
duration: 5,
|
||||
durationCallback(source, effect) {
|
||||
if (source?.hasItem('terrainextender')) {
|
||||
return 8;
|
||||
}
|
||||
return 5;
|
||||
},
|
||||
onSetStatus(status, target, source, effect) {
|
||||
if (status.id === 'slp' && target.isGrounded() && !target.isSemiInvulnerable()) {
|
||||
if (effect.id === 'yawn' || (effect.effectType === 'Move' && !effect.secondaries)) {
|
||||
this.add('-activate', target, 'move: Electric Terrain');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
onTryAddVolatile(status, target) {
|
||||
if (!target.isGrounded() || target.isSemiInvulnerable()) return;
|
||||
if (status.id === 'yawn') {
|
||||
this.add('-activate', target, 'move: Electric Terrain');
|
||||
return null;
|
||||
}
|
||||
},
|
||||
inherit: true,
|
||||
onBasePower(basePower, attacker, defender, move) {
|
||||
if (move.type === 'Electric' && attacker.isGrounded() && !attacker.isSemiInvulnerable()) {
|
||||
this.debug('electric terrain boost');
|
||||
return this.chainModify(1.5);
|
||||
}
|
||||
},
|
||||
onFieldStart(field, source, effect) {
|
||||
if (effect && effect.effectType === 'Ability') {
|
||||
this.add('-fieldstart', 'move: Electric Terrain', `[from] ability: ${effect}`, `[of] ${source}`);
|
||||
} else {
|
||||
this.add('-fieldstart', 'move: Electric Terrain');
|
||||
}
|
||||
},
|
||||
onFieldResidualOrder: 27,
|
||||
onFieldResidualSubOrder: 7,
|
||||
onFieldEnd() {
|
||||
this.add('-fieldend', 'move: Electric Terrain');
|
||||
},
|
||||
},
|
||||
},
|
||||
embargo: {
|
||||
|
|
@ -307,7 +273,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
grassknot: {
|
||||
inherit: true,
|
||||
onTryHit() {},
|
||||
onTryHit: undefined, // no inherit
|
||||
},
|
||||
grasswhistle: {
|
||||
inherit: true,
|
||||
|
|
@ -316,14 +282,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
grassyterrain: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
effectType: 'Terrain',
|
||||
duration: 5,
|
||||
durationCallback(source, effect) {
|
||||
if (source?.hasItem('terrainextender')) {
|
||||
return 8;
|
||||
}
|
||||
return 5;
|
||||
},
|
||||
inherit: true,
|
||||
onBasePower(basePower, attacker, defender, move) {
|
||||
const weakenedMoves = ['earthquake', 'bulldoze', 'magnitude'];
|
||||
if (weakenedMoves.includes(move.id) && defender.isGrounded() && !defender.isSemiInvulnerable()) {
|
||||
|
|
@ -335,27 +294,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
return this.chainModify(1.5);
|
||||
}
|
||||
},
|
||||
onFieldStart(field, source, effect) {
|
||||
if (effect && effect.effectType === 'Ability') {
|
||||
this.add('-fieldstart', 'move: Grassy Terrain', `[from] ability: ${effect}`, `[of] ${source}`);
|
||||
} else {
|
||||
this.add('-fieldstart', 'move: Grassy Terrain');
|
||||
}
|
||||
},
|
||||
onResidualOrder: 5,
|
||||
onResidualSubOrder: 2,
|
||||
onResidual(pokemon) {
|
||||
if (pokemon.isGrounded() && !pokemon.isSemiInvulnerable()) {
|
||||
this.heal(pokemon.baseMaxhp / 16, pokemon, pokemon);
|
||||
} else {
|
||||
this.debug(`Pokemon semi-invuln or not grounded; Grassy Terrain skipped`);
|
||||
}
|
||||
},
|
||||
onFieldResidualOrder: 27,
|
||||
onFieldResidualSubOrder: 7,
|
||||
onFieldEnd() {
|
||||
this.add('-fieldend', 'move: Grassy Terrain');
|
||||
},
|
||||
},
|
||||
},
|
||||
guardianofalola: {
|
||||
|
|
@ -429,11 +367,11 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
heatcrash: {
|
||||
inherit: true,
|
||||
onTryHit() {},
|
||||
onTryHit: undefined, // no inherit
|
||||
},
|
||||
heavyslam: {
|
||||
inherit: true,
|
||||
onTryHit() {},
|
||||
onTryHit: undefined, // no inherit
|
||||
},
|
||||
hiddenpower: {
|
||||
inherit: true,
|
||||
|
|
@ -558,16 +496,9 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
kingsshield: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 1,
|
||||
onStart(target) {
|
||||
this.add('-singleturn', target, 'Protect');
|
||||
},
|
||||
onTryHitPriority: 3,
|
||||
inherit: true,
|
||||
onTryHit(target, source, move) {
|
||||
if (!move.flags['protect'] || move.category === 'Status') {
|
||||
if (move.isZ || move.isMax) target.getMoveHitData(move).zBrokeProtect = true;
|
||||
return;
|
||||
}
|
||||
if (this.checkMoveBypassesProtect(move, source, target, false)) return;
|
||||
this.add('-activate', target, 'move: Protect');
|
||||
const lockedmove = source.getVolatile('lockedmove');
|
||||
if (lockedmove) {
|
||||
|
|
@ -602,7 +533,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
lowkick: {
|
||||
inherit: true,
|
||||
onTryHit() {},
|
||||
onTryHit: undefined, // no inherit
|
||||
},
|
||||
luckychant: {
|
||||
inherit: true,
|
||||
|
|
@ -780,48 +711,13 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
psychicterrain: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
effectType: 'Terrain',
|
||||
duration: 5,
|
||||
durationCallback(source, effect) {
|
||||
if (source?.hasItem('terrainextender')) {
|
||||
return 8;
|
||||
}
|
||||
return 5;
|
||||
},
|
||||
onTryHitPriority: 4,
|
||||
onTryHit(target, source, effect) {
|
||||
if (effect && (effect.priority <= 0.1 || effect.target === 'self')) {
|
||||
return;
|
||||
}
|
||||
if (target.isSemiInvulnerable() || target.isAlly(source)) return;
|
||||
if (!target.isGrounded()) {
|
||||
const baseMove = this.dex.moves.get(effect.id);
|
||||
if (baseMove.priority > 0) {
|
||||
this.hint("Psychic Terrain doesn't affect Pokémon immune to Ground.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.add('-activate', target, 'move: Psychic Terrain');
|
||||
return null;
|
||||
},
|
||||
inherit: true,
|
||||
onBasePower(basePower, attacker, defender, move) {
|
||||
if (move.type === 'Psychic' && attacker.isGrounded() && !attacker.isSemiInvulnerable()) {
|
||||
this.debug('psychic terrain boost');
|
||||
return this.chainModify(1.5);
|
||||
}
|
||||
},
|
||||
onFieldStart(field, source, effect) {
|
||||
if (effect && effect.effectType === 'Ability') {
|
||||
this.add('-fieldstart', 'move: Psychic Terrain', `[from] ability: ${effect}`, `[of] ${source}`);
|
||||
} else {
|
||||
this.add('-fieldstart', 'move: Psychic Terrain');
|
||||
}
|
||||
},
|
||||
onFieldResidualOrder: 27,
|
||||
onFieldResidualSubOrder: 7,
|
||||
onFieldEnd() {
|
||||
this.add('-fieldend', 'move: Psychic Terrain');
|
||||
},
|
||||
},
|
||||
},
|
||||
psychoboost: {
|
||||
|
|
@ -876,7 +772,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
rapidspin: {
|
||||
inherit: true,
|
||||
basePower: 20,
|
||||
secondary: null,
|
||||
secondary: undefined, // no inherit
|
||||
},
|
||||
razorwind: {
|
||||
inherit: true,
|
||||
|
|
@ -1182,6 +1078,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
basePower: 50,
|
||||
pp: 15,
|
||||
willCrit: true,
|
||||
secondary: null,
|
||||
secondary: undefined, // no inherit
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,11 +1,19 @@
|
|||
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
|
||||
standard: {
|
||||
inherit: true,
|
||||
ruleset: ['Obtainable', 'Team Preview', 'Sleep Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Moody Clause', 'Evasion Items Clause', 'Evasion Moves Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod'],
|
||||
ruleset: [
|
||||
'Standard AG',
|
||||
'Sleep Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Items Clause', 'Evasion Moves Clause',
|
||||
],
|
||||
banlist: ['Moody'],
|
||||
},
|
||||
standarddoubles: {
|
||||
inherit: true,
|
||||
ruleset: ['Obtainable', 'Team Preview', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Moody Clause', 'Evasion Abilities Clause', 'Evasion Moves Clause', 'Gravity Sleep Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod'],
|
||||
ruleset: [
|
||||
'Standard AG',
|
||||
'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Abilities Clause', 'Evasion Moves Clause', 'Gravity Sleep Clause',
|
||||
],
|
||||
banlist: ['Moody'],
|
||||
},
|
||||
obtainablemoves: {
|
||||
inherit: true,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
doubleironbash: {
|
||||
inherit: true,
|
||||
isNonstandard: null,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, punch: 1, minimize: 1 },
|
||||
},
|
||||
floatyfall: {
|
||||
inherit: true,
|
||||
|
|
@ -41,8 +42,11 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
desc: "A random move that was introduced in gen 1 is selected for use, other than Counter, Mimic, Mirror Move, Struggle, or Transform.",
|
||||
shortDesc: "Picks a random move from gen 1.",
|
||||
onHit(target, source, effect) {
|
||||
const moves = this.dex.moves.all().filter(move => move.gen === 1 && move.flags['metronome']);
|
||||
onHit(target) {
|
||||
const moves = this.dex.moves.all().filter(move => (
|
||||
(!move.isNonstandard || move.isNonstandard === 'Unobtainable') &&
|
||||
move.flags['metronome'] && move.gen === 1
|
||||
));
|
||||
let randomMove = '';
|
||||
if (moves.length) {
|
||||
moves.sort((a, b) => a.num - b.num);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,16 @@
|
|||
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
|
||||
standard: {
|
||||
inherit: true,
|
||||
ruleset: ['LGPE Normal Rules', 'Obtainable', 'Team Preview', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Moves Clause', 'HP Percentage Mod', 'Cancel Mod', 'Sleep Clause Mod'],
|
||||
ruleset: [
|
||||
'Standard AG',
|
||||
'LGPE Normal Rules', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Moves Clause', 'Sleep Clause Mod',
|
||||
],
|
||||
},
|
||||
standarddoubles: {
|
||||
inherit: true,
|
||||
ruleset: ['LGPE Normal Rules', 'Obtainable', 'Team Preview', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Moves Clause', 'HP Percentage Mod', 'Cancel Mod'],
|
||||
ruleset: [
|
||||
'Standard AG',
|
||||
'LGPE Normal Rules', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Moves Clause',
|
||||
],
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,117 +0,0 @@
|
|||
export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTable = {
|
||||
mummy: {
|
||||
inherit: true,
|
||||
onDamagingHit(damage, target, source, move) {
|
||||
if (target.ability === 'mummy') {
|
||||
const sourceAbility = source.getAbility();
|
||||
if (sourceAbility.flags['cantsuppress'] || sourceAbility.id === 'mummy') {
|
||||
return;
|
||||
}
|
||||
if (this.checkMoveMakesContact(move, source, target, !source.isAlly(target))) {
|
||||
const oldAbility = source.setAbility('mummy', target);
|
||||
if (oldAbility) {
|
||||
this.add('-activate', target, 'ability: Mummy', this.dex.abilities.get(oldAbility).name, `[of] ${source}`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const possibleAbilities = [source.ability, ...(source.m.innates || [])]
|
||||
.filter(val => !this.dex.abilities.get(val).flags['cantsuppress'] && val !== 'mummy');
|
||||
if (!possibleAbilities.length) return;
|
||||
if (this.checkMoveMakesContact(move, source, target, !source.isAlly(target))) {
|
||||
const abil = this.sample(possibleAbilities);
|
||||
if (abil === source.ability) {
|
||||
const oldAbility = source.setAbility('mummy', target);
|
||||
if (oldAbility) {
|
||||
this.add('-activate', target, 'ability: Mummy', this.dex.abilities.get(oldAbility).name, `[of] ${source}`);
|
||||
}
|
||||
} else {
|
||||
source.removeVolatile('ability:' + abil);
|
||||
source.addVolatile('ability:mummy', source);
|
||||
if (abil) {
|
||||
this.add('-activate', target, 'ability: Mummy', this.dex.abilities.get(abil).name, `[of] ${source}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
powerofalchemy: {
|
||||
inherit: true,
|
||||
onAllyFaint(ally) {
|
||||
const pokemon = this.effectState.target;
|
||||
if (!pokemon.hp) return;
|
||||
const isAbility = pokemon.ability === 'powerofalchemy';
|
||||
let possibleAbilities = [ally.ability];
|
||||
if (ally.m.innates) possibleAbilities.push(...ally.m.innates);
|
||||
const additionalBannedAbilities = [pokemon.ability, ...(pokemon.m.innates || [])];
|
||||
possibleAbilities = possibleAbilities
|
||||
.filter(val => !this.dex.abilities.get(val).flags['noreceiver'] && !additionalBannedAbilities.includes(val));
|
||||
if (!possibleAbilities.length) return;
|
||||
const ability = this.dex.abilities.get(possibleAbilities[this.random(possibleAbilities.length)]);
|
||||
this.add('-ability', pokemon, ability, '[from] ability: Power of Alchemy', `[of] ${ally}`);
|
||||
if (isAbility) {
|
||||
pokemon.setAbility(ability);
|
||||
} else {
|
||||
pokemon.removeVolatile("ability:powerofalchemy");
|
||||
pokemon.addVolatile(`ability:${ability}`, pokemon);
|
||||
}
|
||||
},
|
||||
},
|
||||
receiver: {
|
||||
inherit: true,
|
||||
onAllyFaint(ally) {
|
||||
const pokemon = this.effectState.target;
|
||||
if (!pokemon.hp) return;
|
||||
const isAbility = pokemon.ability === 'receiver';
|
||||
let possibleAbilities = [ally.ability];
|
||||
if (ally.m.innates) possibleAbilities.push(...ally.m.innates);
|
||||
const additionalBannedAbilities = [pokemon.ability, ...(pokemon.m.innates || [])];
|
||||
possibleAbilities = possibleAbilities
|
||||
.filter(val => !this.dex.abilities.get(val).flags['noreceiver'] && !additionalBannedAbilities.includes(val));
|
||||
if (!possibleAbilities.length) return;
|
||||
const ability = this.dex.abilities.get(possibleAbilities[this.random(possibleAbilities.length)]);
|
||||
this.add('-ability', pokemon, ability, '[from] ability: Receiver', `[of] ${ally}`);
|
||||
if (isAbility) {
|
||||
pokemon.setAbility(ability);
|
||||
} else {
|
||||
pokemon.removeVolatile("ability:receiver");
|
||||
pokemon.addVolatile(`ability:${ability}`, pokemon);
|
||||
}
|
||||
},
|
||||
},
|
||||
trace: {
|
||||
inherit: true,
|
||||
onUpdate(pokemon) {
|
||||
if (!this.effectState.seek) return;
|
||||
const isAbility = pokemon.ability === 'trace';
|
||||
const possibleTargets: Pokemon[] = [];
|
||||
for (const target of pokemon.side.foe.active) {
|
||||
if (target && !target.fainted) {
|
||||
possibleTargets.push(target);
|
||||
}
|
||||
}
|
||||
while (possibleTargets.length) {
|
||||
const rand = this.random(possibleTargets.length);
|
||||
const target = possibleTargets[rand];
|
||||
let possibleAbilities = [target.ability];
|
||||
if (target.m.innates) possibleAbilities.push(...target.m.innates);
|
||||
const additionalBannedAbilities = [pokemon.ability, ...(pokemon.m.innates || [])];
|
||||
possibleAbilities = possibleAbilities
|
||||
.filter(val => !this.dex.abilities.get(val).flags['notrace'] && !additionalBannedAbilities.includes(val));
|
||||
if (!possibleAbilities.length) {
|
||||
possibleTargets.splice(rand, 1);
|
||||
continue;
|
||||
}
|
||||
const ability = this.dex.abilities.get(this.sample(possibleAbilities));
|
||||
this.add('-ability', pokemon, ability, '[from] ability: Trace', `[of] ${target}`);
|
||||
if (isAbility) {
|
||||
pokemon.setAbility(ability);
|
||||
} else {
|
||||
pokemon.removeVolatile("ability:trace");
|
||||
pokemon.addVolatile(`ability:${ability}`, pokemon);
|
||||
}
|
||||
return;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user