diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 4d103841336..c45eb3eec46 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -1209,7 +1209,7 @@ export default class BattleScene extends Phaser.Scene { this.phaseQueue.push(new TurnInitPhase(this)); } - addModifier(modifier: Modifier, ignoreUpdate?: boolean, playSound?: boolean, virtual?: boolean): Promise { + addModifier(modifier: Modifier, ignoreUpdate?: boolean, playSound?: boolean, virtual?: boolean, instant?: boolean): Promise { return new Promise(resolve => { const soundName = modifier.type.soundName; this.validateAchvs(ModifierAchv, modifier); @@ -1220,11 +1220,11 @@ export default class BattleScene extends Phaser.Scene { } 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).then(() => resolve()); + return this.addModifier(defaultModifierType.newModifier(), ignoreUpdate, playSound, false, instant).then(() => resolve()); } if (!ignoreUpdate && !virtual) - return this.updateModifiers().then(() => resolve()); + return this.updateModifiers(true, instant).then(() => resolve()); } else if (modifier instanceof ConsumableModifier) { if (playSound && !this.sound.get(soundName)) this.playSound(soundName); @@ -1248,7 +1248,7 @@ export default class BattleScene extends Phaser.Scene { modifier.apply(args); } - return Promise.allSettled(this.party.map(p => p.updateInfo())).then(() => resolve()); + return Promise.allSettled(this.party.map(p => p.updateInfo(instant))).then(() => resolve()); } else { const args = [ this ]; if (modifier.shouldApply(args)) @@ -1260,61 +1260,58 @@ export default class BattleScene extends Phaser.Scene { }); } - addEnemyModifier(itemModifier: PersistentModifier, ignoreUpdate?: boolean): Promise { + addEnemyModifier(itemModifier: PersistentModifier, ignoreUpdate?: boolean, instant?: boolean): Promise { return new Promise(resolve => { itemModifier.add(this.enemyModifiers, false, this); if (!ignoreUpdate) - this.updateModifiers(false).then(() => resolve()); + this.updateModifiers(false, instant).then(() => resolve()); else resolve(); }); } - tryTransferHeldItemModifier(itemModifier: PokemonHeldItemModifier, target: Pokemon, transferStack: boolean, playSound: boolean): Promise { + tryTransferHeldItemModifier(itemModifier: PokemonHeldItemModifier, target: Pokemon, transferStack: boolean, playSound: boolean, instant?: boolean): Promise { return new Promise(resolve => { const source = itemModifier.getPokemon(target.scene); const cancelled = new Utils.BooleanHolder(false); - applyAbAttrs(BlockItemTheftAbAttr, target, cancelled); - if (cancelled.value) { - resolve(false); - return; - } - const newItemModifier = itemModifier.clone() as PokemonHeldItemModifier; - newItemModifier.pokemonId = target.id; - const matchingModifier = target.scene.findModifier(m => m instanceof PokemonHeldItemModifier - && (m as PokemonHeldItemModifier).matchType(itemModifier) && m.pokemonId === target.id, target.isPlayer()) as PokemonHeldItemModifier; - let removeOld = true; - if (matchingModifier) { - const maxStackCount = matchingModifier.getMaxStackCount(source.scene); - if (matchingModifier.stackCount >= maxStackCount) { - resolve(false); + applyAbAttrs(BlockItemTheftAbAttr, source, cancelled).then(() => { + if (cancelled.value) + return resolve(false); + const newItemModifier = itemModifier.clone() as PokemonHeldItemModifier; + newItemModifier.pokemonId = target.id; + const matchingModifier = target.scene.findModifier(m => m instanceof PokemonHeldItemModifier + && (m as PokemonHeldItemModifier).matchType(itemModifier) && m.pokemonId === target.id, target.isPlayer()) as PokemonHeldItemModifier; + let removeOld = true; + if (matchingModifier) { + const maxStackCount = matchingModifier.getMaxStackCount(source.scene); + if (matchingModifier.stackCount >= maxStackCount) + return resolve(false); + const countTaken = transferStack ? Math.min(itemModifier.stackCount, maxStackCount - matchingModifier.stackCount) : 1; + itemModifier.stackCount -= countTaken; + newItemModifier.stackCount = matchingModifier.stackCount + countTaken; + removeOld = !itemModifier.stackCount; + } else if (!transferStack) { + newItemModifier.stackCount = 1; + removeOld = !(--itemModifier.stackCount); + } + if (!removeOld || this.removeModifier(itemModifier, !source.isPlayer())) { + const addModifier = () => { + if (!matchingModifier || this.removeModifier(matchingModifier, !target.isPlayer())) { + if (target.isPlayer()) + this.addModifier(newItemModifier, false, playSound, false, instant).then(() => resolve(true)); + else + this.addEnemyModifier(newItemModifier, false, instant).then(() => resolve(true)); + } else + resolve(false); + }; + if (source.isPlayer() !== target.isPlayer()) + this.updateModifiers(source.isPlayer(), instant).then(() => addModifier()); + else + addModifier(); return; } - const countTaken = transferStack ? Math.min(itemModifier.stackCount, maxStackCount - matchingModifier.stackCount) : 1; - itemModifier.stackCount -= countTaken; - newItemModifier.stackCount = matchingModifier.stackCount + countTaken; - removeOld = !itemModifier.stackCount; - } else if (!transferStack) { - newItemModifier.stackCount = 1; - removeOld = !(--itemModifier.stackCount); - } - if (!removeOld || this.removeModifier(itemModifier, !source.isPlayer())) { - const addModifier = () => { - if (!matchingModifier || this.removeModifier(matchingModifier, !target.isPlayer())) { - if (target.isPlayer()) - this.addModifier(newItemModifier, false, playSound).then(() => resolve(true)); - else - this.addEnemyModifier(newItemModifier).then(() => resolve(true)); - } else - resolve(false); - }; - if (source.isPlayer() !== target.isPlayer()) - this.updateModifiers(source.isPlayer()).then(() => addModifier()); - else - addModifier(); - return; - } - resolve(false); + resolve(false); + }); }); } @@ -1366,7 +1363,7 @@ export default class BattleScene extends Phaser.Scene { this.updateModifiers(false).then(() => this.updateUIPositions()); } - updateModifiers(player?: boolean): Promise { + updateModifiers(player?: boolean, instant?: boolean): Promise { if (player === undefined) player = true; return new Promise(resolve => { @@ -1387,7 +1384,7 @@ export default class BattleScene extends Phaser.Scene { modifiers.splice(modifiers.indexOf(modifier), 1); } - this.updatePartyForModifiers(player ? this.getParty() : this.getEnemyParty()).then(() => { + this.updatePartyForModifiers(player ? this.getParty() : this.getEnemyParty(), instant).then(() => { (player ? this.modifierBar : this.enemyModifierBar).updateModifiers(modifiers); if (!player) this.updateUIPositions(); @@ -1396,11 +1393,11 @@ export default class BattleScene extends Phaser.Scene { }); } - updatePartyForModifiers(party: Pokemon[]): Promise { + updatePartyForModifiers(party: Pokemon[], instant?: boolean): Promise { return new Promise(resolve => { Promise.allSettled(party.map(p => { p.calculateStats(); - return p.updateInfo(); + return p.updateInfo(instant); })).then(() => resolve()); }); } diff --git a/src/data/ability.ts b/src/data/ability.ts index 7adcd0bc013..d72dbd62ef8 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -17,6 +17,7 @@ export class Ability { public name: string; public description: string; public generation: integer; + public isPassive: boolean; public attrs: AbAttr[]; public conditions: AbAttrCondition[]; @@ -44,6 +45,11 @@ export class Ability { return !!this.getAttrs(attrType).length; } + passive(): Ability { + this.isPassive = true; + return this; + } + condition(condition: AbAttrCondition): Ability { this.conditions.push(condition); @@ -1508,7 +1514,8 @@ export function initAbilities() { new Ability(Abilities.MINUS, "Minus (N)", "Boosts the Sp. Atk stat of the Pokémon if an ally with the Plus or Minus Ability is also in battle.", 3), new Ability(Abilities.FORECAST, "Forecast (N)", "The Pokémon transforms with the weather to change its type to Water, Fire, or Ice.", 3), new Ability(Abilities.STICKY_HOLD, "Sticky Hold", "Items held by the Pokémon are stuck fast and cannot be removed by other Pokémon.", 3) - .attr(BlockItemTheftAbAttr), + .attr(BlockItemTheftAbAttr) + .passive(), new Ability(Abilities.SHED_SKIN, "Shed Skin (N)", "The Pokémon may heal its own status conditions by shedding its skin.", 3), new Ability(Abilities.GUTS, "Guts (N)", "It's so gutsy that having a status condition boosts the Pokémon's Attack stat.", 3), new Ability(Abilities.MARVEL_SCALE, "Marvel Scale (N)", "The Pokémon's marvelous scales boost the Defense stat if it has a status condition.", 3), diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index 1a61f11d5bc..94479a3efb0 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -1398,20 +1398,26 @@ export abstract class HeldItemTransferModifier extends PokemonHeldItemModifier { const transferredModifierTypes: ModifierTypes.ModifierType[] = []; const itemModifiers = pokemon.scene.findModifiers(m => m instanceof PokemonHeldItemModifier && (m as PokemonHeldItemModifier).pokemonId === targetPokemon.id && m.getTransferrable(withinParty), targetPokemon.isPlayer()) as PokemonHeldItemModifier[]; + + let heldItemTransferPromises: Promise[] = []; for (let i = 0; i < transferredItemCount; i++) { if (!itemModifiers.length) break; const randItemIndex = Utils.randInt(itemModifiers.length); const randItem = itemModifiers[randItemIndex]; - if (pokemon.scene.tryTransferHeldItemModifier(randItem, pokemon, false, false)) { - transferredModifierTypes.push(randItem.type); - itemModifiers.splice(randItemIndex, 1); - } + heldItemTransferPromises.push(pokemon.scene.tryTransferHeldItemModifier(randItem, pokemon, false, false, true).then(success => { + if (success) { + transferredModifierTypes.push(randItem.type); + itemModifiers.splice(randItemIndex, 1); + } + })); } - for (let mt of transferredModifierTypes) - pokemon.scene.queueMessage(this.getTransferMessage(pokemon, targetPokemon, mt)); + Promise.all(heldItemTransferPromises).then(() => { + for (let mt of transferredModifierTypes) + pokemon.scene.queueMessage(this.getTransferMessage(pokemon, targetPokemon, mt)); + }); return !!transferredModifierTypes.length; } @@ -1447,7 +1453,7 @@ export class TurnHeldItemTransferModifier extends HeldItemTransferModifier { } getMaxHeldItemCount(pokemon: Pokemon): integer { - return 3; + return 1; } } diff --git a/src/pokemon.ts b/src/pokemon.ts index 4bbb8eb7c37..0e7f945859d 100644 --- a/src/pokemon.ts +++ b/src/pokemon.ts @@ -608,7 +608,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } canApplyAbility(): boolean { - return this.hp && !this.getAbility().conditions.find(condition => !condition(this)); + const ability = this.getAbility(); + return (this.hp || ability.isPassive) && !this.getAbility().conditions.find(condition => !condition(this)); } getWeight(): number {