In particular, it only activates after all hits in a multi-hit move are performed, and
it won't activate if the move is boosted by Sheer Force.
This commit also implements the interactions of Emergency Exit
with Eject Button and Red Card, and adds tests.
This makes gen 7 the default mod, updates the tests to match, and fixes
the corresponding build error.
Note that this only changes the default Tools mod, the default Formats
mod is now gen6. gen7 must be specified by name in a format, for that
format to be a gen 7 format.
Sometimes mods would mess up if they were loaded in the wrong order.
Specifically, some autogenerated properties of e.g. moves need to be
recalculated for mods.
Anyway, the entire cache system is replaced with a newer, faster,
slightly-more-memory-intensive-but-only-slightly cache system, which
no longer has these kinds of loading order issues.
Battle is now an ES6 class... mostly... it's complicated.
Battle's inheritance system has always been a mess. I tried to redo it
in a sensible way but it caused nondeterministic test failures. Not
even kidding; different things would fail each time I ran tests, even
without code changes. I'll investigate closer later, but this refactor
makes it use ES6 classes with only a small amount of hacking, which is
good enough. It is, at the very least, simpler than the previous mess.
BattleEngine.Battle.construct has been renamed BattleEngine.construct.
Tools will be renamed to Dex soon, which is why the code inside Tools
is calling itself "Dex" now, but right now we're just refactoring its
internal code and not officially renaming it yet.
In the meantime, Tools is now an ES6 Class.
A long-standing bug in learnset loading order (the one
test/chat-plugins/datasearch.js tests for) has finally been fixed, so
Tools.includeMods() is no longer necessary to accurately access modded
data.
Tools.mod has been split into Tools.mod(modid) and
Tools.format(format). The issue of Tools.mod being ambiguous about
whether it's passed a mod or a format hasn't been a _bug_ for a while,
but this is still more readable.
Other renames include:
Tools#isLoaded -> Tools#dataLoaded
Tools.includeMods() -> Tools.includeModData()
Tools.preloadMods() -> Tools.includeMods()
Tools.preloadedMods -> Tools.modsLoaded
Tools.moddedTools -> Tools.dexes
Do not just rename your calls of Tools.includeMods() to
Tools.includeModData(). With the learnset loading bug fixed, there's
no reason to use it unless you need direct access to
Tools.dexes[...].data for some reason (you don't, just use
Tools.mod(...).data)
simulator.js doesn't actually contain the simulator, but is really just
an implementation of battles in the RoomGame interface.
Renames:
`Simulator.Battle` -> `Rooms.RoomBattle`
`Simulator.BattlePlayer` -> `Rooms.RoomBattlePlayer`
`Simulator.SimulatorManager` -> `Rooms.SimulatorManager`
`Simulator.SimulatorProcess` -> `Rooms.SimulatorProcess`
`Simulator.create` -> no longer exists, use `new Rooms.RoomBattle(...)`
Replacing direct references to the arguments object of functions with rest
parametres prevents the function from being deoptimized while still allowing
use of arbitrary arguments. This may also fix some minor memory leaks related
to mishandling the arguments object.
We had a lot of discussion in Dev and a somewhat-close poll, but in
the end "Chat" was a better name than "Messages", and also has the
advantage of being shorter (which is nice for Chat.html and
Chat.plural which should be short).
The following functions have been renamed:
- Tools.html to CommandParser.html
- Tools.plural to CommandParser.plural
- Tools.escapeHTML to CommandParser.escapeHTML
- Tools.toDurationString to CommandParser.toDurationString
- Tools.toTimeStamp to CommandParser.toTimestamp
(notice the lowercase 's')
This is in preparation for a rename of Tools to Dex (by removing the
non-dex-related functions) and a rename of CommandParser to either
Messages or Chat.
Before, an options object containing properties and values to be used
was how decorated instances of the class would be created. This meant
the constructor could assign anything you feel like to `this`. Rather
than that, the constructor now assigns a strict set of values, and
methods are redefined in subclasses.
Basic unit tests were added to test if they could be written for after
the final refactor to fix the other memory leak here.
User#games no longer retains games; it instead gets them from
Rooms(roomid).game.
The Trivia tests needed to be fixed for fidelity to continue passing.
Connection#rooms, previously a null-prototype roomid:room Object,
is now Connection#inRooms, a roomid Set.
This, incidentally, makes it stop retaining rooms, which may make the
GC's job easier and may also lead to unexpected bugs if we get
inconsistent state (we often do get inconsistent state, so look
forward to that!)
The rename is mostly to put it in line with the new User#inRooms,
and for ease of greppability without running into Rooms.rooms.
Part 1 of the rewrite for the entire plugin
This is the rewrite of the classes and commands that handle running
trivia games. Several bugs that happened when running trivia games were
fixed, and unit tests were added to help keep them gone.
Updated remaining Primal Weathers to the new APIs.
Updated misleading test cases relating to base power of moves in
Desolate Land / Primordial Sea.
Increased coverage on weather tests.
- Implements `skip` choice, which acts as a placeholder in the player
choices. This is relevant to double-KOs, since in-game you are allowed
to specify switch-ins in any order.
Among the added tests, are included:
- A skipped test for an edge case in which usage of Reflect Type
causes a typing information leak via the presence/absence of the
"maybe-trapped" warning and cancel prevention.
- Two skipped tests related to partial decisions functionality.
- Basically, support is added only for `move` requests here, and
behind a flag (`battle.supportsPartialDecision`).
- Switching is mostly supported, except for the multiple-KOs case.
- Team Preview needs a rework in order to enable this feature.
Among the newly added rules, there are quite a few intended to enforce
compliance of CONTRIBUTING.md-blessed idioms, as well as ensure
safe usage of classes and constant bindings.
We are also now enforcing usage of early return in commands.js,
which has 100% compliance as of fd2c45c.
This fixes its interaction with Clear Smog because Hit handlers for
moves always activate before all other global event handlers.
Removed the Hit event from the list of events stopped by Mold Breaker
variants as there are no abilities that would be negated by it that
use that handler.
The ModifyMove singleEvent for moves always runs before the
larger event that triggers an ability's event handler and
take precedence over Normalize, so we code exceptions in
Normalize to not change the type in those situations.
Conveniently, all the moves that change type right now are
defaulted to Normal-type, and since Normalize technically
won't change the type of any Normal-type move, we're using
that as the guideline for our exception.
BattlePokemon#runImmunity is now two functions, runImmunity and
runStatusImmunity.
The split is helpful because: 1. NegateImmunity only applies to type
immunities, and 2. Immunity only applies to status immunities and
Ground immunities.
Ground immunities are now entirely handled hardcoded in isGrounded.
This overall doesn't have a noticeable impact on performance, but
it makes certain things behave more predictably, and correctly
shows the ability activation for Levitate, so I assume that means it's
a net positive. I hope I at least improved readability...
The unwieldy system that is typesData is now removed, and is replaced by
the array `types` and the string `addedType`, which track the same amount
of information in a much more efficient way. (Roost is now hardcoded, but
let's not talk about that.)
Incidentally, this now roughly matches client, which tracks typechange
and typeadd as volatiles.
This allows us to remove ModifyPokemon, which overall provides a 10%
performance increase. I was hoping it'd be more substantial, but oh well.
Now that nodejs/node#3072 is mostly fixed, we can finally start using
Node 4+ features.
This refactor:
- uses arrow functions where appropriate
Note that arrow functions still aren't used in Mocha, where `this`
is sometimes meaningful.
This also removes the need for .bind() nearly everywhere, as well
as the `self = this` trick.
- refactors Validator and Connection into ES6 classes
- no longer uses Array#forEach for iterating arrays
We strongly prefer for (let i = 0; i < arr.length; i++) because of
performance reasons. Most forEaches have been replaced with for..of,
though, which is 5x slower than the long-form loop but 2x faster
than forEach, which is good enough outside of most inner loops.
The only exception is tournaments, which is due for a more invasive
refactor soon anyway.
Curse now correctly updates what target it asks for when the user
changes type.
The only remaining targeting issue is when the user changes to
Ghost-type mid-turn in Doubles.
In-game, you can see your opponent's pokemon represented as balls, with
statused pokemon being dark balls. Because of this, light balls are
clearly not statused, which allows you to know when a pokemon has
Natural Cure.
The only exception is in Doubles/Triples, where multiple pokemon that
are statused but could have Natural Cure switch out at the same time,
but not all of them have Natural Cure: it's not possible to know which
pokemon had Natural Cure.
This exception is now handled correctly.
Fixes#1452
Previously, include('./sockets.js') and include('./app.js') would
automatically spawn listener processes.
Now, you have to actually use .listen() to spawn listener processes.
This makes the testing framework simpler, since it no longer needs an
ugly hack to suppress spawning socket processes, and also makes it
easier for the ./pokemon-showdown "binary" to pass a port to app.js.
./pokemon-showdown will now also install dependencies if necessary.
Specifically, Users.users, Users.connections, and Users.pastUsers
are now ES6 Maps. In theory, this should be a minor performance
upgrade, but we still need to profile to make sure.
This is a huge refactor that's a half-scratch rewrite of simulator.js.
Everything seems to be working so far, but with such a huge change,
I wouldn't be surprised if something went wrong.
JSHint's ES6 support is shaky, and its development has stalled as of late.
Since ESLint can do by itself both JSHint and JSCS' jobs, this commit replaces them.
Gulp and its related dependencies are also hereby removed.
Previously moves like Leech Seed incremented residualdmg when used by 1,
but this doesn't actually happen in the game. Instead, an actual game
uses a flag to store toxic poisoning flag, and when it's not specified,
these statuses always dealt 1/16 of full HP.
This fixes the issue where the sequence of moves (Toxic followed by Leech
Seed) was dealing 1/16, 3/16, and 4/16 of full HP in residual damage,
instead of 1/16, 2/16, and 3/16.
Implemented a new priorityEvent function that is set to abort when any
event handler returns a non-undefined result, unlike runEvent which waits
until all event handlers have run. Set RedirectTarget to use this event.
Changed ability/move priorities for RedirectTarget handlers to fit under
this new paradigm.
Added new Lightning Rod and Storm Drain tests to ensure proper behavior.
- This removes one of the reasons of `sendFor` calls' sometimes failing.
- This also fixes battle logs so that they register the proper end type (forfeit).
Add new function battle.insertQueue that inserts a decision into the
correct position in an already-sorted queue instead of re-sorting. Also,
to prevent code reuse, add new funciton battle.resolvePriority to deal
with shared code between battle.addQueue and battle.insertQueue.
Listing the generation number imitates the style used in PS! format names,
and is clearer on which generation it is than listing games from that gen
(so GSC -> Gen 2, etc)
Steel-types are immune to the poison status in Gen 3+, so wrap it into the
"fail when the opposing Pokemon is immune to the status it sets" and set
up the poison-inflicting status test to check Generation 2.
Spin off Thunder Wave to its own test, and also create a test for Glare to
check its Generation 3 behavior as well.
Some tests had incorrect program flow that was resulting in incorrect
expected behaviors.
Improved the wording on some test descriptions.
Gave some of the Pokemon Shell Armor to negate test failures due to
critical hit messages appearing before the type effectiveness messages.
Added BattlePokemon#isGrounded to check for the grounded-ness of a
Pokemon. Also BattlePokemon#isSemiInvulnerable for whether a Pokemon is
in the first turn of a two-turn move that makes them semi-invulnerable.
Fixed Terrain bugs involving Pokemon in a semi-invulnerable state.
Changed OHKO move check to use BattlePokemon#isSemiInvulnerable, fixing a
graphical bug that would display an immunity message when a Pokemon
attempted an OHKO move on a higher-leveled Pokemon that was being held by
the effect of Sky Drop.
Fixed Misty Terrain bug that was causing Rest and the effect of Yawn to
put Pokemon to sleep.
Fixed Misty Terrain bug that was causing Yawn to fail.
Fixed Electric Terrain bug that was causing Yawn to succeed.
"Sheer Force should eliminate Life Orb recoil in a move with secondary
effects" would always pass even with wrong implementation because the
Sheer Force Pokemon being used was not holding a Life Orb.
Added tests related to Mummy to Sheer Force and Rock Head.
Zygarde's Thousand Arrows will KO Eelektross if it gets a critical hit,
meaning that the Weakness Policy being used to check if the move was
super-effective will not activate. Fixed by initializing the battle with a
seed that does not result in a critical hit from Thousand Arrows.
TryPrimaryHit, originally created for Substitute, is currently
being used for Substitute, gems, and auras. Neither of these
should affect all, foeSide, and allySide moves, so the event no
longer fires in these cases.
Included: Bonus: unit test for Substitute not blocking Stealth Rock
Port 18003 was chosen at random, but the point is not to use the same
port as PS itself is running on.
This might not be the best approach, but it probably at least beats
running it on the port in config.js and conflicting with an active
PS process.
- Streams are merged to make sure that all errors and warnings are reported.
- Adds dev dependencies: `merge-stream` and `lazypipe`.
- Tracks a fork of `gulp-jshint` to fix https://github.com/spalger/gulp-jshint/issues/88