Compare commits

..

71 Commits

Author SHA1 Message Date
schmidtc1
7c7408d14a
Update freezy_frost.test.ts
Remove js file extension
2024-09-11 22:02:37 -04:00
schmidtc1
9959a0c3e6
Merge branch 'beta' into freezyfrostbug 2024-09-11 21:59:31 -04:00
Madmadness65
6decd918e5
[Enhancement] Implement Tera-based form changes (Ogerpon and Terapagos) (#4147)
* Add Tera-based form changes

* Make teraType property private
2024-09-11 21:47:41 -04:00
Lylian BALL
8195373824
[Move] Add Retaliate double damage condition (#1831)
* Add retaliate double damage condition

* undo override changes

* add death history and bug fix where retaliate didn't work after 10 turns

* delete the unnecassary log

* optimization

* made some corrections

* add retaliate test as draft

* add retaliate test

* Update src/test/moves/retaliate.test.ts (delete log)

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>

* remove submodule

* Update src/test/moves/retaliate.test.ts

Co-authored-by: schmidtc1 <62030095+schmidtc1@users.noreply.github.com>

* update retaliate test

* Update src/test/moves/retaliate.test.ts

Co-authored-by: schmidtc1 <62030095+schmidtc1@users.noreply.github.com>

* update unit test

* remove wide lens for retaliate test

* Update src/test/moves/retaliate.test.ts

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>

* Update src/battle.ts

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>

* Update src/test/moves/retaliate.test.ts

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>

* Update src/test/moves/retaliate.test.ts

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>

* optimization

* Fix indentation

* Use default values

* Add parentheses for clarity

* Update src/battle.ts

Co-authored-by: schmidtc1 <62030095+schmidtc1@users.noreply.github.com>

* Update src/battle.ts

Co-authored-by: schmidtc1 <62030095+schmidtc1@users.noreply.github.com>

* Update src/data/move.ts

Co-authored-by: schmidtc1 <62030095+schmidtc1@users.noreply.github.com>

* Update src/phases/faint-phase.ts

Co-authored-by: schmidtc1 <62030095+schmidtc1@users.noreply.github.com>

* Update src/phases/faint-phase.ts

Co-authored-by: schmidtc1 <62030095+schmidtc1@users.noreply.github.com>

* bug on import

---------

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
Co-authored-by: schmidtc1 <62030095+schmidtc1@users.noreply.github.com>
Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com>
2024-09-11 21:31:57 -04:00
NightKev
91d266ea74
[Bug] Burning Bulwark, King's Shield, Obstruct and Silk Trap no longer protect against status moves. (#4106)
* Obstruct et al no longer protect against status moves

* Remove `.js` from import

Co-authored-by: ImperialSympathizer <110984302+ben-lear@users.noreply.github.com>

* Add tsdocs for new/modified classes

* List relevant moves in tsdocs

---------

Co-authored-by: ImperialSympathizer <110984302+ben-lear@users.noreply.github.com>
2024-09-11 21:31:38 -04:00
NightKev
951b568590
[Documentation] Add some tsdocs to move.ts, mark rollout and iceball (P) (#4099)
* Add some tsdocs to `move.ts`, some misc cleanup

* Mark Rollout and Ice Ball as partial
2024-09-11 21:05:43 -04:00
flx-sta
18dc1029b7
[Misc] Update issue/feature template (#4148)
* simplify bug-report form. Add `Triage` label to bug & feature form

* Add repro textfield to bug form

* Fix typo

---------

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
2024-09-11 21:01:16 -04:00
Mumble
f294f034aa
[Bug] Run History displays Pokemon that have their natures changed during the run (#4149)
* Nature mints... spaghetti...

* Update src/ui/run-info-ui-handler.ts

Co-authored-by: MokaStitcher <54149968+MokaStitcher@users.noreply.github.com>

* No effect when no items

---------

Co-authored-by: frutescens <info@laptop>
Co-authored-by: MokaStitcher <54149968+MokaStitcher@users.noreply.github.com>
2024-09-11 21:00:26 -04:00
NightKev
fec218b747
[Refactor] setTypeIcons explicitly handles null, mark it as such (#4155) 2024-09-11 20:59:57 -04:00
NightKev
d4cd74c8b7
[P2 Bug] Baddy Bad shouldn't activate Reflect if the target uses Protect, make gravity and water/mud sport ignore protect(#4180) 2024-09-11 20:58:21 -04:00
Amani H.
a6d5fc66f2
[Balance] Disable Eviolite for G-Max Pokémon (#4184)
* [Balance] Disable Eviolite for G-Max Pokémon

* Add Documentation
2024-09-11 20:56:58 -04:00
chaosgrimmon
50a7500561
[Sprite] Fix animated Cursola (#4186)
* [Sprite] Index Cursola exp

* [Sprite] Index shiny Cursola exp

* [Sprite] Update exp Cursola variant palette
2024-09-11 19:46:38 -04:00
Jannik Tappert
b33d86a1db
[BUG] Make Tate & Liza have seeded randomness #4175 2024-09-11 13:55:13 -07:00
NightKev
ce9a75f074
Replace vi.fn() with () => null whenenver possible (#4182) 2024-09-11 13:54:42 -07:00
Lugiad
89dac46dfc
[Localization] Localization batch - [Not meant to be merged until last minute] (#4127)
Co-authored-by: sodam <66295123+sodaMelon@users.noreply.github.com>
Co-authored-by: José Ricardo <josefleury@discente.ufg.br>
Co-authored-by: Chapybara-jp <charlie.beer@hotmail.com>
Co-authored-by: Asdar <asdargmng@gmail.com>
Co-authored-by: Niccolò <123510358+NicusPulcis@users.noreply.github.com>
Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com>
Co-authored-by: Enoch <enoch.jwsong@gmail.com>
Co-authored-by: DanStevensonx <114961842+DanStevensonx@users.noreply.github.com>
Co-authored-by: Yonmaru40 <47717431+40chyan@users.noreply.github.com>
Co-authored-by: SangaraSorama <100420976+SangaraSorama@users.noreply.github.com>
2024-09-11 13:46:26 -07:00
Frederico Santos
abb133e253
Merge pull request #4167 from DayKev/beta
Synchronize beta with main
2024-09-11 15:38:23 +01:00
NightKev
9f82d796d3 Merge branch 'main' into beta 2024-09-11 07:29:18 -07:00
Leo Kim
e657322294
[Enhancement] Update instruction for gamepad in run history UI (#4053)
* update instruction for pad in run history UI

* move getGamepadType function to ui.ts

* Update src/ui/ui.ts

Co-authored-by: Adrian T. <68144167+torranx@users.noreply.github.com>

---------

Co-authored-by: Adrian T. <68144167+torranx@users.noreply.github.com>
2024-09-10 23:45:53 -04:00
Amani H.
4808c07cf9
[Hotfix] Fix System Data Conversion Failure 2 (#4159) 2024-09-10 23:05:48 +01:00
flx-sta
e17bf592c2
[Bug] Use silent mode during tests (unless debugging!) + test workflow optimization (#4154)
* add :silent to all tests

but disable it if the runner is in debug mode!

* fix: use `--silent` instead of `:silent`

Cause the previous was npm scrpt specific (whops)

* remove env and replace with logic in each call

* reduce redundancy by checking out once

* move pre-test into `needs` after `checkout`

* use cache approach in pre-test

* add node.js install step to `setup` job

* WIP: setup -> pre-test -> all other tests

with using cache

* use matrix approach for tests

* fix matrix approach for tests

* fix wrong use of env var in `run-test-template.yml`

* test: out-comment `run-tests` to see whats wrong

* test: see if this works

* let's try using matrix again...

* make `node-version` input a string

* remove `node-version` input for now

* test: without a matrix fornow

* change usage of reuseable workflow call

* fix call of matrix.project

* try using working-dir

* try setup for pre-tests

* remove `runs-on` from run-tests

* fix some identations for run-tests

* add pre-test as requirement for running tests

* use `1` instead of `'1'` to check `runner.debug`

* add `options` input. Possible fix for debug = not silent

* try again...

* not as an ENV but inside

* move 2nd ${{ !runner.debug && '--silent' }} check into test-template

* fix printing `false` instead of empty-string on runner-debug check

* try a yml array approach

* test running with file include path

* make `project` always `main` for now

* remove all extra vitest workspaces

* adopt `shards` workflow in vitest

* fix workflow reference in tests.yml

* add missing `$` in test-shard-template.yml`

* chore: fix vitest.config.ts after merge

man.. cant trust these machines

* make `project` a variable. try to use inputs on job names

* adjust `test-shard-template` job name
2024-09-10 22:13:42 +01:00
flx-sta
14ace40634
[Misc] eslint rule to prevent .js imports (#4160)
* add `eslint-plugin-import-x` module

* add import eslint rules

* remove .js extensions

* rename account.spec to account.test

* move fontFace.setup into `setupFiles`

instead of importing it in `vitest.setup.ts`
2024-09-10 22:34:50 +02:00
MokaStitcher
d1b058fe3e
[UI] fix candy upgrade icon not updating after purchasing eggs (#4153) 2024-09-10 14:00:50 -04:00
AJ Fontaine
150ab3d1b2
[UI/UX] Make "CH-CHING!" sound when unlocking passive (#4151)
* Make "CH-CHING!" sound when unlocking passive

* Remove unused parameters in line above sound
2024-09-10 11:54:23 -04:00
Amani H.
bd4729b4c5
[Hotfix] Fix Lapsing Modifiers Not Rolling (#4152) 2024-09-10 16:53:40 +01:00
PigeonBar
5bf21a4f75
[Bug] Fix rare egg move and species rates for Manaphy eggs (#4125) 2024-09-10 10:15:07 -04:00
Madmadness65
4b8083211a
[P3 Bug] Fix Transform SFX not playing on quiet form changes (#4144) 2024-09-10 10:13:16 -04:00
MokaStitcher
9c4c19b5fb
[UI Bug] Fix HA icon not always showing in egg summary screen (#4150) 2024-09-10 10:12:17 -04:00
James Diefenbach
7dd1832072
[Hotfix] fix UI transition causing unusual freezes after egg summary shown (#4126)
* console logs n stuff

* fix bad ui transition for egg summary freeze bug (logs included)

* cleanup egg lapse phase

* touchup

* add back removed whitespace

* remove console logs

---------

Co-authored-by: James Diefenbach <z5421232@ad.unsw.edu.au>
2024-09-10 14:23:13 +01:00
Amani H.
ebb09dda34
[Hotfix] Fix Lures Refreshing on Reload (#4146) 2024-09-10 10:37:23 +01:00
Raidette
a919b9c0af
[Move] Implement After You (#1789)
* Complete after you implementation (no localization)

* reset override changes

* Remove hardcoded English text, add tests

* Fix test

* Make sure phases occur in the correct order

* fix after-you issues

- fix i18n interpolation ot state "target name" and not "pokemon name" as the target takes the offer, not the user
- fix some tsdocs
- add override to apply
- update scene.findPhase to be able to use generic types. Add tsdocs

* add move-trigger.afterYou for DE

* fix after_you.test.ts

---------

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com>
2024-09-09 14:35:04 -07:00
Adrian T.
e959595471
[Test] Fix throat chop and gorilla tactics tests (#4140) 2024-09-09 16:03:29 -04:00
Jannik Tappert
d9a8448c6e
[Enhancement] Added the ability to localize the tera type hover text (#4138) 2024-09-09 15:57:07 -04:00
Adrian T.
a82d64b5b5
[Ability] Implement Gorilla Tactics (#4051)
* fully implement gorilla tactics

* fix atk increase

* update oversight

* add showAbility param

* fix postmerge

* fix postmerge

* update tests
2024-09-09 15:41:53 -04:00
Brandon Bay
9317093044
[Enhancement] [UI/UX] Add ability and passive tooltips to starter select screen (#4023)
* Add ability and passive tooltips to starter select screen

* Remove explicit casts to BattleScene

* Increase tooltip size, reverse y when necessary, and always show passive tooltip

* Add ability name to tooltip title and persist tooltips between Pokemon

* Use vi function mocks
2024-09-09 15:07:00 -04:00
Adrian T.
9afab182e9
[Test] Remove obsolete splash_only (#4139) 2024-09-09 15:02:11 -04:00
Adrian T.
401568609b
[Dev] Add imports, Handle kebab-case fileName argument in test boilerplate script (#4072)
* add imports, handle kebab-case fileName argument

* fix spacing
2024-09-09 13:00:26 -04:00
Taylor Le Lievre
8df7422e8f
[Bug] Primal weather no longer persists if last mon dies to indirect damage (#3492)
* Fixed Delta Stream remaining active when last mon dies to indirect damage

* Rebasing changes

* Linting fix

* Combined if statements

* Changed params to optional

* Added unit test

* Apply suggestions from code review

* Fix test and remove `.js` from import

---------

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
2024-09-09 12:59:58 -04:00
NightKev
11d912bad8
[Dev] Make OPP_MOVESET_OVERRIDE fully override the enemy's moveset (#4062)
* Make `OPP_MOVESET_OVERRIDE` fully override the enemy's moveset

* Update tests with new override behavior

* Fix tests

* Fix another test

* Move overrides no longer required to be arrays

* Remove `SPLASH_ONLY` test utility variable

* Update moveset override helper functions

* Missed some tests
2024-09-09 12:55:11 -04:00
Adrian T.
c59f6edf36
[Move] Implement Power Shift (#4083)
* fully implement power shift

* cleanup
2024-09-09 12:54:31 -04:00
Leo Kim
80e347840d
[Bug] Fix line spacing in level up stats and move info in Japanese (#4095) 2024-09-09 12:54:17 -04:00
NightKev
89b33466a9
[Test] Fix Safeguard test that relied on a now-fixed bug (#4098) 2024-09-09 12:53:45 -04:00
Lugiad
3d01e905df
[Localization][UI/UX] Clean up of unused localized images (#4110)
* Delete public/images/ui/legacy/summary_moves_effect_de.png

* Delete public/images/ui/legacy/summary_moves_effect_es.png

* Delete public/images/ui/legacy/summary_moves_effect_fr.png

* Delete public/images/ui/legacy/summary_moves_effect_it.png

* Delete public/images/ui/legacy/summary_moves_effect_pt-BR.png

* Delete public/images/ui/legacy/summary_moves_effect_zh-CN.png
2024-09-09 12:53:22 -04:00
Adrian T.
3c05237b2e
[Move] Fully implement Throat Chop (#4115)
* fully implement throat chop

* add linkcode in docs

* address comments

* update test
2024-09-09 12:52:20 -04:00
José Ricardo
a88b989939
[Localization] [pt_BR] Updated some translations (#4131) 2024-09-09 12:50:47 -04:00
Chapybara-jp
e84fe8c24e
[Localisation] [JA] Translated/updated spacing in several files, fixed Ice Face bug (#4129)
* Update ability-trigger.json

* Update ability.json

* Update arena-flyout.json

* Update arena-tag.json

* Update battle.json

* Update fight-ui-handler.json

* Update berry.json

* Update menu.json

* Update party-ui-handler.json

* Update starter-select-ui-handler.json

* Update tutorial.json

* Update move.json

* Update battle.json

* Update arena-flyout.json

* Update arena-flyout.json

* Update arena-tag.json

* Update party-ui-handler.json

* Update settings.json
2024-09-09 12:50:30 -04:00
Mumble
26eb63cf67
[Refactor] Cleaning up Learn move phase (#3672)
* Learn Move Phase rewrite

* Typedocs

* messages with confirm do not need an extra button press no more

* Added Documentation

* This does not work

* so sad

* Some updates

* Eslint issues + clean up

* Additions to handle learning during evolution + test fixes

* some more checks

* Update src/overrides.ts

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>

* Update src/test/phases/learn-move-phase.test.ts

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>

* Added new function and updated tests

* Fixed bracketing and added parameter types

* Added Sketch to the conditional

* Added some fixes. Weird stuff going on.

* Whoops

* async implementation done

* Update src/phases/learn-move-phase.ts

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>

* Made showText=> summary a promise

* adapt learn-move-phase to `async-await`

* await add

---------

Co-authored-by: frutescens <info@laptop>
Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com>
2024-09-09 09:11:46 -07:00
AJ Fontaine
16fc3a87b7
Fix usedTMs crash (#4132) 2024-09-09 14:07:05 +01:00
Adrian T.
f5bf766ff7
[Move] Fully implement Tar Shot (#4043) 2024-09-09 00:42:53 -07:00
innerthunder
c710f85fd3
Fix Pokemon.isTrapped only checking enemy Pokemon for trapping abilities (#4124) 2024-09-09 14:19:59 +08:00
flx-sta
39b6a72517
[Bug] Fix #762: All Pokemon become invisible when capturing then switching with your only pokemon that was not fainted (#4025)
* fix #762 by using slotIndex to add to party

for now the new pokemon was ALWAYS just pushed to the party array. Now it's put into the slot that was also previously selected as the mon to release

* add docs for `Pokemon.addToParty()`

* add simple tests for addToParty

* update `isBetween` docs. Remove `.js` imports
2024-09-09 01:10:47 -04:00
Adrian T.
06f98f6737
[Bug] Fix console error from undefined stockpilingTag (#4118) 2024-09-08 20:50:47 -07:00
innerthunder
68b956cbe6
[Bug] Fix incorrect defensive properties on Terastallized Pokemon (#4070)
* Fix incorrect defensive properties on Terastallized Pokemon

* Add tests to `effectiveness.test.ts`

* Suppress errors from Tera achievement validation
2024-09-08 20:48:09 -07:00
Mumble
a30201f185
[Hotfix] Retrieving the correct form index for correct cry keys (#4121)
* [DOCS] adding JSDocs to `arena.ts` (#3590)

* adding some docs

* Update src/field/pokemon.ts

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>

* seems like battleStats changed to statStages

* Apply suggestions from code review

editing doc text

Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com>

* Update tsdocs, convert comment to tsdoc in `pokemon.ts`

---------

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com>

* [Bug] Fix scrappy (+ some immunity move and ability) in inverse battle (#4067)

* fix scrappy + etc. update inverse battle test code

* update test code following request from swain

* fix and optimize imports (#4061)

- remove any `.js` extension imports
- remove unncessary dynamic imports of `modifier.ts` file. The file was being imported statically & dynamically. Made it pure static
- increase vite chunk-size warning limit

Co-authored-by: Mumble <171087428+frutescens@users.noreply.github.com>

* returned main

* Fixed cry key

* Revert "[DOCS] adding JSDocs to `arena.ts` (#3590)"

This reverts commit 675e6a0635.

* Revert "[Bug] Fix scrappy (+ some immunity move and ability) in inverse battle (#4067)"

This reverts commit 45af0dd170.

* Revert "fix and optimize imports (#4061)"

This reverts commit e12548cdb0.

---------

Co-authored-by: DustinLin <39450497+DustinLin@users.noreply.github.com>
Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com>
Co-authored-by: Leo Kim <47556641+KimJeongSun@users.noreply.github.com>
Co-authored-by: frutescens <info@laptop>
2024-09-08 22:12:37 -04:00
Amani H.
38cb10ff97
[Hotfix] Fix System Data Conversion Failure (#4123) 2024-09-09 02:50:00 +01:00
Opaque02
93d6375894
Updated all fields (except passwords) to allow for 20 characters (#4119) 2024-09-09 00:57:44 +01:00
Mumble
021f31b589
[Hotfix] Retrieve the right cry when alternate-form Pokemon faint + retrieve the correct sprite key (#4117)
* [DOCS] adding JSDocs to `arena.ts` (#3590)

* adding some docs

* Update src/field/pokemon.ts

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>

* seems like battleStats changed to statStages

* Apply suggestions from code review

editing doc text

Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com>

* Update tsdocs, convert comment to tsdoc in `pokemon.ts`

---------

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com>

* [Bug] Fix scrappy (+ some immunity move and ability) in inverse battle (#4067)

* fix scrappy + etc. update inverse battle test code

* update test code following request from swain

* fix and optimize imports (#4061)

- remove any `.js` extension imports
- remove unncessary dynamic imports of `modifier.ts` file. The file was being imported statically & dynamically. Made it pure static
- increase vite chunk-size warning limit

Co-authored-by: Mumble <171087428+frutescens@users.noreply.github.com>

* Fusion hotfix

* returned main

* Faint cry properly retrieved for non fused Pokemon with forms

* Revert "[DOCS] adding JSDocs to `arena.ts` (#3590)"

This reverts commit b73fd97760.

* Revert "[Bug] Fix scrappy (+ some immunity move and ability) in inverse battle (#4067)"

This reverts commit 31fcbf49f4.

* Revert "fix and optimize imports (#4061)"

This reverts commit d1bd6974e4.

* Fixed sprite key generation

---------

Co-authored-by: DustinLin <39450497+DustinLin@users.noreply.github.com>
Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com>
Co-authored-by: Leo Kim <47556641+KimJeongSun@users.noreply.github.com>
Co-authored-by: frutescens <info@laptop>
2024-09-09 00:03:37 +01:00
Mumble
22c60ab532
[Hotfix][Bug] Retrieves the correct cry for Fused Pokemon (#4116)
* [DOCS] adding JSDocs to `arena.ts` (#3590)

* adding some docs

* Update src/field/pokemon.ts

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>

* seems like battleStats changed to statStages

* Apply suggestions from code review

editing doc text

Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com>

* Update tsdocs, convert comment to tsdoc in `pokemon.ts`

---------

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com>

* [Bug] Fix scrappy (+ some immunity move and ability) in inverse battle (#4067)

* fix scrappy + etc. update inverse battle test code

* update test code following request from swain

* fix and optimize imports (#4061)

- remove any `.js` extension imports
- remove unncessary dynamic imports of `modifier.ts` file. The file was being imported statically & dynamically. Made it pure static
- increase vite chunk-size warning limit

Co-authored-by: Mumble <171087428+frutescens@users.noreply.github.com>

* Fusion hotfix

* Revert "fix and optimize imports (#4061)"

This reverts commit 287d671cfd.

* Revert "[Bug] Fix scrappy (+ some immunity move and ability) in inverse battle (#4067)"

This reverts commit 9fd34c95d5.

* Revert "[DOCS] adding JSDocs to `arena.ts` (#3590)"

This reverts commit 0742efd196.

* typo

* Fixed fusionFaintCry to return correct cry

---------

Co-authored-by: DustinLin <39450497+DustinLin@users.noreply.github.com>
Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com>
Co-authored-by: Leo Kim <47556641+KimJeongSun@users.noreply.github.com>
Co-authored-by: frutescens <info@laptop>
2024-09-08 21:42:11 +01:00
Lugiad
df250c8b90
[Localization] New translations batch locales (Move-disabling effects, abilities triggers, error messages and some misc ajustements) (#4068)
* Update battle.json

* Update battler-tags.json

* Update battle.json

* Update battle.json

* Update battler-tags.json

* Update battle.json

* Update battler-tags.json

* Update battler-tags.json

* Update battle.json

* Update battle.json

* Update battler-tags.json

* Update battler-tags.json

* Update battle.json

* Update battle.json

* Update battler-tags.json

* Update battler-tags.json

* Update battle.json

* Update battle.json

* Update battler-tags.json

* Update battle.json

* Update battle.json

* Update battle.json

* Update battler-tags.json

* Update battle.json

* Update battle.json

* Update src/locales/de/battle.json

Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com>

* Update src/locales/de/battler-tags.json

Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com>

* Update battler-tags.json

* Update src/locales/ko/battle.json

Co-authored-by: sodam <66295123+sodaMelon@users.noreply.github.com>

* Update src/locales/ko/battler-tags.json

Co-authored-by: sodam <66295123+sodaMelon@users.noreply.github.com>

* Update src/locales/it/battle.json

Co-authored-by: Niccolò <123510358+NicusPulcis@users.noreply.github.com>

* Update src/locales/it/battler-tags.json

Co-authored-by: Niccolò <123510358+NicusPulcis@users.noreply.github.com>

* Update menu.json

* Update ability-trigger.json

* Update ability-trigger.json

* Update ability-trigger.json

* Update ability-trigger.json

* Update ability-trigger.json

* Update ability-trigger.json

* Update ability-trigger.json

* Update ability-trigger.json

* Update menu.json

* Update menu.json

* Update menu.json

* Update menu.json

* Update menu.json

* Update menu.json

* Update menu.json

* Update menu.json

* Update src/locales/de/ability-trigger.json

Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com>

* Update src/locales/de/ability-trigger.json

Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com>

* Update src/locales/de/menu.json

Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com>

* Update src/locales/ko/ability-trigger.json

Co-authored-by: Leo Kim <47556641+KimJeongSun@users.noreply.github.com>

* Update src/locales/ko/menu.json

Co-authored-by: Leo Kim <47556641+KimJeongSun@users.noreply.github.com>

* Update src/locales/ko/ability-trigger.json

Co-authored-by: Leo Kim <47556641+KimJeongSun@users.noreply.github.com>

* Update src/locales/ko/menu.json

Co-authored-by: Leo Kim <47556641+KimJeongSun@users.noreply.github.com>

* Update menu.json

* Update ability-trigger.json

* Update ability-trigger.json

* Update ability-trigger.json

* Update ability-trigger.json

* Update ability-trigger.json

* Update ability-trigger.json

* Update menu.json

* Update ability-trigger.json

* Update battle.json

* Update battler-tags.json

* Update src/locales/zh_CN/battle.json

Co-authored-by: Yonmaru40 <47717431+40chyan@users.noreply.github.com>

* Update src/locales/zh_TW/battle.json

Co-authored-by: Yonmaru40 <47717431+40chyan@users.noreply.github.com>

* Update modifier-type.json

* Update modifier-type.json

* Update modifier-type.json

* Update modifier-type.json

* Update modifier-type.json

* Update modifier-type.json

* Update modifier-type.json

* Update modifier-type.json

* Update modifier-type.json

* Update modifier-type.json

* Update modifier-type.json

* Update menu.json

* Update battler-tags.json

* Update battle.json

* Update ability-trigger.json

* Update battler-tags.json

* Update battler-tags.json

* Update battler-tags.json

* Update battler-tags.json

* Update modifier-type.json

* Update menu.json

* Update battle.json

* Update tutorial.json

* Update tutorial.json

* Update egg.json

* Update battle.json

* Update battle.json

* Update tutorial.json

* Update egg.json

* Update modifier-type.json

* Update modifier-type.json

* Update modifier-type.json

* Update modifier-type.json

* Update modifier-type.json

* Update challenges.json

* Update src/locales/ko/modifier-type.json

Co-authored-by: Enoch <enoch.jwsong@gmail.com>

* Update src/locales/ko/modifier-type.json

Co-authored-by: Enoch <enoch.jwsong@gmail.com>

* Update src/locales/ja/battle.json

Co-authored-by: Chapybara-jp <charlie.beer@hotmail.com>

* Update src/locales/ja/menu.json

Co-authored-by: Chapybara-jp <charlie.beer@hotmail.com>

* Update src/locales/ja/modifier-type.json

Co-authored-by: Chapybara-jp <charlie.beer@hotmail.com>

* Update src/locales/ja/modifier-type.json

Co-authored-by: Chapybara-jp <charlie.beer@hotmail.com>

* Update src/locales/ja/modifier-type.json

Co-authored-by: Chapybara-jp <charlie.beer@hotmail.com>

* Update dialogue.json

* Update dialogue-misc.json

* Update dialogue-final-boss.json

* Update dialogue-double-battle.json

* Update ability-trigger.json

* Update achv.json

* Update arena-tag.json

* Update battle.json

* Update battler-tags.json

* Update command-ui-handler.json

* Update menu.json

* Update modifier-type.json

* Update modifier.json

* Update move-trigger.json

* Update pokemon-info-container.json

* Update pokemon-info.json

* Update splash-messages.json

* Update status-effect.json

* Update tutorial.json

* Update voucher.json

* Update weather.json

* Update ability-trigger.json

* Update src/locales/de/modifier-type.json

Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com>

* Update src/locales/de/modifier-type.json

Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com>

* Update modifier-type.json

* Update bgm-name.json

* Update bgm-name.json

* Update src/locales/it/menu.json

Co-authored-by: Niccolò <123510358+NicusPulcis@users.noreply.github.com>

* types_ja.png update

* Apply suggestions from code review

Co-authored-by: Yonmaru40 <47717431+40chyan@users.noreply.github.com>

---------

Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com>
Co-authored-by: sodam <66295123+sodaMelon@users.noreply.github.com>
Co-authored-by: Niccolò <123510358+NicusPulcis@users.noreply.github.com>
Co-authored-by: Leo Kim <47556641+KimJeongSun@users.noreply.github.com>
Co-authored-by: Yonmaru40 <47717431+40chyan@users.noreply.github.com>
Co-authored-by: Enoch <enoch.jwsong@gmail.com>
Co-authored-by: Chapybara-jp <charlie.beer@hotmail.com>
2024-09-08 13:57:17 +02:00
Mumble
4a98c36427
[Hotfix] Properly whitelisting fused Pokemon that happen to have Pokemon with alt. forms (#4104) 2024-09-08 02:58:24 -04:00
NightKev
55b89e82c7
[Hotfix] Remove extra Roark victory line, fix baton pass i18n in achv.ts (#4103) 2024-09-08 02:46:56 -04:00
James Diefenbach
7ab0bbbd94
[Hotfix] Fix cases where hatched Pokemon don't get an egg move (#4102)
Co-authored-by: James Diefenbach <z5421232@ad.unsw.edu.au>
2024-09-08 02:45:30 -04:00
innerthunder
8082e6dc58
[Hotfix] Fix harsh weather cancelling moves based on base type (#4097) 2024-09-08 02:29:49 -04:00
James Diefenbach
0bdb697077
[Hotfix] Show enemy item icons after egg summary (#4101)
Co-authored-by: James Diefenbach <z5421232@ad.unsw.edu.au>
2024-09-08 02:18:51 -04:00
flx-sta
2bd07cb84e
fix and optimize imports (#4061)
- remove any `.js` extension imports
- remove unncessary dynamic imports of `modifier.ts` file. The file was being imported statically & dynamically. Made it pure static
- increase vite chunk-size warning limit

Co-authored-by: Mumble <171087428+frutescens@users.noreply.github.com>
2024-09-07 21:37:37 -07:00
Leo Kim
2fc3179bd9
[Bug] Fix scrappy (+ some immunity move and ability) in inverse battle (#4067)
* fix scrappy + etc. update inverse battle test code

* update test code following request from swain
2024-09-07 21:37:14 -07:00
DustinLin
f73a830f77
[DOCS] adding JSDocs to arena.ts (#3590)
* adding some docs

* Update src/field/pokemon.ts

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>

* seems like battleStats changed to statStages

* Apply suggestions from code review

editing doc text

Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com>

* Update tsdocs, convert comment to tsdoc in `pokemon.ts`

---------

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com>
2024-09-07 21:36:47 -07:00
damocleas
a214110030
Voucher Event (#4094)
* Update modifier-type.ts

* Great tier vouch

* Update trainer-victory-phase.ts

* Update trainer-victory-phase.ts

* Update timed-event-manager.ts and loading-scene.ts (#1)

* Update timed-event-manager.ts and loading-scene.ts

* egg-update-zh-cn update

* Update language codes in loading-scene.ts and timed-event-manager.ts

* updated image

---------

Co-authored-by: Frederico Santos <frederico.f.santos@tecnico.ulisboa.pt>
2024-09-08 04:17:02 +01:00
Frederico Santos
9c74a86a10
Merge pull request #4087 from pagefaultgames/beta
Release #4
2024-09-08 04:15:00 +01:00
Amani H.
ffcedfd9a4
[Dev] Save Data Version Migration (#4080)
* Initial Draft

* Successfuly Migration with Vitamins and White Herb

* Apply Session Data Patches Earlier

* Remove Stray `console.log`
2024-09-08 02:40:45 +01:00
Opaque02
b36823af4a
Fixed small RNG misusage (#4092) 2024-09-08 02:33:33 +01:00
James Diefenbach
dfa3993864
Egg summary background touchup (#4091)
* darker egg-summary background

* reset old background for beta

* update egg summary bg

* reset overrides

---------

Co-authored-by: James Diefenbach <z5421232@ad.unsw.edu.au>
2024-09-08 01:32:49 +02:00
450 changed files with 6612 additions and 3733 deletions

View File

@ -1,7 +1,7 @@
name: Bug Report name: Bug Report
description: Create a report to help us improve description: Create a report to help us improve
title: "[Bug] " title: "[Bug] "
labels: ["Bug"] labels: ["Bug", "Triage"]
body: body:
- type: markdown - type: markdown
attributes: attributes:
@ -19,21 +19,12 @@ body:
value: | value: |
--- ---
- type: textarea - type: textarea
id: session-file id: repro
attributes: attributes:
label: Session export file label: Reproduction
description: Open Menu → ManageData → Export Session → Select slot. The file should now be in your `/Downloads` directory. Change the file extension type from `.prsv` to `.txt` (How to [Windows](https://www.guidingtech.com/how-to-change-file-type-on-windows/) | [Mac](https://support.apple.com/guide/mac-help/show-or-hide-filename-extensions-on-mac-mchlp2304/mac) | [iOS](https://www.guidingtech.com/change-file-type-extension-on-iphone/)). description: Describe the steps to reproduce this bug. If applicable attach user/session data at the bottom
placeholder: Focus me and then drop your file here (or use the upload button at the bottom)
validations: validations:
required: false required: true
- type: textarea
id: data-file
attributes:
label: User data export file
description: Open Menu → ManageData → Export Data. The file should now be in your `/Downloads` directory. Change the file extension type from `.prsv` to `.txt` (How to [Windows](https://www.guidingtech.com/how-to-change-file-type-on-windows/) | [Mac](https://support.apple.com/guide/mac-help/show-or-hide-filename-extensions-on-mac-mchlp2304/mac) | [iOS](https://www.guidingtech.com/change-file-type-extension-on-iphone/)).
placeholder: Focus me and then drop your file here (or use the upload button at the bottom)
validations:
required: false
- type: markdown - type: markdown
attributes: attributes:
value: | value: |
@ -60,48 +51,20 @@ body:
attributes: attributes:
value: | value: |
--- ---
- type: dropdown - type: textarea
id: os id: session-file
attributes: attributes:
label: What OS did you observe the bug on? label: Session export file
multiple: true description: Open Menu → ManageData → Export Session → Select slot. The file should now be in your `/Downloads` directory. Change the file extension type from `.prsv` to `.txt` (How to [Windows](https://www.guidingtech.com/how-to-change-file-type-on-windows/) | [Mac](https://support.apple.com/guide/mac-help/show-or-hide-filename-extensions-on-mac-mchlp2304/mac) | [iOS](https://www.guidingtech.com/change-file-type-extension-on-iphone/)).
options: placeholder: Focus me and then drop your file here (or use the upload button at the bottom)
- PC/Windows
- Mac/OSX
- Linux
- iOS
- Android
- Other
validations:
required: true
- type: input
id: os-other
attributes:
label: If other please specify
validations: validations:
required: false required: false
- type: markdown - type: textarea
id: data-file
attributes: attributes:
value: | label: User data export file
--- description: Open Menu → ManageData → Export Data. The file should now be in your `/Downloads` directory. Change the file extension type from `.prsv` to `.txt` (How to [Windows](https://www.guidingtech.com/how-to-change-file-type-on-windows/) | [Mac](https://support.apple.com/guide/mac-help/show-or-hide-filename-extensions-on-mac-mchlp2304/mac) | [iOS](https://www.guidingtech.com/change-file-type-extension-on-iphone/)).
- type: dropdown placeholder: Focus me and then drop your file here (or use the upload button at the bottom)
id: browser
attributes:
label: Which browser do you use?
multiple: true
options:
- Chrome
- Firefox
- Safari
- Edge
- Opera
- Other
validations:
required: true
- type: input
id: browser-other
attributes:
label: If other please specify
validations: validations:
required: false required: false
- type: markdown - type: markdown

View File

@ -1,7 +1,7 @@
name: Feature Request name: Feature Request
description: Suggest an idea for this project description: Suggest an idea for this project
title: "[Feature] " title: "[Feature] "
labels: ["Enhancement"] labels: ["Enhancement", "Triage"]
body: body:
- type: markdown - type: markdown
attributes: attributes:

View File

@ -0,0 +1,30 @@
name: Test Template
on:
workflow_call:
inputs:
project:
required: true
type: string
shard:
required: true
type: number
totalShards:
required: true
type: number
jobs:
test:
name: Shard ${{ inputs.shard }} of ${{ inputs.totalShards }}
runs-on: ubuntu-latest
steps:
- name: Check out Git repository
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install Node.js dependencies
run: npm ci
- name: Run tests
run: npx vitest --project ${{ inputs.project }} --shard=${{ inputs.shard }}/${{ inputs.totalShards }} ${{ !runner.debug && '--silent' || '' }}

View File

@ -15,91 +15,33 @@ on:
types: [checks_requested] types: [checks_requested]
jobs: jobs:
run-misc-tests: # Define a job named "run-tests" pre-test:
name: Run misc tests # Human-readable name for the job name: Run Pre-test
runs-on: ubuntu-latest # Specify the latest Ubuntu runner for the job runs-on: ubuntu-latest
steps:
- name: Check out Git repository # Step to check out the repository
uses: actions/checkout@v4 # Use the checkout action version 4
- name: Set up Node.js # Step to set up Node.js environment
uses: actions/setup-node@v4 # Use the setup-node action version 4
with:
node-version: 20 # Specify Node.js version 20
- name: Install Node.js dependencies # Step to install Node.js dependencies
run: npm ci # Use 'npm ci' to install dependencies
- name: pre-test # pre-test to check overrides
run: npx vitest run --project pre
- name: test misc
run: npx vitest --project misc
run-abilities-tests:
name: Run abilities tests
runs-on: ubuntu-latest
steps: steps:
- name: Check out Git repository - name: Check out Git repository
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
path: tests-action
- name: Set up Node.js - name: Set up Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@v4
with: with:
node-version: 20 node-version: 20
- name: Install Node.js dependencies - name: Install Node.js dependencies
working-directory: tests-action
run: npm ci run: npm ci
- name: pre-test - name: Run Pre-test
run: npx vitest run --project pre working-directory: tests-action
- name: test abilities run: npx vitest run --project pre ${{ !runner.debug && '--silent' || '' }}
run: npx vitest --project abilities
run-items-tests: run-tests:
name: Run items tests name: Run Tests
runs-on: ubuntu-latest needs: [pre-test]
steps: strategy:
- name: Check out Git repository matrix:
uses: actions/checkout@v4 shard: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
- name: Set up Node.js uses: ./.github/workflows/test-shard-template.yml
uses: actions/setup-node@v4 with:
with: project: main
node-version: 20 shard: ${{ matrix.shard }}
- name: Install Node.js dependencies totalShards: 10
run: npm ci
- name: pre-test
run: npx vitest run --project pre
- name: test items
run: npx vitest --project items
run-moves-tests:
name: Run moves tests
runs-on: ubuntu-latest
steps:
- name: Check out Git repository
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install Node.js dependencies
run: npm ci
- name: pre-test
run: npx vitest run --project pre
- name: test moves
run: npx vitest --project moves
run-battle-tests:
name: Run battle tests
runs-on: ubuntu-latest
steps:
- name: Check out Git repository
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install Node.js dependencies
run: npm ci
- name: pre-test
run: npx vitest run --project pre
- name: test battle
run: npx vitest --project battle

View File

@ -20,54 +20,58 @@ const type = args[0]; // "move" or "ability"
let fileName = args[1]; // The file name let fileName = args[1]; // The file name
if (!type || !fileName) { if (!type || !fileName) {
console.error('Please provide both a type ("move", "ability", or "item") and a file name.'); console.error('Please provide a type ("move", "ability", or "item") and a file name.');
process.exit(1); process.exit(1);
} }
// Convert fileName from to snake_case if camelCase is given // Convert fileName from kebab-case or camelCase to snake_case
fileName = fileName.replace(/([a-z])([A-Z])/g, '$1_$2').toLowerCase(); fileName = fileName
.replace(/-+/g, '_') // Convert kebab-case (dashes) to underscores
.replace(/([a-z])([A-Z])/g, '$1_$2') // Convert camelCase to snake_case
.toLowerCase(); // Ensure all lowercase
// Format the description for the test case // Format the description for the test case
const formattedName = fileName const formattedName = fileName
.replace(/_/g, ' ') .replace(/_/g, ' ')
.replace(/\b\w/g, char => char.toUpperCase()); .replace(/\b\w/g, char => char.toUpperCase());
// Determine the directory based on the type // Determine the directory based on the type
let dir; let dir;
let description; let description;
if (type === 'move') { if (type === 'move') {
dir = path.join(__dirname, 'src', 'test', 'moves'); dir = path.join(__dirname, 'src', 'test', 'moves');
description = `Moves - ${formattedName}`; description = `Moves - ${formattedName}`;
} else if (type === 'ability') { } else if (type === 'ability') {
dir = path.join(__dirname, 'src', 'test', 'abilities'); dir = path.join(__dirname, 'src', 'test', 'abilities');
description = `Abilities - ${formattedName}`; description = `Abilities - ${formattedName}`;
} else if (type === "item") { } else if (type === "item") {
dir = path.join(__dirname, 'src', 'test', 'items'); dir = path.join(__dirname, 'src', 'test', 'items');
description = `Items - ${formattedName}`; description = `Items - ${formattedName}`;
} else { } else {
console.error('Invalid type. Please use "move", "ability", or "item".'); console.error('Invalid type. Please use "move", "ability", or "item".');
process.exit(1); process.exit(1);
} }
// Ensure the directory exists // Ensure the directory exists
if (!fs.existsSync(dir)) { if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true }); fs.mkdirSync(dir, { recursive: true });
} }
// Create the file with the given name // Create the file with the given name
const filePath = path.join(dir, `${fileName}.test.ts`); const filePath = path.join(dir, `${fileName}.test.ts`);
if (fs.existsSync(filePath)) { if (fs.existsSync(filePath)) {
console.error(`File "${fileName}.test.ts" already exists.`); console.error(`File "${fileName}.test.ts" already exists.`);
process.exit(1); process.exit(1);
} }
// Define the content template // Define the content template
const content = `import { Abilities } from "#enums/abilities"; const content = `import { Abilities } from "#enums/abilities";
import { Moves } from "#enums/moves";
import { Species } from "#enums/species";
import GameManager from "#test/utils/gameManager"; import GameManager from "#test/utils/gameManager";
import { SPLASH_ONLY } from "#test/utils/testUtils";
import Phaser from "phaser"; import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, it } from "vitest"; import { afterEach, beforeAll, beforeEach, describe, it, expect } from "vitest";
describe("${description}", () => { describe("${description}", () => {
let phaserGame: Phaser.Game; let phaserGame: Phaser.Game;
@ -87,14 +91,15 @@ describe("${description}", () => {
beforeEach(() => { beforeEach(() => {
game = new GameManager(phaserGame); game = new GameManager(phaserGame);
game.override game.override
.moveset([Moves.SPLASH])
.battleType("single") .battleType("single")
.enemyAbility(Abilities.BALL_FETCH) .enemyAbility(Abilities.BALL_FETCH)
.enemyMoveset(SPLASH_ONLY); .enemyMoveset(Moves.SPLASH);
}); });
it("test case", async () => { it("test case", async () => {
// await game.classicMode.startBattle(); // await game.classicMode.startBattle([Species.MAGIKARP]);
// game.move.select(); // game.move.select(Moves.SPLASH);
}, TIMEOUT); }, TIMEOUT);
}); });
`; `;

View File

@ -1,7 +1,7 @@
import tseslint from '@typescript-eslint/eslint-plugin'; import tseslint from '@typescript-eslint/eslint-plugin';
import stylisticTs from '@stylistic/eslint-plugin-ts' import stylisticTs from '@stylistic/eslint-plugin-ts'
import parser from '@typescript-eslint/parser'; import parser from '@typescript-eslint/parser';
// import imports from 'eslint-plugin-import'; // Disabled due to not being compatible with eslint v9 import importX from 'eslint-plugin-import-x';
export default [ export default [
{ {
@ -11,7 +11,7 @@ export default [
parser: parser parser: parser
}, },
plugins: { plugins: {
// imports: imports.configs.recommended // Disabled due to not being compatible with eslint v9 "import-x": importX,
'@stylistic/ts': stylisticTs, '@stylistic/ts': stylisticTs,
'@typescript-eslint': tseslint '@typescript-eslint': tseslint
}, },
@ -39,7 +39,8 @@ export default [
}], }],
"space-before-blocks": ["error", "always"], // Enforces a space before blocks "space-before-blocks": ["error", "always"], // Enforces a space before blocks
"keyword-spacing": ["error", { "before": true, "after": true }], // Enforces spacing before and after keywords "keyword-spacing": ["error", { "before": true, "after": true }], // Enforces spacing before and after keywords
"comma-spacing": ["error", { "before": false, "after": true }] // Enforces spacing after comma "comma-spacing": ["error", { "before": false, "after": true }], // Enforces spacing after comma
"import-x/extensions": ["error", "never", { "json": "always" }], // Enforces no extension for imports unless json
} }
} }
] ]

200
package-lock.json generated
View File

@ -28,6 +28,7 @@
"@vitest/coverage-istanbul": "^2.0.4", "@vitest/coverage-istanbul": "^2.0.4",
"dependency-cruiser": "^16.3.10", "dependency-cruiser": "^16.3.10",
"eslint": "^9.7.0", "eslint": "^9.7.0",
"eslint-plugin-import-x": "^4.2.1",
"jsdom": "^24.0.0", "jsdom": "^24.0.0",
"lefthook": "^1.6.12", "lefthook": "^1.6.12",
"phaser3spectorjs": "^0.0.8", "phaser3spectorjs": "^0.0.8",
@ -2505,6 +2506,19 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/doctrine": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
"integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"esutils": "^2.0.2"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/eastasianwidth": { "node_modules/eastasianwidth": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
@ -2687,6 +2701,155 @@
"url": "https://opencollective.com/eslint" "url": "https://opencollective.com/eslint"
} }
}, },
"node_modules/eslint-import-resolver-node": {
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
"integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==",
"dev": true,
"license": "MIT",
"dependencies": {
"debug": "^3.2.7",
"is-core-module": "^2.13.0",
"resolve": "^1.22.4"
}
},
"node_modules/eslint-import-resolver-node/node_modules/debug": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"ms": "^2.1.1"
}
},
"node_modules/eslint-plugin-import-x": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.2.1.tgz",
"integrity": "sha512-WWi2GedccIJa0zXxx3WDnTgouGQTtdYK1nhXMwywbqqAgB0Ov+p1pYBsWh3VaB0bvBOwLse6OfVII7jZD9xo5Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/utils": "^8.1.0",
"debug": "^4.3.4",
"doctrine": "^3.0.0",
"eslint-import-resolver-node": "^0.3.9",
"get-tsconfig": "^4.7.3",
"is-glob": "^4.0.3",
"minimatch": "^9.0.3",
"semver": "^7.6.3",
"stable-hash": "^0.0.4",
"tslib": "^2.6.3"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0"
}
},
"node_modules/eslint-plugin-import-x/node_modules/@typescript-eslint/scope-manager": {
"version": "8.5.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.5.0.tgz",
"integrity": "sha512-06JOQ9Qgj33yvBEx6tpC8ecP9o860rsR22hWMEd12WcTRrfaFgHr2RB/CA/B+7BMhHkXT4chg2MyboGdFGawYg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.5.0",
"@typescript-eslint/visitor-keys": "8.5.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/eslint-plugin-import-x/node_modules/@typescript-eslint/types": {
"version": "8.5.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.5.0.tgz",
"integrity": "sha512-qjkormnQS5wF9pjSi6q60bKUHH44j2APxfh9TQRXK8wbYVeDYYdYJGIROL87LGZZ2gz3Rbmjc736qyL8deVtdw==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/eslint-plugin-import-x/node_modules/@typescript-eslint/typescript-estree": {
"version": "8.5.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.5.0.tgz",
"integrity": "sha512-vEG2Sf9P8BPQ+d0pxdfndw3xIXaoSjliG0/Ejk7UggByZPKXmJmw3GW5jV2gHNQNawBUyfahoSiCFVov0Ruf7Q==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"@typescript-eslint/types": "8.5.0",
"@typescript-eslint/visitor-keys": "8.5.0",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
"minimatch": "^9.0.4",
"semver": "^7.6.0",
"ts-api-utils": "^1.3.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/eslint-plugin-import-x/node_modules/@typescript-eslint/utils": {
"version": "8.5.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.5.0.tgz",
"integrity": "sha512-6yyGYVL0e+VzGYp60wvkBHiqDWOpT63pdMV2CVG4LVDd5uR6q1qQN/7LafBZtAtNIn/mqXjsSeS5ggv/P0iECw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
"@typescript-eslint/scope-manager": "8.5.0",
"@typescript-eslint/types": "8.5.0",
"@typescript-eslint/typescript-estree": "8.5.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0"
}
},
"node_modules/eslint-plugin-import-x/node_modules/@typescript-eslint/visitor-keys": {
"version": "8.5.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.5.0.tgz",
"integrity": "sha512-yTPqMnbAZJNy2Xq2XU8AdtOW9tJIr+UQb64aXB9f3B1498Zx9JorVgFJcZpEc9UBuCCrdzKID2RGAMkYcDtZOw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.5.0",
"eslint-visitor-keys": "^3.4.3"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/eslint-scope": { "node_modules/eslint-scope": {
"version": "8.0.2", "version": "8.0.2",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz",
@ -3143,6 +3306,19 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/get-tsconfig": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.0.tgz",
"integrity": "sha512-Pgba6TExTZ0FJAn1qkJAjIeKoDJ3CsI2ChuLohJnZl/tTU8MVrq3b+2t5UOPfRa4RMsorClBjJALkJUMjG1PAw==",
"dev": true,
"license": "MIT",
"dependencies": {
"resolve-pkg-maps": "^1.0.0"
},
"funding": {
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
}
},
"node_modules/glob-parent": { "node_modules/glob-parent": {
"version": "6.0.2", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
@ -4854,6 +5030,16 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/resolve-pkg-maps": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
}
},
"node_modules/reusify": { "node_modules/reusify": {
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
@ -5069,6 +5255,13 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/stable-hash": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.4.tgz",
"integrity": "sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==",
"dev": true,
"license": "MIT"
},
"node_modules/stackback": { "node_modules/stackback": {
"version": "0.0.2", "version": "0.0.2",
"resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
@ -5460,6 +5653,13 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/tslib": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
"integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
"dev": true,
"license": "0BSD"
},
"node_modules/type-check": { "node_modules/type-check": {
"version": "0.4.0", "version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",

View File

@ -32,6 +32,7 @@
"@vitest/coverage-istanbul": "^2.0.4", "@vitest/coverage-istanbul": "^2.0.4",
"dependency-cruiser": "^16.3.10", "dependency-cruiser": "^16.3.10",
"eslint": "^9.7.0", "eslint": "^9.7.0",
"eslint-plugin-import-x": "^4.2.1",
"jsdom": "^24.0.0", "jsdom": "^24.0.0",
"lefthook": "^1.6.12", "lefthook": "^1.6.12",
"phaser3spectorjs": "^0.0.8", "phaser3spectorjs": "^0.0.8",

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -3,44 +3,36 @@
"bcb9be": "ae4c95", "bcb9be": "ae4c95",
"f9f2fc": "ffc0e5", "f9f2fc": "ffc0e5",
"7b787c": "793d6d", "7b787c": "793d6d",
"e1dfe2": "e88cc5", "dcd9dd": "e88cc5",
"d0cfd0": "ce6bac", "c9c0ce": "ce6bac",
"b8b4ba": "d7d2f6", "cbc2d1": "d7d2f6",
"938f94": "b465b9", "938f94": "b465b9",
"6c7275": "d3ffff", "fbf2ff": "d3ffff",
"9362e6": "80a4ff", "e66294": "80a4ff",
"fcfcfc": "fcfcfc", "c6bbcb": "a7e6e5",
"4a494e": "a7e6e5", "ffa4c5": "bed5ff",
"c6a4ff": "bed5ff", "7f806a": "4d8894",
"101010": "101010", "a8a0ac": "e88cc5",
"3b3a3f": "4d8894", "7c7a78": "793d6d",
"aeadae": "e88cc5", "bbb4bc": "ce6bac",
"686568": "686568",
"6f6d71": "793d6d",
"b5b4b6": "ce6bac",
"706e6d": "7d7c75",
"af9e9e": "42a2b1" "af9e9e": "42a2b1"
}, },
"2": { "2": {
"bcb9be": "055946", "bcb9be": "055946",
"f9f2fc": "21be70", "f9f2fc": "21be70",
"7b787c": "004140", "7b787c": "004140",
"e1dfe2": "12a169", "dcd9dd": "12a169",
"d0cfd0": "0a7a57", "c9c0ce": "0a7a57",
"b8b4ba": "567f83", "cbc2d1": "567f83",
"938f94": "2b5458", "938f94": "2b5458",
"6c7275": "874059", "fbf2ff": "874059",
"9362e6": "15c05f", "e66294": "15c05f",
"fcfcfc": "fcfcfc", "c6bbcb": "773050",
"4a494e": "773050", "ffa4c5": "8ff3a3",
"c6a4ff": "8ff3a3", "7f806a": "4b1f28",
"101010": "101010", "a8a0ac": "12a169",
"3b3a3f": "4b1f28", "7c7a78": "004140",
"aeadae": "12a169", "bbb4bc": "0a7a57",
"686568": "686568",
"6f6d71": "004140",
"b5b4b6": "0a7a57",
"706e6d": "7d7c75",
"af9e9e": "48c492" "af9e9e": "48c492"
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 799 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 807 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 799 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 800 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 799 B

View File

@ -1,3 +1,3 @@
import BattleScene from "#app/battle-scene.js"; import BattleScene from "#app/battle-scene";
export type ConditionFn = (scene: BattleScene, args?: any[]) => boolean; export type ConditionFn = (scene: BattleScene, args?: any[]) => boolean;

View File

@ -1,4 +1,4 @@
import { type enConfig } from "#app/locales/en/config.js"; import { type enConfig } from "#app/locales/en/config";
import { TOptions } from "i18next"; import { TOptions } from "i18next";
//TODO: this needs to be type properly in the future //TODO: this needs to be type properly in the future

View File

@ -63,7 +63,7 @@ import { Moves } from "#enums/moves";
import { PlayerGender } from "#enums/player-gender"; import { PlayerGender } from "#enums/player-gender";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { UiTheme } from "#enums/ui-theme"; import { UiTheme } from "#enums/ui-theme";
import { TimedEventManager } from "#app/timed-event-manager.js"; import { TimedEventManager } from "#app/timed-event-manager";
import i18next from "i18next"; import i18next from "i18next";
import { TrainerType } from "#enums/trainer-type"; import { TrainerType } from "#enums/trainer-type";
import { battleSpecDialogue } from "./data/dialogue"; import { battleSpecDialogue } from "./data/dialogue";
@ -2193,8 +2193,14 @@ export default class BattleScene extends SceneBase {
return true; return true;
} }
findPhase(phaseFilter: (phase: Phase) => boolean): Phase | undefined { /**
return this.phaseQueue.find(phaseFilter); * Find a specific {@linkcode Phase} in the phase queue.
*
* @param phaseFilter filter function to use to find the wanted phase
* @returns the found phase or undefined if none found
*/
findPhase<P extends Phase = Phase>(phaseFilter: (phase: P) => boolean): P | undefined {
return this.phaseQueue.find(phaseFilter) as P;
} }
tryReplacePhase(phaseFilter: (phase: Phase) => boolean, phase: Phase): boolean { tryReplacePhase(phaseFilter: (phase: Phase) => boolean, phase: Phase): boolean {
@ -2763,20 +2769,20 @@ export default class BattleScene extends SceneBase {
const keys: string[] = []; const keys: string[] = [];
const playerParty = this.getParty(); const playerParty = this.getParty();
playerParty.forEach(p => { playerParty.forEach(p => {
keys.push("pkmn__" + p.species.getSpriteId(p.gender === Gender.FEMALE, p.species.formIndex, p.shiny, p.variant)); keys.push(p.getSpriteKey(true));
keys.push("pkmn__" + p.species.getSpriteId(p.gender === Gender.FEMALE, p.species.formIndex, p.shiny, p.variant, true)); keys.push(p.getBattleSpriteKey(true, true));
keys.push("cry/" + p.species.getCryKey(p.species.formIndex)); keys.push("cry/" + p.species.getCryKey(p.formIndex));
if (p.fusionSpecies && p.getSpeciesForm() !== p.getFusionSpeciesForm()) { if (p.fusionSpecies) {
keys.push("cry/"+p.getFusionSpeciesForm().getCryKey(p.fusionSpecies.formIndex)); keys.push("cry/"+p.fusionSpecies.getCryKey(p.fusionFormIndex));
} }
}); });
// enemyParty has to be operated on separately from playerParty because playerPokemon =/= enemyPokemon // enemyParty has to be operated on separately from playerParty because playerPokemon =/= enemyPokemon
const enemyParty = this.getEnemyParty(); const enemyParty = this.getEnemyParty();
enemyParty.forEach(p => { enemyParty.forEach(p => {
keys.push(p.species.getSpriteKey(p.gender === Gender.FEMALE, p.species.formIndex, p.shiny, p.variant)); keys.push(p.getSpriteKey(true));
keys.push("cry/" + p.species.getCryKey(p.species.formIndex)); keys.push("cry/" + p.species.getCryKey(p.formIndex));
if (p.fusionSpecies && p.getSpeciesForm() !== p.getFusionSpeciesForm()) { if (p.fusionSpecies) {
keys.push("cry/"+p.getFusionSpeciesForm().getCryKey(p.fusionSpecies.formIndex)); keys.push("cry/"+p.fusionSpecies.getCryKey(p.fusionFormIndex));
} }
}); });
return keys; return keys;

View File

@ -1,5 +1,4 @@
import BattleScene from "./battle-scene"; import BattleScene from "./battle-scene";
import { EnemyPokemon, PlayerPokemon, QueuedMove } from "./field/pokemon";
import { Command } from "./ui/command-ui-handler"; import { Command } from "./ui/command-ui-handler";
import * as Utils from "./utils"; import * as Utils from "./utils";
import Trainer, { TrainerVariant } from "./field/trainer"; import Trainer, { TrainerVariant } from "./field/trainer";
@ -7,6 +6,7 @@ import { GameMode } from "./game-mode";
import { MoneyMultiplierModifier, PokemonHeldItemModifier } from "./modifier/modifier"; import { MoneyMultiplierModifier, PokemonHeldItemModifier } from "./modifier/modifier";
import { PokeballType } from "./data/pokeball"; import { PokeballType } from "./data/pokeball";
import { trainerConfigs } from "#app/data/trainer-config"; import { trainerConfigs } from "#app/data/trainer-config";
import Pokemon, { EnemyPokemon, PlayerPokemon, QueuedMove } from "#app/field/pokemon";
import { ArenaTagType } from "#enums/arena-tag-type"; import { ArenaTagType } from "#enums/arena-tag-type";
import { BattleSpec } from "#enums/battle-spec"; import { BattleSpec } from "#enums/battle-spec";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
@ -38,6 +38,11 @@ export interface TurnCommand {
args?: any[]; args?: any[];
} }
export interface FaintLogEntry {
pokemon: Pokemon,
turn: number
}
interface TurnCommands { interface TurnCommands {
[key: number]: TurnCommand | null [key: number]: TurnCommand | null
} }
@ -69,6 +74,8 @@ export default class Battle {
public playerFaints: number = 0; public playerFaints: number = 0;
/** The number of times a Pokemon on the enemy's side has fainted this battle */ /** The number of times a Pokemon on the enemy's side has fainted this battle */
public enemyFaints: number = 0; public enemyFaints: number = 0;
public playerFaintsHistory: FaintLogEntry[] = [];
public enemyFaintsHistory: FaintLogEntry[] = [];
private rngCounter: number = 0; private rngCounter: number = 0;

View File

@ -1,4 +1,4 @@
import {SettingGamepad} from "#app/system/settings/settings-gamepad.js"; import {SettingGamepad} from "#app/system/settings/settings-gamepad";
import {Button} from "#enums/buttons"; import {Button} from "#enums/buttons";
/** /**

1
src/constants.ts Normal file
View File

@ -0,0 +1 @@
export const PLAYER_PARTY_MAX_SIZE = 6;

View File

@ -1595,8 +1595,8 @@ export class PostAttackAbAttr extends AbAttr {
private attackCondition: PokemonAttackCondition; private attackCondition: PokemonAttackCondition;
/** The default attackCondition requires that the selected move is a damaging move */ /** The default attackCondition requires that the selected move is a damaging move */
constructor(attackCondition: PokemonAttackCondition = (user, target, move) => (move.category !== MoveCategory.STATUS)) { constructor(attackCondition: PokemonAttackCondition = (user, target, move) => (move.category !== MoveCategory.STATUS), showAbility: boolean = true) {
super(); super(showAbility);
this.attackCondition = attackCondition; this.attackCondition = attackCondition;
} }
@ -1624,6 +1624,40 @@ export class PostAttackAbAttr extends AbAttr {
} }
} }
/**
* Ability attribute for Gorilla Tactics
* @extends PostAttackAbAttr
*/
export class GorillaTacticsAbAttr extends PostAttackAbAttr {
constructor() {
super((user, target, move) => true, false);
}
/**
*
* @param {Pokemon} pokemon the {@linkcode Pokemon} with this ability
* @param passive n/a
* @param simulated whether the ability is being simulated
* @param defender n/a
* @param move n/a
* @param hitResult n/a
* @param args n/a
* @returns `true` if the ability is applied
*/
applyPostAttackAfterMoveTypeCheck(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean | Promise<boolean> {
if (simulated) {
return simulated;
}
if (pokemon.getTag(BattlerTagType.GORILLA_TACTICS)) {
return false;
}
pokemon.addTag(BattlerTagType.GORILLA_TACTICS);
return true;
}
}
export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr { export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr {
private stealCondition: PokemonAttackCondition | null; private stealCondition: PokemonAttackCondition | null;
@ -3923,7 +3957,7 @@ export class PostBattleLootAbAttr extends PostBattleAbAttr {
} }
export class PostFaintAbAttr extends AbAttr { export class PostFaintAbAttr extends AbAttr {
applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker?: Pokemon, move?: Move, hitResult?: HitResult, ...args: any[]): boolean {
return false; return false;
} }
} }
@ -3974,7 +4008,7 @@ export class PostFaintClearWeatherAbAttr extends PostFaintAbAttr {
* @param args N/A * @param args N/A
* @returns {boolean} Returns true if the weather clears, otherwise false. * @returns {boolean} Returns true if the weather clears, otherwise false.
*/ */
applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker?: Pokemon, move?: Move, hitResult?: HitResult, ...args: any[]): boolean {
const weatherType = pokemon.scene.arena.weather?.weatherType; const weatherType = pokemon.scene.arena.weather?.weatherType;
let turnOffWeather = false; let turnOffWeather = false;
@ -4022,8 +4056,8 @@ export class PostFaintContactDamageAbAttr extends PostFaintAbAttr {
this.damageRatio = damageRatio; this.damageRatio = damageRatio;
} }
applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker?: Pokemon, move?: Move, hitResult?: HitResult, ...args: any[]): boolean {
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) { if (move !== undefined && attacker !== undefined && move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) { //If the mon didn't die to indirect damage
const cancelled = new Utils.BooleanHolder(false); const cancelled = new Utils.BooleanHolder(false);
pokemon.scene.getField(true).map(p => applyAbAttrs(FieldPreventExplosiveMovesAbAttr, p, cancelled, simulated)); pokemon.scene.getField(true).map(p => applyAbAttrs(FieldPreventExplosiveMovesAbAttr, p, cancelled, simulated));
if (cancelled.value || attacker.hasAbilityWithAttr(BlockNonDirectDamageAbAttr)) { if (cancelled.value || attacker.hasAbilityWithAttr(BlockNonDirectDamageAbAttr)) {
@ -4052,8 +4086,8 @@ export class PostFaintHPDamageAbAttr extends PostFaintAbAttr {
super (); super ();
} }
applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker?: Pokemon, move?: Move, hitResult?: HitResult, ...args: any[]): boolean {
if (!simulated) { if (move !== undefined && attacker !== undefined && !simulated) { //If the mon didn't die to indirect damage
const damage = pokemon.turnData.attacksReceived[0].damage; const damage = pokemon.turnData.attacksReceived[0].damage;
attacker.damageAndUpdate((damage), HitResult.OTHER); attacker.damageAndUpdate((damage), HitResult.OTHER);
attacker.turnData.damageTaken += damage; attacker.turnData.damageTaken += damage;
@ -4711,7 +4745,7 @@ export function applyPostBattleAbAttrs(attrType: Constructor<PostBattleAbAttr>,
} }
export function applyPostFaintAbAttrs(attrType: Constructor<PostFaintAbAttr>, export function applyPostFaintAbAttrs(attrType: Constructor<PostFaintAbAttr>,
pokemon: Pokemon, attacker: Pokemon, move: Move, hitResult: HitResult, simulated: boolean = false, ...args: any[]): Promise<void> { pokemon: Pokemon, attacker?: Pokemon, move?: Move, hitResult?: HitResult, simulated: boolean = false, ...args: any[]): Promise<void> {
return applyAbAttrsInternal<PostFaintAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPostFaint(pokemon, passive, simulated, attacker, move, hitResult, args), args, false, simulated); return applyAbAttrsInternal<PostFaintAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPostFaint(pokemon, passive, simulated, attacker, move, hitResult, args), args, false, simulated);
} }
@ -5597,7 +5631,7 @@ export function initAbilities() {
.bypassFaint() .bypassFaint()
.partial(), .partial(),
new Ability(Abilities.GORILLA_TACTICS, 8) new Ability(Abilities.GORILLA_TACTICS, 8)
.unimplemented(), .attr(GorillaTacticsAbAttr),
new Ability(Abilities.NEUTRALIZING_GAS, 8) new Ability(Abilities.NEUTRALIZING_GAS, 8)
.attr(SuppressFieldAbilitiesAbAttr) .attr(SuppressFieldAbilitiesAbAttr)
.attr(UncopiableAbilityAbAttr) .attr(UncopiableAbilityAbAttr)

View File

@ -107,8 +107,8 @@ export interface TerrainBattlerTag {
* to select restricted moves. * to select restricted moves.
*/ */
export abstract class MoveRestrictionBattlerTag extends BattlerTag { export abstract class MoveRestrictionBattlerTag extends BattlerTag {
constructor(tagType: BattlerTagType, turnCount: integer, sourceMove?: Moves, sourceId?: integer) { constructor(tagType: BattlerTagType, lapseType: BattlerTagLapseType | BattlerTagLapseType[], turnCount: integer, sourceMove?: Moves, sourceId?: integer) {
super(tagType, [ BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.TURN_END ], turnCount, sourceMove, sourceId); super(tagType, lapseType, turnCount, sourceMove, sourceId);
} }
/** @override */ /** @override */
@ -119,7 +119,9 @@ export abstract class MoveRestrictionBattlerTag extends BattlerTag {
const move = phase.move; const move = phase.move;
if (this.isMoveRestricted(move.moveId)) { if (this.isMoveRestricted(move.moveId)) {
pokemon.scene.queueMessage(this.interruptedText(pokemon, move.moveId)); if (this.interruptedText(pokemon, move.moveId)) {
pokemon.scene.queueMessage(this.interruptedText(pokemon, move.moveId));
}
phase.cancel(); phase.cancel();
} }
@ -155,7 +157,52 @@ export abstract class MoveRestrictionBattlerTag extends BattlerTag {
* @param {Moves} move {@linkcode Moves} ID of the move being interrupted * @param {Moves} move {@linkcode Moves} ID of the move being interrupted
* @returns {string} text to display when the move is interrupted * @returns {string} text to display when the move is interrupted
*/ */
abstract interruptedText(pokemon: Pokemon, move: Moves): string; interruptedText(pokemon: Pokemon, move: Moves): string {
return "";
}
}
/**
* Tag representing the "Throat Chop" effect. Pokemon with this tag cannot use sound-based moves.
* @see {@link https://bulbapedia.bulbagarden.net/wiki/Throat_Chop_(move) | Throat Chop}
* @extends MoveRestrictionBattlerTag
*/
export class ThroatChoppedTag extends MoveRestrictionBattlerTag {
constructor() {
super(BattlerTagType.THROAT_CHOPPED, [ BattlerTagLapseType.TURN_END, BattlerTagLapseType.PRE_MOVE ], 2, Moves.THROAT_CHOP);
}
/**
* Checks if a {@linkcode Moves | move} is restricted by Throat Chop.
* @override
* @param {Moves} move the {@linkcode Moves | move} to check for sound-based restriction
* @returns true if the move is sound-based
*/
override isMoveRestricted(move: Moves): boolean {
return allMoves[move].hasFlag(MoveFlags.SOUND_BASED);
}
/**
* Shows a message when the player attempts to select a move that is restricted by Throat Chop.
* @override
* @param {Pokemon} pokemon the {@linkcode Pokemon} that is attempting to select the restricted move
* @param {Moves} move the {@linkcode Moves | move} that is being restricted
* @returns the message to display when the player attempts to select the restricted move
*/
override selectionDeniedText(pokemon: Pokemon, move: Moves): string {
return i18next.t("battle:moveCannotBeSelected", { moveName: allMoves[move].name });
}
/**
* Shows a message when a move is interrupted by Throat Chop.
* @override
* @param {Pokemon} pokemon the interrupted {@linkcode Pokemon}
* @param {Moves} move the {@linkcode Moves | move} that was interrupted
* @returns the message to display when the move is interrupted
*/
override interruptedText(pokemon: Pokemon, move: Moves): string {
return i18next.t("battle:throatChopInterruptedMove", { pokemonName: getPokemonNameWithAffix(pokemon) });
}
} }
/** /**
@ -167,7 +214,7 @@ export class DisabledTag extends MoveRestrictionBattlerTag {
private moveId: Moves = Moves.NONE; private moveId: Moves = Moves.NONE;
constructor(sourceId: number) { constructor(sourceId: number) {
super(BattlerTagType.DISABLED, 4, Moves.DISABLE, sourceId); super(BattlerTagType.DISABLED, [ BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.TURN_END ], 4, Moves.DISABLE, sourceId);
} }
/** @override */ /** @override */
@ -178,7 +225,7 @@ export class DisabledTag extends MoveRestrictionBattlerTag {
/** /**
* @override * @override
* *
* Ensures that move history exists on `pokemon` and has a valid move. If so, sets the {@link moveId} and shows a message. * Ensures that move history exists on `pokemon` and has a valid move. If so, sets the {@linkcode moveId} and shows a message.
* Otherwise the move ID will not get assigned and this tag will get removed next turn. * Otherwise the move ID will not get assigned and this tag will get removed next turn.
*/ */
override onAdd(pokemon: Pokemon): void { override onAdd(pokemon: Pokemon): void {
@ -207,7 +254,12 @@ export class DisabledTag extends MoveRestrictionBattlerTag {
return i18next.t("battle:moveDisabled", { moveName: allMoves[move].name }); return i18next.t("battle:moveDisabled", { moveName: allMoves[move].name });
} }
/** @override */ /**
* @override
* @param {Pokemon} pokemon {@linkcode Pokemon} attempting to use the restricted move
* @param {Moves} move {@linkcode Moves} ID of the move being interrupted
* @returns {string} text to display when the move is interrupted
*/
override interruptedText(pokemon: Pokemon, move: Moves): string { override interruptedText(pokemon: Pokemon, move: Moves): string {
return i18next.t("battle:disableInterruptedMove", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: allMoves[move].name }); return i18next.t("battle:disableInterruptedMove", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: allMoves[move].name });
} }
@ -219,6 +271,72 @@ export class DisabledTag extends MoveRestrictionBattlerTag {
} }
} }
/**
* Tag used by Gorilla Tactics to restrict the user to using only one move.
* @extends MoveRestrictionBattlerTag
*/
export class GorillaTacticsTag extends MoveRestrictionBattlerTag {
private moveId = Moves.NONE;
constructor() {
super(BattlerTagType.GORILLA_TACTICS, BattlerTagLapseType.CUSTOM, 0);
}
/** @override */
override isMoveRestricted(move: Moves): boolean {
return move !== this.moveId;
}
/**
* @override
* @param {Pokemon} pokemon the {@linkcode Pokemon} to check if the tag can be added
* @returns `true` if the pokemon has a valid move and no existing {@linkcode GorillaTacticsTag}; `false` otherwise
*/
override canAdd(pokemon: Pokemon): boolean {
return (this.getLastValidMove(pokemon) !== undefined) && !pokemon.getTag(GorillaTacticsTag);
}
/**
* Ensures that move history exists on {@linkcode Pokemon} and has a valid move.
* If so, sets the {@linkcode moveId} and increases the user's Attack by 50%.
* @override
* @param {Pokemon} pokemon the {@linkcode Pokemon} to add the tag to
*/
override onAdd(pokemon: Pokemon): void {
const lastValidMove = this.getLastValidMove(pokemon);
if (!lastValidMove) {
return;
}
this.moveId = lastValidMove;
pokemon.setStat(Stat.ATK, pokemon.getStat(Stat.ATK, false) * 1.5, false);
}
/**
*
* @override
* @param {Pokemon} pokemon n/a
* @param {Moves} move {@linkcode Moves} ID of the move being denied
* @returns {string} text to display when the move is denied
*/
override selectionDeniedText(pokemon: Pokemon, move: Moves): string {
return i18next.t("battle:canOnlyUseMove", { moveName: allMoves[this.moveId].name, pokemonName: getPokemonNameWithAffix(pokemon) });
}
/**
* Gets the last valid move from the pokemon's move history.
* @param {Pokemon} pokemon {@linkcode Pokemon} to get the last valid move from
* @returns {Moves | undefined} the last valid move from the pokemon's move history
*/
getLastValidMove(pokemon: Pokemon): Moves | undefined {
const move = pokemon.getLastXMoves()
.find(m => m.move !== Moves.NONE && m.move !== Moves.STRUGGLE && !m.virtual);
return move?.move;
}
}
/** /**
* BattlerTag that represents the "recharge" effects of moves like Hyper Beam. * BattlerTag that represents the "recharge" effects of moves like Hyper Beam.
*/ */
@ -1180,6 +1298,13 @@ export class ProtectedTag extends BattlerTag {
} }
} }
/** Base class for `BattlerTag`s that block damaging moves but not status moves */
export class DamageProtectedTag extends ProtectedTag {}
/**
* `BattlerTag` class for moves that block damaging moves damage the enemy if the enemy's move makes contact
* Used by {@linkcode Moves.SPIKY_SHIELD}
*/
export class ContactDamageProtectedTag extends ProtectedTag { export class ContactDamageProtectedTag extends ProtectedTag {
private damageRatio: number; private damageRatio: number;
@ -1215,7 +1340,11 @@ export class ContactDamageProtectedTag extends ProtectedTag {
} }
} }
export class ContactStatStageChangeProtectedTag extends ProtectedTag { /**
* `BattlerTag` class for moves that block damaging moves and lower enemy stats if the enemy's move makes contact
* Used by {@linkcode Moves.KINGS_SHIELD}, {@linkcode Moves.OBSTRUCT}, {@linkcode Moves.SILK_TRAP}
*/
export class ContactStatStageChangeProtectedTag extends DamageProtectedTag {
private stat: BattleStat; private stat: BattleStat;
private levels: number; private levels: number;
@ -1271,7 +1400,11 @@ export class ContactPoisonProtectedTag extends ProtectedTag {
} }
} }
export class ContactBurnProtectedTag extends ProtectedTag { /**
* `BattlerTag` class for moves that block damaging moves and burn the enemy if the enemy's move makes contact
* Used by {@linkcode Moves.BURNING_BULWARK}
*/
export class ContactBurnProtectedTag extends DamageProtectedTag {
constructor(sourceMove: Moves) { constructor(sourceMove: Moves) {
super(sourceMove, BattlerTagType.BURNING_BULWARK); super(sourceMove, BattlerTagType.BURNING_BULWARK);
} }
@ -1984,7 +2117,38 @@ export class ExposedTag extends BattlerTag {
} }
} }
/**
* Tag that doubles the type effectiveness of Fire-type moves.
* @extends BattlerTag
*/
export class TarShotTag extends BattlerTag {
constructor() {
super(BattlerTagType.TAR_SHOT, BattlerTagLapseType.CUSTOM, 0);
}
/**
* If the Pokemon is terastallized, the tag cannot be added.
* @param {Pokemon} pokemon the {@linkcode Pokemon} to which the tag is added
* @returns whether the tag is applied
*/
override canAdd(pokemon: Pokemon): boolean {
return !pokemon.isTerastallized();
}
override onAdd(pokemon: Pokemon): void {
pokemon.scene.queueMessage(i18next.t("battlerTags:tarShotOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }));
}
}
/**
* Retrieves a {@linkcode BattlerTag} based on the provided tag type, turn count, source move, and source ID.
*
* @param {BattlerTagType} tagType the type of the {@linkcode BattlerTagType}.
* @param turnCount the turn count.
* @param {Moves} sourceMove the source {@linkcode Moves}.
* @param sourceId the source ID.
* @returns {BattlerTag} the corresponding {@linkcode BattlerTag} object.
*/
export function getBattlerTag(tagType: BattlerTagType, turnCount: number, sourceMove: Moves, sourceId: number): BattlerTag { export function getBattlerTag(tagType: BattlerTagType, turnCount: number, sourceMove: Moves, sourceId: number): BattlerTag {
switch (tagType) { switch (tagType) {
case BattlerTagType.RECHARGING: case BattlerTagType.RECHARGING:
@ -2125,6 +2289,12 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: number, source
case BattlerTagType.GULP_MISSILE_ARROKUDA: case BattlerTagType.GULP_MISSILE_ARROKUDA:
case BattlerTagType.GULP_MISSILE_PIKACHU: case BattlerTagType.GULP_MISSILE_PIKACHU:
return new GulpMissileTag(tagType, sourceMove); return new GulpMissileTag(tagType, sourceMove);
case BattlerTagType.TAR_SHOT:
return new TarShotTag();
case BattlerTagType.THROAT_CHOPPED:
return new ThroatChoppedTag();
case BattlerTagType.GORILLA_TACTICS:
return new GorillaTacticsTag();
case BattlerTagType.NONE: case BattlerTagType.NONE:
default: default:
return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId); return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId);

View File

@ -1,18 +1,18 @@
import * as Utils from "../utils"; import * as Utils from "../utils";
import i18next from "i18next"; import i18next from "i18next";
import { defaultStarterSpecies, DexAttrProps, GameData } from "#app/system/game-data.js"; import { defaultStarterSpecies, DexAttrProps, GameData } from "#app/system/game-data";
import PokemonSpecies, { getPokemonSpecies, getPokemonSpeciesForm, speciesStarters } from "./pokemon-species"; import PokemonSpecies, { getPokemonSpecies, getPokemonSpeciesForm, speciesStarters } from "./pokemon-species";
import Pokemon, { PokemonMove } from "#app/field/pokemon.js"; import Pokemon, { PokemonMove } from "#app/field/pokemon";
import { BattleType, FixedBattleConfig } from "#app/battle.js"; import { BattleType, FixedBattleConfig } from "#app/battle";
import Trainer, { TrainerVariant } from "#app/field/trainer.js"; import Trainer, { TrainerVariant } from "#app/field/trainer";
import { GameMode } from "#app/game-mode.js"; import { GameMode } from "#app/game-mode";
import { Type } from "./type"; import { Type } from "./type";
import { Challenges } from "#enums/challenges"; import { Challenges } from "#enums/challenges";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { TrainerType } from "#enums/trainer-type"; import { TrainerType } from "#enums/trainer-type";
import { Nature } from "./nature"; import { Nature } from "./nature";
import { Moves } from "#app/enums/moves.js"; import { Moves } from "#app/enums/moves";
import { TypeColor, TypeShadow } from "#app/enums/color.js"; import { TypeColor, TypeShadow } from "#app/enums/color";
import { pokemonEvolutions } from "./pokemon-evolutions"; import { pokemonEvolutions } from "./pokemon-evolutions";
import { pokemonFormChanges } from "./pokemon-forms"; import { pokemonFormChanges } from "./pokemon-forms";

View File

@ -1569,8 +1569,7 @@ export const trainerTypeDialogue: TrainerTypeDialogue = {
"dialogue:roark.victory.1", "dialogue:roark.victory.1",
"dialogue:roark.victory.2", "dialogue:roark.victory.2",
"dialogue:roark.victory.3", "dialogue:roark.victory.3",
"dialogue:roark.victory.4", "dialogue:roark.victory.4"
"dialogue:roark.victory.5"
], ],
defeat: [ defeat: [
"dialogue:roark.defeat.1", "dialogue:roark.defeat.1",

View File

@ -8,7 +8,7 @@ import { PlayerPokemon } from "#app/field/pokemon";
import i18next from "i18next"; import i18next from "i18next";
import { EggTier } from "#enums/egg-type"; import { EggTier } from "#enums/egg-type";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { EggSourceType } from "#app/enums/egg-source-types.js"; import { EggSourceType } from "#app/enums/egg-source-types";
export const EGG_SEED = 1073741824; export const EGG_SEED = 1073741824;
@ -222,7 +222,7 @@ export class Egg {
let pokemonSpecies = getPokemonSpecies(this._species); let pokemonSpecies = getPokemonSpecies(this._species);
// Special condition to have Phione eggs also have a chance of generating Manaphy // Special condition to have Phione eggs also have a chance of generating Manaphy
if (this._species === Species.PHIONE) { if (this._species === Species.PHIONE && this._sourceType === EggSourceType.SAME_SPECIES_EGG) {
pokemonSpecies = getPokemonSpecies(Utils.randSeedInt(MANAPHY_EGG_MANAPHY_RATE) ? Species.PHIONE : Species.MANAPHY); pokemonSpecies = getPokemonSpecies(Utils.randSeedInt(MANAPHY_EGG_MANAPHY_RATE) ? Species.PHIONE : Species.MANAPHY);
} }
@ -326,7 +326,8 @@ export class Egg {
break; break;
} }
return Utils.randSeedInt(baseChance * Math.pow(2, 3 - this.tier)) ? Utils.randSeedInt(3) : 3; const tierMultiplier = this.isManaphyEgg() ? 2 : Math.pow(2, 3 - this.tier);
return Utils.randSeedInt(baseChance * tierMultiplier) ? Utils.randSeedInt(3) : 3;
} }
private getEggTierDefaultHatchWaves(eggTier?: EggTier): number { private getEggTierDefaultHatchWaves(eggTier?: EggTier): number {
@ -361,7 +362,12 @@ export class Egg {
* the species that was the legendary focus at the time * the species that was the legendary focus at the time
*/ */
if (this.isManaphyEgg()) { if (this.isManaphyEgg()) {
const rand = Utils.randSeedInt(MANAPHY_EGG_MANAPHY_RATE); /**
* Adding a technicality to make unit tests easier: By making this check pass
* when Utils.randSeedInt(8) = 1, and by making the generatePlayerPokemon() species
* check pass when Utils.randSeedInt(8) = 0, we can tell them apart during tests.
*/
const rand = (Utils.randSeedInt(MANAPHY_EGG_MANAPHY_RATE) !== 1);
return rand ? Species.PHIONE : Species.MANAPHY; return rand ? Species.PHIONE : Species.MANAPHY;
} else if (this.tier === EggTier.MASTER } else if (this.tier === EggTier.MASTER
&& this._sourceType === EggSourceType.GACHA_LEGENDARY) { && this._sourceType === EggSourceType.GACHA_LEGENDARY) {

View File

@ -81,6 +81,16 @@ export enum MoveFlags {
MAKES_CONTACT = 1 << 0, MAKES_CONTACT = 1 << 0,
IGNORE_PROTECT = 1 << 1, IGNORE_PROTECT = 1 << 1,
IGNORE_VIRTUAL = 1 << 2, IGNORE_VIRTUAL = 1 << 2,
/**
* Sound-based moves have the following effects:
* - Pokemon with the {@linkcode Abilities.SOUNDPROOF Soundproof Ability} are unaffected by other Pokemon's sound-based moves.
* - Pokemon affected by {@linkcode Moves.THROAT_CHOP Throat Chop} cannot use sound-based moves for two turns.
* - Sound-based moves used by a Pokemon with {@linkcode Abilities.LIQUID_VOICE Liquid Voice} become Water-type moves.
* - Sound-based moves used by a Pokemon with {@linkcode Abilities.PUNK_ROCK Punk Rock} are boosted by 30%. Pokemon with Punk Rock also take half damage from sound-based moves.
* - All sound-based moves (except Howl) can hit Pokemon behind an active {@linkcode Moves.SUBSTITUTE Substitute}.
*
* cf https://bulbapedia.bulbagarden.net/wiki/Sound-based_move
*/
SOUND_BASED = 1 << 3, SOUND_BASED = 1 << 3,
HIDE_USER = 1 << 4, HIDE_USER = 1 << 4,
HIDE_TARGET = 1 << 5, HIDE_TARGET = 1 << 5,
@ -93,19 +103,20 @@ export enum MoveFlags {
* @see {@linkcode Move.recklessMove()} * @see {@linkcode Move.recklessMove()}
*/ */
RECKLESS_MOVE = 1 << 10, RECKLESS_MOVE = 1 << 10,
/** Indicates a move should be affected by {@linkcode Abilities.BULLETPROOF} */
BALLBOMB_MOVE = 1 << 11, BALLBOMB_MOVE = 1 << 11,
/** Grass types and pokemon with {@linkcode Abilities.OVERCOAT} are immune to powder moves */
POWDER_MOVE = 1 << 12, POWDER_MOVE = 1 << 12,
/** Indicates a move should trigger {@linkcode Abilities.DANCER} */
DANCE_MOVE = 1 << 13, DANCE_MOVE = 1 << 13,
/** Indicates a move should trigger {@linkcode Abilities.WIND_RIDER} */
WIND_MOVE = 1 << 14, WIND_MOVE = 1 << 14,
/** Indicates a move should trigger {@linkcode Abilities.TRIAGE} */
TRIAGE_MOVE = 1 << 15, TRIAGE_MOVE = 1 << 15,
IGNORE_ABILITIES = 1 << 16, IGNORE_ABILITIES = 1 << 16,
/** /** Enables all hits of a multi-hit move to be accuracy checked individually */
* Enables all hits of a multi-hit move to be accuracy checked individually
*/
CHECK_ALL_HITS = 1 << 17, CHECK_ALL_HITS = 1 << 17,
/** /** Indicates a move is able to be redirected to allies in a double battle if the attacker faints */
* Indicates a move is able to be redirected to allies in a double battle if the attacker faints
*/
REDIRECT_COUNTER = 1 << 18, REDIRECT_COUNTER = 1 << 18,
} }
@ -118,22 +129,22 @@ export default class Move implements Localizable {
private _type: Type; private _type: Type;
private _category: MoveCategory; private _category: MoveCategory;
public moveTarget: MoveTarget; public moveTarget: MoveTarget;
public power: integer; public power: number;
public accuracy: integer; public accuracy: number;
public pp: integer; public pp: number;
public effect: string; public effect: string;
public chance: integer; /** The chance of a move's secondary effects activating */
public priority: integer; public chance: number;
public generation: integer; public priority: number;
public attrs: MoveAttr[]; public generation: number;
private conditions: MoveCondition[]; public attrs: MoveAttr[] = [];
private flags: integer; private conditions: MoveCondition[] = [];
private nameAppend: string; /** The move's {@linkcode MoveFlags} */
private flags: number = 0;
private nameAppend: string = "";
constructor(id: Moves, type: Type, category: MoveCategory, defaultMoveTarget: MoveTarget, power: integer, accuracy: integer, pp: integer, chance: integer, priority: integer, generation: integer) { constructor(id: Moves, type: Type, category: MoveCategory, defaultMoveTarget: MoveTarget, power: number, accuracy: number, pp: number, chance: number, priority: number, generation: number) {
this.id = id; this.id = id;
this.nameAppend = "";
this._type = type; this._type = type;
this._category = category; this._category = category;
this.moveTarget = defaultMoveTarget; this.moveTarget = defaultMoveTarget;
@ -144,10 +155,6 @@ export default class Move implements Localizable {
this.priority = priority; this.priority = priority;
this.generation = generation; this.generation = generation;
this.attrs = [];
this.conditions = [];
this.flags = 0;
if (defaultMoveTarget === MoveTarget.USER) { if (defaultMoveTarget === MoveTarget.USER) {
this.setFlag(MoveFlags.IGNORE_PROTECT, true); this.setFlag(MoveFlags.IGNORE_PROTECT, true);
} }
@ -377,7 +384,7 @@ export default class Move implements Localizable {
* @param makesContact The value (boolean) to set the flag to * @param makesContact The value (boolean) to set the flag to
* @returns The {@linkcode Move} that called this function * @returns The {@linkcode Move} that called this function
*/ */
makesContact(makesContact: boolean = true): this { // TODO: is true the correct default? makesContact(makesContact: boolean = true): this {
this.setFlag(MoveFlags.MAKES_CONTACT, makesContact); this.setFlag(MoveFlags.MAKES_CONTACT, makesContact);
return this; return this;
} }
@ -388,7 +395,7 @@ export default class Move implements Localizable {
* example: @see {@linkcode Moves.CURSE} * example: @see {@linkcode Moves.CURSE}
* @returns The {@linkcode Move} that called this function * @returns The {@linkcode Move} that called this function
*/ */
ignoresProtect(ignoresProtect: boolean = true): this { // TODO: is `true` the correct default? ignoresProtect(ignoresProtect: boolean = true): this {
this.setFlag(MoveFlags.IGNORE_PROTECT, ignoresProtect); this.setFlag(MoveFlags.IGNORE_PROTECT, ignoresProtect);
return this; return this;
} }
@ -399,7 +406,7 @@ export default class Move implements Localizable {
* example: @see {@linkcode Moves.NATURE_POWER} * example: @see {@linkcode Moves.NATURE_POWER}
* @returns The {@linkcode Move} that called this function * @returns The {@linkcode Move} that called this function
*/ */
ignoresVirtual(ignoresVirtual: boolean = true): this { // TODO: is `true` the correct default? ignoresVirtual(ignoresVirtual: boolean = true): this {
this.setFlag(MoveFlags.IGNORE_VIRTUAL, ignoresVirtual); this.setFlag(MoveFlags.IGNORE_VIRTUAL, ignoresVirtual);
return this; return this;
} }
@ -410,7 +417,7 @@ export default class Move implements Localizable {
* example: @see {@linkcode Moves.UPROAR} * example: @see {@linkcode Moves.UPROAR}
* @returns The {@linkcode Move} that called this function * @returns The {@linkcode Move} that called this function
*/ */
soundBased(soundBased: boolean = true): this { // TODO: is `true` the correct default? soundBased(soundBased: boolean = true): this {
this.setFlag(MoveFlags.SOUND_BASED, soundBased); this.setFlag(MoveFlags.SOUND_BASED, soundBased);
return this; return this;
} }
@ -421,7 +428,7 @@ export default class Move implements Localizable {
* example: @see {@linkcode Moves.TELEPORT} * example: @see {@linkcode Moves.TELEPORT}
* @returns The {@linkcode Move} that called this function * @returns The {@linkcode Move} that called this function
*/ */
hidesUser(hidesUser: boolean = true): this { // TODO: is `true` the correct default? hidesUser(hidesUser: boolean = true): this {
this.setFlag(MoveFlags.HIDE_USER, hidesUser); this.setFlag(MoveFlags.HIDE_USER, hidesUser);
return this; return this;
} }
@ -432,7 +439,7 @@ export default class Move implements Localizable {
* example: @see {@linkcode Moves.WHIRLWIND} * example: @see {@linkcode Moves.WHIRLWIND}
* @returns The {@linkcode Move} that called this function * @returns The {@linkcode Move} that called this function
*/ */
hidesTarget(hidesTarget: boolean = true): this { // TODO: is `true` the correct default? hidesTarget(hidesTarget: boolean = true): this {
this.setFlag(MoveFlags.HIDE_TARGET, hidesTarget); this.setFlag(MoveFlags.HIDE_TARGET, hidesTarget);
return this; return this;
} }
@ -443,7 +450,7 @@ export default class Move implements Localizable {
* example: @see {@linkcode Moves.BITE} * example: @see {@linkcode Moves.BITE}
* @returns The {@linkcode Move} that called this function * @returns The {@linkcode Move} that called this function
*/ */
bitingMove(bitingMove: boolean = true): this { // TODO: is `true` the correct default? bitingMove(bitingMove: boolean = true): this {
this.setFlag(MoveFlags.BITING_MOVE, bitingMove); this.setFlag(MoveFlags.BITING_MOVE, bitingMove);
return this; return this;
} }
@ -454,7 +461,7 @@ export default class Move implements Localizable {
* example: @see {@linkcode Moves.WATER_PULSE} * example: @see {@linkcode Moves.WATER_PULSE}
* @returns The {@linkcode Move} that called this function * @returns The {@linkcode Move} that called this function
*/ */
pulseMove(pulseMove: boolean = true): this { // TODO: is `true` the correct default? pulseMove(pulseMove: boolean = true): this {
this.setFlag(MoveFlags.PULSE_MOVE, pulseMove); this.setFlag(MoveFlags.PULSE_MOVE, pulseMove);
return this; return this;
} }
@ -465,7 +472,7 @@ export default class Move implements Localizable {
* example: @see {@linkcode Moves.DRAIN_PUNCH} * example: @see {@linkcode Moves.DRAIN_PUNCH}
* @returns The {@linkcode Move} that called this function * @returns The {@linkcode Move} that called this function
*/ */
punchingMove(punchingMove: boolean = true): this { // TODO: is `true` the correct default? punchingMove(punchingMove: boolean = true): this {
this.setFlag(MoveFlags.PUNCHING_MOVE, punchingMove); this.setFlag(MoveFlags.PUNCHING_MOVE, punchingMove);
return this; return this;
} }
@ -476,7 +483,7 @@ export default class Move implements Localizable {
* example: @see {@linkcode Moves.X_SCISSOR} * example: @see {@linkcode Moves.X_SCISSOR}
* @returns The {@linkcode Move} that called this function * @returns The {@linkcode Move} that called this function
*/ */
slicingMove(slicingMove: boolean = true): this { // TODO: is `true` the correct default? slicingMove(slicingMove: boolean = true): this {
this.setFlag(MoveFlags.SLICING_MOVE, slicingMove); this.setFlag(MoveFlags.SLICING_MOVE, slicingMove);
return this; return this;
} }
@ -487,7 +494,7 @@ export default class Move implements Localizable {
* @param recklessMove The value to set the flag to * @param recklessMove The value to set the flag to
* @returns The {@linkcode Move} that called this function * @returns The {@linkcode Move} that called this function
*/ */
recklessMove(recklessMove: boolean = true): this { // TODO: is `true` the correct default? recklessMove(recklessMove: boolean = true): this {
this.setFlag(MoveFlags.RECKLESS_MOVE, recklessMove); this.setFlag(MoveFlags.RECKLESS_MOVE, recklessMove);
return this; return this;
} }
@ -498,7 +505,7 @@ export default class Move implements Localizable {
* example: @see {@linkcode Moves.ELECTRO_BALL} * example: @see {@linkcode Moves.ELECTRO_BALL}
* @returns The {@linkcode Move} that called this function * @returns The {@linkcode Move} that called this function
*/ */
ballBombMove(ballBombMove: boolean = true): this { // TODO: is `true` the correct default? ballBombMove(ballBombMove: boolean = true): this {
this.setFlag(MoveFlags.BALLBOMB_MOVE, ballBombMove); this.setFlag(MoveFlags.BALLBOMB_MOVE, ballBombMove);
return this; return this;
} }
@ -509,7 +516,7 @@ export default class Move implements Localizable {
* example: @see {@linkcode Moves.STUN_SPORE} * example: @see {@linkcode Moves.STUN_SPORE}
* @returns The {@linkcode Move} that called this function * @returns The {@linkcode Move} that called this function
*/ */
powderMove(powderMove: boolean = true): this { // TODO: is `true` the correct default? powderMove(powderMove: boolean = true): this {
this.setFlag(MoveFlags.POWDER_MOVE, powderMove); this.setFlag(MoveFlags.POWDER_MOVE, powderMove);
return this; return this;
} }
@ -520,7 +527,7 @@ export default class Move implements Localizable {
* example: @see {@linkcode Moves.PETAL_DANCE} * example: @see {@linkcode Moves.PETAL_DANCE}
* @returns The {@linkcode Move} that called this function * @returns The {@linkcode Move} that called this function
*/ */
danceMove(danceMove: boolean = true): this { // TODO: is `true` the correct default? danceMove(danceMove: boolean = true): this {
this.setFlag(MoveFlags.DANCE_MOVE, danceMove); this.setFlag(MoveFlags.DANCE_MOVE, danceMove);
return this; return this;
} }
@ -531,7 +538,7 @@ export default class Move implements Localizable {
* example: @see {@linkcode Moves.HURRICANE} * example: @see {@linkcode Moves.HURRICANE}
* @returns The {@linkcode Move} that called this function * @returns The {@linkcode Move} that called this function
*/ */
windMove(windMove: boolean = true): this { // TODO: is `true` the correct default? windMove(windMove: boolean = true): this {
this.setFlag(MoveFlags.WIND_MOVE, windMove); this.setFlag(MoveFlags.WIND_MOVE, windMove);
return this; return this;
} }
@ -542,7 +549,7 @@ export default class Move implements Localizable {
* example: @see {@linkcode Moves.ABSORB} * example: @see {@linkcode Moves.ABSORB}
* @returns The {@linkcode Move} that called this function * @returns The {@linkcode Move} that called this function
*/ */
triageMove(triageMove: boolean = true): this { // TODO: is `true` the correct default? triageMove(triageMove: boolean = true): this {
this.setFlag(MoveFlags.TRIAGE_MOVE, triageMove); this.setFlag(MoveFlags.TRIAGE_MOVE, triageMove);
return this; return this;
} }
@ -553,7 +560,7 @@ export default class Move implements Localizable {
* example: @see {@linkcode Moves.SUNSTEEL_STRIKE} * example: @see {@linkcode Moves.SUNSTEEL_STRIKE}
* @returns The {@linkcode Move} that called this function * @returns The {@linkcode Move} that called this function
*/ */
ignoresAbilities(ignoresAbilities: boolean = true): this { // TODO: is `true` the correct default? ignoresAbilities(ignoresAbilities: boolean = true): this {
this.setFlag(MoveFlags.IGNORE_ABILITIES, ignoresAbilities); this.setFlag(MoveFlags.IGNORE_ABILITIES, ignoresAbilities);
return this; return this;
} }
@ -564,7 +571,7 @@ export default class Move implements Localizable {
* example: @see {@linkcode Moves.TRIPLE_AXEL} * example: @see {@linkcode Moves.TRIPLE_AXEL}
* @returns The {@linkcode Move} that called this function * @returns The {@linkcode Move} that called this function
*/ */
checkAllHits(checkAllHits: boolean = true): this { // TODO: is `true` the correct default? checkAllHits(checkAllHits: boolean = true): this {
this.setFlag(MoveFlags.CHECK_ALL_HITS, checkAllHits); this.setFlag(MoveFlags.CHECK_ALL_HITS, checkAllHits);
return this; return this;
} }
@ -575,7 +582,7 @@ export default class Move implements Localizable {
* example: @see {@linkcode Moves.METAL_BURST} * example: @see {@linkcode Moves.METAL_BURST}
* @returns The {@linkcode Move} that called this function * @returns The {@linkcode Move} that called this function
*/ */
redirectCounter(redirectCounter: boolean = true): this { // TODO: is `true` the correct default? redirectCounter(redirectCounter: boolean = true): this {
this.setFlag(MoveFlags.REDIRECT_COUNTER, redirectCounter); this.setFlag(MoveFlags.REDIRECT_COUNTER, redirectCounter);
return this; return this;
} }
@ -3470,7 +3477,7 @@ export class SpitUpPowerAttr extends VariablePowerAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const stockpilingTag = user.getTag(StockpilingTag); const stockpilingTag = user.getTag(StockpilingTag);
if (stockpilingTag !== null && stockpilingTag.stockpiledCount > 0) { if (stockpilingTag && stockpilingTag.stockpiledCount > 0) {
const power = args[0] as Utils.IntegerHolder; const power = args[0] as Utils.IntegerHolder;
power.value = this.multiplier * stockpilingTag.stockpiledCount; power.value = this.multiplier * stockpilingTag.stockpiledCount;
return true; return true;
@ -3488,7 +3495,7 @@ export class SwallowHealAttr extends HealAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const stockpilingTag = user.getTag(StockpilingTag); const stockpilingTag = user.getTag(StockpilingTag);
if (stockpilingTag !== null && stockpilingTag?.stockpiledCount > 0) { if (stockpilingTag && stockpilingTag.stockpiledCount > 0) {
const stockpiled = stockpilingTag.stockpiledCount; const stockpiled = stockpilingTag.stockpiledCount;
let healRatio: number; let healRatio: number;
@ -4745,7 +4752,7 @@ export class AddArenaTagAttr extends MoveEffectAttr {
return false; return false;
} }
if (move.chance < 0 || move.chance === 100 || user.randSeedInt(100) < move.chance) { if ((move.chance < 0 || move.chance === 100 || user.randSeedInt(100) < move.chance) && user.getLastXMoves(1)[0].result === MoveResult.SUCCESS) {
user.scene.arena.addTag(this.tagType, this.turnCount, move.id, user.id, (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY); user.scene.arena.addTag(this.tagType, this.turnCount, move.id, user.id, (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY);
return true; return true;
} }
@ -5985,9 +5992,8 @@ export class SwapStatAttr extends MoveEffectAttr {
} }
/** /**
* Takes the average of the user's and target's corresponding current * Swaps the user's and target's corresponding current
* {@linkcode stat} values and sets that stat to the average for both * {@linkcode EffectiveStat | stat} values
* temporarily.
* @param user the {@linkcode Pokemon} that used the move * @param user the {@linkcode Pokemon} that used the move
* @param target the {@linkcode Pokemon} that the move was used on * @param target the {@linkcode Pokemon} that the move was used on
* @param move N/A * @param move N/A
@ -6011,6 +6017,62 @@ export class SwapStatAttr extends MoveEffectAttr {
} }
} }
/**
* Attribute used to switch the user's own stats.
* Used by Power Shift.
* @extends MoveEffectAttr
*/
export class ShiftStatAttr extends MoveEffectAttr {
private statToSwitch: EffectiveStat;
private statToSwitchWith: EffectiveStat;
constructor(statToSwitch: EffectiveStat, statToSwitchWith: EffectiveStat) {
super();
this.statToSwitch = statToSwitch;
this.statToSwitchWith = statToSwitchWith;
}
/**
* Switches the user's stats based on the {@linkcode statToSwitch} and {@linkcode statToSwitchWith} attributes.
* @param {Pokemon} user the {@linkcode Pokemon} that used the move
* @param target n/a
* @param move n/a
* @param args n/a
* @returns whether the effect was applied
*/
override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
if (!super.apply(user, target, move, args)) {
return false;
}
const firstStat = user.getStat(this.statToSwitch, false);
const secondStat = user.getStat(this.statToSwitchWith, false);
user.setStat(this.statToSwitch, secondStat, false);
user.setStat(this.statToSwitchWith, firstStat, false);
user.scene.queueMessage(i18next.t("moveTriggers:shiftedStats", {
pokemonName: getPokemonNameWithAffix(user),
statToSwitch: i18next.t(getStatKey(this.statToSwitch)),
statToSwitchWith: i18next.t(getStatKey(this.statToSwitchWith))
}));
return true;
}
/**
* Encourages the user to use the move if the stat to switch with is greater than the stat to switch.
* @param {Pokemon} user the {@linkcode Pokemon} that used the move
* @param target n/a
* @param move n/a
* @returns number of points to add to the user's benefit score
*/
override getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer {
return user.getStat(this.statToSwitchWith, false) > user.getStat(this.statToSwitch, false) ? 10 : 0;
}
}
/** /**
* Attribute used for status moves, namely Power Split and Guard Split, * Attribute used for status moves, namely Power Split and Guard Split,
* that take the average of a user's and target's corresponding * that take the average of a user's and target's corresponding
@ -6215,12 +6277,42 @@ export class VariableTargetAttr extends MoveAttr {
} }
} }
/**
* Attribute for {@linkcode Moves.AFTER_YOU}
*
* [After You - Move | Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/After_You_(move))
*/
export class AfterYouAttr extends MoveEffectAttr {
/**
* Allows the target of this move to act right after the user.
*
* @param user {@linkcode Pokemon} that is using the move.
* @param target {@linkcode Pokemon} that will move right after this move is used.
* @param move {@linkcode Move} {@linkcode Moves.AFTER_YOU}
* @param _args N/A
* @returns true
*/
override apply(user: Pokemon, target: Pokemon, _move: Move, _args: any[]): boolean {
user.scene.queueMessage(i18next.t("moveTriggers:afterYou", {targetName: getPokemonNameWithAffix(target)}));
//Will find next acting phase of the targeted pokémon, delete it and queue it next on successful delete.
const nextAttackPhase = target.scene.findPhase<MovePhase>((phase) => phase.pokemon === target);
if (nextAttackPhase && target.scene.tryRemovePhase((phase: MovePhase) => phase.pokemon === target)) {
target.scene.prependToPhase(new MovePhase(target.scene, target, [...nextAttackPhase.targets], nextAttackPhase.move), MovePhase);
}
return true;
}
}
const failOnGravityCondition: MoveConditionFunc = (user, target, move) => !user.scene.arena.getTag(ArenaTagType.GRAVITY); const failOnGravityCondition: MoveConditionFunc = (user, target, move) => !user.scene.arena.getTag(ArenaTagType.GRAVITY);
const failOnBossCondition: MoveConditionFunc = (user, target, move) => !target.isBossImmune(); const failOnBossCondition: MoveConditionFunc = (user, target, move) => !target.isBossImmune();
const failOnMaxCondition: MoveConditionFunc = (user, target, move) => !target.isMax(); const failOnMaxCondition: MoveConditionFunc = (user, target, move) => !target.isMax();
const failIfSingleBattle: MoveConditionFunc = (user, target, move) => user.scene.currentBattle.double;
const failIfDampCondition: MoveConditionFunc = (user, target, move) => { const failIfDampCondition: MoveConditionFunc = (user, target, move) => {
const cancelled = new Utils.BooleanHolder(false); const cancelled = new Utils.BooleanHolder(false);
user.scene.getField(true).map(p=>applyAbAttrs(FieldPreventExplosiveMovesAbAttr, p, cancelled)); user.scene.getField(true).map(p=>applyAbAttrs(FieldPreventExplosiveMovesAbAttr, p, cancelled));
@ -7051,6 +7143,7 @@ export function initMoves() {
new StatusMove(Moves.CHARM, Type.FAIRY, 100, 20, -1, 0, 2) new StatusMove(Moves.CHARM, Type.FAIRY, 100, 20, -1, 0, 2)
.attr(StatStageChangeAttr, [ Stat.ATK ], -2), .attr(StatStageChangeAttr, [ Stat.ATK ], -2),
new AttackMove(Moves.ROLLOUT, Type.ROCK, MoveCategory.PHYSICAL, 30, 90, 20, -1, 0, 2) new AttackMove(Moves.ROLLOUT, Type.ROCK, MoveCategory.PHYSICAL, 30, 90, 20, -1, 0, 2)
.partial()
.attr(ConsecutiveUseDoublePowerAttr, 5, true, true, Moves.DEFENSE_CURL), .attr(ConsecutiveUseDoublePowerAttr, 5, true, true, Moves.DEFENSE_CURL),
new AttackMove(Moves.FALSE_SWIPE, Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 40, -1, 0, 2) new AttackMove(Moves.FALSE_SWIPE, Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 40, -1, 0, 2)
.attr(SurviveDamageAttr), .attr(SurviveDamageAttr),
@ -7330,9 +7423,11 @@ export function initMoves() {
.attr(HighCritAttr) .attr(HighCritAttr)
.attr(StatusEffectAttr, StatusEffect.BURN), .attr(StatusEffectAttr, StatusEffect.BURN),
new StatusMove(Moves.MUD_SPORT, Type.GROUND, -1, 15, -1, 0, 3) new StatusMove(Moves.MUD_SPORT, Type.GROUND, -1, 15, -1, 0, 3)
.ignoresProtect()
.attr(AddArenaTagAttr, ArenaTagType.MUD_SPORT, 5) .attr(AddArenaTagAttr, ArenaTagType.MUD_SPORT, 5)
.target(MoveTarget.BOTH_SIDES), .target(MoveTarget.BOTH_SIDES),
new AttackMove(Moves.ICE_BALL, Type.ICE, MoveCategory.PHYSICAL, 30, 90, 20, -1, 0, 3) new AttackMove(Moves.ICE_BALL, Type.ICE, MoveCategory.PHYSICAL, 30, 90, 20, -1, 0, 3)
.partial()
.attr(ConsecutiveUseDoublePowerAttr, 5, true, true, Moves.DEFENSE_CURL) .attr(ConsecutiveUseDoublePowerAttr, 5, true, true, Moves.DEFENSE_CURL)
.ballBombMove(), .ballBombMove(),
new AttackMove(Moves.NEEDLE_ARM, Type.GRASS, MoveCategory.PHYSICAL, 60, 100, 15, 30, 0, 3) new AttackMove(Moves.NEEDLE_ARM, Type.GRASS, MoveCategory.PHYSICAL, 60, 100, 15, 30, 0, 3)
@ -7454,6 +7549,7 @@ export function initMoves() {
.recklessMove(), .recklessMove(),
new AttackMove(Moves.MAGICAL_LEAF, Type.GRASS, MoveCategory.SPECIAL, 60, -1, 20, -1, 0, 3), new AttackMove(Moves.MAGICAL_LEAF, Type.GRASS, MoveCategory.SPECIAL, 60, -1, 20, -1, 0, 3),
new StatusMove(Moves.WATER_SPORT, Type.WATER, -1, 15, -1, 0, 3) new StatusMove(Moves.WATER_SPORT, Type.WATER, -1, 15, -1, 0, 3)
.ignoresProtect()
.attr(AddArenaTagAttr, ArenaTagType.WATER_SPORT, 5) .attr(AddArenaTagAttr, ArenaTagType.WATER_SPORT, 5)
.target(MoveTarget.BOTH_SIDES), .target(MoveTarget.BOTH_SIDES),
new SelfStatusMove(Moves.CALM_MIND, Type.PSYCHIC, -1, 20, -1, 0, 3) new SelfStatusMove(Moves.CALM_MIND, Type.PSYCHIC, -1, 20, -1, 0, 3)
@ -7482,6 +7578,7 @@ export function initMoves() {
.attr(AddBattlerTagAttr, BattlerTagType.ROOSTED, true, false) .attr(AddBattlerTagAttr, BattlerTagType.ROOSTED, true, false)
.triageMove(), .triageMove(),
new StatusMove(Moves.GRAVITY, Type.PSYCHIC, -1, 5, -1, 0, 4) new StatusMove(Moves.GRAVITY, Type.PSYCHIC, -1, 5, -1, 0, 4)
.ignoresProtect()
.attr(AddArenaTagAttr, ArenaTagType.GRAVITY, 5) .attr(AddArenaTagAttr, ArenaTagType.GRAVITY, 5)
.target(MoveTarget.BOTH_SIDES), .target(MoveTarget.BOTH_SIDES),
new StatusMove(Moves.MIRACLE_EYE, Type.PSYCHIC, -1, 40, -1, 0, 4) new StatusMove(Moves.MIRACLE_EYE, Type.PSYCHIC, -1, 40, -1, 0, 4)
@ -7868,7 +7965,10 @@ export function initMoves() {
.attr(AbilityGiveAttr), .attr(AbilityGiveAttr),
new StatusMove(Moves.AFTER_YOU, Type.NORMAL, -1, 15, -1, 0, 5) new StatusMove(Moves.AFTER_YOU, Type.NORMAL, -1, 15, -1, 0, 5)
.ignoresProtect() .ignoresProtect()
.unimplemented(), .target(MoveTarget.NEAR_OTHER)
.condition(failIfSingleBattle)
.condition((user, target, move) => !target.turnData.acted)
.attr(AfterYouAttr),
new AttackMove(Moves.ROUND, Type.NORMAL, MoveCategory.SPECIAL, 60, 100, 15, -1, 0, 5) new AttackMove(Moves.ROUND, Type.NORMAL, MoveCategory.SPECIAL, 60, 100, 15, -1, 0, 5)
.soundBased() .soundBased()
.partial(), .partial(),
@ -7922,7 +8022,15 @@ export function initMoves() {
new StatusMove(Moves.REFLECT_TYPE, Type.NORMAL, -1, 15, -1, 0, 5) new StatusMove(Moves.REFLECT_TYPE, Type.NORMAL, -1, 15, -1, 0, 5)
.attr(CopyTypeAttr), .attr(CopyTypeAttr),
new AttackMove(Moves.RETALIATE, Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 5, -1, 0, 5) new AttackMove(Moves.RETALIATE, Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 5, -1, 0, 5)
.partial(), .attr(MovePowerMultiplierAttr, (user, target, move) => {
const turn = user.scene.currentBattle.turn;
const lastPlayerFaint = user.scene.currentBattle.playerFaintsHistory[user.scene.currentBattle.playerFaintsHistory.length - 1];
const lastEnemyFaint = user.scene.currentBattle.enemyFaintsHistory[user.scene.currentBattle.enemyFaintsHistory.length - 1];
return (
(lastPlayerFaint !== undefined && turn - lastPlayerFaint.turn === 1 && user.isPlayer()) ||
(lastEnemyFaint !== undefined && turn - lastEnemyFaint.turn === 1 && !user.isPlayer())
) ? 2 : 1;
}),
new AttackMove(Moves.FINAL_GAMBIT, Type.FIGHTING, MoveCategory.SPECIAL, -1, 100, 5, -1, 0, 5) new AttackMove(Moves.FINAL_GAMBIT, Type.FIGHTING, MoveCategory.SPECIAL, -1, 100, 5, -1, 0, 5)
.attr(UserHpDamageAttr) .attr(UserHpDamageAttr)
.attr(SacrificialAttrOnHit), .attr(SacrificialAttrOnHit),
@ -8402,7 +8510,7 @@ export function initMoves() {
.target(MoveTarget.USER_AND_ALLIES) .target(MoveTarget.USER_AND_ALLIES)
.condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS].find(a => p.hasAbility(a, false)))), .condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS].find(a => p.hasAbility(a, false)))),
new AttackMove(Moves.THROAT_CHOP, Type.DARK, MoveCategory.PHYSICAL, 80, 100, 15, 100, 0, 7) new AttackMove(Moves.THROAT_CHOP, Type.DARK, MoveCategory.PHYSICAL, 80, 100, 15, 100, 0, 7)
.partial(), .attr(AddBattlerTagAttr, BattlerTagType.THROAT_CHOPPED),
new AttackMove(Moves.POLLEN_PUFF, Type.BUG, MoveCategory.SPECIAL, 90, 100, 15, -1, 0, 7) new AttackMove(Moves.POLLEN_PUFF, Type.BUG, MoveCategory.SPECIAL, 90, 100, 15, -1, 0, 7)
.attr(StatusCategoryOnAllyAttr) .attr(StatusCategoryOnAllyAttr)
.attr(HealOnAllyAttr, 0.5, true, false) .attr(HealOnAllyAttr, 0.5, true, false)
@ -8642,7 +8750,7 @@ export function initMoves() {
.condition((user, target, move) => user.getTag(TrappedTag)?.sourceMove !== Moves.NO_RETREAT), // fails if the user is currently trapped by No Retreat .condition((user, target, move) => user.getTag(TrappedTag)?.sourceMove !== Moves.NO_RETREAT), // fails if the user is currently trapped by No Retreat
new StatusMove(Moves.TAR_SHOT, Type.ROCK, 100, 15, -1, 0, 8) new StatusMove(Moves.TAR_SHOT, Type.ROCK, 100, 15, -1, 0, 8)
.attr(StatStageChangeAttr, [ Stat.SPD ], -1) .attr(StatStageChangeAttr, [ Stat.SPD ], -1)
.partial(), .attr(AddBattlerTagAttr, BattlerTagType.TAR_SHOT, false),
new StatusMove(Moves.MAGIC_POWDER, Type.PSYCHIC, 100, 20, -1, 0, 8) new StatusMove(Moves.MAGIC_POWDER, Type.PSYCHIC, 100, 20, -1, 0, 8)
.attr(ChangeTypeAttr, Type.PSYCHIC) .attr(ChangeTypeAttr, Type.PSYCHIC)
.powderMove(), .powderMove(),
@ -8892,7 +9000,8 @@ export function initMoves() {
new AttackMove(Moves.PSYSHIELD_BASH, Type.PSYCHIC, MoveCategory.PHYSICAL, 70, 90, 10, 100, 0, 8) new AttackMove(Moves.PSYSHIELD_BASH, Type.PSYCHIC, MoveCategory.PHYSICAL, 70, 90, 10, 100, 0, 8)
.attr(StatStageChangeAttr, [ Stat.DEF ], 1, true), .attr(StatStageChangeAttr, [ Stat.DEF ], 1, true),
new SelfStatusMove(Moves.POWER_SHIFT, Type.NORMAL, -1, 10, -1, 0, 8) new SelfStatusMove(Moves.POWER_SHIFT, Type.NORMAL, -1, 10, -1, 0, 8)
.unimplemented(), .target(MoveTarget.USER)
.attr(ShiftStatAttr, Stat.ATK, Stat.DEF),
new AttackMove(Moves.STONE_AXE, Type.ROCK, MoveCategory.PHYSICAL, 65, 90, 15, 100, 0, 8) new AttackMove(Moves.STONE_AXE, Type.ROCK, MoveCategory.PHYSICAL, 65, 90, 15, 100, 0, 8)
.attr(AddArenaTrapTagHitAttr, ArenaTagType.STEALTH_ROCK) .attr(AddArenaTrapTagHitAttr, ArenaTagType.STEALTH_ROCK)
.slicingMove(), .slicingMove(),

View File

@ -1,14 +1,15 @@
import { PokemonFormChangeItemModifier } from "../modifier/modifier"; import { PokemonFormChangeItemModifier, TerastallizeModifier } from "../modifier/modifier";
import Pokemon from "../field/pokemon"; import Pokemon from "../field/pokemon";
import { SpeciesFormKey } from "./pokemon-species"; import { SpeciesFormKey } from "./pokemon-species";
import { StatusEffect } from "./status-effect"; import { StatusEffect } from "./status-effect";
import { MoveCategory, allMoves } from "./move"; import { MoveCategory, allMoves } from "./move";
import { Type } from "./type";
import { Constructor } from "#app/utils"; import { Constructor } from "#app/utils";
import { Abilities } from "#enums/abilities"; import { Abilities } from "#enums/abilities";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { TimeOfDay } from "#enums/time-of-day"; import { TimeOfDay } from "#enums/time-of-day";
import { getPokemonNameWithAffix } from "#app/messages.js"; import { getPokemonNameWithAffix } from "#app/messages";
import i18next from "i18next"; import i18next from "i18next";
import { WeatherType } from "./weather"; import { WeatherType } from "./weather";
@ -357,6 +358,41 @@ export class SpeciesDefaultFormMatchTrigger extends SpeciesFormChangeTrigger {
} }
} }
/**
* Class used for triggering form changes based on the user's Tera type.
* Used by Ogerpon and Terapagos.
* @extends SpeciesFormChangeTrigger
*/
export class SpeciesFormChangeTeraTrigger extends SpeciesFormChangeTrigger {
/** The Tera type that triggers the form change */
private teraType: Type;
constructor(teraType: Type) {
super();
this.teraType = teraType;
}
/**
* Checks if the associated Pokémon has the required Tera Shard that matches with the associated Tera type.
* @param {Pokemon} pokemon the Pokémon that is trying to do the form change
* @returns `true` if the Pokémon can change forms, `false` otherwise
*/
canChange(pokemon: Pokemon): boolean {
return !!pokemon.scene.findModifier(m => m instanceof TerastallizeModifier && m.pokemonId === pokemon.id && m.teraType === this.teraType);
}
}
/**
* Class used for triggering form changes based on the user's lapsed Tera type.
* Used by Ogerpon and Terapagos.
* @extends SpeciesFormChangeTrigger
*/
export class SpeciesFormChangeLapseTeraTrigger extends SpeciesFormChangeTrigger {
canChange(pokemon: Pokemon): boolean {
return !!pokemon.scene.findModifier(m => m instanceof TerastallizeModifier && m.pokemonId === pokemon.id);
}
}
/** /**
* Class used for triggering form changes based on weather. * Class used for triggering form changes based on weather.
* Used by Castform and Cherrim. * Used by Castform and Cherrim.
@ -592,6 +628,23 @@ export const pokemonFormChanges: PokemonFormChanges = {
[Species.ALTARIA]: [ [Species.ALTARIA]: [
new SpeciesFormChange(Species.ALTARIA, "", SpeciesFormKey.MEGA, new SpeciesFormChangeItemTrigger(FormChangeItem.ALTARIANITE)) new SpeciesFormChange(Species.ALTARIA, "", SpeciesFormKey.MEGA, new SpeciesFormChangeItemTrigger(FormChangeItem.ALTARIANITE))
], ],
[Species.CASTFORM]: [
new SpeciesFormChange(Species.CASTFORM, "", "sunny", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.SUNNY, WeatherType.HARSH_SUN]), true),
new SpeciesFormChange(Species.CASTFORM, "rainy", "sunny", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.SUNNY, WeatherType.HARSH_SUN]), true),
new SpeciesFormChange(Species.CASTFORM, "snowy", "sunny", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.SUNNY, WeatherType.HARSH_SUN]), true),
new SpeciesFormChange(Species.CASTFORM, "", "rainy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.RAIN, WeatherType.HEAVY_RAIN]), true),
new SpeciesFormChange(Species.CASTFORM, "sunny", "rainy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.RAIN, WeatherType.HEAVY_RAIN]), true),
new SpeciesFormChange(Species.CASTFORM, "snowy", "rainy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.RAIN, WeatherType.HEAVY_RAIN]), true),
new SpeciesFormChange(Species.CASTFORM, "", "snowy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.HAIL, WeatherType.SNOW]), true),
new SpeciesFormChange(Species.CASTFORM, "sunny", "snowy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.HAIL, WeatherType.SNOW]), true),
new SpeciesFormChange(Species.CASTFORM, "rainy", "snowy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.HAIL, WeatherType.SNOW]), true),
new SpeciesFormChange(Species.CASTFORM, "sunny", "", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FORECAST, [WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG]), true),
new SpeciesFormChange(Species.CASTFORM, "rainy", "", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FORECAST, [WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG]), true),
new SpeciesFormChange(Species.CASTFORM, "snowy", "", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FORECAST, [WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG]), true),
new SpeciesFormChange(Species.CASTFORM, "sunny", "", new SpeciesFormChangeActiveTrigger(), true),
new SpeciesFormChange(Species.CASTFORM, "rainy", "", new SpeciesFormChangeActiveTrigger(), true),
new SpeciesFormChange(Species.CASTFORM, "snowy", "", new SpeciesFormChangeActiveTrigger(), true)
],
[Species.BANETTE]: [ [Species.BANETTE]: [
new SpeciesFormChange(Species.BANETTE, "", SpeciesFormKey.MEGA, new SpeciesFormChangeItemTrigger(FormChangeItem.BANETTITE)) new SpeciesFormChange(Species.BANETTE, "", SpeciesFormKey.MEGA, new SpeciesFormChangeItemTrigger(FormChangeItem.BANETTITE))
], ],
@ -627,6 +680,11 @@ export const pokemonFormChanges: PokemonFormChanges = {
new SpeciesFormChange(Species.DEOXYS, "normal", "defense", new SpeciesFormChangeItemTrigger(FormChangeItem.HARD_METEORITE)), new SpeciesFormChange(Species.DEOXYS, "normal", "defense", new SpeciesFormChangeItemTrigger(FormChangeItem.HARD_METEORITE)),
new SpeciesFormChange(Species.DEOXYS, "normal", "speed", new SpeciesFormChangeItemTrigger(FormChangeItem.SMOOTH_METEORITE)) new SpeciesFormChange(Species.DEOXYS, "normal", "speed", new SpeciesFormChangeItemTrigger(FormChangeItem.SMOOTH_METEORITE))
], ],
[Species.CHERRIM]: [
new SpeciesFormChange(Species.CHERRIM, "overcast", "sunshine", new SpeciesFormChangeWeatherTrigger(Abilities.FLOWER_GIFT, [ WeatherType.SUNNY, WeatherType.HARSH_SUN ]), true),
new SpeciesFormChange(Species.CHERRIM, "sunshine", "overcast", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FLOWER_GIFT, [ WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG, WeatherType.HAIL, WeatherType.HEAVY_RAIN, WeatherType.SNOW, WeatherType.RAIN ]), true),
new SpeciesFormChange(Species.CHERRIM, "sunshine", "overcast", new SpeciesFormChangeActiveTrigger(), true)
],
[Species.LOPUNNY]: [ [Species.LOPUNNY]: [
new SpeciesFormChange(Species.LOPUNNY, "", SpeciesFormKey.MEGA, new SpeciesFormChangeItemTrigger(FormChangeItem.LOPUNNITE)) new SpeciesFormChange(Species.LOPUNNY, "", SpeciesFormKey.MEGA, new SpeciesFormChangeItemTrigger(FormChangeItem.LOPUNNITE))
], ],
@ -822,6 +880,14 @@ export const pokemonFormChanges: PokemonFormChanges = {
[Species.SANDACONDA]: [ [Species.SANDACONDA]: [
new SpeciesFormChange(Species.SANDACONDA, "", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)) new SpeciesFormChange(Species.SANDACONDA, "", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS))
], ],
[Species.CRAMORANT]: [
new SpeciesFormChange(Species.CRAMORANT, "", "gulping", new SpeciesFormChangeManualTrigger, true, new SpeciesFormChangeCondition(p => p.getHpRatio() >= .5)),
new SpeciesFormChange(Species.CRAMORANT, "", "gorging", new SpeciesFormChangeManualTrigger, true, new SpeciesFormChangeCondition(p => p.getHpRatio() < .5)),
new SpeciesFormChange(Species.CRAMORANT, "gulping", "", new SpeciesFormChangeManualTrigger, true),
new SpeciesFormChange(Species.CRAMORANT, "gorging", "", new SpeciesFormChangeManualTrigger, true),
new SpeciesFormChange(Species.CRAMORANT, "gulping", "", new SpeciesFormChangeActiveTrigger(false), true),
new SpeciesFormChange(Species.CRAMORANT, "gorging", "", new SpeciesFormChangeActiveTrigger(false), true)
],
[Species.TOXTRICITY]: [ [Species.TOXTRICITY]: [
new SpeciesFormChange(Species.TOXTRICITY, "amped", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)), new SpeciesFormChange(Species.TOXTRICITY, "amped", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)),
new SpeciesFormChange(Species.TOXTRICITY, "lowkey", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)), new SpeciesFormChange(Species.TOXTRICITY, "lowkey", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)),
@ -848,6 +914,10 @@ export const pokemonFormChanges: PokemonFormChanges = {
new SpeciesFormChange(Species.ALCREMIE, "caramel-swirl", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)), new SpeciesFormChange(Species.ALCREMIE, "caramel-swirl", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)),
new SpeciesFormChange(Species.ALCREMIE, "rainbow-swirl", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)) new SpeciesFormChange(Species.ALCREMIE, "rainbow-swirl", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS))
], ],
[Species.EISCUE]: [
new SpeciesFormChange(Species.EISCUE, "", "no-ice", new SpeciesFormChangeManualTrigger(), true),
new SpeciesFormChange(Species.EISCUE, "no-ice", "", new SpeciesFormChangeManualTrigger(), true)
],
[Species.MORPEKO]: [ [Species.MORPEKO]: [
new SpeciesFormChange(Species.MORPEKO, "full-belly", "hangry", new SpeciesFormChangeManualTrigger(), true), new SpeciesFormChange(Species.MORPEKO, "full-belly", "hangry", new SpeciesFormChangeManualTrigger(), true),
new SpeciesFormChange(Species.MORPEKO, "hangry", "full-belly", new SpeciesFormChangeManualTrigger(), true) new SpeciesFormChange(Species.MORPEKO, "hangry", "full-belly", new SpeciesFormChangeManualTrigger(), true)
@ -883,58 +953,24 @@ export const pokemonFormChanges: PokemonFormChanges = {
new SpeciesFormChange(Species.OGERPON, "teal-mask", "wellspring-mask", new SpeciesFormChangeItemTrigger(FormChangeItem.WELLSPRING_MASK)), new SpeciesFormChange(Species.OGERPON, "teal-mask", "wellspring-mask", new SpeciesFormChangeItemTrigger(FormChangeItem.WELLSPRING_MASK)),
new SpeciesFormChange(Species.OGERPON, "teal-mask", "hearthflame-mask", new SpeciesFormChangeItemTrigger(FormChangeItem.HEARTHFLAME_MASK)), new SpeciesFormChange(Species.OGERPON, "teal-mask", "hearthflame-mask", new SpeciesFormChangeItemTrigger(FormChangeItem.HEARTHFLAME_MASK)),
new SpeciesFormChange(Species.OGERPON, "teal-mask", "cornerstone-mask", new SpeciesFormChangeItemTrigger(FormChangeItem.CORNERSTONE_MASK)), new SpeciesFormChange(Species.OGERPON, "teal-mask", "cornerstone-mask", new SpeciesFormChangeItemTrigger(FormChangeItem.CORNERSTONE_MASK)),
new SpeciesFormChange(Species.OGERPON, "teal-mask", "teal-mask-tera", new SpeciesFormChangeManualTrigger(), true), //When holding a Grass Tera Shard new SpeciesFormChange(Species.OGERPON, "teal-mask", "teal-mask-tera", new SpeciesFormChangeTeraTrigger(Type.GRASS)),
new SpeciesFormChange(Species.OGERPON, "teal-mask-tera", "teal-mask", new SpeciesFormChangeManualTrigger(), true), //When no longer holding a Grass Tera Shard new SpeciesFormChange(Species.OGERPON, "teal-mask-tera", "teal-mask", new SpeciesFormChangeLapseTeraTrigger(), true, new SpeciesFormChangeCondition(p => p.getTeraType() !== Type.GRASS)),
new SpeciesFormChange(Species.OGERPON, "wellspring-mask", "wellspring-mask-tera", new SpeciesFormChangeManualTrigger(), true), //When holding a Water Tera Shard new SpeciesFormChange(Species.OGERPON, "wellspring-mask", "wellspring-mask-tera", new SpeciesFormChangeTeraTrigger(Type.WATER)),
new SpeciesFormChange(Species.OGERPON, "wellspring-mask-tera", "wellspring-mask", new SpeciesFormChangeManualTrigger(), true), //When no longer holding a Water Tera Shard new SpeciesFormChange(Species.OGERPON, "wellspring-mask-tera", "wellspring-mask", new SpeciesFormChangeLapseTeraTrigger(), true, new SpeciesFormChangeCondition(p => p.getTeraType() !== Type.WATER)),
new SpeciesFormChange(Species.OGERPON, "hearthflame-mask", "hearthflame-mask-tera", new SpeciesFormChangeManualTrigger(), true), //When holding a Fire Tera Shard new SpeciesFormChange(Species.OGERPON, "hearthflame-mask", "hearthflame-mask-tera", new SpeciesFormChangeTeraTrigger(Type.FIRE)),
new SpeciesFormChange(Species.OGERPON, "hearthflame-mask-tera", "hearthflame-mask", new SpeciesFormChangeManualTrigger(), true), //When no longer holding a Fire Tera Shard new SpeciesFormChange(Species.OGERPON, "hearthflame-mask-tera", "hearthflame-mask", new SpeciesFormChangeLapseTeraTrigger(), true, new SpeciesFormChangeCondition(p => p.getTeraType() !== Type.FIRE)),
new SpeciesFormChange(Species.OGERPON, "cornerstone-mask", "cornerstone-mask-tera", new SpeciesFormChangeManualTrigger(), true), //When holding a Rock Tera Shard new SpeciesFormChange(Species.OGERPON, "cornerstone-mask", "cornerstone-mask-tera", new SpeciesFormChangeTeraTrigger(Type.ROCK)),
new SpeciesFormChange(Species.OGERPON, "cornerstone-mask-tera", "cornerstone-mask", new SpeciesFormChangeManualTrigger(), true) //When no longer holding a Rock Tera Shard new SpeciesFormChange(Species.OGERPON, "cornerstone-mask-tera", "cornerstone-mask", new SpeciesFormChangeLapseTeraTrigger(), true, new SpeciesFormChangeCondition(p => p.getTeraType() !== Type.ROCK))
], ],
[Species.TERAPAGOS]: [ [Species.TERAPAGOS]: [
new SpeciesFormChange(Species.TERAPAGOS, "", "terastal", new SpeciesFormChangeManualTrigger(), true), new SpeciesFormChange(Species.TERAPAGOS, "", "terastal", new SpeciesFormChangeManualTrigger(), true),
new SpeciesFormChange(Species.TERAPAGOS, "terastal", "stellar", new SpeciesFormChangeManualTrigger(), true), //When holding a Stellar Tera Shard new SpeciesFormChange(Species.TERAPAGOS, "terastal", "stellar", new SpeciesFormChangeTeraTrigger(Type.STELLAR)),
new SpeciesFormChange(Species.TERAPAGOS, "stellar", "terastal", new SpeciesFormChangeManualTrigger(), true) //When no longer holding a Stellar Tera Shard new SpeciesFormChange(Species.TERAPAGOS, "stellar", "terastal", new SpeciesFormChangeLapseTeraTrigger(), true, new SpeciesFormChangeCondition(p => p.getTeraType() !== Type.STELLAR))
], ],
[Species.GALAR_DARMANITAN]: [ [Species.GALAR_DARMANITAN]: [
new SpeciesFormChange(Species.GALAR_DARMANITAN, "", "zen", new SpeciesFormChangeManualTrigger(), true), new SpeciesFormChange(Species.GALAR_DARMANITAN, "", "zen", new SpeciesFormChangeManualTrigger(), true),
new SpeciesFormChange(Species.GALAR_DARMANITAN, "zen", "", new SpeciesFormChangeManualTrigger(), true) new SpeciesFormChange(Species.GALAR_DARMANITAN, "zen", "", new SpeciesFormChangeManualTrigger(), true)
], ],
[Species.EISCUE]: [
new SpeciesFormChange(Species.EISCUE, "", "no-ice", new SpeciesFormChangeManualTrigger(), true),
new SpeciesFormChange(Species.EISCUE, "no-ice", "", new SpeciesFormChangeManualTrigger(), true),
],
[Species.CRAMORANT]: [
new SpeciesFormChange(Species.CRAMORANT, "", "gulping", new SpeciesFormChangeManualTrigger, true, new SpeciesFormChangeCondition(p => p.getHpRatio() >= .5)),
new SpeciesFormChange(Species.CRAMORANT, "", "gorging", new SpeciesFormChangeManualTrigger, true, new SpeciesFormChangeCondition(p => p.getHpRatio() < .5)),
new SpeciesFormChange(Species.CRAMORANT, "gulping", "", new SpeciesFormChangeManualTrigger, true),
new SpeciesFormChange(Species.CRAMORANT, "gorging", "", new SpeciesFormChangeManualTrigger, true),
new SpeciesFormChange(Species.CRAMORANT, "gulping", "", new SpeciesFormChangeActiveTrigger(false), true),
new SpeciesFormChange(Species.CRAMORANT, "gorging", "", new SpeciesFormChangeActiveTrigger(false), true),
],
[Species.CASTFORM]: [
new SpeciesFormChange(Species.CASTFORM, "", "sunny", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.SUNNY, WeatherType.HARSH_SUN]), true),
new SpeciesFormChange(Species.CASTFORM, "rainy", "sunny", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.SUNNY, WeatherType.HARSH_SUN]), true),
new SpeciesFormChange(Species.CASTFORM, "snowy", "sunny", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.SUNNY, WeatherType.HARSH_SUN]), true),
new SpeciesFormChange(Species.CASTFORM, "", "rainy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.RAIN, WeatherType.HEAVY_RAIN]), true),
new SpeciesFormChange(Species.CASTFORM, "sunny", "rainy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.RAIN, WeatherType.HEAVY_RAIN]), true),
new SpeciesFormChange(Species.CASTFORM, "snowy", "rainy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.RAIN, WeatherType.HEAVY_RAIN]), true),
new SpeciesFormChange(Species.CASTFORM, "", "snowy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.HAIL, WeatherType.SNOW]), true),
new SpeciesFormChange(Species.CASTFORM, "sunny", "snowy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.HAIL, WeatherType.SNOW]), true),
new SpeciesFormChange(Species.CASTFORM, "rainy", "snowy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.HAIL, WeatherType.SNOW]), true),
new SpeciesFormChange(Species.CASTFORM, "sunny", "", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FORECAST, [WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG]), true),
new SpeciesFormChange(Species.CASTFORM, "rainy", "", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FORECAST, [WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG]), true),
new SpeciesFormChange(Species.CASTFORM, "snowy", "", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FORECAST, [WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG]), true),
new SpeciesFormChange(Species.CASTFORM, "sunny", "", new SpeciesFormChangeActiveTrigger(), true),
new SpeciesFormChange(Species.CASTFORM, "rainy", "", new SpeciesFormChangeActiveTrigger(), true),
new SpeciesFormChange(Species.CASTFORM, "snowy", "", new SpeciesFormChangeActiveTrigger(), true),
],
[Species.CHERRIM]: [
new SpeciesFormChange(Species.CHERRIM, "overcast", "sunshine", new SpeciesFormChangeWeatherTrigger(Abilities.FLOWER_GIFT, [ WeatherType.SUNNY, WeatherType.HARSH_SUN ]), true),
new SpeciesFormChange(Species.CHERRIM, "sunshine", "overcast", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FLOWER_GIFT, [ WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG, WeatherType.HAIL, WeatherType.HEAVY_RAIN, WeatherType.SNOW, WeatherType.RAIN ]), true),
new SpeciesFormChange(Species.CHERRIM, "sunshine", "overcast", new SpeciesFormChangeActiveTrigger(), true),
],
}; };
export function initPokemonForms() { export function initPokemonForms() {

View File

@ -4,7 +4,7 @@ import { Type } from "./type";
import * as Utils from "../utils"; import * as Utils from "../utils";
import { ChangeMovePriorityAbAttr, applyAbAttrs } from "./ability"; import { ChangeMovePriorityAbAttr, applyAbAttrs } from "./ability";
import { ProtectAttr } from "./move"; import { ProtectAttr } from "./move";
import { BattlerIndex } from "#app/battle.js"; import { BattlerIndex } from "#app/battle";
import i18next from "i18next"; import i18next from "i18next";
export enum TerrainType { export enum TerrainType {

View File

@ -1,4 +1,4 @@
import { VariantTier } from "#app/enums/variant-tier.js"; import { VariantTier } from "#app/enums/variant-tier";
export type Variant = 0 | 1 | 2; export type Variant = 0 | 1 | 2;

View File

@ -88,12 +88,14 @@ export class Weather {
return 1; return 1;
} }
isMoveWeatherCancelled(move: Move): boolean { isMoveWeatherCancelled(user: Pokemon, move: Move): boolean {
const moveType = user.getMoveType(move);
switch (this.weatherType) { switch (this.weatherType) {
case WeatherType.HARSH_SUN: case WeatherType.HARSH_SUN:
return move instanceof AttackMove && move.type === Type.WATER; return move instanceof AttackMove && moveType === Type.WATER;
case WeatherType.HEAVY_RAIN: case WeatherType.HEAVY_RAIN:
return move instanceof AttackMove && move.type === Type.FIRE; return move instanceof AttackMove && moveType === Type.FIRE;
} }
return false; return false;

View File

@ -73,4 +73,7 @@ export enum BattlerTagType {
SHELL_TRAP = "SHELL_TRAP", SHELL_TRAP = "SHELL_TRAP",
DRAGON_CHEER = "DRAGON_CHEER", DRAGON_CHEER = "DRAGON_CHEER",
NO_RETREAT = "NO_RETREAT", NO_RETREAT = "NO_RETREAT",
GORILLA_TACTICS = "GORILLA_TACTICS",
THROAT_CHOPPED = "THROAT_CHOPPED",
TAR_SHOT = "TAR_SHOT",
} }

View File

@ -1,7 +1,7 @@
import { ArenaTagSide } from "#app/data/arena-tag.js"; import { ArenaTagSide } from "#app/data/arena-tag";
import { ArenaTagType } from "#enums/arena-tag-type"; import { ArenaTagType } from "#enums/arena-tag-type";
import { TerrainType } from "#app/data/terrain.js"; import { TerrainType } from "#app/data/terrain";
import { WeatherType } from "#app/data/weather.js"; import { WeatherType } from "#app/data/weather";
/** Alias for all {@linkcode ArenaEvent} type strings */ /** Alias for all {@linkcode ArenaEvent} type strings */
export enum ArenaEventType { export enum ArenaEventType {

View File

@ -60,7 +60,7 @@ export class Arena {
this.scene.arenaBg.setTexture(`${biomeKey}_bg`); this.scene.arenaBg.setTexture(`${biomeKey}_bg`);
this.scene.arenaBgTransition.setTexture(`${biomeKey}_bg`); this.scene.arenaBgTransition.setTexture(`${biomeKey}_bg`);
// Redo this on initialise because during save/load the current wave isn't always // Redo this on initialize because during save/load the current wave isn't always
// set correctly during construction // set correctly during construction
this.updatePoolsForTimeOfDay(); this.updatePoolsForTimeOfDay();
} }
@ -289,7 +289,7 @@ export class Arena {
/** /**
* Sets weather to the override specified in overrides.ts * Sets weather to the override specified in overrides.ts
* @param weather new weather to set of type WeatherType * @param weather new {@linkcode WeatherType} to set
* @returns true to force trySetWeather to return true * @returns true to force trySetWeather to return true
*/ */
trySetWeatherOverride(weather: WeatherType): boolean { trySetWeatherOverride(weather: WeatherType): boolean {
@ -301,8 +301,8 @@ export class Arena {
/** /**
* Attempts to set a new weather to the battle * Attempts to set a new weather to the battle
* @param weather new weather to set of type WeatherType * @param weather {@linkcode WeatherType} new {@linkcode WeatherType} to set
* @param hasPokemonSource is the new weather from a pokemon * @param hasPokemonSource boolean if the new weather is from a pokemon
* @returns true if new weather set, false if no weather provided or attempting to set the same weather as currently in use * @returns true if new weather set, false if no weather provided or attempting to set the same weather as currently in use
*/ */
trySetWeather(weather: WeatherType, hasPokemonSource: boolean): boolean { trySetWeather(weather: WeatherType, hasPokemonSource: boolean): boolean {
@ -391,8 +391,8 @@ export class Arena {
return true; return true;
} }
isMoveWeatherCancelled(move: Move) { isMoveWeatherCancelled(user: Pokemon, move: Move) {
return this.weather && !this.weather.isEffectSuppressed(this.scene) && this.weather.isMoveWeatherCancelled(move); return this.weather && !this.weather.isEffectSuppressed(this.scene) && this.weather.isMoveWeatherCancelled(user, move);
} }
isMoveTerrainCancelled(user: Pokemon, targets: BattlerIndex[], move: Move) { isMoveTerrainCancelled(user: Pokemon, targets: BattlerIndex[], move: Move) {
@ -573,6 +573,12 @@ export class Arena {
this.ignoreAbilities = ignoreAbilities; this.ignoreAbilities = ignoreAbilities;
} }
/**
* Applies each `ArenaTag` in this Arena, based on which side (self, enemy, or both) is passed in as a parameter
* @param tagType Either an {@linkcode ArenaTagType} string, or an actual {@linkcode ArenaTag} class to filter which ones to apply
* @param side {@linkcode ArenaTagSide} which side's arena tags to apply
* @param args array of parameters that the called upon tags may need
*/
applyTagsForSide(tagType: ArenaTagType | Constructor<ArenaTag>, side: ArenaTagSide, ...args: unknown[]): void { applyTagsForSide(tagType: ArenaTagType | Constructor<ArenaTag>, side: ArenaTagSide, ...args: unknown[]): void {
let tags = typeof tagType === "string" let tags = typeof tagType === "string"
? this.tags.filter(t => t.tagType === tagType) ? this.tags.filter(t => t.tagType === tagType)
@ -583,11 +589,28 @@ export class Arena {
tags.forEach(t => t.apply(this, args)); tags.forEach(t => t.apply(this, args));
} }
/**
* Applies the specified tag to both sides (ie: both user and trainer's tag that match the Tag specified)
* by calling {@linkcode applyTagsForSide()}
* @param tagType Either an {@linkcode ArenaTagType} string, or an actual {@linkcode ArenaTag} class to filter which ones to apply
* @param args array of parameters that the called upon tags may need
*/
applyTags(tagType: ArenaTagType | Constructor<ArenaTag>, ...args: unknown[]): void { applyTags(tagType: ArenaTagType | Constructor<ArenaTag>, ...args: unknown[]): void {
this.applyTagsForSide(tagType, ArenaTagSide.BOTH, ...args); this.applyTagsForSide(tagType, ArenaTagSide.BOTH, ...args);
} }
addTag(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves | undefined, sourceId: integer, side: ArenaTagSide = ArenaTagSide.BOTH, quiet: boolean = false, targetIndex?: BattlerIndex): boolean { /**
* Adds a new tag to the arena
* @param tagType {@linkcode ArenaTagType} the tag being added
* @param turnCount How many turns the tag lasts
* @param sourceMove {@linkcode Moves} the move the tag came from, or `undefined` if not from a move
* @param sourceId The ID of the pokemon in play the tag came from (see {@linkcode BattleScene.getPokemonById})
* @param side {@linkcode ArenaTagSide} which side(s) the tag applies to
* @param quiet If a message should be queued on screen to announce the tag being added
* @param targetIndex The {@linkcode BattlerIndex} of the target pokemon
* @returns `false` if there already exists a tag of this type in the Arena
*/
addTag(tagType: ArenaTagType, turnCount: number, sourceMove: Moves | undefined, sourceId: number, side: ArenaTagSide = ArenaTagSide.BOTH, quiet: boolean = false, targetIndex?: BattlerIndex): boolean {
const existingTag = this.getTagOnSide(tagType, side); const existingTag = this.getTagOnSide(tagType, side);
if (existingTag) { if (existingTag) {
existingTag.onOverlap(this); existingTag.onOverlap(this);
@ -600,6 +623,7 @@ export class Arena {
return false; return false;
} }
// creates a new tag object
const newTag = getArenaTag(tagType, turnCount || 0, sourceMove, sourceId, targetIndex, side); const newTag = getArenaTag(tagType, turnCount || 0, sourceMove, sourceId, targetIndex, side);
if (newTag) { if (newTag) {
this.tags.push(newTag); this.tags.push(newTag);
@ -613,6 +637,11 @@ export class Arena {
return true; return true;
} }
/**
* Attempts to get a tag from the Arena via {@linkcode getTagOnSide} that applies to both sides
* @param tagType The {@linkcode ArenaTagType} or {@linkcode ArenaTag} to get
* @returns either the {@linkcode ArenaTag}, or `undefined` if it isn't there
*/
getTag(tagType: ArenaTagType | Constructor<ArenaTag>): ArenaTag | undefined { getTag(tagType: ArenaTagType | Constructor<ArenaTag>): ArenaTag | undefined {
return this.getTagOnSide(tagType, ArenaTagSide.BOTH); return this.getTagOnSide(tagType, ArenaTagSide.BOTH);
} }
@ -621,16 +650,35 @@ export class Arena {
return !!this.getTag(tagType); return !!this.getTag(tagType);
} }
/**
* Attempts to get a tag from the Arena from a specific side (the tag passed in has to either apply to both sides, or the specific side only)
*
* eg: `MIST` only applies to the user's side, while `MUD_SPORT` applies to both user and enemy side
* @param tagType The {@linkcode ArenaTagType} or {@linkcode ArenaTag} to get
* @param side The {@linkcode ArenaTagSide} to look at
* @returns either the {@linkcode ArenaTag}, or `undefined` if it isn't there
*/
getTagOnSide(tagType: ArenaTagType | Constructor<ArenaTag>, side: ArenaTagSide): ArenaTag | undefined { getTagOnSide(tagType: ArenaTagType | Constructor<ArenaTag>, side: ArenaTagSide): ArenaTag | undefined {
return typeof(tagType) === "string" return typeof(tagType) === "string"
? this.tags.find(t => t.tagType === tagType && (side === ArenaTagSide.BOTH || t.side === ArenaTagSide.BOTH || t.side === side)) ? this.tags.find(t => t.tagType === tagType && (side === ArenaTagSide.BOTH || t.side === ArenaTagSide.BOTH || t.side === side))
: this.tags.find(t => t instanceof tagType && (side === ArenaTagSide.BOTH || t.side === ArenaTagSide.BOTH || t.side === side)); : this.tags.find(t => t instanceof tagType && (side === ArenaTagSide.BOTH || t.side === ArenaTagSide.BOTH || t.side === side));
} }
/**
* Uses {@linkcode findTagsOnSide} to filter (using the parameter function) for specific tags that apply to both sides
* @param tagPredicate a function mapping {@linkcode ArenaTag}s to `boolean`s
* @returns array of {@linkcode ArenaTag}s from which the Arena's tags return true and apply to both sides
*/
findTags(tagPredicate: (t: ArenaTag) => boolean): ArenaTag[] { findTags(tagPredicate: (t: ArenaTag) => boolean): ArenaTag[] {
return this.findTagsOnSide(tagPredicate, ArenaTagSide.BOTH); return this.findTagsOnSide(tagPredicate, ArenaTagSide.BOTH);
} }
/**
* Returns specific tags from the arena that pass the `tagPredicate` function passed in as a parameter, and apply to the given side
* @param tagPredicate a function mapping {@linkcode ArenaTag}s to `boolean`s
* @param side The {@linkcode ArenaTagSide} to look at
* @returns array of {@linkcode ArenaTag}s from which the Arena's tags return `true` and apply to the given side
*/
findTagsOnSide(tagPredicate: (t: ArenaTag) => boolean, side: ArenaTagSide): ArenaTag[] { findTagsOnSide(tagPredicate: (t: ArenaTag) => boolean, side: ArenaTagSide): ArenaTag[] {
return this.tags.filter(t => tagPredicate(t) && (side === ArenaTagSide.BOTH || t.side === ArenaTagSide.BOTH || t.side === side)); return this.tags.filter(t => tagPredicate(t) && (side === ArenaTagSide.BOTH || t.side === ArenaTagSide.BOTH || t.side === side));
} }

View File

@ -17,7 +17,7 @@ import { initMoveAnim, loadMoveAnimAssets } from "../data/battle-anims";
import { Status, StatusEffect, getRandomStatus } from "../data/status-effect"; import { Status, StatusEffect, getRandomStatus } from "../data/status-effect";
import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEvolutionCondition, FusionSpeciesFormEvolution } from "../data/pokemon-evolutions"; import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEvolutionCondition, FusionSpeciesFormEvolution } from "../data/pokemon-evolutions";
import { reverseCompatibleTms, tmSpecies, tmPoolTiers } from "../data/tms"; import { reverseCompatibleTms, tmSpecies, tmPoolTiers } from "../data/tms";
import { BattlerTag, BattlerTagLapseType, EncoreTag, GroundedTag, HighestStatBoostTag, TypeImmuneTag, getBattlerTag, SemiInvulnerableTag, TypeBoostTag, MoveRestrictionBattlerTag, ExposedTag, DragonCheerTag, CritBoostTag, TrappedTag } from "../data/battler-tags"; import { BattlerTag, BattlerTagLapseType, EncoreTag, GroundedTag, HighestStatBoostTag, TypeImmuneTag, getBattlerTag, SemiInvulnerableTag, TypeBoostTag, MoveRestrictionBattlerTag, ExposedTag, DragonCheerTag, CritBoostTag, TrappedTag, TarShotTag } from "../data/battler-tags";
import { WeatherType } from "../data/weather"; import { WeatherType } from "../data/weather";
import { ArenaTagSide, NoCritTag, WeakenMoveScreenTag } from "../data/arena-tag"; import { ArenaTagSide, NoCritTag, WeakenMoveScreenTag } from "../data/arena-tag";
import { Ability, AbAttr, StatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentStatStagesAbAttr, MoveImmunityAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldStatMultiplierAbAttrs, FieldMultiplyStatAbAttr, AddSecondStrikeAbAttr, UserFieldStatusEffectImmunityAbAttr, UserFieldBattlerTagImmunityAbAttr, BattlerTagImmunityAbAttr, MoveTypeChangeAbAttr, FullHpResistTypeAbAttr, applyCheckTrappedAbAttrs, CheckTrappedAbAttr } from "../data/ability"; import { Ability, AbAttr, StatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentStatStagesAbAttr, MoveImmunityAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldStatMultiplierAbAttrs, FieldMultiplyStatAbAttr, AddSecondStrikeAbAttr, UserFieldStatusEffectImmunityAbAttr, UserFieldBattlerTagImmunityAbAttr, BattlerTagImmunityAbAttr, MoveTypeChangeAbAttr, FullHpResistTypeAbAttr, applyCheckTrappedAbAttrs, CheckTrappedAbAttr } from "../data/ability";
@ -58,6 +58,7 @@ import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
import { SwitchSummonPhase } from "#app/phases/switch-summon-phase"; import { SwitchSummonPhase } from "#app/phases/switch-summon-phase";
import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-phase"; import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-phase";
import { Challenges } from "#enums/challenges"; import { Challenges } from "#enums/challenges";
import { PLAYER_PARTY_MAX_SIZE } from "#app/constants";
export enum FieldPosition { export enum FieldPosition {
CENTER, CENTER,
@ -983,10 +984,16 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
: this.moveset; : this.moveset;
// Overrides moveset based on arrays specified in overrides.ts // Overrides moveset based on arrays specified in overrides.ts
const overrideArray: Array<Moves> = this.isPlayer() ? Overrides.MOVESET_OVERRIDE : Overrides.OPP_MOVESET_OVERRIDE; let overrideArray: Moves | Array<Moves> = this.isPlayer() ? Overrides.MOVESET_OVERRIDE : Overrides.OPP_MOVESET_OVERRIDE;
if (!Array.isArray(overrideArray)) {
overrideArray = [overrideArray];
}
if (overrideArray.length > 0) { if (overrideArray.length > 0) {
if (!this.isPlayer()) {
this.moveset = [];
}
overrideArray.forEach((move: Moves, index: number) => { overrideArray.forEach((move: Moves, index: number) => {
const ppUsed = this.moveset[index]?.ppUsed || 0; const ppUsed = this.moveset[index]?.ppUsed ?? 0;
this.moveset[index] = new PokemonMove(move, Math.min(ppUsed, allMoves[move].pp)); this.moveset[index] = new PokemonMove(move, Math.min(ppUsed, allMoves[move].pp));
}); });
} }
@ -1049,6 +1056,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const teraType = this.getTeraType(); const teraType = this.getTeraType();
if (teraType !== Type.UNKNOWN) { if (teraType !== Type.UNKNOWN) {
types.push(teraType); types.push(teraType);
if (forDefend) {
return types;
}
} }
} }
@ -1320,9 +1330,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
const trappedByAbility = new Utils.BooleanHolder(false); const trappedByAbility = new Utils.BooleanHolder(false);
const opposingField = this.isPlayer() ? this.scene.getEnemyField() : this.scene.getPlayerField();
this.scene.getEnemyField()!.forEach(enemyPokemon => opposingField.forEach(opponent =>
applyCheckTrappedAbAttrs(CheckTrappedAbAttr, enemyPokemon, trappedByAbility, this, trappedAbMessages, simulated) applyCheckTrappedAbAttrs(CheckTrappedAbAttr, opponent, trappedByAbility, this, trappedAbMessages, simulated)
); );
return (trappedByAbility.value || !!this.getTag(TrappedTag)); return (trappedByAbility.value || !!this.getTag(TrappedTag));
@ -1348,7 +1359,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
/** /**
* Calculates the effectiveness of a move against the Pokémon. * Calculates the effectiveness of a move against the Pokémon.
* * This includes modifiers from move and ability attributes.
* @param source {@linkcode Pokemon} The attacking Pokémon. * @param source {@linkcode Pokemon} The attacking Pokémon.
* @param move {@linkcode Move} The move being used by the attacking Pokémon. * @param move {@linkcode Move} The move being used by the attacking Pokémon.
* @param ignoreAbility Whether to ignore abilities that might affect type effectiveness or immunity (defaults to `false`). * @param ignoreAbility Whether to ignore abilities that might affect type effectiveness or immunity (defaults to `false`).
@ -1368,10 +1379,14 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
: 1); : 1);
applyMoveAttrs(VariableMoveTypeMultiplierAttr, source, this, move, typeMultiplier); applyMoveAttrs(VariableMoveTypeMultiplierAttr, source, this, move, typeMultiplier);
if (this.getTypes().find(t => move.isTypeImmune(source, this, t))) { if (this.getTypes(true, true).find(t => move.isTypeImmune(source, this, t))) {
typeMultiplier.value = 0; typeMultiplier.value = 0;
} }
if (this.getTag(TarShotTag) && (this.getMoveType(move) === Type.FIRE)) {
typeMultiplier.value *= 2;
}
const cancelledHolder = cancelled ?? new Utils.BooleanHolder(false); const cancelledHolder = cancelled ?? new Utils.BooleanHolder(false);
if (!ignoreAbility) { if (!ignoreAbility) {
applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, move, cancelledHolder, simulated, typeMultiplier); applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, move, cancelledHolder, simulated, typeMultiplier);
@ -1403,7 +1418,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
/** /**
* Calculates the type effectiveness multiplier for an attack type * Calculates the move's type effectiveness multiplier based on the target's type/s.
* @param moveType {@linkcode Type} the type of the move being used * @param moveType {@linkcode Type} the type of the move being used
* @param source {@linkcode Pokemon} the Pokemon using the move * @param source {@linkcode Pokemon} the Pokemon using the move
* @param ignoreStrongWinds whether or not this ignores strong winds (anticipation, forewarn, stealth rocks) * @param ignoreStrongWinds whether or not this ignores strong winds (anticipation, forewarn, stealth rocks)
@ -1427,22 +1442,26 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
let multiplier = types.map(defType => { let multiplier = types.map(defType => {
const multiplier = new Utils.NumberHolder(getTypeDamageMultiplier(moveType, defType));
applyChallenges(this.scene.gameMode, ChallengeType.TYPE_EFFECTIVENESS, multiplier);
if (source) { if (source) {
const ignoreImmunity = new Utils.BooleanHolder(false); const ignoreImmunity = new Utils.BooleanHolder(false);
if (source.isActive(true) && source.hasAbilityWithAttr(IgnoreTypeImmunityAbAttr)) { if (source.isActive(true) && source.hasAbilityWithAttr(IgnoreTypeImmunityAbAttr)) {
applyAbAttrs(IgnoreTypeImmunityAbAttr, source, ignoreImmunity, simulated, moveType, defType); applyAbAttrs(IgnoreTypeImmunityAbAttr, source, ignoreImmunity, simulated, moveType, defType);
} }
if (ignoreImmunity.value) { if (ignoreImmunity.value) {
return 1; if (multiplier.value === 0) {
return 1;
}
} }
const exposedTags = this.findTags(tag => tag instanceof ExposedTag) as ExposedTag[]; const exposedTags = this.findTags(tag => tag instanceof ExposedTag) as ExposedTag[];
if (exposedTags.some(t => t.ignoreImmunity(defType, moveType))) { if (exposedTags.some(t => t.ignoreImmunity(defType, moveType))) {
return 1; if (multiplier.value === 0) {
return 1;
}
} }
} }
const multiplier = new Utils.NumberHolder(getTypeDamageMultiplier(moveType, defType));
applyChallenges(this.scene.gameMode, ChallengeType.TYPE_EFFECTIVENESS, multiplier);
return multiplier.value; return multiplier.value;
}).reduce((acc, cur) => acc * cur, 1) as TypeDamageMultiplier; }).reduce((acc, cur) => acc * cur, 1) as TypeDamageMultiplier;
@ -2771,7 +2790,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return this.fusionFaintCry(callback); return this.fusionFaintCry(callback);
} }
const key = `cry/${this.getSpeciesForm().getCryKey(this.formIndex)}`; const key = `cry/${this.species.getCryKey(this.formIndex)}`;
//eslint-disable-next-line @typescript-eslint/no-unused-vars //eslint-disable-next-line @typescript-eslint/no-unused-vars
let i = 0; let i = 0;
let rate = 0.85; let rate = 0.85;
@ -2829,7 +2848,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
private fusionFaintCry(callback: Function): void { private fusionFaintCry(callback: Function): void {
const key = `cry/${this.getSpeciesForm().getCryKey(this.formIndex)}`; const key = `cry/${this.species.getCryKey(this.formIndex)}`;
let i = 0; let i = 0;
let rate = 0.85; let rate = 0.85;
const cry = this.scene.playSound(key, { rate: rate }) as AnySound; const cry = this.scene.playSound(key, { rate: rate }) as AnySound;
@ -2837,7 +2856,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const tintSprite = this.getTintSprite(); const tintSprite = this.getTintSprite();
let duration = cry.totalDuration * 1000; let duration = cry.totalDuration * 1000;
const fusionCryKey = `cry/${this.getFusionSpeciesForm().getCryKey(this.fusionFormIndex)}`; const fusionCryKey = `cry/${this.fusionSpecies?.getCryKey(this.fusionFormIndex)}`;
let fusionCry = this.scene.playSound(fusionCryKey, { rate: rate }) as AnySound; let fusionCry = this.scene.playSound(fusionCryKey, { rate: rate }) as AnySound;
fusionCry.stop(); fusionCry.stop();
duration = Math.min(duration, fusionCry.totalDuration * 1000); duration = Math.min(duration, fusionCry.totalDuration * 1000);
@ -3524,7 +3543,6 @@ export default interface Pokemon {
export class PlayerPokemon extends Pokemon { export class PlayerPokemon extends Pokemon {
public compatibleTms: Moves[]; public compatibleTms: Moves[];
public usedTms: Moves[];
constructor(scene: BattleScene, species: PokemonSpecies, level: integer, abilityIndex?: integer, formIndex?: integer, gender?: Gender, shiny?: boolean, variant?: Variant, ivs?: integer[], nature?: Nature, dataSource?: Pokemon | PokemonData) { constructor(scene: BattleScene, species: PokemonSpecies, level: integer, abilityIndex?: integer, formIndex?: integer, gender?: Gender, shiny?: boolean, variant?: Variant, ivs?: integer[], nature?: Nature, dataSource?: Pokemon | PokemonData) {
super(scene, 106, 148, species, level, abilityIndex, formIndex, gender, shiny, variant, ivs, nature, dataSource); super(scene, 106, 148, species, level, abilityIndex, formIndex, gender, shiny, variant, ivs, nature, dataSource);
@ -3548,7 +3566,6 @@ export class PlayerPokemon extends Pokemon {
} }
} }
this.generateCompatibleTms(); this.generateCompatibleTms();
this.usedTms = [];
} }
initBattleInfo(): void { initBattleInfo(): void {
@ -4458,17 +4475,29 @@ export class EnemyPokemon extends Pokemon {
return BattlerIndex.ENEMY + this.getFieldIndex(); return BattlerIndex.ENEMY + this.getFieldIndex();
} }
addToParty(pokeballType: PokeballType) { /**
* Add a new pokemon to the player's party (at `slotIndex` if set).
* @param pokeballType the type of pokeball the pokemon was caught with
* @param slotIndex an optional index to place the pokemon in the party
* @returns the pokemon that was added or null if the pokemon could not be added
*/
addToParty(pokeballType: PokeballType, slotIndex: number = -1) {
const party = this.scene.getParty(); const party = this.scene.getParty();
let ret: PlayerPokemon | null = null; let ret: PlayerPokemon | null = null;
if (party.length < 6) { if (party.length < PLAYER_PARTY_MAX_SIZE) {
this.pokeball = pokeballType; this.pokeball = pokeballType;
this.metLevel = this.level; this.metLevel = this.level;
this.metBiome = this.scene.arena.biomeType; this.metBiome = this.scene.arena.biomeType;
this.metSpecies = this.species.speciesId; this.metSpecies = this.species.speciesId;
const newPokemon = this.scene.addPlayerPokemon(this.species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this.variant, this.ivs, this.nature, this); const newPokemon = this.scene.addPlayerPokemon(this.species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this.variant, this.ivs, this.nature, this);
party.push(newPokemon);
if (Utils.isBetween(slotIndex, 0, PLAYER_PARTY_MAX_SIZE - 1)) {
party.splice(slotIndex, 0, newPokemon);
} else {
party.push(newPokemon);
}
ret = newPokemon; ret = newPokemon;
this.scene.triggerPokemonFormChange(newPokemon, SpeciesFormChangeActiveTrigger, true); this.scene.triggerPokemonFormChange(newPokemon, SpeciesFormChangeActiveTrigger, true);
} }
@ -4501,6 +4530,7 @@ export interface AttackMoveResult {
} }
export class PokemonSummonData { export class PokemonSummonData {
/** [Atk, Def, SpAtk, SpDef, Spd, Acc, Eva] */
public statStages: number[] = [ 0, 0, 0, 0, 0, 0, 0 ]; public statStages: number[] = [ 0, 0, 0, 0, 0, 0, 0 ];
public moveQueue: QueuedMove[] = []; public moveQueue: QueuedMove[] = [];
public tags: BattlerTag[] = []; public tags: BattlerTag[] = [];

View File

@ -357,7 +357,7 @@ export default class Trainer extends Phaser.GameObjects.Container {
// If useNewSpeciesPool is true, we need to generate a new species from the new species pool, otherwise we generate a random species // If useNewSpeciesPool is true, we need to generate a new species from the new species pool, otherwise we generate a random species
let species = useNewSpeciesPool let species = useNewSpeciesPool
? getPokemonSpecies(newSpeciesPool[Math.floor(Math.random() * newSpeciesPool.length)]) ? getPokemonSpecies(newSpeciesPool[Math.floor(Utils.randSeedInt(newSpeciesPool.length))])
: template.isSameSpecies(index) && index > offset : template.isSameSpecies(index) && index > offset
? getPokemonSpecies(battle.enemyParty[offset].species.getTrainerSpeciesForLevel(level, false, template.getStrength(offset), this.scene.currentBattle.waveIndex)) ? getPokemonSpecies(battle.enemyParty[offset].species.getTrainerSpeciesForLevel(level, false, template.getStrength(offset), this.scene.currentBattle.waveIndex))
: this.genNewPartyMemberSpecies(level, strength); : this.genNewPartyMemberSpecies(level, strength);

View File

@ -16,7 +16,7 @@ import {
getIconForLatestInput, swap, getIconForLatestInput, swap,
} from "#app/configs/inputs/configHandler"; } from "#app/configs/inputs/configHandler";
import BattleScene from "./battle-scene"; import BattleScene from "./battle-scene";
import {SettingGamepad} from "#app/system/settings/settings-gamepad.js"; import {SettingGamepad} from "#app/system/settings/settings-gamepad";
import {SettingKeyboard} from "#app/system/settings/settings-keyboard"; import {SettingKeyboard} from "#app/system/settings/settings-keyboard";
import TouchControl from "#app/touch-controls"; import TouchControl from "#app/touch-controls";
import { Button } from "#enums/buttons"; import { Button } from "#enums/buttons";

View File

@ -7,15 +7,15 @@ import { WindowVariant, getWindowVariantSuffix } from "./ui/ui-theme";
import { isMobile } from "./touch-controls"; import { isMobile } from "./touch-controls";
import * as Utils from "./utils"; import * as Utils from "./utils";
import { initI18n } from "./plugins/i18n"; import { initI18n } from "./plugins/i18n";
import {initPokemonPrevolutions} from "#app/data/pokemon-evolutions"; import { initPokemonPrevolutions } from "#app/data/pokemon-evolutions";
import {initBiomes} from "#app/data/biomes"; import { initBiomes } from "#app/data/biomes";
import {initEggMoves} from "#app/data/egg-moves"; import { initEggMoves } from "#app/data/egg-moves";
import {initPokemonForms} from "#app/data/pokemon-forms"; import { initPokemonForms } from "#app/data/pokemon-forms";
import {initSpecies} from "#app/data/pokemon-species"; import { initSpecies } from "#app/data/pokemon-species";
import {initMoves} from "#app/data/move"; import { initMoves } from "#app/data/move";
import {initAbilities} from "#app/data/ability"; import { initAbilities } from "#app/data/ability";
import {initAchievements} from "#app/system/achv"; import { initAchievements } from "#app/system/achv";
import {initTrainerTypeDialogue} from "#app/data/dialogue"; import { initTrainerTypeDialogue } from "#app/data/dialogue";
import { initChallenges } from "./data/challenge"; import { initChallenges } from "./data/challenge";
import i18next from "i18next"; import i18next from "i18next";
import { initStatsKeys } from "./ui/game-stats-ui-handler"; import { initStatsKeys } from "./ui/game-stats-ui-handler";
@ -250,9 +250,9 @@ export class LoadingScene extends SceneBase {
} }
const availableLangs = ["en", "de", "it", "fr", "ja", "ko", "es", "pt-BR", "zh-CN"]; const availableLangs = ["en", "de", "it", "fr", "ja", "ko", "es", "pt-BR", "zh-CN"];
if (lang && availableLangs.includes(lang)) { if (lang && availableLangs.includes(lang)) {
this.loadImage("september-update-"+lang, "events"); this.loadImage("egg-update_"+lang, "events");
} else { } else {
this.loadImage("september-update-en", "events"); this.loadImage("egg-update_en", "events");
} }
this.loadAtlas("statuses", ""); this.loadAtlas("statuses", "");

View File

@ -12,6 +12,7 @@
"typeImmunityHeal": "{{abilityName}} von {{pokemonNameWithAffix}} füllte einige KP auf!", "typeImmunityHeal": "{{abilityName}} von {{pokemonNameWithAffix}} füllte einige KP auf!",
"nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}} vermeidet Schaden mit {{abilityName}}!", "nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}} vermeidet Schaden mit {{abilityName}}!",
"disguiseAvoidedDamage": "Die Tarnung von {{pokemonNameWithAffix}} ist aufgeflogen!!", "disguiseAvoidedDamage": "Die Tarnung von {{pokemonNameWithAffix}} ist aufgeflogen!!",
"fullHpResistType": "Der Panzer von {{pokemonNameWithAffix}} funkelt und verzerrt die Wechselwirkungen zwischen den Typen!",
"moveImmunity": "Es hat keine Wirkung auf {{pokemonNameWithAffix}}...", "moveImmunity": "Es hat keine Wirkung auf {{pokemonNameWithAffix}}...",
"reverseDrain": "{{pokemonNameWithAffix}} saugt Kloakensoße auf!", "reverseDrain": "{{pokemonNameWithAffix}} saugt Kloakensoße auf!",
"postDefendTypeChange": "{{abilityName}} von {{pokemonNameWithAffix}} macht es zu einem {{typeName}}-Typ!", "postDefendTypeChange": "{{abilityName}} von {{pokemonNameWithAffix}} macht es zu einem {{typeName}}-Typ!",
@ -51,6 +52,7 @@
"postSummonTeravolt": "{{pokemonNameWithAffix}} strahlt eine knisternde Aura aus!", "postSummonTeravolt": "{{pokemonNameWithAffix}} strahlt eine knisternde Aura aus!",
"postSummonDarkAura": "{{pokemonNameWithAffix}} strahlt eine dunkle Aura aus!", "postSummonDarkAura": "{{pokemonNameWithAffix}} strahlt eine dunkle Aura aus!",
"postSummonFairyAura": "{{pokemonNameWithAffix}} strahlt eine Feenaura aus!", "postSummonFairyAura": "{{pokemonNameWithAffix}} strahlt eine Feenaura aus!",
"postSummonAuraBreak": "{{pokemonNameWithAffix}} kehrt die Wirkung aller Aura-Fähigkeiten um!",
"postSummonNeutralizingGas": "Reaktionsgas von {{pokemonNameWithAffix}} hat sich in der Umgebung ausgebreitet!", "postSummonNeutralizingGas": "Reaktionsgas von {{pokemonNameWithAffix}} hat sich in der Umgebung ausgebreitet!",
"postSummonAsOneGlastrier": "{{pokemonNameWithAffix}} verfügt über zwei Fähigkeiten!", "postSummonAsOneGlastrier": "{{pokemonNameWithAffix}} verfügt über zwei Fähigkeiten!",
"postSummonAsOneSpectrier": "{{pokemonNameWithAffix}} verfügt über zwei Fähigkeiten!", "postSummonAsOneSpectrier": "{{pokemonNameWithAffix}} verfügt über zwei Fähigkeiten!",
@ -59,4 +61,4 @@
"postSummonTabletsOfRuin": "Unheilstafeln von {{pokemonNameWithAffix}} schwächt {{statName}} aller Pokémon im Umkreis!", "postSummonTabletsOfRuin": "Unheilstafeln von {{pokemonNameWithAffix}} schwächt {{statName}} aller Pokémon im Umkreis!",
"postSummonBeadsOfRuin": "Unheilsjuwelen von {{pokemonNameWithAffix}} schwächt {{statName}} aller Pokémon im Umkreis!", "postSummonBeadsOfRuin": "Unheilsjuwelen von {{pokemonNameWithAffix}} schwächt {{statName}} aller Pokémon im Umkreis!",
"preventBerryUse": "{{pokemonNameWithAffix}} kriegt vor Anspannung keine Beeren mehr runter!" "preventBerryUse": "{{pokemonNameWithAffix}} kriegt vor Anspannung keine Beeren mehr runter!"
} }

View File

@ -44,6 +44,7 @@
"moveNotImplemented": "{{moveName}} ist noch nicht implementiert und kann nicht ausgewählt werden.", "moveNotImplemented": "{{moveName}} ist noch nicht implementiert und kann nicht ausgewählt werden.",
"moveNoPP": "Es sind keine AP für diese Attacke mehr übrig!", "moveNoPP": "Es sind keine AP für diese Attacke mehr übrig!",
"moveDisabled": "{{moveName}} ist deaktiviert!", "moveDisabled": "{{moveName}} ist deaktiviert!",
"disableInterruptedMove": "{{moveName}} von {{pokemonNameWithAffix}} ist blockiert!",
"noPokeballForce": "Eine unsichtbare Kraft verhindert die Nutzung von Pokébällen.", "noPokeballForce": "Eine unsichtbare Kraft verhindert die Nutzung von Pokébällen.",
"noPokeballTrainer": "Du kannst das Pokémon eines anderen Trainers nicht fangen!", "noPokeballTrainer": "Du kannst das Pokémon eines anderen Trainers nicht fangen!",
"noPokeballMulti": "Du kannst erst einen Pokéball werfen, wenn nur noch ein Pokémon übrig ist!", "noPokeballMulti": "Du kannst erst einen Pokéball werfen, wenn nur noch ein Pokémon übrig ist!",
@ -96,4 +97,4 @@
"congratulations": "Glückwunsch!", "congratulations": "Glückwunsch!",
"beatModeFirstTime": "{{speciesName}} hat den {{gameMode}} Modus zum ersten Mal beendet! Du erhältst {{newModifier}}!", "beatModeFirstTime": "{{speciesName}} hat den {{gameMode}} Modus zum ersten Mal beendet! Du erhältst {{newModifier}}!",
"eggSkipPrompt": "Zur Ei-Zusammenfassung springen?" "eggSkipPrompt": "Zur Ei-Zusammenfassung springen?"
} }

View File

@ -67,5 +67,8 @@
"saltCuredLapse": "{{pokemonNameWithAffix}} wurde durch {{moveName}} verletzt!", "saltCuredLapse": "{{pokemonNameWithAffix}} wurde durch {{moveName}} verletzt!",
"cursedOnAdd": "{{pokemonNameWithAffix}} nimmt einen Teil seiner KP und legt einen Fluch auf {{pokemonName}}!", "cursedOnAdd": "{{pokemonNameWithAffix}} nimmt einen Teil seiner KP und legt einen Fluch auf {{pokemonName}}!",
"cursedLapse": "{{pokemonNameWithAffix}} wurde durch den Fluch verletzt!", "cursedLapse": "{{pokemonNameWithAffix}} wurde durch den Fluch verletzt!",
"stockpilingOnAdd": "{{pokemonNameWithAffix}} hortet {{stockpiledCount}}!" "stockpilingOnAdd": "{{pokemonNameWithAffix}} hortet {{stockpiledCount}}!",
} "disabledOnAdd": " {{moveName}} von {{pokemonNameWithAffix}} wurde blockiert!",
"disabledLapse": "{{moveName}} von {{pokemonNameWithAffix}} ist nicht länger blockiert!",
"tarShotOnAdd": "{{pokemonNameWithAffix}} ist nun schwach gegenüber Feuer-Attacken!"
}

View File

@ -3,5 +3,6 @@
"power": "Stärke", "power": "Stärke",
"accuracy": "Genauigkeit", "accuracy": "Genauigkeit",
"abilityFlyInText": "{{passive}}{{abilityName}} von {{pokemonName}} wirkt!", "abilityFlyInText": "{{passive}}{{abilityName}} von {{pokemonName}} wirkt!",
"passive": "Passive Fähigkeit " "passive": "Passive Fähigkeit ",
"teraHover": "Tera-Typ {{type}}"
} }

View File

@ -51,5 +51,7 @@
"renamePokemon": "Pokémon umbennenen", "renamePokemon": "Pokémon umbennenen",
"rename": "Umbenennen", "rename": "Umbenennen",
"nickname": "Spitzname", "nickname": "Spitzname",
"errorServerDown": "Ups! Es gab einen Fehler beim Versuch\nden Server zu kontaktieren\nLasse dieses Fenster offen\nDu wirst automatisch neu verbunden." "errorServerDown": "Ups! Es gab einen Fehler beim Versuch\nden Server zu kontaktieren\nLasse dieses Fenster offen\nDu wirst automatisch neu verbunden.",
} "noSaves": "Du hast keine gespeicherten Dateien!",
"tooManySaves": "Du hast zu viele gespeicherte Dateien!"
}

View File

@ -47,10 +47,14 @@
"description": "Ändert das Wesen zu {{natureName}}. Schaltet dieses Wesen permanent für diesen Starter frei." "description": "Ändert das Wesen zu {{natureName}}. Schaltet dieses Wesen permanent für diesen Starter frei."
}, },
"DoubleBattleChanceBoosterModifierType": { "DoubleBattleChanceBoosterModifierType": {
"description": "Verdoppelt die Wahrscheinlichkeit, dass die nächsten {{battleCount}} Begegnungen mit wilden Pokémon ein Doppelkampf sind." "description": "Vervierfacht die Chance, dass ein Kampf ein Doppelkampf wird, für bis zu {{battleCount}} Kämpfe."
}, },
"TempStatStageBoosterModifierType": { "TempStatStageBoosterModifierType": {
"description": "Erhöht die {{stat}} aller Teammitglieder für 5 Kämpfe um eine Stufe." "description": "Erhöht {{stat}} aller Teammitglieder um {{amount}} für bis zu 5 Kämpfe.",
"extra": {
"stage": "eine Stufe",
"percentage": "30%"
}
}, },
"AttackTypeBoosterModifierType": { "AttackTypeBoosterModifierType": {
"description": "Erhöht die Stärke aller {{moveType}}-Attacken eines Pokémon um 20%." "description": "Erhöht die Stärke aller {{moveType}}-Attacken eines Pokémon um 20%."

View File

@ -66,5 +66,6 @@
"revivalBlessing": "{{pokemonName}} ist wieder fit und kampfbereit!", "revivalBlessing": "{{pokemonName}} ist wieder fit und kampfbereit!",
"swapArenaTags": "{{pokemonName}} hat die Effekte, die auf den beiden Seiten des Kampffeldes wirken, miteinander getauscht!", "swapArenaTags": "{{pokemonName}} hat die Effekte, die auf den beiden Seiten des Kampffeldes wirken, miteinander getauscht!",
"exposedMove": "{{pokemonName}} erkennt {{targetPokemonName}}!", "exposedMove": "{{pokemonName}} erkennt {{targetPokemonName}}!",
"safeguard": "{{targetName}} wird durch Bodyguard geschützt!" "safeguard": "{{targetName}} wird durch Bodyguard geschützt!",
"afterYou": "{{targetName}} lässt sich auf Galanterie ein!"
} }

View File

@ -3,7 +3,7 @@
"badDreams": "{{pokemonName}} is tormented!", "badDreams": "{{pokemonName}} is tormented!",
"costar": "{{pokemonName}} copied {{allyName}}'s stat changes!", "costar": "{{pokemonName}} copied {{allyName}}'s stat changes!",
"iceFaceAvoidedDamage": "{{pokemonNameWithAffix}} avoided\ndamage with {{abilityName}}!", "iceFaceAvoidedDamage": "{{pokemonNameWithAffix}} avoided\ndamage with {{abilityName}}!",
"perishBody": "{{pokemonName}}'s {{abilityName}}\nwill faint both pokemon in 3 turns!", "perishBody": "{{pokemonName}}'s {{abilityName}}\nwill faint both Pokémon in 3 turns!",
"poisonHeal": "{{pokemonName}}'s {{abilityName}}\nrestored its HP a little!", "poisonHeal": "{{pokemonName}}'s {{abilityName}}\nrestored its HP a little!",
"trace": "{{pokemonName}} copied {{targetName}}'s\n{{abilityName}}!", "trace": "{{pokemonName}} copied {{targetName}}'s\n{{abilityName}}!",
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!", "windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!",
@ -61,4 +61,4 @@
"postSummonTabletsOfRuin": "{{pokemonNameWithAffix}}'s Tablets of Ruin lowered the {{statName}}\nof all surrounding Pokémon!", "postSummonTabletsOfRuin": "{{pokemonNameWithAffix}}'s Tablets of Ruin lowered the {{statName}}\nof all surrounding Pokémon!",
"postSummonBeadsOfRuin": "{{pokemonNameWithAffix}}'s Beads of Ruin lowered the {{statName}}\nof all surrounding Pokémon!", "postSummonBeadsOfRuin": "{{pokemonNameWithAffix}}'s Beads of Ruin lowered the {{statName}}\nof all surrounding Pokémon!",
"preventBerryUse": "{{pokemonNameWithAffix}} is too\nnervous to eat berries!" "preventBerryUse": "{{pokemonNameWithAffix}} is too\nnervous to eat berries!"
} }

View File

@ -44,7 +44,10 @@
"moveNotImplemented": "{{moveName}} is not yet implemented and cannot be selected.", "moveNotImplemented": "{{moveName}} is not yet implemented and cannot be selected.",
"moveNoPP": "There's no PP left for\nthis move!", "moveNoPP": "There's no PP left for\nthis move!",
"moveDisabled": "{{moveName}} is disabled!", "moveDisabled": "{{moveName}} is disabled!",
"canOnlyUseMove": "{{pokemonName}} can only use {{moveName}}!",
"moveCannotBeSelected": "{{moveName}} cannot be selected!",
"disableInterruptedMove": "{{pokemonNameWithAffix}}'s {{moveName}}\nis disabled!", "disableInterruptedMove": "{{pokemonNameWithAffix}}'s {{moveName}}\nis disabled!",
"throatChopInterruptedMove": "The effects of Throat Chop prevent\n{{pokemonName}} from using certain moves!",
"noPokeballForce": "An unseen force\nprevents using Poké Balls.", "noPokeballForce": "An unseen force\nprevents using Poké Balls.",
"noPokeballTrainer": "You can't catch\nanother trainer's Pokémon!", "noPokeballTrainer": "You can't catch\nanother trainer's Pokémon!",
"noPokeballMulti": "You can only throw a Poké Ball\nwhen there is one Pokémon remaining!", "noPokeballMulti": "You can only throw a Poké Ball\nwhen there is one Pokémon remaining!",

View File

@ -69,5 +69,6 @@
"cursedLapse": "{{pokemonNameWithAffix}} is afflicted by the Curse!", "cursedLapse": "{{pokemonNameWithAffix}} is afflicted by the Curse!",
"stockpilingOnAdd": "{{pokemonNameWithAffix}} stockpiled {{stockpiledCount}}!", "stockpilingOnAdd": "{{pokemonNameWithAffix}} stockpiled {{stockpiledCount}}!",
"disabledOnAdd": "{{pokemonNameWithAffix}}'s {{moveName}}\nwas disabled!", "disabledOnAdd": "{{pokemonNameWithAffix}}'s {{moveName}}\nwas disabled!",
"disabledLapse": "{{pokemonNameWithAffix}}'s {{moveName}}\nis no longer disabled." "disabledLapse": "{{pokemonNameWithAffix}}'s {{moveName}}\nis no longer disabled.",
"tarShotOnAdd": "{{pokemonNameWithAffix}} became weaker to fire!"
} }

View File

@ -1,6 +1,6 @@
{ {
"title": "Challenge Modifiers", "title": "Challenge Modifiers",
"illegalEvolution": "{{pokemon}} changed into an ineligble pokémon\nfor this challenge!", "illegalEvolution": "{{pokemon}} changed into an ineligible Pokémon\nfor this challenge!",
"noneSelected": "None Selected", "noneSelected": "None Selected",
"singleGeneration": { "singleGeneration": {
"name": "Mono Gen", "name": "Mono Gen",
@ -34,4 +34,4 @@
"value.0": "Off", "value.0": "Off",
"value.1": "On" "value.1": "On"
} }
} }

View File

@ -2,6 +2,7 @@
"pp": "PP", "pp": "PP",
"power": "Power", "power": "Power",
"accuracy": "Accuracy", "accuracy": "Accuracy",
"abilityFlyInText": " {{pokemonName}}'s {{passive}}{{abilityName}}", "abilityFlyInText": " {{pokemonName}}s\n{{passive}}{{abilityName}}",
"passive": "Passive " "passive": "Passive ",
} "teraHover": "{{type}} Terastallized"
}

View File

@ -7,6 +7,7 @@
"switchedStat": "{{pokemonName}} switched {{stat}} with its target!", "switchedStat": "{{pokemonName}} switched {{stat}} with its target!",
"sharedGuard": "{{pokemonName}} shared its guard with the target!", "sharedGuard": "{{pokemonName}} shared its guard with the target!",
"sharedPower": "{{pokemonName}} shared its power with the target!", "sharedPower": "{{pokemonName}} shared its power with the target!",
"shiftedStats": "{{pokemonName}} switched its {{statToSwitch}} and {{statToSwitchWith}}!",
"goingAllOutForAttack": "{{pokemonName}} is going all out for this attack!", "goingAllOutForAttack": "{{pokemonName}} is going all out for this attack!",
"regainedHealth": "{{pokemonName}} regained\nhealth!", "regainedHealth": "{{pokemonName}} regained\nhealth!",
"keptGoingAndCrashed": "{{pokemonName}} kept going\nand crashed!", "keptGoingAndCrashed": "{{pokemonName}} kept going\nand crashed!",
@ -66,5 +67,6 @@
"revivalBlessing": "{{pokemonName}} was revived!", "revivalBlessing": "{{pokemonName}} was revived!",
"swapArenaTags": "{{pokemonName}} swapped the battle effects affecting each side of the field!", "swapArenaTags": "{{pokemonName}} swapped the battle effects affecting each side of the field!",
"exposedMove": "{{pokemonName}} identified\n{{targetPokemonName}}!", "exposedMove": "{{pokemonName}} identified\n{{targetPokemonName}}!",
"safeguard": "{{targetName}} is protected by Safeguard!" "safeguard": "{{targetName}} is protected by Safeguard!",
} "afterYou": "{{pokemonName}} took the kind offer!"
}

View File

@ -12,6 +12,7 @@
"blockItemTheft": "¡{{pokemonNameWithAffix}} evitó el robo gracias a {{abilityName}}!", "blockItemTheft": "¡{{pokemonNameWithAffix}} evitó el robo gracias a {{abilityName}}!",
"typeImmunityHeal": "¡{{pokemonNameWithAffix}} restauró algunos de sus PS gracias a {{abilityName}}!", "typeImmunityHeal": "¡{{pokemonNameWithAffix}} restauró algunos de sus PS gracias a {{abilityName}}!",
"nonSuperEffectiveImmunity": "¡{{pokemonNameWithAffix}} evitó el daño gracias a {{abilityName}}!", "nonSuperEffectiveImmunity": "¡{{pokemonNameWithAffix}} evitó el daño gracias a {{abilityName}}!",
"fullHpResistType": "¡{{pokemonNameWithAffix}} ha hecho brillar su caparazón\ny ha alterado su compatibilidad entre tipos!",
"moveImmunity": "¡No afecta a {{pokemonNameWithAffix}}!", "moveImmunity": "¡No afecta a {{pokemonNameWithAffix}}!",
"reverseDrain": "¡{{pokemonNameWithAffix}} absorbió lodo líquido!", "reverseDrain": "¡{{pokemonNameWithAffix}} absorbió lodo líquido!",
"postDefendTypeChange": "¡{{abilityName}} de {{pokemonNameWithAffix}} cambió a tipo {{typeName}}!", "postDefendTypeChange": "¡{{abilityName}} de {{pokemonNameWithAffix}} cambió a tipo {{typeName}}!",
@ -51,6 +52,7 @@
"postSummonTeravolt": "¡{{pokemonNameWithAffix}} irradia un aura chisporroteante!", "postSummonTeravolt": "¡{{pokemonNameWithAffix}} irradia un aura chisporroteante!",
"postSummonDarkAura": "¡{{pokemonNameWithAffix}} irradia un aura oscura!", "postSummonDarkAura": "¡{{pokemonNameWithAffix}} irradia un aura oscura!",
"postSummonFairyAura": "¡{{pokemonNameWithAffix}} irradia un aura feérica!", "postSummonFairyAura": "¡{{pokemonNameWithAffix}} irradia un aura feérica!",
"postSummonAuraBreak": "¡{{pokemonNameWithAffix}} ha invertido todas las auras!",
"postSummonNeutralizingGas": "¡El Gas Reactivo de {{pokemonNameWithAffix}} se propaga por toda la zona!", "postSummonNeutralizingGas": "¡El Gas Reactivo de {{pokemonNameWithAffix}} se propaga por toda la zona!",
"postSummonAsOneGlastrier": "¡{{pokemonNameWithAffix}} tiene dos Habilidades!", "postSummonAsOneGlastrier": "¡{{pokemonNameWithAffix}} tiene dos Habilidades!",
"postSummonAsOneSpectrier": "¡{{pokemonNameWithAffix}} tiene dos Habilidades!", "postSummonAsOneSpectrier": "¡{{pokemonNameWithAffix}} tiene dos Habilidades!",

View File

@ -42,6 +42,7 @@
"moveNotImplemented": "{{moveName}} aún no está implementado y no se puede seleccionar.", "moveNotImplemented": "{{moveName}} aún no está implementado y no se puede seleccionar.",
"moveNoPP": "¡No hay suficientes PP\npara este movimiento!", "moveNoPP": "¡No hay suficientes PP\npara este movimiento!",
"moveDisabled": "!No puede usar {{moveName}} porque ha sido anulado!", "moveDisabled": "!No puede usar {{moveName}} porque ha sido anulado!",
"disableInterruptedMove": "¡Se ha anulado el movimiento {{moveName}}\nde {{pokemonNameWithAffix}}!",
"noPokeballForce": "Una fuerza misteriosa\nte impide usar Poké Balls.", "noPokeballForce": "Una fuerza misteriosa\nte impide usar Poké Balls.",
"noPokeballTrainer": "¡No puedes atrapar a los\nPokémon de los demás!", "noPokeballTrainer": "¡No puedes atrapar a los\nPokémon de los demás!",
"noPokeballMulti": "¡No se pueden lanzar Poké Balls\ncuando hay más de un Pokémon!", "noPokeballMulti": "¡No se pueden lanzar Poké Balls\ncuando hay más de un Pokémon!",
@ -85,4 +86,4 @@
"statSeverelyFell_other": "¡{{stats}} de\n{{pokemonNameWithAffix}} han bajado muchísimo!", "statSeverelyFell_other": "¡{{stats}} de\n{{pokemonNameWithAffix}} han bajado muchísimo!",
"statWontGoAnyLower_one": "¡El {{stats}} de {{pokemonNameWithAffix}} no puede bajar más!", "statWontGoAnyLower_one": "¡El {{stats}} de {{pokemonNameWithAffix}} no puede bajar más!",
"statWontGoAnyLower_other": "¡{{stats}} de\n{{pokemonNameWithAffix}} no pueden bajar más!" "statWontGoAnyLower_other": "¡{{stats}} de\n{{pokemonNameWithAffix}} no pueden bajar más!"
} }

View File

@ -67,5 +67,8 @@
"saltCuredLapse": "¡{{moveName}} ha herido a {{pokemonNameWithAffix}}!", "saltCuredLapse": "¡{{moveName}} ha herido a {{pokemonNameWithAffix}}!",
"cursedOnAdd": "¡{{pokemonNameWithAffix}} sacrifica algunos PS y maldice a {{pokemonName}}!", "cursedOnAdd": "¡{{pokemonNameWithAffix}} sacrifica algunos PS y maldice a {{pokemonName}}!",
"cursedLapse": "¡{{pokemonNameWithAffix}} es víctima de una maldición!", "cursedLapse": "¡{{pokemonNameWithAffix}} es víctima de una maldición!",
"stockpilingOnAdd": "¡{{pokemonNameWithAffix}} ha reservado energía por {{stockpiledCount}}ª vez!" "stockpilingOnAdd": "¡{{pokemonNameWithAffix}} ha reservado energía por {{stockpiledCount}}ª vez!",
"disabledOnAdd": "¡Se ha anulado el movimiento {{moveName}}\nde {{pokemonNameWithAffix}}!",
"disabledLapse": "¡El movimiento {{moveName}} de {{pokemonNameWithAffix}} ya no está anulado!",
"tarShotOnAdd": "¡{{pokemonNameWithAffix}} se ha vuelto débil ante el fuego!"
} }

View File

@ -3,5 +3,6 @@
"power": "Potencia", "power": "Potencia",
"accuracy": "Precisión", "accuracy": "Precisión",
"abilityFlyInText": " {{passive}}{{pokemonName}}\n{{abilityName}}", "abilityFlyInText": " {{passive}}{{pokemonName}}\n{{abilityName}}",
"passive": "Pasiva de " "passive": "Pasiva de ",
"teraHover": "Tera-tipo {{type}}"
} }

View File

@ -51,5 +51,7 @@
"renamePokemon": "Renombrar Pokémon.", "renamePokemon": "Renombrar Pokémon.",
"rename": "Renombrar", "rename": "Renombrar",
"nickname": "Apodo", "nickname": "Apodo",
"errorServerDown": "¡Ups! Ha habido un problema al contactar con el servidor.\n\nPuedes mantener esta ventana abierta, el juego se reconectará automáticamente." "errorServerDown": "¡Ups! Ha habido un problema al contactar con el servidor.\n\nPuedes mantener esta ventana abierta, el juego se reconectará automáticamente.",
"noSaves": "No tienes ninguna partida guardada registrada!",
"tooManySaves": "¡Tienes demasiadas partidas guardadas registradas!"
} }

View File

@ -47,10 +47,14 @@
"description": "Cambia la naturaleza de un Pokémon a {{natureName}} y desbloquea permanentemente dicha naturaleza para el inicial." "description": "Cambia la naturaleza de un Pokémon a {{natureName}} y desbloquea permanentemente dicha naturaleza para el inicial."
}, },
"DoubleBattleChanceBoosterModifierType": { "DoubleBattleChanceBoosterModifierType": {
"description": "Duplica la posibilidad de que un encuentro sea una combate doble durante {{battleCount}} combates." "description": "Cuadruplica la posibilidad de que un encuentro sea una combate doble durante {{battleCount}} combates."
}, },
"TempStatStageBoosterModifierType": { "TempStatStageBoosterModifierType": {
"description": "Aumenta la est. {{stat}} de todos los miembros del equipo en 1 nivel durante 5 combates." "description": "Aumenta la est. {{stat}} de todos los miembros del equipo en {{amount}} durante 5 combates.",
"extra": {
"stage": "1 nivel",
"percentage": "30%"
}
}, },
"AttackTypeBoosterModifierType": { "AttackTypeBoosterModifierType": {
"description": "Aumenta la potencia de los movimientos de tipo {{moveType}} de un Pokémon en un 20%." "description": "Aumenta la potencia de los movimientos de tipo {{moveType}} de un Pokémon en un 20%."

View File

@ -12,5 +12,6 @@
"stoleItem": "¡{{pokemonName}} robó el objeto\n{{itemName}} de {{targetName}}!", "stoleItem": "¡{{pokemonName}} robó el objeto\n{{itemName}} de {{targetName}}!",
"statEliminated": "¡Los cambios en estadísticas fueron eliminados!", "statEliminated": "¡Los cambios en estadísticas fueron eliminados!",
"revivalBlessing": "¡{{pokemonName}} ha revivido!", "revivalBlessing": "¡{{pokemonName}} ha revivido!",
"safeguard": "¡{{targetName}} está protegido por Velo Sagrado!" "safeguard": "¡{{targetName}} está protegido por Velo Sagrado!",
"afterYou": "¡{{pokemonName}} ha decidido aprovechar la oportunidad!"
} }

View File

@ -3,14 +3,15 @@
"badDreams": "{{pokemonName}} a le sommeil agité !", "badDreams": "{{pokemonName}} a le sommeil agité !",
"costar": "{{pokemonName}} copie les changements de stats\nde {{allyName}} !", "costar": "{{pokemonName}} copie les changements de stats\nde {{allyName}} !",
"iceFaceAvoidedDamage": "{{pokemonNameWithAffix}} évite les dégâts\navec {{abilityName}} !", "iceFaceAvoidedDamage": "{{pokemonNameWithAffix}} évite les dégâts\navec {{abilityName}} !",
"perishBody": "{{abilityName}} de {{pokemonName}}\nmettra les deux Pokémon K.O. dans trois tours !", "perishBody": "{{abilityName}} de {{pokemonName}}\nmettra les deux Pokémon K.O. dans trois tours !",
"poisonHeal": "{{abilityName}} de {{pokemonName}}\nrestaure un peu ses PV !", "poisonHeal": "{{abilityName}} de {{pokemonName}}\nrestaure un peu ses PV !",
"trace": "{{pokemonName}} copie le talent {{abilityName}}\nde {{targetName}} !", "trace": "{{pokemonName}} copie le talent {{abilityName}}\nde {{targetName}} !",
"windPowerCharged": "{{pokemonName}} a été touché par la capacité {{moveName}} et se charge en électricité !", "windPowerCharged": "{{pokemonName}} a été touché par la capacité {{moveName}} et se charge en électricité !",
"quickDraw": "Tir Vif permet à {{pokemonName}}\ndagir plus vite que dhabitude !", "quickDraw": "Tir Vif permet à {{pokemonName}}\ndagir plus vite que dhabitude !",
"blockItemTheft": "{{abilityName}} de {{pokemonNameWithAffix}}\nempêche son objet dêtre volé !", "blockItemTheft": "{{abilityName}} de {{pokemonNameWithAffix}}\nempêche son objet dêtre volé !",
"typeImmunityHeal": "{{abilityName}} de {{pokemonNameWithAffix}}\nrestaure un peu ses PV !", "typeImmunityHeal": "{{abilityName}} de {{pokemonNameWithAffix}}\nrestaure un peu ses PV !",
"nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}} évite\nles dégâts avec {{abilityName}} !", "nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}} évite\nles dégâts avec {{abilityName}} !",
"fullHpResistType": "{{pokemonNameWithAffix}} fait briller sa carapace\net fausse les affinités de type !",
"disguiseAvoidedDamage": "Le déguisement de {{pokemonNameWithAffix}}\ntombe !", "disguiseAvoidedDamage": "Le déguisement de {{pokemonNameWithAffix}}\ntombe !",
"moveImmunity": "Ça naffecte pas {{pokemonNameWithAffix}}…", "moveImmunity": "Ça naffecte pas {{pokemonNameWithAffix}}…",
"reverseDrain": "{{pokemonNameWithAffix}} aspire\nle suintement !", "reverseDrain": "{{pokemonNameWithAffix}} aspire\nle suintement !",
@ -33,12 +34,12 @@
"battlerTagImmunity": "{{abilityName}} de {{pokemonNameWithAffix}}\nempêche {{battlerTagName}} !", "battlerTagImmunity": "{{abilityName}} de {{pokemonNameWithAffix}}\nempêche {{battlerTagName}} !",
"forewarn": "La capacité {{moveName}}\nde {{pokemonNameWithAffix}} a été détectée !", "forewarn": "La capacité {{moveName}}\nde {{pokemonNameWithAffix}} a été détectée !",
"frisk": "{{pokemonNameWithAffix}} fouille {{opponentName}}\net trouve son talent {{opponentAbilityName}} !", "frisk": "{{pokemonNameWithAffix}} fouille {{opponentName}}\net trouve son talent {{opponentAbilityName}} !",
"postWeatherLapseHeal": "{{abilityName}} de {{pokemonNameWithAffix}}\nrestaure un peu ses PV !", "postWeatherLapseHeal": "{{abilityName}} de {{pokemonNameWithAffix}}\nrestaure un peu ses PV !",
"postWeatherLapseDamage": "{{pokemonNameWithAffix}} est blessé\npar son talent {{abilityName}} !", "postWeatherLapseDamage": "{{pokemonNameWithAffix}} est blessé\npar son talent {{abilityName}} !",
"postTurnLootCreateEatenBerry": "{{pokemonNameWithAffix}} a récolté\nune {{berryName}} !", "postTurnLootCreateEatenBerry": "{{pokemonNameWithAffix}} a récolté\nune {{berryName}} !",
"postTurnHeal": "{{abilityName}} de {{pokemonNameWithAffix}}\nrestaure un peu ses PV !", "postTurnHeal": "{{abilityName}} de {{pokemonNameWithAffix}}\nrestaure un peu ses PV !",
"fetchBall": "{{pokemonNameWithAffix}} trouve\nune {{pokeballName}} !", "fetchBall": "{{pokemonNameWithAffix}} trouve\nune {{pokeballName}} !",
"healFromBerryUse": "{{abilityName}} de {{pokemonNameWithAffix}}\nrestaure un peu ses PV !", "healFromBerryUse": "{{abilityName}} de {{pokemonNameWithAffix}}\nrestaure un peu ses PV !",
"arenaTrap": "{{pokemonNameWithAffix}} empêche\nles changements grâce à son talent {{abilityName}} !", "arenaTrap": "{{pokemonNameWithAffix}} empêche\nles changements grâce à son talent {{abilityName}} !",
"postBattleLoot": "{{pokemonNameWithAffix}} ramasse\nlobjet {{itemName}} !", "postBattleLoot": "{{pokemonNameWithAffix}} ramasse\nlobjet {{itemName}} !",
"postFaintContactDamage": "{{pokemonNameWithAffix}} est blessé\npar son talent {{abilityName}} !", "postFaintContactDamage": "{{pokemonNameWithAffix}} est blessé\npar son talent {{abilityName}} !",
@ -49,8 +50,9 @@
"postSummonAnticipation": "{{pokemonNameWithAffix}}\nest tout tremblant !", "postSummonAnticipation": "{{pokemonNameWithAffix}}\nest tout tremblant !",
"postSummonTurboblaze": "{{pokemonNameWithAffix}} dégage\nune aura de flammes incandescentes !", "postSummonTurboblaze": "{{pokemonNameWithAffix}} dégage\nune aura de flammes incandescentes !",
"postSummonTeravolt": "{{pokemonNameWithAffix}} dégage\nune aura électrique instable !", "postSummonTeravolt": "{{pokemonNameWithAffix}} dégage\nune aura électrique instable !",
"postSummonDarkAura": "{{pokemonNameWithAffix}} dégage\nune aura ténébreuse !", "postSummonDarkAura": "{{pokemonNameWithAffix}} dégage\nune aura ténébreuse !",
"postSummonFairyAura": "{{pokemonNameWithAffix}} dégage\nune aura enchanteresse !", "postSummonFairyAura": "{{pokemonNameWithAffix}} dégage\nune aura enchanteresse !",
"postSummonAuraBreak": "{{pokemonNameWithAffix}} inverse\ntoutes les auras !",
"postSummonNeutralizingGas": "Le gaz inhibiteur {{pokemonNameWithAffix}}\nenvahit les lieux !", "postSummonNeutralizingGas": "Le gaz inhibiteur {{pokemonNameWithAffix}}\nenvahit les lieux !",
"postSummonAsOneGlastrier": "{{pokemonNameWithAffix}}\na deux talents !", "postSummonAsOneGlastrier": "{{pokemonNameWithAffix}}\na deux talents !",
"postSummonAsOneSpectrier": "{{pokemonNameWithAffix}}\na deux talents !", "postSummonAsOneSpectrier": "{{pokemonNameWithAffix}}\na deux talents !",

View File

@ -227,7 +227,7 @@
"name": "Angry Birds" "name": "Angry Birds"
}, },
"MONO_POISON": { "MONO_POISON": {
"name": "Touche moi je tempoisonne !" "name": "Touche moi je tempoisonne !"
}, },
"MONO_GROUND": { "MONO_GROUND": {
"name": "Prévisions : Séisme" "name": "Prévisions : Séisme"
@ -242,7 +242,7 @@
"name": "SOS Fantômes" "name": "SOS Fantômes"
}, },
"MONO_STEEL": { "MONO_STEEL": {
"name": "De type Acier !" "name": "De type Acier !"
}, },
"MONO_FIRE": { "MONO_FIRE": {
"name": "Allumer le feu" "name": "Allumer le feu"

View File

@ -54,4 +54,4 @@
"safeguardOnRemove": "Le terrain nest plus protégé\npar le voile mystérieux !", "safeguardOnRemove": "Le terrain nest plus protégé\npar le voile mystérieux !",
"safeguardOnRemovePlayer": "Votre équipe nest plus protégée\npar le voile mystérieux !", "safeguardOnRemovePlayer": "Votre équipe nest plus protégée\npar le voile mystérieux !",
"safeguardOnRemoveEnemy": "Léquipe ennemie nest plus protégée\npar le voile mystérieux !" "safeguardOnRemoveEnemy": "Léquipe ennemie nest plus protégée\npar le voile mystérieux !"
} }

View File

@ -1,70 +1,71 @@
{ {
"bossAppeared": "Un {{bossName}} apparait.", "bossAppeared": "Un {{bossName}} apparait.",
"trainerAppeared": "Un combat est lancé\npar {{trainerName}} !", "trainerAppeared": "Un combat est lancé\npar {{trainerName}} !",
"trainerAppearedDouble": "Un combat est lancé\npar {{trainerName}} !", "trainerAppearedDouble": "Un combat est lancé\npar {{trainerName}} !",
"trainerSendOut": "{{pokemonName}} est envoyé par\n{{trainerName}} !", "trainerSendOut": "{{pokemonName}} est envoyé par\n{{trainerName}} !",
"singleWildAppeared": "Un {{pokemonName}} sauvage apparait !", "singleWildAppeared": "Un {{pokemonName}} sauvage apparait !",
"multiWildAppeared": "Un {{pokemonName1}} et un {{pokemonName2}}\nsauvages apparaissent !", "multiWildAppeared": "Un {{pokemonName1}} et un {{pokemonName2}}\nsauvages apparaissent !",
"playerComeBack": "{{pokemonName}} !\nReviens !", "playerComeBack": "{{pokemonName}} !\nReviens !",
"trainerComeBack": "{{trainerName}} retire {{pokemonName}} !", "trainerComeBack": "{{trainerName}} retire\n{{pokemonName}} !",
"playerGo": "{{pokemonName}} ! Go !", "playerGo": "{{pokemonName}} ! Go !",
"trainerGo": "{{pokemonName}} est envoyé par\n{{trainerName}} !", "trainerGo": "{{pokemonName}} est envoyé par\n{{trainerName}} !",
"switchQuestion": "Voulez-vous changer\nvotre {{pokemonName}} ?", "switchQuestion": "Voulez-vous changer\n{{pokemonName}} ?",
"trainerDefeated": "Vous avez battu\n{{trainerName}} !", "trainerDefeated": "Vous avez battu\n{{trainerName}} !",
"moneyWon": "Vous remportez\n{{moneyAmount}} ₽ !", "moneyWon": "Vous remportez\n{{moneyAmount}} ₽ !",
"moneyPickedUp": "Vous obtenez {{moneyAmount}} ₽ !", "moneyPickedUp": "Vous obtenez {{moneyAmount}} ₽ !",
"pokemonCaught": "Vous avez attrapé {{pokemonName}} !", "pokemonCaught": "Vous avez attrapé\n{{pokemonName}} !",
"addedAsAStarter": "{{pokemonName}} est ajouté\ncomme starter !", "addedAsAStarter": "{{pokemonName}} est ajouté\ncomme starter !",
"partyFull": "Votre équipe est pleine.\nRelâcher un Pokémon pour {{pokemonName}} ?", "partyFull": "Votre équipe est pleine.\nRelâcher un Pokémon pour {{pokemonName}} ?",
"pokemon": "Pokémon", "pokemon": "de Pokémon",
"sendOutPokemon": "{{pokemonName}} ! Go !", "sendOutPokemon": "{{pokemonName}} ! Go !",
"hitResultCriticalHit": "Coup critique !", "hitResultCriticalHit": "Coup critique !",
"hitResultSuperEffective": "Cest super efficace !", "hitResultSuperEffective": "Cest super efficace !",
"hitResultNotVeryEffective": "Ce nest pas très efficace…", "hitResultNotVeryEffective": "Ce nest pas très efficace…",
"hitResultNoEffect": "Ça naffecte pas {{pokemonName}}…", "hitResultNoEffect": "Ça naffecte pas {{pokemonName}}…",
"hitResultImmune": "{{pokemonName}} nest pas affecté !", "hitResultImmune": "{{pokemonName}} nest pas affecté !",
"hitResultOneHitKO": "K.O. en un coup !", "hitResultOneHitKO": "K.O. en un coup !",
"attackFailed": "Mais cela échoue !", "attackFailed": "Mais cela échoue !",
"attackMissed": "{{pokemonNameWithAffix}}\névite lattaque!", "attackMissed": "{{pokemonNameWithAffix}}\névite lattaque!",
"attackHitsCount": "Touché {{count}} fois !", "attackHitsCount": "Touché {{count}} fois !",
"rewardGain": "Vous recevez\n{{modifierName}} !", "rewardGain": "Vous recevez\n{{modifierName}} !",
"expGain": "{{pokemonName}} gagne\n{{exp}} Points dExp !", "expGain": "{{pokemonName}} gagne\n{{exp}} Points dExp !",
"levelUp": "{{pokemonName}} monte au\nN. {{level}} !", "levelUp": "{{pokemonName}} monte au\nN. {{level}} !",
"learnMove": "{{pokemonName}} apprend\n{{moveName}} !", "learnMove": "{{pokemonName}} apprend\n{{moveName}} !",
"learnMovePrompt": "{{pokemonName}} veut apprendre\n{{moveName}}.", "learnMovePrompt": "{{pokemonName}} veut apprendre\n{{moveName}}.",
"learnMoveLimitReached": "Cependant, {{pokemonName}} connait\ndéjà quatre capacités.", "learnMoveLimitReached": "Cependant, {{pokemonName}} connait\ndéjà quatre capacités.",
"learnMoveReplaceQuestion": "Voulez-vous oublier une capacité\net la remplacer par {{moveName}} ?", "learnMoveReplaceQuestion": "Voulez-vous oublier une capacité\net la remplacer par {{moveName}} ?",
"learnMoveStopTeaching": "Arrêter dapprendre\n{{moveName}} ?", "learnMoveStopTeaching": "Arrêter dapprendre\n{{moveName}} ?",
"learnMoveNotLearned": "{{pokemonName}} na pas appris\n{{moveName}}.", "learnMoveNotLearned": "{{pokemonName}} na pas appris\n{{moveName}}.",
"learnMoveForgetQuestion": "Quelle capacité doit être oubliée ?", "learnMoveForgetQuestion": "Quelle capacité doit être oubliée ?",
"learnMoveForgetSuccess": "{{pokemonName}} oublie comment\nutiliser {{moveName}}.", "learnMoveForgetSuccess": "{{pokemonName}} oublie comment\nutiliser {{moveName}}.",
"countdownPoof": "@d{32}1, @d{15}2, @d{15}et@d{15}… @d{15}… @d{15}… @d{15}@s{se/pb_bounce_1}Tadaaa !", "countdownPoof": "@d{32}1, @d{15}2, @d{15}et@d{15}… @d{15}… @d{15}… @d{15}@s{se/pb_bounce_1}Tadaaa !",
"learnMoveAnd": "Et…", "learnMoveAnd": "Et…",
"levelCapUp": "La limite de niveau\na été augmentée à {{levelCap}} !", "levelCapUp": "La limite de niveau\na été augmentée à {{levelCap}} !",
"moveNotImplemented": "{{moveName}} nest pas encore implémenté et ne peut pas être sélectionné.", "moveNotImplemented": "{{moveName}} nest pas encore implémenté et ne peut pas être sélectionné.",
"moveNoPP": "Il ny a plus de PP pour\ncette capacité !", "moveNoPP": "Il ny a plus de PP pour\ncette capacité !",
"moveDisabled": "{{moveName}} est sous entrave !", "moveDisabled": "{{moveName}} est sous entrave !",
"disableInterruptedMove": "Il y a une entrave sur la capacité {{moveName}}\nde{{pokemonNameWithAffix}} !",
"noPokeballForce": "Une force mystérieuse\nempêche lutilisation des Poké Balls.", "noPokeballForce": "Une force mystérieuse\nempêche lutilisation des Poké Balls.",
"noPokeballTrainer": "Le Dresseur détourne la Ball\nVoler, cest mal !", "noPokeballTrainer": "Le Dresseur détourne la Ball\nVoler, cest mal !",
"noPokeballMulti": "Impossible ! On ne peut pas viser\nquand il y a deux Pokémon !", "noPokeballMulti": "Impossible ! On ne peut pas viser\nquand il y a deux Pokémon !",
"noPokeballStrong": "Le Pokémon est trop fort pour être capturé !\nVous devez dabord laffaiblir !", "noPokeballStrong": "Le Pokémon est trop fort pour être capturé !\nVous devez dabord laffaiblir !",
"noEscapeForce": "Une force mystérieuse\nempêche la fuite.", "noEscapeForce": "Une force mystérieuse\nempêche la fuite.",
"noEscapeTrainer": "On ne senfuit pas dun\ncombat de Dresseurs !", "noEscapeTrainer": "On ne senfuit pas dun\ncombat de Dresseurs !",
"noEscapePokemon": "{{moveName}} de {{pokemonName}}\nempêche {{escapeVerb}} !", "noEscapePokemon": "{{moveName}} de {{pokemonName}}\nempêche {{escapeVerb}} !",
"runAwaySuccess": "Vous prenez la fuite !", "runAwaySuccess": "Vous prenez la fuite !",
"runAwayCannotEscape": "Fuite impossible !", "runAwayCannotEscape": "Fuite impossible !",
"escapeVerbSwitch": "le changement", "escapeVerbSwitch": "le changement",
"escapeVerbFlee": "la fuite", "escapeVerbFlee": "la fuite",
"notDisabled": "La capacité {{moveName}}\nde {{pokemonName}} nest plus sous entrave !", "notDisabled": "La capacité {{moveName}}\nde {{pokemonName}} nest plus sous entrave !",
"turnEndHpRestore": "{{pokemonName}} récupère des PV !", "turnEndHpRestore": "{{pokemonName}} récupère des PV !",
"hpIsFull": "Les PV de {{pokemonName}}\nsont au maximum !", "hpIsFull": "Les PV de {{pokemonName}}\nsont au maximum !",
"skipItemQuestion": "Êtes-vous sûr·e de ne pas vouloir prendre dobjet ?", "skipItemQuestion": "Êtes-vous sûr·e de ne pas vouloir prendre dobjet ?",
"itemStackFull": "Quantité maximale de {{fullItemName}} atteinte.\nVous recevez {{itemName}} à la place.", "itemStackFull": "Quantité maximale de {{fullItemName}} atteinte.\nVous recevez {{itemName}} à la place.",
"eggHatching": "Hein ?", "eggHatching": "Hein ?",
"ivScannerUseQuestion": "Utiliser le Scanner dIV\nsur {{pokemonName}} ?", "ivScannerUseQuestion": "Utiliser le Scanner dIV\nsur {{pokemonName}} ?",
"wildPokemonWithAffix": "{{pokemonName}} sauvage", "wildPokemonWithAffix": "{{pokemonName}} sauvage",
"foePokemonWithAffix": "{{pokemonName}} ennemi", "foePokemonWithAffix": "{{pokemonName}} ennemi",
"useMove": "{{pokemonNameWithAffix}} utilise\n{{moveName}} !", "useMove": "{{pokemonNameWithAffix}} utilise\n{{moveName}} !",
"stealEatBerry": "{{pokemonName}} vole et mange\nla {{berryName}} de {{targetName}} !", "stealEatBerry": "{{pokemonName}} vole et mange\nla {{berryName}} de {{targetName}} !",
"ppHealBerry": "La {{berryName}} de {{pokemonNameWithAffix}}\nrestaure les PP de sa capacité {{moveName}} !", "ppHealBerry": "La {{berryName}} de {{pokemonNameWithAffix}}\nrestaure les PP de sa capacité {{moveName}} !",
"hpHealBerry": "La {{berryName}} de {{pokemonNameWithAffix}}\nrestaure son énergie !", "hpHealBerry": "La {{berryName}} de {{pokemonNameWithAffix}}\nrestaure son énergie !",
@ -73,27 +74,27 @@
"fainted": "{{pokemonNameWithAffix}}\nest K.O. !", "fainted": "{{pokemonNameWithAffix}}\nest K.O. !",
"statsAnd": "et", "statsAnd": "et",
"stats": "Les stats", "stats": "Les stats",
"statRose_one": "{{stats}} de {{pokemonNameWithAffix}}\naugmente !", "statRose_one": "{{stats}} de {{pokemonNameWithAffix}}\naugmente !",
"statRose_other": "{{stats}}\nde {{pokemonNameWithAffix}} augmentent !", "statRose_other": "{{stats}}\nde {{pokemonNameWithAffix}} augmentent !",
"statSharplyRose_one": "{{stats}} de {{pokemonNameWithAffix}}\naugmente beaucoup !", "statSharplyRose_one": "{{stats}} de {{pokemonNameWithAffix}}\naugmente beaucoup !",
"statSharplyRose_other": "{{stats}}\nde {{pokemonNameWithAffix}} augmentent beaucoup !", "statSharplyRose_other": "{{stats}}\nde {{pokemonNameWithAffix}} augmentent beaucoup !",
"statRoseDrastically_one": "{{stats}} de {{pokemonNameWithAffix}}\naugmente énormément !", "statRoseDrastically_one": "{{stats}} de {{pokemonNameWithAffix}}\naugmente énormément !",
"statRoseDrastically_other": "{{stats}}\nde {{pokemonNameWithAffix}} augmentent énormément !", "statRoseDrastically_other": "{{stats}}\nde {{pokemonNameWithAffix}} augmentent énormément !",
"statWontGoAnyHigher_one": "{{stats}} de {{pokemonNameWithAffix}}\nne peut plus augmenter !", "statWontGoAnyHigher_one": "{{stats}} de {{pokemonNameWithAffix}}\nne peut plus augmenter !",
"statWontGoAnyHigher_other": "{{stats}}\nde {{pokemonNameWithAffix}} ne peuvent plus augmenter !", "statWontGoAnyHigher_other": "{{stats}}\nde {{pokemonNameWithAffix}} ne peuvent plus augmenter !",
"statFell_one": "{{stats}} de {{pokemonNameWithAffix}}\nbaisse !", "statFell_one": "{{stats}} de {{pokemonNameWithAffix}}\nbaisse !",
"statFell_other": "{{stats}}\nde {{pokemonNameWithAffix}} baissent !", "statFell_other": "{{stats}}\nde {{pokemonNameWithAffix}} baissent !",
"statHarshlyFell_one": "{{stats}} de {{pokemonNameWithAffix}}\nbaisse beaucoup !", "statHarshlyFell_one": "{{stats}} de {{pokemonNameWithAffix}}\nbaisse beaucoup !",
"statHarshlyFell_other": "{{stats}}\nde {{pokemonNameWithAffix}} baissent beaucoup !", "statHarshlyFell_other": "{{stats}}\nde {{pokemonNameWithAffix}} baissent beaucoup !",
"statSeverelyFell_one": "{{stats}} de {{pokemonNameWithAffix}}\nbaisse énormément !", "statSeverelyFell_one": "{{stats}} de {{pokemonNameWithAffix}}\nbaisse énormément !",
"statSeverelyFell_other": "{{stats}}\nde {{pokemonNameWithAffix}} baissent énormément !", "statSeverelyFell_other": "{{stats}}\nde {{pokemonNameWithAffix}} baissent énormément !",
"statWontGoAnyLower_one": "{{stats}} de {{pokemonNameWithAffix}}\nne peut plus baisser !", "statWontGoAnyLower_one": "{{stats}} de {{pokemonNameWithAffix}}\nne peut plus baisser !",
"statWontGoAnyLower_other": "{{stats}}\nde {{pokemonNameWithAffix}} ne peuvent plus baisser !", "statWontGoAnyLower_other": "{{stats}}\nde {{pokemonNameWithAffix}} ne peuvent plus baisser !",
"transformedIntoType": "{{pokemonName}} transformed\ninto the {{type}} type!", "transformedIntoType": "{{pokemonName}} prend\nle type {{type}} !",
"ppReduced": "Les PP de la capacité {{moveName}}\nde {{targetName}} baissent de {{reduction}} !", "ppReduced": "Les PP de la capacité {{moveName}}\nde {{targetName}} baissent de {{reduction}} !",
"retryBattle": "Voulez-vous réessayer depuis le début du combat ?", "retryBattle": "Voulez-vous réessayer depuis le début du combat ?",
"unlockedSomething": "{{unlockedThing}}\na été débloqué.", "unlockedSomething": "{{unlockedThing}}\na été débloqué.",
"congratulations": "Félicitations !", "congratulations": "Félicitations !",
"beatModeFirstTime": "{{speciesName}} a battu le mode {{gameMode}} pour la première fois !\nVous avez reçu {{newModifier}} !", "beatModeFirstTime": "{{speciesName}} a battu le mode {{gameMode}} pour la première fois !\nVous avez reçu {{newModifier}} !",
"eggSkipPrompt": "Aller directement au résumé des Œufs éclos ?" "eggSkipPrompt": "Aller directement au résumé des Œufs éclos ?"
} }

View File

@ -29,8 +29,8 @@
"nightmareOnAdd": "{{pokemonNameWithAffix}} commence à cauchemarder !", "nightmareOnAdd": "{{pokemonNameWithAffix}} commence à cauchemarder !",
"nightmareOnOverlap": "{{pokemonNameWithAffix}} est\ndéjà prisonnier dun cauchemar !", "nightmareOnOverlap": "{{pokemonNameWithAffix}} est\ndéjà prisonnier dun cauchemar !",
"nightmareLapse": "{{pokemonNameWithAffix}}est\nprisonnier dun cauchemar !", "nightmareLapse": "{{pokemonNameWithAffix}}est\nprisonnier dun cauchemar !",
"encoreOnAdd": "{{pokemonNameWithAffix}} !\nEncore une fois !", "encoreOnAdd": "{{pokemonNameWithAffix}} !\nEncore une fois !",
"encoreOnRemove": "{{pokemonNameWithAffix}} nest\nplus obligé dutiliser la même capacité !", "encoreOnRemove": "{{pokemonNameWithAffix}} nest\nplus obligé dutiliser la même capacité !",
"helpingHandOnAdd": "{{pokemonNameWithAffix}} est prêt\nà aider {{pokemonName}} !", "helpingHandOnAdd": "{{pokemonNameWithAffix}} est prêt\nà aider {{pokemonName}} !",
"ingrainLapse": "{{pokemonNameWithAffix}} absorbe\ndes nutriments avec ses racines !", "ingrainLapse": "{{pokemonNameWithAffix}} absorbe\ndes nutriments avec ses racines !",
"ingrainOnTrap": "{{pokemonNameWithAffix}}\nplante ses racines !", "ingrainOnTrap": "{{pokemonNameWithAffix}}\nplante ses racines !",
@ -50,22 +50,25 @@
"protectedOnAdd": "{{pokemonNameWithAffix}}\nest prêt à se protéger !", "protectedOnAdd": "{{pokemonNameWithAffix}}\nest prêt à se protéger !",
"protectedLapse": "{{pokemonNameWithAffix}}\nse protège !", "protectedLapse": "{{pokemonNameWithAffix}}\nse protège !",
"enduringOnAdd": "{{pokemonNameWithAffix}} se prépare\nà encaisser les coups !", "enduringOnAdd": "{{pokemonNameWithAffix}} se prépare\nà encaisser les coups !",
"enduringLapse": "{{pokemonNameWithAffix}}\nencaisse les coups !", "enduringLapse": "{{pokemonNameWithAffix}}\nencaisse les coups !",
"sturdyLapse": "{{pokemonNameWithAffix}}\nencaisse les coups !", "sturdyLapse": "{{pokemonNameWithAffix}}\nencaisse les coups !",
"perishSongLapse": "Le compte à rebours de Requiem\nde {{pokemonNameWithAffix}} descend à {{turnCount}} !", "perishSongLapse": "Le compte à rebours de Requiem\nde {{pokemonNameWithAffix}} descend à {{turnCount}} !",
"centerOfAttentionOnAdd": "{{pokemonNameWithAffix}} devient\nle centre de lattention !", "centerOfAttentionOnAdd": "{{pokemonNameWithAffix}} devient\nle centre de lattention !",
"truantLapse": "{{pokemonNameWithAffix}} paresse !", "truantLapse": "{{pokemonNameWithAffix}} paresse !",
"slowStartOnAdd": "{{pokemonNameWithAffix}}\nnarrive pas à se motiver !", "slowStartOnAdd": "{{pokemonNameWithAffix}}\nnarrive pas à se motiver !",
"slowStartOnRemove": "{{pokemonNameWithAffix}}\narrive enfin à sy mettre sérieusement !", "slowStartOnRemove": "{{pokemonNameWithAffix}}\narrive enfin à sy mettre sérieusement !",
"highestStatBoostOnAdd": "{{statName}} de {{pokemonNameWithAffix}}\nest renforcée !", "highestStatBoostOnAdd": "{{statName}} de {{pokemonNameWithAffix}}\nest renforcée !",
"highestStatBoostOnRemove": "Leffet du talent {{abilityName}}\nde {{pokemonNameWithAffix}} se dissipe !", "highestStatBoostOnRemove": "Leffet du talent {{abilityName}}\nde {{pokemonNameWithAffix}} se dissipe !",
"magnetRisenOnAdd": "{{pokemonNameWithAffix}} lévite\nsur un champ magnétique !", "magnetRisenOnAdd": "{{pokemonNameWithAffix}} lévite\nsur un champ magnétique !",
"magnetRisenOnRemove": "Le magnétisme de{{pokemonNameWithAffix}}\nse dissipe !", "magnetRisenOnRemove": "Le magnétisme de{{pokemonNameWithAffix}}\nse dissipe !",
"critBoostOnAdd": "{{pokemonNameWithAffix}}\nest prêt à tout donner !", "critBoostOnAdd": "{{pokemonNameWithAffix}}\nest prêt à tout donner !",
"critBoostOnRemove": "{{pokemonNameWithAffix}} se détend.", "critBoostOnRemove": "{{pokemonNameWithAffix}} se détend.",
"saltCuredOnAdd": "{{pokemonNameWithAffix}}\nest couvert de sel !", "saltCuredOnAdd": "{{pokemonNameWithAffix}}\nest couvert de sel !",
"saltCuredLapse": "{{pokemonNameWithAffix}} est blessé\npar la capacité {{moveName}} !", "saltCuredLapse": "{{pokemonNameWithAffix}} est blessé\npar la capacité {{moveName}} !",
"cursedOnAdd": "{{pokemonNameWithAffix}} sacrifie des PV\net lance une malédiction sur {{pokemonName}} !", "cursedOnAdd": "{{pokemonNameWithAffix}} sacrifie des PV\net lance une malédiction sur {{pokemonName}} !",
"cursedLapse": "{{pokemonNameWithAffix}} est touché par la malédiction !", "cursedLapse": "{{pokemonNameWithAffix}} est touché par la malédiction !",
"stockpilingOnAdd": "{{pokemonNameWithAffix}} utilise\nla capacité Stockage {{stockpiledCount}} fois !" "stockpilingOnAdd": "{{pokemonNameWithAffix}} utilise\nla capacité Stockage {{stockpiledCount}} fois !",
} "disabledOnAdd": "La capacité {{moveName}}\nde {{pokemonNameWithAffix}} est mise sous entrave !",
"disabledLapse": "La capacité {{moveName}}\nde {{pokemonNameWithAffix}} nest plus sous entrave !",
"tarShotOnAdd": "{{pokemonNameWithAffix}} est maintenant\nvulnérable au feu !"
}

View File

@ -1,46 +1,46 @@
{ {
"SITRUS": { "SITRUS": {
"name": "Baie Sitrus", "name": "Baie Sitrus",
"effect": "Restaure 25% des PV sils sont inférieurs à 50%." "effect": "Restaure 25% des PV du porteur sils sont inférieurs à 50%."
}, },
"LUM": { "LUM": {
"name": "Baie Prine", "name": "Baie Prine",
"effect": "Soigne tout problème de statut permanant et la confusion." "effect": "Soigne tout problème de statut et la confusion du porteur."
}, },
"ENIGMA": { "ENIGMA": {
"name": "Baie Enigma", "name": "Baie Enigma",
"effect": "Restaure 25% des PV si touché par une capacité super efficace." "effect": "Restaure 25% des PV du porteur sil est touché par une capacité super efficace."
}, },
"LIECHI": { "LIECHI": {
"name": "Baie Lichii", "name": "Baie Lichii",
"effect": "Augmente lAttaque si les PV sont inférieurs à 25%." "effect": "Augmente lAttaque du porteur si ses PV sont inférieurs à 25%."
}, },
"GANLON": { "GANLON": {
"name": "Baie Lingan", "name": "Baie Lingan",
"effect": "Augmente la Défense si les PV sont inférieurs à 25%." "effect": "Augmente la Défense du porteur si ses PV sont inférieurs à 25%."
}, },
"PETAYA": { "PETAYA": {
"name": "Baie Pitaye", "name": "Baie Pitaye",
"effect": "Augmente lAtq. Spé. si les PV sont inférieurs à 25%." "effect": "Augmente lAtq. Spé. du porteur si ses PV sont inférieurs à 25%."
}, },
"APICOT": { "APICOT": {
"name": "Baie Abriko", "name": "Baie Abriko",
"effect": "Augmente la Déf. Spé. si les PV sont inférieurs à 25%." "effect": "Augmente la Déf. Spé. du porteur si ses PV sont inférieurs à 25%."
}, },
"SALAC": { "SALAC": {
"name": "Baie Sailak", "name": "Baie Sailak",
"effect": "Augmente la Vitesse si les PV sont inférieurs à 25%." "effect": "Augmente la Vitesse du porteur si ses PV sont inférieurs à 25%."
}, },
"LANSAT": { "LANSAT": {
"name": "Baie Lansat", "name": "Baie Lansat",
"effect": "Augmente le taux de coups critiques si les PV sont inférieurs à 25%." "effect": "Augmente le taux de coups critiques du porteur si ses PV sont inférieurs à 25%."
}, },
"STARF": { "STARF": {
"name": "Baie Frista", "name": "Baie Frista",
"effect": "Augmente énormément une statistique au hasard si les PV sont inférieurs à 25%." "effect": "Augmente énormément une statistique au hasard du porteur si ses PV sont inférieurs à 25%."
}, },
"LEPPA": { "LEPPA": {
"name": "Baie Mepo", "name": "Baie Mepo",
"effect": "Restaure 10 PP à une capacité dès que ses PP tombent à 0." "effect": "Restaure 10 PP à une capacité du porteur dès que ses PP tombent à 0."
} }
} }

View File

@ -3,5 +3,5 @@
"ball": "Ball", "ball": "Ball",
"pokemon": "Pokémon", "pokemon": "Pokémon",
"run": "Fuite", "run": "Fuite",
"actionMessage": "Que doit faire\n{{pokemonName}} ?" "actionMessage": "Que doit faire\n{{pokemonName}} ?"
} }

View File

@ -1,83 +1,83 @@
{ {
"blue_red_double": { "blue_red_double": {
"encounter": { "encounter": {
"1": "Blue : Hé Red, montrons-lui de quel bois on se chauffe !\n$Red : …\n$Blue : Voilà la puissance du Bourg Palette !" "1": "Blue : Hé Red, montrons-lui de quel bois on se chauffe !\n$Red : …\n$Blue : Voilà la puissance du Bourg Palette !"
}, },
"victory": { "victory": {
"1": "Blue : Cétait un magnifique combat !\n$Red : …" "1": "Blue : Cétait un magnifique combat !\n$Red : …"
} }
}, },
"red_blue_double": { "red_blue_double": {
"encounter": { "encounter": {
"1": "Red : … !\n$Blue : Il est pas très loquace.\n$Blue : Mais ne te laisse pas avoir, ça reste un Maitre Pokémon !" "1": "Red : … !\n$Blue : Il est pas très loquace.\n$Blue : Mais ne te laisse pas avoir, ça reste un Maitre Pokémon !"
}, },
"victory": { "victory": {
"1": "Red : … !\n$Blue : La prochaine fois, on va te battre !" "1": "Red : … !\n$Blue : La prochaine fois, on va te battre !"
} }
}, },
"tate_liza_double": { "tate_liza_double": {
"encounter": { "encounter": {
"1": "Lévy : Héhéhé… Tu en fais une drôle de tête.\n$Tatia : Tu ne tattendais pas à rencontrer deux Champions, nest-ce pas ?\n$Lévy : Nous sommes des jumeaux !\n$Tatia : Nous navons pas besoin de parler entre nous !\n$Lévy : Tu crois pouvoir briser…\n$Tatia : … Notre duo parfait ?" "1": "Lévy : Héhéhé… Tu en fais une drôle de tête.\n$Tatia : Tu ne tattendais pas à rencontrer deux Champions, nest-ce pas ?\n$Lévy : Nous sommes des jumeaux !\n$Tatia : Nous navons pas besoin de parler entre nous !\n$Lévy : Tu crois pouvoir briser…\n$Tatia : … Notre duo parfait ?"
}, },
"victory": { "victory": {
"1": "Lévy : Quoi ? Notre combinaison était parfaite !\n$Tatia : Nous avons encore besoin dentrainement…" "1": "Lévy : Quoi ? Notre combinaison était parfaite !\n$Tatia : Nous avons encore besoin dentrainement…"
} }
}, },
"liza_tate_double": { "liza_tate_double": {
"encounter": { "encounter": {
"1": "Tatia : Hihih… Si tu voyais ta tête !\n$Lévy : Oui, nous sommes deux Champions en un !\n$Tatia : Voici mon frère, Lévy…\n$Lévy : … Et ma sœur, Tatia !\n$Tatia : Tu ne penses pas que notre combinaison est parfaite ?" "1": "Tatia : Hihih… Si tu voyais ta tête !\n$Lévy : Oui, nous sommes deux Champions en un !\n$Tatia : Voici mon frère, Lévy…\n$Lévy : … Et ma sœur, Tatia !\n$Tatia : Tu ne penses pas que notre combinaison est parfaite ?"
}, },
"victory": { "victory": {
"1": "Tatia : Quoi ? Notre combinaison…\n$Lévy : … a échoué !" "1": "Tatia : Quoi ? Notre combinaison…\n$Lévy : … a échoué !"
} }
}, },
"wallace_steven_double": { "wallace_steven_double": {
"encounter": { "encounter": {
"1": "Pierre R. : Marc, montrons-lui la puissance des Maitres !\n$Marc : Tu vas gouter au pouvoir de Hoenn !\n$Pierre R. : Cest parti !" "1": "Pierre R. : Marc, montrons-lui la puissance des Maitres !\n$Marc : Tu vas gouter au pouvoir de Hoenn !\n$Pierre R. : Cest parti !"
}, },
"victory": { "victory": {
"1": "Pierre R. : Cétait un beau combat !\n$Marc : Ce sera notre tour la prochaine fois !" "1": "Pierre R. : Cétait un beau combat !\n$Marc : Ce sera notre tour la prochaine fois !"
} }
}, },
"steven_wallace_double": { "steven_wallace_double": {
"encounter": { "encounter": {
"1": "Pierre R. : Excuse-moi, aurais-tu des Pokémon rares ?\n$Marc : Pierre… Nous sommes là pour nous battre, pas pour frimer avec nos Pokémon.\n$Pierre R. : Oh… Je vois… Commençons alors !" "1": "Pierre R. : Excuse-moi, aurais-tu des Pokémon rares ?\n$Marc : Pierre… Nous sommes là pour nous battre, pas pour frimer avec nos Pokémon.\n$Pierre R. : Oh… Je vois… Commençons alors !"
}, },
"victory": { "victory": {
"1": "Pierre R. : Bien, maintenant que ce combat est clos, montrons-nous nos Pokémon !\n$Marc : Pierre…" "1": "Pierre R. : Bien, maintenant que ce combat est clos, montrons-nous nos Pokémon !\n$Marc : Pierre…"
} }
}, },
"alder_iris_double": { "alder_iris_double": {
"encounter": { "encounter": {
"1": "Goyah : Nous sommes lélite des Dresseurs dUnys !\n$Iris : Rien de mieux que des combats contre des prodiges !" "1": "Goyah : Nous sommes lélite des Dresseurs dUnys !\n$Iris : Rien de mieux que des combats contre des prodiges !"
}, },
"victory": { "victory": {
"1": "Goyah : INCROYABLE ! Tes trop doué !\n$Iris : On gagnera la prochaine fois !" "1": "Goyah : INCROYABLE ! Tes trop doué !\n$Iris : On gagnera la prochaine fois !"
} }
}, },
"iris_alder_double": { "iris_alder_double": {
"encounter": { "encounter": {
"1": "Iris : Bienvenue, Dresseur ! Je suis LA Maitresse dUnys !\n$Goyah : Iris, concentre-toi sil te plait…" "1": "Iris : Bienvenue, Dresseur ! Je suis LA Maitresse dUnys !\n$Goyah : Iris, concentre-toi sil te plait…"
}, },
"victory": { "victory": {
"1": "Iris : On a tout donné et pourtant…\n$Goyah : Cette défaite ne pourra que nous être bénéfique !" "1": "Iris : On a tout donné et pourtant…\n$Goyah : Cette défaite ne pourra que nous être bénéfique !"
} }
}, },
"piers_marnie_double": { "piers_marnie_double": {
"encounter": { "encounter": {
"1": "Rosemary : Frérot, montrons-lui la puissance de Smashings !\n$Peterson : Nous sommes les ténèbres !" "1": "Rosemary : Frérot, montrons-lui la puissance de Smashings !\n$Peterson : Nous sommes les ténèbres !"
}, },
"victory": { "victory": {
"1": "Rosemary : Tas amené la lumière dans les ténèbres !\n$Peterson : Ptêtre un peu trop…" "1": "Rosemary : Tas amené la lumière dans les ténèbres !\n$Peterson : Ptêtre un peu trop…"
} }
}, },
"marnie_piers_double": { "marnie_piers_double": {
"encounter": { "encounter": {
"1": "Peterson : Chauds pour un concert ?\n$Rosemary : Frérot… Il est pas là pour chanter, mais se battre…", "1": "Peterson : Chauds pour un concert ?\n$Rosemary : Frérot… Il est pas là pour chanter, mais se battre…",
"1_female": "Peterson : Chauds pour un concert ?\n$Rosemary : Frérot… Elle est pas là pour chanter, mais se battre…" "1_female": "Peterson : Chauds pour un concert ?\n$Rosemary : Frérot… Elle est pas là pour chanter, mais se battre…"
}, },
"victory": { "victory": {
"1": "Peterson : Ça cest du rock !\n$Rosemary : Frérot…" "1": "Peterson : Ça cest du rock !\n$Rosemary : Frérot…"
} }
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"encounter": "Une fois de plus, te revoilà.\nSais-tu que ce nest point là ta première venue ?\n$Tu as été appelé ici parce que ty es déjà venu.\nUn nombre inimaginable de fois.\n$Mais allons-y, faisons le décompte.\nTu en es très précisément à ton {{cycleCount}}e cycle.\n$Chaque cycle réinitialise ton souvenir du précédent.\nMais étrangement, des bribes subsistent en toi.\n$Jusquà maintenant, tu as toujours échoué. Mais je ressens quelque chose de différent cette fois-ci.\n\n$Tu es la seule présence ici, bien que jai le sentiment den ressentir… une autre.\n$Vas-tu enfin me livrer un affrontement digne de ce nom ?\nCe challenge dont je rêve depuis un millénaire ?\n$Commençons.", "encounter": "Une fois de plus, te revoilà.\nSais-tu que ce nest point là ta première venue ?\n$Tu as été appelé ici parce que ty es déjà venu.\nUn nombre inimaginable de fois.\n$Mais allons-y, faisons le décompte.\nTu en es très précisément à ton {{cycleCount}}e cycle.\n$Chaque cycle réinitialise ton souvenir du précédent.\nMais étrangement, des bribes subsistent en toi.\n$Jusquà maintenant, tu as toujours échoué. Mais je ressens quelque chose de différent cette fois-ci.\n\n$Tu es la seule présence ici, bien que jai le sentiment den ressentir… une autre.\n$Vas-tu enfin me livrer un affrontement digne de ce nom ?\nCe challenge dont je rêve depuis un millénaire ?\n$Commençons.",
"encounter_female": "Une fois de plus, te revoilà.\nSais-tu que ce nest point là ta première venue ?\n$Tu as été appelée ici parce que ty es déjà venue.\nUn nombre inimaginable de fois.\n$Mais allons-y, faisons le décompte.\nTu en es très précisément à ton {{cycleCount}}e cycle.\n$Chaque cycle réinitialise ton souvenir du précédent.\nMais étrangement, des bribes subsistent en toi.\n$Jusquà maintenant, tu as toujours échoué. Mais je ressens quelque chose de différent cette fois-ci.\n\n$Tu es la seule présence ici, bien que jai le sentiment den ressentir… une autre.\n$Vas-tu enfin me livrer un affrontement digne de ce nom ?\nCe challenge dont je rêve depuis un millénaire ?\n$Commençons.", "encounter_female": "Une fois de plus, te revoilà.\nSais-tu que ce nest point là ta première venue ?\n$Tu as été appelée ici parce que ty es déjà venue.\nUn nombre inimaginable de fois.\n$Mais allons-y, faisons le décompte.\nTu en es très précisément à ton {{cycleCount}}e cycle.\n$Chaque cycle réinitialise ton souvenir du précédent.\nMais étrangement, des bribes subsistent en toi.\n$Jusquà maintenant, tu as toujours échoué. Mais je ressens quelque chose de différent cette fois-ci.\n\n$Tu es la seule présence ici, bien que jai le sentiment den ressentir… une autre.\n$Vas-tu enfin me livrer un affrontement digne de ce nom ?\nCe challenge dont je rêve depuis un millénaire ?\n$Commençons.",
"firstStageWin": "Je vois. Cette présence était bien réelle.\nJe nai donc plus besoin de retenir mes coups.\n$Ne me déçoit pas.", "firstStageWin": "Je vois. Cette présence était bien réelle.\nJe nai donc plus besoin de retenir mes coups.\n$Ne me déçoit pas.",
"secondStageWin": "… Magnifique." "secondStageWin": "… Magnifique."
} }

View File

@ -1,6 +1,6 @@
{ {
"ending": "@c{shock}Tes revenu ?@d{32} Ça veut dire…@d{96} que tas gagné ?!\n@c{smile_ehalf}Jaurais dû men douter.\n$@c{smile_eclosed}Bien sûr… Jai toujours eu ce sentiment.\n@c{smile}Cest fini maintenant hein ? Tas brisé ce cycle.\n$@c{smile_ehalf}Tas aussi accompli ton rêve non ?\nTu nas pas connu la moindre défaite.\n$Je serai la seule à me souvenir de ce que tas fait.\n@c{angry_mopen}Je tâcherai de ne pas oublier !\n$@c{smile_wave_wink}Jdéconne !@d{64} @c{smile}Jamais joublierai.@d{32}\nTa légende vivra à jamais dans nos cœurs.\n$@c{smile_wave}Bon,@d{64} il se fait tard…@d{96} je crois ?\nDifficile à dire ici.\n$Rentrons, @c{smile_wave_wink}et demain on se fera un ptit combat, comme au bon vieux temps ?", "ending": "@c{shock}Tes revenu ?@d{32} Ça veut dire…@d{96} que tas gagné ?!\n@c{smile_ehalf}Jaurais dû men douter.\n$@c{smile_eclosed}Bien sûr… Jai toujours eu ce sentiment.\n@c{smile}Cest fini maintenant hein ? Tas brisé ce cycle.\n$@c{smile_ehalf}Tas aussi accompli ton rêve non ?\nTu nas pas connu la moindre défaite.\n$Je serai la seule à me souvenir de ce que tas fait.\n@c{angry_mopen}Je tâcherai de ne pas oublier !\n$@c{smile_wave_wink}Jdéconne !@d{64} @c{smile}Jamais joublierai.@d{32}\nTa légende vivra à jamais dans nos cœurs.\n$@c{smile_wave}Bon,@d{64} il se fait tard…@d{96} je crois ?\nDifficile à dire ici.\n$Rentrons, @c{smile_wave_wink}et demain on se fera un ptit combat, comme au bon vieux temps ?",
"ending_female": "@c{smile}Oh ? Tas gagné ?@d{96} @c{smile_eclosed}Jaurais dû men douter.\nMais te voilà enfin de retour.\n$@c{smile}Cest terminé.@d{64} Tas brisé ce cycle infernal.\n$@c{serious_smile_fists}Tas aussi accompli ton rêve non ?\nTu nas pas connu la moindre défaite.\n$@c{neutral}Je suis le seul à me souvenir de ce que tas fait.@d{96}\nJe pense que ça ira, non ?\n$@c{serious_smile_fists}Ta légende vivra à jamais dans nos cœurs.\n$@c{smile_eclosed}Bref, jen ai un peu marre de ce endroit, pas toi ? Rentrons à la maison.\n$@c{serious_smile_fists}On se fera un ptit combat une fois rentrés ?\nSi tes daccord.", "ending_female": "@c{smile}Oh ? Tas gagné ?@d{96} @c{smile_eclosed}Jaurais dû men douter.\nMais te voilà enfin de retour.\n$@c{smile}Cest terminé.@d{64} Tas brisé ce cycle infernal.\n$@c{serious_smile_fists}Tas aussi accompli ton rêve non ?\nTu nas pas connu la moindre défaite.\n$@c{neutral}Je suis le seul à me souvenir de ce que tas fait.@d{96}\nJe pense que ça ira, non ?\n$@c{serious_smile_fists}Ta légende vivra à jamais dans nos cœurs.\n$@c{smile_eclosed}Bref, jen ai un peu marre de ce endroit, pas toi ? Rentrons à la maison.\n$@c{serious_smile_fists}On se fera un ptit combat une fois rentrés ?\nSi tes daccord.",
"ending_endless": "Félicitations ! Vous avez atteint la fin actuelle.\nPlus de contenu à venir bientôt !", "ending_endless": "Félicitations ! Vous avez atteint la fin actuelle.\nPlus de contenu à venir bientôt !",
"ending_name": "Les devs" "ending_name": "Les devs"
} }

View File

@ -1,50 +1,50 @@
{ {
"youngster": { "youngster": {
"encounter": { "encounter": {
"1": "Hé ! Combat ?", "1": "Hé ! Combat ?",
"2": "Toi aussi tu débutes ?", "2": "Toi aussi tu débutes ?",
"3": "Hé, jme souviens pas de ta tête. Combat !", "3": "Hé, jme souviens pas de ta tête. Combat !",
"4": "Jai perdu, alors jessaye de capturer dautres Pokémon.\nHé, tas lair faible toi ! Allez, combat !", "4": "Jai perdu, alors jessaye de capturer dautres Pokémon.\nHé, tas lair faible toi ! Allez, combat !",
"5": "On sconnait ? Jai comme un doute. Dans tous les cas, sympa de te rencontrer !", "5": "On sconnait ? Jai comme un doute. Dans tous les cas, sympa de te rencontrer !",
"6": "Allez, cest parti !", "6": "Allez, cest parti !",
"7": "Attention, me voilà !\nTu vas voir comment jsuis fort !", "7": "Attention, me voilà !\nTu vas voir comment jsuis fort !",
"8": "Coucou… Tu veux voir mes bô Pokémon ?", "8": "Coucou… Tu veux voir mes bô Pokémon ?",
"9": "Trêve de mondanités. Ramène-toi quand tu le sens !", "9": "Trêve de mondanités. Ramène-toi quand tu le sens !",
"10": "Baisse pas ta garde si tu veux pas pleurer davoir perdu face à un gamin.", "10": "Baisse pas ta garde si tu veux pas pleurer davoir perdu face à un gamin.",
"11": "Jai tout donné pour élever mes Pokémon. Attention à toi si tu leur fait du mal !", "11": "Jai tout donné pour élever mes Pokémon. Attention à toi si tu leur fait du mal !",
"12": "Incroyable que ty sois parvenu ! Mais la suite va pas être une partie de plaisir.", "12": "Incroyable que ty sois parvenu ! Mais la suite va pas être une partie de plaisir.",
"12_female": "Incroyable que ty sois parvenue ! Mais la suite va pas être une partie de plaisir.", "12_female": "Incroyable que ty sois parvenue ! Mais la suite va pas être une partie de plaisir.",
"13": "Les combats sont éternels ! Bienvenue dans un monde sans fin !" "13": "Les combats sont éternels ! Bienvenue dans un monde sans fin !"
}, },
"victory": { "victory": {
"1": "Hé, mais tes trop fort !", "1": "Hé, mais tes trop fort !",
"1_female": "Hé, mais tes trop forte !", "1_female": "Hé, mais tes trop forte !",
"2": "En vrai javais aucune chance hein ?", "2": "En vrai javais aucune chance hein ?",
"3": "Jte retrouverai un jour, et là jte battrai !", "3": "Jte retrouverai un jour, et là jte battrai !",
"4": "Arg… Jai plus aucun Pokémon.", "4": "Arg… Jai plus aucun Pokémon.",
"5": "Non… IMPOSSIBLE ! Pourquoi jai encore perdu…", "5": "Non… IMPOSSIBLE ! Pourquoi jai encore perdu…",
"6": "Non ! Jai perdu !", "6": "Non ! Jai perdu !",
"7": "Waah ! Tes trop incroyable ! Jsuis bouche bée !", "7": "Waah ! Tes trop incroyable ! Jsuis bouche bée !",
"8": "Pourquoi… Comment… Pourtant on est les plus forts, mes Pokémon et moi…", "8": "Pourquoi… Comment… Pourtant on est les plus forts, mes Pokémon et moi…",
"9": "Jperdrai pas la prochaine fois ! Remettons ça un jour !", "9": "Jperdrai pas la prochaine fois ! Remettons ça un jour !",
"10": "Weeeesh ! Tu vois que jsuis quun gamin ? Cest pas juste de me bully comme ça !", "10": "Weeeesh ! Tu vois que jsuis quun gamin ? Cest pas juste de me bully comme ça !",
"11": "Tes Pokémon sont trop incroyables !\n… Ptit échange ?", "11": "Tes Pokémon sont trop incroyables !\n… Ptit échange ?",
"12": "Je me suis fait un peu aider plus tôt, mais de quel taf je parlais ?", "12": "Je me suis fait un peu aider plus tôt, mais de quel taf je parlais ?",
"13": "Ahaha ! Et voilà, ça y est !\nTes déjà comme chez toi dans ce monde !" "13": "Ahaha ! Et voilà, ça y est !\nTes déjà comme chez toi dans ce monde !"
} }
}, },
"lass": { "lass": {
"encounter": { "encounter": {
"1": "Affrontons-nous, daccord ?", "1": "Affrontons-nous, daccord ?",
"2": "Tas lair dun nouveau Dresseur. Battons nous !", "2": "Tas lair dun nouveau Dresseur. Battons nous !",
"2_female": "Tas lair dune nouvelle Dresseuse. Battons nous !", "2_female": "Tas lair dune nouvelle Dresseuse. Battons nous !",
"3": "Je te connais pas. Ça te dis de te battre ?", "3": "Je te connais pas. Ça te dis de te battre ?",
"4": "Prenons du bon temps avec ce combat Pokémon !", "4": "Prenons du bon temps avec ce combat Pokémon !",
"5": "Je vais tapprendre à te battre avec tes Pokémon !", "5": "Je vais tapprendre à te battre avec tes Pokémon !",
"6": "Un combat doit toujours être pris au sérieux.\nTes prêt à te battre ?", "6": "Un combat doit toujours être pris au sérieux.\nTes prêt à te battre ?",
"6_female": "Un combat doit toujours être pris au sérieux.\nTes prête à te battre ?", "6_female": "Un combat doit toujours être pris au sérieux.\nTes prête à te battre ?",
"7": "Tu seras pas jeune éternellement. Tas quune chance pendant un combat. Bientôt, tu seras plus quun souvenir.", "7": "Tu seras pas jeune éternellement. Tas quune chance pendant un combat. Bientôt, tu seras plus quun souvenir.",
"8": "Tu ferais mieux dy aller doucement avec moi. Mais je vais me battre sérieusement !", "8": "Tu ferais mieux dy aller doucement avec moi. Mais je vais me battre sérieusement !",
"9": "Je mennuie à lécole. Ya rien à y faire. *Baille*\nJe me bats juste pour passer le temps." "9": "Je mennuie à lécole. Ya rien à y faire. *Baille*\nJe me bats juste pour passer le temps."
}, },
"victory": { "victory": {
@ -52,12 +52,12 @@
"2": "Je ne pensais pas que je perdrais comme ça…", "2": "Je ne pensais pas que je perdrais comme ça…",
"2_female": "Je pensais pas que je perdrais comme ça…", "2_female": "Je pensais pas que je perdrais comme ça…",
"3": "Jespère que jaurai ma revanche un jour.", "3": "Jespère que jaurai ma revanche un jour.",
"4": "Cétait super amusant ! Mais ce combat ma épuisée…", "4": "Cétait super amusant ! Mais ce combat ma épuisée…",
"5": "Tu mas appris une belle leçon ! Tes vraiment incroyable !", "5": "Tu mas appris une belle leçon ! Tes vraiment incroyable !",
"6": "Vraiment ? Jai perdu… ? Cest des choses qui arrivent, ça me déprime mais tu es vraiment très cool.", "6": "Vraiment ? Jai perdu… ? Bon, ça arrive, mais cétait cool quand même.",
"6_female": "Vraiment ? Jai perdu… ? Cest des choses qui arrivent, ça me déprime mais tes vraiment très cool.", "6_female": "Vraiment ? Jai perdu… ? Bon, ça arrive, mais cétait cool quand même.",
"7": "Jai pas besoin de ce genre de souvenirs.\n*Suppression de mémoire en cours…*", "7": "Jai pas besoin de ce genre de souvenirs.\n*Suppression de mémoire en cours…*",
"8": "Hé ! Je tavais dit dy aller doucement avec moi ! Mais tes vraiment si cool quand tu te bats sérieusement…", "8": "Hé ! Je tavais dit dy aller doucement avec moi ! Mais tes vraiment si cool quand tu te bats sérieusement…",
"9": "Jen ai marre des combats Pokémon…\nJe vais chercher dautres trucs à faire…" "9": "Jen ai marre des combats Pokémon…\nJe vais chercher dautres trucs à faire…"
} }
}, },
@ -123,7 +123,7 @@
"encounter": { "encounter": {
"1": "Cest lheure de plonger dans le vif !", "1": "Cest lheure de plonger dans le vif !",
"2": "Cest le moment de surfer sur les vagues de la victoire !", "2": "Cest le moment de surfer sur les vagues de la victoire !",
"3": "Je vais téclabousser de mon talent !" "3": "Je vais téclabousser de mon talent !"
}, },
"victory": { "victory": {
"1": "Tu mas complètement séché", "1": "Tu mas complètement séché",
@ -169,10 +169,10 @@
}, },
"parasol_lady": { "parasol_lady": {
"encounter": { "encounter": {
"1": "Honorons ce terrain de combat avec élégance et équilibre !" "1": "Honorons ce terrain de combat avec élégance et équilibre !"
}, },
"victory": { "victory": {
"1": "Mon élégance demeure inébranlable !" "1": "Mon élégance demeure inébranlable !"
} }
}, },
"rocket_grunt": { "rocket_grunt": {
@ -314,8 +314,8 @@
"3": "On est juste des gars et des meufs normaux, on voit un Pokémon on le prend !", "3": "On est juste des gars et des meufs normaux, on voit un Pokémon on le prend !",
"4": "Pourquoi tu te la joue comme ça ? C'est avec tes dents que tvas jouer frérot.", "4": "Pourquoi tu te la joue comme ça ? C'est avec tes dents que tvas jouer frérot.",
"4_female": "Pourquoi tu te la joue comme ça ? C'est avec tes dents que tvas jouer ma reus.", "4_female": "Pourquoi tu te la joue comme ça ? C'est avec tes dents que tvas jouer ma reus.",
"5": "Cousin, écoute-nous bien ! ♪\nSe taper dessus, ça sert à rien ! ♪\n$Tu tincrustes chez nous, ça sfait pas ! ♪\n$Mais on est sympa, on a un plan pour toi ! ♪", "5": "Cousin, écoute-nous bien ! ♪\nSe taper dessus, ça sert à rien ! ♪\n$Tu tincrustes chez nous, ça sfait pas ! ♪\nMais on est sympa, on a un plan pour toi ! ♪",
"5_female": "Cousine, écoute-nous bien ! ♪\nSe taper dessus, ça sert à rien ! ♪\n$Tu tincrustes chez nous, ça sfait pas ! ♪\n$Mais on est sympa, on a un plan pour toi ! ♪" "5_female": "Cousine, écoute-nous bien ! ♪\nSe taper dessus, ça sert à rien ! ♪\n$Tu tincrustes chez nous, ça sfait pas ! ♪\nMais on est sympa, on a un plan pour toi ! ♪"
}, },
"victory": { "victory": {
"1": "Hein ? Cest déjà terminé ?", "1": "Hein ? Cest déjà terminé ?",
@ -528,14 +528,14 @@
"3": "Ouah ! Tes super balèze !" "3": "Ouah ! Tes super balèze !"
}, },
"defeat": { "defeat": {
"1": "Quen dis-tu? Cest ça, la puissance des Pokémon Eau !", "1": "Quen dis-tu ? Cest ça, la puissance des Pokémon Eau !",
"2": "Jespère que tas pris note des élégantes techniques de nage de mes Pokémon !", "2": "Jespère que tas pris note des élégantes techniques de nage de mes Pokémon !",
"3": "Tes Pokémon ne jouent visiblement pas dans le même bassin…" "3": "Tes Pokémon ne jouent visiblement pas dans le même bassin…"
} }
}, },
"lt_surge": { "lt_surge": {
"encounter": { "encounter": {
"1": "Tas pas froid aux yeux, soldat ! Les combats Pokémon, cest la guerre !", "1": "Tas pas froid aux yeux, soldat ! Les combats Pokémon, cest la guerre !",
"2": "Tu as du guts pour venir me fight ici ! Je vais te shock !", "2": "Tu as du guts pour venir me fight ici ! Je vais te shock !",
"3": "Compte tes dents, tu vas morfler !\nMes Pokémon Électrik vont tatomiser !" "3": "Compte tes dents, tu vas morfler !\nMes Pokémon Électrik vont tatomiser !"
}, },
@ -573,56 +573,56 @@
}, },
"alder": { "alder": {
"encounter": { "encounter": {
"1": "Prépare-toi pour un combat contre le meilleur Dresseur dUnys !" "1": "Prépare-toi pour un combat contre le meilleur Dresseur dUnys !"
}, },
"victory": { "victory": {
"1": "Bien joué ! Tu as sans aucun doute un talent inégalé." "1": "Bien joué ! Tu as sans aucun doute un talent inégalé."
}, },
"defeat": { "defeat": {
"1": "Une brise fraiche traverse mon cœur…\n$Quel effort extraordinaire !" "1": "Une brise fraiche traverse mon cœur…\n$Quel effort extraordinaire !"
} }
}, },
"kieran": { "kieran": {
"encounter": { "encounter": {
"1": "Grâce à un travail acharné, je deviens de plus en plus fort !\n$Je ne perdrai pas." "1": "Grâce à un travail acharné, je deviens de plus en plus fort !\n$Je ne perdrai pas."
}, },
"victory": { "victory": {
"1": "Je ny crois pas…\n$Quel combat amusant et palpitant !" "1": "Je ny crois pas…\n$Quel combat amusant et palpitant !"
}, },
"defeat": { "defeat": {
"1": "Eh beh, quel combat !\n$Il est temps pour toi de tentrainer encore plus dur." "1": "Eh beh, quel combat !\n$Il est temps pour toi de tentrainer encore plus dur."
} }
}, },
"rival": { "rival": {
"encounter": { "encounter": {
"1": "@c{smile}Ah, je te cherchais ! Je savais que tétais pressée de partir, mais je mattendais quand même à un au revoir…\n$@c{smile_eclosed}Tas finalement décidé de réaliser ton rêve ?\nJai peine à y croire.\n$@c{serious_smile_fists}Vu que tes là, ça te dis un petit combat ?\nJe voudrais quand même massurer que tes prête.\n$@c{serious_mopen_fists}Surtout ne te retiens pas et donne-moi tout ce que tas !" "1": "@c{smile}Ah, je te cherchais ! Je savais que tétais pressée de partir, mais je mattendais quand même à un au revoir…\n$@c{smile_eclosed}Tas finalement décidé de réaliser ton rêve ?\nJai peine à y croire.\n$@c{serious_smile_fists}Vu que tes là, ça te dis un petit combat ?\nJe voudrais quand même massurer que tes prête.\n$@c{serious_mopen_fists}Surtout ne te retiens pas et donne-moi tout ce que tas !"
}, },
"victory": { "victory": {
"1": "@c{shock}Wah… Tu mas vraiment lavé.\nTes vraiment une débutante ?\n$@c{smile}Tas peut-être eu de la chance, mais…\nPeut-être que tarriveras jusquau bout du chemin.\n$Dailleurs, le prof ma demandé de te filer ces objets.\nIls ont lair sympas.\n$@c{serious_smile_fists}Bonne chance à toi !" "1": "@c{shock}Wah… Tu mas vraiment lavé.\nTes vraiment une débutante ?\n$@c{smile}Tas peut-être eu de la chance, mais…\nPeut-être que tarriveras jusquau bout du chemin.\n$Dailleurs, le prof ma demandé de te filer ces objets.\nIls ont lair sympas.\n$@c{serious_smile_fists}Bonne chance à toi !"
} }
}, },
"rival_female": { "rival_female": {
"encounter": { "encounter": {
"1": "@c{smile_wave}Ah, te voilà ! Je tai cherché partout !\n@c{angry_mopen}On oublie de dire au revoir à sa meilleure amie ?\n$@c{smile_ehalf}Tas décidé de réaliser ton rêve, hein ?\nCe jour est donc vraiment arrivé…\n$@c{smile}Je veux bien te pardonner de mavoir oubliée,\nà une condition. @c{smile_wave_wink}Que tu maffronte !\n$@c{angry_mopen}Donne tout ! Ce serait dommage que ton aventure finisse avant davoir commencé, hein ?" "1": "@c{smile_wave}Ah, te voilà ! Je tai cherché partout !\n@c{angry_mopen}On oublie de dire au revoir à sa meilleure amie ?\n$@c{smile_ehalf}Tas décidé de réaliser ton rêve, hein ?\nCe jour est donc vraiment arrivé…\n$@c{smile}Je veux bien te pardonner de mavoir oubliée,\nà une condition. @c{smile_wave_wink}Que tu maffronte !\n$@c{angry_mopen}Donne tout ! Ce serait dommage que ton aventure finisse avant davoir commencé, hein ?"
}, },
"victory": { "victory": {
"1": "@c{shock}Tu viens de commencer et tes déjà si fort ?!@d{96}\n@c{angry}Tas triché non ? Avoue !\n$@c{smile_wave_wink}Jdéconne !@d{64} @c{smile_eclosed}Jai perdu dans les règles…\nJai le sentiment que tu vas très bien ten sortir.\n$@c{smile}Dailleurs, le prof veut que je te donne ces quelques objets. Ils te seront utiles, pour sûr !\n$@c{smile_wave}Fais de ton mieux, comme toujours !\nJe crois fort en toi !" "1": "@c{shock}Tu viens de commencer et tes déjà si fort ?!@d{96}\n@c{angry}Tas triché non ? Avoue !\n$@c{smile_wave_wink}Jdéconne !@d{64} @c{smile_eclosed}Jai perdu dans les règles…\nJai le sentiment que tu vas très bien ten sortir.\n$@c{smile}Dailleurs, le prof veut que je te donne ces quelques objets. Ils te seront utiles, pour sûr !\n$@c{smile_wave}Fais de ton mieux, comme toujours !\nJe crois fort en toi !"
} }
}, },
"rival_2": { "rival_2": {
"encounter": { "encounter": {
"1": "@c{smile}Hé, toi aussi tes là ?\n@c{smile_eclosed}Toujours invaincue, hein… ?\n$@c{serious_mopen_fists}Je sais que jai lair de tavoir suivie ici, mais cest pas complètement vrai.\n$@c{serious_smile_fists}Pour être honnête, ça me démangeait davoir une revanche depuis que tu mas battu.\n$Je me suis beaucoup entrainé, alors sois sure que je vais pas retenir mes coups cette fois.\n$@c{serious_mopen_fists}Et comme la dernière fois, ne te retiens pas !\nCest parti !" "1": "@c{smile}Hé, toi aussi tes là ?\n@c{smile_eclosed}Toujours invaincue, hein… ?\n$@c{serious_mopen_fists}Je sais que jai lair de tavoir suivie ici, mais cest pas complètement vrai.\n$@c{serious_smile_fists}Pour être honnête, ça me démangeait davoir une revanche depuis que tu mas battu.\n$Je me suis beaucoup entrainé, alors sois sure que je vais pas retenir mes coups cette fois.\n$@c{serious_mopen_fists}Et comme la dernière fois, ne te retiens pas !\nCest parti !"
}, },
"victory": { "victory": {
"1": "@c{neutral_eclosed}Oh. Je crois que jai trop pris la confiance.\n$@c{smile}Pas grave, cest OK. Je me doutais que ça arriverait.\n@c{serious_mopen_fists}Je vais juste devoir encore plus mentrainer !\n\n$@c{smile}Ah, et pas que taies réellement besoin daide, mais jai ça en trop sur moi qui pourrait tintéresser.\n\n$@c{serious_smile_fists}Mais nespère plus en avoir dautres !\nJe peux pas passer mon temps à aider mon adversaire.\n$@c{smile}Bref, prends soin de toi !" "1": "@c{neutral_eclosed}Oh. Je crois que jai trop pris la confiance.\n$@c{smile}Pas grave, cest OK. Je me doutais que ça arriverait.\n@c{serious_mopen_fists}Je vais juste devoir encore plus mentrainer !\n\n$@c{smile}Ah, et pas que taies réellement besoin daide, mais jai ça en trop sur moi qui pourrait tintéresser.\n\n$@c{serious_smile_fists}Mais nespère plus en avoir dautres !\nJe peux pas passer mon temps à aider mon adversaire.\n$@c{smile}Bref, prends soin de toi !"
} }
}, },
"rival_2_female": { "rival_2_female": {
"encounter": { "encounter": {
"1": "@c{smile_wave}Hé, sympa de te croiser ici. Tas toujours lair invaincu. @c{angry_mopen}Eh… Pas mal !\n$@c{angry_mopen}Je sais à quoi tu penses et non, je tespionne pas.\n@c{smile_eclosed}Cest juste que jétais aussi dans le coin.\n$@c{smile_ehalf}Heureuse pour toi, mais je veux juste te rappeler que cest pas grave de perdre parfois.\n$@c{smile}On apprend de nos erreurs, souvent plus que si on ne connaissait que le succès.\n$@c{angry_mopen}Dans tous les cas je me suis bien entrainée pour cette revanche, tas intérêt à tout donner !" "1": "@c{smile_wave}Hé, sympa de te croiser ici. Tas toujours lair invaincu. @c{angry_mopen}Eh… Pas mal !\n$@c{angry_mopen}Je sais à quoi tu penses et non, je tespionne pas.\n@c{smile_eclosed}Cest juste que jétais aussi dans le coin.\n$@c{smile_ehalf}Heureuse pour toi, mais je veux juste te rappeler que cest pas grave de perdre parfois.\n$@c{smile}On apprend de nos erreurs, souvent plus que si on ne connaissait que le succès.\n$@c{angry_mopen}Dans tous les cas je me suis bien entrainée pour cette revanche, tas intérêt à tout donner !"
}, },
"victory": { "victory": {
"1": "@c{neutral}Je… Jétais pas encore supposée perdre…\n$@c{smile}Bon. Ça veut juste dire que je vais devoir encore plus mentrainer !\n$@c{smile_wave}Jai aussi ça en rab pour toi !\n@c{smile_wave_wink}Inutile de me remercier ~.\n$@c{angry_mopen}Cétaient les derniers, terminé les cadeaux après ceux-là !\n$@c{smile_wave}Allez, tiens le coup !" "1": "@c{neutral}Je… Jétais pas encore supposée perdre…\n$@c{smile}Bon. Ça veut juste dire que je vais devoir encore plus mentrainer !\n$@c{smile_wave}Jai aussi ça en rab pour toi !\n@c{smile_wave_wink}Inutile de me remercier ~.\n$@c{angry_mopen}Cétaient les derniers, terminé les cadeaux après ceux-là !\n$@c{smile_wave}Allez, tiens le coup !"
}, },
"defeat": { "defeat": {
"1": "Je suppose que cest parfois normal de perdre…" "1": "Je suppose que cest parfois normal de perdre…"
@ -630,18 +630,18 @@
}, },
"rival_3": { "rival_3": {
"encounter": { "encounter": {
"1": "@c{smile}Hé, mais qui voilà ! Ça fait un bail.\n@c{neutral}Tes… toujours invaincue ? Incroyable.\n$@c{neutral_eclosed}Tout est devenu un peu… étrange.\nCest plus pareil sans toi au village.\n$@c{serious}Je sais que cest égoïste, mais jai besoin dexpier ça.\n@c{neutral_eclosed}Je crois que tout ça te dépasse.\n$@c{serious}Ne jamais perdre, cest juste irréaliste.\nGrandir, cest parfois aussi savoir perdre.\n$@c{neutral_eclosed}Tas un beau parcours, mais il y a encore tellement à venir et ça va pas sarranger. @c{neutral}Tes prête pour ça ?\n$@c{serious_mopen_fists}Si tu les, alors prouve-le." "1": "@c{smile}Hé, mais qui voilà ! Ça fait un bail.\n@c{neutral}Tes… toujours invaincue ? Incroyable.\n$@c{neutral_eclosed}Tout est devenu un peu… étrange.\nCest plus pareil sans toi au village.\n$@c{serious}Je sais que cest égoïste, mais jai besoin dexpier ça.\n@c{neutral_eclosed}Je crois que tout ça te dépasse.\n$@c{serious}Ne jamais perdre, cest juste irréaliste.\nGrandir, cest parfois aussi savoir perdre.\n$@c{neutral_eclosed}Tas un beau parcours, mais il y a encore tellement à venir et ça va pas sarranger. @c{neutral}Tes prête pour ça ?\n$@c{serious_mopen_fists}Si tu les, alors prouve-le."
}, },
"victory": { "victory": {
"1": "@c{angry_mhalf}Cest lunaire… Jai presque fait que mentrainer…\nAlors pourquoi il y a encore un tel écart entre nous ?" "1": "@c{angry_mhalf}Cest lunaire… Jai presque fait que mentrainer…\nAlors pourquoi il y a encore un tel écart entre nous ?"
} }
}, },
"rival_3_female": { "rival_3_female": {
"encounter": { "encounter": {
"1": "@c{smile_wave}Ça fait une éternité ! Toujours debout hein ?\n@c{angry}Tu commences à me pousser à bout là. @c{smile_wave_wink}Tinquiètes jdéconne !\n$@c{smile_ehalf}Mais en vrai, ta maison te manque pas ? Ou… Moi ?\nJ… Je veux dire… Tu me manques vraiment beaucoup.\n$@c{smile_eclosed}Je te soutiendrai toujours dans tes ambitions, mais la vérité est que tu finiras par perdre un jour ou lautre.\n$@c{smile}Quand ça arrivera, je serai là pour toi, comme toujours.\n@c{angry_mopen}Maintenant, montre-moi à quel point tes devenu fort !" "1": "@c{smile_wave}Ça fait une éternité ! Toujours debout hein ?\n@c{angry}Tu commences à me pousser à bout là. @c{smile_wave_wink}Tinquiètes jdéconne !\n$@c{smile_ehalf}Mais en vrai, ta maison te manque pas ? Ou… Moi ?\nJ… Je veux dire… Tu me manques vraiment beaucoup.\n$@c{smile_eclosed}Je te soutiendrai toujours dans tes ambitions, mais la vérité est que tu finiras par perdre un jour ou lautre.\n$@c{smile}Quand ça arrivera, je serai là pour toi, comme toujours.\n@c{angry_mopen}Maintenant, montre-moi à quel point tes devenu fort !"
}, },
"victory": { "victory": {
"1": "@c{shock}Après tout ça… Ça te suffit toujours pas… ?\nTu reviendras jamais à ce rythme…" "1": "@c{shock}Après tout ça… Ça te suffit toujours pas… ?\nTu reviendras jamais à ce rythme…"
}, },
"defeat": { "defeat": {
"1": "Tas fait de ton mieux.\nAllez, rentrons à la maison." "1": "Tas fait de ton mieux.\nAllez, rentrons à la maison."
@ -652,15 +652,15 @@
"1": "@c{neutral}Hé.\n$Je vais pas y aller par quatre chemins avec toi.\n@c{neutral_eclosed}Je suis là pour gagner. Simple, basique.\n$@c{serious_mhalf_fists}Jai appris à maximiser tout mon potentiel en mentrainant darrachepied.\n$@c{smile}Cest fou tout le temps que tu peux te dégager si tu dors pas en sacrifiant ta vie sociale.\n$@c{serious_mopen_fists}Plus rien na dimportance désormais, pas tant que jaurai pas gagné.\n$@c{neutral_eclosed}Jai atteint un stade où je ne peux plus perdre.\n@c{smile_eclosed}Je présume que ta philosophie était pas si fausse finalement.\n$@c{angry_mhalf}La défaite, cest pour les faibles, et je ne suis plus un faible.\n$@c{serious_mopen_fists}Tiens-toi prête." "1": "@c{neutral}Hé.\n$Je vais pas y aller par quatre chemins avec toi.\n@c{neutral_eclosed}Je suis là pour gagner. Simple, basique.\n$@c{serious_mhalf_fists}Jai appris à maximiser tout mon potentiel en mentrainant darrachepied.\n$@c{smile}Cest fou tout le temps que tu peux te dégager si tu dors pas en sacrifiant ta vie sociale.\n$@c{serious_mopen_fists}Plus rien na dimportance désormais, pas tant que jaurai pas gagné.\n$@c{neutral_eclosed}Jai atteint un stade où je ne peux plus perdre.\n@c{smile_eclosed}Je présume que ta philosophie était pas si fausse finalement.\n$@c{angry_mhalf}La défaite, cest pour les faibles, et je ne suis plus un faible.\n$@c{serious_mopen_fists}Tiens-toi prête."
}, },
"victory": { "victory": {
"1": "@c{neutral}Que…@d{64} Qui es-tu ?" "1": "@c{neutral}Que…@d{64} Qui es-tu ?"
} }
}, },
"rival_4_female": { "rival_4_female": {
"encounter": { "encounter": {
"1": "@c{neutral}Cest moi ! Tu mas pas encore oubliée… nest-ce pas ?\n$@c{smile}Tu devrais être fier dêtre arrivé aussi loin. GG !\nMais cest certainement pas la fin de ton aventure.\n$@c{smile_eclosed}Tas éveillé en moi quelque chose que jignorais.\nTout mon temps passe dans lentrainement.\n$@c{smile_ehalf}Je dors et je mange à peine, je mentraine juste tous les jours, et deviens de plus en plus forte.\n$@c{neutral}En vrai, Je… Jai de la peine à me reconnaitre.\n$Mais maintenant, je suis au top de mes capacités.\nJe doute que tu sois de nouveau capable de me battre.\n$Et tu sais quoi ? Tout ça, cest de ta faute.\n@c{smile_ehalf}Et jignore si je dois te remercier ou te haïr.\n$@c{angry_mopen}Tiens-toi prêt." "1": "@c{neutral}Cest moi ! Tu mas pas encore oubliée… nest-ce pas ?\n$@c{smile}Tu devrais être fier dêtre arrivé aussi loin. GG !\nMais cest certainement pas la fin de ton aventure.\n$@c{smile_eclosed}Tas éveillé en moi quelque chose que jignorais.\nTout mon temps passe dans lentrainement.\n$@c{smile_ehalf}Je dors et je mange à peine, je mentraine juste tous les jours, et deviens de plus en plus forte.\n$@c{neutral}En vrai, Je… Jai de la peine à me reconnaitre.\n$Mais maintenant, je suis au top de mes capacités.\nJe doute que tu sois de nouveau capable de me battre.\n$Et tu sais quoi ? Tout ça, cest de ta faute.\n@c{smile_ehalf}Et jignore si je dois te remercier ou te haïr.\n$@c{angry_mopen}Tiens-toi prêt."
}, },
"victory": { "victory": {
"1": "@c{neutral}Que…@d{64} Qui es-tu ?" "1": "@c{neutral}Que…@d{64} Qui es-tu ?"
}, },
"defeat": { "defeat": {
"1": "$@c{smile}Tu devrais être fier dêtre arrivé jusque là." "1": "$@c{smile}Tu devrais être fier dêtre arrivé jusque là."
@ -687,7 +687,7 @@
}, },
"rival_6": { "rival_6": {
"encounter": { "encounter": {
"1": "@c{smile_eclosed}Nous y revoilà.\n$@c{neutral}Jai eu du temps pour réfléchir à tout ça.\nIl y a une raison à pourquoi tout semble étrange.\n$@c{neutral_eclosed}Ton rêve, ma volonté de te battre…\nFont partie de quelque chose de plus grand.\n$@c{serious}Cest même pas à propos de moi, ni de toi… Mais du monde, @c{serious_mhalf_fists}et te repousser dans tes limites est ma mission.\n$@c{neutral_eclosed}Jignore si je serai capable de laccomplir, mais je ferai tout ce qui est en mon pouvoir.\n$@c{neutral}Cet endroit est terrifiant… Et pourtant il ma lair familier, comme si jy avais déjà mis les pieds.\n$@c{serious_mhalf_fists}Tu ressens la même chose, pas vrai ?\n$@c{serious}… et cest comme si quelque chose ici me parlait.\n$Comme si cétait tout ce que ce monde avait toujours connu.\n$Ces précieux moments ensemble semblent si proches ne sont rien de plus quun lointain souvenir.\n$@c{neutral_eclosed}Dailleurs, qui peut dire aujourdhui quils ont pu être réels ?\n$@c{serious_mopen_fists}Il faut que tu persévères. Si tu tarrêtes, ça naura jamais de fin et tes la seule à en être capable.\n$@c{serious_smile_fists}Difficile de comprendre le sens de tout ça, je sais juste que cest la réalité.\n$@c{serious_mopen_fists}Si tu ne parviens pas à me battre ici et maintenant, tu nas aucune chance." "1": "@c{smile_eclosed}Nous y revoilà.\n$@c{neutral}Jai eu du temps pour réfléchir à tout ça.\nIl y a une raison à pourquoi tout semble étrange.\n$@c{neutral_eclosed}Ton rêve, ma volonté de te battre…\nFont partie de quelque chose de plus grand.\n$@c{serious}Cest même pas à propos de moi, ni de toi… Mais du monde, @c{serious_mhalf_fists}et te repousser dans tes limites est ma mission.\n$@c{neutral_eclosed}Jignore si je serai capable de laccomplir, mais je ferai tout ce qui est en mon pouvoir.\n$@c{neutral}Cet endroit est terrifiant… Et pourtant il ma lair familier, comme si jy avais déjà mis les pieds.\n$@c{serious_mhalf_fists}Tu ressens la même chose, pas vrai ?\n$@c{serious}… et cest comme si quelque chose ici me parlait.\n$Comme si cétait tout ce que ce monde avait toujours connu.\n$Ces précieux moments ensemble qui semblent si proches ne sont rien de plus quun lointain souvenir.\n$@c{neutral_eclosed}Dailleurs, qui peut dire aujourdhui quils ont pu être réels ?\n$@c{serious_mopen_fists}Il faut que tu persévères. Si tu tarrêtes, ça naura jamais de fin et tes la seule à en être capable.\n$@c{serious_smile_fists}Difficile de comprendre le sens de tout ça, je sais juste que cest la réalité.\n$@c{serious_mopen_fists}Si tu ne parviens pas à me battre ici et maintenant, tu nas aucune chance."
}, },
"victory": { "victory": {
"1": "@c{smile_eclosed}Jai fait ce que javais à faire.\n$Promets-moi juste une chose.\n@c{smile}Après avoir réparé ce monde… Rentre à la maison." "1": "@c{smile_eclosed}Jai fait ce que javais à faire.\n$Promets-moi juste une chose.\n@c{smile}Après avoir réparé ce monde… Rentre à la maison."
@ -695,7 +695,7 @@
}, },
"rival_6_female": { "rival_6_female": {
"encounter": { "encounter": {
"1": "@c{smile_ehalf}Cest donc encore entre toi et moi.\n$@c{smile_eclosed}Tu sais, jai beau retouner ça dans tous les sens…\n$@c{smile_ehalf}Quelque chose peut expliquer tout ça, pourquoi tout semble si étrange…\n$@c{smile}Tas tes rêves, jai mes ambitions…\n$Jai juste le sentiment quil y a un grand dessein derrière tout ça, derrière ce quon fait toi et moi.\n$@c{smile_eclosed}Je crois que mon but est de… repousser tes limites.\n$@c{smile_ehalf}Je suis pas certaine de bien être douée à cet exercice, mais je fais de mon mieux.\n$Cet endroit épouvantable cache quelque chose détrange… Tout semble si limpide…\n$Comme… si cétait tout ce que ce monde avait toujours connu.\n$@c{smile_eclosed}Jai le sentiment que nos précieux moments ensemble sont devenus si flous.\n$@c{smile_ehalf}Ont-ils au moins été réels ? Tout semble si loin maintenant…\n$@c{angry_mopen}Il faut que tu persévères. Si tu tarrêtes, ça naura jamais de fin et tes le seul à en être capable.\n$@c{smile_ehalf}Je… jignore le sens de tout ça… Mais je sais que cest la réalité.\n$@c{neutral}Si tu ne parviens pas à me battre ici et maintenant, tu nas aucune chance." "1": "@c{smile_ehalf}Cest donc encore entre toi et moi.\n$@c{smile_eclosed}Tu sais, jai beau retouner ça dans tous les sens…\n$@c{smile_ehalf}Quelque chose peut expliquer tout ça, pourquoi tout semble si étrange…\n$@c{smile}Tas tes rêves, jai mes ambitions…\n$Jai juste le sentiment quil y a un grand dessein derrière tout ça, derrière ce quon fait toi et moi.\n$@c{smile_eclosed}Je crois que mon but est de… repousser tes limites.\n$@c{smile_ehalf}Je suis pas certaine de bien être douée à cet exercice, mais je fais de mon mieux.\n$Cet endroit épouvantable cache quelque chose détrange… Tout semble si limpide…\n$Comme… si cétait tout ce que ce monde avait toujours connu.\n$@c{smile_eclosed}Jai le sentiment que nos précieux moments ensemble sont devenus si flous.\n$@c{smile_ehalf}Ont-ils au moins été réels ? Tout semble si loin maintenant…\n$@c{angry_mopen}Il faut que tu persévères. Si tu tarrêtes, ça naura jamais de fin et tes le seul à en être capable.\n$@c{smile_ehalf}Je… jignore le sens de tout ça… Mais je sais que cest la réalité.\n$@c{neutral}Si tu ne parviens pas à me battre ici et maintenant, tu nas aucune chance."
}, },
"victory": { "victory": {
"1": "@c{smile_ehalf}Je… Je crois que jai rempli ma mission…\n$@c{smile_eclosed}Promets-moi… Après avoir réparé ce monde… Reviens à la maison sain et sauf.\n$@c{smile_ehalf}… Merci." "1": "@c{smile_ehalf}Je… Je crois que jai rempli ma mission…\n$@c{smile_eclosed}Promets-moi… Après avoir réparé ce monde… Reviens à la maison sain et sauf.\n$@c{smile_ehalf}… Merci."

View File

@ -4,7 +4,7 @@
"ultraTier": "Épique", "ultraTier": "Épique",
"masterTier": "Légendaire", "masterTier": "Légendaire",
"defaultTier": "Commun", "defaultTier": "Commun",
"hatchWavesMessageSoon": "Il fait du bruit. Il va éclore !", "hatchWavesMessageSoon": "Il fait du bruit.\nIl va éclore !",
"hatchWavesMessageClose": "Il bouge de temps en temps. Il devrait bientôt éclore.", "hatchWavesMessageClose": "Il bouge de temps en temps. Il devrait bientôt éclore.",
"hatchWavesMessageNotClose": "Quest-ce qui va en sortir ? Ça va mettre du temps.", "hatchWavesMessageNotClose": "Quest-ce qui va en sortir ? Ça va mettre du temps.",
"hatchWavesMessageLongTime": "Cet Œuf va surement mettre du temps à éclore.", "hatchWavesMessageLongTime": "Cet Œuf va surement mettre du temps à éclore.",
@ -16,7 +16,7 @@
"tooManyEggs": "Vous avez trop dŒufs !", "tooManyEggs": "Vous avez trop dŒufs !",
"pull": "Tirage", "pull": "Tirage",
"pulls": "Tirages", "pulls": "Tirages",
"sameSpeciesEgg": "{{species}} sortira de cet Œuf !", "sameSpeciesEgg": "Un {{species}} sortira de cet Œuf !",
"hatchFromTheEgg": "{{pokemonName}} sort de lŒuf !", "hatchFromTheEgg": "{{pokemonName}} sort de lŒuf !",
"eggMoveUnlock": "Capacité Œuf débloquée :\n{{moveName}}", "eggMoveUnlock": "Capacité Œuf débloquée :\n{{moveName}}",
"rareEggMoveUnlock": "Capacité Œuf Rare débloquée :\n{{moveName}}", "rareEggMoveUnlock": "Capacité Œuf Rare débloquée :\n{{moveName}}",

View File

@ -3,5 +3,6 @@
"power": "Puissance", "power": "Puissance",
"accuracy": "Précision", "accuracy": "Précision",
"abilityFlyInText": " {{passive}}{{abilityName}}\nde {{pokemonName}}", "abilityFlyInText": " {{passive}}{{abilityName}}\nde {{pokemonName}}",
"passive": "Passif " "passive": "Passif ",
} "teraHover": "Téracristal {{type}}"
}

View File

@ -6,7 +6,7 @@
"newGame": "Nouvelle partie", "newGame": "Nouvelle partie",
"settings": "Paramètres", "settings": "Paramètres",
"selectGameMode": "Sélectionnez un mode de jeu.", "selectGameMode": "Sélectionnez un mode de jeu.",
"logInOrCreateAccount": "Connectez-vous ou créez un compte pour commencer. Aucun e-mail requis !", "logInOrCreateAccount": "Connectez-vous ou créez un compte pour commencer.\nAucun e-mail requis !",
"username": "Nom dutilisateur", "username": "Nom dutilisateur",
"password": "Mot de passe", "password": "Mot de passe",
"login": "Connexion", "login": "Connexion",
@ -19,29 +19,29 @@
"invalidRegisterPassword": "Le mot de passe doit contenir 6 caractères ou plus", "invalidRegisterPassword": "Le mot de passe doit contenir 6 caractères ou plus",
"usernameAlreadyUsed": "Le nom dutilisateur est déjà utilisé", "usernameAlreadyUsed": "Le nom dutilisateur est déjà utilisé",
"accountNonExistent": "Le nom dutilisateur nexiste pas", "accountNonExistent": "Le nom dutilisateur nexiste pas",
"unmatchingPassword": "Le mot de passe nest pas correct", "unmatchingPassword": "Le mot de passe est incorrect",
"passwordNotMatchingConfirmPassword": "Les mots de passe ne correspondent pas", "passwordNotMatchingConfirmPassword": "Les mots de passe ne correspondent pas",
"confirmPassword": "Confirmer le MDP", "confirmPassword": "Confirmer le MDP",
"registrationAgeWarning": "Vous confirmez en vous inscrivant que vous avez 13 ans ou plus.", "registrationAgeWarning": "En vous inscrivant, vous certifiez que vous avez 13 ans ou plus.",
"backToLogin": "Retour", "backToLogin": "Retour",
"failedToLoadSaveData": "Échec du chargement des données. Veuillez recharger\nla page. Si cela persiste, contactez ladministrateur.", "failedToLoadSaveData": "Échec du chargement des données. Veuillez recharger\nla page. Si cela persiste, contactez ladministrateur.",
"sessionSuccess": "Session chargée avec succès.", "sessionSuccess": "Session chargée avec succès.",
"failedToLoadSession": "Vos données de session nont pas pu être chargées.\nElles pourraient être corrompues.", "failedToLoadSession": "Vos données de session nont pas pu être chargées.\nElles pourraient être corrompues.",
"boyOrGirl": "Es-tu un garçon ou une fille ?", "boyOrGirl": "Es-tu un garçon ou une fille ?",
"evolving": "Quoi ?\n{{pokemonName}} évolue !", "evolving": "Quoi ?\n{{pokemonName}} évolue !",
"stoppedEvolving": "Hein ?\n{{pokemonName}} névolue plus !", "stoppedEvolving": "Hein ?\n{{pokemonName}} névolue plus !",
"pauseEvolutionsQuestion": "Mettre en pause les évolutions pour {{pokemonName}} ?\nElles peuvent être réactivées depuis lécran déquipe.", "pauseEvolutionsQuestion": "Interrompre les évolutions pour {{pokemonName}} ?\nElles peuvent être réactivées depuis lécran déquipe.",
"evolutionsPaused": "Les évolutions ont été mises en pause pour {{pokemonName}}.", "evolutionsPaused": "Les évolutions de {{pokemonName}}\nsont interrompues.",
"evolutionDone": "Félicitations !\n{{pokemonName}} a évolué en {{evolvedPokemonName}} !", "evolutionDone": "Félicitations !\n{{pokemonName}} a évolué en {{evolvedPokemonName}} !",
"dailyRankings": "Classement du Jour", "dailyRankings": "Classement du jour",
"weeklyRankings": "Classement de la Semaine", "weeklyRankings": "Classement de la semaine",
"noRankings": "Pas de Classement", "noRankings": "Pas de classement",
"positionIcon": "#", "positionIcon": "#",
"usernameScoreboard": "Utilisateur", "usernameScoreboard": "Utilisateur",
"score": "Score", "score": "Score",
"wave": "Vague", "wave": "Vague",
"loading": "Chargement…", "loading": "Chargement…",
"loadingAsset": "Chargement de la ressource : {{assetName}}", "loadingAsset": "Chargement des ressources : {{assetName}}",
"playersOnline": "Joueurs connectés", "playersOnline": "Joueurs connectés",
"yes": "Oui", "yes": "Oui",
"no": "Non", "no": "Non",
@ -51,5 +51,7 @@
"renamePokemon": "Renommer le Pokémon", "renamePokemon": "Renommer le Pokémon",
"rename": "Renommer", "rename": "Renommer",
"nickname": "Surnom", "nickname": "Surnom",
"errorServerDown": "Oupsi ! Un problème de connexion au serveur est survenu.\n\nVous pouvez garder cette fenêtre ouverte,\nle jeu se reconnectera automatiquement." "errorServerDown": "Oupsi ! Un problème de connexion au serveur est survenu.\n\nVous pouvez garder cette fenêtre ouverte,\nle jeu se reconnectera automatiquement.",
"noSaves": "Vous navez aucune sauvegarde enregistrée !",
"tooManySaves": "Vous avez trop de sauvegardes enregistrées !"
} }

View File

@ -2,7 +2,7 @@
"ModifierType": { "ModifierType": {
"AddPokeballModifierType": { "AddPokeballModifierType": {
"name": "{{pokeballName}} x{{modifierCount}}", "name": "{{pokeballName}} x{{modifierCount}}",
"description": "Recevez {{modifierCount}} {{pokeballName}}·s. (Inventaire : {{pokeballAmount}})\nTaux de capture : {{catchRate}}" "description": "Recevez {{modifierCount}} {{pokeballName}}·s. (Inventaire : {{pokeballAmount}})\nTaux de capture : {{catchRate}}"
}, },
"AddVoucherModifierType": { "AddVoucherModifierType": {
"name": "{{voucherTypeName}} x{{modifierCount}}", "name": "{{voucherTypeName}} x{{modifierCount}}",
@ -10,8 +10,8 @@
}, },
"PokemonHeldItemModifierType": { "PokemonHeldItemModifierType": {
"extra": { "extra": {
"inoperable": "{{pokemonName}} ne peut pas\nporter cet objet !", "inoperable": "{{pokemonName}} ne peut pas\nporter cet objet !",
"tooMany": "{{pokemonName}} porte trop\ndexemplaires de cet objet !" "tooMany": "{{pokemonName}} porte trop\ndexemplaires de cet objet !"
} }
}, },
"PokemonHpRestoreModifierType": { "PokemonHpRestoreModifierType": {
@ -47,10 +47,14 @@
"description": "Donne la nature {{natureName}} à un Pokémon et la débloque pour le starter lui étant lié." "description": "Donne la nature {{natureName}} à un Pokémon et la débloque pour le starter lui étant lié."
}, },
"DoubleBattleChanceBoosterModifierType": { "DoubleBattleChanceBoosterModifierType": {
"description": "Double les chances de tomber sur un combat double pendant {{battleCount}} combats." "description": "Quadruple les chances de tomber sur un combat double pendant {{battleCount}} combats."
}, },
"TempStatStageBoosterModifierType": { "TempStatStageBoosterModifierType": {
"description": "Augmente dun cran {{stat}} pour toute léquipe pendant 5 combats." "description": "Augmente {{amount}} {{stat}} de toute léquipe pendant 5 combats.",
"extra": {
"stage": "dun cran",
"percentage": "de 30%"
}
}, },
"AttackTypeBoosterModifierType": { "AttackTypeBoosterModifierType": {
"description": "Augmente de 20% la puissance des capacités de type {{moveType}} dun Pokémon." "description": "Augmente de 20% la puissance des capacités de type {{moveType}} dun Pokémon."
@ -85,7 +89,7 @@
"description": "Augmente de {{boostPercent}}% le gain de Points dExp du porteur." "description": "Augmente de {{boostPercent}}% le gain de Points dExp du porteur."
}, },
"PokemonFriendshipBoosterModifierType": { "PokemonFriendshipBoosterModifierType": {
"description": "Augmente le gain damitié de 50% par victoire." "description": "Augmente le gain de bonheur de 50% par victoire."
}, },
"PokemonMoveAccuracyBoosterModifierType": { "PokemonMoveAccuracyBoosterModifierType": {
"description": "Augmente de {{accuracyAmount}} la précision des capacités (maximum 100)." "description": "Augmente de {{accuracyAmount}} la précision des capacités (maximum 100)."
@ -102,17 +106,17 @@
"description": "Apprend la capacité {{moveName}} à un Pokémon.\n(Maintenez C ou Maj pour plus dinfos)" "description": "Apprend la capacité {{moveName}} à un Pokémon.\n(Maintenez C ou Maj pour plus dinfos)"
}, },
"EvolutionItemModifierType": { "EvolutionItemModifierType": {
"description": "Permet à certains Pokémon dévoluer." "description": "Permet à certains Pokémon dévoluer à son contact."
}, },
"FormChangeItemModifierType": { "FormChangeItemModifierType": {
"description": "Permet à certains Pokémon de changer de forme." "description": "Permet à certains Pokémon de changer de forme à son contact."
}, },
"FusePokemonModifierType": { "FusePokemonModifierType": {
"description": "Fusionne deux Pokémon (transfère le talent, sépare les stats de base et les types, partage les capacités)." "description": "Fusionne deux Pokémon (transfère le talent, sépare les stats de base et les types, partage les capacités)."
}, },
"TerastallizeModifierType": { "TerastallizeModifierType": {
"name": "Téra-Éclat {{teraType}}", "name": "Téra-Éclat {{teraType}}",
"description": "{{teraType}} Téracristallise son porteur pendant 10 combats." "description": "Téracristallise son porteur en type {{teraType}} pendant 10 combats."
}, },
"ContactHeldItemTransferChanceModifierType": { "ContactHeldItemTransferChanceModifierType": {
"description": "{{chancePercent}}% de chances de voler un objet de ladversaire en lattaquant." "description": "{{chancePercent}}% de chances de voler un objet de ladversaire en lattaquant."
@ -198,7 +202,7 @@
"GOLDEN_PUNCH": { "name": "Poing Doré", "description": "La moitié des dégâts infligés sont convertis en argent." }, "GOLDEN_PUNCH": { "name": "Poing Doré", "description": "La moitié des dégâts infligés sont convertis en argent." },
"COIN_CASE": { "name": "Boite Jetons", "description": "Tous les 10 combats, recevez 10% de votre argent en intérêts." }, "COIN_CASE": { "name": "Boite Jetons", "description": "Tous les 10 combats, recevez 10% de votre argent en intérêts." },
"LOCK_CAPSULE": { "name": "Poké Écrin", "description": "Permet de conserver la rareté des objets si vous relancez les objets proposés." }, "LOCK_CAPSULE": { "name": "Poké Écrin", "description": "Permet de choisir de bloquer le niveau de rareté lors dune relance des objets gratuits proposés." },
"GRIP_CLAW": { "name": "Accro Griffe" }, "GRIP_CLAW": { "name": "Accro Griffe" },
"WIDE_LENS": { "name": "Loupe" }, "WIDE_LENS": { "name": "Loupe" },
@ -247,7 +251,7 @@
}, },
"SpeciesBoosterItem": { "SpeciesBoosterItem": {
"LIGHT_BALL": { "name": "Balle Lumière", "description": "À faire tenir à Pikachu. Un orbe énigmatique qui double son Attaque et son Atq. Spé. ." }, "LIGHT_BALL": { "name": "Balle Lumière", "description": "À faire tenir à Pikachu. Un orbe énigmatique qui double son Attaque et son Atq. Spé. ." },
"THICK_CLUB": { "name": "Masse Os", "description": "À faire tenir à Osselait ou Ossatueur. Un os dur qui double leur Attaque." }, "THICK_CLUB": { "name": "Masse Os", "description": "À faire tenir à Osselait ou à Ossatueur, formes dAlola incluses. Un os dur qui double leur Attaque." },
"METAL_POWDER": { "name": "Poudre Métal", "description": "À faire tenir à Métamorph. Cette poudre étrange, très fine mais résistante, double sa Défense." }, "METAL_POWDER": { "name": "Poudre Métal", "description": "À faire tenir à Métamorph. Cette poudre étrange, très fine mais résistante, double sa Défense." },
"QUICK_POWDER": { "name": "Poudre Vite", "description": "À faire tenir à Métamorph. Cette poudre étrange, très fine mais résistante, double sa Vitesse." } "QUICK_POWDER": { "name": "Poudre Vite", "description": "À faire tenir à Métamorph. Cette poudre étrange, très fine mais résistante, double sa Vitesse." }
}, },

View File

@ -3,7 +3,7 @@
"turnHealApply": "Les PV de {{pokemonNameWithAffix}}\nsont un peu restaurés par les {{typeName}} !", "turnHealApply": "Les PV de {{pokemonNameWithAffix}}\nsont un peu restaurés par les {{typeName}} !",
"hitHealApply": "Les PV de {{pokemonNameWithAffix}}\nsont un peu restaurés par le {{typeName}} !", "hitHealApply": "Les PV de {{pokemonNameWithAffix}}\nsont un peu restaurés par le {{typeName}} !",
"pokemonInstantReviveApply": "{{pokemonNameWithAffix}} a repris connaissance\navec sa {{typeName}} et est prêt à se battre de nouveau !", "pokemonInstantReviveApply": "{{pokemonNameWithAffix}} a repris connaissance\navec sa {{typeName}} et est prêt à se battre de nouveau !",
"resetNegativeStatStageApply": "Les stats baissées de {{pokemonNameWithAffix}}\nsont restaurées par l{{typeName}} !", "resetNegativeStatStageApply": "Les stats baissées de {{pokemonNameWithAffix}}\nsont restaurées par l{{typeName}} !",
"moneyInterestApply": "La {{typeName}} vous rapporte\n{{moneyAmount}}  dintérêts !", "moneyInterestApply": "La {{typeName}} vous rapporte\n{{moneyAmount}}  dintérêts !",
"turnHeldItemTransferApply": "{{itemName}} de {{pokemonNameWithAffix}} est absorbé·e\npar le {{typeName}} de {{pokemonName}} !", "turnHeldItemTransferApply": "{{itemName}} de {{pokemonNameWithAffix}} est absorbé·e\npar le {{typeName}} de {{pokemonName}} !",
"contactHeldItemTransferApply": "{{itemName}} de {{pokemonNameWithAffix}} est volé·e\npar l{{typeName}} de {{pokemonName}} !", "contactHeldItemTransferApply": "{{itemName}} de {{pokemonNameWithAffix}} est volé·e\npar l{{typeName}} de {{pokemonName}} !",

View File

@ -1,12 +1,12 @@
{ {
"hitWithRecoil": "{{pokemonName}} est blessé par le contrecoup !", "hitWithRecoil": "{{pokemonName}} est blessé par le contrecoup !",
"cutHpPowerUpMove": "{{pokemonName}} sacrifie des PV\net augmente la puissance ses capacités !", "cutHpPowerUpMove": "{{pokemonName}} sacrifie des PV\net augmente la puissance de ses capacités !",
"absorbedElectricity": "{{pokemonName}} absorbe de lélectricité !", "absorbedElectricity": "{{pokemonName}} absorbe de lélectricité !",
"switchedStatChanges": "{{pokemonName}} permute\nles changements de stats avec ceux de sa cible !", "switchedStatChanges": "{{pokemonName}} permute\nles changements de stats avec ceux de sa cible !",
"switchedTwoStatChanges": "{{pokemonName}} permute les changements de {{firstStat} et de {{secondStat}} avec ceux de sa cible !", "switchedTwoStatChanges": "{{pokemonName}} permute les changements de {{firstStat}} et de {{secondStat}} avec ceux de sa cible !",
"switchedStat": "{{pokemonName}} et sa cible échangent leur {{stat}} !", "switchedStat": "{{pokemonName}} et sa cible échangent leur {{stat}} !",
"sharedGuard": "{{pokemonName}} additionne sa garde à celle de sa cible et redistribue le tout équitablement !", "sharedGuard": "{{pokemonName}} additionne sa garde à celle de sa cible et redistribue le tout équitablement !",
"sharedPower": "{{pokemonName}} additionne sa force à celle de sa cible et redistribue le tout équitablement !", "sharedPower": "{{pokemonName}} additionne sa force à celle de sa cible et redistribue le tout équitablement !",
"goingAllOutForAttack": "{{pokemonName}} a pris\ncette capacité au sérieux !", "goingAllOutForAttack": "{{pokemonName}} a pris\ncette capacité au sérieux !",
"regainedHealth": "{{pokemonName}}\nrécupère des PV !", "regainedHealth": "{{pokemonName}}\nrécupère des PV !",
"keptGoingAndCrashed": "{{pokemonName}}\nsécrase au sol !", "keptGoingAndCrashed": "{{pokemonName}}\nsécrase au sol !",
@ -22,7 +22,7 @@
"loweredItsHead": "{{pokemonName}}\nbaisse la tête !", "loweredItsHead": "{{pokemonName}}\nbaisse la tête !",
"isGlowing": "{{pokemonName}} est entouré\ndune lumière intense !", "isGlowing": "{{pokemonName}} est entouré\ndune lumière intense !",
"bellChimed": "Un grelot sonne !", "bellChimed": "Un grelot sonne !",
"foresawAnAttack": "{{pokemonName}}\nprévoit une attaque !", "foresawAnAttack": "{{pokemonName}}\nprévoit une attaque !",
"isTighteningFocus": "{{pokemonName}} se concentre\nau maximum !", "isTighteningFocus": "{{pokemonName}} se concentre\nau maximum !",
"hidUnderwater": "{{pokemonName}}\nse cache sous leau !", "hidUnderwater": "{{pokemonName}}\nse cache sous leau !",
"soothingAromaWaftedThroughArea": "Une odeur apaisante flotte dans lair !", "soothingAromaWaftedThroughArea": "Une odeur apaisante flotte dans lair !",
@ -34,7 +34,7 @@
"becameCloakedInFreezingAir": "{{pokemonName}} est entouré\ndun air glacial !", "becameCloakedInFreezingAir": "{{pokemonName}} est entouré\ndun air glacial !",
"isChargingPower": "{{pokemonName}}\nconcentre son énergie !", "isChargingPower": "{{pokemonName}}\nconcentre son énergie !",
"burnedItselfOut": "Le feu intérieur de {{pokemonName}}\nsest entièrement consumé !", "burnedItselfOut": "Le feu intérieur de {{pokemonName}}\nsest entièrement consumé !",
"startedHeatingUpBeak": "{{pokemonName}}\nfait chauffer son bec !", "startedHeatingUpBeak": "{{pokemonName}}\nfait chauffer son bec !",
"setUpShellTrap": "{{pokemonName}} déclenche\nle Carapiège!", "setUpShellTrap": "{{pokemonName}} déclenche\nle Carapiège!",
"isOverflowingWithSpacePower": "La puissance du cosmos afflue dans le corps\nde {{pokemonName}} !", "isOverflowingWithSpacePower": "La puissance du cosmos afflue dans le corps\nde {{pokemonName}} !",
"usedUpAllElectricity": "{{pokemonName}}a utilisé\ntoute son électricité !", "usedUpAllElectricity": "{{pokemonName}}a utilisé\ntoute son électricité !",
@ -66,5 +66,6 @@
"revivalBlessing": "{{pokemonName}} a repris connaissance\net est prêt à se battre de nouveau !", "revivalBlessing": "{{pokemonName}} a repris connaissance\net est prêt à se battre de nouveau !",
"swapArenaTags": "Les effets affectant chaque côté du terrain\nont été échangés par {{pokemonName}} !", "swapArenaTags": "Les effets affectant chaque côté du terrain\nont été échangés par {{pokemonName}} !",
"exposedMove": "{{targetPokemonName}} est identifié\npar {{pokemonName}} !", "exposedMove": "{{targetPokemonName}} est identifié\npar {{pokemonName}} !",
"safeguard": "{{targetName}} est protégé\npar la capacité Rune Protect !" "safeguard": "{{targetName}} est protégé\npar la capacité Rune Protect !",
} "afterYou": "{{pokemonName}} accepte\navec joie !"
}

View File

@ -1,7 +1,7 @@
{ {
"moveset": "Capacités", "moveset": "Capacités",
"gender": "Sexe :", "gender": "Sexe :",
"ability": "Talent :", "ability": "Talent :",
"nature": "Nature :", "nature": "Nature :",
"form": "Forme :" "form": "Forme :"
} }

View File

@ -6,9 +6,9 @@
"ATKshortened": "Atq", "ATKshortened": "Atq",
"DEF": "Défense", "DEF": "Défense",
"DEFshortened": "Déf", "DEFshortened": "Déf",
"SPATK": "Atq. Spé.", "SPATK": "Atq. Spé.",
"SPATKshortened": "AtqSp", "SPATKshortened": "AtqSp",
"SPDEF": "Déf. Spé.", "SPDEF": "Déf. Spé.",
"SPDEFshortened": "DéfSp", "SPDEFshortened": "DéfSp",
"SPD": "Vitesse", "SPD": "Vitesse",
"SPDshortened": "Vit", "SPDshortened": "Vit",
@ -17,7 +17,7 @@
"HPStat": "PV" "HPStat": "PV"
}, },
"Type": { "Type": {
"UNKNOWN": "Inconnu", "UNKNOWN": "???",
"NORMAL": "Normal", "NORMAL": "Normal",
"FIGHTING": "Combat", "FIGHTING": "Combat",
"FLYING": "Vol", "FLYING": "Vol",

View File

@ -1,36 +1,36 @@
{ {
"battlesWon": "combats gagnés !", "battlesWon": "combats gagnés !",
"joinTheDiscord": "Rejoins le Discord !", "joinTheDiscord": "Rejoins le Discord !",
"infiniteLevels": "Niveaux infinis !", "infiniteLevels": "Niveaux infinis !",
"everythingStacks": "Tout se cumule !", "everythingStacks": "Tout se cumule !",
"optionalSaveScumming": "Optional Save Scumming!", "optionalSaveScumming": "Optional Save Scumming !",
"biomes": "35 biomes !", "biomes": "35 biomes !",
"openSource": "Open Source !", "openSource": "Open Source !",
"playWithSpeed": "Joue en vitesse x5 !", "playWithSpeed": "Joue en vitesse x5 !",
"liveBugTesting": "Tests de bugs en direct !", "liveBugTesting": "Tests de bugs en direct !",
"heavyInfluence": "Grosse influence de RoR2 !", "heavyInfluence": "Grosse influence de RoR2 !",
"pokemonRiskAndPokemonRain": "Pokémon Risk et Pokémon Rain !", "pokemonRiskAndPokemonRain": "Pokémon Risk et Pokémon Rain !",
"nowWithMoreSalt": "Désormais avec 33% de sel en plus !", "nowWithMoreSalt": "Désormais avec 33% de sel en plus !",
"infiniteFusionAtHome": "Infinite Fusion, chez vous !", "infiniteFusionAtHome": "Infinite Fusion, chez vous !",
"brokenEggMoves": "Des Capacités Œuf craquées !", "brokenEggMoves": "Des Capacités Œuf craquées !",
"magnificent": "Magnifique !", "magnificent": "Magnifique !",
"mubstitute": "Mubstitute !", "mubstitute": "Mubstitute !",
"thatsCrazy": "Cest une dinguerie !", "thatsCrazy": "Cest une dinguerie !",
"oranceJuice": "Jus dorange !", "oranceJuice": "Jus dorange !",
"questionableBalancing": "Équilibrage douteux !", "questionableBalancing": "Équilibrage douteux !",
"coolShaders": "Cool shaders !", "coolShaders": "Cool shaders !",
"aiFree": "Garanti sans IA !", "aiFree": "Garanti sans IA !",
"suddenDifficultySpikes": "De soudains pics de difficultés !", "suddenDifficultySpikes": "De soudains pics de difficultés !",
"basedOnAnUnfinishedFlashGame": "Basé sur un jeu Flash abandonné !", "basedOnAnUnfinishedFlashGame": "Basé sur un jeu Flash abandonné !",
"moreAddictiveThanIntended": "Plus addictif que prévu !", "moreAddictiveThanIntended": "Plus addictif que prévu !",
"mostlyConsistentSeeds": "Des seeds à peu près stables !", "mostlyConsistentSeeds": "Des seeds à peu près stables !",
"achievementPointsDontDoAnything": "Les Points de Succès servent à rien !", "achievementPointsDontDoAnything": "Les Points de Succès servent à rien !",
"youDoNotStartAtLevel": "Ne commence pas au Niveau 2000 !", "youDoNotStartAtLevel": "Ne commence pas au Niveau 2000 !",
"dontTalkAboutTheManaphyEggIncident": "Ne parle pas de lincident de lŒuf de Manaphy !", "dontTalkAboutTheManaphyEggIncident": "Ne parle pas de lincident de lŒuf de Manaphy !",
"alsoTryPokengine": "Essaye aussi Pokéngine !", "alsoTryPokengine": "Essaye aussi Pokéngine !",
"alsoTryEmeraldRogue": "Essaye aussi Emerald Rogue!", "alsoTryEmeraldRogue": "Essaye aussi Emerald Rogue!",
"alsoTryRadicalRed": "Essaye aussi Radical Red !", "alsoTryRadicalRed": "Essaye aussi Radical Red !",
"eeveeExpo": "Eevee Expo !", "eeveeExpo": "Eevee Expo !",
"ynoproject": "YNOproject !", "ynoproject": "YNOproject !",
"breedersInSpace": "Des Éleveurs dans lespace !" "breedersInSpace": "Des Éleveurs dans lespace !"
} }

View File

@ -33,7 +33,7 @@
"obtainSource": "{{pokemonNameWithAffix}} est paralysé\npar {{sourceText}} ! Il aura du mal à attaquer !", "obtainSource": "{{pokemonNameWithAffix}} est paralysé\npar {{sourceText}} ! Il aura du mal à attaquer !",
"activation": "{{pokemonNameWithAffix}} est paralysé !\nIl na pas pu attaquer !", "activation": "{{pokemonNameWithAffix}} est paralysé !\nIl na pas pu attaquer !",
"overlap": "{{pokemonNameWithAffix}} est\ndéjà paralysé.", "overlap": "{{pokemonNameWithAffix}} est\ndéjà paralysé.",
"heal": "{{pokemonNameWithAffix}} nest\nplus paralysé !" "heal": "{{pokemonNameWithAffix}} nest\nplus paralysé !"
}, },
"sleep": { "sleep": {
"name": "Sommeil", "name": "Sommeil",
@ -62,4 +62,4 @@
"overlap": "{{pokemonNameWithAffix}} est\ndéjà brulé.", "overlap": "{{pokemonNameWithAffix}} est\ndéjà brulé.",
"heal": "{{pokemonNameWithAffix}} nest\nplus brulé !" "heal": "{{pokemonNameWithAffix}} nest\nplus brulé !"
} }
} }

View File

@ -1,10 +1,10 @@
{ {
"intro": "Bienvenue dans PokéRogue, un fangame axé sur les combats Pokémon avec des éléments roguelite !\n$Ce jeu nest pas monétisé et nous ne prétendons pas à la propriété de Pokémon, ni des éléments sous copyright\n$utilisés.\n$Ce jeu est toujours en développement, mais entièrement jouable.\n$Tout signalement de bugs passe par le serveur Discord.\n$Si le jeu est lent, vérifiez que lAccélération Matérielle est activée dans les paramètres du navigateur.", "intro": "Bienvenue dans PokéRogue, un fangame axé sur les combats Pokémon avec des éléments roguelite !\n$Ce jeu nest pas monétisé et nous ne prétendons à la propriété daucun élément sous copyright utilisé.\n$Bien quen développement permanent, PokéRogue reste entièrement jouable.\n$Tout signalement de bugs et derreurs quelconques passe par le serveur Discord.\n$Si le jeu est lent, vérifiez que lAccélération Matérielle est activée dans les paramètres du navigateur.",
"accessMenu": "Accédez au menu avec M ou Échap lors de lattente dune\naction.\n$Il contient les paramètres et diverses fonctionnalités", "accessMenu": "Accédez au menu avec M ou Échap lors de lattente dune\naction.\n$Il contient les paramètres et diverses fonctionnalités.",
"menu": "Vous pouvez accéder aux paramètres depuis ce menu.\n$Vous pouvez entre autres y changer la vitesse du jeu ou le style de fenêtre.\n$Il y a également toute une variété dautres fonctionnalités,\n$jetez-y un œil !", "menu": "Vous pouvez accéder aux paramètres depuis ce menu.\n$Vous pouvez entre autres y changer la vitesse du jeu ou le style de fenêtre…\n$Mais également des tonnes dautres fonctionnalités, jetez-y un œil !",
"starterSelect": "Choisissez vos starters depuis cet écran avec Z ou Espace.\nIls formeront votre équipe de départ.\n$Chacun possède une valeur. Votre équipe peut avoir jusquà\n6 membres, tant que vous ne dépassez pas un cout de 10.\n$Vous pouvez aussi choisir le sexe, le talent et la forme en\nfonction des variants déjà capturés ou éclos.\n$Les IVs dun starter sont les meilleurs de tous ceux de son\nespèce déjà obtenus. Essayez donc den obtenir plusieurs !", "starterSelect": "Choisissez vos starters depuis cet écran avec Z ou Espace.\nIls formeront votre équipe de départ.\n$Chacun possède une valeur. Votre équipe peut avoir jusquà 6 membres, sans dépasser un cout de 10.\n$Vous pouvez aussi choisir le sexe, le talent et la forme en\nfonction des variants déjà capturés ou éclos.\n$Les IV dun starter sont les meilleurs de tous ceux de son espèce déjà possédés. Obtenez-en plusieurs !",
"pokerus": "Chaque jour, 3 starters tirés aléatoirement ont un contour\n$violet. Si un starter que vous possédez la, essayez de\n$lajouter à votre équipe. Vérifiez bien son résumé !", "pokerus": "Chaque jour, 3 starters tirés aléatoirement ont un contour violet.\n$Si un starter que vous possédez la, essayez de lajouter à votre équipe. Vérifiez bien son résumé !",
"statChange": "Les changements de stats restent à travers les combats tant que le Pokémon nest pas rappelé.\n$Vos Pokémon sont rappelés avant un combat de Dresseur et avant dentrer dans un nouveau biome.\n$Vous pouvez voir en combat les changements de stats dun Pokémon en maintenant C ou Maj.\n$Vous pouvez également voir les capacités de ladversaire en maintenant V.\n$Seules les capacités que le Pokémon a utilisées dans ce combat sont consultables.", "statChange": "Les changements de stats persistent à travers les combats tant que le Pokémon nest pas rappelé.\n$Vos Pokémon sont rappelés avant un combat de Dresseur et avant dentrer dans un nouveau biome.\n$Vous pouvez voir en combat les changements de stats dun Pokémon en maintenant C ou Maj.\n$Vous pouvez également voir les capacités de ladversaire en maintenant V.\n$Seules les capacités que le Pokémon a utilisées dans ce combat sont consultables.",
"selectItem": "Après chaque combat, vous avez le choix entre 3 objets\ntirés au sort. Vous ne pouvez en prendre quun.\n$Cela peut être des objets consommables, des objets à\nfaire tenir, ou des objets passifs aux effets permanents.\n$La plupart des effets des objets non-consommables se cumuleront de diverses manières.\n$Certains objets apparaitront sils peuvent être utilisés, comme les objets dévolution.\n$Vous pouvez aussi transférer des objets tenus entre Pokémon en utilisant loption de transfert.\n$Loption de transfert apparait en bas à droite dès que vous avez obtenu un objet à faire tenir.\n$Vous pouvez acheter des consommables avec de largent.\nPlus vous progressez, plus le choix sera varié.\n$Choisir un des objets gratuits déclenchera le prochain combat, donc faites bien tous vos achats avant.", "selectItem": "Après chaque combat, vous avez le choix entre 3 objets\ntirés au sort. Vous ne pouvez en prendre quun.\n$Cela peut être des objets consommables, des objets à\nfaire tenir, ou des objets passifs aux effets permanents.\n$La plupart des effets des objets non-consommables se cumuleront de diverses manières.\n$Certains objets napparaitront que sils ont une utilité immédiate, comme les objets dévolution.\n$Vous pouvez aussi transférer des objets tenus entre Pokémon en utilisant loption de transfert.\n$Loption de transfert apparait en bas à droite dès quun Pokémon de léquipe porte un objet.\n$Vous pouvez acheter des consommables avec de largent.\nPlus vous progressez, plus le choix sera large.\n$Choisir un des objets gratuits déclenchera le prochain combat, donc faites bien tous vos achats avant.",
"eggGacha": "Depuis cet écran, vous pouvez échanger vos coupons\ncontre des Œufs de Pokémon.\n$Les Œufs éclosent après avoir remporté un certain nombre\nde combats. Les plus rares mettent plus de temps.\n$Les Pokémon éclos ne rejoindront pas votre équipe,\nmais seront ajoutés à vos starters.\n$Les Pokémon issus dŒufs ont généralement de\nmeilleurs IVs que les Pokémon sauvages.\n$Certains Pokémon ne peuvent être obtenus\nque dans des Œufs.\n$Il y a 3 différentes machines à actionner avec différents\nbonus, prenez celle qui vous convient le mieux !" "eggGacha": "Depuis cet écran, vous pouvez utiliser vos coupons\npour recevoir Œufs de Pokémon au hasard.\n$Les Œufs éclosent après avoir remporté un certain nombre de combats. Plus ils sont rares, plus ils mettent de temps.\n$Les Pokémon éclos ne rejoindront pas votre équipe, mais seront ajoutés à vos starters.\n$Les Pokémon issus dŒufs ont généralement de meilleurs IV que les Pokémon sauvages.\n$Certains Pokémon ne peuvent être obtenus que dans des Œufs.\n$Il y a 3 différentes machines à actionner avec différents\nbonus, prenez celle qui vous convient le mieux !"
} }

View File

@ -1,9 +1,9 @@
{ {
"vouchers": "Coupons", "vouchers": "Coupons",
"eggVoucher": "Coupon Œuf", "eggVoucher": "Coupon Œuf",
"eggVoucherPlus": "Coupon Œuf +", "eggVoucherPlus": "Coupon Œuf +",
"eggVoucherPremium": "Coupon Œuf Premium", "eggVoucherPremium": "Coupon Œuf Premium",
"eggVoucherGold": "Coupon Œuf Or", "eggVoucherGold": "Coupon Œuf Or",
"locked": "Verrouillé", "locked": "Verrouillé",
"defeatTrainer": "Vaincre {{trainerName}}" "defeatTrainer": "Vaincre {{trainerName}}"
} }

View File

@ -1,32 +1,32 @@
{ {
"sunnyStartMessage": "Les rayons du soleil brillent !", "sunnyStartMessage": "Les rayons du soleil brillent !",
"sunnyLapseMessage": "Les rayons du soleil brillent fort !", "sunnyLapseMessage": "Les rayons du soleil brillent fort !",
"sunnyClearMessage": "Les rayons du soleil saffaiblissent !", "sunnyClearMessage": "Les rayons du soleil saffaiblissent !",
"rainStartMessage": "Il commence à pleuvoir !", "rainStartMessage": "Il commence à pleuvoir !",
"rainLapseMessage": "La pluie continue de tomber !", "rainLapseMessage": "La pluie continue de tomber !",
"rainClearMessage": "La pluie sest arrêtée !", "rainClearMessage": "La pluie sest arrêtée !",
"sandstormStartMessage": "Une tempête de sable se prépare !", "sandstormStartMessage": "Une tempête de sable se prépare !",
"sandstormLapseMessage": "La tempête de sable fait rage !", "sandstormLapseMessage": "La tempête de sable fait rage !",
"sandstormClearMessage": "La tempête de sable se calme !", "sandstormClearMessage": "La tempête de sable se calme !",
"sandstormDamageMessage": "La tempête de sable inflige des dégâts\nà {{pokemonNameWithAffix}} !", "sandstormDamageMessage": "La tempête de sable inflige des dégâts\nà {{pokemonNameWithAffix}} !",
"hailStartMessage": "Il commence à grêler !", "hailStartMessage": "Il commence à grêler !",
"hailLapseMessage": "La grêle continue de tomber !", "hailLapseMessage": "La grêle continue de tomber !",
"hailClearMessage": "La grêle sest arrêtée !", "hailClearMessage": "La grêle sest arrêtée !",
"hailDamageMessage": "La grêle inflige des dégâts\nà {{pokemonNameWithAffix}} !", "hailDamageMessage": "La grêle inflige des dégâts\nà {{pokemonNameWithAffix}} !",
"snowStartMessage": "Il commence à neiger !", "snowStartMessage": "Il commence à neiger !",
"snowLapseMessage": "Il y a une tempête de neige !", "snowLapseMessage": "Il y a une tempête de neige !",
"snowClearMessage": "La neige sest arrêtée !", "snowClearMessage": "La neige sest arrêtée !",
"fogStartMessage": "Le brouillard devient épais…", "fogStartMessage": "Le brouillard devient épais…",
"fogLapseMessage": "Le brouillard continue !", "fogLapseMessage": "Le brouillard continue !",
"fogClearMessage": "Le brouillard sest dissipé !", "fogClearMessage": "Le brouillard sest dissipé !",
"heavyRainStartMessage": "Une pluie battante sabat soudainement !", "heavyRainStartMessage": "Une pluie battante sabat soudainement !",
"heavyRainLapseMessage": "La pluie battante continue.", "heavyRainLapseMessage": "La pluie battante continue.",
"heavyRainClearMessage": "La pluie battante sest arrêtée…", "heavyRainClearMessage": "La pluie battante sest arrêtée…",
"harshSunStartMessage": "Les rayons du soleil sintensifient !", "harshSunStartMessage": "Les rayons du soleil sintensifient !",
"harshSunLapseMessage": "Les rayons du soleil sont brulants !", "harshSunLapseMessage": "Les rayons du soleil sont brulants !",
"harshSunClearMessage": "Les rayons du soleil saffaiblissent !", "harshSunClearMessage": "Les rayons du soleil saffaiblissent !",
"strongWindsStartMessage": "Un vent mystérieux se lève !", "strongWindsStartMessage": "Un vent mystérieux se lève !",
"strongWindsLapseMessage": "Le vent mystérieux souffle violemment !", "strongWindsLapseMessage": "Le vent mystérieux souffle violemment !",
"strongWindsEffectMessage": "Le courant aérien mystérieux affaiblit lattaque!", "strongWindsEffectMessage": "Le courant aérien mystérieux affaiblit lattaque !",
"strongWindsClearMessage": "Le vent mystérieux sest dissipé…" "strongWindsClearMessage": "Le vent mystérieux sest dissipé…"
} }

View File

@ -11,6 +11,7 @@
"blockItemTheft": "{{abilityName}} di {{pokemonNameWithAffix}}\nlo rende immune ai furti!", "blockItemTheft": "{{abilityName}} di {{pokemonNameWithAffix}}\nlo rende immune ai furti!",
"typeImmunityHeal": "{{pokemonName}} recupera alcuni PS\ncon {{abilityName}}!", "typeImmunityHeal": "{{pokemonName}} recupera alcuni PS\ncon {{abilityName}}!",
"nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}} evita il colpo\ncon {{abilityName}}!", "nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}} evita il colpo\ncon {{abilityName}}!",
"fullHpResistType": "{{pokemonNameWithAffix}} fa risplendere la sua corazza\ne altera i rapporti tra i tipi!",
"disguiseAvoidedDamage": "{{pokemonNameWithAffix}} è stato smascherato!", "disguiseAvoidedDamage": "{{pokemonNameWithAffix}} è stato smascherato!",
"moveImmunity": "Non ha effetto su {{pokemonNameWithAffix}}!", "moveImmunity": "Non ha effetto su {{pokemonNameWithAffix}}!",
"reverseDrain": "{{pokemonNameWithAffix}} ha assorbito la melma!", "reverseDrain": "{{pokemonNameWithAffix}} ha assorbito la melma!",
@ -51,6 +52,7 @@
"postSummonTeravolt": "{{pokemonNameWithAffix}} emana unaura repulsiva!", "postSummonTeravolt": "{{pokemonNameWithAffix}} emana unaura repulsiva!",
"postSummonDarkAura": "Labilità Auratetra di {{pokemonNameWithAffix}} è attiva.", "postSummonDarkAura": "Labilità Auratetra di {{pokemonNameWithAffix}} è attiva.",
"postSummonFairyAura": "Labilità Aurafolletto di {{pokemonNameWithAffix}} è attiva.", "postSummonFairyAura": "Labilità Aurafolletto di {{pokemonNameWithAffix}} è attiva.",
"postSummonAuraBreak": "{{pokemonNameWithAffix}} inverte gli effetti di tutte le aure!",
"postSummonNeutralizingGas": "Il Gas Reagente di {{pokemonNameWithAffix}}\nsi diffonde tuttintorno!", "postSummonNeutralizingGas": "Il Gas Reagente di {{pokemonNameWithAffix}}\nsi diffonde tuttintorno!",
"postSummonAsOneGlastrier": "{{pokemonNameWithAffix}} ha due abilità!", "postSummonAsOneGlastrier": "{{pokemonNameWithAffix}} ha due abilità!",
"postSummonAsOneSpectrier": "{{pokemonNameWithAffix}} ha due abilità!", "postSummonAsOneSpectrier": "{{pokemonNameWithAffix}} ha due abilità!",
@ -59,4 +61,4 @@
"postSummonTabletsOfRuin": "La/l'{{statName}} dei Pokémon intorno si indebolisce a causa\ndell'abilità Amuleto Nefasto di {{pokemonNameWithAffix}}!", "postSummonTabletsOfRuin": "La/l'{{statName}} dei Pokémon intorno si indebolisce a causa\ndell'abilità Amuleto Nefasto di {{pokemonNameWithAffix}}!",
"postSummonBeadsOfRuin": "La/l'{{statName}} dei Pokémon intorno si indebolisce a causa\ndell'abilità Monile Nefasto di {{pokemonNameWithAffix}}!", "postSummonBeadsOfRuin": "La/l'{{statName}} dei Pokémon intorno si indebolisce a causa\ndell'abilità Monile Nefasto di {{pokemonNameWithAffix}}!",
"preventBerryUse": "{{pokemonNameWithAffix}} non riesce a\nmangiare le bacche per l'agitazione!" "preventBerryUse": "{{pokemonNameWithAffix}} non riesce a\nmangiare le bacche per l'agitazione!"
} }

View File

@ -44,6 +44,7 @@
"moveNotImplemented": "{{moveName}} non è ancora implementata e non può essere selezionata.", "moveNotImplemented": "{{moveName}} non è ancora implementata e non può essere selezionata.",
"moveNoPP": "Non ci sono PP rimanenti\nper questa mossa!", "moveNoPP": "Non ci sono PP rimanenti\nper questa mossa!",
"moveDisabled": "{{moveName}} è disabilitata!", "moveDisabled": "{{moveName}} è disabilitata!",
"disableInterruptedMove": "La mossa {{moveName}} di\n{{pokemonNameWithAffix}} è bloccata!",
"noPokeballForce": "Una forza misteriosa\nimpedisce l'uso delle Poké Ball.", "noPokeballForce": "Una forza misteriosa\nimpedisce l'uso delle Poké Ball.",
"noPokeballTrainer": "Non puoi catturare\nPokémon di altri allenatori!", "noPokeballTrainer": "Non puoi catturare\nPokémon di altri allenatori!",
"noPokeballMulti": "Puoi lanciare una Poké Ball\nsolo quando rimane un singolo Pokémon!", "noPokeballMulti": "Puoi lanciare una Poké Ball\nsolo quando rimane un singolo Pokémon!",
@ -95,4 +96,4 @@
"congratulations": "Congratulazioni!", "congratulations": "Congratulazioni!",
"beatModeFirstTime": "{{speciesName}} ha completato la modalità {{gameMode}} per la prima volta!\nHai ricevuto {{newModifier}}!", "beatModeFirstTime": "{{speciesName}} ha completato la modalità {{gameMode}} per la prima volta!\nHai ricevuto {{newModifier}}!",
"ppReduced": "I PP della mossa {{moveName}} di\n{{targetName}} sono stati ridotti di {{reduction}}!" "ppReduced": "I PP della mossa {{moveName}} di\n{{targetName}} sono stati ridotti di {{reduction}}!"
} }

View File

@ -67,5 +67,8 @@
"saltCuredLapse": "{{pokemonNameWithAffix}} viene colpito da {{moveName}}!", "saltCuredLapse": "{{pokemonNameWithAffix}} viene colpito da {{moveName}}!",
"cursedOnAdd": "{{pokemonNameWithAffix}} ha sacrificato metà dei suoi PS per\nlanciare una maledizione su {{pokemonName}}!", "cursedOnAdd": "{{pokemonNameWithAffix}} ha sacrificato metà dei suoi PS per\nlanciare una maledizione su {{pokemonName}}!",
"cursedLapse": "{{pokemonNameWithAffix}} subisce la maledizione!", "cursedLapse": "{{pokemonNameWithAffix}} subisce la maledizione!",
"stockpilingOnAdd": "{{pokemonNameWithAffix}} ha usato Accumulo per la\n{{stockpiledCount}}ª volta!" "stockpilingOnAdd": "{{pokemonNameWithAffix}} ha usato Accumulo per la\n{{stockpiledCount}}ª volta!",
} "disabledOnAdd": "La mossa {{moveName}} di\n{{pokemonNameWithAffix}} è stata bloccata!",
"disabledLapse": "La mossa {{moveName}} di\n{{pokemonNameWithAffix}} non è più bloccata!",
"tarShotOnAdd": "{{pokemonNameWithAffix}} è diventato vulnerabile\nal tipo Fuoco!"
}

View File

@ -2,6 +2,7 @@
"pp": "PP", "pp": "PP",
"power": "Potenza", "power": "Potenza",
"accuracy": "Precisione", "accuracy": "Precisione",
"abilityFlyInText": "{{passive}} {{pokemonName}} {{abilityName}}", "abilityFlyInText": "{{passive}}{{pokemonName}}\n{{abilityName}}",
"passive": "Passiva di " "passive": "Passiva di ",
} "teraHover": "Teracristallizzato {{type}}"
}

View File

@ -51,5 +51,7 @@
"renamePokemon": "Rinomina un Pokémon", "renamePokemon": "Rinomina un Pokémon",
"rename": "Rinomina", "rename": "Rinomina",
"nickname": "Nickname", "nickname": "Nickname",
"errorServerDown": "Poffarbacco! C'è stato un errore nella comunicazione col server.\n\nPuoi lasciare questa finestra aperta,\nil gioco si riconnetterà automaticamente." "errorServerDown": "Poffarbacco! C'è stato un errore nella comunicazione col server.\n\nPuoi lasciare questa finestra aperta,\nil gioco si riconnetterà automaticamente.",
} "noSaves": "Non ci sono file di salvataggio registrati!",
"tooManySaves": "Ci sono troppi file di salvataggio registrati!"
}

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