Compare commits

...

19 Commits

Author SHA1 Message Date
Ethan
d2c5a283d1
[Ability] Implement Poison Heal (#1245)
* Implement Poison Heal Ability

* Removed unneeded import

* Fix some comments, as well as make Poison Heal only notify when healing

* Eslint fix

* Revert Phases

* Pushing for sake of reviewing; PR IS NOT DONE IT NEEDS TO BE TESTED AND COMMENTED AGAIN

* Changed the way healing is done, through a heal phase instead of heal(); Also added better documentation

* Changed healing, as well as making abilityTriggers updated
2024-05-30 18:58:40 -04:00
HighMans
af20712cb5
[Feature] Make 31IVs show up as Gold (#1380)
* Make 31IVs show as gold on summary & when caught.

* Add comments to change.
2024-05-30 18:39:25 -04:00
Ronn
3f6e43a12d
Starter select - Implement up and down offset navigation (#1480)
* Handle offset up and down navigation

* add comments
2024-05-30 17:27:53 -05:00
Jannik Tappert
7ac6016df3
[Localization] Fixed Bugsy dialogue. And some fixes in the german dialogue (#1616) 2024-05-30 18:22:28 -04:00
dielle000
bda3013c19
Allow selection of item quantity when transferring items (fixes #723) (#1394)
* Transferring item does not kick out of transfer menu

* Select simultaneously the item to transfer and the quantity

* eslint fix

* eslint fix

* Reset quantity on scroll

* Documentation

* eslint fix
2024-05-30 16:58:10 -05:00
Adrian T
31e3293c51
[Ability][Move] Finish wind rider/power + tailwind implementation (#1566)
* finish wind moves + tailwind implementation

* move code and add documentations

* remove partial tag of wind_power

* add translations, fix move bugs

* fix ability trigger message

* fix ability trigger message

* add es localization

* move out of else statement
2024-05-30 17:42:46 -04:00
Tempoanon
cb6a0b9973
Fix bug with variant rate (#1613) 2024-05-30 22:25:53 +01:00
Ethan
d70ab3eaf6
[Move] Implement Punishment (#1610)
* Implement Punishment and reopen pull request 373

* Fix console log and ()
2024-05-30 17:01:42 -04:00
Gianluca Fuoco
2fd87a3cad
[Bug] Add Giga Impact Opp BG img (#1584)
* fix: add missing image by rotating giga impact image 180 degrees

* fix: move over impact in image
2024-05-30 16:48:06 -04:00
MrWaterT
2c784c662f
[Localization] Update Korean rival dialogue (#1597)
* Update small Korean locales

* Translate Korean classic story conversation

* Minor translation edit in Korean

3: translate 'not the same back home'
  from 'atmosphere of home is not like before'
  to 'returning to previous state is impossible'
3_female: now 'home' clearly means their hometown, not only player's house
6, 6_female: simple nuance-of-sentence modification
2024-05-30 16:40:31 -04:00
Tempoanon
3e932ce2d0
Shinylock uncatchable Pokemon in endless mode (#1252)
* Shinylock uncatchable Pokemon

* Fix typos

* Pass the linter vibe check

* Remove 2 shinylock cases

* refactor
2024-05-30 16:20:27 -04:00
Dmitriy K
329c9619f6
Add unthaw logic to Steam Eruption, Scorching Sands, Matcha Gotcha and all Damaging Fire moves (#940)
* Add unthaw to moves that are missing it

* Add unthaw to all damaging fire moves

* Add Status Effect overrides for easier testing

* clean up comments and readd status cure prefaint

* use helper instead of accessing attrs directly

* remove status overrides
2024-05-30 15:04:50 -05:00
Benjamin Odom
1415b74682
[QoL] Fix Final VS Code Error (#1608)
* Fix i18next and mobile errors

* Move File and Fix Error
2024-05-30 19:37:59 +01:00
Madmadness65
13797fe322 Revert change to Minior forms
Apparently its Meteor forms couldn't be selected if you caught it while it was in its Core form, so the change to this Pokémon specifically had to be reverted. It still immediately transforms back into Meteor form when starting a run, so this change should be harmless.
2024-05-30 13:06:25 -05:00
Benjamin Odom
060ffc6716
Fix i18next and mobile errors (#1601) 2024-05-30 18:51:58 +01:00
InnocentGameDev
fcc98d372d
Fix Spanish translation and typos in modifier-type.ts (#1606) 2024-05-30 13:50:47 -04:00
Matthew Olker
ed7a4045d8 show luck after reroll 2024-05-30 13:45:30 -04:00
ImperialSympathizer
3b852c5bf2
[Bug] Fix weather effects to work on the first turn of being cast (#1503)
* update weather phase so weather effects proc properly

* remove redundant weather replace phase logic

---------

Co-authored-by: ImperialSympathizer <imperialsympathizer@gmail.com>
2024-05-30 12:07:28 -05:00
Dmitriy K
b1c208cd86
[Feature] Add status override (#1602) 2024-05-30 12:49:57 -04:00
40 changed files with 655 additions and 315 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

@ -90,6 +90,7 @@ export default class BattleScene extends SceneBase {
public seVolume: number = 1;
public gameSpeed: integer = 1;
public damageNumbersMode: integer = 0;
public reroll: boolean = false;
public showMovesetFlyout: boolean = true;
public showLevelUpStats: boolean = true;
public enableTutorials: boolean = import.meta.env.VITE_BYPASS_TUTORIAL === "1";
@ -1311,6 +1312,7 @@ export default class BattleScene extends SceneBase {
const formattedMoney =
this.moneyFormat === MoneyFormat.ABBREVIATED ? Utils.formatFancyLargeNumber(this.money, 3) : this.money.toLocaleString();
this.moneyText.setText(`${formattedMoney}`);
this.fieldUI.moveAbove(this.moneyText, this.luckText);
if (forceVisible) {
this.moneyText.setVisible(true);
}
@ -1322,12 +1324,8 @@ export default class BattleScene extends SceneBase {
}
updateAndShowText(duration: integer): void {
this.fieldUI.moveBelow(this.moneyText, this.luckText);
const labels = [ this.luckLabelText, this.luckText ];
labels.map(t => {
t.setAlpha(0);
t.setVisible(true);
});
labels.forEach(t => t.setAlpha(0));
const luckValue = getPartyLuckValue(this.getParty());
this.luckText.setText(getLuckString(luckValue));
if (luckValue < 14) {
@ -1339,18 +1337,24 @@ export default class BattleScene extends SceneBase {
this.tweens.add({
targets: labels,
duration: duration,
alpha: 1
alpha: 1,
onComplete: () => {
labels.forEach(t => t.setVisible(true));
}
});
}
hideLuckText(duration: integer): void {
if (this.reroll) {
return;
}
const labels = [ this.luckLabelText, this.luckText ];
this.tweens.add({
targets: labels,
duration: duration,
alpha: 0,
onComplete: () => {
labels.map(l => l.setVisible(false));
labels.forEach(l => l.setVisible(false));
}
});
}
@ -1872,7 +1876,20 @@ export default class BattleScene extends SceneBase {
});
}
tryTransferHeldItemModifier(itemModifier: PokemonHeldItemModifier, target: Pokemon, transferStack: boolean, playSound: boolean, instant?: boolean, ignoreUpdate?: boolean): Promise<boolean> {
/**
* Try to transfer a held item to another pokemon.
* If the recepient already has the maximum amount allowed for this item, the transfer is cancelled.
* The quantity to transfer is automatically capped at how much the recepient can take before reaching the maximum stack size for the item.
* A transfer that moves a quantity smaller than what is specified in the transferQuantity parameter is still considered successful.
* @param itemModifier {@linkcode PokemonHeldItemModifier} item to transfer (represents the whole stack)
* @param target {@linkcode Pokemon} pokemon recepient in this transfer
* @param playSound {boolean}
* @param transferQuantity {@linkcode integer} how many items of the stack to transfer. Optional, defaults to 1
* @param instant {boolean}
* @param ignoreUpdate {boolean}
* @returns true if the transfer was successful
*/
tryTransferHeldItemModifier(itemModifier: PokemonHeldItemModifier, target: Pokemon, playSound: boolean, transferQuantity: integer = 1, instant?: boolean, ignoreUpdate?: boolean): Promise<boolean> {
return new Promise(resolve => {
const source = itemModifier.pokemonId ? itemModifier.getPokemon(target.scene) : null;
const cancelled = new Utils.BooleanHolder(false);
@ -1890,14 +1907,16 @@ export default class BattleScene extends SceneBase {
if (matchingModifier.stackCount >= maxStackCount) {
return resolve(false);
}
const countTaken = transferStack ? Math.min(itemModifier.stackCount, maxStackCount - matchingModifier.stackCount) : 1;
const countTaken = Math.min(transferQuantity, itemModifier.stackCount, maxStackCount - matchingModifier.stackCount);
itemModifier.stackCount -= countTaken;
newItemModifier.stackCount = matchingModifier.stackCount + countTaken;
removeOld = !itemModifier.stackCount;
} else if (!transferStack) {
newItemModifier.stackCount = 1;
removeOld = !(--itemModifier.stackCount);
} else {
const countTaken = Math.min(transferQuantity, itemModifier.stackCount);
itemModifier.stackCount -= countTaken;
newItemModifier.stackCount = countTaken;
}
removeOld = !itemModifier.stackCount;
if (!removeOld || !source || this.removeModifier(itemModifier, !source.isPlayer())) {
const addModifier = () => {
if (!matchingModifier || this.removeModifier(matchingModifier, !target.isPlayer())) {

View File

@ -674,7 +674,10 @@ export class PostDefendApplyBattlerTagAbAttr extends PostDefendAbAttr {
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
if (this.condition(pokemon, attacker, move.getMove())) {
if (!pokemon.getTag(this.tagType)) {
pokemon.addTag(this.tagType, undefined, undefined, pokemon.id);
pokemon.scene.queueMessage(i18next.t("abilityTriggers:windPowerCharged", { pokemonName: pokemon.name, moveName: move.getName() }));
}
return true;
}
return false;
@ -1226,7 +1229,7 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr {
const heldItems = this.getTargetHeldItems(defender).filter(i => i.getTransferrable(false));
if (heldItems.length) {
const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)];
pokemon.scene.tryTransferHeldItemModifier(stolenItem, pokemon, false, false).then(success => {
pokemon.scene.tryTransferHeldItemModifier(stolenItem, pokemon, false).then(success => {
if (success) {
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` stole\n${defender.name}'s ${stolenItem.type.name}!`));
}
@ -1315,7 +1318,7 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr {
const heldItems = this.getTargetHeldItems(attacker).filter(i => i.getTransferrable(false));
if (heldItems.length) {
const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)];
pokemon.scene.tryTransferHeldItemModifier(stolenItem, pokemon, false, false).then(success => {
pokemon.scene.tryTransferHeldItemModifier(stolenItem, pokemon, false).then(success => {
if (success) {
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` stole\n${attacker.name}'s ${stolenItem.type.name}!`));
}
@ -2066,6 +2069,37 @@ export class BlockNonDirectDamageAbAttr extends AbAttr {
}
}
/**
* This attribute will block any status damage that you put in the parameter.
*/
export class BlockStatusDamageAbAttr extends BlockNonDirectDamageAbAttr {
private effects: StatusEffect[];
/**
* @param {StatusEffect[]} effects The status effect(s) that will be blocked from damaging the ability pokemon
*/
constructor(...effects: StatusEffect[]) {
super(false);
this.effects = effects;
}
/**
* @param {Pokemon} pokemon The pokemon with the ability
* @param {boolean} passive N/A
* @param {Utils.BooleanHolder} cancelled Whether to cancel the status damage
* @param {any[]} args N/A
* @returns Returns true if status damage is blocked
*/
apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
if (this.effects.includes(pokemon.status.effect)) {
cancelled.value = true;
return true;
}
return false;
}
}
export class BlockOneHitKOAbAttr extends AbAttr {
apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
cancelled.value = true;
@ -2380,6 +2414,41 @@ export class PostTurnAbAttr extends AbAttr {
}
}
/**
* This attribute will heal 1/8th HP if the ability pokemon has the correct status.
*/
export class PostTurnStatusHealAbAttr extends PostTurnAbAttr {
private effects: StatusEffect[];
/**
* @param {StatusEffect[]} effects The status effect(s) that will qualify healing the ability pokemon
*/
constructor(...effects: StatusEffect[]) {
super(false);
this.effects = effects;
}
/**
* @param {Pokemon} pokemon The pokemon with the ability that will receive the healing
* @param {Boolean} passive N/A
* @param {any[]} args N/A
* @returns Returns true if healed from status, false if not
*/
applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise<boolean> {
if (this.effects.includes(pokemon.status.effect)) {
if (pokemon.getMaxHp() !== pokemon.hp) {
const scene = pokemon.scene;
const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name;
scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.getBattlerIndex(),
Math.max(Math.floor(pokemon.getMaxHp() / 8), 1), i18next.t("abilityTriggers:poisonHeal", { pokemonName: pokemon.name, abilityName: abilityName}), true));
return true;
}
}
return false;
}
}
/**
* After the turn ends, resets the status of either the ability holder or their ally
* @param {boolean} allyTarget Whether to target ally, defaults to false (self-target)
@ -2870,7 +2939,7 @@ export class PostBattleLootAbAttr extends PostBattleAbAttr {
const postBattleLoot = pokemon.scene.currentBattle.postBattleLoot;
if (postBattleLoot.length) {
const randItem = Utils.randSeedItem(postBattleLoot);
if (pokemon.scene.tryTransferHeldItemModifier(randItem, pokemon, false, true, true)) {
if (pokemon.scene.tryTransferHeldItemModifier(randItem, pokemon, true, 1, true)) {
postBattleLoot.splice(postBattleLoot.indexOf(randItem), 1);
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` picked up\n${randItem.type.name}!`));
return true;
@ -3200,6 +3269,50 @@ export class MoneyAbAttr extends PostBattleAbAttr {
}
}
/**
* Applies a stat change after a Pokémon is summoned,
* conditioned on the presence of a specific arena tag.
*
* @extends {PostSummonStatChangeAbAttr}
*/
export class PostSummonStatChangeOnArenaAbAttr extends PostSummonStatChangeAbAttr {
/**
* The type of arena tag that conditions the stat change.
* @private
* @type {ArenaTagType}
*/
private tagType: ArenaTagType;
/**
* Creates an instance of PostSummonStatChangeOnArenaAbAttr.
* Initializes the stat change to increase Attack by 1 stage if the specified arena tag is present.
*
* @param {ArenaTagType} tagType - The type of arena tag to check for.
*/
constructor(tagType: ArenaTagType) {
super([BattleStat.ATK], 1, true, false);
this.tagType = tagType;
}
/**
* Applies the post-summon stat change if the specified arena tag is present on pokemon's side.
* This is used in Wind Rider ability.
*
* @param {Pokemon} pokemon - The Pokémon being summoned.
* @param {boolean} passive - Whether the effect is passive.
* @param {any[]} args - Additional arguments.
* @returns {boolean} - Returns true if the stat change was applied, otherwise false.
*/
applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean {
const side = pokemon.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY;
if (pokemon.scene.arena.getTagOnSide(this.tagType, side)) {
return super.applyPostSummon(pokemon, passive, args);
}
return false;
}
}
function applyAbAttrsInternal<TAttr extends AbAttr>(attrType: { new(...args: any[]): TAttr },
pokemon: Pokemon, applyFunc: AbAttrApplyFunc<TAttr>, args: any[], isAsync: boolean = false, showAbilityInstant: boolean = false, quiet: boolean = false, passive: boolean = false): Promise<void> {
return new Promise(resolve => {
@ -3685,7 +3798,8 @@ export function initAbilities() {
new Ability(Abilities.IRON_FIST, 4)
.attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.PUNCHING_MOVE), 1.2),
new Ability(Abilities.POISON_HEAL, 4)
.unimplemented(),
.attr(PostTurnStatusHealAbAttr, StatusEffect.TOXIC, StatusEffect.POISON)
.attr(BlockStatusDamageAbAttr, StatusEffect.TOXIC, StatusEffect.POISON),
new Ability(Abilities.ADAPTABILITY, 4)
.attr(StabBoostAbAttr),
new Ability(Abilities.SKILL_LINK, 4)
@ -4270,9 +4384,9 @@ export function initAbilities() {
.attr(TypeImmunityStatChangeAbAttr, Type.FIRE, BattleStat.DEF, 2)
.ignorable(),
new Ability(Abilities.WIND_RIDER, 9)
.attr(MoveImmunityStatChangeAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.getMove().hasFlag(MoveFlags.WIND_MOVE), BattleStat.ATK, 1)
.ignorable()
.partial(),
.attr(MoveImmunityStatChangeAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.getMove().hasFlag(MoveFlags.WIND_MOVE) && move.getMove().category !== MoveCategory.STATUS, BattleStat.ATK, 1)
.attr(PostSummonStatChangeOnArenaAbAttr, ArenaTagType.TAILWIND)
.ignorable(),
new Ability(Abilities.GUARD_DOG, 9)
.attr(PostIntimidateStatChangeAbAttr, [BattleStat.ATK], 1, true)
.attr(ForceSwitchOutImmunityAbAttr)
@ -4280,8 +4394,7 @@ export function initAbilities() {
new Ability(Abilities.ROCKY_PAYLOAD, 9)
.attr(MoveTypePowerBoostAbAttr, Type.ROCK),
new Ability(Abilities.WIND_POWER, 9)
.attr(PostDefendApplyBattlerTagAbAttr, (target, user, move) => move.hasFlag(MoveFlags.WIND_MOVE), BattlerTagType.CHARGED)
.partial(),
.attr(PostDefendApplyBattlerTagAbAttr, (target, user, move) => move.hasFlag(MoveFlags.WIND_MOVE), BattlerTagType.CHARGED),
new Ability(Abilities.ZERO_TO_HERO, 9)
.attr(UncopiableAbilityAbAttr)
.attr(UnswappableAbilityAbAttr)

View File

@ -4,7 +4,7 @@ import * as Utils from "../utils";
import { MoveCategory, allMoves, MoveTarget } from "./move";
import { getPokemonMessage } from "../messages";
import Pokemon, { HitResult, PokemonMove } from "../field/pokemon";
import { MoveEffectPhase, PokemonHealPhase, StatChangePhase} from "../phases";
import { MoveEffectPhase, PokemonHealPhase, ShowAbilityPhase, StatChangePhase} from "../phases";
import { StatusEffect } from "./status-effect";
import { BattlerIndex } from "../battle";
import { Moves } from "./enums/moves";
@ -12,6 +12,9 @@ import { ArenaTagType } from "./enums/arena-tag-type";
import { BlockNonDirectDamageAbAttr, ProtectStatAbAttr, applyAbAttrs } from "./ability";
import { BattleStat } from "./battle-stat";
import { CommonAnim, CommonBattleAnim } from "./battle-anims";
import { Abilities } from "./enums/abilities";
import { BattlerTagType } from "./enums/battler-tag-type";
import i18next from "i18next";
export enum ArenaTagSide {
BOTH,
@ -625,6 +628,22 @@ class TailwindTag extends ArenaTag {
onAdd(arena: Arena): void {
arena.scene.queueMessage(`The Tailwind blew from behind${this.side === ArenaTagSide.PLAYER ? "\nyour" : this.side === ArenaTagSide.ENEMY ? "\nthe opposing" : ""} team!`);
const source = arena.scene.getPokemonById(this.sourceId);
const party = source.isPlayer() ? source.scene.getPlayerField() : source.scene.getEnemyField();
for (const pokemon of party) {
// Apply the CHARGED tag to party members with the WIND_POWER ability
if (pokemon.hasAbility(Abilities.WIND_POWER) && !pokemon.getTag(BattlerTagType.CHARGED)) {
pokemon.addTag(BattlerTagType.CHARGED);
pokemon.scene.queueMessage(i18next.t("abilityTriggers:windPowerCharged", { pokemonName: pokemon.name, moveName: this.getMoveName() }));
}
// Raise attack by one stage if party member has WIND_RIDER ability
if (pokemon.hasAbility(Abilities.WIND_RIDER)) {
pokemon.scene.unshiftPhase(new ShowAbilityPhase(pokemon.scene, pokemon.getBattlerIndex()));
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [BattleStat.ATK], 1, true));
}
}
}
onRemove(arena: Arena): void {

View File

@ -423,6 +423,14 @@ export default class Move implements Localizable {
export class AttackMove extends Move {
constructor(id: Moves, type: Type, category: MoveCategory, power: integer, accuracy: integer, pp: integer, chance: integer, priority: integer, generation: integer) {
super(id, type, category, MoveTarget.NEAR_OTHER, power, accuracy, pp, chance, priority, generation);
/**
* {@link https://bulbapedia.bulbagarden.net/wiki/Freeze_(status_condition)}
* > All damaging Fire-type moves can now thaw a frozen target, regardless of whether or not they have a chance to burn;
*/
if (this.type === Type.FIRE) {
this.addAttr(new HealStatusEffectAttr(false, StatusEffect.FREEZE));
}
}
getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer {
@ -1437,7 +1445,7 @@ export class StealHeldItemChanceAttr extends MoveEffectAttr {
const highestItemTier = heldItems.map(m => m.type.getOrInferTier(poolType)).reduce((highestTier, tier) => Math.max(tier, highestTier), 0);
const tierHeldItems = heldItems.filter(m => m.type.getOrInferTier(poolType) === highestItemTier);
const stolenItem = tierHeldItems[user.randSeedInt(tierHeldItems.length)];
user.scene.tryTransferHeldItemModifier(stolenItem, user, false, false).then(success => {
user.scene.tryTransferHeldItemModifier(stolenItem, user, false).then(success => {
if (success) {
user.scene.queueMessage(getPokemonMessage(user, ` stole\n${target.name}'s ${stolenItem.type.name}!`));
}
@ -1486,7 +1494,7 @@ export class RemoveHeldItemAttr extends MoveEffectAttr {
const highestItemTier = heldItems.map(m => m.type.getOrInferTier(poolType)).reduce((highestTier, tier) => Math.max(tier, highestTier), 0);
const tierHeldItems = heldItems.filter(m => m.type.getOrInferTier(poolType) === highestItemTier);
const stolenItem = tierHeldItems[user.randSeedInt(tierHeldItems.length)];
user.scene.tryTransferHeldItemModifier(stolenItem, user, false, false).then(success => {
user.scene.tryTransferHeldItemModifier(stolenItem, user, false).then(success => {
if (success) {
user.scene.queueMessage(getPokemonMessage(user, ` knocked off\n${target.name}'s ${stolenItem.type.name}!`));
}
@ -1612,15 +1620,31 @@ export class StealEatBerryAttr extends EatBerryAttr {
}
}
/**
* Move attribute that signals that the move should cure a status effect
* @extends MoveEffectAttr
* @see {@linkcode apply()}
*/
export class HealStatusEffectAttr extends MoveEffectAttr {
/** List of Status Effects to cure */
private effects: StatusEffect[];
/**
* @param selfTarget - Whether this move targets the user
* @param ...effects - List of status effects to cure
*/
constructor(selfTarget: boolean, ...effects: StatusEffect[]) {
super(selfTarget);
this.effects = effects;
}
/**
* @param user {@linkcode Pokemon} source of the move
* @param target {@linkcode Pokemon} target of the move
* @param move the {@linkcode Move} being used
* @returns true if the status is cured
*/
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
if (!super.apply(user, target, move, args)) {
return false;
@ -2680,12 +2704,57 @@ export class HitCountPowerAttr extends VariablePowerAttr {
}
}
/**
* Turning a once was (StatChangeCountPowerAttr) statement and making it available to call for any attribute.
* @param {Pokemon} pokemon The pokemon that is being used to calculate the count of positive stats
* @returns {number} Returns the amount of positive stats
*/
const countPositiveStats = (pokemon: Pokemon): number => {
return pokemon.summonData.battleStats.reduce((total, stat) => (stat && stat > 0) ? total + stat : total, 0);
};
/**
* Attribute that increases power based on the amount of positive stat increases.
*/
export class StatChangeCountPowerAttr extends VariablePowerAttr {
/**
* @param {Pokemon} user The pokemon that is being used to calculate the amount of positive stats
* @param {Pokemon} target N/A
* @param {Move} move N/A
* @param {any[]} args The argument for VariablePowerAttr, accumulates and sets the amount of power multiplied by stats
* @returns {boolean} Returns true if attribute is applied
*/
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const positiveStats: number = user.summonData.battleStats.reduce((total, stat) => stat > 0 && stat ? total + stat : total, 0);
const positiveStats: number = countPositiveStats(user);
(args[0] as Utils.NumberHolder).value += positiveStats * 20;
return true;
}
}
/**
* Punishment normally has a base power of 60,
* but gains 20 power for every increased stat stage the target has,
* up to a maximum of 200 base power in total.
*/
export class PunishmentPowerAttr extends VariablePowerAttr {
private PUNISHMENT_MIN_BASE_POWER = 60;
private PUNISHMENT_MAX_BASE_POWER = 200;
/**
* @param {Pokemon} user N/A
* @param {Pokemon} target The pokemon that the move is being used against, as well as calculating the stats for the min/max base power
* @param {Move} move N/A
* @param {any[]} args The value that is being changed due to VariablePowerAttr
* @returns Returns true if attribute is applied
*/
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const positiveStats: number = countPositiveStats(target);
(args[0] as Utils.NumberHolder).value = Math.min(
this.PUNISHMENT_MAX_BASE_POWER,
this.PUNISHMENT_MIN_BASE_POWER + positiveStats * 20
);
return true;
}
}
@ -6041,7 +6110,8 @@ export function initMoves() {
new StatusMove(Moves.GUARD_SWAP, Type.PSYCHIC, -1, 10, -1, 0, 4)
.unimplemented(),
new AttackMove(Moves.PUNISHMENT, Type.DARK, MoveCategory.PHYSICAL, -1, 100, 5, -1, 0, 4)
.unimplemented(),
.makesContact(true)
.attr(PunishmentPowerAttr),
new AttackMove(Moves.LAST_RESORT, Type.NORMAL, MoveCategory.PHYSICAL, 140, 100, 5, -1, 0, 4)
.attr(LastResortAttr),
new StatusMove(Moves.WORRY_SEED, Type.GRASS, 100, 10, -1, 0, 4)
@ -6612,6 +6682,7 @@ export function initMoves() {
.target(MoveTarget.ALL_NEAR_ENEMIES),
new AttackMove(Moves.STEAM_ERUPTION, Type.WATER, MoveCategory.SPECIAL, 110, 95, 5, 30, 0, 6)
.attr(HealStatusEffectAttr, true, StatusEffect.FREEZE)
.attr(HealStatusEffectAttr, false, StatusEffect.FREEZE)
.attr(StatusEffectAttr, StatusEffect.BURN),
new AttackMove(Moves.HYPERSPACE_HOLE, Type.PSYCHIC, MoveCategory.SPECIAL, 80, -1, 5, -1, 0, 6)
.ignoresProtect(),
@ -7288,6 +7359,7 @@ export function initMoves() {
.attr(MultiHitAttr, MultiHitType._2),
new AttackMove(Moves.SCORCHING_SANDS, Type.GROUND, MoveCategory.SPECIAL, 70, 100, 10, 30, 0, 8)
.attr(HealStatusEffectAttr, true, StatusEffect.FREEZE)
.attr(HealStatusEffectAttr, false, StatusEffect.FREEZE)
.attr(StatusEffectAttr, StatusEffect.BURN),
new StatusMove(Moves.JUNGLE_HEALING, Type.GRASS, -1, 10, -1, 0, 8)
.attr(HealAttr, 0.25, true, false)
@ -7667,6 +7739,7 @@ export function initMoves() {
new AttackMove(Moves.MATCHA_GOTCHA, Type.GRASS, MoveCategory.SPECIAL, 80, 90, 15, 20, 0, 9)
.attr(HitHealAttr)
.attr(HealStatusEffectAttr, true, StatusEffect.FREEZE)
.attr(HealStatusEffectAttr, false, StatusEffect.FREEZE)
.attr(StatusEffectAttr, StatusEffect.BURN)
.target(MoveTarget.ALL_NEAR_ENEMIES)
.triageMove()

View File

@ -2137,13 +2137,13 @@ export function initSpecies() {
new PokemonForm("Blue Meteor Form", "blue-meteor", Type.ROCK, Type.FLYING, 0.3, 40, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 440, 60, 60, 100, 60, 100, 60, 30, 70, 154, false, "", true),
new PokemonForm("Indigo Meteor Form", "indigo-meteor", Type.ROCK, Type.FLYING, 0.3, 40, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 440, 60, 60, 100, 60, 100, 60, 30, 70, 154, false, "", true),
new PokemonForm("Violet Meteor Form", "violet-meteor", Type.ROCK, Type.FLYING, 0.3, 40, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 440, 60, 60, 100, 60, 100, 60, 30, 70, 154, false, "", true),
new PokemonForm("Red Core Form", "red", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154),
new PokemonForm("Orange Core Form", "orange", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154),
new PokemonForm("Yellow Core Form", "yellow", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154),
new PokemonForm("Green Core Form", "green", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154),
new PokemonForm("Blue Core Form", "blue", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154),
new PokemonForm("Indigo Core Form", "indigo", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154),
new PokemonForm("Violet Core Form", "violet", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154),
new PokemonForm("Red Core Form", "red", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154, false, null, true),
new PokemonForm("Orange Core Form", "orange", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154, false, null, true),
new PokemonForm("Yellow Core Form", "yellow", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154, false, null, true),
new PokemonForm("Green Core Form", "green", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154, false, null, true),
new PokemonForm("Blue Core Form", "blue", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154, false, null, true),
new PokemonForm("Indigo Core Form", "indigo", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154, false, null, true),
new PokemonForm("Violet Core Form", "violet", Type.ROCK, Type.FLYING, 0.3, 0.3, Abilities.SHIELDS_DOWN, Abilities.NONE, Abilities.NONE, 500, 60, 100, 60, 100, 60, 120, 30, 70, 154, false, null, true),
),
new PokemonSpecies(Species.KOMALA, 7, false, false, false, "Drowsing Pokémon", Type.NORMAL, null, 0.4, 19.9, Abilities.COMATOSE, Abilities.NONE, Abilities.NONE, 480, 65, 115, 65, 75, 95, 65, 45, 70, 168, GrowthRate.SLOW, 50, false),
new PokemonSpecies(Species.TURTONATOR, 7, false, false, false, "Blast Turtle Pokémon", Type.FIRE, Type.DRAGON, 2, 212, Abilities.SHELL_ARMOR, Abilities.NONE, Abilities.NONE, 485, 60, 78, 135, 91, 85, 36, 70, 50, 170, GrowthRate.MEDIUM_FAST, 50, false),

View File

@ -5,7 +5,7 @@ import * as Utils from "../utils";
import PokemonSpecies, { getPokemonSpecies } from "../data/pokemon-species";
import { Species } from "../data/enums/species";
import { Weather, WeatherType, getTerrainClearMessage, getTerrainStartMessage, getWeatherClearMessage, getWeatherStartMessage } from "../data/weather";
import { CommonAnimPhase, WeatherEffectPhase } from "../phases";
import { CommonAnimPhase } from "../phases";
import { CommonAnim } from "../data/battle-anims";
import { Type } from "../data/type";
import Move from "../data/move";
@ -302,11 +302,9 @@ export class Arena {
this.weather = weather ? new Weather(weather, hasPokemonSource ? 5 : 0) : null;
if (this.weather) {
this.scene.tryReplacePhase(phase => phase instanceof WeatherEffectPhase && phase.weather.weatherType === oldWeatherType, new WeatherEffectPhase(this.scene, this.weather));
this.scene.unshiftPhase(new CommonAnimPhase(this.scene, undefined, undefined, CommonAnim.SUNNY + (weather - 1)));
this.scene.queueMessage(getWeatherStartMessage(weather));
} else {
this.scene.tryRemovePhase(phase => phase instanceof WeatherEffectPhase && phase.weather.weatherType === oldWeatherType);
this.scene.queueMessage(getWeatherClearMessage(oldWeatherType));
}

View File

@ -1222,7 +1222,22 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
}
}
/**
* Function that tries to set a Pokemon shiny based on the trainer's trainer ID and secret ID
* Endless Pokemon in the end biome are unable to be set to shiny
*
* The exact mechanic is that it calculates E as the XOR of the player's trainer ID and secret ID
* F is calculated as the XOR of the first 16 bits of the Pokemon's ID with the last 16 bits
* The XOR of E and F are then compared to the thresholdOverride (default case 32) to see whether or not to generate a shiny
* @param thresholdOverride number that is divided by 2^16 (65536) to get the shiny chance
* @returns true if the Pokemon has been set as a shiny, false otherwise
*/
trySetShiny(thresholdOverride?: integer): boolean {
// Shiny Pokemon should not spawn in the end biome in endless
if (this.scene.gameMode.isEndless && this.scene.arena.biomeType === Biome.END) {
return false;
}
const rand1 = Utils.binToDec(Utils.decToBin(this.id).substring(0, 16));
const rand2 = Utils.binToDec(Utils.decToBin(this.id).substring(16, 32));
@ -1250,18 +1265,25 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return this.shiny;
}
/**
* Generates a variant
* Has a 10% of returning 2 (epic variant)
* And a 30% of returning 1 (rare variant)
* Returns 0 (basic shiny) if there is no variant or 60% of the time otherwise
* @returns the shiny variant
*/
generateVariant(): Variant {
if (!this.shiny || !variantData.hasOwnProperty(this.species.speciesId)) {
return 0;
}
const rand = Utils.randSeedInt(10);
if (rand > 3) {
return 0;
if (rand >= 4) {
return 0; // 6/10
} else if (rand >= 1) {
return 1; // 3/10
} else {
return 2; // 1/10
}
if (rand) {
return 1;
}
return 2;
}
generateFusionSpecies(forStarter?: boolean): void {
@ -2804,6 +2826,10 @@ export class PlayerPokemon extends Pokemon {
constructor(scene: BattleScene, species: PokemonSpecies, level: integer, abilityIndex: integer, formIndex: integer, gender: Gender, shiny: boolean, variant: Variant, ivs: integer[], nature: Nature, dataSource: Pokemon | PokemonData) {
super(scene, 106, 148, species, level, abilityIndex, formIndex, gender, shiny, variant, ivs, nature, dataSource);
if (Overrides.STATUS_OVERRIDE) {
this.status = new Status(Overrides.STATUS_OVERRIDE);
}
if (Overrides.SHINY_OVERRIDE) {
this.shiny = true;
this.initShinySparkle();
@ -3163,7 +3189,7 @@ export class PlayerPokemon extends Pokemon {
&& (m as PokemonHeldItemModifier).pokemonId === pokemon.id, true) as PokemonHeldItemModifier[];
const transferModifiers: Promise<boolean>[] = [];
for (const modifier of fusedPartyMemberHeldModifiers) {
transferModifiers.push(this.scene.tryTransferHeldItemModifier(modifier, this, true, false, true, true));
transferModifiers.push(this.scene.tryTransferHeldItemModifier(modifier, this, false, modifier.getStackCount(), true, true));
}
Promise.allSettled(transferModifiers).then(() => {
this.scene.updateModifiers(true, true).then(() => {
@ -3213,6 +3239,10 @@ export class EnemyPokemon extends Pokemon {
this.setBoss();
}
if (Overrides.OPP_STATUS_OVERRIDE) {
this.status = new Status(Overrides.OPP_STATUS_OVERRIDE);
}
if (!dataSource) {
this.generateAndPopulateMoveset();

View File

@ -1,6 +1,6 @@
import Phaser from "phaser";
import * as Utils from "./utils";
import {initTouchControls} from "./touch-controls";
import {ButtonKey, initTouchControls} from "./touch-controls";
import pad_generic from "./configs/pad_generic";
import pad_unlicensedSNES from "./configs/pad_unlicensedSNES";
import pad_xbox360 from "./configs/pad_xbox360";
@ -357,7 +357,7 @@ export class InputsController {
[Button.SPEED_UP]: [keyCodes.PLUS],
[Button.SLOW_DOWN]: [keyCodes.MINUS]
};
const mobileKeyConfig = {};
const mobileKeyConfig = new Map<string, ButtonKey>();
for (const b of Utils.getEnumValues(Button)) {
const keys: Phaser.Input.Keyboard.Key[] = [];
if (keyConfig.hasOwnProperty(b)) {

View File

@ -3,4 +3,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "{{pokemonName}} wurde durch {{abilityName}}\nvor Rückstoß geschützt!",
"badDreams": "{{pokemonName}} ist in einem Alptraum gefangen!",
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!",
} as const;

View File

@ -516,7 +516,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
},
"victory": {
1: "Oh, es scheint, als hätte ich verloren.",
2: "Es scheint, als hätte ich noch so viel mehr zu lernen, wenn es um den Kämpfe geht.",
2: "Es scheint, als hätte ich noch so viel mehr zu lernen, wenn es um Kämpfe geht.",
3: "Ich werde mir zu Herzen nehmen, was ich heute gelernt habe."
},
"defeat": {
@ -775,7 +775,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
},
"marshal": {
"encounter": {
1: `Mein Mentor, Lauro, sieht sieht Potential in dir. Ich werde dich testen,
1: `Mein Mentor, Lauro, sieht Potential in dir. Ich werde dich testen,
$dich an die Grenzen deiner Stärke bringen. Kiai!`,
2: "Ein Sieg, ein entscheidender Sieg, das ist mein Ziel! Herausforderer, hier komme ich!",
3: "Ich selber suche die Stärke eines Kämpfers zu entwickeln und jede Schwäche in mir zu brechen!"
@ -930,7 +930,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
},
"lacey": {
"encounter": {
1: "Ich werde dir mit meiner gewohnten Team, als Mitglied der Top Vier gegenüberstehen."
1: "Ich werde dir mit meinem gewohnten Team, als Mitglied der Top Vier gegenüberstehen."
},
"victory": {
1: "Das war ein großartiger Kampf!"
@ -1025,7 +1025,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
},
"cress": {
"encounter": {
1: "Das ist korrekt! Ich und meine geschätzten Wasser-Typen werden deine Gegner im Kampf sein!"
1: "Das ist korrekt! Ich und meine geschätzten Wasser-Pokémon werden deine Gegner im Kampf sein!"
},
"victory": {
1: "Verlieren? Ich? Das glaube ich nicht."
@ -1234,8 +1234,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
},
"bugsy": {
"encounter": {
1: `Wow, erstaunlich! Du bist ein Experte für Pokémon!
$Meine Forschung ist noch nicht abgeschlossen. OK, du gewinnst.`,
1: "Ich bin Kai, der Arenaleiter von Azalea City. Ich bin ein großer Fan von Käfer-Pokémon.",
},
"victory": {
1: `Wow, erstaunlich! Du bist ein Experte für Pokémon!

View File

@ -3,5 +3,7 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "{{pokemonName}}'s {{abilityName}}\nprotected it from recoil!",
"badDreams": "{{pokemonName}} is tormented!",
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!",
"perishBody": "{{pokemonName}}'s {{abilityName}}\nwill faint both pokemon in 3 turns!",
"poisonHeal": "{{pokemonName}}'s {{abilityName}}\nrestored its HP a little!"
} as const;

View File

@ -1203,8 +1203,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
},
"bugsy": {
"encounter": {
1: `Whoa, amazing! You're an expert on Pokémon!
$My research isn't complete yet. OK, you win.`,
1: "I'm Bugsy! I never lose when it comes to bug Pokémon!"
},
"victory": {
1: "Whoa, amazing! You're an expert on Pokémon!\nMy research isn't complete yet. OK, you win."

View File

@ -2,5 +2,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "¡{{abilityName}} de {{pokemonName}}\nlo protegió del daño de retroceso!",
"badDreams": "¡{{pokemonName}} está atormentado!"
"badDreams": "¡{{pokemonName}} está atormentado!",
"windPowerCharged": "¡{{pokemonName}} se ha cargado de electricidad gracias a {{moveName}}!",
} as const;

View File

@ -1203,8 +1203,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
},
"bugsy": {
"encounter": {
1: `Whoa, amazing! You're an expert on Pokémon!
$My research isn't complete yet. OK, you win.`,
1: "I'm Bugsy! I never lose when it comes to bug Pokémon!"
},
"victory": {
1: "Whoa, amazing! You're an expert on Pokémon!\nMy research isn't complete yet. OK, you win."

View File

@ -12,12 +12,12 @@ export const modifierType: ModifierTypeTranslationEntries = {
},
"PokemonHeldItemModifierType": {
extra: {
"inoperable": "¡{{pokemonName}} no puede\ntener este objeto!",
"tooMany": "¡{{pokemonName}} tiene este objeto\ndemasiada veces!",
"inoperable": "¡{{pokemonName}} no puede\nrecibir este objeto!",
"tooMany": "¡{{pokemonName}} tiene este objeto\ndemasiadas veces!",
}
},
"PokemonHpRestoreModifierType": {
description: "Restaura {{restorePoints}} PS o {{restorePercent}}% PS de un Pokémon, cualquiera de los dos sea el mas alto",
description: "Restaura {{restorePoints}} PS o, al menos, un {{restorePercent}}% PS de un Pokémon",
extra: {
"fully": "Restaura todos los PS de un Pokémon",
"fullyWithStatus": "Restaura todos los PS de un Pokémon y cura todos los problemas de estados",
@ -46,13 +46,13 @@ export const modifierType: ModifierTypeTranslationEntries = {
},
"PokemonNatureChangeModifierType": {
name: "Menta {{natureName}}",
description: "Cambia la naturaleza de un Pokémon a {{natureName}} y desbloquea permanentemente la naturaleza para el inicial",
description: "Cambia la naturaleza de un Pokémon a {{natureName}} y desbloquea permanentemente dicha naturaleza para el inicial",
},
"DoubleBattleChanceBoosterModifierType": {
description: "Duplica la posibilidad de que un encuentro sea una combate doble por {{battleCount}} combates",
description: "Duplica la posibilidad de que un encuentro sea una combate doble durante {{battleCount}} combates",
},
"TempBattleStatBoosterModifierType": {
description: "Aumenta el {{tempBattleStatName}} de todos los miembros del equipo en 1 nivel para 5 combates",
description: "Aumenta la est. {{tempBattleStatName}} de todos los miembros del equipo en 1 nivel durante 5 combates",
},
"AttackTypeBoosterModifierType": {
description: "Aumenta la potencia de los movimientos de tipo {{moveType}} de un Pokémon en un 20%",
@ -64,7 +64,7 @@ export const modifierType: ModifierTypeTranslationEntries = {
description: "Aumenta el nivel de todos los miembros del equipo en 1",
},
"PokemonBaseStatBoosterModifierType": {
description: "Aumenta {{statName}} base del portador en un 10%. Cuanto mayores sean tus IV, mayor será el límite de acumulación",
description: "Aumenta la est. {{statName}} base del portador en un 10%.\nCuanto mayores sean tus IVs, mayor será el límite de acumulación",
},
"AllPokemonFullHpRestoreModifierType": {
description: "Restaura el 100% de los PS de todos los Pokémon",
@ -75,7 +75,7 @@ export const modifierType: ModifierTypeTranslationEntries = {
"MoneyRewardModifierType": {
description: "Otorga una {{moneyMultiplier}} cantidad de dinero (₽{{moneyAmount}})",
extra: {
"small": "pequaña",
"small": "pequeña",
"moderate": "moderada",
"large": "gran",
},
@ -110,7 +110,7 @@ export const modifierType: ModifierTypeTranslationEntries = {
},
"TerastallizeModifierType": {
name: "Teralito {{teraType}}",
description: "Teracristaliza al portador al tipo {{teraType}} por 10 combates",
description: "Teracristaliza al portador al tipo {{teraType}} durante 10 combates",
},
"ContactHeldItemTransferChanceModifierType": {
description: "Al atacar, hay un {{chancePercent}}% de posibilidades de que robes el objeto que tiene el enemigo",
@ -128,11 +128,11 @@ export const modifierType: ModifierTypeTranslationEntries = {
"RARE_CANDY": { name: "Carameloraro" },
"RARER_CANDY": { name: "Rarer Candy" },
"MEGA_BRACELET": { name: "Mega-aro", description: "Las Megapiedras están disponible" },
"DYNAMAX_BAND": { name: "Maximuñequera", description: "Las Maxisetas están disponible" },
"TERA_ORB": { name: "Orbe Teracristal", description: "Los Teralitos están disponible" },
"MEGA_BRACELET": { name: "Mega-aro", description: "Las Megapiedras están disponibles" },
"DYNAMAX_BAND": { name: "Maximuñequera", description: "Las Maxisetas están disponibles" },
"TERA_ORB": { name: "Orbe Teracristal", description: "Los Teralitos están disponibles" },
"MAP": { name: "Mapa", description: "Te permite elegir tu destino" },
"MAP": { name: "Mapa", description: "Te permite elegir tu camino al final del bioma" },
"POTION": { name: "Poción" },
"SUPER_POTION": { name: "Superpoción" },
@ -145,7 +145,7 @@ export const modifierType: ModifierTypeTranslationEntries = {
"FULL_HEAL": { name: "Cura Total" },
"SACRED_ASH": { name: "Cen Sagrada" },
"SACRED_ASH": { name: "Cen. Sagrada" },
"REVIVER_SEED": { name: "Semilla Revivir", description: "Revive al portador con la mitad de sus PS al debilitarse" },
@ -165,9 +165,9 @@ export const modifierType: ModifierTypeTranslationEntries = {
"MEMORY_MUSHROOM": { name: "Memory Mushroom", description: "Recall one Pokémon's forgotten move" },
"EXP_SHARE": { name: "Repartir EXP", description: "Los que no combatan reciben el 20% de la EXP" },
"EXP_BALANCE": { name: "EXP. Balance", description: "Reparte la EXP recibida a los miembros del equipo que tengan menos nivel" },
"EXP_BALANCE": { name: "EXP. Balance", description: "Da mayor parte de la EXP recibida a los miembros del equipo que tengan menos nivel" },
"OVAL_CHARM": { name: "Amuleto Oval", description: "When multiple Pokémon participate in a battle, each gets an extra 10% of the total EXP" },
"OVAL_CHARM": { name: "Amuleto Oval", description: "Cada Pokémon combatiente recibe un 10% adicional de la EXP total" },
"EXP_CHARM": { name: "Amuleto EXP" },
"SUPER_EXP_CHARM": { name: "Super Amuleto EXP" },
@ -176,7 +176,7 @@ export const modifierType: ModifierTypeTranslationEntries = {
"LUCKY_EGG": { name: "Huevo Suerte" },
"GOLDEN_EGG": { name: "Huevo Dorado" },
"SOOTHE_BELL": { name: "Camp Alivio" },
"SOOTHE_BELL": { name: "Camp. Alivio" },
"SOUL_DEW": { name: "Rocío bondad", description: "Aumenta la influencia de la naturaleza de un Pokémon en sus estadísticas en un 10% (aditivo)" },
@ -184,13 +184,13 @@ export const modifierType: ModifierTypeTranslationEntries = {
"BIG_NUGGET": { name: "Maxipepita" },
"RELIC_GOLD": { name: "Real de oro" },
"AMULET_COIN": { name: "Moneda amuleto", description: "Aumenta el dinero ganado en un 20%" },
"AMULET_COIN": { name: "Moneda Amuleto", description: "Aumenta el dinero ganado en un 20%" },
"GOLDEN_PUNCH": { name: "Puño Dorado", description: "Otorga el 50% del daño infligido como dinero" },
"COIN_CASE": { name: "Monedero", description: "Después de cada 10 combates, recibe el 10% de tu dinero en intereses" },
"LOCK_CAPSULE": { name: "Cápsula candado", description: "Le permite bloquear las rarezas de los objetos al cambiar de objetos" },
"GRIP_CLAW": { name: "Garra garfio" },
"GRIP_CLAW": { name: "Garra Garfio" },
"WIDE_LENS": { name: "Lupa" },
"MULTI_LENS": { name: "Multi Lens" },
@ -214,7 +214,7 @@ export const modifierType: ModifierTypeTranslationEntries = {
"SHINY_CHARM": { name: "Amuleto Iris", description: "Aumenta drásticamente la posibilidad de que un Pokémon salvaje sea Shiny" },
"ABILITY_CHARM": { name: "Amuleto Habilidad", description: "Aumenta drásticamente la posibilidad de que un Pokémon salvaje tenga una habilidad oculta" },
"IV_SCANNER": { name: "Escáner IV", description: "Permite escanear los IV de Pokémon salvajes. Se revelan 2 IV por cada objeto Los mejores IV se muestran primero" },
"IV_SCANNER": { name: "Escáner IV", description: "Permite escanear los IVs de Pokémon salvajes. Se revelan 2 IVs por cada objeto.\nLos mejores IVs se muestran primero" },
"DNA_SPLICERS": { name: "Punta ADN" },
@ -241,7 +241,7 @@ export const modifierType: ModifierTypeTranslationEntries = {
"x_sp_def": "Def. Esp. X",
"x_speed": "Velocidad X",
"x_accuracy": "Precisión X",
"dire_hit": "Directo",
"dire_hit": "Crítico X",
},
AttackTypeBoosterItem: {
"silk_scarf": "Pañuelo Seda",
@ -274,7 +274,7 @@ export const modifierType: ModifierTypeTranslationEntries = {
EvolutionItem: {
"NONE": "None",
"LINKING_CORD": "Cordón unión",
"LINKING_CORD": "Cordón Unión",
"SUN_STONE": "Piedra Solar",
"MOON_STONE": "Piedra Lunar",
"LEAF_STONE": "Piedra Hoja",
@ -285,24 +285,24 @@ export const modifierType: ModifierTypeTranslationEntries = {
"DUSK_STONE": "Piedra Noche",
"DAWN_STONE": "Piedra Alba",
"SHINY_STONE": "Piedra Día",
"CRACKED_POT": "Tetera agrietada",
"SWEET_APPLE": "Manzana dulce",
"TART_APPLE": "Manzana ácida",
"STRAWBERRY_SWEET": "Confite fresa",
"UNREMARKABLE_TEACUP": "Cuenco mediocre",
"CRACKED_POT": "Tetera Agrietada",
"SWEET_APPLE": "Manzana Dulce",
"TART_APPLE": "Manzana Ácida",
"STRAWBERRY_SWEET": "Confite Fresa",
"UNREMARKABLE_TEACUP": "Cuenco Mediocre",
"CHIPPED_POT": "Tetera rota",
"BLACK_AUGURITE": "Mineral negro",
"GALARICA_CUFF": "Brazal galanuez",
"GALARICA_WREATH": "Corona galanuez",
"PEAT_BLOCK": "Bloque de turba",
"AUSPICIOUS_ARMOR": "Armadura auspiciosa",
"MALICIOUS_ARMOR": "Armadura maldita",
"MASTERPIECE_TEACUP": "Cuenco exquisito",
"METAL_ALLOY": "Metal compuesto",
"SCROLL_OF_DARKNESS": "Manuscrito sombras",
"SCROLL_OF_WATERS": "Manuscrito aguas",
"SYRUPY_APPLE": "Manzana melosa",
"CHIPPED_POT": "Tetera Rota",
"BLACK_AUGURITE": "Mineral Negro",
"GALARICA_CUFF": "Brazal Galanuez",
"GALARICA_WREATH": "Corona Galanuez",
"PEAT_BLOCK": "Bloque de Turba",
"AUSPICIOUS_ARMOR": "Armadura Auspiciosa",
"MALICIOUS_ARMOR": "Armadura Maldita",
"MASTERPIECE_TEACUP": "Cuenco Exquisito",
"METAL_ALLOY": "Metal Compuesto",
"SCROLL_OF_DARKNESS": "Manuscrito Sombras",
"SCROLL_OF_WATERS": "Manuscrito Aguas",
"SYRUPY_APPLE": "Manzana Melosa",
},
FormChangeItem: {
"NONE": "None",
@ -356,32 +356,32 @@ export const modifierType: ModifierTypeTranslationEntries = {
"TYRANITARITE": "Tyranitarita",
"VENUSAURITE": "Venusaurita",
"BLUE_ORB": "Blue Orb",
"RED_ORB": "Red Orb",
"SHARP_METEORITE": "Sharp Meteorite",
"HARD_METEORITE": "Hard Meteorite",
"SMOOTH_METEORITE": "Smooth Meteorite",
"ADAMANT_CRYSTAL": "Adamant Crystal",
"LUSTROUS_ORB": "Lustrous Orb",
"GRISEOUS_CORE": "Griseous Core",
"REVEAL_GLASS": "Reveal Glass",
"GRACIDEA": "Gracidea",
"MAX_MUSHROOMS": "Max Mushrooms",
"DARK_STONE": "Dark Stone",
"LIGHT_STONE": "Light Stone",
"PRISON_BOTTLE": "Prison Bottle",
"N_LUNARIZER": "N Lunarizer",
"N_SOLARIZER": "N Solarizer",
"RUSTED_SWORD": "Rusted Sword",
"RUSTED_SHIELD": "Rusted Shield",
"ICY_REINS_OF_UNITY": "Icy Reins Of Unity",
"SHADOW_REINS_OF_UNITY": "Shadow Reins Of Unity",
"WELLSPRING_MASK": "Wellspring Mask",
"HEARTHFLAME_MASK": "Hearthflame Mask",
"CORNERSTONE_MASK": "Cornerstone Mask",
"SHOCK_DRIVE": "Shock Drive",
"BURN_DRIVE": "Burn Drive",
"CHILL_DRIVE": "Chill Drive",
"DOUSE_DRIVE": "Douse Drive",
"BLUE_ORB": "Prisma Azul",
"RED_ORB": "Prisma Rojo",
"SHARP_METEORITE": "Meteorito Afilado",
"HARD_METEORITE": "Meteorito Duro",
"SMOOTH_METEORITE": "Meteorito Suave",
"ADAMANT_CRYSTAL": "Gran Diamansfera",
"LUSTROUS_ORB": "Gran Lustresfera",
"GRISEOUS_CORE": "Gran Griseosfera",
"REVEAL_GLASS": "Espejo Veraz",
"GRACIDEA": "Gracídea",
"MAX_MUSHROOMS": "MaxiSetas",
"DARK_STONE": "Piedra Oscura",
"LIGHT_STONE": "Piedra Luminosa",
"PRISON_BOTTLE": "Vasija Castigo",
"N_LUNARIZER": "Necroluna",
"N_SOLARIZER": "Necrosol",
"RUSTED_SWORD": "Espada Oxidada",
"RUSTED_SHIELD": "Escudo Oxidado",
"ICY_REINS_OF_UNITY": "Riendas Unión Heladas",
"SHADOW_REINS_OF_UNITY": "Riendas Unión Oscuras",
"WELLSPRING_MASK": "Máscara Fuente",
"HEARTHFLAME_MASK": "Máscara Horno",
"CORNERSTONE_MASK": "Máscara Cimiento",
"SHOCK_DRIVE": "FulgoROM",
"BURN_DRIVE": "PiroROM",
"CHILL_DRIVE": "CrioROM",
"DOUSE_DRIVE": "HidroROM",
},
} as const;

View File

@ -2,5 +2,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "{{abilityName}}\nde {{pokemonName}} le protège du contrecoup !",
"badDreams": "{{pokemonName}} a le sommeil agité !"
"badDreams": "{{pokemonName}} a le sommeil agité !",
"windPowerCharged": "{{pokemonName}} a été touché par la capacité {{moveName}} et se charge en électricité !"
} as const;

View File

@ -1203,8 +1203,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
},
"bugsy": {
"encounter": {
1: `Whoa, amazing! You're an expert on Pokémon!
$My research isn't complete yet. OK, you win.`,
1: "I'm Bugsy! I never lose when it comes to bug Pokémon!"
},
"victory": {
1: "Whoa, amazing! You're an expert on Pokémon!\nMy research isn't complete yet. OK, you win."

View File

@ -3,4 +3,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "{{abilityName}} di {{pokemonName}}\nl'ha protetto dal contraccolpo!",
"badDreams": "{{pokemonName}} è tormentato!",
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!",
} as const;

View File

@ -1203,8 +1203,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
},
"bugsy": {
"encounter": {
1: `Whoa, amazing! You're an expert on Pokémon!
$My research isn't complete yet. OK, you win.`,
1: "I'm Bugsy! I never lose when it comes to bug Pokémon!"
},
"victory": {
1: "Whoa, amazing! You're an expert on Pokémon!\nMy research isn't complete yet. OK, you win."

View File

@ -2,5 +2,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "{{pokemonName}}(는)은 {{abilityName}} 때문에\n반동 데미지를 받지 않는다!",
"badDreams": "{{pokemonName}} is tormented!",
"badDreams": "{{pokemonName}}(는)은\n나이트메어 때문에 시달리고 있다!",
} as const;

View File

@ -1203,8 +1203,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
},
"bugsy": {
"encounter": {
1: `Whoa, amazing! You're an expert on Pokémon!
$My research isn't complete yet. OK, you win.`,
1: "I'm Bugsy! I never lose when it comes to bug Pokémon!"
},
"victory": {
1: "Whoa, amazing! You're an expert on Pokémon!\nMy research isn't complete yet. OK, you win."
@ -2086,127 +2085,125 @@ export const PGMdialogue: DialogueTranslationEntries = {
},
"rival": {
"encounter": {
1: `@c{smile}Hey, I was looking for you! I knew you were eager to get going but I expected at least a goodbye
$@c{smile_eclosed}So you're really pursuing your dream after all?\n I almost can't believe it.
$@c{serious_smile_fists}Since we're here, how about a battle?\nAfter all, I want to make sure you're ready.
$@c{serious_mopen_fists}Don't hold back, I want you to give me everything you've got!`
1: `@c{smile}오, 찾았다! 떠나려는 건 알고 있었지만\n인사정도는 해줄 줄 알았는데
$@c{smile_eclosed} ?\n듣고도 믿.
$@c{serious_smile_fists} , ?\n준비가 .
$@c{serious_mopen_fists} ,\n너의 !`
},
"victory": {
1: `@c{shock}Wow… You cleaned me out.\nAre you actually a beginner?
$@c{smile}Maybe it was a bit of luck but\nWho knows you might just be able to go all the way.
$By the way, the professor asked me to give you these items. They look pretty cool.
$@c{serious_smile_fists}Good luck out there!`
1: `@c{shock}와… 정말 깔끔하게 당했네.\n초보자 맞아?
$@c{smile} \n그래도 .
$그나저나, .\n좋아 .
$@c{serious_smile_fists}, !`
},
},
"rival_female": {
"encounter": {
1: `@c{smile_wave}There you are! I've been looking everywhere for you!\n@c{angry_mopen}Did you forget to say goodbye to your best friend?
$@c{smile_ehalf}You're going after your dream, huh?\nThat day is really today isn't it
$@c{smile}Anyway, I'll forgive you for forgetting me, but on one condition. @c{smile_wave_wink}You have to battle me!
$@c{angry_mopen}Give it your all! Wouldn't want your adventure to be over before it started, right?`
1: `@c{smile_wave}여깄구나! 찾고 있었어!\n@c{angry_mopen}절친한테 작별인사도 안 하는거야?
$@c{smile_ehalf} . ?\n이런
$@c{smile}, .\n@c{smile_wave_wink} !
$@c{angry_mopen} .\n모험을 !`
},
"victory": {
1: `@c{shock}You just started and you're already this strong?!@d{96}\n@c{angry}You totally cheated, didn't you?
$@c{smile_wave_wink}Just kidding!@d{64} @c{smile_eclosed}I lost fair and square I have a feeling you're going to do really well out there.
$@c{smile}By the way, the professor wanted me to give you some items. Hopefully they're helpful!
$@c{smile_wave}Do your best like always! I believe in you!`
1: `@c{shock}왜 벌써 이렇게 센 건데?!@d{96}\n@c{angry}아니면 뭔가 속임수, 그런 거?
$@c{smile_wave_wink}, !@d{64} @c{smile_eclosed} \n너 .
$@c{smile} , .\n도움이 !
$@c{smile_wave} ! 믿 !`
},
},
"rival_2": {
"encounter": {
1: `@c{smile}Hey, you're here too?\n@c{smile_eclosed}Still a perfect record, huh…?
$@c{serious_mopen_fists}I know it kind of looks like I followed you here, but that's mostly not true.
$@c{serious_smile_fists}Honestly though, I've been itching for a rematch since you beat me back at home.
$I've been doing a lot of my own training so I'll definitely put up a fight this time.
$@c{serious_mopen_fists}Don't hold back, just like before!\nLet's go!`
1: `@c{smile}어라, 너 여깄었구나?\n@c{smile_eclosed}아직도 전승 중이라, 이거지…?
$@c{serious_mopen_fists} , .
$@c{serious_smile_fists} .
$ ?
$@c{serious_mopen_fists}, !\n배틀이야!`
},
"victory": {
1: `@c{neutral_eclosed}Oh. I guess I was overconfident.
$@c{smile}That's alright, though. I figured this might happen.\n@c{serious_mopen_fists}It just means I need to try harder for next time!\n
$@c{smile}Oh, not that you really need the help, but I had an extra one of these lying around and figured you might want it.\n
$@c{serious_smile_fists}Don't expect another one after this, though!\nI can't keep giving my opponent an advantage after all.
$@c{smile}Anyway, take care!`
1: `@c{neutral_eclosed}이런. 자신감이 과했나봐.
$@c{smile}, .\n@c{serious_mopen_fists} !\n
$@c{smile} , .\n남는 .
$@c{serious_smile_fists} , ?\n공평하게 .
$@c{smile} . !`
},
},
"rival_2_female": {
"encounter": {
1: `@c{smile_wave}Oh, fancy meeting you here. Looks like you're still undefeated. @c{angry_mopen}Huh… Not bad!
$@c{angry_mopen}I know what you're thinking, and no, I wasn't creeping on you. @c{smile_eclosed}I just happened to be in the area.
$@c{smile_ehalf}I'm happy for you but I just want to let you know that it's OK to lose sometimes.
$@c{smile}We learn from our mistakes, often more than we would if we kept succeeding.
$@c{angry_mopen}In any case, I've been training hard for our rematch, so you'd better give it your all!`
1: `@c{smile_wave}우연이네, 이런 곳에서 만나고.\n아직 연전연승이구나? @c{angry_mopen}나쁘지 않아!
$@c{angry_mopen} , .\n@c{smile_eclosed} .
$@c{smile_ehalf} , .
$@c{smile} .\n때로는 .
$@c{angry_mopen}, ,\n너도 !`
},
"victory": {
1: `@c{neutral}I… wasn't supposed to lose that time
$@c{smile}Aw well. That just means I'll have to train even harder for next time!
$@c{smile_wave}I also got you another one of these!\n@c{smile_wave_wink}No need to thank me~.
$@c{angry_mopen}This is the last one, though! You won't be getting anymore freebies from me after this!
$@c{smile_wave}Keep at it!`
1: `@c{neutral}이… 번에도 져버릴 줄이야
$@c{smile}, . !
$@c{smile_wave} !\n@c{smile_wave_wink} ~.
$@c{angry_mopen}, !\n또 !
$@c{smile_wave}!`
},
"defeat": {
1: "It's OK to lose sometimes…"
1: "가끔은 지는 것도 괜찮아…"
}
},
"rival_3": {
"encounter": {
1: `@c{smile}Hey, look who it is! It's been a while.\n@c{neutral}You're… still undefeated? Huh.
$@c{neutral_eclosed}Things have been kind of strange.\nIt's not the same back home without you.
$@c{serious}I know it's selfish, but I need to get this off my chest.\n@c{neutral_eclosed}I think you're in over your head here.
$@c{serious}Never losing once is just unrealistic.\nWe need to lose sometimes in order to grow.
$@c{neutral_eclosed}You've had a great run but there's still so much ahead, and it only gets harder. @c{neutral}Are you prepared for that?
$@c{serious_mopen_fists}If so, prove it to me.`
1: `@c{smile}이게 누구야! 오랜만이야.\n@c{neutral}역시나… 쭉 이기고 있었구나?
$@c{neutral_eclosed} . \n혼자 .
$@c{serious} .\n@c{neutral_eclosed} .
$@c{serious} .\n사람은 .
$@c{neutral_eclosed} ,\n갈 . @c{neutral} ?
$@c{serious_mopen_fists}, .`
},
"victory": {
1: "@c{angry_mhalf}This is ridiculous… I've hardly stopped training…\nHow are we still so far apart?"
1: "@c{angry_mhalf}말도 안 돼… 한시도 쉬지 않고 훈련했는데…\n어째서 전혀 닿을 수 없는거야?"
},
},
"rival_3_female": {
"encounter": {
1: `@c{smile_wave}Long time no see! Still haven't lost, huh.\n@c{angry}You're starting to get on my nerves. @c{smile_wave_wink}Just kidding!
$@c{smile_ehalf}But really, don't you miss home by now? Or… me?\nI… I mean, we've really missed you.
$@c{smile_eclosed}I support you in your dream and everything, but the reality is you're going to lose sooner or later.
$@c{smile}And when you do, I'll be there for you like always.\n@c{angry_mopen}Now, let me show you how strong I've become!`
1: `@c{smile_wave}오랜만이야! 아직도 안 졌구나.\n@c{angry}거슬리게 말야. @c{smile_wave_wink}농담이야!
$@c{smile_ehalf} , ? ?\n나 , .
$@c{smile_eclosed} ,\n넌 .
$@c{smile} .\n@c{angry_mopen} , !`
},
"victory": {
1: "@c{shock}After all that… it wasn't enough…?\nYou'll never come back at this rate…"
1: "@c{shock}이렇게까지 했는데도… 모자랐던 거야…?\n이러면 정말로 너는 이제 영영…"
},
"defeat": {
1: "You gave it your best, now let's go home."
1: "최선을 다 했지.\n집에 갈 시간이야."
}
},
"rival_4": {
"encounter": {
1: `@c{neutral}Hey.
$I won't mince words or pleasantries with you.\n@c{neutral_eclosed}I'm here to win, plain and simple.
$@c{serious_mhalf_fists}I've learned to maximize my potential by putting all my time into training.
$@c{smile}You get a lot of extra time when you cut out the unnecessary sleep and social interaction.
$@c{serious_mopen_fists}None of that matters anymore, not until I win.
$@c{neutral_eclosed}I've even reached the point where I don't lose anymore.\n@c{smile_eclosed}I suppose your philosophy wasn't so wrong after all.
$@c{angry_mhalf}Losing is for the weak, and I'm not weak anymore.
$@c{serious_mopen_fists}Prepare yourself.`
1: `@c{neutral}안녕.
$잡담은 .\n@c{neutral_eclosed} . .
$@c{serious_mhalf_fists} .
$@c{smile} .\n줄일 .
$@c{serious_mopen_fists} .\n이제 .
$@c{neutral_eclosed} .\n@c{smile_eclosed} .
$@c{angry_mhalf} , .
$@c{serious_mopen_fists}.`
},
"victory": {
1: "@c{neutral}What…@d{64} What are you?"
1: "@c{neutral}너…@d{64} 너 대체 뭐야?"
},
},
"rival_4_female": {
"encounter": {
1: `@c{neutral}It's me! You didn't forget about me again… did you?
$@c{smile}You should be proud of how far you made it. Congrats!\nBut it looks like it's the end of your journey.
$@c{smile_eclosed}You've awoken something in me I never knew was there.\nIt seems like all I do now is train.
$@c{smile_ehalf}I hardly even eat or sleep now, I just train my Pokémon all day, getting stronger every time.
$@c{neutral}In fact, I hardly recognize myself.
$And now, I've finally reached peak performance.\nI don't think anyone could beat me now.
$And you know what? It's all because of you.\n@c{smile_ehalf}I don't know whether to thank you or hate you.
$@c{angry_mopen}Prepare yourself.`
1: `@c{neutral}나야! 날 잊어버리고 있던 건… 아니지?
$@c{smile} . !\n하지만 .
$@c{smile_eclosed} .\n이제 .
$@c{smile_ehalf} , .\n더 .
$@c{neutral}, .
$그렇지만 , .\n아무도 .
$그거 ? .\n@c{smile_ehalf} .
$@c{angry_mopen}.`
},
"victory": {
1: "@c{neutral}What…@d{64} What are you?"
1: "@c{neutral}너…@d{64} 너 대체 뭐야?"
},
"defeat": {
1: "$@c{smile}You should be proud of how far you made it."
1: "$@c{smile}네가 키운 상대야. 자랑스럽지?"
}
},
"rival_5": {
@ -2231,47 +2228,46 @@ export const PGMdialogue: DialogueTranslationEntries = {
},
"rival_6": {
"encounter": {
1: `@c{smile_eclosed}We meet again.
$@c{neutral}I've had some time to reflect on all this.\nThere's a reason this all seems so strange.
$@c{neutral_eclosed}Your dream, my drive to beat you\nIt's all a part of something greater.
$@c{serious}This isn't about me, or about you… This is about the world, @c{serious_mhalf_fists}and it's my purpose to push you to your limits.
$@c{neutral_eclosed}Whether I've fulfilled that purpose I can't say, but I've done everything in my power.
$@c{neutral}This place we ended up in is terrifying Yet somehow I feel unphased, like I've been here before.
$@c{serious_mhalf_fists}You feel the same, don't you?
$@c{serious}and it's like something here is speaking to me.\nThis is all the world's known for a long time now.
$Those times we cherished together that seem so recent are nothing but a distant memory.
$@c{neutral_eclosed}Who can say whether they were ever even real in the first place.
$@c{serious_mopen_fists}You need to keep pushing, because if you don't, it will never end. You're the only one who can do this.
$@c{serious_smile_fists}I hardly know what any of this means, I just know that it's true.
$@c{serious_mopen_fists}If you can't defeat me here and now, you won't stand a chance.`
1: `@c{smile_eclosed}다시 만났구나.
$@c{neutral} .\n이 .
$@c{neutral_eclosed} , \n이건 .
$@c{serious} \n@c{serious_mhalf_fists} .
$@c{neutral_eclosed} .
$@c{neutral} \n언젠가 .
$@c{serious_mhalf_fists} ?
$@c{serious} .\n오랫동안 .
$우리가 .
$@c{neutral_eclosed} ?
$@c{serious_mopen_fists} . .\n오직 .
$@c{serious_smile_fists} , .
$@c{serious_mopen_fists} , .`
},
"victory": {
1: `@c{smile_eclosed}It looks like my work is done here.
$I want you to promise me one thing.\n@c{smile}After you heal the world, please come home.`
1: `@c{smile_eclosed}내 역할은 여기까진 것 같아.
$하나만 .\n@c{smile} , .`
},
},
"rival_6_female": {
"encounter": {
1: `@c{smile_ehalf}So it's just us again.
$@c{smile_eclosed}You know, I keep going around and around in my head
$@c{smile_ehalf}There's something to all this, why everything seems so strange now
$@c{smile}You have your dream, and I have this ambition in me
$I just can't help but feel there's a greater purpose to all this, to what we're doing, you and I.
$@c{smile_eclosed}I think I'm supposed to push you to your limits.
$@c{smile_ehalf}I'm not sure if I've been doing a good job at that, but I've tried my best up to now.
$It's something about this strange and dreadful place Everything seems so clear
$This is all the world's known for a long time now.
$@c{smile_eclosed}It's like I can barely remember the memories we cherished together.
$@c{smile_ehalf}Were they even real? They seem so far away now
$@c{angry_mopen}You need to keep pushing, because if you don't, it will never end. You're the only one who can do this.
$@c{smile_ehalf}I don't know what all this means… but I feel it's true.
$@c{neutral}If you can't defeat me here and now, you won't stand a chance.`
1: `@c{smile_ehalf}또 이렇게 만났네.
$@c{smile_eclosed} 릿
$@c{smile_ehalf} .\n분명
$@c{smile} ,\n나는
$, \n더 .
$@c{smile_eclosed} \n한계까지 .
$@c{smile_ehalf} , .
$ \n모든게
$이건 .
$@c{smile_eclosed} , .
$@c{smile_ehalf} ?
$@c{angry_mopen} . , . \n오직 .
$@c{smile_ehalf} \n이거 .
$@c{neutral} , .`
},
"victory": {
1: `@c{smile_ehalf}I… I think I fulfilled my purpose…
$@c{smile_eclosed}Promise me After you heal the world Please come home safe.
$@c{smile_ehalf}Thank you.`
1: `@c{smile_ehalf}나… 내 소임을 다 한 기분이야…
$@c{smile_eclosed} \n집으로 .
$@c{smile_ehalf}.`
},
},
};
@ -2282,17 +2278,17 @@ export const PGFdialogue: DialogueTranslationEntries = PGMdialogue;
// Dialogue of the endboss of the game when the player character is male (Or unset)
export const PGMbattleSpecDialogue: SimpleTranslationEntries = {
"encounter": `It appears the time has finally come once again.\nYou know why you have come here, do you not?
$You were drawn here, because you have been here before.\nCountless times.
$Though, perhaps it can be counted.\nTo be precise, this is in fact your 5,643,853rd cycle.
$Each cycle your mind reverts to its former state.\nEven so, somehow, remnants of your former selves remain.
$Until now you have yet to succeed, but I sense a different presence in you this time.\n
$You are the only one here, though it is as if there is another.
$Will you finally prove a formidable challenge to me?\nThe challenge I have longed for for millennia?
$We begin.`,
"firstStageWin": `I see. The presence I felt was indeed real.\nIt appears I no longer need to hold back.
$Do not disappoint me.`,
"secondStageWin": "…Magnificent."
"encounter": `드디어 때가 다시 도래했다.\n당도한 연유를 아는가?
$이미 .\n셀 .
$아니, .\n정확히 5,643,853.
$ .\n하지만 , .
$실패만을 ,\n지금은 .\n
$홀로 ,
$마침내 ?\n수천 ?
$시작하지.`,
"firstStageWin": `그렇군. 정말로 있었어.\n이제 주저할 필요는 없다.
$실망시키지 .`,
"secondStageWin": "…고무적이군."
};
// Dialogue of the endboss of the game when the player character is female. For languages that do not have gendered pronouns, this can be set to PGMbattleSpecDialogue.
@ -2301,22 +2297,22 @@ export const PGFbattleSpecDialogue: SimpleTranslationEntries = PGMbattleSpecDial
// Dialogue that does not fit into any other category (e.g. tutorial messages, or the end of the game). For when the player character is male
export const PGMmiscDialogue: SimpleTranslationEntries = {
"ending":
`@c{smile}Oh? You won?@d{96} @c{smile_eclosed}I guess I should've known.\nBut, you're back now.
$@c{smile}It's over.@d{64} You ended the loop.
$@c{serious_smile_fists}You fulfilled your dream too, didn't you?\nYou didn't lose even once.
$@c{neutral}I'm the only one who'll remember what you did.@d{96}\nI guess that's okay, isn't it?
$@c{serious_smile_fists}Your legend will always live on in our hearts.
$@c{smile_eclosed}Anyway, I've had about enough of this place, haven't you? Let's head home.
$@c{serious_smile_fists}Maybe when we get back, we can have another battle?\nIf you're up to it.`,
`@c{smile}오? 이긴거야?@d{96} @c{smile_eclosed}진즉 알았어야 했는데.\n아무튼, 돌아왔구나.
$@c{smile} .@d{64} .
$@c{serious_smile_fists} .\n진짜로 .
$@c{neutral} .@d{96}\n그래도, ?
$@c{serious_smile_fists} \n너와 .
$@c{smile_eclosed} \n이제 .
$@c{serious_smile_fists}, ?\n네가 .`,
"ending_female":
`@c{shock}You're back?@d{32} Does that mean…@d{96} you won?!\n@c{smile_ehalf}I should have known you had it in you.
$@c{smile_eclosed}Of course I always had that feeling.\n@c{smile}It's over now, right? You ended the loop.
$@c{smile_ehalf}You fulfilled your dream too, didn't you?\nYou didn't lose even once.
$I'll be the only one to remember what you did.\n@c{angry_mopen}I'll try not to forget!
$@c{smile_wave_wink}Just kidding!@d{64} @c{smile}I'd never forget.@d{32}\nYour legend will live on in our hearts.
$@c{smile_wave}Anyway,@d{64} it's getting late…@d{96} I think?\nIt's hard to tell in this place.
$Let's go home. @c{smile_wave_wink}Maybe tomorrow, we can have another battle, for old time's sake?`,
"ending_endless": "Congratulations on reaching the current end!\nMore content is coming soon.",
`@c{shock}돌아왔구나?@d{32} 그 말은…@d{96} 이겼어?!\n@c{smile_ehalf}그럴 줄 알았다니까.
$@c{smile_eclosed} .\n@c{smile} , ? .
$@c{smile_ehalf} .\n어떻게 ?
$네가 .\n@c{angry_mopen}, !
$@c{smile_wave_wink}!@d{64} @c{smile} .@d{32}\n오늘 .
$@c{smile_wave},@d{64} @d{96}\n이런 ?
$집에 . @c{smile_wave_wink} ,\n추억을 .`,
"ending_endless": "끝에 도달하신 것을 축하드립니다!\n더 많은 컨텐츠를 기다려주세요.",
"ending_name": "Devs"
};
// Dialogue that does not fit into any other category (e.g. tutorial messages, or the end of the game). For when the player character is female. For languages that do not have gendered pronouns, this can be set to PGMmiscDialogue.

View File

@ -11,6 +11,7 @@ export const menu: SimpleTranslationEntries = {
"dailyRun": "데일리 런 (베타)",
"loadGame": "불러오기",
"newGame": "새 게임",
"settings": "설정",
"selectGameMode": "게임 모드를 선택해주세요.",
"logInOrCreateAccount": "로그인 또는 등록을 해 주세요. 개인정보를 요구하지 않습니다!",
"username": "이름",

View File

@ -3,4 +3,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "{{abilityName}} de {{pokemonName}}\nprotegeu-o do dano de recuo!",
"badDreams": "{{pokemonName}} está tendo pesadelos!",
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!"
} as const;

View File

@ -1203,8 +1203,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
},
"bugsy": {
"encounter": {
1: `Whoa, amazing! You're an expert on Pokémon!
$My research isn't complete yet. OK, you win.`,
1: "I'm Bugsy! I never lose when it comes to bug Pokémon!"
},
"victory": {
1: "Whoa, amazing! You're an expert on Pokémon!\nMy research isn't complete yet. OK, you win."

View File

@ -2,5 +2,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "{{pokemonName}} 的 {{abilityName}}\n抵消了反作用力",
"badDreams": "{{pokemonName}} 被折磨着!"
"badDreams": "{{pokemonName}} 被折磨着!",
"windPowerCharged": "受 {{moveName}} 的影响, {{pokemonName}} 提升了能力!"
} as const;

View File

@ -1203,8 +1203,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
},
"bugsy": {
"encounter": {
1: `Whoa, amazing! You're an expert on Pokémon!
$My research isn't complete yet. OK, you win.`,
1: "I'm Bugsy! I never lose when it comes to bug Pokémon!"
},
"victory": {
1: "Whoa, amazing! You're an expert on Pokémon!\nMy research isn't complete yet. OK, you win."

View File

@ -3,4 +3,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "{{pokemonName}} 的 {{abilityName}}\n抵消了反作用力!",
"badDreams": "{{pokemonName}} 被折磨着!",
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!"
} as const;

View File

@ -1203,8 +1203,7 @@ export const PGMdialogue: DialogueTranslationEntries = {
},
"bugsy": {
"encounter": {
1: `Whoa, amazing! You're an expert on Pokémon!
$My research isn't complete yet. OK, you win.`,
1: "I'm Bugsy! I never lose when it comes to bug Pokémon!"
},
"victory": {
1: "Whoa, amazing! You're an expert on Pokémon!\nMy research isn't complete yet. OK, you win."

View File

@ -1868,7 +1868,7 @@ export abstract class HeldItemTransferModifier extends PokemonHeldItemModifier {
}
const randItemIndex = pokemon.randSeedInt(itemModifiers.length);
const randItem = itemModifiers[randItemIndex];
heldItemTransferPromises.push(pokemon.scene.tryTransferHeldItemModifier(randItem, pokemon, false, false).then(success => {
heldItemTransferPromises.push(pokemon.scene.tryTransferHeldItemModifier(randItem, pokemon, false).then(success => {
if (success) {
transferredModifierTypes.push(randItem.type);
itemModifiers.splice(randItemIndex, 1);

View File

@ -13,6 +13,7 @@ import { PokeballCounts } from "./battle-scene";
import { PokeballType } from "./data/pokeball";
import {TimeOfDay} from "#app/data/enums/time-of-day";
import { Gender } from "./data/gender";
import { StatusEffect } from "./data/status-effect";
/**
* Overrides for testing different in game situations
@ -63,6 +64,7 @@ export const STARTING_LEVEL_OVERRIDE: integer = 0;
export const STARTER_SPECIES_OVERRIDE: Species | integer = 0;
export const ABILITY_OVERRIDE: Abilities = Abilities.NONE;
export const PASSIVE_ABILITY_OVERRIDE: Abilities = Abilities.NONE;
export const STATUS_OVERRIDE: StatusEffect = StatusEffect.NONE;
export const GENDER_OVERRIDE: Gender = null;
export const MOVESET_OVERRIDE: Array<Moves> = [];
export const SHINY_OVERRIDE: boolean = false;
@ -76,6 +78,7 @@ export const OPP_SPECIES_OVERRIDE: Species | integer = 0;
export const OPP_LEVEL_OVERRIDE: number = 0;
export const OPP_ABILITY_OVERRIDE: Abilities = Abilities.NONE;
export const OPP_PASSIVE_ABILITY_OVERRIDE = Abilities.NONE;
export const OPP_STATUS_OVERRIDE: StatusEffect = StatusEffect.NONE;
export const OPP_GENDER_OVERRIDE: Gender = null;
export const OPP_MOVESET_OVERRIDE: Array<Moves> = [];
export const OPP_SHINY_OVERRIDE: boolean = false;

View File

@ -1513,7 +1513,7 @@ export class SwitchSummonPhase extends SummonPhase {
const batonPassModifier = this.scene.findModifier(m => m instanceof SwitchEffectTransferModifier
&& (m as SwitchEffectTransferModifier).pokemonId === this.lastPokemon.id) as SwitchEffectTransferModifier;
if (batonPassModifier && !this.scene.findModifier(m => m instanceof SwitchEffectTransferModifier && (m as SwitchEffectTransferModifier).pokemonId === switchedPokemon.id)) {
this.scene.tryTransferHeldItemModifier(batonPassModifier, switchedPokemon, false, false);
this.scene.tryTransferHeldItemModifier(batonPassModifier, switchedPokemon, false);
}
}
}
@ -2194,9 +2194,7 @@ export class TurnStartPhase extends FieldPhase {
}
if (this.scene.arena.weather) {
this.scene.pushPhase(new WeatherEffectPhase(this.scene, this.scene.arena.weather));
}
this.scene.pushPhase(new WeatherEffectPhase(this.scene));
for (const o of order) {
if (field[o].status && field[o].status.isPostTurn()) {
@ -2379,6 +2377,10 @@ export class CommonAnimPhase extends PokemonPhase {
this.targetIndex = targetIndex;
}
setAnimation(anim: CommonAnim) {
this.anim = anim;
}
start() {
new CommonBattleAnim(this.anim, this.getPokemon(), this.targetIndex !== undefined ? (this.player ? this.scene.getEnemyField() : this.scene.getPlayerField())[this.targetIndex] : this.getPokemon()).play(this.scene, () => {
this.end();
@ -3202,12 +3204,22 @@ export class StatChangePhase extends PokemonPhase {
export class WeatherEffectPhase extends CommonAnimPhase {
public weather: Weather;
constructor(scene: BattleScene, weather: Weather) {
super(scene, undefined, undefined, CommonAnim.SUNNY + (weather.weatherType - 1));
this.weather = weather;
constructor(scene: BattleScene) {
super(scene, undefined, undefined, CommonAnim.SUNNY + ((scene?.arena?.weather?.weatherType || WeatherType.NONE) - 1));
this.weather = scene?.arena?.weather;
}
start() {
// Update weather state with any changes that occurred during the turn
this.weather = this.scene?.arena?.weather;
if (!this.weather) {
this.end();
return;
}
this.setAnimation(CommonAnim.SUNNY + (this.weather.weatherType - 1));
if (this.weather.isDamaging()) {
const cancelled = new Utils.BooleanHolder(false);
@ -4841,6 +4853,8 @@ export class SelectModifierPhase extends BattlePhase {
if (!this.rerollCount) {
this.updateSeed();
} else {
this.scene.reroll = false;
}
const party = this.scene.getParty();
@ -4872,6 +4886,7 @@ export class SelectModifierPhase extends BattlePhase {
this.scene.ui.playError();
return false;
} else {
this.scene.reroll = true;
this.scene.unshiftPhase(new SelectModifierPhase(this.scene, this.rerollCount + 1, typeOptions.map(o => o.type.tier)));
this.scene.ui.clearText();
this.scene.ui.setMode(Mode.MESSAGE).then(() => super.end());
@ -4880,14 +4895,12 @@ export class SelectModifierPhase extends BattlePhase {
this.scene.playSound("buy");
}
} else if (cursor === 1) {
this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.MODIFIER_TRANSFER, -1, (fromSlotIndex: integer, itemIndex: integer, toSlotIndex: integer) => {
this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.MODIFIER_TRANSFER, -1, (fromSlotIndex: integer, itemIndex: integer, itemQuantity: integer, toSlotIndex: integer) => {
if (toSlotIndex !== undefined && fromSlotIndex < 6 && toSlotIndex < 6 && fromSlotIndex !== toSlotIndex && itemIndex > -1) {
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, this.getRerollCost(typeOptions, this.scene.lockModifierTiers)).then(() => {
const itemModifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier
&& (m as PokemonHeldItemModifier).getTransferrable(true) && (m as PokemonHeldItemModifier).pokemonId === party[fromSlotIndex].id) as PokemonHeldItemModifier[];
const itemModifier = itemModifiers[itemIndex];
this.scene.tryTransferHeldItemModifier(itemModifier, party[toSlotIndex], true, true);
});
this.scene.tryTransferHeldItemModifier(itemModifier, party[toSlotIndex], true, itemQuantity);
} else {
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, this.getRerollCost(typeOptions, this.scene.lockModifierTiers));
}

View File

@ -80,26 +80,30 @@ export interface Localizable {
const alternativeFonts = {
"ko": [
new FontFace("emerald", "url(./fonts/PokePT_Wansung.ttf)")
new FontFace("emerald", "url(./fonts/PokePT_Wansung.ttf)"),
],
};
function loadFont(language: string) {
const altFontLanguages = Object.keys(alternativeFonts);
if (!alternativeFonts[language]) {
language = language.split(/[-_/]/)[0];
}
if (alternativeFonts[language]) {
alternativeFonts[language].forEach(f => {
document.fonts.add(f);
alternativeFonts[language].forEach((fontFace: FontFace) => {
document.fonts.add(fontFace);
});
const altFontLanguages = Object.keys(alternativeFonts);
altFontLanguages.splice(altFontLanguages.indexOf(language), 0);
}
altFontLanguages.forEach(f=> {
if (f && f.status === "loaded") {
document.fonts.delete(f);
(Object.values(alternativeFonts)).forEach(fontFaces => {
fontFaces.forEach(fontFace => {
if (fontFace && fontFace.status === "loaded") {
document.fonts.delete(fontFace);
}
});
});
}
export function initI18n(): void {
@ -179,6 +183,7 @@ export function initI18n(): void {
// Module declared to make referencing keys in the localization files type-safe.
declare module "i18next" {
interface CustomTypeOptions {
defaultNS: "menu"; // Even if we don't use it, i18next requires a valid default namespace
resources: {
menu: SimpleTranslationEntries;
menuUiHandler: SimpleTranslationEntries;

View File

@ -1,9 +1,9 @@
interface ButtonKey {
export interface ButtonKey {
onDown: (opt: object) => void;
onUp: (opt: object) => void;
}
type ButtonMap = Map<string, ButtonKey>;
export type ButtonMap = Map<string, ButtonKey>;
export const keys = new Map();
export const keysDown = new Map();

View File

@ -147,6 +147,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
this.scene.showFieldOverlay(750);
this.scene.updateAndShowText(750);
this.scene.updateMoneyText();
let i = 0;
@ -382,7 +383,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
this.eraseCursor();
this.scene.hideFieldOverlay(250);
this.scene.hideLuckText(750);
this.scene.hideLuckText(250);
const options = this.options.concat(this.shopOptionsRows.flat());
this.options.splice(0, this.options.length);

View File

@ -57,7 +57,7 @@ export enum PartyOption {
}
export type PartySelectCallback = (cursor: integer, option: PartyOption) => void;
export type PartyModifierTransferSelectCallback = (fromCursor: integer, index: integer, toCursor?: integer) => void;
export type PartyModifierTransferSelectCallback = (fromCursor: integer, index: integer, itemQuantity?: integer, toCursor?: integer) => void;
export type PartyModifierSpliceSelectCallback = (fromCursor: integer, toCursor?: integer) => void;
export type PokemonSelectFilter = (pokemon: PlayerPokemon) => string;
export type PokemonModifierTransferSelectFilter = (pokemon: PlayerPokemon, modifier: PokemonHeldItemModifier) => string;
@ -87,6 +87,10 @@ export default class PartyUiHandler extends MessageUiHandler {
private transferMode: boolean;
private transferOptionCursor: integer;
private transferCursor: integer;
/** Current quantity selection for every item held by the pokemon selected for the transfer */
private transferQuantities: integer[];
/** Stack size of every item that the selected pokemon is holding */
private transferQuantitiesMax: integer[];
private lastCursor: integer = 0;
private selectCallback: PartySelectCallback | PartyModifierTransferSelectCallback;
@ -231,8 +235,8 @@ export default class PartyUiHandler extends MessageUiHandler {
let success = false;
if (this.optionsMode) {
if (button === Button.ACTION) {
const option = this.options[this.optionsCursor];
if (button === Button.ACTION) {
const pokemon = this.scene.getParty()[this.cursor];
if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER && !this.transferMode && option !== PartyOption.CANCEL) {
this.startTransfer();
@ -270,7 +274,9 @@ export default class PartyUiHandler extends MessageUiHandler {
}
if (this.selectCallback) {
if (option === PartyOption.TRANSFER) {
(this.selectCallback as PartyModifierTransferSelectCallback)(this.transferCursor, this.transferOptionCursor, this.cursor);
if (this.transferCursor !== this.cursor) {
(this.selectCallback as PartyModifierTransferSelectCallback)(this.transferCursor, this.transferOptionCursor, this.transferQuantities[this.transferOptionCursor], this.cursor);
}
this.clearTransfer();
} else if (this.partyUiMode === PartyUiMode.SPLICE) {
if (option === PartyOption.SPLICE) {
@ -369,17 +375,50 @@ export default class PartyUiHandler extends MessageUiHandler {
return true;
} else {
switch (button) {
case Button.LEFT:
/** Decrease quantity for the current item and update UI */
if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) {
this.transferQuantities[option] = this.transferQuantities[option] === 1 ? this.transferQuantitiesMax[option] : this.transferQuantities[option] - 1;
this.updateOptions();
success = this.setCursor(this.optionsCursor); /** Place again the cursor at the same position. Necessary, otherwise the cursor disappears */
}
break;
case Button.RIGHT:
/** Increase quantity for the current item and update UI */
if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) {
this.transferQuantities[option] = this.transferQuantities[option] === this.transferQuantitiesMax[option] ? 1 : this.transferQuantities[option] + 1;
this.updateOptions();
success = this.setCursor(this.optionsCursor); /** Place again the cursor at the same position. Necessary, otherwise the cursor disappears */
}
break;
case Button.UP:
success = this.setCursor(this.optionsCursor ? this.optionsCursor - 1 : this.options.length - 1);
/** If currently selecting items to transfer, reset quantity selection */
if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) {
this.transferQuantities[option] = this.transferQuantitiesMax[option];
this.updateOptions();
}
success = this.setCursor(this.optionsCursor ? this.optionsCursor - 1 : this.options.length - 1); /** Move cursor */
break;
case Button.DOWN:
success = this.setCursor(this.optionsCursor < this.options.length - 1 ? this.optionsCursor + 1 : 0);
/** If currently selecting items to transfer, reset quantity selection */
if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) {
this.transferQuantities[option] = this.transferQuantitiesMax[option];
this.updateOptions();
}
success = this.setCursor(this.optionsCursor < this.options.length - 1 ? this.optionsCursor + 1 : 0); /** Move cursor */
break;
}
}
} else {
if (button === Button.ACTION) {
if (this.cursor < 6) {
if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER && !this.transferMode) {
/** Initialize item quantities for the selected Pokemon */
const itemModifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier
&& (m as PokemonHeldItemModifier).getTransferrable(true) && (m as PokemonHeldItemModifier).pokemonId === this.scene.getParty()[this.cursor].id) as PokemonHeldItemModifier[];
this.transferQuantities = itemModifiers.map(item => item.getStackCount());
this.transferQuantitiesMax = itemModifiers.map(item => item.getStackCount());
}
this.showOptions();
ui.playSelect();
} else if (this.partyUiMode === PartyUiMode.FAINT_SWITCH || this.partyUiMode === PartyUiMode.REVIVAL_BLESSING) {
@ -555,7 +594,7 @@ export default class PartyUiHandler extends MessageUiHandler {
break;
case PartyUiMode.MODIFIER_TRANSFER:
if (!this.transferMode) {
optionsMessage = "Select a held item to transfer.";
optionsMessage = "Select a held item to transfer.\nUse < and > to change the quantity.";
}
break;
case PartyUiMode.SPLICE:
@ -569,7 +608,12 @@ export default class PartyUiHandler extends MessageUiHandler {
this.updateOptions();
/** When an item is being selected for transfer, the message box is taller as the message occupies two lines */
if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) {
this.partyMessageBox.setSize(262 - Math.max(this.optionsBg.displayWidth - 56, 0), 42);
} else {
this.partyMessageBox.setSize(262 - Math.max(this.optionsBg.displayWidth - 56, 0), 30);
}
this.setCursor(0);
}
@ -741,8 +785,9 @@ export default class PartyUiHandler extends MessageUiHandler {
} else {
const itemModifier = itemModifiers[option];
optionName = itemModifier.type.name;
if (itemModifier.stackCount > 1) {
optionName += ` (${itemModifier.stackCount})`;
/** For every item that has stack bigger than 1, display the current quantity selection */
if (this.transferQuantitiesMax[option] > 1) {
optionName += ` (${this.transferQuantities[option]})`;
}
}

View File

@ -1339,11 +1339,27 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
case Button.UP:
if (row) {
success = this.setCursor(this.cursor - 9);
} else {
// when strictly opposite starter based on rows length
// does not exits, set cursor on the second to last row
if (this.cursor + (rows - 1) * 9 > genStarters - 1) {
success = this.setCursor(this.cursor + (rows - 2) * 9);
} else {
success = this.setCursor(this.cursor + (rows - 1) * 9);
}
}
break;
case Button.DOWN:
if (row < rows - 2 || (row < rows - 1 && this.cursor % 9 <= (genStarters - 1) % 9)) {
success = this.setCursor(this.cursor + 9);
} else {
// if there is no starter below while being on the second to
// last row, adjust cursor position with one line less
if (row === rows - 2 && this.cursor + 9 > genStarters - 1) {
success = this.setCursor(this.cursor - (rows - 2) * 9);
} else {
success = this.setCursor(this.cursor - (rows - 1) * 9);
}
}
break;
case Button.LEFT:

View File

@ -68,7 +68,14 @@ export class StatsContainer extends Phaser.GameObjects.Container {
this.statsIvsCache = ivChartData.slice(0);
this.ivStatValueTexts.map((t: BBCodeText, i: integer) => {
let label = ivs[i].toString();
let label = "";
// Check to see if IVs are 31, if so change the text style to gold, otherwise leave them be.
if (ivs[i] === 31) {
label += `[color=${getTextColor(TextStyle.SUMMARY_GOLD, false, (this.scene as BattleScene).uiTheme)}][shadow]${ivs[i].toString()}[/shadow][/color]`;
} else {
label = ivs[i].toString();
}
if (this.showDiff && originalIvs) {
if (originalIvs[i] < ivs[i]) {
label += ` ([color=${getTextColor(TextStyle.SUMMARY_BLUE, false, (this.scene as BattleScene).uiTheme)}][shadow=${getTextColor(TextStyle.SUMMARY_BLUE, true, (this.scene as BattleScene).uiTheme)}]+${ivs[i] - originalIvs[i]}[/shadow][/color])`;

11
src/vite.env.d.ts vendored Normal file
View File

@ -0,0 +1,11 @@
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_BYPASS_LOGIN?: string;
readonly VITE_BYPASS_TUTORIAL?: string;
readonly VITE_API_BASE_URL?: string;
}
interface ImportMeta {
readonly env: ImportMetaEnv
}

11
vite.env.d.ts vendored
View File

@ -1,11 +0,0 @@
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_BYPASS_LOGIN: string;
readonly VITE_BYPASS_TUTORIAL: string;
readonly VITE_API_BASE_URL: string;
}
interface ImportMeta {
readonly env: ImportMetaEnv;
}