Compare commits

...

1055 Commits

Author SHA1 Message Date
shrianshChari
0e66fb4fc3
Create tests for Synchronoise (#11834)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Create tests for Synchronoise

* Remove noisy elements

Co-authored-by: André Bastos Dias <80102738+andrebastosdias@users.noreply.github.com>

---------

Co-authored-by: André Bastos Dias <80102738+andrebastosdias@users.noreply.github.com>
2026-03-21 11:41:23 -06:00
André Bastos Dias
54ac918828
Remove unnecessary type assertion in Beat Up (#11832)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2026-03-19 23:08:45 -06:00
André Bastos Dias
815b5f260a
Support inheritance of ability, item, and move conditions (#11754)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2026-03-19 03:44:48 -07:00
TurboRx
2dfe57c13a
Bump GitHub Actions versions (#11826)
Co-authored-by: TurboRx <TurboRx@users.noreply.github.com>
2026-03-18 18:03:59 -07:00
André Bastos Dias
6938f1f807
Show the hint message for Ogerpon Terastallization only on one side (#11810)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2026-03-17 23:40:12 -06:00
Kris Johnson
e57a806630 Linked: Fix Upper Hand 2026-03-17 22:58:12 -06:00
André Bastos Dias
e7b13b7df3
Implement Pomeg Glitch Clause (#11800) 2026-03-17 16:37:23 -07:00
Slayer95
307b84fe4c
Make Beat Up info withholding a rule: Beat Up Nicknames Mod (#11825) 2026-03-17 16:30:54 -07:00
SantiagoRR2004
9e270bebe4
Fix #11744; Importing mysql2 and pg when it is not required (#11747)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2026-03-17 15:04:07 -07:00
Sunny
c7717be292
Gen 1 Stadium Rentals: Fix implementation (#11824)
* Implementing Stadium Rentals

* pidgeot fix

* Duplicate Fixing
2026-03-17 15:58:19 -06:00
Aurastic
79483f6616
Explicitly set type="submit" on form buttons (#11726)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2026-03-17 00:17:03 -07:00
Slayer95
1832b39b7b
Allow highlighting on broadcast !faq,rfaq,daily,avatars (#11818)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2026-03-16 22:03:01 -07:00
André Bastos Dias
84f6e93478
Remove single-ban clauses (#11822) 2026-03-16 19:54:59 -07:00
Mia
2b55cb90fc Rooms: Ensure minor activity queue is restored on startup
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2026-03-16 15:24:56 -05:00
Mia
f01268f26c Moderation: Fix /offlineforcerename modlogging
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2026-03-16 01:12:02 -05:00
Kris Johnson
c0c337ec45 Pokebilities AAA: Fix bans 2026-03-15 19:33:10 -06:00
Kris Johnson
0c78853bc6 350 Cup: Update bans 2026-03-15 19:32:28 -06:00
Kris Johnson
4ceb02536c Linked: Update bans 2026-03-15 19:31:23 -06:00
demir
6bd082af47
35 Pokes: Ban Tyranitar, unban Wo-Chien (#11814)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2026-03-15 15:12:43 -06:00
André Bastos Dias
be33fc1ee6
LC: Ban Shellder (#11819)
* LC: Ban Shellder

https://www.smogon.com/forums/threads/dirty-little-secret-shellder-suspect-test.3778358/post-10909234

* Ban Shellder in formats

* Remove Shellder from LC UU banlist
2026-03-15 15:12:23 -06:00
Kris Johnson
bf6e6efbe7 Add [Gen 1] Stadium Rentals
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2026-03-13 22:31:59 -06:00
EvGym
3b326cfa83
Adding Gen 3 Hoenn Stadium format (#11797)
* Adding gen 3 colosseum format, updating win check

* Update formats.ts

* Adding Gen 3 Hoenn Stadium format

* They want open team sheets on the format

* Fixing selfKO clause code for the gen3colosseum mod.
- Perish song only cares if the user is the last mon, we had that wrong.
- Corrected the game resolution code to properly calculate winners/draws (Has been tested on a dev server)

* forgot Destiny bond

* Cleaning up ban and unban lists for hoenn stadium

* Deoxys is not nonstandard

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2026-03-13 19:32:36 -06:00
Kris Johnson
2742d9dd47 Remove unused mods
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2026-03-13 13:23:06 -06:00
Kris Johnson
c4d659391a STABmons: Update bans 2026-03-13 12:59:42 -06:00
Kris Johnson
400a7c54bc Shared Power: Ban Sturdy 2026-03-13 12:57:59 -06:00
Kris Johnson
834cca8b8e Pokebilities AAA: Update bans 2026-03-13 12:57:30 -06:00
Kris Johnson
4a736e5af1 Pokebilities: Update Neutralizing Gas to modern code 2026-03-13 12:54:33 -06:00
Leonard Craft III
03fc6de00e VGC: Update Regulation I ladders
https://x.com/playpokemon/status/2032502235205366020
2026-03-13 12:44:38 -05:00
Kris Johnson
c6504627ec
Appease linter
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2026-03-09 12:28:27 -06:00
André Bastos Dias
e5c7fe52ed
Orre Colosseum: Allow Deoxys formes (#11811) 2026-03-09 12:21:04 -06:00
Kris Johnson
8d87bb5a9c Fix typo 2026-03-09 12:03:23 -06:00
Kris Johnson
cc68e3e967 Linked: Fix modified-priority moves in a link 2026-03-09 12:00:37 -06:00
Marty-D
b809f86f09
Add new avatars
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2026-03-08 19:52:29 -04:00
André Bastos Dias
7af1d0e48f
Simplify Gen 3 Colosseum implementation (#11799)
* Simplify Gen 3 Colosseum implementation

* Remove formats-data

* Re-add
2026-03-08 12:46:22 -06:00
André Bastos Dias
3f071d4b8a
Add and use the Standard AG ruleset in previous generations (#11796)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Add and use the Standard AG ruleset in previous generations

* Fix gen1 and gen1stadium

* Fix Gen 1 again
2026-03-08 12:42:16 -06:00
André Bastos Dias
8539330f7e
National Dex: Re-ban Zamazenta after suspect test (#11795) 2026-03-08 12:41:35 -06:00
livid washed
802c1c1d99
Add March 2026 Randomized Format Spotlight (#11792)
* Add March 2026 Randomized Format Spotlight

* Make message clearer ( I think)

* lint

* Move to gen9/teams.ts

* Move to gen9/teams.ts pt 2

* done

* lint

* Prevent mons from being harmed by Godly Gift stat passing
2026-03-08 12:41:18 -06:00
livid washed
d57d100065
Hotfix Sitrus Iron Bundle in gen 9 randdubs (#11801) 2026-03-08 12:40:26 -06:00
Caznovia
e78411f6e7
[Gen 4] VGC 2009: Fix future event legality (#11805) 2026-03-08 12:06:55 -06:00
Slayer95
55f9e85172
Linked: Fix inconsistent implementations of twoturnmove, lockedmove (#11804)
* Linked: Fix inconsistent implementations of twoturnmove, lockedmove

* Linked: Sturdier implementation for Torment
2026-03-08 12:06:19 -06:00
VannAccessible
b36a3ea036
Linked: Ban Chlorophyll and restrict Sunny Day, ETerrain (#11806)
* Linked: Ban Chlorophyll and restrict Sunny Day, ETerrain to formats.ts

https://www.smogon.com/forums/threads/linked-omotm.3776838/page-4#post-10897129

* Update formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2026-03-08 11:39:32 -06:00
Karthik99999
cb47056b1b Fix Skill Swap messages
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2026-03-07 02:35:15 -05:00
Marty-D
59709dba6c
Fix item numbers
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2026-03-05 18:41:57 -05:00
Kris Johnson
04a026782d Linked: Fix priority on moves in the first moveslots while choice-locked
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2026-03-03 14:48:32 -07:00
Kris Johnson
4415c0ffbe Pokebilities AAA: Ban Dragapult 2026-03-03 14:34:32 -07:00
André Bastos Dias
f494d48434
Fix injective field position indexing (#11789) 2026-03-03 14:32:45 -07:00
shrianshChari
cf8cbd8f5d
DPP UU: Ban Sleep moves (#11794)
https://www.smogon.com/forums/threads/sleep-in-dpp-uu.3777509/post-10893690
2026-03-03 14:32:06 -07:00
InkyDarkBird
dd60398eac
SV Linked: Update bans (#11793)
* SV Linked: Update bans

* Update formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2026-03-03 14:31:40 -07:00
MathyFurret
50ad403c5c Help tickets: Escape HTML in lock reason 2026-03-03 11:51:46 -06:00
Slayer95
7bd04f470c
Linked: Remove m.lastMoveAbsolute in favor of lastMove (#11791)
* Fix Linked last move checks

At some point between af6affb and 045fe456, Linked's concept of
last absolute move changed from using the 2nd move in a link to
using the 1st move, likely in an attempt to preserve the 1st move
information that used to be stored for debugging purposes.

However, the redefinition has impacted the mechanics of Sketch, and
other moves for a long time.

This commit restores the original mechanics, and gets rid of the
last absolute move concept, in favor of the orthodox pokemon.lastMove.
In consequence, all modded data entries that now match gen9 are
also deleted.

* Linked: Fix Grassy Glide priority calculation
2026-03-03 09:50:30 -07:00
Kris Johnson
59529d79e0 FIx lint
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2026-03-02 22:40:11 -07:00
Kris Johnson
5f698aaf74 Linked: Update runAction for missing action choices 2026-03-02 22:38:21 -07:00
Kris Johnson
4c8c7cbdef FIx lint 2026-03-02 21:15:53 -07:00
Kris Johnson
6545c74486 Linked: Fix bugs with Encore, Stalwart, Propeller Tail, and Snipe Shot 2026-03-02 21:14:50 -07:00
Kris Johnson
bf612bf9ee Fix lint 2026-03-02 20:01:49 -07:00
Kris Johnson
e4801e992a Linked: Fix priority of linked moves (again) 2026-03-02 19:56:45 -07:00
Kris Johnson
65e046529c 4v4 Doubles UU: Add Best of checkbox for challenges 2026-03-02 19:55:47 -07:00
Kris Johnson
8ce95e4a2c Linked: Fix crash 2026-03-02 19:53:51 -07:00
André Bastos Dias
c9f530f412
Legends Z-A OU: March tier shifts (#11788)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2026-03-01 14:26:44 -07:00
Kris Johnson
e8bd7a5905 Linked and PokeAAA: Update bans 2026-03-01 14:22:08 -07:00
Kris Johnson
746d3ddf62 PokeAAA: Update bans 2026-03-01 10:52:06 -07:00
Kris Johnson
3a3c6739f2 Implement March 2026 tier shifts 2026-03-01 10:28:13 -07:00
Kris Johnson
c8ed448422 BH: Update bans 2026-03-01 10:27:21 -07:00
Kris Johnson
16675b07bc Make 4v4 Doubles UU actually doubles 2026-03-01 10:26:15 -07:00
Kris Johnson
eaff3cf2a8 Reimplement ORAS Pure Hackmons ladder
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2026-03-01 03:40:36 -07:00
Yoshiblaze
376da145ff
Add [Gen 6] Megas Revisited Random Battle (#11778)
* March PMOTM Part 1

* March PMOTM Part 2

* March PMOTM Part 3

* March PMOTM Part 4

* March PMOTM Part 5

* Update data/mods/gen6megasrevisited/abilities.ts

* Update data/mods/gen6megasrevisited/scripts.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2026-03-01 03:37:04 -07:00
livid washed
1d8968acdf
Randomized formats update (#11782)
* Randomized set updates

* fix some things

* add resttalk primarina gen 7

* Create Pokemon incompability system

* Simplify code

* tghost oinkolognes

* Give sash back to doubles smeargle

* Give sash back to doubles smeargle
2026-03-01 03:20:05 -07:00
demir
261dcddca6
35 Pokes: Update list of allowed Pokemon for March 2026 (#11784) 2026-03-01 03:19:50 -07:00
Kris Johnson
be25932aff
Update rotational ladders (#11785)
* Update Kalos starter Mega abilities

* Update rotational ladders
2026-03-01 03:19:22 -07:00
Mia
8a0685b03f Ladder tours: Cap deadline length 2026-03-01 01:11:09 -06:00
Kris Johnson
76eb3eb3bf
Update Kalos starter Mega abilities (#11781)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2026-02-27 19:50:24 -07:00
Niadev
c30261be77
Ban Okidogi from National Dex UU (#11779) 2026-02-27 18:21:20 -07:00
Sunny
3ad40b4a5c
Gen 1 LC: Add Accuracy and Sleep Moves Clause (#11776)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
Co-authored-by: kn-Kris <165436526+kn-Kris@users.noreply.github.com>
2026-02-22 19:27:12 -07:00
Kris Johnson
95aad7df02 Gen 6 Mix and Mega: Ban Gengarite and restrict Entei
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2026-02-21 17:50:31 -07:00
André Bastos Dias
1091524b94
Gen 1: Fix underflow glitch applied to mimicked duplicate moves (#11746)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
* Fix underflow glitch applied to mimicked duplicate moves

* Remove flags

* Remove console.log
2026-02-17 18:36:37 -07:00
André Bastos Dias
f4889cac74
Implement Zacian and Zamazenta transformations as species conditions (#11748)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Implement Zacian and Zamazenta transformations as species conditions

* Remove custom transformation from gen8linked
2026-02-17 18:34:52 -07:00
dot-Comfey
42f591a330
Remove hardcoding of formes inheriting learnsets (#11750)
* Remove hardcoding of formes inheriting learnsets

* Fix learnset inheritance

* Update learnsets.ts
2026-02-17 18:33:57 -07:00
André Bastos Dias
a66fecae31
Add Knock Off + Poison Touch + Lum Berry test (#11769) 2026-02-17 18:33:31 -07:00
Kris Johnson
9cfe6c1333
NatDex: Move Zamazenta-C to OU for suspect 2026-02-17 17:11:39 -07:00
VannAccessible
686819e5e1
Flipped: Ban Annihilape (#11765)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
* Add Annihilape to the banlist in formats.ts

For Flipped. 

Vote: https://www.smogon.com/forums/threads/flipped-other-metagame-of-the-month.3711301/page-3#post-10871384

Ty!

* Update formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2026-02-14 20:10:47 -07:00
demir
6b5cf272d6
Sleep Moves Clause (#11766) 2026-02-14 20:10:18 -07:00
iforgetwhyimhere
a7f286ee0d
Add "Same Letter Clause" (#11767)
* Add "Same Letter Rule"

* cleanup

* indentation

* ^

Co-authored-by: Slayer95 <ivojulca@hotmail.com>

* change slc desc

* clarify rejection message

---------

Co-authored-by: Slayer95 <ivojulca@hotmail.com>
2026-02-14 20:09:56 -07:00
André Bastos Dias
c448db8692
Deduct PP from Gen 3 and Gen 4 Pursuit (#11753)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2026-02-13 09:57:41 -07:00
TurboRx
7a55285dd1
Fix Stomping Tantrum incorrectly doubling after canceled two-turn moves (#11760)
* fix stomping tantrum not doubling when fly is canceled by smack down

* Update sim/battle-actions.ts

Co-authored-by: André Bastos Dias <80102738+andrebastosdias@users.noreply.github.com>

---------

Co-authored-by: TurboRx <TurboRx@users.noreply.github.com>
Co-authored-by: André Bastos Dias <80102738+andrebastosdias@users.noreply.github.com>
2026-02-13 09:57:20 -07:00
André Bastos Dias
ae43883ed1
Legends Z-A OU: January tier shifts (#11756) 2026-02-13 09:54:22 -07:00
Runo
2ad682ce28
NatDex RU: Ban Sharpedo-Mega (#11763)
https://www.smogon.com/forums/threads/national-dex-ru-metagame-discussion.3713801/post-10871103
2026-02-13 09:53:48 -07:00
iforgetwhyimhere
84df91ed10
Six By Six: Remove Gunk Rock (#11761) 2026-02-13 09:53:37 -07:00
VannAccessible
32f8ffecaa
Flipped: Fix ruleset (#11758)
Unban Zamazenta and ban Sleep Moves in Flipped. Council vote here:

https://www.smogon.com/forums/threads/flipped-other-metagame-of-the-month.3711301/page-3#post-10868527
2026-02-13 09:53:14 -07:00
iforgetwhyimhere
c55e84f7cb
Add randffats command help (#11759)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2026-02-11 17:22:56 -05:00
André Bastos Dias
737a8095ac
Add Full Arceus Clause (#11725)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
* Enable Arceus EV Limit Mod

* English

* Add comment with implementation location

* Add Full Arceus Clause

* Add event for clause

* Move comment

* Lint

* Simplify assignments

* Revert Melmetal changes

* Revert "Revert Melmetal changes"

This reverts commit 8c4a04e67c.

* Reapply "Revert Melmetal changes"

This reverts commit 7553972011.

* Add explanation comment

* Remove test

* Comment
2026-02-08 10:24:39 -07:00
André Bastos Dias
b9caaaa927
LC UU: Ban Light Clay (#11745)
https://www.smogon.com/forums/threads/sv-lc-uu-metagame-resource-and-discussion-thread.3711750/post-10863288
2026-02-08 10:23:34 -07:00
InkyDarkBird
8f8c96915d
SV Flipped: Update bans (#11751) 2026-02-08 10:23:17 -07:00
Kris Johnson
f75c7e4ef8 GSC ZU: Fix bans 2026-02-08 10:22:33 -07:00
Karthik Bandagonda
df367633bc
Refactor Skill Swap to its own function (#11563)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2026-02-06 08:47:29 -05:00
André Bastos Dias
af4f85a33c
ADV UU: Drop Fearow, Hypno and Manectric (#11740)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
https://www.smogon.com/forums/threads/adv-rarelyused.3731043/post-10860568
2026-02-06 01:16:33 -07:00
HiZo
2ca5d0f3ca
Mix and Mega formats: Fix banlists (#11743)
* LC Mix and Mega: Bans Sticky Web

* @clastia smells
2026-02-06 01:16:16 -07:00
Aurastic
0fd2b67850
Automodchat: Prevent idle or busy staff from being treated as online (#11727)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2026-02-04 00:26:23 -06:00
André Bastos Dias
08562488b0
Refactor Illusion switch out check (#11742)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2026-02-03 16:09:04 -07:00
André Bastos Dias
a6c45ecb45
Remove Slow Start volatile tag on suppression (#11571)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2026-02-02 17:47:14 -07:00
Lucas
e847960a1b
Add different dexes to /reevo (#11731)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
Co-authored-by: Meijer,L. (Lucas) <l.meijer6@students.uu.nl>
2026-02-01 16:32:18 -07:00
André Bastos Dias
1cbbf9bf65
Gen 3 Pursuit only activates on the selected target (#11611)
* Gen 3 Pursuit only activates on the chosen target

* Change

* Fix following Pursuits

* Resolve further conflicts

* Update gen 4

* Don't need to check for allies
2026-02-01 16:31:28 -07:00
InkyDarkBird
d769756639
SV Flipped: Fix bans (#11739) 2026-02-01 14:12:56 -07:00
ACakeWearingAHat
ccdc32dd7c
Randomized format set updates (#11728)
* Randomized format set updates

* revert some changes from last month

* lint

* further updates

* Gen 1 changes

* Re-split whimsicott in gen 9 doubles

* Merge arceus-ghost sets (cosmetic change)

* Don't duplicate subseed on whimsicott

* Replace Fake Tears with twave on screens meowstic and merge roles

* doubles screens grimmsnarl: +twave

* Update SD silvally ice and psychic in gen 8

---------

Co-authored-by: Kelvin Liu <115855253+livid-washed@users.noreply.github.com>
2026-02-01 13:00:57 -07:00
Kris Johnson
95416b29dc
Move Pet Mod spotlight ladders 2026-02-01 12:50:14 -07:00
Yoshiblaze
fcd41c87a1
Add New Pet Mod of the Season, Six by Six Random Battle, and Remove Previous PMOTM (#11737)
* Delete data/random-battles/scootopiav2 directory

* 6x6 Part 1

* Delete data/mods/scootopiav2 directory

* 6x6 Pt 2

* 6x6 Pt 3
2026-02-01 12:49:08 -07:00
André Bastos Dias
d3f6885435
Fix Pursuit interaction with Choice items in Gens 3 and 4 (#11735)
* Reapply "Gens 3-4: Truant, Sleep and Freeze should block Pursuit activation (#…" (#11733)

This reverts commit 2180a5c998.

* Fix Pursuit interaction with Choice items in Gens 3 and 4

* Fix
2026-02-01 12:26:56 -07:00
surfnWOB
5f1667c2f4
ADV 200 Doubles: Ban Wobbuffet and Wynaut (#11732) 2026-02-01 12:26:39 -07:00
HiZo
d6cae36487
Fortemons: Allow validator to work with unlearnable moves when prompted (#11736)
* Fortemons: allow validator to work with unlearnable moves when prompted

* Apply suggestion from @KrisXV

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2026-02-01 12:15:36 -07:00
demir
aa592f2742
35 Pokes: Update list of allowed Pokemon for February 2026 (#11738) 2026-02-01 12:06:51 -07:00
Kris Johnson
4cb7ecf998 Add February 2026 spotlight ladders 2026-02-01 11:44:53 -07:00
Kris Johnson
2180a5c998
Revert "Gens 3-4: Truant, Sleep and Freeze should block Pursuit activation (#…" (#11733)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
This reverts commit faa549e02f.
2026-01-30 11:38:29 -07:00
André Bastos Dias
12bb66810e
GSC PU: Ban Baton Pass (#11722)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2026-01-26 12:23:48 -07:00
missshowdown
42ceec9a6b
GSC: Move Ariados and Charmeleon to ZUBL (#11721)
https://www.smogon.com/forums/threads/zu-old-gens-hub-ariados-and-charmeleon-banned-from-gsc-zu-405.3646944/post-10829741
The two were banned from GSC ZU on January 10th, 2026
2026-01-26 12:23:31 -07:00
André Bastos Dias
117cb69c89
Expand Arceus EV Limit to all level 100 events (#11724) 2026-01-26 09:24:43 -06:00
Kris Johnson
fc70a34fd3 ORAS Mix and Mega: Restrict Deoxys-Speed 2026-01-25 14:26:32 -07:00
André Bastos Dias
faa549e02f
Gens 3-4: Truant, Sleep and Freeze should block Pursuit activation (#11680) 2026-01-25 12:26:02 -05:00
TurboRx
550a9ad2a9
Fix visualize function Set case callback arguments (#11525) 2026-01-25 09:11:14 -05:00
TurboRx
2b02955fdc
Make /rank command output horizontally scrollable (#11586) 2026-01-25 08:33:29 -05:00
Slayer95
b0dc94f196
Further update tests after startup refactor (#11521)
- Adds config.lazysockets to prevent listening to the network
- Fixes modlog tests
2026-01-25 07:58:21 -05:00
Kris Johnson
712867050c 1v1 Factory: Fix Carbink's level 2026-01-24 16:25:18 -07:00
Kris Johnson
b99ff0165a 1v1 Factory: Fix Haxorus's moves 2026-01-23 23:57:12 -07:00
Kris Johnson
cd653397db Fix typo 2026-01-23 23:47:30 -07:00
Kris Johnson
feed5acb9c Fix build 2026-01-23 23:28:25 -07:00
Kris Johnson
7a560fae3f 1v1 Factory: Update set generation logic 2026-01-23 23:14:12 -07:00
Kris Johnson
973e1e0b96 Gen 6/7 Mix and Mega: Fix validation 2026-01-23 14:43:25 -07:00
HiZo
daddd5793a
Super Staff Bros: Fix Flygonite (#11718) 2026-01-22 12:55:51 -07:00
André Bastos Dias
dd3d52b838
GSC: NU-PU tier shifts (#11717)
* GSC: PU drops

* Move Hitmontop from PU to NU
2026-01-20 14:55:40 -07:00
HiZo
ea160e1059
LC Mix and Mega: Ban Absolite Z (#11712)
* LC Mix and Mega: Ban Absolite Z

https://www.smogon.com/forums/threads/sv-lc-mix-and-mega.3749640/#post-10831401

* Update config/formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2026-01-19 01:30:59 -07:00
FeluciaPS
3619ad8eef
1v1: Ban Custap Berry (#11710)
https://www.smogon.com/forums/threads/one-more-time-custap-berry-suspect.3775688/post-10836343
2026-01-17 12:47:54 -07:00
LumarisX
cc37f4c724
Add Mega Darkrai as a Dark Void user (#11708)
* add mega darkrai as a dark void user

* remove auto formatting

* Update data/moves.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2026-01-15 14:40:15 -07:00
shrianshChari
56faffd46c
[Gen 3] ADV 200: Give Wish to Pokemon that can breed with Pikachu (#11709)
* ADV 200: Add Wish to the movesets of Pokemon that can breed with Pikachu

* These files were not supposed to be here
2026-01-15 00:34:47 -07:00
HiZo
3bd1a1e329
Bio Mech Mons: Fix fling (#11707) 2026-01-14 20:17:58 -07:00
HiZo
0e435f9887
Partners in Crime: Ban Oricorio over Dancer (#11703)
* Partners in Crime: Ban Oricorio over Dancer

* Update config/formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2026-01-14 19:38:31 -07:00
Emikatana
7e557b7cf5
Add new ChatBats mons + bug fixes (#11705)
* adding new mons

* adding new mons

* adding new mons

* adding new mons

* adding focus band changes

* add moves

* +new mons

* +new mons

* +new mons

* +new mons

* +sinister arrows

* +new abilities

* fix

* fix

* fix

* fixing sinister arrows

* fixing oceanic blessing

* fixing sinister arrows clarity

* oops

* fixing oceanic blessing

* fixing sinister arrows

* oop

* fixing biogenesis

* fixing oceanic blessing message

* fixing some stuff

* fixing sinister arrows

* oops

* updating test mons

* removing test code

* kyogre level down

* lint issues

* lint issues

* lint fix (why)

* lint badly

* adding new ChatBats mons

* adding new mons

* adding new mons

* new mons

* raticite + fixing focus band

* adding jello body

* fixing electric terrain + Volbeat and adding Jello Body

* adding last breakfast

* adding nibble nibble

* fix

* fix

* fixing electric terrain

* fixing crowverload

* fixing focus band hopefully

* fix focus band (final)

* testing breakfast

* fixing breakfast

* fixes

* hopefully fixing breakfast

* oops

* removing debug text and adding descriptions

* description

* balance changes + fixing raticate ability

* removing test code

* lint fix

* lint

* lint fixes

* lint fix for the lint fix

* lint fix

* fixing team generation failing sometimes
2026-01-14 19:38:03 -07:00
Kris Johnson
8ac23313bb Camove Chaos: Ban Roserade 2026-01-14 19:31:32 -07:00
André Bastos Dias
5dfa67e248
Remove Gen 3 check in Gen 4 code (#11706) 2026-01-14 19:12:54 -06:00
André Bastos Dias
ea822f8863
Auctions: Show managers of top bidder in bid info box (#11702) 2026-01-13 11:02:16 -07:00
André Bastos Dias
fe37e47d54
Update OU by technicality (#11698)
* SS: Move Victini to (OU)

* SM: Move Tangrowth to (OU)

* ORAS: Move Jirachi to (OU)
2026-01-12 11:35:03 -07:00
TurboRx
b5514e03af
Update LICENSE Year (#11689) 2026-01-11 13:57:14 -08:00
Kris Johnson
a86abb2b6b Fix test 2026-01-10 22:28:55 -07:00
Kris Johnson
f5011b81ec EBC: Auto tie should kick in after turn 1000 ends 2026-01-10 20:16:28 -07:00
Guangcong Luo
9fd696977c Fix crash in formatText 2026-01-10 14:36:51 -08:00
Guangcong Luo
f2883557ca Protect against infinite loop 2026-01-10 21:31:12 +00:00
Kris Johnson
6bcb0f7f32 Fix typo 2026-01-09 19:04:38 -07:00
Kris Johnson
275fc63851 BMM: Fix validation 2026-01-09 18:58:45 -07:00
Kris Johnson
d547152057 Update aliases 2026-01-09 17:34:36 -07:00
Mia
28fd76a151 Fix checks 2026-01-09 16:00:06 -06:00
HiZo
2c13c40578
Biomechmons: Properly make items consumable if not in the item slot (#11697) 2026-01-09 15:56:32 -06:00
Kris Johnson
dd421f7466 Add old gens of Mix and Mega for MnMPL 2026-01-08 21:43:25 -07:00
André Bastos Dias
684150d9d7
Implement Mega Stones as {key: value} pairs (#11684)
* Implement Mega Stones as pairs {key: value}

* Fix Mega Evolution check

* Add constructor guards to Dex getters

* Update config/formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2026-01-08 14:59:22 -07:00
HiZo
ee77cf98ae
Bio Mech Mons: Bugfixes (#11692)
* fix useItem and eatItem

* Fix banned move smuggling more

* o v e r h a u l

* lint

* lint

* this does not handle certain edgecases like Keldeo-Res

* Fix Keldeo-Resolute validation

* Update formats.ts

* woopsie

* oop

* e

* Update scripts.ts

* Update scripts.ts

* oh yea refactor this too

* Update moves.ts

* fix issue with PP not being deducted

* simplify metronome check

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2026-01-08 14:35:48 -07:00
Caznovia
020da8412f
Add Smeargle's Colosseum event learnset (#11673) 2026-01-08 14:29:26 -07:00
Aurastic
35e871e1d1
Thing of the day: Add destroy handler (#11694) 2026-01-08 14:21:17 -07:00
André Bastos Dias
6d9a1cd20f
Ubers UU: Drop Regieleki and ban Giratina (#11678)
https://www.smogon.com/forums/threads/sv-ubers-uu-metagame-discussion-giratina-ban-post-739.3731761/post-10818790
https://www.smogon.com/forums/threads/sv-ubers-uu-metagame-discussion-giratina-ban-post-739.3731761/post-10820664
2026-01-08 14:20:36 -07:00
André Bastos Dias
537afeea76
DPP: Sleep Moves Clause (#11687) 2026-01-08 12:49:48 -06:00
André Bastos Dias
7a3f4dbbe2
Update Official Formats to Regulation I (#11686) 2026-01-05 20:40:27 -06:00
Kris Johnson
c671f43d50 Add a /1v1factory command 2026-01-05 16:24:32 -07:00
Kris Johnson
acdbd55ee5 Bio Mech Mons: Fix duped item exploit 2026-01-05 16:11:51 -07:00
André Bastos Dias
1a18b3dd55
Make Battle#debug more flexible (#11685) 2026-01-05 11:03:25 -06:00
HiZo
f5483a18d0
BioMechMons: Fix bug with aliases (#11679) 2026-01-03 18:12:53 -05:00
InkyDarkBird
1b3275a22f
Bio Mech Mons: Fix Deoxys ban (#11675) 2026-01-02 16:16:58 -07:00
demir
de0358b763
35 Pokes: Add January 26 Pokemon (#11670) 2026-01-02 09:44:11 -07:00
André Bastos Dias
c735c99724
Legends Z-A: Add obtainable Pokémon (#11672)
* Legends Z-A: Add obtainable Pokémon

I don't feel like updating each Mega as the seasons go by.

* Fix data test
2026-01-02 09:43:26 -07:00
Runo
cf82bac342
NatDex: Fix Salamence and Gardevoir-Mega's Tiers (#11671)
Should be marked RUBL but seems to be a typo
2026-01-02 09:42:40 -07:00
livid washed
6304bec9dc
Random Battles hotfix: Fix Competitive Boltund (#11669) 2026-01-02 09:40:25 -07:00
HiZo
cb910c6973
Bio Mech Mons: Fix bugs (#11668)
* Bio Mech Mons

Unban Ability Shield

* Fix bug with air balloon
2026-01-02 09:40:01 -07:00
Yoshiblaze
7fabf3ab4b
Add New Pet Mod of the Month, Scootopia Random Battle, and Remove Previous PMOTM (#11651)
* Scootopia: Initial Commit

* Scootopia: Fix errors

* Scootopia: Fix most new errors

* one more

* Update and fix

* Avoid double bans

* more duplicate bans

* fix name credit

* Scootopia: Add Sets and proper Generation of Super Types

* Fix new errors

* fix error perchance

* perchance.

* forgot to re-fix these

* Update data/mods/scootopiav2/rulesets.ts

* Update data/mods/scootopiav2/rulesets.ts

---------

Co-authored-by: Meijer,L. (Lucas) <l.meijer6@students.uu.nl>
Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2026-01-01 19:30:50 -07:00
ACakeWearingAHat
190940fc58
Random Battles hotfix: prevent Weakness Policy on Emboar, Arbok, Seviper (#11666)
wow we're actually using counter.get('physicalsetup') for the first time!
2026-01-01 19:08:32 -07:00
livid washed
d71eae4fc3
Remove banner advertising RBTT player signups (#11663) 2026-01-01 19:08:17 -07:00
Zachary Perlmutter
cec4772767
National Dex Ubers UU: Implement tier shifts (#11664)
Deoxys-Speed and Melmetal drop, Alomomola and Kingambit rise
https://www.smogon.com/forums/threads/national-dex-ubers-uu-october-shifts-108-bans-109.3742166/page-5#-january-2026-shifts
2026-01-01 19:07:27 -07:00
Atlas
51eae1b871
Bio Mech Mons: Fix desc (#11667) 2026-01-01 19:06:40 -07:00
HiZo
df32a5f5bb
Bio Mech Mons: Fix validator (#11665)
* fix changing abils while transformed

* fix infinity moveslot pokemon

* fix validation

* beef up banned element smuggling

* right

* fix dupes

* lint

* Lint

* fix trace and air balloon

* AAAAAAAAAAAAAAAAAAAAA

* oops

* Update moves.ts

* aaaa
2026-01-01 18:20:47 -07:00
Kris Johnson
a77084b6d5
Implement January 2026 tier shifts (#11662) 2026-01-01 13:37:08 -07:00
Kris Johnson
02828be7b6
Fix typo 2026-01-01 11:31:47 -07:00
Clas
f2f5bb9786
Camove Chaos: Fix Deoxys/Landorus Legality (#11660)
* Camove Chaos: Fix Deoxys/Landorus Legality

Fixes legalities regarding Lando-T and Deoxys-D/S

* Apply suggestions from code review

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2026-01-01 11:09:32 -07:00
Kris Johnson
0cf3933f8a Z-A OU: Actually implement the nerfs 2026-01-01 10:29:24 -07:00
Kris Johnson
4a6196f310 Z-A OU: Implement tier shifts and bans/buffs/nerfs 2026-01-01 10:22:54 -07:00
HiZo
b7d8dee113
Add Bio Mech Mons (#11656)
* reattempt

* Create scripts.ts

* Update scripts.ts

* boiler plate idk

* more work

* now we doin it

* more stuff to push

* yea sure

* tomorrow me's problem

* refactor setAbility

* fix line length

* Fix this edgecase

* ok general bs done woooo

* lint

* Import code dhelmise worked on

* AAAA I FORGOT ABOUT THIS

* Add useItem and eatItem

* Ensure items dont get procced again

* add more stuff to mod later

* fix issue from merging conflicts

* lint

* allow ability-less pokemon

* fix crash

* fix crash with knock off

* refactor for knock off crash

* fix issue with required items in validation

* account for this too

* add choiceLock code from SiC

* add transformInto

* remove old comments

* start work on edgecases

mostly just the stuff from SP/SiC

* a

* dhelmise pls dont steal my kneecaps

* bug fixes pt. 1

* more bugfix

* AAAAAAAAAAAAAAAAA

* one day ill be done

* fix gastro acid

* i hate it here

* >_>

* a

* Update config/formats.ts

* Update data/mods/biomechmons/items.ts

* Update data/mods/biomechmons/items.ts

* Update data/mods/biomechmons/scripts.ts

* bugfix 1

* fix move dupe bug

* move this to the omotm section, add banlist

* woops

* Update formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2026-01-01 10:05:51 -07:00
Kris Johnson
b7e25e9a09 1v1 Factory: Fix natures 2026-01-01 10:04:07 -07:00
Atlas
5062101622
Fix 1v1 factory Volcanion typo (#11661)
Co-authored-by: KingNeodude <109841009+KingNeodude@users.noreply.github.com>
2026-01-01 09:11:15 -07:00
Kris Johnson
48727c319d Fix typo! 2026-01-01 02:52:08 -07:00
adrivrie
ad9d7add4b
Random Battles: December 2025 balance patch (#11653)
Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2026-01-01 02:48:23 -07:00
Kris Johnson
61a7a3a675 Add January 2026 rotational formats 2026-01-01 02:47:40 -07:00
Caznovia
6a2b1ad82e
Update /intro command links (#11654) 2026-01-01 02:29:12 -07:00
Kris Johnson
305fff4049 Fix failed tests 2026-01-01 02:28:28 -07:00
livid washed
63bdcb392b
Add January 2026 Randomized Format Spotlight (#11659)
* Add January 2026 Randomzied Format Spotlight

* didn't mean to remove that line

* lint
2026-01-01 02:25:37 -07:00
Kris Johnson
cacd9a80bb Fix block scoped variable duping 2026-01-01 02:24:58 -07:00
surfnWOB
ee8568588a
Gen 3: Add ADV 200 Doubles format (#11657) 2026-01-01 02:22:09 -07:00
André Bastos Dias
b636814279
RBY: Tier Shifts (#11652)
https://www.smogon.com/forums/threads/rby-uu-hub.3647713/post-10816029
https://www.smogon.com/forums/threads/rby-pu-hub.3700527/post-10816027
2026-01-01 02:21:48 -07:00
Kris Johnson
af4110abee Fix build again 2026-01-01 02:19:26 -07:00
livid washed
021acd4c4c
Add banners advertising RBTT player signups to Random Battles formats (#11658) 2026-01-01 02:17:09 -07:00
Runo
156ef64700
ZA OU: Fix Greninja-Bond Movepool (#11649) 2026-01-01 02:16:38 -07:00
ACakeWearingAHat
f10c7af9e5
Randomized format set udpates (#11655)
* Randomized format set updates

* updoot

* more thing

* role names

* lint

* Change old gens Golduck from Bulky Attacker to Bulky Setup with subcm as an option

* Remove unnecessary PT

* Level 73 Pikachu in gen 2

* 75% tbolt for Persian in gen 1

* ionnss yelled at me

* Add aura sphere to mewtwo in gen 8

* Make wigglytuff always Competitive in gen 8

* council veto of lum klawf removal

* toxic dreig

* life orb trailblaze mamoswine

* prevent choice trailblaze lmao

* Force Ice Shard on Gen 5 Mamoswine and merge into a single set

---------

Co-authored-by: Kelvin Liu <liuc.kelvin9901@hotmail.com>
Co-authored-by: Kelvin Liu <115855253+livid-washed@users.noreply.github.com>
2026-01-01 02:16:12 -07:00
Kris Johnson
07469afc59 Fix build 2026-01-01 02:11:33 -07:00
Kris Johnson
e54906fe2c Add Likeshop ladders 2026-01-01 00:46:06 -07:00
Kris Johnson
40efc83fa0 ADV LC: Ban Diglett 2025-12-28 11:51:52 -07:00
Caznovia
0abc64a1a6
Gen 3: Remove Tickle from King's Rock list (#11479) 2025-12-28 10:20:33 -06:00
Kris Johnson
16c2c7e90b
Legends Z-A OU: Ban Genesect
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-12-21 11:34:08 -07:00
Aurastic
7d2de8779e
Thing of the Day: Add auto-start support (#11633)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-12-19 22:39:55 -06:00
InkyDarkBird
03f76488f4
Mix and Mega and Convergence: Update bans (#11637)
* Mix and Mega and Convergence: Update bans

fix

fix

SV Convergence: Update bans

SV Convergence: Update bans

* Mix and Mega Bans
2025-12-19 21:21:23 -07:00
Runo
d99280a578
Z-A OU: Ban Light Clay + Implement Missing Items (#11634)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Z-A OU: Add Soul Dew

* Update scripts.ts

* Update formats.ts

* Update config/formats.ts

* Update data/mods/gen9legendsou/scripts.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-12-19 13:41:45 -07:00
Kris Johnson
29627552e8 Fix build
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-12-17 15:16:01 -07:00
Kris Johnson
66a6eec955 Z-A OU: Update bans 2025-12-17 15:15:14 -07:00
Kris Johnson
5b88ce0556 Z-A OU: Update Zeraora-Mega ability and item legality 2025-12-17 12:04:06 -07:00
Kris Johnson
43cedf4025 Mix and Mega: Fix non-Mega Stone items
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-12-16 07:46:33 -07:00
HiZo
2ed92845c9
Fix bugs with Zygardite (#11628)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Fix bugs with Zygardite

* Update data/mods/mixandmega/scripts.ts

* Update data/items.ts

* fix error

* Apply suggestions from code review

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-12-15 23:41:04 -07:00
Kris Johnson
2c58b396cb Mix and Mega: Release Z-A stones
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-12-15 19:53:21 -07:00
Mia
5a02f59339 Usersearch: Exempt guests from term matches on overview page
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-12-14 23:21:19 -06:00
André Bastos Dias
fa3b107c95
Metronome Battle: Ban Tatsugiri-Mega (#11623)
* Metronome Battle: Ban Tatsugiri-Mega

* Refactor

* Ban the Mega Stone

* Fix test
2025-12-14 21:12:41 -07:00
Kris Johnson
11458b1bd3 Fix build 2025-12-14 21:11:56 -07:00
Kris Johnson
0fc4e743bb Fix build 2025-12-14 12:28:07 -07:00
André Bastos Dias
9df62c450e
Fix Meowstic-M-Mega test (#11624)
9c6d0bf25d
2025-12-14 11:05:10 -07:00
Kris Johnson
9c6d0bf25d Fix Mega Meowstic-M's forme 2025-12-14 10:00:20 -07:00
Runo
3498499a7f
NatDex RU: Ban Slowbronite (#11616) 2025-12-14 09:56:38 -07:00
André Bastos Dias
8e999f3c51
National Dex UU: Ban Iron Moth (#11618)
https://www.smogon.com/forums/threads/sv-national-dex-uu-stage-8-3-moth-to-a-flame.3774328/#post-10801535
2025-12-14 09:56:24 -07:00
André Bastos Dias
f245f28c83
Ubers UU: Ban Arceus-Electric (#11621)
https://www.smogon.com/forums/threads/sv-ubers-uu-metagame-discussion-arceus-electric-ban-post-736.3731761/post-10802137
2025-12-14 09:56:10 -07:00
Kris Johnson
cd95a13a78 Legends Z-A: Update abilities and ban Magearna-Mega 2025-12-14 09:54:22 -07:00
Mia
39c43fc8b1 Artemis: Ignore ETIMEDOUT errors
Not on our end. Not much we can do.
2025-12-13 13:11:39 -06:00
Kris Johnson
27ecc9e7d1 Legends Z-A: Update legality 2025-12-12 12:48:24 -07:00
André Bastos Dias
ce3cff6168
Legends Z-A: Multiple fixes (#11617)
* Legends Z-A: multiple fixes

* Fix knocking Mega stones

* Revert Tatsugiri-Mega naming

* Revert "Revert Tatsugiri-Mega naming"

This reverts commit 49b97f1e06.

* Revert Tatsugiri-Mega renaming

* Renam Meowstic-Mega to Meowstic-M-Mega

* Apply suggestions from code review

* Remove type mismatch error for megaStone

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-12-12 12:39:15 -07:00
Pac n cheese
236833b92f
Update staff list command (#11585)
The current page led to nowhere so I updated it to point to https://www.smogon.com/forums/posts/10715136/ instead.
2025-12-12 09:29:08 -06:00
adrivrie
4990f0a65e
Random Battles: Prevent Magearna-Mega from showing up (#11615) 2025-12-12 09:28:18 -06:00
Kris Johnson
9df07a958d Z-A OU: Ban Shed Tail 2025-12-12 00:59:18 -07:00
InkyDarkBird
56a4b2a747
Voltturn Mayhem + Convergence Bans (#11605)
* SV Voltturn Mayhem: Update Bans

fix

SV Voltturn Mayhem: Update bans

* fix

* SV Convergence: Update bans

* Update config/formats.ts

* Update formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-12-12 00:18:19 -07:00
André Bastos Dias
e13942b721
Legends Z-A: Add learnsets (#11609)
* Legends Z-A: Release Mewtwo

* Fix tests

* Add event

* Fix BDSP and Legends Z-A event pokeballs

* Add DLC learnsets

* Fix previous events

* Inherit events

* Add Mega-Z

* Add final number of species

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-12-12 00:16:53 -07:00
Runo
be5057c9e8
NatDex RU: Ban Slowbro-Mega (#11612)
* Update formats.ts

* Update formats-data.ts
2025-12-12 00:10:06 -07:00
Emikatana
6f9b1e6213
ChatBats updates and fixes (#11610)
* adding new mons

* adding new mons

* adding new mons

* adding new mons

* adding focus band changes

* add moves

* +new mons

* +new mons

* +new mons

* +new mons

* +sinister arrows

* +new abilities

* fix

* fix

* fix

* fixing sinister arrows

* fixing oceanic blessing

* fixing sinister arrows clarity

* oops

* fixing oceanic blessing

* fixing sinister arrows

* oop

* fixing biogenesis

* fixing oceanic blessing message

* fixing some stuff

* fixing sinister arrows

* oops

* updating test mons

* removing test code

* kyogre level down

* lint issues

* lint issues

* lint fix (why)

* lint badly
2025-12-12 00:08:56 -07:00
Kris Johnson
30ff784f2c
Z-A: Add DLC Pokemon (#11613)
* Z-A: Add DLC Pokemon

* za ou learnsets

* zaou changes

* skip test 4 now

* dfadasas
2025-12-12 00:04:05 -07:00
shrianshChari
7828ec3220
RU: Ban Lilligant-Hisui (#11606)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
www.smogon.com/forums/threads/np-ru-stage-21-dancing-on-my-own-remix-hisuian-lilligant-suspect-test.3774205/post-10796202
2025-12-08 20:11:21 -07:00
Sergio Garcia
13aa6355af
Fix various typos (#11607) 2025-12-08 18:38:02 -06:00
InkyDarkBird
787fd585e6
SV Convergence: Update Bans (#11603)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-12-05 10:01:28 -07:00
Yoshiblaze
96904095bf
Monster Hunter: Updates and Fixes (#11604) 2025-12-05 10:01:07 -07:00
Kris Johnson
533de76f4e Revert 2v2 rename
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-12-03 23:19:24 -07:00
missshowdown
5b3f2a121e
Move Toxicroak to ZU (#11601)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
Toxicroak did not have enough usage to move from ZU to PU when it moved from ZU to NU in the October 2024 tier shifts. It should quickdrop back to ZU. 

https://www.smogon.com/forums/threads/usage-based-tier-update-for-october-2024-november-45-december-69.3752345/

This same situation has happened with Indeedee between UU and NU. It would be a similar situation if Torkoal rose from ZU to OU. It would not make sense for it to have to drop through UU, RU, NU, and PU to ZU again even if it remained in OU for a year if it did not see consistent usage in those tiers before it rose.
2025-12-02 18:49:42 -07:00
Kris Johnson
3b8813e3a2 Rename 2v2 Doubles 2025-12-02 18:49:28 -07:00
Kris Johnson
2f948d7a5d Legends Z-A: Update tiers 2025-12-02 18:48:35 -07:00
Spammernoob69
0faca2ef1d
Cresceidon Nerf (#11590)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Cresceidon Nerf

-Encore

https://www.smogon.com/forums/threads/np-sv-cap-stage-6-wave-of-mutilation-cresceidon-nerf.3772222/#post-10764751

* Cresceidon nerf for CAP Rands
2025-12-01 23:08:40 -07:00
Yoshiblaze
7112ed9564
Add December's Pet Mod of the Month, Monster Hunter Showdown Random Battle, and Remove the Previous PMOTM (#11597)
* spookymod Initial commit

npm not working locally for me anymore, it's 57 commits time

* Spookymod: Fix initial errors

* Spookymod: Fix more initial errors

* checking something

* Spookymod: checking something

* Spookymod: Fix const error

* Spookymod: Fix some errors

* Spookymod: fix small errors

* Spookymod: Fix a couple more errors

* Spookymod: More small errors

* Remove chatlines, fix generation

* Spookymod: Fully remove chat stuff

* Spookymod: errors

* trailing space

* remove random \

* Fix most errors

* Spookymod: Fix ID errors

* Spookymod: Fix Revive

* fix toId

* Monster Hunter: Initial Commit

* Monster Hunter: Fix errors

* Monster Hunter: Fix more errors

* oh there it is

* Monster Hunter: More errors

* Monster Hunter: Fix commas

* /*

* Monster Hunter: Some more errors

* one more

* Remove nonexistent ability

* Monster Hunter: Random Set Fix

* Movepool edit

* Set tweaks

* try fix abilities

* Large update from DH + Ability fixes

https://github.com/scoopapa/DH2/pull/1471

* Revert "Large update from DH + Ability fixes"

This reverts commit f5d10087b0.

* Re-delete spookymod

* Re-add the stuff that didn't break

---------

Co-authored-by: Meijer,L. (Lucas) <l.meijer6@students.uu.nl>
2025-12-01 23:08:28 -07:00
demir
df6ec6faa1
35 Pokes: Update list of allowed Pokemon for December 2025 (#11599)
* it's december!! :D

* Apply suggestions from code review

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-12-01 23:08:19 -07:00
André Bastos Dias
c6028d6458
Legends Z-A: Release Chesnaughtite (#11595)
* Legends Z-A: Release Chesnaughtite

* Fix test
2025-12-01 23:07:05 -07:00
Kris Johnson
b27e545e94 Add December 2025 rotational ladders 2025-12-01 23:06:26 -07:00
Kris Johnson
b2b885d68c LC UU: Unban Munchlax 2025-12-01 21:48:28 -07:00
Kris Johnson
3a5828895d Move Toxicroak to PU 2025-12-01 21:47:48 -07:00
shrianshChari
fba466c13d
BDSP: Move Absol to RUBL (#11596)
https://www.smogon.com/forums/threads/bdsp-ru-ru-tier-shifts-post-128.3695563/page-6#post-10789689
2025-12-01 18:24:53 -07:00
demir
7c154118e5
35 Pokes: Unban certain Z-Crystals (#11600) 2025-12-01 18:23:17 -07:00
Leonard Craft III
bccddf3975 Remove VGC Reg H formats
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-11-30 21:20:33 -06:00
André Bastos Dias
9fae1b8a01
National Dex Doubles: Ban Espathra (#11593)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
https://www.smogon.com/forums/threads/national-dex-doubles-ou-metagame-discussion-shadow-tag-banned.3720802/post-10788720
2025-11-28 09:42:12 -07:00
livid washed
08bcb39912
Random Battles: Don't lower Atk EVs/IVs with Force of the Fallen Mod (#11589)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
* Random Battles: Don't lower Atk EVs/IVs with Force of the Fallen Mod

* Lint
2025-11-25 20:35:33 -07:00
André Bastos Dias
526f4f17d5
UU: Ban Zarude (#11588)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
https://www.smogon.com/forums/threads/uu-suspect-process-round-16-brass-monkey.3773648/post-10787121
2025-11-24 18:39:03 -07:00
HoeenHero
aa1ff9fbe5 SV PU: Ban Frosmoth
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-11-24 09:10:51 -05:00
Mia
972f89fa28 Replays: Fix crash in uploading replays with un-rounded ratings
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-11-23 20:06:44 -06:00
Mia
e94ba6a848 Log PIDs for all subprocess crashes 2025-11-23 20:00:07 -06:00
Mia
f66eef5271 Fix typo 2025-11-23 19:44:44 -06:00
Mia
be4f2bd6ab Log Unix timestamp of crashes 2025-11-23 19:42:29 -06:00
Mia
8bae904193 SQL: Log process ID in errors for easier debugging 2025-11-23 19:39:22 -06:00
livid washed
1ee0986f67
Advertise Ladder Achievements Project for the Randomized Spotlight (#11577)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-11-18 17:36:22 -07:00
InkyDarkBird
5390fc1d20
SV Fortemons: Update bans (#11576)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-11-16 20:52:36 -07:00
Kris Johnson
5e542aae99 PLZA OU: Nerf Mega Floette's ability
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-11-16 09:01:29 -07:00
André Bastos Dias
6b2b9e18ba
Fix gen8legends pokedex file name (#11568) 2025-11-16 08:44:41 -07:00
André Bastos Dias
c919f52630
ADV NU: One Boost Passer Clause (#11567)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-11-15 09:37:00 -07:00
Aleksa
8ebb431d6c
Pokébilities: Ban Kingambit (#11574)
https://www.smogon.com/forums/threads/sv-pok%C3%A9bilities-suspect-kingambit-and-yanmega.3772844/post-10775271
2025-11-15 09:36:22 -07:00
André Bastos Dias
90020fbf67
Fix crystal-free Z-Moves and Dynamax-less Max Moves (#11090)
* Fix crystal-free Z-moves' interaction with Disable, Imprison and Taunt

* Fix

* Dynamax Pokemon should be affected by Taunt

* Fix with rest of Dynamax mechanics
2025-11-15 09:36:12 -07:00
André Bastos Dias
e8eda2446f
DPP Doubles: Ban Explosion and Self-Destruct (#11569)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
https://www.smogon.com/forums/threads/dpp-doubles-ou-explosion-banned.3717286/post-10771023
2025-11-10 21:29:53 -06:00
André Bastos Dias
c1e7db7735
Sort Dex entries (#11565)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
* Sort Dex entries

* Fix ExhaustiveRunner
2025-11-09 00:04:57 -07:00
André Bastos Dias
a75e0b49e9
Let's Go: Fix Legends Z-A Mega legality (#11566)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Let's Go: Fix Legends Z-A megas legality

* Remove redundant condition

* Fix lint

* Update data/mods/gen7letsgo/scripts.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-11-08 21:04:53 -07:00
Yoshiblaze
69081ea829
Add November's Pet Mod of the Month (#11552)
* spookymod Initial commit

npm not working locally for me anymore, it's 57 commits time

* Spookymod: Fix initial errors

* Spookymod: Fix more initial errors

* checking something

* Spookymod: checking something

* Spookymod: Fix const error

* Spookymod: Fix some errors

* Spookymod: fix small errors

* Spookymod: Fix a couple more errors

* Spookymod: More small errors

* Remove chatlines, fix generation

* Spookymod: Fully remove chat stuff

* Spookymod: errors

* trailing space

* remove random \

* Fix most errors

* Spookymod: Fix ID errors

* Spookymod: Fix Revive

* Spookymod: Fix toID

* Spookymod: Minor fixes

* Spookymod: Minor fixes

* Spookymod: More bugs

* Spookymod: Fix one of the Jumpscare images

* Spookymod: Move pairs

* Spookymod: Indents

* Spookymod: Some Temporary Fixes

* Apply suggestions from code review

---------

Co-authored-by: Meijer,L. (Lucas) <l.meijer6@students.uu.nl>
Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-11-08 15:04:15 -07:00
André Bastos Dias
ba85377563
Gen IV: Fix interaction between Magic Guard and Toxic Spikes (#11564)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-11-07 20:53:26 -06:00
demir
af7e9dbb3c
35 Pokes: Update list of allowed Pokemon for November 2025 (#11557)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
* 35 Pokes: Update list of allowed Pokemon for November 2025

* Fix meowstic forme

my bad! miscommunication happened

* Update config/formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-11-06 14:35:20 -07:00
André Bastos Dias
b971dd072e
Legends Z-A: Release Delphoxite and Diancie (#11561)
* Legends Z-A: Release Delphoxite and Diancie

* Fix data test

* Add Diancie event

* Add event to Legends Z-A OU
2025-11-06 14:35:09 -07:00
HoeenHero
ad3b40f1c9 Specify room identity with info commands to properly fix ignoring spectators/opponent
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-11-06 15:34:27 -05:00
André Bastos Dias
ca306027fa
UU: Ban Ogerpon-Cornerstone (#11559)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
https://www.smogon.com/forums/threads/uu-suspect-process-round-15-goofy-goober-rock-ogerpon-cornerstone-banned.3772794/post-10764128
2025-11-05 09:31:01 -07:00
André Bastos Dias
039ee5a8ae
NatDex Doubles: Ban Deoxys-Attack (#11558)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
https://www.smogon.com/forums/threads/national-dex-doubles-ou-metagame-discussion-shadow-tag-banned.3720802/post-10763924
2025-11-04 22:10:20 -07:00
InkyDarkBird
bc580f98af
SV Fortemons: Update bans (#11560) 2025-11-04 22:07:05 -07:00
Kris Johnson
bbad9183f2 Implement November 2025 tier shifts
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-11-01 23:32:03 -06:00
André Bastos Dias
0f4a8bd0c2
Fix Ogerpon item in Challenge Cup (#11544) 2025-11-01 23:28:47 -06:00
livid washed
e06072ed8b
Add November 2025 Randomized Format Spotlight (#11549)
* Implement November 2025 Randomized format Spotlight

* Shuffle moves in gen 8, like in other gens

* Remove console.log lines

* simplify code a lil

* lint
2025-11-01 23:28:23 -06:00
ACakeWearingAHat
9b9112c227
Randomized format set updates (#11551)
* Randomized format set updates

* lint

* Council decision: Revert Alcremie

* Apply suggestions from code review

* Add resttalk marowak in gen 2

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
Co-authored-by: livid-washed <115855253+livid-washed@users.noreply.github.com>
2025-11-01 23:27:16 -06:00
André Bastos Dias
0e41bcfc6e
Legends Z-A OU: Implement November tier shifts (#11553)
* Legends Z-A OU: Implement November tier shifts

* Update base and mega forms based on mega stone usage

* Fix Floette-Eternal tier
2025-11-01 23:27:03 -06:00
Leonard Craft III
59318c3f96
Add VGC Regulation F (#11555)
* Add VGC Regulation F

* Also update aliases

* I can't be bothered to properly fix that
2025-11-01 23:26:41 -06:00
Kris Johnson
97c7a70bfd
Add November 2025 rotational ladders (#11554)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-11-01 20:04:38 -06:00
André Bastos Dias
0005dd6a40
ADV: Implement PU and ZU shifts (#11550)
https://www.smogon.com/forums/threads/zu-old-gens-hub-oras-bans-379.3646944/post-10759948
2025-11-01 20:00:06 -06:00
weirlind120
5421909ffc
Update Gen 4 Draft (#11546)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
Updating Gen 4 Draft to the implementation for DDT. Approved by Draft Leaders.
2025-11-01 08:31:57 -04:00
André Bastos Dias
6e5e42e1d3
Fix interaction between Wonder Guard and typeless moves (#11548)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-10-31 16:31:59 -07:00
André Bastos Dias
00fe920ec0
Fix Taunt not working on Dynamaxed Pokemon (#11361)
https://www.smogon.com/forums/threads/sword-shield-battle-mechanics-research.3655528/post-8337140
2025-10-31 16:17:31 -07:00
Mia
874aa6f73c Fix link extraction in smogtours art credit field
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
GOD. FUCK. FUCK THIS. WOW. CANNOT BELIEVE IO SUFFERED THROUGH DEBUGGING THIS FOR HOURS _THE FIRST TIME_ AND MANAGED TO FORGET IT EVEN THOUGH THE METHOD I HAD TO FIX IT WITH IS _FOURTEEN LINES ABOVE_. FUCK.
2025-10-28 13:42:30 -05:00
Kris Johnson
7b0158b4ab Z-A OU: Give Mega Chandelure Magic Guard
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-10-27 12:28:06 -06:00
André Bastos Dias
e1eae4b88d
Legends Z-A: Add Light Ball (#11537)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-10-27 01:05:05 -06:00
André Bastos Dias
142d2bb6c3
Complete Legends Arceus pokedex (#11536) 2025-10-27 01:04:44 -06:00
kn-Kris
ae832da721
Gen 1 Stadium OU: Add June 2025 Rises (#11539) 2025-10-27 01:04:09 -06:00
Kris Johnson
27f2a9d3b9 Formemons: Fix Arceus validation 2025-10-27 01:02:11 -06:00
Kris Johnson
ac406bb3aa Z-A OU: Update Mega Greninja and Mega Ampharos's abilities
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-10-26 13:16:55 -06:00
Spammernoob69
4737bb273f
CAP: Implement Ramnarok 's buffs and full learnset (#11535)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
Buffs: +7 SpA, -7 Atk to both forms
Full movepool

https://www.smogon.com/forums/threads/cap-36-part-16-post-play-lookback-poll-2.3772516/post-10742571

https://www.smogon.com/forums/threads/cap-36-part-15-final-movepool-submissions.3768808/post-10654259
2025-10-26 02:34:16 -06:00
TurboRx
8fb533e4b9
Config: Arrays are not valid for Config.subprocesses (#11532)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-10-25 23:04:35 -07:00
Kris Johnson
c33bfbd004 Z-A OU: Split Pokemon into OU and UU 2025-10-25 16:56:18 -06:00
Alex "Mathy
bc044e3037
IPTools: Fix CIDR ranges at 128.* and up (#11466)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-10-25 18:26:44 -04:00
Kris Johnson
46980af8ce Z-A OU: Ban Mega Metagross 2025-10-25 14:42:42 -06:00
Kris Johnson
87a0f0fcde PLZA: Fix Zygarde and Eternal Floette events 2025-10-25 14:39:24 -06:00
André Bastos Dias
87dfb36c5c
Fix Legends Z-A learnsets (#11533)
* Fix Legends Z-A learnsets

* Add trailing commas
2025-10-25 14:30:16 -06:00
Kris Johnson
b6902782ab Update Z-A OU learnsets 2025-10-25 14:29:54 -06:00
André Bastos Dias
54d7abae08
Legends Z-A: Fix Kadabra tier (#11530)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-10-24 20:45:25 -06:00
Leonard Craft III
963d49aa93 Remove Terastal Crescendo
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-10-24 16:25:03 -05:00
André Bastos Dias
b2a85d2559
BH: Ban Sleep Talk and unban Comatose (#11527)
https://www.smogon.com/forums/threads/balanced-hackmons.3710859/post-10751647
2025-10-24 14:22:59 -06:00
Kris Johnson
2f2e193dad Z-A OU: Remove empty learnset arrays 2025-10-24 14:21:11 -06:00
Kris Johnson
31b555ee3f Z-A OU: Ban Zygarde 2025-10-24 14:20:25 -06:00
adrivrie
fd782a300b
Hackmons Cup: Remove new megas (#11529) 2025-10-24 14:00:53 -06:00
Kris Johnson
1aaa8137e6 Z-A OU: Ban Mega Alakazam and Mega Kangaskhan
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-10-22 12:22:56 -06:00
Kris Johnson
caf0b9b9d3 Z-A OU: Fix Floette's ability 2025-10-22 12:18:33 -06:00
Kris Johnson
f7e10ad94a Z-A OU: Rework Pyroar and Greninja 2025-10-22 12:08:18 -06:00
Kris Johnson
85bfc60fe8 Fix Floettite onTakeItem check 2025-10-22 12:05:30 -06:00
André Bastos Dias
af9af342e1
Separate gen9legends and gen9legendsou format data (#11518) 2025-10-22 12:04:07 -06:00
André Bastos Dias
44ded79364
Z-A OU: Fix removal of Zygardite in battle (#11520) 2025-10-22 10:32:54 -04:00
HoeenHero
0ef2d38ac3 Z-A OU: Fix removal of megastones from mega greninja and slowbro 2025-10-22 09:46:37 -04:00
Marty-D
6cfb5cfc98
Add new aliases
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-10-21 20:10:20 -04:00
Kris Johnson
34bd4c5d71 Z-A OU: Fix dexited mega stones 2025-10-21 16:00:02 -06:00
Kris Johnson
e8ecbc0518 Add Z-A OU changes 2025-10-21 15:58:17 -06:00
Kris Johnson
cd23d6ff53 Add new aliases
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-10-21 14:54:19 -06:00
Kris Johnson
6b354689ca Z-A: Fix Greninja-Bond's learnset 2025-10-21 14:21:51 -06:00
Justin Xing
9562cec389
Add Pretty Feather (#11408) 2025-10-21 12:11:09 -04:00
Marty-D
9e6f71c175
Descriptions: Add new items 2025-10-21 12:10:23 -04:00
Marty-D
31d94e6d1e
Update Mega Stone sprites 2025-10-21 12:08:20 -04:00
André Bastos Dias
16bf2213c0
Fix Zygarde-Mega battleOnly forme (#11517)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Fix Zygarde-Mega battleOnly forme

* Revert changes
2025-10-21 02:53:00 -06:00
André Bastos Dias
68596ed027
Fix Legends Z-A test (#11516) 2025-10-21 02:51:53 -06:00
Kris Johnson
f083a5b45d Z-A: Fix Water Shuriken 2025-10-21 00:38:20 -06:00
Kris Johnson
7600085fc0 Z-A: Greninja-Bond should be unreleased 2025-10-21 00:16:07 -06:00
Kris Johnson
f532e74000 Legends Z-A: Remove Terastallization 2025-10-20 23:46:53 -06:00
Kris Johnson
fcddb7fe21 Legends Z-A: Fix Greninja validation 2025-10-20 23:46:01 -06:00
Kris Johnson
5b5adadd66 Starmie is not LC 2025-10-20 23:36:06 -06:00
Kris Johnson
332093b59e Fix Legends Z-A format legality 2025-10-20 23:30:31 -06:00
Kris Johnson
6d4985c51e Fix typo 2025-10-20 23:07:53 -06:00
Kris Johnson
0a2112b19b Legends Z-A: Fixed unreleased Pokemon tiers 2025-10-20 23:03:04 -06:00
Kris Johnson
64a0978b8a Fix typo 2025-10-20 22:53:39 -06:00
Kris Johnson
93e8759892 Add Legends Z-A speculative ladder 2025-10-20 22:49:30 -06:00
André Bastos Dias
f69ebf7fed
Add Legends: Z-A Learnsets (#11508)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Add Legends Z-A mod

* Fix lint

* Use double quotes for isNonstandard

* Add 9L0 moves

* Add legendary encounters

* Add Unobtainable

* Inherit legendary learnsets

* Fix Floette-Mega id

* Use strangeball for gen8legends events

* Simplify isPrimal

* Create tests

* Edit comment

* Release Greninja-Mega

* Add Mega Floette and Mega Zygarde aliases

* Fix gen9legends learnset indentation

* Add pokedex changes

* Fix lint

* Fix test

* Revert changes

* Update formats-data.ts

* Fix tests

* Add updated stats for Mega Mawile and Mega Medicham

* Inherit Mega Starmie stats

* Remove Kleavor from Scyther evolutions

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-10-20 15:49:26 -06:00
Kris Johnson
b3374fb2e5
Move Terrakion back to NUBL
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-10-20 13:04:13 -06:00
InkyDarkBird
851acf73ba
Tera Override: Update bans (#11515) 2025-10-20 12:55:24 -06:00
Guangcong Luo
0c69a1f7e3 Fix crash on startup with serialized bestof games
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
The parent bestof game doesn't get serialized, but their subgames do,
which crashes PS when they get deserialized. Setting the correct flag
prevents that crash.
2025-10-20 02:29:35 -07:00
André Bastos Dias
65c3bf81c6
Godly Gift: Restrict Araquanid and Iron Hands (#11513)
https://www.smogon.com/forums/threads/godly-gift.3710734/post-10744699
2025-10-19 23:05:09 -06:00
André Bastos Dias
1bc2d58eec
RU: Ban Mamoswine (#11514)
https://www.smogon.com/forums/threads/np-ru-stage-20-steppa-pig-mamoswine-banned.3771936/#post-10745262
2025-10-19 23:05:00 -06:00
Mia
debd7bebc3 Fix crash on startup
Chat being loaded after roomlogs causes a crash in room initialization.
2025-10-19 23:26:20 -05:00
Marty-D
5bef393f6f
Add new avatars
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-10-19 20:29:24 -04:00
Slayer95
4b8c6a4d6d
Refactor startup (#11346)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
This minimizes side effects of import/require across the codebase,
and lets the caller be responsible of initializing child processeses,
as well as other async logic, such as restoring saved battles.
2025-10-17 19:37:47 -07:00
Karthik Bandagonda
d0d1eab7b7
Gens 3-4: Fix Knock Off + Recycle Interaction (#11510)
* Gens 3-4: Fix Knock Off + Recycle Interaction

* forgot to actually remove the item
2025-10-17 16:34:51 -06:00
Aurastic
b7c444cee5
make plza default (#11511) 2025-10-17 13:07:19 -06:00
Lusamine
8a75295b1b
Wi-Fi: Change Z-A GA background for readability (#11512) 2025-10-17 13:07:01 -06:00
Aurastic
558a799c81
Wi-Fi: Add support for PLZA (#11505)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-10-15 20:35:51 -06:00
Kris Johnson
f159beb578 fix things 2025-10-15 20:14:30 -06:00
Kris Johnson
051a404478 Add Legends: Z-A Pokemon and items 2025-10-15 16:46:14 -06:00
Zachary Perlmutter
612707d654
National Dex Ubers UU: Ban Chien Pao and Dracovish (#11504)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* National Dex Ubers UU: Ban Chien Pao and Dracovish

https://www.smogon.com/forums/threads/national-dex-ubers-uu-october-shifts-108.3742166/page-5#-dracovish-and-chien-pao-have-been-quickbanned

* Update formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-10-14 20:35:30 -06:00
Aleksa
c4cd55e397
Pokébilities: Ban Icy/Smooth/Damp Rocks (#11495)
* Pokébilities: organize bans, remove redundant smeargle

(Smeargle is already banned via Moody)

* Ban Icy/Smooth/Damp Rocks

https://www.smogon.com/forums/threads/pok%C3%A9bilities.3712725/post-10732153

* Update config/formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-10-14 20:35:20 -06:00
André Bastos Dias
0d555b62f4
PU: Ban Heracross (#11501)
https://www.smogon.com/forums/threads/pu-council-updates.3718204/post-10735944
2025-10-14 20:34:08 -06:00
Karthik99999
dc48d8234e Gens 3-4: Fix Knock Off state being reset on switch out
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-10-14 18:12:25 -07:00
Mia
f1adacf0ee Chat: Ensure CommandContext#pmTransform properly handles /raw messages
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-10-12 11:59:48 -05:00
Mia
805b17ba3e Ensure /dt works in PMs 2025-10-12 11:51:12 -05:00
Mia
ef70c3193a Prevent /dt from bypassing ignore spectators 2025-10-11 20:00:33 -05:00
InkyDarkBird
e3854f06e8
Trademarked: Update bans (#11499)
* SV Trademarked: Unban Magnet Pull

* ban decidueye and smeargle

* Update config/formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-10-10 18:36:35 -06:00
André Bastos Dias
5ead2874eb
Reset ability and item state on switch in (#11488) 2025-10-06 18:19:07 -07:00
André Bastos Dias
c2162bd442
NU: Ban Azelf (#11487)
* NU: Ban Azelf and Terrakion

https://www.smogon.com/forums/threads/np-stage-17-azelf-terrakion-banned.3767218/post-10728227

* Update data/formats-data.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-10-06 02:20:57 -06:00
Karthik Bandagonda
4425ec2719
Add onChooseTeam event for formats (#11476)
* Add onChooseTeam event for formats

* Fix VGC 2010 autochoose

* Use custom validation instead of Limit One Restricted

* cleaner code

* clean up chooseTeam code
2025-10-06 02:20:44 -06:00
livid washed
c7bd8da8b6
Advertise Ladder Achievements Project for the Randomized Spotlight (#11483) 2025-10-06 02:17:50 -06:00
Aleksa
afbe769358
Pokébilities: Update bans (#11475)
* Pokébilities: Update bans

Newer OU bans

* comma.

* Update formats.ts

* add volc

* add gougingfire

* remove brightpowder

* Update formats.ts

* Update config/formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-10-06 02:17:20 -06:00
Zachary Perlmutter
4db305f846
National Dex Ubers UU: Implement shifts (#11481)
* National Dex Ubers UU: Implement shifts

Chansey, Ditto, Hatterene are banned, Terapagos is freed.

https://www.smogon.com/forums/threads/national-dex-ubers-uu-survey-106.3742166/page-5#-tier-shifts

* Update formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-10-06 02:17:10 -06:00
Mathieu-ISSINDOU
859e6dcaa9
Camomons: Update bans (#11477)
* (OM) SV Camomons: banlist update

Deoxys-Speed unban: https://www.smogon.com/forums/threads/camomons-vr-updates-124-deoxys-speed-freed-125.3711340/post-10585015

Gouging Fire and Palafin bans:
https://www.smogon.com/forums/threads/camomons-vr-updates-124-deoxys-speed-freed-125.3711340/post-10532530

* Update formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-10-06 02:14:16 -06:00
pyuk-bot
8890d95d61
FFA Rands: Fix more bugs (#11478)
* Update sets.json

* Make unburden item higher priority than acrobatics
2025-10-06 02:13:56 -06:00
Yoshiblaze
57d62f664a
Slight set changes/fixes + Slate 24 (#11486) 2025-10-06 02:13:03 -06:00
André Bastos Dias
d4e84d80d7
ZU: Ban Heat Rock (#11482)
https://www.smogon.com/forums/threads/np-zu-stage-18-flower-heat-rock-ban-17.3770736/#post-10726613
2025-10-06 02:08:58 -06:00
InkyDarkBird
2f0fb74325
SV Revelationmons: Ban Gliscor (#11485) 2025-10-06 02:07:36 -06:00
André Bastos Dias
2dc477f9d8
Revert Flower Veil changes (#11480)
* Revert Flower Veil changes

* Update data/mods/teraoverride/abilities.ts

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

* Update data/mods/teraoverride/abilities.ts

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

* Update data/mods/teraoverride/abilities.ts

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-10-04 10:50:41 -06:00
Kris Johnson
03cf977b12
Fix Lilligant-Hisui and Diancie's tiers
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-10-02 13:49:42 -06:00
shrianshChari
6dc97b208c
RU: Update bans (#11472)
https://www.smogon.com/forums/threads/np-sv-ru-stage-18-kings-queens-july-2025-shifts-serperior-quickbanned-7.3767219/post-10724015
2025-10-02 13:37:26 -06:00
demir
912a4c1388
35 Pokes: Ban Spinda, unban Moltres (#11473)
https://www.smogon.com/forums/threads/35-pokes-september-2025.3749375/post-10724031
2025-10-02 13:33:37 -06:00
Yoshiblaze
c75fe52753
Blank Canvas: Fix New Sprite Viewer Code (#11474)
* Blank Canvas: Fix New Sprite Viewer Code

* Forcing Assault Vest for AV Pivot

* Fix error

* actually fix error
2025-10-02 13:33:10 -06:00
Kris Johnson
05aa26d108 Add October 2025 OMotM and fix Flower Veil 2025-10-02 13:31:43 -06:00
Kris Johnson
45e4f2e882 Fix Drednaw and Inteleon's tiers 2025-10-01 21:34:19 -06:00
foilmirror
9292dd4546
ADV: Ban Glalie from RU (#11468)
* ADV: Ban Glalie from RU

* Update formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-10-01 21:24:29 -06:00
Kris Johnson
f52bc482bb
Add Terastal Crescendo online competition (#11471)
* Add Terastal Crescendo online competition

* Fix build
2025-10-01 21:13:50 -06:00
missshowdown
8f75a35759
Update ZU by usage NFEs (#11469)
* Update ZU by usage NFEs


Pikachu is not ZU by usage by a longshot

* Update data/formats-data.ts

* Update data/formats-data.ts

* Update data/formats-data.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-10-01 20:08:53 -06:00
André Bastos Dias
f34f220a66
ADV PU: Ban Baton Pass + Substitute (#11470)
* ADV PU: Ban Baton Pass + Substitute

https://www.smogon.com/forums/threads/adv-pu.3729689/page-2#post-10723414

* Fix ADV ZU
2025-10-01 20:04:21 -06:00
Kris Johnson
7554287821 Fix build 2025-10-01 20:01:05 -06:00
Kris Johnson
ef80a83683 Update lcotm alias 2025-10-01 19:59:13 -06:00
Kris Johnson
2dbd3e8772 Add October 2025 rotational formats 2025-10-01 19:51:50 -06:00
adrivrie
b1192c40e5
Random Battles: September 2025 balance patch (#11465) 2025-10-01 12:44:06 -06:00
demir
1731cf159e
35 Pokes: Update list of allowed Pokemon for October 2025 (#11467)
* 35 Pokes: Update list of allowed Pokemon for October 2025

https://www.smogon.com/forums/threads/35-pokes-september-2025.3749375/

* Update config/formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-10-01 12:43:38 -06:00
Yoshiblaze
fbe978a9c9
Add October PMotM: Blank Canvas Random Battle (#11463)
* Blank Canvas Rands: Initial Commit

* Add in all Item hardcodes

* a couple more set adjustments

* Update data/mods/blankcanvas/rulesets.ts

* Apply suggestions from code review

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-10-01 12:41:03 -06:00
Kris Johnson
1d741a1209 Implement October 2025 tier shifts 2025-10-01 12:18:52 -06:00
André Bastos Dias
42861c0c9b
GSC PU: Ban Poliwhirl (#11458)
https://www.smogon.com/forums/threads/gsc-pu-discussion-thread-trap-pass-banned-post-55.3671458/post-10716462
2025-09-29 09:11:49 -06:00
Kris Johnson
6f21617d42 ORAS OU: Ban evasion abilities, King's Rock, Razor Fang, and Quick Claw
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-09-28 18:40:32 -06:00
Kris Johnson
343839efa0
GSC: Move Feraligatr to UU 2025-09-28 16:56:45 -06:00
Eve
2145f582c9
LGPE: UU/RU tier changes (#11462)
Kingler rose from RU to UU
Arcanine Fell from UU to RU
Chansey Fell from UU to RU
Cloyster Fell from UU to RU
Dugtrio Fell from UU to RU
Eevee-Starter Fell from UU to RU
Kabutops Fell from UU to RU
Lapras Fell from UU to RU
Moltres Fell from UU to RU
Omastar Fell from UU to RU
Persian-Alola Fell from UU to RU
Pikachu-Starter Fell from UU to RU
Sandslash-Alola Fell from UU to RU
Tentacruel Fell from UU to RU
Vileplume Fell from UU to RU
Wigglytuff Fell from UU to RU
2025-09-28 16:56:04 -06:00
André Bastos Dias
9b631af072
SM LC: Ban Vulpix-Alola (#11460)
* SM LC: Ban Vulpix-Alola

https://www.smogon.com/forums/threads/vulpix-alola-in-sm-lc.3771276/#post-10718757

* Update formats.ts
2025-09-28 13:54:05 -06:00
Karthik99999
ae49cc9c66 Update Heal Block messages 2025-09-28 00:51:06 -07:00
Karthik99999
96233e6576 Add Shiny Koraidon/Miraidon events
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-09-26 14:07:04 -07:00
Kris Johnson
16f3718c39
ADV ZU: Ban Clamperl
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-09-25 13:30:50 -06:00
Kris Johnson
875eed575c
Bad 'n Boosted: Ban Pawmot 2025-09-25 13:29:54 -06:00
Runo
f6120ffe4f
NatDex RU: Ban Okidogi and Thundurus (#11453)
https://www.smogon.com/forums/threads/national-dex-ru-metagame-discussion.3713801/post-10711661
2025-09-25 13:28:33 -06:00
André Bastos Dias
7ad9c45191
Fix gender validation (#11449)
https://www.smogon.com/forums/threads/bug-report-validator.3771139/
2025-09-25 13:28:06 -06:00
André Bastos Dias
658cb99fac
RBY UU: Ban Confuse Ray and Supersonic (#11457) 2025-09-25 13:27:38 -06:00
Kris Johnson
3c1cb0912f
ZU: Ban Bellossom 2025-09-25 13:27:19 -06:00
André Bastos Dias
7eca4741ab
Fix Tera Stellar not applying <60 bp boost on first use (#11455)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-09-21 20:47:21 -07:00
Kris Johnson
68c6f9aa35 Tour Settings: Make autoconfirmed only actually work
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-09-20 18:04:29 -06:00
Kris Johnson
1423bb6904
ADV: Fix Glalie's tier again
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-09-19 18:37:16 -06:00
Karthik99999
c164f85009 Add Shiny Chi-Yu event
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-09-18 17:59:34 -07:00
Karthik99999
bd5fdfc68e Add Bo3 checkbox to VGC 2009/2010
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-09-17 21:04:38 -07:00
André Bastos Dias
a6d2c8cda5
Fix the priority of the Partial Trapping check in Gen 1 (#11390)
* Fix the priority of the Partial Trapping check in Gen 1

https://github.com/pret/pokered/blob/master/engine/battle/core.asm#L3326

* Maybe this wasn't related
2025-09-17 20:08:28 -06:00
Alex "Mathy
6bf169523d
Datacenters: Log to upperstaff (#11450)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-09-16 21:32:34 -05:00
Kris Johnson
def592aba0
ADV: Fix Clamperl's tier
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-09-15 23:18:40 -06:00
Alex "Mathy
ee81fdcca9
IPTools: Fix CIDR implementation (#11448)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-09-15 17:38:55 -05:00
André Bastos Dias
be2ea86180
Fix Conversion2 in Gens 3 and 4 (#11357) 2025-09-15 15:02:16 -06:00
Emikatana
ab4d6742d8
ChatBats updates and balance changes (#11446)
* add new ChatBats mons

* add new mons

* adding new mons + updates

* add new mons + updates

* updating abilities

* adding new moves

* item updates

* adding edits to Terrains

* adding code for testing (will remove)

* adding isBerry to Tart Apple to make it work with Ripen

* fixing Crowverload

* fixing crowverload

* fixing Crowverload

* fixing crowverload (final)

* ok maybe fix Crowverload?

* fixing terrain shift

* fixing rillaboom

* adding animations + fixing Wacky Whack

* changing order of things in Terrain Shift

* fixing Genesect

* fixing

* fix

* updating

* fixing Techno Blast doing no damage

* fixing Genesect

* fixing lint

* oops

* updating testing code

* testing

* giving Mew a positive onSwitchInPriority so it activates before hazards

* set updates

* item updates

* set updates

* set updates

* updates

* removing Koraidon/Dachsbun interaction

* level updates

* updating testing code

* fixing biogenesis displaying wrong types

* fixing biogenesis

* removing test code

* lint fix

* lint fixes

* fixing lint issues

* updating descriptions

* updating descriptions

* Apply suggestions from code review

* Apply suggestions from code review

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-09-15 15:01:49 -06:00
Mia
a157e3db0e Update cassiopeia's staffmon 2025-09-15 15:59:05 -05:00
missshowdown
56b9561219
Quickban Clamperl from ADV ZU (#11444)
https://www.smogon.com/forums/threads/clamperl-in-adv-zu.3771014/
Clamperl is being quickbanned with an immediate suspect test
2025-09-15 12:15:34 -06:00
Kris Johnson
ae6d677edc
Refactor color support for cosmetic formes (#11442)
* Refactor color support for cosmetic formes

* Oops

* Oop2s

* Fix build

* Fix build ?
2025-09-15 12:15:22 -06:00
Mia
8af9d9cfab Best-of: Nullify child game parent rooms on expiry rather than destroy 2025-09-15 13:12:44 -05:00
André Bastos Dias
dbb10a22d3
ADV: Move Glalie to UU (#11443)
https://www.smogon.com/forums/threads/adv-rarelyused.3731043/post-10702900
2025-09-15 12:07:56 -06:00
Mia
42294611bb Bo3: Remove parent expiry cap, store roomids instead of direct references
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-09-14 16:10:48 -05:00
Kris Johnson
f20c0403bc
Add Same Color Clause
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-09-13 19:27:04 -06:00
ACakeWearingAHat
9c52db4321
Random Battles hotfix: Bulky Attacker Appletun (#11427)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
prevents Apple Acidless Appletun
2025-09-13 15:39:06 -06:00
pyuk-bot
ac2d14a299
FFA Rands: Fix more bugs (#11437)
* Increase priority of acrobatics check for items

* Fix Tornadus-Therian’s ability

* Fix Slowking’s signature move spelling
2025-09-13 15:38:47 -06:00
demir
b8a526d479
35 Pokes: Ban Shed Tail (#11436) 2025-09-13 15:38:18 -06:00
André Bastos Dias
1b2e721a37
AAA Doubles: Ban Gholdengo (#11439)
https://www.smogon.com/forums/threads/almost-any-ability-doubles-gholdengo-banned.3770036/#post-10702379
2025-09-13 15:37:20 -06:00
André Bastos Dias
84409bf462
AAA UU: Update bans (#11438)
* AAA UU: Ban Hydreigon, Slither Wing​ and Zamazenta-Crowned

https://www.smogon.com/forums/threads/almost-any-ability-uu.3770034/#post-10701164

* Clean
2025-09-13 15:37:08 -06:00
RADU
32ce74568d
National Dex 1v1: Ban Dragonite (#11441)
* National Dex 1v1: Ban Dragonite

https://www.smogon.com/forums/threads/1v1-other-tiers.3726778/post-10703217

* Update formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-09-13 15:36:50 -06:00
Yoshiblaze
10e3a12d4e
Do Not Use: Minor changes (#11440)
* One more adjustment

* Adjust Jigglypuff Pt. 1

* Adjust Jigglypuff Pt. 2
2025-09-13 15:36:09 -06:00
Kris Johnson
02b461c848
Fix crash 2025-09-13 15:35:47 -06:00
Kris Johnson
336f1d58f1 Make SCL rooms super secret
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-09-11 18:00:58 -06:00
InkyDarkBird
4495da1c15
Revelationmons: Update bans (#11435)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-09-09 20:17:55 -06:00
Kris Johnson
2eca53c782
Godly Gift: Unban Gholdengo for suspect
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-09-08 12:28:35 -06:00
Kris Johnson
79a073e2d8
Gen 7/8 BH: Fix banlist 2025-09-08 12:24:55 -06:00
André Bastos Dias
8b37edc5ea
Doubles OU: Ban Flutter Mane after suspect test (#11434)
https://www.smogon.com/forums/threads/np-sv-dou-stage-15-without-me-flutter-mane-suspect.3770221/post-10699160
2025-09-08 12:23:40 -06:00
André Bastos Dias
3d4f34e784
Correctly implement Cud Chew and Slow Start (#11376)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
Co-authored-by: Karthik Bandagonda <32044378+Karthik99999@users.noreply.github.com>
2025-09-07 15:24:34 -07:00
shrianshChari
8584c3cf50
Gen 5: Remove Powder immunity from Overcoat (#11430) 2025-09-07 11:32:48 -07:00
InkyDarkBird
421d35113c
Update Alphabet Cup and Shared Power bans (#11428)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-09-05 19:48:12 -06:00
Karthik99999
ad36e04327 Add Shiny Ting-Lu event
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-09-04 21:42:01 -07:00
Guangcong Luo
e18740c70a Fix MySQL support in db library
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
(Broken in a341d3c566)
2025-09-03 22:08:11 -07:00
pyuk-bot
da359b0d8f
Add "Rebalance Levels" rule for random formats (#11422)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-09-03 13:07:19 -06:00
ACakeWearingAHat
ce510af51f
Randomized format set updates (#11426)
* Randomized format set updates

* Appletun

* Delete mono-rock rhydon in gen 2

* Rename deoxys roles in gen 3 for greater clarity

* Shuffle around stunfisk sets to reduce resttalk a bit

---------

Co-authored-by: livid-washed <115855253+livid-washed@users.noreply.github.com>
2025-09-03 13:06:17 -06:00
pyuk-bot
e4998fa279
FFA Rands: Assorted bug fixes (#11423)
* FFA Rands: Assorted bug fixes

* Don't enforce Protect on Wallbreaker

* Make Suicune and Raikou always be Pressure

* Prevent Tera Blast Sylveon from getting Silk Scarf

* Fix Imprisoner Zoroark ability
2025-09-03 13:05:51 -06:00
livid washed
318bc27ed2
Add September 2025 Randomized Format Spotlight (#11425)
* Add September 2025 Randomized Format Spotlight

* lol weird indent
2025-09-03 13:04:35 -06:00
shrianshChari
de10d91321
ADV: Add Speed Pass Clause (#11424)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* ADV: Ban the combination of Baton Pass and Speed-boosting

https://www.smogon.com/forums/threads/speedpass-in-adv-ou.3769223/page-3#post-10692421

* Satisfy linter

* guh

* Create Speed Pass Clause

* do it to ou

* Apply suggestions from code review

* Update test

* ugh

* ughhhhhhh

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-09-02 21:59:44 -06:00
Yoshiblaze
af1833b74a
Do Not Use Rands: Fix Hidden Power IVs & Fix Bad Sets (#11421)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Do Not Use Rands: Fix Hidden Power IVs

* Slight set adjustment Pt. 1

* Slight set adjustment Pt. 2

* Some more set adjustments Pt. 1

* Some more set adjustments Pt. 2

* More adjustments

* More adjustments cont.

* fix lechonk
2025-09-02 13:09:18 -06:00
shrianshChari
743d259186
ADV: Ban NUBL from NU (#11420)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-09-01 10:47:45 -06:00
André Bastos Dias
7255086287
35 Pokes: Unban Shed Tail (#11418)
https://www.smogon.com/forums/threads/35-pokes-september-2025.3749375/post-10690485
2025-09-01 10:28:56 -06:00
demir
f480b8c442
35 Pokes: Update list of allowed Pokemon for September 2025 (#11419) 2025-09-01 10:28:48 -06:00
Mia
8b1efe7e45 Sim: Verbosely debug validator effectType mismatches 2025-09-01 11:28:10 -05:00
Karthik99999
f4a7f092f6 VGC/BSS: Remove Reg I ladder
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-08-31 23:59:46 -07:00
Karthik99999
fde7a7962a Add VGC 2023 Reg C as challengeable format 2025-08-31 23:59:21 -07:00
dot-Comfey
7357f0fa8f
Add HOME relearner for LA (#11409)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Add HOME relearner for LA

* Update dex-species.ts

Workaround for a crash caused by using the LA mod in dexsearch

* Fix more crashes

* `gen8legendsarceus` -> `gen8legends`
2025-08-31 23:59:04 -06:00
ACakeWearingAHat
c3e0bbd61d
Revamp Gen 9 Free-For-All Random Battle (#11406)
* WIP free-for-all revamp

* bonus touches

* Create ffa-sets.json

* Most stuff besides items

* Fix plate distribution logic

* The Palafin thing

* Update teams.ts

* Update index.ts

* Update server/chat-plugins/randombattles/index.ts

Co-authored-by: pyuk-bot <21160928+pyuk-bot@users.noreply.github.com>

---------

Co-authored-by: MacChaeger <21160928+pyuk-bot@users.noreply.github.com>
Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-08-31 23:58:46 -06:00
Kris Johnson
8797d4628c Remove inactive ladders 2025-08-31 23:57:15 -06:00
Kris Johnson
5fb1a1dd85 Add September 2025 rotational format ladders 2025-08-31 23:49:53 -06:00
André Bastos Dias
f50dc0f836
Add tests for Fairy Aura and Mold Breaker interaction (#11392) 2025-08-31 23:40:06 -06:00
adrivrie
d2591ecc75
Random Battles: August 2025 balance patch (#11411)
* Random Battles: August 2025 balance patch

* Apply suggestions from code review

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-08-31 23:39:28 -06:00
André Bastos Dias
cec4e42f02
National Dex Godly Gift: Update bans (#11412) 2025-08-31 23:39:18 -06:00
Yoshiblaze
9c4a4277fb
Add New Pet Mod of the Month: Do Not Use Random Battle (#11413)
* Change Scream Tail's ability

* Balls Random Battle: Initial Commit

* Fix errors

* fix 1 more error

* Team Generator Temp Fix + Add Broadcast

* actually add the broadcast message

* Add new Virus sprite

* Add new Virus sprite for real this time

* September PMOTM Initial Commit

* Fix errors

* Fix error

* Possible error fix + set adjustments

* Remove console.log

* Move Pet Mods to Column 2

* Update config/formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-08-31 23:38:13 -06:00
Kris Johnson
a35198aca7
ZU: Ban Floatzel
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-08-31 16:03:58 -06:00
André Bastos Dias
2acecdb7bb
Revelationmons: Ban Arcanine-Hisui (#11415)
* Revelationmons: Ban Arcanine-Hisui

https://www.smogon.com/forums/threads/revelationmons.3711644/post-10689138

* Line breaks
2025-08-31 15:45:38 -06:00
InkyDarkBird
62a399b347
STABmons: Update restrictions (#11416) 2025-08-31 15:45:17 -06:00
Leonard Craft III
919135f432 DOU: Ban Commander, unban Tatsugiri
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
https://www.smogon.com/forums/posts/10687711/
2025-08-29 19:39:05 -05:00
Mia
9f0e3584de DOU: Unban Flutter Mane 2025-08-29 19:16:11 -05:00
TurboRx
38228cf1be
Fix typos (#11405) 2025-08-29 15:07:02 -07:00
André Bastos Dias
139e57e56a
Add test for Poison Puppeteer and Lum Berry interaction (#11375)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-08-27 12:22:41 -06:00
Kris Johnson
c339b13ca6
Inheritance: Re-ban Shaymin-Sky 2025-08-27 12:20:52 -06:00
André Bastos Dias
79885b011a
DPP Doubles OU: Ban Swagger (#11404)
* DPP Doubles OU: Ban Swagger

https://www.smogon.com/forums/threads/dpp-doubles-ou.3717286/page-6#post-10379087

* Apply suggestions from code review

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-08-27 12:17:25 -06:00
dot-Comfey
b27ddb4ae2
Add BDSP HOME relearner and fix BDSP event legality (#11374)
* Allow BDSP moves to be learned via HOME relearner

* Update team-validator.ts

Commented out my changes to see if this was causing a test to fail; turns out my code isn't at fault.

* Update team-validator.ts

* Don't get learnset for Pokemon that don't exist in BDSP

Without the isNonstandard check, the learnset will be taken from the base learnsets.ts file, which could result in detecting moves that are actually not from BDSP.

* Fix BDSP legality

* Update team-validator.ts

* Fix test and learnsets

* Update data.js

* Prevent illegal transfers to/from BDSP

Nincada from outside BDSP cannot be sent to BDSP, Nincada from BDSP cannot be sent to other Switch games, and Spinda cannot be sent from or to BDSP. Currently this has no effect in regular Gen 9, but it technically does in Gen 9 Natdex (I have no idea if anything changes), and it may affect future generations.
2025-08-27 12:15:59 -06:00
André Bastos Dias
d0696157a3
ADV NU: Ban Glalie (#11403)
https://www.smogon.com/forums/threads/revisiting-adv-nu.3749245/page-4#post-10685090
2025-08-27 12:10:18 -06:00
André Bastos Dias
7561ae90a9
BW Doubles OU: Ban Shadow Tag (#11402)
https://www.smogon.com/forums/threads/bw-doubles-ou-shadow-tag-suspect-post-79.3606719/page-4#post-10684817
2025-08-27 12:09:48 -06:00
Emikatana
0cda843116
ChatBats: Update with new mons, bugfixes, and balance changes (#11386)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
* updating with new mons and changes

* updating

* adding new sets and updating changed ones

* updating items

* adding custom moves

* adding test enforcement

* fix lint

* fixing this nonsense

* fixes + adding descriptions

* fixing bugs

* fixing set things

* fixing anim

* fixing hail mary

* removing Psychic Noise from Mesprit set

* fixing mesprit hardcodes

* updating test hardcodes

* preventing Mew from generating Max, G-Max, and Z-moves

* Altaria-Mega will now get Roost instead of Draco Meteor on Dragon Dance sets

* add Typhlosion Mega

* add Typhlosionite

* add Typhlosion-Mega

* add Typhlosion

* add Heat Sink

* fixing Koraidon levels and Mega evolving

* updating test hardcodes

* fixing Koraidon

* level and set updates

* commenting out testing code

* lint

* lint

* need to test one more thing

* fixing some neutralizing gas stuff

* updating test list

* removing Gigantamax moves from Mew's movepool

* removing test code

* fixing lint issues with heat sink

* ensuring that Altaria and Typhlosion do not get selected if the team already has a Mega

* add Terapagos

* +Terapagos

* illumise/volbeat update + Terapagos

* +Terapagos

* fix

* updating volbeat/illumise

* adding Tera Wheel

* changing Tera Starstorm + fixing Raging Bull bug

* fixing call illumise and call volbeat

* removing custom message from Tera Wheel

* removing test code

* Apply suggestions from code review

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-08-24 19:00:30 -06:00
André Bastos Dias
2abd5c12d5
National Dex 1v1: Ban Melmetal (#11387)
https://www.smogon.com/forums/threads/1v1-other-tiers.3726778/#post-10671271
2025-08-24 18:32:55 -06:00
André Bastos Dias
29612dd396
AAA UU: Ban Archaludon and Mamoswine (#11396) 2025-08-24 15:40:23 -06:00
Vaibhav Hariani
51c5cc594b
Fix comments for priority in the sim (#11385) 2025-08-24 13:19:27 -07:00
TurboRx
2bc7166d4e
fix(workflow): remove extra brace in update_version.yml (#11395) 2025-08-24 13:18:27 -07:00
Karthik99999
2ece981dae Add Shiny Chien-Pao event
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-08-22 18:51:57 -07:00
pyuk-bot
c1b536d2f3
FFA: Make Court Change always rotate 90° clockwise (#11389)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-08-21 21:31:54 -07:00
Karthik99999
5f9ef6e4cb Send source for Entrainment ability change 2025-08-21 21:11:36 -07:00
Mia
df1567a51a Fix typo
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-08-19 02:46:15 -05:00
Mia
5205be2c5a Restore 'pdon' alias 2025-08-19 02:44:11 -05:00
Brendan Leahey
73558a31f4
Little Cup: Ban Torchic (#11380)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Little Cup: Ban Torchic

Banned via suspect test: https://www.smogon.com/forums/threads/free-bird-torchic-suspect-test.3768884/post-10674062

* Update formats-data.ts

* Little Cup: Remove Torchic from LCUU Banlist

* Update config/formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-08-18 12:52:41 -06:00
Mia
06325a0b57 Room-battle: Fix crash in ladder update
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-08-17 13:43:37 -05:00
Mia
16765c31f7 Helptickets: Add usercard for reporter 2025-08-17 13:42:19 -05:00
André Bastos Dias
3ac9aa1121
AAA Doubles: Ban Terapagos (#11378) 2025-08-17 12:34:38 -06:00
Karthik99999
ac20e7c438 Add Worlds 2025 Toedscool event
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-08-15 02:39:11 -04:00
Mia
ffe2f3111b Helptickets: Properly log claim duration for text tickets
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-08-14 21:51:44 -05:00
André Bastos Dias
f420a8ee12
Remove BDSP Eject Button inheritance (#11352)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-08-14 10:34:49 -06:00
André Bastos Dias
3468744364
Directly reference volatile when getting sourceEffect for partiallytrapped damage (#11360) 2025-08-14 11:46:02 -04:00
Karthik99999
7143879536 Best-of: Check for overall winner after ties
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-08-13 22:26:26 -04:00
Karthik Bandagonda
9e13a9eec3
Fix ChatBats call ability crash (#11367) 2025-08-13 20:17:32 -06:00
Karthik99999
321c7bd112 ChatBats: Actually use the randomChatBatsTeam function
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-08-13 17:07:00 -04:00
dot-Comfey
60a4698695
Allow past gen moves to be learned via HOME relearner (#11362) 2025-08-13 14:35:48 -06:00
André Bastos Dias
643d650c03
Remove console.log in test (#11366) 2025-08-13 14:35:32 -06:00
André Bastos Dias
3a67660d9e
Fix Trace message timing (#11282)
Co-authored-by: Karthik99999 <bandagondak0217@gmail.com>
2025-08-13 14:11:49 -04:00
pyuk-bot
1ee9efa2c8
Always allow canceling a switch with Shed Shell (#11365)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-08-12 19:57:37 -04:00
Mia
99c0799376 Teams: Don't crash on close when database not enabled
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-08-12 11:05:11 -05:00
Kris Johnson
478faeeb69
Inheritance: Unban Shaymin-Sky for suspect
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-08-11 20:18:00 -06:00
Kris Johnson
a3932e114e Fix typo 2025-08-11 18:22:22 -06:00
Kris Johnson
368419d7d4 Fix typo 2025-08-11 18:20:53 -06:00
Kris Johnson
ace0df5c23 AAA UU: Update bans 2025-08-11 18:18:38 -06:00
Kris Johnson
c1e292bf2a AAA Doubles: Update banlist 2025-08-11 18:16:54 -06:00
Karthik99999
f1055d9c1c Spotlights: Fix missing comma in source
I'm bad
2025-08-11 18:48:06 -04:00
Karthik99999
2ceb8375b6 Spotlights: Remove image dimensions from source 2025-08-11 18:42:34 -04:00
Kris Johnson
4980b7c36c AAA Doubles: Fix banlist 2025-08-11 16:29:54 -06:00
Kris Johnson
04454f58ac AAA: Fix validation on Arceus/Silvally formes 2025-08-11 16:29:00 -06:00
Mia
fdffa2abdd Rooms: Prevent expiry of Bo3 parent rooms
Apparently some games last long enough that the parent rooms will expire due to the 15 minute limitation, terminating the child games as well. So we're just going to prevent those from expiring while child games exist. If they're truly inactive, they'll get hit once the child games expire.
2025-08-11 16:57:07 -05:00
Mia
d1efa30cf4 Fix TeamValidatorAsync global
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-08-11 15:31:42 -05:00
André Bastos Dias
73bf84e9b4
Fix OHKO moves in Gen 3 (#11355)
* Fix OHKO moves in Gen 3

* Fix lint
2025-08-11 14:16:09 -06:00
André Bastos Dias
0d9a9f3ef8
Fix Recycle in Gens 3-4 (#11348)
* Fix Recycle in Gens 3-4

* Revert refactor

* Add Recycle as a sourceEffect
2025-08-11 14:14:15 -06:00
Kris Johnson
b106dde6c0 Fix build 2025-08-11 14:12:34 -06:00
Kris Johnson
5e2fb9b0a0 ADV OU: Add Accuracy Trap Clause 2025-08-11 14:11:00 -06:00
Emikatana
2e977534d4
ChatBats: Balance update, new mons, and bugfixes (#11358)
* adding new mons

* adding new mons

* adding new moves

* Fixing ability name

* adding new mons

* adding new mons

* implementing Frostbite

* issue

* Burn Out easter egg

* adding eeveelution ability

* test hardcodes

* fixes

* ehhh not worth the effort

* fixing Eeveelution

* im confused

* eh reverting this stuff

* ok ok

* hmm

* fixing this

* fixing eeveelution

* bugtesting fg

* fck i typod

* burnout

* fixes

* removing Eeveelution

* fixing abilities

* fixing ability

* fixing eeveelution stuff

* fixing freezing glare

* adding conditions file

* fixing  Vaporeon

* sigh

* fixing

* fixing vaporeon

* lint

* testing freezing glare fix

* fixing frostbite

* Freezing Glare tests + animations

* adding animations for eevee moves

* fixing Freezing Glare

* fixing flip flop and hydroelectric dam

* updating test hardcodes

* fixing flip flop message

* level and set changes

* Araquanid move incompatibility + Iron Crown item fix

* lint

* lint

* removing old comments

* fixing Dugtrio set

* fixing Call descriptions

* fixing crash

* nvm

* Call abilities now do not inflict damage, instead of doing no damage

* couple more slight buffs

* removing contact from Icicle Storm

* Update data/mods/chatbats/abilities.ts

Co-authored-by: André Bastos Dias <80102738+andrebastosdias@users.noreply.github.com>

* Update data/mods/chatbats/abilities.ts

Co-authored-by: André Bastos Dias <80102738+andrebastosdias@users.noreply.github.com>

* Kris suggestion

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

* Apply suggestions from code review by Kris

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

* Update data/mods/chatbats/pokedex.ts

---------

Co-authored-by: André Bastos Dias <80102738+andrebastosdias@users.noreply.github.com>
Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-08-11 13:55:13 -06:00
Kris Johnson
9d85f6e687 Fix build 2025-08-11 13:54:16 -06:00
André Bastos Dias
ee5c3cee62
National Dex BH: Ban Orichalcum Pulse, Imprison, and Sleep Talk (#11359)
https://www.smogon.com/forums/threads/national-dex-balanced-hackmons.3711099/page-13#post-10666658
2025-08-11 13:45:27 -06:00
Kris Johnson
928ed14f07 Formats: Add temporary formats for team tournaments 2025-08-11 13:44:53 -06:00
Lucas
7e6cea3605
Mafia: Add Search Capability (#10682)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-08-10 13:52:03 -04:00
HoeenHero
c7c2f81ab2 PU: Ban Duraludon
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-08-10 07:42:30 -04:00
Karthik99999
dbdb492557 Fix forme tier inheritance
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-08-09 12:45:16 -04:00
Karthik99999
799d2e1f45 Add Shiny Wo-Chien event
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-08-07 20:32:09 -04:00
HiZo
fcdefab367
Inheritance: Fix DLC2 Paradox Pokemon validation (#11343)
* Inheritance: Fix DLC2 Paradox validation

* just do this instead

* Update config/formats.ts

* Update config/formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-08-07 17:56:10 -06:00
Waleed Hassan
ea3a0579bc
PW replay should persist through roomid changes (#11342) 2025-08-07 16:51:04 -07:00
Lucas
ccd9b5cae7
Update ChatBats winrates tracking (#11338)
* Update ChatBats winrates tracking

Set ChatBats to have no minimum ELO to start tracking winrates

* Update winrates.tsx

* Update winrates.tsx
2025-08-07 16:13:29 -06:00
demir
2b834af990
fix scizor mega oopsie (#11341) 2025-08-07 16:11:54 -06:00
Slayer95
b5d398e6d7
Fix info leak on side-specific battle.hint API (#11307)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-08-07 07:10:54 -07:00
Slayer95
018ea4abef
Support running PS in a single process again (#11331)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-08-07 00:29:18 -07:00
Waleed Hassan
f891287bac
/savereplay: Stop re-generating passwords (#11328)
The same password is now used across all `/savereplay`s in a battle so
replay links now don't get broken just because someone saved the replay
after you.
2025-08-06 20:19:08 -07:00
HoeenHero
7f1c827c28 RU: Ban Salamence
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-08-06 14:16:33 -04:00
Emikatana
21495a92f1
Add new Pet Mods Leader's Choice (ChatBats) and Remove Previous Leader's Choice (#11309)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* adding ChatBats

* ChatBats abilities

* adding Format data for ChatBats

* items for ChatBats

* moves for ChatBats

* chatBats pokedex

* chatbats learnsets

* Delete data/mods/ccapm2024 directory

* ChatBats random sets

* ChatBats teams.ts

* snow -> snowscape

* fix

* updating PRNG code

* fixing outdated prng code

* fixing more outdated PRNG code

* fixing more outdated code

* (hopefully) fixing error messages

* level fixes

* fixing errors for real

* fix??

* fuck this im manually doing. forme change

* fix

* im an idiot

* fix ???

* fixing setAbility not properly overriding cantsuppress abilities

* fixing Koraidon not having proper max HP

* oop i bad

* still dumb somehow

* fix????

* fixing duplicate message

* nvm

* fixing message errors

* wording change

* updating link

* wording update part 2

* removing testing hardcodes

* +Magneton

* +magneton

* +Magneton

* +Magnet Bomb changes

* +Magneton

* +Magneton

* animation test

* adding test hardcodes

* fixing magneton getting weird sets

* fixing Order Up breaking when used by Mew + Magnet Bomb fix

* more tests

* fixing Biogenesis to properly apply mew's base types

* fixing Mew again

* fixing Biogenesis for real

* removing test hardcodes

* removing debug message I accidentally left in

* enforcing Salamence to test BSC

* im badly

* Testing done, reverting changes

* adding description for Magnet Bomb

* Add Chatbats to rwr tracking

* Fix linting issues

* fixing lint issues

* fixing lint issues

* fixing lint issues

* suggested change from review

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

* suggested change from review

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

* suggested change from review

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

* suggested change from review

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

* suggested change from review

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

* suggested change from review

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

* suggested change from review

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

* suggested change from review

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

* suggested change from review

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

* suggested change from review

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

* suggested change from review

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

* suggested change from review

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

* suggested change from review

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

* suggested change from review

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

* suggested change from review

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

* fixing mistake

* making Thunder Kick a seperate move

* adding Zarel's suggestion

Co-authored-by: Guangcong Luo <guangcongluo@gmail.com>

* fixing lint issues

* fixing lint issues

* fixing lint issues

* now??

* i hate this

* why does it care about how many indentations are in front of comments

* add hail mary (Delibird ability)

* add delibir

* Add Delibird

* add Delibird

* add Delibird

* Add Delibird

* ok so I'm an idiot

* Update config/formats.ts

* Apply suggestions from code review

* fixing a problem

* fix

* fixing errors

* fix

* fix

* fixing most of the errors

* fix

* apparently this file is not needed?

* fixing thunderkick not working

* fixing all the errors

* fixes

* fixing errors

* fix

* fixing lint issues

* fixing

* updating teambuilder

* ok

* final fixes

* ok ok ok

* fuck this stupid bss factory shit

* i hate

* ughhh

* plsss

* deleting all the BSS factory code as it's not needed and keeps throwing errors

* finishing

* Cleaning up teams.ts

* oop

* fixing

* fixes

* fix lint

* adding Data Preview to ChatBats

* Update teams.ts

* Update data/random-battles/chatbats/teams.ts

* Update config/formats.ts

* Update data/random-battles/chatbats/teams.ts

* Update data/random-battles/chatbats/teams.ts

* Update data/random-battles/chatbats/teams.ts

* Update config/formats.ts

* Update config/formats.ts

* Apply suggestions from code review

* Apply suggestions from code review

* oops

* Update moves.ts

* Apply suggestions from code review

---------

Co-authored-by: Lucas <33839844+Lucas-Meijer@users.noreply.github.com>
Co-authored-by: ORH <emi@ORHs-MacBook-Air.local>
Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
Co-authored-by: Guangcong Luo <guangcongluo@gmail.com>
2025-08-06 01:05:03 -06:00
André Bastos Dias
49676c06f7
35 Pokes: Ban Toxapex and unban Scizor (#11333)
https://www.smogon.com/forums/threads/35-pokes-august-2025.3749375/page-8#post-10660401
2025-08-05 23:55:29 -06:00
Kris Johnson
2f03ce912d /dt: Move crit rate next to weight 2025-08-05 23:55:04 -06:00
JCLH-ETS
2586a8f39b
/dt: Show crit rates for Pokemon in Gen 1 (#11336)
* Changed /dt1 command to show gen 1 Pokemon crit rates

* Fixed code style to be lint-approved

---------

Co-authored-by: Jean-Christophe <legerhe@gmail.com>
2025-08-05 23:51:24 -06:00
Guangcong Luo
f770b255f3 Database: Revert syntax for multiline queries
As explicitly documented in `CONTRIBUTING.md`, we are against multiline
template strings. While I see the advantages in readability for the
multiline approach, I'd rather not send extraneous whitespace to the
database.
2025-08-05 22:11:43 -07:00
Mia
4a8341586a Database: Fix PG syntax error in update, remove unnecessary set method
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-08-05 16:38:28 -05:00
Mia
932350d503 Database: Remove more invalid limit statements
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-08-04 22:35:49 -05:00
Mia
a341d3c566 Database: Remove LIMIT clauses from primary key mutating methods
PG doesn't support LIMIT in these, and they don't need it anyway since primary keys should be unique.
2025-08-04 22:16:35 -05:00
Mia
d32ad3dc98 Teams: Insert dates properly after migration
Numbers don't get validated right ffor dates, here. Only ISO strings and __maybe__ date objects? Definitely ISO strings, though
2025-08-04 22:03:29 -05:00
Mia
70f9725113 Seasons: Remove logging for failed ladder requests 2025-08-04 22:00:29 -05:00
Mia
18cdce9803 Fix merge errors 2025-08-04 21:55:33 -05:00
livid washed
db07049c6c
Advertise Ladder Achievements Project for the Randomized Spotlight (#11332)
* Add Ladder Achievements Project banner for Randomized Spotlight

* Link to randbats room

* Update config/formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-08-04 20:53:35 -06:00
Guangcong Luo
31a4289cc6
Refactor Teams plugin to use lib/database (#11109)
* Refactor Teams.save

Fixes a bug where passwords were changed every time a team was updated.

* Refactor Teams to use lib/database

* Add unit tests

(This found a bug which has also been fixed)

* Test more things

---------

Co-authored-by: Mia <49593536+mia-pi-git@users.noreply.github.com>
2025-08-04 21:51:42 -05:00
André Bastos Dias
f753dbfdf0
Refactor stat calculation (#11321)
* Refactor stat calculation

* Simplify conditions

* Preserve comments

* Fix Nature Swap
2025-08-04 20:50:49 -06:00
dot-Comfey
15c2716034
Update help ticket page for lost password (#11275)
* Update help ticket page for lost password

* Update server/chat-plugins/helptickets.ts

Co-authored-by: Mia <49593536+mia-pi-git@users.noreply.github.com>

---------

Co-authored-by: Mia <49593536+mia-pi-git@users.noreply.github.com>
2025-08-04 21:49:09 -05:00
André Bastos Dias
3a82310b30
National Dex RU: Ban Archaludon (#11322) 2025-08-04 20:48:38 -06:00
André Bastos Dias
e473be87d1
Refactor Let's Go Normal Rules (#11324)
* Allow AVs should take happiness into account

* Default happiness is already set in pokemon.ts

* Default happiness in the validator

natureModify only receives the set, not the actual Pokemon :/

* Implement Let's Go Normal Rules

* Fixes

* Remove EV limit

* Remove condition

* Add EV Limit = 0

Avoid "Pokemon has exactly 0 EVs - did you forget to EV it?"

* Final fix

* Happiness is fixed to 70

* Revert changes

* Rename Let's Go to LGPE

* Re-add comment
2025-08-04 20:48:27 -06:00
Mia
7b8acfeadb Add server version to /version
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-08-04 15:55:28 -05:00
Mia
3b5e0b558b Ladder tracker: Allow viewing leaderboard without broadcasting 2025-08-04 15:02:03 -05:00
Mia
d51d959669 Ladder tours: Stop logging failed requests 2025-08-04 14:07:41 -05:00
André Bastos Dias
5eee238838
Fix Transform and Mimic PP in Gen 1 (#11323)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-08-03 18:16:20 -07:00
André Bastos Dias
9ae55bad0e
National Dex UU: Ban Tyranitar-Mega (#11325)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-08-03 13:57:22 -06:00
Mia
bd0d0ebedb Teams: Trim arguments on save
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-08-02 00:36:26 -05:00
Mia
5fafd91d24 Teams: Report back blocked names to users 2025-08-02 00:30:57 -05:00
Guangcong Luo
8d75112e4a
Revert #11314 (Test supported Node versions)
I also added a really long comment so people know why.
2025-08-01 21:28:33 -07:00
adrivrie
1931b23006
Random Battles: July 2025 balance patch (#11320)
Some checks are pending
Node.js CI / build (20.x) (push) Waiting to run
Node.js CI / build (22.x) (push) Waiting to run
Node.js CI / build (24.x) (push) Waiting to run
* Random Battles: July 2025 balance patch

* lower babyrands elo floor for winrate gathering

* grammar fix
2025-08-01 09:58:55 -06:00
Yoshiblaze
936f9e4680
Add August Pet Mod of the Month (#11303)
Some checks are pending
Node.js CI / build (20.x) (push) Waiting to run
Node.js CI / build (22.x) (push) Waiting to run
Node.js CI / build (24.x) (push) Waiting to run
* Change Scream Tail's ability

* Balls Random Battle: Initial Commit

* Fix errors

* fix 1 more error

* Team Generator Temp Fix + Add Broadcast

* actually add the broadcast message

* Add new Virus sprite

* Add new Virus sprite for real this time
2025-08-01 07:52:34 -06:00
ACakeWearingAHat
525d72e6fe
Randomized format set updates (#11311)
* Randomized format set updates

* Remove punches from the other Metagross set as well

---------

Co-authored-by: livid-washed <115855253+livid-washed@users.noreply.github.com>
2025-08-01 07:51:31 -06:00
demir
6c053abea9
35 Pokes: Update list of allowed Pokemon for August 2025 (#11317) 2025-08-01 07:48:54 -06:00
Kris Johnson
9873c3f32e Add August 2025 rotational formats 2025-08-01 07:47:29 -06:00
Kris Johnson
d24a41bcca Add No Freeze Mod
Requested by goldmason for use in old generation custom formats
2025-08-01 07:39:03 -06:00
Leonard Craft III
01286250cb
VGC/BSS: Add Regulation J and re-add H (#11318) 2025-08-01 06:46:04 -05:00
Mia
8cc6743a47 Teams: Do not redirect to a page when upload fails
Some checks are pending
Node.js CI / build (20.x) (push) Waiting to run
Node.js CI / build (22.x) (push) Waiting to run
Node.js CI / build (24.x) (push) Waiting to run
2025-07-31 18:56:48 -05:00
Sergio Garcia
03e1fb6dff
Test supported Node versions (#11314)
Some checks are pending
Node.js CI / build (20.x) (push) Waiting to run
Node.js CI / build (22.x) (push) Waiting to run
Node.js CI / build (24.x) (push) Waiting to run
* Fix typo

* Remove unnessecary file

* Test supported Node versions

---------

Co-authored-by: Mia <49593536+mia-pi-git@users.noreply.github.com>
Co-authored-by: HoeenHero <HoeenCoder@users.noreply.github.com>
2025-07-31 10:12:49 -05:00
Mia
503030c0d8 Fix typo 2025-07-31 10:11:55 -05:00
Sergio Garcia
005d98993f
Use URL API (#11316)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Fix typo

* Remove unnessecary file

* Use URL API

Clears this warning

```
(node:44968) [DEP0169] DeprecationWarning: `url.parse()`
  behavior is not standardized and prone to errors that have
  security implications. Use the WHATWG URL API instead. CVEs are
  not issued for `url.parse()` vulnerabilities.
```

---------

Co-authored-by: Mia <49593536+mia-pi-git@users.noreply.github.com>
Co-authored-by: HoeenHero <HoeenCoder@users.noreply.github.com>
2025-07-31 10:04:20 -05:00
Mia
c135ecdce8 Ladder tours: Don't broadcast updates on failure 2025-07-31 09:58:08 -05:00
Mia
20e5727112 Ladder tours: Suppress JSON errors
This happens when the PHP site throws errors. Which happens too much because PHP sucks ass.
2025-07-30 23:50:40 -05:00
Karthik99999
a718a33227 Fix Ogerpon/Terapagos Tera Types in Challenge Cup 2025-07-30 22:50:09 -04:00
Aurastic
3f0c9fe991
Don't consider user active on '/cmd rooms' (#11286)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-07-30 04:35:18 -07:00
André Bastos Dias
43bb532f48
National Dex AAA: Ban Ceruledge (#11301)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* National Dex AAA: Ban Ceruledge

* Update formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-07-29 18:25:22 -06:00
André Bastos Dias
909c8c51f1
Fix Healing Wish and Lunar Dance switch in priority (#11146) 2025-07-29 17:48:23 -06:00
André Bastos Dias
f24d648c8a
Fix accuracy of Gen 1 trapping moves (#11305)
* Fix accuracy of Gen 1 trapping moves

* Fix tests

* Update data/mods/gen1/scripts.ts

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

* Update data/mods/gen1stadium/scripts.ts

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

* Update data/mods/gen3/scripts.ts

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-07-29 17:47:49 -06:00
Kris Johnson
d757e52be0
Mix and Mega: Restrict Ceruledge 2025-07-29 17:47:02 -06:00
André Bastos Dias
aa2f2a306f
Add Celebrate Flabébé event (#11306)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-07-28 19:16:47 -04:00
André Bastos Dias
e27ae66ec6
Fix Burn Up thawing user when user does not have Fire type (#11304) 2025-07-28 18:56:51 -04:00
André Bastos Dias
7f58261221
ZU: Ban Porygon2 (#11300)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-07-27 20:04:24 -04:00
InkyDarkBird
cd0b071a3e
Full Potential: Update bans (#11297)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
* Full Potential: Update bans 4

* Fix misspelling
2025-07-25 22:53:58 -06:00
Dieter Reinert
e716ef1aba
Info: Prevent crash in makecustomchallenge when user parameter is missing (#11296)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-07-24 09:00:40 -07:00
Mia
4cd2f90abf Teams: Increase max team size to 50 sets
Some checks failed
Node.js CI / build (18.x) (push) Waiting to run
Publish to npm / test (push) Has been cancelled
Publish to npm / get-version (push) Has been cancelled
Publish to npm / npm-publish (push) Has been cancelled
2025-07-24 01:10:25 -05:00
Guangcong Luo
455546c69f Remove sucrase dependency 2025-07-23 22:13:33 -07:00
Mia
2467596832 Teams: Censor nicknames on display, not upload 2025-07-24 00:06:03 -05:00
skymin3
8691ace824
Update /help othermetas (#11182)
Approved Forum suggestion: https://www.smogon.com/forums/threads/make-the-om-help-command-more-helpful.3766005/

the /om is a bit weird, it's just a link to the forums not a link to direct information like /om all does, so I changed the wording there. !om is also changed since it's not descriptive.
2025-07-23 23:48:29 -05:00
Guangcong Luo
6e2ca2b3ff Update some dependencies 2025-07-23 21:36:32 -07:00
Guangcong Luo
7a9e535e35
Vendor node-static (#11295)
Also includes a decent amount of refactoring to bring it in line with Showdown code standards.

---------

Co-authored-by: Slayer95 <ivojulca@hotmail.com>
2025-07-23 21:19:55 -07:00
Mia
1487d52db0 Teams: Make shareable link clickable 2025-07-23 23:10:36 -05:00
André Bastos Dias
05de0574b7
Add test for Gen 3 berries (#11141)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-07-23 03:29:04 -07:00
André Bastos Dias
ac3c06daf0
Approximate Rebound to Magic Bounce/Coat implementation (#11290) 2025-07-23 03:13:47 -07:00
Mia
ef56c668d2 Suspects: Fall back on existing suspect URL in edits if need be
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-07-22 12:51:49 -05:00
Kris Johnson
d97b176082 Revert "Simplify the implementation of locked moves (#11256)"
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
This reverts commit 4d634394f5.
2025-07-22 03:38:29 -06:00
André Bastos Dias
4d634394f5
Simplify the implementation of locked moves (#11256) 2025-07-22 02:14:13 -07:00
André Bastos Dias
fd21559ba8
Refactor Gen 1 partial trapping (#11189) 2025-07-22 02:12:20 -07:00
André Bastos Dias
f74586f765
Implement Imprison disabling logic using Test Fight (#11208) 2025-07-22 02:09:45 -07:00
Mia
99af09ba7c Chat: Ensure absolute plugin files are always loaded
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
Accounting for loading outside of the normal dir
2025-07-21 17:28:19 -05:00
Mia
0899c4b7b3 Chat: Annotate commands with plugin names for categorization 2025-07-21 17:15:40 -05:00
André Bastos Dias
46d77d4b06
35 Pokes: Ban Rillaboom and unban Sandaconda (#11287)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-07-21 11:01:36 -06:00
André Bastos Dias
48316b5864
GSC ZU: Ban Mantine (#11288) 2025-07-21 11:01:23 -06:00
Runo
33673d88bc
NatDex UU: Ban Iron Crown (#11289)
https://www.smogon.com/forums/threads/sv-national-dex-uu-stage-8-2-king-without-a-crown.3768238/
2025-07-21 11:01:10 -06:00
Kris Johnson
b019954f68
PU: Unban Duraludon for suspect 2025-07-21 10:29:24 -06:00
Mia
9ca1b0c35f Chatlog: Rewrite argument protocol for searches
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-07-19 00:28:33 -05:00
Mia
e9fd0b76dd Chatlog: Render search arguments in display 2025-07-19 00:12:40 -05:00
Mia
3823ec2471 Fix typo
WHY DID THIS NOT GET STAGED I SPECIFICALLY CLICKED STAGE
2025-07-19 00:10:07 -05:00
Mia
546dfd07ff Searchlog: Standardize handling of search parameters
Makes this easier to extend for the future, too.
2025-07-19 00:08:20 -05:00
Mia
4d314e3f5e Ladder trackers: Suppress user-facing errors on restoration
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-07-18 14:28:08 -05:00
Mia
67ca3b04eb Fix searchlog padding 2025-07-18 13:09:47 -05:00
Mia
ad3cedc8ad Actually guard dates via regex testing 2025-07-18 13:00:40 -05:00
Mia
0c4298d29d Fix typo 2025-07-18 12:58:48 -05:00
Mia
c4a6e8de1f Searchlog: Fix next/prev month buttons 2025-07-18 12:58:02 -05:00
Mia
4012a4b532 Searchlog: Add prev/next month buttons, fix date handling for more ambiguous dates 2025-07-18 12:53:34 -05:00
Mia
2b7e1d48b5 Searchlog: Allow searching only a username
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-07-17 23:26:21 -05:00
Mia
4d4c541a57 Searchlog: Adjust header to be more descriptive 2025-07-17 23:14:48 -05:00
Mia
20072695c1 Fix typo 2025-07-17 23:13:41 -05:00
Mia
fa5295db23 Searchlog: Use plainto_tsquery to sanitize syntax 2025-07-17 23:12:11 -05:00
Mia
88726667a1 Searchlog: Fix text rendering 2025-07-17 23:08:35 -05:00
Mia
e81d70440e Chatlog: Fully deprecate support for 'all' dates 2025-07-17 22:58:02 -05:00
Mia
5f31e2efe3 Chatlog: Restore /searchlog 2025-07-17 22:54:09 -05:00
Yoshiblaze
29f0455878
Change Scream Tail's ability (#11283)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-07-17 15:28:22 -06:00
InkyDarkBird
450528489c
Full Potential and Battlefields Bans (#11284)
* Full Potential and Battlefields Bans 3

* Full Potential ban fix

* Update config/formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-07-17 15:27:57 -06:00
Slayer95
19d279c9b5
CLI: Update to use util.parseArgs (#11245)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
---------

Co-authored-by: Guangcong Luo <guangcongluo@gmail.com>
2025-07-17 05:06:26 -07:00
Sergio
38b0d9475e
Minor changes to the help boxes of /ds and /ms (#11094)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
* Minor changes to the help boxes of /ds and /ms

Removed parameters that do nothing (instruct, mimic), changed ssb examples (they were obsolete), added a couple more things. Would love to make the wall of mods you can use with both ds and ms smaller, since a lot of those don't actually change their behaviour, like randomroulette, but I'm not sure how to approach it. A hardcoded list of mods that change things is an option.

* Added "restricted" as a parameter
2025-07-15 21:11:15 -06:00
André Bastos Dias
324966b811
CAP: Prevent Polar Flare from thawing targets (#11273) 2025-07-15 21:39:19 -04:00
André Bastos Dias
53fe99a6ff
Fix interaction between Max Weather Ball and -ate Abilities (#11138)
Some checks failed
Node.js CI / build (18.x) (push) Waiting to run
Publish to npm / test (push) Has been cancelled
Publish to npm / get-version (push) Has been cancelled
Publish to npm / npm-publish (push) Has been cancelled
* Fix interaction between Max Weather Ball and -ate Abilities

* Apply to the other moves

* Revert Normalize

* Revert "Revert Normalize"

This reverts commit e6f670daa8.
2025-07-15 11:36:07 -06:00
shrianshChari
6cf20d2101
Gen 1: Ban all partial trapping moves from UU (#11277)
* Gen 1: Ban all partial trapping moves from UU

https://www.smogon.com/forums/threads/rby-uu-hub.3647713/page-10#post-10630807

* bruh
2025-07-15 11:33:57 -06:00
André Bastos Dias
c12111b5a8
STABmons: Ban Meloetta (#11279) 2025-07-15 11:31:23 -06:00
André Bastos Dias
beed07db0b
[Gen 8] National Dex Doubles: Update bans (#11280)
* [Gen 8] National Dex Doubles: Ban Charizard, Regieleki and Weakness Policy

* Update formats.ts
2025-07-15 11:30:44 -06:00
André Bastos Dias
b11d29db70
National Dex LC: Update bans (#11281) 2025-07-15 11:23:08 -06:00
André Bastos Dias
63c36a1dca
Doubles LC: Ban Stantler (#11278)
* Doubles LC: Ban Stantler

* Extend across multiple lines
2025-07-15 11:22:46 -06:00
ACakeWearingAHat
eb6d580a90
CAP Random Battle: Add Ramnarok (#11276)
this thing more broken than cawm y'all
2025-07-14 16:23:59 -06:00
André Bastos Dias
85d60cefe6
Make Chromera a Sub-Legendary (#11274) 2025-07-14 14:08:37 -07:00
hammer798
fddbf8adb5
Fix item filters duplicating search terms (#11271) 2025-07-14 14:03:08 -07:00
Slayer95
7d8f01f849
Remove build on postinstall (#11244)
- Errors in the node build script will no longer cause a false perception
that dependencies cannot be installed.
- Simplifies 1cea3f39cb
2025-07-14 13:34:46 -07:00
Slayer95
0b6c1dbeec
Make some dependencies optional: probe-image-size, source-map-support (#11247) 2025-07-14 03:01:41 -07:00
André Bastos Dias
3b7b1d2864
Don't update the timer when an updated request is sent (#11251)
* Don't add time if there is a request update

* Ups

* Change prevRequest to updatedRequest

* Fix tests

* Refactor

* Fix tests
2025-07-13 15:38:58 -06:00
Zachary Perlmutter
14f8677565
National Dex Ubers UU: Implement Tier shifts (#11268)
* National Dex Ubers UU: Implement Tier Shifts

https://www.smogon.com/forums/threads/national-dex-ubers-uu-shifts-84.3742166/post-10610952

* Update formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-07-13 12:06:10 -06:00
Marty-D
b3fd853052
Mark CAP 36 alternate form as Illegal 2025-07-13 12:39:57 -04:00
Spammernoob69
613613b6b6
Implement CAP 36 (#11270) 2025-07-13 10:49:17 -04:00
Slayer95
07b90b13cf
Refactor Team Preview to avoid code duplication (#11237)
DRY is particularly relevant because of the hardcodes,
which are unlikely to be kept in sync in OM code.
2025-07-12 20:57:05 -06:00
André Bastos Dias
3b6af0dd6d
Re-number CAP moves and abilities (#11257) 2025-07-12 15:17:35 -06:00
shrianshChari
fccf112a61
BDSP: Move Chatot and Drifblim to PUBL (#11267)
https://www.smogon.com/forums/threads/bdsp-pu-tier-shifts-post-79.3700009/page-4#post-10626194
2025-07-12 15:16:31 -06:00
Runo
e589a90ed5
NatDex AAA: Ban Good as Gold and Intrepid Sword (#11265)
https://www.smogon.com/forums/threads/national-dex-almost-any-ability.3726510/post-10612994
2025-07-12 14:36:24 -05:00
Kris Johnson
0ad85d4127
35 Pokes: Replace Gliscor with Feraligatr
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
https://www.smogon.com/forums/threads/35-pokes-july-2025.3749375/page-8#post-10624305
2025-07-11 01:35:44 -06:00
Slayer95
2b32c8f57c
Send teampreview request after Tera Type info (#11238)
Refs #8546
2025-07-11 01:33:12 -06:00
André Bastos Dias
9bcca73a33
Modify HP after forme regression (#11261)
* Modify HP after forme regression

* Clip negative HP

* Change method name

* Don't reveal illusion

Should be redundant

* Move message timing

* Fix dynamax

* Clip HP for possible OMs

* Check using baseMaxHp

* Conditions.........

* Use ternary operation

* Fix comment
2025-07-11 01:32:43 -06:00
demir
2857a7b5ee
Add test for 35 Pokes banlist (#11246)
* Add test for 35 Pokes banlist

* Return if no 35 Pokes or no unbanlist

* Move Sneasel-Hisui to ND RU

* Update data/formats-data.ts

* Changed logic to use isBannedSpecies instead of legalTeam

* Simplify to comparing the accepted length

* Bring back `allowed`, use otherFormes

* Moved .length

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-07-11 01:30:15 -06:00
hammer798
014c77353e
RBY: Drop Slowbro from OU to UU, Drop Victreebel from OU to NU (#11260) 2025-07-11 01:28:07 -06:00
Chessking345
0bd2f3e778
Godly Gift: Evasion Abilities Clause (#11255) 2025-07-11 01:27:45 -06:00
InkyDarkBird
481c3d14b7
Full Potential: Update bans (#11258) 2025-07-11 01:10:41 -06:00
kabilapok
ff8cc48ba2
SV NFE: Ban Vigoroth (#11259)
https://www.smogon.com/forums/threads/sv-nfe-metagame-discussion-vigoroth-ban-post-146.3710638/post-10618590
2025-07-11 01:10:08 -06:00
Yoshiblaze
eb550ea05c
VaporeMons Random Battle: Minor changes and bugfixes (#11264)
* Fix Sitrus Berry HP Numbers

* Fix Software Crash's type picking

* Split Froslass' set into two
2025-07-11 01:09:44 -06:00
Mia
3bab394e1b SSB: Remove Lily
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-07-07 22:09:34 -05:00
Kris Johnson
6fc4ef4c45
SSB: Fix bugs with set generation
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-07-07 16:38:26 -06:00
missshowdown
2fffb4a3ca
GSC ZU: Fix tiers for low-rank NFEs (#11253)
https://www.smogon.com/forums/threads/zu-old-gens-hub-oras-bans-379.3646944/post-10502838
Both Diglett and Slowpoke are D rank on the most recent ZU viability list, the same as other Pokemon tiered as LC like Smoochum, Snubbull, Mankey, etc, so they should be tiered the same.
2025-07-07 16:29:00 -06:00
Kris Johnson
f92b63cc1a Fix typo 2025-07-07 16:26:52 -06:00
Mia
07a2820cf2 Punishments: Disallow Tor IPs from connecting 2025-07-07 12:18:39 -05:00
Kris Johnson
9ba1623c03
Rename [Gen 8] Galar Dex Draft
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-07-06 11:37:35 -06:00
André Bastos Dias
f8f08443ac
Remove obsolete inheritance (#11249) 2025-07-06 11:18:38 -06:00
Kris Johnson
4edd58a832 Fix Baton Pass Trap Clause validation 2025-07-06 11:15:18 -06:00
InkyDarkBird
377838ccc0
Battlefields: Update bans (#11250) 2025-07-06 10:47:33 -06:00
Kris Johnson
f4380feffe
RU: Ban Serperior
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-07-05 14:04:00 -06:00
Sergio
2ce41f17f3
Fix typos in Alola and Unova Dex rulesets (#11248)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-07-05 08:28:12 -05:00
Kris Johnson
baf2ea69ac
NatDex: Fix Sneasel-Hisui's tier 2025-07-05 01:47:43 -06:00
Slayer95
c49644c295
Deprecate "Custom" group bans (#11242)
* Doc: Remove Staff Bros moves mention in "Custom" group bans

Fixes #6819

* Deprecate "Custom" group ban
2025-07-05 01:46:07 -06:00
livid washed
696811790c
Add July 2025 Randomized Format Spotlight (#11239)
* Add July 2025 Randomized Format Spotlight

* fix desc

* Add Auto choose mod
2025-07-05 01:33:34 -06:00
Slayer95
88d53617d6
RoomBattleTimer: Reset turn seconds on wait requests (#11240)
Previously, if a player timed out under VGC timer and knocked their opponent,
they would be treated as timing out their following 'wait' request
2025-07-05 01:32:10 -06:00
InkyDarkBird
a097a4265a
Full Potential: Update bans (#11243) 2025-07-05 00:36:47 -06:00
missshowdown
a8794d47fb
Fix ZU NFEs (#11241)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
* Fix ZU NFEs

Hisuian Sneasel had >4.52% average usage in ZU in the last three months just like Dipplin, Hattrem, Magneton, and Primeape. Porygon2 also had >4.52% average usage in ZU and was ZU before it moved to NU, so it moves back to ZU. 

Hisuian Sneasel stats
https://www.smogon.com/stats/2025-04/gen9zu-1630.txt - 5.14%
https://www.smogon.com/stats/2025-05/gen9zu-1630.txt - 8.72%
https://www.smogon.com/stats/2025-06/gen9zu-1630.txt - 8.57%
Average: 7.48%

Porygon2 stats
https://www.smogon.com/stats/2025-01/gen9zu-1630.txt - 10.03%
https://www.smogon.com/stats/2025-02/gen9zu-1630.txt - 9.35%
https://www.smogon.com/stats/2025-03/gen9zu-1630.txt - 13.80%
Average: 11.15%

* Update data/formats-data.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-07-02 12:49:52 -06:00
Kris Johnson
6733e2fc10
NatDex: Fix Mega Slowbro's tier
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-07-02 01:57:44 -06:00
InkyDarkBird
17e16863aa
Battlefields: Update bans (#11236)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-07-01 17:33:34 -06:00
shrianshChari
def62ad205
NU: Ban Politoed (#11234)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
https://www.smogon.com/forums/threads/np-stage-17-barracuda-politoed-banned-tier-shift.3767218/#post-10610897
2025-07-01 12:18:23 -06:00
shrianshChari
6a416d3cb2
RU: Ban Ogerpon (#11235)
https://www.smogon.com/forums/threads/np-sv-ru-stage-18-kings-queens-july-2025-shifts-ogerpon-quickbanned.3767219/
2025-07-01 12:18:13 -06:00
Marty
99242d57bb Past Gens: Update OU by technicality
https://www.smogon.com/forums/posts/10610694/
2025-07-01 10:43:02 -04:00
André Bastos Dias
6a44ac42b9
Fix Klutz's interaction with Fling (#11203) 2025-07-01 10:13:16 -04:00
urkerab
4e1b6e1d7f
Simplify Battlefields (#11233) 2025-07-01 08:09:59 -06:00
Kris Johnson
5771f65626 Add July 2025 tier shifts 2025-07-01 08:09:12 -06:00
urkerab
862f409e57
SideConditionStart event should target the side with the condition (#11216)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* SideConditionStart event should target the side with the condition

* Use Slayer95's approach

* Delete data/mods/gen9fe/abilities.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-07-01 01:34:17 -06:00
André Bastos Dias
ac19dbb9e5
Move the gender logic to the validator (#11198)
* Move the gender logic to the validator

* Modify test seed

* Modify seed for other test

* Fix for RandBats

* Remove gender enforcement

* Revert "Remove gender enforcement"

This reverts commit c9c66a3725.

* Allow choosing genderless Pokemon

Without this, genders will always default to '' and never to 'N'
2025-07-01 01:26:42 -06:00
ACakeWearingAHat
6397bfddb3
Randomized format set updates (#11232)
* Randomized format set updates

* Update doubles-sets.json

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-07-01 01:25:58 -06:00
Yoshiblaze
92482df250
Add July Pet Mod of the Month (VaporeMons Random Battle) (#11230)
* July PMOTM Initial Commit

* Clean up conditions.ts and items.ts

* Clean up abilities.ts

* Clean up pokedex.ts

* Clean up moves.ts Pt. 1

* just changing shelter (i keep losing track of lines)

* Clean up moves.ts Pt. 3 (lost track of lines again)

* Clean up moves.ts Pt. 4

* Clean up moves.ts Pt. 5

* Final clean up Pt. 1

* Final clean up Pt. 2

* Final clean up Pt. 2.1

* Final clean up Pt. 3

* desert storm fix

* desert storm "fix"

* Add VaporeMons to teams.ts

* Remove gen9fe from formats.ts

* Adding VaporeMons Randbats Sets Pt. 1

* Fix Ditto

* Add Randbats Sets Pt. 2

* Add Randbats Sets Pt. 3

* Shorten Garganacl's line

* Fix Typo

* Add Randbats Sets Pt. 4

* Fix error

* Final Randbats Sets

* Minor bugfixes

* Remove Speed-boosting Natures

* Extremely Minor Fixes

* Fix Vaporemons issues

* Fix style errors

* Fix Death Aura & Fair Fight not ending

* Remove test format and Fusion Evolution

* Give Skarmory Sledgehammer Blow

* Fix Illusion's flags

* Add Illusion Level Mod

---------

Co-authored-by: Meijer,L. (Lucas) <l.meijer6@students.uu.nl>
2025-07-01 01:22:44 -06:00
Karthik Bandagonda
d3d834c91a
Allow Picked Team Size to be used without Team Preview (#11224)
* Add Pick Team rule

* Make Team Preview and Pick Team mutually exclusive

* Automatically apply rule if Picked Team Size exists without preview

* Remove mutually exclusive part

* Move teamsize to start action
2025-07-01 01:20:57 -06:00
adrivrie
bc832df368
Random Battles: June 2025 balance patch (#11229) 2025-07-01 01:17:36 -06:00
dot-Comfey
6533311382
Fix oversight from #11217 (#11228) 2025-07-01 01:17:21 -06:00
demir
c969dcb4e7
35 Pokes: Update list of allowed Pokemon for July 2025 (#11231)
* 35 Pokes: Update list of allowed Pokemon for July 2025

* Missing space
2025-07-01 01:17:01 -06:00
Kris Johnson
3b825333ea RBY PU: Ban Rapidash
https://www.smogon.com/forums/threads/rby-pu-hub.3700527/page-8#post-10610118
2025-07-01 01:16:32 -06:00
Kris Johnson
babf4f6576 Add July 2025 rotational formats 2025-07-01 01:15:44 -06:00
HoeenHero
8bcd2c2960 Teams: Improve error messages
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
Moving the auth at least check later means the locked error message will actually trigger for locked users providing a clearer error message to them.
2025-06-30 12:40:33 -04:00
Leonard Craft III
6e41ce15e3 Add Nickname Clause to Standard Draft
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-06-29 22:42:46 -05:00
dot-Comfey
5a4c785ec4
Fix more button in /modlog (#11217)
* Fix more button in /modlog

* Drivers can use /mls

* Update modlog-viewer.ts
2025-06-29 22:09:06 -05:00
Alex "Mathy
9cd93f2a0c
Permalock plugin: Fix room not updating after notice (#11218) 2025-06-29 22:08:13 -05:00
Mia
c03510f909 Users: Don't remove rangelocks on user merge 2025-06-29 22:06:39 -05:00
Alex "Mathy
687b1c4ae0
/show: Fix unescaped HTML template (#11225) 2025-06-29 15:02:38 -06:00
BoingK
4979f9f91c
Tier Shift: Ban Necrozma-Dusk-Mane (#11220)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
https://www.smogon.com/forums/threads/omotm-tier-shift.3720396/post-10603857
2025-06-29 11:32:15 -06:00
André Bastos Dias
5e65007240
ORAS ZU: Ban Huntail and Light Clay (#11221) 2025-06-29 11:31:47 -06:00
Alex "Mathy
063a19e6c1
Randomized formats: Fix genders (#11227)
* Randomized formats: Fix genders

* Old gens
2025-06-29 11:31:24 -06:00
André Bastos Dias
a512048ae8
Ubers UU: Ban Spectrier (#11226) 2025-06-29 11:31:04 -06:00
André Bastos Dias
fdbe0e3b5b
National Dex UU: Ban Hawlucha (#11202)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-06-28 11:36:29 -04:00
Karthik99999
aab6b728cb /ssb: Fix text formatting issues
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-06-25 19:27:19 -04:00
André Bastos Dias
3b4a2c9bf5
Fix HP bar percentages and colours (#11213) 2025-06-25 14:14:46 -07:00
Karthik99999
f795b5d750 CODEOWNERS: Add Karthik to Auctions
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-06-25 12:27:57 -04:00
Karthik99999
e0ccfa1532 Auctions: Fix draft order display 2025-06-25 12:27:09 -04:00
André Bastos Dias
b598355b66
Gen 3: Fix Magnet Pull not trapping allies (#11207)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-06-24 23:51:48 -04:00
Karthik99999
e982385e54 Show Best of checkbox for random battle formats
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
Requested by Randbats ROs
2025-06-24 20:33:56 -04:00
Eve
20717b7c67
LGPE: Implement OU tier changes (#11219) 2025-06-24 20:22:38 -04:00
André Bastos Dias
dc7294ed6e
Remove unused code (#11215)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
* Remove unused Move#negateSecondary
* Remove unused 'SubDamage' event
* Remove unused Move#pressureTarget
* Partially remove unused Move#spreadModifier
2025-06-22 08:21:19 -07:00
Slayer95
7835b015d9
Explain insecure subdomain in server/README.md (#11212)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
---------

Co-authored-by: Guangcong Luo <guangcongluo@gmail.com>
2025-06-20 16:47:56 -07:00
skymin3
f68b7e94c4
Aliases: Remove Wormadams (#11209) 2025-06-20 06:04:14 -07:00
zianwangs
d6e98c21fb
Fix typos (#11200) 2025-06-19 04:10:12 -07:00
Kris Johnson
36ae30160c Auto Responder: Fix ignore page view for regex terms 2025-06-17 13:36:55 -06:00
Kris Johnson
1c28a150e7 Auto Responder: Fix /ar view keys not escaping regex keys 2025-06-17 13:14:39 -06:00
skymin3
08305c7497
STABmons: Update bans (#11194)
Forum post: https://www.smogon.com/forums/threads/stabmons.3710577/post-10590886
2025-06-16 10:08:29 -06:00
André Bastos Dias
1bbb8ec800
ADV: Move Medicham to OU (#11199) 2025-06-16 10:07:41 -06:00
Guangcong Luo
6903a2e2e7
Document new URL format
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
This doesn't say what the format is, but it's pretty easy to figure
out from the redirect, if you particularly care.
2025-06-15 08:11:10 -07:00
Guangcong Luo
e7b2be606a Fix client redirect
For a long time, connecting to non-localhost servers didn't work without
an HTTPS cert. But it's now once again possible. All you need is an
IP with an open port, and a dream.

Syntax is a little different than before. To go to `1.2.3.4` at port `5000`

- before: `http://1.2.3.4-5000.psim.us`
- after: `http://1-2-3-4--5000.insecure.psim.us`

Supporting multiple dots in the URL is too complicated, unfortunately.

The other way still works: `http://1.2.3.4:5000`

And yes, I would 100% recommend that one.
2025-06-15 07:25:04 -07:00
skymin3
f8a4a61874
/dt: Add new aliases (#11157)
* DT aliases update 

Added:
hydra: Hydrapple
duskroc: Lycanroc-dusk
necro: Necrozma
ultranecro: Necrozma-Ultra
Soulblaze: Clangorous Soulblaze
prank: Prankster
jask: Ninjask
horo: Zoroark-Hisui
horoark: Zoroark-Hisui
pompom: oricorio-pom-pom
sensu: Oricorio-Sensu
baile: Oricorio
pau: Oricorio-Pa'u
maud: Audino-Mega
fog: Defog
imp: Imposter
geezing: Weezing-Galar

Removed
ss: Stoked Sparksufer

* Aliase Remove: SSS + Extreme + Searing + Oricorio

* Few more Aliases
2025-06-14 19:03:20 -06:00
Lucas
4536eee620
/dexsearch: Add support for sorting by (doubles) tier (#11150)
* ds: add tier sorting

* Add support for doubles and natdex tiers

* fix unnecessary nationalSearch passing

---------

Co-authored-by: Meijer,L. (Lucas) <l.meijer6@students.uu.nl>
2025-06-14 19:01:25 -06:00
André Bastos Dias
73a8b3188b
Break Illusion on Tera formes (#11190) 2025-06-14 18:59:23 -06:00
André Bastos Dias
4435fc48b8
Fix Terastallization test (#11195) 2025-06-14 10:45:30 -06:00
Kris Johnson
acf0fb8a2e
Fix build 2025-06-13 22:40:34 -06:00
Mia
c73803efe7 Ladder tours: Expose tracker object for debugging 2025-06-13 22:16:47 -05:00
André Bastos Dias
0b6d2aa399
Fix tests for low‑BP Terastallized moves (#11193)
* Fix tests for Terastallized low‑BP moves

* Fix error messages
2025-06-13 14:46:03 -06:00
motogp-bit
b5304c68b5
Mafia: Fix /mafia resetgame (#11192)
Co-authored-by: HoeenHero <HoeenCoder@users.noreply.github.com>
2025-06-12 11:14:17 -04:00
Lucas
6007bdc0b9
Mafia: Improve host/gameban (#11036)
* Improve host/gameban

- Allow for offline namehostban and namegameban.
- Notify users when they get host and gamebanned.
- Fix hostbans, which did not work at all.
- Fix host and gamebanned users from being able to subhost

* Change aliases and remove gameban unhostbanning.
2025-06-11 22:03:43 -04:00
skymin3
2b027d9d5a
Trademarked: Update bans (#11184)
* Trademarked Update Bans + Unban Regigigas

Banwave post: https://www.smogon.com/forums/threads/trademarked.3714688/post-10583109 

Bans
Annihilape
Hoopa-Unbound
Keldeo
shaymin sky (this makes me sad)
Weavile
Light Clay

Move restrict
Heal Bell

Unban: Regigigas

* Alignment fix
2025-06-11 19:05:56 -06:00
André Bastos Dias
f3c17bcf75
National Dex: Ban Roaring Moon (#11187) 2025-06-11 19:05:24 -06:00
Mia
92f5871309 Ladder tours: Properly force battles public 2025-06-10 17:42:00 -05:00
Mia
5e61465955 Ladder trackers: Adjust help 2025-06-09 19:20:30 -05:00
Lucas
71041ecfe1
Mafia: add maximum role length. (#11064)
Today, a bug was found where using revealas on a long role crashed PS!

I alleviated this by adding a maximum role length (instead of having it be uncapped, as currently people could spam PS using unlimited length roles) and moving the 'infinite loop' check to not be triggered by long roles.


Co-authored-by: Meijer,L. (Lucas) <l.meijer6@students.uu.nl>
2025-06-09 18:47:52 -04:00
Kris Johnson
92ed7a4243 /formathelp: Fix crash 2025-06-09 14:16:53 -06:00
Dieter Reinert
dd96c0de95
Mafia: Fix crash when distributing roles with insufficient roles (#11183) 2025-06-07 09:18:06 -07:00
skymin3
edd2068e23
Add Acupressure to Evasion Moves Clause (#11181)
https://www.smogon.com/forums/threads/include-acupressure-in-evasion-clause.3738246/post-10583328
2025-06-06 16:56:58 -07:00
Mia
48ba18608b Ladder tours: Run notifications at the beginning of games, not end 2025-06-06 11:54:23 -05:00
Dieter Reinert
5c9ccae9a0
Fusion Evolution: Fix Serene Sync crash with onHit effects (#11179)
* Gen9FE: Fix Serene Sync crash with onHit effects

* Feedback

* eslint: trailing space

* eslint

* Update data/mods/gen9fe/abilities.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-06-05 17:43:27 -06:00
cheesetheorange
6522f7987b
Scavengers: Fix scrollbars (#11176) 2025-06-04 19:15:44 -07:00
Mia
9560f87ebd Remove accidentally-committed debug info 2025-06-04 16:04:59 -05:00
Mia
9f8e8acd53 Fix typo 2025-06-04 12:54:47 -05:00
Mia
8b6964f060 Ladder tours: Do not save while loading 2025-06-04 12:52:22 -05:00
Kris Johnson
e26eadfa4c Ladder Tracker: Don't log the IP of the user setting a tracker 2025-06-04 11:36:16 -06:00
Kris Johnson
7f69e2893d Revert "Return the right error on /searchlog (#11174)"
This reverts commit a94972bbd2.
2025-06-04 11:21:49 -06:00
Mia
bde88764cb
Add a plugin to support native ladder tour tracking (#11016) 2025-06-03 23:11:22 -05:00
Sergio Garcia
9a2c4739b0
Improve chatlog error message when disabled (#11173) 2025-06-03 15:22:54 -07:00
Dieter Reinert
561fe5e375
Dex: Update isName signature to match expected inputs (#11172) 2025-06-03 15:22:05 -07:00
Sergio Garcia
a94972bbd2
Return the right error on /searchlog (#11174) 2025-06-03 15:20:28 -07:00
TomOfTomKat
6d1337ad0a
SV OU: Add Evasion Abilities Clause (#11175)
Replaces the manual bans of Snow Cloak and Sand Veil with Evasion Abilities Clause. There is no actual impact on legality, this is a consistency change. This change is approved by star and finch:

starmaster — 10:32 AM
we did literally create it for ou
so idk why that is
it should just have the clause
UT  — 10:35 AM
@Finch do you mind if I submit a pull request to remove Sand Veil + Snow Cloak bans from OU and replace it with Evasion Abilities Clause? This should have absolutely no change on the tier and is a backend consistency thing
Finch — 10:36 AM
@Ruft good with you? Checks out to me
2025-06-03 11:56:41 -06:00
Dieter Reinert
fd1c2f1738
Dex: Prevent isName crash on null/undefined (#11167) 2025-06-02 16:00:40 -07:00
Guangcong Luo
80996b1a3b Allow multiple empty moveslots 2025-06-02 08:43:32 -07:00
Kris Johnson
db6107b462
Implement June 2025 tier shifts 2025-06-02 01:22:27 -06:00
Lucas
de1d24e4eb
OMs: add Bad 'n Boosted data command (#11165)
* Add bnb command

* Update server/chat-plugins/othermetas.ts

---------

Co-authored-by: Meijer,L. (Lucas) <l.meijer6@students.uu.nl>
Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-06-02 01:21:20 -06:00
Dieter Reinert
2815ce3d62
Info commands: Fix crash when using /data with Tier Shift Mod (#11149)
* Info commands: Fix crash when using /data with Tier Shift Mod

Fixes a crash that occurred when using the `/data` command (or its aliases like `/dt`) with a format that includes the "Tier Shift Mod" rule.

### The Bug
When users tried to view Pokémon data in a format with Tier Shift Mod, the command would crash with:
```TS
TypeError: Cannot read properties of undefined (reading 'has')
at Object.onModifySpecies (/home/ps/main/data/rulesets.ts:2260:45)```


### Root Cause
The info command was calling `format.onModifySpecies` with a mock Battle context that was missing the `ruleTable` property. The Tier Shift Mod's `onModifySpecies` function needs to check `this.ruleTable.has("standardnatdex")` to determine whether to use National Dex tiers.

### The Fix
Added the missing `ruleTable` property to the mock Battle context in `server/chat-commands/info.ts`. The mock context now includes:
- `dex`
- `clampIntRange`
- `toID`
- `ruleTable` (newly added)

This ensures that any format modifier that needs to access the rule table won't crash when called from the data command.

* Use optional chaning instead of constructing a full rule table.

* Fix: formatting

* More formatting

* formatting due to merge

* Update data/rulesets.ts

* ESLint: Resolve "Type boolean trivially inferred from a boolean literal, remove type annotation"

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-06-02 01:20:34 -06:00
kabilapok
5aca342e2f
SV NFE: Ban Misdreavus (#11170)
* SV NFE: Ban Misdreavus

https://www.smogon.com/forums/threads/sv-nfe-metagame-discussion-misdreavus-ban-post-137.3710638/post-10578825

* Update formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-06-02 01:12:46 -06:00
Kris Johnson
8dfed1fa21 Update runImmunity type for mods 2025-06-02 01:12:29 -06:00
Lucas
a3a822d564
Fix Fusion Evolution Random Battle (#11164)
* Fix FERB

* Fully pokemon section of scripts.ts

---------

Co-authored-by: Meijer,L. (Lucas) <l.meijer6@students.uu.nl>
Co-authored-by: Yoshiblaze <53023564+Yoshiblaze@users.noreply.github.com>
2025-06-02 01:03:23 -06:00
Kaen
e1fb179e9c
Tier Shift: Update bans (#11169) 2025-06-02 00:59:14 -06:00
Dieter Reinert
cf11f04043
SSB: Fix crash when Hot Pursuit triggers with no foes (#11168) 2025-06-02 00:58:54 -06:00
Kris Johnson
372d05e49c Disable Fusion Evolution 2025-06-01 02:10:07 -06:00
Kris Johnson
af908a36b8
Tier Shift: Unban some Arceus formes 2025-06-01 02:05:57 -06:00
André Bastos Dias
eb3c1f6a39
Fix Magic Bounce in Free-For-All battles (#11144)
* Fix Magic Bounce in Free-For-All battles

* Fix test with unmodified speed

* Modify test name

* Fix test name

* Fix test
2025-06-01 02:00:26 -06:00
André Bastos Dias
3e9d498805
Implement genderless Pokemon in Hackmons (#11161)
* Implement genderless Pokemon in Hackmons

* Fix

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

* Fix 2

* Fix RNG test

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-06-01 01:56:12 -06:00
Yoshiblaze
909aefddbf
Add June Pet Mod of the Season: Fusion Evolution Random Battle (#11153)
* June PMOTM Initial Commit

* Initial Cleanup Pt. 1

* Initial Cleanup Pt. 2

* Initial Cleanup Pt. 3

* Initial Cleanup Pt. 4

* Fix Trailing Spaces

* Fix Indents

* Fix initial style errors

* One more small fix

* Initial random-teams.ts creation

* Shorten Line

* Add Egg Groups

* More cleanup Pt. 1

* More cleanup Pt. 2

* Remove assertion

* Final Ability Cleanup for now

* Bring scripts.ts to modern conventions

* Fix indent and line length

* Temporarily change unit tests to not bug out

* Temporarily change unit tests to not bug out

* Add format, fix style

* Fix two more minor errors

* Fix Random Teams Error

* Change opening message

* Add Sprite Viewer

* fix 696 indents at the same time

* Remove fix for local-only bug

* Move Bad 'n Boosted to challengeable OMs

* Update config/formats.ts

---------

Co-authored-by: Meijer,L. (Lucas) <l.meijer6@students.uu.nl>
Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-06-01 01:55:07 -06:00
demir
085a67ee3a
35 Pokes: Update list of allowed Pokemon for June 2025 (#11162) 2025-06-01 01:53:52 -06:00
shrianshChari
dbb7dcff8c
UU: Ban Meowscarada (#11163)
https://www.smogon.com/forums/threads/sv-uu-suspect-process-round-14-meow-the-jewels.3764964/page-2#post-10577934
2025-06-01 01:52:04 -06:00
Kris Johnson
64b80ca9f5 Add June 2025 rotational formats 2025-06-01 01:51:17 -06:00
livid washed
4ccaa1598d
Gen 1 Random Battle updates (#11158)
* Updates

* Gen 4 Honchkrow LO
2025-05-31 19:12:41 -06:00
missshowdown
adbb32c71e
GSC ZU: Ban Poliwag and legalize Ariados (#11160)
https://www.smogon.com/forums/threads/zu-old-gens-hub-gsc-shifts-375.3646944/post-10561800
2025-05-31 12:55:52 -06:00
Karthik99999
6a8e18ec96 Fix Dynamax Request setting gmax parameter when the set does not have gmax 2025-05-31 12:33:11 -04:00
André Bastos Dias
6513f4b18a
Activate Wonder Guard if the target is immune (#11130)
* Activate Wonder Guard if the target is immune

* Lint

* Correctly check for immunities

* Refactor runImmunity

* Change all move.type to move

For example, this fixes Thousand Arrows vs Air Ballon Terapagos. Tera Shell was not activating.

* Remove unnecessary cast
2025-05-31 01:28:46 -06:00
André Bastos Dias
a2f2f14ada
Fix Echoed Voice's BP raise when there is no target (#11139)
* Echoed Voice's BP should raise even if there is no target

* Fix test description
2025-05-31 01:24:49 -06:00
ACakeWearingAHat
d67f64d00e
Randomized format set updates (#11156)
* Randomized format set updates

* obliterate psyshock from doubles

* fix bssf pult
2025-05-31 01:23:55 -06:00
Runo
466be38a53
Fix [Gen 8 DLC 1] National Dex AG legality (#11129)
* Update formats.ts

* Update formats.ts

* Update formats.ts

* Update formats-data.ts

* Update formats-data.ts
2025-05-30 21:18:17 -06:00
skymin3
0bde1a1103
SSNDDOU: Ban Beat Up (#11155)
https://www.smogon.com/forums/threads/new-generation-8-national-dex-doubles-metagame-discussion-resources.3764717/post-10577032
2025-05-30 21:17:57 -06:00
Guangcong Luo
2b05770780 Add forme names as fuzzy matches
(For `/dt` etc)
2025-05-30 19:54:00 -07:00
EvGym
ee3d1805c9
Add Gen 3 Colosseum format (#11135)
* Adding gen 3 colosseum format, updating win check

* Update formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-05-30 18:43:52 -06:00
FeluciaPS
fa88abb5d6
Add /dm as a /pm alias (#11154) 2025-05-30 16:33:28 -07:00
adrivrie
9c857973a2
Random Battles: May 2025 balance patch (#11148) 2025-05-30 11:43:22 -06:00
skymin3
da9a5c4d8d
Update aliases (#11120)
---------

Co-authored-by: Guangcong Luo <guangcongluo@gmail.com>
2025-05-29 22:44:57 -07:00
André Bastos Dias
233c618f97
Fix Chatter's old gen mechanics (#11140) 2025-05-29 21:50:01 -07:00
André Bastos Dias
cf03724b91
Add test for Magician + Throat Spray (#11145) 2025-05-29 20:22:40 -07:00
HiZo
0187007de5
Fix Endless Battle Clause in Gen 5 (#11143) 2025-05-29 16:56:49 -04:00
skymin3
10a58c0e16
SSNDDOU: Ban Venusaur & Ally Switch (#11128)
https://www.smogon.com/forums/threads/new-generation-8-national-dex-doubles-metagame-discussion-resources.3764717/post-10569613 ally switch ban

https://www.smogon.com/forums/threads/new-generation-8-national-dex-doubles-metagame-discussion-resources.3764717/post-10558240 venusaur ban
2025-05-28 19:52:59 -07:00
ShivaD173
13578bce64
Add test for an Eject Pack interaction (#10704) 2025-05-28 17:22:01 -07:00
Guangcong Luo
cd20be423f
Fix timer for mid-turn requests (#11127) 2025-05-28 17:07:41 -07:00
Guangcong Luo
66018a56b8 Fix ticket spacing 2025-05-28 16:30:30 -07:00
André Bastos Dias
859f5f5be8
Fix interaction between Pursuit and Follow Me (#10991) 2025-05-28 15:54:10 -04:00
André Bastos Dias
e08bc7abdf
Activate Opportunist after Mega and Tera (#11134) 2025-05-26 18:10:22 -07:00
Guangcong Luo
f616e48196 Validate mod capitalization 2025-05-26 16:30:06 -07:00
PartMan
4b2ac032d6
Pages: Notify bots when a user leaves a bot page (#11136) 2025-05-26 11:45:52 -07:00
Guangcong Luo
17f8fbc46a Unbold 5000 in auction help message 2025-05-25 18:58:33 -07:00
Marty-D
a260a5f026
Doubles LC: Ban Misdreavus
https://www.smogon.com/forums/posts/10571581/
2025-05-25 20:55:19 -04:00
Marty-D
cb8381e2b9
NU: Ban Porygon-Z
https://www.smogon.com/forums/posts/10571290/
2025-05-25 20:51:49 -04:00
André Bastos Dias
0f663cd46f
Refactor White Herb activation (#11133) 2025-05-25 12:57:58 -07:00
André Bastos Dias
14b3c117b3
Fix Tera Blast's interaction with Unaware (#10897)
* Fix Tera Blast's interaction with Unaware

* Remove comment

* Update to ESLint 9

* Add Download + Simple test
2025-05-25 10:02:45 -06:00
Sergio Garcia
b81ff9a69a
Remove useless spreads (#11132) 2025-05-24 16:19:48 -07:00
André Bastos Dias
5669abc8c5
Fix the form order of Flabébé's evolution line (#11131) 2025-05-24 16:18:15 -04:00
InkyDarkBird
57dec7aa5e
Trademarked: Update restrictions (#11126)
* Trademarked Restricts

* unrestrict Skill Swap
2025-05-23 18:30:15 -06:00
Guangcong Luo
e07080ce5c
Support fuzzy searching /dt etc (#11124)
This add's the teambuilder's fuzzy matching to /dt and similar commands.
2025-05-23 00:26:23 -07:00
dot-Comfey
8f57aa50bf
Help Tickets: Fix claim button text for text tickets (#10978)
Nitpick; the button to check out a text ticket shows as "Claim" when someone else is already looking at the ticket or it is already closed, which doesn't really make sense.
2025-05-22 13:11:46 -06:00
Kris Johnson
d972d8e21b Add some Gen 8 National Dex formats 2025-05-22 13:10:07 -06:00
Aleksa
f94b419caa
Metronome Battle: Ban Pecharunt (#11123) 2025-05-22 12:00:28 -07:00
sunnytangg
34295c1f6b
Gen 4: Fix Haze not removing Focus Energy (#11114) 2025-05-20 19:39:41 -07:00
André Bastos Dias
99ff2921e5
Fix Mold Breaker interactions with abilities' Start events (#10877) 2025-05-20 19:06:22 -07:00
Guangcong Luo
df8a236c16 Teams: Hardcode no "Cathy" alias
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-05-19 19:21:44 -07:00
Guangcong Luo
803be601e6 Improve CompoundWordNames validation
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-05-19 11:16:50 -07:00
Lucas
fc3ab2cf61
Add rule to automatically display Pokemon information (#11122)
---------

Co-authored-by: Guangcong Luo <guangcongluo@gmail.com>
2025-05-19 10:53:43 -07:00
skymin3
a58e184872
Commands: Update help FAQ and improve !faq fails (#11118)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
https://www.smogon.com/forums/threads/clean-up-update-error-message-for-faq.3764560/ 
!faq fails no longer send the failed message message in chat, this is very helpful for room auth who are the users of broadcast commands
For whatever reason '!faq all' fails used a replybox? I can't think of a single non dev command that uses visible replyboxes in chat for fails, so changed this for an errorReply.
I cleaned up the wording of the /help faq, and I added some topics that were not there previously.
2025-05-19 01:18:28 -07:00
Guangcong Luo
a87a05fc7f Update CompoundWordNames for gen 7-9
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-05-18 17:50:46 -07:00
Guangcong Luo
f54a9ed5e1 Make sure data files never import
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-05-18 15:19:34 -07:00
Guangcong Luo
417a9183f8 Revert "Add rule to automatically display Pokemon information (#11097)"
You can't import chat from rulesets.

This reverts commit c4e1a4b154.
2025-05-18 14:44:13 -07:00
Guangcong Luo
99c69509ad
Port CompoundWordNames into data/aliases (#11121)
This is what lets you type "ww" or "wind" to find "whirlwind" in the
teambuilder (and PSdex) search.

These were previously in the client build scripts, where I think most
people didn't realize how to find or update them.
2025-05-18 13:39:06 -07:00
Guangcong Luo
7f51282b16 Fix build error
Ugh, this is incredibly annoying, I tested before pushing but committed
this into the wrong branch.
2025-05-18 13:18:42 -07:00
Guangcong Luo
ef9e1d23e2 Validate aliases in unit tests 2025-05-18 12:34:28 -07:00
Lucas
c4e1a4b154
Add rule to automatically display Pokemon information (#11097)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
Pet Mods requested a Data Mod that automatically shows information for formats that have many custom changes (currently CCAPM2024 Random Battle).
2025-05-18 08:17:13 -07:00
Lucas
5e9d392c28
Scavengers: Add Pointless twist (#11044) 2025-05-18 08:08:56 -07:00
pyuk-bot
0ee3291761
Teams: Automatically remove empty moveslots (#11119)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-05-17 21:36:44 -07:00
skymin3
9b6bb90cb5
RU: Ban Oricorio-Pom-Pom (#11116)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
https://www.smogon.com/forums/threads/sv-ru-suspect-process-14-dance-dance-oricorio-pom-pom-suspect-test.3764185/post-10562255
2025-05-17 19:17:05 -04:00
HiZo
f09476998e
Trademarked: Don't movelock the user into a Trademark (#11117) 2025-05-17 14:38:37 -07:00
skymin3
337c3ed4dd
Trademarked: Restrict Skill Swap (#11115)
https://www.smogon.com/forums/threads/trademarked.3714688/post-10562311
2025-05-17 13:15:56 -07:00
HoeenHero
7f4f4fe584 Timer: Properly detect first turn when automatically starting the timer
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-05-17 09:08:24 -04:00
Guangcong Luo
c5e63f84ab Fix crash when restarting with active Bo3
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-05-16 10:42:56 -07:00
André Bastos Dias
a7f7e9049c
Send detailschange after forme regression (#11113) 2025-05-16 10:26:36 -07:00
Guangcong Luo
f13fe4495b Fix timer bug
nextRequest is no longer called on all players simultaneously,
meaning turnSecondsLeft might not be initialized when the timer starts.
2025-05-16 10:25:50 -07:00
André Bastos Dias
9af6808163
Update aliases and base formes (#11111) 2025-05-16 09:53:48 -07:00
Guangcong Luo
c5ef8ea3e5 Update timer for requests after updates
I figured PR #11105 would have some unintended side effect, but this
one isn't bad at all. There's no longer an easy way to tell whether
requests are move requests or not, but it's easy enough to instead
track the current turn.
2025-05-16 09:15:50 -07:00
André Bastos Dias
8158284427
Refactor fainted forme regression (#10878)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-05-16 07:40:49 -07:00
skymin3
ca3e6faaae
Trademarked: Ban Wish (#11110)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-05-15 21:04:14 -07:00
shrianshChari
27f55f7116
[Gen 3] ADV 200: Vulpix gets Spite by breeding with the event Absol (#11112) 2025-05-15 21:00:38 -07:00
Guangcong Luo
091241f1bb
Sim: Emit requests after updates (#11105)
Fixes #8546
2025-05-15 20:30:02 -07:00
André Bastos Dias
3db46c58eb
Implement White Herb and Eject Pack like Mirror Herb (#10890)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-05-15 11:39:46 -07:00
livid washed
4f270fa968
Random Battles: Improve set generation with >4 moves (#11104)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Improve Random Battles handing of increased max moves

* use moves.size instead of this.maxmovecount

* oops

* lint
2025-05-14 13:45:50 -06:00
Kris Johnson
ec15de7e79
Gen 1: Fix partial trapping error message order
Fixes sending the can't move message after the partially trapped Pokemon has already moved
2025-05-14 10:05:18 -06:00
shrianshChari
0e2a8001ff
Validator: Check if Smeargle is nonstandard instead of its tier (#11107) 2025-05-14 08:33:10 -07:00
André Bastos Dias
a4fbc8619b
Fix Gen 4 Snatch (#10905) 2025-05-14 08:26:15 -07:00
shrianshChari
f23c953273
Fix egg move validation when Smeargle is Unreleased (#11102)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-05-13 19:46:36 -07:00
André Bastos Dias
be76e2a686
Fix requiredTeraType (#11106) 2025-05-13 15:08:38 -07:00
André Bastos Dias
d25aba9aff
Fix: Terastallize Ogerpon and Terapagos with different Tera types (#10814) 2025-05-13 14:44:46 -07:00
Guangcong Luo
72d7d38568
SIM-PROTOCOL: Update for clarity
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
Fixes #9911
2025-05-13 13:29:53 -07:00
skymin3
012b6716fb
Have invalid !rfaq fail over to !faq (#11096)
* !rfaq fail over to !faq 

Approved Suggestion: https://www.smogon.com/forums/threads/have-rfaq-fail-over-to-faq-if-a-match-is-not-found.3687458/ 

Code calls for RFAQ topics if that fails it checks the FAQ topic list. Sounds straightforward until you realize the faq broadcast fail command is archaic and for some reason the failed FAQ broadcast message still goes through on top of the actual faq error return message, along with the faq help, it's very messy I might just fix that next. This is bypassed by having the run broadcast call AFTER the topic is read as valid, so none of this nonsense can happen. I really thought this would be easy, turns out, not really (atleast for me).
2025-05-13 12:00:19 -07:00
Guangcong Luo
fe45b7d1bf Add |queryresponse|teamupdate| for /teams 2025-05-13 10:42:37 -07:00
skymin3
80c1460db8
Improve error messages shown to non-autoconfirmed (#11057)
https://www.smogon.com/forums/threads/improve-the-error-messages-shown-to-non-autoconfirmed-users-trying-to-access-certain-features.3737016/#post-10532853

A few of the non-autoconfirm error messages don't explain what autoconfirm means, which a new user likely doesn't know what autoconfirm is.
2025-05-13 09:12:52 -07:00
Kris Johnson
48d4a386b7 /roompromote: Fix punctuation on messages logged to staff room 2025-05-13 09:32:57 -06:00
FeluciaPS
ab3e4f4c50
ORAS 1v1: Ban Mew (#11099)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
https://www.smogon.com/forums/threads/1v1-old-gens.3646875/post-10554192
2025-05-12 18:46:20 -07:00
Guangcong Luo
a7489f0995 Fix /removedaily with two args
Fixes #11103
2025-05-12 17:45:59 -07:00
Sergio Garcia
d044cd7bc5
Github Actions: Fix linter issues and bump old actions (#11101)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
As reported by `actionlint`
2025-05-12 07:13:58 -07:00
skymin3
a7e9d9883b
Trademarked: Update bans (#11098)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
(Mew, Zamazenta-Hero, Trick, Switcheroo, all confusion moves, Toxic)

https://www.smogon.com/forums/threads/trademarked.3714688/post-10550469
2025-05-09 17:49:18 -07:00
Kaen
fb65a43ced
Trademarked: Update bans (#11091)
https://www.smogon.com/forums/threads/trademarked.3714688/page-5#post-10546099

Shed Tail is also supposed to be fully banned.
2025-05-09 17:03:23 -07:00
shrianshChari
33f7b41d03
[Gen 3] ADV 200: Implement One Boost Passer Clause (#11095)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-05-08 18:46:34 -05:00
shrianshChari
f2c7891775
UNO: Notify player if drawn card cannot be played (#11069) 2025-05-08 14:28:09 -07:00
Guangcong Luo
b979451e76 Fix uploading packed teams
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
Packed teams weren't supported because `splitFirst` was called with
too high a limit. This fixes that.
2025-05-07 20:20:14 -07:00
Guangcong Luo
23c387f4a0 Add privacy to |queryresponse|teamupload|
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-05-07 19:45:01 -07:00
Mia
9a670548fa Teams: Account for OMs in validation 2025-05-07 20:14:52 -05:00
Guangcong Luo
d25ab4b4b3 Sync eslint with client
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
Mostly this is relevant for `context.tr` tagged lines to be unlimited
length.
2025-05-06 22:13:03 -07:00
slainey
548f6911e9
Daily Spotlight: Add Delete button in list page (#11065)
---------

Co-authored-by: Guangcong Luo <guangcongluo@gmail.com>
2025-05-06 22:07:38 -07:00
Giagantic
a01bb7d4a3
Balanced Hackmons: Ban Power Trip (#11092)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Balanced Hackmons Banned Power Trip Due to Suspect!

https://www.smogon.com/forums/threads/sv-bh-suspect-5-power-trip.3763405/post-10546843

* Update config/formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-05-05 20:12:28 -06:00
missshowdown
906cc41d41
Update GSC PU/ZU tiering (#11093)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
https://www.smogon.com/forums/threads/gsc-pu-viability-rankings-furret-less-post-16.3673353/post-10539134
2025-05-05 17:04:59 -06:00
Guangcong Luo
42d52e36e0 Refactor spotlights
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
Fix /removedaily, adding a new "all" option to work like it's
documented to work, and fix the documentation.

Also remove support for legacy image format. A lot of functions were
async that didn't need to be.

Also remove an entirely unused sorting pass mistakenly introduced in
11ab3d83f8
(The queue was sorted, then immediately ignored to iterate it by index,
which is for the best, because showing the queue in any order other
than queue order is not useful.)
2025-05-05 07:05:59 -07:00
Guangcong Luo
a1e9066f9e Use class="details" and class="gray" 2025-05-05 04:43:05 -07:00
André Bastos Dias
79fd439fcd
Sim: Refactor event callbacks into a getter (#11089)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-05-04 18:12:59 -07:00
Kris Johnson
a8b794b1a7 SSB: marillvibes renamed to calmvibes
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-05-03 21:45:01 -06:00
Kris Johnson
ce7f05e240 SSB: Fix Archefaewild placement 2025-05-03 21:39:00 -06:00
Kris Johnson
8835f8b73d SSB: Rename DianaNicole 2025-05-03 20:56:42 -06:00
Karthik Bandagonda
6d7778167d
Auctions: Auto create players when using assignplayer (#11085)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-05-03 11:41:24 -05:00
Kaen
31e7e9bab5
Trademarked: Update bans (#11086) 2025-05-03 02:42:34 -06:00
shrianshChari
9bd91a6dae
[Gen 3] ADV 200: Re-add Wish Bagon event (#11084)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-05-02 18:07:07 -06:00
shrianshChari
751ac04a21
[Gen 3] ADV 200: Fix learnsets (#11080)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Goldeen line only learns Megahorn in FRLG

* Tentacool and Anorith only get Rapid Spin when chain bred through Kabuto

* No Pokemon can get the move Present without Delibird from FRLG

* Sandshrew gets Metal Claw by by breeding with Sneasel

* Oddish only leearns Swords Dance by move tutor or chain breeding with Hoppip

* Kirlia only learns Magical Leaf in FRLG

* Cacturne only learns Destiny Bond and Revenge in FRLG

* Corphish line only learns Crunch in FRLG

* Spheal only learns Defense Curl in FRLG

* No Pokemon gets Wish as an egg move until FRLG

* Remove all event moves

* Add learnsets for the Igglybuff line

* Pichu cannot obtain Volt Tackle until Emerald

* Re-legalize "Pokemon Center 5th Anniversary Eggs" moves

* Make PC 5th Anniversary moves exclusive

* Igglybuff can get Wish by breeding with the Wish Pikachu

* shroomish-rayquaza

* Update learnsets.ts

* Update learnsets.ts

* Update learnsets.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-05-01 20:15:37 -06:00
Kaen
4ff71c51e0
Trademarked: Update bans (#11081)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-05-01 16:17:12 -06:00
shrianshChari
1c805b8049
BDSP: Drop Torkoal and Sandslash to PU (#11082) 2025-05-01 16:16:57 -06:00
Kris Johnson
671f4edfad Update [Gen 3] Draft ruleset 2025-05-01 16:15:44 -06:00
Kris Johnson
e015dc78e9 RBY LC: Fix legality again 2025-05-01 11:33:02 -06:00
Kris Johnson
1f7d2a26f1 Gen 1 LC: Fix legality 2025-05-01 11:23:45 -06:00
Kris Johnson
dcd7f2d8df
Update OMotM/LCotM aliases 2025-05-01 11:13:21 -06:00
Kaen
a4d35be1f0
Trademarked: Updates bans (#11079)
* Trademarked: Updates bans

* Update formats.ts

* Update formats.ts

* Update config/formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-05-01 10:43:28 -06:00
Kris Johnson
cabcc8d419 Add May 2025 rotational ladders 2025-05-01 10:35:14 -06:00
Kris Johnson
ed30b21165 May 2025 tier shift 2025-05-01 10:05:52 -06:00
Runo
2ea0348b66
NatDex Godly Gift: Ban Power Construct (#11048)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* NatDex Godly Gift: Ban Power Construct

https://www.smogon.com/forums/threads/national-dex-godly-gift.3748640/post-10498888

* Added the trailing comma

* Update formats.ts

* Update formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-04-30 23:42:56 -06:00
André Bastos Dias
9fac6d66cc
Fix Beat Up using wrong form stat (#10986)
* Fix Beat Up using wrong form stat

* Fix Beat Up in older gens
2025-04-30 23:41:02 -06:00
demir
4d227e26dc
35 Pokes: Update list of allowed Pokemon for May 2025 (#11077)
* 35 Pokes: May 2025 update

* Update formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-04-30 23:36:40 -06:00
ACakeWearingAHat
0f60b6458e
Randomized format set updates (#11073)
* Randomized format set updates

* fix rolename

* dugtrio cb teras

* Update data/random-battles/gen9/teams.ts

* Update data/random-battles/gen9/teams.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-04-30 23:36:19 -06:00
Brendan Leahey
fb1b7d040c
LC UU: Ban Minccino (#11066)
* Implement Minccino Ban

* Update config/formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-04-30 23:36:11 -06:00
Yoshiblaze
78247527fd
Add New Pet Mod Leader's Choice, Community Create-A-Pet Mod 2024 (#11054)
* Add CCAPM Pt. 1

* Add CCAPM Pt. 2

* Add CCAPM Pt. 3

* Add CCAPM Pt. 4

* Add CCAPM Spreadsheet Broadcast

* Last second set change

* Add searchShow: false,
2025-04-30 23:36:03 -06:00
HiZo
6668106730
Godly Gift Mod: Don't automatically assume Zygarde-Complete is a god (#11063)
* Godly Gift Mod: Don't automatically assume Zygarde-Complete is a god

* Also add a validation check here

* Add suggestion from code review

* oops
2025-04-30 23:32:28 -06:00
Lucas
7135b1d196
Fix Trademarked (#11067)
Add effectType

Co-authored-by: Meijer,L. (Lucas) <l.meijer6@students.uu.nl>
2025-04-30 23:31:22 -06:00
livid washed
2dab03e2c0
Add May 2025 Randomized Format Spotlight (#11074) 2025-04-30 23:31:02 -06:00
livid washed
0d07a671f2
Pick-Your-Team Random Battle: Add Shared Power functionality (#11070) 2025-04-30 23:29:33 -06:00
demir
4e188f3dd7
35 Pokes: Ban Tangled Feet (#11071) 2025-04-30 23:25:37 -06:00
shrianshChari
d6d74a3b8e
BDSP: Update NU-PU legality (#11072)
https://www.smogon.com/forums/threads/bdsp-pu-grumpig-ban-post-71.3700009/page-4#post-10538113
2025-04-30 23:25:17 -06:00
adrivrie
591a83cd63
Random Battles: April 2025 balance patch (#11075) 2025-04-30 23:25:00 -06:00
shrianshChari
8167652d11
Create a format for [Gen 3] ADV 200 (#11076)
* Add ADV 200 support

* Add ADV 200 format

* Completely remove move tutors and some FRLG egg moves

* Fix validator

* Remove unobtainable berries

* Remove Pokemon XD purification moves

* Removed other Pokemon XD purification moves for completeness

* Prepare for it to become an official format

* Remove extraneous files

* Satisfy linter

* Satisfy linter (again)

* Fix typing and simplify items

* Fix learnset types

* Rename mod to gen3rs
2025-04-30 23:24:49 -06:00
Karthik Bandagonda
71759c417a
VGC/BSS: Remove Regulation G ladders (#11078) 2025-04-30 23:24:17 -06:00
Marty-D
58711d3511
Descriptions: Update some Abilities 2025-04-30 22:17:35 -04:00
Andrew Huang
e00df54850
Descriptions: Fix Gen 1 Leech Seed (#11055) 2025-04-30 22:09:32 -04:00
HiZo
e7c5f126da
Teams: Sanitize OM Nicknames (#11068)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-04-27 20:51:10 -07:00
Mia
f2290ced37 Teams: Improve note on sharing teams onsite vs offsite
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-04-27 13:07:32 -05:00
HiZo
3c2a45c68c
Battles: Show custom rules in log (#11047)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-04-25 20:58:41 -07:00
HiZo
60786853de
Gen 1 Stadium: Implement the 1/65536 miss (#11061) 2025-04-25 20:57:49 -07:00
Runo
db8576e2b3
NatDex BH: Fix legality (#11049)
Dexited Pokemon were not allowed for some reason, this is a work around.
2025-04-25 21:13:59 -06:00
TomOfTomKat
78bd34e2d9
Info: Update /smogonintro links (#11058)
Removed outdated links in /smogoninfo and replaced them with up to date ones:

https://www.smogon.com/forums/threads/introduction-to-smogon.3710821/
https://www.smogon.com/forums/threads/smogon-discord-server-directory.3652546/
2025-04-25 21:13:24 -06:00
Giagantic
5a3e33257e
Mix and Mega: Restrict Walking Wake (#11059)
https://www.smogon.com/forums/threads/mix-and-mega-suspect-14-walking-wake.3762856/post-10533623
2025-04-25 21:12:54 -06:00
TomOfTomKat
f86f08cb9a
Info: Update /tier (#11062)
Replace outdated (like, since XY outdated) links with current links.

I don't *love* dumping users at the Smogon Metagames forum, but there is no where else I am aware of that has all of our formats listed out.

Also updated the description to explain how /tier works and explain what type of information it contains.
2025-04-25 20:59:09 -06:00
slainey
6d455ab03e
Moderation: Clarify duration of default roombans (#11046)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
https://www.smogon.com/forums/threads/clarification-on-how-long-a-ban-lasts.3761482/ 

2 day bans do not say the amount of time which can be confusing to new users as they think a room ban is permanent. This commit does so without influencing week room ban text logs which already do note the 1 week time limit. This is an approved suggestion on the forums as well.
2025-04-24 07:05:13 -07:00
André Bastos Dias
427e2deb6b
Refactor Magician code (#11053) 2025-04-24 06:11:12 -07:00
Andrew Huang
36fb26649a
Fix bug letting Gen-2 OHKO moves skip level check (#11050)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-04-23 23:10:48 -07:00
André Bastos Dias
6b3d0eefbd
Fix Sparkling Aria's interaction with Shield Dust (#10882)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-04-23 16:57:31 -07:00
Mia
c273081062 Move Zoroark-H to RUBL 2025-04-23 17:23:21 -05:00
Marty
6d98dfa237 Descriptions: Update Shield Dust and Covert Cloak
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
Closes #11042
2025-04-21 21:23:38 -04:00
shrianshChari
74d9c773c2
BH: Ban King's Rock and Razor Fang (#11043)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
https://www.smogon.com/forums/threads/balanced-hackmons.3710859/page-39#post-10529187
2025-04-21 11:01:29 -06:00
WifiLatency
9c1457ee9b
/ds: Collapsibles New Styling (#11041)
Co-authored-by: Guangcong Luo <guangcongluo@gmail.com>
2025-04-21 05:07:44 -07:00
HiZo
3a08216317
Destiny Bond does not get copied by Baton Pass (#11015)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
Appeared as a bug within Relay Race, after doing a quick deep dive into decompilations in checking if this is just pokemon jank(tm) I can confirm this is just never the case.

Sources: 
https://github.com/pret/pokeplatinum/blob/main/include/constants/battle/moves.h#L46 (BATTLE_EFFECT_KO_MON_THAT_DEFEATED_USER notably isn't included)

4618ba7407/src/battle_main.c (L3175) (STATUS2_DESTINY_BOND notably isn't included)
2025-04-21 00:37:00 -06:00
VannAccessible
33f2e8ffa3
Relay Race: Unban Regieleki and Terapagos (#11039)
* Update formats.ts

Relay Race: Unban Regieleki and Terapagos

* Update formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-04-21 00:36:44 -06:00
Lucas
0fcbe9fcec
Bad 'n Boosted: Ban Espeon (#11037)
Co-authored-by: Meijer,L. (Lucas) <l.meijer6@students.uu.nl>
2025-04-20 23:51:46 -06:00
shrianshChari
f3ed0ee66d
UU: Ban Rillaboom (#11040)
https://www.smogon.com/forums/threads/rillaboom-is-now-banned-from-sv-uu.3763544/#post-10528374
2025-04-20 23:41:56 -06:00
Kris Johnson
793fee5467 GitHub: Send HTML boxes through /raw 2025-04-20 23:40:13 -06:00
Marty-D
535657e766
Add new avatars
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-04-18 18:03:29 -04:00
Guangcong Luo
57380ae0b5 Redesign Smogtours plugin
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-04-17 21:02:00 -07:00
Alex "Mathy
d249e388e4
FFA/Multi: Fix simultaneous timeouts (#10311)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-04-17 20:47:39 -05:00
Alex "Mathy
6793b8a6ab
Fix timer not ending when player uses /leavegame (#11035) 2025-04-17 20:47:14 -05:00
Guangcong Luo
cc1f5c043f Redesign /tours
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-04-17 04:26:58 +00:00
Kris Johnson
a251474697 /tours: Remove `target="_blank" from room URLs 2025-04-16 21:21:26 -06:00
Kris Johnson
71f784c180 Tournaments: Make /tours usable in PMs/console 2025-04-16 21:03:51 -06:00
Alex "Mathy
fa4cc97fa1
Old gens: Fix partial trapping status not disappearing (#11034) 2025-04-16 19:41:26 -07:00
Lucas
32f62518f7
Mafia: Allow playercap to be changed as long as the game has not started (#11033)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-04-16 17:28:24 -04:00
Aurastic
777ce4d38a
Increase /addhtmlfaq character limit 8192 to 10000 (#11032) 2025-04-16 13:24:08 -07:00
Mia
77d0732af3 Chat: Add clarifying message to pages that require logins 2025-04-16 13:13:02 -05:00
Kris Johnson
ed9764bc23
Convert SSB and Rands Winrate chat plugins to tsx (#11030)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-04-15 13:37:41 -06:00
shrianshChari
49d81ab318
National Dex: Update bans (#11029)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-04-15 02:24:55 -06:00
Sergio Garcia
fc23103de1
Fix random typos (#11020)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-04-13 23:59:36 -07:00
prunyy
789456572d
Fix Pokemoves Bugs: Category, Validator, and Hitting Substitute (#11026)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Fix Pokemoves Bugs: Category, Validator, and Hitting Substitute

* Fix Pokemove Validator Again

* Remove Pokemove Re-Check

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

* Format Pokemove Category

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>

* Update config/formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-04-13 11:12:35 -06:00
VannAccessible
61d5684b4d
Relay Race: Ban Acupressure (#11028)
* Update formats.ts

Ban Acupressure in Relay Race OM, per VannAccessible, format leader

* Fix build issue

* Update formats.ts

---------

Co-authored-by: Guangcong Luo <guangcongluo@gmail.com>
Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-04-13 10:51:33 -06:00
Guangcong Luo
2186bc919f
GitHub Actions: Update setup-node
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
This is in the hope that it helps with PR annotations.
2025-04-12 18:12:55 -07:00
Guangcong Luo
14ec078746 Fix battles sending requests after they're over 2025-04-12 17:33:38 -07:00
Guangcong Luo
4079fe7846 Database library: Support raw strings in SQL()
This is nearly never the right thing to do, but I guess some people
want raw power.
2025-04-12 17:13:47 -07:00
Kris Johnson
2990bc79e2
Relay Race: Update bans
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-04-11 10:37:08 -06:00
Mia
0f8a31252b Teams: Link to the new website in more places
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-04-09 19:32:00 -05:00
Mia
0cd19ed250 Teams: Correct shareable link display 2025-04-09 19:29:17 -05:00
Mia
d758c21c64 Teams: Add static shortlinks to display page 2025-04-09 19:27:33 -05:00
Mia
ae542f3e0c Teams: Allow items/abilities/types as set nicknames
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
For OMs.
2025-04-09 11:48:49 -05:00
WifiLatency
c4a5ed50e4
/ds: Param to expand collapsible datasearches by default (#11023)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Reimplement all as a param to automatically expand nonbroadcast results.

* Tests ensuring datasearches don't expand when broadcast with all
2025-04-08 23:53:40 -06:00
Guangcong Luo
89b976fe70 Update PROTOCOL.md docs
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-04-08 21:32:50 -07:00
demir
01d1ed0624
Put Hattrem in ND and Doubles NFE (#11022) 2025-04-08 22:06:56 -06:00
WifiLatency
7d989abe8e
/ds: Add comparing stats (#10984)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Add comparing stats

* Fix duplicate comparison overwriting and error feedback

* Error on duplicates, invalid ranges, and muliple inequality operators

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-04-07 21:23:40 -06:00
WifiLatency
81b3471cae
Datasearch: Make results collapsible (#10995)
* Make ds collapsible

* Make other search commands collapsible.

* Remove all as a parameter for searches

* use readmore element with content attrs defined

* Rework to support chrome due to details linebreak quirk

* Move the toggle button down to the results line for broadcast commands
2025-04-07 21:19:47 -06:00
André Bastos Dias
0f64804714
Fix G-Max Wind Rage's interaction with G-Max Steelsurge (#10988)
* Fix G-Max Wind Rage's interaction with G-Max Steelsurge

* Keep same order
2025-04-07 21:16:29 -06:00
Kris Johnson
9ff1398c69
Use Chat.ErrorMessage instead of errorReply in more places (#11017) 2025-04-07 21:15:27 -06:00
Chessking345
40f4915925
Add LGPE Starter Formes support for select formats (#11018)
* Add LGPE Starter formes to Hackmons Forme Legality

* Add LGPE Starter formes to Formemons
Add LGPE Starter formes learnset in SV

* Floette-Eternal SV learnset
2025-04-07 21:13:30 -06:00
shrianshChari
60fad5523d
Gen 5 BW1: Use May 2012 tiers (#11013)
* Gen 5 BW1: Use May 2012 tiers

* Satisfy linter
2025-04-07 21:12:56 -06:00
Kris Johnson
8e1888b463 National Dex Doubles: Ban Shadow Tag 2025-04-07 21:10:34 -06:00
Kris Johnson
3bbdb4e00e ADV UUBL: Remove ladder 2025-04-07 21:09:52 -06:00
Kris Johnson
5fdf220101
Move Dragalge to PUBL
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-04-06 21:43:11 -06:00
Marty-D
b7acdf9d3c
Descriptions: Update Baton Pass 2025-04-06 18:11:15 -04:00
Mia
291636a807 Suspects: Relax URL requirement
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
Smogon generates the URLs now.
2025-04-05 23:22:02 -05:00
FeluciaPS
dc156eaff5
GSC 1v1: Ban confusion moves (#11012)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
https://www.smogon.com/forums/threads/1v1-old-gens.3646875/post-10506727
2025-04-04 22:38:42 -06:00
Karthik Bandagonda
06d8a8963b
Ensure megax and megay actions show up in inputlog (#11014) 2025-04-04 23:28:06 -05:00
Kris Johnson
c63f633f32 Remove unused mod folders
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-04-03 20:54:10 -06:00
HiZo
b48abbf09e
Gens 1-2: Give Paralysis a more accurate full paralysis chance (#10966)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-04-03 10:32:31 -07:00
missshowdown
cb81863dc5
ZU: Fix placements of some NFE Pokemon (#11009)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
Ursaring and Gurdurr did not see an average of 4.52% usage in ZU across January, February, and March. Hattrem did. 

Ursaring: (2.02 + 3.21 + 6.36) / 3 = 3.87 < 4.52
Gurdurr: (1.77 + 6.52 + 4.56) / 3 = 4.26 < 4.52
Hattrem: (8.22 + 9.41 + 2.91) / 3 = 6.85 > 4.52

https://www.smogon.com/stats/2025-01/gen9zu-1630.txt
https://www.smogon.com/stats/2025-02/gen9zu-1630.txt
https://www.smogon.com/stats/2025-03/gen9zu-1630.txt
2025-04-03 01:11:33 -06:00
Guangcong Luo
7979ef12cc Allow Hangul in names
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-04-02 16:44:06 -07:00
Mia
1a9d691493 Youtube: Update roomid references in groupwatch list 2025-04-02 16:21:08 -05:00
Kris Johnson
6f1cd87732 Gen 1: Fix protocol message for partial trapping lock 2025-04-02 13:12:53 -06:00
Kris Johnson
65b08549d7
Update OMotM/LCotM aliases
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-04-02 02:11:03 -06:00
HiZo
319d8060b7
Add Relay Race (#11005)
* Add Relay Race

* fix dragouts

* also eject button

* ruleset

* banlist

* Apply suggestions from code review

* Apply suggestions from code review

* Update formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-04-02 02:10:28 -06:00
demir
cf7826be73
35Pokes: Ban Shed Tail (#11007) 2025-04-02 02:07:29 -06:00
Kris Johnson
c654d83a0c Revert AFD 2025 changes 2025-04-02 02:00:58 -06:00
Kris Johnson
991cc727f7
Fix build again
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-04-01 13:04:50 -06:00
Kris Johnson
07cbce7ce0
Fix build 2025-04-01 12:32:55 -06:00
Kris Johnson
d8fa1532f4 Formemons: Fix legality
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-04-01 11:31:37 -06:00
Kris Johnson
e9caabaec1 Add April 2025 tier shifts 2025-04-01 11:21:58 -06:00
Kris Johnson
0c659c658c Fix Monkey's Paw
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-04-01 01:10:46 -06:00
Kris Johnson
95e935b6af Fix typo 2025-04-01 00:54:35 -06:00
Kris Johnson
de52e37ac9 Move Monkey's Paw 2025-04-01 00:24:19 -06:00
Kris Johnson
eccd7efd4c Fix build 2025-04-01 00:18:52 -06:00
Alex "Mathy
9ba3752d50
Dexsearch: Allow sorting by Pokedex number (#11001)
* Dexsearch: Allow sorting by Pokedex number

* fix whitespace
2025-04-01 00:17:47 -06:00
Typhon
18b96a8d03
April 2025 35 Pokes Update (#11002)
* April 2025 35 Pokes Update 

Update to the national dex 35 pokes format to include the pokemon which will be usable for the month of April 2025.

* Update formats.ts

Correct the spelling of Chimecho

* Update formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-04-01 00:16:17 -06:00
Kris Johnson
dba4211641 Add remaining rotational formats 2025-04-01 00:14:22 -06:00
Kris Johnson
46b2ab79b4 Add April 2024 OMotM 2025-03-31 23:59:48 -06:00
Kris Johnson
87e6f20664
Implement Monkey's Paw (#11004) 2025-03-31 22:38:53 -06:00
ACakeWearingAHat
09facb8cbb
Randomized format set updates (#11000)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-03-31 20:31:12 -04:00
adrivrie
152e7eed93
Random Battles: March 2025 balance patch (#10999) 2025-03-31 20:28:48 -04:00
Karthik Bandagonda
1a0953ffb6
VGC/BSS: Add Regulation I (#11003) 2025-03-31 19:17:33 -05:00
Mia
dd5c134603 Fix build
I'm going to set something on fire.
2025-03-31 18:45:37 -05:00
Mia
ef5ea9f0ff Chatlog: Fix searching linecounts for deleted rooms 2025-03-31 18:34:26 -05:00
Mia
5383667f2c Chatlog: Allow searching linecounts for deleted rooms 2025-03-31 18:28:44 -05:00
Mia
3dd18fdfa5 Chatlog: Don't check filesystem for database log searches 2025-03-31 18:22:16 -05:00
Mia
d7bfa16a36 Youtube: Update roomid 2025-03-31 12:57:38 -05:00
André Bastos Dias
e6658f6768
Fix Water Shuriken's interaction with Battle Bond Greninja-Ash in Gen 9 (#10997)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-03-29 11:16:14 -05:00
Tree69420
58ce1e6dfa
RBY NU and below: Make APT Clause transitive (#10994)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
https://www.smogon.com/forums/threads/rby-nu-hub.3679758/post-10496208
2025-03-28 16:43:36 -06:00
Kris Johnson
26f3952930
SSB: Balance patch (#10992)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Start doing things

* Fix build

* fwefe

* ewps

* no imperial

* more adjustments
2025-03-27 20:51:52 -06:00
HoeenHero
c04e8118bc ADV UUBL: Reapply One Boost Passer Clause
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
On request of the tournament hosts and to match
the standard ruleset of the format.
2025-03-24 22:20:59 -04:00
HoeenHero
7e1622dc19 Add IVs to HOME shiny Meltan event 2025-03-24 22:07:18 -04:00
HoeenHero
ff32395a86
Add missing HOME dex completion gifts (#10989)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-03-23 22:44:57 -04:00
Marty-D
a56b9801cf
Descriptions: Update Chloroblast
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-03-21 22:38:35 -04:00
TehTayTeh
a337f2b4b4
ADV UUBL: Update bans (#10982)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
* Fixing Gen 3 UUBL

- Added 'Baton Pass + Salac Berry" to banlist which was always intended to be included, but was missed initially.
- Unbanned Soundproof and Sand Veil, which are bans carried over from OU that should not apply

* Update formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-03-19 13:28:39 -06:00
Oldenmw
415ae6be39
[Gen 5] Draft: Ban Sand Stream ++ Sand Rush (#10981) 2025-03-19 13:21:18 -06:00
Kris Johnson
f5fffca889
Move Magby to NFE 2025-03-19 13:20:52 -06:00
Kris Johnson
e288deabc9
LC UU: Ban Deerling 2025-03-19 13:20:21 -06:00
FeluciaPS
40b44b04ab
Little Cup: Ban Magby (#10980)
* Little Cup: Ban Magby

https://www.smogon.com/forums/threads/secrets-your-fire-magby-suspect-test.3760876/post-10485326

* Fair enough
2025-03-19 13:19:34 -06:00
Kris Johnson
4e6355837d
STABmons: Update bans
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-03-18 00:53:07 -06:00
WifiLatency
bdeb19f26a
/ds: Add rule functionality (#10973)
* /ds metagame rules with moves compability.

* mon attributes compatibility

* pokedex rule compatibility.

* clean up. support convergencelegality

* updated dexsearchhelp. better error feedback.

* Fix negations for abilities and moves.

* Scrapped convergence, cleanup.

* Updated dshelp for the mapped rule param values.

* Fixed duplicate formes and tests reciving species.

* Support /ds stacking multiple rules

* Apply suggestions from code review

* tests for /ds rule functionality

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-03-18 00:50:32 -06:00
Lucas
c06500fbef
Bad n Boosted: Ban Araquanid, add Sleep Moves Clause (#10977)
* Update Bans in BnB

Ban Araquanid and turn Sleep Clause into Sleep Moves Clause.

* Update config/formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-03-18 00:46:17 -06:00
sunnytangg
673f5e11dd
Challenge Cup: Fix Ogerpon tera types (#10971)
* Fix CC2v2 Ogerpon having incorrect tera types

* Remove print statements

* Update data/random-battles/gen9/teams.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-03-17 15:37:09 -06:00
pyuk-bot
945f130e66
OMs: Fix innates meant to activate on switch-in (#10976)
* Prevent Toxic Spikes from activating after being absorbed

* Fix everything else

* OMs: Fix innates meant to activate on switch-in
2025-03-17 15:34:52 -06:00
Guangcong Luo
2f0ce9c423 Implement Chilly Reception message
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
This is a bit hacky, but works in all the most common situations.

I wrote this a few weeks ago but was undecided about the `[premajor]`
tag format. I'm still not sure about it, but it's not like I'm going
to be any more sure if I keep waiting.
2025-03-16 01:33:05 -07:00
Kris Johnson
8ff6033077 Update CODEOWNERS
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-03-15 14:33:31 -06:00
missshowdown
9b04fd7073
RBY ZU VL Update: Ponyta LC + Wartortle NFE (#10972)
https://www.smogon.com/forums/threads/rby-zu-hub.3732499/page-4#post-10479767
2025-03-15 14:26:16 -06:00
Guangcong Luo
d0e3531e8b Fix burned Explosion damage
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-03-14 22:45:59 -07:00
WifiLatency
7279f81cc3
Allow users to broadcast !avatar (#10961)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* command properly functions when duplicated but cant broadcast with the normal name.

* Prevent users from providing no argument.

* Removed extraneous null check and ternary assignment.

* Remove extraneous newline.

* Update server/chat-commands/avatars.tsx

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-03-14 13:55:56 -06:00
shrianshChari
0f3eaaf2f1
Allow Illegal Pokemon into National Dex Draft formats (#10968) 2025-03-14 13:55:30 -06:00
FeluciaPS
0fe2067c9b
1v1: Ban Regidrago (#10970)
https://www.smogon.com/forums/threads/second-chance-regidrago-suspect.3760726/post-10478814
2025-03-14 13:55:10 -06:00
shrianshChari
243ca8b294
Ubers UU: Ban Zacian (#10969)
* Ubers UU: Ban Zacian

* Appease linter
2025-03-14 13:54:59 -06:00
Kris Johnson
f6ccab5e83 Frantic Fusions: Add 2 Ability Clause for suspect 2025-03-14 13:51:55 -06:00
André Bastos Dias
f53e9995b7
Fix Heal Block messages (#10964) 2025-03-14 12:07:26 -04:00
Guangcong Luo
ae22234ed0 Add Guaranteed Secondary Mod
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
This is currently for tests, but does have the side effect of plausibly
being fun as an actual mod to add to games.
2025-03-13 15:34:47 -07:00
HiZo
75533cca60
Fix Gen 1 PP underflow (#10967)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
PP is now deducted after the move rather than before, which is more
accurate and also simplifies the code.

Co-authored-by: Guangcong Luo <guangcongluo@gmail.com>
2025-03-12 21:59:30 -07:00
sunnytangg
dbf5830353
Fix freeze lingering after fainting from Pursuit (#10959) 2025-03-12 19:34:50 -07:00
Guangcong Luo
a5ae0ee42b Sim: Correctly clear maybeLocked
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-03-11 14:13:21 -07:00
WifiLatency
232af5c19f
/ds: Fix searching for trapping and partial trapping moves (#10962)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Adds trap as a search param to movesearch without modifying any moves.

* minor regex optimization.

* Implement in a less hacky manner.

* clean up adding both trapping statuses to the orgroup.

* Fixed conditional mixing trapped moves with other volatilestatuses.
2025-03-11 14:39:50 -06:00
Kris Johnson
e251645e11
National Dex OU: Ban Dragapult 2025-03-11 14:36:41 -06:00
Kris Johnson
eb3c7d1d61
National Dex UU: Ban Mega Gallade 2025-03-11 14:35:53 -06:00
shrianshChari
39f90f25fd
UU: Ban Quaquaval (#10963)
https://www.smogon.com/forums/threads/sv-uu-suspect-process-round-13-the-duck-song.3760500/page-2#post-10475920
2025-03-11 14:34:55 -06:00
HoeenHero
4cb442e33d Don't send a message if source is null
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
Client doesn't expect or handle (read: crashes) if source is null.
2025-03-09 18:23:38 -04:00
shrianshChari
ab1f7a2952
Add NatDex Mod to NatDex Draft formats (#10958)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Add NatDex Mod to NatDex Draft formats

* Fix tests

* Fix tests (again)
2025-03-09 13:04:13 -06:00
André Bastos Dias
f2736e1a3f
Fix Psychic Noise's interaction with Life Dew (#10892)
* Fix Psychic Noise's interaction with Life Dew

* Add FIXME comment

* Remove unreachable code

* Update to ESLint 9
2025-03-09 12:05:02 -06:00
WifiLatency
4346e3d34c
Add Restricted as a /ds Parameter (#10952)
* added restricted as a param for /ds using the species tags.

* comply with max line length.
2025-03-09 12:03:15 -06:00
WifiLatency
7bf04ad1e1
Implement searching for tiers by inequality to /ds (#10949)
* Implemented tier searching using inequalities.

* Fixed the value of OU being higher than CAP.

* Fixed AND searching for tiers with inequalities.

* Update server/chat-plugins/datasearch.ts

* Update server/chat-plugins/datasearch.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-03-09 12:03:06 -06:00
WifiLatency
f1ba8179c0
Add Number Generation Aliases to /learn (#10955)
* learn command generation shorthand now matches other datasearch commands.

* Retain support for generational prefixes.
2025-03-09 12:00:02 -06:00
Yoshiblaze
917bb0dd32
Add New Pet Mod of the Season (Bad 'n Boosted) (#10947)
* Add Bad 'n Boosted

* Add Mod Folder for Bad 'n Boosted so /dt works with it

* Fix indents

* Fix indents

* Remove Little Colosseum

* Change Bad 'n Boosted to a mod rather than a folder

* Apply suggestions from code review

* Update config/formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-03-09 11:59:50 -06:00
pyuk-bot
ae626838bf
CGT: Fix level history page (#10930)
* CGT: Fix level history viewer

* More efficiently iterate the array in reverse
2025-03-09 11:53:20 -06:00
ken
64b033a8c9
Monotype: Ban Gouging Fire (#10953)
* Ban Gouging Fire from Gen9Monotype

https://www.smogon.com/forums/threads/sv-monotype-suspect-11-dirty-dancer-gouging-fire-suspect-test.3760390/post-10470291

* Update formats.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-03-09 11:52:51 -06:00
Vertigo
ef4029ce57
Add boosting effects to Baton Pass Stat Clause (#10948) 2025-03-09 11:44:15 -06:00
Distrib
18ca337e13
Helptickets: Fix user profile links with spaces (#10951) 2025-03-09 11:43:53 -06:00
Spammernoob69
6280f3366c
CAP: Nerf Kitsunoh (#10942)
* CAP Kitsunoh Buff Process

Changelog:
  Kitsunoh:
    +14 Attack (103 to 117)
    +18 Speed (110 to 128)
    +Trace
    +Encore
    +Upper Hand
    -Iron Fist

* Chuggalong 2.0

Speed: -7 (115 to 108)
+White Smoke
+Slow Start

Full movepool: https://www.smogon.com/forums/threads/cap-34-part-17-final-movepool-submissions.3748657/post-10221427

* Update learnsets.ts

Added Event to Chuggalong learnset

* Update learnsets.ts

* Added CAP35 (Shox)

* Added CAP 34 Prevos (Chuggon, Draggalong)

Implemented Chuggon, Draggalong

* Fixed Shox data

* Added evo/prevo entry in pokedex

* Add Evo Level + Entrainment Egg Move

* Added Toxic to Chuggalong line

I was informed we had decided to add Toxic to Chuggalong's movepool for flavor reasons, as it is given to most (all?) Poison types.

* Shox 2.0

Added Shox Full Movepool + PPL stat buff (+18 SpA, +6 Def, +10 SpD, -18 Atk)

* Update learnsets.ts

Oops

* Update learnsets.ts

Pajantom Substitute.

* Kitsunoh Nerf

* Update pokedex.ts

* Remove Encore from CAP Randbats sets
2025-03-09 11:42:11 -06:00
InkyDarkBird
10c692b174
Alphabet Cup: Update bans (#10943)
* alphabet cup new bans

* alphabet cup bans
2025-03-09 11:41:17 -06:00
missshowdown
f9a74915d3
ZU: Ban Venomoth (#10954)
https://www.smogon.com/forums/threads/np-zu-stage-14-firestarter-venomoth-ban-11.3759085/#post-10455380
2025-03-09 11:37:54 -06:00
Guangcong Luo
c280cca53b
Fix Gen 1 Wrap (#10936)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-03-08 21:55:22 -08:00
Guangcong Luo
d6e17ebc9e Fix -All Pokemon overriding Min Source Gen
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-03-06 20:16:57 -08:00
Guangcong Luo
c90643efd0 Fix style
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-03-06 17:56:44 -08:00
Guangcong Luo
99ea179aaa Minor optimizations 2025-03-06 16:53:54 -08:00
Guangcong Luo
d9557375a0
Introduce "NatDex Mod" (#10939)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
"Standard NatDex" is very weird compared to how OMs usually work.

See "TierShift Mod" and "Godly Gift Mod". NatDex now gets its own mod,
which can be mixed into any other format, instead of needing to start
with NatDex.

This would make Min Source Gen overriding annoying, so it now defaults
to the current gen in Gen 9+, if Obtainable is set and +Past isn't. So
now you don't need to manually set Min Source Gen to enforce Obtainable
in Gen 9.
2025-03-06 03:40:36 -08:00
André Bastos Dias
c5b8ff7e47
Magician should steal the item if the opponent faints (#10911)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-03-05 23:25:18 -06:00
pyuk-bot
285cf9e2e6
Prevent Toxic Spikes from activating after being absorbed (#10940) 2025-03-05 22:41:56 -06:00
Syrinix
94f049ce19
Update /faq lostpassword (#10944)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
We are no longer doing password resets.
2025-03-05 04:59:58 -08:00
HiZo
b10f385d40
Mix and Mega: Unfree Crucibellite (#10945)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Mix and Mega: Unfree Crucibellite

* Update data/mods/mixandmega/scripts.ts

---------

Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
2025-03-04 23:15:52 -07:00
cat-colon-three
36aa7462af
National Dex Godly Gift: Add Species Clause (#10938)
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
https://www.smogon.com/forums/threads/national-dex-godly-gift.3748640/
2025-03-03 14:47:56 -08:00
Guangcong Luo
23c0ec34d2 Update dependencies
Some checks failed
Node.js CI / build (18.x) (push) Waiting to run
Publish to npm / test (push) Has been cancelled
Publish to npm / get-version (push) Has been cancelled
Publish to npm / npm-publish (push) Has been cancelled
2025-03-03 04:26:26 -08:00
Guangcong Luo
74aa072bfb Fix /formathelp for past-gen formats
NatDex Mod refactor caught a bug. `format.gen` isn't meaningful.

...maybe it should be... Main concern would be perf impact, to load
all the datamods to get their gen. Probably not worth it?
2025-03-03 04:06:20 -08:00
livid washed
d5f4cbf053
Add March 2025 Randomized Format Spotlight (#10937)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Add March 2025 Randomized Format Spotlight

* Shorter name
2025-03-02 20:53:44 -07:00
Guangcong Luo
c0b088f8e5 Tests: Remove 'pokemon' option on battles
(It's redundant with the 'legality' option which is named more clearly)
2025-03-02 19:12:00 -08:00
livid washed
46ab6455c9
Randomized format set updates (#10934)
* Randomized format set updates

* oops
2025-03-02 19:05:41 -07:00
adrivrie
6e66cd2fff
Random Battles: February 2025 balance patch (#10931) 2025-03-02 19:05:24 -07:00
Guangcong Luo
0cb51158aa
Make "All Pokemon" rules more convenient (#10932)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
* Make "All Pokemon" rules more convenient

Previously, "+All Pokemon" did nothing except override "-All Pokemon",
which switched from a default-allow to default-deny system.

They still do that, but they now also override all previous pokemon
bans/unbans. This makes it easier to replace a banlist/whitelist
from an inherited ruleset without needing to reverse every previous
ban/unban.

This also adds an error if you use `+All Pokemon` in a ruleset where
it doesn't do anything.

Fixes #10772
2025-03-02 14:47:30 -08:00
cat-colon-three
7b32d0f8c7
National Dex Godly Gift: Ban Mega Rayquaza (#10935)
* National Dex Godly Gift: Ban Mega Rayquaza

https://www.smogon.com/forums/threads/national-dex-godly-gift.3748640/#post-10460861

* banning mray v2
2025-03-02 15:05:25 -07:00
Guangcong Luo
95d6547739 Update SQLite dependencies
Some checks failed
Node.js CI / build (18.x) (push) Waiting to run
Publish to npm / test (push) Has been cancelled
Publish to npm / get-version (push) Has been cancelled
Publish to npm / npm-publish (push) Has been cancelled
2025-03-02 00:10:22 -08:00
Guangcong Luo
5424ef069f Lint translations and tools
(Our earlier eslint changes missed some things.)
2025-03-01 22:40:58 -08:00
Kris Johnson
2d4eecf5c4 35 Pokes: Fix Golem legality
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-03-01 10:56:47 -07:00
Kris Johnson
af4ae79fa6 Update 35 Pokes allowed list 2025-03-01 10:55:22 -07:00
Kris Johnson
6200a86c3e Remove duplicate entry 2025-03-01 10:39:20 -07:00
Kris Johnson
cc1fa09b47 Implement March 2025 tier shift 2025-03-01 10:35:56 -07:00
Kris Johnson
61b2544477 Add more March 2025 rotational formats 2025-03-01 10:35:11 -07:00
Kris Johnson
91198ac2c7 Add March 2025 rotational formats 2025-03-01 10:35:01 -07:00
Slayer95
674defa1b1
Fix uncaught exceptions in net library (#10628)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
Added missing error event handler
2025-03-01 03:18:43 -08:00
Guangcong Luo
719bc1a87f Fix crash when leaving UNO game
Fixes #10821
2025-03-01 03:11:51 -08:00
Mia
2a88d42831 Seasons: Properly prioritize current format badge
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
2025-02-27 18:14:25 -06:00
Mia
21b368a88f Users: Enforce ip-based punishments after rename as well as on login
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
2025-02-27 14:05:39 -06:00
Guangcong Luo
be518c5025 Suppress crash from probable race condition
Some checks failed
Node.js CI / build (18.x) (push) Waiting to run
Publish to npm / test (push) Has been cancelled
Publish to npm / get-version (push) Has been cancelled
Publish to npm / npm-publish (push) Has been cancelled
2025-02-26 22:28:46 -08:00
Guangcong Luo
557ed5008b Correctly support Node 18 2025-02-26 21:42:14 -08:00
Guangcong Luo
d8a051e364 It turns out Web Crypto isn't in Node 18
I was deceived by `crypto.getRandomValues` working in the repl, but
that's just because the repl has the Node standard library
pre-imported.

Anyway, this new code should work correctly in all of Node 18, newer
Node, and the browser.
2025-02-26 21:33:16 -08:00
Guangcong Luo
c0fcb03f4c Ugh I forgot why we can't update @types/node
(Newer versions don't play well with CommonJS modules. And there isn't
really even anywhere I can comment this to remind me not to do it...)
2025-02-26 20:21:10 -08:00
Guangcong Luo
d4fc262f7f Remove Node crypto dependency from sim 2025-02-26 18:03:08 -08:00
482 changed files with 207028 additions and 19360 deletions

View File

@ -15,23 +15,23 @@ jobs:
last_version: ${{ steps.last_version.outputs.version }}
token_exists: ${{ steps.check_token.outputs.token }}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
with:
fetch-depth: 50
# Check if the package.json version field has changed since the last push
- name: Get current version from package.json
id: current_version
run: |
echo "version=$(jq -r .version package.json)" >> $GITHUB_OUTPUT
echo "version=$(jq -r .version package.json)" >> "$GITHUB_OUTPUT"
- name: Get the version from the last push
id: last_version
run: |
git checkout ${{ github.event.before }}
echo "version=$(jq -r .version package.json)" >> $GITHUB_OUTPUT
echo "version=$(jq -r .version package.json)" >> "$GITHUB_OUTPUT"
- name: Check if NPM_TOKEN exists
id: check_token
run: |
echo "token=$(if [ -n "${{ secrets.NPM_TOKEN }}" ]; then echo true; else echo false; fi)" >> $GITHUB_OUTPUT
echo "token=$(if [ -n "${{ secrets.NPM_TOKEN }}" ]; then echo true; else echo false; fi)" >> "$GITHUB_OUTPUT"
npm-publish:
needs:
- test
@ -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@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 18
cache: 'npm'

View File

@ -17,15 +17,23 @@ jobs:
strategy:
matrix:
node-version: [18.x]
# Testing multiple Node versions makes CI take forever, and basically
# never actually finds anything we care about. Testing one is enough.
#
# This number should be left at the oldest Node LTS version capable of
# running Node without errors (it doesn't matter if it's unsupported).
# Please freely bump this version (and the check in `pokemon-showdown`
# and `server/index.ts`) if you want to use features from newer versions;
# this is purely for our own reference, not to constrain programmers.
node-version: ['18.x']
steps:
- uses: actions/checkout@v3
- 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@v3
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
@ -35,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
@ -58,14 +66,14 @@ 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
data/**
sim/**
- name: Run selective lint & neccessary tests (if pull request)
- name: Run selective lint & necessary tests (if pull request)
if: ${{ github.event_name == 'pull_request' }}
run: npm run full-test-ci
env:

View File

@ -3,12 +3,12 @@ name: Update the npm package version
on:
workflow_dispatch:
inputs:
version:
required: true
type: choice
description: Version type
default: patch
options:
version:
required: true
type: choice
description: Version type
default: patch
options:
- major
- minor
- patch
@ -16,27 +16,30 @@ on:
- preminor
- prepatch
- prerelease
jobs:
update_version:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 18
cache: 'npm'
- id: bump_version
run: |
echo "old_version=$(jq -r .version package.json)" >> $GITHUB_OUTPUT
echo "old_version=$(jq -r .version package.json)" >> "$GITHUB_OUTPUT"
npm version ${{ github.event.inputs.version }} --no-git-tag-version
echo "new_version=$(jq -r .version package.json)" >> $GITHUB_OUTPUT
echo "new_version=$(jq -r .version package.json)" >> "$GITHUB_OUTPUT"
- uses: peter-evans/create-pull-request@v4
- uses: peter-evans/create-pull-request@v8
with:
title: Bump package.json version to v${{ steps.bump_version.outputs.new_version }}}
title: Bump package.json version to v${{ steps.bump_version.outputs.new_version }}
body: |
Bump package.json version from `v${{ steps.bump_version.outputs.old_version }}` to `v${{ steps.bump_version.outputs.new_version }}`
commit-message: Bump package.json version to v${{ steps.bump_version.outputs.new_version }}
branch: npm-version-bump
base: master

View File

@ -1,25 +1,25 @@
config/formats.ts @KrisXV @Marty-D
data/mods/*/random-teams.ts @AnnikaCodes
data/mods/gen9ssb/ @HoeenCoder @HisuianZoroark @KrisXV
data/random-sets.json @MathyFurret @ACakeWearingAHat @livid-washed @adrivrie
data/random-teams.ts @AnnikaCodes @KrisXV @MathyFurret @ACakeWearingAHat @livid-washed @adrivrie
data/random-battles/ @KrisXV @MathyFurret @ACakeWearingAHat @livid-washed @adrivrie
data/text/ @Marty-D
databases/ @monsanto
lib/sql.ts @mia-pi-git
server/artemis/* @mia-pi-git
server/chat-plugins/random-battles/ @KrisXV @AnnikaCodes
server/chat-plugins/abuse-monitor.ts @mia-pi-git
server/chat-plugins/auction.ts @Karthik99999
server/chat-plugins/datasearch.ts @KrisXV
server/chat-plugins/friends.ts @mia-pi-git
server/chat-plugins/github.ts @mia-pi-git
server/chat-plugins/hosts.ts @AnnikaCodes
server/chat-plugins/helptickets*.ts @mia-pi-git
server/chat-plugins/laddertours.ts @mia-pi-git
server/chat-plugins/mafia.ts @HoeenCoder
server/chat-plugins/othermetas.ts @KrisXV
server/chat-plugins/permalocks.ts @mia-pi-git
server/chat-plugins/quotes.ts @mia-pi-git @KrisXV
server/chat-plugins/random-battles.ts @KrisXV @AnnikaCodes
server/chat-plugins/repeats.ts @AnnikaCodes
server/chat-plugins/responder.ts @mia-pi-git
server/chat-plugins/rock-paper-scissors.ts @mia-pi-git
server/chat-plugins/sample-teams.ts @KrisXV
server/chat-plugins/scavenger*.ts @xfix @sparkychildcharlie @PartMan7
sever/chat-plugins/teams.ts @mia-pi-git

View File

@ -301,13 +301,13 @@ In general, we prefer modern ways of writing things as long as they're supported
- Multiline template strings: A frequent source of bugs (and also weird for readability), so we prefer to explicitly use `\n` and concatenate over multiple lines.
- `async`/`await`: We prefer it for readability, but in certain cases we use raw Promises or even callbacks for performance. Don't worry about it too much; we usually won't nitpick code that uses any async implementation (although we might insist on `async`/`await` if the readability difference is huge).
- `async`/`await`: We prefer it for readability, but in certain cases we use raw Promises or even callbacks for performance. Don't worry about it too much; we usually won't nitpick code that uses either async implementation (although we might insist on `async`/`await` if the readability difference is huge).
- getters/setters/`Proxy`: We are generally very anti-magic. There are certain places in the code we do use magic where it's massively DRYer (or for historical reasons), but we prefer to explicitly mark that setting a variable is actually running a function with many and varied side effects. Please have a better reason than "`.foo` is less visual clutter than `.getFoo()`".
- Constant Enums: Don't use; we prefer constant union types, like `type Category = 'Physical' | 'Special' | 'Status'`
- Default Properties: Mediocre performance when compiled with `sucrase`. This is fine for objects that are rarely created, but prefer setting properties directly in a constructor, for objects created in inner loops.
- Default Properties: Use.
Dependencies

View File

@ -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

View File

@ -144,7 +144,7 @@ represented by a space), and the rest of the string being their username.
`|uhtml|NAME|HTML`
> We recieved an HTML message (NAME) that can change what it's displaying,
> We received an HTML message (NAME) that can change what it's displaying,
> this is used in things like our Polls system, for example.
`|uhtmlchange|NAME|HTML`
@ -305,7 +305,7 @@ represented by a space), and the rest of the string being their username.
`|tournament|update|JSON`
> `JSON` is a JSON object representing the changes in the tournament
> since the last update you recieved or the start of the tournament.
> since the last update you received or the start of the tournament.
> These include:
>
format: the tournament's custom name or the format being used
@ -478,7 +478,9 @@ If the challenge is accepted, you will receive a room initialization message.
`JSON.searching` will be an array of format IDs you're currently searching for
games in.
`JSON.games` will be a `{roomid: title}` table of games you're currently in.
`JSON.games` will be a `{roomid: title}` table of games you're currently in,
or `null` if you're in no games.
Note that this includes ALL games, so `|updatesearch|` will be sent when you
start/end challenge battles, and even non-Pokémon games like Mafia.

17
build
View File

@ -2,10 +2,12 @@
"use strict";
try {
// technically this was introduced in Node 17, but we'll ask for the most recent LTS with it to be safe
structuredClone({});
// fetch was introduced in Node 18, which is EOL,
// so we'll ask for the most recent "Active LTS" with it to be safe
// https://nodejs.org/en/about/previous-releases
fetch;
} catch (e) {
console.log("We require Node.js version 18 or later; you're using " + process.version);
console.error("We require Node.js version 22 or later; you're using " + process.version);
process.exit(1);
}
@ -22,13 +24,10 @@ function shell(cmd) {
// Check to make sure the most recently added or updated dependency is installed at the correct version
try {
var version = require('esbuild').version.split('.');
if (parseInt(version[1]) < 16) {
throw new Error("esbuild version too old");
}
require.resolve('ts-chacha20');
} catch (e) {
console.log('Installing dependencies...');
shell('npm install');
shell('npm ci');
}
// Make sure config.js exists. If not, copy it over synchronously from
@ -48,7 +47,5 @@ try {
// for some reason, esbuild won't be requirable until a tick has passed
// see https://stackoverflow.com/questions/53270058/node-cant-find-certain-modules-after-synchronous-install
setImmediate(() => {
// npm package, don't rebuild
if (process.argv[2] === 'postinstall' && fs.existsSync('dist')) return;
require('./tools/build-utils').transpile(force, decl);
});

View File

@ -45,7 +45,7 @@ Bans are just a `-` followed by the thing you want to ban.
`- Future` - ban things that only appears in a future generation (such as Arceus in Gen 1)
`- Custom` - ban made-up things other than CAP (such as Magikarp's Revenge, or Staff Bros moves)
`- Custom` - (DEPRECATED) ban miscellaneous other things
`- Nonexistent` - catch-all to ban all nonexistent Pokémon, items, etc. Includes: `- CAP, - Past, - Future, - LGPE`
@ -83,10 +83,20 @@ Syntax is identical to bans, just replace `-` with `+`, like:
More specific always trumps less specific:
`- all Pokemon, + Uber, - Giratina, + Giratina-Altered` - allow only Ubers other than Giratina-Origin
`- all pokemon, + Uber, - Giratina, + Giratina-Altered` - allow only Ubers other than Giratina-Origin
`- all pokemon, + Giratina-Altered, - Giratina, + Uber` - allow only Ubers other than Giratina-Origin
`- Nonexistent, + Necturna` - don't allow anything from outside the game, except the CAP Necturna
Except `all pokemon`, which removes all bans/unbans of pokemon before it:
`- all pokemon, + Pikachu, + Raichu` - allow Pikachu and Raichu
`+ Pikachu, - all pokemon, + Raichu` - allow only Raichu
(Note that `all pokemon` does not affect obtainability rules. `+ all pokemon` will not allow CAPs or anything like that.)
For equally specific rules, the last rule wins:
`- Pikachu, - Pikachu, + Pikachu` - allow Pikachu
@ -128,7 +138,7 @@ Whitelisting
Instead of a banlist, you can have a list of allowed things:
`- all Pokemon, + Charmander, + Squirtle, + Bulbasaur` - allow only Kanto starters
`- all pokemon, + Charmander, + Squirtle, + Bulbasaur` - allow only Kanto starters
`- all moves, + move: Metronome` - allow only the move Metronome

View File

@ -15,23 +15,6 @@ exports.port = 8000;
*/
exports.bindaddress = '0.0.0.0';
/**
* workers - the number of networking child processes to spawn
* This should be no greater than the number of threads available on your
* server's CPU. If you're not sure how many you have, you can check from a
* terminal by running:
*
* $ node -e "console.log(require('os').cpus().length)"
*
* Using more workers than there are available threads will cause performance
* issues. Keeping a couple threads available for use for OS-related work and
* other PS processes will likely give you the best performance, if your
* server's CPU is capable of multithreading. If you don't know what any of
* this means or you are unfamiliar with PS' networking code, leave this set
* to 1.
*/
exports.workers = 1;
/**
* wsdeflate - compresses WebSocket messages
* Toggles use of the Sec-WebSocket-Extension permessage-deflate extension.
@ -42,6 +25,15 @@ exports.workers = 1;
*/
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 = {
@ -92,6 +84,50 @@ Main's SSL deploy script from Let's Encrypt looks like:
*/
exports.proxyip = false;
// subprocesses - the number of child processes to use for various tasks.
// Can be set to `0` instead of `{...}` to stop using subprocesses, if you're running out of RAM.
exports.subprocesses = {
/**
* network - the number of networking child processes to spawn
* This should be no greater than the number of threads available on your
* server's CPU. If you're not sure how many you have, you can check from a
* terminal by running:
*
* $ node -e "console.log(require('os').cpus().length)"
*
* Using more workers than there are available threads will cause performance
* issues. Keeping a couple threads available for use for OS-related work and
* other PS processes will likely give you the best performance, if your
* server's CPU is capable of multithreading. If you don't know what any of
* this means or you are unfamiliar with PS' networking code, leave this set
* to 1.
*/
network: 1,
/**
* for simulating battles
* You should leave this at 1 unless your server has a very large
* amount of traffic (i.e. hundreds of concurrent battles).
*/
simulator: 1,
// beyond this point, it'd be very weird if you needed more than one of each of these
/** for validating teams */
validator: 1,
/** for user authentication */
verifier: 1,
localartemis: 1,
remoteartemis: 1,
friends: 1,
chatdb: 1,
modlog: 1,
pm: 1,
/** for the battlesearch chat plugin */
battlesearch: 1,
/** datasearch - for the datasearch chat plugin */
datasearch: 1,
};
/**
* Various debug options
*
@ -401,15 +437,6 @@ exports.logchallenges = false;
*/
exports.loguserstats = 1000 * 60 * 10; // 10 minutes
/**
* validatorprocesses - the number of processes to use for validating teams
* simulatorprocesses - the number of processes to use for handling battles
* You should leave both of these at 1 unless your server has a very large
* amount of traffic (i.e. hundreds of concurrent battles).
*/
exports.validatorprocesses = 1;
exports.simulatorprocesses = 1;
/**
* inactiveuserthreshold - how long a user must be inactive before being pruned
* from the `users` array. The default is 1 hour.
@ -500,7 +527,7 @@ exports.lastfmkey = '';
exports.chatlogreader = 'fs';
/**
* permissions and groups:
* Each entry in `grouplist` is a seperate group. Some of the members are "special"
* Each entry in `grouplist` is a separate group. Some of the members are "special"
* while the rest is just a normal permission.
* The order of the groups determines their ranking.
* The special members are as follows:

File diff suppressed because it is too large Load Diff

View File

@ -127,6 +127,7 @@ List of all in-battle forme changes:
- Darmanitan (Zen Mode)
- Meloetta (Relic Song)
- Shaymin-Sky (Frozen status)
- Ramnarok (Polar Flare)
- Mega evolutions
- Primal reversions
- Ultra Burst

View File

@ -60,7 +60,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
const noModifyType = [
'judgment', 'multiattack', 'naturalgift', 'revelationdance', 'technoblast', 'terrainpulse', 'weatherball',
];
if (move.type === 'Normal' && !noModifyType.includes(move.id) &&
if (move.type === 'Normal' && (!noModifyType.includes(move.id) || this.activeMove?.isMax) &&
!(move.isZ && move.category !== 'Status') && !(move.name === 'Tera Blast' && pokemon.terastallized)) {
move.type = 'Flying';
move.typeChangerBoosted = this.effect;
@ -145,7 +145,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
if (
effect.effectType === "Move" &&
!effect.multihit &&
(!effect.negateSecondary && !(effect.hasSheerForce && source.hasAbility('sheerforce')))
!(effect.hasSheerForce && source.hasAbility('sheerforce'))
) {
this.effectState.checkedAngerShell = false;
} else {
@ -301,7 +301,6 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
},
aurabreak: {
onStart(pokemon) {
if (this.suppressingAbility(pokemon)) return;
this.add('-ability', pokemon, 'Aura Break');
},
onAnyTryPrimaryHit(target, source, move) {
@ -357,12 +356,19 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
},
battlebond: {
onSourceAfterFaint(length, target, source, effect) {
if (source.bondTriggered) return;
if (effect?.effectType !== 'Move') return;
if (source.abilityState.battleBondTriggered) return;
if (source.species.id === 'greninjabond' && source.hp && !source.transformed && source.side.foePokemonLeft()) {
this.boost({ atk: 1, spa: 1, spe: 1 }, source, source, this.effect);
this.add('-activate', source, 'ability: Battle Bond');
source.abilityState.battleBondTriggered = true;
source.bondTriggered = true;
}
},
onModifyMovePriority: -1,
onModifyMove(move, attacker) {
if (move.id === 'watershuriken' && attacker.species.name === 'Greninja-Ash' &&
!attacker.transformed) {
move.multihit = 3;
}
},
flags: { failroleplay: 1, noreceiver: 1, noentrain: 1, notrace: 1, failskillswap: 1, cantsuppress: 1 },
@ -405,7 +411,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
if (
effect.effectType === "Move" &&
!effect.multihit &&
(!effect.negateSecondary && !(effect.hasSheerForce && source.hasAbility('sheerforce')))
!(effect.hasSheerForce && source.hasAbility('sheerforce'))
) {
this.effectState.checkedBerserk = false;
} else {
@ -734,33 +740,29 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
num: 238,
},
cudchew: {
onEatItem(item, pokemon) {
if (item.isBerry && pokemon.addVolatile('cudchew')) {
pokemon.volatiles['cudchew'].berry = item;
onEatItem(item, pokemon, source, effect) {
if (item.isBerry && (!effect || !['bugbite', 'pluck'].includes(effect.id))) {
this.effectState.berry = item;
this.effectState.counter = 2;
// This is needed in case the berry was eaten during residuals, preventing the timer from decreasing this turn
if (!this.queue.peek()) this.effectState.counter--;
}
},
onEnd(pokemon) {
delete pokemon.volatiles['cudchew'];
},
condition: {
noCopy: true,
duration: 2,
onRestart() {
this.effectState.duration = 2;
},
onResidualOrder: 28,
onResidualSubOrder: 2,
onEnd(pokemon) {
if (pokemon.hp) {
const item = this.effectState.berry;
this.add('-activate', pokemon, 'ability: Cud Chew');
this.add('-enditem', pokemon, item.name, '[eat]');
if (this.singleEvent('Eat', item, null, pokemon, null, null)) {
this.runEvent('EatItem', pokemon, null, null, item);
}
if (item.onEat) pokemon.ateBerry = true;
onResidualOrder: 28,
onResidualSubOrder: 2,
onResidual(pokemon) {
if (!this.effectState.berry || !pokemon.hp) return;
if (--this.effectState.counter <= 0) {
const item = this.effectState.berry;
this.add('-activate', pokemon, 'ability: Cud Chew');
this.add('-enditem', pokemon, item.name, '[eat]');
if (this.singleEvent('Eat', item, null, pokemon, null, null)) {
this.runEvent('EatItem', pokemon, null, null, item);
}
},
if (item.onEat) pokemon.ateBerry = true;
delete this.effectState.berry;
delete this.effectState.counter;
}
},
flags: {},
name: "Cud Chew",
@ -982,7 +984,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
const hitSub = target.volatiles['substitute'] && !move.flags['bypasssub'] && !(move.infiltrates && this.gen >= 6);
if (hitSub) return;
if (!target.runImmunity(move.type)) return;
if (!target.runImmunity(move)) return;
return false;
},
onEffectiveness(typeMod, target, type, move) {
@ -994,7 +996,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
const hitSub = target.volatiles['substitute'] && !move.flags['bypasssub'] && !(move.infiltrates && this.gen >= 6);
if (hitSub) return;
if (!target.runImmunity(move.type)) return;
if (!target.runImmunity(move)) return;
return 0;
},
onUpdate(pokemon) {
@ -1159,9 +1161,9 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
},
embodyaspectcornerstone: {
onStart(pokemon) {
if (pokemon.baseSpecies.name === 'Ogerpon-Cornerstone-Tera' &&
this.effectState.embodied !== pokemon.previouslySwitchedIn) {
this.effectState.embodied = pokemon.previouslySwitchedIn;
if (pokemon.baseSpecies.name === 'Ogerpon-Cornerstone-Tera' && pokemon.terastallized &&
!this.effectState.embodied) {
this.effectState.embodied = true;
this.boost({ def: 1 }, pokemon);
}
},
@ -1172,9 +1174,9 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
},
embodyaspecthearthflame: {
onStart(pokemon) {
if (pokemon.baseSpecies.name === 'Ogerpon-Hearthflame-Tera' &&
this.effectState.embodied !== pokemon.previouslySwitchedIn) {
this.effectState.embodied = pokemon.previouslySwitchedIn;
if (pokemon.baseSpecies.name === 'Ogerpon-Hearthflame-Tera' && pokemon.terastallized &&
!this.effectState.embodied) {
this.effectState.embodied = true;
this.boost({ atk: 1 }, pokemon);
}
},
@ -1185,9 +1187,9 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
},
embodyaspectteal: {
onStart(pokemon) {
if (pokemon.baseSpecies.name === 'Ogerpon-Teal-Tera' &&
this.effectState.embodied !== pokemon.previouslySwitchedIn) {
this.effectState.embodied = pokemon.previouslySwitchedIn;
if (pokemon.baseSpecies.name === 'Ogerpon-Teal-Tera' && pokemon.terastallized &&
!this.effectState.embodied) {
this.effectState.embodied = true;
this.boost({ spe: 1 }, pokemon);
}
},
@ -1198,9 +1200,9 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
},
embodyaspectwellspring: {
onStart(pokemon) {
if (pokemon.baseSpecies.name === 'Ogerpon-Wellspring-Tera' &&
this.effectState.embodied !== pokemon.previouslySwitchedIn) {
this.effectState.embodied = pokemon.previouslySwitchedIn;
if (pokemon.baseSpecies.name === 'Ogerpon-Wellspring-Tera' && pokemon.terastallized &&
!this.effectState.embodied) {
this.effectState.embodied = true;
this.boost({ spd: 1 }, pokemon);
}
},
@ -1541,7 +1543,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
const noModifyType = [
'judgment', 'multiattack', 'naturalgift', 'revelationdance', 'technoblast', 'terrainpulse', 'weatherball',
];
if (move.type === 'Normal' && !noModifyType.includes(move.id) &&
if (move.type === 'Normal' && (!noModifyType.includes(move.id) || this.activeMove?.isMax) &&
!(move.isZ && move.category !== 'Status') && !(move.name === 'Tera Blast' && pokemon.terastallized)) {
move.type = 'Electric';
move.typeChangerBoosted = this.effect;
@ -1928,7 +1930,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
if (!target) return;
if (move.category !== 'Physical' || target.species.id !== 'eiscue') return;
if (target.volatiles['substitute'] && !(move.flags['bypasssub'] || move.infiltrates)) return;
if (!target.runImmunity(move.type)) return;
if (!target.runImmunity(move)) return;
return false;
},
onEffectiveness(typeMod, target, type, move) {
@ -1938,7 +1940,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
const hitSub = target.volatiles['substitute'] && !move.flags['bypasssub'] && !(move.infiltrates && this.gen >= 6);
if (hitSub) return;
if (!target.runImmunity(move.type)) return;
if (!target.runImmunity(move)) return;
return 0;
},
onUpdate(pokemon) {
@ -2002,7 +2004,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
if (!possibleTarget.fainted) {
// If Ogerpon is in the last slot while the Illusion Pokemon is Terastallized
// Illusion will not disguise as anything
if (!pokemon.terastallized || possibleTarget.species.baseSpecies !== 'Ogerpon') {
if (!pokemon.terastallized || !['Ogerpon', 'Terapagos'].includes(possibleTarget.species.baseSpecies)) {
pokemon.illusion = possibleTarget;
}
break;
@ -2015,7 +2017,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();
@ -2257,12 +2259,12 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
},
libero: {
onPrepareHit(source, target, move) {
if (this.effectState.libero === source.previouslySwitchedIn) return;
if (this.effectState.libero) return;
if (move.hasBounced || move.flags['futuremove'] || move.sourceEffect === 'snatch' || move.callsMove) return;
const type = move.type;
if (type && type !== '???' && source.getTypes().join() !== type) {
if (!source.setType(type)) return;
this.effectState.libero = source.previouslySwitchedIn;
this.effectState.libero = true;
this.add('-start', source, 'typechange', type, '[from] ability: Libero');
}
},
@ -2331,10 +2333,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: {},
@ -2397,11 +2396,9 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
newMove.hasBounced = true;
newMove.pranksterBoosted = false;
this.actions.useMove(newMove, this.effectState.target, { target: source });
move.hasBounced = true; // only bounce once in free-for-all battles
return null;
},
condition: {
duration: 1,
},
flags: { breakable: 1 },
name: "Magic Bounce",
rating: 4,
@ -2421,16 +2418,21 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
},
magician: {
onAfterMoveSecondarySelf(source, target, move) {
if (!move || !target || source.switchFlag === true) return;
if (target !== source && move.category !== 'Status') {
if (source.item || source.volatiles['gem'] || move.id === 'fling') return;
const yourItem = target.takeItem(source);
if (!yourItem) return;
if (!source.setItem(yourItem)) {
target.item = yourItem.id; // bypass setItem so we don't break choicelock or anything
if (!move || source.switchFlag === true || !move.hitTargets || source.item || source.volatiles['gem'] ||
move.id === 'fling' || move.category === 'Status') return;
const hitTargets = move.hitTargets;
this.speedSort(hitTargets);
for (const pokemon of hitTargets) {
if (pokemon !== source) {
const yourItem = pokemon.takeItem(source);
if (!yourItem) continue;
if (!source.setItem(yourItem)) {
pokemon.item = yourItem.id; // bypass setItem so we don't break choicelock or anything
continue;
}
this.add('-item', source, yourItem, '[from] ability: Magician', `[of] ${pokemon}`);
return;
}
this.add('-item', source, yourItem, '[from] ability: Magician', `[of] ${target}`);
}
},
flags: {},
@ -2709,10 +2711,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: {},
@ -2918,9 +2917,9 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
const noModifyType = [
'hiddenpower', 'judgment', 'multiattack', 'naturalgift', 'revelationdance', 'struggle', 'technoblast', 'terrainpulse', 'weatherball',
];
if (!(move.isZ && move.category !== 'Status') && !noModifyType.includes(move.id) &&
if (!(move.isZ && move.category !== 'Status') &&
// TODO: Figure out actual interaction
!(move.name === 'Tera Blast' && pokemon.terastallized)) {
(!noModifyType.includes(move.id) || this.activeMove?.isMax) && !(move.name === 'Tera Blast' && pokemon.terastallized)) {
move.type = 'Normal';
move.typeChangerBoosted = this.effect;
}
@ -2985,6 +2984,16 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
this.boost(this.effectState.boosts, this.effectState.target);
delete this.effectState.boosts;
},
onAnyAfterMega() {
if (!this.effectState.boosts) return;
this.boost(this.effectState.boosts, this.effectState.target);
delete this.effectState.boosts;
},
onAnyAfterTerastallization() {
if (!this.effectState.boosts) return;
this.boost(this.effectState.boosts, this.effectState.target);
delete this.effectState.boosts;
},
onAnyAfterMove() {
if (!this.effectState.boosts) return;
this.boost(this.effectState.boosts, this.effectState.target);
@ -3204,7 +3213,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
const noModifyType = [
'judgment', 'multiattack', 'naturalgift', 'revelationdance', 'technoblast', 'terrainpulse', 'weatherball',
];
if (move.type === 'Normal' && !noModifyType.includes(move.id) &&
if (move.type === 'Normal' && (!noModifyType.includes(move.id) || this.activeMove?.isMax) &&
!(move.isZ && move.category !== 'Status') && !(move.name === 'Tera Blast' && pokemon.terastallized)) {
move.type = 'Fairy';
move.typeChangerBoosted = this.effect;
@ -3294,13 +3303,8 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
if (pokemon.species.id === 'zygardecomplete' || pokemon.hp > pokemon.maxhp / 2) return;
this.add('-activate', pokemon, 'ability: Power Construct');
pokemon.formeChange('Zygarde-Complete', this.effect, true);
pokemon.baseMaxhp = Math.floor(Math.floor(
2 * pokemon.species.baseStats['hp'] + pokemon.set.ivs['hp'] + Math.floor(pokemon.set.evs['hp'] / 4) + 100
) * pokemon.level / 100 + 10);
const newMaxHP = pokemon.volatiles['dynamax'] ? (2 * pokemon.baseMaxhp) : pokemon.baseMaxhp;
pokemon.hp = newMaxHP - (pokemon.maxhp - pokemon.hp);
pokemon.maxhp = newMaxHP;
this.add('-heal', pokemon, pokemon.getHealth, '[silent]');
pokemon.canMegaEvo = pokemon.canMegaEvo === false ? false : this.actions.canMegaEvo(pokemon);
pokemon.formeRegression = true;
},
flags: { failroleplay: 1, noreceiver: 1, noentrain: 1, notrace: 1, failskillswap: 1, cantsuppress: 1 },
name: "Power Construct",
@ -3312,9 +3316,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
if (!this.effectState.target.hp) return;
const ability = target.getAbility();
if (ability.flags['noreceiver'] || ability.id === 'noability') return;
if (this.effectState.target.setAbility(ability)) {
this.add('-ability', this.effectState.target, ability, '[from] ability: Power of Alchemy', `[of] ${target}`);
}
this.effectState.target.setAbility(ability, target);
},
flags: { failroleplay: 1, noreceiver: 1, noentrain: 1, notrace: 1 },
name: "Power of Alchemy",
@ -3408,12 +3410,12 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
},
protean: {
onPrepareHit(source, target, move) {
if (this.effectState.protean === source.previouslySwitchedIn) return;
if (this.effectState.protean) return;
if (move.hasBounced || move.flags['futuremove'] || move.sourceEffect === 'snatch' || move.callsMove) return;
const type = move.type;
if (type && type !== '???' && source.getTypes().join() !== type) {
if (!source.setType(type)) return;
this.effectState.protean = source.previouslySwitchedIn;
this.effectState.protean = true;
this.add('-start', source, 'typechange', type, '[from] ability: Protean');
}
},
@ -3701,9 +3703,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
if (!this.effectState.target.hp) return;
const ability = target.getAbility();
if (ability.flags['noreceiver'] || ability.id === 'noability') return;
if (this.effectState.target.setAbility(ability)) {
this.add('-ability', this.effectState.target, ability, '[from] ability: Receiver', `[of] ${target}`);
}
this.effectState.target.setAbility(ability, target);
},
flags: { failroleplay: 1, noreceiver: 1, noentrain: 1, notrace: 1 },
name: "Receiver",
@ -3729,7 +3729,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
const noModifyType = [
'judgment', 'multiattack', 'naturalgift', 'revelationdance', 'technoblast', 'terrainpulse', 'weatherball',
];
if (move.type === 'Normal' && !noModifyType.includes(move.id) &&
if (move.type === 'Normal' && (!noModifyType.includes(move.id) || this.activeMove?.isMax) &&
!(move.isZ && move.category !== 'Status') && !(move.name === 'Tera Blast' && pokemon.terastallized)) {
move.type = 'Ice';
move.typeChangerBoosted = this.effect;
@ -4143,7 +4143,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
shielddust: {
onModifySecondaries(secondaries) {
this.debug('Shield Dust prevent secondary');
return secondaries.filter(effect => !!(effect.self || effect.dustproof));
return secondaries.filter(effect => !!effect.self);
},
flags: { breakable: 1 },
name: "Shield Dust",
@ -4224,35 +4224,35 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
},
slowstart: {
onStart(pokemon) {
pokemon.addVolatile('slowstart');
this.add('-start', pokemon, 'ability: Slow 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, 'Slow Start');
delete this.effectState.counter;
}
}
},
onModifyAtkPriority: 5,
onModifyAtk(atk, pokemon) {
if (this.effectState.counter) {
return this.chainModify(0.5);
}
},
onModifySpe(spe, pokemon) {
if (this.effectState.counter) {
return this.chainModify(0.5);
}
},
onEnd(pokemon) {
delete pokemon.volatiles['slowstart'];
if (pokemon.beingCalledBack) return;
this.add('-end', pokemon, 'Slow Start', '[silent]');
},
condition: {
duration: 5,
onResidualOrder: 28,
onResidualSubOrder: 2,
onStart(target) {
this.add('-start', target, 'ability: Slow Start');
},
onResidual(pokemon) {
if (!pokemon.activeTurns) {
this.effectState.duration! += 1;
}
},
onModifyAtkPriority: 5,
onModifyAtk(atk, pokemon) {
return this.chainModify(0.5);
},
onModifySpe(spe, pokemon) {
return this.chainModify(0.5);
},
onEnd(target) {
this.add('-end', target, 'Slow Start');
},
},
flags: {},
name: "Slow Start",
rating: -1,
@ -4720,6 +4720,24 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
rating: 3,
num: 33,
},
swordofruin: {
onStart(pokemon) {
if (this.suppressingAbility(pokemon)) return;
this.add('-ability', pokemon, 'Sword of Ruin');
},
onAnyModifyDef(def, target, source, move) {
const abilityHolder = this.effectState.target;
if (target.hasAbility('Sword of Ruin')) return;
if (!move.ruinedDef?.hasAbility('Sword of Ruin')) move.ruinedDef = abilityHolder;
if (move.ruinedDef !== abilityHolder) return;
this.debug('Sword of Ruin Def drop');
return this.chainModify(0.75);
},
flags: {},
name: "Sword of Ruin",
rating: 4.5,
num: 285,
},
symbiosis: {
onAllyAfterUseItem(item, pokemon) {
if (pokemon.switchFlag) return;
@ -4755,24 +4773,6 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
rating: 2,
num: 28,
},
swordofruin: {
onStart(pokemon) {
if (this.suppressingAbility(pokemon)) return;
this.add('-ability', pokemon, 'Sword of Ruin');
},
onAnyModifyDef(def, target, source, move) {
const abilityHolder = this.effectState.target;
if (target.hasAbility('Sword of Ruin')) return;
if (!move.ruinedDef?.hasAbility('Sword of Ruin')) move.ruinedDef = abilityHolder;
if (move.ruinedDef !== abilityHolder) return;
this.debug('Sword of Ruin Def drop');
return this.chainModify(0.75);
},
flags: {},
name: "Sword of Ruin",
rating: 4.5,
num: 285,
},
tabletsofruin: {
onStart(pokemon) {
if (this.suppressingAbility(pokemon)) return;
@ -4879,14 +4879,6 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
if (pokemon.species.forme !== 'Terastal') {
this.add('-activate', pokemon, 'ability: Tera Shift');
pokemon.formeChange('Terapagos-Terastal', this.effect, true);
pokemon.regressionForme = false;
pokemon.baseMaxhp = Math.floor(Math.floor(
2 * pokemon.species.baseStats['hp'] + pokemon.set.ivs['hp'] + Math.floor(pokemon.set.evs['hp'] / 4) + 100
) * pokemon.level / 100 + 10);
const newMaxHP = pokemon.baseMaxhp;
pokemon.hp = newMaxHP - (pokemon.maxhp - pokemon.hp);
pokemon.maxhp = newMaxHP;
this.add('-heal', pokemon, pokemon.getHealth, '[silent]');
}
},
flags: { failroleplay: 1, noreceiver: 1, noentrain: 1, notrace: 1, failskillswap: 1, cantsuppress: 1, notransform: 1 },
@ -5061,9 +5053,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
const target = this.sample(possibleTargets);
const ability = target.getAbility();
if (pokemon.setAbility(ability)) {
this.add('-ability', pokemon, ability, '[from] ability: Trace', `[of] ${target}`);
}
pokemon.setAbility(ability, target);
},
flags: { failroleplay: 1, noreceiver: 1, noentrain: 1, notrace: 1 },
name: "Trace",
@ -5274,20 +5264,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",
@ -5447,7 +5424,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
target.addVolatile('charge');
}
},
onAllySideConditionStart(target, source, sideCondition) {
onSideConditionStart(side, source, sideCondition) {
const pokemon = this.effectState.target;
if (sideCondition.id === 'tailwind') {
pokemon.addVolatile('charge');
@ -5472,7 +5449,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
return null;
}
},
onAllySideConditionStart(target, source, sideCondition) {
onSideConditionStart(side, source, sideCondition) {
const pokemon = this.effectState.target;
if (sideCondition.id === 'tailwind') {
this.boost({ atk: 1 }, pokemon, pokemon);
@ -5486,10 +5463,10 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
},
wonderguard: {
onTryHit(target, source, move) {
if (target === source || move.category === 'Status' || move.type === '???' || move.id === 'struggle') return;
if (target === source || move.category === 'Status' || move.id === 'struggle') return;
if (move.id === 'skydrop' && !source.volatiles['skydrop']) return;
this.debug('Wonder Guard immunity: ' + move.id);
if (target.runEffectiveness(move) <= 0) {
if (target.runEffectiveness(move) <= 0 || !target.runImmunity(move)) {
if (move.smartTarget) {
move.smartTarget = false;
} else {
@ -5561,14 +5538,14 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
if (pokemon.baseSpecies.baseSpecies !== 'Palafin') return;
if (pokemon.species.forme !== 'Hero') {
pokemon.formeChange('Palafin-Hero', this.effect, true);
pokemon.regressionForme = false;
pokemon.heroMessageDisplayed = false;
}
},
onSwitchIn(pokemon) {
if (pokemon.baseSpecies.baseSpecies !== 'Palafin') return;
if (!this.effectState.heroMessageDisplayed && pokemon.species.forme === 'Hero') {
if (!pokemon.heroMessageDisplayed && pokemon.species.forme === 'Hero') {
this.add('-activate', pokemon, 'ability: Zero to Hero');
this.effectState.heroMessageDisplayed = true;
pokemon.heroMessageDisplayed = true;
}
},
flags: { failroleplay: 1, noreceiver: 1, noentrain: 1, notrace: 1, failskillswap: 1, cantsuppress: 1, notransform: 1 },
@ -5594,7 +5571,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
flags: { breakable: 1 },
name: "Mountaineer",
rating: 3,
num: -2,
num: -1,
},
rebound: {
isNonstandard: "CAP",
@ -5602,32 +5579,32 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
onTryHit(target, source, move) {
if (this.effectState.target.activeTurns) return;
if (target === source || move.hasBounced || !move.flags['reflectable']) {
if (target === source || move.hasBounced || !move.flags['reflectable'] || target.isSemiInvulnerable()) {
return;
}
const newMove = this.dex.getActiveMove(move.id);
newMove.hasBounced = true;
newMove.pranksterBoosted = false;
this.actions.useMove(newMove, target, { target: source });
return null;
},
onAllyTryHitSide(target, source, move) {
if (this.effectState.target.activeTurns) return;
if (target.isAlly(source) || move.hasBounced || !move.flags['reflectable']) {
if (target.isAlly(source) || move.hasBounced || !move.flags['reflectable'] || target.isSemiInvulnerable()) {
return;
}
const newMove = this.dex.getActiveMove(move.id);
newMove.hasBounced = true;
newMove.pranksterBoosted = false;
this.actions.useMove(newMove, this.effectState.target, { target: source });
move.hasBounced = true; // only bounce once in free-for-all battles
return null;
},
condition: {
duration: 1,
},
flags: { breakable: 1 },
name: "Rebound",
rating: 3,
num: -3,
num: -2,
},
persistent: {
isNonstandard: "CAP",
@ -5635,6 +5612,6 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
flags: {},
name: "Persistent",
rating: 3,
num: -4,
num: -3,
},
};

File diff suppressed because it is too large Load Diff

View File

@ -1,78 +0,0 @@
// Data for computer-generated teams
export const MOVE_PAIRINGS: { [moveID: IDEntry]: IDEntry } = {
rest: 'sleeptalk',
sleeptalk: 'rest',
};
// Bonuses to move ratings by ability
export const ABILITY_MOVE_BONUSES: { [abilityID: IDEntry]: { [moveID: IDEntry]: number } } = {
contrary: { terablast: 2 },
drought: { sunnyday: 0.2, solarbeam: 2 },
drizzle: { raindance: 0.2, solarbeam: 0.2, hurricane: 2 },
};
// Bonuses to move ratings by move type
export const ABILITY_MOVE_TYPE_BONUSES: { [abilityID: IDEntry]: { [typeName: string]: number } } = {
darkaura: { Dark: 1.33 },
dragonsmaw: { Dragon: 1.5 },
fairyaura: { Fairy: 1.33 },
steelworker: { Steel: 1.5 },
steelyspirit: { Steel: 1.5 },
transistor: { Electric: 1.3 },
// -ate moves
pixilate: { Normal: 1.5 * 1.2 },
refrigerate: { Normal: 1.5 * 1.2 },
aerilate: { Normal: 1.5 * 1.2 },
normalize: { Normal: 1.2 },
// weather
drizzle: { Water: 1.4, Fire: 0.6 },
drought: { Fire: 1.4, Water: 0.6 },
};
// For moves whose quality isn't obvious from data
// USE SPARINGLY!
export const HARDCODED_MOVE_WEIGHTS: { [moveID: IDEntry]: number } = {
// Fails unless user is asleep
snore: 0,
// Hard to use
lastresort: 0.1, dreameater: 0.1,
// Useless without Berry + sucks even then
belch: 0.2,
// Power increases in conditions out of our control that may occur
avalanche: 1.2,
ficklebeam: 1.3,
hex: 1.2,
stompingtantrum: 1.2,
temperflare: 1.2,
// Attacks that set hazards on hit
// We REALLY like hazards
stoneaxe: 16,
ceaselessedge: 16,
// screens
lightscreen: 3, reflect: 3, auroraveil: 3, // TODO: make sure AVeil always gets Snow?
tailwind: 2,
// mess with the opponent
taunt: 2, disable: 2, encore: 3,
// healing moves
// TODO: should healing moves be more common on bulkier pokemon?
// 25%
junglehealing: 3, lifedew: 3,
// 50%
milkdrink: 5, moonlight: 5, morningsun: 5, recover: 5, roost: 5,
shoreup: 5, slackoff: 5, softboiled: 5, synthesis: 5,
// delayed/consequence
rest: 3, // has sleeptalk potential
wish: 2,
// requires terrain
steelroller: 0.1,
};
export const WEIGHT_BASED_MOVES = ['heatcrash', 'heavyslam', 'lowkick', 'grassknot'];
export const TARGET_HP_BASED_MOVES = ['crushgrip', 'hardpress'];

File diff suppressed because it is too large Load Diff

View File

@ -91,12 +91,11 @@ export const Conditions: import('../sim/dex-conditions').ConditionDataTable = {
}
if (target.species.name === 'Shaymin-Sky' && target.baseSpecies.baseSpecies === 'Shaymin') {
target.formeChange('Shaymin', this.effect, true);
target.regressionForme = false;
}
},
onBeforeMovePriority: 10,
onBeforeMove(pokemon, target, move) {
if (move.flags['defrost']) return;
if (move.flags['defrost'] && !(move.id === 'burnup' && !pokemon.hasType('Fire'))) return;
if (this.randomChance(1, 5)) {
pokemon.cureStatus();
return;
@ -116,7 +115,7 @@ export const Conditions: import('../sim/dex-conditions').ConditionDataTable = {
}
},
onDamagingHit(damage, target, source, move) {
if (move.type === 'Fire' && move.category !== 'Status') {
if (move.type === 'Fire' && move.category !== 'Status' && move.id !== 'polarflare') {
target.cureStatus();
}
},
@ -271,6 +270,11 @@ export const Conditions: import('../sim/dex-conditions').ConditionDataTable = {
this.effectState.duration = 2;
}
},
onAfterMove(pokemon) {
if (this.effectState.duration === 1) {
pokemon.removeVolatile('lockedmove');
}
},
onEnd(target) {
if (this.effectState.trueDuration > 1) return;
target.addVolatile('confusion');
@ -875,6 +879,65 @@ 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');
pokemon.baseMoveSlots[ironHeadIndex] = {
move: move.name,
id: move.id,
pp: move.noPPBoosts ? move.pp : move.pp * 8 / 5,
maxpp: move.noPPBoosts ? move.pp : move.pp * 8 / 5,
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');
pokemon.baseMoveSlots[ironHeadIndex] = {
move: move.name,
id: move.id,
pp: move.noPPBoosts ? move.pp : move.pp * 8 / 5,
maxpp: move.noPPBoosts ? move.pp : move.pp * 8 / 5,
target: move.target,
disabled: false,
disabledSource: '',
used: false,
};
pokemon.moveSlots = pokemon.baseMoveSlots.slice();
}
},
},
rolloutstorage: {
name: 'rolloutstorage',
duration: 2,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,206 @@
export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTable = {
magician: {
inherit: true,
onAfterMoveSecondarySelf(source, target, move) {
if (!move || source.switchFlag === true || !move.hitTargets || source.item || source.volatiles['gem'] ||
move.id === 'fling' || move.category === 'Status') return;
const hitTargets = move.hitTargets;
this.speedSort(hitTargets);
for (const pokemon of hitTargets) {
if (pokemon !== source) {
const yourItem = pokemon.takeItem(source);
if (!yourItem) continue;
if (!source.setItem(yourItem)) {
if (!this.dex.items.get(yourItem.id).exists) {
pokemon.setItem(yourItem.id);
continue;
}
pokemon.item = yourItem.id; // bypass setItem so we don't break choicelock or anything
continue;
}
this.add('-item', source, yourItem, '[from] ability: Magician', `[of] ${pokemon}`);
return;
}
}
},
},
neutralizinggas: {
inherit: true,
onSwitchIn(pokemon) {
this.add('-ability', pokemon, 'Neutralizing Gas');
pokemon.abilityState.ending = false;
const strongWeathers = ['desolateland', 'primordialsea', 'deltastream'];
for (const target of this.getAllActive()) {
if (target.hasItem('Ability Shield')) {
this.add('-block', target, 'item: Ability Shield');
continue;
}
// Can't suppress a Tatsugiri inside of Dondozo already
if (target.volatiles['commanding']) {
continue;
}
if (target.illusion) {
this.singleEvent('End', this.dex.abilities.get('Illusion'), target.abilityState, target, pokemon, 'neutralizinggas');
}
if (target.volatiles['slowstart']) {
delete target.volatiles['slowstart'];
this.add('-end', target, 'Slow Start', '[silent]');
}
if (strongWeathers.includes(target.getAbility().id)) {
this.singleEvent('End', this.dex.abilities.get(target.getAbility().id), target.abilityState, target, pokemon, 'neutralizinggas');
}
if (!this.dex.abilities.get(target.ability).exists) {
const isItem = (target.m.scrambled.items as { inSlot: string }[]).findIndex(e => e.inSlot === 'Ability');
if (isItem >= 0) {
target.removeVolatile('item:' + this.toID(target.m.scrambled.items[isItem].thing));
} else if ((target.m.scrambled.moves as { inSlot: string }[]).findIndex(e => e.inSlot === 'Ability') >= 0) {
const isMove = (target.m.scrambled.moves as { inSlot: string }[]).findIndex(e => e.inSlot === 'Ability');
const indexOfMove = target.moveSlots.findIndex(m => this.toID(target.m.scrambled.moves[isMove].thing) === m.id);
if (indexOfMove >= 0) target.moveSlots.splice(indexOfMove, 1);
}
}
}
},
onEnd(source) {
if (source.transformed) return;
for (const pokemon of this.getAllActive()) {
if (pokemon !== source && pokemon.hasAbility('Neutralizing Gas')) {
return;
}
}
this.add('-end', source, 'ability: Neutralizing Gas');
// FIXME this happens before the pokemon switches out, should be the opposite order.
// Not an easy fix since we cant use a supported event. Would need some kind of special event that
// gathers events to run after the switch and then runs them when the ability is no longer accessible.
// (If you're tackling this, do note extreme weathers have the same issue)
// Mark this pokemon's ability as ending so Pokemon#ignoringAbility skips it
if (source.abilityState.ending) return;
source.abilityState.ending = true;
const sortedActive = this.getAllActive();
this.speedSort(sortedActive);
for (const pokemon of sortedActive) {
if (pokemon !== source) {
if (pokemon.getAbility().flags['cantsuppress']) continue; // does not interact with e.g Ice Face, Zen Mode
if (pokemon.hasItem('abilityshield')) continue; // don't restart abilities that weren't suppressed
// Will be suppressed by Pokemon#ignoringAbility if needed
this.singleEvent('Start', pokemon.getAbility(), pokemon.abilityState, pokemon);
if (pokemon.ability === "gluttony") {
pokemon.abilityState.gluttony = false;
}
}
if (!this.dex.abilities.get(pokemon.ability).exists) {
const isItem = (pokemon.m.scrambled.items as { inSlot: string }[]).findIndex(e => e.inSlot === 'Ability');
if (isItem >= 0) {
pokemon.addVolatile('item:' + this.toID(pokemon.m.scrambled.items[isItem].thing));
} else if ((pokemon.m.scrambled.moves as { inSlot: string }[]).findIndex(e => e.inSlot === 'Ability') >= 0) {
const findMove = (pokemon.m.scrambled.moves as { inSlot: string }[]).findIndex(e => e.inSlot === 'Ability');
const findSlot = pokemon.baseMoveSlots.find(e => e.id === this.toID(pokemon.m.scrambled.moves[findMove].thing));
pokemon.moveSlots.push(this.dex.deepClone(findSlot));
}
}
}
},
},
pickpocket: {
inherit: true,
onAfterMoveSecondary(target, source, move) {
if (source && source !== target && move?.flags['contact']) {
if (target.item || target.switchFlag || target.forceSwitchFlag || source.switchFlag === true) {
return;
}
const yourItem = source.takeItem(target);
if (!yourItem) {
return;
}
if (!target.setItem(yourItem)) {
if (!this.dex.items.get(yourItem.id).exists) {
target.setItem(yourItem.id);
return;
}
source.item = yourItem.id;
return;
}
this.add('-enditem', source, yourItem, '[silent]', '[from] ability: Pickpocket', `[of] ${source}`);
this.add('-item', target, yourItem, '[from] ability: Pickpocket', `[of] ${source}`);
}
},
},
trace: {
inherit: true,
onStart(pokemon) {
this.effectState.seek = true;
// n.b. only affects Hackmons
// interaction with No Ability is complicated: https://www.smogon.com/forums/threads/pokemon-sun-moon-battle-mechanics-research.3586701/page-76#post-7790209
if (pokemon.adjacentFoes().some(foeActive => foeActive.ability === 'noability')) {
this.effectState.seek = false;
}
// interaction with Ability Shield is similar to No Ability
if (pokemon.hasItem('Ability Shield') && this.toID(pokemon.ability) === 'trace') {
this.add('-block', pokemon, 'item: Ability Shield');
this.effectState.seek = false;
}
if (this.effectState.seek) {
this.singleEvent('Update', this.effect, this.effectState, pokemon);
}
},
onUpdate(pokemon) {
if (!this.effectState.seek) return;
const possibleTargets = pokemon.adjacentFoes().filter(
target => !target.getAbility().flags['notrace'] && target.ability !== 'noability'
);
if (!possibleTargets.length) return;
const target = this.sample(possibleTargets);
const ability = target.getAbility();
if (this.toID(pokemon.item) === 'trace') {
this.add('-ability', pokemon, ability.name, 'Trace');
pokemon.setItem(ability.name);
return;
} else if (pokemon.volatiles['ability:trace']?.inSlot === 'Move') {
if (this.dex.abilities.get(ability.name).exists) {
pokemon.removeVolatile('ability:trace');
pokemon.m.scrambled.abilities.splice(
(pokemon.m.scrambled.abilities as { thing: string, inSlot: string }[]).findIndex(e =>
this.toID(e.thing) === 'trace' && e.inSlot === 'Move'), 1);
this.add('-ability', pokemon, ability.name, 'Trace');
pokemon.addVolatile(`ability:${ability.id}`);
pokemon.m.scrambled.abilities.push({ thing: ability.name, inSlot: 'Move' });
} else if (this.dex.items.get(ability.name).exists) {
pokemon.removeVolatile('ability:trace');
pokemon.m.scrambled.abilities.splice(
(pokemon.m.scrambled.abilities as { thing: string, inSlot: string }[]).findIndex(e =>
this.toID(e.thing) === 'trace' && e.inSlot === 'Move'), 1);
this.add('-ability', pokemon, ability.name, 'Trace');
pokemon.addVolatile(`item:${ability.id}`);
pokemon.m.scrambled.items.push({ thing: this.dex.items.get(ability.name).name, inSlot: 'Move' });
} else {
const move = this.dex.moves.get(ability.name);
if (move.exists) {
pokemon.removeVolatile('ability:trace');
pokemon.m.scrambled.abilities.splice(
(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 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,
target: move.target,
disabled: false,
used: false,
};
pokemon.baseMoveSlots.push(newMove);
pokemon.moveSlots.push(newMove);
}
}
return;
}
pokemon.setAbility(ability, target);
},
},
};

View File

@ -0,0 +1,44 @@
export const Conditions: import('../../../sim/dex-conditions').ModdedConditionDataTable = {
choicelock: {
inherit: true,
onBeforeMove(pokemon, target, move) {
const choiceItem = pokemon.getItem().isChoice ||
Object.keys(pokemon.volatiles).some(v => (
v.startsWith('item:') && this.dex.items.get(v.split(':')[1]).isChoice
));
if (!choiceItem) {
pokemon.removeVolatile('choicelock');
return;
}
if (
!pokemon.ignoringItem() && !pokemon.volatiles['dynamax'] &&
move.id !== this.effectState.move && move.id !== 'struggle'
) {
// Fails unless the Choice item is being ignored, and no PP is lost
this.addMove('move', pokemon, move.name);
this.attrLastMove('[still]');
this.debug("Disabled by Choice item lock");
this.add('-fail', pokemon);
return false;
}
},
onDisableMove(pokemon) {
const choiceItem = pokemon.getItem().isChoice ||
Object.keys(pokemon.volatiles).some(v => (
v.startsWith('item:') && this.dex.items.get(v.split(':')[1]).isChoice
));
if (!choiceItem || !pokemon.hasMove(this.effectState.move)) {
pokemon.removeVolatile('choicelock');
return;
}
if (pokemon.ignoringItem() || pokemon.volatiles['dynamax']) {
return;
}
for (const moveSlot of pokemon.moveSlots) {
if (moveSlot.id !== this.effectState.move) {
pokemon.disableMove(moveSlot.id, false, this.effectState.sourceEffect);
}
}
},
},
};

View File

@ -0,0 +1,41 @@
export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
airballoon: {
inherit: true,
// airborneness implemented in sim/pokemon.js:Pokemon#isGrounded
onDamagingHit(damage, target, source, move) {
this.add('-enditem', target, 'Air Balloon');
if (target.item === 'airballoon') {
target.item = '';
this.clearEffectState(target.itemState);
} else {
const isBMM = target.volatiles['item:airballoon']?.inSlot;
if (isBMM) {
target.removeVolatile('item:airballoon');
target.m.scrambled.items.splice((target.m.scrambled.items as { thing: string, inSlot: string }[]).findIndex(e =>
this.toID(e.thing) === 'airballoon' && e.inSlot === isBMM), 1);
if (isBMM === 'Ability') target.setAbility('No Ability');
}
}
this.runEvent('AfterUseItem', target, null, null, this.dex.items.get('airballoon'));
},
onAfterSubDamage(damage, target, source, effect) {
this.debug('effect: ' + effect.id);
if (effect.effectType === 'Move') {
this.add('-enditem', target, 'Air Balloon');
if (target.item === 'airballoon') {
target.item = '';
this.clearEffectState(target.itemState);
} else {
const isBMM = target.volatiles['item:airballoon']?.inSlot;
if (isBMM) {
target.removeVolatile('item:airballoon');
target.m.scrambled.items.splice((target.m.scrambled.items as { thing: string, inSlot: string }[]).findIndex(e =>
this.toID(e.thing) === 'airballoon' && e.inSlot === isBMM), 1);
if (isBMM === 'Ability') target.setAbility('No Ability');
}
}
this.runEvent('AfterUseItem', target, null, null, this.dex.items.get('airballoon'));
}
},
},
};

View File

@ -0,0 +1,419 @@
export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
// Remember, everything deals with SLOTS not with properties as they are!
covet: {
inherit: true,
onAfterHit(target, source, move) {
if (source.item || source.volatiles['gem']) {
return;
}
const yourItem = target.takeItem(source);
if (!yourItem) {
return;
}
if (
!this.singleEvent('TakeItem', yourItem, target.itemState, source, target, move, yourItem) ||
!source.setItem(yourItem)
) {
if (!this.dex.items.get(yourItem.id).exists) {
target.setItem(yourItem.id);
return;
}
target.item = yourItem.id; // bypass setItem so we don't break choicelock or anything
return;
}
this.add('-item', source, yourItem, '[from] move: Covet', `[of] ${target}`);
},
},
embargo: {
inherit: true,
condition: {
duration: 5,
onStart(pokemon) {
this.add('-start', pokemon, 'Embargo');
this.singleEvent('End', pokemon.getItem(), pokemon.itemState, pokemon);
if (!this.dex.items.get(pokemon.item).exists) {
const isAbil = (pokemon.m.scrambled.abilities as { inSlot: string }[]).findIndex(e => e.inSlot === 'Item');
if (isAbil >= 0) {
pokemon.removeVolatile('ability:' + this.toID(pokemon.m.scrambled.abilities[isAbil].thing));
} else if ((pokemon.m.scrambled.moves as { inSlot: string }[]).findIndex(e => e.inSlot === 'Item') >= 0) {
const isMove = (pokemon.m.scrambled.moves as { inSlot: string }[]).findIndex(e => e.inSlot === 'Item');
const slotNo = pokemon.moveSlots.findIndex(m => this.toID(pokemon.m.scrambled.moves[isMove].thing) === m.id);
if (slotNo >= 0) pokemon.moveSlots.splice(slotNo, 1);
}
}
},
// Item suppression implemented in Pokemon.ignoringItem() within sim/pokemon.js
onResidualOrder: 21,
onEnd(pokemon) {
this.add('-end', pokemon, 'Embargo');
if (!this.dex.items.get(pokemon.item).exists) {
const isAbil = (pokemon.m.scrambled.abilities as { inSlot: string }[]).findIndex(e => e.inSlot === 'Item');
if (isAbil >= 0) {
pokemon.addVolatile('ability:' + this.toID(pokemon.m.scrambled.abilities[isAbil].thing));
} else if ((pokemon.m.scrambled.moves as { inSlot: string }[]).findIndex(e => e.inSlot === 'Item') >= 0) {
const findMove = (pokemon.m.scrambled.moves as { inSlot: string }[]).findIndex(e => e.inSlot === 'Item');
const findSlot = pokemon.baseMoveSlots.find(e => e.id === this.toID(pokemon.m.scrambled.moves[findMove].thing));
pokemon.moveSlots.push(this.dex.deepClone(findSlot));
}
}
},
},
},
magicroom: {
inherit: true,
condition: {
duration: 5,
durationCallback(source, effect) {
if (source?.hasAbility('persistent')) {
this.add('-activate', source, 'ability: Persistent', '[move] Magic Room');
return 7;
}
return 5;
},
onFieldStart(target, source) {
if (source?.hasAbility('persistent')) {
this.add('-fieldstart', 'move: Magic Room', `[of] ${source}`, '[persistent]');
} else {
this.add('-fieldstart', 'move: Magic Room', `[of] ${source}`);
}
for (const mon of this.getAllActive()) {
this.singleEvent('End', mon.getItem(), mon.itemState, mon);
if (!this.dex.items.get(mon.item).exists) {
const isAbil = (mon.m.scrambled.abilities as { inSlot: string }[]).findIndex(e => e.inSlot === 'Item');
if (isAbil >= 0) {
mon.removeVolatile('ability:' + this.toID(mon.m.scrambled.abilities[isAbil].thing));
} else if ((mon.m.scrambled.moves as { inSlot: string }[]).findIndex(e => e.inSlot === 'Item') >= 0) {
const isMove = (mon.m.scrambled.moves as { inSlot: string }[]).findIndex(e => e.inSlot === 'Item');
const slotNo = mon.moveSlots.findIndex(m => this.toID(mon.m.scrambled.moves[isMove].thing) === m.id);
if (slotNo >= 0) mon.moveSlots.splice(slotNo, 1);
}
}
}
},
onFieldRestart(target, source) {
this.field.removePseudoWeather('magicroom');
},
// Item suppression implemented in Pokemon.ignoringItem() within sim/pokemon.js
onFieldResidualOrder: 27,
onFieldResidualSubOrder: 6,
onFieldEnd() {
this.add('-fieldend', 'move: Magic Room', '[of] ' + this.effectState.source);
for (const pokemon of this.getAllActive()) {
if (!this.dex.items.get(pokemon.item).exists) {
const isAbil = (pokemon.m.scrambled.abilities as { inSlot: string }[]).findIndex(e => e.inSlot === 'Item');
if (isAbil >= 0) {
pokemon.addVolatile('ability:' + this.toID(pokemon.m.scrambled.abilities[isAbil].thing));
} else if ((pokemon.m.scrambled.moves as { inSlot: string }[]).findIndex(e => e.inSlot === 'Item') >= 0) {
const findMove = (pokemon.m.scrambled.moves as { inSlot: string }[]).findIndex(e => e.inSlot === 'Item');
const findSlot = pokemon.baseMoveSlots.find(e => e.id === this.toID(pokemon.m.scrambled.moves[findMove].thing));
pokemon.moveSlots.push(this.dex.deepClone(findSlot));
}
}
}
},
},
},
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 (!this.dex.abilities.get(pokemon.ability).exists) {
const isItem = (pokemon.m.scrambled.items as { inSlot: string }[]).findIndex(e => e.inSlot === 'Ability');
if (isItem >= 0) {
pokemon.removeVolatile('item:' + this.toID(pokemon.m.scrambled.items[isItem].thing));
} else if ((pokemon.m.scrambled.moves as { inSlot: string }[]).findIndex(e => e.inSlot === 'Ability') >= 0) {
const isMove = (pokemon.m.scrambled.moves as { inSlot: string }[]).findIndex(e => e.inSlot === 'Ability');
const slotNo = pokemon.moveSlots.findIndex(m => this.toID(pokemon.m.scrambled.moves[isMove].thing) === m.id);
if (slotNo >= 0) pokemon.moveSlots.splice(slotNo, 1);
}
}
},
},
},
trick: {
inherit: true,
onHit(target, source, move) {
const yourItem = target.takeItem(source);
const myItem = source.takeItem();
if (target.item || source.item || (!yourItem && !myItem)) {
if (yourItem) {
if (!this.dex.items.get(yourItem.id).exists) {
target.setItem(yourItem.id);
} else {
target.item = yourItem.id;
}
}
if (myItem) {
if (!this.dex.items.get(myItem.id).exists) {
source.setItem(myItem.id);
} else {
source.item = myItem.id;
}
}
return false;
}
if (
(myItem && !this.singleEvent('TakeItem', myItem, source.itemState, target, source, move, myItem)) ||
(yourItem && !this.singleEvent('TakeItem', yourItem, target.itemState, source, target, move, yourItem))
) {
if (yourItem) {
if (!this.dex.items.get(yourItem.id).exists) {
target.setItem(yourItem.id);
} else {
target.item = yourItem.id;
}
}
if (myItem) {
if (!this.dex.items.get(myItem.id).exists) {
source.setItem(myItem.id);
} else {
source.item = myItem.id;
}
}
return false;
}
this.add('-activate', source, 'move: Trick', `[of] ${target}`);
if (myItem) {
target.setItem(myItem);
this.add('-item', target, myItem, '[from] move: Trick');
} else {
this.add('-enditem', target, yourItem, '[silent]', '[from] move: Trick');
}
if (yourItem) {
source.setItem(yourItem);
this.add('-item', source, yourItem, '[from] move: Trick');
} else {
this.add('-enditem', source, myItem, '[silent]', '[from] move: Trick');
}
},
},
sketch: {
inherit: true,
onHit(target, source) {
const move = target.lastMove;
if (source.transformed || !move || source.moves.includes(move.id)) return false;
if (move.flags['nosketch'] || move.isZ || move.isMax) return false;
const sketchIndex = source.moves.indexOf('sketch');
if (sketchIndex < 0) return false;
if (this.toID(source.item) === 'sketch') {
source.setItem(move.name);
this.add('-activate', source, 'move: Sketch', move.name);
return;
} else if (this.toID(source.ability) === 'sketch') {
source.setAbility(move.name);
this.add('-activate', source, 'move: Sketch', move.name);
return;
}
const sketchedMove = {
move: move.name,
id: move.id,
pp: move.pp,
maxpp: move.pp,
target: move.target,
disabled: false,
used: false,
};
source.moveSlots[sketchIndex] = sketchedMove;
source.baseMoveSlots[sketchIndex] = sketchedMove;
this.add('-activate', source, 'move: Sketch', move.name);
},
},
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();
const sourceIsBMM = !this.dex.abilities.get(sourceAbility).exists;
const targetIsBMM = !this.dex.abilities.get(targetAbility).exists;
if (target.isAlly(source)) {
this.add('-activate', source, 'move: Skill Swap', '', '', `[of] ${target}`);
} else {
this.add('-activate', source, 'move: Skill Swap', targetAbility, sourceAbility, `[of] ${target}`);
}
this.singleEvent('End', sourceAbility, source.abilityState, source);
if (sourceIsBMM) {
const isItem = (source.m.scrambled.items as { inSlot: string }[]).findIndex(e => e.inSlot === 'Ability');
if (isItem >= 0) {
source.removeVolatile('item:' + this.toID(source.m.scrambled.items[isItem].thing));
source.m.scrambled.items.splice(isItem, 1);
} else if ((source.m.scrambled.moves as { inSlot: string }[]).findIndex(e => e.inSlot === 'Ability') >= 0) {
const isMove = (source.m.scrambled.moves as { inSlot: string }[]).findIndex(e => e.inSlot === 'Ability');
source.baseMoveSlots.splice(
source.baseMoveSlots.findIndex(m => this.toID(source.m.scrambled.moves[isMove].thing) === m.id), 1);
source.moveSlots.splice(source.moveSlots.findIndex(m => this.toID(source.m.scrambled.moves[isMove].thing) === m.id), 1);
source.m.scrambled.moves.splice(isMove, 1);
}
}
this.singleEvent('End', targetAbility, target.abilityState, target);
if (targetIsBMM) {
const isItem = (target.m.scrambled.items as { inSlot: string }[]).findIndex(e => e.inSlot === 'Ability');
if (isItem >= 0) {
target.removeVolatile('item:' + this.toID(target.m.scrambled.items[isItem].thing));
target.m.scrambled.items.splice(isItem, 1);
} else if ((target.m.scrambled.moves as { inSlot: string }[]).findIndex(e => e.inSlot === 'Ability') >= 0) {
const isMove = (target.m.scrambled.moves as { inSlot: string }[]).findIndex(e => e.inSlot === 'Ability');
target.baseMoveSlots.splice(
target.baseMoveSlots.findIndex(m => this.toID(target.m.scrambled.moves[isMove].thing) === m.id), 1);
target.moveSlots.splice(target.moveSlots.findIndex(m => this.toID(target.m.scrambled.moves[isMove].thing) === m.id), 1);
target.m.scrambled.moves.splice(isMove, 1);
}
}
source.ability = source.baseAbility = targetAbility.id;
target.ability = target.baseAbility = sourceAbility.id;
source.abilityState = this.initEffectState({ id: this.toID(source.ability), target: source });
target.abilityState = this.initEffectState({ id: this.toID(target.ability), target });
source.volatileStaleness = undefined;
if (!target.isAlly(source)) target.volatileStaleness = 'external';
this.singleEvent('Start', targetAbility, source.abilityState, source);
if (targetIsBMM) {
if (this.dex.items.get(targetAbility.id).exists) {
source.m.scrambled.items.push({ thing: targetAbility.id, inSlot: 'Ability' });
const effect = 'item:' + this.toID(targetAbility.id);
source.addVolatile(effect);
source.volatiles[effect].inSlot = 'Ability';
} else {
source.m.scrambled.moves.push({ thing: targetAbility.id, inSlot: 'Ability' });
const bmmMove = Dex.moves.get(targetAbility.id);
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,
target: bmmMove.target,
disabled: false,
used: false,
};
source.baseMoveSlots.push(newMove);
source.moveSlots.push(newMove);
}
}
this.singleEvent('Start', sourceAbility, target.abilityState, target);
if (sourceIsBMM) {
if (this.dex.items.get(sourceAbility.id).exists) {
target.m.scrambled.items.push({ thing: sourceAbility.id, inSlot: 'Ability' });
const effect = 'item:' + this.toID(sourceAbility.id);
target.addVolatile(effect);
target.volatiles[effect].inSlot = 'Ability';
} else {
target.m.scrambled.moves.push({ thing: sourceAbility.id, inSlot: 'Ability' });
const bmmMove = Dex.moves.get(sourceAbility.id);
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,
target: bmmMove.target,
disabled: false,
used: false,
};
target.baseMoveSlots.push(newMove);
target.moveSlots.push(newMove);
}
}
},
},
switcheroo: {
inherit: true,
onHit(target, source, move) {
const yourItem = target.takeItem(source);
const myItem = source.takeItem();
if (target.item || source.item || (!yourItem && !myItem)) {
if (yourItem) {
if (!this.dex.items.get(yourItem.id).exists) {
target.setItem(yourItem.id);
} else {
target.item = yourItem.id;
}
}
if (myItem) {
if (!this.dex.items.get(myItem.id).exists) {
source.setItem(myItem.id);
} else {
source.item = myItem.id;
}
}
return false;
}
if (
(myItem && !this.singleEvent('TakeItem', myItem, source.itemState, target, source, move, myItem)) ||
(yourItem && !this.singleEvent('TakeItem', yourItem, target.itemState, source, target, move, yourItem))
) {
if (yourItem) {
if (!this.dex.items.get(yourItem.id).exists) {
target.setItem(yourItem.id);
} else {
target.item = yourItem.id;
}
}
if (myItem) {
if (!this.dex.items.get(myItem.id).exists) {
source.setItem(myItem.id);
} else {
source.item = myItem.id;
}
}
return false;
}
this.add('-activate', source, 'move: Trick', `[of] ${target}`);
if (myItem) {
target.setItem(myItem);
this.add('-item', target, myItem, '[from] move: Switcheroo');
} else {
this.add('-enditem', target, yourItem, '[silent]', '[from] move: Switcheroo');
}
if (yourItem) {
source.setItem(yourItem);
this.add('-item', source, yourItem, '[from] move: Switcheroo');
} else {
this.add('-enditem', source, myItem, '[silent]', '[from] move: Switcheroo');
}
},
},
thief: {
inherit: true,
onAfterHit(target, source, move) {
if (source.item || source.volatiles['gem']) {
return;
}
const yourItem = target.takeItem(source);
if (!yourItem) {
return;
}
if (!this.singleEvent('TakeItem', yourItem, target.itemState, source, target, move, yourItem) ||
!source.setItem(yourItem)) {
if (!this.dex.items.get(yourItem.id).exists) {
target.setItem(yourItem.id);
return;
}
target.item = yourItem.id; // bypass setItem so we don't break choicelock or anything
return;
}
this.add('-enditem', target, yourItem, '[silent]', '[from] move: Thief', `[of] ${source}`);
this.add('-item', source, yourItem, '[from] move: Thief', `[of] ${target}`);
},
},
};

View File

@ -0,0 +1,584 @@
import { RESTORATIVE_BERRIES } from "../../../sim/pokemon";
export const Scripts: ModdedBattleScriptsData = {
pokemon: {
isGrounded(negateImmunity) {
if ('gravity' in this.battle.field.pseudoWeather) return true;
if ('ingrain' in this.volatiles && this.battle.gen >= 4) return true;
if ('smackdown' in this.volatiles) return true;
const item = (this.ignoringItem() ? '' : this.item);
if (item === 'ironball' || (this.volatiles['item:ironball'] && !this.ignoringItem())) return true;
// If a Fire/Flying type uses Burn Up and Roost, it becomes ???/Flying-type, but it's still grounded.
if (!negateImmunity && this.hasType('Flying') && !(this.hasType('???') && 'roost' in this.volatiles)) return false;
if (this.hasAbility('levitate') && !this.battle.suppressingAbility(this)) return null;
if ('magnetrise' in this.volatiles) return false;
if ('telekinesis' in this.volatiles) return false;
if (item === 'airballoon' || (this.volatiles['item:airballoon'] && !this.ignoringItem())) return false;
return true;
},
getAbility() {
const ability = this.battle.dex.abilities.getByID(this.ability);
if (ability.exists) return ability;
let abil = this.battle.dex.items.getByID(this.ability) as Item | Move;
if (!abil.exists) abil = this.battle.dex.moves.getByID(this.ability);
return {
id: this.ability,
name: abil.name || this.ability,
flags: {},
effectType: "Ability",
toString() {
return abil.name || this.id;
},
} as Ability;
},
hasAbility(ability) {
if (this.ignoringAbility()) return false;
if (Array.isArray(ability)) return ability.some(abil => this.hasAbility(abil));
const abilityid = this.battle.toID(ability);
return this.ability === abilityid || !!this.volatiles['ability:' + abilityid];
},
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.scrambled.abilities as { thing: string }[]).some(
abils => this.battle.toID(abils.thing) === '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.scrambled.abilities as { thing: string }[]).some(abils => this.battle.toID(abils.thing) === 'neutralizinggas'))
)) && !this.getAbility().flags['cantsuppress']
)
);
},
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 (typeof ability === 'string') {
if (this.battle.dex.abilities.get(ability).exists) {
ability = this.battle.dex.abilities.get(ability);
} else {
const abilString = ability;
let abil = this.battle.dex.items.get(abilString) as Item | Move;
if (!abil.exists) abil = this.battle.dex.moves.get(abilString);
ability = {
id: abil.id || abilString,
name: abil.name || abilString,
flags: {},
effectType: "Ability",
toString() {
return abil.name || abilString;
},
} 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);
} else {
if (!this.battle.runEvent('TakeItem', this, source, null, abil as Item)) return false;
}
oldAbility = {
id: this.ability,
name: abil.name || this.ability,
flags: {},
effectType: "Ability",
toString() {
return abil.name || this.id;
},
} as Ability;
isOldBMMAbil = true;
}
if (allThings.has(ability.id)) return false;
if (!isFromFormeChange) {
if (ability.flags['cantsuppress'] || this.getAbility().flags['cantsuppress']) return false;
}
if (!isFromFormeChange && !isTransform) {
const setAbilityEvent: boolean | null = this.battle.runEvent('SetAbility', this, source, sourceEffect, ability);
if (!setAbilityEvent) return setAbilityEvent;
}
this.battle.singleEvent('End', oldAbility, this.abilityState, this, source);
if (isOldBMMAbil) {
const isItem = (this.m.scrambled.items as { inSlot: string }[]).findIndex(e => e.inSlot === 'Ability');
if (isItem >= 0) {
this.removeVolatile('item:' + this.battle.toID(this.m.scrambled.items[isItem].thing));
this.m.scrambled.items.splice(isItem, 1);
} else if ((this.m.scrambled.moves as { inSlot: string }[]).findIndex(e => e.inSlot === 'Ability') >= 0) {
const isMove = (this.m.scrambled.moves as { inSlot: string }[]).findIndex(e => e.inSlot === 'Ability');
if (!isTransform) {
let indexOfMove = this.baseMoveSlots.findIndex(m => this.battle.toID(this.m.scrambled.moves[isMove].thing) === m.id);
if (indexOfMove >= 0) this.baseMoveSlots.splice(indexOfMove, 1);
if (oldAbility.id !== 'mimic') {
indexOfMove = this.moveSlots.findIndex(m => this.battle.toID(this.m.scrambled.moves[isMove].thing) === m.id);
}
if (indexOfMove >= 0) this.moveSlots.splice(indexOfMove, 1);
}
this.m.scrambled.moves.splice(isMove, 1);
}
}
this.ability = ability.id;
// ability changes are permanent in BioMechMons
if (!isTransform && !this.transformed) this.baseAbility = ability.id;
this.abilityState = this.battle.initEffectState({ id: ability.id, target: this });
if (sourceEffect && !isFromFormeChange && !isTransform) {
if (source) {
this.battle.add('-ability', this, ability.name, oldAbility.name, `[from] ${sourceEffect.fullname}`, `[of] ${source}`);
} else {
this.battle.add('-ability', this, ability.name, oldAbility.name, `[from] ${sourceEffect.fullname}`);
}
}
if (ability.id && this.battle.gen > 3 &&
(!isTransform || oldAbility.id !== ability.id || this.battle.gen <= 4)) {
this.battle.singleEvent('Start', ability, this.abilityState, this, source);
}
if (isBMMAbil) {
if (this.battle.dex.items.get(ability.id).exists) {
this.m.scrambled.items.push({ thing: ability.id, inSlot: 'Ability' });
const effect = 'item:' + this.battle.toID(ability.id);
this.addVolatile(effect);
this.volatiles[effect].inSlot = 'Ability';
} else {
this.m.scrambled.moves.push({ thing: ability.id, inSlot: 'Ability' });
const move = Dex.moves.get(ability.id);
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,
target: move.target,
disabled: false,
used: false,
};
if (!isTransform) {
this.baseMoveSlots.push(newMove);
this.moveSlots.push(newMove);
}
}
}
return oldAbility.id;
},
getItem() {
const item = this.battle.dex.items.getByID(this.item);
if (item.exists) return item;
let bmmItem = this.battle.dex.abilities.getByID(this.item) as Ability | Move;
if (!bmmItem.exists) bmmItem = this.battle.dex.moves.getByID(this.item);
return {
id: this.item,
name: bmmItem.name || this.name,
effectType: "Item",
toString() {
return bmmItem.name || this.id;
},
} as Item;
},
hasItem(item) {
if (this.ignoringItem()) return false;
if (Array.isArray(item)) return item.some(i => this.hasItem(i));
const itemId = this.battle.toID(item);
return this.item === itemId || !!this.volatiles['item:' + itemId];
},
takeItem(source) {
if (!this.item) return false;
if (!source) source = this;
if (this.battle.gen <= 4) {
if (source.itemKnockedOff) 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) {
wrongSlot = (this.m.scrambled.moves as { inSlot: string }[]).findIndex(e => e.inSlot === 'Item');
let indexOfMove = this.baseMoveSlots.findIndex(m => this.battle.toID(this.m.scrambled.moves[wrongSlot].thing) === m.id);
if (indexOfMove >= 0) this.baseMoveSlots.splice(indexOfMove, 1);
if (item.id !== 'mimic') {
indexOfMove = this.moveSlots.findIndex(m => this.battle.toID(this.m.scrambled.moves[wrongSlot].thing) === m.id);
}
if (indexOfMove >= 0) this.moveSlots.splice(indexOfMove, 1);
this.m.scrambled.moves.splice(wrongSlot, 1);
}
const oldItemState = this.itemState;
this.battle.clearEffectState(this.itemState);
this.pendingStaleness = undefined;
this.battle.singleEvent('End', item, oldItemState, this);
this.battle.runEvent('AfterTakeItem', this, null, null, item);
return item;
}
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 (typeof item === 'string') {
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);
} else {
if ((newData as Ability).flags['failskillswap']) return false;
}
item = {
id: newData.id || itemString,
name: newData.name || itemString,
effectType: "Item",
toString() {
return newData.name || itemString;
},
} 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);
const external = inflicted && source && !source.isAlly(this);
this.pendingStaleness = external ? 'external' : 'internal';
} else {
this.pendingStaleness = undefined;
}
const oldItem = this.getItem();
if (!this.battle.dex.items.get(oldItem).exists) isOldBMMItem = true;
const oldItemState = this.itemState;
this.item = item.id;
this.itemState = this.battle.initEffectState({ id: item.id, target: this });
if (oldItem.exists) this.battle.singleEvent('End', oldItem, oldItemState, this);
if (isOldBMMItem) {
const isAbil = (this.m.scrambled.abilities as { inSlot: string }[]).findIndex(e => e.inSlot === 'Item');
if (isAbil >= 0) {
this.removeVolatile('ability:' + this.battle.toID(this.m.scrambled.items[isAbil].thing));
this.m.scrambled.abilities.splice(isAbil, 1);
} else if ((this.m.scrambled.moves as { inSlot: string }[]).findIndex(e => e.inSlot === 'Item') >= 0) {
const isMove = (this.m.scrambled.moves as { inSlot: string }[]).findIndex(e => e.inSlot === 'Item');
let indexOfMove = this.baseMoveSlots.findIndex(m => this.battle.toID(this.m.scrambled.moves[isMove].thing) === m.id);
if (indexOfMove >= 0) this.baseMoveSlots.splice(indexOfMove, 1);
if (oldItem.id !== 'mimic') {
indexOfMove = this.moveSlots.findIndex(m => this.battle.toID(this.m.scrambled.moves[isMove].thing) === m.id);
}
if (indexOfMove >= 0) this.moveSlots.splice(indexOfMove, 1);
this.m.scrambled.moves.splice(isMove, 1);
}
}
if (item.id) {
this.battle.singleEvent('Start', item, this.itemState, this, source, effect);
}
if (isBMMItem) {
if (this.battle.dex.abilities.get(item.id).exists) {
this.m.scrambled.abilities.push({ thing: item.id, inSlot: 'Item' });
const abileffect = 'ability:' + this.battle.toID(item.id);
this.addVolatile(abileffect);
this.volatiles[abileffect].inSlot = 'Item';
} else {
this.m.scrambled.moves.push({ thing: item.id, inSlot: 'Item' });
const move = Dex.moves.get(item.id);
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,
target: move.target,
disabled: false,
used: false,
};
this.baseMoveSlots.push(newMove);
this.moveSlots.push(newMove);
}
}
return true;
},
eatItem(force, source, sourceEffect) {
const item = sourceEffect?.effectType === 'Item' ? sourceEffect :
this.battle.effect.effectType === 'Item' ? this.battle.effect : this.getItem();
if (!item) return false;
if ((!this.hp && this.battle.toID(item.name) !== 'jabocaberry' && this.battle.toID(item.name) !== 'rowapberry') ||
!this.isActive) return false;
if (!sourceEffect && this.battle.effect) sourceEffect = this.battle.effect;
if (!source && this.battle.event?.target) source = this.battle.event.target;
// if (sourceEffect?.effectType === 'Item' && this.item !== sourceEffect.id && source === this) {
// // if an item is telling us to eat it but we aren't holding it, we probably shouldn't eat what we are holding
// return false;
// }
if (
this.battle.runEvent('UseItem', this, null, null, Dex.items.get(item.name)) &&
(force || this.battle.runEvent('TryEatItem', this, null, null, Dex.items.get(item.name)))
) {
this.battle.add('-enditem', this, Dex.items.get(item.name), '[eat]');
this.battle.singleEvent('Eat', Dex.items.get(item.name), this.itemState, this, source, sourceEffect);
this.battle.runEvent('EatItem', this, source, sourceEffect, Dex.items.get(item.name));
if (RESTORATIVE_BERRIES.has(item.id)) {
switch (this.pendingStaleness) {
case 'internal':
if (this.staleness !== 'external') this.staleness = 'internal';
break;
case 'external':
this.staleness = 'external';
break;
}
this.pendingStaleness = undefined;
}
const isBMM = this.volatiles[item.id]?.inSlot;
if (isBMM) {
const dexItem = this.battle.dex.items.get(item.name);
this.removeVolatile(item.id);
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;
this.item = '';
}
this.battle.clearEffectState(this.itemState);
this.usedItemThisTurn = true;
this.ateBerry = true;
this.battle.runEvent('AfterUseItem', this, null, null, Dex.items.get(item.name));
return true;
}
return false;
},
useItem(source, sourceEffect) {
const item = sourceEffect?.effectType === 'Item' ? sourceEffect :
this.battle.effect.effectType === 'Item' ? this.battle.effect : this.getItem();
if ((!this.hp && !item.isGem) || !this.isActive) return false;
if (!item) return false;
if (!sourceEffect && this.battle.effect) sourceEffect = this.battle.effect;
if (!source && this.battle.event?.target) source = this.battle.event.target;
// const item = this.getItem();
// if (sourceEffect?.effectType === 'Item' && this.item !== sourceEffect.id && source === this) {
// // if an item is telling us to eat it but we aren't holding it, we probably shouldn't eat what we are holding
// return false;
// }
if (this.battle.runEvent('UseItem', this, null, null, Dex.items.get(item.name))) {
switch (item.id) {
case 'redcard':
this.battle.add('-enditem', this, Dex.items.get(item.name), `[of] ${source}`);
break;
default:
if (item.isGem) {
this.battle.add('-enditem', this, Dex.items.get(item.name), '[from] gem');
} else {
this.battle.add('-enditem', this, Dex.items.get(item.name));
}
break;
}
if (item.boosts) {
this.battle.boost(item.boosts, this, source, Dex.items.get(item.name));
}
this.battle.singleEvent('Use', Dex.items.get(item.name), this.itemState, this, source, sourceEffect);
const isBMM = this.volatiles[item.id]?.inSlot;
if (isBMM) {
const dexItem = this.battle.dex.items.get(item.name);
this.removeVolatile(item.id);
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;
this.item = '';
}
this.battle.clearEffectState(this.itemState);
this.usedItemThisTurn = true;
this.battle.runEvent('AfterUseItem', this, null, null, item);
return true;
}
return false;
},
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' ||
(['Ogerpon', 'Terapagos'].includes(species.baseSpecies) && (this.terastallized || pokemon.terastallized)) ||
this.terastallized === 'Stellar'
) {
return false;
}
if (this.battle.dex.currentMod === 'gen1stadium' && (
species.name === 'Ditto' ||
(this.species.name === 'Ditto' && pokemon.moves.includes('transform'))
)) {
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.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 remove all of the overlapping crit volatiles before adding 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.knownType = true;
this.apparentType = this.terastallized;
}
if (this.battle.gen > 2) this.setAbility(pokemon.ability, this, null, true, true);
// 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);
}
}
}
// Pokemon transformed into Ogerpon cannot Terastallize
// restoring their ability to tera after they untransform is handled ELSEWHERE
if (['Ogerpon', 'Terapagos'].includes(this.species.baseSpecies) && this.canTerastallize) this.canTerastallize = false;
for (const volatile in this.volatiles) {
if (this.volatiles[volatile].inSlot && this.volatiles[volatile].inSlot === 'Move') {
this.removeVolatile(volatile);
}
}
for (const volatile in pokemon.volatiles) {
if (pokemon.volatiles[volatile].inSlot && pokemon.volatiles[volatile].inSlot === 'Move') {
this.addVolatile(volatile);
this.volatiles[volatile].inSlot = 'Move';
}
}
return true;
},
},
field: {
suppressingWeather() {
for (const pokemon of this.battle.getAllActive()) {
const innates = Object.keys(pokemon.volatiles).filter(x => x.startsWith('ability:'));
if (pokemon && !pokemon.ignoringAbility() &&
(pokemon.getAbility().suppressWeather || innates.some(x => (
this.battle.dex.abilities.get(x.replace('ability:', '')).suppressWeather
)))) {
return true;
}
}
return false;
},
},
};

View File

@ -0,0 +1,993 @@
export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTable = {
thickfat: {
// prevents burning
inherit: true,
onUpdate(pokemon) {
if (pokemon.status === 'brn') {
this.add('-activate', pokemon, 'ability: Thick Fat');
pokemon.cureStatus();
}
},
onSetStatus(status, target, source, effect) {
if (status.id !== 'brn') return;
if ((effect as Move)?.status) {
this.add('-immune', target, '[from] ability: Thick Fat');
}
return false;
},
shortDesc: "-50% damage from Fire and Ice. Burn immune.",
},
callillumise: {
onDamagePriority: -30,
onDamage(damage, target, source, effect) {
if (damage >= target.hp) {
this.add('-ability', target, 'Call Illumise');
this.effectState.callillumise = true;
return target.hp - 1;
}
},
onUpdate(pokemon) {
if (!this.effectState.callillumise) return;
this.add('-message', `Volbeat calls upon Illumise for aid!`);
// Define new moves
const newMoves = ['bugbuzz', 'icebeam', 'thunderbolt', 'quiverdance'];
// Update move slots
pokemon.moveSlots = newMoves.map(move => {
const moveData = this.dex.moves.get(move);
return {
move: moveData.name,
id: moveData.id,
pp: moveData.pp,
maxpp: moveData.pp,
target: moveData.target,
disabled: false,
used: false,
};
});
// this forces the UI to update move slots visually
(pokemon as any).baseMoveSlots = pokemon.moveSlots.slice();
// removes status/boosts
pokemon.cureStatus();
pokemon.clearBoosts();
// forces the UI to update part II
this.add('-clearboost', pokemon, '[from] ability: Call Illumise', '[silent]');
for (const volatile in pokemon.volatiles) {
this.add('-end', pokemon, volatile);
}
pokemon.clearVolatile(true);
// form change + heal
pokemon.formeChange('Illumise', null, true);
this.heal(pokemon.maxhp);
// sets new ability
pokemon.setAbility('Tinted Lens', null, null, true);
pokemon.baseAbility = pokemon.ability;
this.add('-ability', pokemon, 'Tinted Lens');
},
flags: {
breakable: 1, failroleplay: 1, noreceiver: 1, noentrain: 1, notrace: 1, failskillswap: 1, notransform: 1,
},
name: "Call Illumise",
rating: 5,
num: -100,
shortDesc: "When Volbeat gets low on HP, it calls Illumise for aid.",
},
callvolbeat: {
onDamagePriority: -30,
onDamage(damage, target, source, effect) {
if (damage >= target.hp) {
this.add('-ability', target, 'Call Volbeat');
this.effectState.callvolbeat = true;
return target.hp - 1;
}
},
onUpdate(pokemon) {
if (!this.effectState.callvolbeat) return;
this.add('-message', `Illumise calls upon Volbeat for aid!`);
// Define new moves
const newMoves = ['victorydance', 'lunge', 'mightycleave', 'earthquake'];
// Update move slots
pokemon.moveSlots = newMoves.map(move => {
const moveData = this.dex.moves.get(move);
return {
move: moveData.name,
id: moveData.id,
pp: moveData.pp,
maxpp: moveData.pp,
target: moveData.target,
disabled: false,
used: false,
};
});
// this forces the UI to update move slots visually
(pokemon as any).baseMoveSlots = pokemon.moveSlots.slice();
// removes status/boosts
pokemon.cureStatus();
pokemon.clearBoosts();
// forces the UI to update part II
this.add('-clearboost', pokemon, '[from] ability: Call Volbeat', '[silent]');
for (const volatile in pokemon.volatiles) {
this.add('-end', pokemon, volatile);
}
pokemon.clearVolatile(true);
// form change + heal
pokemon.formeChange('Volbeat', null, true);
this.heal(pokemon.maxhp);
// sets new ability
pokemon.setAbility('Dancer', null, null, true);
pokemon.baseAbility = pokemon.ability;
this.add('-ability', pokemon, 'Dancer');
},
flags: {
breakable: 1, failroleplay: 1, noreceiver: 1, noentrain: 1, notrace: 1, failskillswap: 1, notransform: 1,
},
name: "Call Volbeat",
rating: 5,
num: -101,
shortDesc: "When Illumise gets low on HP, it calls Volbeat for aid.",
},
shortfuse: {
onDamagePriority: -30,
onDamage(damage, target, source, effect) {
if (damage >= target.hp) {
this.add('-ability', target, 'Short Fuse');
this.effectState.shortfuse = true;
return target.hp - 1;
}
},
onUpdate(pokemon) {
if (this.effectState.shortfuse) {
delete this.effectState.shortfuse;
this.actions.useMove('explosion', pokemon);
}
this.checkFainted();
},
flags: {
breakable: 1, failroleplay: 1, noreceiver: 1, noentrain: 1, notrace: 1, failskillswap: 1,
},
name: "Short Fuse",
rating: 5,
num: -102,
shortDesc: "If KO'd, use Explosion instead.",
},
hydroelectricdam: {
// Copied from the code for Sand Spit
onDamagingHit(damage, target, source, move) {
this.field.setWeather('raindance');
},
flags: {},
name: "Hydroelectric Dam",
rating: 5,
num: -103,
shortDesc: "Starts Rain Dance when hit by an attack.",
},
frozenarmor: {
onTryHit(target, source, move) {
if (move.category !== 'Status') {
this.add('-ability', target, 'Frozen Armor');
// reduces base power of incoming moves by 20 (math.max prevents base power from reducing below 0)
move.basePower = Math.max(move.basePower - 20, 0);
}
},
onSwitchInPriority: -1,
onUpdate(pokemon) {
// checks if Glastrier is below 50% HP, if so transforms into Caly-Ice and sets ability to As One
if (pokemon.species.id !== 'glastrier' || !pokemon.hp) return;
if (pokemon.hp < pokemon.maxhp / 2) {
if (pokemon.species.id !== 'calyrexice' && pokemon.ability === 'frozenarmor') {
pokemon.formeChange('Calyrex-Ice', null, true);
this.add('-message', `Glastrier's Frozen Armor has shattered!`);
// pokemon.setAbility('As One (Glastrier)');
pokemon.baseAbility = pokemon.ability;
// this.add('-ability', pokemon, 'As One');
}
}
},
flags: { failroleplay: 1, noreceiver: 1, noentrain: 1, notrace: 1, failskillswap: 1 },
name: "Frozen Armor",
rating: 5,
num: -105,
shortDesc: "-20 BP on attacks targeting Glastrier, at 50% HP become Calyrex-Ice.",
},
flipflop: {
onDamagingHitOrder: 1,
onTryHit(target, source, move) {
if (move.flags['contact']) {
let flipFlopBoosts = false;
const invertedBoosts: SparseBoostsTable = {};
for (const stat in source.boosts) {
if (source.boosts[stat as BoostID] > 0) {
// checks for boosts on source of move, inverts boosts and adds them to invertedBoosts table
invertedBoosts[stat as BoostID] = -2 * source.boosts[stat as BoostID];
if (!flipFlopBoosts) {
this.add('-ability', target, 'Flip Flop');
flipFlopBoosts = true;
}
}
}
// applies boosts
this.boost(invertedBoosts, source, target);
}
},
flags: {},
name: "Flip Flop",
rating: 5,
num: -104,
shortDesc: "When hit by contact move, invert attackers stat boosts.",
},
grasspelt: {
inherit: true,
onDamagingHit(damage, target, source, move) {
this.field.setTerrain('grassyterrain');
},
shortDesc: "Starts Grassy Terrain on hit. 1.5x Def in Grassy Terrain.",
},
aquaveil: {
onSwitchInPriority: -1,
// fakes the effect of aqua ring volatile lel
onStart(pokemon) {
this.add('-start', pokemon, 'Aqua Ring');
},
// provides effects of Water Bubble because Aqua Ring is modified to provide Water Bubble.
onResidualOrder: 6,
onResidual(pokemon) {
this.heal(pokemon.baseMaxhp / 16);
},
onSourceModifyAtkPriority: 5,
onSourceModifyAtk(atk, attacker, defender, move) {
if (move.type === 'Fire') {
return this.chainModify(0.5);
}
},
onSourceModifySpAPriority: 5,
onSourceModifySpA(atk, attacker, defender, move) {
if (move.type === 'Fire') {
return this.chainModify(0.5);
}
},
onModifyAtk(atk, attacker, defender, move) {
if (move.type === 'Water') {
return this.chainModify(2);
}
},
onModifySpA(atk, attacker, defender, move) {
if (move.type === 'Water') {
return this.chainModify(2);
}
},
// this ability is supposed to just add Aqua Ring (the volatile) to the Pokemon on switch in
flags: { cantsuppress: 1 },
name: "Aqua Veil",
rating: 5,
num: -106,
shortDesc: "Starts Aqua Ring on switch in.",
},
// unaware + water absorb
stillwater: {
onAnyModifyBoost(boosts, pokemon) {
const unawareUser = this.effectState.target;
if (unawareUser === pokemon) return;
if (unawareUser === this.activePokemon && pokemon === this.activeTarget) {
boosts['def'] = 0;
boosts['spd'] = 0;
boosts['evasion'] = 0;
}
if (pokemon === this.activePokemon && unawareUser === this.activeTarget) {
boosts['atk'] = 0;
boosts['def'] = 0;
boosts['spa'] = 0;
boosts['accuracy'] = 0;
}
},
onTryHit(target, source, move) {
if (target !== source && move.type === 'Water') {
if (!this.heal(target.baseMaxhp / 4)) {
this.add('-immune', target, '[from] ability: Still Water');
}
return null;
}
},
flags: { breakable: 1 },
name: "Still Water",
rating: 5,
num: -107,
shortDesc: "Unaware + Water Absorb",
},
kingofthehill: {
// sharpness + mountaineer + prevents hazard immunity
onDamage(damage, target, source, effect) {
if (effect && effect.id === 'stealthrock') {
return false;
}
},
onTryHit(target, source, move) {
if (move.type === 'Rock' && !target.activeTurns) {
this.add('-immune', target, '[from] ability: King of the Hill');
return null;
}
},
// sharpness
onBasePowerPriority: 19,
onBasePower(basePower, attacker, defender, move) {
if (move.flags['slicing']) {
this.debug('Sharpness boost');
return this.chainModify(1.5);
}
},
// starts side condition for foes, side condition interacts with hazard effects
onStart(pokemon) {
this.add('-ability', pokemon, 'King of the Hill');
for (const side of pokemon.side.foeSidesWithConditions()) {
side.addSideCondition('kingofthehill');
}
},
onEnd(pokemon) {
for (const side of pokemon.side.foeSidesWithConditions()) {
if (side.getSideCondition('kingofthehill')) {
side.removeSideCondition('kingofthehill');
}
}
},
condition: {},
flags: { breakable: 1 },
name: "King of the Hill",
rating: 5,
num: -108,
shortDesc: "Mountaineer + Sharpness. Opponent cannot ignore hazard damage.",
},
// stockpile on hit
omnivore: {
onDamagingHitOrder: 1,
onDamagingHit(damage, target, source, move) {
if (!target.hp) return;
this.add('-activate', target, 'ability: Omnivore');
target.addVolatile('stockpile');
},
flags: {},
name: "Omnivore",
rating: 5,
num: -109,
shortDesc: "Gain Stockpile charge when hit by attack.",
},
// disguise clone
pseudowoodo: {
onDamagePriority: 1,
onDamage(damage, target, source, effect) {
if (effect?.effectType === 'Move' && ['sudowoodo'].includes(target.species.id)) {
this.add('-activate', target, 'ability: Pseudowoodo');
this.effectState.rock = true;
return 0;
}
},
onCriticalHit(target, source, move) {
if (!target) return;
if (!['sudowoodo'].includes(target.species.id)) {
return;
}
const hitSub = target.volatiles['substitute'] && !move.flags['bypasssub'] && !(move.infiltrates && this.gen >= 6);
if (hitSub) return;
if (!target.runImmunity(move.type)) return;
return false;
},
onEffectiveness(typeMod, target, type, move) {
if (!target || move.category === 'Status') return;
if (!['sudowoodo'].includes(target.species.id)) {
return;
}
const hitSub = target.volatiles['substitute'] && !move.flags['bypasssub'] && !(move.infiltrates && this.gen >= 6);
if (hitSub) return;
if (!target.runImmunity(move.type)) return;
return 0;
},
onUpdate(pokemon) {
if (['sudowoodo'].includes(pokemon.species.id) && this.effectState.rock) {
const speciesid = 'Sudowoodo-Rock';
pokemon.formeChange(speciesid, this.effect, true);
this.damage(pokemon.baseMaxhp / 8, pokemon, pokemon, this.dex.species.get(speciesid));
}
},
flags: {
failroleplay: 1, noreceiver: 1, noentrain: 1, notrace: 1, failskillswap: 1,
breakable: 1, notransform: 1,
},
name: "Pseudowoodo",
rating: 5,
num: -110,
shortDesc: "Disguise. Becomes Rock type when it breaks.",
},
magicguard: {
onDamage(damage, target, source, effect) {
// prevents magic guard from blocking hazard damage while King of the Hill is active
if (target.side.getSideCondition('kingofthehill')) {
const hazards = ['stealthrock', 'spikes', 'toxicspikes', 'stickyweb'];
if (effect && hazards.includes(effect.id)) {
return;
}
}
if (effect.effectType !== 'Move') {
if (effect.effectType === 'Ability') this.add('-activate', source, 'ability: ' + effect.name);
return false;
}
},
flags: {},
name: "Magic Guard",
rating: 4,
num: 98,
},
disguise: {
onDamagePriority: 1,
onDamage(damage, target, source, effect) {
if (effect?.effectType === 'Move' && ['mimikyu', 'mimikyutotem'].includes(target.species.id)) {
this.add('-activate', target, 'ability: Disguise');
this.effectState.busted = true;
return 0;
}
},
onCriticalHit(target, source, move) {
if (!target) return;
if (!['mimikyu', 'mimikyutotem'].includes(target.species.id)) {
return;
}
const hitSub = target.volatiles['substitute'] && !move.flags['bypasssub'] && !(move.infiltrates && this.gen >= 6);
if (hitSub) return;
if (!target.runImmunity(move.type)) return;
return false;
},
onEffectiveness(typeMod, target, type, move) {
if (!target || move.category === 'Status') return;
if (!['mimikyu', 'mimikyutotem'].includes(target.species.id)) {
return;
}
const hitSub = target.volatiles['substitute'] && !move.flags['bypasssub'] && !(move.infiltrates && this.gen >= 6);
if (hitSub) return;
if (!target.runImmunity(move.type)) return;
return 0;
},
onUpdate(pokemon) {
if (['mimikyu', 'mimikyutotem'].includes(pokemon.species.id) && this.effectState.busted) {
const speciesid = pokemon.species.id === 'mimikyutotem' ? 'Mimikyu-Busted-Totem' : 'Mimikyu-Busted';
pokemon.formeChange(speciesid, this.effect, true);
this.damage(pokemon.baseMaxhp / 8, pokemon, pokemon, this.dex.species.get(speciesid));
}
// sets ability to perish body
if (pokemon.species.id === 'mimikyubusted' && pokemon.ability === 'disguise') {
pokemon.setAbility("Perish Body");
pokemon.baseAbility = pokemon.ability;
}
},
// cantsuppress flag removed to allow for ability change
flags: {
failroleplay: 1, noreceiver: 1, noentrain: 1, notrace: 1, failskillswap: 1,
breakable: 1, notransform: 1,
},
name: "Disguise",
rating: 3.5,
num: 209,
},
gulpmissile: {
inherit: true,
onTryHit(target, source, move) {
// Storm Drain effect while cramorant-gulping
if (target !== source && move.type === 'Water' && target.species.id === 'cramorantgulping') {
if (!this.boost({ spa: 1 })) {
this.add('-immune', target, '[from] ability: Gulp Missile');
}
return null;
}
// Lightning Rod effect while cramorant-gorging
if (target !== source && move.type === 'Electric' && target.species.id === 'cramorantgorging') {
if (!this.boost({ spa: 1 })) {
this.add('-immune', target, '[from] ability: Gulp Missile');
}
return null;
}
return;
},
},
asoneglastrier: {
inherit: true,
// removing these flags allows Frozen Armor to correctly set Caly-Ice ability as As One
flags: {},
},
protean: {
inherit: true,
onPrepareHit(source, target, move) {
if (move.hasBounced || move.flags['futuremove'] || move.sourceEffect === 'snatch' || move.callsMove) return;
const type = move.type;
if (type && type !== '???' && source.getTypes().join() !== type) {
if (!source.setType(type)) return;
this.add('-start', source, 'typechange', type, '[from] ability: Protean');
}
},
rating: 4.5,
shortDesc: "Gen 8 Protean.",
},
berserk: {
onUpdate(pokemon) {
if (pokemon.species.id !== 'infernape' || !pokemon.hp || pokemon.m.triggeredBerserk) return;
if (pokemon.hp < pokemon.maxhp / 2) {
this.boost({ spa: 1 }, pokemon, pokemon);
pokemon.m.triggeredBerserk = true;
}
},
flags: {},
name: "Berserk",
rating: 2,
num: 201,
},
bloodsoakedcrescent: {
// modifies atk
onStart(pokemon) {
this.add('-ability', pokemon, 'Blood-Soaked Crescent');
},
onModifyAtkPriority: 1,
onModifyAtk(atk, pokemon) {
if (pokemon.volatiles['dynamax']) return;
this.debug('bsc Attack boost');
return this.chainModify(1.5);
},
// ends move lock properly
onAfterMove(pokemon) {
if (pokemon.volatiles['bloodsoakedcrescent']?.duration === 1) {
pokemon.removeVolatile('bloodsoakedcrescent');
this.add('-end', pokemon, 'Blood-Soaked Rage');
}
},
// applies move lock
onAfterMoveSecondarySelf(pokemon, source, move) {
if (move.id === 'dragondance') return;
if (!pokemon.volatiles['bloodsoakedcrescent']) {
this.add('-start', pokemon, 'Blood-Soaked Rage');
}
pokemon.addVolatile('bloodsoakedcrescent');
},
// condition is just lockedmove with some changes
condition: {
// Outrage, Thrash, Petal Dance...
duration: 2,
onResidual(target) {
if (target.status === 'slp') {
// don't lock, and bypass confusion for calming
delete target.volatiles['bloodsoakedcrescent'];
}
this.effectState.trueDuration--;
},
onStart(target, source, effect) {
this.effectState.trueDuration = this.random(2, 4);
this.effectState.move = this.activeMove;
},
onRestart() {
if (this.effectState.trueDuration >= 2) {
this.effectState.duration = 2;
}
},
onEnd(target) {
if (this.effectState.trueDuration > 1) return;
target.addVolatile('confusion');
},
onLockMove(pokemon) {
if (pokemon.volatiles['dynamax']) return;
return this.effectState.move;
},
},
flags: {},
name: "Blood-Soaked Crescent",
rating: 5,
num: -111,
shortDesc: "1.5x Attack, but attacks have the Outrage effect.",
},
powerspot: {
onChargeMove(pokemon, target, move) {
this.debug('power spot - remove charge turn for ' + move.id);
this.attrLastMove('[still]');
this.addMove('-anim', pokemon, move.name, target);
return false; // skip charge turn
},
onAfterMoveSecondarySelf(pokemon, target, move) {
if (pokemon.getVolatile('mustrecharge')) {
pokemon.removeVolatile('mustrecharge');
this.add('-end', pokemon, 'mustrecharge');
}
},
flags: {},
name: "Power Spot",
rating: 5,
num: 249,
shortDesc: "Moves ignore charge/recharge turns.",
},
biogenesis: {
onSwitchInPriority: -1,
onBeforeSwitchIn(pokemon) {
if (pokemon.m.didRandomMoves) return;
const moves = this.dex.moves.all();
const newMoves = [];
while (newMoves.length < 8) {
const newMove = this.sample(moves);
if (newMove.basePower === 1) continue;
if (newMove.isMax === true) continue;
if (newMove.isNonstandard === "Gigantamax") continue;
if (newMoves.map(x => x.id).includes(newMove.id)) continue;
newMoves.push(newMove);
}
// Update move slots
pokemon.moveSlots = newMoves.map(move => {
const moveData = this.dex.moves.get(move);
return {
move: moveData.name,
id: moveData.id,
pp: moveData.pp,
maxpp: moveData.pp,
target: moveData.target,
disabled: false,
used: false,
};
});
// this forces the UI to update move slots visually
(pokemon as any).baseMoveSlots = pokemon.moveSlots.slice();
pokemon.m.didRandomMoves = true;
},
onSwitchIn(pokemon) {
if (!pokemon) return; // Chat command
if (!pokemon.m.hasTypeChanged) {
this.add('-ability', pokemon, 'Biogenesis');
this.add('-anim', pokemon, 'Growth', pokemon);
this.add('-message', `Mew evolves into a new form with its Biogenesis!`);
}
const attackingMoves = pokemon.baseMoveSlots
.map(slot => this.dex.moves.get(slot.id))
.filter(move => move.category !== "Status");
// pick types of first 2 attacking moves (failsafe if there are none)
const types = attackingMoves.length ?
[...new Set(attackingMoves.slice(0, 2).map(move => move.type))] :
pokemon.types;
pokemon.setType(types);
pokemon.baseTypes = pokemon.types;
pokemon.m.hasTypeChanged = true;
this.add('-start', pokemon, 'typechange', (pokemon.illusion || pokemon).getTypes(true).join('/'), '[silent]');
},
flags: { failroleplay: 1, noreceiver: 1, noentrain: 1, notrace: 1, failskillswap: 1,
breakable: 1, notransform: 1, cantsuppress: 1 },
name: "Biogenesis",
rating: 5,
num: -112,
shortDesc: "This Pokemon receives 8 completely random moves at the start of the game.",
},
orichalcumpulse: {
onStart(pokemon) {
pokemon.updateMaxHp();
if (this.field.setWeather('sunnyday')) {
this.add('-activate', pokemon, 'Orichalcum Pulse', '[source]');
} else if (this.field.isWeather('sunnyday')) {
this.add('-activate', pokemon, 'ability: Orichalcum Pulse');
}
},
onModifyAtkPriority: 5,
onModifyAtk(atk, pokemon) {
if (['sunnyday', 'desolateland'].includes(pokemon.effectiveWeather())) {
this.debug('Orichalcum boost');
return this.chainModify([5461, 4096]);
}
},
flags: {},
name: "Orichalcum Pulse",
rating: 4.5,
num: 288,
},
hailmary: {
onStart(pokemon) {
this.add('-activate', pokemon, 'ability: Hail Mary');
},
onModifySpe(spe, pokemon) {
if (this.field.isWeather(['hail', 'snowscape'])) {
this.debug('hail mary spe boost');
return this.chainModify(2);
}
},
onModifyAtkPriority: 5,
onModifyAtk(atk, pokemon) {
if (this.field.isWeather(['hail', 'snowscape'])) {
this.debug('hail mary atk boost');
return this.chainModify(1.5);
}
},
onSourceModifyAccuracyPriority: -1,
onSourceModifyAccuracy(accuracy, target, source, move) {
if (this.field.isWeather(['hail', 'snowscape'])) {
if (move.category === 'Physical' && typeof accuracy === 'number') {
return this.chainModify([3277, 4096]);
}
}
},
flags: {},
name: "Hail Mary",
rating: 5,
num: -113,
shortDesc: "In Snowscape: 2x Speed, 1.5x Attack, 0.8x accuracy.",
},
brainfreeze: {
onModifyCritRatio(critRatio, source, target) {
if (target && (target.status === 'frostbite' || this.field.isWeather('snowscape'))) return 5;
},
flags: {},
name: "Brain Freeze",
rating: 5,
num: -114,
shortDesc: "If Snowscape or target is Frostbitten, attacks auto Crit.",
},
neutralizinggas: {
inherit: true,
onStart(pokemon) {
// this makes Neutralizing Gas properly show as activated in the client when Typhlosion Mega evolves
this.add('-ability', pokemon, 'Neutralizing Gas');
},
},
terawheel: {
onStart(pokemon) {
pokemon.canTerastallize = null;
},
// copied from SSB High Performance Computing
onResidualOrder: 6,
onResidual(source) {
const type = this.sample(this.dex.types.names().filter(i => i !== source.getTypes()[0]));
if (source.setType(type)) {
this.add('-start', source, 'typechange', type, '[from] ability: Tera Wheel');
}
},
flags: {},
name: "Tera Wheel",
rating: 5,
num: -115,
shortDesc: "End of turn: this Pokemon switches to a random type (including Stellar).",
},
download: {
inherit: true,
onUpdate(pokemon) {
if (pokemon.species.name === 'Genesect-Burn' && pokemon.terastallized) {
pokemon.setAbility('Drought', null, null, true);
pokemon.baseAbility = pokemon.ability;
this.add('-ability', pokemon, 'Drought');
}
if (pokemon.species.name === 'Genesect-Chill' && pokemon.terastallized) {
pokemon.setAbility('Snow Warning', null, null, true);
pokemon.baseAbility = pokemon.ability;
this.add('-ability', pokemon, 'Snow Warning');
}
if (pokemon.species.name === 'Genesect-Douse' && pokemon.terastallized) {
pokemon.setAbility('Drizzle', null, null, true);
pokemon.baseAbility = pokemon.ability;
this.add('-ability', pokemon, 'Drizzle');
}
if (pokemon.species.name === 'Genesect-Shock' && pokemon.terastallized) {
pokemon.setAbility('Electric Surge', null, null, true);
pokemon.baseAbility = pokemon.ability;
this.add('-ability', pokemon, 'Electric Surge');
}
},
shortDesc: "Download + Gets weather setting move when Tera.",
},
battlerage: {
onDamagingHit(damage, target, source, effect) {
this.boost({ atk: 1 });
},
flags: {},
name: "Battle Rage",
rating: 5,
num: -116,
shortDesc: "+1 Atk when hit by an attack.",
},
terrainshift: {
onStart(source) {
if (source.hp >= source.maxhp) {
source.setType("Electric");
this.field.setTerrain('electricterrain');
this.add('-start', source, 'typechange', 'Electric', '[silent]');
} else if (source.hp >= (2 * source.maxhp) / 3) {
source.setType("Fairy");
this.field.setTerrain('mistyterrain');
this.add('-start', source, 'typechange', 'Fairy', '[silent]');
} else if (source.hp >= source.maxhp / 3) {
source.setType("Grass");
this.field.setTerrain('grassyterrain');
this.add('-start', source, 'typechange', 'Grass', '[silent]');
} else {
source.setType("Psychic");
this.field.setTerrain('psychicterrain');
this.add('-start', source, 'typechange', 'Psychic', '[silent]');
}
},
flags: {},
name: "Terrain Shift",
rating: 5,
num: -117,
shortDesc: "Sets terrain depending on HP value.",
},
dragonsjaw: {
onBasePower(basePower, attacker, defender, move) {
if (defender.hasType('Dragon') && defender.hasType('Steel')) {
return this.chainModify(1.5);
} else if (defender.hasType('Dragon')) {
return this.chainModify(2.25);
} else if (defender.hasType('Steel')) {
return;
} else return this.chainModify(1.5);
},
onTryHit(target, source, move) {
if (target.hasType('Fairy')) {
return null;
}
},
onModifyMovePriority: -2,
onModifyMove(move) {
if (move.secondaries) {
this.debug('doubling secondary chance');
for (const secondary of move.secondaries) {
if (secondary.chance) secondary.chance *= 2;
}
}
if (move.self?.chance) move.self.chance *= 2;
},
flags: {},
name: "Dragon's Jaw",
rating: 5,
num: -118,
shortDesc: "Serene Grace + Bite attacks are Dragon type.",
},
corrosivesoul: {
onStart(source) {
this.field.setTerrain('corrosivesoul');
},
condition: {
effectType: 'Terrain',
duration: 5,
durationCallback(source, effect) {
if (source?.hasItem('terrainextender')) {
return 8;
}
return 5;
},
onFieldStart(field, source, effect) {
if (effect?.effectType === 'Ability') {
this.add('-fieldstart', 'move: Corrosive Soul', '[from] ability: ' + effect.name, `[of] ${source}`);
} else {
this.add('-fieldstart', 'move: Corrosive Soul');
}
},
onResidualOrder: 5,
onResidualSubOrder: 2,
onResidual(pokemon) {
const move = this.dex.getActiveMove('smog');
move.accuracy = 100;
const target = pokemon.foes()[0];
if (target && !target.fainted) {
this.actions.useMove(move, pokemon, { target });
}
},
onFieldResidualOrder: 27,
onFieldResidualSubOrder: 7,
onFieldEnd() {
this.add('-fieldend', 'move: Corrosive Soul');
},
},
flags: {},
name: "Corrosive Soul",
rating: 5,
num: -119,
shortDesc: "Sets Corrosive Terrian: active Pokemon hit each other with Smog.",
},
oceanicblessing: {
onSwitchInPriority: -2,
onStart(pokemon) {
this.singleEvent('WeatherChange', this.effect, this.effectState, pokemon);
},
onWeatherChange(pokemon) {
if (!pokemon.isActive || pokemon.baseSpecies.baseSpecies !== 'Kyogre' || pokemon.transformed) return;
if (!pokemon.hp) return;
if (['raindance', 'primordialsea'].includes(pokemon.effectiveWeather())) {
if (pokemon.species.id !== 'kyogreprimal') {
pokemon.formeChange('Kyogre-Primal', this.effect, false);
}
} else {
if (pokemon.species.id === 'kyogreprimal') {
pokemon.formeChange('kyogre', this.effect, false);
}
}
},
onAllyModifyAtkPriority: 3,
onAllyModifyAtk(atk, pokemon) {
if (this.effectState.target.baseSpecies.baseSpecies !== 'Kyogre') return;
if (['raindance', 'primordialsea'].includes(pokemon.effectiveWeather())) {
return this.chainModify(1.5);
}
},
onAllyModifySpDPriority: 4,
onAllyModifySpD(spd, pokemon) {
if (this.effectState.target.baseSpecies.baseSpecies !== 'Kyogre') return;
if (['raindance', 'primordialsea'].includes(pokemon.effectiveWeather())) {
return this.chainModify(1.5);
}
},
flags: { failroleplay: 1, noreceiver: 1, noentrain: 1, notrace: 1, breakable: 1 },
name: "Oceanic Blessing",
rating: 5,
num: -120,
shortDesc: "Flower Gift but Kyogre",
},
autospin: {
onResidual(pokemon, s, effect) {
const move = this.dex.getActiveMove('metronome');
const target = pokemon.foes()[0];
if (target && !target.fainted && (pokemon.hp >= pokemon.maxhp / 2)) {
this.actions.useMove(move, pokemon, { target, sourceEffect: effect });
} else if (target && !target.fainted && (pokemon.hp <= pokemon.maxhp / 10)) {
this.actions.useMove(move, pokemon, { target, sourceEffect: effect });
this.actions.useMove(move, pokemon, { target, sourceEffect: effect });
this.actions.useMove(move, pokemon, { target, sourceEffect: effect });
} else if (target && !target.fainted) {
this.actions.useMove(move, pokemon, { target, sourceEffect: effect });
this.actions.useMove(move, pokemon, { target, sourceEffect: effect });
}
},
flags: {},
name: "Auto Spin",
rating: 5,
num: -121,
shortDesc: "Use Metronome at end of turn.",
},
corrosion: {
inherit: true,
onModifyMovePriority: -5,
onModifyMove(move) {
if (!move.ignoreImmunity) move.ignoreImmunity = {};
if (move.ignoreImmunity !== true) {
move.ignoreImmunity['Poison'] = true;
}
},
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.",
},
};

View File

@ -0,0 +1,20 @@
export const Conditions: import('../../../sim/dex-conditions').ModdedConditionDataTable = {
frostbite: {
name: 'frostbite',
effectType: 'Status',
onStart(target) {
this.add('-start', target, 'Frostbite', '[silent]');
this.add('-message', `${target.species.name} is inflicted with frostbite!`);
},
onSwitchIn(pokemon) {
this.add('-start', pokemon, 'Frostbite', '[silent]');
},
onResidualOrder: 10,
onResidual(pokemon) {
this.damage(pokemon.baseMaxhp / 16);
},
onBasePower(basePower, source, target) {
return basePower / 2;
},
},
};

150
data/mods/chatbats/items.ts Normal file
View File

@ -0,0 +1,150 @@
export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
bigroot: {
inherit: true,
onTryHealPriority: 1,
onTryHeal(damage, target, source, effect) {
const heals = ['drain', 'leechseed', 'ingrain', 'aquaring', 'strengthsap'];
if (heals.includes(effect.id)) {
return this.chainModify([6144, 4096]);
}
},
shortDesc: "Holder gains 1.5x HP from draining, Aqua Ring, Ingrain, Leech Seed, Strength Sap.",
},
masquerainite: {
name: "Masquerainite",
spritenum: 1,
megaStone: { "Masquerain": "Masquerain-Mega" },
itemUser: ["Masquerain"],
onTakeItem(item, source) {
return !item.megaStone?.[source.baseSpecies.baseSpecies];
},
num: -1,
gen: 9,
desc: "If held by a Masquerain, this item allows it to Mega Evolve in battle.",
},
starfberry: {
name: "Starf Berry",
spritenum: 472,
isBerry: true,
naturalGift: {
basePower: 100,
type: "Psychic",
},
onUpdate(pokemon) {
if (pokemon.hp <= pokemon.maxhp / 2 ||
((pokemon.hp <= pokemon.maxhp / 2 && pokemon.hasAbility('gluttony') && pokemon.abilityState.gluttony))) {
pokemon.eatItem();
}
},
onEat(pokemon) {
const stats: BoostID[] = [];
let stat: BoostID;
for (stat in pokemon.boosts) {
if (stat !== 'accuracy' && stat !== 'evasion' && pokemon.boosts[stat] < 6) {
stats.push(stat);
}
}
if (stats.length) {
const randomStat = this.sample(stats);
const boost: SparseBoostsTable = {};
boost[randomStat] = 2;
this.boost(boost);
}
},
num: 207,
gen: 3,
},
typhlosionite: {
name: "Typhlosionite",
spritenum: 1,
megaStone: { "Typhlosion": "Typhlosion-Mega" },
itemUser: ["Typhlosion"],
onTakeItem(item, source) {
return !item.megaStone?.[source.baseSpecies.baseSpecies];
},
num: -2,
gen: 9,
desc: "If held by a Typhlosion, this item allows it to Mega Evolve in battle.",
},
tartapple: {
name: "Tart Apple",
spritenum: 712,
isBerry: true,
fling: {
basePower: 30,
},
onBasePowerPriority: 15,
onBasePower(basePower, user, target, move) {
if (
move && (user.baseSpecies.num === 841) &&
(move.type === 'Grass' || move.type === 'Ground')
) {
return this.chainModify([4915, 4096]);
}
},
onUpdate(pokemon) {
if (pokemon.hp <= pokemon.maxhp / 2) {
pokemon.eatItem();
}
},
onTryEatItem(item, pokemon) {
if (!this.runEvent('TryHeal', pokemon, null, this.effect, pokemon.baseMaxhp / 4)) return false;
},
onEat(pokemon) {
this.heal(pokemon.baseMaxhp / 4);
},
itemUser: ["Flapple"],
num: 1117,
gen: 8,
desc: "Grass- and Ground-type moves have 1.2x power. Restores 1/4 max HP when at 1/2 max HP or less.",
},
thickclub: {
name: "Thick Club",
spritenum: 491,
fling: {
basePower: 130,
},
onModifyAtkPriority: 1,
onModifyAtk(atk, pokemon) {
if (pokemon.baseSpecies.baseSpecies === 'Mandibuzz' || pokemon.baseSpecies.baseSpecies === 'Mew') {
return this.chainModify(2);
}
},
itemUser: ["Marowak", "Marowak-Alola", "Marowak-Alola-Totem", "Cubone", "Mandibuzz", "Mew"],
num: 258,
gen: 2,
desc: "Doubles Attack.",
},
focusband: {
name: "Focus Band",
spritenum: 150,
fling: {
basePower: 10,
},
onDamagePriority: -40,
onDamage(damage, target, source, effect) {
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.",
},
};

1752
data/mods/chatbats/moves.ts Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,514 @@
export const Pokedex: import('../../../sim/dex-species').ModdedSpeciesDataTable = {
volcarona: {
inherit: true,
abilities: { 0: "Fluffy" },
},
golemalola: {
inherit: true,
},
lurantis: {
inherit: true,
baseStats: { hp: 85, atk: 105, def: 90, spa: 95, spd: 90, spe: 75 },
},
ironcrown: {
inherit: true,
abilities: { 0: "Queenly Majesty", H: "Battle Armor" },
},
mamoswine: {
inherit: true,
},
ceruledge: {
inherit: true,
},
carbink: {
inherit: true,
abilities: { 0: "Magic Bounce" },
},
moltres: {
inherit: true,
abilities: { 0: "Magic Guard" },
},
kommoo: {
inherit: true,
baseStats: { hp: 75, atk: 100, def: 125, spa: 110, spd: 105, spe: 85 },
abilities: { 0: "Punk Rock" },
},
illumise: {
inherit: true,
abilities: { 0: "Call Volbeat" },
},
volbeat: {
inherit: true,
abilities: { 0: "Call Illumise" },
},
abomasnow: {
inherit: true,
},
abomasnowmega: {
inherit: true,
baseStats: { hp: 90, atk: 132, def: 105, spa: 92, spd: 105, spe: 70 },
abilities: { 0: "Slush Rush" },
},
dugtrio: {
inherit: true,
},
altaria: {
inherit: true,
abilities: { 0: "Fluffy" },
},
altariamega: {
inherit: true,
},
tyranitar: {
inherit: true,
abilities: { 0: "Sand Stream", H: "Sharpness" },
},
tyranitarmega: {
inherit: true,
baseStats: { hp: 100, atk: 114, def: 150, spa: 155, spd: 110, spe: 71 },
types: ["Rock", "Dragon"],
},
mimikyu: {
inherit: true,
baseStats: { hp: 65, atk: 110, def: 80, spa: 50, spd: 105, spe: 96 },
},
mimikyubusted: {
inherit: true,
abilities: { 0: "Perish Body" },
baseStats: { hp: 65, atk: 90, def: 80, spa: 50, spd: 105, spe: 116 },
},
mesprit: {
inherit: true,
abilities: { 0: "Liquid Voice" },
types: ["Psychic", "Water"],
},
electrode: {
inherit: true,
abilities: { 0: "Short Fuse" },
types: ["Electric", "Normal"],
},
taurospaldeacombat: {
inherit: true,
abilities: { 0: "Adaptability" },
},
chiyu: {
inherit: true,
abilities: { 0: "Water Absorb" },
baseStats: { hp: 55, atk: 135, def: 80, spa: 80, spd: 120, spe: 100 },
},
wochien: {
inherit: true,
abilities: { 0: "Liquid Ooze" },
types: ["Grass", "Water"],
},
staraptor: {
inherit: true,
types: ["Flying"],
},
archaludon: {
inherit: true,
abilities: { 0: "Hydroelectric Dam", 1: "Stamina" },
},
malamar: {
inherit: true,
abilities: { 0: "Flip Flop" },
baseStats: { hp: 86, atk: 92, def: 88, spa: 88, spd: 75, spe: 73 },
},
empoleon: {
inherit: true,
abilities: { 0: "Sharpness" },
types: ["Water", "Steel", "Flying"],
},
glastrier: {
inherit: true,
abilities: { 0: "Frozen Armor" },
},
calyrexice: {
inherit: true,
baseStats: { hp: 100, atk: 165, def: 130, spa: 85, spd: 110, spe: 90 },
},
regieleki: {
inherit: true,
abilities: { 0: "Galvanize" },
},
lycanrocmidnight: {
inherit: true,
abilities: { 0: "Technician" },
},
lycanroc: {
inherit: true,
abilities: { 0: "Drought" },
},
lycanrocdusk: {
inherit: true,
abilities: { 0: "Strong Jaw" },
},
dodrio: {
inherit: true,
abilities: { 0: "Speed Boost" },
types: ["Flying", "Fighting"],
},
whiscash: {
inherit: true,
abilities: { 0: "Regenerator" },
baseStats: { hp: 110, atk: 78, def: 88, spa: 76, spd: 86, spe: 60 },
},
hippowdon: {
inherit: true,
abilities: { 0: "Earth Eater" },
},
cramorant: {
inherit: true,
baseStats: { hp: 90, atk: 85, def: 75, spa: 85, spd: 95, spe: 85 },
},
cramorantgulping: {
inherit: true,
baseStats: { hp: 90, atk: 85, def: 75, spa: 85, spd: 95, spe: 85 },
abilities: { 0: "Storm Drain" },
},
cramorantgorging: {
inherit: true,
baseStats: { hp: 90, atk: 85, def: 75, spa: 85, spd: 95, spe: 85 },
abilities: { 0: "Lightning Rod" },
},
grafaiai: {
inherit: true,
baseStats: { hp: 83, atk: 95, def: 65, spa: 80, spd: 72, spe: 110 },
},
tatsugiri: {
inherit: true,
abilities: { 0: "Regenerator" },
baseStats: { hp: 78, atk: 50, def: 70, spa: 120, spd: 95, spe: 82 },
},
kyurem: {
inherit: true,
abilities: { 0: "Skill Link" },
},
roaringmoon: {
inherit: true,
abilities: { 0: "Shadow Shield" },
},
milotic: {
inherit: true,
abilities: { 0: "Aqua Veil" },
types: ["Water", "Fairy"],
},
gogoat: {
inherit: true,
types: ["Grass", "Rock"],
},
clodsire: {
inherit: true,
abilities: { 0: "Still Water" },
},
masquerain: {
inherit: true,
abilities: { 0: "Intimidate" },
},
masquerainmega: {
num: -999,
name: "Masquerain-Mega",
baseSpecies: "Masquerain",
forme: "Mega",
types: ["Bug", "Dark"],
genderRatio: { M: 0.5, F: 0.5 },
baseStats: { hp: 70, atk: 60, def: 82, spa: 140, spd: 82, spe: 120 },
abilities: { 0: "Primordial Sea" },
heightm: 0.8,
weightkg: 3.6,
color: "Blue",
eggGroups: ["Water 1", "Bug"],
requiredItem: "Masquerainite",
},
kyuremblack: {
inherit: true,
abilities: { 0: "Teravolt" },
types: ["Dragon", "Ice", "Electric"],
},
ironthorns: {
inherit: true,
abilities: { 0: "Iron Barbs" },
},
dudunsparce: {
inherit: true,
abilities: { 0: "Earth Eater" },
types: ["Normal", "Ground"],
},
dudunsparcethreesegment: {
inherit: true,
abilities: { 0: "Earth Eater" },
types: ["Normal", "Ground"],
},
chienpao: {
inherit: true,
abilities: { 0: "Tablets of Ruin" },
},
pelipper: {
inherit: true,
},
kleavor: {
inherit: true,
abilities: { 0: "King of the Hill" },
baseStats: { hp: 120, atk: 135, def: 95, spa: 45, spd: 75, spe: 85 },
},
araquanid: {
inherit: true,
},
avalugghisui: {
inherit: true,
abilities: { 0: "Multiscale" },
baseStats: { hp: 95, atk: 127, def: 184, spa: 68, spd: 72, spe: 76 },
},
swalot: {
inherit: true,
abilities: { 0: "Omnivore" },
},
zapdosgalar: {
inherit: true,
types: ["Electric", "Fighting"],
},
phione: {
inherit: true,
},
sudowoodo: {
inherit: true,
abilities: { 0: "Pseudowoodo" },
types: ["Grass"],
baseForme: "Grass",
otherFormes: ["Sudowoodo-Rock"],
formeOrder: ["Sudowoodo", "Sudowoodo-Rock"],
},
sudowoodorock: {
num: 185,
name: "Sudowoodo-Rock",
baseSpecies: "Sudowoodo",
forme: "Rock",
types: ["Rock"],
baseStats: { hp: 70, atk: 100, def: 110, spa: 30, spd: 65, spe: 30 },
abilities: { 0: "Pseudowoodo" },
heightm: 1.7,
weightkg: 38,
color: "Brown",
eggGroups: ["Mineral"],
requiredAbility: "Pseudowoodo",
battleOnly: "Sudowoodo",
},
dondozo: {
inherit: true,
},
golurk: {
inherit: true,
},
meowscarada: {
inherit: true,
},
infernape: {
inherit: true,
abilities: { 0: "Berserk" },
},
salamence: {
inherit: true,
abilities: { 0: "Aerilate" },
},
salamencemega: {
num: 373,
name: "Salamence-Mega",
baseSpecies: "Salamence",
forme: "Mega",
types: ["Dragon", "Flying"],
baseStats: { hp: 95, atk: 145, def: 130, spa: 120, spd: 90, spe: 120 },
abilities: { 0: "Blood-Soaked Crescent" },
heightm: 1.8,
weightkg: 112.6,
color: "Blue",
eggGroups: ["Dragon"],
requiredItem: "Salamencite",
},
urshifu: {
inherit: true,
abilities: { 0: "Sniper" },
},
urshifurapidstrike: {
inherit: true,
abilities: { 0: "Sniper" },
},
stonjourner: {
inherit: true,
},
veluza: {
inherit: true,
types: ["Water", "Ghost"],
},
ogerponhearthflame: {
inherit: true,
abilities: { 0: "Intimidate" },
},
dachsbun: {
inherit: true,
},
koraidon: {
inherit: true,
},
mew: {
inherit: true,
abilities: { 0: "Biogenesis" },
},
magneton: {
inherit: true,
},
delibird: {
inherit: true,
abilities: { 0: "Hail Mary" },
baseStats: { hp: 45, atk: 90, def: 45, spa: 65, spd: 45, spe: 136 },
},
articunogalar: {
inherit: true,
abilities: { 0: "Brain Freeze" },
},
vaporeon: {
inherit: true,
abilities: { 0: "Marvel Scale" },
},
jolteon: {
inherit: true,
abilities: { 0: "Quick Feet" },
},
flareon: {
inherit: true,
abilities: { 0: "Guts" },
baseStats: { hp: 65, atk: 130, def: 65, spa: 60, spd: 110, spe: 95 },
},
garganacl: {
inherit: true,
},
swanna: {
inherit: true,
abilities: { 0: "Serene Grace" },
baseStats: { hp: 75, atk: 117, def: 93, spa: 117, spd: 93, spe: 128 },
},
typhlosion: {
inherit: true,
abilities: { 0: "Magic Guard" },
},
typhlosionmega: {
num: -998,
name: "Typhlosion-Mega",
baseSpecies: "Typhlosion",
forme: "Mega",
types: ["Fire", "Water"],
genderRatio: { M: 0.5, F: 0.5 },
baseStats: { hp: 78, atk: 103, def: 98, spa: 140, spd: 115, spe: 100 },
abilities: { 0: "Neutralizing Gas" },
heightm: 1.7,
weightkg: 84.5,
color: "Blue",
eggGroups: ["Field"],
requiredItem: "Typhlosionite",
},
terapagos: {
inherit: true,
},
terapagosterastal: {
inherit: true,
abilities: { 0: "Tera Wheel" },
},
terapagosstellar: {
inherit: true,
types: ["Stellar"],
},
flapple: {
inherit: true,
abilities: { 0: "Ripen" },
types: ["Grass", "Ground"],
},
genesect: {
inherit: true,
abilities: { 0: "Download" },
},
honchkrow: {
inherit: true,
abilities: { 0: "Supreme Overlord" },
baseStats: { hp: 100, atk: 125, def: 52, spa: 125, spd: 52, spe: 71 },
},
primeape: {
inherit: true,
abilities: { 0: "Battle Rage" },
},
rillaboom: {
inherit: true,
abilities: { 0: "Terrain Shift" },
},
mandibuzz: {
inherit: true,
abilities: { 0: "Weak Armor" },
types: ["Dark", "Ground"],
},
feraligatr: {
inherit: true,
},
feraligatrmega: {
num: -988,
name: "Feraligatr-Mega",
baseSpecies: "Feraligatr",
forme: "Mega",
types: ["Dragon"],
genderRatio: { M: 0.875, F: 0.125 },
baseStats: { hp: 85, atk: 145, def: 120, spa: 99, spd: 103, spe: 78 },
abilities: { 0: "Dragon's Jaw" },
heightm: 2.3,
weightkg: 108.8,
color: "Blue",
eggGroups: ["Monster", "Water 1"],
requiredItem: "Feraligite",
gen: 9,
},
salazzle: {
inherit: true,
abilities: { 0: "Corrosive Soul" },
},
kyogre: {
inherit: true,
abilities: { 0: "Oceanic Blessing" },
},
azelf: {
inherit: true,
abilities: { 0: "Auto Spin" },
types: ["Psychic", "Normal"],
},
decidueye: {
inherit: true,
abilities: { 0: "Overgrow", 1: "Sniper" },
},
ogerponcornerstone: {
inherit: true,
abilities: { 0: "Solid Rock" },
},
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",
},
};

View File

@ -0,0 +1,304 @@
export const Scripts: ModdedBattleScriptsData = {
gen: 9,
init() {
this.modData('Learnsets', 'lurantis').learnset.icehammer = ['9L1'];
this.modData('Learnsets', 'ironcrown').learnset.kingsshield = ['9L1'];
this.modData('Learnsets', 'ironcrown').learnset.bodypress = ['9L1'];
this.modData('Learnsets', 'carbink').learnset.moonlight = ['9L1'];
this.modData('Learnsets', 'carbink').learnset.voltswitch = ['9L1'];
this.modData('Learnsets', 'carbink').learnset.spikes = ['9L1'];
this.modData('Learnsets', 'moltres').learnset.woodhammer = ['9L1'];
this.modData('Learnsets', 'moltres').learnset.wavecrash = ['9L1'];
this.modData('Learnsets', 'moltres').learnset.defog = ['9L1'];
this.modData('Learnsets', 'kommoo').learnset.aurasphere = ['9L1'];
this.modData('Learnsets', 'illumise').learnset.quiverdance = ['9L1'];
this.modData('Learnsets', 'illumise').learnset.thunderbolt = ['9L1'];
this.modData('Learnsets', 'illumise').learnset.icebeam = ['9L1'];
this.modData('Learnsets', 'volbeat').learnset.victorydance = ['9L1'];
this.modData('Learnsets', 'volbeat').learnset.mightycleave = ['9L1'];
this.modData('Learnsets', 'volbeat').learnset.earthquake = ['9L1'];
this.modData('Learnsets', 'abomasnow').learnset.glaciallance = ['9L1'];
this.modData('Learnsets', 'abomasnow').learnset.appleacid = ['9L1'];
this.modData('Learnsets', 'abomasnow').learnset.partingshot = ['9L1'];
this.modData('Learnsets', 'dugtrio').learnset.mightycleave = ['9L1'];
this.modData('Learnsets', 'dugtrio').learnset.saltcure = ['9L1'];
this.modData('Learnsets', 'dugtrio').learnset.acrobatics = ['9L1'];
this.modData('Learnsets', 'altaria').learnset.beakblast = ['9L1'];
this.modData('Learnsets', 'altaria').learnset.return = ['9L1'];
this.modData('Learnsets', 'altaria').learnset.explosion = ['9L1'];
this.modData('Learnsets', 'tyranitar').learnset.stoneaxe = ['9L1'];
this.modData('Learnsets', 'tyranitar').learnset.ceaselessedge = ['9L1'];
this.modData('Learnsets', 'tyranitar').learnset.kowtowcleave = ['9L1'];
this.modData('Learnsets', 'tyranitar').learnset.pursuit = ['9L1'];
this.modData('Learnsets', 'tyranitar').learnset.switcheroo = ['9L1'];
this.modData('Learnsets', 'tyranitar').learnset.accelerock = ['9L1'];
this.modData('Learnsets', 'tyranitar').learnset.dracometeor = ['9L1'];
this.modData('Learnsets', 'tyranitar').learnset.mysticalpower = ['9L1'];
this.modData('Learnsets', 'tyranitar').learnset.sandsearstorm = ['9L1'];
this.modData('Learnsets', 'mimikyu').learnset.spiritshackle = ['9L1'];
this.modData('Learnsets', 'mimikyu').learnset.uturn = ['9L1'];
this.modData('Learnsets', 'mimikyu').learnset.obstruct = ['9L1'];
this.modData('Learnsets', 'mesprit').learnset.agility = ['9L1'];
this.modData('Learnsets', 'mesprit').learnset.storedpower = ['9L1'];
this.modData('Learnsets', 'mesprit').learnset.torchsong = ['9L1'];
this.modData('Learnsets', 'mesprit').learnset.cosmicpower = ['9L1'];
this.modData('Learnsets', 'mesprit').learnset.aquaring = ['9L1'];
this.modData('Learnsets', 'mesprit').learnset.freezedry = ['9L1'];
this.modData('Learnsets', 'electrode').learnset.encore = ['9L1'];
this.modData('Learnsets', 'electrode').learnset.rapidspin = ['9L1'];
this.modData('Learnsets', 'taurospaldeacombat').learnset.extremespeed = ['9L1'];
this.modData('Learnsets', 'taurospaldeacombat').learnset.uturn = ['9L1'];
this.modData('Learnsets', 'taurospaldeacombat').learnset.knockoff = ['9L1'];
this.modData('Learnsets', 'chiyu').learnset.splash = ['9L1'];
this.modData('Learnsets', 'chiyu').learnset.tripledive = ['9L1'];
this.modData('Learnsets', 'chiyu').learnset.pyroball = ['9L1'];
this.modData('Learnsets', 'chiyu').learnset.knockoff = ['9L1'];
this.modData('Learnsets', 'chiyu').learnset.suckerpunch = ['9L1'];
this.modData('Learnsets', 'wochien').learnset.partingshot = ['9L1'];
this.modData('Learnsets', 'wochien').learnset.strengthsap = ['9L1'];
this.modData('Learnsets', 'wochien').learnset.bouncingbubble = ['9L1'];
this.modData('Learnsets', 'staraptor').learnset.jumpkick = ['9L1'];
this.modData('Learnsets', 'staraptor').learnset.flareblitz = ['9L1'];
this.modData('Learnsets', 'staraptor').learnset.wavecrash = ['9L1'];
this.modData('Learnsets', 'staraptor').learnset.headsmash = ['9L1'];
this.modData('Learnsets', 'archaludon').learnset.scald = ['9L1'];
this.modData('Learnsets', 'archaludon').learnset.hydropump = ['9L1'];
this.modData('Learnsets', 'malamar').learnset.willowisp = ['9L1'];
this.modData('Learnsets', 'malamar').learnset.recover = ['9L1'];
this.modData('Learnsets', 'malamar').learnset.eeriespell = ['9L1'];
this.modData('Learnsets', 'malamar').learnset.sweetkiss = ['9L1'];
this.modData('Learnsets', 'malamar').learnset.spiritbreak = ['9L1'];
this.modData('Learnsets', 'empoleon').learnset.nastyplot = ['9L1'];
this.modData('Learnsets', 'empoleon').learnset.watershuriken = ['9L1'];
this.modData('Learnsets', 'empoleon').learnset.tachyoncutter = ['9L1'];
this.modData('Learnsets', 'empoleon').learnset.secretsword = ['9L1'];
this.modData('Learnsets', 'regieleki').learnset.blazingtorque = ['9L1'];
this.modData('Learnsets', 'regieleki').learnset.soak = ['9L1'];
this.modData('Learnsets', 'lycanrocmidnight').learnset.accelerock = ['9L1'];
this.modData('Learnsets', 'lycanrocmidnight').learnset.bonerush = ['9L1'];
this.modData('Learnsets', 'lycanrocmidnight').learnset.stormthrow = ['9L1'];
this.modData('Learnsets', 'lycanroc').learnset.firelash = ['9L1'];
this.modData('Learnsets', 'lycanroc').learnset.uturn = ['9L1'];
this.modData('Learnsets', 'lycanroc').learnset.spikes = ['9L1'];
this.modData('Learnsets', 'lycanrocdusk').learnset.mountainmaw = ['9L1'];
this.modData('Learnsets', 'lycanrocdusk').learnset.icefang = ['9L1'];
this.modData('Learnsets', 'dodrio').learnset.triplearrows = ['9L1'];
this.modData('Learnsets', 'dodrio').learnset.obstruct = ['9L1'];
this.modData('Learnsets', 'whiscash').learnset.toxic = ['9L1'];
this.modData('Learnsets', 'whiscash').learnset.flipturn = ['9L1'];
this.modData('Learnsets', 'whiscash').learnset.scald = ['9L1'];
this.modData('Learnsets', 'hippowdon').learnset.saltcure = ['9L1'];
this.modData('Learnsets', 'cramorant').learnset.beakblast = ['9L1'];
this.modData('Learnsets', 'grafaiai').learnset.bulkup = ['9L1'];
this.modData('Learnsets', 'grafaiai').learnset.scavenge = ['9L1'];
this.modData('Learnsets', 'grafaiai').learnset.drainpunch = ['9L1'];
this.modData('Learnsets', 'kyurem').learnset.earthquake = ['9L1'];
this.modData('Learnsets', 'roaringmoon').learnset.firelash = ['9L1'];
this.modData('Learnsets', 'roaringmoon').learnset.glaiverush = ['9L1'];
this.modData('Learnsets', 'milotic').learnset.bouncybubble = ['9L1'];
this.modData('Learnsets', 'milotic').learnset.moonblast = ['9L1'];
this.modData('Learnsets', 'gogoat').learnset.headsmash = ['9L1'];
this.modData('Learnsets', 'clodsire').learnset.barbbarrage = ['9L1'];
this.modData('Learnsets', 'masquerain').learnset.roost = ['9L1'];
this.modData('Learnsets', 'masquerain').learnset.darkpulse = ['9L1'];
this.modData('Learnsets', 'kyuremblack').learnset.icehammer = ['9L1'];
this.modData('Learnsets', 'kyuremblack').learnset.dragonhammer = ['9L1'];
this.modData('Learnsets', 'kyuremblack').learnset.roost = ['9L1'];
this.modData('Learnsets', 'kyuremblack').learnset.earthquake = ['9L1'];
this.modData('Learnsets', 'ironthorns').learnset.ironstrike = ['9L1'];
this.modData('Learnsets', 'ironthorns').learnset.knockoff = ['9L1'];
this.modData('Learnsets', 'chienpao').learnset.bulkup = ['9L1'];
this.modData('Learnsets', 'chienpao').learnset.iciclestorm = ['9L1'];
this.modData('Learnsets', 'pelipper').learnset.bleakwindstorm = ['9L1'];
this.modData('Learnsets', 'pelipper').learnset.sandsearstorm = ['9L1'];
this.modData('Learnsets', 'pelipper').learnset.wildboltstorm = ['9L1'];
this.modData('Learnsets', 'pelipper').learnset.springtidestorm = ['9L1'];
this.modData('Learnsets', 'araquanid').learnset.surgingstrikes = ['9L1'];
this.modData('Learnsets', 'araquanid').learnset.flipturn = ['9L1'];
this.modData('Learnsets', 'araquanid').learnset.silktrap = ['9L1'];
this.modData('Learnsets', 'araquanid').learnset.firstimpression = ['9L1'];
this.modData('Learnsets', 'avalugghisui').learnset.mountainmaw = ['9L1'];
this.modData('Learnsets', 'swalot').learnset.earthpower = ['9L1'];
this.modData('Learnsets', 'zapdosgalar').learnset.wildcharge = ['9L1'];
this.modData('Learnsets', 'phione').learnset.workup = ['9L1'];
this.modData('Learnsets', 'phione').learnset.tidalsurge = ['9L1'];
this.modData('Learnsets', 'phione').learnset.geyser = ['9L1'];
this.modData('Learnsets', 'sudowoodo').learnset.bonsaibounce = ['9L1'];
this.modData('Learnsets', 'sudowoodo').learnset.synthesis = ['9L1'];
this.modData('Learnsets', 'dondozo').learnset.hornleech = ['9L1'];
this.modData('Learnsets', 'dondozo').learnset.fishiousrend = ['9L1'];
this.modData('Learnsets', 'dondozo').learnset.recover = ['9L1'];
this.modData('Learnsets', 'dondozo').learnset.flipturn = ['9L1'];
this.modData('Learnsets', 'golurk').learnset.shatteredseal = ['9L1'];
this.modData('Learnsets', 'golurk').learnset.trickroom = ['9L1'];
this.modData('Learnsets', 'golurk').learnset.headlongrush = ['9L1'];
this.modData('Learnsets', 'meowscarada').learnset.encore = ['9L1'];
this.modData('Learnsets', 'meowscarada').learnset.spectralthief = ['9L1'];
this.modData('Learnsets', 'infernape').learnset.alloutassault = ['9L1'];
this.modData('Learnsets', 'infernape').learnset.mindblown = ['9L1'];
this.modData('Learnsets', 'infernape').learnset.bitterblade = ['9L1'];
this.modData('Learnsets', 'salamence').learnset.uturn = ['9L1'];
this.modData('Learnsets', 'salamence').learnset.dragonascent = ['9L1'];
this.modData('Learnsets', 'salamence').learnset.bloodmoon = ['9L1'];
this.modData('Learnsets', 'urshifu').learnset.agility = ['9L1'];
this.modData('Learnsets', 'urshifu').learnset.aquajet = ['9L1'];
this.modData('Learnsets', 'urshifurapidstrike').learnset.agility = ['9L1'];
this.modData('Learnsets', 'urshifurapidstrike').learnset.suckerpunch = ['9L1'];
this.modData('Learnsets', 'stonjourner').learnset.rockwrecker = ['9L1'];
this.modData('Learnsets', 'stonjourner').learnset.meteorassault = ['9L1'];
this.modData('Learnsets', 'stonjourner').learnset.skyattack = ['9L1'];
this.modData('Learnsets', 'stonjourner').learnset.solarblade = ['9L1'];
this.modData('Learnsets', 'veluza').learnset.ragefist = ['9L1'];
this.modData('Learnsets', 'ogerpon').learnset.leafblade = ['9L1'];
this.modData('Learnsets', 'ogerpon').learnset.crabhammer = ['9L1'];
this.modData('Learnsets', 'ogerpon').learnset.stoneedge = ['9L1'];
this.modData('Learnsets', 'dachsbun').learnset.nuzzle = ['9L1'];
this.modData('Learnsets', 'dachsbun').learnset.spiritbreak = ['9L1'];
this.modData('Learnsets', 'dachsbun').learnset.morningsun = ['9L1'];
this.modData('Learnsets', 'magneton').learnset.magnetbomb = ['9L1'];
this.modData('Learnsets', 'delibird').learnset.iciclestorm = ['9L1'];
this.modData('Learnsets', 'hitmontop').learnset.bulletseed = ['9L1'];
this.modData('Learnsets', 'articunogalar').learnset.aeroblast = ['9L1'];
this.modData('Learnsets', 'articunogalar').learnset.oblivionwing = ['9L1'];
this.modData('Learnsets', 'articunogalar').learnset.aurasphere = ['9L1'];
this.modData('Learnsets', 'vaporeon').learnset.voltswitch = ['9L1'];
this.modData('Learnsets', 'vaporeon').learnset.burnout = ['9L1'];
this.modData('Learnsets', 'garganacl').learnset.thunderwave = ['9L1'];
this.modData('Learnsets', 'garganacl').learnset.saltcurse = ['9L1'];
this.modData('Learnsets', 'garganacl').learnset.purify = ['9L1'];
this.modData('Learnsets', 'swanna').learnset.bleakwindstorm = ['9L1'];
this.modData('Learnsets', 'swanna').learnset.steameruption = ['9L1'];
this.modData('Learnsets', 'swanna').learnset.flyby = ['9L1'];
this.modData('Learnsets', 'typhlosion').learnset.heatsink = ['9L1'];
this.modData('Learnsets', 'typhlosion').learnset.steameruption = ['9L1'];
this.modData('Learnsets', 'typhlosion').learnset.matchagotcha = ['9L1'];
this.modData('Learnsets', 'typhlosion').learnset.calmmind = ['9L1'];
this.modData('Learnsets', 'typhlosion').learnset.morningsun = ['9L1'];
this.modData('Learnsets', 'terapagos').learnset.nastyplot = ['9L1'];
this.modData('Learnsets', 'tatsugiri').learnset.switcheroo = ['9L1'];
this.modData('Learnsets', 'tatsugiri').learnset.sashimishuffle = ['9L1'];
this.modData('Learnsets', 'tatsugiri').learnset.twister = ['9L1'];
this.modData('Learnsets', 'tatsugiri').learnset.waterspout = ['9L1'];
this.modData('Learnsets', 'flapple').learnset.earthquake = ['9L1'];
this.modData('Learnsets', 'flapple').learnset.grabapple = ['9L1'];
this.modData('Learnsets', 'flapple').learnset.flareblitz = ['9L1'];
this.modData('Learnsets', 'genesect').learnset.earthquake = ['9L1'];
this.modData('Learnsets', 'genesect').learnset.sunsteelstrike = ['9L1'];
this.modData('Learnsets', 'genesect').learnset.behemothblade = ['9L1'];
this.modData('Learnsets', 'genesect').learnset.makeitrain = ['9L1'];
this.modData('Learnsets', 'genesect').learnset.tachyoncutter = ['9L1'];
this.modData('Learnsets', 'honchkrow').learnset.crowverload = ['9L1'];
this.modData('Learnsets', 'honchkrow').learnset.oblivionwing = ['9L1'];
this.modData('Learnsets', 'honchkrow').learnset.closecombat = ['9L1'];
this.modData('Learnsets', 'primeape').learnset.knockoff = ['9L1'];
this.modData('Learnsets', 'primeape').learnset.ironhead = ['9L1'];
this.modData('Learnsets', 'rillaboom').learnset.naturesfury = ['9L1'];
this.modData('Learnsets', 'rillaboom').learnset.landswrath = ['9L1'];
this.modData('Learnsets', 'mandibuzz').learnset.fling = ['9L1'];
this.modData('Learnsets', 'mandibuzz').learnset.scavenge = ['9L1'];
this.modData('Learnsets', 'mandibuzz').learnset.bonemerang = ['9L1'];
this.modData('Learnsets', 'feraligatr').learnset.firefang = ['9L1'];
this.modData('Learnsets', 'feraligatr').learnset.thunderfang = ['9L1'];
this.modData('Learnsets', 'feraligatr').learnset.poisonfang = ['9L1'];
this.modData('Learnsets', 'salazzle').learnset.magmastorm = ['9L1'];
this.modData('Learnsets', 'salazzle').learnset.malignantchain = ['9L1'];
this.modData('Learnsets', 'salazzle').learnset.psychicnoise = ['9L1'];
this.modData('Learnsets', 'salazzle').learnset.banefulbunker = ['9L1'];
this.modData('Learnsets', 'kyogre').learnset.hurricane = ['9L1'];
this.modData('Learnsets', 'kyogre').learnset.tidalsurge = ['9L1'];
this.modData('Learnsets', 'azelf').learnset.rapidspin = ['9L1'];
this.modData('Learnsets', 'azelf').learnset.lootbox = ['9L1'];
this.modData('Learnsets', 'azelf').learnset.acupressure = ['9L1'];
this.modData('Learnsets', 'decidueye').learnset.sinisterarrows = ['9L1'];
this.modData('Learnsets', 'ogerpon').learnset.sappyseed = ['9L1'];
this.modData('Learnsets', 'ogerpon').learnset.thousandwaves = ['9L1'];
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'];
},
};

View File

@ -15,10 +15,8 @@ export const Scripts: ModdedBattleScriptsData = {
move.hit = 0;
}
if (!move.ignoreImmunity || (move.ignoreImmunity !== true && !move.ignoreImmunity[move.type])) {
if (!target.runImmunity(move.type, !suppressMessages)) {
return false;
}
if (!target.runImmunity(move, !suppressMessages)) {
return false;
}
if (move.ohko) return target.maxhp;

View File

@ -10,7 +10,7 @@ There were only 151 Pokémon plus MissingNo, just a handful of moves, no abiliti
EVd to the max and we had some kind of different IVs, which maxed at 15 and every point gave 2 to the stat, so in
a similar fashion, Pokes used to have 30 IVs on each stat.
The following sources have been used and extremly useful when developing this mod:
The following sources have been used and extremely useful when developing this mod:
https://raw.github.com/po-devs/pokemon-online/master/bin/database/rby-stuff.txt
https://www.smogon.com/rb/articles/differences
https://www.smogon.com/forums/threads/past-gens-research-thread.3506992/#post-5878612

View File

@ -185,38 +185,98 @@ export const Conditions: import('../../../sim/dex-conditions').ModdedConditionDa
},
partiallytrapped: {
name: 'partiallytrapped',
// this is the duration of Wrap if it doesn't continue.
// (i.e. if the attacker switches out.)
// the full duration is tracked in partialtrappinglock
duration: 2,
// defender still takes PSN damage, etc
// TODO: research exact mechanics
onBeforeMovePriority: 9,
onBeforeMove(pokemon) {
this.add('cant', pokemon, 'partiallytrapped');
return false;
},
onRestart() {
this.effectState.duration = 2;
},
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';
},
onDisableMove(target) {
target.maybeLocked = true;
},
},
fakepartiallytrapped: {
name: 'fakepartiallytrapped',
// Wrap ended this turn, but you don't know that
// until you try to use an attack
duration: 2,
onDisableMove(target) {
target.maybeLocked = true;
},
},
partialtrappinglock: {
name: 'partialtrappinglock',
durationCallback() {
const duration = this.sample([2, 2, 2, 3, 3, 3, 4, 5]);
return duration;
return this.sample([2, 2, 2, 3, 3, 3, 4, 5]);
},
onStart(target, source, effect) {
const foe = target.foes()[0];
if (!foe) return false;
this.effectState.move = effect.id;
this.effectState.totalDuration = this.effectState.duration!;
this.effectState.damage = this.lastDamage;
this.effectState.locked = foe;
foe.addVolatile('partiallytrapped', target, effect);
},
onDisableMove(pokemon) {
if (!pokemon.hasMove(this.effectState.move)) {
onOverrideAction(pokemon, target, move) {
return this.effectState.move;
},
onBeforeMove(pokemon, target, move) {
if (target !== this.effectState.locked) {
pokemon.removeVolatile('partialtrappinglock');
}
},
onAfterMove(pokemon, target, move) {
if (target && target.hp <= 0) {
delete pokemon.volatiles['partialtrappinglock'];
return;
}
for (const moveSlot of pokemon.moveSlots) {
if (moveSlot.id !== this.effectState.move) {
pokemon.disableMove(moveSlot.id);
if (this.effectState.duration === 1) {
if (this.effectState.totalDuration !== 5) {
pokemon.addVolatile('fakepartiallytrapped');
pokemon.volatiles['fakepartiallytrapped'].counterpart = target;
target.addVolatile('fakepartiallytrapped');
target.volatiles['fakepartiallytrapped'].counterpart = pokemon;
}
} else {
target.addVolatile('partiallytrapped', pokemon, move);
}
},
onLockMove() {
return this.effectState.move;
},
onDisableMove(pokemon) {
pokemon.maybeLocked = true;
},
},
mustrecharge: {
inherit: true,
duration: 0,
onBeforeMovePriority: 7,
onStart() {},
onAfterMove(pokemon, target, move) {
if (target && target.hp <= 0) {
delete pokemon.volatiles['mustrecharge'];
return;
}
this.add('-mustrecharge', pokemon);
},
},
lockedmove: {
// Thrash and Petal Dance.
@ -236,6 +296,11 @@ export const Conditions: import('../../../sim/dex-conditions').ModdedConditionDa
this.queue.changeAction(pokemon, { choice: 'move', moveid: move.id });
}
},
onAfterMove(pokemon) {
if (pokemon.volatiles['lockedmove'].time <= 0) {
pokemon.removeVolatile('lockedmove');
}
},
},
twoturnmove: {
// Skull Bash, Solar Beam, ...

View File

@ -21,7 +21,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "LC",
},
wartortle: {
tier: "ZU",
tier: "NFE",
},
blastoise: {
tier: "NU",
@ -51,7 +51,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "NFE",
},
pidgeot: {
tier: "ZU",
tier: "PU",
},
rattata: {
tier: "LC",
@ -90,7 +90,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "NFE",
},
nidoqueen: {
tier: "PU",
tier: "ZU",
},
nidoranm: {
tier: "LC",
@ -117,7 +117,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "LC",
},
wigglytuff: {
tier: "PU",
tier: "ZU",
},
zubat: {
tier: "LC",
@ -132,7 +132,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "NFE",
},
vileplume: {
tier: "PU",
tier: "ZU",
},
paras: {
tier: "LC",
@ -168,7 +168,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "LC",
},
primeape: {
tier: "ZU",
tier: "PU",
},
growlithe: {
tier: "LC",
@ -189,7 +189,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "PU",
},
kadabra: {
tier: "UU",
tier: "NU",
},
alakazam: {
tier: "OU",
@ -201,7 +201,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "NFE",
},
machamp: {
tier: "PU",
tier: "ZU",
},
bellsprout: {
tier: "LC",
@ -210,13 +210,13 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "NFE",
},
victreebel: {
tier: "OU",
tier: "NU",
},
tentacool: {
tier: "ZU",
},
tentacruel: {
tier: "UU",
tier: "NU",
},
geodude: {
tier: "LC",
@ -225,19 +225,19 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "PU",
},
golem: {
tier: "UU",
tier: "NU",
},
ponyta: {
tier: "ZU",
tier: "LC",
},
rapidash: {
tier: "PU",
tier: "UU",
},
slowpoke: {
tier: "ZU",
},
slowbro: {
tier: "OU",
tier: "UU",
},
magnemite: {
tier: "LC",
@ -258,7 +258,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "LC",
},
dewgong: {
tier: "UU",
tier: "NU",
},
grimer: {
tier: "LC",
@ -288,19 +288,19 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "ZU",
},
hypno: {
tier: "UUBL",
tier: "UU",
},
krabby: {
tier: "LC",
},
kingler: {
tier: "PU",
tier: "ZU",
},
voltorb: {
tier: "LC",
},
electrode: {
tier: "UU",
tier: "NU",
},
exeggcute: {
tier: "PU",
@ -339,7 +339,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "OU",
},
tangela: {
tier: "UU",
tier: "NU",
},
kangaskhan: {
tier: "UU",
@ -366,7 +366,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "NU",
},
scyther: {
tier: "ZU",
tier: "PU",
},
jynx: {
tier: "OU",
@ -375,10 +375,10 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "UU",
},
magmar: {
tier: "ZU",
tier: "PU",
},
pinsir: {
tier: "PU",
tier: "ZU",
},
tauros: {
tier: "OU",
@ -390,7 +390,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "UU",
},
lapras: {
tier: "UUBL",
tier: "UU",
},
ditto: {
tier: "ZU",
@ -399,7 +399,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "LC",
},
vaporeon: {
tier: "UU",
tier: "NU",
},
jolteon: {
tier: "OU",
@ -414,7 +414,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "ZU",
},
omastar: {
tier: "UU",
tier: "NU",
},
kabuto: {
tier: "LC",
@ -429,13 +429,13 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "OU",
},
articuno: {
tier: "UUBL",
tier: "UU",
},
zapdos: {
tier: "OU",
},
moltres: {
tier: "NU",
tier: "UU",
},
dratini: {
tier: "LC",

View File

@ -76,7 +76,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
bind: {
inherit: true,
ignoreImmunity: true,
volatileStatus: 'partiallytrapped',
self: {
volatileStatus: 'partialtrappinglock',
},
@ -86,19 +85,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
this.hint("In Gen 1, partial trapping moves negate the recharge turn of Hyper Beam, even if they miss.", true);
}
},
onHit(target, source) {
/**
* The duration of the partially trapped must be always renewed to 2
* so target doesn't move on trapper switch out as happens in gen 1.
* However, this won't happen if there's no switch and the trapper is
* about to end its partial trapping.
**/
if (target.volatiles['partiallytrapped']) {
if (source.volatiles['partialtrappinglock'] && source.volatiles['partialtrappinglock'].duration! > 1) {
target.volatiles['partiallytrapped'].duration = 2;
}
}
},
},
bite: {
inherit: true,
@ -137,7 +123,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
inherit: true,
accuracy: 75,
pp: 10,
volatileStatus: 'partiallytrapped',
self: {
volatileStatus: 'partialtrappinglock',
},
@ -147,19 +132,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
this.hint("In Gen 1, partial trapping moves negate the recharge turn of Hyper Beam, even if they miss.", true);
}
},
onHit(target, source) {
/**
* The duration of the partially trapped must be always renewed to 2
* so target doesn't move on trapper switch out as happens in gen 1.
* However, this won't happen if there's no switch and the trapper is
* about to end its partial trapping.
**/
if (target.volatiles['partiallytrapped']) {
if (source.volatiles['partialtrappinglock'] && source.volatiles['partialtrappinglock'].duration! > 1) {
target.volatiles['partiallytrapped'].duration = 2;
}
}
},
},
constrict: {
inherit: true,
@ -239,22 +211,13 @@ 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,
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));
@ -263,9 +226,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
// 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--;
@ -280,17 +240,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
return false;
}
},
onDisableMove(pokemon) {
for (const moveSlot of pokemon.moveSlots) {
if (moveSlot.id === this.effectState.move) {
pokemon.disableMove(moveSlot.id);
}
}
},
},
secondary: null,
target: "normal",
type: "Normal",
},
dizzypunch: {
inherit: true,
@ -320,7 +270,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
inherit: true,
accuracy: 70,
basePower: 15,
volatileStatus: 'partiallytrapped',
self: {
volatileStatus: 'partialtrappinglock',
},
@ -330,19 +279,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
this.hint("In Gen 1, partial trapping moves negate the recharge turn of Hyper Beam, even if they miss.", true);
}
},
onHit(target, source) {
/**
* The duration of the partially trapped must be always renewed to 2
* so target doesn't move on trapper switch out as happens in gen 1.
* However, this won't happen if there's no switch and the trapper is
* about to end its partial trapping.
**/
if (target.volatiles['partiallytrapped']) {
if (source.volatiles['partialtrappinglock'] && source.volatiles['partialtrappinglock'].duration! > 1) {
target.volatiles['partiallytrapped'].duration = 2;
}
}
},
},
fly: {
inherit: true,
@ -361,11 +297,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() {},
},
},
glare: {
@ -450,9 +384,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
inherit: true,
onHit() {},
condition: {
onStart(target) {
this.add('-start', target, 'move: Leech Seed');
},
inherit: true,
onAfterMoveSelfPriority: 1,
onAfterMoveSelf(pokemon) {
const leecher = this.getAtSlot(pokemon.volatiles['leechseed'].sourceSlot);
@ -478,15 +410,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,
onTryHit(pokemon) {
if (pokemon.volatiles['lightscreen']) {
return false;
@ -498,7 +424,22 @@ 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,
@ -523,6 +464,13 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
this.add('-start', source, 'Mimic', move.name);
},
},
minimize: {
inherit: true,
condition: {
inherit: true,
onSourceModifyDamage() {},
},
},
mirrormove: {
inherit: true,
onHit(pokemon) {
@ -537,9 +485,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) {
@ -655,15 +601,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,
onTryHit(pokemon) {
if (pokemon.volatiles['reflect']) {
return false;
@ -674,9 +614,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
this.add('-start', pokemon, 'Reflect');
},
},
secondary: null,
target: "self",
type: "Psychic",
},
rest: {
inherit: true,
@ -808,15 +746,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
onModifyMove() {},
},
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');
@ -836,11 +766,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() {},
onTryHitPriority: -1,
onTryHit(target, source, move) {
if (move.category === 'Status') {
@ -862,8 +797,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
let uncappedDamage = move.hit > 1 ? this.lastDamage : this.actions.getDamage(source, target, move);
if (move.id === 'bide') uncappedDamage = source.volatiles['bide'].damage * 2;
if (!uncappedDamage && uncappedDamage !== 0) return null;
uncappedDamage = this.runEvent('SubDamage', target, source, move, uncappedDamage);
if (!uncappedDamage && uncappedDamage !== 0) return uncappedDamage;
this.lastDamage = uncappedDamage;
target.volatiles['substitute'].hp -= uncappedDamage > target.volatiles['substitute'].hp ?
target.volatiles['substitute'].hp : uncappedDamage;
@ -906,13 +839,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,
@ -950,7 +877,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
inherit: true,
accuracy: 85,
ignoreImmunity: true,
volatileStatus: 'partiallytrapped',
self: {
volatileStatus: 'partialtrappinglock',
},
@ -960,18 +886,5 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
this.hint("In Gen 1, partial trapping moves negate the recharge turn of Hyper Beam, even if they miss.", true);
}
},
onHit(target, source) {
/**
* The duration of the partially trapped must be always renewed to 2
* so target doesn't move on trapper switch out as happens in gen 1.
* However, this won't happen if there's no switch and the trapper is
* about to end its partial trapping.
**/
if (target.volatiles['partiallytrapped']) {
if (source.volatiles['partialtrappinglock'] && source.volatiles['partialtrappinglock'].duration! > 1) {
target.volatiles['partiallytrapped'].duration = 2;
}
}
},
},
};

View File

@ -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': {

View File

@ -25,6 +25,25 @@ export const Scripts: ModdedBattleScriptsData = {
// BattlePokemon scripts.
pokemon: {
inherit: true,
// In gen 1, a Pokémon can have two instances of the same move using Mimic
// we need to make sure to deduct PP from a move that has PP left
deductPP(move, amount, target) {
move = this.battle.dex.moves.get(move);
// first loop: get the first instance with PP left
// second loop: get the first instance, even if it has no PP left
for (let i = 0; i < 2; i++) {
for (const ppData of this.moveSlots) {
if (ppData.id !== move.id) continue;
ppData.used = true;
if (!ppData.pp && i === 0) continue;
if (!amount) amount = 1;
ppData.pp -= amount;
return amount;
}
}
return 0;
},
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");
@ -129,16 +148,19 @@ export const Scripts: ModdedBattleScriptsData = {
let sourceEffect = options?.sourceEffect;
const target = this.battle.getTarget(pokemon, moveOrMoveName, targetLoc);
let move = this.battle.dex.getActiveMove(moveOrMoveName);
if (move.id !== 'struggle') {
const changedMove = this.battle.runEvent('OverrideAction', pokemon, target, move);
if (changedMove && changedMove !== true) {
move = this.battle.dex.getActiveMove(changedMove);
}
}
// 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.
const autoHyperBeam = (
move.id === 'recharge' && !pokemon.volatiles['mustrecharge'] && !pokemon.volatiles['partiallytrapped']
);
if (autoHyperBeam) {
if (move.id === 'recharge' && !pokemon.volatiles['mustrecharge'] && !pokemon.volatiles['partiallytrapped']) {
move = this.battle.dex.getActiveMove('hyperbeam');
this.battle.hint(`In Gen 1, 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.`, true);
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);
}
if (target?.subFainted) target.subFainted = null;
@ -151,41 +173,31 @@ export const Scripts: ModdedBattleScriptsData = {
this.battle.runEvent('AfterMoveSelf', pokemon, target, move);
return;
}
if (move.beforeMoveCallback) {
if (move.beforeMoveCallback.call(this.battle, pokemon, target, move)) {
this.battle.clearActiveMove(true);
return;
}
if (move.beforeMoveCallback?.call(this.battle, pokemon, target, move)) {
this.battle.clearActiveMove(true);
return;
}
let lockedMove = this.battle.runEvent('LockMove', pokemon);
if (lockedMove === true) lockedMove = false;
if (
!lockedMove &&
(!pokemon.volatiles['partialtrappinglock'] || pokemon.volatiles['partialtrappinglock'].locked !== target)
) {
pokemon.deductPP(move, null, target);
} else {
sourceEffect = move;
if (pokemon.volatiles['twoturnmove']) {
// Two-turn moves like Sky Attack deduct PP on their second turn.
pokemon.deductPP(pokemon.volatiles['twoturnmove'].originalMove, null, target);
}
}
if (
(pokemon.volatiles['partialtrappinglock'] && target !== pokemon.volatiles['partialtrappinglock'].locked) ||
autoHyperBeam
) {
const moveSlot = pokemon.moveSlots.find(ms => ms.id === move.id);
const lockedMove = pokemon.getLockedMove();
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 = 63;
this.battle.hint("In Gen 1, if a player is forced to use a move with 0 PP, the move will underflow to have 63 PP.");
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.");
}
}
this.useMove(move, pokemon, { target, sourceEffect });
// Restore PP if the move is the first turn of a charging move. Save the move from which PP should be deducted if the move succeeds.
if (pokemon.volatiles['twoturnmove']) {
pokemon.deductPP(move, -1, target);
pokemon.volatiles['twoturnmove'].originalMove = move.id;
pokemon.volatiles['twoturnmove'].ppMove = move.id;
}
},
// This function deals with AfterMoveSelf events.
@ -223,37 +235,9 @@ export const Scripts: ModdedBattleScriptsData = {
// The move is our 'final' move (a failed Mirror Move, or any move that isn't Metronome or Mirror Move).
pokemon.side.lastMove = move;
if (pokemon.volatiles['lockedmove']?.time <= 0) pokemon.removeVolatile('lockedmove');
// If target fainted
if (target && target.hp <= 0) {
// We remove recharge
if (pokemon.volatiles['mustrecharge']) pokemon.removeVolatile('mustrecharge');
delete pokemon.volatiles['partialtrappinglock'];
} else {
if (pokemon.volatiles['mustrecharge']) this.battle.add('-mustrecharge', pokemon);
if (pokemon.hp) this.battle.runEvent('AfterMoveSelf', pokemon, target, move);
}
// For partial trapping moves, we are saving the target
if (move.volatileStatus === 'partiallytrapped' && target && target.hp > 0) {
// Let's check if the lock exists
if (pokemon.volatiles['partialtrappinglock'] && target.volatiles['partiallytrapped']) {
// Here the partialtrappinglock volatile has been already applied
const sourceVolatile = pokemon.volatiles['partialtrappinglock'];
const targetVolatile = target.volatiles['partiallytrapped'];
if (!sourceVolatile.locked) {
// If it's the first hit, we save the target
sourceVolatile.locked = target;
} else if (target !== pokemon && target !== sourceVolatile.locked) {
// Our target switched out! Re-roll the duration, damage, and accuracy.
const duration = this.battle.sample([2, 2, 2, 3, 3, 3, 4, 5]);
sourceVolatile.duration = duration;
sourceVolatile.locked = target;
// Duration reset thus partially trapped at 2 always.
targetVolatile.duration = 2;
}
} // If we move to here, the move failed and there's no partial trapping lock.
this.battle.runEvent('AfterMove', pokemon, target, move);
if (!target || target.hp > 0) {
this.battle.runEvent('AfterMoveSelf', pokemon, target, move);
}
}
}
@ -293,7 +277,7 @@ export const Scripts: ModdedBattleScriptsData = {
return false;
}
if (sourceEffect) attrs += `|[from]${this.battle.dex.conditions.get(sourceEffect)}`;
if (sourceEffect) attrs += `|[from] ${this.battle.dex.conditions.get(sourceEffect).name}`;
this.battle.addMove('move', pokemon, move.name, `${target}${attrs}`);
if (!this.battle.singleEvent('Try', move, null, pokemon, target, move)) {
@ -332,10 +316,8 @@ export const Scripts: ModdedBattleScriptsData = {
return true;
}
if (!move.negateSecondary) {
this.battle.singleEvent('AfterMoveSecondarySelf', move, null, pokemon, target, move);
this.battle.runEvent('AfterMoveSecondarySelf', pokemon, target, move);
}
this.battle.singleEvent('AfterMoveSecondarySelf', move, null, pokemon, target, move);
this.battle.runEvent('AfterMoveSecondarySelf', pokemon, target, move);
return true;
},
// This function attempts a move hit and returns the attempt result before the actual hit happens.
@ -370,10 +352,7 @@ export const Scripts: ModdedBattleScriptsData = {
}
// Then, check if the Pokémon is immune to this move.
if (
(!move.ignoreImmunity || (move.ignoreImmunity !== true && !move.ignoreImmunity[move.type])) &&
!target.runImmunity(move.type, true)
) {
if (!target.runImmunity(move, true)) {
if (move.selfdestruct) {
this.battle.faint(pokemon, pokemon, move);
}
@ -388,11 +367,6 @@ export const Scripts: ModdedBattleScriptsData = {
// Now, let's calculate the accuracy.
let accuracy = move.accuracy;
// Partial trapping moves: true accuracy while it lasts
if (move.volatileStatus === 'partiallytrapped' && target === pokemon.volatiles['partialtrappinglock']?.locked) {
accuracy = true;
}
// If a sleep inducing move is used while the user is recharging, the accuracy is true.
if (move.status === 'slp' && target?.volatiles['mustrecharge']) {
accuracy = true;
@ -499,10 +473,8 @@ export const Scripts: ModdedBattleScriptsData = {
if (move.ohko) this.battle.add('-ohko');
if (!move.negateSecondary) {
this.battle.singleEvent('AfterMoveSecondary', move, null, target, pokemon, move);
this.battle.runEvent('AfterMoveSecondary', target, pokemon, move);
}
this.battle.singleEvent('AfterMoveSecondary', move, null, target, pokemon, move);
this.battle.runEvent('AfterMoveSecondary', target, pokemon, move);
return damage;
},
@ -527,14 +499,6 @@ export const Scripts: ModdedBattleScriptsData = {
if (target) {
hitResult = this.battle.singleEvent('TryHit', moveData, {}, target, pokemon, move);
// Handle here the applying of partial trapping moves to Pokémon with Substitute
if (targetSub && moveData.volatileStatus && moveData.volatileStatus === 'partiallytrapped') {
target.addVolatile(moveData.volatileStatus, pokemon, move);
if (!pokemon.volatiles['partialtrappinglock'] || pokemon.volatiles['partialtrappinglock'].duration! > 1) {
target.volatiles[moveData.volatileStatus].duration = 2;
}
}
if (!hitResult) {
if (hitResult === false) this.battle.add('-fail', target);
return false;
@ -609,7 +573,7 @@ export const Scripts: ModdedBattleScriptsData = {
didSomething = true;
// Check the status of the Pokémon whose turn is not.
// When a move that affects stat levels is used, if the Pokémon whose turn it is not right now is paralyzed or
// burned, the correspoding stat penalties will be applied again to that Pokémon.
// burned, the corresponding stat penalties will be applied again to that Pokémon.
if (pokemon.side.foe.active[0].status) {
// If it's paralysed, quarter its speed.
if (pokemon.side.foe.active[0].status === 'par') {
@ -700,11 +664,6 @@ export const Scripts: ModdedBattleScriptsData = {
this.moveHit(pokemon, pokemon, move, moveData.self, isSecondary, true);
}
// Now we can save the partial trapping damage.
if (pokemon.volatiles['partialtrappinglock']) {
pokemon.volatiles['partialtrappinglock'].damage = this.battle.lastDamage;
}
// Apply move secondaries.
if (moveData.secondaries && target && target.hp > 0) {
for (const secondary of moveData.secondaries) {
@ -751,10 +710,8 @@ export const Scripts: ModdedBattleScriptsData = {
}
// Let's see if the target is immune to the move.
if (!move.ignoreImmunity || (move.ignoreImmunity !== true && !move.ignoreImmunity[move.type])) {
if (!target.runImmunity(move.type, true)) {
return false;
}
if (!target.runImmunity(move, true)) {
return false;
}
// Is it an OHKO move?
@ -778,7 +735,7 @@ export const Scripts: ModdedBattleScriptsData = {
}
// If it's the first hit on a Normal-type partially trap move, it hits Ghosts anyways but damage is 0.
if (move.volatileStatus === 'partiallytrapped' && move.type === 'Normal' && target.hasType('Ghost')) {
if (move.self?.volatileStatus === 'partialtrappinglock' && move.type === 'Normal' && target.hasType('Ghost')) {
return 0;
}

View File

@ -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);
@ -39,10 +34,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
// NOTE: In future generations the damage is capped to the remaining HP of the
// Substitute, here we deliberately use the uncapped damage when tracking lastDamage etc.
// Also, multi-hit moves must always deal the same damage as the first hit for any subsequent hits
let uncappedDamage = move.hit > 1 ? this.lastDamage : this.actions.getDamage(source, target, move);
const uncappedDamage = move.hit > 1 ? this.lastDamage : this.actions.getDamage(source, target, move);
if (!uncappedDamage && uncappedDamage !== 0) return null;
uncappedDamage = this.runEvent('SubDamage', target, source, move, uncappedDamage);
if (!uncappedDamage && uncappedDamage !== 0) return uncappedDamage;
this.lastDamage = uncappedDamage;
target.volatiles['substitute'].hp -= uncappedDamage > target.volatiles['substitute'].hp ?
target.volatiles['substitute'].hp : uncappedDamage;
@ -78,9 +71,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
}
return accuracy;
},
onEnd(target) {
this.add('-end', target, 'Substitute');
},
},
},
swift: {

View File

@ -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: {

View File

@ -225,7 +225,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "NFE",
},
golem: {
tier: "OU",
tier: "UU",
},
ponyta: {
tier: "LC",
@ -270,7 +270,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "LC",
},
cloyster: {
tier: "OU",
tier: "UU",
},
gastly: {
tier: "LC",
@ -279,7 +279,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "UU",
},
gengar: {
tier: "OU",
tier: "UU",
},
onix: {
tier: "UU",
@ -342,7 +342,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "UU",
},
kangaskhan: {
tier: "OU",
tier: "UU",
},
horsea: {
tier: "LC",
@ -369,7 +369,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "UU",
},
jynx: {
tier: "OU",
tier: "UU",
},
electabuzz: {
tier: "UU",
@ -402,7 +402,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "UU",
},
jolteon: {
tier: "OU",
tier: "UU",
},
flareon: {
tier: "UU",

View File

@ -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 });
@ -220,12 +220,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');
@ -249,8 +244,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
damage = target.volatiles['substitute'].hp;
}
if (!damage && damage !== 0) return null;
damage = this.runEvent('SubDamage', target, source, move, damage);
if (!damage && damage !== 0) return damage;
target.volatiles['substitute'].hp -= damage;
this.lastDamage = damage;
if (target.volatiles['substitute'].hp <= 0) {
@ -277,9 +270,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
}
return 0;
},
onEnd(target) {
this.add('-end', target, 'Substitute');
},
},
secondary: null,
target: "self",

View File

@ -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'];
}
},
},
};

View File

@ -199,7 +199,7 @@ export const Scripts: ModdedBattleScriptsData = {
return false;
}
if (sourceEffect) attrs += `|[from]${this.battle.dex.conditions.get(sourceEffect)}`;
if (sourceEffect) attrs += `|[from] ${this.battle.dex.conditions.get(sourceEffect).name}`;
this.battle.addMove('move', pokemon, move.name, `${target}${attrs}`);
if (!this.battle.singleEvent('Try', move, null, pokemon, target, move)) {
@ -231,10 +231,8 @@ export const Scripts: ModdedBattleScriptsData = {
return true;
}
if (!move.negateSecondary) {
this.battle.singleEvent('AfterMoveSecondarySelf', move, null, pokemon, target, move);
this.battle.runEvent('AfterMoveSecondarySelf', pokemon, target, move);
}
this.battle.singleEvent('AfterMoveSecondarySelf', move, null, pokemon, target, move);
this.battle.runEvent('AfterMoveSecondarySelf', pokemon, target, move);
return true;
},
tryMoveHit(target, pokemon, move) {
@ -252,10 +250,7 @@ export const Scripts: ModdedBattleScriptsData = {
}
// Then, check if the Pokemon is immune to this move.
if (
(!move.ignoreImmunity || (move.ignoreImmunity !== true && !move.ignoreImmunity[move.type])) &&
!target.runImmunity(move.type, true)
) {
if (!target.runImmunity(move, true)) {
if (move.selfdestruct) {
this.battle.faint(pokemon, pokemon, move);
}
@ -305,10 +300,16 @@ export const Scripts: ModdedBattleScriptsData = {
}
accuracy = this.battle.runEvent('Accuracy', target, pokemon, move, accuracy);
// Stadium fixes the 1/256 accuracy bug.
if (accuracy !== true && !this.battle.randomChance(accuracy + 1, 256)) {
// Stadium attempts to fix the 1/256 miss by rerolling if the first value
// would trigger the 1/256 miss.
let randomValue = this.battle.random(256);
if (randomValue === 256) randomValue = this.battle.random(256);
if (accuracy !== true && randomValue > accuracy) {
this.battle.attrLastMove('[miss]');
this.battle.add('-miss', pokemon);
if (accuracy === 255) {
this.battle.hint("In Pokemon Stadium, moves with 100% accuracy can still miss 1/65536 of the time.");
}
damage = false;
this.battle.lastDamage = 0;
}
@ -365,10 +366,8 @@ export const Scripts: ModdedBattleScriptsData = {
if (move.ohko) this.battle.add('-ohko');
if (!move.negateSecondary) {
this.battle.singleEvent('AfterMoveSecondary', move, null, target, pokemon, move);
this.battle.runEvent('AfterMoveSecondary', target, pokemon, move);
}
this.battle.singleEvent('AfterMoveSecondary', move, null, target, pokemon, move);
this.battle.runEvent('AfterMoveSecondary', target, pokemon, move);
return damage;
},
@ -549,10 +548,8 @@ export const Scripts: ModdedBattleScriptsData = {
}
// Let's see if the target is immune to the move.
if (!move.ignoreImmunity || (move.ignoreImmunity !== true && !move.ignoreImmunity[move.type])) {
if (!target.runImmunity(move.type, true)) {
return false;
}
if (!target.runImmunity(move, true)) {
return false;
}
// Is it an OHKO move?

View File

@ -18,7 +18,7 @@ export const Conditions: import('../../../sim/dex-conditions').ModdedConditionDa
inherit: true,
onBeforeMovePriority: 2,
onBeforeMove(pokemon) {
if (this.randomChance(1, 4)) {
if (this.randomChance(63, 256)) {
this.add('cant', pokemon, 'par');
return false;
}
@ -177,6 +177,11 @@ export const Conditions: import('../../../sim/dex-conditions').ModdedConditionDa
onStart(target, source, effect) {
this.effectState.move = effect.id;
},
onAfterMove(pokemon) {
if (this.effectState.duration === 1) {
pokemon.removeVolatile('lockedmove');
}
},
onEnd(target) {
// Confusion begins even if already confused
delete target.volatiles['confusion'];

View File

@ -12,7 +12,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "LC",
},
charmeleon: {
tier: "ZU",
tier: "ZUBL",
},
charizard: {
tier: "UUBL",
@ -21,7 +21,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "LC",
},
wartortle: {
tier: "ZU",
tier: "PU",
},
blastoise: {
tier: "UU",
@ -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",
@ -162,7 +162,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "PU",
},
diglett: {
tier: "ZU",
tier: "LC",
},
dugtrio: {
tier: "NU",
@ -192,10 +192,10 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "UU",
},
poliwag: {
tier: "ZU",
tier: "ZUBL",
},
poliwhirl: {
tier: "ZUBL",
tier: "PUBL",
},
poliwrath: {
tier: "NUBL",
@ -237,7 +237,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "UUBL",
},
geodude: {
tier: "ZU",
tier: "PU",
},
graveler: {
tier: "NU",
@ -246,13 +246,13 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "OU",
},
ponyta: {
tier: "PU",
tier: "ZU",
},
rapidash: {
tier: "NU",
},
slowpoke: {
tier: "ZU",
tier: "LC",
},
slowbro: {
tier: "UU",
@ -267,7 +267,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "UU",
},
farfetchd: {
tier: "NU",
tier: "PU",
},
doduo: {
tier: "ZU",
@ -321,7 +321,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "NU",
},
voltorb: {
tier: "ZU",
tier: "PU",
},
electrode: {
tier: "UU",
@ -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",
@ -513,7 +513,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "LC",
},
bayleef: {
tier: "ZU",
tier: "PU",
},
meganium: {
tier: "UUBL",
@ -534,13 +534,13 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "ZU",
},
feraligatr: {
tier: "NUBL",
tier: "UU",
},
sentret: {
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: "PU",
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",
@ -699,13 +699,13 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "PU",
},
mantine: {
tier: "ZU",
tier: "ZUBL",
},
skarmory: {
tier: "OU",
},
houndour: {
tier: "NU",
tier: "PU",
},
houndoom: {
tier: "UUBL",

View File

@ -252,11 +252,11 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
}
},
},
berserkgene: {
berry: {
inherit: true,
isNonstandard: null,
},
berry: {
berserkgene: {
inherit: true,
isNonstandard: null,
},

View File

@ -51,64 +51,10 @@ 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]');
},
},
},
counter: {
@ -139,12 +85,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() {},
},
},
detect: {
@ -157,10 +103,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 +115,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
if (source.volatiles['lockon'] && target === source.volatiles['lockon'].source) return;
return false;
},
onSourceModifyDamage() {},
onSourceBasePower(basePower, target, source, move) {
if (move.id === 'earthquake' || move.id === 'magnitude') {
return this.chainModify(2);
@ -186,43 +130,19 @@ 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 moveIndex = lockedMove ? target.moves.indexOf(lockedMove) : -1;
if (moveIndex < 0 || target.lastMoveEncore?.flags['failencore'] || target.moveSlots[moveIndex].pp <= 0) {
const moveSlot = lockedMove ? target.getMoveData(lockedMove) : null;
if (!moveSlot || target.lastMoveEncore?.flags['failencore'] || moveSlot.pp <= 0) {
// it failed
return false;
}
this.effectState.move = lockedMove;
this.add('-start', target, 'Encore');
},
onOverrideAction(pokemon) {
return this.effectState.move;
},
onResidualOrder: 13,
onResidual(target) {
const lockedMoveIndex = target.moves.indexOf(this.effectState.move);
if (lockedMoveIndex >= 0 && target.moveSlots[lockedMoveIndex].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,
},
},
endure: {
@ -244,7 +164,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 +180,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
if (source.volatiles['lockon'] && target === source.volatiles['lockon'].source) return;
return false;
},
onSourceModifyDamage() {},
onSourceBasePower(basePower, target, source, move) {
if (move.id === 'gust' || move.id === 'twister') {
return this.chainModify(2);
@ -270,9 +191,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 +203,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: {
@ -340,9 +250,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
inherit: true,
onHit() {},
condition: {
onStart(target) {
this.add('-start', target, 'move: Leech Seed');
},
inherit: true,
onResidual() {},
onAfterMoveSelfPriority: 2,
onAfterMoveSelf(pokemon) {
if (!pokemon.hp) return;
@ -378,10 +287,8 @@ 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() {},
},
},
lowkick: {
@ -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,
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() {},
onAfterMoveSelfPriority: 1,
onAfterMoveSelf(pokemon) {
if (pokemon.status === 'slp') this.damage(pokemon.baseMaxhp / 4);
@ -527,11 +421,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
onMoveFail(target, source, move) {
source.addVolatile('lockedmove');
},
onAfterMove(pokemon) {
if (pokemon.volatiles['lockedmove'] && pokemon.volatiles['lockedmove'].duration === 1) {
pokemon.removeVolatile('lockedmove');
}
},
},
painsplit: {
inherit: true,
@ -540,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: {
@ -557,11 +438,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
onMoveFail(target, source, move) {
source.addVolatile('lockedmove');
},
onAfterMove(pokemon) {
if (pokemon.volatiles['lockedmove'] && pokemon.volatiles['lockedmove'].duration === 1) {
pokemon.removeVolatile('lockedmove');
}
},
},
poisongas: {
inherit: true,
@ -583,9 +459,18 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
},
pursuit: {
inherit: true,
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() {},
condition: {
duration: 1,
inherit: true,
onBeforeSwitchOut(pokemon) {
this.debug('Pursuit start');
let alreadyAdded = false;
@ -685,41 +570,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: {
@ -785,31 +637,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,
},
},
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);
@ -846,10 +681,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
if (!damage) {
return null;
}
damage = this.runEvent('SubDamage', target, source, move, damage);
if (!damage) {
return damage;
}
if (damage > target.volatiles['substitute'].hp) {
damage = target.volatiles['substitute'].hp as number;
}
@ -866,9 +697,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: {
@ -918,11 +746,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
onMoveFail(target, source, move) {
source.addVolatile('lockedmove');
},
onAfterMove(pokemon) {
if (pokemon.volatiles['lockedmove'] && pokemon.volatiles['lockedmove'].duration === 1) {
pokemon.removeVolatile('lockedmove');
}
},
},
toxic: {
inherit: true,

View File

@ -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',

View File

@ -187,10 +187,7 @@ export const Scripts: ModdedBattleScriptsData = {
move.ignoreImmunity = (move.category === 'Status');
}
if (
(!move.ignoreImmunity || (move.ignoreImmunity !== true && !move.ignoreImmunity[move.type])) &&
!target.runImmunity(move.type, true)
) {
if (!target.runImmunity(move, true)) {
return false;
}
@ -206,6 +203,11 @@ export const Scripts: ModdedBattleScriptsData = {
return false;
}
if (move.ohko && pokemon.level < target.level) {
this.battle.add('-immune', target, '[ohko]');
return false;
}
let accuracy = move.accuracy;
if (move.alwaysHit) {
accuracy = true;
@ -216,13 +218,8 @@ export const Scripts: ModdedBattleScriptsData = {
if (accuracy !== true) {
accuracy = Math.floor(accuracy * 255 / 100);
if (move.ohko) {
if (pokemon.level >= target.level) {
accuracy += (pokemon.level - target.level) * 2;
accuracy = Math.min(accuracy, 255);
} else {
this.battle.add('-immune', target, '[ohko]');
return false;
}
accuracy += (pokemon.level - target.level) * 2;
accuracy = Math.min(accuracy, 255);
}
if (!move.ignoreAccuracy) {
if (pokemon.boosts.accuracy > 0) {
@ -296,10 +293,8 @@ export const Scripts: ModdedBattleScriptsData = {
}
if (move.ohko) this.battle.add('-ohko');
if (!move.negateSecondary) {
this.battle.singleEvent('AfterMoveSecondary', move, null, target, pokemon, move);
this.battle.runEvent('AfterMoveSecondary', target, pokemon, move);
}
this.battle.singleEvent('AfterMoveSecondary', move, null, target, pokemon, move);
this.battle.runEvent('AfterMoveSecondary', target, pokemon, move);
if (move.recoil && move.totalDamage) {
this.battle.damage(this.calcRecoilDamage(move.totalDamage, move, pokemon), pokemon, target, 'recoil');
@ -497,10 +492,8 @@ export const Scripts: ModdedBattleScriptsData = {
}
// Let's test for immunities.
if (!move.ignoreImmunity || (move.ignoreImmunity !== true && !move.ignoreImmunity[move.type])) {
if (!target.runImmunity(move.type, true)) {
return false;
}
if (!target.runImmunity(move, true)) {
return false;
}
// Is it an OHKO move?

View File

@ -1,898 +0,0 @@
export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormatsDataTable = {
bulbasaur: {
tier: "LC",
},
ivysaur: {
tier: "NFE",
},
venusaur: {
tier: "OU",
doublesTier: "DOU",
},
charmander: {
tier: "LC",
},
charmeleon: {
tier: "NFE",
},
charizard: {
tier: "OU",
doublesTier: "DOU",
},
squirtle: {
tier: "LC",
},
wartortle: {
tier: "NFE",
},
blastoise: {
tier: "OU",
doublesTier: "DOU",
},
caterpie: {
tier: "LC",
},
metapod: {
tier: "NFE",
},
butterfree: {
tier: "OU",
doublesTier: "DOU",
},
weedle: {
tier: "LC",
},
kakuna: {
tier: "NFE",
},
beedrill: {
tier: "OU",
doublesTier: "DOU",
},
pidgey: {
tier: "LC",
},
pidgeotto: {
tier: "NFE",
},
pidgeot: {
tier: "OU",
doublesTier: "DOU",
},
rattata: {
tier: "LC",
},
raticate: {
tier: "OU",
doublesTier: "DOU",
},
spearow: {
tier: "LC",
},
fearow: {
tier: "OU",
doublesTier: "DOU",
},
ekans: {
tier: "LC",
},
arbok: {
tier: "OU",
doublesTier: "DOU",
},
pichu: {
tier: "LC",
},
pikachu: {
tier: "OU",
doublesTier: "NFE",
},
raichu: {
tier: "OU",
doublesTier: "DOU",
},
sandshrew: {
tier: "LC",
},
sandslash: {
tier: "OU",
doublesTier: "DOU",
},
nidoranf: {
tier: "LC",
},
nidorina: {
tier: "NFE",
},
nidoqueen: {
tier: "OU",
doublesTier: "DOU",
},
nidoranm: {
tier: "LC",
},
nidorino: {
tier: "NFE",
},
nidoking: {
tier: "OU",
doublesTier: "DOU",
},
cleffa: {
tier: "LC",
},
clefairy: {
tier: "NFE",
},
clefable: {
tier: "OU",
doublesTier: "DOU",
},
vulpix: {
tier: "LC",
},
ninetales: {
tier: "OU",
doublesTier: "DOU",
},
igglybuff: {
tier: "LC",
},
jigglypuff: {
tier: "NFE",
},
wigglytuff: {
tier: "OU",
doublesTier: "DOU",
},
zubat: {
tier: "LC",
},
golbat: {
tier: "NFE",
},
crobat: {
tier: "OU",
doublesTier: "DOU",
},
oddish: {
tier: "LC",
},
gloom: {
tier: "NFE",
},
vileplume: {
tier: "OU",
doublesTier: "DOU",
},
bellossom: {
tier: "OU",
doublesTier: "DOU",
},
paras: {
tier: "LC",
},
parasect: {
tier: "OU",
doublesTier: "DOU",
},
venonat: {
tier: "LC",
},
venomoth: {
tier: "OU",
doublesTier: "DOU",
},
diglett: {
tier: "LC",
},
dugtrio: {
tier: "OU",
doublesTier: "DOU",
},
meowth: {
tier: "LC",
},
persian: {
tier: "OU",
doublesTier: "DOU",
},
psyduck: {
tier: "LC",
},
golduck: {
tier: "OU",
doublesTier: "DOU",
},
mankey: {
tier: "LC",
},
primeape: {
tier: "OU",
doublesTier: "DOU",
},
growlithe: {
tier: "LC",
},
arcanine: {
tier: "OU",
doublesTier: "DOU",
},
poliwag: {
tier: "LC",
},
poliwhirl: {
tier: "NFE",
},
poliwrath: {
tier: "OU",
doublesTier: "DOU",
},
politoed: {
tier: "OU",
doublesTier: "DOU",
},
abra: {
tier: "LC",
},
kadabra: {
tier: "OU",
doublesTier: "NFE",
},
alakazam: {
tier: "OU",
doublesTier: "DOU",
},
machop: {
tier: "LC",
},
machoke: {
tier: "NFE",
},
machamp: {
tier: "OU",
doublesTier: "DOU",
},
bellsprout: {
tier: "LC",
},
weepinbell: {
tier: "NFE",
},
victreebel: {
tier: "OU",
doublesTier: "DOU",
},
tentacool: {
tier: "LC",
},
tentacruel: {
tier: "OU",
doublesTier: "DOU",
},
geodude: {
tier: "LC",
},
graveler: {
tier: "NFE",
},
golem: {
tier: "OU",
doublesTier: "DOU",
},
ponyta: {
tier: "LC",
},
rapidash: {
tier: "OU",
doublesTier: "DOU",
},
slowpoke: {
tier: "LC",
},
slowbro: {
tier: "OU",
doublesTier: "DOU",
},
slowking: {
tier: "OU",
doublesTier: "DOU",
},
magnemite: {
tier: "LC",
},
magneton: {
tier: "OU",
doublesTier: "DOU",
},
farfetchd: {
tier: "OU",
doublesTier: "DOU",
},
doduo: {
tier: "LC",
},
dodrio: {
tier: "OU",
doublesTier: "DOU",
},
seel: {
tier: "LC",
},
dewgong: {
tier: "OU",
doublesTier: "DOU",
},
grimer: {
tier: "LC",
},
muk: {
tier: "OU",
doublesTier: "DOU",
},
shellder: {
tier: "LC",
},
cloyster: {
tier: "OU",
doublesTier: "DOU",
},
gastly: {
tier: "LC",
},
haunter: {
tier: "OU",
doublesTier: "DOU",
},
gengar: {
tier: "OU",
doublesTier: "DOU",
},
onix: {
tier: "LC",
},
steelix: {
tier: "OU",
doublesTier: "DOU",
},
drowzee: {
tier: "LC",
},
hypno: {
tier: "OU",
doublesTier: "DOU",
},
krabby: {
tier: "LC",
},
kingler: {
tier: "OU",
doublesTier: "DOU",
},
voltorb: {
tier: "LC",
},
electrode: {
tier: "OU",
doublesTier: "DOU",
},
exeggcute: {
tier: "LC",
},
exeggutor: {
tier: "OU",
doublesTier: "DOU",
},
cubone: {
tier: "LC",
},
marowak: {
tier: "OU",
doublesTier: "DOU",
},
tyrogue: {
tier: "LC",
},
hitmonlee: {
tier: "OU",
doublesTier: "DOU",
},
hitmonchan: {
tier: "OU",
doublesTier: "DOU",
},
hitmontop: {
tier: "OU",
doublesTier: "DOU",
},
lickitung: {
tier: "OU",
doublesTier: "DOU",
},
koffing: {
tier: "LC",
},
weezing: {
tier: "OU",
doublesTier: "DOU",
},
rhyhorn: {
tier: "LC",
},
rhydon: {
tier: "OU",
doublesTier: "DOU",
},
chansey: {
tier: "OU",
doublesTier: "NFE",
},
blissey: {
tier: "OU",
doublesTier: "DOU",
},
tangela: {
tier: "OU",
doublesTier: "DOU",
},
kangaskhan: {
tier: "OU",
doublesTier: "DOU",
},
horsea: {
tier: "LC",
},
seadra: {
tier: "NFE",
},
kingdra: {
tier: "OU",
doublesTier: "DOU",
},
goldeen: {
tier: "LC",
},
seaking: {
tier: "OU",
doublesTier: "DOU",
},
staryu: {
tier: "LC",
},
starmie: {
tier: "OU",
doublesTier: "DOU",
},
mrmime: {
tier: "OU",
doublesTier: "DOU",
},
scyther: {
tier: "OU",
doublesTier: "NFE",
},
scizor: {
tier: "OU",
doublesTier: "DOU",
},
smoochum: {
tier: "LC",
},
jynx: {
tier: "OU",
doublesTier: "DOU",
},
elekid: {
tier: "LC",
},
electabuzz: {
tier: "OU",
doublesTier: "DOU",
},
magby: {
tier: "LC",
},
magmar: {
tier: "OU",
doublesTier: "DOU",
},
pinsir: {
tier: "OU",
doublesTier: "DOU",
},
tauros: {
tier: "OU",
doublesTier: "DOU",
},
magikarp: {
tier: "LC",
},
gyarados: {
tier: "OU",
doublesTier: "DOU",
},
lapras: {
tier: "OU",
doublesTier: "DOU",
},
ditto: {
tier: "OU",
doublesTier: "DOU",
},
eevee: {
tier: "LC",
},
vaporeon: {
tier: "OU",
doublesTier: "DOU",
},
jolteon: {
tier: "OU",
doublesTier: "DOU",
},
flareon: {
tier: "OU",
doublesTier: "DOU",
},
espeon: {
tier: "OU",
doublesTier: "DOU",
},
umbreon: {
tier: "OU",
doublesTier: "DOU",
},
porygon: {
tier: "LC",
},
porygon2: {
tier: "OU",
doublesTier: "DOU",
},
omanyte: {
tier: "LC",
},
omastar: {
tier: "OU",
doublesTier: "DOU",
},
kabuto: {
tier: "LC",
},
kabutops: {
tier: "OU",
doublesTier: "DOU",
},
aerodactyl: {
tier: "OU",
doublesTier: "DOU",
},
snorlax: {
tier: "OU",
doublesTier: "DOU",
},
articuno: {
tier: "OU",
doublesTier: "DOU",
},
zapdos: {
tier: "OU",
doublesTier: "DOU",
},
moltres: {
tier: "OU",
doublesTier: "DOU",
},
dratini: {
tier: "LC",
},
dragonair: {
tier: "NFE",
},
dragonite: {
tier: "OU",
doublesTier: "DOU",
},
mewtwo: {
tier: "Uber",
doublesTier: "DUber",
},
mew: {
tier: "Uber",
doublesTier: "DUber",
},
chikorita: {
tier: "LC",
},
bayleef: {
tier: "NFE",
},
meganium: {
tier: "OU",
doublesTier: "DOU",
},
cyndaquil: {
tier: "LC",
},
quilava: {
tier: "NFE",
},
typhlosion: {
tier: "OU",
doublesTier: "DOU",
},
totodile: {
tier: "LC",
},
croconaw: {
tier: "NFE",
},
feraligatr: {
tier: "OU",
doublesTier: "DOU",
},
sentret: {
tier: "LC",
},
furret: {
tier: "OU",
doublesTier: "DOU",
},
hoothoot: {
tier: "LC",
},
noctowl: {
tier: "OU",
doublesTier: "DOU",
},
ledyba: {
tier: "LC",
},
ledian: {
tier: "OU",
doublesTier: "DOU",
},
spinarak: {
tier: "LC",
},
ariados: {
tier: "OU",
doublesTier: "DOU",
},
chinchou: {
tier: "LC",
},
lanturn: {
tier: "OU",
doublesTier: "DOU",
},
togepi: {
tier: "LC",
},
togetic: {
tier: "OU",
doublesTier: "DOU",
},
natu: {
tier: "LC",
},
xatu: {
tier: "OU",
doublesTier: "DOU",
},
mareep: {
tier: "LC",
},
flaaffy: {
tier: "NFE",
},
ampharos: {
tier: "OU",
doublesTier: "DOU",
},
marill: {
tier: "LC",
},
azumarill: {
tier: "OU",
doublesTier: "DOU",
},
sudowoodo: {
tier: "OU",
doublesTier: "DOU",
},
hoppip: {
tier: "LC",
},
skiploom: {
tier: "NFE",
},
jumpluff: {
tier: "OU",
doublesTier: "DOU",
},
aipom: {
tier: "OU",
doublesTier: "DOU",
},
sunkern: {
tier: "LC",
},
sunflora: {
tier: "OU",
doublesTier: "DOU",
},
yanma: {
tier: "OU",
doublesTier: "DOU",
},
wooper: {
tier: "LC",
},
quagsire: {
tier: "OU",
doublesTier: "DOU",
},
murkrow: {
tier: "OU",
doublesTier: "DOU",
},
misdreavus: {
tier: "OU",
doublesTier: "DOU",
},
unown: {
tier: "OU",
doublesTier: "DOU",
},
wobbuffet: {
tier: "OU",
doublesTier: "DOU",
},
girafarig: {
tier: "OU",
doublesTier: "DOU",
},
pineco: {
tier: "LC",
},
forretress: {
tier: "OU",
doublesTier: "DOU",
},
dunsparce: {
tier: "OU",
doublesTier: "DOU",
},
gligar: {
tier: "OU",
doublesTier: "DOU",
},
snubbull: {
tier: "LC",
},
granbull: {
tier: "OU",
doublesTier: "DOU",
},
qwilfish: {
tier: "OU",
doublesTier: "DOU",
},
shuckle: {
tier: "OU",
doublesTier: "DOU",
},
heracross: {
tier: "OU",
doublesTier: "DOU",
},
sneasel: {
tier: "OU",
doublesTier: "DOU",
},
teddiursa: {
tier: "LC",
},
ursaring: {
tier: "OU",
doublesTier: "DOU",
},
slugma: {
tier: "LC",
},
magcargo: {
tier: "OU",
doublesTier: "DOU",
},
swinub: {
tier: "LC",
},
piloswine: {
tier: "OU",
doublesTier: "DOU",
},
corsola: {
tier: "OU",
doublesTier: "DOU",
},
remoraid: {
tier: "LC",
},
octillery: {
tier: "OU",
doublesTier: "DOU",
},
delibird: {
tier: "OU",
doublesTier: "DOU",
},
mantine: {
tier: "OU",
doublesTier: "DOU",
},
skarmory: {
tier: "OU",
doublesTier: "DOU",
},
houndour: {
tier: "LC",
},
houndoom: {
tier: "OU",
doublesTier: "DOU",
},
phanpy: {
tier: "LC",
},
donphan: {
tier: "OU",
doublesTier: "DOU",
},
stantler: {
tier: "OU",
doublesTier: "DOU",
},
smeargle: {
tier: "OU",
doublesTier: "DOU",
},
miltank: {
tier: "OU",
doublesTier: "DOU",
},
raikou: {
tier: "OU",
doublesTier: "DOU",
},
entei: {
tier: "OU",
doublesTier: "DOU",
},
suicune: {
tier: "OU",
doublesTier: "DOU",
},
larvitar: {
tier: "LC",
},
pupitar: {
tier: "NFE",
},
tyranitar: {
tier: "OU",
doublesTier: "DOU",
},
lugia: {
tier: "Uber",
doublesTier: "DUber",
},
hooh: {
tier: "Uber",
doublesTier: "DUber",
},
celebi: {
tier: "OU",
doublesTier: "DOU",
},
};

View File

@ -1,49 +0,0 @@
export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
encore: {
inherit: true,
condition: {
durationCallback() {
return this.random(3, 7);
},
onStart(target) {
const lockedMove = target.lastMoveEncore?.id || '';
const moveIndex = lockedMove ? target.moves.indexOf(lockedMove) : -1;
if (moveIndex < 0 || target.lastMoveEncore?.flags['failencore'] || target.moveSlots[moveIndex].pp <= 0) {
// it failed
return false;
}
this.effectState.move = lockedMove;
this.add('-start', target, 'Encore');
},
onOverrideAction(pokemon) {
return this.effectState.move;
},
onModifyMove(move, pokemon) {
if (['normal', 'any', 'adjacentFoe'].includes(move.target)) {
move.target = 'randomNormal';
}
},
onResidualOrder: 13,
onResidual(target) {
const lockedMoveIndex = target.moves.indexOf(this.effectState.move);
if (lockedMoveIndex >= 0 && target.moveSlots[lockedMoveIndex].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);
}
}
},
},
},
};

View File

@ -1,19 +0,0 @@
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
standarddoubles: {
effectType: 'ValidatorRule',
name: 'Standard Doubles',
ruleset: ['Obtainable', 'Sleep Clause Mod', 'Freeze Clause Mod', 'Species Clause', 'OHKO Clause', 'Evasion Moves Clause', 'Endless battle Clause', 'HP Percentage Mod', 'Cancel Mod'],
banlist: [
'Hypnosis + Mean Look',
'Hypnosis + Spider Web',
'Lovely Kiss + Mean Look',
'Lovely Kiss + Spider Web',
'Sing + Mean Look',
'Sing + Spider Web',
'Sleep Powder + Mean Look',
'Sleep Powder + Spider Web',
'Spore + Mean Look',
'Spore + Spider Web',
],
},
};

View File

@ -1,319 +0,0 @@
export const Scripts: ModdedBattleScriptsData = {
inherit: 'gen2',
gen: 2,
pokemon: {
inherit: true,
getStat(statName, unboosted, unmodified, fastReturn) {
// @ts-expect-error type checking prevents 'hp' from being passed, but we're paranoid
if (statName === 'hp') throw new Error("Please read `maxhp` directly");
// base stat
let stat = this.storedStats[statName];
// Stat boosts.
if (!unboosted) {
let boost = this.boosts[statName];
if (boost > 6) boost = 6;
if (boost < -6) boost = -6;
if (boost >= 0) {
const boostTable = [1, 1.5, 2, 2.5, 3, 3.5, 4];
stat = Math.floor(stat * boostTable[boost]);
} else {
const numerators = [100, 66, 50, 40, 33, 28, 25];
stat = Math.floor(stat * numerators[-boost] / 100);
}
}
if (this.status === 'par' && statName === 'spe') {
stat = Math.floor(stat / 4);
}
if (!unmodified) {
// Burn attack drop is checked when you get the attack stat upon switch in and used until switch out.
if (this.status === 'brn' && statName === 'atk') {
stat = Math.floor(stat / 2);
}
}
// Gen 2 caps stats at 999 and min is 1.
stat = this.battle.clampIntRange(stat, 1, 999);
if (fastReturn) return stat;
// Screens
if (!unboosted) {
if (
(statName === 'def' && this.side.sideConditions['reflect']) ||
(statName === 'spd' && this.side.sideConditions['lightscreen'])
) {
if (this.side.active.length === 1) {
stat *= 2;
} else {
stat *= 1.5;
}
}
}
// Handle boosting items
if (
(['Cubone', 'Marowak'].includes(this.baseSpecies.name) && this.item === 'thickclub' && statName === 'atk') ||
(this.baseSpecies.name === 'Pikachu' && this.item === 'lightball' && statName === 'spa')
) {
stat *= 2;
} else if (this.baseSpecies.name === 'Ditto' && this.item === 'metalpowder' && ['def', 'spd'].includes(statName)) {
stat = Math.floor(stat * 1.5);
}
return stat;
},
},
actions: {
inherit: true,
getDamage(source, target, move, suppressMessages) {
// First of all, we get the move.
if (typeof move === 'string') {
move = this.dex.getActiveMove(move);
} else if (typeof move === 'number') {
move = {
basePower: move,
type: '???',
category: 'Physical',
willCrit: false,
flags: {},
} as unknown as ActiveMove;
}
// Let's test for immunities.
if (!move.ignoreImmunity || (move.ignoreImmunity !== true && !move.ignoreImmunity[move.type])) {
if (!target.runImmunity(move.type, true)) {
return false;
}
}
// Is it an OHKO move?
if (move.ohko) {
return target.maxhp;
}
// We edit the damage through move's damage callback
if (move.damageCallback) {
return move.damageCallback.call(this.battle, source, target);
}
// We take damage from damage=level moves
if (move.damage === 'level') {
return source.level;
}
// If there's a fix move damage, we run it
if (move.damage) {
return move.damage;
}
// We check the category and typing to calculate later on the damage
move.category = this.battle.getCategory(move);
// '???' is typeless damage: used for Struggle and Confusion etc
if (!move.type) move.type = '???';
const type = move.type;
// We get the base power and apply basePowerCallback if necessary
let basePower: number | false | null | undefined = move.basePower;
if (move.basePowerCallback) {
basePower = move.basePowerCallback.call(this.battle, source, target, move);
}
// We check for Base Power
if (!basePower) {
if (basePower === 0) return; // Returning undefined means not dealing damage
return basePower;
}
basePower = this.battle.clampIntRange(basePower, 1);
// Checking for the move's Critical Hit ratio
let critRatio = this.battle.runEvent('ModifyCritRatio', source, target, move, move.critRatio || 0);
critRatio = this.battle.clampIntRange(critRatio, 0, 5);
const critMult = [0, 17, 32, 64, 85, 128];
let isCrit = move.willCrit || false;
if (typeof move.willCrit === 'undefined') {
if (critRatio) {
isCrit = this.battle.random(256) < critMult[critRatio];
}
}
if (isCrit && this.battle.runEvent('CriticalHit', target, null, move)) {
target.getMoveHitData(move).crit = true;
}
// Happens after crit calculation
if (basePower) {
// confusion damage
if (move.isConfusionSelfHit) {
move.type = move.baseMoveType!;
basePower = this.battle.runEvent('BasePower', source, target, move, basePower, true);
move.type = '???';
} else {
basePower = this.battle.runEvent('BasePower', source, target, move, basePower, true);
}
if (basePower && move.basePowerModifier) {
basePower *= move.basePowerModifier;
}
}
if (!basePower) return 0;
basePower = this.battle.clampIntRange(basePower, 1);
// We now check for attacker and defender
let level = source.level;
// Using Beat Up
if (move.allies) {
this.battle.add('-activate', source, 'move: Beat Up', '[of] ' + move.allies[0].name);
level = move.allies[0].level;
}
const attacker = move.overrideOffensivePokemon === 'target' ? target : source;
const defender = move.overrideDefensivePokemon === 'source' ? source : target;
const isPhysical = move.category === 'Physical';
const atkType: StatIDExceptHP = move.overrideOffensiveStat || (isPhysical ? 'atk' : 'spa');
const defType: StatIDExceptHP = move.overrideDefensiveStat || (isPhysical ? 'def' : 'spd');
let unboosted = false;
let noburndrop = false;
if (isCrit) {
if (!suppressMessages) this.battle.add('-crit', target);
// Stat level modifications are ignored if they are neutral to or favour the defender.
// Reflect and Light Screen defensive boosts are only ignored if stat level modifications were also ignored as a result of that.
if (attacker.boosts[atkType] <= defender.boosts[defType]) {
unboosted = true;
noburndrop = true;
}
}
let attack = attacker.getStat(atkType, unboosted, noburndrop);
let defense = defender.getStat(defType, unboosted);
// Using Beat Up
if (move.allies) {
attack = move.allies[0].species.baseStats.atk;
move.allies.shift();
defense = defender.species.baseStats.def;
}
// Moves that ignore offense and defense respectively.
if (move.ignoreOffensive) {
this.battle.debug('Negating (sp)atk boost/penalty.');
// The attack drop from the burn is only applied when attacker's attack level is higher than defender's defense level.
attack = attacker.getStat(atkType, true, true);
}
if (move.ignoreDefensive) {
this.battle.debug('Negating (sp)def boost/penalty.');
defense = target.getStat(defType, true, true);
}
if (move.id === 'present') {
const typeIndexes: { [k: string]: number } = {
Normal: 0, Fighting: 1, Flying: 2, Poison: 3, Ground: 4, Rock: 5, Bug: 7, Ghost: 8, Steel: 9,
Fire: 20, Water: 21, Grass: 22, Electric: 23, Psychic: 24, Ice: 25, Dragon: 26, Dark: 27,
};
attack = 10;
const attackerLastType = attacker.getTypes().slice(-1)[0];
const defenderLastType = defender.getTypes().slice(-1)[0];
defense = typeIndexes[attackerLastType] || 1;
level = typeIndexes[defenderLastType] || 1;
this.battle.hint("Gen 2 Present has a glitched damage calculation using the secondary types of the Pokemon for the Attacker's Level and Defender's Defense.", true);
}
// When either attack or defense are higher than 256, they are both divided by 4 and modded by 256.
// This is what causes the rollover bugs.
if (attack >= 256 || defense >= 256) {
if (attack >= 1024 || defense >= 1024) {
this.battle.hint("In Gen 2, a stat will roll over to a small number if it is larger than 1024.");
}
attack = this.battle.clampIntRange(Math.floor(attack / 4) % 256, 1);
defense = this.battle.clampIntRange(Math.floor(defense / 4) % 256, 1);
}
// Self destruct moves halve defense at this point.
if (move.selfdestruct && defType === 'def') {
defense = this.battle.clampIntRange(Math.floor(defense / 2), 1);
}
// Let's go with the calculation now that we have what we need.
// We do it step by step just like the game does.
let damage = level * 2;
damage = Math.floor(damage / 5);
damage += 2;
damage *= basePower;
damage *= attack;
damage = Math.floor(damage / defense);
damage = Math.floor(damage / 50);
if (isCrit) damage *= 2;
damage = Math.floor(this.battle.runEvent('ModifyDamage', attacker, defender, move, damage));
damage = this.battle.clampIntRange(damage, 1, 997);
damage += 2;
// Weather modifiers
if (
(type === 'Water' && this.battle.field.isWeather('raindance')) ||
(type === 'Fire' && this.battle.field.isWeather('sunnyday'))
) {
damage = Math.floor(damage * 1.5);
} else if (
((type === 'Fire' || move.id === 'solarbeam') && this.battle.field.isWeather('raindance')) ||
(type === 'Water' && this.battle.field.isWeather('sunnyday'))
) {
damage = Math.floor(damage / 2);
}
// STAB damage bonus, the "???" type never gets STAB
if (type !== '???' && source.hasType(type)) {
damage += Math.floor(damage / 2);
}
// Type effectiveness
const totalTypeMod = target.runEffectiveness(move);
// Super effective attack
if (totalTypeMod > 0) {
if (!suppressMessages) this.battle.add('-supereffective', target);
damage *= 2;
if (totalTypeMod >= 2) {
damage *= 2;
}
}
// Resisted attack
if (totalTypeMod < 0) {
if (!suppressMessages) this.battle.add('-resisted', target);
damage = Math.floor(damage / 2);
if (totalTypeMod <= -2) {
damage = Math.floor(damage / 2);
}
}
// Attempting to add correct spread damage nerf
const { targets } = source.getMoveTargets(move, target);
if (targets.length > 1) move.spreadHit = true;
if (move.spreadHit && move.target === 'allAdjacentFoes') {
const spreadModifier = move.spreadModifier || 0.5;
this.battle.debug(`Spread modifier: ${spreadModifier}`);
damage = this.battle.modify(damage, spreadModifier);
}
// Apply random factor if damage is greater than 1, except for Flail and Reversal
if (!move.noDamageVariance && damage > 1) {
damage *= this.battle.random(217, 256);
damage = Math.floor(damage / 255);
}
// If damage is less than 1, we return 1
if (basePower && !Math.floor(damage)) {
return 1;
}
// We are done, this is the final damage
return damage;
},
},
};

View File

@ -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',

View File

@ -122,10 +122,7 @@ export const Scripts: ModdedBattleScriptsData = {
move.ignoreImmunity = (move.category === 'Status');
}
if (
(!move.ignoreImmunity || (move.ignoreImmunity !== true && !move.ignoreImmunity[move.type])) &&
!target.runImmunity(move.type, true)
) {
if (!target.runImmunity(move, true)) {
return false;
}
@ -231,10 +228,8 @@ export const Scripts: ModdedBattleScriptsData = {
}
if (move.ohko) this.battle.add('-ohko');
if (!move.negateSecondary) {
this.battle.singleEvent('AfterMoveSecondary', move, null, target, pokemon, move);
this.battle.runEvent('AfterMoveSecondary', target, pokemon, move);
}
this.battle.singleEvent('AfterMoveSecondary', move, null, target, pokemon, move);
this.battle.runEvent('AfterMoveSecondary', target, pokemon, move);
// Implementing Recoil mechanics from Stadium 2.
// If a pokemon caused the other to faint with a recoil move and only one pokemon remains on both sides,
// recoil damage will not be taken.
@ -258,10 +253,8 @@ export const Scripts: ModdedBattleScriptsData = {
}
// Let's test for immunities.
if (!move.ignoreImmunity || (move.ignoreImmunity !== true && !move.ignoreImmunity[move.type])) {
if (!target.runImmunity(move.type, true)) {
return false;
}
if (!target.runImmunity(move, true)) {
return false;
}
// Is it an OHKO move?

View File

@ -91,6 +91,8 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
},
},
lightningrod: {
inherit: true,
onAnyRedirectTarget() {},
onFoeRedirectTarget(target, source, source2, move) {
// don't count Hidden Power as Electric-type
if (this.dex.moves.get(move.id).type !== 'Electric') return;
@ -98,10 +100,23 @@ 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() {},
onAnyTrapPokemon(pokemon) {
if (pokemon.hasType('Steel') && pokemon.isAdjacent(this.effectState.target)) {
pokemon.tryTrap(true);
}
},
onAnyMaybeTrapPokemon(pokemon, source) {
if (!source) source = this.effectState.target;
if (!source || !pokemon.isAdjacent(source)) return;
if (!pokemon.knownType || pokemon.hasType('Steel')) {
pokemon.maybeTrapped = true;
}
},
},
minus: {
inherit: true,
@ -181,9 +196,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
const target = pokemon.side.randomFoe();
if (!target || target.fainted) return;
const ability = target.getAbility();
if (pokemon.setAbility(ability)) {
this.add('-ability', pokemon, ability, '[from] ability: Trace', `[of] ${target}`);
}
pokemon.setAbility(ability, target);
},
flags: {},
},

View File

@ -3,7 +3,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "LC",
},
ivysaur: {
tier: "PU",
tier: "ZU",
},
venusaur: {
tier: "UUBL",
@ -21,7 +21,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "LC",
},
wartortle: {
tier: "ZU",
tier: "PU",
},
blastoise: {
tier: "UU",
@ -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",
@ -762,7 +762,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "LC",
},
grovyle: {
tier: "PU",
tier: "ZU",
},
sceptile: {
tier: "UUBL",
@ -879,7 +879,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "RUBL",
},
shedinja: {
tier: "ZUBL",
tier: "PU",
},
whismur: {
tier: "LC",
@ -924,13 +924,13 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "ZU",
},
medicham: {
tier: "UUBL",
tier: "OU",
},
electrike: {
tier: "LC",
},
manectric: {
tier: "UU",
tier: "RU",
},
plusle: {
tier: "NU",
@ -1056,13 +1056,10 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "ZU",
},
castformsunny: {
tier: "ZU",
},
castformrainy: {
tier: "ZU",
},
castformsnowy: {
tier: "ZU",
},
kecleon: {
tier: "NU",
@ -1092,7 +1089,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "LC",
},
glalie: {
tier: "NU",
tier: "NUBL",
},
spheal: {
tier: "LC",
@ -1104,7 +1101,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "UU",
},
clamperl: {
tier: "ZU",
tier: "PU",
},
huntail: {
tier: "NU",

View File

@ -82,6 +82,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
num: 208,
gen: 3,
isNonstandard: "Unobtainable",
// No competitive use
},
fastball: {
inherit: true,
@ -138,8 +139,8 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
inherit: true,
onModifyMove(move) {
const affectedByKingsRock = [
'aerialace', 'aeroblast', 'aircutter', 'armthrust', 'barrage', 'beatup', 'bide', 'bind', 'blastburn', 'bonerush', 'bonemerang', 'bounce', 'brickbreak', 'bulletseed', 'clamp', 'cometpunch', 'crabhammer', 'crosschop', 'cut', 'dig', 'dive', 'doublekick', 'doubleslap', 'doubleedge', 'dragonbreath', 'dragonclaw', 'dragonrage', 'drillpeck', 'earthquake', 'eggbomb', 'endeavor', 'eruption', 'explosion', 'extremespeed', 'falseswipe', 'feintattack', 'firespin', 'flail', 'fly', 'frenzyplant', 'frustration', 'furyattack', 'furycutter', 'furyswipes', 'gust', 'hiddenpower', 'highjumpkick', 'hornattack', 'hydrocannon', 'hydropump', 'hyperbeam', 'iceball', 'iciclespear', 'jumpkick', 'karatechop', 'leafblade', 'lowkick', 'machpunch', 'magicalleaf', 'magnitude', 'megakick', 'megapunch', 'megahorn', 'meteormash', 'mudshot', 'muddywater', 'nightshade', 'outrage', 'overheat', 'payday', 'peck', 'petaldance', 'pinmissile', 'poisontail', 'pound', 'psychoboost', 'psywave', 'quickattack', 'rage', 'rapidspin', 'razorleaf', 'razorwind', 'return', 'revenge', 'reversal', 'rockblast', 'rockthrow', 'rollingkick', 'rollout', 'sandtomb', 'scratch', 'seismictoss', 'selfdestruct', 'shadowpunch', 'shockwave', 'signalbeam', 'silverwind', 'skullbash', 'skyattack', 'skyuppercut', 'slam', 'slash', 'snore', 'solarbeam', 'sonicboom', 'spikecannon', 'spitup', 'steelwing', 'strength', 'struggle', 'submission', 'surf', 'swift', 'tackle', 'takedown', 'thrash', 'tickle', 'triplekick', 'twister', 'uproar', 'visegrip', 'vinewhip', 'vitalthrow', 'volttackle', 'watergun', 'waterpulse', 'waterfall', 'weatherball', 'whirlpool', 'wingattack', 'wrap',
];
'aerialace', 'aeroblast', 'aircutter', 'armthrust', 'barrage', 'beatup', 'bide', 'bind', 'blastburn', 'bonerush', 'bonemerang', 'bounce', 'brickbreak', 'bulletseed', 'clamp', 'cometpunch', 'crabhammer', 'crosschop', 'cut', 'dig', 'dive', 'doublekick', 'doubleslap', 'doubleedge', 'dragonbreath', 'dragonclaw', 'dragonrage', 'drillpeck', 'earthquake', 'eggbomb', 'endeavor', 'eruption', 'explosion', 'extremespeed', 'falseswipe', 'feintattack', 'firespin', 'flail', 'fly', 'frenzyplant', 'frustration', 'furyattack', 'furycutter', 'furyswipes', 'gust', 'hiddenpower', 'highjumpkick', 'hornattack', 'hydrocannon', 'hydropump', 'hyperbeam', 'iceball', 'iciclespear', 'jumpkick', 'karatechop', 'leafblade', 'lowkick', 'machpunch', 'magicalleaf', 'magnitude', 'megakick', 'megapunch', 'megahorn', 'meteormash', 'mudshot', 'muddywater', 'nightshade', 'outrage', 'overheat', 'payday', 'peck', 'petaldance', 'pinmissile', 'poisontail', 'pound', 'psychoboost', 'psywave', 'quickattack', 'rage', 'rapidspin', 'razorleaf', 'razorwind', 'return', 'revenge', 'reversal', 'rockblast', 'rockthrow', 'rollingkick', 'rollout', 'sandtomb', 'scratch', 'seismictoss', 'selfdestruct', 'shadowpunch', 'shockwave', 'signalbeam', 'silverwind', 'skullbash', 'skyattack', 'skyuppercut', 'slam', 'slash', 'snore', 'solarbeam', 'sonicboom', 'spikecannon', 'spitup', 'steelwing', 'strength', 'struggle', 'submission', 'surf', 'swift', 'tackle', 'takedown', 'thrash', 'triplekick', 'twister', 'uproar', 'visegrip', 'vinewhip', 'vitalthrow', 'volttackle', 'watergun', 'waterpulse', 'waterfall', 'weatherball', 'whirlpool', 'wingattack', 'wrap',
]; // Tickle also has the move flag, but can never flinch because King's Rock requires damage to trigger
if (affectedByKingsRock.includes(move.id)) {
if (!move.secondaries) move.secondaries = [];
move.secondaries.push({

View File

@ -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,15 +41,16 @@ 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 move.allies!.shift()!.species.baseStats.atk;
return this.dex.species.get(move.allies!.shift()!.set.species).baseStats.atk;
},
onFoeModifySpDPriority: -101,
onFoeModifySpD(def, pokemon) {
this.event.modifier = 1;
return pokemon.species.baseStats.def;
return this.dex.species.get(pokemon.set.species).baseStats.def;
},
},
},
@ -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() {},
onBeforeMove(pokemon, target, move) {
if (this.effectState.duration === 1) {
this.add('-end', pokemon, 'move: Bide');
@ -110,12 +98,6 @@ 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: {
@ -154,20 +136,39 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
this.add('-start', target, 'typechange', type);
},
},
conversion2: {
inherit: true,
onHit(target, source) {
if (!target.lastMoveUsed) {
return false;
}
const possibleTypes = [];
const lastMoveUsed = target.lastMoveUsed;
const attackType = lastMoveUsed.id === 'struggle' ? 'Normal' : lastMoveUsed.type;
for (const typeName of this.dex.types.names()) {
const typeCheck = this.dex.types.get(typeName).damageTaken[attackType];
if (typeCheck === 2 || typeCheck === 3) {
possibleTypes.push(typeName);
}
}
if (!possibleTypes.length) {
return false;
}
const randomType = this.sample(possibleTypes);
if (!source.setType(randomType)) return false;
this.add('-start', source, 'typechange', randomType);
},
},
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() {},
onDamagePriority: -101,
onDamage(damage, target, source, effect) {
if (
@ -201,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,
"onResidualSubOrder": undefined,
},
},
dive: {
@ -286,56 +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 moveIndex = target.lastMove ? target.moves.indexOf(target.lastMove.id) : -1;
if (
!target.lastMove || target.lastMove.flags['failencore'] ||
!target.moveSlots[moveIndex] || target.moveSlots[moveIndex].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) {
if (
target.moves.includes(this.effectState.move) &&
target.moveSlots[target.moves.indexOf(this.effectState.move)].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,
@ -380,12 +305,11 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
volatileStatus: undefined,
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)) {
@ -412,6 +336,15 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
inherit: true,
ignoreImmunity: false,
},
haze: {
inherit: true,
onHitField() {
this.add('-clearallboost');
for (const pokemon of this.getAllActive()) {
pokemon.clearBoosts();
}
},
},
hiddenpower: {
inherit: true,
category: "Physical",
@ -474,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() {},
onDamagePriority: -101,
onDamage(damage, target, source, effect) {
if (
@ -525,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,
@ -550,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,
@ -653,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,
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,
},
},
teeterdance: {
@ -688,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);
},
},
},

View File

@ -2,7 +2,23 @@ export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable
standard: {
effectType: 'ValidatorRule',
name: 'Standard',
desc: "The standard ruleset for all offical 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'],
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},
},
};

View File

@ -49,7 +49,7 @@ export const Scripts: ModdedBattleScriptsData = {
// In Generation 3, the spread move modifier is 0.5x instead of 0.75x. Moves that hit both foes
// and the user's ally, like Earthquake and Explosion, don't get affected by spread modifiers
if (move.spreadHit && move.target === 'allAdjacentFoes') {
const spreadModifier = move.spreadModifier || 0.5;
const spreadModifier = 0.5;
this.battle.debug(`Spread modifier: ${spreadModifier}`);
baseDamage = this.battle.modify(baseDamage, spreadModifier);
}
@ -162,7 +162,7 @@ export const Scripts: ModdedBattleScriptsData = {
let movename = move.name;
if (move.id === 'hiddenpower') movename = 'Hidden Power';
if (sourceEffect) attrs += `|[from]${this.dex.conditions.get(sourceEffect)}`;
if (sourceEffect) attrs += `|[from] ${this.dex.conditions.get(sourceEffect).name}`;
this.battle.addMove('move', pokemon, movename, `${target}${attrs}`);
if (!target) {
@ -256,7 +256,7 @@ export const Scripts: ModdedBattleScriptsData = {
return false;
}
if (!move.negateSecondary && !(move.hasSheerForce && pokemon.hasAbility('sheerforce'))) {
if (!(move.hasSheerForce && pokemon.hasAbility('sheerforce'))) {
this.battle.singleEvent('AfterMoveSecondarySelf', move, null, pokemon, target, move);
this.battle.runEvent('AfterMoveSecondarySelf', pokemon, target, move);
}
@ -308,10 +308,7 @@ export const Scripts: ModdedBattleScriptsData = {
move.ignoreImmunity = (move.category === 'Status');
}
if (
(!move.ignoreImmunity || (move.ignoreImmunity !== true && !move.ignoreImmunity[move.type])) &&
!target.runImmunity(move.type)
) {
if (!target.runImmunity(move)) {
naturalImmunity = true;
} else {
hitResult = this.battle.singleEvent('TryImmunity', move, {}, target, pokemon, move);
@ -471,7 +468,7 @@ export const Scripts: ModdedBattleScriptsData = {
this.battle.eachEvent('Update');
if (target && !move.negateSecondary) {
if (target) {
this.battle.singleEvent('AfterMoveSecondary', move, null, target, pokemon, move);
this.battle.runEvent('AfterMoveSecondary', target, pokemon, move);
}

View File

@ -0,0 +1,25 @@
/**
* Gen 3 colosseum modifications (perish song should fail if it effects all remaining pokemon)
*/
export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
perishsong: {
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;
}
},
},
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;
}
},
},
};

View File

@ -0,0 +1,27 @@
export const Scripts: ModdedBattleScriptsData = {
inherit: 'gen3',
gen: 3,
checkWin(faintData?: Battle['faintQueue'][0]) {
if (this.sides.every(side => !side.pokemonLeft)) {
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()) {
this.win(side);
return true;
}
}
},
};

File diff suppressed because it is too large Load Diff

58
data/mods/gen3rs/items.ts Normal file
View File

@ -0,0 +1,58 @@
export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
apicotberry: {
inherit: true,
isNonstandard: "Unobtainable",
},
berryjuice: {
inherit: true,
isNonstandard: "Unobtainable",
},
fastball: {
inherit: true,
isNonstandard: "Unobtainable",
},
ganlonberry: {
inherit: true,
isNonstandard: "Unobtainable",
},
heavyball: {
inherit: true,
isNonstandard: "Unobtainable",
},
lansatberry: {
inherit: true,
isNonstandard: "Unobtainable",
},
levelball: {
inherit: true,
isNonstandard: "Unobtainable",
},
loveball: {
inherit: true,
isNonstandard: "Unobtainable",
},
lureball: {
inherit: true,
isNonstandard: "Unobtainable",
},
moonball: {
inherit: true,
isNonstandard: "Unobtainable",
},
petayaberry: {
inherit: true,
isNonstandard: "Unobtainable",
},
salacberry: {
inherit: true,
isNonstandard: "Unobtainable",
},
sportball: {
inherit: true,
isNonstandard: "Unobtainable",
},
starfberry: {
inherit: true,
isNonstandard: "Unobtainable",
},
};

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,3 @@
export const Scripts: ModdedBattleScriptsData = {
inherit: 'gen7',
gen: 7,
inherit: 'gen3',
};

View File

@ -23,6 +23,9 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
onResidualSubOrder: 10,
},
blaze: {
inherit: true,
onModifyAtk() {},
onModifySpA() {},
onBasePowerPriority: 2,
onBasePower(basePower, attacker, defender, move) {
if (move.type === 'Fire' && attacker.hp <= attacker.maxhp / 3) {
@ -30,9 +33,6 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
return this.chainModify(1.5);
}
},
name: "Blaze",
rating: 2,
num: 66,
},
cloudnine: {
inherit: true,
@ -58,7 +58,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
onSourceModifyAccuracy(accuracy) {
if (typeof accuracy !== 'number') return;
this.debug('compoundeyes - enhancing accuracy');
return accuracy * 1.3;
return this.chainModify(1.3);
},
inherit: true,
},
@ -128,19 +128,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() {},
onModifySpA() {},
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: {
@ -190,7 +186,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
inherit: true,
onStart(pokemon) {
const target = pokemon.side.randomFoe();
if (target?.item && !target.itemState.knockedOff) {
if (target?.item) {
this.add('-item', '', target.getItem().name, '[from] ability: Frisk', `[of] ${pokemon}`);
}
},
@ -200,20 +196,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() {},
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,
@ -270,31 +265,24 @@ 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,
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,
},
naturalcure: {
inherit: true,
@ -318,6 +306,9 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
},
},
overgrow: {
inherit: true,
onModifyAtk() {},
onModifySpA() {},
onBasePowerPriority: 2,
onBasePower(basePower, attacker, defender, move) {
if (move.type === 'Grass' && attacker.hp <= attacker.maxhp / 3) {
@ -325,26 +316,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() {},
rating: 0,
num: 53,
// No competitive use
},
plus: {
inherit: true,
onModifySpAPriority: undefined,
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 +345,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,14 +367,14 @@ 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);
}
},
},
serenegrace: {
inherit: true,
onModifyMove(move) {
if (move.secondaries) {
if (move.secondaries && move.id !== 'chatter') {
this.debug('doubling secondary chance');
for (const secondary of move.secondaries) {
if (secondary.chance) secondary.chance *= 2;
@ -404,16 +388,14 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
onResidualSubOrder: 3,
},
simple: {
inherit: true,
onChangeBoost() {},
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 +404,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);
}
},
},
@ -442,9 +424,10 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
},
},
stench: {
name: "Stench",
inherit: true,
onModifyMove() {},
rating: 0,
num: 1,
// No competitive use
},
stickyhold: {
inherit: true,
@ -466,6 +449,9 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
rating: 0,
},
swarm: {
inherit: true,
onModifyAtk() {},
onModifySpA() {},
onBasePowerPriority: 2,
onBasePower(basePower, attacker, defender, move) {
if (move.type === 'Bug' && attacker.hp <= attacker.maxhp / 3) {
@ -473,9 +459,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 +478,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() {},
onSourceModifySpA() {},
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() {},
onModifySpA() {},
onBasePowerPriority: 2,
onBasePower(basePower, attacker, defender, move) {
if (move.type === 'Water' && attacker.hp <= attacker.maxhp / 3) {
@ -519,9 +504,6 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
return this.chainModify(1.5);
}
},
name: "Torrent",
rating: 2,
num: 67,
},
trace: {
inherit: true,
@ -534,22 +516,10 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
if (bannedAbilities.includes(target.ability)) {
return;
}
if (pokemon.setAbility(ability)) {
this.add('-ability', pokemon, ability, '[from] ability: Trace', `[of] ${target}`);
}
pokemon.setAbility(ability, target);
},
flags: { notrace: 1 },
},
unburden: {
inherit: true,
condition: {
onModifySpe(spe, pokemon) {
if ((!pokemon.item || pokemon.itemState.knockedOff) && !pokemon.ignoringAbility()) {
return this.chainModify(2);
}
},
},
},
vitalspirit: {
inherit: true,
rating: 2.5,
@ -561,12 +531,16 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
this.hint("In Gen 4, Fire Fang is always able to hit through Wonder Guard.", true, target.side);
return;
}
if (target === source || move.category === 'Status' || move.type === '???' || move.id === 'struggle') return;
if (target === source || move.category === 'Status' || move.type === '???') return;
this.debug('Wonder Guard immunity: ' + move.id);
if (target.runEffectiveness(move) <= 0) {
if (target.runEffectiveness(move) <= 0 || !target.runImmunity(move)) {
this.add('-immune', target, '[from] ability: Wonder Guard');
return null;
}
},
},
rebound: {
inherit: true,
onTryHitSide() {},
},
};

View File

@ -116,6 +116,10 @@ export const Conditions: import('../../../sim/dex-conditions').ModdedConditionDa
onResidualOrder: 10,
onResidualSubOrder: 9,
},
lockedmove: {
inherit: true,
onAfterMove() {},
},
choicelock: {
inherit: true,
onStart(pokemon) {

View File

@ -736,7 +736,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "NU",
},
weavile: {
tier: "OU",
tier: "(OU)",
},
teddiursa: {
tier: "LC",
@ -1137,9 +1137,12 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
castform: {
tier: "NU",
},
castformsunny: {},
castformrainy: {},
castformsnowy: {},
castformsunny: {
},
castformrainy: {
},
castformsnowy: {
},
kecleon: {
tier: "NU",
},

View File

@ -144,7 +144,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
},
focussash: {
inherit: true,
onDamage() { },
onDamage() {},
onTryHit(target, source, move) {
if (target !== source && target.hp === target.maxhp) {
target.addVolatile('focussash');
@ -306,11 +306,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 +319,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
}
this.effectState.lastMove = move.id;
},
onModifyDamage() {},
onModifyDamagePhase2(damage, source, target, move) {
return damage * (1 + (this.effectState.numConsecutive / 10));
},
@ -331,7 +328,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

View File

@ -1,11 +1,20 @@
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,
ruleset: ['Obtainable', 'Species Clause', 'Nickname Clause', 'Item Clause = 1', 'Adjust Level Down = 50', 'Cancel Mod'],
ruleset: ['Obtainable', 'Species Clause', 'Nickname Clause', 'Beat Up Nicknames Mod', 'Item Clause = 1', 'Adjust Level Down = 50', 'Picked Team Size = Auto', 'Cancel Mod'],
},
teampreview: {
inherit: true,

View File

@ -55,10 +55,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;

View File

@ -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"],

View File

@ -43,6 +43,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
newMove.hasBounced = true;
newMove.pranksterBoosted = false;
this.actions.useMove(newMove, this.effectState.target, { target: source });
move.hasBounced = true; // only bounce once in free-for-all battles
return null;
},
},
@ -64,6 +65,9 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
},
overcoat: {
inherit: true,
onImmunity(type, pokemon) {
if (type === 'sandstorm' || type === 'hail') return false;
},
onTryHit() {},
flags: {},
rating: 0.5,
@ -87,4 +91,20 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
inherit: true,
onAllyTryHitSide() {},
},
rebound: {
inherit: true,
onAllyTryHitSide(target, source, move) {
if (this.effectState.target.activeTurns) return;
if (target.isAlly(source) || move.hasBounced || !move.flags['reflectable']) {
return;
}
const newMove = this.dex.getActiveMove(move.id);
newMove.hasBounced = true;
newMove.pranksterBoosted = false;
this.actions.useMove(newMove, this.effectState.target, { target: source });
move.hasBounced = true; // only bounce once in free-for-all battles
return null;
},
},
};

View File

@ -15,6 +15,7 @@ export const Conditions: import('../../../sim/dex-conditions').ModdedConditionDa
const trapper = this.effectState.source;
if (trapper && (!trapper.isActive || trapper.hp <= 0 || !trapper.activeTurns)) {
delete pokemon.volatiles['partiallytrapped'];
this.add('-end', pokemon, this.effectState.sourceEffect, '[partiallytrapped]', '[silent]');
return;
}
this.damage(pokemon.baseMaxhp / this.effectState.boundDivisor);

View File

@ -1347,7 +1347,8 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
},
castformrainy: {
},
castformsnowy: {},
castformsnowy: {
},
kecleon: {
tier: "PU",
doublesTier: "DUU",
@ -1625,7 +1626,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "LC",
},
gastrodon: {
tier: "OU",
tier: "(OU)",
doublesTier: "DOU",
},
drifloon: {

View File

@ -36,8 +36,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
autotomize: {
inherit: true,
volatileStatus: 'autotomize',
onHit(pokemon) {
},
onHit() {},
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 },
@ -105,7 +108,10 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
inherit: true,
basePower: 60,
onModifyMove(move, pokemon) {
if (pokemon.species.name !== 'Chatot') delete move.secondaries;
if (pokemon.species.name !== 'Chatot') {
const confusion = move.secondaries?.find(secondary => secondary.volatileStatus === 'confusion');
if (confusion) confusion.chance = 0; // boosted by Sheer Force
}
},
secondary: {
chance: 10,
@ -189,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 },
@ -257,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;
@ -352,8 +359,17 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
},
healpulse: {
inherit: true,
heal: [1, 2],
onHit() {},
onHit(target, source) {
const success = !!this.heal(Math.ceil(target.baseMaxhp * 0.5));
if (success && !target.isAlly(source)) {
target.staleness = 'external';
}
return success;
},
},
heatcrash: {
inherit: true,
flags: { contact: 1, protect: 1, mirror: 1, nonsky: 1, metronome: 1 },
},
heatwave: {
inherit: true,
@ -486,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) {
@ -502,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: {
@ -519,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;
@ -545,6 +530,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
newMove.hasBounced = true;
newMove.pranksterBoosted = false;
this.actions.useMove(newMove, this.effectState.target, { target: source });
move.hasBounced = true; // only bounce once in free-for-all battles
return null;
},
},
@ -578,18 +564,18 @@ 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() {},
},
},
moonlight: {
inherit: true,
type: "Normal",
},
muddywater: {
inherit: true,
basePower: 95,
},
mudsport: {
inherit: true,
pseudoWeather: undefined,
@ -608,10 +594,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
},
},
},
muddywater: {
inherit: true,
basePower: 95,
},
naturepower: {
inherit: true,
onTryHit() {},
@ -652,6 +634,10 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
inherit: true,
basePower: 70,
},
psychoshift: {
inherit: true,
accuracy: 90,
},
psychup: {
inherit: true,
onHit(target, source) {
@ -662,10 +648,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
this.add('-copyboost', source, target, '[from] move: Psych Up');
},
},
psychoshift: {
inherit: true,
accuracy: 90,
},
psywave: {
inherit: true,
accuracy: 80,
@ -680,11 +662,7 @@ 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,
inherit: true,
onTryHit(target, source, effect) {
// Quick Guard only blocks moves with a natural positive priority
// (e.g. it doesn't block 0 priority moves boosted by Prankster)
@ -711,13 +689,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
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) {
@ -727,14 +699,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: {
@ -785,19 +749,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,
@ -885,12 +836,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);
delete target.volatiles['partiallytrapped'];
},
onTryPrimaryHitPriority: -1,
inherit: true,
onTryPrimaryHit(target, source, move) {
if (target === source || move.flags['bypasssub']) {
return;
@ -901,10 +847,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
this.attrLastMove('[still]');
return null;
}
damage = this.runEvent('SubDamage', target, source, move, damage);
if (!damage) {
return damage;
}
if (damage > target.volatiles['substitute'].hp) {
damage = target.volatiles['substitute'].hp as number;
}
@ -926,9 +868,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: {

View File

@ -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: {

View File

@ -2,39 +2,108 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
venusaur: {
tier: "OU",
},
raichu: {
tier: "PU",
},
golbat: {
tier: "NFE",
},
vileplume: {
tier: "NU",
},
dugtrio: {
tier: "OU",
},
primeape: {
tier: "RU",
},
cloyster: {
tier: "OU",
},
electrode: {
tier: "PU",
},
marowak: {
tier: "NU",
},
chansey: {
tier: "OU",
},
kangaskhan: {
tier: "PU",
},
electabuzz: {
tier: "PU",
},
lapras: {
tier: "PU",
},
ditto: {
tier: "PU",
},
vaporeon: {
tier: "OU",
},
jolteon: {
tier: "OU",
},
flareon: {
tier: "NU",
},
ampharos: {
tier: "PU",
},
quagsire: {
tier: "NU",
},
espeon: {
tier: "OU",
},
donphan: {
tier: "OU",
},
linoone: {
tier: "PU",
},
vigoroth: {
tier: "NFE",
},
roselia: {
tier: "RU",
},
zangoose: {
tier: "PU",
},
cradily: {
tier: "PU",
},
absol: {
tier: "NU",
},
froslass: {
tier: "UU",
},
metagross: {
tier: "OU",
},
regice: {
tier: "PU",
},
deoxysdefense: {
tier: "UUBL",
},
torterra: {
tier: "NU",
},
infernape: {
tier: "OU",
},
luxray: {
tier: "NU",
},
garchomp: {
tier: "Uber",
},
lucario: {
tier: "OU",
},
@ -50,27 +119,96 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
abomasnow: {
tier: "UUBL",
},
garchomp: {
tier: "Uber",
magmortar: {
tier: "NU",
},
leafeon: {
tier: "NU",
},
porygonz: {
tier: "RUBL",
},
rotomfrost: {
tier: "PU",
},
emboar: {
tier: "NU",
},
stoutland: {
tier: "UU",
},
liepard: {
tier: "PU",
},
simipour: {
tier: "PU",
},
gigalith: {
tier: "PU",
},
excadrill: {
tier: "Uber",
},
seismitoad: {
tier: "PU",
},
throh: {
tier: "PU",
},
scolipede: {
tier: "RU",
},
basculin: {
tier: "NU",
},
scrafty: {
tier: "OU",
},
cofagrigus: {
tier: "RU",
},
carracosta: {
tier: "PU",
},
cinccino: {
tier: "NU",
},
gothorita: {
tier: "NFE",
},
gothitelle: {
tier: "PU",
},
swanna: {
tier: "PU",
},
escavalier: {
tier: "UU",
},
amoongus: {
tier: "NU",
},
chandelure: {
tier: "UU",
},
haxorus: {
tier: "OU",
},
cryogonal: {
tier: "NU",
},
mienshao: {
tier: "OU",
},
golurk: {
tier: "RU",
},
mandibuzz: {
tier: "RU",
},
durant: {
tier: "RUBL",
},
hydreigon: {
tier: "OU",
},

View File

@ -1585,7 +1585,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "LC",
},
huntail: {
tier: "ZU",
tier: "ZUBL",
doublesTier: "(DUU)",
},
gorebyss: {
@ -1678,7 +1678,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
doublesTier: "DUber",
},
jirachi: {
tier: "OU",
tier: "(OU)",
doublesTier: "DUber",
},
deoxys: {

View File

@ -34,51 +34,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
},
},
},
encore: {
inherit: true,
condition: {
duration: 3,
onStart(target) {
const moveIndex = target.lastMove ? target.moves.indexOf(target.lastMove.id) : -1;
if (
!target.lastMove || target.lastMove.flags['failencore'] ||
!target.moveSlots[moveIndex] || target.moveSlots[moveIndex].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 lockedMoveIndex = target.moves.indexOf(this.effectState.move);
if (lockedMoveIndex >= 0 && target.moveSlots[lockedMoveIndex].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,
@ -90,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,
@ -99,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 },
@ -129,38 +65,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
mistyterrain: {
inherit: true,
condition: {
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() {},
},
},
mysticalfire: {
@ -181,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,
@ -265,11 +168,7 @@ 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,
inherit: true,
onTryHit(target, source, effect) {
// Wide Guard blocks damaging spread moves
if (

View File

@ -148,6 +148,14 @@ export const Pokedex: import('../../../sim/dex-species').ModdedSpeciesDataTable
inherit: true,
color: "Gray",
},
burmysandy: {
inherit: true,
color: "Gray",
},
burmytrash: {
inherit: true,
color: "Gray",
},
wormadam: {
inherit: true,
color: "Gray",
@ -164,6 +172,14 @@ export const Pokedex: import('../../../sim/dex-species').ModdedSpeciesDataTable
inherit: true,
color: "Pink",
},
shelloseast: {
inherit: true,
color: "Purple",
},
gastrodoneast: {
inherit: true,
color: "Purple",
},
arceus: {
inherit: true,
color: "Gray",
@ -297,6 +313,18 @@ export const Pokedex: import('../../../sim/dex-species').ModdedSpeciesDataTable
inherit: true,
color: "Yellow",
},
deerlingsummer: {
inherit: true,
color: "Yellow",
},
deerlingautumn: {
inherit: true,
color: "Yellow",
},
deerlingwinter: {
inherit: true,
color: "Yellow",
},
cubchoo: {
inherit: true,
abilities: { 0: "Snow Cloak", H: "Rattled" },
@ -318,6 +346,82 @@ export const Pokedex: import('../../../sim/dex-species').ModdedSpeciesDataTable
inherit: true,
color: "Black",
},
vivillonicysnow: {
inherit: true,
color: "Black",
},
vivillonpolar: {
inherit: true,
color: "Black",
},
vivillontundra: {
inherit: true,
color: "Black",
},
vivilloncontinental: {
inherit: true,
color: "Black",
},
vivillongarden: {
inherit: true,
color: "Black",
},
vivillonelegant: {
inherit: true,
color: "Black",
},
vivillonmodern: {
inherit: true,
color: "Black",
},
vivillonmarine: {
inherit: true,
color: "Black",
},
vivillonarchipelago: {
inherit: true,
color: "Black",
},
vivillonhighplains: {
inherit: true,
color: "Black",
},
vivillonsandstorm: {
inherit: true,
color: "Black",
},
vivillonriver: {
inherit: true,
color: "Black",
},
vivillonmonsoon: {
inherit: true,
color: "Black",
},
vivillonsavanna: {
inherit: true,
color: "Black",
},
vivillonsun: {
inherit: true,
color: "Black",
},
vivillonocean: {
inherit: true,
color: "Black",
},
vivillonjungle: {
inherit: true,
color: "Black",
},
vivillonfancy: {
inherit: true,
color: "Black",
},
vivillonpokeball: {
inherit: true,
color: "Black",
},
meowstic: {
inherit: true,
color: "White",

View File

@ -0,0 +1,369 @@
export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTable = {
merciless: {
shortDesc: "This Pokemon's attacks are critical hits if the target is statused.",
onModifyCritRatio(critRatio, source, target) {
if (target?.status) return 5;
},
name: "Merciless",
rating: 1.5,
num: 196,
gen: 6,
},
pocketdimension: {
shortDesc: "This Pokemon switches out after using a status move.",
onModifyMove(move, pokemon) {
if (move.category === 'Status') {
move.selfSwitch = true;
this.add('-ability', pokemon, 'Pocket Dimension');
this.add('-message', `${pokemon.name} will switch out if this moves lands!`);
}
},
name: "Pocket Dimension",
rating: 4.5,
},
grassysurge: {
inherit: true,
gen: 6,
},
mistysurge: {
inherit: true,
gen: 6,
},
neutralizinggas: {
inherit: true,
// Ability suppression cancelled in scripts.ts
// new Ability suppression implemented in scripts.ts
onSwitchIn(pokemon) {},
onEnd(source) {},
onStart(pokemon) {
this.add('-ability', pokemon, 'Neutralizing Gas');
},
// onModifyPriority implemented in relevant abilities
onFoeBeforeMovePriority: 13,
onFoeBeforeMove(attacker, defender, move) {
attacker.addVolatile('neutralizinggas');
},
condition: {
onAfterMove(pokemon) {
pokemon.removeVolatile('neutralizinggas');
},
},
flags: { failroleplay: 1, noreceiver: 1, noentrain: 1, notrace: 1, failskillswap: 1, notransform: 1 },
desc: "While this Pokemon is active, opposing Pokemon's moves and their effects ignore its own Ability. Does not affect the As One, Battle Bond, Comatose, Disguise, Gulp Missile, Ice Face, Multitype, Power Construct, RKS System, Schooling, Shields Down, Stance Change, or Zen Mode Abilities.",
shortDesc: "While this Pokemon is active, opposing Pokemon's Ability has no effect when it uses moves.",
gen: 6,
},
nostalgiatrip: {
shortDesc: "This Pokemon's moves have the damage categories they would have in Gen 3. Fairy-type moves are Special.",
onStart(pokemon) {
this.add('-ability', pokemon, 'Nostalgia Trip');
this.add('-message', `This Pokemon is experiencing a nostalgia trip!`);
},
onModifyMovePriority: 8,
onModifyMove(move, pokemon) {
if (move.category === "Status") return;
if (['Fire', 'Water', 'Grass', 'Electric', 'Dark', 'Psychic', 'Dragon', 'Fairy', 'Ice'].includes(move.type)) {
move.category = "Special";
} else {
move.category = "Physical";
}
},
name: "Nostalgia Trip",
rating: 4,
gen: 6,
},
weatherreport: {
onBeforeMovePriority: 0.5,
onBeforeMove(target, source, move) {
if (move.type === 'Fire') {
this.field.setWeather('sunnyday');
} else if (move.type === 'Water') {
this.field.setWeather('raindance');
}
},
name: "Weather Report",
shortDesc: "Before using a Water or Fire-type move, this Pokemon sets Rain Dance or Sunny Day respectively.",
rating: 4,
gen: 6,
},
armortail: {
inherit: true,
gen: 6,
},
brainpower: {
onModifySpAPriority: 5,
onModifySpA(spa) {
return this.chainModify(2);
},
name: "Brain Power",
shortDesc: "This Pokemon's Special Attack is doubled.",
rating: 5,
},
neuroforce: {
inherit: true,
gen: 6,
},
bugzapper: {
onTryHit(target, source, move) {
if (target !== source && move.type === 'Bug') {
if (!source.addVolatile('trapped', target, move, 'trapper')) {
this.add('-immune', target, '[from] ability: Bug Zapper');
}
return null;
}
},
name: "Bug Zapper",
shortDesc: "This Pokemon is immune to Bug-type moves and traps the foe if hit by one.",
rating: 5,
},
exoskeleton: {
onSourceModifyDamage(damage, source, target, move) {
if (move.category === 'Physical') {
return this.chainModify(0.5);
}
},
name: "Exoskeleton",
shortDesc: "This Pokemon receives 1/2 damage from physical attacks; Hazard immunity.",
rating: 4,
},
icescales: {
inherit: true,
onModifyAtkPriority: 5,
onModifyAtk(atk, attacker, defender, move) {
if (move.type === 'Ice') {
this.debug('Ice Scales boost');
return this.chainModify(1.5);
}
},
onModifySpAPriority: 5,
onModifySpA(atk, attacker, defender, move) {
if (move.type === 'Ice') {
this.debug('Ice Scales boost');
return this.chainModify(1.5);
}
},
onImmunity(type, pokemon) {
if (type === 'hail') return false;
},
shortDesc: "This Pokemon receives 1/2 damage from special attacks. Ice moves have 1.5x power. Hail immunity.",
gen: 6,
},
eartheater: {
inherit: true,
onDamage(damage, target, source, effect) {
if (effect && (effect.id === 'stealthrock' || effect.id === 'spikes')) {
this.heal(damage);
return false;
}
},
shortDesc: "Heals 1/4 of its max HP when hit by Ground; Ground immunity. Healed by Spikes and Stealth Rock.",
gen: 6,
},
toxicchain: {
inherit: true,
gen: 6,
},
shellejection: {
onModifyMovePriority: -1,
onModifyMove(move, attacker) {
if (move.category === 'Special') {
attacker.addVolatile('shellejection');
this.add('-ability', attacker, 'Shell Ejection');
this.add('-message', `${attacker.name} is getting ready to leave the battlefield!`);
this.add('-message', `${attacker.name} can no longer use status moves!`);
}
},
condition: {
duration: 2,
onDisableMove(pokemon) {
for (const moveSlot of pokemon.moveSlots) {
const move = this.dex.moves.get(moveSlot.id);
if (move.category === 'Status' && move.id !== 'mefirst') {
pokemon.disableMove(moveSlot.id);
}
}
},
onSwitchOut(pokemon) {
pokemon.heal(pokemon.baseMaxhp / 3);
},
onEnd(pokemon) {
this.add('-ability', pokemon, 'Shell Ejection');
this.add('-message', `${pokemon.name} ejected itself from its shell!`);
pokemon.heal(pokemon.baseMaxhp / 3);
pokemon.switchFlag = true;
},
},
name: "Shell Ejection",
rating: 3.5,
gen: 6,
shortDesc: "On using Special move: switching heals 1/3, can't use status, switches out at end of next turn.",
},
sharpness: {
inherit: true,
gen: 6,
},
dauntlessshield: {
onStart(pokemon) {
this.boost({ def: 1 }, pokemon);
pokemon.addVolatile('dauntlessshield');
},
onResidualOrder: 6,
onResidual(pokemon) {
if (pokemon.positiveBoosts()) {
this.heal(pokemon.baseMaxhp / 16);
this.add('-message', `${pokemon.name}'s shield gives it strength!`);
}
},
name: "Dauntless Shield",
rating: 5,
num: 235,
shortDesc: "+1 Defense on switch-in. Heals 1/16 of max HP if it has a positive boost.",
gen: 6,
},
confidence: {
onSourceAfterFaint(length, target, source, effect) {
if (effect && effect.effectType === 'Move') {
this.boost({ spa: length }, source);
}
},
name: "Confidence",
rating: 3,
shortDesc: "This Pokemon's Sp. Atk is raised by 1 stage if it attacks and KOes another Pokemon.",
gen: 6,
},
electricsurge: {
inherit: true,
gen: 6,
},
goodasgold: {
inherit: true,
gen: 6,
},
opportunist: {
inherit: true,
onUpdate(pokemon) {
let activate = false;
const boosts: SparseBoostsTable = {};
let i: BoostID;
for (i in pokemon.boosts) {
if (pokemon.boosts[i] < 0) {
activate = true;
boosts[i] = 0;
}
}
if (this.effectState.herb) return;
if (activate) {
pokemon.setBoost(boosts);
this.effectState.herb = true;
this.add('-ability', pokemon, 'Opportunist');
this.add('-clearnegativeboost', pokemon, '[silent]');
}
},
onSwitchIn(pokemon) {
delete this.effectState.herb;
},
shortDesc: "Copies foe's stat gains as they happen. Resets negative stat changes once per switch-in.",
gen: 6,
},
intoxicate: {
onModifyTypePriority: -1,
onModifyType(move, pokemon) {
const noModifyType = [
'judgment', 'multiattack', 'naturalgift', 'revelationdance', 'technoblast', 'terrainpulse', 'weatherball',
];
if (move.type === 'Normal' && !noModifyType.includes(move.id) &&
!(move.isZ && move.category !== 'Status') && !(move.name === 'Tera Blast' && pokemon.terastallized)) {
move.type = 'Poison';
move.typeChangerBoosted = this.effect;
}
},
onBasePowerPriority: 23,
onBasePower(basePower, pokemon, target, move) {
if (move.typeChangerBoosted) return this.chainModify([5325, 4096]);
},
name: "Intoxicate",
rating: 4,
shortDesc: "This Pokemon's Normal-type moves become Poison-type and have 1.3x power.",
},
dragonsgale: {
onStart(source) {
this.field.setWeather('deltastream');
},
onAnySetWeather(target, source, weather) {
const strongWeathers = ['desolateland', 'primordialsea', 'deltastream'];
if (this.field.getWeather().id === 'deltastream' && !strongWeathers.includes(weather.id)) return false;
},
onEnd(pokemon) {
if (this.field.weatherState.source !== pokemon) return;
for (const target of this.getAllActive()) {
if (target === pokemon) continue;
if (target.hasAbility('dragonsgale')) {
this.field.weatherState.source = target;
return;
}
}
this.field.clearWeather();
},
onDamage(damage, target, source, effect) {
if (effect && (effect.id === 'stealthrock' || effect.id === 'spikes')) {
return damage / 2;
}
},
flags: {},
name: "Dragon's Gale",
shortDesc: "On switch-in, sets Delta Stream. User takes halved damage from hazards.",
rating: 5,
},
parentalbond: {
onPrepareHit(source, target, move) {
if (move.category === 'Status' || move.selfdestruct || move.multihit) return;
if ([
'endeavor', 'seismictoss', 'psywave', 'nightshade', 'sonicboom', 'dragonrage',
'superfang', 'naturesmadness', 'bide', 'counter', 'mirrorcoat', 'metalburst',
].includes(move.id)) return;
if (!move.spreadHit && !move.isZ && !move.isMax) {
move.multihit = 2;
move.multihitType = 'parentalbond';
}
},
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');
}
},
name: "Parental Bond",
rating: 4.5,
shortDesc: "This Pokemon's damaging moves hit twice. The second hit has its damage quartered.",
num: 184,
},
// for ngas
galewings: {
// for ngas
inherit: true,
onModifyPriority(priority, pokemon, target, move) {
for (const poke of this.getAllActive()) {
if (poke.hasAbility('neutralizinggas') && poke.side.id !== pokemon.side.id && !poke.abilityState.ending) {
return;
}
}
if (move && move.type === 'Flying') return priority + 1;
},
},
prankster: {
// for ngas
inherit: true,
onModifyPriority(priority, pokemon, target, move) {
for (const poke of this.getAllActive()) {
if (poke.hasAbility('neutralizinggas') && poke.side.id !== pokemon.side.id && !poke.abilityState.ending) {
return;
}
}
if (move?.category === 'Status') {
move.pranksterBoosted = true;
return priority + 1;
}
},
},
};

View File

@ -0,0 +1,26 @@
export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormatsDataTable = {
blaziken: {
tier: "OU",
},
blazikenmega: {
tier: "OU",
},
gengarmega: {
tier: "OU",
},
kangaskhanmega: {
tier: "OU",
},
lucariomega: {
tier: "OU",
},
mawilemega: {
tier: "OU",
},
sableyemega: {
tier: "OU",
},
salamencemega: {
tier: "OU",
},
};

View File

@ -0,0 +1,12 @@
export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
meteorite: {
name: "Meteorite",
spritenum: 615,
megaStone: { "Rayquaza": "Rayquaza-Mega" },
itemUser: ["Rayquaza"],
onTakeItem(item, source) {
return !item.megaStone?.[source.baseSpecies.baseSpecies];
},
desc: "If held by a Rayquaza, this item allows it to Mega Evolve in battle.",
},
};

View File

@ -0,0 +1,77 @@
export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
stealthrock: {
inherit: true,
condition: {
// this is a side condition
onSideStart(side) {
this.add('-sidestart', side, 'move: Stealth Rock');
},
onSwitchIn(pokemon) {
if (pokemon.hasItem('heavydutyboots') || pokemon.hasAbility('exoskeleton')) return;
const typeMod = this.clampIntRange(pokemon.runEffectiveness(this.dex.getActiveMove('stealthrock')), -6, 6);
this.damage(pokemon.maxhp * (2 ** typeMod) / 8);
},
},
},
toxicspikes: {
inherit: true,
condition: {
// this is a side condition
onSideStart(side) {
this.add('-sidestart', side, 'move: Toxic Spikes');
this.effectState.layers = 1;
},
onSideRestart(side) {
if (this.effectState.layers >= 2) return false;
this.add('-sidestart', side, 'move: Toxic Spikes');
this.effectState.layers++;
},
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') || pokemon.hasAbility('exoskeleton')) {
// 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]);
}
},
},
},
spikes: {
inherit: true,
condition: {
// this is a side condition
onSideStart(side) {
this.add('-sidestart', side, 'Spikes');
this.effectState.layers = 1;
},
onSideRestart(side) {
if (this.effectState.layers >= 3) return false;
this.add('-sidestart', side, 'Spikes');
this.effectState.layers++;
},
onSwitchIn(pokemon) {
if (!pokemon.isGrounded() || pokemon.hasItem('heavydutyboots') || pokemon.hasAbility('exoskeleton')) 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: {
onSideStart(side) {
this.add('-sidestart', side, 'move: Sticky Web');
},
onSwitchIn(pokemon) {
if (!pokemon.isGrounded() || pokemon.hasItem('heavydutyboots') || pokemon.hasAbility('exoskeleton')) return;
this.add('-activate', pokemon, 'move: Sticky Web');
this.boost({ spe: -1 }, pokemon, pokemon.side.foe.active[0], this.dex.getActiveMove('stickyweb'));
},
},
},
};

View File

@ -0,0 +1,249 @@
export const Pokedex: import('../../../sim/dex-species').ModdedSpeciesDataTable = {
audinomega: {
inherit: true,
types: ["Normal", "Electric"],
baseStats: { hp: 103, atk: 60, def: 120, spa: 110, spd: 97, spe: 55 },
abilities: { 0: "Regenerator" },
},
houndoommega: {
inherit: true,
types: ["Dark", "Fire"],
baseStats: { hp: 75, atk: 90, def: 90, spa: 140, spd: 90, spe: 115 },
abilities: { 0: "Merciless" },
},
lucariomega: {
inherit: true,
types: ["Fighting", "Steel"],
baseStats: { hp: 70, atk: 125, def: 70, spa: 140, spd: 94, spe: 126 },
abilities: { 0: "Lightning Rod" },
},
banettemega: {
inherit: true,
types: ["Ghost", "Steel"],
baseStats: { hp: 64, atk: 149, def: 75, spa: 83, spd: 83, spe: 101 },
abilities: { 0: "Pocket Dimension" },
},
glaliemega: {
inherit: true,
types: ["Ice", "Steel"],
baseStats: { hp: 80, atk: 160, def: 70, spa: 95, spd: 70, spe: 105 },
abilities: { 0: "Refrigerate" },
},
venusaurmega: {
inherit: true,
types: ["Grass", "Poison"],
baseStats: { hp: 80, atk: 82, def: 123, spa: 120, spd: 120, spe: 100 },
abilities: { 0: "Grassy Surge" },
},
blastoisemega: {
inherit: true,
types: ["Water", "Fairy"],
baseStats: { hp: 79, atk: 83, def: 130, spa: 135, spd: 105, spe: 98 },
abilities: { 0: "Misty Surge" },
},
charizardmegay: {
inherit: true,
types: ["Fire", "Flying"],
baseStats: { hp: 78, atk: 94, def: 93, spa: 159, spd: 110, spe: 100 },
abilities: { 0: "Dragon's Gale" },
},
alakazammega: {
inherit: true,
types: ["Psychic", "Ice"],
baseStats: { hp: 55, atk: 50, def: 75, spa: 155, spd: 125, spe: 140 },
abilities: { 0: "Magic Guard" },
},
pinsirmega: {
inherit: true,
types: ["Bug", "Ice"],
baseStats: { hp: 65, atk: 150, def: 110, spa: 80, spd: 85, spe: 110 },
abilities: { 0: "Mountaineer" },
},
gengarmega: {
inherit: true,
types: ["Ghost", "Poison"],
baseStats: { hp: 60, atk: 65, def: 105, spa: 155, spd: 105, spe: 110 },
abilities: { 0: "Neutralizing Gas" },
},
aerodactylmega: {
inherit: true,
types: ["Rock", "Flying"],
baseStats: { hp: 80, atk: 140, def: 65, spa: 85, spd: 100, spe: 145 },
abilities: { 0: "Nostalgia Trip" },
},
steelixmega: {
inherit: true,
types: ["Steel", "Ground"],
baseStats: { hp: 75, atk: 135, def: 210, spa: 55, spd: 105, spe: 30 },
abilities: { 0: "Flash Fire" },
weightkg: 999.9,
},
altariamega: {
inherit: true,
types: ["Dragon", "Fairy"],
baseStats: { hp: 75, atk: 90, def: 90, spa: 140, spd: 115, spe: 80 },
abilities: { 0: "Weather Report" },
},
sceptilemega: {
inherit: true,
types: ["Grass", "Dragon"],
baseStats: { hp: 70, atk: 95, def: 79, spa: 145, spd: 99, spe: 142 },
abilities: { 0: "Armor Tail" },
},
swampertmega: {
inherit: true,
types: ["Water", "Poison"],
baseStats: { hp: 100, atk: 145, def: 110, spa: 85, spd: 110, spe: 85 },
abilities: { 0: "Toxic Chain" },
},
manectricmega: {
inherit: true,
types: ["Electric"],
baseStats: { hp: 70, atk: 75, def: 80, spa: 135, spd: 85, spe: 130 },
abilities: { 0: "Bug Zapper" },
},
absolmega: {
inherit: true,
types: ["Dark", "Fairy"],
baseStats: { hp: 65, atk: 130, def: 60, spa: 135, spd: 60, spe: 115 },
abilities: { 0: "Neuroforce" },
},
medichammega: {
inherit: true,
types: ["Fighting", "Psychic"],
baseStats: { hp: 60, atk: 60, def: 100, spa: 90, spd: 100, spe: 100 },
abilities: { 0: "Brain Power" },
},
sableyemega: {
inherit: true,
types: ["Dark", "Ghost"],
baseStats: { hp: 50, atk: 95, def: 115, spa: 85, spd: 115, spe: 20 },
},
beedrillmega: {
inherit: true,
types: ["Bug", "Rock"],
baseStats: { hp: 65, atk: 140, def: 85, spa: 45, spd: 85, spe: 75 },
abilities: { 0: "Exoskeleton" },
},
mawilemega: {
inherit: true,
types: ["Steel", "Fairy"],
baseStats: { hp: 50, atk: 90, def: 125, spa: 70, spd: 95, spe: 50 },
abilities: { 0: "Huge Power" },
},
abomasnowmega: {
inherit: true,
types: ["Grass"],
abilities: { 0: "Ice Scales" },
},
cameruptmega: {
inherit: true,
types: ["Fire", "Ground"],
baseStats: { hp: 70, atk: 80, def: 140, spa: 135, spd: 115, spe: 20 },
abilities: { 0: "Earth Eater" },
},
slowbromega: {
inherit: true,
types: ["Water", "Psychic"],
baseStats: { hp: 95, atk: 75, def: 150, spa: 120, spd: 120, spe: 30 },
abilities: { 0: "Shell Ejection" },
},
gallademega: {
inherit: true,
types: ["Psychic", "Fighting"],
baseStats: { hp: 68, atk: 150, def: 100, spa: 75, spd: 127, spe: 98 },
abilities: { 0: "Sharpness" },
},
ampharosmega: {
inherit: true,
types: ["Electric", "Dragon"],
baseStats: { hp: 90, atk: 95, def: 95, spa: 165, spd: 110, spe: 55 },
abilities: { 0: "Mega Launcher" },
},
gyaradosmega: {
inherit: true,
types: ["Water", "Flying"],
baseStats: { hp: 95, atk: 130, def: 109, spa: 85, spd: 130, spe: 91 },
abilities: { 0: "Aerilate" },
},
heracrossmega: {
inherit: true,
types: ["Bug", "Fighting"],
baseStats: { hp: 80, atk: 150, def: 150, spa: 40, spd: 110, spe: 70 },
abilities: { 0: "Iron Barbs" },
},
sharpedomega: {
inherit: true,
types: ["Water", "Electric"],
baseStats: { hp: 70, atk: 130, def: 55, spa: 145, spd: 55, spe: 105 },
abilities: { 0: "No Guard" },
},
gardevoirmega: {
inherit: true,
types: ["Psychic", "Fairy"],
baseStats: { hp: 68, atk: 65, def: 100, spa: 150, spd: 127, spe: 108 },
},
aggronmega: {
inherit: true,
types: ["Steel"],
baseStats: { hp: 70, atk: 145, def: 185, spa: 85, spd: 85, spe: 60 },
abilities: { 0: "Dauntless Shield" },
},
kangaskhanmega: {
inherit: true,
types: ["Normal", "Ground"],
baseStats: { hp: 105, atk: 125, def: 105, spa: 50, spd: 105, spe: 100 },
},
salamencemega: {
inherit: true,
types: ["Dragon", "Flying"],
baseStats: { hp: 95, atk: 135, def: 105, spa: 155, spd: 105, spe: 105 },
abilities: { 0: "Confidence" },
},
garchompmega: {
inherit: true,
types: ["Dragon", "Ground"],
baseStats: { hp: 108, atk: 150, def: 115, spa: 140, spd: 85, spe: 102 },
abilities: { 0: "Water Absorb" },
},
tyranitarmega: {
inherit: true,
types: ["Rock", "Electric"],
baseStats: { hp: 100, atk: 144, def: 120, spa: 110, spd: 144, spe: 82 },
abilities: { 0: "Electric Surge" },
},
latiasmega: {
inherit: true,
abilities: { 0: "Trace" },
},
latiosmega: {
inherit: true,
baseStats: { hp: 80, atk: 140, def: 100, spa: 150, spd: 120, spe: 110 },
abilities: { 0: "Opportunist" },
},
dianciemega: {
inherit: true,
abilities: { 0: "Good As Gold" },
},
blazikenmega: {
inherit: true,
baseStats: { hp: 80, atk: 150, def: 80, spa: 120, spd: 90, spe: 110 },
abilities: { 0: "Regenerator" },
},
mewtwomegax: {
inherit: true,
types: ["Psychic", "Poison"],
baseStats: { hp: 106, atk: 140, def: 130, spa: 154, spd: 120, spe: 130 },
abilities: { 0: "Intoxicate" },
},
mewtwomegay: {
inherit: true,
types: ["Psychic", "Water"],
baseStats: { hp: 106, atk: 120, def: 110, spa: 194, spd: 130, spe: 120 },
abilities: { 0: "Levitate" },
},
rayquazamega: {
inherit: true,
requiredItem: "Meteorite",
},
};

View File

@ -0,0 +1,33 @@
export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable = {
megadatamod: {
effectType: 'Rule',
name: 'Mega Data Mod',
desc: 'Gives data on stats, Ability and types when a Pokémon Mega Evolves or undergoes Ultra Burst.',
onSwitchIn(pokemon) {
if (pokemon.species.forme.startsWith('Mega') || pokemon.species.forme.startsWith('Ultra')) {
this.add('-start', pokemon, 'typechange', pokemon.getTypes(true).join('/'), '[silent]');
}
},
onAfterMega(pokemon) {
this.add('-start', pokemon, 'typechange', pokemon.getTypes(true).join('/'), '[silent]');
const species = pokemon.species;
let buf = `<span class="col pokemonnamecol" style="white-space: nowrap">${species.name}</span> `;
buf += `<span class="col typecol">`;
buf += `<img src="https://${Config.routes.client}/sprites/types/${species.types[0]}.png" alt="${species.types[0]}" height="14" width="32">`;
if (species.types[1]) {
buf += `<img src="https://${Config.routes.client}/sprites/types/${species.types[1]}.png" alt="${species.types[1]}" height="14" width="32">`;
}
buf += `</span> `;
buf += `<span style="float: left ; min-height: 26px"><span class="col abilitycol">${species.abilities[0]}</span><span class="col abilitycol"></span></span>`;
const stats = [];
let stat: StatID;
for (stat in species.baseStats) {
const statNames: { [k in StatID]: string } = { hp: "HP", atk: "Atk", def: "Def", spa: "SpA", spd: "SpD", spe: "Spe" };
stats.push(`<span class="col statcol"><em>${statNames[stat]}</em><br>${species.baseStats[stat]}</span>`);
}
buf += `<span style="float: left ; min-height: 26px">${stats.join(' ')}</span>`;
buf += `</span>`;
this.add(`raw|<ul class="utilichart"><li class="result">${buf}</li><li style="clear: both"></li></ul>`);
},
},
};

View File

@ -0,0 +1,237 @@
export const Scripts: ModdedBattleScriptsData = {
gen: 6,
inherit: 'gen6',
actions: {
// for parental bond
modifyDamage(
baseDamage: number, pokemon: Pokemon, target: Pokemon, move: ActiveMove, 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 = 0.25;
this.battle.debug(`Parental Bond modifier: ${bondModifier}`);
baseDamage = this.battle.modify(baseDamage, bondModifier);
}
baseDamage = this.battle.runEvent('WeatherModifyDamage', pokemon, target, move, baseDamage);
const isCrit = target.getMoveHitData(move).crit;
if (isCrit) {
baseDamage = tr(baseDamage * (move.critModifier || (this.battle.gen >= 6 ? 1.5 : 2)));
}
baseDamage = this.battle.randomizer(baseDamage);
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;
}
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);
}
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);
}
}
// 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);
if (move.isZOrMaxPowered && target.getMoveHitData(move).zBrokeProtect) {
baseDamage = this.battle.modify(baseDamage, 0.25);
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);
},
},
pokemon: {
// for neutralizing gas
ignoringAbility() {
if (this.battle.gen >= 5 && !this.isActive) return true;
if (this.getAbility().flags['notransform'] && this.transformed) return true;
if (this.getAbility().flags['cantsuppress']) return false;
if (this.volatiles['gastroacid']) return true;
if (this.ability === ('neutralizinggas' as ID)) return false;
if (this.volatiles['neutralizinggas']) return true;
return false;
},
},
init() {
this.modData("Learnsets", "lucario").learnset.meteormash = ["6L1"];
this.modData("Learnsets", "lucario").learnset.machpunch = ["6L1"];
this.modData("Learnsets", "houndoom").learnset.toxicspikes = ["6L1"];
this.modData("Learnsets", "houndoom").learnset.venoshock = ["6L1"];
this.modData("Learnsets", "houndoom").learnset.hex = ["6L1"];
this.modData("Learnsets", "audino").learnset.discharge = ["6L1"];
this.modData("Learnsets", "audino").learnset.voltswitch = ["6L1"];
this.modData("Learnsets", "audino").learnset.chargebeam = ["6L1"];
this.modData("Learnsets", "audino").learnset.charge = ["6L1"];
this.modData("Learnsets", "audino").learnset.zapcannon = ["6L1"];
this.modData("Learnsets", "glalie").learnset.thunderfang = ["6L1"];
this.modData("Learnsets", "glalie").learnset.partingshot = ["6L1"];
this.modData("Learnsets", "glalie").learnset.boomburst = ["6L1"];
this.modData("Learnsets", "banette").learnset.ironhead = ["6L1"];
this.modData("Learnsets", "banette").learnset.metalsound = ["6L1"];
this.modData("Learnsets", "banette").learnset.powder = ["6L1"];
this.modData("Learnsets", "banette").learnset.stealthrock = ["6L1"];
this.modData("Learnsets", "banette").learnset.defog = ["6L1"];
this.modData("Learnsets", "venusaur").learnset.psychic = ["6L1"];
this.modData("Learnsets", "venusaur").learnset.calmmind = ["6L1"];
this.modData("Learnsets", "blastoise").learnset.moonblast = ["6L1"];
this.modData("Learnsets", "blastoise").learnset.mistyterrain = ["6L1"];
this.modData("Learnsets", "blastoise").learnset.taunt = ["6L1"];
this.modData("Learnsets", "blastoise").learnset.drainingkiss = ["6L1"];
this.modData("Learnsets", "blastoise").learnset.dazzlinggleam = ["6L1"];
this.modData("Learnsets", "charizard").learnset.calmmind = ["6L1"];
this.modData("Learnsets", "charizard").learnset.hurricane = ["6L1"];
this.modData("Learnsets", "charizard").learnset.lavaplume = ["6L1"];
this.modData("Learnsets", "gengar").learnset.reflecttype = ["6L1"];
this.modData("Learnsets", "gengar").learnset.calmmind = ["6L1"];
this.modData("Learnsets", "alakazam").learnset.blizzard = ["6L1"];
this.modData("Learnsets", "alakazam").learnset.flashcannon = ["6L1"];
this.modData("Learnsets", "alakazam").learnset.icebeam = ["6L1"];
this.modData("Learnsets", "alakazam").learnset.hail = ["6L1"];
this.modData("Learnsets", "pinsir").learnset.hail = ["6L1"];
this.modData("Learnsets", "pinsir").learnset.megahorn = ["6L1"];
this.modData("Learnsets", "pinsir").learnset.uturn = ["6L1"];
this.modData("Learnsets", "pinsir").learnset.iceshard = ["6L1"];
this.modData("Learnsets", "pinsir").learnset.iciclecrash = ["6L1"];
this.modData("Learnsets", "pinsir").learnset.icebeam = ["6L1"];
this.modData("Learnsets", "pinsir").learnset.blizzard = ["6L1"];
this.modData("Learnsets", "pinsir").learnset.roost = ["6L1"];
this.modData("Learnsets", "pinsir").learnset.iciclespear = ["6L1"];
this.modData("Learnsets", "aerodactyl").learnset.powergem = ["6L1"];
this.modData("Learnsets", "aerodactyl").learnset.shadowball = ["6L1"];
this.modData("Learnsets", "aerodactyl").learnset.hurricane = ["6L1"];
this.modData("Learnsets", "steelix").learnset.heatcrash = ["6L1"];
this.modData("Learnsets", "steelix").learnset.rapidspin = ["6L1"];
this.modData("Learnsets", "steelix").learnset.smackdown = ["6L1"];
this.modData("Learnsets", "altaria").learnset.scald = ["6L1"];
this.modData("Learnsets", "altaria").learnset.hydropump = ["6L1"];
this.modData("Learnsets", "altaria").learnset.thunder = ["6L1"];
this.modData("Learnsets", "sceptile").learnset.calmmind = ["6L1"];
this.modData("Learnsets", "sceptile").learnset.sludgewave = ["6L1"];
this.modData("Learnsets", "swampert").learnset.sludgebomb = ["6L1"];
this.modData("Learnsets", "swampert").learnset.bulkup = ["6L1"];
this.modData("Learnsets", "swampert").learnset.toxicspikes = ["6L1"];
this.modData("Learnsets", "swampert").learnset.aquajet = ["6L1"];
this.modData("Learnsets", "swampert").learnset.gunkshot = ["6L1"];
this.modData("Learnsets", "swampert").learnset.poisonjab = ["6L1"];
this.modData("Learnsets", "pidgeot").learnset.focusblast = ["6L1"];
this.modData("Learnsets", "absol").learnset.closecombat = ["6L1"];
this.modData("Learnsets", "absol").learnset.moonblast = ["6L1"];
this.modData("Learnsets", "absol").learnset.moonlight = ["6L1"];
this.modData("Learnsets", "medicham").learnset.aurasphere = ["6L1"];
this.modData("Learnsets", "medicham").learnset.thunderbolt = ["6L1"];
this.modData("Learnsets", "medicham").learnset.closecombat = ["6L1"];
this.modData("Learnsets", "medicham").learnset.gunkshot = ["6L1"];
this.modData("Learnsets", "medicham").learnset.healingwish = ["6L1"];
this.modData("Learnsets", "beedrill").learnset.earthquake = ["6L1"];
this.modData("Learnsets", "beedrill").learnset.stoneedge = ["6L1"];
this.modData("Learnsets", "beedrill").learnset.rockslide = ["6L1"];
this.modData("Learnsets", "beedrill").learnset.smackdown = ["6L1"];
this.modData("Learnsets", "beedrill").learnset.stealthrock = ["6L1"];
this.modData("Learnsets", "beedrill").learnset.diamondstorm = ["6L1"];
this.modData("Learnsets", "mawile").learnset.firepunch = ["6L1"];
this.modData("Learnsets", "mawile").learnset.rockslide = ["6L1"];
this.modData("Learnsets", "mawile").learnset.slackoff = ["6L1"];
this.modData("Learnsets", "camerupt").learnset.morningsun = ["6L1"];
this.modData("Learnsets", "abomasnow").learnset.spikyshield = ["6L1"];
this.modData("Learnsets", "abomasnow").learnset.earthpower = ["6L1"];
this.modData("Learnsets", "abomasnow").learnset.hornleech = ["6L1"];
this.modData("Learnsets", "gallade").learnset.sacredsword = ["6L1"];
this.modData("Learnsets", "gallade").learnset.machpunch = ["6L1"];
this.modData('Moves', 'aerialace').flags.slicing = 1;
this.modData('Moves', 'aircutter').flags.slicing = 1;
this.modData('Moves', 'airslash').flags.slicing = 1;
this.modData('Moves', 'behemothblade').flags.slicing = 1;
this.modData('Moves', 'crosspoison').flags.slicing = 1;
this.modData('Moves', 'cut').flags.slicing = 1;
this.modData('Moves', 'furycutter').flags.slicing = 1;
this.modData('Moves', 'nightslash').flags.slicing = 1;
this.modData('Moves', 'psychocut').flags.slicing = 1;
this.modData('Moves', 'razorleaf').flags.slicing = 1;
this.modData('Moves', 'razorshell').flags.slicing = 1;
this.modData('Moves', 'sacredsword').flags.slicing = 1;
this.modData('Moves', 'slash').flags.slicing = 1;
this.modData('Moves', 'solarblade').flags.slicing = 1;
this.modData('Moves', 'xscissor').flags.slicing = 1;
this.modData("Learnsets", "ampharos").learnset.waterpulse = ["6L1"];
this.modData("Learnsets", "ampharos").learnset.aurasphere = ["6L1"];
this.modData("Learnsets", "ampharos").learnset.darkpulse = ["6L1"];
this.modData("Learnsets", "ampharos").learnset.defog = ["6L1"];
this.modData("Learnsets", "ampharos").learnset.slackoff = ["6L1"];
this.modData("Learnsets", "heracross").learnset.healorder = ["6L1"];
this.modData("Learnsets", "heracross").learnset.circlethrow = ["6L1"];
this.modData("Learnsets", "heracross").learnset.spikes = ["6L1"];
this.modData("Learnsets", "heracross").learnset.icepunch = ["6L1"];
this.modData("Learnsets", "sharpedo").learnset.thunder = ["6L1"];
this.modData("Learnsets", "gardevoir").learnset.rapidspin = ["6L1"];
this.modData("Learnsets", "gardevoir").learnset.mysticalfire = ["6L1"];
this.modData("Learnsets", "aggron").learnset.voltswitch = ["6L1"];
this.modData("Learnsets", "kangaskhan").learnset.milkdrink = ["6L1"];
this.modData("Learnsets", "salamence").learnset.hurricane = ["6L1"];
this.modData("Learnsets", "salamence").learnset.airslash = ["6L1"];
this.modData("Learnsets", "salamence").learnset.ironhead = ["6L1"];
this.modData("Learnsets", "tyranitar").learnset.wildcharge = ["6L1"];
this.modData("Learnsets", "tyranitar").learnset.waterfall = ["6L1"];
this.modData("Learnsets", "diancie").learnset.spikyshield = ["6L1"];
this.modData("Learnsets", "blaziken").learnset.uturn = ["6L1"];
this.modData("Learnsets", "blaziken").learnset.spikes = ["6L1"];
this.modData("Learnsets", "blaziken").learnset.roost = ["6L1"];
this.modData("Learnsets", "blaziken").learnset.closecombat = ["6L1"];
this.modData("Learnsets", "mewtwo").learnset.extremespeed = ["6L1"];
this.modData("Learnsets", "mewtwo").learnset.sludgewave = ["6L1"];
this.modData("Learnsets", "mewtwo").learnset.swordsdance = ["6L1"];
this.modData("Learnsets", "mewtwo").learnset.uturn = ["6L1"];
this.modData("Learnsets", "mewtwo").learnset.closecombat = ["6L1"];
this.modData("Learnsets", "mewtwo").learnset.drainpunch = ["6L1"];
this.modData("Learnsets", "mewtwo").learnset.machpunch = ["6L1"];
this.modData("Learnsets", "mewtwo").learnset.scald = ["6L1"];
this.modData("Learnsets", "mewtwo").learnset.surf = ["6L1"];
this.modData("Learnsets", "mewtwo").learnset.hydropump = ["6L1"];
this.modData("Learnsets", "rayquaza").learnset.coil = ["6L1"];
this.modData("Learnsets", "rayquaza").learnset.defog = ["6L1"];
},
};

View File

@ -0,0 +1,46 @@
export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
blueorb: {
inherit: true,
onSwitchIn(pokemon) {
if (pokemon.isActive && !pokemon.species.isPrimal && !pokemon.transformed) {
// @ts-expect-error modded
const species: Species = this.actions.getMixedSpecies(pokemon.m.originalSpecies, 'Kyogre-Primal', pokemon);
if (pokemon.m.originalSpecies === 'Kyogre') {
pokemon.formeChange(species, this.effect, true);
} else {
pokemon.formeChange(species, this.effect, true);
pokemon.baseSpecies = species;
this.add('-start', pokemon, 'Blue Orb', '[silent]');
}
}
},
onTakeItem: false,
},
redorb: {
inherit: true,
onSwitchIn(pokemon) {
if (pokemon.isActive && !pokemon.species.isPrimal && !pokemon.transformed) {
// @ts-expect-error modded
const species: Species = this.actions.getMixedSpecies(pokemon.m.originalSpecies, 'Groudon-Primal', pokemon);
if (pokemon.m.originalSpecies === 'Groudon') {
pokemon.formeChange(species, this.effect, true);
} else {
pokemon.formeChange(species, this.effect, true);
pokemon.baseSpecies = species;
this.add('-start', pokemon, 'Red Orb', '[silent]');
const apparentSpecies = pokemon.illusion ? pokemon.illusion.species.name : pokemon.m.originalSpecies;
const oSpecies = this.dex.species.get(apparentSpecies);
if (pokemon.illusion) {
const types = oSpecies.types;
if (types.length > 1 || types[types.length - 1] !== 'Fire') {
this.add('-start', pokemon, 'typechange', (types[0] !== 'Fire' ? types[0] + '/' : '') + 'Fire', '[silent]');
}
} else if (oSpecies.types.length !== pokemon.species.types.length || oSpecies.types[1] !== pokemon.species.types[1]) {
this.add('-start', pokemon, 'typechange', pokemon.species.types.join('/'), '[silent]');
}
}
}
},
onTakeItem: false,
},
};

View File

@ -0,0 +1,117 @@
export const Scripts: ModdedBattleScriptsData = {
gen: 6,
inherit: 'gen6',
init() {
for (const i in this.data.Items) {
if (!this.data.Items[i].megaStone) continue;
this.modData('Items', i).onTakeItem = false;
}
},
actions: {
canMegaEvo(pokemon) {
if (pokemon.species.isMega || pokemon.species.isPrimal) return null;
const item = pokemon.getItem();
if (item.megaStone) {
const values = Object.values(item.megaStone);
if (values.includes(pokemon.name)) return null;
return values[0];
} else if (pokemon.baseMoves.includes('dragonascent')) {
return 'Rayquaza-Mega';
} else {
return null;
}
},
runMegaEvo(pokemon) {
if (pokemon.species.isMega || pokemon.species.isPrimal) return false;
const species: Species = (this as any).getMixedSpecies(pokemon.m.originalSpecies, pokemon.canMegaEvo, pokemon);
// Do we have a proper sprite for it? Code for when megas actually exist
if (this.dex.species.get(pokemon.canMegaEvo as any).baseSpecies === pokemon.m.originalSpecies) {
pokemon.formeChange(species, pokemon.getItem(), true);
} else {
const oSpecies = this.dex.species.get(pokemon.m.originalSpecies);
const oMegaSpecies = this.dex.species.get((species as any).originalSpecies);
pokemon.formeChange(species, pokemon.getItem(), true);
this.battle.add('-start', pokemon, oMegaSpecies.requiredItem, '[silent]');
if (oSpecies.types.join('/') !== pokemon.species.types.join('/')) {
this.battle.add('-start', pokemon, 'typechange', pokemon.species.types.join('/'), '[silent]');
}
}
pokemon.canMegaEvo = false;
return true;
},
getMixedSpecies(originalForme, formeChange, pokemon) {
const originalSpecies = this.dex.species.get(originalForme);
const formeChangeSpecies = this.dex.species.get(formeChange);
if (originalSpecies.baseSpecies === formeChangeSpecies.baseSpecies) {
return formeChangeSpecies;
}
const deltas = (this as any).getFormeChangeDeltas(formeChangeSpecies, pokemon);
const species = (this as any).mutateOriginalSpecies(originalSpecies, deltas);
return species;
},
getFormeChangeDeltas(formeChangeSpecies, pokemon) {
// Should be fine as long as Necrozma-U doesn't get added or Game Freak makes me sad with some convoluted forme change
const baseSpecies = this.dex.species.get(formeChangeSpecies.isMega ?
formeChangeSpecies.battleOnly as string : formeChangeSpecies.baseSpecies);
const deltas: {
ability: string,
baseStats: SparseStatsTable,
weighthg: number,
heightm: number,
originalSpecies: string,
requiredItem: string | undefined,
type?: string,
formeType?: string,
isMega?: boolean,
} = {
ability: formeChangeSpecies.abilities['0'],
baseStats: {},
weighthg: formeChangeSpecies.weighthg - baseSpecies.weighthg,
heightm: ((formeChangeSpecies.heightm * 10) - (baseSpecies.heightm * 10)) / 10,
originalSpecies: formeChangeSpecies.name,
requiredItem: formeChangeSpecies.requiredItem,
};
let statId: StatID;
for (statId in formeChangeSpecies.baseStats) {
deltas.baseStats[statId] = formeChangeSpecies.baseStats[statId] - baseSpecies.baseStats[statId];
}
let formeType: string | null = null;
if (formeChangeSpecies.types.length > baseSpecies.types.length) {
deltas.type = formeChangeSpecies.types[1];
} else if (formeChangeSpecies.types.length < baseSpecies.types.length) {
deltas.type = baseSpecies.types[0];
} else if (formeChangeSpecies.types[1] !== baseSpecies.types[1]) {
deltas.type = formeChangeSpecies.types[1];
}
if (formeChangeSpecies.isMega && !formeType) formeType = 'Mega';
if (formeChangeSpecies.isPrimal) formeType = 'Primal';
if (formeType) deltas.formeType = formeType;
return deltas;
},
mutateOriginalSpecies(speciesOrForme, deltas) {
if (!deltas) throw new TypeError("Must specify deltas!");
const species = this.dex.deepClone(this.dex.species.get(speciesOrForme));
species.abilities = { '0': deltas.ability };
if (species.types[0] === deltas.type) {
species.types = [deltas.type];
} else if (deltas.type) {
species.types = [species.types[0], deltas.type];
}
const baseStats = species.baseStats;
for (const statName in baseStats) {
baseStats[statName] = this.battle.clampIntRange(baseStats[statName] + deltas.baseStats[statName], 1, 255);
}
species.weighthg = Math.max(1, species.weighthg + deltas.weighthg);
species.heightm = Math.max(0.1, ((species.heightm * 10) + (deltas.heightm * 10)) / 10);
species.originalSpecies = deltas.originalSpecies;
species.requiredItem = deltas.requiredItem;
if (deltas.formeType === 'Mega' || deltas.isMega) species.isMega = true;
if (deltas.formeType === 'Primal') species.isPrimal = true;
return species;
},
},
};

View File

@ -19,6 +19,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
if (['mimikyu', 'mimikyutotem'].includes(pokemon.species.id) && this.effectState.busted) {
const speciesid = pokemon.species.id === 'mimikyutotem' ? 'Mimikyu-Busted-Totem' : 'Mimikyu-Busted';
pokemon.formeChange(speciesid, this.effect, true);
pokemon.formeRegression = true;
}
},
},
@ -71,14 +72,8 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
onTryBoost() {},
},
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() {},
},
scrappy: {
inherit: true,
@ -86,33 +81,18 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
},
slowstart: {
inherit: true,
condition: {
duration: 5,
onResidualOrder: 28,
onResidualSubOrder: 2,
onStart(target) {
this.add('-start', target, 'ability: Slow Start');
},
onModifyAtkPriority: 5,
onModifyAtk(atk, pokemon, target, move) {
// This is because the game checks the move's category in data, rather than what it is currently, unlike e.g. Huge Power
if (this.dex.moves.get(move.id).category === 'Physical') {
return this.chainModify(0.5);
}
},
onModifySpAPriority: 5,
onModifySpA(spa, pokemon, target, move) {
// Ordinary Z-moves like Breakneck Blitz will halve the user's Special Attack as well
if (this.dex.moves.get(move.id).category === 'Physical') {
return this.chainModify(0.5);
}
},
onModifySpe(spe, pokemon) {
onModifyAtk(atk, pokemon, target, move) {
// This is because the game checks the move's category in data, rather than what it is currently, unlike e.g. Huge Power
if (this.effectState.counter && this.dex.moves.get(move.id).category === 'Physical') {
return this.chainModify(0.5);
},
onEnd(target) {
this.add('-end', target, 'Slow Start');
},
}
},
onModifySpAPriority: 5,
onModifySpA(spa, pokemon, target, move) {
// Ordinary Z-moves like Breakneck Blitz will halve the user's Special Attack as well
if (this.effectState.counter && this.dex.moves.get(move.id).category === 'Physical') {
return this.chainModify(0.5);
}
},
},
soundproof: {

View File

@ -207,7 +207,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "NFE",
},
vulpixalola: {
tier: "LC",
tier: "NFE",
},
ninetales: {
tier: "RU",
@ -592,7 +592,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
doublesTier: "NFE",
},
tangrowth: {
tier: "OU",
tier: "(OU)",
doublesTier: "(DUU)",
},
kangaskhan: {
@ -916,7 +916,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "NFE",
},
azumarill: {
tier: "OU",
tier: "(OU)",
doublesTier: "DUU",
},
bonsly: {

View File

@ -127,10 +127,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
onHit(target, source, move) {
let success = false;
if (!target.volatiles['substitute'] || move.infiltrates) success = !!this.boost({ evasion: -1 });
const removeTarget = [
'reflect', 'lightscreen', 'auroraveil', 'safeguard', 'mist', 'spikes', 'toxicspikes', 'stealthrock', 'stickyweb',
];
const removeAll = ['spikes', 'toxicspikes', 'stealthrock', 'stickyweb'];
const removeTarget = ['reflect', 'lightscreen', 'auroraveil', 'safeguard', 'mist', ...removeAll];
for (const targetCondition of removeTarget) {
if (target.side.removeSideCondition(targetCondition)) {
if (!removeAll.includes(targetCondition)) continue;
@ -184,46 +182,13 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
electricterrain: {
inherit: true,
condition: {
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: {
@ -317,13 +282,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
grassyterrain: {
inherit: true,
condition: {
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: {
@ -386,7 +324,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
inherit: true,
condition: {
duration: 2,
onSwitchInPriority: 1,
onSwitchIn(target) {
if (!target.fainted) {
target.heal(target.maxhp);
@ -559,11 +496,7 @@ 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;
@ -613,7 +546,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
inherit: true,
condition: {
duration: 2,
onSwitchInPriority: 1,
onSwitchIn(target) {
if (!target.fainted) {
target.heal(target.maxhp);
@ -782,47 +714,13 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
psychicterrain: {
inherit: true,
condition: {
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: {
@ -1154,39 +1052,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
inherit: true,
isNonstandard: null,
},
trick: {
inherit: true,
onHit(target, source, move) {
const yourItem = target.takeItem(source);
const myItem = source.takeItem();
if (target.item || source.item || (!yourItem && !myItem)) {
if (yourItem) target.item = yourItem.id;
if (myItem) source.item = myItem.id;
return false;
}
if (
(myItem && !this.singleEvent('TakeItem', myItem, source.itemState, target, source, move, myItem)) ||
(yourItem && !this.singleEvent('TakeItem', yourItem, target.itemState, source, target, move, yourItem))
) {
if (yourItem) target.item = yourItem.id;
if (myItem) source.item = myItem.id;
return false;
}
this.add('-activate', source, 'move: Trick', `[of] ${target}`);
if (myItem) {
target.setItem(myItem);
this.add('-item', target, myItem, '[from] move: Trick');
} else {
this.add('-enditem', target, yourItem, '[silent]', '[from] move: Trick');
}
if (yourItem) {
source.setItem(yourItem);
this.add('-item', source, yourItem, '[from] move: Trick');
} else {
this.add('-enditem', source, myItem, '[silent]', '[from] move: Trick');
}
},
},
trumpcard: {
inherit: true,
isNonstandard: null,

View File

@ -59,6 +59,14 @@ export const Pokedex: import('../../../sim/dex-species').ModdedSpeciesDataTable
inherit: true,
eggGroups: ["Bug"],
},
burmysandy: {
inherit: true,
color: "Green",
},
burmytrash: {
inherit: true,
color: "Green",
},
magnezone: {
inherit: true,
evoType: "levelExtra",
@ -83,6 +91,94 @@ export const Pokedex: import('../../../sim/dex-species').ModdedSpeciesDataTable
abilities: { 0: "Flash Fire", H: "Flame Body" },
unreleasedHidden: true,
},
deerlingsummer: {
inherit: true,
color: "Pink",
},
deerlingautumn: {
inherit: true,
color: "Pink",
},
deerlingwinter: {
inherit: true,
color: "Pink",
},
vivillonicysnow: {
inherit: true,
color: "White",
},
vivillonpolar: {
inherit: true,
color: "White",
},
vivillontundra: {
inherit: true,
color: "White",
},
vivilloncontinental: {
inherit: true,
color: "White",
},
vivillongarden: {
inherit: true,
color: "White",
},
vivillonelegant: {
inherit: true,
color: "White",
},
vivillonmodern: {
inherit: true,
color: "White",
},
vivillonmarine: {
inherit: true,
color: "White",
},
vivillonarchipelago: {
inherit: true,
color: "White",
},
vivillonhighplains: {
inherit: true,
color: "White",
},
vivillonsandstorm: {
inherit: true,
color: "White",
},
vivillonriver: {
inherit: true,
color: "White",
},
vivillonmonsoon: {
inherit: true,
color: "White",
},
vivillonsavanna: {
inherit: true,
color: "White",
},
vivillonsun: {
inherit: true,
color: "White",
},
vivillonocean: {
inherit: true,
color: "White",
},
vivillonjungle: {
inherit: true,
color: "White",
},
vivillonfancy: {
inherit: true,
color: "White",
},
vivillonpokeball: {
inherit: true,
color: "White",
},
aegislash: {
inherit: true,
baseStats: { hp: 60, atk: 50, def: 150, spa: 50, spd: 150, spe: 60 },

View File

@ -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,

View File

@ -116,7 +116,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
},
pikachustarter: {
isNonstandard: null,
tier: "UU",
tier: "RU",
doublesTier: "DOU",
},
raichu: {
@ -138,7 +138,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
doublesTier: "DOU",
},
sandslashalola: {
tier: "UU",
tier: "RU",
doublesTier: "DOU",
},
nidoranf: {
@ -158,7 +158,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "NFE",
},
nidoking: {
tier: "OU",
tier: "UU",
doublesTier: "DOU",
},
clefairy: {
@ -186,7 +186,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "LC",
},
wigglytuff: {
tier: "UU",
tier: "RU",
doublesTier: "DOU",
},
zubat: {
@ -203,7 +203,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "NFE",
},
vileplume: {
tier: "UU",
tier: "RU",
doublesTier: "DOU",
},
paras: {
@ -227,7 +227,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "LC",
},
dugtrio: {
tier: "UU",
tier: "RU",
doublesTier: "DOU",
},
dugtrioalola: {
@ -245,7 +245,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
doublesTier: "DOU",
},
persianalola: {
tier: "UU",
tier: "RU",
doublesTier: "DOU",
},
psyduck: {
@ -266,7 +266,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "LC",
},
arcanine: {
tier: "UU",
tier: "RU",
doublesTier: "DOU",
},
poliwag: {
@ -276,7 +276,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "NFE",
},
poliwrath: {
tier: "OU",
tier: "UU",
doublesTier: "DOU",
},
abra: {
@ -317,7 +317,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "LC",
},
tentacruel: {
tier: "UU",
tier: "RU",
doublesTier: "DOU",
},
geodude: {
@ -401,7 +401,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "LC",
},
cloyster: {
tier: "OU",
tier: "RU",
doublesTier: "DOU",
},
gastly: {
@ -433,7 +433,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "LC",
},
kingler: {
tier: "RU",
tier: "UU",
doublesTier: "DOU",
},
voltorb: {
@ -492,7 +492,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
doublesTier: "DOU",
},
chansey: {
tier: "UU",
tier: "RU",
doublesTier: "DOU",
},
tangela: {
@ -572,7 +572,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
doublesTier: "DOU",
},
lapras: {
tier: "UU",
tier: "RU",
doublesTier: "DOU",
},
ditto: {
@ -584,7 +584,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
},
eeveestarter: {
isNonstandard: null,
tier: "UU",
tier: "RU",
doublesTier: "DOU",
},
vaporeon: {
@ -607,14 +607,14 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
tier: "LC",
},
omastar: {
tier: "UU",
tier: "RU",
doublesTier: "DOU",
},
kabuto: {
tier: "LC",
},
kabutops: {
tier: "UU",
tier: "RU",
doublesTier: "DOU",
},
aerodactyl: {
@ -626,7 +626,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
doublesTier: "DOU",
},
snorlax: {
tier: "OU",
tier: "UU",
doublesTier: "DOU",
},
articuno: {
@ -638,7 +638,7 @@ export const FormatsData: import('../../../sim/dex-species').ModdedSpeciesFormat
doublesTier: "DOU",
},
moltres: {
tier: "UU",
tier: "RU",
doublesTier: "DOU",
},
dratini: {

Some files were not shown because too many files have changed in this diff Show More