Compare commits

...

12 Commits

Author SHA1 Message Date
Madmadness65
219f227cab Remove basic Voucher from Ultra item pool
It should only be in the Great item pool now.
2024-06-04 21:53:22 -05:00
sodam
7cc5ca1839
[Localization] Korean Kanto gym leader dialogue ( (#1794)
* localized to korean (Gym leader's dialouge at Kanto region)

* modified Brock's dialogue clearly

* Add missed word to lt_surge's dialogue
2024-06-04 22:17:49 -04:00
Madmadness65
1dd7a792d4 Fix Wide Lens being accidentally added to Rogue pool 2024-06-04 21:15:10 -05:00
damocleas
dd3ffb4315
Voucher Item tier changes/addition (#1516)
* Voucher Item tier changes/addition

- Voucher moved from Ultra -> Great Tier, given a weight of 1 and disappears after first reroll, should still appear more often with a healthy team than in ultra tier at all.
- Voucher Plus moved from Master -> Rogue Tier, with weight starting at 9 -> 5 and decreasing with each reroll with 3 -> 2
Should appear just a bit more often than before.
- Voucher Premium added to Master (based on suggestion from Madmadness) with same weight as new Voucher Plus, and disabled in Endless / Endless Spliced
Should appear ~20% of the time with *perfect luck* in a whole average classic run.

Overall would be a 40-45% increase in total eggs in perfect conditions (luck, healthy team, etc.)

* fixed an extra spacebar at the end of 1303

* fixed an extra spacebar at the end of 1360

* fixed to account for Wide Lens being added
2024-06-04 22:05:29 -04:00
Matthew Olker
7eb0e8e77d revert pokemon info container depth change 2024-06-04 21:45:36 -04:00
Matthew Olker
7c9e5e9f52 loading screen disclaimer 2024-06-04 21:41:36 -04:00
Matthew Olker
5464f964c9 add more gameobject names for debugging 2024-06-04 21:06:46 -04:00
Frede
cfe9b3303a
[QoL] Pokemon Info Container always on top of Battle UI (#1782)
* Added "Skip Dialogues" option (if at least 1 classic win)

* Removed error sound and hide option instead when classic wins = 0

* Add skip dialogues option to Unlockables and show unlocked message on first classic win

* Only skips seen dialogues, removed dialogue option from unlockables, seen dialogues get saved to local storage

* oops

* dont show charSprite when skipping a dialogue, small fixes

* pokemonInfoContainer always on top of battle UI when shown

---------

Co-authored-by: Frederik Hobein <frederik.hobein@nterra.com>
2024-06-04 21:05:25 -04:00
Adrian T
48f60a5b50
[QoL] add message when quick claw is triggered (#1684) 2024-06-04 18:11:30 -04:00
Benjamin Odom
d04010226d
[Bug] Fix Leppa Berries not Updating Flyout PP (#1806)
* Fix Leppa Berries not Updating Flyout PP

* Code Cleanup

* Update battle-flyout.ts
2024-06-04 16:59:39 -05:00
AJ Fontaine
eecad0fdc4
Balance endless tokens (#1733)
* Balanced tokens

* Remove existing tokens, all 10 stack limit

* Linter complained

* Sorry Mr. Lint I’ll do better next time

* Removed redundant min

* Used a version system to update tokens

* The linter has peculiar tastes

* See if this works

* I'm at my limit omg wtf Sam

* Call me Swoobat the way I keep it Simple

* Clean up some log statements

* Adjust token weights to make up for removal of sleep and freeze

* Be so fr GitHub that’s not a real merge conflict
2024-06-04 16:39:22 -05:00
Jannik Tappert
a8205ae819
[Bug] Handle if the browser gives a long form of a language (like "de-DE") … (#1795)
* Handle if the browser gives a long form of a language (like "de-DE") for cases where we only have the short form "de".

* Changed it so that now resolved Language is now used anywhere. This is basically what i orignally did manually but provided from i18next directly
2024-06-04 15:11:02 -05:00
35 changed files with 282 additions and 172 deletions

View File

@ -1,4 +1,5 @@
import Move from "./data/move";
import { BerryModifier } from "./modifier/modifier";
/** Alias for all {@linkcode BattleScene} events */
export enum BattleSceneEventType {
@ -13,6 +14,12 @@ export enum BattleSceneEventType {
* @see {@linkcode MoveUsedEvent}
*/
MOVE_USED = "onMoveUsed",
/**
* Triggers when a berry gets successfully used
* @see {@linkcode BerryUsedEvent}
*/
BERRY_USED = "onBerryUsed",
/**
* Triggers on the first turn of a new battle
* @see {@linkcode TurnInitEvent}
@ -23,6 +30,7 @@ export enum BattleSceneEventType {
* @see {@linkcode TurnEndEvent}
*/
TURN_END = "onTurnEnd",
/**
* Triggers when a new {@linkcode Arena} is created during initialization
* @see {@linkcode NewArenaEvent}
@ -50,7 +58,7 @@ export class CandyUpgradeNotificationChangedEvent extends Event {
*/
export class MoveUsedEvent extends Event {
/** The ID of the {@linkcode Pokemon} that used the {@linkcode Move} */
public userId: number;
public pokemonId: number;
/** The {@linkcode Move} used */
public move: Move;
/** The amount of PP used on the {@linkcode Move} this turn */
@ -58,11 +66,25 @@ export class MoveUsedEvent extends Event {
constructor(userId: number, move: Move, ppUsed: number) {
super(BattleSceneEventType.MOVE_USED);
this.userId = userId;
this.pokemonId = userId;
this.move = move;
this.ppUsed = ppUsed;
}
}
/**
* Container class for {@linkcode BattleSceneEventType.BERRY_USED} events
* @extends Event
*/
export class BerryUsedEvent extends Event {
/** The {@linkcode BerryModifier} being used */
public berryModifier: BerryModifier;
constructor(berry: BerryModifier) {
super(BattleSceneEventType.BERRY_USED);
this.berryModifier = berry;
}
}
/**
* Container class for {@linkcode BattleSceneEventType.TURN_INIT} events
* @extends Event

View File

@ -213,7 +213,7 @@ export class LoadingScene extends SceneBase {
this.loadAtlas("types", "");
// Get current lang and load the types atlas for it. English will only load types while all other languages will load types and types_<lang>
const lang = i18next.language;
const lang = i18next.resolvedLanguage;
if (lang !== "en") {
if (Utils.verifyLang(lang)) {
this.loadAtlas(`types_${lang}`, "");
@ -352,14 +352,17 @@ export class LoadingScene extends SceneBase {
const width = this.cameras.main.width;
const height = this.cameras.main.height;
const logo = this.add.image(width / 2, 240, "");
const midWidth = width / 2;
const midHeight = height / 2;
const logo = this.add.image(midWidth, 240, "");
logo.setVisible(false);
logo.setOrigin(0.5, 0.5);
logo.setScale(4);
const percentText = this.make.text({
x: width / 2,
y: height / 2 - 24,
x: midWidth,
y: midHeight - 24,
text: "0%",
style: {
font: "72px emerald",
@ -369,8 +372,8 @@ export class LoadingScene extends SceneBase {
percentText.setOrigin(0.5, 0.5);
const assetText = this.make.text({
x: width / 2,
y: height / 2 + 48,
x: midWidth,
y: midHeight + 48,
text: "",
style: {
font: "48px emerald",
@ -379,6 +382,32 @@ export class LoadingScene extends SceneBase {
});
assetText.setOrigin(0.5, 0.5);
const disclaimerText = this.make.text({
x: midWidth,
y: assetText.y + 152,
text: i18next.t("menu:disclaimer"),
style: {
font: "72px emerald",
color: "#DA3838",
},
});
disclaimerText.setOrigin(0.5, 0.5);
const disclaimerDescriptionText = this.make.text({
x: midWidth,
y: disclaimerText.y + 120,
text: i18next.t("menu:disclaimerDescription"),
style: {
font: "48px emerald",
color: "#ffffff",
align: "center"
},
});
disclaimerDescriptionText.setOrigin(0.5, 0.5);
disclaimerText.setVisible(false);
disclaimerDescriptionText.setVisible(false);
const intro = this.add.video(0, 0);
intro.setOrigin(0, 0);
intro.setScale(3);
@ -388,7 +417,7 @@ export class LoadingScene extends SceneBase {
percentText.setText(`${Math.floor(parsedValue * 100)}%`);
progressBar.clear();
progressBar.fillStyle(0xffffff, 0.8);
progressBar.fillRect(width / 2 - 320, 360, 640 * parsedValue, 64);
progressBar.fillRect(midWidth - 320, 360, 640 * parsedValue, 64);
});
this.load.on("fileprogress", file => {
@ -423,6 +452,8 @@ export class LoadingScene extends SceneBase {
ease: "Sine.easeIn"
});
loadingGraphics.map(g => g.setVisible(true));
disclaimerText.setVisible(true);
disclaimerDescriptionText.setVisible(true);
});
intro.play();
break;

View File

@ -49,4 +49,6 @@ export const menu: SimpleTranslationEntries = {
"empty":"Leer",
"yes":"Ja",
"no":"Nein",
"disclaimer": "DISCLAIMER",
"disclaimerDescription": "This game is an unfinished product; it might have playability issues (including the potential loss of save data),\n change without notice, and may or may not be updated further or completed."
} as const;

View File

@ -230,10 +230,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"ENEMY_HEAL": { name: "Wiederherstellungsmarke", description: "Heilt 2% der maximalen KP pro Runde" },
"ENEMY_ATTACK_POISON_CHANCE": { name: "Giftmarke" },
"ENEMY_ATTACK_PARALYZE_CHANCE": { "name": "Lähmungsmarke" },
"ENEMY_ATTACK_SLEEP_CHANCE": { "name": "Schlafmarke" },
"ENEMY_ATTACK_FREEZE_CHANCE": { "name": "Gefriermarke" },
"ENEMY_ATTACK_BURN_CHANCE": { "name": "Brandmarke" },
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { "name": "Vollheilungsmarke", "description": "Fügt eine 10%ige Chance hinzu, jede Runde einen Statuszustand zu heilen" },
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { "name": "Vollheilungsmarke", "description": "Fügt eine 2,5%ige Chance hinzu, jede Runde einen Statuszustand zu heilen" },
"ENEMY_ENDURE_CHANCE": { "name": "Ausdauer-Marke" },
"ENEMY_FUSED_CHANCE": { "name": "Fusionsmarke", "description": "Fügt eine 1%ige Chance hinzu, dass ein wildes Pokémon eine Fusion ist" },

View File

@ -49,4 +49,6 @@ export const menu: SimpleTranslationEntries = {
"empty":"Empty",
"yes":"Yes",
"no":"No",
"disclaimer": "DISCLAIMER",
"disclaimerDescription": "This game is an unfinished product; it might have playability issues (including the potential loss of save data),\n change without notice, and may or may not be updated further or completed."
} as const;

View File

@ -230,10 +230,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"ENEMY_HEAL": { name: "Recovery Token", description: "Heals 2% of max HP every turn" },
"ENEMY_ATTACK_POISON_CHANCE": { name: "Poison Token" },
"ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Paralyze Token" },
"ENEMY_ATTACK_SLEEP_CHANCE": { name: "Sleep Token" },
"ENEMY_ATTACK_FREEZE_CHANCE": { name: "Freeze Token" },
"ENEMY_ATTACK_BURN_CHANCE": { name: "Burn Token" },
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Full Heal Token", description: "Adds a 10% chance every turn to heal a status condition" },
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Full Heal Token", description: "Adds a 2.5% chance every turn to heal a status condition" },
"ENEMY_ENDURE_CHANCE": { name: "Endure Token" },
"ENEMY_FUSED_CHANCE": { name: "Fusion Token", description: "Adds a 1% chance that a wild Pokémon will be a fusion" },
},

View File

@ -49,4 +49,6 @@ export const menu: SimpleTranslationEntries = {
"empty":"Vacío",
"yes":"Sí",
"no":"No",
"disclaimer": "DISCLAIMER",
"disclaimerDescription": "This game is an unfinished product; it might have playability issues (including the potential loss of save data),\n change without notice, and may or may not be updated further or completed."
} as const;

View File

@ -230,10 +230,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"ENEMY_HEAL": { name: "Recovery Token", description: "Cura el 2% de los PS máximo en cada turno" },
"ENEMY_ATTACK_POISON_CHANCE": { name: "Poison Token" },
"ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Paralyze Token" },
"ENEMY_ATTACK_SLEEP_CHANCE": { name: "Sleep Token" },
"ENEMY_ATTACK_FREEZE_CHANCE": { name: "Freeze Token" },
"ENEMY_ATTACK_BURN_CHANCE": { name: "Burn Token" },
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Full Heal Token", description: "Agrega un 10% de probabilidad cada turno de curar un problema de estado" },
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Full Heal Token", description: "Agrega un 2.5% de probabilidad cada turno de curar un problema de estado" },
"ENEMY_ENDURE_CHANCE": { name: "Endure Token" },
"ENEMY_FUSED_CHANCE": { name: "Fusion Token", description: "Agrega un 1% de probabilidad de que un Pokémon salvaje sea una fusión" },
},

View File

@ -44,4 +44,6 @@ export const menu: SimpleTranslationEntries = {
"empty":"Vide",
"yes":"Oui",
"no":"Non",
"disclaimer": "DISCLAIMER",
"disclaimerDescription": "This game is an unfinished product; it might have playability issues (including the potential loss of save data),\n change without notice, and may or may not be updated further or completed."
} as const;

View File

@ -230,10 +230,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"ENEMY_HEAL": { name: "Jeton Soin", description: "Soigne 2% des PV max à chaque tour" },
"ENEMY_ATTACK_POISON_CHANCE": { name: "Jeton Poison" },
"ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Jeton Paralysie" },
"ENEMY_ATTACK_SLEEP_CHANCE": { name: "Jeton Sommeil" },
"ENEMY_ATTACK_FREEZE_CHANCE": { name: "Jeton Gel" },
"ENEMY_ATTACK_BURN_CHANCE": { name: "Jeton Brulure" },
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Jeton Total Soin", description: "Ajoute 10% de chances à chaque tour de se soigner dun problème de statut." },
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Jeton Total Soin", description: "Ajoute 2.5% de chances à chaque tour de se soigner dun problème de statut." },
"ENEMY_ENDURE_CHANCE": { name: "Jeton Ténacité" },
"ENEMY_FUSED_CHANCE": { name: "Jeton Fusion", description: "Ajoute 1% de chances quun Pokémon sauvage soit une fusion." },
},

View File

@ -49,4 +49,6 @@ export const menu: SimpleTranslationEntries = {
"empty":"Vuoto",
"yes":"Si",
"no":"No",
"disclaimer": "DISCLAIMER",
"disclaimerDescription": "This game is an unfinished product; it might have playability issues (including the potential loss of save data),\n change without notice, and may or may not be updated further or completed."
} as const;

View File

@ -230,10 +230,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"ENEMY_HEAL": { name: "Gettone del Recupero", description: "Cura il 2% dei PS massimi ogni turno" },
"ENEMY_ATTACK_POISON_CHANCE": { name: "Gettone del Veleno" },
"ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Gettone della Paralisi" },
"ENEMY_ATTACK_SLEEP_CHANCE": { name: "Gettone del Sonno" },
"ENEMY_ATTACK_FREEZE_CHANCE": { name: "Gettone del Congelamento" },
"ENEMY_ATTACK_BURN_CHANCE": { name: "Gettone della Bruciatura" },
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Gettone Guarigione Completa", description: "Aggiunge una probabilità del 10% a ogni turno di curare una condizione di stato" },
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Gettone Guarigione Completa", description: "Aggiunge una probabilità del 2.5% a ogni turno di curare una condizione di stato" },
"ENEMY_ENDURE_CHANCE": { name: "Gettone di Resistenza" },
"ENEMY_FUSED_CHANCE": { name: "Gettone della fusione", description: "Aggiunge l'1% di possibilità che un Pokémon selvatico sia una fusione" },
},

View File

@ -373,141 +373,141 @@ export const PGMdialogue: DialogueTranslationEntries = {
},
"brock": {
"encounter": {
1: "My expertise on Rock-type Pokémon will take you down! Come on!",
2: "My rock-hard willpower will overwhelm you!",
3: "Allow me to show you the true strength of my Pokémon!"
1: "내 전문인 바위 타입 포켓몬으로 널 쓰러뜨려줄게! 덤벼!",
2: "바위같은 의지로 널 압도하겠어!",
3: "내 포켓몬의 진정한 힘을 보여줄게!"
},
"victory": {
1: "Your Pokémon's strength have overcome my rock-hard defenses!",
2: "The world is huge! I'm glad to have had a chance to battle you.",
3: "Perhaps I should go back to pursuing my dream as a Pokémon Breeder…"
1: "네 포켓몬의 힘이 바위같은 내 방어를 이겼어!",
2: "세상은 넓구나! 너랑 겨뤄볼 수 있어서 즐거웠어.",
3: "아마도 난 포켓몬 브리더의 꿈을 이루러 가야할지도…"
},
"defeat": {
1: "The best offense is a good defense!\nThat's my way of doing things!",
2: "Come study rocks with me next time to better learn how to fight them!",
3: "Hah, all my traveling around the regions is paying off!"
1: "최선의 공격은 적절한 방어지!\n그게 내 방식이야!",
2: "다음에 나한테 더 배우러와. 바위타입과 어떻게 싸워야하는지 알려주지!",
3: "아, 여러 지역을 돌아다니며 여행한 보람이 있군!"
}
},
"misty": {
"encounter": {
1: "My policy is an all out offensive with Water-type Pokémon!",
2: "Hiya, I'll show you the strength of my aquatic Pokémon!",
3: "My dream was to go on a journey and battle powerful trainers…\nWill you be a sufficient challenge?"
1: "내 방침은 물타입 포켓몬으로 공격하고 공격하고 또 공격하는 거!",
2: "아하핫, 너한테 내 물타입 포켓몬들의 힘을 보여줄게!",
3: "내 꿈은 여행을 다니며 강한 트레이너들과 배틀하는 거였어…\n네가 그 충분한 도전자가 될 수 있는지 볼까?"
},
"victory": {
1: "You really are strong… I'll admit that you are skilled…",
2: "Grrr… You know you just got lucky, right?!",
3: "Wow, you're too much! I can't believe you beat me!"
1: "너 정말로 강하구나… 그 실력 인정하도록 할게…",
2: "으으… 너 그냥 운이 좋았던거야, 그치?!",
3: "우와, 너 대단해! 날 이기다니 믿을 수 없어!"
},
"defeat": {
1: "Was the mighty Misty too much for you?",
2: "I hope you saw my Pokémon's elegant swimming techniques!",
3: "Your Pokémon were no match for my pride and joys!"
1: "최강인 최이슬! 너한테 좀 심했나?",
2: "내 포켓몬들의 우아한 수영 테크닉을 봤길 바랄게!",
3: "내 프라이드와 즐거움엔 네 포켓몬들은 상대가 안 돼. "
}
},
"lt_surge": {
"encounter": {
1: "My Electric Pokémon saved me during the war! I'll show you how!",
2: "Ten-hut! I'll shock you into surrender!",
3: "I'll zap you just like I do to all my enemies in battle!"
1: "마이 전기 포켓몬은 전쟁에서 미를 구했어요! 하우를 유에게 보여줄게요!",
2: "헤이! 쇼크로 유를 항복시키겠어요!",
3: "배틀에서 마이 에너미에게 했던 것처럼 유에게도 펀치를 날리겠어요!"
},
"victory": {
1: "Whoa! Your team's the real deal, kid!",
2: "Aaargh, you're strong! Even my electric tricks lost against you.",
3: "That was an absolutely shocking loss!"
1: "와우, 키드! 유어 팀은 진짜 대단하군요!",
2: "으흐흑, 유는 스트롱하네요! 마이 전기 트릭도 유에겐 로스트입니다.",
3: "앱솔루트하고 쇼킹한 패배였어요!"
},
"defeat": {
1: "Oh yeah! When it comes to Electric-type Pokémon, I'm number one in the world!",
2: "Hahaha! That was an electrifying battle, kid!",
3: "A Pokémon battle is war, and I have showed you first-hand combat!"
1: "오우 예! 전기 타입 포켓몬이라면, 미가 월드에서 넘버 원이에요!",
2: "하하하! 키드, 이것이 찌릿찌릿 일렉트릭 배틀입니다!",
3: "포켓몬 배틀은 전쟁, 앤드 나는 유에게 직접 전투를 보여줬습니다!"
}
},
"erika": {
"encounter": {
1: "Ah, the weather is lovely here…\nOh, a battle? Very well then.",
2: "My Pokémon battling skills rival that of my flower arranging skills.",
3: "Oh, I hope the pleasant aroma of my Pokémon doesn't put me to sleep again…",
4: "Seeing flowers in a garden is so soothing."
1: "아, 오늘은 날씨가 좋네요…\n음, 배틀일까요? 그럼 더 좋죠.",
2: "제 포켓몬들의 배틀 실력은 제 꽃꽂이 실력만큼 대단하답니다.",
3: "아, 제 포켓몬의 달콤한 향기가 저를 다시 잠들게 하지 않았으면 좋겠는데……",
4: "정원에서 꽃을 보면 마음이 편안해져요.”."
},
"victory": {
1: "Oh! I concede defeat.",
2: "That match was most delightful.",
3: "Ah, it appears it is my loss…",
4: "Oh, my goodness."
1: "앗! 제 패배를 인정합니다.",
2: "방금 경기 정말 달콤했어요.",
3: "아, 제가 진 것 같네요…",
4: "앗, 맙소사."
},
"defeat": {
1: "I was afraid I would doze off…",
2: "Oh my, it seems my Grass Pokémon overwhelmed you.",
3: "That battle was such a soothing experience.",
4: "Oh… Is that all?"
1: "저 조금 걱정했어요. 너무 졸려서…",
2: "어머, 제 풀 포켓몬이 당신을 압도한 것 같네요.",
3: "이 배틀 정말로 편안한 경험이었네요.",
4: "어머… 이게 끝인가요?"
}
},
"janine": {
"encounter": {
1: "I am mastering the art of poisonous attacks.\nI shall spar with you today!",
2: "Father trusts that I can hold my own.\nI will prove him right!",
3: "My ninja techniques are only second to my Father's!\nCan you keep up?"
1: "난 독을 사용하는 인술을 갈고 닦고 있어.\n오늘 수련에서는 너랑 대련할거야!",
2: "아버지는 내가 잘해낼 수 있다고 신뢰하셔.\n 그게 맞는다는 걸 증명할게!",
3: "내 인술은 아버지한테 뒤처지지 않아! 따라올 수 있겠어? "
},
"victory": {
1: "Even now, I still need training… I understand.",
2: "Your battle technique has outmatched mine.",
3: "I'm going to really apply myself and improve my skills."
1: "역시 아직도, 난 더 수련이 필요해… 납득했어.",
2: "네 배틀 기술이 내 인술보다 한 수위야.",
3: "더 스스로 갈고 닦아서, 내 인술을 향상 시키겠어."
},
"defeat": {
1: "Fufufu… the poison has sapped all your strength to battle.",
2: "Ha! You didn't stand a chance against my superior ninja skills!",
3: "Father's faith in me has proven to not be misplaced."
1: "후후후… 독이 네 기력을 모두 가져가버렸네.",
2: "하핫, 너 내 인술에 맞설 기회를 잡지 못했구나!",
3: "나를 향한 아버지의 신뢰, 틀리지 않았다는 걸 증명해냈어."
}
},
"sabrina": {
"encounter": {
1: "Through my psychic ability, I had a vision of your arrival!",
2: "I dislike fighting, but if you wish, I will show you my powers!",
3: "I can sense great ambition in you. I shall see if it not unfounded."
1: "내 초능력을 통해서, 너의 도착은 예상하고 있었어!",
2: "싸우는 건 좋아하지 않지만 네가 원한다면… 나의 힘을 보여줄게!",
3: "네게서 큰 염원이 느껴져. 그것이 근거 없는 것이 아닌지 지켜보겠어."
},
"victory": {
1: "Your power… It far exceeds what I foresaw…",
2: "I failed to accurately predict your power.",
3: "Even with my immense psychic powers, I cannot sense another as strong as you."
1: "너의 힘은… 내가 예견했던 것보다 훨씬 뛰어나…",
2: "나는 너의 힘을 정확하게 예측하지 못했어.",
3: "나 엄청난 초능력을 가지고도, 너처럼 강한 사람을 느끼지 못했네."
},
"defeat": {
1: "This victory… It is exactly as I foresaw in my visions!",
2: "Perhaps it was another I sensed a great desire in…",
3: "Hone your abilities before recklessly charging into battle.\nYou never know what the future may hold if you do…"
1: "이 승리는… 내가 환상에서 예견한 그대로네!",
2: "아마도 그건, 내가 깊이 느꼈던 또 다른 염원이었을거야…",
3: "무모하게 배틀에 임하기 전에 능력을 갈고닦도록.\n넌 미래가 어떻게 될지 예지할 수 없으니까…"
}
},
"blaine": {
"encounter": {
1: "Hah! Hope you brought a Burn Heal!",
2: "My fiery Pokémon will incinerate all challengers!",
3: "Get ready to play with fire!"
1: "우오오~옷! 화상치료제는 잘 준비했는가!",
2: "나의 포켓몬은 모든 것을 불꽃으로 태워버리는 강한 녀석들뿐이다!",
3: "불꽃과 함께할 준비는 됐는가!"
},
"victory": {
1: "I have burned down to nothing! Not even ashes remain!",
2: "Didn't I stoke the flames high enough?",
3: "I'm all burned out… But this makes my motivation to improve burn even hotter!"
1: "아무것도 남지 않고 불타버렸다! 재조차 남지 않았어!",
2: "내가 불을 너무 세게 피우지 않았나?",
3: "불태웠다… 하지만 이건 불꽃을 향상시키려는 내 동기를 더욱 뜨겁게 만드는군!"
},
"defeat": {
1: "My raging inferno cannot be quelled!",
2: "My Pokémon have been powered up with the heat from this victory!",
3: "Hah! My passion burns brighter than yours!"
1: "나의 타오르는 불길은 진압할 수 없다!",
2: "내 포켓몬은 이번 승리의 열기로 더욱 강해졌다!",
3: "하! 내 열정이 네 것보다 더 밝게 타오르고 있군!"
}
},
"giovanni": {
"encounter": {
1: "I, the leader of Team Rocket, will make you feel a world of pain!",
2: "My training here will be vital before I am to face my old associates again.",
3: "I do not think you are prepared for the level of failure you are about to experience!"
1: "나, 로켓단의 리더가, 고통의 세계를 느끼게 해주마!",
2: "옛 동료들과 다시 만나기 전, 이곳에서의 훈련은 매우 중요하겠군.",
3: "너는 곧 경험하게 될 실패에 대한 준비가 되어 있지 않군!"
},
"victory": {
1: "WHAT! Me, lose?! There is nothing I wish to say to you!",
2: "Hmph… You could never understand what I hope to achieve.",
3: "This defeat is merely delaying the inevitable.\nI will rise Team Rocket from the ashes in due time."
1: "하! 내가 졌다고?! 더 이상 할말이 없군!",
2: "흐음… 넌 내가 이루고자 하는 것을 결코 이해할 수 없을 거다.",
3: "이 패배는 피할 수 없는 것을 단지 지연시킬 뿐.\n때가 되면 잿더미에서 로켓단을 일으켜 세울 것이다."
},
"defeat": {
1: "Not being able to measure your own strength shows that you are still but a child.",
2: "Do not try to interfere with me again.",
3: "I hope you understand how foolish challenging me was."
1: "자신의 힘을 스스로 잴수 없다는 것은 네가 아직 꼬맹이라는 것을 보여준다고 할 수 있지.",
2: "다시는 나를 방해하지 말도록.",
3: "나에게 도전하는 것이 얼마나 어리석은 짓인지 이해했으면 좋겠군."
}
},
"roxanne": {

View File

@ -49,4 +49,6 @@ export const menu: SimpleTranslationEntries = {
"empty":"빈 슬롯",
"yes":"예",
"no":"아니오",
"disclaimer": "DISCLAIMER",
"disclaimerDescription": "This game is an unfinished product; it might have playability issues (including the potential loss of save data),\n change without notice, and may or may not be updated further or completed."
} as const;

View File

@ -230,10 +230,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"ENEMY_HEAL": { name: "회복 토큰", description: "매 턴 최대 체력의 2%를 회복" },
"ENEMY_ATTACK_POISON_CHANCE": { name: "독 토큰" },
"ENEMY_ATTACK_PARALYZE_CHANCE": { name: "마비 토큰" },
"ENEMY_ATTACK_SLEEP_CHANCE": { name: "잠듦 토큰" },
"ENEMY_ATTACK_FREEZE_CHANCE": { name: "얼음 토큰" },
"ENEMY_ATTACK_BURN_CHANCE": { name: "화상 토큰" },
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "만병통치 토큰", description: "매 턴 상태이상에서 회복될 확률 10% 추가" },
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "만병통치 토큰", description: "매 턴 상태이상에서 회복될 확률 2.5% 추가" },
"ENEMY_ENDURE_CHANCE": { name: "버티기 토큰" },
"ENEMY_FUSED_CHANCE": { name: "합체 토큰", description: "야생 포켓몬이 합체할 확률 1% 추가" },
},

View File

@ -49,4 +49,6 @@ export const menu: SimpleTranslationEntries = {
"empty": "Vazio",
"yes": "Sim",
"no": "Não",
"disclaimer": "DISCLAIMER",
"disclaimerDescription": "This game is an unfinished product; it might have playability issues (including the potential loss of save data),\n change without notice, and may or may not be updated further or completed."
} as const;

View File

@ -230,10 +230,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"ENEMY_HEAL": { name: "Token de Recuperação", description: "Cura 2% dos PS máximos a cada turno" },
"ENEMY_ATTACK_POISON_CHANCE": { name: "Token de Veneno" },
"ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Token de Paralisia" },
"ENEMY_ATTACK_SLEEP_CHANCE": { name: "Token de Sono" },
"ENEMY_ATTACK_FREEZE_CHANCE": { name: "Token de Congelamento" },
"ENEMY_ATTACK_BURN_CHANCE": { name: "Token de Queimadura" },
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Token de Cura Total", description: "Adiciona uma chance de 10% a cada turno de curar uma condição de status" },
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Token de Cura Total", description: "Adiciona uma chance de 2.5% a cada turno de curar uma condição de status" },
"ENEMY_ENDURE_CHANCE": { name: "Token de Persistência" },
"ENEMY_FUSED_CHANCE": { name: "Token de Fusão", description: "Adiciona uma chance de 1% de que um Pokémon selvagem seja uma fusão" },
},

View File

@ -49,4 +49,6 @@ export const menu: SimpleTranslationEntries = {
"empty": "空",
"yes": "是",
"no": "否",
"disclaimer": "DISCLAIMER",
"disclaimerDescription": "This game is an unfinished product; it might have playability issues (including the potential loss of save data),\n change without notice, and may or may not be updated further or completed."
} as const;

View File

@ -230,10 +230,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"ENEMY_HEAL": { name: "回复硬币", description: "每回合回复2%最大HP" },
"ENEMY_ATTACK_POISON_CHANCE": { name: "剧毒硬币" },
"ENEMY_ATTACK_PARALYZE_CHANCE": { name: "麻痹硬币" },
"ENEMY_ATTACK_SLEEP_CHANCE": { name: "睡眠硬币" },
"ENEMY_ATTACK_FREEZE_CHANCE": { name: "冰冻硬币" },
"ENEMY_ATTACK_BURN_CHANCE": { name: "灼烧硬币" },
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "万灵药硬币", description: "增加10%每回合治愈异常状态的概率" },
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "万灵药硬币", description: "增加2.5%每回合治愈异常状态的概率" },
"ENEMY_ENDURE_CHANCE": { name: "忍受硬币" },
"ENEMY_FUSED_CHANCE": { name: "融合硬币", description: "增加1%野生融合宝可梦出现概率" },
},

View File

@ -49,4 +49,6 @@ export const menu: SimpleTranslationEntries = {
"empty":"空",
"yes":"是",
"no":"否",
"disclaimer": "DISCLAIMER",
"disclaimerDescription": "This game is an unfinished product; it might have playability issues (including the potential loss of save data),\n change without notice, and may or may not be updated further or completed."
} as const;

View File

@ -282,12 +282,10 @@ export const modifierType: ModifierTypeTranslationEntries = {
ENEMY_HEAL: { name: "恢復硬幣", description: "每回合恢復2%最大HP" },
ENEMY_ATTACK_POISON_CHANCE: { name: "劇毒硬幣" },
ENEMY_ATTACK_PARALYZE_CHANCE: { name: "麻痹硬幣" },
ENEMY_ATTACK_SLEEP_CHANCE: { name: "睡眠硬幣" },
ENEMY_ATTACK_FREEZE_CHANCE: { name: "冰凍硬幣" },
ENEMY_ATTACK_BURN_CHANCE: { name: "灼燒硬幣" },
ENEMY_STATUS_EFFECT_HEAL_CHANCE: {
name: "萬靈藥硬幣",
description: "增加10%每回合治癒異常狀態的概率",
description: "增加2.5%每回合治癒異常狀態的概率",
},
ENEMY_ENDURE_CHANCE: { name: "忍受硬幣" },
ENEMY_FUSED_CHANCE: {

View File

@ -978,8 +978,8 @@ export class EnemyAttackStatusEffectChanceModifierType extends ModifierType {
private chancePercent: integer;
private effect: StatusEffect;
constructor(localeKey: string, iconImage: string, chancePercent: integer, effect: StatusEffect) {
super(localeKey, iconImage, (type, args) => new Modifiers.EnemyAttackStatusEffectChanceModifier(type, effect, chancePercent), "enemy_status_chance");
constructor(localeKey: string, iconImage: string, chancePercent: integer, effect: StatusEffect, stackCount?: integer) {
super(localeKey, iconImage, (type, args) => new Modifiers.EnemyAttackStatusEffectChanceModifier(type, effect, chancePercent, stackCount), "enemy_status_chance");
this.chancePercent = chancePercent;
this.effect = effect;
@ -1216,14 +1216,12 @@ export const modifierTypes = {
ENEMY_DAMAGE_BOOSTER: () => new ModifierType("modifierType:ModifierType.ENEMY_DAMAGE_BOOSTER", "wl_item_drop", (type, _args) => new Modifiers.EnemyDamageBoosterModifier(type, 5)),
ENEMY_DAMAGE_REDUCTION: () => new ModifierType("modifierType:ModifierType.ENEMY_DAMAGE_REDUCTION", "wl_guard_spec", (type, _args) => new Modifiers.EnemyDamageReducerModifier(type, 2.5)),
//ENEMY_SUPER_EFFECT_BOOSTER: () => new ModifierType('Type Advantage Token', 'Increases damage of super effective attacks by 30%', (type, _args) => new Modifiers.EnemySuperEffectiveDamageBoosterModifier(type, 30), 'wl_custom_super_effective'),
ENEMY_HEAL: () => new ModifierType("modifierType:ModifierType.ENEMY_HEAL", "wl_potion", (type, _args) => new Modifiers.EnemyTurnHealModifier(type, 2)),
ENEMY_ATTACK_POISON_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType("modifierType:ModifierType.ENEMY_ATTACK_POISON_CHANCE", "wl_antidote", 10, StatusEffect.POISON),
ENEMY_ATTACK_PARALYZE_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType("modifierType:ModifierType.ENEMY_ATTACK_PARALYZE_CHANCE", "wl_paralyze_heal", 10, StatusEffect.PARALYSIS),
ENEMY_ATTACK_SLEEP_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType("modifierType:ModifierType.ENEMY_ATTACK_SLEEP_CHANCE", "wl_awakening", 10, StatusEffect.SLEEP),
ENEMY_ATTACK_FREEZE_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType("modifierType:ModifierType.ENEMY_ATTACK_FREEZE_CHANCE", "wl_ice_heal", 10, StatusEffect.FREEZE),
ENEMY_ATTACK_BURN_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType("modifierType:ModifierType.ENEMY_ATTACK_BURN_CHANCE", "wl_burn_heal", 10, StatusEffect.BURN),
ENEMY_STATUS_EFFECT_HEAL_CHANCE: () => new ModifierType("modifierType:ModifierType.ENEMY_STATUS_EFFECT_HEAL_CHANCE", "wl_full_heal", (type, _args) => new Modifiers.EnemyStatusEffectHealChanceModifier(type, 10)),
ENEMY_ENDURE_CHANCE: () => new EnemyEndureChanceModifierType("modifierType:ModifierType.ENEMY_ENDURE_CHANCE", "wl_reset_urge", 2.5),
ENEMY_HEAL: () => new ModifierType("modifierType:ModifierType.ENEMY_HEAL", "wl_potion", (type, _args) => new Modifiers.EnemyTurnHealModifier(type, 2, 10)),
ENEMY_ATTACK_POISON_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType("modifierType:ModifierType.ENEMY_ATTACK_POISON_CHANCE", "wl_antidote", 5, StatusEffect.POISON, 10),
ENEMY_ATTACK_PARALYZE_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType("modifierType:ModifierType.ENEMY_ATTACK_PARALYZE_CHANCE", "wl_paralyze_heal", 2.5, StatusEffect.PARALYSIS, 10),
ENEMY_ATTACK_BURN_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType("modifierType:ModifierType.ENEMY_ATTACK_BURN_CHANCE", "wl_burn_heal", 5, StatusEffect.BURN, 10),
ENEMY_STATUS_EFFECT_HEAL_CHANCE: () => new ModifierType("modifierType:ModifierType.ENEMY_STATUS_EFFECT_HEAL_CHANCE", "wl_full_heal", (type, _args) => new Modifiers.EnemyStatusEffectHealChanceModifier(type, 2.5, 10)),
ENEMY_ENDURE_CHANCE: () => new EnemyEndureChanceModifierType("modifierType:ModifierType.ENEMY_ENDURE_CHANCE", "wl_reset_urge", 2),
ENEMY_FUSED_CHANCE: () => new ModifierType("modifierType:ModifierType.ENEMY_FUSED_CHANCE", "wl_custom_spliced", (type, _args) => new Modifiers.EnemyFusionChanceModifier(type, 1)),
};
@ -1324,6 +1322,7 @@ const modifierPool: ModifierPool = {
new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 3),
new WeightedModifierType(modifierTypes.TERA_SHARD, 1),
new WeightedModifierType(modifierTypes.DNA_SPLICERS, (party: Pokemon[]) => party[0].scene.gameMode.isSplicedOnly && party.filter(p => !p.fusionSpecies).length > 1 ? 4 : 0),
new WeightedModifierType(modifierTypes.VOUCHER, (party: Pokemon[], rerollCount: integer) => !party[0].scene.gameMode.isDaily ? Math.max(1 - rerollCount, 0) : 0, 1),
].map(m => {
m.setTier(ModifierTier.GREAT); return m;
}),
@ -1359,7 +1358,6 @@ const modifierPool: ModifierPool = {
new WeightedModifierType(modifierTypes.EXP_SHARE, 12),
new WeightedModifierType(modifierTypes.EXP_BALANCE, 4),
new WeightedModifierType(modifierTypes.TERA_ORB, (party: Pokemon[]) => Math.min(Math.max(Math.floor(party[0].scene.currentBattle.waveIndex / 50) * 2, 1), 4), 4),
new WeightedModifierType(modifierTypes.VOUCHER, (party: Pokemon[], rerollCount: integer) => !party[0].scene.gameMode.isDaily ? Math.max(3 - rerollCount, 0) : 0, 3),
new WeightedModifierType(modifierTypes.WIDE_LENS, 4),
].map(m => {
m.setTier(ModifierTier.ULTRA); return m;
@ -1384,6 +1382,7 @@ const modifierPool: ModifierPool = {
new WeightedModifierType(modifierTypes.FORM_CHANGE_ITEM, 18),
new WeightedModifierType(modifierTypes.MEGA_BRACELET, (party: Pokemon[]) => Math.min(Math.ceil(party[0].scene.currentBattle.waveIndex / 50), 4) * 8, 32),
new WeightedModifierType(modifierTypes.DYNAMAX_BAND, (party: Pokemon[]) => Math.min(Math.ceil(party[0].scene.currentBattle.waveIndex / 50), 4) * 8, 32),
new WeightedModifierType(modifierTypes.VOUCHER_PLUS, (party: Pokemon[], rerollCount: integer) => !party[0].scene.gameMode.isDaily ? Math.max(5 - rerollCount * 2, 0) : 0, 5),
].map(m => {
m.setTier(ModifierTier.ROGUE); return m;
}),
@ -1392,7 +1391,7 @@ const modifierPool: ModifierPool = {
new WeightedModifierType(modifierTypes.SHINY_CHARM, 14),
new WeightedModifierType(modifierTypes.HEALING_CHARM, 18),
new WeightedModifierType(modifierTypes.MULTI_LENS, 18),
new WeightedModifierType(modifierTypes.VOUCHER_PLUS, (party: Pokemon[], rerollCount: integer) => !party[0].scene.gameMode.isDaily ? Math.max(9 - rerollCount * 3, 0) : 0, 9),
new WeightedModifierType(modifierTypes.VOUCHER_PREMIUM, (party: Pokemon[], rerollCount: integer) => !party[0].scene.gameMode.isDaily && !party[0].scene.gameMode.isEndless && !party[0].scene.gameMode.isSplicedOnly ? Math.max(6 - rerollCount * 2, 0) : 0, 6),
new WeightedModifierType(modifierTypes.DNA_SPLICERS, (party: Pokemon[]) => !party[0].scene.gameMode.isSplicedOnly && party.filter(p => !p.fusionSpecies).length > 1 ? 24 : 0, 24),
new WeightedModifierType(modifierTypes.MINI_BLACK_HOLE, (party: Pokemon[]) => party[0].scene.gameData.unlocks[Unlockables.MINI_BLACK_HOLE] ? 1 : 0, 1),
].map(m => {
@ -1466,15 +1465,13 @@ const trainerModifierPool: ModifierPool = {
const enemyBuffModifierPool: ModifierPool = {
[ModifierTier.COMMON]: [
new WeightedModifierType(modifierTypes.ENEMY_DAMAGE_BOOSTER, 10),
new WeightedModifierType(modifierTypes.ENEMY_DAMAGE_REDUCTION, 10),
new WeightedModifierType(modifierTypes.ENEMY_ATTACK_POISON_CHANCE, 2),
new WeightedModifierType(modifierTypes.ENEMY_ATTACK_PARALYZE_CHANCE, 2),
new WeightedModifierType(modifierTypes.ENEMY_ATTACK_SLEEP_CHANCE, 2),
new WeightedModifierType(modifierTypes.ENEMY_ATTACK_FREEZE_CHANCE, 2),
new WeightedModifierType(modifierTypes.ENEMY_ATTACK_BURN_CHANCE, 2),
new WeightedModifierType(modifierTypes.ENEMY_STATUS_EFFECT_HEAL_CHANCE, 10),
new WeightedModifierType(modifierTypes.ENEMY_ENDURE_CHANCE, 5),
new WeightedModifierType(modifierTypes.ENEMY_DAMAGE_BOOSTER, 9),
new WeightedModifierType(modifierTypes.ENEMY_DAMAGE_REDUCTION, 9),
new WeightedModifierType(modifierTypes.ENEMY_ATTACK_POISON_CHANCE, 3),
new WeightedModifierType(modifierTypes.ENEMY_ATTACK_PARALYZE_CHANCE, 3),
new WeightedModifierType(modifierTypes.ENEMY_ATTACK_BURN_CHANCE, 3),
new WeightedModifierType(modifierTypes.ENEMY_STATUS_EFFECT_HEAL_CHANCE, 9),
new WeightedModifierType(modifierTypes.ENEMY_ENDURE_CHANCE, 4),
new WeightedModifierType(modifierTypes.ENEMY_FUSED_CHANCE, 1)
].map(m => {
m.setTier(ModifierTier.COMMON); return m;

View File

@ -776,6 +776,9 @@ export class BypassSpeedChanceModifier extends PokemonHeldItemModifier {
if (!bypassSpeed.value && pokemon.randSeedInt(10) < this.getStackCount()) {
bypassSpeed.value = true;
if (this.type instanceof ModifierTypes.PokemonHeldItemModifierType && this.type.id === "QUICK_CLAW") {
pokemon.scene.queueMessage(getPokemonMessage(pokemon, " used its quick claw to move faster!"));
}
return true;
}
@ -2141,7 +2144,7 @@ export class EnemyDamageReducerModifier extends EnemyDamageMultiplierModifier {
}
export class EnemyTurnHealModifier extends EnemyPersistentModifier {
private healPercent: number;
public healPercent: number;
constructor(type: ModifierType, healPercent: number, stackCount?: integer) {
super(type, stackCount);
@ -2176,23 +2179,23 @@ export class EnemyTurnHealModifier extends EnemyPersistentModifier {
}
getMaxStackCount(scene: BattleScene): integer {
return 15;
return 10;
}
}
export class EnemyAttackStatusEffectChanceModifier extends EnemyPersistentModifier {
public effect: StatusEffect;
private chance: number;
public chance: number;
constructor(type: ModifierType, effect: StatusEffect, chancePercent: number, stackCount?: integer) {
super(type, stackCount);
this.effect = effect;
this.chance = (chancePercent || 10) / 100;
this.chance = (chancePercent || 5) / 100;
}
match(modifier: Modifier): boolean {
return modifier instanceof EnemyAttackStatusEffectChanceModifier && modifier.effect === this.effect && modifier.chance === this.chance;
return modifier instanceof EnemyAttackStatusEffectChanceModifier && modifier.effect === this.effect;
}
clone(): EnemyAttackStatusEffectChanceModifier {
@ -2211,19 +2214,23 @@ export class EnemyAttackStatusEffectChanceModifier extends EnemyPersistentModifi
return false;
}
getMaxStackCount(scene: BattleScene): integer {
return 10;
}
}
export class EnemyStatusEffectHealChanceModifier extends EnemyPersistentModifier {
private chance: number;
public chance: number;
constructor(type: ModifierType, chancePercent: number, stackCount?: integer) {
super(type, stackCount);
this.chance = (chancePercent || 10) / 100;
this.chance = (chancePercent || 2.5) / 100;
}
match(modifier: Modifier): boolean {
return modifier instanceof EnemyStatusEffectHealChanceModifier && modifier.chance === this.chance;
return modifier instanceof EnemyStatusEffectHealChanceModifier;
}
clone(): EnemyStatusEffectHealChanceModifier {
@ -2245,19 +2252,23 @@ export class EnemyStatusEffectHealChanceModifier extends EnemyPersistentModifier
return false;
}
getMaxStackCount(scene: BattleScene): integer {
return 10;
}
}
export class EnemyEndureChanceModifier extends EnemyPersistentModifier {
private chance: number;
public chance: number;
constructor(type: ModifierType, chancePercent: number, stackCount?: integer) {
super(type, stackCount);
constructor(type: ModifierType, chancePercent?: number, stackCount?: integer) {
super(type, stackCount || 10);
this.chance = (chancePercent || 2.5) / 100;
this.chance = (chancePercent || 2) / 100;
}
match(modifier: Modifier) {
return modifier instanceof EnemyEndureChanceModifier && modifier.chance === this.chance;
return modifier instanceof EnemyEndureChanceModifier;
}
clone() {

View File

@ -61,7 +61,7 @@ import { Abilities } from "./data/enums/abilities";
import * as Overrides from "./overrides";
import { TextStyle, addTextObject } from "./ui/text";
import { Type } from "./data/type";
import { MoveUsedEvent, TurnEndEvent, TurnInitEvent } from "./battle-scene-events";
import { BerryUsedEvent, MoveUsedEvent, TurnEndEvent, TurnInitEvent } from "./battle-scene-events";
export class LoginPhase extends Phase {
@ -2244,6 +2244,7 @@ export class BerryPhase extends FieldPhase {
berryModifier.consumed = false;
}
}
this.scene.eventTarget.dispatchEvent(new BerryUsedEvent(berryModifier)); // Announce a berry was used
}
this.scene.updateModifiers(pokemon.isPlayer());

View File

@ -34,6 +34,8 @@ import {setSettingGamepad, SettingGamepad, settingGamepadDefaults} from "./setti
import {setSettingKeyboard, SettingKeyboard} from "#app/system/settings/settings-keyboard";
import { TerrainChangedEvent, WeatherChangedEvent } from "#app/field/arena-events.js";
import { Device } from "#app/enums/devices.js";
import { EnemyAttackStatusEffectChanceModifier } from "../modifier/modifier";
import { StatusEffect } from "#app/data/status-effect.js";
const saveKey = "x0i2O7WRiANTqPmZ"; // Temporary; secure encryption is not yet necessary
@ -1078,6 +1080,9 @@ export class GameData {
if (md?.className === "ExpBalanceModifier") { // Temporarily limit EXP Balance until it gets reworked
md.stackCount = Math.min(md.stackCount, 4);
}
if (md instanceof EnemyAttackStatusEffectChanceModifier && md.effect === StatusEffect.FREEZE || md.effect === StatusEffect.SLEEP) {
continue;
}
ret.push(new PersistentModifierData(md, player));
}
return ret;

View File

@ -81,11 +81,11 @@ export default class ArenaFlyout extends Phaser.GameObjects.Container {
private readonly fieldEffectInfo: ArenaEffectInfo[] = [];
// Stores callbacks in a variable so they can be unsubscribed from when destroyed
private onNewArenaEvent = (event: Event) => this.onNewArena(event);
private onTurnInitEvent = (event: Event) => this.onTurnInit(event);
private onTurnEndEvent = (event: Event) => this.onTurnEnd(event);
private readonly onNewArenaEvent = (event: Event) => this.onNewArena(event);
private readonly onTurnInitEvent = (event: Event) => this.onTurnInit(event);
private readonly onTurnEndEvent = (event: Event) => this.onTurnEnd(event);
private onFieldEffectChangedEvent = (event: Event) => this.onFieldEffectChanged(event);
private readonly onFieldEffectChangedEvent = (event: Event) => this.onFieldEffectChanged(event);
constructor(scene: Phaser.Scene) {
super(scene, 0, 0);
@ -379,6 +379,6 @@ export default class ArenaFlyout extends Phaser.GameObjects.Container {
this.battleScene.arena.eventTarget.removeEventListener(ArenaEventType.TAG_ADDED, this.onFieldEffectChangedEvent);
this.battleScene.arena.eventTarget.removeEventListener(ArenaEventType.TAG_REMOVED, this.onFieldEffectChangedEvent);
super.destroy();
super.destroy(fromScene);
}
}

View File

@ -4,7 +4,9 @@ import * as Utils from "../utils";
import BattleScene from "#app/battle-scene.js";
import { UiTheme } from "#app/enums/ui-theme.js";
import Move from "#app/data/move.js";
import { BattleSceneEventType, MoveUsedEvent } from "#app/battle-scene-events.js";
import { BattleSceneEventType, BerryUsedEvent, MoveUsedEvent } from "#app/battle-scene-events.js";
import { BerryType } from "#app/data/enums/berry-type.js";
import { Moves } from "#app/data/enums/moves.js";
/** Container for info about a {@linkcode Move} */
interface MoveInfo {
@ -53,7 +55,9 @@ export default class BattleFlyout extends Phaser.GameObjects.Container {
/** The array of {@linkcode MoveInfo} used to track moves for the {@linkcode Pokemon} linked to the flyout */
private moveInfo: MoveInfo[] = new Array();
private readonly onMoveUsed = (event) => this.updateInfo(event);
// Stores callbacks in a variable so they can be unsubscribed from when destroyed
private readonly onMoveUsedEvent = (event: Event) => this.onMoveUsed(event);
private readonly onBerryUsedEvent = (event: Event) => this.onBerryUsed(event);
constructor(scene: Phaser.Scene, player: boolean) {
super(scene, 0, 0);
@ -109,11 +113,12 @@ export default class BattleFlyout extends Phaser.GameObjects.Container {
this.name = `Flyout ${this.pokemon.name}`;
this.flyoutParent.name = `Flyout Parent ${this.pokemon.name}`;
this.battleScene.eventTarget.addEventListener(BattleSceneEventType.MOVE_USED, this.onMoveUsed);
this.battleScene.eventTarget.addEventListener(BattleSceneEventType.MOVE_USED, this.onMoveUsedEvent);
this.battleScene.eventTarget.addEventListener(BattleSceneEventType.BERRY_USED, this.onBerryUsedEvent);
}
/** Sets and formats the text property for all {@linkcode Phaser.GameObjects.Text} in the flyoutText array */
setText() {
private setText() {
for (let i = 0; i < this.flyoutText.length; i++) {
const flyoutText = this.flyoutText[i];
const moveInfo = this.moveInfo[i];
@ -122,21 +127,23 @@ export default class BattleFlyout extends Phaser.GameObjects.Container {
continue;
}
const currentPp = Math.max(moveInfo.maxPp - moveInfo.ppUsed, 0);
const currentPp = moveInfo.maxPp - moveInfo.ppUsed;
flyoutText.text = `${moveInfo.move.name} ${currentPp}/${moveInfo.maxPp}`;
}
}
/** Updates all of the {@linkcode MoveInfo} objects in the moveInfo array */
updateInfo(event: Event) {
private onMoveUsed(event: Event) {
const moveUsedEvent = event as MoveUsedEvent;
if (!moveUsedEvent || moveUsedEvent.userId !== this.pokemon?.id) {
if (!moveUsedEvent
|| moveUsedEvent.pokemonId !== this.pokemon?.id
|| moveUsedEvent.move.id === Moves.STRUGGLE) { // Ignore Struggle
return;
}
const foundInfo = this.moveInfo.find(x => x?.move.id === moveUsedEvent.move.id);
if (foundInfo) {
foundInfo.ppUsed += moveUsedEvent.ppUsed;
foundInfo.ppUsed = Math.min(foundInfo.ppUsed + moveUsedEvent.ppUsed, foundInfo.maxPp);
} else {
this.moveInfo.push({move: moveUsedEvent.move, maxPp: moveUsedEvent.move.pp, ppUsed: moveUsedEvent.ppUsed});
}
@ -144,6 +151,23 @@ export default class BattleFlyout extends Phaser.GameObjects.Container {
this.setText();
}
private onBerryUsed(event: Event) {
const berryUsedEvent = event as BerryUsedEvent;
if (!berryUsedEvent
|| berryUsedEvent.berryModifier.pokemonId !== this.pokemon?.id
|| berryUsedEvent.berryModifier.berryType !== BerryType.LEPPA) { // We only care about Leppa berries
return;
}
const foundInfo = this.moveInfo.find(info => info.ppUsed === info.maxPp);
if (!foundInfo) { // This will only happen on a de-sync of PP tracking
return;
}
foundInfo.ppUsed = Math.max(foundInfo.ppUsed - 10, 0);
this.setText();
}
/** Animates the flyout to either show or hide it by applying a fade and translation */
toggleFlyout(visible: boolean): void {
this.scene.tweens.add({
@ -156,8 +180,9 @@ export default class BattleFlyout extends Phaser.GameObjects.Container {
}
destroy(fromScene?: boolean): void {
this.battleScene.eventTarget.removeEventListener(BattleSceneEventType.MOVE_USED, this.onMoveUsed);
this.battleScene.eventTarget.removeEventListener(BattleSceneEventType.MOVE_USED, this.onMoveUsedEvent);
this.battleScene.eventTarget.removeEventListener(BattleSceneEventType.BERRY_USED, this.onBerryUsedEvent);
super.destroy();
super.destroy(fromScene);
}
}

View File

@ -35,7 +35,7 @@ export default class FightUiHandler extends UiHandler {
this.movesContainer = this.scene.add.container(18, -38.7);
ui.add(this.movesContainer);
this.typeIcon = this.scene.add.sprite((this.scene.game.canvas.width / 6) - 57, -36,`types${Utils.verifyLang(i18next.language) ? `_${i18next.language}` : ""}` , "unknown");
this.typeIcon = this.scene.add.sprite((this.scene.game.canvas.width / 6) - 57, -36,`types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}` , "unknown");
this.typeIcon.setVisible(false);
ui.add(this.typeIcon);
@ -168,7 +168,7 @@ export default class FightUiHandler extends UiHandler {
if (hasMove) {
const pokemonMove = moveset[cursor];
this.typeIcon.setTexture(`types${Utils.verifyLang(i18next.language) ? `_${i18next.language}` : ""}`, Type[pokemonMove.getMove().type].toLowerCase()).setScale(0.8);
this.typeIcon.setTexture(`types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`, Type[pokemonMove.getMove().type].toLowerCase()).setScale(0.8);
this.moveCategoryIcon.setTexture("categories", MoveCategory[pokemonMove.getMove().category].toLowerCase()).setScale(1.0);
const power = pokemonMove.getMove().power;

View File

@ -73,13 +73,16 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container {
}
setup(): void {
const currentLanguage = i18next.language;
this.setName("container-pkmn-info");
const currentLanguage = i18next.resolvedLanguage;
const langSettingKey = Object.keys(languageSettings).find(lang => currentLanguage.includes(lang));
const textSettings = languageSettings[langSettingKey];
const infoBg = addWindow(this.scene, 0, 0, this.infoWindowWidth, 132);
infoBg.setOrigin(0.5, 0.5);
infoBg.setName("window-info-bg");
this.pokemonMovesContainer = this.scene.add.container(6, 14);
this.pokemonMovesContainer.setName("container-pkmn-moves");
this.movesContainerInitialX = this.pokemonMovesContainer.x;
@ -89,21 +92,26 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container {
const movesBg = addWindow(this.scene, 0, 0, 58, 52);
movesBg.setOrigin(1, 0);
movesBg.setName("window-moves-bg");
this.pokemonMovesContainer.add(movesBg);
const movesLabel = addTextObject(this.scene, -movesBg.width / 2, 6, i18next.t("pokemonInfoContainer:moveset"), TextStyle.WINDOW, { fontSize: "64px" });
movesLabel.setOrigin(0.5, 0);
movesLabel.setName("text-moves");
this.pokemonMovesContainer.add(movesLabel);
for (let m = 0; m < 4; m++) {
const moveContainer = this.scene.add.container(-6, 18 + 7 * m);
moveContainer.setScale(0.5);
moveContainer.setName("container-move");
const moveBg = this.scene.add.nineslice(0, 0, "type_bgs", "unknown", 92, 14, 2, 2, 2, 2);
moveBg.setOrigin(1, 0);
moveBg.setName("nineslice-move-bg");
const moveLabel = addTextObject(this.scene, -moveBg.width / 2, 0, "-", TextStyle.PARTY);
moveLabel.setOrigin(0.5, 0);
moveLabel.setName("text-move-label");
this.pokemonMoveBgs.push(moveBg);
this.pokemonMoveLabels.push(moveLabel);
@ -132,38 +140,46 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container {
this.pokemonGenderLabelText = addTextObject(this.scene, infoContainerLabelXPos, 18, i18next.t("pokemonInfoContainer:gender"), TextStyle.WINDOW, { fontSize: infoContainerTextSize });
this.pokemonGenderLabelText.setOrigin(1, 0);
this.pokemonGenderLabelText.setVisible(false);
this.pokemonGenderLabelText.setName("text-pkmn-gender-label");
this.add(this.pokemonGenderLabelText);
this.pokemonGenderText = addTextObject(this.scene, infoContainerTextXPos, 18, "", TextStyle.WINDOW, { fontSize: infoContainerTextSize });
this.pokemonGenderText.setOrigin(0, 0);
this.pokemonGenderText.setVisible(false);
this.pokemonGenderText.setName("text-pkmn-gender");
this.add(this.pokemonGenderText);
this.pokemonAbilityLabelText = addTextObject(this.scene, infoContainerLabelXPos, 28, i18next.t("pokemonInfoContainer:ability"), TextStyle.WINDOW, { fontSize: infoContainerTextSize });
this.pokemonAbilityLabelText.setOrigin(1, 0);
this.pokemonAbilityLabelText.setName("text-pkmn-ability-label");
this.add(this.pokemonAbilityLabelText);
this.pokemonAbilityText = addTextObject(this.scene, infoContainerTextXPos, 28, "", TextStyle.WINDOW, { fontSize: infoContainerTextSize });
this.pokemonAbilityText.setOrigin(0, 0);
this.pokemonAbilityText.setName("text-pkmn-ability");
this.add(this.pokemonAbilityText);
this.pokemonNatureLabelText = addTextObject(this.scene, infoContainerLabelXPos, 38, i18next.t("pokemonInfoContainer:nature"), TextStyle.WINDOW, { fontSize: infoContainerTextSize });
this.pokemonNatureLabelText.setOrigin(1, 0);
this.pokemonNatureLabelText.setName("text-pkmn-nature-label");
this.add(this.pokemonNatureLabelText);
this.pokemonNatureText = addBBCodeTextObject(this.scene, infoContainerTextXPos, 38, "", TextStyle.WINDOW, { fontSize: infoContainerTextSize, lineSpacing: 3, maxLines: 2 });
this.pokemonNatureText.setOrigin(0, 0);
this.pokemonNatureText.setName("text-pkmn-nature");
this.add(this.pokemonNatureText);
this.pokemonShinyIcon = this.scene.add.image(-43.5, 48.5, "shiny_star");
this.pokemonShinyIcon.setOrigin(0, 0);
this.pokemonShinyIcon.setScale(0.75);
this.pokemonShinyIcon.setInteractive(new Phaser.Geom.Rectangle(0, 0, 12, 15), Phaser.Geom.Rectangle.Contains);
this.pokemonShinyIcon.setName("img-pkmn-shiny-icon");
this.add(this.pokemonShinyIcon);
this.pokemonFusionShinyIcon = this.scene.add.image(this.pokemonShinyIcon.x, this.pokemonShinyIcon.y, "shiny_star_2");
this.pokemonFusionShinyIcon.setOrigin(0, 0);
this.pokemonFusionShinyIcon.setScale(0.75);
this.pokemonFusionShinyIcon.setName("img-pkmn-fusion-shiny-icon");
this.add(this.pokemonFusionShinyIcon);
this.setVisible(false);

View File

@ -251,7 +251,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
setup() {
const ui = this.getUi();
const currentLanguage = i18next.language;
const currentLanguage = i18next.resolvedLanguage;
const langSettingKey = Object.keys(languageSettings).find(lang => currentLanguage.includes(lang));
const textSettings = languageSettings[langSettingKey];
@ -518,11 +518,11 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.pokemonSprite.setPipeline(this.scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], ignoreTimeTint: true });
this.starterSelectContainer.add(this.pokemonSprite);
this.type1Icon = this.scene.add.sprite(8, 98, `types${Utils.verifyLang(i18next.language) ? `_${i18next.language}` : ""}`); this.type1Icon.setScale(0.5);
this.type1Icon = this.scene.add.sprite(8, 98, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`); this.type1Icon.setScale(0.5);
this.type1Icon.setOrigin(0, 0);
this.starterSelectContainer.add(this.type1Icon);
this.type2Icon = this.scene.add.sprite(26, 98, `types${Utils.verifyLang(i18next.language) ? `_${i18next.language}` : ""}`); this.type2Icon.setScale(0.5);
this.type2Icon = this.scene.add.sprite(26, 98, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`); this.type2Icon.setScale(0.5);
this.type2Icon.setOrigin(0, 0);
this.starterSelectContainer.add(this.type2Icon);

View File

@ -23,6 +23,7 @@ export class StatsContainer extends Phaser.GameObjects.Container {
}
setup() {
this.setName("container-stats");
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);

View File

@ -695,7 +695,7 @@ export default class SummaryUiHandler extends UiHandler {
const getTypeIcon = (index: integer, type: Type, tera: boolean = false) => {
const xCoord = 39 + 34 * index;
const typeIcon = !tera
? this.scene.add.sprite(xCoord, 42, `types${Utils.verifyLang(i18next.language) ? `_${i18next.language}` : ""}`, Type[type].toLowerCase()) : this.scene.add.sprite(xCoord, 42, "type_tera");
? this.scene.add.sprite(xCoord, 42, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`, Type[type].toLowerCase()) : this.scene.add.sprite(xCoord, 42, "type_tera");
if (tera) {
typeIcon.setScale(0.5);
const typeRgb = getTypeRgb(type);
@ -897,7 +897,7 @@ export default class SummaryUiHandler extends UiHandler {
if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) {
this.extraMoveRowContainer.setVisible(true);
const newMoveTypeIcon = this.scene.add.sprite(0, 0, `types${Utils.verifyLang(i18next.language) ? `_${i18next.language}` : ""}`, Type[this.newMove.type].toLowerCase());
const newMoveTypeIcon = this.scene.add.sprite(0, 0, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`, Type[this.newMove.type].toLowerCase());
newMoveTypeIcon.setOrigin(0, 1);
this.extraMoveRowContainer.add(newMoveTypeIcon);
@ -920,7 +920,7 @@ export default class SummaryUiHandler extends UiHandler {
this.moveRowsContainer.add(moveRowContainer);
if (move) {
const typeIcon = this.scene.add.sprite(0, 0, `types${Utils.verifyLang(i18next.language) ? `_${i18next.language}` : ""}`, Type[move.getMove().type].toLowerCase()); typeIcon.setOrigin(0, 1);
const typeIcon = this.scene.add.sprite(0, 0, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`, Type[move.getMove().type].toLowerCase()); typeIcon.setOrigin(0, 1);
moveRowContainer.add(typeIcon);
}

View File

@ -98,7 +98,7 @@ export function addTextInputObject(scene: Phaser.Scene, x: number, y: number, wi
}
function getTextStyleOptions(style: TextStyle, uiTheme: UiTheme, extraStyleOptions?: Phaser.Types.GameObjects.Text.TextStyle): [ Phaser.Types.GameObjects.Text.TextStyle | InputText.IConfig, string, number, number ] {
const lang = i18next.language;
const lang = i18next.resolvedLanguage;
let shadowXpos = 4;
let shadowYpos = 5;

View File

@ -174,6 +174,7 @@ export default class UI extends Phaser.GameObjects.Container {
}
setup(): void {
this.setName("container-ui");
for (const handler of this.handlers) {
handler.setup();
}

View File

@ -396,7 +396,7 @@ English itself counts as not available
export function verifyLang(lang?: string): boolean {
//IMPORTANT - ONLY ADD YOUR LANG HERE IF YOU'VE ALREADY ADDED ALL THE NECESSARY IMAGES
if (!lang) {
lang = i18next.language;
lang = i18next.resolvedLanguage;
}
switch (lang) {