diff --git a/src/battle-scene.ts b/src/battle-scene.ts index bb4803a9eb1..c94522d3af5 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -1653,8 +1653,9 @@ export default class BattleScene extends SceneBase { return Math.floor(moneyValue / 10) * 10; } - addModifier(modifier: Modifier, ignoreUpdate?: boolean, playSound?: boolean, virtual?: boolean, instant?: boolean): Promise { + addModifier(modifier: Modifier, ignoreUpdate?: boolean, playSound?: boolean, virtual?: boolean, instant?: boolean): Promise { return new Promise(resolve => { + let success = false; const soundName = modifier.type.soundName; this.validateAchvs(ModifierAchv, modifier); const modifiersToRemove: PersistentModifier[] = []; @@ -1664,20 +1665,20 @@ export default class BattleScene extends SceneBase { modifiersToRemove.push(...(this.findModifiers(m => m instanceof TerastallizeModifier && m.pokemonId === modifier.pokemonId))); if ((modifier as PersistentModifier).add(this.modifiers, !!virtual, this)) { if (modifier instanceof PokemonFormChangeItemModifier || modifier instanceof TerastallizeModifier) - modifier.apply([ this.getPokemonById(modifier.pokemonId), true ]); + success = modifier.apply([ this.getPokemonById(modifier.pokemonId), true ]); if (playSound && !this.sound.get(soundName)) this.playSound(soundName); } else if (!virtual) { const defaultModifierType = getDefaultModifierTypeForTier(modifier.type.tier); this.queueMessage(`The stack for this item is full.\n You will receive ${defaultModifierType.name} instead.`, null, true); - return this.addModifier(defaultModifierType.newModifier(), ignoreUpdate, playSound, false, instant).then(() => resolve()); + return this.addModifier(defaultModifierType.newModifier(), ignoreUpdate, playSound, false, instant).then(success => resolve(success)); } for (let rm of modifiersToRemove) this.removeModifier(rm); if (!ignoreUpdate && !virtual) - return this.updateModifiers(true, instant).then(() => resolve()); + return this.updateModifiers(true, instant).then(() => resolve(success)); } else if (modifier instanceof ConsumableModifier) { if (playSound && !this.sound.get(soundName)) this.playSound(soundName); @@ -1700,19 +1701,26 @@ export default class BattleScene extends SceneBase { if (modifier.shouldApply(args)) { const result = modifier.apply(args); if (result instanceof Promise) - modifierPromises.push(result); + modifierPromises.push(result.then(s => success ||= s)); + else + success ||= result; } } - return Promise.allSettled([this.party.map(p => p.updateInfo(instant)), ...modifierPromises]).then(() => resolve()); + return Promise.allSettled([this.party.map(p => p.updateInfo(instant)), ...modifierPromises]).then(() => resolve(success)); } else { const args = [ this ]; - if (modifier.shouldApply(args)) - modifier.apply(args); + if (modifier.shouldApply(args)) { + const result = modifier.apply(args); + if (result instanceof Promise) { + return result.then(success => resolve(success)); + } else + success ||= result; + } } } - resolve(); + resolve(success); }); } diff --git a/src/battle.ts b/src/battle.ts index b7dbb9a4219..b8ac378029f 100644 --- a/src/battle.ts +++ b/src/battle.ts @@ -212,6 +212,8 @@ export default class Battle { } randSeedInt(scene: BattleScene, range: integer, min: integer = 0): integer { + if (range <= 1) + return min; let ret: integer; const tempRngCounter = scene.rngCounter; const tempSeedOverride = scene.rngSeedOverride; diff --git a/src/data/move.ts b/src/data/move.ts index bce72eb4e3a..489f25142f9 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -939,6 +939,32 @@ export class StatusEffectAttr extends MoveEffectAttr { } } +export class PsychoShiftEffectAttr extends MoveEffectAttr { + constructor() { + super(false, MoveEffectTrigger.HIT); + } + + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + const statusToApply: StatusEffect = user.status?.effect; + + user.scene.queueMessage(getPokemonMessage(user, getStatusEffectHealText(user.status.effect))); + user.resetStatus(); + user.updateInfo(); + + if (target.status) { + return false; + } + if (!target.status || (target.status.effect === statusToApply && move.chance < 0)) + return target.trySetStatus(statusToApply, true); + + return false; + } + + getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { + return !(this.selfTarget ? user : target).status && (this.selfTarget ? user : target).canSetStatus(user.status?.effect, true) ? Math.floor(move.chance * -0.1) : 0; + } +} + export class StealHeldItemChanceAttr extends MoveEffectAttr { private chance: number; @@ -4388,7 +4414,9 @@ export function initMoves() { new StatusMove(Moves.EMBARGO, i18next.t('move:embargo.name'), Type.DARK, 100, 15, i18next.t('move:embargo.effect'), -1, 0, 4), new AttackMove(Moves.FLING, i18next.t('move:fling.name'), Type.DARK, MoveCategory.PHYSICAL, -1, 100, 10, i18next.t('move:fling.effect'), -1, 0, 4) .makesContact(false), - new StatusMove(Moves.PSYCHO_SHIFT, i18next.t('move:psychoShift.name'), Type.PSYCHIC, 100, 10, i18next.t('move:psychoShift.effect'), -1, 0, 4), + new StatusMove(Moves.PSYCHO_SHIFT, i18next.t('move:psychoShift.name'), Type.PSYCHIC, 100, 10, i18next.t('move:psychoShift.effect'), -1, 0, 4) + .attr(PsychoShiftEffectAttr) + .condition((user, target, move) => user.status?.effect === StatusEffect.BURN || user.status?.effect === StatusEffect.POISON || user.status?.effect === StatusEffect.TOXIC || user.status?.effect === StatusEffect.PARALYSIS),, new AttackMove(Moves.TRUMP_CARD, i18next.t('move:trumpCard.name'), Type.NORMAL, MoveCategory.SPECIAL, -1, -1, 5, i18next.t('move:trumpCard.effect'), -1, 0, 4) .makesContact(), new StatusMove(Moves.HEAL_BLOCK, i18next.t('move:healBlock.name'), Type.PSYCHIC, 100, 15, i18next.t('move:healBlock.effect'), -1, 0, 4) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index bf7073ad0bf..2452a978789 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -536,7 +536,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (this.getTag(BattlerTagType.SLOW_START)) ret >>= 1; if (this.status && this.status.effect === StatusEffect.PARALYSIS) - ret >>= 2; + ret >>= 1; break; } @@ -1213,7 +1213,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } if (source.getTag(BattlerTagType.CRIT_BOOST)) critLevel.value += 2; - const critChance = Math.ceil(16 / Math.pow(2, critLevel.value)); + const critChance = [24, 8, 2, 1][Math.max(0, Math.min(critLevel.value, 3))]; isCritical = !source.getTag(BattlerTagType.NO_CRIT) && (critChance === 1 || !this.scene.randBattleSeedInt(critChance)); if (isCritical) { const blockCrit = new Utils.BooleanHolder(false); diff --git a/src/loading-scene.ts b/src/loading-scene.ts index ebdcb6c2749..53933294491 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -254,6 +254,8 @@ export class LoadingScene extends SceneBase { } loadLoadingScreen() { + const mobile = isMobile(); + const loadingGraphics: any[] = []; const bg = this.add.image(0, 0, ''); @@ -318,7 +320,7 @@ export class LoadingScene extends SceneBase { loadingGraphics.push(bg, graphics, progressBar, progressBox, logo, percentText, assetText); - if (!isMobile()) + if (!mobile) loadingGraphics.map(g => g.setVisible(false)); const destroyLoadingAssets = () => { @@ -348,9 +350,13 @@ export class LoadingScene extends SceneBase { break; case 'loading_bg': bg.setTexture('loading_bg'); + if (mobile) + bg.setVisible(true); break; case 'logo': logo.setTexture('logo'); + if (mobile) + logo.setVisible(true); break; } }); diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index de4477a3e68..1dde041b782 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -1001,9 +1001,11 @@ export class PokemonHpRestoreModifier extends ConsumablePokemonModifier { if (this.fainted || this.healStatus) pokemon.resetStatus(); pokemon.hp = Math.min(pokemon.hp + Math.max(Math.ceil(Math.max(Math.floor((this.restorePercent * 0.01) * pokemon.getMaxHp()), restorePoints)), 1), pokemon.getMaxHp()); + + return true; } - return true; + return false; } } diff --git a/src/phases.ts b/src/phases.ts index f668278d273..08e4f1d6999 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -4162,10 +4162,15 @@ export class SelectModifierPhase extends BattlePhase { const applyModifier = (modifier: Modifier, playSound: boolean = false) => { const result = this.scene.addModifier(modifier, false, playSound); if (cost) { - this.scene.money -= cost; - this.scene.updateMoneyText(); - this.scene.playSound('buy'); - (this.scene.ui.getHandler() as ModifierSelectUiHandler).updateCostText(); + result.then(success => { + if (success) { + this.scene.money -= cost; + this.scene.updateMoneyText(); + this.scene.playSound('buy'); + (this.scene.ui.getHandler() as ModifierSelectUiHandler).updateCostText(); + } else + this.scene.ui.playError(); + }); } else { const doEnd = () => { this.scene.ui.clearText();