`BattlePokedex` is now `Pokedex`, `BattleItems` is now `Items`, etc.
I also renamed `Movedex` to `Moves` and `Statuses` to `Conditions`.
`TypeChart` isn't `Types` yet, because unlike the others, it's not
indexed by ID. That should probably be fixed one day.
Previously, ending a read stream was `stream.push(null)`, and ending a
write stream was `stream.end()`. This was often confusing, and so now,
these are consistently `stream.pushEnd()` and `stream.writeEnd()`.
This refactor already found a bug in which `stream.end()` was used
where `stream.push(null)` should have been.
Also in this refactor: By default, `pushError` ends the stream. You can
pass `true` as the second parameter if the error is recoverable (the
stream shouldn't end).
ede3aaec correctly added restorative berries to the
staleness/termination calculation as per the adjusted specification
but failed to update the win condition.
Inverse Mod needs to go first, to calculate the negated effectiveness.
Disguise goes second, to suppress effectiveness.
Delta Stream goes third, to weaken moves super-effective against Flying types.
Tar Shot goes last, to make its victim weak to Fire type moves.
This allows the existing test for Delta Stream with Tar Shot to pass.
Additionally a new test for Delta Stream with Inverse Mod now passes.
A test for Flying Press with Inverse Mod is also included.
It's a judgment call that doesn't belong among the other factual
information in `moves.ts`.
The information is still around; in the client's `battle-dex-search.ts`
in `BattleMoveSearch#moveIsNotUseless`. But now it's all in one place.
fb18721e82
This check exists for maxMove.basePower but not zMove. Thank you
SadisticMystic for confirming that while "it has an entry of 1 in
the data table, [it]'s a meaningless entry which is impossible
to access"
This mostly serves to provide cleaner and more consistent field
naming. maxMove currently doesn't have boosts or effects to group
together but who knows what will be thrown at us via DLC, and being
symmetrical with zMoves is a nice.
- `Modded[Effect]Data` are now correctly defined: they must either have
`inherit: true` and be partial, or not have `inherit: true` and be a
complete `[Effect]Data` entry
- `id` is no longer allowed; instead, it's calculated directly from
`toID(name)`. The one exception, Hidden Power, gets a `realMove`
property to track this (it's still used to set `.id`, though;
TODO: really fix it properly).
- `num` is still required in `data/pokedex.ts` (dex number),
`data/moves.ts` (move index number, for Metronome), and
`data/items.ts` (minisprite sprite-sheet location). It's still not
required for mod-only items and moves.
- `num` is no longer allowed for PureEffects (in `statuses.ts`) where
it's always been meaningless.
- `color` and `heightm`, being completely flavor, are still not
required for `pokedex.ts` in mods. They're still required in the base
pokedex.
The whole `checkBattleForme` system, introduced in 4410843e5a
and currently used in Gen 6 and 7, seems to have always been bugged.
As TI mentions in #5970, we already use `getPokemonPool` for alternate
forme handling.
I've replaced it with a roll for cosmetic formes.
As confirmed by SadisticMystic, base power cannot be above 255, so
this move data is clearly incorrect and results in downstream users
of the data files such as the Smogon or PS dex or the tooltips
displaying misleading information.
Apparently our old hack was to prevent Unown formes completely, because
locked users would sometimes use them to spell bad words.
I don't like that approach, so now only locked users can't use Unown
formes.
The server now uses the same approach as the client of treating
cosmetic formes as real formes, as documented in `FORMES.md`.
This eliminates the need for the `.forme` and `.speciesid` properties
of `Pokemon`.
`pokemon.id` has also been removed: useful, since it turns out half
of its uses were bugs that should have used `pokemon.species.id`.
In addition, they should not activate for a spread move that ends the game.
(This contrasts with Soul-Heart, which will activate until the last target.)
PS wasn't correctly detecting `disabled: 'hidden'` moves as disabled
for the purposes of detecting Struggle activation. This has been fixed.
Thanks to DaWoblefet for unit tests!
Fixes#6620
BasicEffect always had a `status` property to support the pattern of
testing it to see if it's a move that sets status directly.
This is just a situation that TypeScript is bad at.
Another possibility would be to set `status: undefined` on PureEffect,
Ability, Item, and Species, but I think that's also ugly. Casting to
Move is probably the best approach, so that's what we do now.
For historical reasons, move property definitions have been very blurry
across `EffectData`. Fortunately, recent refactors have made it
possible to put them all where they're supposed to be.
The data/.ts refactor left a few .js files in, which weren't deleted
between 13 and 3 days ago:
c85f5bccb0
Because of this, the corresponding `.ts` files were considered new,
rather than renamed, and changes to the `.js` files got deleted rather
than merged.
Fortunately, this only affected `moves.js`, which has now been manually
re-merged with the changes.
Previously, format bans/unbans were processed in order of "most specific
to least specific".
So `+Giratina-Origin` trumps `-Giratina` trumps `+Uber` trumps
`-All Pokemon`.
And nonstandard reasons (`Unobtainable`, `Past`, `CAP`, etc) were
slotted between `Uber` and `All Pokemon`.
This has the unfortunate effect that if a base ruleset allows a certain
normally-banned category of Pokémon, you can't use `-All Pokemon` to
whitelist a list of Pokémon.
Moving nonstandard reasons to lowest precedence once again allows
`-All Pokemon` to be used as intended.
Custom Game is intended to be a "choose your own rules" format. It's usually pretty easy to tell if a
rule is being followed or not (a level 500 Pokémon is rather conspicuous) but EVs are generally
considered a secret.
For this reason, I've added a message for a discrepancy in EV use: one player adhering to the 510 EV
limit, and the other player not adhering to it.
This message is specific to Debug Mode (which Custom Game is, by default), which already leaks some
minor information, anyway.
To avoid information leaks completely, use Custom Rules:
https://github.com/smogon/pokemon-showdown/blob/master/config/CUSTOM-RULES.md
Frankenstein checkJs-Typescript with globals derps out and lets this
kind of thing slide, but without `hit` (which is only assigned the
line below) you can't cast to ActiveMove.
Apparently the teambuilder still defaults nicknames to full species
names, instead of base names as you might expect. This will have to be
fixed later...
Renames:
- .status -> .effect
- .statusData -> .state
- .thing -> .effectHolder
`thing` was always a really weird "I don't know what to call this"
variable name, but it's been renamed `effectHolder`, which should be
much clearer. `status` -> `effect` is I think the last remnant of old
PS code which called all effects "statuses". `statusData` -> `state`,
on the other hand, is the very first step in an initiative to calling
less things "data".
This allows OMs like Cross Evolution to use nicknames of other species
in `onValidateSet`.
Enforcement also now generates an error message, instead of silently
changing the name.
I also made it such that unbans are no longer inherited. This makes it simpler to follow Smogon's system of tier transitivity, and suspect tests without suspect ladders.
Pokemon that are not available in-game are now consolidated into `isNonstandard`. 'Past' indicates that the Pokemon no longer works in the current generation. 'Unobtainable' indicates that the Pokemon works but can only be obtained through hacking.
Moves that are not available in-game are now consolidated into `isNonstandard`. 'Past' indicates that the item no longer works in the current generation. 'Unobtainable' indicates that the item works but can only be obtained through hacking.
Items that are not available in-game are now consolidated into `isNonstandard`. 'Past' indicates that the item no longer works in the current generation. 'Unobtainable' indicates that the item works but can only be obtained through hacking.
Credit to @lusamine for testing many of these items in Sw/Sh.
This removes the redundant 'SwitchOut' code, and continues to ensure
that switching and dragging share as much code as possible, which
should help avoid bugs where they previously were different for no
reason.
Regression caused by: 47b55f96bc
`Battle#dragIn` used to run the `SwitchOut` event among other functions
but were accidentally left off in the refactor. This commit adds them back.
The main bug caused by this is Natural Cure not curing status aliments when
phased out by Roar.
dragIn and switchIn being two separate functions is a weird historical
quirk that leads to inconsistencies in implementation.
The only reason they need to be separated is a Mold Breaker quirk:
1da65efb12
(This is now done with an `if` statement.)
This should fix a lot of Roar/Whirlwind mechanics issues from `dragIn`
being on outdated mechanics compared to `switchIn`.
`activeTurns` was previously a horrible hack, used for "first full turn
only" effects like Speed Boost as well as "first move action" effects
like Fake Out.
In addition to being a huge hazard for API users such as OMs, this also
means weird bugs such as Speed Boost not working if you get hit by
Sky Drop on your first turn.
This commit fixes them by splitting these counters into two - an
`activeTurns` counter for Speed Boost, and an `activeMoveActions`
counter for Fake Out.
Move targets are now intended to be +1 +2 +3 for foes. The old syntax
of using 1 2 3 is still supported, but is not recommended.
(The old syntax will still be used in the old client, but the Preact
client will support the new syntax going forward.)
This makes the difference between move number and move target
clearer.
This also fixes the Conversion 2 ambiguity (although for backwards
compatibility, we do still need to special-case it).
Four years ago, Slayer95 added an error for invalid data files.
c1e452ea59 (diff-498e7bc80cf67d246be8aa3f2bbbb653R88)
To bypass the try/catch, he returned the error, and then checked for
the result being `instanceof Error`.
Three years ago, I refactored `tryRequire` to `loadDataFile` and moved
the `MODULE_NOT_FOUND` check from outside the function to inside it.
2604780ec5
But I didn't notice the `return new Error` pattern, so I didn't update
that to the modern pattern, so error checking has been broken ever
since.
"TS4053: Return type of public method from exported class has or is
using name 'Nature' from external module but cannot be named."
PS misses out on these errors because its TSC is dump in checkJS
mode, but if you ever try to emit with TSC it will type check things
properly.
- add support to the RandomPlayerAI for Dynamaxing
- add support to ExhaustiveRunner for Gigantamax Pokemon
- simplify range logic in RandomPlayerAPI
- handle crash from toID (needed by data/scripts.js) and Config
(needed if a Battle takes long enough to potentially allow for
requesting ties) globals not being defined
- mark Gen 8 formats as runnable by the runners
This is mostly just a follow up to #6342.
`prefer-optional-chaining` was turned on and fixed in every location it
complained in. The transformed function [0] looks expensive from a
glance but from skimming through the replaced sites it doesn't appear
to be ran in any important place, so it should be OK.
The linter improvements are:
- Increase linter performance
- Make `full-lint` and `lint` write to different caches so we
avoid overwriting their caches since they're different configs
- Change husky's hook to `npm run lint` so as to write to the
same cache
- Remove `@typescript-eslint/eslint-plugin-tslint` which is
essentially a wrapper to TSLint because the rules aren't worth
running another linter
- Convert `.eslintrc.json` and `.eslintrc-syntax.json` to two spaces
rather than four tabs to respect PS' `.editorconfig`
- Rename `fulllint` to `full-lint` to ease spelling it
[0] - https://pastie.io/mmtxpf.js (prettified)
Dragon Darts has a variety of mechanics that I don't care to fully
write unit tests for, but this commit should track its in-game
implementation much more closely.
If anyone still has a Dragon Darts interaction that this implementation
handles incorrectly, they should confront me about it.
Fixes#6279
This new protocol spec resolves ambiguities in cases where multiple
message types would be valid (no more wondering if an ability
activation is `-activate` or `-ability`, no more wondering if a
blocked attack is `-fail` or `-block` or `-immune` or `-activate`). It
also better matches the client's `data/text.js`.
Previously, battle queue stuff was just strewn around `battle.ts`.
This gives it a new home: `battle-queue.ts`.
This was intended to make `battle.ts` slightly more tractable, although
the difference is so small that maybe I shouldn't bother. Oh, well,
every little bit helps.
This is a really hacky implementation of Emergency Exit, but Emergency
Exit itself is a huge mess on cart, too.
Our previous implementation:
- activated Emergency Exit at AfterMoveSecondary timing for move damage
- activated Emergency Exit immediately after dealing any other damage
This new one:
- activates Emergency Exit only in three situations:
- right after AfterMoveSecondary timing, for move damage
- right after DamagingHit timing, for DamagingHit residual damage
(Rough Skin, Iron Barbs, Rocky Helmet)
- right after the switch update, for switch-hazard residual damage
(Stealth Rock, Spikes)
- does not otherwise activate (so Substitute, Hail, Toxic, etc no
longer activate Emergency Exit)
This should much accurately simulate Emergency Exit behavior, including
most famously timing it after healing berries after hazards, as
documented in:
https://www.smogon.com/forums/threads/pokemon-sun-moon-battle-mechanics-research.3586701/#post-7075354Fixes#6309
Fixes#6346
The `AfterDamage` event has been replaced with `DamagingHit`, which
which happens for damaging moves after secondaries.
The `AfterHit` event has also been moved after `DamagingHit`, to make
sure Knock Off still procs after Rocky Helmet.
`AfterHit` is no longer a valid event on `secondary` and `self` blocks,
because it's meaningless in those blocks, anyway. All `self.onAfterHit`
and `secondary.onAfterHit` handlers have been moved to `onHit`, which
should have the same timing in practice.
- Healing Wish is not consumed if the Pokemon switching in
has full health and no status condition.
- Being statused with full health will consume the Healing Wish.
- It does not trigger on damage after switching in.
- The effect will be consumed if an injured Pokemon is swapped
into a slot with an active Healing Wish by Ally Switch.
This adds a `boosts` property to items that runs in `useItem`.
This allows it to be added to `datasearch` or similar plugins.
The item activation messages are now as accurate as in-game.
The Gem activation message is also consolidated in `useItem`.
Check whether the move is a max move. If it isn't, then resolve the choice as usual. Otherwise, do not add the move to the queue, and let the runDynamax mechanic handle move resolution.
Added regression test to check for focus punch message in both dynamaxed and regular use
- `Obtainable` and `Team Preview` are now part of `Standard`
- `minSourceGen: 8` is now a part of `-Unreleased` (which is part of
`Obtainable`) in Gen 8. Instead, it's NatDex that overrides it with
`minSourceGen: 1`. This allows `!Standard, Standard NatDex` and
`!Standard NatDex, Standard` to work as intended.
- Duplicate rules are now checked for (does not apply to subrules, so
multiple inheritance is still possible)
- It is now possible to inherit `minSourceGen` from rules.
Custom rules can now use whitelists instead of blacklists.
Whitelist rules look like:
`- all moves, + Metronome`
(Metronome Battle does not use this ruleset currently, because its
scripted check displays a better error message than a whitelist rule,
which can't actually display the whitelist as of the current
implementation.)
This merges the Glitch and Pokestar tags into a new Unobtainable tag that defines Pokemon that are only obtainable through hacking (such as Floette-Eternal and Missingno.). These Pokemon are legal in Hackmons of their specific generation only. Custom is used in future gens instead of Past because of National Dex legality.
New research shows that only Zacian-Crowned and Zamazenta-Crowned are unobtainable out-of-battle. So, reverting the validateForme changes and hardcoding it in BH instead of using Obtainable Formes.
- Cherrim should revert if given a Utility Umbrella in Sun.
- Castform shouldn't keep transforming if it holds a Utility Umbrella.
- Leaf guard Utility Umbrella check works but is just inconsistent placement.
- Sun/Rain affected recovery moves should heal 50% with Utility Umbrella.
- Solar moves power should halve in sand or hail even with Utility Umbrella.
- Weather Ball should double in power if Magic Room blocks Utility Umbrella.
Struggle is now coded as a locked move, meaning you can't use Z-moves,
mega, or dynamax if you're forced to Struggle.
In addition, Dynamax undisables all moves for its duration.
Fixes#6088
`Dex.installFormat` has been deprecated and removed. Formats are now
directly created and cached by our unit test framework. This should
lead to fewer weird bugs.
Keldeo-R is not a battle forme and is possible to hack without Secret Sword, unlike most other formes. It should be restricted by the rule that prevents hacks and not the rule that validates battle formes. This is mostly relevant for Hackmons.
- In gen 8, Silvally is able to enter battles in different types if it doesn't have RKS System (i.e. it doesn't require a Memory).
- In gen 8, formes that transform in battle are no longer able to start in that forme (relevant to BH).
We now track `baseMaxhp`, the pre-Dynamax max HP. We also have a new
function `getUndynamaxedHP` for use by moves that use it (famously,
Endeavor).
- `baseStoredStats` is unused outside of the mouseover stats display.
I updated its implementation to reflect this.
- Power Construct doesn't have a defined behavior during Dynamax. I
ended up implementing an approximation of what it should probably do.
- Endeavor, Pain Split, Super Fang, and Nature's Madness now work on
undynamaxed HP.
- Moves that deal or heal percentage damage now do it based on
undynamaxed max HP, other than G-Max Finale.
Fixes#6131Fixes#6087
This adds new properties `isUnreleased: 'Past'` and
`unreleasedHidden: 'Past'`, which mark a Pokémon or Hidden Ability as
released in past gens, but not in the current gen. This allows them
to be banned in present-gen-only formats, but not in past-gen-transfer
formats.
We have a new command:
`./pokemon-showdown simulate-battle --replay`
which will extract the omniscient log from an input log.
Remember: debugging is as easy as running `simulate-battle` and pasting
an input log. `--replay` will just make the output easier to read.
Pokemon that are holding an Item that enables Mega Evolution, Primal Revision, or the use of a Z-Move cannot Dynamax. A Rayquaza that can Mega Evolve also cannot Dynamax.
Also fixes an alias loop with the national dex format/ruleset.
In Generation 8, a Pokemon's speed updates dynamically. Meaning that it can move sooner than expected if its speed is modified by something such as tailwind or swift swim. This is different from past generations where the Pokemon's updated speed would only take effect the next turn.
Specifically we now check the battle.canDynamax method when
notifying a player about their pokemon's eligibility to dynamax.
This enforces the fact that pokemon that are transformed into
dynamax ineligible pokemon cannot dynamax themselves.
As a result of this change the pokemon.canDynamax flag is unnessecary
and has been refactored to a side.canDynamax flag. All pokemon specific
dynamax checks should use the battle.canDynamax method.
`item.itemUser` replaces `item.zMoveUser`, and is a new field
representing a list of possible users of an item, for items that are
restricted to specific species.
`item.zMoveUser` is a base forme for items that affect every forme, and
a forme name otherwise (forme name is currently only used for
`forcedForme` uses).
Arceus is a weird case. Both generic Z crystals and Plates, while
having unique effects on Arceus, also have effects on other Pokémon.
For this reason, Arceus isn't listed as an `itemUser` of either of
these item types - use-cases that want this should also check
`item.forcedForme`.
This is mostly intended to be useful to move-searching and custom
rules (like NatDex, which will only allow past-gen items associated
with removed species).
Like gmaxPower, Z-move powers mostly follow a formula, which can be
applied to newer moves.
(In the future, we can save some bytes by not listing the powers.)
PS apparently doesn't have gen-accurate Ability data for Pokémon in
Gen 3 that gained Abilities between Gen 3 and Gen 4 (like Pidgeot
still has Tangled Feet in Gen 3), but that will have to be left for
a future commit.
- Centiskorch was misspelled in formats-data, causing a crash in the
egg validator
- A few validation errors were due to Gen 6 not inheriting from Gen 7,
Gen 7 not having a scripts file, and Gen 8 having a gen of 7
- Intimidate (Gen 7) wasn't inheriting from Intimidate (Gen 8), giving
it no name, causing a few validation errors
(Technically not a build error, but I also added Keen Eye to the list
of Intimidate immunities, as reported by SadisticMystic.)
- A lot of tests relied on Teleport always failing; these have been
switched to Gen 7 or swapped Teleport for Celebrate
- Inverse Mod suddenly stopped working; its implementation was a huge
hack and I can't figure out what went wrong, so I've switched it to
using the same system the other mod tests use. It's still a huge
hack, but I don't have the free time to fix it right now.
PS already tracks which evolution level an egg move or event pokemon
learns a move from, but apparently this was not tracked for DW moves.
This fixes a compatibility interaction between DW Marill and Azurill
moves.
This happened because the father checker was simplistic enough
that it didn't think to check Duskull for Pain Split, since
Dusclops learns it in future gens.
- Tyranitar egg moves are fixed
- Staravia egg moves are now properly supported
(9742ecf62f was a hack that caused the Tyranitar problem)
- Some Pokemon evolve by having a move in their learnset (like Piloswine
with Ancient Power). These can only carry three other moves from their
prevo, because the fourth move must be the evo move. This restriction
doesn't apply to gen 6+ eggs, which can get around the restriction with
the relearner.
Fixes#2287
(Except Shiftry and friends, but those are already tracked in
`rulesets:obtainablemoves`.)
Previously, we split gen 2-5 egg move validation into two phases,
`checkLearnset` where we searched for a valid father, and
`reconcileLearnset` where we made sure the father could learn the move
combination.
Egg move validation has now been completely moved out of these
functions and into `validateSource`, which calls `findEggMoveFathers`.
The new algorithm no longer requires `C` moves to be hardcoded into
`learnsets.js`, now doing a more thorough check validation for the
father's move combination. This should be slower than before, but
net performance should be massively improved due to two other
optimizations in this refactor:
- We no longer do any father-searching if the moveset can be obtained
any other way - in particular, this means no more father validation
in gen 6+ where all egg move combinations are legal anyway.
- We only check fully-evolved pokemon as fathers (because anything a
prevo can learn, its evos can learn, too - yes, we remember to make
exceptions for Salazzle, Combee, and future-gen evos)
In addition, `/learn` should now provide significantly better
information for egg move breeding, since it uses a more thorough check
instead of the validator's short-circuiting the moment it finds a valid
father.
This also improves some baby-only move validation, specifically fixing
the issue with Seismic Toss Charm Chansey.
- Repealing rules now always works, regardless of rule order
(Fixes AAA validation)
- Fix a check for egg move hidden ability validation
(Fixes a Gen 4 Dragon Dance Charizard set)
- Always ban AG when banning Uber
(Fixes allowing Rayquaza-Mega in lower tiers)
- Fix ability validation in Let's Go
- Fix valid-move-combo dexsearch
In most other similar systems, like TeamValidator, we use `thing.dex` instead of having it extend `ModdedDex`. Battle has always extended `ModdedDex`, though. This changes Battle to match the others.
This should fix an issue with `Battle.data` not being cached.
This also frees up Battle to extend ObjectReadWriteStream<string> in a future update.
* Refactor validator
This is a major refactor intended to make the default rules easier to
understand, and also easier for OMs to bypass.
Removed rules:
- `Pokemon`: This is now `-Nonexistent`. Its previous name was intended
to be interpreted as "simulate the Pokémon games exactly, and only
allow what they allow". The new name should make it clearer that it
mainly bans CAPs and other nonexistent Pokémon and functionality.
- `-Illegal`: This is now `Obtainable` (see below).
- `Allow CAP`: This is now `+CAP`. Instead of having a hardcoded rule,
OMs can now be manually whitelist any pokemon/item/etc or group of
them, overriding `-Nonexistent`.
- `Ignore Illegal Abilities`: This is now `!Obtainable Abilities` (see
below).
`Obtainable` was previously `-Illegal`, and does the same thing: Makes
sure you have a regular Pokémon game with only Pokémon that can be
obtained without hacking.
But instead of being a ban, it's now a rule that does nothing by
itself, except contain more rules:
- `Obtainable Moves`
- `Obtainable Abilities`
- `Obtainable Formes`
- `Obtainable Misc`
- `-Nonexistent`
- `-Unreleased`
This allows OMs to piecemeal repeal and unban any of these individual
rules, instead of the previous approach of unbanning them all and
manually reimplementing every single validation you wanted to keep.
* Refactor PokemonSources into a class
This mostly just makes a lot of the weirder checks in the validator
substantially more readable.
This also renames `lsetData` to `setSources`, which should also help
readability.
* Validate Bottle Cap HP types
Fixes an issue reported here:
https://github.com/Zarel/Pokemon-Showdown/issues/5742#issuecomment-533850288
* Fix several move validation issues
Fixes#5742
We have a new MoveSource type: R for Restricted. R moves work like
level-up/tutor/TM moves, except you're limited to one R move.
- Shedinja move stolen from Ninjask in Gen 3-4 are now R moves instead
of event moves. This allows them to coexist with Nincada egg moves.
- Necrozma-DW/DM now inherit moves/events from Necrozma (like Rotom,
but with event validation). This allows them to be shiny.
- Pokemon can now get egg moves from their own evolutions. This fixes
some Tyrogue, Charmander, and Treecko sets mentioned in #5742
- Some more C moves were added, fixing some Hitmontop and Chatot sets
mentioned in #5742
* Improve ability/move compatibility validator
- New ability ratings
- Improve move pools
- Allow non-status moves to be re-rolled if rejected (this fixes all undesired move set combinations)
- Update move & ability rejections
- New item possibilities
0|1|H|S saves minimal space over the ability ID and requires parsers have the data files, in addition to limiting the ability to search abilities in the teambuilder. Similar, gender can be elided most of the time and just chosen randomly if not specified.