From 05b01400759b76a0b68a7c5efccc712400b6e4c8 Mon Sep 17 00:00:00 2001 From: Mistmemo <114654503+LeoDoby@users.noreply.github.com> Date: Wed, 1 May 2024 02:32:02 +0200 Subject: [PATCH 01/45] Add color for the IV scanner (#363) * Add color for the IV scanner add a new color SUMMARY_GREEN in text.js, add the green color if the iv of the pokemon is better than the iv on the starter of that pokemon Co-authored-by: EmoUsedHM01 <131687820+emousedhm01@users.noreply.github.com> * fix battle-message-ui-handler.ts formatting * fix missing similicon battle-message-ui-handler.ts * modified so it take a boolean instead of doing lot of else if battle-message-ui-handler.ts --------- Co-authored-by: EmoUsedHM01 <131687820+emousedhm01@users.noreply.github.com> --- src/ui/battle-message-ui-handler.ts | 52 ++++++++++++++++++----------- src/ui/text.ts | 4 +++ 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/src/ui/battle-message-ui-handler.ts b/src/ui/battle-message-ui-handler.ts index 7bf983c34ed..77144d6bbc0 100644 --- a/src/ui/battle-message-ui-handler.ts +++ b/src/ui/battle-message-ui-handler.ts @@ -1,5 +1,5 @@ import BattleScene, { Button } from "../battle-scene"; -import { addTextObject, TextStyle } from "./text"; +import { addBBCodeTextObject, addTextObject, getTextColor, TextStyle } from "./text"; import { Mode } from "./ui"; import * as Utils from "../utils"; import MessageUiHandler from "./message-ui-handler"; @@ -9,7 +9,7 @@ import { addWindow } from "./ui-theme"; export default class BattleMessageUiHandler extends MessageUiHandler { private levelUpStatsContainer: Phaser.GameObjects.Container; private levelUpStatsIncrContent: Phaser.GameObjects.Text; - private levelUpStatsValuesContent: Phaser.GameObjects.Text; + private levelUpStatsValuesContent: BBCodeText; private nameBox: Phaser.GameObjects.NineSlice; private nameText: Phaser.GameObjects.Text; @@ -29,7 +29,7 @@ export default class BattleMessageUiHandler extends MessageUiHandler { this.textCallbackTimer = null; const bg = this.scene.add.sprite(0, 0, 'bg', this.scene.windowType); - bg.setOrigin(0, 1); + bg.setOrigin(0, 1); ui.add(bg); this.bg = bg; @@ -95,18 +95,19 @@ export default class BattleMessageUiHandler extends MessageUiHandler { this.levelUpStatsContainer = levelUpStatsContainer; - const levelUpStatsBg = addWindow(this.scene, (this.scene.game.canvas.width / 6), -100, 128, 100); - levelUpStatsBg.setOrigin(1, 0); - levelUpStatsContainer.add(levelUpStatsBg); - - const levelUpStatsLabelsContent = addTextObject(this.scene, (this.scene.game.canvas.width / 6) - 121, -94, '', TextStyle.WINDOW, { maxLines: 6 }); + const levelUpStatsLabelsContent = addTextObject(this.scene, (this.scene.game.canvas.width / 6) - 73, -94, '', TextStyle.WINDOW, { maxLines: 6 }); let levelUpStatsLabelText = ''; const stats = Utils.getEnumValues(Stat); for (let s of stats) levelUpStatsLabelText += `${getStatName(s)}\n`; - levelUpStatsLabelsContent.text = levelUpStatsLabelText; + levelUpStatsLabelsContent.x -= levelUpStatsLabelsContent.displayWidth; + + const levelUpStatsBg = addWindow(this.scene, (this.scene.game.canvas.width / 6), -100, 80 + levelUpStatsLabelsContent.displayWidth, 100); + levelUpStatsBg.setOrigin(1, 0); + levelUpStatsContainer.add(levelUpStatsBg); + levelUpStatsContainer.add(levelUpStatsLabelsContent); const levelUpStatsIncrContent = addTextObject(this.scene, (this.scene.game.canvas.width / 6) - 50, -94, '+\n+\n+\n+\n+\n+', TextStyle.WINDOW, { maxLines: 6 }); @@ -114,7 +115,7 @@ export default class BattleMessageUiHandler extends MessageUiHandler { this.levelUpStatsIncrContent = levelUpStatsIncrContent; - const levelUpStatsValuesContent = addTextObject(this.scene, (this.scene.game.canvas.width / 6) - 7, -94, '', TextStyle.WINDOW, { maxLines: 6 }); + const levelUpStatsValuesContent = addBBCodeTextObject(this.scene, (this.scene.game.canvas.width / 6) - 7, -94, '', TextStyle.WINDOW, { maxLines: 6 , lineSpacing: 5}); levelUpStatsValuesContent.setOrigin(1, 0); levelUpStatsValuesContent.setAlign('right'); levelUpStatsContainer.add(levelUpStatsValuesContent); @@ -208,7 +209,7 @@ export default class BattleMessageUiHandler extends MessageUiHandler { } else shownStats = stats; for (let s of stats) - levelUpStatsValuesText += `${shownStats.indexOf(s) > -1 ? this.getIvDescriptor(ivs[s]) : '???'}\n`; + levelUpStatsValuesText += `${shownStats.indexOf(s) > -1 ? this.getIvDescriptor(ivs[s], s) : '???'}\n`; this.levelUpStatsValuesContent.text = levelUpStatsValuesText; this.levelUpStatsIncrContent.setVisible(false); this.levelUpStatsContainer.setVisible(true); @@ -221,18 +222,29 @@ export default class BattleMessageUiHandler extends MessageUiHandler { }); } - getIvDescriptor(value: integer): string { + getIvDescriptor(value: integer, typeIv: integer): string { + let starterIvs: number[] = this.scene.gameData.dexData[this.scene.getEnemyPokemon().species.speciesId].ivs; + let uiTheme = (this.scene as BattleScene).uiTheme; // Assuming uiTheme is accessible + + // Function to wrap text in color based on comparison + const coloredText = (text: string, isBetter: boolean) => { + const textStyle: TextStyle = isBetter ? TextStyle.SUMMARY_GREEN : TextStyle.SUMMARY; + const color = getTextColor(textStyle, false, uiTheme); + return `[color=${color}][shadow=${getTextColor(textStyle, true, uiTheme)}]${text}[/shadow][/color]`; + }; + if (value > 30) - return 'Best'; + return coloredText('Best', value > starterIvs[typeIv]); if (value === 30) - return 'Fantastic'; + return coloredText('Fantastic', value > starterIvs[typeIv]); if (value > 20) - return 'Very Good'; + return coloredText('Very Good', value > starterIvs[typeIv]); if (value > 10) - return 'Pretty Good'; - if (value) - return 'Decent'; - return 'No Good'; + return coloredText('Pretty Good', value > starterIvs[typeIv]); + if (value > 0) + return coloredText('Decent', value > starterIvs[typeIv]); + + return coloredText('No Good', value > starterIvs[typeIv]); } showNameText(name: string): void { @@ -244,4 +256,4 @@ export default class BattleMessageUiHandler extends MessageUiHandler { hideNameText(): void { this.nameBoxContainer.setVisible(false); } -} \ No newline at end of file +} diff --git a/src/ui/text.ts b/src/ui/text.ts index bfb02d06e27..a8cce878240 100644 --- a/src/ui/text.ts +++ b/src/ui/text.ts @@ -19,6 +19,7 @@ export enum TextStyle { SUMMARY_PINK, SUMMARY_GOLD, SUMMARY_GRAY, + SUMMARY_GREEN, MONEY, SETTINGS_LABEL, SETTINGS_SELECTED, @@ -82,6 +83,7 @@ function getTextStyleOptions(style: TextStyle, uiTheme: UiTheme, extraStyleOptio case TextStyle.SUMMARY_PINK: case TextStyle.SUMMARY_GOLD: case TextStyle.SUMMARY_GRAY: + case TextStyle.SUMMARY_GREEN: case TextStyle.WINDOW: case TextStyle.WINDOW_ALT: case TextStyle.MESSAGE: @@ -160,6 +162,8 @@ export function getTextColor(textStyle: TextStyle, shadow?: boolean, uiTheme: Ui return !shadow ? '#e8e8a8' : '#a0a060'; case TextStyle.SUMMARY_GRAY: return !shadow ? '#a0a0a0' : '#636363'; + case TextStyle.SUMMARY_GREEN: + return !shadow ? '#78c850' : '#306850'; case TextStyle.SETTINGS_LABEL: return !shadow ? '#f8b050' : '#c07800'; case TextStyle.SETTINGS_SELECTED: From 718585062bf3d5bf5067003da9a6b70bfb407940 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Tue, 30 Apr 2024 22:06:54 -0400 Subject: [PATCH 02/45] Add togglable stat change display --- index.css | 4 + index.html | 3 + public/images/pbinfo_stat_numbers.json | 293 ++++++++++++++++++ .../ui/legacy/pbinfo_enemy_boss_stats.png | Bin 0 -> 435 bytes .../ui/legacy/pbinfo_enemy_mini_stats.png | Bin 0 -> 666 bytes .../ui/legacy/pbinfo_player_mini_stats.png | Bin 0 -> 674 bytes .../images/ui/legacy/pbinfo_player_stats.png | Bin 0 -> 285 bytes public/images/ui/legacy/pbinfo_stat.json | 188 +++++++++++ public/images/ui/legacy/pbinfo_stat.png | Bin 0 -> 263 bytes .../images/ui/legacy/pbinfo_stat_numbers.json | 293 ++++++++++++++++++ .../images/ui/legacy/pbinfo_stat_numbers.png | Bin 0 -> 392 bytes public/images/ui/pbinfo_enemy_boss.png | Bin 554 -> 526 bytes public/images/ui/pbinfo_enemy_boss_stats.png | Bin 0 -> 257 bytes public/images/ui/pbinfo_enemy_mini.png | Bin 888 -> 851 bytes public/images/ui/pbinfo_enemy_mini_stats.png | Bin 0 -> 642 bytes public/images/ui/pbinfo_enemy_type.png | Bin 1502 -> 3599 bytes public/images/ui/pbinfo_enemy_type1.png | Bin 1360 -> 3305 bytes public/images/ui/pbinfo_enemy_type2.png | Bin 1340 -> 3197 bytes public/images/ui/pbinfo_player.png | Bin 654 -> 619 bytes public/images/ui/pbinfo_player_mini.png | Bin 898 -> 860 bytes public/images/ui/pbinfo_player_mini_stats.png | Bin 0 -> 648 bytes public/images/ui/pbinfo_player_stats.png | Bin 0 -> 312 bytes public/images/ui/pbinfo_player_type1.png | Bin 1340 -> 3197 bytes public/images/ui/pbinfo_player_type2.png | Bin 1360 -> 3305 bytes public/images/ui/pbinfo_stat.json | 188 +++++++++++ public/images/ui/pbinfo_stat.png | Bin 0 -> 278 bytes public/images/ui/pbinfo_stat_numbers.json | 293 ++++++++++++++++++ public/images/ui/pbinfo_stat_numbers.png | Bin 0 -> 430 bytes src/battle-scene.ts | 72 +++-- src/data/splash-messages.ts | 3 +- src/field/pokemon.ts | 4 + src/loading-scene.ts | 6 + src/locales/de/tutorial.ts | 4 + src/locales/en/tutorial.ts | 4 + src/locales/es/tutorial.ts | 4 + src/locales/fr/tutorial.ts | 4 + src/locales/it/tutorial.ts | 4 + src/phases.ts | 10 +- src/tutorial.ts | 6 + src/ui/battle-info.ts | 100 +++++- 40 files changed, 1440 insertions(+), 43 deletions(-) create mode 100644 public/images/pbinfo_stat_numbers.json create mode 100644 public/images/ui/legacy/pbinfo_enemy_boss_stats.png create mode 100644 public/images/ui/legacy/pbinfo_enemy_mini_stats.png create mode 100644 public/images/ui/legacy/pbinfo_player_mini_stats.png create mode 100644 public/images/ui/legacy/pbinfo_player_stats.png create mode 100644 public/images/ui/legacy/pbinfo_stat.json create mode 100644 public/images/ui/legacy/pbinfo_stat.png create mode 100644 public/images/ui/legacy/pbinfo_stat_numbers.json create mode 100644 public/images/ui/legacy/pbinfo_stat_numbers.png create mode 100644 public/images/ui/pbinfo_enemy_boss_stats.png create mode 100644 public/images/ui/pbinfo_enemy_mini_stats.png create mode 100644 public/images/ui/pbinfo_player_mini_stats.png create mode 100644 public/images/ui/pbinfo_player_stats.png create mode 100644 public/images/ui/pbinfo_stat.json create mode 100644 public/images/ui/pbinfo_stat.png create mode 100644 public/images/ui/pbinfo_stat_numbers.json create mode 100644 public/images/ui/pbinfo_stat_numbers.png diff --git a/index.css b/index.css index 9a507ad6766..dd47387adee 100644 --- a/index.css +++ b/index.css @@ -150,6 +150,10 @@ body { display: none; } +#touchControls:not([data-ui-mode='COMMAND']):not([data-ui-mode='FIGHT']):not([data-ui-mode='BALL']):not([data-ui-mode='TARGET_SELECT']) #apad #apadStats { + display: none; +} + #apad .apadRectBtnContainer + .apadSqBtnContainer { top: calc(var(--controls-size) * -1.9); left: calc(var(--controls-size) * -0.9); diff --git a/index.html b/index.html index bd316330a99..506fa4f1efa 100644 --- a/index.html +++ b/index.html @@ -74,6 +74,9 @@
V
+
+ Shift +
Menu
diff --git a/public/images/pbinfo_stat_numbers.json b/public/images/pbinfo_stat_numbers.json new file mode 100644 index 00000000000..32170690aa0 --- /dev/null +++ b/public/images/pbinfo_stat_numbers.json @@ -0,0 +1,293 @@ +{ + "textures": [ + { + "image": "pbinfo_stat_numbers.png", + "format": "RGBA8888", + "size": { + "w": 117, + "h": 8 + }, + "scale": 1, + "frames": [ + { + "filename": "+1", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "+2", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 9, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "+3", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 18, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "+4", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 27, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "+5", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 36, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "+6", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 45, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-1", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 54, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-2", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 63, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-3", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 72, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-4", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 81, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-5", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 90, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-6", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 99, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "0", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 108, + "y": 0, + "w": 9, + "h": 8 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:794aa4af3291db5abd8a2667626c1998:1a6706ad557b92f9bf099c23e02af4a6:6537c634087637bb27e8a1edb1ee2e35$" + } +} diff --git a/public/images/ui/legacy/pbinfo_enemy_boss_stats.png b/public/images/ui/legacy/pbinfo_enemy_boss_stats.png new file mode 100644 index 0000000000000000000000000000000000000000..94c9f2a181736d88c6752f2c97ed0bbbee23ebcc GIT binary patch literal 435 zcmeAS@N?(olHy`uVBq!ia0vp^n}ArJgAGVJb4-r_QjEnx?oJHr&dIz4vU5FM978JR zyuG8?cgR7a?csXf_7^8kc|Ex$m-yBz<$7q-n^RU*Eb9Vy3q^L$xwlCBgn&~-ln2-0 zC$%D(Zao#Zd6NElh+n&%^Pj+>91Q?jM7YZ*~R6rK6tBHXtJ>3o}%+B70Tit?}|9LLp3388Oyx(ny$dZ`X4n6UD>PshjO%e?;W3et7Lx@QEIV2LHO-ZhLc6eY9Ry zIQ|Mdb1{9R)SaoXcSRIE<`z6H%nuWjbE9V$ zXGWbr(B0xb=lC1f6GDcM4fWFUoyzXm2QNAn5;^S^|FUJBo0|`=UT>R$XHs^CNV z##av>ty$f?T7lzV!;W1Rn!7wYzpJ*28OBxY>HqxBa!BncE&SaXRbV6dDO(__3L?7E8i*EoZkKZ{HwqsHRc+nk205eyDOS2sxDu$ zd@tM{5g62QzVkTGE`^WE*Hfq8w-A>Rt4KTHq5izn`AE{j-lt}1uFk6Sl=!q)x&3rH zmfHGREPZQC>e=c~;%vpYyt-a*X%jpw^vJ`ZrANz4IZ?ukeBYJTaNN^-KBA z)J%%Y&U~o6pj>*#j=aoIas@k?dF)+-(V{Q3XI{exr|Grpv%NI5;(qK@ xp0+UKM9$<@NoVioZhp6Q^O64&v*v`HV4ZIk%FUH_dOOew44$rjF6*2UngE&&E5rZ* literal 0 HcmV?d00001 diff --git a/public/images/ui/legacy/pbinfo_player_mini_stats.png b/public/images/ui/legacy/pbinfo_player_mini_stats.png new file mode 100644 index 0000000000000000000000000000000000000000..dd2b7e65ba3522986e78d6844a6be8823c3382ae GIT binary patch literal 674 zcmV;T0$u%yP)EX>4Tx04R}tkv&MmKpe$iQ%gl!9Lyl%kfA!+MMWJ;6^me@v=v%)FuC*#nzSS- zE{=k0!NHHks)LKOt`4q(Aou~|>f)s6A|?JWDYS_3;J6>}?mh0_0Ya# zo%24i$jY)xd`>)J&;^MfxvseU#<}FMz%xZ7o1P~YiKS8xD?QB0hDJP198oo$@`aqs zD(5ZETD8GC_v9}O74(%1*J+L-fh8o7qK*_aP(c+IqO|Iym`Kxp+`~WO_*3Lk$W;L& z#{z25AUl5WKlt6PS)7`5lR|MI@M7B^V?b~hXg6*9``EVICxHJMxYE1+S__!_B)!?y zB1gdBHgIv>)s#Kpat9cGs>_D#NPe0^u?W1M(KqFRp<7^J&F!tTkJASrOIK2l+uOfqI{p0s^F(smE#4Fv0000mP)t-s0001cl!Q`iV>wbnAvplXy>s5y zwg3O#*3P|BYg+%cd;kCcN$J_5c5S*Us$?%8vTKwfg`6|6Wc}-=`Gc19G2( z)VthFjRI1_B|(0{3_xi#U}t|v7bsoq>Eaj?(fam=p-_VZhjU<>!iIbQ4@G5d*>KA2 zr+S66yVASV%+m`tUAT0h%_Vu-2F6#OE9N=hF1aYEASTnz@k_ZzU>c{|jD#j+;!l_T zYhIRn;@{452VTh2;XbSE{bIVBSPWaCe#7lsobz5x%h_{T;XlZgp00i_>zopr0I}G2 ADF6Tf literal 0 HcmV?d00001 diff --git a/public/images/ui/legacy/pbinfo_stat.json b/public/images/ui/legacy/pbinfo_stat.json new file mode 100644 index 00000000000..b7da47fc192 --- /dev/null +++ b/public/images/ui/legacy/pbinfo_stat.json @@ -0,0 +1,188 @@ +{ + "textures": [ + { + "image": "pbinfo_stat.png", + "format": "RGBA8888", + "size": { + "w": 112, + "h": 6 + }, + "scale": 1, + "frames": [ + { + "filename": "SPATK", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 19, + "h": 8 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 18, + "h": 6 + }, + "frame": { + "x": 0, + "y": 0, + "w": 18, + "h": 6 + } + }, + { + "filename": "SPDEF", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 19, + "h": 8 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 18, + "h": 6 + }, + "frame": { + "x": 18, + "y": 0, + "w": 18, + "h": 6 + } + }, + { + "filename": "CRIT", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 17, + "h": 8 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 16, + "h": 6 + }, + "frame": { + "x": 36, + "y": 0, + "w": 16, + "h": 6 + } + }, + { + "filename": "ACC", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 13, + "h": 8 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 12, + "h": 6 + }, + "frame": { + "x": 52, + "y": 0, + "w": 12, + "h": 6 + } + }, + { + "filename": "ATK", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 13, + "h": 8 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 12, + "h": 6 + }, + "frame": { + "x": 64, + "y": 0, + "w": 12, + "h": 6 + } + }, + { + "filename": "DEF", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 13, + "h": 8 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 12, + "h": 6 + }, + "frame": { + "x": 76, + "y": 0, + "w": 12, + "h": 6 + } + }, + { + "filename": "EVA", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 13, + "h": 8 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 12, + "h": 6 + }, + "frame": { + "x": 88, + "y": 0, + "w": 12, + "h": 6 + } + }, + { + "filename": "SPD", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 13, + "h": 8 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 12, + "h": 6 + }, + "frame": { + "x": 100, + "y": 0, + "w": 12, + "h": 6 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:40d30205ce8efd40dfa86cd11b0491d6:7076db6ed74199dcfb38fc8cd4d4a0e8:05882267d3999884e0491134e98b1b53$" + } +} diff --git a/public/images/ui/legacy/pbinfo_stat.png b/public/images/ui/legacy/pbinfo_stat.png new file mode 100644 index 0000000000000000000000000000000000000000..62ec3758772daea6013a4de5532575a66caf8116 GIT binary patch literal 263 zcmeAS@N?(olHy`uVBq!ia0vp^1whQk!3-pITwg5(Qk(%kA+A8$!NK9)wXI7Q-Kzj{ z7)yfuf*Bm1-ADteDDa3ZW?Ec4QuN(io6fN32b;e=)XJ@8wjxa57 z6;5`pyz#?~2;;a-r4XYn{3?!Y<6HKbItN$2xk}gw>0y zUzy)p<5e-!w)Vy<(87aih3;8-LtI=7KLTHk<}Jk-^i|&t;uc GLK6T7%VuW) literal 0 HcmV?d00001 diff --git a/public/images/ui/legacy/pbinfo_stat_numbers.json b/public/images/ui/legacy/pbinfo_stat_numbers.json new file mode 100644 index 00000000000..9c74ee86dbc --- /dev/null +++ b/public/images/ui/legacy/pbinfo_stat_numbers.json @@ -0,0 +1,293 @@ +{ + "textures": [ + { + "image": "pbinfo_stat_numbers.png", + "format": "RGBA8888", + "size": { + "w": 117, + "h": 8 + }, + "scale": 1, + "frames": [ + { + "filename": "+1", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "+2", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 9, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "+3", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 18, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "+4", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 27, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "+5", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 36, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "+6", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 45, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-1", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 54, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-2", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 63, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-3", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 72, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-4", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 81, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-5", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 90, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-6", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 99, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "0", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 108, + "y": 0, + "w": 9, + "h": 8 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:1f22b7cb085faf9e9764273fa5e70c28:afc5587ebacca78d178ac7e0c434591b:6537c634087637bb27e8a1edb1ee2e35$" + } +} diff --git a/public/images/ui/legacy/pbinfo_stat_numbers.png b/public/images/ui/legacy/pbinfo_stat_numbers.png new file mode 100644 index 0000000000000000000000000000000000000000..ee1453b21070f8de40a299a2d0c82c49093799cc GIT binary patch literal 392 zcmV;30eAk1P)NeVolC?^B79yfh4NP^lrY9U!*DY-V@3rV{hYdQ>YK;=1YJaz3T;`<^$DGJL<5 z0VRW87@CHmA>NuYKzH1TLC5xSzn%dVgI*Y#hCzM2e@<+(--30)Oref_gmu$R&9E*Q zKCPUg&65~>rQzm$c=)wGxON}pkE{!ZPit-h_?q;dhMV)@;n(^|U!-Qgl_%A@VDM** z28vT)T`)O@Pln{f8%r6yr(x9i(DP6xH!0n5bN5`F;gccxJgbFgqhZwe(DRg7RCba7 mA?H5)Du%PaS?j+(7uOe-FYwO$9P0Z30000Ik&UmVKT0GxPa8d!07jZZ!ddIBQBbh_PFZe&65JuT|9nKq=MA`2Ra01f-NW z91f+QE2Xg6Y_!guHF6k+mXtE_eP3^s9ZQpWyFcUJ3~9SRW4V~*j$cQ1WnC#{?2Y{H zp1HO|plBRLh_0>&dpk(u@=|B3Ul!cn-d9Bu|Irn<2(MATii<NL1q8595j002ovPDHLkV1ifd@6!MP delta 515 zcmV+e0{s1s1gZp(F@NMqL_t(|obB6BYQjJm1@M;=C_;s9>aGx7IS8(W?BZR#K+fR> zdKYIGa4pEV(m;21BcvdOLb@oX#w6N||Hk-!EB%ba5WYMoi2;a+$P89q(Q(?bWqnK1js?_P5*2T3V0acimCcp71_vhnu(jb5jIunqv- zU|m?J^YT3J;D0uwQBe98btaL0--i&Q%orEbYPFKro2Hw%bs$(LP1z0Bn7Fmy_dE4% zMRfpBN}Xl?_f7}_DJACfdG6;*DGY~0t+A6v4#Sx>8X@+5UvHKdwn^skG{U|W(s&x7 z*QuwrAFS-cx>Cy61NqkdXW#0iF_3fBLidQcv~I9QcYG^xiwstFvMunJ#6@+wo@071 z6=j=LzJ;IG-9*kySisI*Q}3$_A-J?SlT8{I?O!P+!f>JWs8i-krl0glDKjDTt88$>!uSb_l5uf002ovPDHLk FV1lYA{=)zO diff --git a/public/images/ui/pbinfo_enemy_boss_stats.png b/public/images/ui/pbinfo_enemy_boss_stats.png new file mode 100644 index 0000000000000000000000000000000000000000..7148a7af4759141abb5e2b39c02a17b45af905e5 GIT binary patch literal 257 zcmeAS@N?(olHy`uVBq!ia0vp^n}ArJgAGVJb4-r_QjEnx?oJHr&dIz4a&~*VIEGZr zd3$>`-ysJ9)(e`BNfSH%{_kJqko58BL=U^z3cqSH|eR)57 zW1&p?=O4X~e>-L8TFuvct=1%`yX>BUe4QLNkl8GRYx|2)P*70tlomTy+AL)kaKVi zE&#J{fxIOH3ldw!o(@eA9|jTwfke-5G6qF2@~g-B0uhl?&o>!GQQmYRa=R?cyz5!T z`|(5+MftElx~(F4j)*+88Q$()i?q{0_b3h8Z?jzmZ4pWY0rr0qL21w(A*rB55THl| zr9t=9O$8-_0MJt!bXT2JP$CGRMv#IUK>#&^6m9ha8#1%t_N<261?l{K=~*1pAjk_btXV2r7AjK;-r zyc-`ce5q`T&+mUP){_|k&bdbFdlX{~)>_gu^?vW1V>+D%9edXZS(f#zwRw^xVO733 z=iJLT_%&7jLr5Bc=c*yJqh3v!6wCSI$(1zcmbE+B8p>2?Q-u1?3(9$bLGjrb(}}GC z&Tny{X#k#=SKD&ZXsreQPoB<=eZOzJOKWr2MgYCV+*TmByu~acA|fIpa@iluDW|ek SO(V4c0000wNkl)q|N~u!nI~O4Yq?Ab0 z)cUDa4A$g)|GB+zjjyH$DNlu{Sp;D;RZA6(J^uv|5`cGRUYNim(gR9s1U zPC0iQQ-etbpCZ(@E->2xpqYObLeyev0QOIDQc7gm-04MCwVfaNvS^f20{C4#?Hk+n z_uXHMMb~Ko*z*>1x7*b&2cv4u=Wc00L_|bHM0D5>)LE${MNRhx00000NkvXXu0mjf DZ|lEX>4Tx04R}tkv&MmP!xqvQ>7vm5sQd8WT;LSL`4J_sbUc+7C6sqP{?%e(K->QQng1AHR!9McVpc!PL) z)6zNb6Ngw)Qi#uq#|*k4@gvt|m)|%S92R(H$VeyWi9^IW<^6Ko+1t_sz&)j z#$|=`7H73wWzBo?7Y1|MN{Z{Wh7rRO;z&S*j4Dbf!$O31jT93}I*)qzha7)`Tr#;z zVB}ap1u7)R5B>+gXKUssC)}i96zF`h?T-;4unRP5w*7r<+l>>z{|sDdEq|pB%zTnw zYiZ#lpm!U%xNd3k9&ot>3_j_SAvuztmXOZ_?`QN)S)l(G=w5T@);!1Q1CXX!E#CkK zhrnoove!M{-PJy~e|wtq`vH(aagbUB zzo-t5uI_cI;7<`vL}@r@>=fw7Q_>^>xEhuomQto)FNAjEI4-`=cWfUYlv1Ys?$EX( z{-b279fr-f*TOp8O^+I^-|2j;`a~!KNp6au2K}h1f+CP)E`l2L=hG@E0!flV4f^#- z6%>Ia27#GDAc;X>X8YJF+efPS#oQskn5pI%x-*WUY4S8Vs<2+QHAobJnOn>qX}QG= c008jX1y1rsg=?D3Y5)KL07*qoM6N<$f~t=qVE_OC literal 0 HcmV?d00001 diff --git a/public/images/ui/pbinfo_enemy_type.png b/public/images/ui/pbinfo_enemy_type.png index 021a120070c1872b54405196e4bcb2cec9920d06..9bac63e5e72ba305c0c7769d72bc39d72aa8202e 100644 GIT binary patch literal 3599 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 diff --git a/public/images/ui/pbinfo_enemy_type1.png b/public/images/ui/pbinfo_enemy_type1.png index 89b84d7f6305169db2e227aa33a9e2202cdeebfa..6d94871e8da1dfd56a0271a6a8ef1ae8e9d6c3c4 100644 GIT binary patch literal 3305 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 delta 1332 zcmV-41K;roK6x|8rVOt-T?ULCa%fweLZBshW_&&HC;* zO0vk;&DMDOm4U9|mAs4J&B(p@`1tjx^{$}s^^2`iam|Lp|9@hcy`Z4dqs6<(m4=$( z@Ycwh|J;Giu7~bbDWAdC&0W2FNPBZod$Y)zgQZ%P*Yx1fkon7G_No9%p+S^Ti}|f> zm8jtMc@R>*?(~L`sg$n0l(@~ZN?llm^Z)<=0d!JMQvg8b*k%9#010qNS#tmY4#WTe z4#WYKD-Ig~0DlAzNkl(^Y-#Wr6(Oj4xVAPdRD7!nD#iAB*BzHNIOCF7+K!2!Mo?4Ma{y?`n4?k5THGfPb znjaf?PygBd=;)}=AC3b1KsV?cB*s@ciU)rw57cPk>(CnArfu-@+b7_eU=Lj1OnvNcwffW0-uP_mXO_l4S!y5_eP^JhH)c@!3IEp%o=Epqlf^Q zdl4vm%oVI6jAf-z5$|I$U2Dmtnyz&NU|gM1Tovo?z9%sl038k@0T?JGHsIL@QDnrd zDzX{HYQ?=uvO=g-#FB$Nsuv5}+iLfdlS^uKdBRa(`I~AmiC0_`**#%3i+m|xZDaqP znSbbOs;KIv6AN{%B`!mDz1^R4OyqbTAb6NW0}$>+AUJ_2A{5z+2=NU>5xD9kiW7b_ ziQ3*&JDtuMz*$E^ zq5Oy)WOl}~7tbVB4ihDjPFJx4ljiYZ^SDMTc5Eak+VETLetdjNB~Onz3M4|@U_y^2 zIZTv9KC>90ws`^*7o%$YR54G)Z&akbQ~r1nO{!**|rqpNJ<0!EF`8Alxn}7E5 z(}~lmd`(2y!z<9KqCiv?B4ap}nkwRT+RHPkNNQz9jwytB>h0bPVUU_P&kYuaaOFk$ z8LiIGod{VZ7{z9D<;CVoyik#-*^P(`O#DR2_+sU8C^NhOn2+~R33uoA15d^47ggKu*i{Slh@`p?1>g%h%6Cw5J!=T0U*R1MnDJ6|U#*Z*JkoesN4y6h&V9 zS^IL#rHNpS$$z3KVzb$F)3Ol+L9lnip}Z&_gDU{iG###yJqW`PfbDi$yYFhX!dhEB z4IRgEH!YixG)-SW$f;^_3~?M|t<_*LPlNlL+mTx`uF6D6l4LfiP&6*cw*!3q`#KE6 z*>nv)$B`rn;PGFB@1WyQS!;op!Bg3K(f(8CKUlOl=YJNph0sZ>!pgJLse-2Lyi&dt}*K+!0R$E0vTWLUzE`_5mXrc zsQaRf);@*cL$jCTsXOrp#Tb)a{=Cd~yPcLDF5CP8>Nk1daueF@H!&L_t(|obBAdPTNo%hT%6=r7mDtOmVaZ|#D^=AwA$T>{|y z{`MMK0n4%gn9t{_=Z;1rTz8s03~k$XIW5~GzVAQ(BKK9E&tTg&t~=GuVw47V*Ecn{ zq+W@M;5bfWQX%fXAUY0k`1iGCS&iu$vV0E5aexf}HGd3;XC*YPKAz_Re{P;O?Z=(J z@3P-4P6>ipC$SJTFR}T;@LhT#Kr@~tNIX4Rlr7F3ih1JlvSD0}h;CUMrfz+?^FUrW92r7(fqb;z7>41Gsv{dh>cWt0R&T-FUZ9s?$T_$M z7l7HfK;Dvp1&OUH5K*IY>CJ^)^|N88NNC4pVs+=4}QGTmJ(3~vGe$D%9 z=$A!Nln?u(Y8Bx=BIU(qc)3?Ccq~Cn18LBHo9*gki69XmDIk9lNQ3S;P6ZMHlCDey z(x7{MDv$_}bVVYN2HmyUuGk}Bhem)T8UcGW0wi(y`1JhcWAML^ZL!&|BuT^msC0bn znVUT57V~&KuA`Qlv)1Y@{gNcD<5}t0Th136Ouiehu`ZX)k+t@4i#a$Ek|dEaCiL`1 z#BqEW7bo8HP4R#J`Jwe>CP{M6HBw()j4`s-DoxYU_nmW^PNyfwu5N@Z%X-$@JV}zU zDj%G4?%^B!KbQQ5<1~;eTs0Iss;zudEa!_mSJIraxeHnvd@8glLd*6A{^x002ovPDHLkV1g-F&x8N~ delta 473 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 delta 1332 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 Wt8RFN+!3I289ZJ6T-G@yGywokWokPB literal 0 HcmV?d00001 diff --git a/public/images/ui/pbinfo_stat_numbers.json b/public/images/ui/pbinfo_stat_numbers.json new file mode 100644 index 00000000000..ec4f7117bb7 --- /dev/null +++ b/public/images/ui/pbinfo_stat_numbers.json @@ -0,0 +1,293 @@ +{ + "textures": [ + { + "image": "pbinfo_stat_numbers.png", + "format": "RGBA8888", + "size": { + "w": 117, + "h": 8 + }, + "scale": 1, + "frames": [ + { + "filename": "1", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "2", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 9, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "3", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 18, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "4", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 27, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "5", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 36, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "6", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 45, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-1", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 54, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-2", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 63, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-3", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 72, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-4", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 81, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-5", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 90, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-6", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 99, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "0", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 108, + "y": 0, + "w": 9, + "h": 8 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:b0719fae0d9b670a727148cdc7202249:afc5587ebacca78d178ac7e0c434591b:4825a9f02f72f1fe28a724c6c5dffb37$" + } +} diff --git a/public/images/ui/pbinfo_stat_numbers.png b/public/images/ui/pbinfo_stat_numbers.png new file mode 100644 index 0000000000000000000000000000000000000000..c778ba992734421a718b2c49db1db0ae77a28e09 GIT binary patch literal 430 zcmV;f0a5;mP)X}UpFSFJe%YMSjb zvz=}Te=dw_+OM;>zwNiTz<(WGW!%j?&)@0VTARh5OWbc`j(J{Tok%Zt#$YoH;sBj7 z0D#IlJRc6p%*|?r>-8D{#_^;+F^22I1yqy`_PebZNKrNbfWEEq_WF{{oLyYu^!yS4 z#PO(4jM4P@WGYS8UqlLVGYqiSvW&F&OBuS>FtHC$Vz?0ZyX|CN5<3@SjG<>5X2}?8 zQ)v+?7z&xQg%~oUa!zD?QzeEgj_Hh<7_VVM6DZ`EEo4UD)*|DZy2Lt;DavMIyoRBA zxP2Ty%KN9gENZI8IE_78Q^T$GD~(@jhsGYQsdI~*V!X;!+J?fg{Gd2S+NQZaWGcsm zi<{b~a&9zLI&@IbQb7LyuD?x7eaKXf@hzMCJ+VH0TaTtDpMHPh p)) + p.toggleStats(pressed); + if (pressed) + this.setLastProcessedMovementTime(Button.STATS); + } else + return; + } if (inputSuccess && this.enableVibration && typeof navigator.vibrate !== 'undefined') navigator.vibrate(vibrationLength || 10); } @@ -1443,7 +1454,7 @@ export default class BattleScene extends SceneBase { * or not. It will only return true once, until the key is released and pressed down * again. */ - gamepadButtonJustDown(button: Phaser.Input.Gamepad.Button) : boolean { + gamepadButtonJustDown(button: Phaser.Input.Gamepad.Button): boolean { if (!button || !this.gamepadSupport) return false; @@ -1463,6 +1474,23 @@ export default class BattleScene extends SceneBase { return this.buttonKeys[button].some(k => Phaser.Input.Keyboard.JustDown(k)) || this.gamepadButtonJustDown(gamepad?.buttons[this.gamepadKeyConfig[button]]); } + /** + * gamepadButtonJustUp returns true if @param button has just been released + * or not. It will only return true once, until the key is released and pressed down + * again. + */ + gamepadButtonJustUp(button: Phaser.Input.Gamepad.Button): boolean { + if (!button || !this.gamepadSupport) + return false; + + return !this.gamepadButtonStates[button.index]; + } + + buttonJustReleased(button: Button): boolean { + const gamepad = this.input.gamepad?.gamepads[0]; + return this.buttonKeys[button].some(k => Phaser.Input.Keyboard.JustUp(k)) || this.gamepadButtonJustUp(gamepad?.buttons[this.gamepadKeyConfig[button]]); + } + /** * repeatInputDurationJustPassed returns true if @param button has been held down long * enough to fire a repeated input. A button must claim the movementButtonLock before diff --git a/src/data/splash-messages.ts b/src/data/splash-messages.ts index 11629cf05d7..198ff07cec9 100644 --- a/src/data/splash-messages.ts +++ b/src/data/splash-messages.ts @@ -33,6 +33,5 @@ splashMessages.push(...[ 'Also Try Emerald Rogue!', 'Also Try Radical Red!', 'Eevee Expo!', - 'YNOproject!', - 'Shh, don\'t tell Sam!' + 'YNOproject!' ]); \ No newline at end of file diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 9a7bfb48621..7072875d3ce 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -1179,6 +1179,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return this.battleInfo.updateInfo(this, instant); } + toggleStats(visible: boolean): void { + this.battleInfo.toggleStats(visible); + } + addExp(exp: integer) { const maxExpLevel = this.scene.getMaxExpLevel(); const initialExp = this.exp; diff --git a/src/loading-scene.ts b/src/loading-scene.ts index 2f37b900ab5..875d618ec0f 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -39,15 +39,21 @@ export class LoadingScene extends SceneBase { } this.loadAtlas('namebox', 'ui'); this.loadImage('pbinfo_player', 'ui'); + this.loadImage('pbinfo_player_stats', 'ui'); this.loadImage('pbinfo_player_mini', 'ui'); + this.loadImage('pbinfo_player_mini_stats', 'ui'); this.loadAtlas('pbinfo_player_type', 'ui'); this.loadAtlas('pbinfo_player_type1', 'ui'); this.loadAtlas('pbinfo_player_type2', 'ui'); this.loadImage('pbinfo_enemy_mini', 'ui'); + this.loadImage('pbinfo_enemy_mini_stats', 'ui'); this.loadImage('pbinfo_enemy_boss', 'ui'); + this.loadImage('pbinfo_enemy_boss_stats', 'ui'); this.loadAtlas('pbinfo_enemy_type', 'ui'); this.loadAtlas('pbinfo_enemy_type1', 'ui'); this.loadAtlas('pbinfo_enemy_type2', 'ui'); + this.loadAtlas('pbinfo_stat', 'ui'); + this.loadAtlas('pbinfo_stat_numbers', 'ui'); this.loadImage('overlay_lv', 'ui'); this.loadAtlas('numbers', 'ui'); this.loadAtlas('numbers_red', 'ui'); diff --git a/src/locales/de/tutorial.ts b/src/locales/de/tutorial.ts index 2722c02ad45..f37afcae92d 100644 --- a/src/locales/de/tutorial.ts +++ b/src/locales/de/tutorial.ts @@ -20,6 +20,10 @@ export const tutorial: SimpleTranslationEntries = { "pokerus": `A daily random 3 selectable starters have a purple border. $If you see a starter you own with one of these,\ntry adding it to your party. Be sure to check its summary!`, + "statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. + $Your Pokémon are recalled before a trainer battle and before entering a new biome. + $You can also view the stat changes for the Pokémon on the field by holding shift.`, + "selectItem": `After every battle, you are given a choice of 3 random items.\nYou may only pick one. $These range from consumables, to Pokémon held items, to passive permanent items. $Most non-consumable item effects will stack in various ways. diff --git a/src/locales/en/tutorial.ts b/src/locales/en/tutorial.ts index 2722c02ad45..f37afcae92d 100644 --- a/src/locales/en/tutorial.ts +++ b/src/locales/en/tutorial.ts @@ -20,6 +20,10 @@ export const tutorial: SimpleTranslationEntries = { "pokerus": `A daily random 3 selectable starters have a purple border. $If you see a starter you own with one of these,\ntry adding it to your party. Be sure to check its summary!`, + "statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. + $Your Pokémon are recalled before a trainer battle and before entering a new biome. + $You can also view the stat changes for the Pokémon on the field by holding shift.`, + "selectItem": `After every battle, you are given a choice of 3 random items.\nYou may only pick one. $These range from consumables, to Pokémon held items, to passive permanent items. $Most non-consumable item effects will stack in various ways. diff --git a/src/locales/es/tutorial.ts b/src/locales/es/tutorial.ts index 2722c02ad45..f37afcae92d 100644 --- a/src/locales/es/tutorial.ts +++ b/src/locales/es/tutorial.ts @@ -20,6 +20,10 @@ export const tutorial: SimpleTranslationEntries = { "pokerus": `A daily random 3 selectable starters have a purple border. $If you see a starter you own with one of these,\ntry adding it to your party. Be sure to check its summary!`, + "statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. + $Your Pokémon are recalled before a trainer battle and before entering a new biome. + $You can also view the stat changes for the Pokémon on the field by holding shift.`, + "selectItem": `After every battle, you are given a choice of 3 random items.\nYou may only pick one. $These range from consumables, to Pokémon held items, to passive permanent items. $Most non-consumable item effects will stack in various ways. diff --git a/src/locales/fr/tutorial.ts b/src/locales/fr/tutorial.ts index c9f8a392e1e..55262b195ca 100644 --- a/src/locales/fr/tutorial.ts +++ b/src/locales/fr/tutorial.ts @@ -25,6 +25,10 @@ export const tutorial: SimpleTranslationEntries = { $violet. Si un starter que vous possédez l’a, essayez de $ l’ajouter à votre équipe. Vérifiez bien son résumé !`, + "statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. + $Your Pokémon are recalled before a trainer battle and before entering a new biome. + $You can also view the stat changes for the Pokémon on the field by holding shift.`, + "selectItem": `Après chaque combat, vous avez le choix entre 3 objets\ntirés au sort. Vous ne pouvez en prendre qu’un. $Cela peut être des objets consommables, des objets à\nfaire tenir, ou des objets passifs aux effets permanents. $La plupart des effets des objets non-consommables se cumuleront de diverses manières. diff --git a/src/locales/it/tutorial.ts b/src/locales/it/tutorial.ts index 2722c02ad45..f37afcae92d 100644 --- a/src/locales/it/tutorial.ts +++ b/src/locales/it/tutorial.ts @@ -20,6 +20,10 @@ export const tutorial: SimpleTranslationEntries = { "pokerus": `A daily random 3 selectable starters have a purple border. $If you see a starter you own with one of these,\ntry adding it to your party. Be sure to check its summary!`, + "statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. + $Your Pokémon are recalled before a trainer battle and before entering a new biome. + $You can also view the stat changes for the Pokémon on the field by holding shift.`, + "selectItem": `After every battle, you are given a choice of 3 random items.\nYou may only pick one. $These range from consumables, to Pokémon held items, to passive permanent items. $Most non-consumable item effects will stack in various ways. diff --git a/src/phases.ts b/src/phases.ts index 8eda33de20e..ceba555f2ce 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2671,7 +2671,6 @@ export class StatChangePhase extends PokemonPhase { let random = false; - const allStats = Utils.getEnumValues(BattleStat); if (this.stats.length === 1 && this.stats[0] === BattleStat.RAND) { this.stats[0] = this.getRandomStat(); random = true; @@ -2712,8 +2711,11 @@ export class StatChangePhase extends PokemonPhase { for (let stat of filteredStats) pokemon.summonData.battleStats[stat] = Math.max(Math.min(pokemon.summonData.battleStats[stat] + levels.value, 6), -6); - applyPostStatChangeAbAttrs(PostStatChangeAbAttr, pokemon, filteredStats, this.levels, this.selfTarget) - this.end(); + applyPostStatChangeAbAttrs(PostStatChangeAbAttr, pokemon, filteredStats, this.levels, this.selfTarget); + + pokemon.updateInfo(); + + handleTutorial(this.scene, Tutorial.Stat_Change).then(() => super.end()); }; if (relLevels.filter(l => l).length && this.scene.moveAnimations) { @@ -3337,7 +3339,7 @@ export class TrainerVictoryPhase extends BattlePhase { const trainerType = this.scene.currentBattle.trainer.config.trainerType; if (vouchers.hasOwnProperty(TrainerType[trainerType])) { if (!this.scene.validateVoucher(vouchers[TrainerType[trainerType]]) && this.scene.currentBattle.trainer.config.isBoss) - this.scene.pushPhase(new ModifierRewardPhase(this.scene, modifierTypes.VOUCHER)); + this.scene.unshiftPhase(new ModifierRewardPhase(this.scene, [ modifierTypes.VOUCHER, modifierTypes.VOUCHER, modifierTypes.VOUCHER_PLUS, modifierTypes.VOUCHER_PREMIUM ][vouchers[TrainerType[trainerType]].voucherType])); } this.scene.ui.showText(i18next.t('menu:trainerDefeated', { trainerName: this.scene.currentBattle.trainer.getName(TrainerSlot.NONE, true) }), null, () => { diff --git a/src/tutorial.ts b/src/tutorial.ts index 918c68b9bb4..88e88fa809c 100644 --- a/src/tutorial.ts +++ b/src/tutorial.ts @@ -9,6 +9,7 @@ export enum Tutorial { Menu = "MENU", Starter_Select = "STARTER_SELECT", Pokerus = "POKERUS", + Stat_Change = "STAT_CHANGE", Select_Item = "SELECT_ITEM", Egg_Gacha = "EGG_GACHA" } @@ -42,6 +43,11 @@ const tutorialHandlers = { scene.ui.showText(i18next.t("tutorial:pokerus"), null, () => scene.ui.showText('', null, () => resolve()), null, true); }); }, + [Tutorial.Stat_Change]: (scene: BattleScene) => { + return new Promise(resolve => { + scene.showFieldOverlay(1000).then(() => scene.ui.showText(i18next.t("tutorial:statChange"), null, () => scene.ui.showText('', null, () => scene.hideFieldOverlay(1000).then(() => resolve())), null, true)); + }); + }, [Tutorial.Select_Item]: (scene: BattleScene) => { return new Promise(resolve => { scene.ui.setModeWithoutClear(Mode.MESSAGE).then(() => { diff --git a/src/ui/battle-info.ts b/src/ui/battle-info.ts index ae794a256fa..3c2b541c618 100644 --- a/src/ui/battle-info.ts +++ b/src/ui/battle-info.ts @@ -7,6 +7,9 @@ import { StatusEffect } from '../data/status-effect'; import BattleScene from '../battle-scene'; import { Type, getTypeRgb } from '../data/type'; import { getVariantTint } from '#app/data/variant'; +import { BattleStat } from '#app/data/battle-stat'; + +const battleStatOrder = [ BattleStat.ATK, BattleStat.DEF, BattleStat.SPATK, BattleStat.SPDEF, BattleStat.ACC, BattleStat.EVA, BattleStat.SPD ]; export default class BattleInfo extends Phaser.GameObjects.Container { private player: boolean; @@ -24,6 +27,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { private lastLevelExp: integer; private lastLevel: integer; private lastLevelCapped: boolean; + private lastBattleStats: string; private box: Phaser.GameObjects.Sprite; private nameText: Phaser.GameObjects.Text; @@ -46,6 +50,11 @@ export default class BattleInfo extends Phaser.GameObjects.Container { public expMaskRect: Phaser.GameObjects.Graphics; + private statsContainer: Phaser.GameObjects.Container; + private statsBox: Phaser.GameObjects.Sprite; + private statValuesContainer: Phaser.GameObjects.Container; + private statNumbers: Phaser.GameObjects.Sprite[]; + constructor(scene: Phaser.Scene, x: number, y: number, player: boolean) { super(scene, x, y); this.player = player; @@ -138,18 +147,6 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.levelNumbersContainer = this.scene.add.container(9.5, (this.scene as BattleScene).uiTheme ? 0 : -0.5); this.levelContainer.add(this.levelNumbersContainer); - this.type1Icon = this.scene.add.sprite(player ? -139 : -15, player ? -17 : -15.5, `pbinfo_${player ? 'player' : 'enemy'}_type1`); - this.type1Icon.setOrigin(0, 0); - this.add(this.type1Icon); - - this.type2Icon = this.scene.add.sprite(player ? -139 : -15, player ? -1 : -2.5, `pbinfo_${player ? 'player' : 'enemy'}_type2`); - this.type2Icon.setOrigin(0, 0); - this.add(this.type2Icon); - - this.type3Icon = this.scene.add.sprite(player ? -154 : 0, player ? -17 : -15.5, `pbinfo_${player ? 'player' : 'enemy'}_type`); - this.type3Icon.setOrigin(0, 0); - this.add(this.type3Icon); - if (this.player) { this.hpNumbersContainer = this.scene.add.container(-15, 10); this.add(this.hpNumbersContainer); @@ -171,6 +168,46 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.expBar = expBar; this.expMaskRect = expMaskRect; } + + this.statsContainer = this.scene.add.container(0, 0); + this.statsContainer.setAlpha(0); + this.add(this.statsContainer); + + this.statsBox = this.scene.add.sprite(0, 0, `${this.getTextureName()}_stats`); + this.statsBox.setOrigin(1, 0.5); + this.statsContainer.add(this.statsBox); + + const statLabels: Phaser.GameObjects.Sprite[] = []; + this.statNumbers = []; + + this.statValuesContainer = this.scene.add.container(0, 0); + this.statsContainer.add(this.statValuesContainer); + + battleStatOrder.map((s, i) => { + const statX = i > 1 ? this.statNumbers[i - 2].x + this.statNumbers[i - 2].width + 4 : -this.statsBox.width + 8; + const statY = -this.statsBox.height / 2 + 4 + (i < battleStatOrder.length - 1 ? (i % 2 ? 10 : 0) : 5); + const statLabel = this.scene.add.sprite(statX, statY, 'pbinfo_stat', BattleStat[s]); + statLabel.setOrigin(0, 0); + statLabels.push(statLabel); + this.statValuesContainer.add(statLabel); + + const statNumber = this.scene.add.sprite(statX + statLabel.width, statY, 'pbinfo_stat_numbers', '3'); + statNumber.setOrigin(0, 0); + this.statNumbers.push(statNumber); + this.statValuesContainer.add(statNumber); + }); + + this.type1Icon = this.scene.add.sprite(player ? -139 : -15, player ? -17 : -15.5, `pbinfo_${player ? 'player' : 'enemy'}_type1`); + this.type1Icon.setOrigin(0, 0); + this.add(this.type1Icon); + + this.type2Icon = this.scene.add.sprite(player ? -139 : -15, player ? -1 : -2.5, `pbinfo_${player ? 'player' : 'enemy'}_type2`); + this.type2Icon.setOrigin(0, 0); + this.add(this.type2Icon); + + this.type3Icon = this.scene.add.sprite(player ? -154 : 0, player ? -17 : -15.5, `pbinfo_${player ? 'player' : 'enemy'}_type`); + this.type3Icon.setOrigin(0, 0); + this.add(this.type3Icon); } initInfo(pokemon: Pokemon) { @@ -258,7 +295,14 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.expMaskRect.x = (pokemon.levelExp / getLevelTotalExp(pokemon.level, pokemon.species.growthRate)) * 510; this.lastExp = pokemon.exp; this.lastLevelExp = pokemon.levelExp; + + this.statValuesContainer.setPosition(8, 7) } + + const battleStats = battleStatOrder.map(() => 0); + + this.lastBattleStats = battleStats.join(''); + this.updateBattleStats(battleStats); } getTextureName(): string { @@ -272,6 +316,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.mini = mini; this.box.setTexture(this.getTextureName()); + this.statsBox.setTexture(`${this.getTextureName()}_stats`); if (this.player) this.y -= 12 * (mini ? 1 : -1); @@ -284,21 +329,34 @@ export default class BattleInfo extends Phaser.GameObjects.Container { el.y += -8 * (mini ? 1 : -1); }); + this.statValuesContainer.x += 2 * (mini ? 1 : -1); + this.statValuesContainer.y += -7 * (mini ? 1 : -1); + const toggledElements = [ this.hpNumbersContainer, this.expBar ]; toggledElements.forEach(el => el.setVisible(!mini)); } + toggleStats(visible: boolean): void { + this.scene.tweens.add({ + targets: this.statsContainer, + duration: Utils.fixedInt(125), + ease: 'Sine.easeInOut', + alpha: visible ? 1 : 0 + }); + } + updateBossSegments(pokemon: EnemyPokemon): void { const boss = !!pokemon.bossSegments; if (boss !== this.boss) { this.boss = boss; - [ this.nameText, this.genderText, this.teraIcon, this.splicedIcon, this.shinyIcon, this.ownedIcon, this.statusIndicator, this.levelContainer ].map(e => e.x += 48 * (boss ? -1 : 1)); + [ this.nameText, this.genderText, this.teraIcon, this.splicedIcon, this.shinyIcon, this.ownedIcon, this.statusIndicator, this.levelContainer, this.statValuesContainer ].map(e => e.x += 48 * (boss ? -1 : 1)); this.hpBar.x += 38 * (boss ? -1 : 1); this.hpBar.y += 2 * (this.boss ? -1 : 1); this.hpBar.setTexture(`overlay_hp${boss ? '_boss' : ''}`); this.box.setTexture(this.getTextureName()); + this.statsBox.setTexture(`${this.getTextureName()}_stats`); } this.bossSegments = boss ? pokemon.bossSegments : 0; @@ -317,6 +375,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { const divider = this.scene.add.rectangle(0, 0, 1, this.hpBar.height - (uiTheme ? 0 : 1), pokemon.bossSegmentIndex >= s ? 0xFFFFFF : 0x404040) divider.setOrigin(0.5, 0); this.add(divider); + this.moveBelow(divider as Phaser.GameObjects.GameObject, this.statsContainer); divider.setPositionRelative(this.hpBar, dividerX, uiTheme ? 0 : 1); this.hpBarSegmentDividers.push(divider); @@ -439,6 +498,11 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.lastLevel = pokemon.level; } + const battleStats = pokemon.summonData.battleStats.join(''); + + if (this.lastBattleStats !== battleStats) + this.updateBattleStats(pokemon.summonData.battleStats); + this.shinyIcon.setVisible(pokemon.isShiny()); resolve(); @@ -513,7 +577,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { }); } - setLevel(level: integer) { + setLevel(level: integer): void { const isCapped = level >= (this.scene as BattleScene).getMaxExpLevel(); this.levelNumbersContainer.removeAll(true); const levelStr = level.toString(); @@ -522,7 +586,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.levelContainer.setX((this.player ? -41 : -50) - 8 * Math.max(levelStr.length - 3, 0)); } - setHpNumbers(hp: integer, maxHp: integer) { + setHpNumbers(hp: integer, maxHp: integer): void { if (!this.player || !this.scene) return; this.hpNumbersContainer.removeAll(true); @@ -535,6 +599,12 @@ export default class BattleInfo extends Phaser.GameObjects.Container { for (let i = hpStr.length - 1; i >= 0; i--) this.hpNumbersContainer.add(this.scene.add.image(offset++ * -8, 0, 'numbers', hpStr[i])); } + + updateBattleStats(battleStats: integer[]): void { + battleStatOrder.map((s, i) => { + this.statNumbers[i].setFrame(battleStats[s].toString()); + }); + } } export class PlayerBattleInfo extends BattleInfo { From 8a54e862fc0d165f1f6ca8967ca6f5940d624f01 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Tue, 30 Apr 2024 22:14:24 -0400 Subject: [PATCH 03/45] Revert "Add togglable stat change display" This reverts commit 718585062bf3d5bf5067003da9a6b70bfb407940. --- index.css | 4 - index.html | 3 - public/images/pbinfo_stat_numbers.json | 293 ------------------ .../ui/legacy/pbinfo_enemy_boss_stats.png | Bin 435 -> 0 bytes .../ui/legacy/pbinfo_enemy_mini_stats.png | Bin 666 -> 0 bytes .../ui/legacy/pbinfo_player_mini_stats.png | Bin 674 -> 0 bytes .../images/ui/legacy/pbinfo_player_stats.png | Bin 285 -> 0 bytes public/images/ui/legacy/pbinfo_stat.json | 188 ----------- public/images/ui/legacy/pbinfo_stat.png | Bin 263 -> 0 bytes .../images/ui/legacy/pbinfo_stat_numbers.json | 293 ------------------ .../images/ui/legacy/pbinfo_stat_numbers.png | Bin 392 -> 0 bytes public/images/ui/pbinfo_enemy_boss.png | Bin 526 -> 554 bytes public/images/ui/pbinfo_enemy_boss_stats.png | Bin 257 -> 0 bytes public/images/ui/pbinfo_enemy_mini.png | Bin 851 -> 888 bytes public/images/ui/pbinfo_enemy_mini_stats.png | Bin 642 -> 0 bytes public/images/ui/pbinfo_enemy_type.png | Bin 3599 -> 1502 bytes public/images/ui/pbinfo_enemy_type1.png | Bin 3305 -> 1360 bytes public/images/ui/pbinfo_enemy_type2.png | Bin 3197 -> 1340 bytes public/images/ui/pbinfo_player.png | Bin 619 -> 654 bytes public/images/ui/pbinfo_player_mini.png | Bin 860 -> 898 bytes public/images/ui/pbinfo_player_mini_stats.png | Bin 648 -> 0 bytes public/images/ui/pbinfo_player_stats.png | Bin 312 -> 0 bytes public/images/ui/pbinfo_player_type1.png | Bin 3197 -> 1340 bytes public/images/ui/pbinfo_player_type2.png | Bin 3305 -> 1360 bytes public/images/ui/pbinfo_stat.json | 188 ----------- public/images/ui/pbinfo_stat.png | Bin 278 -> 0 bytes public/images/ui/pbinfo_stat_numbers.json | 293 ------------------ public/images/ui/pbinfo_stat_numbers.png | Bin 430 -> 0 bytes src/battle-scene.ts | 72 ++--- src/data/splash-messages.ts | 3 +- src/field/pokemon.ts | 4 - src/loading-scene.ts | 6 - src/locales/de/tutorial.ts | 4 - src/locales/en/tutorial.ts | 4 - src/locales/es/tutorial.ts | 4 - src/locales/fr/tutorial.ts | 4 - src/locales/it/tutorial.ts | 4 - src/phases.ts | 10 +- src/tutorial.ts | 6 - src/ui/battle-info.ts | 100 +----- 40 files changed, 43 insertions(+), 1440 deletions(-) delete mode 100644 public/images/pbinfo_stat_numbers.json delete mode 100644 public/images/ui/legacy/pbinfo_enemy_boss_stats.png delete mode 100644 public/images/ui/legacy/pbinfo_enemy_mini_stats.png delete mode 100644 public/images/ui/legacy/pbinfo_player_mini_stats.png delete mode 100644 public/images/ui/legacy/pbinfo_player_stats.png delete mode 100644 public/images/ui/legacy/pbinfo_stat.json delete mode 100644 public/images/ui/legacy/pbinfo_stat.png delete mode 100644 public/images/ui/legacy/pbinfo_stat_numbers.json delete mode 100644 public/images/ui/legacy/pbinfo_stat_numbers.png delete mode 100644 public/images/ui/pbinfo_enemy_boss_stats.png delete mode 100644 public/images/ui/pbinfo_enemy_mini_stats.png delete mode 100644 public/images/ui/pbinfo_player_mini_stats.png delete mode 100644 public/images/ui/pbinfo_player_stats.png delete mode 100644 public/images/ui/pbinfo_stat.json delete mode 100644 public/images/ui/pbinfo_stat.png delete mode 100644 public/images/ui/pbinfo_stat_numbers.json delete mode 100644 public/images/ui/pbinfo_stat_numbers.png diff --git a/index.css b/index.css index dd47387adee..9a507ad6766 100644 --- a/index.css +++ b/index.css @@ -150,10 +150,6 @@ body { display: none; } -#touchControls:not([data-ui-mode='COMMAND']):not([data-ui-mode='FIGHT']):not([data-ui-mode='BALL']):not([data-ui-mode='TARGET_SELECT']) #apad #apadStats { - display: none; -} - #apad .apadRectBtnContainer + .apadSqBtnContainer { top: calc(var(--controls-size) * -1.9); left: calc(var(--controls-size) * -0.9); diff --git a/index.html b/index.html index 506fa4f1efa..bd316330a99 100644 --- a/index.html +++ b/index.html @@ -74,9 +74,6 @@
V
-
- Shift -
Menu
diff --git a/public/images/pbinfo_stat_numbers.json b/public/images/pbinfo_stat_numbers.json deleted file mode 100644 index 32170690aa0..00000000000 --- a/public/images/pbinfo_stat_numbers.json +++ /dev/null @@ -1,293 +0,0 @@ -{ - "textures": [ - { - "image": "pbinfo_stat_numbers.png", - "format": "RGBA8888", - "size": { - "w": 117, - "h": 8 - }, - "scale": 1, - "frames": [ - { - "filename": "+1", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "+2", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 9, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "+3", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 18, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "+4", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 27, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "+5", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 36, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "+6", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 45, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "-1", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 54, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "-2", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 63, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "-3", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 72, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "-4", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 81, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "-5", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 90, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "-6", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 99, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "0", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 108, - "y": 0, - "w": 9, - "h": 8 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:794aa4af3291db5abd8a2667626c1998:1a6706ad557b92f9bf099c23e02af4a6:6537c634087637bb27e8a1edb1ee2e35$" - } -} diff --git a/public/images/ui/legacy/pbinfo_enemy_boss_stats.png b/public/images/ui/legacy/pbinfo_enemy_boss_stats.png deleted file mode 100644 index 94c9f2a181736d88c6752f2c97ed0bbbee23ebcc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 435 zcmeAS@N?(olHy`uVBq!ia0vp^n}ArJgAGVJb4-r_QjEnx?oJHr&dIz4vU5FM978JR zyuG8?cgR7a?csXf_7^8kc|Ex$m-yBz<$7q-n^RU*Eb9Vy3q^L$xwlCBgn&~-ln2-0 zC$%D(Zao#Zd6NElh+n&%^Pj+>91Q?jM7YZ*~R6rK6tBHXtJ>3o}%+B70Tit?}|9LLp3388Oyx(ny$dZ`X4n6UD>PshjO%e?;W3et7Lx@QEIV2LHO-ZhLc6eY9Ry zIQ|Mdb1{9R)SaoXcSRIE<`z6H%nuWjbE9V$ zXGWbr(B0xb=lC1f6GDcM4fWFUoyzXm2QNAn5;^S^|FUJBo0|`=UT>R$XHs^CNV z##av>ty$f?T7lzV!;W1Rn!7wYzpJ*28OBxY>HqxBa!BncE&SaXRbV6dDO(__3L?7E8i*EoZkKZ{HwqsHRc+nk205eyDOS2sxDu$ zd@tM{5g62QzVkTGE`^WE*Hfq8w-A>Rt4KTHq5izn`AE{j-lt}1uFk6Sl=!q)x&3rH zmfHGREPZQC>e=c~;%vpYyt-a*X%jpw^vJ`ZrANz4IZ?ukeBYJTaNN^-KBA z)J%%Y&U~o6pj>*#j=aoIas@k?dF)+-(V{Q3XI{exr|Grpv%NI5;(qK@ xp0+UKM9$<@NoVioZhp6Q^O64&v*v`HV4ZIk%FUH_dOOew44$rjF6*2UngE&&E5rZ* diff --git a/public/images/ui/legacy/pbinfo_player_mini_stats.png b/public/images/ui/legacy/pbinfo_player_mini_stats.png deleted file mode 100644 index dd2b7e65ba3522986e78d6844a6be8823c3382ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 674 zcmV;T0$u%yP)EX>4Tx04R}tkv&MmKpe$iQ%gl!9Lyl%kfA!+MMWJ;6^me@v=v%)FuC*#nzSS- zE{=k0!NHHks)LKOt`4q(Aou~|>f)s6A|?JWDYS_3;J6>}?mh0_0Ya# zo%24i$jY)xd`>)J&;^MfxvseU#<}FMz%xZ7o1P~YiKS8xD?QB0hDJP198oo$@`aqs zD(5ZETD8GC_v9}O74(%1*J+L-fh8o7qK*_aP(c+IqO|Iym`Kxp+`~WO_*3Lk$W;L& z#{z25AUl5WKlt6PS)7`5lR|MI@M7B^V?b~hXg6*9``EVICxHJMxYE1+S__!_B)!?y zB1gdBHgIv>)s#Kpat9cGs>_D#NPe0^u?W1M(KqFRp<7^J&F!tTkJASrOIK2l+uOfqI{p0s^F(smE#4Fv0000mP)t-s0001cl!Q`iV>wbnAvplXy>s5y zwg3O#*3P|BYg+%cd;kCcN$J_5c5S*Us$?%8vTKwfg`6|6Wc}-=`Gc19G2( z)VthFjRI1_B|(0{3_xi#U}t|v7bsoq>Eaj?(fam=p-_VZhjU<>!iIbQ4@G5d*>KA2 zr+S66yVASV%+m`tUAT0h%_Vu-2F6#OE9N=hF1aYEASTnz@k_ZzU>c{|jD#j+;!l_T zYhIRn;@{452VTh2;XbSE{bIVBSPWaCe#7lsobz5x%h_{T;XlZgp00i_>zopr0I}G2 ADF6Tf diff --git a/public/images/ui/legacy/pbinfo_stat.json b/public/images/ui/legacy/pbinfo_stat.json deleted file mode 100644 index b7da47fc192..00000000000 --- a/public/images/ui/legacy/pbinfo_stat.json +++ /dev/null @@ -1,188 +0,0 @@ -{ - "textures": [ - { - "image": "pbinfo_stat.png", - "format": "RGBA8888", - "size": { - "w": 112, - "h": 6 - }, - "scale": 1, - "frames": [ - { - "filename": "SPATK", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 19, - "h": 8 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 18, - "h": 6 - }, - "frame": { - "x": 0, - "y": 0, - "w": 18, - "h": 6 - } - }, - { - "filename": "SPDEF", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 19, - "h": 8 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 18, - "h": 6 - }, - "frame": { - "x": 18, - "y": 0, - "w": 18, - "h": 6 - } - }, - { - "filename": "CRIT", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 17, - "h": 8 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 16, - "h": 6 - }, - "frame": { - "x": 36, - "y": 0, - "w": 16, - "h": 6 - } - }, - { - "filename": "ACC", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 13, - "h": 8 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 12, - "h": 6 - }, - "frame": { - "x": 52, - "y": 0, - "w": 12, - "h": 6 - } - }, - { - "filename": "ATK", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 13, - "h": 8 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 12, - "h": 6 - }, - "frame": { - "x": 64, - "y": 0, - "w": 12, - "h": 6 - } - }, - { - "filename": "DEF", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 13, - "h": 8 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 12, - "h": 6 - }, - "frame": { - "x": 76, - "y": 0, - "w": 12, - "h": 6 - } - }, - { - "filename": "EVA", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 13, - "h": 8 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 12, - "h": 6 - }, - "frame": { - "x": 88, - "y": 0, - "w": 12, - "h": 6 - } - }, - { - "filename": "SPD", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 13, - "h": 8 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 12, - "h": 6 - }, - "frame": { - "x": 100, - "y": 0, - "w": 12, - "h": 6 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:40d30205ce8efd40dfa86cd11b0491d6:7076db6ed74199dcfb38fc8cd4d4a0e8:05882267d3999884e0491134e98b1b53$" - } -} diff --git a/public/images/ui/legacy/pbinfo_stat.png b/public/images/ui/legacy/pbinfo_stat.png deleted file mode 100644 index 62ec3758772daea6013a4de5532575a66caf8116..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 263 zcmeAS@N?(olHy`uVBq!ia0vp^1whQk!3-pITwg5(Qk(%kA+A8$!NK9)wXI7Q-Kzj{ z7)yfuf*Bm1-ADteDDa3ZW?Ec4QuN(io6fN32b;e=)XJ@8wjxa57 z6;5`pyz#?~2;;a-r4XYn{3?!Y<6HKbItN$2xk}gw>0y zUzy)p<5e-!w)Vy<(87aih3;8-LtI=7KLTHk<}Jk-^i|&t;uc GLK6T7%VuW) diff --git a/public/images/ui/legacy/pbinfo_stat_numbers.json b/public/images/ui/legacy/pbinfo_stat_numbers.json deleted file mode 100644 index 9c74ee86dbc..00000000000 --- a/public/images/ui/legacy/pbinfo_stat_numbers.json +++ /dev/null @@ -1,293 +0,0 @@ -{ - "textures": [ - { - "image": "pbinfo_stat_numbers.png", - "format": "RGBA8888", - "size": { - "w": 117, - "h": 8 - }, - "scale": 1, - "frames": [ - { - "filename": "+1", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "+2", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 9, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "+3", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 18, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "+4", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 27, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "+5", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 36, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "+6", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 45, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "-1", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 54, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "-2", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 63, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "-3", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 72, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "-4", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 81, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "-5", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 90, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "-6", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 99, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "0", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 108, - "y": 0, - "w": 9, - "h": 8 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:1f22b7cb085faf9e9764273fa5e70c28:afc5587ebacca78d178ac7e0c434591b:6537c634087637bb27e8a1edb1ee2e35$" - } -} diff --git a/public/images/ui/legacy/pbinfo_stat_numbers.png b/public/images/ui/legacy/pbinfo_stat_numbers.png deleted file mode 100644 index ee1453b21070f8de40a299a2d0c82c49093799cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 392 zcmV;30eAk1P)NeVolC?^B79yfh4NP^lrY9U!*DY-V@3rV{hYdQ>YK;=1YJaz3T;`<^$DGJL<5 z0VRW87@CHmA>NuYKzH1TLC5xSzn%dVgI*Y#hCzM2e@<+(--30)Oref_gmu$R&9E*Q zKCPUg&65~>rQzm$c=)wGxON}pkE{!ZPit-h_?q;dhMV)@;n(^|U!-Qgl_%A@VDM** z28vT)T`)O@Pln{f8%r6yr(x9i(DP6xH!0n5bN5`F;gccxJgbFgqhZwe(DRg7RCba7 mA?H5)Du%PaS?j+(7uOe-FYwO$9P0Z30000aGx7IS8(W?BZR#K+fR> zdKYIGa4pEV(m;21BcvdOLb@oX#w6N||Hk-!EB%ba5WYMoi2;a+$P89q(Q(?bWqnK1js?_P5*2T3V0acimCcp71_vhnu(jb5jIunqv- zU|m?J^YT3J;D0uwQBe98btaL0--i&Q%orEbYPFKro2Hw%bs$(LP1z0Bn7Fmy_dE4% zMRfpBN}Xl?_f7}_DJACfdG6;*DGY~0t+A6v4#Sx>8X@+5UvHKdwn^skG{U|W(s&x7 z*QuwrAFS-cx>Cy61NqkdXW#0iF_3fBLidQcv~I9QcYG^xiwstFvMunJ#6@+wo@071 z6=j=LzJ;IG-9*kySisI*Q}3$_A-J?SlT8{I?O!P+!f>JWs8i-krl0glDKjDTt88$>!uSb_l5uf002ovPDHLk FV1lYA{=)zO delta 487 zcmVIk&UmVKT0GxPa8d!07jZZ!ddIBQBbh_PFZe&65JuT|9nKq=MA`2Ra01f-NW z91f+QE2Xg6Y_!guHF6k+mXtE_eP3^s9ZQpWyFcUJ3~9SRW4V~*j$cQ1WnC#{?2Y{H zp1HO|plBRLh_0>&dpk(u@=|B3Ul!cn-d9Bu|Irn<2(MATii<NL1q8595j002ovPDHLkV1ifd@6!MP diff --git a/public/images/ui/pbinfo_enemy_boss_stats.png b/public/images/ui/pbinfo_enemy_boss_stats.png deleted file mode 100644 index 7148a7af4759141abb5e2b39c02a17b45af905e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 257 zcmeAS@N?(olHy`uVBq!ia0vp^n}ArJgAGVJb4-r_QjEnx?oJHr&dIz4a&~*VIEGZr zd3$>`-ysJ9)(e`BNfSH%{_kJqko58BL=U^z3cqSH|eR)57 zW1&p?=O4X~e>-L8TFuvct=1%`yX>BUe4QwNkl)q|N~u!nI~O4Yq?Ab0 z)cUDa4A$g)|GB+zjjyH$DNlu{Sp;D;RZA6(J^uv|5`cGRUYNim(gR9s1U zPC0iQQ-etbpCZ(@E->2xpqYObLeyev0QOIDQc7gm-04MCwVfaNvS^f20{C4#?Hk+n z_uXHMMb~Ko*z*>1x7*b&2cv4u=Wc00L_|bHM0D5>)LE${MNRhx00000NkvXXu0mjf DZ|lLNkl8GRYx|2)P*70tlomTy+AL)kaKVi zE&#J{fxIOH3ldw!o(@eA9|jTwfke-5G6qF2@~g-B0uhl?&o>!GQQmYRa=R?cyz5!T z`|(5+MftElx~(F4j)*+88Q$()i?q{0_b3h8Z?jzmZ4pWY0rr0qL21w(A*rB55THl| zr9t=9O$8-_0MJt!bXT2JP$CGRMv#IUK>#&^6m9ha8#1%t_N<261?l{K=~*1pAjk_btXV2r7AjK;-r zyc-`ce5q`T&+mUP){_|k&bdbFdlX{~)>_gu^?vW1V>+D%9edXZS(f#zwRw^xVO733 z=iJLT_%&7jLr5Bc=c*yJqh3v!6wCSI$(1zcmbE+B8p>2?Q-u1?3(9$bLGjrb(}}GC z&Tny{X#k#=SKD&ZXsreQPoB<=eZOzJOKWr2MgYCV+*TmByu~acA|fIpa@iluDW|ek SO(V4c0000EX>4Tx04R}tkv&MmP!xqvQ>7vm5sQd8WT;LSL`4J_sbUc+7C6sqP{?%e(K->QQng1AHR!9McVpc!PL) z)6zNb6Ngw)Qi#uq#|*k4@gvt|m)|%S92R(H$VeyWi9^IW<^6Ko+1t_sz&)j z#$|=`7H73wWzBo?7Y1|MN{Z{Wh7rRO;z&S*j4Dbf!$O31jT93}I*)qzha7)`Tr#;z zVB}ap1u7)R5B>+gXKUssC)}i96zF`h?T-;4unRP5w*7r<+l>>z{|sDdEq|pB%zTnw zYiZ#lpm!U%xNd3k9&ot>3_j_SAvuztmXOZ_?`QN)S)l(G=w5T@);!1Q1CXX!E#CkK zhrnoove!M{-PJy~e|wtq`vH(aagbUB zzo-t5uI_cI;7<`vL}@r@>=fw7Q_>^>xEhuomQto)FNAjEI4-`=cWfUYlv1Ys?$EX( z{-b279fr-f*TOp8O^+I^-|2j;`a~!KNp6au2K}h1f+CP)E`l2L=hG@E0!flV4f^#- z6%>Ia27#GDAc;X>X8YJF+efPS#oQskn5pI%x-*WUY4S8Vs<2+QHAobJnOn>qX}QG= c008jX1y1rsg=?D3Y5)KL07*qoM6N<$f~t=qVE_OC diff --git a/public/images/ui/pbinfo_enemy_type.png b/public/images/ui/pbinfo_enemy_type.png index 9bac63e5e72ba305c0c7769d72bc39d72aa8202e..021a120070c1872b54405196e4bcb2cec9920d06 100644 GIT binary patch literal 1502 zcmXw3e>l^59RD&u=ccklkrpRr5<fnh6k_S2{W7L7M z-u$_fs5z|3JThfIZhj>vf2A;Ol~}!6vHB@x@25&&4P&{!zP?c%v(a_#GdV;0!csb% zA(cw)w?mv{dgKx@KK_97)X;g^K{d`JFaZG6pgT(rpiuV%fC9_Y1sM=E+Hi-6({=yG zxoCXs&Z*1^4UcG#nDE;8NB&feT+%pQDt-9g(#mvpj&!dCxj4~1iTcj#WUk(Yh+O{m zxmHG){;FeW(-VZ1x9ZY?^zZ;D@MFk&A_&BKeql53NRSK2!S_KE=XJ9PmmDj*ZIYx~ zTg9pyr*I9=_cN%IW))RtSLGltUlzv+_dpo1cVx9E_YL;E)(~hH+7v8>_uNQ7A?d3n z*^lR<-JJn9yxt;uln$25#AKM%>8vasJgBHuQ+Vg-@<^UVWu7?2V6u&>38Tba{J}$S zV(f(tS-AhEz1Ga$$KYO!W|{d#Nf^fyNsDe77C;Id)&1~GVO*Hi@$iS&N!kgxts2$B zoJg@T<&}T%q;UIkzxjl4ihwuOxg8^Qdc*I%T7TpsOW(<1mzVUoj29K0r1|{pdgna4 z&8kKv9m6CE%W?Vx;(Wv35O8L*OA^$tu8BJYzo)r85@ExX)EQwyx&s$$jDFNM?6E_dii|3k`+mD)0Rjpr!9)ox>gN7O_05b$7 zh-Cmw;T1baQQ6?w$OJ8Uauw2!Me)&j+nD%Fv4R-V8kMt5p#B zRX0wvKmR%XS;e0{gV-bjt2gvFYW~diB zxSs22nK2yIv0XE_6Y1Uh@j;mitpMW~gtb^0y+bJzYJoU}Jg2zmLC;7ujHm0vjKSPE zg<^<;G5AV}M~dZzHrN@Cby}FF@n8VN@W!-aYc_h{(yu;zS6zWXk)NFb+gdy6jJ+Mo z-RyzY@62$Nspw+%(#I`y5qTW8TLpF~I=ekdrM>;Ixen@t3;az~zkui1`J#0Hqb`?D zqMfOe)lOehL2>?PC)Fab1F?7AR^2eNqTNouQZ82b*?Ul1^-N=cO^x6f)MUrqYFX&n zViWJ!OIQOzgMFmuD7_PG3~z9tE{XiFK3mpPg~H9eH^R83^8Kv3ui9VkXvf%E_uRtr zVO;!3?U5RE+iSNHR2%4!Bmqi)drkKzt5!(KDPMU8!`o}EcntfsWNDGD3<`*Q6At0BKS`47C$X9aYeb!_U0x*TY~<5hSE8n8iUmue1aT_L@j9XO;i@vXJOa= zM!DY1da9gR_TgAx-U6pN%Y0^L29=$c?$kOmqRmkk&xRY|vZGU#hT1`nxk{fTg@1Z+ znzkPF5qP7j)Q?j2LVj7U0RES|Vh$hWlH9jho!K42`>;mfZ)as?!3|Ci&Ckvg-UnVo resupsym6>#pP=$lydvQr&2;62s?XefC_i8JmjRxxJ}&H2p_%^y$!^{i literal 3599 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 diff --git a/public/images/ui/pbinfo_player.png b/public/images/ui/pbinfo_player.png index fee08f71044ee488bd172bf9b02db706a9cf4082..9d3e03bd66d86cdf8ab3cfd59be4ef9d6410ccd5 100644 GIT binary patch delta 616 zcmV-u0+;>k1daueF@H!&L_t(|obBAdPTNo%hT%6=r7mDtOmVaZ|#D^=AwA$T>{|y z{`MMK0n4%gn9t{_=Z;1rTz8s03~k$XIW5~GzVAQ(BKK9E&tTg&t~=GuVw47V*Ecn{ zq+W@M;5bfWQX%fXAUY0k`1iGCS&iu$vV0E5aexf}HGd3;XC*YPKAz_Re{P;O?Z=(J z@3P-4P6>ipC$SJTFR}T;@LhT#Kr@~tNIX4Rlr7F3ih1JlvSD0}h;CUMrfz+?^FUrW92r7(fq+sU8C^NhOn2+~R33uoA15d^47ggK
u*i{Slh@`p?1>g%h%6Cw5J!=T0U*R1MnDJ6|U#*Z*JkoesN4y6h&V9 zS^IL#rHNpS$$z3KVzb$F)3Ol+L9lnip}Z&_gDU{iG###yJqW`PfbDi$yYFhX!dhEB z4IRgEH!YixG)-SW$f;^_3~?M|t<_*LPlNlL+mTx`uF6D6l4LfiP&6*cw*!3q`#KE6 z*>nv)$B`rn;PGFB@1WyQS!;op!Bg3K(f(8CKUlOl=YJNph0sZ>!pgJLse-2Lyi&dt}*K+!0R$E0vTWLUzE`_5mXrc zsQaRf);@*cL$jCTsXOrp#Tb)a{=Cd~yPcLDF5CP8>N7zOZ`s!|s^Ay5~jkO`|t=mu+hfnI_k z=inM#0M>Zx5s;aZNL^66l`fsq0gNCG1sw9X?>Cu1(1-l#*$DxNh%_t9$+kU+E$jPQ zwNL@#_zq#X{59{lreA2=gSdO&%~lna!$zEJhMTf#p=vQ&8km0u^%t$9gC&BAKmZI9 zfoaej`>DW0AOII80@I**bSf|r2*3r2z%*#CXdQ8nKpSiX0>DO~Ej9uH;N|1Lr!OCk z|9z~BkFR$CK&RD99q;S3dWF_jB}TWHN28}aYPmWoB_8}&0Km$brjE76Y>xK$v+x@8 zG8_(1e#Z0OcDH|+jT6CjT?ipePcMYyIJb;z7>41Gsv{dh>cWt0R&T-FUZ9s?$T_$M z7l7HfK;Dvp1&OUH5K*IY>CJ^)^|N88NNC4pVs+=4}QGTmJ(3~vGe$D%9 z=$A!Nln?u(Y8Bx=BIU(qc)3?Ccq~Cn18LBHo9*gki69XmDIk9lNQ3S;P6ZMHlCDey z(x7{MDv$_}bVVYN2HmyUuGk}Bhem)T8UcGW0wi(y`1JhcWAML^ZL!&|BuT^msC0bn znVUT57V~&KuA`Qlv)1Y@{gNcD<5}t0Th136Ouiehu`ZX)k+t@4i#a$Ek|dEaCiL`1 z#BqEW7bo8HP4R#J`Jwe>CP{M6HBw()j4`s-DoxYU_nmW^PNyfwu5N@Z%X-$@JV}zU zDj%G4?%^B!KbQQ5<1~;eTs0Iss;zudEa!_mSJIraxeHnvd@8glLd*6A{^x002ovPDHLkV1g-F&x8N~ diff --git a/public/images/ui/pbinfo_player_mini_stats.png b/public/images/ui/pbinfo_player_mini_stats.png deleted file mode 100644 index 7ce3bd1af1e541826337cedf9f284a5d14d9661d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 648 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 diff --git a/public/images/ui/pbinfo_player_type2.png b/public/images/ui/pbinfo_player_type2.png index 6d94871e8da1dfd56a0271a6a8ef1ae8e9d6c3c4..89b84d7f6305169db2e227aa33a9e2202cdeebfa 100644 GIT binary patch delta 1352 zcmV-O1-JU?8PE!l8Gi!+001|Fw5tFB0LD;ER7Ff_ah$F9y`@@v&QkxzF{M&D_fj$c z|NkH$C}^ON?{M#0&gZSAl&*R^dt>K;roK6x|8rVOt-T?ULCa%fweLZBshW_&&HA#) z*Ui>=uHluui{JW{fz8OhuAuPssP*{x`1OmehQj}QNPD25(tm@cTBF6g$d!hg;qd?5 zfl8r4*2tQaP>WJ=&CRZdVwt_}I7)L+d!ND9&0W3jRVlN`nw8h|;Lwoy%VhSd0F|iV z`K@jCc@WLAO7w=1sg$n0l(JYVN?hu22&L|x<$1xtHZ=fSB1)Trhy?v zoa3n3UrWrX;+*zippZEd6gn4+-m@z3Iz>?lBFaT&Gu~8G0(^~DNvbr&_PnBMxTl-6$7${0tvjq z8{UgbXK9_@DJo}*X;tK!C{;z0C&Nb2)Kns?;ACA*RXRszdZlWyMp0|ce(E9^i1>AC z)eNo5V6|GEI+X!`PEO^sgG}kXI%pvNf*4421%Km)KMzoI_Lmwn%y ztZ7sgQD}&wGNY#Crd6|N)KMlzb*y>R?0tz_zUsE$4+f_HsePl~CU|R9Qp9sA9r6>Z6O;EJ|jp?<^(Di!Uj&>*>2owya16-_YeAtY+jotiG{xT@Mxr{f#Y5=N~xdrxA@ zC8xb!FpvrJo>8YP=~h%yVuDc(Eb1X7I+dGsE$URqltB7vY+xP}HF}G#aR?K~-*Opgn&3-PS zot~cu122I~e$K7RlCDL)Bqwe~Re!Of9zvof{Xo^#sIjGUuWIvFtu_1KF#ukJgG*qU zVWNCbRn^UGyYWh2JDoHq~D#xXTM7g2Zlu?)I9;4Qp{qFAW*Dv79x39p@pRwMW z=p7aOM$e~DNnI0u67$Ey!$VTnYdk%D!Pg)EAi+j>Pl;#J?YIZf>@=DnB0#4gWz*>~@TwpZ$Le*Q*bmNc=P)Px>qe(QJbv@}9BwInvjmRN~AA~$EW}N5&-bgs~suPG)r}LnHc~)Q}Q^r-oHsn?E(O=*P9Y4|J<z$QrZ&QnTawD4a0DK^lFFJ_{HuHso4{+>;+A~ zJDd>G0639lV(LcR&iJEOJDkNZ6IloW;OC^HYe{msJ)&;p$*YCG@CX1PHhB>7nLhJe zbEDUJE(1U?Fm0LvfWPnvf`Mr*b(UcmuI5Jh$=KvUZCQK78gD6~C$H8d8Hna{KSb`y ztJRXi>-DDkhtfZy#xK2`8o%_irJU-sl#b?Me5Q{Z496l$kxurSC1fe3gyLYZ@l(|y zafUSFZ1>_beFz4o5e!UQ%30BfD`UtKiG(68t7VeQ!Qw(?qb+6IaAEkY zl#p$plB!M?kPhy^=%lm}+dU#@6)Y~~W`*rtuV&X?N5mYVj?#%(N@)ybgWMX-BT)oi}3z>{){QOOX8fVRm)dfbJ-IuAG ztQjjUA&?HPNJ$DuauJT?n$)61O56J~(Ns0ur8Tw~$|%`^A#*ZTQA!EPfHf6~Rix52 zc3oh^VkDC|IK9yl^*jtU&RQlmNt{kvLZY&dAcXZT6^7gpx`iHHq{FJ`+f5; zzdn;SHq+3QcmavB48w5c*C*s>r&_IL>$aOOr+ado$)b#33Z)U|!rQmIrb zb>qYh^R=jJ`>v&KoVa1Wc9hGv{&5Qckl3F zGG?F4Y`ln0ciuwCQYQP7aM!xIMl9W`M_0jJ>*g-PQd$V9vAfo78O@y6bKtIZTQ0&% zn#-{#W1LxHf5LJslm7$1`o5glpD?>eO7O>uX>>mp4u**4T`0cea|uq)WaG*4WgLezT;ksf7?o2Unz|F0x%EBeqPW)Mg4x zlHIRgP;rEIl(#!uF<0$3<0y)yRK}2PO!1@NDq}!#U#59U-IUEinKn+?tg)$^E1M1@ zyFZ5P{+M=zrG!Lji=#4Jl3Z?SzvS5D0nZ8mK&gKv^7HeZ?|rFENatg>rFG5kmt~X> zcvf&Gtl2m5p8x=D%^SI{YY9a&q9QXTp^Q>RClZR3%6aJ2Oi3tG?hIygCV;-HMCoX4 zqoTDXB+BmhzDB8krET|Qlv2XQm?;T~GGiw)T#{T41m2W3C@sAg4Gj-+W!>Fh;QaaT z007bGOV01hkw}Hb3;-G$9z-Nkp`^|-48s+TzGNY@Q)%hF2n61Ac3&p4#>PR*IVzLU zn}#w<(Li+pky86^BgRS>JC0DK?C$=;wjo=GrIf~yriIQ-RY#i3G%sacl*N%0jlQJ6 zFE=(0TDl*JRA{HwGRft-exDTtuYQ5{h)=SBJE8oS{f*M@PpZrIJu= z=!DKAhveJ*{MJX6Q!ki0BBeA_*f`M-E7@RK2t`VE%CJW4IaWlej3G5Qg^jNUYqQ3AlN!HaM=2TekEbI^<*Nu+d~%S6bA zLrJKkBom6E7!HwAN=TK-h(?w*6T425KlkN%ni~XFV^RM23C(j~fkWoRc0#5kBuYm} zGQ%awUy~2Xm35XR=KEDIMo>w6`7rF#XxP0HBPa<@@DGxEOf_WhgA# z#hGobe#bPNnHshjHHJpj-!IQh4P$bw%VI|7bdu(>I4|=G%8>u?bINYAl#cdbXQqa2 z$&`dd>8Q2La7l9c`L?&E4Se}|s4UuGDQ`V~4ghehWoKr&Tv@aMt;f&d@Q%k!6FZq} zY?1Qtj>jxiRCapoD@;t!5T*SZ+n1lGBxpT;P8tTz&@c?wv6h`?p{@Z@(nX(dd)xW< z%WT)^m@ZaXw1GQEvgEQDOLnB$IMOkRVyPrlO&J-vl2AseB9iG?%TD|E!`9>HaC+=3 zyJ~7eqIB#a8ZJpL=eFqo9l*%^6fF@`zRmjFmu(CyACSLR$;@RH<;YI{Sfre7%Xhwy zEt;vySedyz+s6MXyRLiex!jg%XZPiUrD{XnIc|+DQUbt{^XkSVmeTgFclw+350LJv zjt)@da&F5s*O(~TW4Z{d*|vN&AvHKy%2TP#l!Qd7Zlc%H8Ex5m1h6| zmp|{ox^MPjg|`u_Hm4U*HxJzn0N8Xw@jUkEj|=a3&Rdheb9slR4LjFH`JUf&ce|E_E z{}svpterdVy{%tx0+Rc(Z~J@b|C1k`eV5_ROCq^$J(@P$iDMs6B01y6+V5ki*>3p^r=85p>QL70(Y)*K0-;9^e~#}JM4YbQkt9Z}$Lk>2rt zuKR?x9W_gW7GHdEIZRA3PQiWWf_gEBD>-+P7WbQFDeB5(FiQnkYJT0+d!^ilFVNop z&g@AaU;a`5G;zDk43V2*;$L0AUpUvbfi-hpw1(4@QY8*&1zW>D^RKHGtIA58?GDdB z^z5+u8@b1GkFN|~6tyyB+m=mNc0TgfI9*xz^hZc=_{JB-6D{k$v)J#gjM>h5gnvUW Wt8RFN+!3I289ZJ6T-G@yGywokWokPB diff --git a/public/images/ui/pbinfo_stat_numbers.json b/public/images/ui/pbinfo_stat_numbers.json deleted file mode 100644 index ec4f7117bb7..00000000000 --- a/public/images/ui/pbinfo_stat_numbers.json +++ /dev/null @@ -1,293 +0,0 @@ -{ - "textures": [ - { - "image": "pbinfo_stat_numbers.png", - "format": "RGBA8888", - "size": { - "w": 117, - "h": 8 - }, - "scale": 1, - "frames": [ - { - "filename": "1", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "2", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 9, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "3", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 18, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "4", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 27, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "5", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 36, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "6", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 45, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "-1", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 54, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "-2", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 63, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "-3", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 72, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "-4", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 81, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "-5", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 90, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "-6", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 99, - "y": 0, - "w": 9, - "h": 8 - } - }, - { - "filename": "0", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 9, - "h": 8 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 9, - "h": 8 - }, - "frame": { - "x": 108, - "y": 0, - "w": 9, - "h": 8 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:b0719fae0d9b670a727148cdc7202249:afc5587ebacca78d178ac7e0c434591b:4825a9f02f72f1fe28a724c6c5dffb37$" - } -} diff --git a/public/images/ui/pbinfo_stat_numbers.png b/public/images/ui/pbinfo_stat_numbers.png deleted file mode 100644 index c778ba992734421a718b2c49db1db0ae77a28e09..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 430 zcmV;f0a5;mP)X}UpFSFJe%YMSjb zvz=}Te=dw_+OM;>zwNiTz<(WGW!%j?&)@0VTARh5OWbc`j(J{Tok%Zt#$YoH;sBj7 z0D#IlJRc6p%*|?r>-8D{#_^;+F^22I1yqy`_PebZNKrNbfWEEq_WF{{oLyYu^!yS4 z#PO(4jM4P@WGYS8UqlLVGYqiSvW&F&OBuS>FtHC$Vz?0ZyX|CN5<3@SjG<>5X2}?8 zQ)v+?7z&xQg%~oUa!zD?QzeEgj_Hh<7_VVM6DZ`EEo4UD)*|DZy2Lt;DavMIyoRBA zxP2Ty%KN9gENZI8IE_78Q^T$GD~(@jhsGYQsdI~*V!X;!+J?fg{Gd2S+NQZaWGcsm zi<{b~a&9zLI&@IbQb7LyuD?x7eaKXf@hzMCJ+VH0TaTtDpMHPh p)) - p.toggleStats(pressed); - if (pressed) - this.setLastProcessedMovementTime(Button.STATS); - } else - return; - } + } else + return; if (inputSuccess && this.enableVibration && typeof navigator.vibrate !== 'undefined') navigator.vibrate(vibrationLength || 10); } @@ -1454,7 +1443,7 @@ export default class BattleScene extends SceneBase { * or not. It will only return true once, until the key is released and pressed down * again. */ - gamepadButtonJustDown(button: Phaser.Input.Gamepad.Button): boolean { + gamepadButtonJustDown(button: Phaser.Input.Gamepad.Button) : boolean { if (!button || !this.gamepadSupport) return false; @@ -1474,23 +1463,6 @@ export default class BattleScene extends SceneBase { return this.buttonKeys[button].some(k => Phaser.Input.Keyboard.JustDown(k)) || this.gamepadButtonJustDown(gamepad?.buttons[this.gamepadKeyConfig[button]]); } - /** - * gamepadButtonJustUp returns true if @param button has just been released - * or not. It will only return true once, until the key is released and pressed down - * again. - */ - gamepadButtonJustUp(button: Phaser.Input.Gamepad.Button): boolean { - if (!button || !this.gamepadSupport) - return false; - - return !this.gamepadButtonStates[button.index]; - } - - buttonJustReleased(button: Button): boolean { - const gamepad = this.input.gamepad?.gamepads[0]; - return this.buttonKeys[button].some(k => Phaser.Input.Keyboard.JustUp(k)) || this.gamepadButtonJustUp(gamepad?.buttons[this.gamepadKeyConfig[button]]); - } - /** * repeatInputDurationJustPassed returns true if @param button has been held down long * enough to fire a repeated input. A button must claim the movementButtonLock before diff --git a/src/data/splash-messages.ts b/src/data/splash-messages.ts index 198ff07cec9..11629cf05d7 100644 --- a/src/data/splash-messages.ts +++ b/src/data/splash-messages.ts @@ -33,5 +33,6 @@ splashMessages.push(...[ 'Also Try Emerald Rogue!', 'Also Try Radical Red!', 'Eevee Expo!', - 'YNOproject!' + 'YNOproject!', + 'Shh, don\'t tell Sam!' ]); \ No newline at end of file diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 7072875d3ce..9a7bfb48621 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -1179,10 +1179,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return this.battleInfo.updateInfo(this, instant); } - toggleStats(visible: boolean): void { - this.battleInfo.toggleStats(visible); - } - addExp(exp: integer) { const maxExpLevel = this.scene.getMaxExpLevel(); const initialExp = this.exp; diff --git a/src/loading-scene.ts b/src/loading-scene.ts index 875d618ec0f..2f37b900ab5 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -39,21 +39,15 @@ export class LoadingScene extends SceneBase { } this.loadAtlas('namebox', 'ui'); this.loadImage('pbinfo_player', 'ui'); - this.loadImage('pbinfo_player_stats', 'ui'); this.loadImage('pbinfo_player_mini', 'ui'); - this.loadImage('pbinfo_player_mini_stats', 'ui'); this.loadAtlas('pbinfo_player_type', 'ui'); this.loadAtlas('pbinfo_player_type1', 'ui'); this.loadAtlas('pbinfo_player_type2', 'ui'); this.loadImage('pbinfo_enemy_mini', 'ui'); - this.loadImage('pbinfo_enemy_mini_stats', 'ui'); this.loadImage('pbinfo_enemy_boss', 'ui'); - this.loadImage('pbinfo_enemy_boss_stats', 'ui'); this.loadAtlas('pbinfo_enemy_type', 'ui'); this.loadAtlas('pbinfo_enemy_type1', 'ui'); this.loadAtlas('pbinfo_enemy_type2', 'ui'); - this.loadAtlas('pbinfo_stat', 'ui'); - this.loadAtlas('pbinfo_stat_numbers', 'ui'); this.loadImage('overlay_lv', 'ui'); this.loadAtlas('numbers', 'ui'); this.loadAtlas('numbers_red', 'ui'); diff --git a/src/locales/de/tutorial.ts b/src/locales/de/tutorial.ts index f37afcae92d..2722c02ad45 100644 --- a/src/locales/de/tutorial.ts +++ b/src/locales/de/tutorial.ts @@ -20,10 +20,6 @@ export const tutorial: SimpleTranslationEntries = { "pokerus": `A daily random 3 selectable starters have a purple border. $If you see a starter you own with one of these,\ntry adding it to your party. Be sure to check its summary!`, - "statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. - $Your Pokémon are recalled before a trainer battle and before entering a new biome. - $You can also view the stat changes for the Pokémon on the field by holding shift.`, - "selectItem": `After every battle, you are given a choice of 3 random items.\nYou may only pick one. $These range from consumables, to Pokémon held items, to passive permanent items. $Most non-consumable item effects will stack in various ways. diff --git a/src/locales/en/tutorial.ts b/src/locales/en/tutorial.ts index f37afcae92d..2722c02ad45 100644 --- a/src/locales/en/tutorial.ts +++ b/src/locales/en/tutorial.ts @@ -20,10 +20,6 @@ export const tutorial: SimpleTranslationEntries = { "pokerus": `A daily random 3 selectable starters have a purple border. $If you see a starter you own with one of these,\ntry adding it to your party. Be sure to check its summary!`, - "statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. - $Your Pokémon are recalled before a trainer battle and before entering a new biome. - $You can also view the stat changes for the Pokémon on the field by holding shift.`, - "selectItem": `After every battle, you are given a choice of 3 random items.\nYou may only pick one. $These range from consumables, to Pokémon held items, to passive permanent items. $Most non-consumable item effects will stack in various ways. diff --git a/src/locales/es/tutorial.ts b/src/locales/es/tutorial.ts index f37afcae92d..2722c02ad45 100644 --- a/src/locales/es/tutorial.ts +++ b/src/locales/es/tutorial.ts @@ -20,10 +20,6 @@ export const tutorial: SimpleTranslationEntries = { "pokerus": `A daily random 3 selectable starters have a purple border. $If you see a starter you own with one of these,\ntry adding it to your party. Be sure to check its summary!`, - "statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. - $Your Pokémon are recalled before a trainer battle and before entering a new biome. - $You can also view the stat changes for the Pokémon on the field by holding shift.`, - "selectItem": `After every battle, you are given a choice of 3 random items.\nYou may only pick one. $These range from consumables, to Pokémon held items, to passive permanent items. $Most non-consumable item effects will stack in various ways. diff --git a/src/locales/fr/tutorial.ts b/src/locales/fr/tutorial.ts index 55262b195ca..c9f8a392e1e 100644 --- a/src/locales/fr/tutorial.ts +++ b/src/locales/fr/tutorial.ts @@ -25,10 +25,6 @@ export const tutorial: SimpleTranslationEntries = { $violet. Si un starter que vous possédez l’a, essayez de $ l’ajouter à votre équipe. Vérifiez bien son résumé !`, - "statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. - $Your Pokémon are recalled before a trainer battle and before entering a new biome. - $You can also view the stat changes for the Pokémon on the field by holding shift.`, - "selectItem": `Après chaque combat, vous avez le choix entre 3 objets\ntirés au sort. Vous ne pouvez en prendre qu’un. $Cela peut être des objets consommables, des objets à\nfaire tenir, ou des objets passifs aux effets permanents. $La plupart des effets des objets non-consommables se cumuleront de diverses manières. diff --git a/src/locales/it/tutorial.ts b/src/locales/it/tutorial.ts index f37afcae92d..2722c02ad45 100644 --- a/src/locales/it/tutorial.ts +++ b/src/locales/it/tutorial.ts @@ -20,10 +20,6 @@ export const tutorial: SimpleTranslationEntries = { "pokerus": `A daily random 3 selectable starters have a purple border. $If you see a starter you own with one of these,\ntry adding it to your party. Be sure to check its summary!`, - "statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. - $Your Pokémon are recalled before a trainer battle and before entering a new biome. - $You can also view the stat changes for the Pokémon on the field by holding shift.`, - "selectItem": `After every battle, you are given a choice of 3 random items.\nYou may only pick one. $These range from consumables, to Pokémon held items, to passive permanent items. $Most non-consumable item effects will stack in various ways. diff --git a/src/phases.ts b/src/phases.ts index ceba555f2ce..8eda33de20e 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2671,6 +2671,7 @@ export class StatChangePhase extends PokemonPhase { let random = false; + const allStats = Utils.getEnumValues(BattleStat); if (this.stats.length === 1 && this.stats[0] === BattleStat.RAND) { this.stats[0] = this.getRandomStat(); random = true; @@ -2711,11 +2712,8 @@ export class StatChangePhase extends PokemonPhase { for (let stat of filteredStats) pokemon.summonData.battleStats[stat] = Math.max(Math.min(pokemon.summonData.battleStats[stat] + levels.value, 6), -6); - applyPostStatChangeAbAttrs(PostStatChangeAbAttr, pokemon, filteredStats, this.levels, this.selfTarget); - - pokemon.updateInfo(); - - handleTutorial(this.scene, Tutorial.Stat_Change).then(() => super.end()); + applyPostStatChangeAbAttrs(PostStatChangeAbAttr, pokemon, filteredStats, this.levels, this.selfTarget) + this.end(); }; if (relLevels.filter(l => l).length && this.scene.moveAnimations) { @@ -3339,7 +3337,7 @@ export class TrainerVictoryPhase extends BattlePhase { const trainerType = this.scene.currentBattle.trainer.config.trainerType; if (vouchers.hasOwnProperty(TrainerType[trainerType])) { if (!this.scene.validateVoucher(vouchers[TrainerType[trainerType]]) && this.scene.currentBattle.trainer.config.isBoss) - this.scene.unshiftPhase(new ModifierRewardPhase(this.scene, [ modifierTypes.VOUCHER, modifierTypes.VOUCHER, modifierTypes.VOUCHER_PLUS, modifierTypes.VOUCHER_PREMIUM ][vouchers[TrainerType[trainerType]].voucherType])); + this.scene.pushPhase(new ModifierRewardPhase(this.scene, modifierTypes.VOUCHER)); } this.scene.ui.showText(i18next.t('menu:trainerDefeated', { trainerName: this.scene.currentBattle.trainer.getName(TrainerSlot.NONE, true) }), null, () => { diff --git a/src/tutorial.ts b/src/tutorial.ts index 88e88fa809c..918c68b9bb4 100644 --- a/src/tutorial.ts +++ b/src/tutorial.ts @@ -9,7 +9,6 @@ export enum Tutorial { Menu = "MENU", Starter_Select = "STARTER_SELECT", Pokerus = "POKERUS", - Stat_Change = "STAT_CHANGE", Select_Item = "SELECT_ITEM", Egg_Gacha = "EGG_GACHA" } @@ -43,11 +42,6 @@ const tutorialHandlers = { scene.ui.showText(i18next.t("tutorial:pokerus"), null, () => scene.ui.showText('', null, () => resolve()), null, true); }); }, - [Tutorial.Stat_Change]: (scene: BattleScene) => { - return new Promise(resolve => { - scene.showFieldOverlay(1000).then(() => scene.ui.showText(i18next.t("tutorial:statChange"), null, () => scene.ui.showText('', null, () => scene.hideFieldOverlay(1000).then(() => resolve())), null, true)); - }); - }, [Tutorial.Select_Item]: (scene: BattleScene) => { return new Promise(resolve => { scene.ui.setModeWithoutClear(Mode.MESSAGE).then(() => { diff --git a/src/ui/battle-info.ts b/src/ui/battle-info.ts index 3c2b541c618..ae794a256fa 100644 --- a/src/ui/battle-info.ts +++ b/src/ui/battle-info.ts @@ -7,9 +7,6 @@ import { StatusEffect } from '../data/status-effect'; import BattleScene from '../battle-scene'; import { Type, getTypeRgb } from '../data/type'; import { getVariantTint } from '#app/data/variant'; -import { BattleStat } from '#app/data/battle-stat'; - -const battleStatOrder = [ BattleStat.ATK, BattleStat.DEF, BattleStat.SPATK, BattleStat.SPDEF, BattleStat.ACC, BattleStat.EVA, BattleStat.SPD ]; export default class BattleInfo extends Phaser.GameObjects.Container { private player: boolean; @@ -27,7 +24,6 @@ export default class BattleInfo extends Phaser.GameObjects.Container { private lastLevelExp: integer; private lastLevel: integer; private lastLevelCapped: boolean; - private lastBattleStats: string; private box: Phaser.GameObjects.Sprite; private nameText: Phaser.GameObjects.Text; @@ -50,11 +46,6 @@ export default class BattleInfo extends Phaser.GameObjects.Container { public expMaskRect: Phaser.GameObjects.Graphics; - private statsContainer: Phaser.GameObjects.Container; - private statsBox: Phaser.GameObjects.Sprite; - private statValuesContainer: Phaser.GameObjects.Container; - private statNumbers: Phaser.GameObjects.Sprite[]; - constructor(scene: Phaser.Scene, x: number, y: number, player: boolean) { super(scene, x, y); this.player = player; @@ -147,6 +138,18 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.levelNumbersContainer = this.scene.add.container(9.5, (this.scene as BattleScene).uiTheme ? 0 : -0.5); this.levelContainer.add(this.levelNumbersContainer); + this.type1Icon = this.scene.add.sprite(player ? -139 : -15, player ? -17 : -15.5, `pbinfo_${player ? 'player' : 'enemy'}_type1`); + this.type1Icon.setOrigin(0, 0); + this.add(this.type1Icon); + + this.type2Icon = this.scene.add.sprite(player ? -139 : -15, player ? -1 : -2.5, `pbinfo_${player ? 'player' : 'enemy'}_type2`); + this.type2Icon.setOrigin(0, 0); + this.add(this.type2Icon); + + this.type3Icon = this.scene.add.sprite(player ? -154 : 0, player ? -17 : -15.5, `pbinfo_${player ? 'player' : 'enemy'}_type`); + this.type3Icon.setOrigin(0, 0); + this.add(this.type3Icon); + if (this.player) { this.hpNumbersContainer = this.scene.add.container(-15, 10); this.add(this.hpNumbersContainer); @@ -168,46 +171,6 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.expBar = expBar; this.expMaskRect = expMaskRect; } - - this.statsContainer = this.scene.add.container(0, 0); - this.statsContainer.setAlpha(0); - this.add(this.statsContainer); - - this.statsBox = this.scene.add.sprite(0, 0, `${this.getTextureName()}_stats`); - this.statsBox.setOrigin(1, 0.5); - this.statsContainer.add(this.statsBox); - - const statLabels: Phaser.GameObjects.Sprite[] = []; - this.statNumbers = []; - - this.statValuesContainer = this.scene.add.container(0, 0); - this.statsContainer.add(this.statValuesContainer); - - battleStatOrder.map((s, i) => { - const statX = i > 1 ? this.statNumbers[i - 2].x + this.statNumbers[i - 2].width + 4 : -this.statsBox.width + 8; - const statY = -this.statsBox.height / 2 + 4 + (i < battleStatOrder.length - 1 ? (i % 2 ? 10 : 0) : 5); - const statLabel = this.scene.add.sprite(statX, statY, 'pbinfo_stat', BattleStat[s]); - statLabel.setOrigin(0, 0); - statLabels.push(statLabel); - this.statValuesContainer.add(statLabel); - - const statNumber = this.scene.add.sprite(statX + statLabel.width, statY, 'pbinfo_stat_numbers', '3'); - statNumber.setOrigin(0, 0); - this.statNumbers.push(statNumber); - this.statValuesContainer.add(statNumber); - }); - - this.type1Icon = this.scene.add.sprite(player ? -139 : -15, player ? -17 : -15.5, `pbinfo_${player ? 'player' : 'enemy'}_type1`); - this.type1Icon.setOrigin(0, 0); - this.add(this.type1Icon); - - this.type2Icon = this.scene.add.sprite(player ? -139 : -15, player ? -1 : -2.5, `pbinfo_${player ? 'player' : 'enemy'}_type2`); - this.type2Icon.setOrigin(0, 0); - this.add(this.type2Icon); - - this.type3Icon = this.scene.add.sprite(player ? -154 : 0, player ? -17 : -15.5, `pbinfo_${player ? 'player' : 'enemy'}_type`); - this.type3Icon.setOrigin(0, 0); - this.add(this.type3Icon); } initInfo(pokemon: Pokemon) { @@ -295,14 +258,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.expMaskRect.x = (pokemon.levelExp / getLevelTotalExp(pokemon.level, pokemon.species.growthRate)) * 510; this.lastExp = pokemon.exp; this.lastLevelExp = pokemon.levelExp; - - this.statValuesContainer.setPosition(8, 7) } - - const battleStats = battleStatOrder.map(() => 0); - - this.lastBattleStats = battleStats.join(''); - this.updateBattleStats(battleStats); } getTextureName(): string { @@ -316,7 +272,6 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.mini = mini; this.box.setTexture(this.getTextureName()); - this.statsBox.setTexture(`${this.getTextureName()}_stats`); if (this.player) this.y -= 12 * (mini ? 1 : -1); @@ -329,34 +284,21 @@ export default class BattleInfo extends Phaser.GameObjects.Container { el.y += -8 * (mini ? 1 : -1); }); - this.statValuesContainer.x += 2 * (mini ? 1 : -1); - this.statValuesContainer.y += -7 * (mini ? 1 : -1); - const toggledElements = [ this.hpNumbersContainer, this.expBar ]; toggledElements.forEach(el => el.setVisible(!mini)); } - toggleStats(visible: boolean): void { - this.scene.tweens.add({ - targets: this.statsContainer, - duration: Utils.fixedInt(125), - ease: 'Sine.easeInOut', - alpha: visible ? 1 : 0 - }); - } - updateBossSegments(pokemon: EnemyPokemon): void { const boss = !!pokemon.bossSegments; if (boss !== this.boss) { this.boss = boss; - [ this.nameText, this.genderText, this.teraIcon, this.splicedIcon, this.shinyIcon, this.ownedIcon, this.statusIndicator, this.levelContainer, this.statValuesContainer ].map(e => e.x += 48 * (boss ? -1 : 1)); + [ this.nameText, this.genderText, this.teraIcon, this.splicedIcon, this.shinyIcon, this.ownedIcon, this.statusIndicator, this.levelContainer ].map(e => e.x += 48 * (boss ? -1 : 1)); this.hpBar.x += 38 * (boss ? -1 : 1); this.hpBar.y += 2 * (this.boss ? -1 : 1); this.hpBar.setTexture(`overlay_hp${boss ? '_boss' : ''}`); this.box.setTexture(this.getTextureName()); - this.statsBox.setTexture(`${this.getTextureName()}_stats`); } this.bossSegments = boss ? pokemon.bossSegments : 0; @@ -375,7 +317,6 @@ export default class BattleInfo extends Phaser.GameObjects.Container { const divider = this.scene.add.rectangle(0, 0, 1, this.hpBar.height - (uiTheme ? 0 : 1), pokemon.bossSegmentIndex >= s ? 0xFFFFFF : 0x404040) divider.setOrigin(0.5, 0); this.add(divider); - this.moveBelow(divider as Phaser.GameObjects.GameObject, this.statsContainer); divider.setPositionRelative(this.hpBar, dividerX, uiTheme ? 0 : 1); this.hpBarSegmentDividers.push(divider); @@ -498,11 +439,6 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.lastLevel = pokemon.level; } - const battleStats = pokemon.summonData.battleStats.join(''); - - if (this.lastBattleStats !== battleStats) - this.updateBattleStats(pokemon.summonData.battleStats); - this.shinyIcon.setVisible(pokemon.isShiny()); resolve(); @@ -577,7 +513,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { }); } - setLevel(level: integer): void { + setLevel(level: integer) { const isCapped = level >= (this.scene as BattleScene).getMaxExpLevel(); this.levelNumbersContainer.removeAll(true); const levelStr = level.toString(); @@ -586,7 +522,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.levelContainer.setX((this.player ? -41 : -50) - 8 * Math.max(levelStr.length - 3, 0)); } - setHpNumbers(hp: integer, maxHp: integer): void { + setHpNumbers(hp: integer, maxHp: integer) { if (!this.player || !this.scene) return; this.hpNumbersContainer.removeAll(true); @@ -599,12 +535,6 @@ export default class BattleInfo extends Phaser.GameObjects.Container { for (let i = hpStr.length - 1; i >= 0; i--) this.hpNumbersContainer.add(this.scene.add.image(offset++ * -8, 0, 'numbers', hpStr[i])); } - - updateBattleStats(battleStats: integer[]): void { - battleStatOrder.map((s, i) => { - this.statNumbers[i].setFrame(battleStats[s].toString()); - }); - } } export class PlayerBattleInfo extends BattleInfo { From 6fd5709b13adfc71f6bf7b402df82af3f983477a Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Tue, 30 Apr 2024 23:02:16 -0400 Subject: [PATCH 04/45] Reapply stat change feature with fixes --- index.css | 4 + index.html | 3 + public/images/pbinfo_stat_numbers.json | 293 ++++++++++++++++++ .../ui/legacy/pbinfo_enemy_boss_stats.png | Bin 0 -> 435 bytes .../ui/legacy/pbinfo_enemy_mini_stats.png | Bin 0 -> 666 bytes .../ui/legacy/pbinfo_player_mini_stats.png | Bin 0 -> 674 bytes .../images/ui/legacy/pbinfo_player_stats.png | Bin 0 -> 285 bytes public/images/ui/legacy/pbinfo_stat.json | 188 +++++++++++ public/images/ui/legacy/pbinfo_stat.png | Bin 0 -> 263 bytes .../images/ui/legacy/pbinfo_stat_numbers.json | 293 ++++++++++++++++++ .../images/ui/legacy/pbinfo_stat_numbers.png | Bin 0 -> 392 bytes public/images/ui/pbinfo_enemy_boss.png | Bin 554 -> 526 bytes public/images/ui/pbinfo_enemy_boss_stats.png | Bin 0 -> 257 bytes public/images/ui/pbinfo_enemy_mini.png | Bin 888 -> 851 bytes public/images/ui/pbinfo_enemy_mini_stats.png | Bin 0 -> 642 bytes public/images/ui/pbinfo_enemy_type.png | Bin 1502 -> 3599 bytes public/images/ui/pbinfo_enemy_type1.png | Bin 1360 -> 3305 bytes public/images/ui/pbinfo_enemy_type2.png | Bin 1340 -> 3197 bytes public/images/ui/pbinfo_player.png | Bin 654 -> 619 bytes public/images/ui/pbinfo_player_mini.png | Bin 898 -> 860 bytes public/images/ui/pbinfo_player_mini_stats.png | Bin 0 -> 648 bytes public/images/ui/pbinfo_player_stats.png | Bin 0 -> 312 bytes public/images/ui/pbinfo_player_type1.png | Bin 1340 -> 3197 bytes public/images/ui/pbinfo_player_type2.png | Bin 1360 -> 3305 bytes public/images/ui/pbinfo_stat.json | 188 +++++++++++ public/images/ui/pbinfo_stat.png | Bin 0 -> 278 bytes public/images/ui/pbinfo_stat_numbers.json | 293 ++++++++++++++++++ public/images/ui/pbinfo_stat_numbers.png | Bin 0 -> 430 bytes src/battle-scene.ts | 72 +++-- src/data/splash-messages.ts | 3 +- src/field/pokemon.ts | 4 + src/loading-scene.ts | 6 + src/locales/de/tutorial.ts | 4 + src/locales/en/tutorial.ts | 4 + src/locales/es/tutorial.ts | 4 + src/locales/fr/tutorial.ts | 4 + src/locales/it/tutorial.ts | 4 + src/phases.ts | 10 +- src/tutorial.ts | 6 + src/ui/battle-info.ts | 102 +++++- 40 files changed, 1442 insertions(+), 43 deletions(-) create mode 100644 public/images/pbinfo_stat_numbers.json create mode 100644 public/images/ui/legacy/pbinfo_enemy_boss_stats.png create mode 100644 public/images/ui/legacy/pbinfo_enemy_mini_stats.png create mode 100644 public/images/ui/legacy/pbinfo_player_mini_stats.png create mode 100644 public/images/ui/legacy/pbinfo_player_stats.png create mode 100644 public/images/ui/legacy/pbinfo_stat.json create mode 100644 public/images/ui/legacy/pbinfo_stat.png create mode 100644 public/images/ui/legacy/pbinfo_stat_numbers.json create mode 100644 public/images/ui/legacy/pbinfo_stat_numbers.png create mode 100644 public/images/ui/pbinfo_enemy_boss_stats.png create mode 100644 public/images/ui/pbinfo_enemy_mini_stats.png create mode 100644 public/images/ui/pbinfo_player_mini_stats.png create mode 100644 public/images/ui/pbinfo_player_stats.png create mode 100644 public/images/ui/pbinfo_stat.json create mode 100644 public/images/ui/pbinfo_stat.png create mode 100644 public/images/ui/pbinfo_stat_numbers.json create mode 100644 public/images/ui/pbinfo_stat_numbers.png diff --git a/index.css b/index.css index 9a507ad6766..dd47387adee 100644 --- a/index.css +++ b/index.css @@ -150,6 +150,10 @@ body { display: none; } +#touchControls:not([data-ui-mode='COMMAND']):not([data-ui-mode='FIGHT']):not([data-ui-mode='BALL']):not([data-ui-mode='TARGET_SELECT']) #apad #apadStats { + display: none; +} + #apad .apadRectBtnContainer + .apadSqBtnContainer { top: calc(var(--controls-size) * -1.9); left: calc(var(--controls-size) * -0.9); diff --git a/index.html b/index.html index bd316330a99..177a92efce6 100644 --- a/index.html +++ b/index.html @@ -74,6 +74,9 @@
V
+
+ C +
Menu
diff --git a/public/images/pbinfo_stat_numbers.json b/public/images/pbinfo_stat_numbers.json new file mode 100644 index 00000000000..32170690aa0 --- /dev/null +++ b/public/images/pbinfo_stat_numbers.json @@ -0,0 +1,293 @@ +{ + "textures": [ + { + "image": "pbinfo_stat_numbers.png", + "format": "RGBA8888", + "size": { + "w": 117, + "h": 8 + }, + "scale": 1, + "frames": [ + { + "filename": "+1", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "+2", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 9, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "+3", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 18, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "+4", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 27, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "+5", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 36, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "+6", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 45, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-1", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 54, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-2", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 63, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-3", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 72, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-4", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 81, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-5", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 90, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-6", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 99, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "0", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 108, + "y": 0, + "w": 9, + "h": 8 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:794aa4af3291db5abd8a2667626c1998:1a6706ad557b92f9bf099c23e02af4a6:6537c634087637bb27e8a1edb1ee2e35$" + } +} diff --git a/public/images/ui/legacy/pbinfo_enemy_boss_stats.png b/public/images/ui/legacy/pbinfo_enemy_boss_stats.png new file mode 100644 index 0000000000000000000000000000000000000000..94c9f2a181736d88c6752f2c97ed0bbbee23ebcc GIT binary patch literal 435 zcmeAS@N?(olHy`uVBq!ia0vp^n}ArJgAGVJb4-r_QjEnx?oJHr&dIz4vU5FM978JR zyuG8?cgR7a?csXf_7^8kc|Ex$m-yBz<$7q-n^RU*Eb9Vy3q^L$xwlCBgn&~-ln2-0 zC$%D(Zao#Zd6NElh+n&%^Pj+>91Q?jM7YZ*~R6rK6tBHXtJ>3o}%+B70Tit?}|9LLp3388Oyx(ny$dZ`X4n6UD>PshjO%e?;W3et7Lx@QEIV2LHO-ZhLc6eY9Ry zIQ|Mdb1{9R)SaoXcSRIE<`z6H%nuWjbE9V$ zXGWbr(B0xb=lC1f6GDcM4fWFUoyzXm2QNAn5;^S^|FUJBo0|`=UT>R$XHs^CNV z##av>ty$f?T7lzV!;W1Rn!7wYzpJ*28OBxY>HqxBa!BncE&SaXRbV6dDO(__3L?7E8i*EoZkKZ{HwqsHRc+nk205eyDOS2sxDu$ zd@tM{5g62QzVkTGE`^WE*Hfq8w-A>Rt4KTHq5izn`AE{j-lt}1uFk6Sl=!q)x&3rH zmfHGREPZQC>e=c~;%vpYyt-a*X%jpw^vJ`ZrANz4IZ?ukeBYJTaNN^-KBA z)J%%Y&U~o6pj>*#j=aoIas@k?dF)+-(V{Q3XI{exr|Grpv%NI5;(qK@ xp0+UKM9$<@NoVioZhp6Q^O64&v*v`HV4ZIk%FUH_dOOew44$rjF6*2UngE&&E5rZ* literal 0 HcmV?d00001 diff --git a/public/images/ui/legacy/pbinfo_player_mini_stats.png b/public/images/ui/legacy/pbinfo_player_mini_stats.png new file mode 100644 index 0000000000000000000000000000000000000000..dd2b7e65ba3522986e78d6844a6be8823c3382ae GIT binary patch literal 674 zcmV;T0$u%yP)EX>4Tx04R}tkv&MmKpe$iQ%gl!9Lyl%kfA!+MMWJ;6^me@v=v%)FuC*#nzSS- zE{=k0!NHHks)LKOt`4q(Aou~|>f)s6A|?JWDYS_3;J6>}?mh0_0Ya# zo%24i$jY)xd`>)J&;^MfxvseU#<}FMz%xZ7o1P~YiKS8xD?QB0hDJP198oo$@`aqs zD(5ZETD8GC_v9}O74(%1*J+L-fh8o7qK*_aP(c+IqO|Iym`Kxp+`~WO_*3Lk$W;L& z#{z25AUl5WKlt6PS)7`5lR|MI@M7B^V?b~hXg6*9``EVICxHJMxYE1+S__!_B)!?y zB1gdBHgIv>)s#Kpat9cGs>_D#NPe0^u?W1M(KqFRp<7^J&F!tTkJASrOIK2l+uOfqI{p0s^F(smE#4Fv0000mP)t-s0001cl!Q`iV>wbnAvplXy>s5y zwg3O#*3P|BYg+%cd;kCcN$J_5c5S*Us$?%8vTKwfg`6|6Wc}-=`Gc19G2( z)VthFjRI1_B|(0{3_xi#U}t|v7bsoq>Eaj?(fam=p-_VZhjU<>!iIbQ4@G5d*>KA2 zr+S66yVASV%+m`tUAT0h%_Vu-2F6#OE9N=hF1aYEASTnz@k_ZzU>c{|jD#j+;!l_T zYhIRn;@{452VTh2;XbSE{bIVBSPWaCe#7lsobz5x%h_{T;XlZgp00i_>zopr0I}G2 ADF6Tf literal 0 HcmV?d00001 diff --git a/public/images/ui/legacy/pbinfo_stat.json b/public/images/ui/legacy/pbinfo_stat.json new file mode 100644 index 00000000000..b7da47fc192 --- /dev/null +++ b/public/images/ui/legacy/pbinfo_stat.json @@ -0,0 +1,188 @@ +{ + "textures": [ + { + "image": "pbinfo_stat.png", + "format": "RGBA8888", + "size": { + "w": 112, + "h": 6 + }, + "scale": 1, + "frames": [ + { + "filename": "SPATK", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 19, + "h": 8 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 18, + "h": 6 + }, + "frame": { + "x": 0, + "y": 0, + "w": 18, + "h": 6 + } + }, + { + "filename": "SPDEF", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 19, + "h": 8 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 18, + "h": 6 + }, + "frame": { + "x": 18, + "y": 0, + "w": 18, + "h": 6 + } + }, + { + "filename": "CRIT", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 17, + "h": 8 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 16, + "h": 6 + }, + "frame": { + "x": 36, + "y": 0, + "w": 16, + "h": 6 + } + }, + { + "filename": "ACC", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 13, + "h": 8 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 12, + "h": 6 + }, + "frame": { + "x": 52, + "y": 0, + "w": 12, + "h": 6 + } + }, + { + "filename": "ATK", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 13, + "h": 8 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 12, + "h": 6 + }, + "frame": { + "x": 64, + "y": 0, + "w": 12, + "h": 6 + } + }, + { + "filename": "DEF", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 13, + "h": 8 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 12, + "h": 6 + }, + "frame": { + "x": 76, + "y": 0, + "w": 12, + "h": 6 + } + }, + { + "filename": "EVA", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 13, + "h": 8 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 12, + "h": 6 + }, + "frame": { + "x": 88, + "y": 0, + "w": 12, + "h": 6 + } + }, + { + "filename": "SPD", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 13, + "h": 8 + }, + "spriteSourceSize": { + "x": 1, + "y": 2, + "w": 12, + "h": 6 + }, + "frame": { + "x": 100, + "y": 0, + "w": 12, + "h": 6 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:40d30205ce8efd40dfa86cd11b0491d6:7076db6ed74199dcfb38fc8cd4d4a0e8:05882267d3999884e0491134e98b1b53$" + } +} diff --git a/public/images/ui/legacy/pbinfo_stat.png b/public/images/ui/legacy/pbinfo_stat.png new file mode 100644 index 0000000000000000000000000000000000000000..62ec3758772daea6013a4de5532575a66caf8116 GIT binary patch literal 263 zcmeAS@N?(olHy`uVBq!ia0vp^1whQk!3-pITwg5(Qk(%kA+A8$!NK9)wXI7Q-Kzj{ z7)yfuf*Bm1-ADteDDa3ZW?Ec4QuN(io6fN32b;e=)XJ@8wjxa57 z6;5`pyz#?~2;;a-r4XYn{3?!Y<6HKbItN$2xk}gw>0y zUzy)p<5e-!w)Vy<(87aih3;8-LtI=7KLTHk<}Jk-^i|&t;uc GLK6T7%VuW) literal 0 HcmV?d00001 diff --git a/public/images/ui/legacy/pbinfo_stat_numbers.json b/public/images/ui/legacy/pbinfo_stat_numbers.json new file mode 100644 index 00000000000..9c74ee86dbc --- /dev/null +++ b/public/images/ui/legacy/pbinfo_stat_numbers.json @@ -0,0 +1,293 @@ +{ + "textures": [ + { + "image": "pbinfo_stat_numbers.png", + "format": "RGBA8888", + "size": { + "w": 117, + "h": 8 + }, + "scale": 1, + "frames": [ + { + "filename": "+1", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "+2", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 9, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "+3", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 18, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "+4", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 27, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "+5", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 36, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "+6", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 45, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-1", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 54, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-2", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 63, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-3", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 72, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-4", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 81, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-5", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 90, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-6", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 99, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "0", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 108, + "y": 0, + "w": 9, + "h": 8 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:1f22b7cb085faf9e9764273fa5e70c28:afc5587ebacca78d178ac7e0c434591b:6537c634087637bb27e8a1edb1ee2e35$" + } +} diff --git a/public/images/ui/legacy/pbinfo_stat_numbers.png b/public/images/ui/legacy/pbinfo_stat_numbers.png new file mode 100644 index 0000000000000000000000000000000000000000..ee1453b21070f8de40a299a2d0c82c49093799cc GIT binary patch literal 392 zcmV;30eAk1P)NeVolC?^B79yfh4NP^lrY9U!*DY-V@3rV{hYdQ>YK;=1YJaz3T;`<^$DGJL<5 z0VRW87@CHmA>NuYKzH1TLC5xSzn%dVgI*Y#hCzM2e@<+(--30)Oref_gmu$R&9E*Q zKCPUg&65~>rQzm$c=)wGxON}pkE{!ZPit-h_?q;dhMV)@;n(^|U!-Qgl_%A@VDM** z28vT)T`)O@Pln{f8%r6yr(x9i(DP6xH!0n5bN5`F;gccxJgbFgqhZwe(DRg7RCba7 mA?H5)Du%PaS?j+(7uOe-FYwO$9P0Z30000Ik&UmVKT0GxPa8d!07jZZ!ddIBQBbh_PFZe&65JuT|9nKq=MA`2Ra01f-NW z91f+QE2Xg6Y_!guHF6k+mXtE_eP3^s9ZQpWyFcUJ3~9SRW4V~*j$cQ1WnC#{?2Y{H zp1HO|plBRLh_0>&dpk(u@=|B3Ul!cn-d9Bu|Irn<2(MATii<NL1q8595j002ovPDHLkV1ifd@6!MP delta 515 zcmV+e0{s1s1gZp(F@NMqL_t(|obB6BYQjJm1@M;=C_;s9>aGx7IS8(W?BZR#K+fR> zdKYIGa4pEV(m;21BcvdOLb@oX#w6N||Hk-!EB%ba5WYMoi2;a+$P89q(Q(?bWqnK1js?_P5*2T3V0acimCcp71_vhnu(jb5jIunqv- zU|m?J^YT3J;D0uwQBe98btaL0--i&Q%orEbYPFKro2Hw%bs$(LP1z0Bn7Fmy_dE4% zMRfpBN}Xl?_f7}_DJACfdG6;*DGY~0t+A6v4#Sx>8X@+5UvHKdwn^skG{U|W(s&x7 z*QuwrAFS-cx>Cy61NqkdXW#0iF_3fBLidQcv~I9QcYG^xiwstFvMunJ#6@+wo@071 z6=j=LzJ;IG-9*kySisI*Q}3$_A-J?SlT8{I?O!P+!f>JWs8i-krl0glDKjDTt88$>!uSb_l5uf002ovPDHLk FV1lYA{=)zO diff --git a/public/images/ui/pbinfo_enemy_boss_stats.png b/public/images/ui/pbinfo_enemy_boss_stats.png new file mode 100644 index 0000000000000000000000000000000000000000..7148a7af4759141abb5e2b39c02a17b45af905e5 GIT binary patch literal 257 zcmeAS@N?(olHy`uVBq!ia0vp^n}ArJgAGVJb4-r_QjEnx?oJHr&dIz4a&~*VIEGZr zd3$>`-ysJ9)(e`BNfSH%{_kJqko58BL=U^z3cqSH|eR)57 zW1&p?=O4X~e>-L8TFuvct=1%`yX>BUe4QLNkl8GRYx|2)P*70tlomTy+AL)kaKVi zE&#J{fxIOH3ldw!o(@eA9|jTwfke-5G6qF2@~g-B0uhl?&o>!GQQmYRa=R?cyz5!T z`|(5+MftElx~(F4j)*+88Q$()i?q{0_b3h8Z?jzmZ4pWY0rr0qL21w(A*rB55THl| zr9t=9O$8-_0MJt!bXT2JP$CGRMv#IUK>#&^6m9ha8#1%t_N<261?l{K=~*1pAjk_btXV2r7AjK;-r zyc-`ce5q`T&+mUP){_|k&bdbFdlX{~)>_gu^?vW1V>+D%9edXZS(f#zwRw^xVO733 z=iJLT_%&7jLr5Bc=c*yJqh3v!6wCSI$(1zcmbE+B8p>2?Q-u1?3(9$bLGjrb(}}GC z&Tny{X#k#=SKD&ZXsreQPoB<=eZOzJOKWr2MgYCV+*TmByu~acA|fIpa@iluDW|ek SO(V4c0000wNkl)q|N~u!nI~O4Yq?Ab0 z)cUDa4A$g)|GB+zjjyH$DNlu{Sp;D;RZA6(J^uv|5`cGRUYNim(gR9s1U zPC0iQQ-etbpCZ(@E->2xpqYObLeyev0QOIDQc7gm-04MCwVfaNvS^f20{C4#?Hk+n z_uXHMMb~Ko*z*>1x7*b&2cv4u=Wc00L_|bHM0D5>)LE${MNRhx00000NkvXXu0mjf DZ|lEX>4Tx04R}tkv&MmP!xqvQ>7vm5sQd8WT;LSL`4J_sbUc+7C6sqP{?%e(K->QQng1AHR!9McVpc!PL) z)6zNb6Ngw)Qi#uq#|*k4@gvt|m)|%S92R(H$VeyWi9^IW<^6Ko+1t_sz&)j z#$|=`7H73wWzBo?7Y1|MN{Z{Wh7rRO;z&S*j4Dbf!$O31jT93}I*)qzha7)`Tr#;z zVB}ap1u7)R5B>+gXKUssC)}i96zF`h?T-;4unRP5w*7r<+l>>z{|sDdEq|pB%zTnw zYiZ#lpm!U%xNd3k9&ot>3_j_SAvuztmXOZ_?`QN)S)l(G=w5T@);!1Q1CXX!E#CkK zhrnoove!M{-PJy~e|wtq`vH(aagbUB zzo-t5uI_cI;7<`vL}@r@>=fw7Q_>^>xEhuomQto)FNAjEI4-`=cWfUYlv1Ys?$EX( z{-b279fr-f*TOp8O^+I^-|2j;`a~!KNp6au2K}h1f+CP)E`l2L=hG@E0!flV4f^#- z6%>Ia27#GDAc;X>X8YJF+efPS#oQskn5pI%x-*WUY4S8Vs<2+QHAobJnOn>qX}QG= c008jX1y1rsg=?D3Y5)KL07*qoM6N<$f~t=qVE_OC literal 0 HcmV?d00001 diff --git a/public/images/ui/pbinfo_enemy_type.png b/public/images/ui/pbinfo_enemy_type.png index 021a120070c1872b54405196e4bcb2cec9920d06..9bac63e5e72ba305c0c7769d72bc39d72aa8202e 100644 GIT binary patch literal 3599 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 diff --git a/public/images/ui/pbinfo_enemy_type1.png b/public/images/ui/pbinfo_enemy_type1.png index 89b84d7f6305169db2e227aa33a9e2202cdeebfa..6d94871e8da1dfd56a0271a6a8ef1ae8e9d6c3c4 100644 GIT binary patch literal 3305 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 delta 1332 zcmV-41K;roK6x|8rVOt-T?ULCa%fweLZBshW_&&HC;* zO0vk;&DMDOm4U9|mAs4J&B(p@`1tjx^{$}s^^2`iam|Lp|9@hcy`Z4dqs6<(m4=$( z@Ycwh|J;Giu7~bbDWAdC&0W2FNPBZod$Y)zgQZ%P*Yx1fkon7G_No9%p+S^Ti}|f> zm8jtMc@R>*?(~L`sg$n0l(@~ZN?llm^Z)<=0d!JMQvg8b*k%9#010qNS#tmY4#WTe z4#WYKD-Ig~0DlAzNkl(^Y-#Wr6(Oj4xVAPdRD7!nD#iAB*BzHNIOCF7+K!2!Mo?4Ma{y?`n4?k5THGfPb znjaf?PygBd=;)}=AC3b1KsV?cB*s@ciU)rw57cPk>(CnArfu-@+b7_eU=Lj1OnvNcwffW0-uP_mXO_l4S!y5_eP^JhH)c@!3IEp%o=Epqlf^Q zdl4vm%oVI6jAf-z5$|I$U2Dmtnyz&NU|gM1Tovo?z9%sl038k@0T?JGHsIL@QDnrd zDzX{HYQ?=uvO=g-#FB$Nsuv5}+iLfdlS^uKdBRa(`I~AmiC0_`**#%3i+m|xZDaqP znSbbOs;KIv6AN{%B`!mDz1^R4OyqbTAb6NW0}$>+AUJ_2A{5z+2=NU>5xD9kiW7b_ ziQ3*&JDtuMz*$E^ zq5Oy)WOl}~7tbVB4ihDjPFJx4ljiYZ^SDMTc5Eak+VETLetdjNB~Onz3M4|@U_y^2 zIZTv9KC>90ws`^*7o%$YR54G)Z&akbQ~r1nO{!**|rqpNJ<0!EF`8Alxn}7E5 z(}~lmd`(2y!z<9KqCiv?B4ap}nkwRT+RHPkNNQz9jwytB>h0bPVUU_P&kYuaaOFk$ z8LiIGod{VZ7{z9D<;CVoyik#-*^P(`O#DR2_+sU8C^NhOn2+~R33uoA15d^47ggK
u*i{Slh@`p?1>g%h%6Cw5J!=T0U*R1MnDJ6|U#*Z*JkoesN4y6h&V9 zS^IL#rHNpS$$z3KVzb$F)3Ol+L9lnip}Z&_gDU{iG###yJqW`PfbDi$yYFhX!dhEB z4IRgEH!YixG)-SW$f;^_3~?M|t<_*LPlNlL+mTx`uF6D6l4LfiP&6*cw*!3q`#KE6 z*>nv)$B`rn;PGFB@1WyQS!;op!Bg3K(f(8CKUlOl=YJNph0sZ>!pgJLse-2Lyi&dt}*K+!0R$E0vTWLUzE`_5mXrc zsQaRf);@*cL$jCTsXOrp#Tb)a{=Cd~yPcLDF5CP8>Nk1daueF@H!&L_t(|obBAdPTNo%hT%6=r7mDtOmVaZ|#D^=AwA$T>{|y z{`MMK0n4%gn9t{_=Z;1rTz8s03~k$XIW5~GzVAQ(BKK9E&tTg&t~=GuVw47V*Ecn{ zq+W@M;5bfWQX%fXAUY0k`1iGCS&iu$vV0E5aexf}HGd3;XC*YPKAz_Re{P;O?Z=(J z@3P-4P6>ipC$SJTFR}T;@LhT#Kr@~tNIX4Rlr7F3ih1JlvSD0}h;CUMrfz+?^FUrW92r7(fqb;z7>41Gsv{dh>cWt0R&T-FUZ9s?$T_$M z7l7HfK;Dvp1&OUH5K*IY>CJ^)^|N88NNC4pVs+=4}QGTmJ(3~vGe$D%9 z=$A!Nln?u(Y8Bx=BIU(qc)3?Ccq~Cn18LBHo9*gki69XmDIk9lNQ3S;P6ZMHlCDey z(x7{MDv$_}bVVYN2HmyUuGk}Bhem)T8UcGW0wi(y`1JhcWAML^ZL!&|BuT^msC0bn znVUT57V~&KuA`Qlv)1Y@{gNcD<5}t0Th136Ouiehu`ZX)k+t@4i#a$Ek|dEaCiL`1 z#BqEW7bo8HP4R#J`Jwe>CP{M6HBw()j4`s-DoxYU_nmW^PNyfwu5N@Z%X-$@JV}zU zDj%G4?%^B!KbQQ5<1~;eTs0Iss;zudEa!_mSJIraxeHnvd@8glLd*6A{^x002ovPDHLkV1g-F&x8N~ delta 473 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 delta 1332 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 Wt8RFN+!3I289ZJ6T-G@yGywokWokPB literal 0 HcmV?d00001 diff --git a/public/images/ui/pbinfo_stat_numbers.json b/public/images/ui/pbinfo_stat_numbers.json new file mode 100644 index 00000000000..ec4f7117bb7 --- /dev/null +++ b/public/images/ui/pbinfo_stat_numbers.json @@ -0,0 +1,293 @@ +{ + "textures": [ + { + "image": "pbinfo_stat_numbers.png", + "format": "RGBA8888", + "size": { + "w": 117, + "h": 8 + }, + "scale": 1, + "frames": [ + { + "filename": "1", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "2", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 9, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "3", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 18, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "4", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 27, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "5", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 36, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "6", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 45, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-1", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 54, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-2", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 63, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-3", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 72, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-4", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 81, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-5", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 90, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "-6", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 99, + "y": 0, + "w": 9, + "h": 8 + } + }, + { + "filename": "0", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 9, + "h": 8 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 9, + "h": 8 + }, + "frame": { + "x": 108, + "y": 0, + "w": 9, + "h": 8 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:b0719fae0d9b670a727148cdc7202249:afc5587ebacca78d178ac7e0c434591b:4825a9f02f72f1fe28a724c6c5dffb37$" + } +} diff --git a/public/images/ui/pbinfo_stat_numbers.png b/public/images/ui/pbinfo_stat_numbers.png new file mode 100644 index 0000000000000000000000000000000000000000..c778ba992734421a718b2c49db1db0ae77a28e09 GIT binary patch literal 430 zcmV;f0a5;mP)X}UpFSFJe%YMSjb zvz=}Te=dw_+OM;>zwNiTz<(WGW!%j?&)@0VTARh5OWbc`j(J{Tok%Zt#$YoH;sBj7 z0D#IlJRc6p%*|?r>-8D{#_^;+F^22I1yqy`_PebZNKrNbfWEEq_WF{{oLyYu^!yS4 z#PO(4jM4P@WGYS8UqlLVGYqiSvW&F&OBuS>FtHC$Vz?0ZyX|CN5<3@SjG<>5X2}?8 zQ)v+?7z&xQg%~oUa!zD?QzeEgj_Hh<7_VVM6DZ`EEo4UD)*|DZy2Lt;DavMIyoRBA zxP2Ty%KN9gENZI8IE_78Q^T$GD~(@jhsGYQsdI~*V!X;!+J?fg{Gd2S+NQZaWGcsm zi<{b~a&9zLI&@IbQb7LyuD?x7eaKXf@hzMCJ+VH0TaTtDpMHPh p)) + p.toggleStats(pressed); + if (pressed) + this.setLastProcessedMovementTime(Button.STATS); + } else + return; + } if (inputSuccess && this.enableVibration && typeof navigator.vibrate !== 'undefined') navigator.vibrate(vibrationLength || 10); } @@ -1443,7 +1454,7 @@ export default class BattleScene extends SceneBase { * or not. It will only return true once, until the key is released and pressed down * again. */ - gamepadButtonJustDown(button: Phaser.Input.Gamepad.Button) : boolean { + gamepadButtonJustDown(button: Phaser.Input.Gamepad.Button): boolean { if (!button || !this.gamepadSupport) return false; @@ -1463,6 +1474,23 @@ export default class BattleScene extends SceneBase { return this.buttonKeys[button].some(k => Phaser.Input.Keyboard.JustDown(k)) || this.gamepadButtonJustDown(gamepad?.buttons[this.gamepadKeyConfig[button]]); } + /** + * gamepadButtonJustUp returns true if @param button has just been released + * or not. It will only return true once, until the key is released and pressed down + * again. + */ + gamepadButtonJustUp(button: Phaser.Input.Gamepad.Button): boolean { + if (!button || !this.gamepadSupport) + return false; + + return !this.gamepadButtonStates[button.index]; + } + + buttonJustReleased(button: Button): boolean { + const gamepad = this.input.gamepad?.gamepads[0]; + return this.buttonKeys[button].some(k => Phaser.Input.Keyboard.JustUp(k)) || this.gamepadButtonJustUp(gamepad?.buttons[this.gamepadKeyConfig[button]]); + } + /** * repeatInputDurationJustPassed returns true if @param button has been held down long * enough to fire a repeated input. A button must claim the movementButtonLock before diff --git a/src/data/splash-messages.ts b/src/data/splash-messages.ts index 11629cf05d7..198ff07cec9 100644 --- a/src/data/splash-messages.ts +++ b/src/data/splash-messages.ts @@ -33,6 +33,5 @@ splashMessages.push(...[ 'Also Try Emerald Rogue!', 'Also Try Radical Red!', 'Eevee Expo!', - 'YNOproject!', - 'Shh, don\'t tell Sam!' + 'YNOproject!' ]); \ No newline at end of file diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 9a7bfb48621..7072875d3ce 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -1179,6 +1179,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return this.battleInfo.updateInfo(this, instant); } + toggleStats(visible: boolean): void { + this.battleInfo.toggleStats(visible); + } + addExp(exp: integer) { const maxExpLevel = this.scene.getMaxExpLevel(); const initialExp = this.exp; diff --git a/src/loading-scene.ts b/src/loading-scene.ts index 2f37b900ab5..875d618ec0f 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -39,15 +39,21 @@ export class LoadingScene extends SceneBase { } this.loadAtlas('namebox', 'ui'); this.loadImage('pbinfo_player', 'ui'); + this.loadImage('pbinfo_player_stats', 'ui'); this.loadImage('pbinfo_player_mini', 'ui'); + this.loadImage('pbinfo_player_mini_stats', 'ui'); this.loadAtlas('pbinfo_player_type', 'ui'); this.loadAtlas('pbinfo_player_type1', 'ui'); this.loadAtlas('pbinfo_player_type2', 'ui'); this.loadImage('pbinfo_enemy_mini', 'ui'); + this.loadImage('pbinfo_enemy_mini_stats', 'ui'); this.loadImage('pbinfo_enemy_boss', 'ui'); + this.loadImage('pbinfo_enemy_boss_stats', 'ui'); this.loadAtlas('pbinfo_enemy_type', 'ui'); this.loadAtlas('pbinfo_enemy_type1', 'ui'); this.loadAtlas('pbinfo_enemy_type2', 'ui'); + this.loadAtlas('pbinfo_stat', 'ui'); + this.loadAtlas('pbinfo_stat_numbers', 'ui'); this.loadImage('overlay_lv', 'ui'); this.loadAtlas('numbers', 'ui'); this.loadAtlas('numbers_red', 'ui'); diff --git a/src/locales/de/tutorial.ts b/src/locales/de/tutorial.ts index 2722c02ad45..7a27f2077e6 100644 --- a/src/locales/de/tutorial.ts +++ b/src/locales/de/tutorial.ts @@ -20,6 +20,10 @@ export const tutorial: SimpleTranslationEntries = { "pokerus": `A daily random 3 selectable starters have a purple border. $If you see a starter you own with one of these,\ntry adding it to your party. Be sure to check its summary!`, + "statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. + $Your Pokémon are recalled before a trainer battle and before entering a new biome. + $You can also view the stat changes for the Pokémon on the field by holding C.`, + "selectItem": `After every battle, you are given a choice of 3 random items.\nYou may only pick one. $These range from consumables, to Pokémon held items, to passive permanent items. $Most non-consumable item effects will stack in various ways. diff --git a/src/locales/en/tutorial.ts b/src/locales/en/tutorial.ts index 2722c02ad45..7a27f2077e6 100644 --- a/src/locales/en/tutorial.ts +++ b/src/locales/en/tutorial.ts @@ -20,6 +20,10 @@ export const tutorial: SimpleTranslationEntries = { "pokerus": `A daily random 3 selectable starters have a purple border. $If you see a starter you own with one of these,\ntry adding it to your party. Be sure to check its summary!`, + "statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. + $Your Pokémon are recalled before a trainer battle and before entering a new biome. + $You can also view the stat changes for the Pokémon on the field by holding C.`, + "selectItem": `After every battle, you are given a choice of 3 random items.\nYou may only pick one. $These range from consumables, to Pokémon held items, to passive permanent items. $Most non-consumable item effects will stack in various ways. diff --git a/src/locales/es/tutorial.ts b/src/locales/es/tutorial.ts index 2722c02ad45..7a27f2077e6 100644 --- a/src/locales/es/tutorial.ts +++ b/src/locales/es/tutorial.ts @@ -20,6 +20,10 @@ export const tutorial: SimpleTranslationEntries = { "pokerus": `A daily random 3 selectable starters have a purple border. $If you see a starter you own with one of these,\ntry adding it to your party. Be sure to check its summary!`, + "statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. + $Your Pokémon are recalled before a trainer battle and before entering a new biome. + $You can also view the stat changes for the Pokémon on the field by holding C.`, + "selectItem": `After every battle, you are given a choice of 3 random items.\nYou may only pick one. $These range from consumables, to Pokémon held items, to passive permanent items. $Most non-consumable item effects will stack in various ways. diff --git a/src/locales/fr/tutorial.ts b/src/locales/fr/tutorial.ts index c9f8a392e1e..e280ee2d5dc 100644 --- a/src/locales/fr/tutorial.ts +++ b/src/locales/fr/tutorial.ts @@ -25,6 +25,10 @@ export const tutorial: SimpleTranslationEntries = { $violet. Si un starter que vous possédez l’a, essayez de $ l’ajouter à votre équipe. Vérifiez bien son résumé !`, + "statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. + $Your Pokémon are recalled before a trainer battle and before entering a new biome. + $You can also view the stat changes for the Pokémon on the field by holding C.`, + "selectItem": `Après chaque combat, vous avez le choix entre 3 objets\ntirés au sort. Vous ne pouvez en prendre qu’un. $Cela peut être des objets consommables, des objets à\nfaire tenir, ou des objets passifs aux effets permanents. $La plupart des effets des objets non-consommables se cumuleront de diverses manières. diff --git a/src/locales/it/tutorial.ts b/src/locales/it/tutorial.ts index 2722c02ad45..7a27f2077e6 100644 --- a/src/locales/it/tutorial.ts +++ b/src/locales/it/tutorial.ts @@ -20,6 +20,10 @@ export const tutorial: SimpleTranslationEntries = { "pokerus": `A daily random 3 selectable starters have a purple border. $If you see a starter you own with one of these,\ntry adding it to your party. Be sure to check its summary!`, + "statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. + $Your Pokémon are recalled before a trainer battle and before entering a new biome. + $You can also view the stat changes for the Pokémon on the field by holding C.`, + "selectItem": `After every battle, you are given a choice of 3 random items.\nYou may only pick one. $These range from consumables, to Pokémon held items, to passive permanent items. $Most non-consumable item effects will stack in various ways. diff --git a/src/phases.ts b/src/phases.ts index 8eda33de20e..ceba555f2ce 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2671,7 +2671,6 @@ export class StatChangePhase extends PokemonPhase { let random = false; - const allStats = Utils.getEnumValues(BattleStat); if (this.stats.length === 1 && this.stats[0] === BattleStat.RAND) { this.stats[0] = this.getRandomStat(); random = true; @@ -2712,8 +2711,11 @@ export class StatChangePhase extends PokemonPhase { for (let stat of filteredStats) pokemon.summonData.battleStats[stat] = Math.max(Math.min(pokemon.summonData.battleStats[stat] + levels.value, 6), -6); - applyPostStatChangeAbAttrs(PostStatChangeAbAttr, pokemon, filteredStats, this.levels, this.selfTarget) - this.end(); + applyPostStatChangeAbAttrs(PostStatChangeAbAttr, pokemon, filteredStats, this.levels, this.selfTarget); + + pokemon.updateInfo(); + + handleTutorial(this.scene, Tutorial.Stat_Change).then(() => super.end()); }; if (relLevels.filter(l => l).length && this.scene.moveAnimations) { @@ -3337,7 +3339,7 @@ export class TrainerVictoryPhase extends BattlePhase { const trainerType = this.scene.currentBattle.trainer.config.trainerType; if (vouchers.hasOwnProperty(TrainerType[trainerType])) { if (!this.scene.validateVoucher(vouchers[TrainerType[trainerType]]) && this.scene.currentBattle.trainer.config.isBoss) - this.scene.pushPhase(new ModifierRewardPhase(this.scene, modifierTypes.VOUCHER)); + this.scene.unshiftPhase(new ModifierRewardPhase(this.scene, [ modifierTypes.VOUCHER, modifierTypes.VOUCHER, modifierTypes.VOUCHER_PLUS, modifierTypes.VOUCHER_PREMIUM ][vouchers[TrainerType[trainerType]].voucherType])); } this.scene.ui.showText(i18next.t('menu:trainerDefeated', { trainerName: this.scene.currentBattle.trainer.getName(TrainerSlot.NONE, true) }), null, () => { diff --git a/src/tutorial.ts b/src/tutorial.ts index 918c68b9bb4..88e88fa809c 100644 --- a/src/tutorial.ts +++ b/src/tutorial.ts @@ -9,6 +9,7 @@ export enum Tutorial { Menu = "MENU", Starter_Select = "STARTER_SELECT", Pokerus = "POKERUS", + Stat_Change = "STAT_CHANGE", Select_Item = "SELECT_ITEM", Egg_Gacha = "EGG_GACHA" } @@ -42,6 +43,11 @@ const tutorialHandlers = { scene.ui.showText(i18next.t("tutorial:pokerus"), null, () => scene.ui.showText('', null, () => resolve()), null, true); }); }, + [Tutorial.Stat_Change]: (scene: BattleScene) => { + return new Promise(resolve => { + scene.showFieldOverlay(1000).then(() => scene.ui.showText(i18next.t("tutorial:statChange"), null, () => scene.ui.showText('', null, () => scene.hideFieldOverlay(1000).then(() => resolve())), null, true)); + }); + }, [Tutorial.Select_Item]: (scene: BattleScene) => { return new Promise(resolve => { scene.ui.setModeWithoutClear(Mode.MESSAGE).then(() => { diff --git a/src/ui/battle-info.ts b/src/ui/battle-info.ts index ae794a256fa..ae8f518e727 100644 --- a/src/ui/battle-info.ts +++ b/src/ui/battle-info.ts @@ -7,6 +7,9 @@ import { StatusEffect } from '../data/status-effect'; import BattleScene from '../battle-scene'; import { Type, getTypeRgb } from '../data/type'; import { getVariantTint } from '#app/data/variant'; +import { BattleStat } from '#app/data/battle-stat'; + +const battleStatOrder = [ BattleStat.ATK, BattleStat.DEF, BattleStat.SPATK, BattleStat.SPDEF, BattleStat.ACC, BattleStat.EVA, BattleStat.SPD ]; export default class BattleInfo extends Phaser.GameObjects.Container { private player: boolean; @@ -24,6 +27,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { private lastLevelExp: integer; private lastLevel: integer; private lastLevelCapped: boolean; + private lastBattleStats: string; private box: Phaser.GameObjects.Sprite; private nameText: Phaser.GameObjects.Text; @@ -46,6 +50,11 @@ export default class BattleInfo extends Phaser.GameObjects.Container { public expMaskRect: Phaser.GameObjects.Graphics; + private statsContainer: Phaser.GameObjects.Container; + private statsBox: Phaser.GameObjects.Sprite; + private statValuesContainer: Phaser.GameObjects.Container; + private statNumbers: Phaser.GameObjects.Sprite[]; + constructor(scene: Phaser.Scene, x: number, y: number, player: boolean) { super(scene, x, y); this.player = player; @@ -138,18 +147,6 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.levelNumbersContainer = this.scene.add.container(9.5, (this.scene as BattleScene).uiTheme ? 0 : -0.5); this.levelContainer.add(this.levelNumbersContainer); - this.type1Icon = this.scene.add.sprite(player ? -139 : -15, player ? -17 : -15.5, `pbinfo_${player ? 'player' : 'enemy'}_type1`); - this.type1Icon.setOrigin(0, 0); - this.add(this.type1Icon); - - this.type2Icon = this.scene.add.sprite(player ? -139 : -15, player ? -1 : -2.5, `pbinfo_${player ? 'player' : 'enemy'}_type2`); - this.type2Icon.setOrigin(0, 0); - this.add(this.type2Icon); - - this.type3Icon = this.scene.add.sprite(player ? -154 : 0, player ? -17 : -15.5, `pbinfo_${player ? 'player' : 'enemy'}_type`); - this.type3Icon.setOrigin(0, 0); - this.add(this.type3Icon); - if (this.player) { this.hpNumbersContainer = this.scene.add.container(-15, 10); this.add(this.hpNumbersContainer); @@ -171,6 +168,46 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.expBar = expBar; this.expMaskRect = expMaskRect; } + + this.statsContainer = this.scene.add.container(0, 0); + this.statsContainer.setAlpha(0); + this.add(this.statsContainer); + + this.statsBox = this.scene.add.sprite(0, 0, `${this.getTextureName()}_stats`); + this.statsBox.setOrigin(1, 0.5); + this.statsContainer.add(this.statsBox); + + const statLabels: Phaser.GameObjects.Sprite[] = []; + this.statNumbers = []; + + this.statValuesContainer = this.scene.add.container(0, 0); + this.statsContainer.add(this.statValuesContainer); + + battleStatOrder.map((s, i) => { + const statX = i > 1 ? this.statNumbers[i - 2].x + this.statNumbers[i - 2].width + 4 : -this.statsBox.width + 8; + const statY = -this.statsBox.height / 2 + 4 + (i < battleStatOrder.length - 1 ? (i % 2 ? 10 : 0) : 5); + const statLabel = this.scene.add.sprite(statX, statY, 'pbinfo_stat', BattleStat[s]); + statLabel.setOrigin(0, 0); + statLabels.push(statLabel); + this.statValuesContainer.add(statLabel); + + const statNumber = this.scene.add.sprite(statX + statLabel.width, statY, 'pbinfo_stat_numbers', '3'); + statNumber.setOrigin(0, 0); + this.statNumbers.push(statNumber); + this.statValuesContainer.add(statNumber); + }); + + this.type1Icon = this.scene.add.sprite(player ? -139 : -15, player ? -17 : -15.5, `pbinfo_${player ? 'player' : 'enemy'}_type1`); + this.type1Icon.setOrigin(0, 0); + this.add(this.type1Icon); + + this.type2Icon = this.scene.add.sprite(player ? -139 : -15, player ? -1 : -2.5, `pbinfo_${player ? 'player' : 'enemy'}_type2`); + this.type2Icon.setOrigin(0, 0); + this.add(this.type2Icon); + + this.type3Icon = this.scene.add.sprite(player ? -154 : 0, player ? -17 : -15.5, `pbinfo_${player ? 'player' : 'enemy'}_type`); + this.type3Icon.setOrigin(0, 0); + this.add(this.type3Icon); } initInfo(pokemon: Pokemon) { @@ -258,7 +295,14 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.expMaskRect.x = (pokemon.levelExp / getLevelTotalExp(pokemon.level, pokemon.species.growthRate)) * 510; this.lastExp = pokemon.exp; this.lastLevelExp = pokemon.levelExp; + + this.statValuesContainer.setPosition(8, 7) } + + const battleStats = battleStatOrder.map(() => 0); + + this.lastBattleStats = battleStats.join(''); + this.updateBattleStats(battleStats); } getTextureName(): string { @@ -272,6 +316,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.mini = mini; this.box.setTexture(this.getTextureName()); + this.statsBox.setTexture(`${this.getTextureName()}_stats`); if (this.player) this.y -= 12 * (mini ? 1 : -1); @@ -284,21 +329,34 @@ export default class BattleInfo extends Phaser.GameObjects.Container { el.y += -8 * (mini ? 1 : -1); }); + this.statValuesContainer.x += 2 * (mini ? 1 : -1); + this.statValuesContainer.y += -7 * (mini ? 1 : -1); + const toggledElements = [ this.hpNumbersContainer, this.expBar ]; toggledElements.forEach(el => el.setVisible(!mini)); } + toggleStats(visible: boolean): void { + this.scene.tweens.add({ + targets: this.statsContainer, + duration: Utils.fixedInt(125), + ease: 'Sine.easeInOut', + alpha: visible ? 1 : 0 + }); + } + updateBossSegments(pokemon: EnemyPokemon): void { const boss = !!pokemon.bossSegments; if (boss !== this.boss) { this.boss = boss; - [ this.nameText, this.genderText, this.teraIcon, this.splicedIcon, this.shinyIcon, this.ownedIcon, this.statusIndicator, this.levelContainer ].map(e => e.x += 48 * (boss ? -1 : 1)); + [ this.nameText, this.genderText, this.teraIcon, this.splicedIcon, this.shinyIcon, this.ownedIcon, this.statusIndicator, this.levelContainer, this.statValuesContainer ].map(e => e.x += 48 * (boss ? -1 : 1)); this.hpBar.x += 38 * (boss ? -1 : 1); this.hpBar.y += 2 * (this.boss ? -1 : 1); this.hpBar.setTexture(`overlay_hp${boss ? '_boss' : ''}`); this.box.setTexture(this.getTextureName()); + this.statsBox.setTexture(`${this.getTextureName()}_stats`); } this.bossSegments = boss ? pokemon.bossSegments : 0; @@ -317,6 +375,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { const divider = this.scene.add.rectangle(0, 0, 1, this.hpBar.height - (uiTheme ? 0 : 1), pokemon.bossSegmentIndex >= s ? 0xFFFFFF : 0x404040) divider.setOrigin(0.5, 0); this.add(divider); + this.moveBelow(divider as Phaser.GameObjects.GameObject, this.statsContainer); divider.setPositionRelative(this.hpBar, dividerX, uiTheme ? 0 : 1); this.hpBarSegmentDividers.push(divider); @@ -439,6 +498,13 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.lastLevel = pokemon.level; } + if (pokemon.summonData) { + const battleStats = pokemon.summonData.battleStats.join(''); + + if (this.lastBattleStats !== battleStats) + this.updateBattleStats(pokemon.summonData.battleStats); + } + this.shinyIcon.setVisible(pokemon.isShiny()); resolve(); @@ -513,7 +579,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { }); } - setLevel(level: integer) { + setLevel(level: integer): void { const isCapped = level >= (this.scene as BattleScene).getMaxExpLevel(); this.levelNumbersContainer.removeAll(true); const levelStr = level.toString(); @@ -522,7 +588,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.levelContainer.setX((this.player ? -41 : -50) - 8 * Math.max(levelStr.length - 3, 0)); } - setHpNumbers(hp: integer, maxHp: integer) { + setHpNumbers(hp: integer, maxHp: integer): void { if (!this.player || !this.scene) return; this.hpNumbersContainer.removeAll(true); @@ -535,6 +601,12 @@ export default class BattleInfo extends Phaser.GameObjects.Container { for (let i = hpStr.length - 1; i >= 0; i--) this.hpNumbersContainer.add(this.scene.add.image(offset++ * -8, 0, 'numbers', hpStr[i])); } + + updateBattleStats(battleStats: integer[]): void { + battleStatOrder.map((s, i) => { + this.statNumbers[i].setFrame(battleStats[s].toString()); + }); + } } export class PlayerBattleInfo extends BattleInfo { From 93765d41215fc006b790695f5af16ad3523d33b9 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Tue, 30 Apr 2024 23:23:32 -0400 Subject: [PATCH 05/45] Update battle info on stat change --- src/data/move.ts | 6 ++++++ src/field/pokemon.ts | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/data/move.ts b/src/data/move.ts index 5d5fec95729..ccf3872b473 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -1552,6 +1552,8 @@ export class CopyStatsAttr extends MoveEffectAttr { else user.removeTag(BattlerTagType.CRIT_BOOST); + user.updateInfo(); + target.scene.queueMessage(getPokemonMessage(user, 'copied\n') + getPokemonMessage(target, `'s stat changes!`)); return true; @@ -1566,6 +1568,8 @@ export class InvertStatsAttr extends MoveEffectAttr { for (let s = 0; s < target.summonData.battleStats.length; s++) target.summonData.battleStats[s] *= -1; + user.updateInfo(); + target.scene.queueMessage(getPokemonMessage(target, `'s stat changes\nwere all reversed!`)); return true; @@ -1580,6 +1584,8 @@ export class ResetStatsAttr extends MoveEffectAttr { for (let s = 0; s < target.summonData.battleStats.length; s++) target.summonData.battleStats[s] = 0; + user.updateInfo(); + target.scene.queueMessage(getPokemonMessage(target, `'s stat changes\nwere eliminated!`)); return true; diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 7072875d3ce..55036e1906d 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -1624,6 +1624,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.summonData.tags.push(tag); if (this instanceof PlayerPokemon && source.summonData.battleStats.find(bs => bs === 6)) this.scene.validateAchv(achvs.TRANSFER_MAX_BATTLE_STAT); + this.updateInfo(); } getMoveHistory(): TurnMove[] { @@ -1924,6 +1925,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } this.summonDataPrimer = null; } + this.updateInfo(); } resetBattleData(): void { From 7ad9c67673d348651e26f499c7e6dd5d7390953b Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Tue, 30 Apr 2024 23:27:22 -0400 Subject: [PATCH 06/45] Fix crash on catch --- src/battle-scene.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 39eb912ef87..8f07256e327 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -1438,7 +1438,7 @@ export default class BattleScene extends SceneBase { } else { let pressed = false; if (this.buttonJustReleased(Button.STATS) || (pressed = this.buttonJustPressed(Button.STATS))) { - for (let p of this.getField().filter(p => p)) + for (let p of this.getField().filter(p => p?.isActive(true))) p.toggleStats(pressed); if (pressed) this.setLastProcessedMovementTime(Button.STATS); From e06561044010f88e59f53b96d5d7b308f9a29207 Mon Sep 17 00:00:00 2001 From: lucfd <83493765+lucfd@users.noreply.github.com> Date: Tue, 30 Apr 2024 23:30:10 -0400 Subject: [PATCH 07/45] Fixed Dire Claw & Tri-Attack status chances (#367) * created MultiStatusEffectAttr * removed testing stuff * switched to randSeedItem --- src/data/move.ts | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index ccf3872b473..60e07b8f513 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -1009,6 +1009,25 @@ export class StatusEffectAttr extends MoveEffectAttr { } } +export class MultiStatusEffectAttr extends StatusEffectAttr { + public effects: StatusEffect[]; + + constructor(effects: StatusEffect[], selfTarget?: boolean, cureTurn?: integer, overrideStatus?: boolean) { + super(effects[0], selfTarget, cureTurn, overrideStatus); + this.effects = effects; + } + + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + this.effect = Utils.randSeedItem(this.effects); + const result = super.apply(user, target, move, args); + return result; + } + + getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { + return !(this.selfTarget ? user : target).status && (this.selfTarget ? user : target).canSetStatus(this.effect, true) ? Math.floor(move.chance * -0.1) : 0; + } +} + export class PsychoShiftEffectAttr extends MoveEffectAttr { constructor() { super(false, MoveEffectTrigger.HIT); @@ -4170,9 +4189,7 @@ export function initMoves() { new SelfStatusMove(Moves.CONVERSION, Type.NORMAL, -1, 30, -1, 0, 1) .attr(FirstMoveTypeAttr), new AttackMove(Moves.TRI_ATTACK, Type.NORMAL, MoveCategory.SPECIAL, 80, 100, 10, 20, 0, 1) - .attr(StatusEffectAttr, StatusEffect.PARALYSIS) - .attr(StatusEffectAttr, StatusEffect.BURN) - .attr(StatusEffectAttr, StatusEffect.FREEZE), + .attr(MultiStatusEffectAttr, [StatusEffect.BURN, StatusEffect.FREEZE, StatusEffect.PARALYSIS]), new AttackMove(Moves.SUPER_FANG, Type.NORMAL, MoveCategory.PHYSICAL, -1, 90, 10, -1, 0, 1) .attr(TargetHalfHpDamageAttr), new AttackMove(Moves.SLASH, Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 20, -1, 0, 1) @@ -5986,9 +6003,7 @@ export function initMoves() { .soundBased() .partial(), new AttackMove(Moves.DIRE_CLAW, Type.POISON, MoveCategory.PHYSICAL, 80, 100, 15, 50, 0, 8) - .attr(StatusEffectAttr, StatusEffect.POISON) - .attr(StatusEffectAttr, StatusEffect.PARALYSIS) - .attr(StatusEffectAttr, StatusEffect.SLEEP), + .attr(MultiStatusEffectAttr, [StatusEffect.POISON, StatusEffect.PARALYSIS, StatusEffect.SLEEP]), new AttackMove(Moves.PSYSHIELD_BASH, Type.PSYCHIC, MoveCategory.PHYSICAL, 70, 90, 10, 100, 0, 8) .attr(StatChangeAttr, BattleStat.DEF, 1, true), new SelfStatusMove(Moves.POWER_SHIFT, Type.NORMAL, -1, 10, 100, 0, 8) From 17ec6b3ccc4b286bca017d23e9935d98de8b9db6 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Wed, 1 May 2024 00:12:04 -0400 Subject: [PATCH 08/45] Fix start button mapping --- src/battle-scene.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 8f07256e327..0f2f712a501 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -205,8 +205,8 @@ export default class BattleScene extends SceneBase { [Button.SUBMIT]: 17, // touchpad [Button.ACTION]: 0, // X [Button.CANCEL]: 1, // O - [Button.MENU]: 8, // share - [Button.STATS]: 9, // options + [Button.MENU]: 9, // options + [Button.STATS]: 8, // share [Button.CYCLE_SHINY]: 5, // RB [Button.CYCLE_FORM]: 4, // LB [Button.CYCLE_GENDER]: 6, // LT From 77caa8ece5e3ce7f06e3bf694fc1d6628f5fa4c0 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Wed, 1 May 2024 00:27:11 -0400 Subject: [PATCH 09/45] Add back shift for toggling stats --- src/battle-scene.ts | 4 ++-- src/locales/de/tutorial.ts | 2 +- src/locales/en/tutorial.ts | 2 +- src/locales/es/tutorial.ts | 2 +- src/locales/fr/tutorial.ts | 2 +- src/locales/it/tutorial.ts | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 0f2f712a501..cbf363f689a 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -617,7 +617,7 @@ export default class BattleScene extends SceneBase { [Button.ACTION]: [keyCodes.SPACE, keyCodes.ENTER, keyCodes.Z], [Button.CANCEL]: [keyCodes.BACKSPACE, keyCodes.X], [Button.MENU]: [keyCodes.ESC, keyCodes.M], - [Button.STATS]: [keyCodes.C], + [Button.STATS]: [keyCodes.SHIFT, keyCodes.C], [Button.CYCLE_SHINY]: [keyCodes.R], [Button.CYCLE_FORM]: [keyCodes.F], [Button.CYCLE_GENDER]: [keyCodes.G], @@ -1437,7 +1437,7 @@ export default class BattleScene extends SceneBase { } } else { let pressed = false; - if (this.buttonJustReleased(Button.STATS) || (pressed = this.buttonJustPressed(Button.STATS))) { + if (this.ui && (this.buttonJustReleased(Button.STATS) || (pressed = this.buttonJustPressed(Button.STATS)))) { for (let p of this.getField().filter(p => p?.isActive(true))) p.toggleStats(pressed); if (pressed) diff --git a/src/locales/de/tutorial.ts b/src/locales/de/tutorial.ts index 7a27f2077e6..2773b6710ba 100644 --- a/src/locales/de/tutorial.ts +++ b/src/locales/de/tutorial.ts @@ -22,7 +22,7 @@ export const tutorial: SimpleTranslationEntries = { "statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. $Your Pokémon are recalled before a trainer battle and before entering a new biome. - $You can also view the stat changes for the Pokémon on the field by holding C.`, + $You can also view the stat changes for the Pokémon on the field by holding C or Shift.`, "selectItem": `After every battle, you are given a choice of 3 random items.\nYou may only pick one. $These range from consumables, to Pokémon held items, to passive permanent items. diff --git a/src/locales/en/tutorial.ts b/src/locales/en/tutorial.ts index 7a27f2077e6..2773b6710ba 100644 --- a/src/locales/en/tutorial.ts +++ b/src/locales/en/tutorial.ts @@ -22,7 +22,7 @@ export const tutorial: SimpleTranslationEntries = { "statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. $Your Pokémon are recalled before a trainer battle and before entering a new biome. - $You can also view the stat changes for the Pokémon on the field by holding C.`, + $You can also view the stat changes for the Pokémon on the field by holding C or Shift.`, "selectItem": `After every battle, you are given a choice of 3 random items.\nYou may only pick one. $These range from consumables, to Pokémon held items, to passive permanent items. diff --git a/src/locales/es/tutorial.ts b/src/locales/es/tutorial.ts index 7a27f2077e6..2773b6710ba 100644 --- a/src/locales/es/tutorial.ts +++ b/src/locales/es/tutorial.ts @@ -22,7 +22,7 @@ export const tutorial: SimpleTranslationEntries = { "statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. $Your Pokémon are recalled before a trainer battle and before entering a new biome. - $You can also view the stat changes for the Pokémon on the field by holding C.`, + $You can also view the stat changes for the Pokémon on the field by holding C or Shift.`, "selectItem": `After every battle, you are given a choice of 3 random items.\nYou may only pick one. $These range from consumables, to Pokémon held items, to passive permanent items. diff --git a/src/locales/fr/tutorial.ts b/src/locales/fr/tutorial.ts index e280ee2d5dc..b60ccc03b5d 100644 --- a/src/locales/fr/tutorial.ts +++ b/src/locales/fr/tutorial.ts @@ -27,7 +27,7 @@ export const tutorial: SimpleTranslationEntries = { "statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. $Your Pokémon are recalled before a trainer battle and before entering a new biome. - $You can also view the stat changes for the Pokémon on the field by holding C.`, + $You can also view the stat changes for the Pokémon on the field by holding C or Shift.`, "selectItem": `Après chaque combat, vous avez le choix entre 3 objets\ntirés au sort. Vous ne pouvez en prendre qu’un. $Cela peut être des objets consommables, des objets à\nfaire tenir, ou des objets passifs aux effets permanents. diff --git a/src/locales/it/tutorial.ts b/src/locales/it/tutorial.ts index 7a27f2077e6..2773b6710ba 100644 --- a/src/locales/it/tutorial.ts +++ b/src/locales/it/tutorial.ts @@ -22,7 +22,7 @@ export const tutorial: SimpleTranslationEntries = { "statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. $Your Pokémon are recalled before a trainer battle and before entering a new biome. - $You can also view the stat changes for the Pokémon on the field by holding C.`, + $You can also view the stat changes for the Pokémon on the field by holding C or Shift.`, "selectItem": `After every battle, you are given a choice of 3 random items.\nYou may only pick one. $These range from consumables, to Pokémon held items, to passive permanent items. From eac9b4d385a137e24601953ae1dd237ef6cdcd14 Mon Sep 17 00:00:00 2001 From: TeKrop Date: Wed, 1 May 2024 00:11:05 +0200 Subject: [PATCH 10/45] fix: reworked daily and weekly rankings translations workflow --- src/locales/de/menu.ts | 2 +- src/locales/en/menu.ts | 2 +- src/locales/es/menu.ts | 2 +- src/locales/fr/menu.ts | 2 +- src/locales/it/menu.ts | 2 +- src/ui/daily-run-scoreboard.ts | 5 +++-- 6 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/locales/de/menu.ts b/src/locales/de/menu.ts index 4876fa3432a..442cfae218f 100644 --- a/src/locales/de/menu.ts +++ b/src/locales/de/menu.ts @@ -59,8 +59,8 @@ export const menu: SimpleTranslationEntries = { "escapeVerbSwitch": "auswechseln", "escapeVerbFlee": "flucht", "notDisabled": "{{moveName}} ist\nnicht mehr deaktiviert!", - "rankings": "Rankings", "dailyRankings": "Daily Rankings", + "weeklyRankings": "Weekly Rankings", "noRankings": "No Rankings", "loading": "Loading…", "playersOnline": "Players Online" diff --git a/src/locales/en/menu.ts b/src/locales/en/menu.ts index 1d840a3eb03..82a09e49d4f 100644 --- a/src/locales/en/menu.ts +++ b/src/locales/en/menu.ts @@ -78,8 +78,8 @@ export const menu: SimpleTranslationEntries = { "skipItemQuestion": "Are you sure you want to skip taking an item?", "eggHatching": "Oh?", "ivScannerUseQuestion": "Use IV Scanner on {{pokemonName}}?", - "rankings": "Rankings", "dailyRankings": "Daily Rankings", + "weeklyRankings": "Weekly Rankings", "noRankings": "No Rankings", "loading": "Loading…", "playersOnline": "Players Online" diff --git a/src/locales/es/menu.ts b/src/locales/es/menu.ts index e72710cee37..5dccc2e4eb3 100644 --- a/src/locales/es/menu.ts +++ b/src/locales/es/menu.ts @@ -62,8 +62,8 @@ export const menu: SimpleTranslationEntries = { "skipItemQuestion": "¿Estás seguro de que no quieres coger un objeto?", "eggHatching": "¿Y esto?", "ivScannerUseQuestion": "¿Quieres usar el Escáner de IVs en {{pokemonName}}?", - "rankings": "Rankings", "dailyRankings": "Daily Rankings", + "weeklyRankings": "Weekly Rankings", "noRankings": "No Rankings", "loading": "Loading…", "playersOnline": "Players Online" diff --git a/src/locales/fr/menu.ts b/src/locales/fr/menu.ts index 037f0f3b5e2..d5478c67a26 100644 --- a/src/locales/fr/menu.ts +++ b/src/locales/fr/menu.ts @@ -73,8 +73,8 @@ export const menu: SimpleTranslationEntries = { "skipItemQuestion": "Êtes-vous sûr·e de ne pas vouloir prendre d’objet ?", "eggHatching": "Oh ?", "ivScannerUseQuestion": "Utiliser le Scanner d’IV sur {{pokemonName}} ?", - "rankings": "Classement", "dailyRankings": "Classement du Jour", + "weeklyRankings": "Classement de la Semaine", "noRankings": "Pas de Classement", "loading": "Chargement…", "playersOnline": "Joueurs Connectés" diff --git a/src/locales/it/menu.ts b/src/locales/it/menu.ts index b9e288c26ce..c37a37b5169 100644 --- a/src/locales/it/menu.ts +++ b/src/locales/it/menu.ts @@ -7,8 +7,8 @@ export const menu: SimpleTranslationEntries = { "loadGame": "Carica Partita", "dailyRun": "Corsa Giornaliera (Beta)", "selectGameMode": "Seleziona una modalità di gioco.", - "rankings": "Rankings", "dailyRankings": "Daily Rankings", + "weeklyRankings": "Weekly Rankings", "noRankings": "No Rankings", "loading": "Loading…", "playersOnline": "Players Online" diff --git a/src/ui/daily-run-scoreboard.ts b/src/ui/daily-run-scoreboard.ts index 1379ec6a8ef..8f7ca0bf110 100644 --- a/src/ui/daily-run-scoreboard.ts +++ b/src/ui/daily-run-scoreboard.ts @@ -11,6 +11,7 @@ interface RankingEntry { wave: integer } +// Don't forget to update translations when adding a new category enum ScoreboardCategory { DAILY, WEEKLY @@ -40,7 +41,7 @@ export class DailyRunScoreboard extends Phaser.GameObjects.Container { const titleWindow = addWindow(this.scene, 0, 0, 114, 18, false, false, null, null, WindowVariant.THIN); this.add(titleWindow); - this.titleLabel = addTextObject(this.scene, titleWindow.displayWidth / 2, titleWindow.displayHeight / 2, i18next.t('menu:dailyRankings'), TextStyle.WINDOW, { fontSize: '64px' }); + this.titleLabel = addTextObject(this.scene, titleWindow.displayWidth / 2, titleWindow.displayHeight / 2, i18next.t('menu:loading'), TextStyle.WINDOW, { fontSize: '64px' }); this.titleLabel.setOrigin(0.5, 0.5); this.add(this.titleLabel); @@ -156,7 +157,7 @@ export class DailyRunScoreboard extends Phaser.GameObjects.Container { .then(jsonResponse => { this.page = page; this.category = category; - this.titleLabel.setText(`${Utils.toReadableString(ScoreboardCategory[category])} ${i18next.t("menu:rankings")}`); + this.titleLabel.setText(`${i18next.t(`menu:${ScoreboardCategory[category].toLowerCase()}Rankings`)}`); this.prevPageButton.setAlpha(page > 1 ? 1 : 0.5); this.nextPageButton.setAlpha(page < this.pageCount ? 1 : 0.5); this.pageNumberLabel.setText(page.toString()); From 3b09e176a29922ef8a20d028eb345eb72bc3df66 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Wed, 1 May 2024 09:44:57 -0400 Subject: [PATCH 11/45] Fix IV text not comparing against starter species --- src/data/pokemon-species.ts | 4 ++-- src/ui/battle-message-ui-handler.ts | 6 ++++-- src/ui/pokemon-info-container.ts | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index 4136be5b70f..2f8edefa403 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -138,9 +138,9 @@ export abstract class PokemonSpeciesForm { this.genderDiffs = genderDiffs; } - getRootSpeciesId(): Species { + getRootSpeciesId(forStarter: boolean = false): Species { let ret = this.speciesId; - while (pokemonPrevolutions.hasOwnProperty(ret)) + while (pokemonPrevolutions.hasOwnProperty(ret) && (!forStarter || !speciesStarters.hasOwnProperty(ret))) ret = pokemonPrevolutions[ret]; return ret; } diff --git a/src/ui/battle-message-ui-handler.ts b/src/ui/battle-message-ui-handler.ts index 77144d6bbc0..7819017d896 100644 --- a/src/ui/battle-message-ui-handler.ts +++ b/src/ui/battle-message-ui-handler.ts @@ -5,6 +5,7 @@ import * as Utils from "../utils"; import MessageUiHandler from "./message-ui-handler"; import { getStatName, Stat } from "../data/pokemon-stat"; import { addWindow } from "./ui-theme"; +import BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext"; export default class BattleMessageUiHandler extends MessageUiHandler { private levelUpStatsContainer: Phaser.GameObjects.Container; @@ -223,8 +224,9 @@ export default class BattleMessageUiHandler extends MessageUiHandler { } getIvDescriptor(value: integer, typeIv: integer): string { - let starterIvs: number[] = this.scene.gameData.dexData[this.scene.getEnemyPokemon().species.speciesId].ivs; - let uiTheme = (this.scene as BattleScene).uiTheme; // Assuming uiTheme is accessible + const starterSpecies = this.scene.getEnemyPokemon().species.getRootSpeciesId(true); + const starterIvs: number[] = this.scene.gameData.dexData[starterSpecies].ivs; + const uiTheme = (this.scene as BattleScene).uiTheme; // Assuming uiTheme is accessible // Function to wrap text in color based on comparison const coloredText = (text: string, isBetter: boolean) => { diff --git a/src/ui/pokemon-info-container.ts b/src/ui/pokemon-info-container.ts index 4d8ecfe0b03..572a28f10c8 100644 --- a/src/ui/pokemon-info-container.ts +++ b/src/ui/pokemon-info-container.ts @@ -161,8 +161,9 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container { if (isFusion) this.pokemonFusionShinyIcon.setTint(getVariantTint(pokemon.fusionVariant)); - const originalIvs: integer[] = this.scene.gameData.dexData[pokemon.species.speciesId].caughtAttr - ? this.scene.gameData.dexData[pokemon.species.speciesId].ivs + const starterSpeciesId = pokemon.species.getRootSpeciesId(true); + const originalIvs: integer[] = this.scene.gameData.dexData[starterSpeciesId].caughtAttr + ? this.scene.gameData.dexData[starterSpeciesId].ivs : null; this.statsContainer.updateIvs(pokemon.ivs, originalIvs); From fc1a9f02837af4ebd5aee428e80d886a7b158e17 Mon Sep 17 00:00:00 2001 From: thicco-catto <67873211+thicco-catto@users.noreply.github.com> Date: Wed, 1 May 2024 16:16:58 +0200 Subject: [PATCH 12/45] Select Move UI Shows PP (#372) * Select move UI shows PP * Removed testing forced max pp * PP only shows when using PP restoring items * Removed testing max pp again * Update src/phases.ts * Update src/ui/party-ui-handler.ts --------- Co-authored-by: Samuel H --- src/phases.ts | 5 +++-- src/ui/party-ui-handler.ts | 11 ++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/phases.ts b/src/phases.ts index ceba555f2ce..ad2a7537de7 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -19,7 +19,7 @@ import { BattleStat, getBattleStatLevelChangeDescription, getBattleStatName } fr import { biomeLinks, getBiomeName } from "./data/biomes"; import { Biome } from "./data/enums/biome"; import { ModifierTier } from "./modifier/modifier-tier"; -import { FusePokemonModifierType, ModifierPoolType, ModifierType, ModifierTypeFunc, ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, RememberMoveModifierType, TmModifierType, getDailyRunStarterModifiers, getEnemyBuffModifierForWave, getModifierType, getPlayerModifierTypeOptions, getPlayerShopModifierTypeOptionsForWave, modifierTypes, regenerateModifierPoolThresholds } from "./modifier/modifier-type"; +import { FusePokemonModifierType, ModifierPoolType, ModifierType, ModifierTypeFunc, ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, PokemonPpRestoreModifierType, PokemonPpUpModifierType, RememberMoveModifierType, TmModifierType, getDailyRunStarterModifiers, getEnemyBuffModifierForWave, getModifierType, getPlayerModifierTypeOptions, getPlayerShopModifierTypeOptionsForWave, modifierTypes, regenerateModifierPoolThresholds } from "./modifier/modifier-type"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; import { BattlerTagLapseType, EncoreTag, HideSpriteTag as HiddenTag, ProtectedTag, TrappedTag } from "./data/battler-tags"; import { BattlerTagType } from "./data/enums/battler-tag-type"; @@ -4340,6 +4340,7 @@ export class SelectModifierPhase extends BattlePhase { const isMoveModifier = modifierType instanceof PokemonMoveModifierType; const isTmModifier = modifierType instanceof TmModifierType; const isRememberMoveModifier = modifierType instanceof RememberMoveModifierType; + const isPpRestoreModifier = modifierType instanceof PokemonPpRestoreModifierType; const partyUiMode = isMoveModifier ? PartyUiMode.MOVE_MODIFIER : isTmModifier ? PartyUiMode.TM_MODIFIER : isRememberMoveModifier ? PartyUiMode.REMEMBER_MOVE_MODIFIER @@ -4359,7 +4360,7 @@ export class SelectModifierPhase extends BattlePhase { }); } else this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, this.getRerollCost(typeOptions, this.scene.lockModifierTiers)); - }, pokemonModifierType.selectFilter, modifierType instanceof PokemonMoveModifierType ? (modifierType as PokemonMoveModifierType).moveSelectFilter : undefined, tmMoveId); + }, pokemonModifierType.selectFilter, modifierType instanceof PokemonMoveModifierType ? (modifierType as PokemonMoveModifierType).moveSelectFilter : undefined, tmMoveId, isPpRestoreModifier); } } else applyModifier(modifierType.newModifier()); diff --git a/src/ui/party-ui-handler.ts b/src/ui/party-ui-handler.ts index 29a4037f12f..35014fa7027 100644 --- a/src/ui/party-ui-handler.ts +++ b/src/ui/party-ui-handler.ts @@ -90,6 +90,7 @@ export default class PartyUiHandler extends MessageUiHandler { private selectFilter: PokemonSelectFilter | PokemonModifierTransferSelectFilter; private moveSelectFilter: PokemonMoveSelectFilter; private tmMoveId: Moves; + private showMovePp: boolean; private iconAnimHandler: PokemonIconAnimHandler; @@ -185,6 +186,7 @@ export default class PartyUiHandler extends MessageUiHandler { ? args[4] as PokemonMoveSelectFilter : PartyUiHandler.FilterAllMoves; this.tmMoveId = args.length > 5 && args[5] ? args[5] : Moves.NONE; + this.showMovePp = args.length > 6 && args[6]; this.partyContainer.setVisible(true); this.partyBg.setTexture(`party_bg${this.scene.currentBattle.double ? '_double' : ''}`); @@ -663,7 +665,14 @@ export default class PartyUiHandler extends MessageUiHandler { case PartyOption.MOVE_2: case PartyOption.MOVE_3: case PartyOption.MOVE_4: - optionName = pokemon.moveset[option - PartyOption.MOVE_1].getName(); + const move = pokemon.moveset[option - PartyOption.MOVE_1]; + if(this.showMovePp) { + const maxPP = move.getMovePp(); + const currPP = maxPP - move.ppUsed; + optionName = `${move.getName()} ${currPP}/${maxPP}`; + } else { + optionName = move.getName(); + } break; default: if (formChangeItemModifiers && option >= PartyOption.FORM_CHANGE_ITEM) { From 56b24c70b6c7b5ddc1c51b6bdaa20c01d7fa2810 Mon Sep 17 00:00:00 2001 From: Mistmemo <114654503+LeoDoby@users.noreply.github.com> Date: Wed, 1 May 2024 16:50:13 +0200 Subject: [PATCH 13/45] fix double battle iv scanner color (#379) * Add color for the IV scanner add a new color SUMMARY_GREEN in text.js, add the green color if the iv of the pokemon is better than the iv on the starter of that pokemon Co-authored-by: EmoUsedHM01 <131687820+emousedhm01@users.noreply.github.com> * fix battle-message-ui-handler.ts formatting * fix missing similicon battle-message-ui-handler.ts * modified so it take a boolean instead of doing lot of else if battle-message-ui-handler.ts * Fix iv scanner only doing color for the right pokemon in double fight --------- Co-authored-by: EmoUsedHM01 <131687820+emousedhm01@users.noreply.github.com> --- src/ui/battle-message-ui-handler.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ui/battle-message-ui-handler.ts b/src/ui/battle-message-ui-handler.ts index 7819017d896..5e2cb56518f 100644 --- a/src/ui/battle-message-ui-handler.ts +++ b/src/ui/battle-message-ui-handler.ts @@ -210,7 +210,7 @@ export default class BattleMessageUiHandler extends MessageUiHandler { } else shownStats = stats; for (let s of stats) - levelUpStatsValuesText += `${shownStats.indexOf(s) > -1 ? this.getIvDescriptor(ivs[s], s) : '???'}\n`; + levelUpStatsValuesText += `${shownStats.indexOf(s) > -1 ? this.getIvDescriptor(ivs[s], s, pokemonId) : '???'}\n`; this.levelUpStatsValuesContent.text = levelUpStatsValuesText; this.levelUpStatsIncrContent.setVisible(false); this.levelUpStatsContainer.setVisible(true); @@ -223,8 +223,8 @@ export default class BattleMessageUiHandler extends MessageUiHandler { }); } - getIvDescriptor(value: integer, typeIv: integer): string { - const starterSpecies = this.scene.getEnemyPokemon().species.getRootSpeciesId(true); + getIvDescriptor(value: integer, typeIv: integer, pokemonId: integer): string { + const starterSpecies = this.scene.getPokemonById(pokemonId).species.getRootSpeciesId(true); const starterIvs: number[] = this.scene.gameData.dexData[starterSpecies].ivs; const uiTheme = (this.scene as BattleScene).uiTheme; // Assuming uiTheme is accessible From c8583d6c69efdb45a0bc9c80646e5d0fdcb8919f Mon Sep 17 00:00:00 2001 From: Thomas David <66013753+Kiriox94@users.noreply.github.com> Date: Sat, 27 Apr 2024 11:30:23 +0200 Subject: [PATCH 14/45] Update manifest.webmanifest --- public/manifest.webmanifest | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/manifest.webmanifest b/public/manifest.webmanifest index e6eedd27e2f..c75c70a8d45 100644 --- a/public/manifest.webmanifest +++ b/public/manifest.webmanifest @@ -4,7 +4,8 @@ "description": "A Pokémon fangame heavily inspired by the roguelite genre. Battle endlessly while gathering stacking items, exploring many different biomes, and reaching Pokémon stats you never thought possible.", "scope": "/", "start_url": "/", - "display": "standalone", + "display": "fullscreen", + "orientation": "landscape", "background_color": "#8c8c8c", "theme_color": "#8c8c8c", "icons": [ From 68f33266070893aa42138868cea1d903a926bc09 Mon Sep 17 00:00:00 2001 From: Madmadness65 Date: Wed, 1 May 2024 12:21:22 -0500 Subject: [PATCH 15/45] Add Heal Block back to level up learnsets The move itself is still not functional yet, but will be valuable for Endless when it is. Also made Curse's flavor text accurate to the canon games. --- src/data/move.ts | 2 +- src/data/pokemon-level-moves.ts | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/data/move.ts b/src/data/move.ts index 60e07b8f513..6ece04c70c4 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -2615,7 +2615,7 @@ export class CurseAttr extends MoveEffectAttr { } let curseRecoilDamage = Math.floor(user.getMaxHp() / 2); user.damageAndUpdate(curseRecoilDamage, HitResult.OTHER, false, true, true); - user.scene.queueMessage(getPokemonMessage(user, ' cut its own HP!')); + user.scene.queueMessage(getPokemonMessage(user, ` cut its own HP\nand laid a curse on the ${target.name}!`)); target.addTag(BattlerTagType.CURSED, 0, move.id, user.id); return true; } else { diff --git a/src/data/pokemon-level-moves.ts b/src/data/pokemon-level-moves.ts index 07691b01eff..0b545d1bd63 100644 --- a/src/data/pokemon-level-moves.ts +++ b/src/data/pokemon-level-moves.ts @@ -4278,6 +4278,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 30, Moves.ANCIENT_POWER ], [ 40, Moves.LIFE_DEW ], [ 50, Moves.LEECH_SEED ], + [ 55, Moves.HEAL_BLOCK ], [ 60, Moves.RECOVER ], [ 70, Moves.FUTURE_SIGHT ], [ 80, Moves.HEALING_WISH ], @@ -4976,6 +4977,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 23, Moves.ABSORB ], [ 29, Moves.SHADOW_SNEAK ], [ 36, Moves.FURY_SWIPES ], + [ 41, Moves.HEAL_BLOCK ], [ 43, Moves.MIND_READER ], [ 50, Moves.SHADOW_BALL ], [ 57, Moves.SPITE ], @@ -5796,6 +5798,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 20, Moves.PSYSHOCK ], [ 25, Moves.COSMIC_POWER ], [ 30, Moves.PSYCHIC ], + [ 33, Moves.HEAL_BLOCK ], [ 35, Moves.STONE_EDGE ], [ 40, Moves.FUTURE_SIGHT ], [ 45, Moves.MAGIC_ROOM ], @@ -5814,6 +5817,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 20, Moves.ZEN_HEADBUTT ], [ 25, Moves.COSMIC_POWER ], [ 30, Moves.PSYCHIC ], + [ 33, Moves.HEAL_BLOCK ], [ 35, Moves.STONE_EDGE ], [ 40, Moves.SOLAR_BEAM ], [ 45, Moves.WONDER_ROOM ], @@ -5890,6 +5894,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 3, Moves.RAPID_SPIN ], [ 6, Moves.CONFUSION ], [ 9, Moves.ROCK_TOMB ], + [ 10, Moves.HEAL_BLOCK ], [ 12, Moves.POWER_TRICK ], [ 15, Moves.PSYBEAM ], [ 18, Moves.ANCIENT_POWER ], @@ -5911,6 +5916,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.MUD_SLAP ], [ 1, Moves.RAPID_SPIN ], [ 9, Moves.ROCK_TOMB ], + [ 10, Moves.HEAL_BLOCK ], [ 12, Moves.POWER_TRICK ], [ 15, Moves.PSYBEAM ], [ 18, Moves.ANCIENT_POWER ], @@ -6506,6 +6512,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.LATIOS]: [ [ 1, Moves.DRAGON_DANCE ], [ 1, Moves.STORED_POWER ], + [ 1, Moves.HEAL_BLOCK ], [ 5, Moves.HELPING_HAND ], [ 10, Moves.RECOVER ], [ 15, Moves.CONFUSION ], @@ -7364,6 +7371,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 36, Moves.IRON_DEFENSE ], [ 40, Moves.METAL_SOUND ], [ 44, Moves.FUTURE_SIGHT ], + [ 45, Moves.HEAL_BLOCK ], ], [Species.BRONZONG]: [ [ 0, Moves.BLOCK ], @@ -7382,6 +7390,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 38, Moves.IRON_DEFENSE ], [ 44, Moves.METAL_SOUND ], [ 50, Moves.FUTURE_SIGHT ], + [ 52, Moves.HEAL_BLOCK ], [ 56, Moves.RAIN_DANCE ], ], [Species.BONSLY]: [ @@ -9491,6 +9500,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.YAMASK]: [ [ 1, Moves.PROTECT ], [ 1, Moves.ASTONISH ], + [ 1, Moves.HEAL_BLOCK ], [ 4, Moves.HAZE ], [ 8, Moves.NIGHT_SHADE ], [ 12, Moves.DISABLE ], @@ -9513,6 +9523,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.PROTECT ], [ 1, Moves.SCARY_FACE ], [ 1, Moves.ASTONISH ], + [ 1, Moves.HEAL_BLOCK ], [ 12, Moves.DISABLE ], [ 16, Moves.WILL_O_WISP ], [ 20, Moves.CRAFTY_SHIELD ], @@ -9720,6 +9731,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 24, Moves.HYPNOSIS ], [ 28, Moves.FAKE_TEARS ], [ 33, Moves.PSYCH_UP ], + [ 34, Moves.HEAL_BLOCK ], [ 36, Moves.PSYCHIC ], [ 40, Moves.FLATTER ], [ 44, Moves.FUTURE_SIGHT ], @@ -9735,6 +9747,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 20, Moves.PSYSHOCK ], [ 24, Moves.HYPNOSIS ], [ 28, Moves.FAKE_TEARS ], + [ 34, Moves.HEAL_BLOCK ], [ 35, Moves.PSYCH_UP ], [ 46, Moves.FLATTER ], [ 52, Moves.FUTURE_SIGHT ], @@ -9750,6 +9763,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 20, Moves.PSYSHOCK ], [ 24, Moves.HYPNOSIS ], [ 28, Moves.FAKE_TEARS ], + [ 34, Moves.HEAL_BLOCK ], [ 35, Moves.PSYCH_UP ], [ 40, Moves.PSYCHIC ], [ 48, Moves.FLATTER ], @@ -9771,6 +9785,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 36, Moves.PSYCHIC ], [ 40, Moves.SKILL_SWAP ], [ 44, Moves.FUTURE_SIGHT ], + [ 46, Moves.HEAL_BLOCK ], [ 48, Moves.WONDER_ROOM ], ], [Species.DUOSION]: [ @@ -9787,6 +9802,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 35, Moves.PAIN_SPLIT ], [ 40, Moves.PSYCHIC ], [ 46, Moves.SKILL_SWAP ], + [ 50, Moves.HEAL_BLOCK ], [ 52, Moves.FUTURE_SIGHT ], [ 58, Moves.WONDER_ROOM ], ], @@ -9805,6 +9821,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 35, Moves.PAIN_SPLIT ], [ 40, Moves.PSYCHIC ], [ 48, Moves.SKILL_SWAP ], + [ 54, Moves.HEAL_BLOCK ], [ 56, Moves.FUTURE_SIGHT ], [ 64, Moves.WONDER_ROOM ], ], @@ -10209,6 +10226,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.GROWL ], [ 1, Moves.CONFUSION ], [ 6, Moves.IMPRISON ], + [ 8, Moves.HEAL_BLOCK ], [ 12, Moves.TELEPORT ], [ 18, Moves.PSYBEAM ], [ 24, Moves.GUARD_SPLIT ], @@ -10226,6 +10244,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.TELEPORT ], [ 1, Moves.IMPRISON ], [ 1, Moves.PSYCHIC_TERRAIN ], + [ 8, Moves.HEAL_BLOCK ], [ 18, Moves.PSYBEAM ], [ 24, Moves.GUARD_SPLIT ], [ 24, Moves.POWER_SPLIT ], @@ -10884,6 +10903,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 20, Moves.SHOCK_WAVE ], [ 25, Moves.AGILITY ], [ 30, Moves.CHARGE ], + [ 31, Moves.HEAL_BLOCK ], [ 35, Moves.VOLT_SWITCH ], [ 40, Moves.CRUNCH ], [ 45, Moves.DISCHARGE ], @@ -11972,6 +11992,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 40, Moves.PLAY_ROUGH ], [ 44, Moves.MAGIC_ROOM ], [ 48, Moves.FOUL_PLAY ], + [ 50, Moves.HEAL_BLOCK ], [ 52, Moves.LAST_RESORT ], ], [Species.PHANTUMP]: [ @@ -13045,6 +13066,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 45, Moves.IRON_HEAD ], [ 50, Moves.TAKE_DOWN ], [ 55, Moves.DOUBLE_EDGE ], + [ 60, Moves.HEAL_BLOCK ], ], [Species.SILVALLY]: [ [ 0, Moves.MULTI_ATTACK ], @@ -13059,6 +13081,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.ICE_FANG ], [ 1, Moves.FIRE_FANG ], [ 1, Moves.IRON_HEAD ], + [ 1, Moves.HEAL_BLOCK ], [ 15, Moves.DOUBLE_HIT ], [ 20, Moves.METAL_SOUND ], [ 25, Moves.CRUSH_CLAW ], From e6c31966d79e71746f0893f4354d6890ebb88b3c Mon Sep 17 00:00:00 2001 From: dielle000 <168655502+dielle000@users.noreply.github.com> Date: Wed, 1 May 2024 21:10:31 +0200 Subject: [PATCH 16/45] Change pokemon stats chart Stats are arranged like in the mainline games --- src/ui/stats-container.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ui/stats-container.ts b/src/ui/stats-container.ts index 0144658051f..b8d9c59a4d7 100644 --- a/src/ui/stats-container.ts +++ b/src/ui/stats-container.ts @@ -4,7 +4,8 @@ import { Stat, getStatName } from "../data/pokemon-stat"; import { TextStyle, addBBCodeTextObject, addTextObject, getTextColor } from "./text"; const ivChartSize = 24; -const ivChartStatCoordMultipliers = [ [ 0, 1 ], [ 0.825, 0.5 ], [ 0.825, -0.5 ], [ 0, -1 ], [ -0.825, -0.5 ], [ -0.825, 0.5 ] ]; +const ivChartStatCoordMultipliers = [ [ 0, -1 ], [ 0.825, -0.5 ], [ 0.825, 0.5 ], [ -0.825, -0.5 ], [ -0.825, 0.5 ], [ 0, 1 ] ]; +const ivChartStatIndexes = [0,1,2,5,4,3] // swap special attack and speed const defaultIvChartData = new Array(12).fill(null).map(() => 0); export class StatsContainer extends Phaser.GameObjects.Container { @@ -22,7 +23,7 @@ export class StatsContainer extends Phaser.GameObjects.Container { } setup() { - const ivChartBgData = new Array(6).fill(null).map((_, i: integer) => [ ivChartSize * ivChartStatCoordMultipliers[i][0], ivChartSize * ivChartStatCoordMultipliers[i][1] ] ).flat(); + const ivChartBgData = new Array(6).fill(null).map((_, i: integer) => [ ivChartSize * ivChartStatCoordMultipliers[ivChartStatIndexes[i]][0], ivChartSize * ivChartStatCoordMultipliers[ivChartStatIndexes[i]][1] ] ).flat(); const ivChartBg = this.scene.add.polygon(48, 44, ivChartBgData, 0xd8e0f0, 0.625); ivChartBg.setOrigin(0, 0); @@ -62,7 +63,7 @@ export class StatsContainer extends Phaser.GameObjects.Container { updateIvs(ivs: integer[], originalIvs?: integer[]): void { if (ivs) { - const ivChartData = new Array(6).fill(null).map((_, i) => [ (ivs[i] / 31) * ivChartSize * ivChartStatCoordMultipliers[i][0], (ivs[i] / 31) * ivChartSize * ivChartStatCoordMultipliers[i][1] ] ).flat(); + const ivChartData = new Array(6).fill(null).map((_, i) => [ (ivs[ivChartStatIndexes[i]] / 31) * ivChartSize * ivChartStatCoordMultipliers[ivChartStatIndexes[i]][0], (ivs[ivChartStatIndexes[i]] / 31) * ivChartSize * ivChartStatCoordMultipliers[ivChartStatIndexes[i]][1] ] ).flat(); const lastIvChartData = this.statsIvsCache || defaultIvChartData; this.statsIvsCache = ivChartData.slice(0); From 10169382d95b8249dbb8023d1051646d890debd1 Mon Sep 17 00:00:00 2001 From: InfernoVulpix <66154242+InfernoVulpix@users.noreply.github.com> Date: Wed, 1 May 2024 16:14:19 -0400 Subject: [PATCH 17/45] Implemented Synchronoise's effect (#221) * Implemented Synchronoise's effect Tested with Soak, Forest's Curse, and a variety of attacker and defender types. * Fixed Synchronoise double battle functionality It now does zero damage only to targets who do not share any types with it, while correctly damaging any who do. It also fails entirely if the user is UNKNOWN type. --- src/data/move.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/data/move.ts b/src/data/move.ts index 6ece04c70c4..78c47e1ea66 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -3706,6 +3706,19 @@ export class FirstMoveCondition extends MoveCondition { } } +export class hitsSameTypeAttr extends VariableMoveTypeMultiplierAttr { + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + const multiplier = args[0] as Utils.NumberHolder; + if (!user.getTypes().some(type => target.getTypes().includes(type))){ + multiplier.value = 0; + return true; + } + return false; + } +} + +const unknownTypeCondition: MoveConditionFunc = (user, target, move) => !user.getTypes().includes(Type.UNKNOWN); + export type MoveTargetSet = { targets: BattlerIndex[]; multiple: boolean; @@ -5087,7 +5100,8 @@ export function initMoves() { .condition(failOnMaxCondition), new AttackMove(Moves.SYNCHRONOISE, Type.PSYCHIC, MoveCategory.SPECIAL, 120, 100, 10, -1, 0, 5) .target(MoveTarget.ALL_NEAR_OTHERS) - .partial(), + .condition(unknownTypeCondition) + .attr(hitsSameTypeAttr), new AttackMove(Moves.ELECTRO_BALL, Type.ELECTRIC, MoveCategory.SPECIAL, -1, 100, 10, -1, 0, 5) .attr(BattleStatRatioPowerAttr, Stat.SPD) .ballBombMove(), From d6ca09e4317fa60b15abcd4b7ede5a71d3c9ebea Mon Sep 17 00:00:00 2001 From: Xavion3 Date: Thu, 2 May 2024 06:36:47 +1000 Subject: [PATCH 18/45] Implement Belch --- src/data/berry.ts | 12 ++++++++++++ src/data/move.ts | 2 +- src/field/pokemon.ts | 2 ++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/data/berry.ts b/src/data/berry.ts index b28772373b1..1228bb54904 100644 --- a/src/data/berry.ts +++ b/src/data/berry.ts @@ -99,6 +99,8 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc { case BerryType.SITRUS: case BerryType.ENIGMA: return (pokemon: Pokemon) => { + if (pokemon.battleData) + pokemon.battleData.berriesEaten.push(berryType); const hpHealed = new Utils.NumberHolder(Math.floor(pokemon.getMaxHp() / 4)); applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, hpHealed); pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.getBattlerIndex(), @@ -106,6 +108,8 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc { }; case BerryType.LUM: return (pokemon: Pokemon) => { + if (pokemon.battleData) + pokemon.battleData.berriesEaten.push(berryType); if (pokemon.status) { pokemon.scene.queueMessage(getPokemonMessage(pokemon, getStatusEffectHealText(pokemon.status.effect))); pokemon.resetStatus(); @@ -119,6 +123,8 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc { case BerryType.APICOT: case BerryType.SALAC: return (pokemon: Pokemon) => { + if (pokemon.battleData) + pokemon.battleData.berriesEaten.push(berryType); const battleStat = (berryType - BerryType.LIECHI) as BattleStat; const statLevels = new Utils.NumberHolder(1); applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, statLevels); @@ -126,16 +132,22 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc { }; case BerryType.LANSAT: return (pokemon: Pokemon) => { + if (pokemon.battleData) + pokemon.battleData.berriesEaten.push(berryType); pokemon.addTag(BattlerTagType.CRIT_BOOST); }; case BerryType.STARF: return (pokemon: Pokemon) => { + if (pokemon.battleData) + pokemon.battleData.berriesEaten.push(berryType); const statLevels = new Utils.NumberHolder(2); applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, statLevels); pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ BattleStat.RAND ], statLevels.value)); }; case BerryType.LEPPA: return (pokemon: Pokemon) => { + if (pokemon.battleData) + pokemon.battleData.berriesEaten.push(berryType); const ppRestoreMove = pokemon.getMoveset().find(m => !m.getPpRatio()); ppRestoreMove.ppUsed = Math.max(ppRestoreMove.ppUsed - 10, 0); pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` restored PP to its move ${ppRestoreMove.getName()}\nusing its ${getBerryName(berryType)}!`)); diff --git a/src/data/move.ts b/src/data/move.ts index 78c47e1ea66..8b94756d04b 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -5301,7 +5301,7 @@ export function initMoves() { new StatusMove(Moves.MAT_BLOCK, Type.FIGHTING, -1, 10, -1, 0, 6) .unimplemented(), new AttackMove(Moves.BELCH, Type.POISON, MoveCategory.SPECIAL, 120, 90, 10, -1, 0, 6) - .partial(), + .condition((user, target, move) => user.battleData.berriesEaten.length > 0), new StatusMove(Moves.ROTOTILLER, Type.GROUND, -1, 10, 100, 0, 6) .target(MoveTarget.ALL) .unimplemented(), diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 55036e1906d..ed248f7cc80 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -43,6 +43,7 @@ import { Nature, getNatureStatMultiplier } from '../data/nature'; import { SpeciesFormChange, SpeciesFormChangeActiveTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangeStatusEffectTrigger } from '../data/pokemon-forms'; import { TerrainType } from '../data/terrain'; import { TrainerSlot } from '../data/trainer-config'; +import { BerryType } from '../data/berry'; import { ABILITY_OVERRIDE, MOVE_OVERRIDE, OPP_ABILITY_OVERRIDE, OPP_MOVE_OVERRIDE, OPP_SHINY_OVERRIDE, OPP_VARIANT_OVERRIDE } from '../overrides'; export enum FieldPosition { @@ -2993,6 +2994,7 @@ export class PokemonSummonData { export class PokemonBattleData { public hitCount: integer = 0; public endured: boolean = false; + public berriesEaten: BerryType[] = []; } export class PokemonBattleSummonData { From 5a6ea40dae30a0fe5364acd4054389d34c479095 Mon Sep 17 00:00:00 2001 From: Xavion3 Date: Thu, 2 May 2024 07:09:54 +1000 Subject: [PATCH 19/45] Implement Acrobatics Currently scales from 0-5 items --- src/data/move.ts | 2 +- src/field/pokemon.ts | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/data/move.ts b/src/data/move.ts index 8b94756d04b..a13c1ac8861 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -5171,7 +5171,7 @@ export function initMoves() { new StatusMove(Moves.QUASH, Type.DARK, 100, 15, -1, 0, 5) .unimplemented(), new AttackMove(Moves.ACROBATICS, Type.FLYING, MoveCategory.PHYSICAL, 55, 100, 15, -1, 0, 5) - .partial(), + .attr(MovePowerMultiplierAttr, (user, target, move) => Math.max(1, 2 - 0.2 * user.getHeldItems().reduce((v, m) => v + m.stackCount, 0))), new StatusMove(Moves.REFLECT_TYPE, Type.NORMAL, -1, 15, -1, 0, 5) .attr(CopyTypeAttr), new AttackMove(Moves.RETALIATE, Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 5, -1, 0, 5) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index ed248f7cc80..82915ce41bc 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -456,6 +456,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return 1; } + getHeldItems(): PokemonHeldItemModifier[] { + if (!this.scene) + return []; + return this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier && (m as PokemonHeldItemModifier).pokemonId === this.id, this.isPlayer()) as PokemonHeldItemModifier[]; + } + updateScale(): void { this.setScale(this.getSpriteScale()); } From 0f153d39b1131de54805822be32c790c1363b013 Mon Sep 17 00:00:00 2001 From: Tempoanon <163687446+TempsRay@users.noreply.github.com> Date: Wed, 1 May 2024 17:47:32 -0400 Subject: [PATCH 20/45] Fix effect spore immunities, tera blast TM distribution, and IVs shown on catch (#388) * Fix effect spore, tera blast distribution, and IVs shown on catch * Forgot to add tms * Unown does not learn any TMs * Fix some tera blast learns * delelele whooooop --- src/data/ability.ts | 15 +- src/data/tms.ts | 435 ++++++++++++++++++++++++++++++++++++++++++-- src/phases.ts | 2 +- 3 files changed, 433 insertions(+), 19 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 2ac7d6be1ac..35f6da685eb 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -679,6 +679,19 @@ export class PostDefendContactApplyStatusEffectAbAttr extends PostDefendAbAttr { } } +export class EffectSporeAbAttr extends PostDefendContactApplyStatusEffectAbAttr { + constructor() { + super(10, StatusEffect.POISON, StatusEffect.PARALYSIS, StatusEffect.SLEEP); + } + + applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { + if (attacker.hasAbility(Abilities.OVERCOAT) || attacker.isOfType(Type.GRASS)) { + return false; + } + return super.applyPostDefend(pokemon, passive, attacker, move, hitResult, args); + } +} + export class PostDefendContactApplyTagChanceAbAttr extends PostDefendAbAttr { private chance: integer; private tagType: BattlerTagType; @@ -2572,7 +2585,7 @@ export function initAbilities() { .attr(TypeImmunityAbAttr, Type.GROUND, (pokemon: Pokemon) => !pokemon.getTag(BattlerTagType.IGNORE_FLYING) && !pokemon.scene.arena.getTag(ArenaTagType.GRAVITY) && !pokemon.getTag(BattlerTagType.GROUNDED)) .ignorable(), new Ability(Abilities.EFFECT_SPORE, 3) - .attr(PostDefendContactApplyStatusEffectAbAttr, 10, StatusEffect.POISON, StatusEffect.PARALYSIS, StatusEffect.SLEEP), + .attr(EffectSporeAbAttr), new Ability(Abilities.SYNCHRONIZE, 3) .attr(SyncEncounterNatureAbAttr) .unimplemented(), diff --git a/src/data/tms.ts b/src/data/tms.ts index 71264d16c62..332eb2234b1 100644 --- a/src/data/tms.ts +++ b/src/data/tms.ts @@ -29550,7 +29550,6 @@ export const tmSpecies: TmSpecies = { Species.MURKROW, Species.SLOWKING, Species.MISDREAVUS, - Species.UNOWN, Species.GIRAFARIG, Species.PINECO, Species.FORRETRESS, @@ -62012,21 +62011,49 @@ export const tmSpecies: TmSpecies = { Species.ALOLA_MAROWAK, ], [Moves.TERA_BLAST]: [ + Species.BULBASAUR, + Species.IVYSAUR, + Species.VENUSAUR, Species.CHARMANDER, Species.CHARMELEON, Species.CHARIZARD, + Species.SQUIRTLE, + Species.WARTORTLE, + Species.BLASTOISE, + Species.BUTTERFREE, + Species.BEEDRILL, + Species.PIDGEY, + Species.PIDGEOTTO, + Species.PIDGEOT, + Species.RATTATA, + Species.RATICATE, + Species.SPEAROW, + Species.FEAROW, Species.EKANS, Species.ARBOK, Species.PIKACHU, Species.RAICHU, Species.SANDSHREW, Species.SANDSLASH, + Species.NIDORAN_F, + Species.NIDORINA, + Species.NIDOQUEEN, + Species.NIDORAN_M, + Species.NIDORINO, + Species.NIDOKING, Species.CLEFAIRY, Species.CLEFABLE, Species.VULPIX, Species.NINETALES, Species.JIGGLYPUFF, Species.WIGGLYTUFF, + Species.ZUBAT, + Species.GOLBAT, + Species.ODDISH, + Species.GLOOM, + Species.VILEPLUME, + Species.PARAS, + Species.PARASECT, Species.VENONAT, Species.VENOMOTH, Species.DIGLETT, @@ -62042,16 +62069,31 @@ export const tmSpecies: TmSpecies = { Species.POLIWAG, Species.POLIWHIRL, Species.POLIWRATH, + Species.ABRA, + Species.KADABRA, + Species.ALAKAZAM, + Species.MACHOP, + Species.MACHOKE, + Species.MACHAMP, Species.BELLSPROUT, Species.WEEPINBELL, Species.VICTREEBEL, + Species.TENTACOOL, + Species.TENTACRUEL, Species.GEODUDE, Species.GRAVELER, Species.GOLEM, + Species.PONYTA, + Species.RAPIDASH, Species.SLOWPOKE, Species.SLOWBRO, Species.MAGNEMITE, Species.MAGNETON, + Species.FARFETCHD, + Species.DODUO, + Species.DODRIO, + Species.SEEL, + Species.DEWGONG, Species.GRIMER, Species.MUK, Species.SHELLDER, @@ -62059,20 +62101,52 @@ export const tmSpecies: TmSpecies = { Species.GASTLY, Species.HAUNTER, Species.GENGAR, + Species.ONIX, Species.DROWZEE, Species.HYPNO, + Species.KRABBY, + Species.KINGLER, Species.VOLTORB, Species.ELECTRODE, + Species.EXEGGCUTE, + Species.EXEGGUTOR, + Species.CUBONE, + Species.MAROWAK, + Species.HITMONLEE, + Species.HITMONCHAN, + Species.LICKITUNG, Species.KOFFING, Species.WEEZING, + Species.RHYHORN, + Species.RHYDON, Species.CHANSEY, + Species.TANGELA, + Species.KANGASKHAN, + Species.HORSEA, + Species.SEADRA, + Species.GOLDEEN, + Species.SEAKING, + Species.STARYU, + Species.STARMIE, + Species.MR_MIME, Species.SCYTHER, + Species.JYNX, + Species.ELECTABUZZ, + Species.MAGMAR, + Species.PINSIR, Species.TAUROS, Species.GYARADOS, + Species.LAPRAS, Species.EEVEE, Species.VAPOREON, Species.JOLTEON, Species.FLAREON, + Species.PORYGON, + Species.OMANYTE, + Species.OMASTAR, + Species.KABUTO, + Species.KABUTOPS, + Species.AERODACTYL, Species.SNORLAX, Species.ARTICUNO, Species.ZAPDOS, @@ -62082,21 +62156,37 @@ export const tmSpecies: TmSpecies = { Species.DRAGONITE, Species.MEWTWO, Species.MEW, + Species.CHIKORITA, + Species.BAYLEEF, + Species.MEGANIUM, Species.CYNDAQUIL, Species.QUILAVA, Species.TYPHLOSION, + Species.TOTODILE, + Species.CROCONAW, + Species.FERALIGATR, Species.SENTRET, Species.FURRET, Species.HOOTHOOT, Species.NOCTOWL, + Species.LEDYBA, + Species.LEDIAN, Species.SPINARAK, Species.ARIADOS, + Species.CROBAT, + Species.CHINCHOU, + Species.LANTURN, Species.PICHU, Species.CLEFFA, Species.IGGLYBUFF, + Species.TOGEPI, + Species.TOGETIC, + Species.NATU, + Species.XATU, Species.MAREEP, Species.FLAAFFY, Species.AMPHAROS, + Species.BELLOSSOM, Species.MARILL, Species.AZUMARILL, Species.SUDOWOODO, @@ -62120,8 +62210,12 @@ export const tmSpecies: TmSpecies = { Species.FORRETRESS, Species.DUNSPARCE, Species.GLIGAR, + Species.STEELIX, + Species.SNUBBULL, + Species.GRANBULL, Species.QWILFISH, Species.SCIZOR, + Species.SHUCKLE, Species.HERACROSS, Species.SNEASEL, Species.TEDDIURSA, @@ -62130,24 +62224,58 @@ export const tmSpecies: TmSpecies = { Species.MAGCARGO, Species.SWINUB, Species.PILOSWINE, + Species.CORSOLA, + Species.REMORAID, + Species.OCTILLERY, Species.DELIBIRD, + Species.MANTINE, + Species.SKARMORY, Species.HOUNDOUR, Species.HOUNDOOM, + Species.KINGDRA, Species.PHANPY, Species.DONPHAN, + Species.PORYGON2, Species.STANTLER, + Species.TYROGUE, + Species.HITMONTOP, + Species.SMOOCHUM, + Species.ELEKID, + Species.MAGBY, + Species.MILTANK, Species.BLISSEY, + Species.RAIKOU, + Species.ENTEI, + Species.SUICUNE, Species.LARVITAR, Species.PUPITAR, Species.TYRANITAR, + Species.LUGIA, + Species.HO_OH, + Species.CELEBI, + Species.TREECKO, + Species.GROVYLE, + Species.SCEPTILE, + Species.TORCHIC, + Species.COMBUSKEN, + Species.BLAZIKEN, + Species.MUDKIP, + Species.MARSHTOMP, + Species.SWAMPERT, Species.POOCHYENA, Species.MIGHTYENA, + Species.ZIGZAGOON, + Species.LINOONE, + Species.BEAUTIFLY, + Species.DUSTOX, Species.LOTAD, Species.LOMBRE, Species.LUDICOLO, Species.SEEDOT, Species.NUZLEAF, Species.SHIFTRY, + Species.TAILLOW, + Species.SWELLOW, Species.WINGULL, Species.PELIPPER, Species.RALTS, @@ -62160,49 +62288,101 @@ export const tmSpecies: TmSpecies = { Species.SLAKOTH, Species.VIGOROTH, Species.SLAKING, + Species.NINCADA, + Species.NINJASK, + Species.SHEDINJA, + Species.WHISMUR, + Species.LOUDRED, + Species.EXPLOUD, Species.MAKUHITA, Species.HARIYAMA, Species.AZURILL, Species.NOSEPASS, + Species.SKITTY, + Species.DELCATTY, Species.SABLEYE, + Species.MAWILE, + Species.ARON, + Species.LAIRON, + Species.AGGRON, Species.MEDITITE, Species.MEDICHAM, + Species.ELECTRIKE, + Species.MANECTRIC, + Species.PLUSLE, + Species.MINUN, Species.VOLBEAT, Species.ILLUMISE, + Species.ROSELIA, Species.GULPIN, Species.SWALOT, + Species.CARVANHA, + Species.SHARPEDO, + Species.WAILMER, + Species.WAILORD, Species.NUMEL, Species.CAMERUPT, Species.TORKOAL, Species.SPOINK, Species.GRUMPIG, + Species.SPINDA, + Species.TRAPINCH, + Species.VIBRAVA, + Species.FLYGON, Species.CACNEA, Species.CACTURNE, Species.SWABLU, Species.ALTARIA, Species.ZANGOOSE, Species.SEVIPER, + Species.LUNATONE, + Species.SOLROCK, Species.BARBOACH, Species.WHISCASH, Species.CORPHISH, Species.CRAWDAUNT, + Species.BALTOY, + Species.CLAYDOL, + Species.LILEEP, + Species.CRADILY, + Species.ANORITH, + Species.ARMALDO, Species.FEEBAS, Species.MILOTIC, + Species.CASTFORM, + Species.KECLEON, Species.SHUPPET, Species.BANETTE, Species.DUSKULL, Species.DUSCLOPS, Species.TROPIUS, Species.CHIMECHO, + Species.ABSOL, Species.SNORUNT, Species.GLALIE, + Species.SPHEAL, + Species.SEALEO, + Species.WALREIN, + Species.CLAMPERL, + Species.HUNTAIL, + Species.GOREBYSS, + Species.RELICANTH, Species.LUVDISC, Species.BAGON, Species.SHELGON, Species.SALAMENCE, + Species.METANG, + Species.METAGROSS, + Species.REGIROCK, + Species.REGICE, + Species.REGISTEEL, + Species.LATIAS, + Species.LATIOS, Species.KYOGRE, Species.GROUDON, Species.RAYQUAZA, + Species.JIRACHI, + Species.DEOXYS, Species.TURTWIG, Species.GROTLE, Species.TORTERRA, @@ -62215,30 +62395,49 @@ export const tmSpecies: TmSpecies = { Species.STARLY, Species.STARAVIA, Species.STARAPTOR, + Species.BIDOOF, + Species.BIBAREL, Species.KRICKETOT, Species.KRICKETUNE, Species.SHINX, Species.LUXIO, Species.LUXRAY, + Species.BUDEW, + Species.ROSERADE, + Species.CRANIDOS, + Species.RAMPARDOS, + Species.SHIELDON, + Species.BASTIODON, + Species.BURMY, + Species.WORMADAM, + Species.MOTHIM, Species.COMBEE, Species.VESPIQUEN, Species.PACHIRISU, Species.BUIZEL, Species.FLOATZEL, + Species.CHERUBI, + Species.CHERRIM, Species.SHELLOS, Species.GASTRODON, Species.AMBIPOM, Species.DRIFLOON, Species.DRIFBLIM, + Species.BUNEARY, + Species.LOPUNNY, Species.MISMAGIUS, Species.HONCHKROW, + Species.GLAMEOW, + Species.PURUGLY, Species.CHINGLING, Species.STUNKY, Species.SKUNTANK, Species.BRONZOR, Species.BRONZONG, Species.BONSLY, + Species.MIME_JR, Species.HAPPINY, + Species.CHATOT, Species.SPIRITOMB, Species.GIBLE, Species.GABITE, @@ -62248,19 +62447,30 @@ export const tmSpecies: TmSpecies = { Species.LUCARIO, Species.HIPPOPOTAS, Species.HIPPOWDON, + Species.SKORUPI, + Species.DRAPION, Species.CROAGUNK, Species.TOXICROAK, + Species.CARNIVINE, Species.FINNEON, Species.LUMINEON, + Species.MANTYKE, Species.SNOVER, Species.ABOMASNOW, Species.WEAVILE, Species.MAGNEZONE, + Species.LICKILICKY, + Species.RHYPERIOR, + Species.TANGROWTH, + Species.ELECTIVIRE, + Species.MAGMORTAR, + Species.TOGEKISS, Species.YANMEGA, Species.LEAFEON, Species.GLACEON, Species.GLISCOR, Species.MAMOSWINE, + Species.PORYGON_Z, Species.GALLADE, Species.PROBOPASS, Species.DUSKNOIR, @@ -62272,39 +62482,127 @@ export const tmSpecies: TmSpecies = { Species.DIALGA, Species.PALKIA, Species.HEATRAN, + Species.REGIGIGAS, Species.GIRATINA, Species.CRESSELIA, + Species.PHIONE, + Species.MANAPHY, + Species.DARKRAI, + Species.SHAYMIN, Species.ARCEUS, + Species.VICTINI, + Species.SNIVY, + Species.SERVINE, + Species.SERPERIOR, + Species.TEPIG, + Species.PIGNITE, + Species.EMBOAR, Species.OSHAWOTT, Species.DEWOTT, Species.SAMUROTT, + Species.PATRAT, + Species.WATCHOG, + Species.LILLIPUP, + Species.HERDIER, + Species.STOUTLAND, + Species.PURRLOIN, + Species.LIEPARD, + Species.PANSAGE, + Species.SIMISAGE, + Species.PANSEAR, + Species.SIMISEAR, + Species.PANPOUR, + Species.SIMIPOUR, + Species.MUNNA, + Species.MUSHARNA, + Species.PIDOVE, + Species.TRANQUILL, + Species.UNFEZANT, + Species.BLITZLE, + Species.ZEBSTRIKA, + Species.ROGGENROLA, + Species.BOLDORE, + Species.GIGALITH, + Species.WOOBAT, + Species.SWOOBAT, + Species.DRILBUR, + Species.EXCADRILL, + Species.AUDINO, Species.TIMBURR, Species.GURDURR, Species.CONKELDURR, + Species.TYMPOLE, + Species.PALPITOAD, + Species.SEISMITOAD, + Species.THROH, + Species.SAWK, Species.SEWADDLE, Species.SWADLOON, Species.LEAVANNY, + Species.VENIPEDE, + Species.WHIRLIPEDE, + Species.SCOLIPEDE, + Species.COTTONEE, + Species.WHIMSICOTT, Species.PETILIL, Species.LILLIGANT, Species.BASCULIN, Species.SANDILE, Species.KROKOROK, Species.KROOKODILE, + Species.DARUMAKA, + Species.DARMANITAN, + Species.MARACTUS, + Species.DWEBBLE, + Species.CRUSTLE, + Species.SCRAGGY, + Species.SCRAFTY, + Species.SIGILYPH, + Species.YAMASK, + Species.COFAGRIGUS, + Species.TIRTOUGA, + Species.CARRACOSTA, + Species.ARCHEN, + Species.ARCHEOPS, + Species.TRUBBISH, + Species.GARBODOR, Species.ZORUA, Species.ZOROARK, + Species.MINCCINO, + Species.CINCCINO, Species.GOTHITA, Species.GOTHORITA, Species.GOTHITELLE, + Species.SOLOSIS, + Species.DUOSION, + Species.REUNICLUS, Species.DUCKLETT, Species.SWANNA, + Species.VANILLITE, + Species.VANILLISH, + Species.VANILLUXE, Species.DEERLING, Species.SAWSBUCK, + Species.EMOLGA, + Species.KARRABLAST, + Species.ESCAVALIER, Species.FOONGUS, Species.AMOONGUSS, + Species.FRILLISH, + Species.JELLICENT, Species.ALOMOMOLA, + Species.JOLTIK, + Species.GALVANTULA, + Species.FERROSEED, + Species.FERROTHORN, + Species.KLINK, + Species.KLANG, + Species.KLINKLANG, Species.TYNAMO, Species.EELEKTRIK, Species.EELEKTROSS, + Species.ELGYEM, + Species.BEHEEYEM, Species.LITWICK, Species.LAMPENT, Species.CHANDELURE, @@ -62314,23 +62612,40 @@ export const tmSpecies: TmSpecies = { Species.CUBCHOO, Species.BEARTIC, Species.CRYOGONAL, + Species.SHELMET, + Species.ACCELGOR, + Species.STUNFISK, Species.MIENFOO, Species.MIENSHAO, + Species.DRUDDIGON, + Species.GOLETT, + Species.GOLURK, Species.PAWNIARD, Species.BISHARP, + Species.BOUFFALANT, Species.RUFFLET, Species.BRAVIARY, Species.VULLABY, Species.MANDIBUZZ, + Species.HEATMOR, + Species.DURANT, Species.DEINO, Species.ZWEILOUS, Species.HYDREIGON, Species.LARVESTA, Species.VOLCARONA, + Species.COBALION, + Species.TERRAKION, + Species.VIRIZION, Species.TORNADUS, Species.THUNDURUS, + Species.RESHIRAM, + Species.ZEKROM, Species.LANDORUS, + Species.KYUREM, + Species.KELDEO, Species.MELOETTA, + Species.GENESECT, Species.CHESPIN, Species.QUILLADIN, Species.CHESNAUGHT, @@ -62345,6 +62660,8 @@ export const tmSpecies: TmSpecies = { 'battle-bond', 'ash', ], + Species.BUNNELBY, + Species.DIGGERSBY, Species.FLETCHLING, Species.FLETCHINDER, Species.TALONFLAME, @@ -62354,14 +62671,43 @@ export const tmSpecies: TmSpecies = { Species.LITLEO, Species.PYROAR, Species.FLABEBE, - Species.FLOETTE, + [ + Species.FLOETTE, + 'red', + 'yellow', + 'orange', + 'blue', + 'white', + ], Species.FLORGES, Species.SKIDDO, Species.GOGOAT, + Species.PANCHAM, + Species.PANGORO, + Species.FURFROU, + Species.ESPURR, + Species.MEOWSTIC, + Species.HONEDGE, + Species.DOUBLADE, + Species.AEGISLASH, + Species.SPRITZEE, + Species.AROMATISSE, + Species.SWIRLIX, + Species.SLURPUFF, + Species.INKAY, + Species.MALAMAR, + Species.BINACLE, + Species.BARBARACLE, Species.SKRELP, Species.DRAGALGE, Species.CLAUNCHER, Species.CLAWITZER, + Species.HELIOPTILE, + Species.HELIOLISK, + Species.TYRUNT, + Species.TYRANTRUM, + Species.AMAURA, + Species.AURORUS, Species.SYLVEON, Species.HAWLUCHA, Species.DEDENNE, @@ -62372,16 +62718,30 @@ export const tmSpecies: TmSpecies = { Species.KLEFKI, Species.PHANTUMP, Species.TREVENANT, + Species.PUMPKABOO, + Species.GOURGEIST, Species.BERGMITE, Species.AVALUGG, Species.NOIBAT, Species.NOIVERN, + Species.XERNEAS, + Species.YVELTAL, + Species.ZYGARDE, Species.DIANCIE, Species.HOOPA, Species.VOLCANION, Species.ROWLET, Species.DARTRIX, Species.DECIDUEYE, + Species.LITTEN, + Species.TORRACAT, + Species.INCINEROAR, + Species.POPPLIO, + Species.BRIONNE, + Species.PRIMARINA, + Species.PIKIPEK, + Species.TRUMBEAK, + Species.TOUCANNON, Species.YUNGOOS, Species.GUMSHOOS, Species.GRUBBIN, @@ -62394,28 +62754,84 @@ export const tmSpecies: TmSpecies = { Species.RIBOMBEE, Species.ROCKRUFF, Species.LYCANROC, + Species.WISHIWASHI, Species.MAREANIE, Species.TOXAPEX, Species.MUDBRAY, Species.MUDSDALE, + Species.DEWPIDER, + Species.ARAQUANID, Species.FOMANTIS, Species.LURANTIS, + Species.MORELULL, + Species.SHIINOTIC, Species.SALANDIT, Species.SALAZZLE, + Species.STUFFUL, + Species.BEWEAR, Species.BOUNSWEET, Species.STEENEE, Species.TSAREENA, + Species.COMFEY, Species.ORANGURU, Species.PASSIMIAN, + Species.WIMPOD, + Species.GOLISOPOD, Species.SANDYGAST, Species.PALOSSAND, + Species.TYPE_NULL, + Species.SILVALLY, + Species.MINIOR, Species.KOMALA, + Species.TURTONATOR, + Species.TOGEDEMARU, Species.MIMIKYU, Species.BRUXISH, + Species.DRAMPA, + Species.DHELMISE, Species.JANGMO_O, Species.HAKAMO_O, Species.KOMMO_O, + Species.TAPU_KOKO, + Species.TAPU_LELE, + Species.TAPU_BULU, + Species.TAPU_FINI, + Species.SOLGALEO, + Species.LUNALA, + Species.NIHILEGO, + Species.BUZZWOLE, + Species.PHEROMOSA, + Species.XURKITREE, + Species.CELESTEELA, + Species.KARTANA, + Species.GUZZLORD, + Species.NECROZMA, Species.MAGEARNA, + Species.MARSHADOW, + Species.POIPOLE, + Species.NAGANADEL, + Species.STAKATAKA, + Species.BLACEPHALON, + Species.ZERAORA, + Species.ALOLA_RATTATA, + Species.ALOLA_RATICATE, + Species.ALOLA_RAICHU, + Species.ALOLA_SANDSHREW, + Species.ALOLA_SANDSLASH, + Species.ALOLA_VULPIX, + Species.ALOLA_NINETALES, + Species.ALOLA_DIGLETT, + Species.ALOLA_DUGTRIO, + Species.ALOLA_MEOWTH, + Species.ALOLA_PERSIAN, + Species.ALOLA_GEODUDE, + Species.ALOLA_GRAVELER, + Species.ALOLA_GOLEM, + Species.ALOLA_GRIMER, + Species.ALOLA_MUK, + Species.ALOLA_EXEGGUTOR, + Species.ALOLA_MAROWAK, + Species.ETERNAL_FLOETTE, Species.GROOKEY, Species.THWACKEY, Species.RILLABOOM, @@ -62596,21 +63012,6 @@ export const tmSpecies: TmSpecies = { Species.MUNKIDORI, Species.FEZANDIPITI, Species.OGERPON, - Species.ALOLA_RAICHU, - Species.ALOLA_SANDSHREW, - Species.ALOLA_SANDSLASH, - Species.ALOLA_VULPIX, - Species.ALOLA_NINETALES, - Species.ALOLA_DIGLETT, - Species.ALOLA_DUGTRIO, - Species.ALOLA_MEOWTH, - Species.ALOLA_PERSIAN, - Species.ALOLA_GEODUDE, - Species.ALOLA_GRAVELER, - Species.ALOLA_GOLEM, - Species.ALOLA_GRIMER, - Species.ALOLA_MUK, - Species.ETERNAL_FLOETTE, Species.GALAR_MEOWTH, Species.GALAR_SLOWPOKE, Species.GALAR_SLOWBRO, diff --git a/src/phases.ts b/src/phases.ts index ad2a7537de7..2e0b8425567 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -4095,7 +4095,7 @@ export class AttemptCapturePhase extends PokemonPhase { this.scene.pokemonInfoContainer.show(pokemon, true); - this.scene.gameData.updateSpeciesDexIvs(pokemon.species.speciesId, pokemon.ivs); + this.scene.gameData.updateSpeciesDexIvs(pokemon.species.getRootSpeciesId(true), pokemon.ivs); this.scene.ui.showText(i18next.t('menu:pokemonCaught', { pokemonName: pokemon.name }), null, () => { const end = () => { From 7a418109c3063d45cd0f334ff1ef61dc87f339c6 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Wed, 1 May 2024 18:17:12 -0400 Subject: [PATCH 21/45] Fix not checking move conditions for AI --- src/data/ability.ts | 6 +++--- src/data/move.ts | 24 +++++++++++++++--------- src/field/pokemon.ts | 2 +- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 35f6da685eb..7c350f025be 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -919,8 +919,8 @@ export class MovePowerBoostAbAttr extends VariableMovePowerAbAttr { private condition: PokemonAttackCondition; private powerMultiplier: number; - constructor(condition: PokemonAttackCondition, powerMultiplier: number) { - super(true); + constructor(condition: PokemonAttackCondition, powerMultiplier: number, showAbility: boolean = true) { + super(showAbility); this.condition = condition; this.powerMultiplier = powerMultiplier; } @@ -2725,7 +2725,7 @@ export function initAbilities() { .attr(TypeImmunityStatChangeAbAttr, Type.ELECTRIC, BattleStat.SPD, 1) .ignorable(), new Ability(Abilities.RIVALRY, 4) - .attr(MovePowerBoostAbAttr, (user, target, move) => user.gender !== Gender.GENDERLESS && target.gender !== Gender.GENDERLESS && user.gender === target.gender, 1.25) + .attr(MovePowerBoostAbAttr, (user, target, move) => user.gender !== Gender.GENDERLESS && target.gender !== Gender.GENDERLESS && user.gender === target.gender, 1.25, true) .attr(MovePowerBoostAbAttr, (user, target, move) => user.gender !== Gender.GENDERLESS && target.gender !== Gender.GENDERLESS && user.gender !== target.gender, 0.75), new Ability(Abilities.STEADFAST, 4) .attr(FlinchStatChangeAbAttr, BattleStat.SPD, 1), diff --git a/src/data/move.ts b/src/data/move.ts index a13c1ac8861..d6367794a35 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -3645,6 +3645,20 @@ export class MoneyAttr extends MoveEffectAttr { } } +export class LastResortAttr extends MoveAttr { + getCondition(): MoveConditionFunc { + return (user: Pokemon, target: Pokemon, move: Move) => { + const uniqueUsedMoveIds = new Set(); + const movesetMoveIds = user.getMoveset().map(m => m.moveId); + user.getMoveHistory().map(m => { + if (m.move !== move.id && movesetMoveIds.find(mm => mm === m.move)) + uniqueUsedMoveIds.add(m.move); + }); + return uniqueUsedMoveIds.size >= movesetMoveIds.length - 1; + }; + } +} + const failOnGravityCondition: MoveConditionFunc = (user, target, move) => !user.scene.arena.getTag(ArenaTagType.GRAVITY); const failOnBossCondition: MoveConditionFunc = (user, target, move) => !target.isBossImmune(); @@ -4836,15 +4850,7 @@ export function initMoves() { new AttackMove(Moves.PUNISHMENT, Type.DARK, MoveCategory.PHYSICAL, -1, 100, 5, -1, 0, 4) .unimplemented(), new AttackMove(Moves.LAST_RESORT, Type.NORMAL, MoveCategory.PHYSICAL, 140, 100, 5, -1, 0, 4) - .condition((user, target, move) => { - const uniqueUsedMoveIds = new Set(); - const movesetMoveIds = user.getMoveset().map(m => m.moveId); - user.getMoveHistory().map(m => { - if (m.move !== move.id && movesetMoveIds.find(mm => mm === m.move)) - uniqueUsedMoveIds.add(m.move); - }); - return uniqueUsedMoveIds.size >= movesetMoveIds.length - 1; - }), + .attr(LastResortAttr), new StatusMove(Moves.WORRY_SEED, Type.GRASS, 100, 10, -1, 0, 4) .attr(AbilityChangeAttr, Abilities.INSOMNIA), new AttackMove(Moves.SUCKER_PUNCH, Type.DARK, MoveCategory.PHYSICAL, 70, 100, 5, -1, 1, 4) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 82915ce41bc..ce2d8dfffe6 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -2680,7 +2680,7 @@ export class EnemyPokemon extends Pokemon { for (let mt of moveTargets[move.id]) { const target = this.scene.getField()[mt]; let targetScore = move.getUserBenefitScore(this, target, move) + move.getTargetBenefitScore(this, target, move) * (mt < BattlerIndex.ENEMY === this.isPlayer() ? 1 : -1); - if (move.name.endsWith(' (N)')) + if (move.name.endsWith(' (N)') || !move.applyConditions(this, target, move)) targetScore = -20; else if (move instanceof AttackMove) { const effectiveness = target.getAttackMoveEffectiveness(this, pokemonMove); From 89e2642d91e419d2ec61574f98d1e9286f213ce9 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Wed, 1 May 2024 18:24:21 -0400 Subject: [PATCH 22/45] Fix update issue for battle stats display --- src/ui/battle-info.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/ui/battle-info.ts b/src/ui/battle-info.ts index ae8f518e727..2ca0457c801 100644 --- a/src/ui/battle-info.ts +++ b/src/ui/battle-info.ts @@ -498,11 +498,14 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.lastLevel = pokemon.level; } - if (pokemon.summonData) { - const battleStats = pokemon.summonData.battleStats.join(''); - - if (this.lastBattleStats !== battleStats) - this.updateBattleStats(pokemon.summonData.battleStats); + const battleStats = pokemon.summonData + ? pokemon.summonData.battleStats + : battleStatOrder.map(() => 0); + const battleStatsStr = battleStats.join(''); + + if (this.lastBattleStats !== battleStatsStr) { + this.updateBattleStats(battleStats); + this.lastBattleStats = battleStatsStr; } this.shinyIcon.setVisible(pokemon.isShiny()); From e34b20466426a9944a71306b993c6d149eeabd20 Mon Sep 17 00:00:00 2001 From: TeKrop Date: Wed, 1 May 2024 22:48:58 +0200 Subject: [PATCH 23/45] feat: added support for localisation on battle scene sentences --- src/field/pokemon.ts | 13 +++++++------ src/locales/de/menu.ts | 7 ++++++- src/locales/en/menu.ts | 7 ++++++- src/locales/es/menu.ts | 7 ++++++- src/locales/fr/menu.ts | 7 ++++++- src/locales/it/menu.ts | 7 ++++++- 6 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index ce2d8dfffe6..8c9224f5e1f 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -45,6 +45,7 @@ import { TerrainType } from '../data/terrain'; import { TrainerSlot } from '../data/trainer-config'; import { BerryType } from '../data/berry'; import { ABILITY_OVERRIDE, MOVE_OVERRIDE, OPP_ABILITY_OVERRIDE, OPP_MOVE_OVERRIDE, OPP_SHINY_OVERRIDE, OPP_VARIANT_OVERRIDE } from '../overrides'; +import i18next from '../plugins/i18n'; export enum FieldPosition { CENTER, @@ -1417,7 +1418,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { damage.value = this.damageAndUpdate(damage.value, result as DamageResult, isCritical, oneHitKo, oneHitKo); this.turnData.damageTaken += damage.value; if (isCritical) - this.scene.queueMessage('A critical hit!'); + this.scene.queueMessage(i18next.t('menu:hitResultCriticalHit')); this.scene.setPhaseQueueSplice(); if (source.isPlayer()) { this.scene.validateAchvs(DamageAchv, damage); @@ -1435,16 +1436,16 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (source.turnData.hitsLeft === 1) { switch (result) { case HitResult.SUPER_EFFECTIVE: - this.scene.queueMessage('It\'s super effective!'); + this.scene.queueMessage(i18next.t('menu:hitResultSuperEffective')); break; case HitResult.NOT_VERY_EFFECTIVE: - this.scene.queueMessage('It\'s not very effective…'); + this.scene.queueMessage(i18next.t('menu:hitResultNotVeryEffective')); break; case HitResult.NO_EFFECT: - this.scene.queueMessage(`It doesn\'t affect ${this.name}!`); + this.scene.queueMessage(i18next.t('menu:hitResultNoEffect', { pokemonName: this.name })); break; case HitResult.ONE_HIT_KO: - this.scene.queueMessage('It\'s a one-hit KO!'); + this.scene.queueMessage(i18next.t('menu:hitResultOneHitKO')); break; } } @@ -1461,7 +1462,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, battlerMove, cancelled, typeMultiplier)); } if (!typeMultiplier.value) - this.scene.queueMessage(`It doesn\'t affect ${this.name}!`); + this.scene.queueMessage(i18next.t('menu:hitResultNoEffect', { pokemonName: this.name })); result = cancelled.value || !typeMultiplier.value ? HitResult.NO_EFFECT : HitResult.STATUS; break; } diff --git a/src/locales/de/menu.ts b/src/locales/de/menu.ts index 442cfae218f..a8e0a901f3f 100644 --- a/src/locales/de/menu.ts +++ b/src/locales/de/menu.ts @@ -63,5 +63,10 @@ export const menu: SimpleTranslationEntries = { "weeklyRankings": "Weekly Rankings", "noRankings": "No Rankings", "loading": "Loading…", - "playersOnline": "Players Online" + "playersOnline": "Players Online", + "hitResultCriticalHit": "A critical hit!", + "hitResultSuperEffective": "It's super effective!", + "hitResultNotVeryEffective": "It's not very effective…", + "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", + "hitResultOneHitKO": "It's a one-hit KO!" } as const; \ No newline at end of file diff --git a/src/locales/en/menu.ts b/src/locales/en/menu.ts index 82a09e49d4f..21620e9b30f 100644 --- a/src/locales/en/menu.ts +++ b/src/locales/en/menu.ts @@ -82,5 +82,10 @@ export const menu: SimpleTranslationEntries = { "weeklyRankings": "Weekly Rankings", "noRankings": "No Rankings", "loading": "Loading…", - "playersOnline": "Players Online" + "playersOnline": "Players Online", + "hitResultCriticalHit": "A critical hit!", + "hitResultSuperEffective": "It's super effective!", + "hitResultNotVeryEffective": "It's not very effective…", + "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", + "hitResultOneHitKO": "It's a one-hit KO!" } as const; \ No newline at end of file diff --git a/src/locales/es/menu.ts b/src/locales/es/menu.ts index 5dccc2e4eb3..0a43f19b768 100644 --- a/src/locales/es/menu.ts +++ b/src/locales/es/menu.ts @@ -66,5 +66,10 @@ export const menu: SimpleTranslationEntries = { "weeklyRankings": "Weekly Rankings", "noRankings": "No Rankings", "loading": "Loading…", - "playersOnline": "Players Online" + "playersOnline": "Players Online", + "hitResultCriticalHit": "A critical hit!", + "hitResultSuperEffective": "It's super effective!", + "hitResultNotVeryEffective": "It's not very effective…", + "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", + "hitResultOneHitKO": "It's a one-hit KO!" } as const; \ No newline at end of file diff --git a/src/locales/fr/menu.ts b/src/locales/fr/menu.ts index d5478c67a26..c485412bf1a 100644 --- a/src/locales/fr/menu.ts +++ b/src/locales/fr/menu.ts @@ -77,5 +77,10 @@ export const menu: SimpleTranslationEntries = { "weeklyRankings": "Classement de la Semaine", "noRankings": "Pas de Classement", "loading": "Chargement…", - "playersOnline": "Joueurs Connectés" + "playersOnline": "Joueurs Connectés", + "hitResultCriticalHit": "Coup critique!", + "hitResultSuperEffective": "C'est super efficace!", + "hitResultNotVeryEffective": "Ce n'est pas très efficace…", + "hitResultNoEffect": "Ça n'affecte pas {{pokemonName}}…", + "hitResultOneHitKO": "K.O. en un coup!" } as const; diff --git a/src/locales/it/menu.ts b/src/locales/it/menu.ts index c37a37b5169..118c1dccb5f 100644 --- a/src/locales/it/menu.ts +++ b/src/locales/it/menu.ts @@ -11,5 +11,10 @@ export const menu: SimpleTranslationEntries = { "weeklyRankings": "Weekly Rankings", "noRankings": "No Rankings", "loading": "Loading…", - "playersOnline": "Players Online" + "playersOnline": "Players Online", + "hitResultCriticalHit": "A critical hit!", + "hitResultSuperEffective": "It's super effective!", + "hitResultNotVeryEffective": "It's not very effective…", + "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", + "hitResultOneHitKO": "It's a one-hit KO!" } as const; \ No newline at end of file From 6ac224ab8a4e3e5ec6aa7fdc2d8b60111343f2fd Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Wed, 1 May 2024 18:53:48 -0400 Subject: [PATCH 24/45] Refactor to split battle messages from menu --- src/field/pokemon.ts | 12 ++--- src/locales/de/battle.ts | 52 ++++++++++++++++++ src/locales/de/fight-ui-handler.ts | 6 +++ src/locales/de/menu.ts | 31 +---------- src/locales/en/battle.ts | 52 ++++++++++++++++++ src/locales/en/menu.ts | 50 +---------------- src/locales/es/battle.ts | 52 ++++++++++++++++++ src/locales/es/fight-ui-handler.ts | 6 +++ src/locales/es/menu.ts | 50 +---------------- src/locales/fr/battle.ts | 52 ++++++++++++++++++ src/locales/fr/menu.ts | 50 +---------------- src/locales/it/battle.ts | 52 ++++++++++++++++++ src/locales/it/fight-ui-handler.ts | 6 +++ src/locales/it/menu.ts | 35 +++++++++--- src/phases.ts | 86 +++++++++++++++--------------- src/plugins/i18n.ts | 18 +++++++ 16 files changed, 378 insertions(+), 232 deletions(-) create mode 100644 src/locales/de/battle.ts create mode 100644 src/locales/de/fight-ui-handler.ts create mode 100644 src/locales/en/battle.ts create mode 100644 src/locales/es/battle.ts create mode 100644 src/locales/es/fight-ui-handler.ts create mode 100644 src/locales/fr/battle.ts create mode 100644 src/locales/it/battle.ts create mode 100644 src/locales/it/fight-ui-handler.ts diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 8c9224f5e1f..a966a24303f 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -1418,7 +1418,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { damage.value = this.damageAndUpdate(damage.value, result as DamageResult, isCritical, oneHitKo, oneHitKo); this.turnData.damageTaken += damage.value; if (isCritical) - this.scene.queueMessage(i18next.t('menu:hitResultCriticalHit')); + this.scene.queueMessage(i18next.t('battle:hitResultCriticalHit')); this.scene.setPhaseQueueSplice(); if (source.isPlayer()) { this.scene.validateAchvs(DamageAchv, damage); @@ -1436,16 +1436,16 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (source.turnData.hitsLeft === 1) { switch (result) { case HitResult.SUPER_EFFECTIVE: - this.scene.queueMessage(i18next.t('menu:hitResultSuperEffective')); + this.scene.queueMessage(i18next.t('battle:hitResultSuperEffective')); break; case HitResult.NOT_VERY_EFFECTIVE: - this.scene.queueMessage(i18next.t('menu:hitResultNotVeryEffective')); + this.scene.queueMessage(i18next.t('battle:hitResultNotVeryEffective')); break; case HitResult.NO_EFFECT: - this.scene.queueMessage(i18next.t('menu:hitResultNoEffect', { pokemonName: this.name })); + this.scene.queueMessage(i18next.t('battle:hitResultNoEffect', { pokemonName: this.name })); break; case HitResult.ONE_HIT_KO: - this.scene.queueMessage(i18next.t('menu:hitResultOneHitKO')); + this.scene.queueMessage(i18next.t('battle:hitResultOneHitKO')); break; } } @@ -1462,7 +1462,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, battlerMove, cancelled, typeMultiplier)); } if (!typeMultiplier.value) - this.scene.queueMessage(i18next.t('menu:hitResultNoEffect', { pokemonName: this.name })); + this.scene.queueMessage(i18next.t('battle:hitResultNoEffect', { pokemonName: this.name })); result = cancelled.value || !typeMultiplier.value ? HitResult.NO_EFFECT : HitResult.STATUS; break; } diff --git a/src/locales/de/battle.ts b/src/locales/de/battle.ts new file mode 100644 index 00000000000..61191a1165a --- /dev/null +++ b/src/locales/de/battle.ts @@ -0,0 +1,52 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const battle: SimpleTranslationEntries = { + "bossAppeared": "{{bossName}} erscheint.", + "trainerAppeared": "{{trainerName}}\nmöchte kämpfen!", + "singleWildAppeared": "Ein wildes {{pokemonName}} erscheint!", + "multiWildAppeared": "Ein wildes {{pokemonName1}}\nund {{pokemonName2}} erscheinen!", + "playerComeBack": "Komm zurück, {{pokemonName}}!", + "trainerComeBack": "{{trainerName}} ruft {{pokemonName}} zurück!", + "playerGo": "Los! {{pokemonName}}!", + "trainerGo": "{{trainerName}} sendet {{pokemonName}} raus!", + "switchQuestion": "Willst du\n{{pokemonName}} auswechseln?", + "trainerDefeated": `You defeated\n{{trainerName}}!`, + "pokemonCaught": "{{pokemonName}} was caught!", + "pokemon": "Pokémon", + "sendOutPokemon": "Los! {{pokemonName}}!", + "hitResultCriticalHit": "A critical hit!", + "hitResultSuperEffective": "It's super effective!", + "hitResultNotVeryEffective": "It's not very effective…", + "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", + "hitResultOneHitKO": "It's a one-hit KO!", + "attackFailed": "But it failed!", + "attackHitsCount": `Hit {{count}} time(s)!`, + "expGain": "{{pokemonName}} gained\n{{exp}} EXP. Points!", + "levelUp": "{{pokemonName}} grew to\nLv. {{level}}!", + "learnMove": "{{pokemonName}} learned\n{{moveName}}!", + "learnMovePrompt": "{{pokemonName}} wants to learn the\nmove {{moveName}}.", + "learnMoveLimitReached": "However, {{pokemonName}} already\nknows four moves.", + "learnMoveReplaceQuestion": "Should a move be forgotten and\nreplaced with {{moveName}}?", + "learnMoveStopTeaching": "Stop trying to teach\n{{moveName}}?", + "learnMoveNotLearned": "{{pokemonName}} did not learn the\nmove {{moveName}}.", + "learnMoveForgetQuestion": "Which move should be forgotten?", + "learnMoveForgetSuccess": "{{pokemonName}} forgot how to\nuse {{moveName}}.", + "levelCapUp": "Das Levellimit\nhat sich zu {{levelCap}} erhöht!", + "moveNotImplemented": "{{moveName}} ist noch nicht implementiert und kann nicht ausgewählt werden.", + "moveDisabled": "{{moveName}} ist deaktiviert!", + "noPokeballForce": "Eine unsichtbare Kraft\nverhindert die Nutzung von Pokébällen.", + "noPokeballTrainer": "Du kannst das Pokémon\neines anderen Trainers nicht fangen!", + "noPokeballMulti": "Du kannst erst einen Pokéball werden,\nwenn nur noch ein Pokémon übrig ist!", + "noPokeballStrong": "Das Ziel-Pokémon ist zu stark, um gefangen zu werden!\nDu musst es zuerst schwächen!", + "noEscapeForce": "Eine unsichtbare Kraft\nverhindert die Flucht.", + "noEscapeTrainer": "Du kannst nicht\naus einem Trainerkampf fliehen!", + "noEscapePokemon": "{{pokemonName}}'s {{moveName}}\nverhindert {{escapeVerb}}!", + "runAwaySuccess": "You got away safely!", + "runAwayCannotEscape": 'You can\'t escape!', + "escapeVerbSwitch": "auswechseln", + "escapeVerbFlee": "flucht", + "notDisabled": "{{moveName}} ist\nnicht mehr deaktiviert!", + "skipItemQuestion": "Are you sure you want to skip taking an item?", + "eggHatching": "Oh?", + "ivScannerUseQuestion": "Use IV Scanner on {{pokemonName}}?" +} as const; \ No newline at end of file diff --git a/src/locales/de/fight-ui-handler.ts b/src/locales/de/fight-ui-handler.ts new file mode 100644 index 00000000000..1ce9e0317bf --- /dev/null +++ b/src/locales/de/fight-ui-handler.ts @@ -0,0 +1,6 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const fightUiHandler: SimpleTranslationEntries = { + "pp": "PP", + "power": "POWER", +} as const; \ No newline at end of file diff --git a/src/locales/de/menu.ts b/src/locales/de/menu.ts index a8e0a901f3f..c648b15bfe8 100644 --- a/src/locales/de/menu.ts +++ b/src/locales/de/menu.ts @@ -35,38 +35,9 @@ export const menu: SimpleTranslationEntries = { "boyOrGirl": "Bist du ein Junge oder ein Mädchen?", "boy": "Junge", "girl": "Mädchen", - "bossAppeared": "{{bossName}} erscheint.", - "trainerAppeared": "{{trainerName}}\nmöchte kämpfen!", - "singleWildAppeared": "Ein wildes {{pokemonName}} erscheint!", - "multiWildAppeared": "Ein wildes {{pokemonName1}}\nund {{pokemonName2}} erscheinen!", - "playerComeBack": "Komm zurück, {{pokemonName}}!", - "trainerComeBack": "{{trainerName}} ruft {{pokemonName}} zurück!", - "playerGo": "Los! {{pokemonName}}!", - "trainerGo": "{{trainerName}} sendet {{pokemonName}} raus!", - "switchQuestion": "Willst du\n{{pokemonName}} auswechseln?", - "pokemon": "Pokémon", - "sendOutPokemon": "Los! {{pokemonName}}!", - "levelCapUp": "Das Levellimit\nhat sich zu {{levelCap}} erhöht!", - "moveNotImplemented": "{{moveName}} ist noch nicht implementiert und kann nicht ausgewählt werden.", - "moveDisabled": "{{moveName}} ist deaktiviert!", - "noPokeballForce": "Eine unsichtbare Kraft\nverhindert die Nutzung von Pokébällen.", - "noPokeballTrainer": "Du kannst das Pokémon\neines anderen Trainers nicht fangen!", - "noPokeballMulti": "Du kannst erst einen Pokéball werden,\nwenn nur noch ein Pokémon übrig ist!", - "noPokeballStrong": "Das Ziel-Pokémon ist zu stark, um gefangen zu werden!\nDu musst es zuerst schwächen!", - "noEscapeForce": "Eine unsichtbare Kraft\nverhindert die Flucht.", - "noEscapeTrainer": "Du kannst nicht\naus einem Trainerkampf fliehen!", - "noEscapePokemon": "{{pokemonName}}'s {{moveName}}\nverhindert {{escapeVerb}}!", - "escapeVerbSwitch": "auswechseln", - "escapeVerbFlee": "flucht", - "notDisabled": "{{moveName}} ist\nnicht mehr deaktiviert!", "dailyRankings": "Daily Rankings", "weeklyRankings": "Weekly Rankings", "noRankings": "No Rankings", "loading": "Loading…", - "playersOnline": "Players Online", - "hitResultCriticalHit": "A critical hit!", - "hitResultSuperEffective": "It's super effective!", - "hitResultNotVeryEffective": "It's not very effective…", - "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", - "hitResultOneHitKO": "It's a one-hit KO!" + "playersOnline": "Players Online" } as const; \ No newline at end of file diff --git a/src/locales/en/battle.ts b/src/locales/en/battle.ts new file mode 100644 index 00000000000..599672a1b19 --- /dev/null +++ b/src/locales/en/battle.ts @@ -0,0 +1,52 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const battle: SimpleTranslationEntries = { + "bossAppeared": "{{bossName}} appeared.", + "trainerAppeared": "{{trainerName}}\nwould like to battle!", + "singleWildAppeared": "A wild {{pokemonName}} appeared!", + "multiWildAppeared": "A wild {{pokemonName1}}\nand {{pokemonName2}} appeared!", + "playerComeBack": "Come back, {{pokemonName}}!", + "trainerComeBack": "{{trainerName}} withdrew {{pokemonName}}!", + "playerGo": "Go! {{pokemonName}}!", + "trainerGo": "{{trainerName}} sent out {{pokemonName}}!", + "switchQuestion": "Will you switch\n{{pokemonName}}?", + "trainerDefeated": `You defeated\n{{trainerName}}!`, + "pokemonCaught": "{{pokemonName}} was caught!", + "pokemon": "Pokémon", + "sendOutPokemon": "Go! {{pokemonName}}!", + "hitResultCriticalHit": "A critical hit!", + "hitResultSuperEffective": "It's super effective!", + "hitResultNotVeryEffective": "It's not very effective…", + "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", + "hitResultOneHitKO": "It's a one-hit KO!", + "attackFailed": "But it failed!", + "attackHitsCount": `Hit {{count}} time(s)!`, + "expGain": "{{pokemonName}} gained\n{{exp}} EXP. Points!", + "levelUp": "{{pokemonName}} grew to\nLv. {{level}}!", + "learnMove": "{{pokemonName}} learned\n{{moveName}}!", + "learnMovePrompt": "{{pokemonName}} wants to learn the\nmove {{moveName}}.", + "learnMoveLimitReached": "However, {{pokemonName}} already\nknows four moves.", + "learnMoveReplaceQuestion": "Should a move be forgotten and\nreplaced with {{moveName}}?", + "learnMoveStopTeaching": "Stop trying to teach\n{{moveName}}?", + "learnMoveNotLearned": "{{pokemonName}} did not learn the\nmove {{moveName}}.", + "learnMoveForgetQuestion": "Which move should be forgotten?", + "learnMoveForgetSuccess": "{{pokemonName}} forgot how to\nuse {{moveName}}.", + "levelCapUp": "The level cap\nhas increased to {{levelCap}}!", + "moveNotImplemented": "{{moveName}} is not yet implemented and cannot be selected.", + "moveDisabled": "{{moveName}} is disabled!", + "noPokeballForce": "An unseen force\nprevents using Poké Balls.", + "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!", + "noPokeballStrong": "The target Pokémon is too strong to be caught!\nYou need to weaken it first!", + "noEscapeForce": "An unseen force\nprevents escape.", + "noEscapeTrainer": "You can't run\nfrom a trainer battle!", + "noEscapePokemon": "{{pokemonName}}'s {{moveName}}\nprevents {{escapeVerb}}!", + "runAwaySuccess": "You got away safely!", + "runAwayCannotEscape": 'You can\'t escape!', + "escapeVerbSwitch": "switching", + "escapeVerbFlee": "fleeing", + "notDisabled": "{{moveName}} is disabled\nno more!", + "skipItemQuestion": "Are you sure you want to skip taking an item?", + "eggHatching": "Oh?", + "ivScannerUseQuestion": "Use IV Scanner on {{pokemonName}}?" +} as const; \ No newline at end of file diff --git a/src/locales/en/menu.ts b/src/locales/en/menu.ts index 21620e9b30f..42888b17337 100644 --- a/src/locales/en/menu.ts +++ b/src/locales/en/menu.ts @@ -35,57 +35,9 @@ export const menu: SimpleTranslationEntries = { "boyOrGirl": "Are you a boy or a girl?", "boy": "Boy", "girl": "Girl", - "bossAppeared": "{{bossName}} appeared.", - "trainerAppeared": "{{trainerName}}\nwould like to battle!", - "singleWildAppeared": "A wild {{pokemonName}} appeared!", - "multiWildAppeared": "A wild {{pokemonName1}}\nand {{pokemonName2}} appeared!", - "playerComeBack": "Come back, {{pokemonName}}!", - "trainerComeBack": "{{trainerName}} withdrew {{pokemonName}}!", - "playerGo": "Go! {{pokemonName}}!", - "trainerGo": "{{trainerName}} sent out {{pokemonName}}!", - "switchQuestion": "Will you switch\n{{pokemonName}}?", - "trainerDefeated": `You defeated\n{{trainerName}}!`, - "pokemonCaught": "{{pokemonName}} was caught!", - "pokemon": "Pokémon", - "sendOutPokemon": "Go! {{pokemonName}}!", - "attackFailed": "But it failed!", - "attackHitsCount": `Hit {{count}} time(s)!`, - "expGain": "{{pokemonName}} gained\n{{exp}} EXP. Points!", - "levelUp": "{{pokemonName}} grew to\nLv. {{level}}!", - "learnMove": "{{pokemonName}} learned\n{{moveName}}!", - "learnMovePrompt": "{{pokemonName}} wants to learn the\nmove {{moveName}}.", - "learnMoveLimitReached": "However, {{pokemonName}} already\nknows four moves.", - "learnMoveReplaceQuestion": "Should a move be forgotten and\nreplaced with {{moveName}}?", - "learnMoveStopTeaching": "Stop trying to teach\n{{moveName}}?", - "learnMoveNotLearned": "{{pokemonName}} did not learn the\nmove {{moveName}}.", - "learnMoveForgetQuestion": "Which move should be forgotten?", - "learnMoveForgetSuccess": "{{pokemonName}} forgot how to\nuse {{moveName}}.", - "levelCapUp": "The level cap\nhas increased to {{levelCap}}!", - "moveNotImplemented": "{{moveName}} is not yet implemented and cannot be selected.", - "moveDisabled": "{{moveName}} is disabled!", - "noPokeballForce": "An unseen force\nprevents using Poké Balls.", - "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!", - "noPokeballStrong": "The target Pokémon is too strong to be caught!\nYou need to weaken it first!", - "noEscapeForce": "An unseen force\nprevents escape.", - "noEscapeTrainer": "You can't run\nfrom a trainer battle!", - "noEscapePokemon": "{{pokemonName}}'s {{moveName}}\nprevents {{escapeVerb}}!", - "runAwaySuccess": "You got away safely!", - "runAwayCannotEscape": 'You can\'t escape!', - "escapeVerbSwitch": "switching", - "escapeVerbFlee": "fleeing", - "notDisabled": "{{moveName}} is disabled\nno more!", - "skipItemQuestion": "Are you sure you want to skip taking an item?", - "eggHatching": "Oh?", - "ivScannerUseQuestion": "Use IV Scanner on {{pokemonName}}?", "dailyRankings": "Daily Rankings", "weeklyRankings": "Weekly Rankings", "noRankings": "No Rankings", "loading": "Loading…", - "playersOnline": "Players Online", - "hitResultCriticalHit": "A critical hit!", - "hitResultSuperEffective": "It's super effective!", - "hitResultNotVeryEffective": "It's not very effective…", - "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", - "hitResultOneHitKO": "It's a one-hit KO!" + "playersOnline": "Players Online" } as const; \ No newline at end of file diff --git a/src/locales/es/battle.ts b/src/locales/es/battle.ts new file mode 100644 index 00000000000..1d4345a6f5b --- /dev/null +++ b/src/locales/es/battle.ts @@ -0,0 +1,52 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const battle: SimpleTranslationEntries = { + "bossAppeared": "¡{{bossName}} te corta el paso!", + "trainerAppeared": "¡{{trainerName}}\nte desafía!", + "singleWildAppeared": "¡Un {{pokemonName}} salvaje te corta el paso!", + "multiWildAppeared": "¡Un {{pokemonName1}} y un {{pokemonName2}} salvajes\nte cortan el paso!", + "playerComeBack": "¡{{pokemonName}}, ven aquí!", + "trainerComeBack": "¡{{trainerName}} retira a {{pokemonName}} del combate!", + "playerGo": "¡Adelante, {{pokemonName}}!", + "trainerGo": "¡{{trainerName}} saca a {{pokemonName}}!", + "switchQuestion": "¿Quieres cambiar a\n{{pokemonName}}?", + "trainerDefeated": "¡Has derrotado a\n{{trainerName}}!", + "pokemonCaught": "¡{{pokemonName}} atrapado!", + "pokemon": "Pokémon", + "sendOutPokemon": "¡Adelante, {{pokemonName}}!", + "hitResultCriticalHit": "A critical hit!", + "hitResultSuperEffective": "It's super effective!", + "hitResultNotVeryEffective": "It's not very effective…", + "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", + "hitResultOneHitKO": "It's a one-hit KO!", + "attackFailed": "¡Pero ha fallado!", + "attackHitsCount": `N.º de golpes: {{count}}.`, + "expGain": "{{pokemonName}} ha ganado\n{{exp}} puntos de experiencia.", + "levelUp": "¡{{pokemonName}} ha subido al \nNv. {{level}}!", + "learnMove": "¡{{pokemonName}} ha aprendido {{moveName}}!", + "learnMovePrompt": "{{pokemonName}} quiere aprender {{moveName}}.", + "learnMoveLimitReached": "Pero, {{pokemonName}} ya conoce\ncuatro movimientos.", + "learnMoveReplaceQuestion": "¿Quieres sustituir uno de sus movimientos por {{moveName}}?", + "learnMoveStopTeaching": "¿Prefieres que no aprenda\n{{moveName}}?", + "learnMoveNotLearned": "{{pokemonName}} no ha aprendido {{moveName}}.", + "learnMoveForgetQuestion": "¿Qué movimiento quieres que olvide?", + "learnMoveForgetSuccess": "{{pokemonName}} ha olvidado cómo utilizar {{moveName}}.", + "levelCapUp": "¡Se ha incrementado el\nnivel máximo a {{levelCap}}!", + "moveNotImplemented": "{{moveName}} aún no está implementado y no se puede seleccionar.", + "moveDisabled": "!No puede usar {{moveName}} porque ha sido anulado!", + "noPokeballForce": "Una fuerza misteriosa\nte impide usar Poké Balls.", + "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!", + "noPokeballStrong": "¡Este Pokémon es demasiado fuerte para ser capturado!\nNecesitas bajarle los PS primero!", + "noEscapeForce": "Una fuerza misteriosa\nte impide huir.", + "noEscapeTrainer": "¡No puedes huir de los\ncombates contra Entrenadores!", + "noEscapePokemon": "¡El movimiento {{moveName}} de {{pokemonName}} impide la huida!", + "runAwaySuccess": "¡Escapas sin problemas!", + "runAwayCannotEscape": "¡No has podido escapar!", + "escapeVerbSwitch": "cambiar", + "escapeVerbFlee": "huir", + "notDisabled": "¡El movimiento {{moveName}}\nya no está anulado!", + "skipItemQuestion": "¿Estás seguro de que no quieres coger un objeto?", + "eggHatching": "¿Y esto?", + "ivScannerUseQuestion": "¿Quieres usar el Escáner de IVs en {{pokemonName}}?" +} as const; \ No newline at end of file diff --git a/src/locales/es/fight-ui-handler.ts b/src/locales/es/fight-ui-handler.ts new file mode 100644 index 00000000000..1ce9e0317bf --- /dev/null +++ b/src/locales/es/fight-ui-handler.ts @@ -0,0 +1,6 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const fightUiHandler: SimpleTranslationEntries = { + "pp": "PP", + "power": "POWER", +} as const; \ No newline at end of file diff --git a/src/locales/es/menu.ts b/src/locales/es/menu.ts index 0a43f19b768..c67287ae0cc 100644 --- a/src/locales/es/menu.ts +++ b/src/locales/es/menu.ts @@ -19,57 +19,9 @@ export const menu: SimpleTranslationEntries = { "boyOrGirl": "¿Eres un chico o una chica?", "boy": "Chico", "girl": "Chica", - "bossAppeared": "¡{{bossName}} te corta el paso!", - "trainerAppeared": "¡{{trainerName}}\nte desafía!", - "singleWildAppeared": "¡Un {{pokemonName}} salvaje te corta el paso!", - "multiWildAppeared": "¡Un {{pokemonName1}} y un {{pokemonName2}} salvajes\nte cortan el paso!", - "playerComeBack": "¡{{pokemonName}}, ven aquí!", - "trainerComeBack": "¡{{trainerName}} retira a {{pokemonName}} del combate!", - "playerGo": "¡Adelante, {{pokemonName}}!", - "trainerGo": "¡{{trainerName}} saca a {{pokemonName}}!", - "switchQuestion": "¿Quieres cambiar a\n{{pokemonName}}?", - "trainerDefeated": "¡Has derrotado a\n{{trainerName}}!", - "pokemonCaught": "¡{{pokemonName}} atrapado!", - "pokemon": "Pokémon", - "sendOutPokemon": "¡Adelante, {{pokemonName}}!", - "attackFailed": "¡Pero ha fallado!", - "attackHitsCount": `N.º de golpes: {{count}}.`, - "expGain": "{{pokemonName}} ha ganado\n{{exp}} puntos de experiencia.", - "levelUp": "¡{{pokemonName}} ha subido al \nNv. {{level}}!", - "learnMove": "¡{{pokemonName}} ha aprendido {{moveName}}!", - "learnMovePrompt": "{{pokemonName}} quiere aprender {{moveName}}.", - "learnMoveLimitReached": "Pero, {{pokemonName}} ya conoce\ncuatro movimientos.", - "learnMoveReplaceQuestion": "¿Quieres sustituir uno de sus movimientos por {{moveName}}?", - "learnMoveStopTeaching": "¿Prefieres que no aprenda\n{{moveName}}?", - "learnMoveNotLearned": "{{pokemonName}} no ha aprendido {{moveName}}.", - "learnMoveForgetQuestion": "¿Qué movimiento quieres que olvide?", - "learnMoveForgetSuccess": "{{pokemonName}} ha olvidado cómo utilizar {{moveName}}.", - "levelCapUp": "¡Se ha incrementado el\nnivel máximo a {{levelCap}}!", - "moveNotImplemented": "{{moveName}} aún no está implementado y no se puede seleccionar.", - "moveDisabled": "!No puede usar {{moveName}} porque ha sido anulado!", - "noPokeballForce": "Una fuerza misteriosa\nte impide usar Poké Balls.", - "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!", - "noPokeballStrong": "¡Este Pokémon es demasiado fuerte para ser capturado!\nNecesitas bajarle los PS primero!", - "noEscapeForce": "Una fuerza misteriosa\nte impide huir.", - "noEscapeTrainer": "¡No puedes huir de los\ncombates contra Entrenadores!", - "noEscapePokemon": "¡El movimiento {{moveName}} de {{pokemonName}} impide la huida!", - "runAwaySuccess": "¡Escapas sin problemas!", - "runAwayCannotEscape": "¡No has podido escapar!", - "escapeVerbSwitch": "cambiar", - "escapeVerbFlee": "huir", - "notDisabled": "¡El movimiento {{moveName}}\nya no está anulado!", - "skipItemQuestion": "¿Estás seguro de que no quieres coger un objeto?", - "eggHatching": "¿Y esto?", - "ivScannerUseQuestion": "¿Quieres usar el Escáner de IVs en {{pokemonName}}?", "dailyRankings": "Daily Rankings", "weeklyRankings": "Weekly Rankings", "noRankings": "No Rankings", "loading": "Loading…", - "playersOnline": "Players Online", - "hitResultCriticalHit": "A critical hit!", - "hitResultSuperEffective": "It's super effective!", - "hitResultNotVeryEffective": "It's not very effective…", - "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", - "hitResultOneHitKO": "It's a one-hit KO!" + "playersOnline": "Players Online" } as const; \ No newline at end of file diff --git a/src/locales/fr/battle.ts b/src/locales/fr/battle.ts new file mode 100644 index 00000000000..8768c30155a --- /dev/null +++ b/src/locales/fr/battle.ts @@ -0,0 +1,52 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const battle: SimpleTranslationEntries = { + "bossAppeared": "Un {{bossName}} apparaît.", + "trainerAppeared": "Un combat est lancé\npar {{trainerName}} !", + "singleWildAppeared": "Un {{pokemonName}} sauvage apparaît !", + "multiWildAppeared": "Un {{pokemonName1}} et un {{pokemonName2}}\nsauvages apparaissent !", + "playerComeBack": "{{pokemonName}}, on change !\nReviens !", + "trainerComeBack": "{{trainerName}} retire {{pokemonName}} !", + "playerGo": "{{pokemonName}} ! Go !", + "trainerGo": "{{pokemonName}} est envoyé par\n{{trainerName}} !", + "switchQuestion": "Voulez-vous changer\n{{pokemonName}} ?", + "trainerDefeated": `Vous avez battu\n{{trainerName}} !`, + "pokemonCaught": "Vous avez attrapé {{pokemonName}} !", + "pokemon": "Pokémon", + "sendOutPokemon": "{{pokemonName}} ! Go !", + "hitResultCriticalHit": "Coup critique!", + "hitResultSuperEffective": "C’est super efficace!", + "hitResultNotVeryEffective": "Ce n’est pas très efficace…", + "hitResultNoEffect": "Ça n’affecte pas {{pokemonName}}…", + "hitResultOneHitKO": "K.O. en un coup!", + "attackFailed": "Mais cela échoue !", + "attackHitsCount": `Touché {{count}} fois !`, + "expGain": "{{pokemonName}} gagne\n{{exp}} Points d’Exp !", + "levelUp": "{{pokemonName}} monte au\nN. {{level}} !", + "learnMove": "{{pokemonName}} apprend \n{{moveName}} !", + "learnMovePrompt": "{{pokemonName}} veut apprendre\n{{moveName}}.", + "learnMoveLimitReached": "Cependant, {{pokemonName}} connait\ndéjà quatre capacités.", + "learnMoveReplaceQuestion": "Voulez-vous oublier une capacité\net la remplacer par {{moveName}} ?", + "learnMoveStopTeaching": "Arrêter d’apprendre\n{{moveName}} ?", + "learnMoveNotLearned": "{{pokemonName}} n’a pas appris\n{{moveName}}.", + "learnMoveForgetQuestion": "Quelle capacité doit être oubliée ?", + "learnMoveForgetSuccess": "{{pokemonName}} oublie comment\nutiliser {{moveName}}.", + "levelCapUp": "La limite de niveau\na été augmentée à {{levelCap}} !", + "moveNotImplemented": "{{moveName}} n’est pas encore implémenté et ne peut pas être sélectionné.", + "moveDisabled": "{{moveName}} est sous entrave !", + "noPokeballForce": "Une force mystérieuse\nempêche l’utilisation des Poké Balls.", + "noPokeballTrainer": "Le Dresseur détourne la Ball\nVoler, c’est mal !", + "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 d’abord l’affaiblir !", + "noEscapeForce": "Une force mystérieuse\nempêche la fuite.", + "noEscapeTrainer": "On ne s’enfuit pas d’un\ncombat de Dresseurs !", + "noEscapePokemon": "{{moveName}} de {{pokemonName}}\nempêche {{escapeVerb}} !", + "runAwaySuccess": "Vous prenez la fuite !", + "runAwayCannotEscape": "Fuite impossible !", + "escapeVerbSwitch": "le changement", + "escapeVerbFlee": "la fuite", + "notDisabled": "{{moveName}} n’est plus sous entrave !", + "skipItemQuestion": "Êtes-vous sûr·e de ne pas vouloir prendre d’objet ?", + "eggHatching": "Oh ?", + "ivScannerUseQuestion": "Utiliser le Scanner d’IV sur {{pokemonName}} ?" +} as const; \ No newline at end of file diff --git a/src/locales/fr/menu.ts b/src/locales/fr/menu.ts index c485412bf1a..1744297089c 100644 --- a/src/locales/fr/menu.ts +++ b/src/locales/fr/menu.ts @@ -30,57 +30,9 @@ export const menu: SimpleTranslationEntries = { "boyOrGirl": "Es-tu un garçon ou une fille ?", "boy": "Garçon", "girl": "Fille", - "bossAppeared": "Un {{bossName}} apparaît.", - "trainerAppeared": "Un combat est lancé\npar {{trainerName}} !", - "singleWildAppeared": "Un {{pokemonName}} sauvage apparaît !", - "multiWildAppeared": "Un {{pokemonName1}} et un {{pokemonName2}}\nsauvages apparaissent !", - "playerComeBack": "{{pokemonName}}, on change !\nReviens !", - "trainerComeBack": "{{trainerName}} retire {{pokemonName}} !", - "playerGo": "{{pokemonName}} ! Go !", - "trainerGo": "{{pokemonName}} est envoyé par\n{{trainerName}} !", - "switchQuestion": "Voulez-vous changer\n{{pokemonName}} ?", - "trainerDefeated": `Vous avez battu\n{{trainerName}} !`, - "pokemonCaught": "Vous avez attrapé {{pokemonName}} !", - "pokemon": "Pokémon", - "sendOutPokemon": "{{pokemonName}} ! Go !", - "attackFailed": "Mais cela échoue !", - "attackHitsCount": `Touché {{count}} fois !`, - "expGain": "{{pokemonName}} gagne\n{{exp}} Points d’Exp !", - "levelUp": "{{pokemonName}} monte au\nN. {{level}} !", - "learnMove": "{{pokemonName}} apprend \n{{moveName}} !", - "learnMovePrompt": "{{pokemonName}} veut apprendre\n{{moveName}}.", - "learnMoveLimitReached": "Cependant, {{pokemonName}} connait\ndéjà quatre capacités.", - "learnMoveReplaceQuestion": "Voulez-vous oublier une capacité\net la remplacer par {{moveName}} ?", - "learnMoveStopTeaching": "Arrêter d’apprendre\n{{moveName}} ?", - "learnMoveNotLearned": "{{pokemonName}} n’a pas appris\n{{moveName}}.", - "learnMoveForgetQuestion": "Quelle capacité doit être oubliée ?", - "learnMoveForgetSuccess": "{{pokemonName}} oublie comment\nutiliser {{moveName}}.", - "levelCapUp": "La limite de niveau\na été augmentée à {{levelCap}} !", - "moveNotImplemented": "{{moveName}} n’est pas encore implémenté et ne peut pas être sélectionné.", - "moveDisabled": "{{moveName}} est sous entrave !", - "noPokeballForce": "Une force mystérieuse\nempêche l’utilisation des Poké Balls.", - "noPokeballTrainer": "Le Dresseur détourne la Ball\nVoler, c’est mal !", - "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 d’abord l’affaiblir !", - "noEscapeForce": "Une force mystérieuse\nempêche la fuite.", - "noEscapeTrainer": "On ne s’enfuit pas d’un\ncombat de Dresseurs !", - "noEscapePokemon": "{{moveName}} de {{pokemonName}}\nempêche {{escapeVerb}} !", - "runAwaySuccess": "Vous prenez la fuite !", - "runAwayCannotEscape": "Fuite impossible !", - "escapeVerbSwitch": "le changement", - "escapeVerbFlee": "la fuite", - "notDisabled": "{{moveName}} n’est plus sous entrave !", - "skipItemQuestion": "Êtes-vous sûr·e de ne pas vouloir prendre d’objet ?", - "eggHatching": "Oh ?", - "ivScannerUseQuestion": "Utiliser le Scanner d’IV sur {{pokemonName}} ?", "dailyRankings": "Classement du Jour", "weeklyRankings": "Classement de la Semaine", "noRankings": "Pas de Classement", "loading": "Chargement…", - "playersOnline": "Joueurs Connectés", - "hitResultCriticalHit": "Coup critique!", - "hitResultSuperEffective": "C'est super efficace!", - "hitResultNotVeryEffective": "Ce n'est pas très efficace…", - "hitResultNoEffect": "Ça n'affecte pas {{pokemonName}}…", - "hitResultOneHitKO": "K.O. en un coup!" + "playersOnline": "Joueurs Connectés" } as const; diff --git a/src/locales/it/battle.ts b/src/locales/it/battle.ts new file mode 100644 index 00000000000..599672a1b19 --- /dev/null +++ b/src/locales/it/battle.ts @@ -0,0 +1,52 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const battle: SimpleTranslationEntries = { + "bossAppeared": "{{bossName}} appeared.", + "trainerAppeared": "{{trainerName}}\nwould like to battle!", + "singleWildAppeared": "A wild {{pokemonName}} appeared!", + "multiWildAppeared": "A wild {{pokemonName1}}\nand {{pokemonName2}} appeared!", + "playerComeBack": "Come back, {{pokemonName}}!", + "trainerComeBack": "{{trainerName}} withdrew {{pokemonName}}!", + "playerGo": "Go! {{pokemonName}}!", + "trainerGo": "{{trainerName}} sent out {{pokemonName}}!", + "switchQuestion": "Will you switch\n{{pokemonName}}?", + "trainerDefeated": `You defeated\n{{trainerName}}!`, + "pokemonCaught": "{{pokemonName}} was caught!", + "pokemon": "Pokémon", + "sendOutPokemon": "Go! {{pokemonName}}!", + "hitResultCriticalHit": "A critical hit!", + "hitResultSuperEffective": "It's super effective!", + "hitResultNotVeryEffective": "It's not very effective…", + "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", + "hitResultOneHitKO": "It's a one-hit KO!", + "attackFailed": "But it failed!", + "attackHitsCount": `Hit {{count}} time(s)!`, + "expGain": "{{pokemonName}} gained\n{{exp}} EXP. Points!", + "levelUp": "{{pokemonName}} grew to\nLv. {{level}}!", + "learnMove": "{{pokemonName}} learned\n{{moveName}}!", + "learnMovePrompt": "{{pokemonName}} wants to learn the\nmove {{moveName}}.", + "learnMoveLimitReached": "However, {{pokemonName}} already\nknows four moves.", + "learnMoveReplaceQuestion": "Should a move be forgotten and\nreplaced with {{moveName}}?", + "learnMoveStopTeaching": "Stop trying to teach\n{{moveName}}?", + "learnMoveNotLearned": "{{pokemonName}} did not learn the\nmove {{moveName}}.", + "learnMoveForgetQuestion": "Which move should be forgotten?", + "learnMoveForgetSuccess": "{{pokemonName}} forgot how to\nuse {{moveName}}.", + "levelCapUp": "The level cap\nhas increased to {{levelCap}}!", + "moveNotImplemented": "{{moveName}} is not yet implemented and cannot be selected.", + "moveDisabled": "{{moveName}} is disabled!", + "noPokeballForce": "An unseen force\nprevents using Poké Balls.", + "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!", + "noPokeballStrong": "The target Pokémon is too strong to be caught!\nYou need to weaken it first!", + "noEscapeForce": "An unseen force\nprevents escape.", + "noEscapeTrainer": "You can't run\nfrom a trainer battle!", + "noEscapePokemon": "{{pokemonName}}'s {{moveName}}\nprevents {{escapeVerb}}!", + "runAwaySuccess": "You got away safely!", + "runAwayCannotEscape": 'You can\'t escape!', + "escapeVerbSwitch": "switching", + "escapeVerbFlee": "fleeing", + "notDisabled": "{{moveName}} is disabled\nno more!", + "skipItemQuestion": "Are you sure you want to skip taking an item?", + "eggHatching": "Oh?", + "ivScannerUseQuestion": "Use IV Scanner on {{pokemonName}}?" +} as const; \ No newline at end of file diff --git a/src/locales/it/fight-ui-handler.ts b/src/locales/it/fight-ui-handler.ts new file mode 100644 index 00000000000..1ce9e0317bf --- /dev/null +++ b/src/locales/it/fight-ui-handler.ts @@ -0,0 +1,6 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const fightUiHandler: SimpleTranslationEntries = { + "pp": "PP", + "power": "POWER", +} as const; \ No newline at end of file diff --git a/src/locales/it/menu.ts b/src/locales/it/menu.ts index 118c1dccb5f..9812236b7f0 100644 --- a/src/locales/it/menu.ts +++ b/src/locales/it/menu.ts @@ -1,5 +1,10 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; +/** + * The menu namespace holds most miscellaneous text that isn't directly part of the game's + * contents or directly related to Pokemon data. This includes menu navigation, settings, + * account interactions, descriptive text, etc. + */ export const menu: SimpleTranslationEntries = { "cancel": "Annulla", "continue": "Continua", @@ -7,14 +12,32 @@ export const menu: SimpleTranslationEntries = { "loadGame": "Carica Partita", "dailyRun": "Corsa Giornaliera (Beta)", "selectGameMode": "Seleziona una modalità di gioco.", + "logInOrCreateAccount": "Log in or create an account to start. No email required!", + "username": "Username", + "password": "Password", + "login": "Login", + "register": "Register", + "emptyUsername": "Username must not be empty", + "invalidLoginUsername": "The provided username is invalid", + "invalidRegisterUsername": "Username must only contain letters, numbers, or underscores", + "invalidLoginPassword": "The provided password is invalid", + "invalidRegisterPassword": "Password must be 6 characters or longer", + "usernameAlreadyUsed": "The provided username is already in use", + "accountNonExistent": "The provided user does not exist", + "unmatchingPassword": "The provided password does not match", + "passwordNotMatchingConfirmPassword": "Password must match confirm password", + "confirmPassword": "Confirm Password", + "registrationAgeWarning": "By registering, you confirm you are of 13 years of age or older.", + "backToLogin": "Back to Login", + "failedToLoadSaveData": "Failed to load save data. Please reload the page.\nIf this continues, please contact the administrator.", + "sessionSuccess": "Session loaded successfully.", + "failedToLoadSession": "Your session data could not be loaded.\nIt may be corrupted.", + "boyOrGirl": "Are you a boy or a girl?", + "boy": "Boy", + "girl": "Girl", "dailyRankings": "Daily Rankings", "weeklyRankings": "Weekly Rankings", "noRankings": "No Rankings", "loading": "Loading…", - "playersOnline": "Players Online", - "hitResultCriticalHit": "A critical hit!", - "hitResultSuperEffective": "It's super effective!", - "hitResultNotVeryEffective": "It's not very effective…", - "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", - "hitResultOneHitKO": "It's a one-hit KO!" + "playersOnline": "Players Online" } as const; \ No newline at end of file diff --git a/src/phases.ts b/src/phases.ts index 2e0b8425567..72f0e10cc3e 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -815,14 +815,14 @@ export class EncounterPhase extends BattlePhase { const enemyField = this.scene.getEnemyField(); if (this.scene.currentBattle.battleSpec === BattleSpec.FINAL_BOSS) - return i18next.t('menu:bossAppeared', {bossName: enemyField[0].name}); + return i18next.t('battle:bossAppeared', {bossName: enemyField[0].name}); if (this.scene.currentBattle.battleType === BattleType.TRAINER) - return i18next.t('menu:trainerAppeared', {trainerName: this.scene.currentBattle.trainer.getName(TrainerSlot.NONE, true)}); + return i18next.t('battle:trainerAppeared', {trainerName: this.scene.currentBattle.trainer.getName(TrainerSlot.NONE, true)}); return enemyField.length === 1 - ? i18next.t('menu:singleWildAppeared', {pokemonName: enemyField[0].name}) - : i18next.t('menu:multiWildAppeared', {pokemonName1: enemyField[0].name, pokemonName2: enemyField[1].name}) + ? i18next.t('battle:singleWildAppeared', {pokemonName: enemyField[0].name}) + : i18next.t('battle:multiWildAppeared', {pokemonName1: enemyField[0].name, pokemonName2: enemyField[1].name}) } doEncounterCommon(showEncounterMessage: boolean = true) { @@ -1187,7 +1187,7 @@ export class SummonPhase extends PartyMemberPokemonPhase { } if (this.player) { - this.scene.ui.showText(i18next.t('menu:playerGo', { pokemonName: this.getPokemon().name })); + this.scene.ui.showText(i18next.t('battle:playerGo', { pokemonName: this.getPokemon().name })); if (this.player) this.scene.pbTray.hide(); this.scene.trainer.setTexture(`trainer_${this.scene.gameData.gender === PlayerGender.FEMALE ? 'f' : 'm'}_back_pb`); @@ -1355,8 +1355,8 @@ export class SwitchSummonPhase extends SummonPhase { applyPreSwitchOutAbAttrs(PreSwitchOutAbAttr, pokemon); this.scene.ui.showText(this.player ? - i18next.t('menu:playerComeBack', { pokemonName: pokemon.name }) : - i18next.t('menu:trainerComeBack', { + i18next.t('battle:playerComeBack', { pokemonName: pokemon.name }) : + i18next.t('battle:trainerComeBack', { trainerName: this.scene.currentBattle.trainer.getName(!(this.fieldIndex % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER), pokemonName: pokemon.name }) @@ -1396,8 +1396,8 @@ export class SwitchSummonPhase extends SummonPhase { party[this.fieldIndex] = switchedPokemon; const showTextAndSummon = () => { this.scene.ui.showText(this.player ? - i18next.t('menu:playerGo', { pokemonName: switchedPokemon.name }) : - i18next.t('menu:trainerGo', { + i18next.t('battle:playerGo', { pokemonName: switchedPokemon.name }) : + i18next.t('battle:trainerGo', { trainerName: this.scene.currentBattle.trainer.getName(!(this.fieldIndex % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER), pokemonName: this.getPokemon().name }) @@ -1544,7 +1544,7 @@ export class CheckSwitchPhase extends BattlePhase { return; } - this.scene.ui.showText(i18next.t('menu:switchQuestion', { pokemonName: this.useName ? pokemon.name : i18next.t('menu:pokemon') }), null, () => { + this.scene.ui.showText(i18next.t('battle:switchQuestion', { pokemonName: this.useName ? pokemon.name : i18next.t('battle:pokemon') }), null, () => { this.scene.ui.setMode(Mode.CONFIRM, () => { this.scene.ui.setMode(Mode.MESSAGE); this.scene.tryRemovePhase(p => p instanceof PostSummonPhase && p.player && p.fieldIndex === this.fieldIndex); @@ -1564,7 +1564,7 @@ export class SummonMissingPhase extends SummonPhase { } preSummon(): void { - this.scene.ui.showText(i18next.t('menu:sendOutPokemon', { pokemonName: this.getPokemon().name})); + this.scene.ui.showText(i18next.t('battle:sendOutPokemon', { pokemonName: this.getPokemon().name})); this.scene.time.delayedCall(250, () => this.summon()); } } @@ -1579,7 +1579,7 @@ export class LevelCapPhase extends FieldPhase { this.scene.ui.setMode(Mode.MESSAGE).then(() => { this.scene.playSound('level_up_fanfare'); - this.scene.ui.showText(i18next.t('menu:levelCapUp', { levelCap: this.scene.getMaxExpLevel() }), null, () => this.end(), null, true); + this.scene.ui.showText(i18next.t('battle:levelCapUp', { levelCap: this.scene.getMaxExpLevel() }), null, () => this.end(), null, true); this.executeForAll(pokemon => pokemon.updateInfo(true)); }); } @@ -1673,7 +1673,7 @@ export class CommandPhase extends FieldPhase { const move = playerPokemon.getMoveset()[cursor]; if (move.getName().endsWith(' (N)')) { this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.showText(i18next.t('menu:moveNotImplemented', { moveName: move.getName().slice(0, -4) }), null, () => { + this.scene.ui.showText(i18next.t('battle:moveNotImplemented', { moveName: move.getName().slice(0, -4) }), null, () => { this.scene.ui.clearText(); this.scene.ui.setMode(Mode.FIGHT, this.fieldIndex); }, null, true); @@ -1692,7 +1692,7 @@ export class CommandPhase extends FieldPhase { const move = playerPokemon.getMoveset()[cursor]; if (playerPokemon.summonData.disabledMove === move.moveId) { this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.showText(i18next.t('menu:moveDisabled', { moveName: move.getName() }), null, () => { + this.scene.ui.showText(i18next.t('battle:moveDisabled', { moveName: move.getName() }), null, () => { this.scene.ui.clearText(); this.scene.ui.setMode(Mode.FIGHT, this.fieldIndex); }, null, true); @@ -1703,14 +1703,14 @@ export class CommandPhase extends FieldPhase { if (this.scene.arena.biomeType === Biome.END && (!this.scene.gameMode.isClassic || (this.scene.getEnemyField().filter(p => p.isActive(true)).some(p => !p.scene.gameData.dexData[p.species.speciesId].caughtAttr) && this.scene.gameData.getStarterCount(d => !!d.caughtAttr) < Object.keys(speciesStarters).length - 1))) { this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.showText(i18next.t('menu:noPokeballForce'), null, () => { + this.scene.ui.showText(i18next.t('battle:noPokeballForce'), null, () => { this.scene.ui.showText(null, 0); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); }, null, true); } else if (this.scene.currentBattle.battleType === BattleType.TRAINER) { this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.showText(i18next.t('menu:noPokeballTrainer'), null, () => { + this.scene.ui.showText(i18next.t('battle:noPokeballTrainer'), null, () => { this.scene.ui.showText(null, 0); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); }, null, true); @@ -1719,7 +1719,7 @@ export class CommandPhase extends FieldPhase { if (targets.length > 1) { this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.showText(i18next.t('menu:noPokeballMulti'), null, () => { + this.scene.ui.showText(i18next.t('battle:noPokeballMulti'), null, () => { this.scene.ui.showText(null, 0); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); }, null, true); @@ -1728,7 +1728,7 @@ export class CommandPhase extends FieldPhase { if (targetPokemon.isBoss() && targetPokemon.bossSegmentIndex >= 1 && cursor < PokeballType.MASTER_BALL) { this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.showText(i18next.t('menu:noPokeballStrong'), null, () => { + this.scene.ui.showText(i18next.t('battle:noPokeballStrong'), null, () => { this.scene.ui.showText(null, 0); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); }, null, true); @@ -1748,14 +1748,14 @@ export class CommandPhase extends FieldPhase { if (!isSwitch && this.scene.arena.biomeType === Biome.END) { this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.showText(i18next.t('menu:noEscapeForce'), null, () => { + this.scene.ui.showText(i18next.t('battle:noEscapeForce'), null, () => { this.scene.ui.showText(null, 0); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); }, null, true); } else if (!isSwitch && this.scene.currentBattle.battleType === BattleType.TRAINER) { this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.showText(i18next.t('menu:noEscapeTrainer'), null, () => { + this.scene.ui.showText(i18next.t('battle:noEscapeTrainer'), null, () => { this.scene.ui.showText(null, 0); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); }, null, true); @@ -1778,10 +1778,10 @@ export class CommandPhase extends FieldPhase { this.scene.ui.setMode(Mode.MESSAGE); } this.scene.ui.showText( - i18next.t('menu:noEscapePokemon', { + i18next.t('battle:noEscapePokemon', { pokemonName: this.scene.getPokemonById(trapTag.sourceId).name, moveName: trapTag.getMoveName(), - escapeVerb: isSwitch ? i18next.t('menu:escapeVerbSwitch') : i18next.t('menu:escapeVerbFlee') + escapeVerb: isSwitch ? i18next.t('battle:escapeVerbSwitch') : i18next.t('battle:escapeVerbFlee') }), null, () => { @@ -2031,7 +2031,7 @@ export class TurnEndPhase extends FieldPhase { pokemon.lapseTags(BattlerTagLapseType.TURN_END); if (pokemon.summonData.disabledMove && !--pokemon.summonData.disabledTurns) { - this.scene.pushPhase(new MessagePhase(this.scene, i18next.t('menu:notDisabled', { moveName: allMoves[pokemon.summonData.disabledMove].name }))); + this.scene.pushPhase(new MessagePhase(this.scene, i18next.t('battle:notDisabled', { moveName: allMoves[pokemon.summonData.disabledMove].name }))); pokemon.summonData.disabledMove = Moves.NONE; } @@ -2339,7 +2339,7 @@ export class MovePhase extends BattlePhase { } showFailedText(failedText: string = null): void { - this.scene.queueMessage(failedText || i18next.t('menu:attackFailed')); + this.scene.queueMessage(failedText || i18next.t('battle:attackFailed')); } end() { @@ -2402,7 +2402,7 @@ export class MoveEffectPhase extends PokemonPhase { moveHistoryEntry.result = MoveResult.MISS; applyMoveAttrs(MissEffectAttr, user, null, this.move.getMove()); } else { - this.scene.queueMessage(i18next.t('menu:attackFailed')); + this.scene.queueMessage(i18next.t('battle:attackFailed')); moveHistoryEntry.result = MoveResult.FAIL; } return this.end(); @@ -2486,7 +2486,7 @@ export class MoveEffectPhase extends PokemonPhase { else { const hitsTotal = user.turnData.hitCount - Math.max(user.turnData.hitsLeft, 0); if (hitsTotal > 1) - this.scene.queueMessage(i18next.t('menu:attackHitsCount', { count: hitsTotal })); + this.scene.queueMessage(i18next.t('battle:attackHitsCount', { count: hitsTotal })); this.scene.applyModifiers(HitHealModifier, this.player, user); } } @@ -3342,7 +3342,7 @@ export class TrainerVictoryPhase extends BattlePhase { this.scene.unshiftPhase(new ModifierRewardPhase(this.scene, [ modifierTypes.VOUCHER, modifierTypes.VOUCHER, modifierTypes.VOUCHER_PLUS, modifierTypes.VOUCHER_PREMIUM ][vouchers[TrainerType[trainerType]].voucherType])); } - this.scene.ui.showText(i18next.t('menu:trainerDefeated', { trainerName: this.scene.currentBattle.trainer.getName(TrainerSlot.NONE, true) }), null, () => { + this.scene.ui.showText(i18next.t('battle:trainerDefeated', { trainerName: this.scene.currentBattle.trainer.getName(TrainerSlot.NONE, true) }), null, () => { const victoryMessages = this.scene.currentBattle.trainer.getVictoryMessages(); const showMessage = () => { let message: string; @@ -3609,7 +3609,7 @@ export class ExpPhase extends PlayerPartyMemberPokemonPhase { let exp = new Utils.NumberHolder(this.expValue); this.scene.applyModifiers(ExpBoosterModifier, true, exp); exp.value = Math.floor(exp.value); - this.scene.ui.showText(i18next.t('menu:expGain', { pokemonName: pokemon.name, exp: exp.value }), null, () => { + this.scene.ui.showText(i18next.t('battle:expGain', { pokemonName: pokemon.name, exp: exp.value }), null, () => { const lastLevel = pokemon.level; let newLevel: integer; pokemon.addExp(exp.value); @@ -3697,7 +3697,7 @@ export class LevelUpPhase extends PlayerPartyMemberPokemonPhase { pokemon.calculateStats(); pokemon.updateInfo(); this.scene.playSound('level_up_fanfare'); - this.scene.ui.showText(i18next.t('menu:levelUp', { pokemonName: this.getPokemon().name, level: this.level }), null, () => this.scene.ui.getMessageHandler().promptLevelUpStats(this.partyMemberIndex, prevStats, false).then(() => this.end()), null, true); + this.scene.ui.showText(i18next.t('battle:levelUp', { pokemonName: this.getPokemon().name, level: this.level }), null, () => this.scene.ui.getMessageHandler().promptLevelUpStats(this.partyMemberIndex, prevStats, false).then(() => this.end()), null, true); if (this.level <= 100) { const levelMoves = this.getPokemon().getLevelMoves(this.lastLevel + 1); for (let lm of levelMoves) @@ -3746,7 +3746,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { .then(() => { this.scene.ui.setMode(messageMode).then(() => { this.scene.playSound('level_up_fanfare'); - this.scene.ui.showText(i18next.t('menu:learnMove', { pokemonName: pokemon.name, moveName: move.name }), null, () => { + this.scene.ui.showText(i18next.t('battle:learnMove', { pokemonName: pokemon.name, moveName: move.name }), null, () => { this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeMoveLearnedTrigger, true); this.end(); }, messageMode === Mode.EVOLUTION_SCENE ? 1000 : null, true); @@ -3755,15 +3755,15 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { }); } else { this.scene.ui.setMode(messageMode).then(() => { - this.scene.ui.showText(i18next.t('menu:learnMovePrompt', { pokemonName: pokemon.name, moveName: move.name }), null, () => { - this.scene.ui.showText(i18next.t('menu:learnMoveLimitReached', { pokemonName: pokemon.name }), null, () => { - this.scene.ui.showText(i18next.t('menu:learnMoveReplaceQuestion', { moveName: move.name }), null, () => { + this.scene.ui.showText(i18next.t('battle:learnMovePrompt', { pokemonName: pokemon.name, moveName: move.name }), null, () => { + this.scene.ui.showText(i18next.t('battle:learnMoveLimitReached', { pokemonName: pokemon.name }), null, () => { + this.scene.ui.showText(i18next.t('battle:learnMoveReplaceQuestion', { moveName: move.name }), null, () => { const noHandler = () => { this.scene.ui.setMode(messageMode).then(() => { - this.scene.ui.showText(i18next.t('menu:learnMoveStopTeaching', { moveName: move.name }), null, () => { + this.scene.ui.showText(i18next.t('battle:learnMoveStopTeaching', { moveName: move.name }), null, () => { this.scene.ui.setModeWithoutClear(Mode.CONFIRM, () => { this.scene.ui.setMode(messageMode); - this.scene.ui.showText(i18next.t('menu:learnMoveNotLearned', { pokemonName: pokemon.name, moveName: move.name }), null, () => this.end(), null, true); + this.scene.ui.showText(i18next.t('battle:learnMoveNotLearned', { pokemonName: pokemon.name, moveName: move.name }), null, () => this.end(), null, true); }, () => { this.scene.ui.setMode(messageMode); this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.partyMemberIndex, this.moveId)); @@ -3774,7 +3774,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { }; this.scene.ui.setModeWithoutClear(Mode.CONFIRM, () => { this.scene.ui.setMode(messageMode); - this.scene.ui.showText(i18next.t('menu:learnMoveForgetQuestion'), null, () => { + this.scene.ui.showText(i18next.t('battle:learnMoveForgetQuestion'), null, () => { this.scene.ui.setModeWithoutClear(Mode.SUMMARY, this.getPokemon(), SummaryUiMode.LEARN_MOVE, move, (moveIndex: integer) => { if (moveIndex === 4) { noHandler(); @@ -3782,7 +3782,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { } this.scene.ui.setMode(messageMode).then(() => { this.scene.ui.showText('@d{32}1, @d{15}2, and@d{15}… @d{15}… @d{15}… @d{15}@s{pb_bounce_1}Poof!', null, () => { - this.scene.ui.showText(i18next.t('menu:learnMoveForgetSuccess', { pokemonName: pokemon.name, moveName: pokemon.moveset[moveIndex].getName() }), null, () => { + this.scene.ui.showText(i18next.t('battle:learnMoveForgetSuccess', { pokemonName: pokemon.name, moveName: pokemon.moveset[moveIndex].getName() }), null, () => { this.scene.ui.showText('And…', null, () => { pokemon.setMove(moveIndex, Moves.NONE); this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.partyMemberIndex, this.moveId)); @@ -4097,7 +4097,7 @@ export class AttemptCapturePhase extends PokemonPhase { this.scene.gameData.updateSpeciesDexIvs(pokemon.species.getRootSpeciesId(true), pokemon.ivs); - this.scene.ui.showText(i18next.t('menu:pokemonCaught', { pokemonName: pokemon.name }), null, () => { + this.scene.ui.showText(i18next.t('battle:pokemonCaught', { pokemonName: pokemon.name }), null, () => { const end = () => { this.scene.pokemonInfoContainer.hide(); this.removePb(); @@ -4183,7 +4183,7 @@ export class AttemptRunPhase extends PokemonPhase { if (playerPokemon.randSeedInt(256) < escapeChance.value) { this.scene.playSound('flee'); - this.scene.queueMessage(i18next.t('menu:runAwaySuccess'), null, true, 500); + this.scene.queueMessage(i18next.t('battle:runAwaySuccess'), null, true, 500); this.scene.tweens.add({ targets: [ this.scene.arenaEnemy, enemyField ].flat(), @@ -4204,7 +4204,7 @@ export class AttemptRunPhase extends PokemonPhase { this.scene.pushPhase(new BattleEndPhase(this.scene)); this.scene.pushPhase(new NewBattlePhase(this.scene)); } else - this.scene.queueMessage(i18next.t('menu:runAwayCannotEscape'), null, true, 500); + this.scene.queueMessage(i18next.t('battle:runAwayCannotEscape'), null, true, 500); this.end(); } @@ -4236,7 +4236,7 @@ export class SelectModifierPhase extends BattlePhase { const modifierSelectCallback = (rowCursor: integer, cursor: integer) => { if (rowCursor < 0 || cursor < 0) { - this.scene.ui.showText(i18next.t('menu:skipItemQuestion'), null, () => { + this.scene.ui.showText(i18next.t('battle:skipItemQuestion'), null, () => { this.scene.ui.setOverlayMode(Mode.CONFIRM, () => { this.scene.ui.revertMode(); this.scene.ui.setMode(Mode.MESSAGE); @@ -4415,7 +4415,7 @@ export class EggLapsePhase extends Phase { }); if (eggsToHatch.length) { - this.scene.queueMessage(i18next.t('menu:eggHatching')); + this.scene.queueMessage(i18next.t('battle:eggHatching')); for (let egg of eggsToHatch) this.scene.unshiftPhase(new EggHatchPhase(this.scene, egg)); @@ -4509,7 +4509,7 @@ export class ScanIvsPhase extends PokemonPhase { const pokemon = this.getPokemon(); - this.scene.ui.showText(i18next.t('menu:ivScannerUseQuestion', { pokemonName: pokemon.name }), null, () => { + this.scene.ui.showText(i18next.t('battle:ivScannerUseQuestion', { pokemonName: pokemon.name }), null, () => { this.scene.ui.setMode(Mode.CONFIRM, () => { this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.clearText(); diff --git a/src/plugins/i18n.ts b/src/plugins/i18n.ts index 22a407c3b42..4d770ae0a12 100644 --- a/src/plugins/i18n.ts +++ b/src/plugins/i18n.ts @@ -13,6 +13,12 @@ import { menuUiHandler as frMenuUiHandler } from '../locales/fr/menu-ui-handler. import { menuUiHandler as itMenuUiHandler } from '../locales/it/menu-ui-handler.js'; import { menuUiHandler as deMenuUiHandler } from '../locales/de/menu-ui-handler.js'; +import { battle as enBattle } from '../locales/en/battle'; +import { battle as esBattle } from '../locales/es/battle'; +import { battle as itBattle } from '../locales/it/battle'; +import { battle as frBattle } from '../locales/fr/battle'; +import { battle as deBattle } from '../locales/de/battle'; + import { move as enMove } from '../locales/en/move'; import { move as esMove } from '../locales/es/move'; import { move as frMove } from '../locales/fr/move'; @@ -45,7 +51,10 @@ import { commandUiHandler as frCommandUiHandler } from '../locales/fr/command-ui import { commandUiHandler as deCommandUiHandler } from '../locales/de/command-ui-handler'; import { fightUiHandler as enFightUiHandler } from '../locales/en/fight-ui-handler'; +import { fightUiHandler as esFightUiHandler } from '../locales/es/fight-ui-handler'; import { fightUiHandler as frFightUiHandler } from '../locales/fr/fight-ui-handler'; +import { fightUiHandler as itFightUiHandler } from '../locales/it/fight-ui-handler'; +import { fightUiHandler as deFightUiHandler } from '../locales/de/fight-ui-handler'; import { tutorial as enTutorial } from '../locales/en/tutorial'; import { tutorial as esTutorial } from '../locales/es/tutorial'; @@ -113,6 +122,7 @@ export function initI18n(): void { en: { menu: enMenu, menuUiHandler: enMenuUiHandler, + battle: enBattle, move: enMove, ability: enAbility, pokeball: enPokeball, @@ -125,17 +135,20 @@ export function initI18n(): void { es: { menu: esMenu, menuUiHandler: esMenuUiHandler, + battle: esBattle, move: esMove, ability: esAbility, pokeball: esPokeball, pokemon: esPokemon, pokemonStat: esPokemonStat, commandUiHandler: esCommandUiHandler, + fightUiHandler: esFightUiHandler, tutorial: esTutorial, }, fr: { menu: frMenu, menuUiHandler: frMenuUiHandler, + battle: frBattle, move: frMove, ability: frAbility, pokeball: frPokeball, @@ -148,18 +161,22 @@ export function initI18n(): void { it: { menu: itMenu, menuUiHandler: itMenuUiHandler, + battle: itBattle, pokemonStat: itPokemonStat, + fightUiHandler: itFightUiHandler, tutorial: itTutorial, }, de: { menu: deMenu, menuUiHandler: deMenuUiHandler, + battle: deBattle, move: deMove, ability: deAbility, pokeball: dePokeball, pokemon: dePokemon, pokemonStat: dePokemonStat, commandUiHandler: deCommandUiHandler, + fightUiHandler: deFightUiHandler, tutorial: deTutorial, } }, @@ -173,6 +190,7 @@ declare module 'i18next' { menu: typeof enMenu; menuUiHandler: typeof enMenuUiHandler; move: typeof enMove; + battle: typeof enBattle, ability: typeof enAbility; pokeball: typeof enPokeball; pokemon: typeof enPokemon; From ad59c0a7c4ae8543aba02e9ed39052545207ceac Mon Sep 17 00:00:00 2001 From: Benjamin Odom Date: Wed, 1 May 2024 18:05:34 -0500 Subject: [PATCH 25/45] Fixed Rounding Error For TargetHalfHpDamageAttr Moves that deal half of a target's HP were not able to deal damage if the target had 1 HP. Used Math.max to ensure 1 is the lowest this value ever evaluates to. --- src/data/move.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/move.ts b/src/data/move.ts index d6367794a35..ad1ae31c06f 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -557,7 +557,7 @@ export class TargetHalfHpDamageAttr extends FixedDamageAttr { } apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - (args[0] as Utils.IntegerHolder).value = Math.floor(target.hp / 2); + (args[0] as Utils.IntegerHolder).value = Math.max(Math.floor(target.hp / 2), 1); return true; } From 86b0596a60d831eadc78de3ae57b202ab780d14c Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Wed, 1 May 2024 19:28:07 -0400 Subject: [PATCH 26/45] Add rogue achievement and voucher tier --- public/images/ui/achv_bar_4.png | Bin 458 -> 418 bytes public/images/ui/achv_bar_5.png | Bin 0 -> 458 bytes public/images/ui/legacy/achv_bar_4.png | Bin 433 -> 344 bytes public/images/ui/legacy/achv_bar_5.png | Bin 0 -> 433 bytes src/system/achv.ts | 5 ++++- src/system/voucher.ts | 2 +- 6 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 public/images/ui/achv_bar_5.png create mode 100644 public/images/ui/legacy/achv_bar_5.png diff --git a/public/images/ui/achv_bar_4.png b/public/images/ui/achv_bar_4.png index cc06af91620256e98ab26c762a49fe432cf584ce..debf8bfe2114a634e6f39e696088cca466d3a8d6 100644 GIT binary patch delta 394 zcmV;50d@Y$1EK?v7k?%Q0ssI2#x!fF00001b5ch_0Itp)=>Px$LPe5nZXH! zFc3wpBK4#ItH>!mqy-DuyQkdKgXJs;o?T>M+#TW)c4Hjj!yw5ej4ywZ@7OtG5Q0D_ z=9oHT03}l>fKmn}d0##5Rh3dHjAMy$o##JeiIEq)5tlraDt|->D02anU1ET;v*5Y| z6hJ9EhM^QFK*77B-cF_7tPTmjJD!-mLD1)_}DDB>PJ|%hYjCu6^6oT5=pb!Y! zy*5zP;-JJXgYq0l_A=TA*Fe!sWS!@0plFkZ$Olj|-U?6vrOa?bDF;evZ{Ebgrfs?@ z+(6HB&)Ca o0#&KYjDGtnRR9104rN$LW=%~1DgXcg2mk;800000(v!Ra4yk6PRR910 delta 411 zcmV;M0c8H71Ih!C7k?-S1^@s6b6lN|00001b5ch_0Itp)=>Px$YDq*vRA_DP__;of?62bTd;NQQCQhHNFtOB4BZe*7Di40I}8YfDoB_3*|Oia zMUmn^pOP0RegQ?4r?39U(RGNJ=(r9L8!B8F6)uc;y_*&*X^7a3YUo7pI@nQ#`fV5VOgs5Im<(9|lzo(r!xMo&& z-}A2B{AZ(YPQEzf@0RS;5BDB9#ED&hE3w3Un#k-;jNdNnO}=>J*2h|x>>UOW&0OMc zt=yjrT8X)$q#B=8ROsDu0jaQ>BteDVa??MX7Vv(E4&|GC<6uLL{*U??yJc5Pd0V!AT5KPxnOMwJ q?cnataG_EN7zKQ(5uRzjz6@GGHU|)cz@^~HAj;F#&t;ucLK6T2Ilt8a literal 0 HcmV?d00001 diff --git a/public/images/ui/legacy/achv_bar_4.png b/public/images/ui/legacy/achv_bar_4.png index dae7a30dec065d67334e6c7cbac6c05716d38fef..d52fbfd055e8a4839ab16a495f9dcccbcbdd71a5 100644 GIT binary patch delta 329 zcmdnUe1mC%L_G^L0|P^2QNtb}#aJBV?!<0h-v4*igLY0h6zQhc&hD}*Eg|98VGW)C zo{X+< zFWp}Gqp9Qyz2uY-l{Gwk_ZS)E-p|raFcyCUbTnUTglC$sFM}44%>l$9a4C2)i1Kvx Kb6Mw<&;$VCBZQ*> delta 419 zcmV;U0bKsr0n6zU{cp-{T%Si1Th`~q2ngF_cV1fg~gbjao)E?p$akUdLgUA%IME?RSG;`1Nd zlw5y3(n9lUD0P2!^ZxSo3buWR`v;gTr<(kjR)&tU1aY2H>wgb&3=6Jl7vMF4{rLQZ zI8O@)vEL_eUdOO7>J2ejPBmRT8RsbmR=@B9wq34i!!>OLX}Iy!#O@Xc06>t2wJcEn zz}r-mB>;d?ZwS4-yMr{u)$t7H50^?8wHVLgt^8J^%e%ZIf1`?2W7l;~mA_U*9bReG zMsR`?oDrPhjDO&}nclSDu>`NUi@TF{NFOx-Tbo@x`5Y#$z$gH&I9Hu3-f N002ovPDHLkV1jh6!Y}{; diff --git a/public/images/ui/legacy/achv_bar_5.png b/public/images/ui/legacy/achv_bar_5.png new file mode 100644 index 0000000000000000000000000000000000000000..dae7a30dec065d67334e6c7cbac6c05716d38fef GIT binary patch literal 433 zcmV;i0Z#sjP)7@C0mv(P8pKm(nTD)6%^_uSfNn5=~%k@9sB}WgM&jCK?I?84s^)oATC`b z$&fuuW?j5;i7r}mY2x!A+mu{?J<>w+YAAJocJu!7_6oLrhx-SZET@|Mm{x|4vIKFS zQtJJ2ejPBmRT8RsbmR=@B9wq34i!!>OL zX}Iy!#O@Xc06>t2wJcEnz}r-mB>;d?ZwS4-yMr{u)$t7H50^?8wHVLgt^8J^%e%ZI zf1`?2W7l;~mA_U*9bReGMsR`?oDrPhjNrSO-n8Gb1h2S@yOVZEA2k46>};po}6Pyv8;Os}>i}76fLh3kY9ew$WZD94`t$cWUzVgMi z^>*cN!Q~t9|HB(sS-f5s!5zawlqEYmY9cSViCv%G!Z9oWpA!%qrm8l1ZfY}B#hIRJ b6O(Ko9+rbtUwk(500000NkvXXu0mjfWv;=( literal 0 HcmV?d00001 diff --git a/src/system/achv.ts b/src/system/achv.ts index 2307347db3a..f63dd5b2810 100644 --- a/src/system/achv.ts +++ b/src/system/achv.ts @@ -7,6 +7,7 @@ export enum AchvTier { COMMON, GREAT, ULTRA, + ROGUE, MASTER } @@ -50,8 +51,10 @@ export class Achv { } getTier(): AchvTier { - if (this.score >= 100) + if (this.score >= 150) return AchvTier.MASTER; + if (this.score >= 100) + return AchvTier.ROGUE; if (this.score >= 50) return AchvTier.ULTRA; if (this.score >= 25) diff --git a/src/system/voucher.ts b/src/system/voucher.ts index c3bae6f0878..276e74eeb0d 100644 --- a/src/system/voucher.ts +++ b/src/system/voucher.ts @@ -44,7 +44,7 @@ export class Voucher { case VoucherType.PREMIUM: return AchvTier.ULTRA; case VoucherType.GOLDEN: - return AchvTier.MASTER; + return AchvTier.ROGUE; } } } From 2f8000885e2db76b607fdff06c26b7696284d491 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Wed, 1 May 2024 19:29:04 -0400 Subject: [PATCH 27/45] Fix coloring error in rogue achievement bar --- public/images/ui/achv_bar_4.png | Bin 418 -> 318 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/public/images/ui/achv_bar_4.png b/public/images/ui/achv_bar_4.png index debf8bfe2114a634e6f39e696088cca466d3a8d6..f14026c7a34c13829053ffaa2291bda986ab9a3c 100644 GIT binary patch delta 270 zcmZ3)ypL&uc)bP-GXn!dV^PB%AjMc5hfTEf3IKb_|iYz z`ktrkcX2!j)5|Irh^<_ql=sx>kNm}{?V1yo#iTQ9o;sXAImK%7!4DyQs>T&o#ClL1!5l5_R&8W;0LU KRzA6gQ4IjBLuz*b delta 394 zcmV;50d@Yq0-^(u7k?%Q0ssI2#x!fF00001b5ch_0Itp)=>Px$LPe5nZXH! zFc3wpBK4#ItH>!mqy-DuyQkdKgXJs;o?T>M+#TW)c4Hjj!yw5ej4ywZ@7OtG5Q0D_ z=9oHT03}l>fKmn}d0##5Rh3dHjAMy$o##JeiIEq)5tlraDt|->D02anU1ET;v*5Y| z6hJ9EhM^QFK*77B-cF_7tPTmjJD!-mLD1)_}DDB>PJ|%hYjCu6^6oT5=pb!Y! zy*5zP;-JJXgYq0l_A=TA*Fe!sWS!@0plFkZ$Olj|-U?6vrOa?bDF;evZ{Ebgrfs?@ z+(6HB&)Ca o0#&KYjDGtnRR9104rN$LW=%~1DgXcg2mk;800000(vvU&4wJ#8yZ`_I From ba5bef123cffbadffd120f90960f94ea99f6efea Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Wed, 1 May 2024 19:42:06 -0400 Subject: [PATCH 28/45] Load missed master achievement bar --- src/loading-scene.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/loading-scene.ts b/src/loading-scene.ts index 875d618ec0f..d0751e9a2da 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -67,6 +67,7 @@ export class LoadingScene extends SceneBase { this.loadImage('achv_bar_2', 'ui'); this.loadImage('achv_bar_3', 'ui'); this.loadImage('achv_bar_4', 'ui'); + this.loadImage('achv_bar_5', 'ui'); this.loadImage('shiny_star', 'ui', 'shiny.png'); this.loadImage('shiny_star_1', 'ui', 'shiny_1.png'); this.loadImage('shiny_star_2', 'ui', 'shiny_2.png'); From 6d9424e43158123f9bceff53f5499f53f59ea694 Mon Sep 17 00:00:00 2001 From: Xavion3 Date: Thu, 2 May 2024 14:22:30 +1000 Subject: [PATCH 29/45] Implement Gastro Acid (#393) --- src/data/move.ts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/data/move.ts b/src/data/move.ts index ad1ae31c06f..e1694ede8a3 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -3594,6 +3594,25 @@ export class SwitchAbilitiesAttr extends MoveEffectAttr { } } +export class SuppressAbilitiesAttr extends MoveEffectAttr { + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + if (!super.apply(user, target, move, args)) + return false; + + target.summonData.abilitySuppressed = true; + + target.scene.queueMessage(getPokemonMessage(target, ` ability\nwas suppressed!`)); + + return true; + } + + getCondition(): MoveConditionFunc { + return (user, target, move) => !target.getAbility().hasAttr(UnsuppressableAbilityAbAttr); + } +} + + + export class TransformAttr extends MoveEffectAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise { return new Promise(resolve => { @@ -4831,7 +4850,7 @@ export function initMoves() { new SelfStatusMove(Moves.POWER_TRICK, Type.PSYCHIC, -1, 10, -1, 0, 4) .unimplemented(), new StatusMove(Moves.GASTRO_ACID, Type.POISON, 100, 10, -1, 0, 4) - .unimplemented(), + .attr(SuppressAbilitiesAttr), new StatusMove(Moves.LUCKY_CHANT, Type.NORMAL, -1, 30, -1, 0, 4) .attr(AddBattlerTagAttr, BattlerTagType.NO_CRIT, false, false, 5) .target(MoveTarget.USER_SIDE) From a1bb0e7baf00d4f11929e360652537a2dc7dfc8a Mon Sep 17 00:00:00 2001 From: Lugiad Date: Thu, 2 May 2024 06:26:24 +0200 Subject: [PATCH 30/45] Updated French transaltion for tutorial.ts (#375) Translation of "statChange" + some remaning typos --- src/locales/fr/tutorial.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/locales/fr/tutorial.ts b/src/locales/fr/tutorial.ts index b60ccc03b5d..1502b285356 100644 --- a/src/locales/fr/tutorial.ts +++ b/src/locales/fr/tutorial.ts @@ -8,7 +8,7 @@ export const tutorial: SimpleTranslationEntries = { $Tout signalement de bugs passe par le serveur Discord. $Si le jeu est lent, vérifiez que l’Accélération Matérielle est activée dans les paramètres du navigateur.`, - "accessMenu": `Accédez au menu avec M ou Échap lors de l'attente d’une\naction. + "accessMenu": `Accédez au menu avec M ou Échap lors de l’attente d’une\naction. $Il contient les paramètres et diverses fonctionnalités`, "menu": `Vous pouvez accéder aux paramètres depuis ce menu. @@ -17,17 +17,20 @@ export const tutorial: SimpleTranslationEntries = { $jetez-y un œil !`, "starterSelect": `Choisissez vos starters depuis cet écran.\nIls formeront votre équipe de départ. - $Chacun possède une valeur. Votre équipe peut avoir jusqu’à\n6 membres, tant que vous ne dépassez pas un coût de 10. + $Chacun possède une valeur. Votre équipe peut avoir jusqu’à\n6 membres, tant que vous ne dépassez pas un cout de 10. $Vous pouvez aussi choisir le sexe, le talent et la forme en\nfonction des variants déjà capturés ou éclos. $Les IVs d’un starter sont les meilleurs de tous ceux de son\nespèce déjà obtenus. Essayez donc d’en obtenir plusieurs !`, "pokerus": `Chaque jour, 3 starters tirés aléatoirement ont un contour $violet. Si un starter que vous possédez l’a, essayez de - $ l’ajouter à votre équipe. Vérifiez bien son résumé !`, + $l’ajouter à votre équipe. Vérifiez bien son résumé !`, - "statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. - $Your Pokémon are recalled before a trainer battle and before entering a new biome. - $You can also view the stat changes for the Pokémon on the field by holding C or Shift.`, + "statChange": `Les changements de stats restent à travers les combats tant que le Pokémon + $n’est pas rappelé. + $Vos Pokémon sont rappelés avant un combat de Dresseur et avant d’entrer + $dans un nouveau biome. + $Vous pouvez également voir en combat les changements de stats d’un Pokémon + $en maintenant C ou Maj.`, "selectItem": `Après chaque combat, vous avez le choix entre 3 objets\ntirés au sort. Vous ne pouvez en prendre qu’un. $Cela peut être des objets consommables, des objets à\nfaire tenir, ou des objets passifs aux effets permanents. @@ -44,4 +47,4 @@ export const tutorial: SimpleTranslationEntries = { $Les Pokémon issus d’Œufs ont généralement de\nmeilleurs IVs que les Pokémon sauvages. $Certains Pokémon ne peuvent être obtenus\nque dans des Œufs. $Il y a 3 différentes machines à actionner avec différents\nbonus, prenez celle qui vous convient le mieux !`, -} as const; \ No newline at end of file +} as const; From c9152cda3f27c0277cedc7782cad00a39428163f Mon Sep 17 00:00:00 2001 From: Benjamin Odom Date: Thu, 2 May 2024 00:17:32 -0500 Subject: [PATCH 31/45] Fix Mobile PWA not showing in true Fullscreen (#394) * Fixed Rounding Error For TargetHalfHpDamageAttr Moves that deal half of a target's HP were not able to deal damage if the target had 1 HP. Used Math.max to ensure 1 is the lowest this value ever evaluates to. * Fix Mobile PWA not showing in true Fullscreen adding "fullscreen" to the display attribute wasn't enough, but adding it to the start_url attribute was. This does not appear to affect PC (which is good since it shouldn't). * Allow any orientation for mobile PWA remove the orientation restriction since it doesn't prevent fullscreen PWA from displaying properly. --- public/manifest.webmanifest | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/public/manifest.webmanifest b/public/manifest.webmanifest index c75c70a8d45..4b5f2dbadd1 100644 --- a/public/manifest.webmanifest +++ b/public/manifest.webmanifest @@ -3,9 +3,8 @@ "short_name": "PokéRogue", "description": "A Pokémon fangame heavily inspired by the roguelite genre. Battle endlessly while gathering stacking items, exploring many different biomes, and reaching Pokémon stats you never thought possible.", "scope": "/", - "start_url": "/", + "start_url": "https://pokerogue.net", "display": "fullscreen", - "orientation": "landscape", "background_color": "#8c8c8c", "theme_color": "#8c8c8c", "icons": [ From 71893e8428f410c8d22ee31abb87223ba0336977 Mon Sep 17 00:00:00 2001 From: Lugiad Date: Thu, 2 May 2024 14:34:59 +0200 Subject: [PATCH 32/45] Update Spanish fight-ui-handler.ts --- src/locales/es/fight-ui-handler.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/locales/es/fight-ui-handler.ts b/src/locales/es/fight-ui-handler.ts index 1ce9e0317bf..b431e3b7065 100644 --- a/src/locales/es/fight-ui-handler.ts +++ b/src/locales/es/fight-ui-handler.ts @@ -2,5 +2,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const fightUiHandler: SimpleTranslationEntries = { "pp": "PP", - "power": "POWER", -} as const; \ No newline at end of file + "power": "POTENCIA", +} as const; From 10506f9cf58975088836db96aad2fca691ab7889 Mon Sep 17 00:00:00 2001 From: Lugiad Date: Thu, 2 May 2024 14:37:05 +0200 Subject: [PATCH 33/45] Update italian pokemon-stat.ts (#389) * Update italian pokemon-stat.ts * Update italian pokemon-stat.ts --- src/locales/it/pokemon-stat.ts | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/locales/it/pokemon-stat.ts b/src/locales/it/pokemon-stat.ts index 7a209461b11..a3a62edebe2 100644 --- a/src/locales/it/pokemon-stat.ts +++ b/src/locales/it/pokemon-stat.ts @@ -1,16 +1,16 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const pokemonStat: SimpleTranslationEntries = { - "HP": "Max. HP", - "HPshortened": "MaxHP", - "ATK": "Attack", - "ATKshortened": "Atk", - "DEF": "Defense", - "DEFshortened": "Def", - "SPATK": "Sp. Atk", - "SPATKshortened": "SpAtk", - "SPDEF": "Sp. Def", - "SPDEFshortened": "SpDef", - "SPD": "Speed", - "SPDshortened": "Spd" -} as const; \ No newline at end of file + "HP": "PS Max", + "HPshortened": "PS", + "ATK": "Attacco", + "ATKshortened": "Att", + "DEF": "Difensa", + "DEFshortened": "Dif", + "SPATK": "Att. Sp.", + "SPATKshortened": "AttSp", + "SPDEF": "Dif. Sp.", + "SPDEFshortened": "DifSp", + "SPD": "Velocità", + "SPDshortened": "Vel" +} as const; From 0185dd639e0238b60a248d4f0f51dc89c245bebe Mon Sep 17 00:00:00 2001 From: James Lin Date: Thu, 2 May 2024 05:44:10 -0700 Subject: [PATCH 34/45] Catch global errors and rejected promises and display them in an alert box. (#351) * Catch errors and rejected promises. * Clean up --- src/main.ts | 16 ++++++++++++++++ src/phases.ts | 2 ++ src/ui/daily-run-scoreboard.ts | 2 +- src/ui/title-ui-handler.ts | 3 +++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/main.ts b/src/main.ts index 6a00693fc71..4b181f58174 100644 --- a/src/main.ts +++ b/src/main.ts @@ -9,6 +9,22 @@ import BBCodeText from 'phaser3-rex-plugins/plugins/bbcodetext'; import TransitionImagePackPlugin from 'phaser3-rex-plugins/templates/transitionimagepack/transitionimagepack-plugin.js'; import { LoadingScene } from './loading-scene'; + +// Catch global errors and display them in an alert so users can report the issue. +window.onerror = function (message, source, lineno, colno, error) { + console.error(error); + let errorString = `Received unhandled error. Open browser console and click OK to see details.\nError: ${message}\nSource: ${source}\nLine: ${lineno}\nColumn: ${colno}\nStack: ${error.stack}`; + alert(errorString); + // Avoids logging the error a second time. + return true; +}; + +// Catch global promise rejections and display them in an alert so users can report the issue. +window.addEventListener('unhandledrejection', (event) => { + let errorString = `Received unhandled promise rejection. Open browser console and click OK to see details.\nReason: ${event.reason}`; + alert(errorString); + }); + const config: Phaser.Types.Core.GameConfig = { type: Phaser.WEBGL, parent: 'app', diff --git a/src/phases.ts b/src/phases.ts index 72f0e10cc3e..2ffa25aef0f 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -331,6 +331,8 @@ export class TitlePhase extends Phase { this.scene.sessionPlayTime = 0; this.end(); }); + }).catch(err => { + console.error("Failed to load daily run:\n", err); }); }); } diff --git a/src/ui/daily-run-scoreboard.ts b/src/ui/daily-run-scoreboard.ts index 8f7ca0bf110..8b258b3a702 100644 --- a/src/ui/daily-run-scoreboard.ts +++ b/src/ui/daily-run-scoreboard.ts @@ -167,7 +167,7 @@ export class DailyRunScoreboard extends Phaser.GameObjects.Container { } else this.loadingLabel.setText(i18next.t('menu:noRankings')); }); - }); + }).catch(err => { console.error("Failed to load daily rankings:\n", err) }); } } diff --git a/src/ui/title-ui-handler.ts b/src/ui/title-ui-handler.ts index c430764e4da..6f873c6b0a1 100644 --- a/src/ui/title-ui-handler.ts +++ b/src/ui/title-ui-handler.ts @@ -65,6 +65,9 @@ export default class TitleUiHandler extends OptionSelectUiHandler { this.playerCountLabel.setText(`${stats.playerCount} ${i18next.t("menu:playersOnline")}`); if (this.splashMessage === battleCountSplashMessage) this.splashMessageText.setText(battleCountSplashMessage.replace('{COUNT}', stats.battleCount.toLocaleString('en-US'))); + }) + .catch(err => { + console.error("Failed to fetch title stats:\n", err); }); } From 3a7a48fe833f9ab1a10339f3fdd4b10b190cdae3 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Thu, 2 May 2024 09:00:36 -0400 Subject: [PATCH 35/45] Temporarily disable error handling --- src/main.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main.ts b/src/main.ts index 4b181f58174..b3b4d5f3cc6 100644 --- a/src/main.ts +++ b/src/main.ts @@ -14,7 +14,7 @@ import { LoadingScene } from './loading-scene'; window.onerror = function (message, source, lineno, colno, error) { console.error(error); let errorString = `Received unhandled error. Open browser console and click OK to see details.\nError: ${message}\nSource: ${source}\nLine: ${lineno}\nColumn: ${colno}\nStack: ${error.stack}`; - alert(errorString); + //alert(errorString); // Avoids logging the error a second time. return true; }; @@ -22,8 +22,9 @@ window.onerror = function (message, source, lineno, colno, error) { // Catch global promise rejections and display them in an alert so users can report the issue. window.addEventListener('unhandledrejection', (event) => { let errorString = `Received unhandled promise rejection. Open browser console and click OK to see details.\nReason: ${event.reason}`; - alert(errorString); - }); + console.error(event.reason); + //alert(errorString); +}); const config: Phaser.Types.Core.GameConfig = { type: Phaser.WEBGL, From 322838cfb5a9d486e0f46e60c85efbeb7f1b564b Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Thu, 2 May 2024 11:37:06 -0400 Subject: [PATCH 36/45] Move service-worker to public folder --- service-worker.js => public/service-worker.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename service-worker.js => public/service-worker.js (100%) diff --git a/service-worker.js b/public/service-worker.js similarity index 100% rename from service-worker.js rename to public/service-worker.js From ddb4383b1f9620fbc5040189076eba57668e3985 Mon Sep 17 00:00:00 2001 From: Madmadness65 Date: Thu, 2 May 2024 14:01:57 -0500 Subject: [PATCH 37/45] Move Porygon line down to Rare in Factory biome This makes the Porygon line more common than before. --- src/data/biomes.ts | 12 ++++++------ src/data/move.ts | 5 +---- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/data/biomes.ts b/src/data/biomes.ts index d6e84bcbc7c..c6a3c95b631 100644 --- a/src/data/biomes.ts +++ b/src/data/biomes.ts @@ -615,7 +615,7 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ Species.QWILFISH, Species.CORSOLA, Species.OCTILLERY, { 1: [ Species.MANTYKE ], 20: [ Species.MANTINE ] }, Species.ALOMOMOLA, { 1: [ Species.TYNAMO ], 39: [ Species.EELEKTRIK ] }, Species.DHELMISE ] + [TimeOfDay.ALL]: [ Species.QWILFISH, Species.CORSOLA, Species.OCTILLERY, { 1: [ Species.MANTYKE ], 52: [ Species.MANTINE ] }, Species.ALOMOMOLA, { 1: [ Species.TYNAMO ], 39: [ Species.EELEKTRIK ] }, Species.DHELMISE ] }, [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], @@ -1128,8 +1128,8 @@ export const biomePokemonPools: BiomePokemonPools = { ] }, [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.BRONZOR ], 33: [ Species.BRONZONG ] }, Species.KLEFKI ] }, - [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.PORYGON ], 30: [ Species.PORYGON2 ] }, { 1: [ Species.BELDUM ], 20: [ Species.METANG ], 45: [ Species.METAGROSS ] } ] }, + [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.PORYGON ], 30: [ Species.PORYGON2 ] } ] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.BELDUM ], 20: [ Species.METANG ], 45: [ Species.METAGROSS ] } ] }, [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.GENESECT, Species.MAGEARNA ] }, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KLINKLANG, Species.KLEFKI ] }, [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, @@ -1319,7 +1319,7 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [ Species.VESPIQUEN, { 1: [ Species.CHERUBI ], 25: [ Species.CHERRIM ] }, { 1: [ Species.SEWADDLE ], 20: [ Species.SWADLOON ], 30: [ Species.LEAVANNY ] } ], [TimeOfDay.DUSK]: [ Species.SHROOMISH, { 1: [ Species.PURRLOIN ], 20: [ Species.LIEPARD ] }, { 1: [ Species.FOONGUS ], 39: [ Species.AMOONGUSS ] } ], [TimeOfDay.NIGHT]: [ { 1: [ Species.SPINARAK ], 22: [ Species.ARIADOS ] }, Species.SHROOMISH, { 1: [ Species.PURRLOIN ], 20: [ Species.LIEPARD ] }, { 1: [ Species.FOONGUS ], 39: [ Species.AMOONGUSS ] } ], - [TimeOfDay.ALL]: [ Species.AIPOM, { 1: [ Species.BLITZLE ], 27: [ Species.ZEBSTRIKA ] }, { 1: [ Species.PIKIPEK ], 14: [ Species.TRUMBEAK ], 36: [ Species.TOUCANNON ] } ] + [TimeOfDay.ALL]: [ Species.AIPOM, { 1: [ Species.BLITZLE ], 27: [ Species.ZEBSTRIKA ] }, { 1: [ Species.PIKIPEK ], 14: [ Species.TRUMBEAK ], 28: [ Species.TOUCANNON ] } ] }, [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [ Species.EXEGGCUTE, Species.TROPIUS, Species.COMBEE, Species.KOMALA ], @@ -2708,7 +2708,7 @@ export const biomeTrainerPools: BiomeTrainerPools = { ] ], [ Species.PORYGON, Type.NORMAL, -1, [ - [ Biome.FACTORY, BiomePoolTier.SUPER_RARE ], + [ Biome.FACTORY, BiomePoolTier.RARE ], [ Biome.SPACE, BiomePoolTier.SUPER_RARE ], [ Biome.LABORATORY, BiomePoolTier.RARE ] ] @@ -3165,7 +3165,7 @@ export const biomeTrainerPools: BiomeTrainerPools = { ] ], [ Species.PORYGON2, Type.NORMAL, -1, [ - [ Biome.FACTORY, BiomePoolTier.SUPER_RARE ], + [ Biome.FACTORY, BiomePoolTier.RARE ], [ Biome.SPACE, BiomePoolTier.SUPER_RARE ], [ Biome.LABORATORY, BiomePoolTier.RARE ] ] diff --git a/src/data/move.ts b/src/data/move.ts index e1694ede8a3..e300b3ae20d 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -3611,8 +3611,6 @@ export class SuppressAbilitiesAttr extends MoveEffectAttr { } } - - export class TransformAttr extends MoveEffectAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise { return new Promise(resolve => { @@ -6357,8 +6355,7 @@ export function initMoves() { }), // TODO Add Instruct/Encore interaction new AttackMove(Moves.COMEUPPANCE, Type.DARK, MoveCategory.PHYSICAL, 1, 100, 10, -1, 0, 9) .attr(CounterDamageAttr, (move: Move) => (move.category === MoveCategory.PHYSICAL || move.category === MoveCategory.SPECIAL), 1.5) - .target(MoveTarget.ATTACKER) - .partial(), + .target(MoveTarget.ATTACKER), new AttackMove(Moves.AQUA_CUTTER, Type.WATER, MoveCategory.PHYSICAL, 70, 100, 20, -1, 0, 9) .attr(HighCritAttr) .slicingMove() From 9d8f7ddcf0b8afb07df95a10ec7839b8f83b1594 Mon Sep 17 00:00:00 2001 From: Benjamin Odom Date: Thu, 2 May 2024 14:10:21 -0500 Subject: [PATCH 38/45] Implement Tailwind (#398) Added a new ArenaTagType for Tailwind. Lasts 4 turns including the turn used. --- src/data/arena-tag.ts | 16 ++++++++++++++++ src/data/enums/arena-tag-type.ts | 3 ++- src/data/move.ts | 4 ++-- src/field/pokemon.ts | 5 +++++ 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/data/arena-tag.ts b/src/data/arena-tag.ts index a879c68d4ce..8942cfe4b3e 100644 --- a/src/data/arena-tag.ts +++ b/src/data/arena-tag.ts @@ -482,6 +482,20 @@ export class GravityTag extends ArenaTag { } } +class TailwindTag extends ArenaTag { + constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) { + super(ArenaTagType.TAILWIND, turnCount, Moves.TAILWIND, sourceId, side); + } + + onAdd(arena: Arena): void { + arena.scene.queueMessage(`The Tailwind blew from behind${this.side === ArenaTagSide.PLAYER ? '\nyour' : this.side === ArenaTagSide.ENEMY ? '\nthe opposing' : ''} team!`); + } + + onRemove(arena: Arena): void { + arena.scene.queueMessage(`${this.side === ArenaTagSide.PLAYER ? 'Your' : this.side === ArenaTagSide.ENEMY ? 'The opposing' : ''} team's Tailwind petered out!`); + } +} + export function getArenaTag(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves, sourceId: integer, targetIndex?: BattlerIndex, side: ArenaTagSide = ArenaTagSide.BOTH): ArenaTag { switch (tagType) { case ArenaTagType.MIST: @@ -513,5 +527,7 @@ export function getArenaTag(tagType: ArenaTagType, turnCount: integer, sourceMov return new LightScreenTag(turnCount, sourceId, side); case ArenaTagType.AURORA_VEIL: return new AuroraVeilTag(turnCount, sourceId, side); + case ArenaTagType.TAILWIND: + return new TailwindTag(turnCount, sourceId, side); } } diff --git a/src/data/enums/arena-tag-type.ts b/src/data/enums/arena-tag-type.ts index 8478b6f3f57..2ecac8b5677 100644 --- a/src/data/enums/arena-tag-type.ts +++ b/src/data/enums/arena-tag-type.ts @@ -15,5 +15,6 @@ export enum ArenaTagType { GRAVITY = "GRAVITY", REFLECT = "REFLECT", LIGHT_SCREEN = "LIGHT_SCREEN", - AURORA_VEIL = "AURORA_VEIL" + AURORA_VEIL = "AURORA_VEIL", + TAILWIND = "TAILWIND" } diff --git a/src/data/move.ts b/src/data/move.ts index e300b3ae20d..b26af03fc5e 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -4805,8 +4805,8 @@ export function initMoves() { .partial(), new StatusMove(Moves.TAILWIND, Type.FLYING, -1, 15, -1, 0, 4) .windMove() - .target(MoveTarget.USER_SIDE) - .unimplemented(), + .attr(AddArenaTagAttr, ArenaTagType.TAILWIND, 4, true) + .target(MoveTarget.USER_SIDE), new StatusMove(Moves.ACUPRESSURE, Type.NORMAL, -1, 30, -1, 0, 4) .attr(StatChangeAttr, BattleStat.RAND, 2) .target(MoveTarget.USER_OR_NEAR_ALLY), diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index a966a24303f..daa7876853b 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -589,6 +589,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { ret *= 1.5; break; case Stat.SPD: + // Check both the player and enemy to see if Tailwind should be multiplying the speed of the Pokemon + if ((this.isPlayer() && this.scene.arena.getTagOnSide(ArenaTagType.TAILWIND, ArenaTagSide.PLAYER)) + || (!this.isPlayer() && this.scene.arena.getTagOnSide(ArenaTagType.TAILWIND, ArenaTagSide.ENEMY))) + ret *= 2; + if (this.getTag(BattlerTagType.SLOW_START)) ret >>= 1; if (this.status && this.status.effect === StatusEffect.PARALYSIS) From dffa9b2704dba212dfbaf1f1c518c4e65edb8737 Mon Sep 17 00:00:00 2001 From: maru Date: Thu, 2 May 2024 15:48:59 -0400 Subject: [PATCH 39/45] Add more files to be purged from CF cache on deploy --- .github/workflows/deploy.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index e678a297852..07aed42a5a7 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -41,4 +41,6 @@ jobs: files: | https://pokerogue.net/ https://pokerogue.net/index.html - https://pokerogue.net/manifest.json \ No newline at end of file + https://pokerogue.net/manifest.json + https://pokerogue.net/manifest.webmanifest + https://pokerogue.net/service-worker.js \ No newline at end of file From 991f097e9e2488192dd7a6d8084365e49aa9200b Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Thu, 2 May 2024 17:48:08 -0400 Subject: [PATCH 40/45] Rebalance friendship and add starter friendship with candy reward --- src/data/pokemon-species.ts | 26 +++++++++++++++++++++++++- src/field/pokemon.ts | 27 +++++++++++++++++++++++++-- src/modifier/modifier-type.ts | 2 +- src/modifier/modifier.ts | 9 ++++----- src/phases.ts | 15 +++++---------- src/system/game-data.ts | 5 ++++- 6 files changed, 64 insertions(+), 20 deletions(-) diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index 2f8edefa403..c67f0c14b47 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -367,8 +367,8 @@ export abstract class PokemonSpeciesForm { loadAssets(scene: BattleScene, female: boolean, formIndex?: integer, shiny?: boolean, variant?: Variant, startLoad?: boolean): Promise { return new Promise(resolve => { const spriteKey = this.getSpriteKey(female, formIndex, shiny, variant); - scene.load.audio(this.getCryKey(formIndex), `audio/cry/${this.getCryKey(formIndex)}.m4a`); scene.loadPokemonAtlas(spriteKey, this.getSpriteAtlasPath(female, formIndex, shiny, variant)); + scene.load.audio(this.getCryKey(formIndex), `audio/cry/${this.getCryKey(formIndex)}.m4a`); scene.load.once(Phaser.Loader.Events.COMPLETE, () => { const originalWarn = console.warn; // Ignore warnings for missing frames, because there will be a lot @@ -3156,6 +3156,30 @@ export const noStarterFormKeys: string[] = [ SpeciesFormKey.ETERNAMAX ].map(k => k.toString()); +export function getStarterValueFriendshipCap(value: integer): integer { + switch (value) { + case 1: + return 20; + case 2: + return 40; + case 3: + return 60; + case 4: + return 100; + case 5: + return 140; + case 6: + return 200; + case 7: + return 280; + case 8: + case 9: + return 450; + default: + return 600; + } +} + export const starterPassiveAbilities = { [Species.BULBASAUR]: Abilities.SOLAR_POWER, [Species.CHARMANDER]: Abilities.INTIMIDATE, diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index daa7876853b..08482bbd914 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -5,12 +5,12 @@ import { variantData } from '#app/data/variant'; import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from '../ui/battle-info'; import { Moves } from "../data/enums/moves"; import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, VariablePowerAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, MultiHitAttr, StatusMoveTypeImmunityAttr, MoveTarget, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveTypeAttr, VariableMoveCategoryAttr } from "../data/move"; -import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, starterPassiveAbilities } from '../data/pokemon-species'; +import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, getStarterValueFriendshipCap, speciesStarters, starterPassiveAbilities } from '../data/pokemon-species'; import * as Utils from '../utils'; import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from '../data/type'; import { getLevelTotalExp } from '../data/exp'; import { Stat } from '../data/pokemon-stat'; -import { AttackTypeBoosterModifier, DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, PokemonBaseStatModifier, PokemonHeldItemModifier, PokemonMultiHitModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempBattleStatBoosterModifier, TerastallizeModifier } from '../modifier/modifier'; +import { AttackTypeBoosterModifier, DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, PokemonBaseStatModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonMultiHitModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempBattleStatBoosterModifier, TerastallizeModifier } from '../modifier/modifier'; import { PokeballType } from '../data/pokeball'; import { Gender } from '../data/gender'; import { initMoveAnim, loadMoveAnimAssets } from '../data/battle-anims'; @@ -2367,6 +2367,29 @@ export class PlayerPokemon extends Pokemon { }, PartyUiHandler.FilterNonFainted); }); } + + addFriendship(friendship: integer): void { + const starterSpeciesId = this.species.getRootSpeciesId(); + const starterData = this.scene.gameData.starterData[starterSpeciesId]; + const amount = new Utils.IntegerHolder(friendship); + const starterAmount = new Utils.IntegerHolder(friendship * (this.scene.gameMode.isClassic ? 2 : 1)); + if (amount.value > 0) { + this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, this, amount); + this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, this, starterAmount); + + this.friendship = Math.min(this.friendship + amount.value, 255); + if (this.friendship === 255) + this.scene.validateAchv(achvs.MAX_FRIENDSHIP); + starterData.friendship = (starterData.friendship || 0) + starterAmount.value; + if (starterData.friendship >= getStarterValueFriendshipCap(speciesStarters[starterSpeciesId])) { + this.scene.gameData.addStarterCandy(getPokemonSpecies(starterSpeciesId), 1); + starterData.friendship = 0; + } + } else { + this.friendship = Math.max(this.friendship + amount.value, 0); + starterData.friendship = Math.max((starterData.friendship || 0) + starterAmount.value, 0); + } + } getPossibleEvolution(evolution: SpeciesFormEvolution): Promise { return new Promise(resolve => { diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 6237e8b5a50..4229b8be3b7 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -1058,7 +1058,6 @@ const modifierPool: ModifierPool = { new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 10), new WeightedModifierType(modifierTypes.TM_ULTRA, 8), new WeightedModifierType(modifierTypes.RARER_CANDY, 4), - new WeightedModifierType(modifierTypes.SOOTHE_BELL, (party: Pokemon[]) => party.find(p => (pokemonEvolutions.hasOwnProperty(p.species.speciesId) && pokemonEvolutions[p.species.speciesId].find(e => e.condition && e.condition instanceof SpeciesFriendshipEvolutionCondition)) || p.moveset.find(m => m.moveId === Moves.RETURN)) ? 16 : 0, 16), new WeightedModifierType(modifierTypes.GOLDEN_PUNCH, 2), new WeightedModifierType(modifierTypes.IV_SCANNER, 4), new WeightedModifierType(modifierTypes.EXP_CHARM, 8), @@ -1078,6 +1077,7 @@ const modifierPool: ModifierPool = { new WeightedModifierType(modifierTypes.BATON, 2), new WeightedModifierType(modifierTypes.SOUL_DEW, 8), //new WeightedModifierType(modifierTypes.OVAL_CHARM, 6), + new WeightedModifierType(modifierTypes.SOOTHE_BELL, 4), new WeightedModifierType(modifierTypes.ABILITY_CHARM, 6), new WeightedModifierType(modifierTypes.FOCUS_BAND, 5), new WeightedModifierType(modifierTypes.KINGS_ROCK, 3), diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index d8fad1466b9..88b009d3a48 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -1111,9 +1111,7 @@ export class PokemonLevelIncrementModifier extends ConsumablePokemonModifier { pokemon.levelExp = 0; } - const friendshipIncrease = new Utils.IntegerHolder(5); - pokemon.scene.applyModifier(PokemonFriendshipBoosterModifier, true, pokemon, friendshipIncrease); - pokemon.friendship = Math.min(pokemon.friendship + friendshipIncrease.value, 255); + pokemon.addFriendship(5); pokemon.scene.unshiftPhase(new LevelUpPhase(pokemon.scene, pokemon.scene.getParty().indexOf(pokemon), pokemon.level - levelCount.value, pokemon.level)); @@ -1392,13 +1390,14 @@ export class PokemonFriendshipBoosterModifier extends PokemonHeldItemModifier { } apply(args: any[]): boolean { - (args[1] as Utils.IntegerHolder).value *= 1 + 0.5 * this.getStackCount(); + const friendship = args[1] as Utils.IntegerHolder; + friendship.value = Math.floor(friendship.value * (1 + 0.5 * this.getStackCount())); return true; } getMaxHeldItemCount(pokemon: Pokemon): integer { - return 5; + return 3; } } diff --git a/src/phases.ts b/src/phases.ts index 2ffa25aef0f..4c2f5536268 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -6,7 +6,7 @@ import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMov import { Mode } from './ui/ui'; import { Command } from "./ui/command-ui-handler"; import { Stat } from "./data/pokemon-stat"; -import { BerryModifier, ContactHeldItemTransferChanceModifier, EnemyAttackStatusEffectChanceModifier, EnemyPersistentModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, FusePokemonModifier, HealingBoosterModifier, HitHealModifier, LapsingPersistentModifier, MapModifier, Modifier, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, SwitchEffectTransferModifier, TempBattleStatBoosterModifier, TurnHealModifier, TurnHeldItemTransferModifier, MoneyMultiplierModifier, MoneyInterestModifier, IvScannerModifier, PokemonFriendshipBoosterModifier, LapsingPokemonHeldItemModifier, PokemonMultiHitModifier, PokemonMoveAccuracyBoosterModifier } from "./modifier/modifier"; +import { BerryModifier, ContactHeldItemTransferChanceModifier, EnemyAttackStatusEffectChanceModifier, EnemyPersistentModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, FusePokemonModifier, HealingBoosterModifier, HitHealModifier, LapsingPersistentModifier, MapModifier, Modifier, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, SwitchEffectTransferModifier, TempBattleStatBoosterModifier, TurnHealModifier, TurnHeldItemTransferModifier, MoneyMultiplierModifier, MoneyInterestModifier, IvScannerModifier, LapsingPokemonHeldItemModifier, PokemonMultiHitModifier, PokemonMoveAccuracyBoosterModifier } from "./modifier/modifier"; import PartyUiHandler, { PartyOption, PartyUiMode } from "./ui/party-ui-handler"; import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./data/pokeball"; import { CommonAnim, CommonBattleAnim, MoveAnim, initMoveAnim, loadMoveAnimAssets } from "./data/battle-anims"; @@ -3154,8 +3154,8 @@ export class FaintPhase extends PokemonPhase { this.scene.getField(true).filter(p => p !== pokemon).forEach(p => p.removeTagsBySourceId(pokemon.id)); pokemon.faintCry(() => { - const friendshipDecrease = new Utils.IntegerHolder(10); - pokemon.friendship = Math.max(pokemon.friendship - friendshipDecrease.value, 0); + if (pokemon instanceof PlayerPokemon) + pokemon.addFriendship(-10); pokemon.hideInfo(); this.scene.playSound('faint'); this.scene.tweens.add({ @@ -3226,13 +3226,8 @@ export class VictoryPhase extends PokemonPhase { for (let partyMember of expPartyMembers) { const pId = partyMember.id; const participated = participantIds.has(pId); - if (participated) { - const friendshipIncrease = new Utils.IntegerHolder(2); - this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, partyMember, friendshipIncrease); - partyMember.friendship = Math.min(partyMember.friendship + friendshipIncrease.value, 255); - if (partyMember.friendship === 255) - this.scene.validateAchv(achvs.MAX_FRIENDSHIP); - } + if (participated) + partyMember.addFriendship(2); else if (!expShareModifier) { partyMemberExp.push(0); continue; diff --git a/src/system/game-data.ts b/src/system/game-data.ts index e11c2dcc572..b7495a1eac9 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -169,6 +169,7 @@ export interface StarterDataEntry { moveset: StarterMoveset | StarterFormMoveData; eggMoves: integer; candyCount: integer; + friendship: integer; abilityAttr: integer; passiveAttr: integer; valueReduction: integer; @@ -988,6 +989,7 @@ export class GameData { moveset: null, eggMoves: 0, candyCount: 0, + friendship: 0, abilityAttr: defaultStarterSpecies.includes(speciesId) ? AbilityAttr.ABILITY_1 : 0, passiveAttr: 0, valueReduction: 0 @@ -1035,6 +1037,7 @@ export class GameData { const hasPrevolution = pokemonPrevolutions.hasOwnProperty(species.speciesId); const newCatch = !caughtAttr; + const hasNewAttr = (caughtAttr & dexAttr) !== dexAttr; if (incrementCount) { if (!fromEgg) { @@ -1057,7 +1060,7 @@ export class GameData { this.gameStats.shinyPokemonHatched++; } - if (!hasPrevolution) + if (!hasPrevolution && (!pokemon.scene.gameMode.isDaily || hasNewAttr)) this.addStarterCandy(species, (1 * (pokemon.isShiny() ? 5 * Math.pow(2, pokemon.variant || 0) : 1)) * (fromEgg || pokemon.isBoss() ? 2 : 1)); } From fec87718300aa5d0bd56f1679ed853815316a33d Mon Sep 17 00:00:00 2001 From: Benjamin Odom Date: Thu, 2 May 2024 16:49:22 -0500 Subject: [PATCH 41/45] Fix Shedinja Luck and Crash Shedinja wasn't taking the luck value from Ninjask so when it calculated its luck it just took the entire fused Pokemon's luck somehow. This has been fixed so it takes both the first and second part of the fusion's luck values instead. Also fixes an issue where Shedinja crashed the game if it was the second part of a fusion combo. Now the correct pokemon species gets checked against and the correct pokemon evolution occurs to create Shedinja. --- src/field/pokemon.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 08482bbd914..c5036ce72c6 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -2457,12 +2457,17 @@ export class PlayerPokemon extends Pokemon { private handleSpecialEvolutions(evolution: SpeciesFormEvolution) { const isFusion = evolution instanceof FusionSpeciesFormEvolution; - if ((!isFusion ? this.species : this.fusionSpecies).speciesId === Species.NINCADA && evolution.speciesId === Species.NINJASK) { - const newEvolution = pokemonEvolutions[this.species.speciesId][1]; + + const evoSpecies = (!isFusion ? this.species : this.fusionSpecies) + if (evoSpecies.speciesId === Species.NINCADA && evolution.speciesId === Species.NINJASK) { + const newEvolution = pokemonEvolutions[evoSpecies.speciesId][1]; + if (newEvolution.condition.predicate(this)) { const newPokemon = this.scene.addPlayerPokemon(this.species, this.level, this.abilityIndex, this.formIndex, undefined, this.shiny, this.variant, this.ivs, this.nature); newPokemon.natureOverride = this.natureOverride; newPokemon.moveset = this.moveset.slice(); + newPokemon.luck = this.luck; + newPokemon.fusionSpecies = this.fusionSpecies; newPokemon.fusionFormIndex = this.fusionFormIndex; newPokemon.fusionAbilityIndex = this.fusionAbilityIndex; @@ -2470,8 +2475,9 @@ export class PlayerPokemon extends Pokemon { newPokemon.fusionVariant = this.fusionVariant; newPokemon.fusionGender = this.fusionGender; newPokemon.fusionLuck = this.fusionLuck; + this.scene.getParty().push(newPokemon); - newPokemon.evolve(newEvolution); + newPokemon.evolve(!isFusion ? newEvolution : new FusionSpeciesFormEvolution(this.id, newEvolution)); const modifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier && (m as PokemonHeldItemModifier).pokemonId === this.id, true) as PokemonHeldItemModifier[]; modifiers.forEach(m => { From 67431fb83b82d45cc98f59a324a3a8ecbd7fb7ff Mon Sep 17 00:00:00 2001 From: Simoninoo <105045724+Simoninoo@users.noreply.github.com> Date: Fri, 3 May 2024 02:45:45 +0200 Subject: [PATCH 42/45] Patch Ita (#399) * Syntax correction * Tutorial translation --- src/locales/it/pokemon-stat.ts | 2 +- src/locales/it/tutorial.ts | 62 +++++++++++++++++----------------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/locales/it/pokemon-stat.ts b/src/locales/it/pokemon-stat.ts index a3a62edebe2..b2c023aa383 100644 --- a/src/locales/it/pokemon-stat.ts +++ b/src/locales/it/pokemon-stat.ts @@ -5,7 +5,7 @@ export const pokemonStat: SimpleTranslationEntries = { "HPshortened": "PS", "ATK": "Attacco", "ATKshortened": "Att", - "DEF": "Difensa", + "DEF": "Difesa", "DEFshortened": "Dif", "SPATK": "Att. Sp.", "SPATKshortened": "AttSp", diff --git a/src/locales/it/tutorial.ts b/src/locales/it/tutorial.ts index 2773b6710ba..898dcead8a4 100644 --- a/src/locales/it/tutorial.ts +++ b/src/locales/it/tutorial.ts @@ -1,42 +1,42 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const tutorial: SimpleTranslationEntries = { - "intro": `Welcome to PokéRogue! This is a battle-focused Pokémon fangame with roguelite elements. - $This game is not monetized and we claim no ownership of Pokémon nor of the copyrighted assets used. - $The game is a work in progress, but fully playable.\nFor bug reports, please use the Discord community. - $If the game runs slowly, please ensure 'Hardware Acceleration' is turned on in your browser settings.`, + "intro": `Benvenuto in PokéRogue! Questo gioco si concentra sulle battaglie, con elementi roguelite. + $Questo gioco non è monetizzato e non siamo proprietari di Pokemon e Assets presenti nel gioco. + $Il gioco è work-in-progress ma giocabile al 100%.\nPer reportare eventuali bugs è possibile discuterne sul nostro Discord. + $Se il game risulta 'lento', assicurati di aver abilitato l'Accelerazione Hardware nelle impostazioni del tuo Browser`, - "accessMenu": `To access the menu, press M or Escape while awaiting input.\nThe menu contains settings and various features.`, + "accessMenu": `Per accedere al menù, press M o Esc.\nDal menù puoi cambiare impostazioni, controllare la wiki e accedere a varie features.`, - "menu": `From this menu you can access the settings. - $From the settings you can change game speed, window style, and other options. - $There are also various other features here, so be sure to check them all!`, + "menu": `Da questo menù puoi accedere alle impostazioni. + $Dalle impostazioni puoi cambiare velocità di gioco, stile di finestra e altre opzioni. + $Ci sono varie funzionalità, controlla bene e non perderti nulla!`, - "starterSelect": `From this screen, you can select your starters.\nThese are your initial party members. - $Each starter has a value. Your party can have up to\n6 members as long as the total does not exceed 10. - $You can also select gender, ability, and form depending on\nthe variants you've caught or hatched. - $The IVs for a species are also the best of every one you've\ncaught or hatched, so try to get lots of the same species!`, + "starterSelect": `Da questa schermata puoi selezionare il tuo starter.\nQuesti sono i membri iniziali del tuo parti. + $Ogni starter ha un valore. Puoi avere fino a \n6 Pokèmon, avendo a disposizione un massimo di 10 punti. + $Puoi anche selezionare Sesso, Abilità, e Forma a seconda delle\nvarianti che hai catturato o schiuso. + $Le IVs di una specie sono le migliori rispetto a tutte quelle che hai\ncatturato o schiuso, quindi prova a catturarne il piu possibile!`, - "pokerus": `A daily random 3 selectable starters have a purple border. - $If you see a starter you own with one of these,\ntry adding it to your party. Be sure to check its summary!`, + "pokerus": `Giornalmente 3 Starter casuali disponibili avranno il bordo viola. + $Se possiedi uno di questi starter,\nprova ad aggiungerlo al party. Ricorda di controllare le info!`, - "statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. - $Your Pokémon are recalled before a trainer battle and before entering a new biome. - $You can also view the stat changes for the Pokémon on the field by holding C or Shift.`, + "statChange": `I cambiamenti alle statistiche persistono fintanto che i tuoi pokèmon resteranno in campo. + $I tuoi pokemon verranno richiamati quando incontrerai un allenatore o al cambiamento di bioma. + $Puoi anche vedere i cambiamenti alle statistiche in corso tenendo premuto C o Shift`, - "selectItem": `After every battle, you are given a choice of 3 random items.\nYou may only pick one. - $These range from consumables, to Pokémon held items, to passive permanent items. - $Most non-consumable item effects will stack in various ways. - $Some items will only show up if they can be used, such as evolution items. - $You can also transfer held items between Pokémon using the transfer option. - $The transfer option will appear in the bottom right once you have obtained a held item. - $You may purchase consumable items with money, and a larger variety will be available the further you get. - $Be sure to buy these before you pick your random item, as it will progress to the next battle once you do.`, + "selectItem": `Dopo ogni battaglia avrai disponibili tre item.\nPotrai prenderne solo uno. + $Questi spaziano tra consumabili, item tenuti da Pokèmon o con un effetto passivo permanente. + $La maggior parte degli Item non Consumabili possono stackare in diversi modi. + $Alcuni Item risulteranno disponibili solo se possono essere usati, come Item Evolutivi. + $Puoi anche passare un Item tenuto da un Pokèmon ad un altro attraverso l'opzione 'trasferisci strumento'. + $L'opzione 'trasferisci strumento' sarà disponibile solo dopo aver assegnato uno strumento ad un Pokèmon. + $Puoi acquistare consumabili con le monete, progredendo saranno poi disponibili ulteriori oggetti. + $Assicurati di fare un acquisto prima di selezionare un item casuale, poichè passerai subito alla lotta successiva.`, - "eggGacha": `From this screen, you can redeem your vouchers for\nPokémon eggs. - $Eggs have to be hatched and get closer to hatching after\nevery battle. Rarer eggs take longer to hatch. - $Hatched Pokémon also won't be added to your party, they will\nbe added to your starters. - $Pokémon hatched from eggs generally have better IVs than\nwild Pokémon. - $Some Pokémon can only even be obtained from eggs. - $There are 3 different machines to pull from with different\nbonuses, so pick the one that suits you best!`, + "eggGacha": `Da questa schermata, puoi riscattare i tuoi vouchers in cambio di\nuova Pokèmon. + $Le uova vanno schiuse e saranno sempre più vicine alla schiusura dopo\nogni battaglia. Le uova più rare impiegheranno più battaglie per la schiusura. + $I Pokémon schiusi non verranno aggiunti alla tua squadra, saranno\naggiunti ai tuoi starters. + $I Pokémon schiusi generalmente hanno IVs migliori rispetto ai\n Pokémon selvatici. + $Alcuni Pokémon possono essere ottenuti solo tramite uova. + $Ci sono 3 diversi macchinari con differenti\nbonus, scegli quello che preferisci!`, } as const; \ No newline at end of file From b30ab6136e8df4c792420d1c0e7f3777ca984330 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Thu, 2 May 2024 21:55:11 -0400 Subject: [PATCH 43/45] Starter friendship for candies is split between spliced species --- src/field/pokemon.ts | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index c5036ce72c6..7720d741b20 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -37,7 +37,7 @@ import PartyUiHandler, { PartyOption, PartyUiMode } from '../ui/party-ui-handler import SoundFade from 'phaser3-rex-plugins/plugins/soundfade'; import { LevelMoves } from '../data/pokemon-level-moves'; import { DamageAchv, achvs } from '../system/achv'; -import { DexAttr, StarterMoveset } from '../system/game-data'; +import { DexAttr, StarterDataEntry, StarterMoveset } from '../system/game-data'; import { QuantizerCelebi, argbFromRgba, rgbaFromArgb } from '@material/material-color-utilities'; import { Nature, getNatureStatMultiplier } from '../data/nature'; import { SpeciesFormChange, SpeciesFormChangeActiveTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangeStatusEffectTrigger } from '../data/pokemon-forms'; @@ -2370,9 +2370,13 @@ export class PlayerPokemon extends Pokemon { addFriendship(friendship: integer): void { const starterSpeciesId = this.species.getRootSpeciesId(); - const starterData = this.scene.gameData.starterData[starterSpeciesId]; + const fusionStarterSpeciesId = this.isFusion() ? this.fusionSpecies.getRootSpeciesId() : 0; + const starterData = [ + this.scene.gameData.starterData[starterSpeciesId], + fusionStarterSpeciesId ? this.scene.gameData.starterData[fusionStarterSpeciesId] : null + ].filter(d => d); const amount = new Utils.IntegerHolder(friendship); - const starterAmount = new Utils.IntegerHolder(friendship * (this.scene.gameMode.isClassic ? 2 : 1)); + const starterAmount = new Utils.IntegerHolder(Math.floor(friendship * (this.scene.gameMode.isClassic ? 2 : 1) / (fusionStarterSpeciesId ? 2 : 1))); if (amount.value > 0) { this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, this, amount); this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, this, starterAmount); @@ -2380,14 +2384,18 @@ export class PlayerPokemon extends Pokemon { this.friendship = Math.min(this.friendship + amount.value, 255); if (this.friendship === 255) this.scene.validateAchv(achvs.MAX_FRIENDSHIP); - starterData.friendship = (starterData.friendship || 0) + starterAmount.value; - if (starterData.friendship >= getStarterValueFriendshipCap(speciesStarters[starterSpeciesId])) { - this.scene.gameData.addStarterCandy(getPokemonSpecies(starterSpeciesId), 1); - starterData.friendship = 0; - } + starterData.forEach((sd: StarterDataEntry, i: integer) => { + const speciesId = !i ? starterSpeciesId : fusionStarterSpeciesId as Species; + sd.friendship = (sd.friendship || 0) + starterAmount.value; + if (sd.friendship >= getStarterValueFriendshipCap(speciesStarters[speciesId])) { + this.scene.gameData.addStarterCandy(getPokemonSpecies(speciesId), 1); + sd.friendship = 0; + } + }); } else { this.friendship = Math.max(this.friendship + amount.value, 0); - starterData.friendship = Math.max((starterData.friendship || 0) + starterAmount.value, 0); + for (let sd of starterData) + sd.friendship = Math.max((sd.friendship || 0) + starterAmount.value, 0); } } From 60117947322354f51801e01d295d9657bae1af66 Mon Sep 17 00:00:00 2001 From: Madmadness65 Date: Thu, 2 May 2024 21:58:38 -0500 Subject: [PATCH 44/45] Minor egg move fix Gen 8 fossils unintentionally had Earthquake. They have now been replaced. --- src/data/egg-moves.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data/egg-moves.ts b/src/data/egg-moves.ts index 800c9a0ef25..221496a177d 100644 --- a/src/data/egg-moves.ts +++ b/src/data/egg-moves.ts @@ -458,9 +458,9 @@ export const speciesEggMoves = { [Species.MORPEKO]: [ Moves.TRIPLE_AXEL, Moves.OBSTRUCT, Moves.PARTING_SHOT, Moves.SWORDS_DANCE ], [Species.CUFANT]: [ Moves.LIQUIDATION, Moves.HEAVY_SLAM, Moves.CLOSE_COMBAT, Moves.GIGATON_HAMMER ], [Species.DRACOZOLT]: [ Moves.TRIPLE_AXEL, Moves.DRAGON_HAMMER, Moves.FIRE_LASH, Moves.DRAGON_DANCE ], - [Species.ARCTOZOLT]: [ Moves.TRIPLE_AXEL, Moves.EARTHQUAKE, Moves.HIGH_HORSEPOWER, Moves.SHIFT_GEAR ], + [Species.ARCTOZOLT]: [ Moves.TRIPLE_AXEL, Moves.LIQUIDATION, Moves.HIGH_HORSEPOWER, Moves.SHIFT_GEAR ], [Species.DRACOVISH]: [ Moves.TRIPLE_AXEL, Moves.DRAGON_HAMMER, Moves.THUNDER_FANG, Moves.DRAGON_DANCE ], - [Species.ARCTOVISH]: [ Moves.TRIPLE_AXEL, Moves.EARTHQUAKE, Moves.HIGH_HORSEPOWER, Moves.SHIFT_GEAR ], + [Species.ARCTOVISH]: [ Moves.TRIPLE_AXEL, Moves.SUPERCELL_SLAM, Moves.HIGH_HORSEPOWER, Moves.SHIFT_GEAR ], [Species.DURALUDON]: [ Moves.CALM_MIND, Moves.BODY_PRESS, Moves.EARTH_POWER, Moves.RECOVER ], [Species.DREEPY]: [ Moves.DRAGON_ENERGY, Moves.SHED_TAIL, Moves.BLAZING_TORQUE, Moves.SPECTRAL_THIEF ], [Species.ZACIAN]: [ Moves.MAGICAL_TORQUE, Moves.BITTER_BLADE, Moves.LEAF_BLADE, Moves.VICTORY_DANCE ], From fbc08005715ac1b1bdb4a3e38e6bf468ad3625e7 Mon Sep 17 00:00:00 2001 From: Matt Ross <13306707+mattrossdev@users.noreply.github.com> Date: Thu, 2 May 2024 22:20:41 -0700 Subject: [PATCH 45/45] Issue/smack down should cancel fly (#407) * Smack down and thousand arrows should cancel charging fly * Remove console log * Update interruptible check to use flying tag instead of move history * Remove extra comma --- src/data/battler-tags.ts | 25 +++++++++++++++++++++++++ src/data/enums/battler-tag-type.ts | 1 + src/data/move.ts | 4 ++++ src/phases.ts | 2 +- 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index aaab9f9a4a2..2521a0e03c5 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -163,6 +163,29 @@ export class FlinchedTag extends BattlerTag { } } +export class InterruptedTag extends BattlerTag { + constructor(sourceMove: Moves){ + super(BattlerTagType.INTERRUPTED, BattlerTagLapseType.PRE_MOVE, 0, sourceMove) + } + + canAdd(pokemon: Pokemon): boolean { + return !!pokemon.getTag(BattlerTagType.FLYING) + } + + onAdd(pokemon: Pokemon): void { + super.onAdd(pokemon); + + pokemon.getMoveQueue().shift() + pokemon.pushMoveHistory({move: Moves.NONE, result: MoveResult.OTHER}) + } + + lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { + super.lapse(pokemon, lapseType); + (pokemon.scene.getCurrentPhase() as MovePhase).cancel(); + return true + } +} + export class ConfusedTag extends BattlerTag { constructor(turnCount: integer, sourceMove: Moves) { super(BattlerTagType.CONFUSED, BattlerTagLapseType.MOVE, turnCount, sourceMove); @@ -1081,6 +1104,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc return new RechargingTag(sourceMove); case BattlerTagType.FLINCHED: return new FlinchedTag(sourceMove); + case BattlerTagType.INTERRUPTED: + return new InterruptedTag(sourceMove); case BattlerTagType.CONFUSED: return new ConfusedTag(turnCount, sourceMove); case BattlerTagType.INFATUATED: diff --git a/src/data/enums/battler-tag-type.ts b/src/data/enums/battler-tag-type.ts index 4d810b737aa..f76e5526f7e 100644 --- a/src/data/enums/battler-tag-type.ts +++ b/src/data/enums/battler-tag-type.ts @@ -3,6 +3,7 @@ export enum BattlerTagType { NONE = "NONE", RECHARGING = "RECHARGING", FLINCHED = "FLINCHED", + INTERRUPTED = "INTERRUPTED", CONFUSED = "CONFUSED", INFATUATED = "INFATUATED", SEEDED = "SEEDED", diff --git a/src/data/move.ts b/src/data/move.ts index b26af03fc5e..a227c522a86 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -5106,6 +5106,8 @@ export function initMoves() { .unimplemented(), new AttackMove(Moves.SMACK_DOWN, Type.ROCK, MoveCategory.PHYSICAL, 50, 100, 15, 100, 0, 5) .attr(AddBattlerTagAttr, BattlerTagType.IGNORE_FLYING, false, false, 5) + .attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED) + .attr(RemoveBattlerTagAttr, [BattlerTagType.FLYING]) .attr(HitsTagAttr, BattlerTagType.FLYING, false) .makesContact(false), new AttackMove(Moves.STORM_THROW, Type.FIGHTING, MoveCategory.PHYSICAL, 60, 100, 10, -1, 0, 5) @@ -5469,6 +5471,8 @@ export function initMoves() { new AttackMove(Moves.THOUSAND_ARROWS, Type.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, 100, 0, 6) .attr(NeutralDamageAgainstFlyingTypeMultiplierAttr) .attr(HitsTagAttr, BattlerTagType.FLYING, false) + .attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED) + .attr(RemoveBattlerTagAttr, [BattlerTagType.FLYING]) .makesContact(false) .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.THOUSAND_WAVES, Type.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 6) diff --git a/src/phases.ts b/src/phases.ts index 4c2f5536268..40ab1f30637 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2333,7 +2333,7 @@ export class MovePhase extends BattlePhase { return; } - if (this.pokemon.getTag(BattlerTagType.RECHARGING)) + if (this.pokemon.getTag(BattlerTagType.RECHARGING|| BattlerTagType.INTERRUPTED)) return; this.scene.queueMessage(getPokemonMessage(this.pokemon, ` used\n${this.move.getName()}!`), 500);