mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-06-21 17:12:44 +02:00
Reverted unneeded changes
This commit is contained in:
parent
5531b3c5cd
commit
69bcbdcaa1
@ -2614,10 +2614,10 @@ export default class BattleScene extends SceneBase {
|
|||||||
|
|
||||||
addModifier(
|
addModifier(
|
||||||
modifier: Modifier | null,
|
modifier: Modifier | null,
|
||||||
ignoreUpdate = false,
|
ignoreUpdate?: boolean,
|
||||||
playSound = false,
|
playSound?: boolean,
|
||||||
virtual = false,
|
virtual?: boolean,
|
||||||
instant = false,
|
instant?: boolean,
|
||||||
cost?: number,
|
cost?: number,
|
||||||
): boolean {
|
): boolean {
|
||||||
// We check against modifier.type to stop a bug related to loading in a pokemon that has a form change item, which prior to some patch
|
// We check against modifier.type to stop a bug related to loading in a pokemon that has a form change item, which prior to some patch
|
||||||
@ -2631,7 +2631,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
this.validateAchvs(ModifierAchv, modifier);
|
this.validateAchvs(ModifierAchv, modifier);
|
||||||
const modifiersToRemove: PersistentModifier[] = [];
|
const modifiersToRemove: PersistentModifier[] = [];
|
||||||
if (modifier instanceof PersistentModifier) {
|
if (modifier instanceof PersistentModifier) {
|
||||||
if ((modifier as PersistentModifier).add(this.modifiers, virtual)) {
|
if ((modifier as PersistentModifier).add(this.modifiers, !!virtual)) {
|
||||||
if (modifier instanceof PokemonFormChangeItemModifier) {
|
if (modifier instanceof PokemonFormChangeItemModifier) {
|
||||||
const pokemon = this.getPokemonById(modifier.pokemonId);
|
const pokemon = this.getPokemonById(modifier.pokemonId);
|
||||||
if (pokemon) {
|
if (pokemon) {
|
||||||
@ -2704,7 +2704,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
addEnemyModifier(modifier: PersistentModifier, ignoreUpdate = false, instant = false): Promise<void> {
|
addEnemyModifier(modifier: PersistentModifier, ignoreUpdate?: boolean, instant?: boolean): Promise<void> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const modifiersToRemove: PersistentModifier[] = [];
|
const modifiersToRemove: PersistentModifier[] = [];
|
||||||
if ((modifier as PersistentModifier).add(this.enemyModifiers, false)) {
|
if ((modifier as PersistentModifier).add(this.enemyModifiers, false)) {
|
||||||
@ -2732,128 +2732,124 @@ export default class BattleScene extends SceneBase {
|
|||||||
* If the recepient already has the maximum amount allowed for this item, the transfer is cancelled.
|
* 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.
|
* 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.
|
* A transfer that moves a quantity smaller than what is specified in the transferQuantity parameter is still considered successful.
|
||||||
* @param itemModifier - {@linkcode PokemonHeldItemModifier} to transfer (represents whole stack)
|
* @param itemModifier {@linkcode PokemonHeldItemModifier} item to transfer (represents the whole stack)
|
||||||
* @param target - Recipient {@linkcode Pokemon} recieving items
|
* @param target {@linkcode Pokemon} recepient in this transfer
|
||||||
* @param playSound - Whether to play a sound when transferring the item
|
* @param playSound `true` to play a sound when transferring the item
|
||||||
* @param transferQuantity - How many items of the stack to transfer. Optional, default `1`
|
* @param transferQuantity How many items of the stack to transfer. Optional, defaults to `1`
|
||||||
* @param itemLost - Whether to treat the item's current holder as losing the item (for now, this simply enables Unburden). Default: `true`.
|
* @param instant ??? (Optional)
|
||||||
* @returns Whether the transfer was successful
|
* @param ignoreUpdate ??? (Optional)
|
||||||
|
* @param itemLost If `true`, treat the item's current holder as losing the item (for now, this simply enables Unburden). Default is `true`.
|
||||||
|
* @returns `true` if the transfer was successful
|
||||||
*/
|
*/
|
||||||
tryTransferHeldItemModifier(
|
tryTransferHeldItemModifier(
|
||||||
itemModifier: PokemonHeldItemModifier,
|
itemModifier: PokemonHeldItemModifier,
|
||||||
target: Pokemon,
|
target: Pokemon,
|
||||||
playSound: boolean,
|
playSound: boolean,
|
||||||
transferQuantity = 1,
|
transferQuantity = 1,
|
||||||
|
instant?: boolean,
|
||||||
|
ignoreUpdate?: boolean,
|
||||||
itemLost = true,
|
itemLost = true,
|
||||||
): boolean {
|
): boolean {
|
||||||
const source = itemModifier.getPokemon();
|
const source = itemModifier.pokemonId ? itemModifier.getPokemon() : null;
|
||||||
// Check if source even exists and error if not.
|
|
||||||
// Almost certainly redundant due to checking inside condition, but better log twice than not at all
|
|
||||||
if (isNullOrUndefined(source)) {
|
|
||||||
console.error(
|
|
||||||
`Pokemon ${target.getNameToRender()} tried to transfer %d items from nonexistent source; item: `,
|
|
||||||
transferQuantity,
|
|
||||||
itemModifier,
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for effects that might block us from stealing
|
|
||||||
const cancelled = new BooleanHolder(false);
|
const cancelled = new BooleanHolder(false);
|
||||||
if (source.isPlayer() !== target.isPlayer()) {
|
|
||||||
|
if (source && source.isPlayer() !== target.isPlayer()) {
|
||||||
applyAbAttrs(BlockItemTheftAbAttr, source, cancelled);
|
applyAbAttrs(BlockItemTheftAbAttr, source, cancelled);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cancelled.value) {
|
if (cancelled.value) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if we have an item already and calc how much to transfer
|
const newItemModifier = itemModifier.clone() as PokemonHeldItemModifier;
|
||||||
|
newItemModifier.pokemonId = target.id;
|
||||||
const matchingModifier = this.findModifier(
|
const matchingModifier = this.findModifier(
|
||||||
(m): m is PokemonHeldItemModifier =>
|
m => m instanceof PokemonHeldItemModifier && m.matchType(itemModifier) && m.pokemonId === target.id,
|
||||||
m instanceof PokemonHeldItemModifier && m.matchType(itemModifier) && m.pokemonId === target.id,
|
|
||||||
target.isPlayer(),
|
target.isPlayer(),
|
||||||
);
|
) as PokemonHeldItemModifier;
|
||||||
|
|
||||||
|
if (matchingModifier) {
|
||||||
|
const maxStackCount = matchingModifier.getMaxStackCount();
|
||||||
|
if (matchingModifier.stackCount >= maxStackCount) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
const countTaken = Math.min(
|
const countTaken = Math.min(
|
||||||
transferQuantity,
|
transferQuantity,
|
||||||
itemModifier.stackCount,
|
itemModifier.stackCount,
|
||||||
matchingModifier?.getCountUnderMax() ?? Number.MAX_SAFE_INTEGER,
|
maxStackCount - matchingModifier.stackCount,
|
||||||
);
|
);
|
||||||
if (countTaken <= 0) {
|
|
||||||
// Can't transfer negative items
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
itemModifier.stackCount -= countTaken;
|
itemModifier.stackCount -= countTaken;
|
||||||
|
newItemModifier.stackCount = matchingModifier.stackCount + countTaken;
|
||||||
// If the old modifier is at 0 stacks, try to remove it
|
|
||||||
if (itemModifier.stackCount <= 0 && !this.removeModifier(itemModifier, !source.isPlayer())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: what does this do and why is it here
|
|
||||||
if (source.isPlayer() !== target.isPlayer()) {
|
|
||||||
this.updateModifiers(source.isPlayer(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add however much we took to the recieving pokemon, creating a new modifier if the target lacked one prio
|
|
||||||
if (matchingModifier) {
|
|
||||||
matchingModifier.stackCount += countTaken;
|
|
||||||
} else {
|
} else {
|
||||||
const newItemModifier = itemModifier.clone() as PokemonHeldItemModifier;
|
const countTaken = Math.min(transferQuantity, itemModifier.stackCount);
|
||||||
newItemModifier.pokemonId = target.id;
|
itemModifier.stackCount -= countTaken;
|
||||||
newItemModifier.stackCount = countTaken;
|
newItemModifier.stackCount = countTaken;
|
||||||
if (target.isPlayer()) {
|
|
||||||
this.addModifier(newItemModifier, false, playSound);
|
|
||||||
} else {
|
|
||||||
this.addEnemyModifier(newItemModifier);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemLost) {
|
const removeOld = itemModifier.stackCount === 0;
|
||||||
|
|
||||||
|
if (!removeOld || !source || this.removeModifier(itemModifier, source.isEnemy())) {
|
||||||
|
const addModifier = () => {
|
||||||
|
if (!matchingModifier || this.removeModifier(matchingModifier, target.isEnemy())) {
|
||||||
|
if (target.isPlayer()) {
|
||||||
|
this.addModifier(newItemModifier, ignoreUpdate, playSound, false, instant);
|
||||||
|
if (source && itemLost) {
|
||||||
applyPostItemLostAbAttrs(PostItemLostAbAttr, source, false);
|
applyPostItemLostAbAttrs(PostItemLostAbAttr, source, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
this.addEnemyModifier(newItemModifier, ignoreUpdate, instant);
|
||||||
|
if (source && itemLost) {
|
||||||
|
applyPostItemLostAbAttrs(PostItemLostAbAttr, source, false);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
if (source && source.isPlayer() !== target.isPlayer() && !ignoreUpdate) {
|
||||||
|
this.updateModifiers(source.isPlayer(), instant);
|
||||||
|
addModifier();
|
||||||
|
} else {
|
||||||
|
addModifier();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
canTransferHeldItemModifier(itemModifier: PokemonHeldItemModifier, target: Pokemon, transferQuantity = 1): boolean {
|
canTransferHeldItemModifier(itemModifier: PokemonHeldItemModifier, target: Pokemon, transferQuantity = 1): boolean {
|
||||||
const source = itemModifier.getPokemon();
|
const mod = itemModifier.clone() as PokemonHeldItemModifier;
|
||||||
if (isNullOrUndefined(source)) {
|
const source = mod.pokemonId ? mod.getPokemon() : null;
|
||||||
console.error(
|
|
||||||
`Pokemon ${target.getNameToRender()} tried to transfer %d items from nonexistent source; item: `,
|
|
||||||
transferQuantity,
|
|
||||||
itemModifier,
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we somehow lack the item being transferred, skip
|
|
||||||
if (!this.hasModifier(itemModifier, !source.isPlayer())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check enemy theft prevention
|
|
||||||
// TODO: Verify whether sticky hold procs on friendly fire ally theft
|
|
||||||
if (source.isPlayer() !== target.isPlayer()) {
|
|
||||||
const cancelled = new BooleanHolder(false);
|
const cancelled = new BooleanHolder(false);
|
||||||
|
|
||||||
|
if (source && source.isPlayer() !== target.isPlayer()) {
|
||||||
applyAbAttrs(BlockItemTheftAbAttr, source, cancelled);
|
applyAbAttrs(BlockItemTheftAbAttr, source, cancelled);
|
||||||
|
}
|
||||||
|
|
||||||
if (cancelled.value) {
|
if (cancelled.value) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const matchingModifier = this.findModifier(
|
||||||
|
m => m instanceof PokemonHeldItemModifier && m.matchType(mod) && m.pokemonId === target.id,
|
||||||
|
target.isPlayer(),
|
||||||
|
) as PokemonHeldItemModifier;
|
||||||
|
|
||||||
|
if (matchingModifier) {
|
||||||
|
const maxStackCount = matchingModifier.getMaxStackCount();
|
||||||
|
if (matchingModifier.stackCount >= maxStackCount) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const countTaken = Math.min(transferQuantity, mod.stackCount, maxStackCount - matchingModifier.stackCount);
|
||||||
|
mod.stackCount -= countTaken;
|
||||||
|
} else {
|
||||||
|
const countTaken = Math.min(transferQuantity, mod.stackCount);
|
||||||
|
mod.stackCount -= countTaken;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, ensure we can actually steal at least 1 item
|
const removeOld = mod.stackCount === 0;
|
||||||
const matchingModifier = this.findModifier(
|
|
||||||
(m): m is PokemonHeldItemModifier =>
|
return !removeOld || !source || this.hasModifier(itemModifier, !source.isPlayer());
|
||||||
m instanceof PokemonHeldItemModifier && m.matchType(itemModifier) && m.pokemonId === target.id,
|
|
||||||
target.isPlayer(),
|
|
||||||
);
|
|
||||||
const countTaken = Math.min(
|
|
||||||
transferQuantity,
|
|
||||||
itemModifier.stackCount,
|
|
||||||
matchingModifier?.getCountUnderMax() ?? Number.MAX_SAFE_INTEGER,
|
|
||||||
);
|
|
||||||
return countTaken > 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
removePartyMemberModifiers(partyMemberIndex: number): Promise<void> {
|
removePartyMemberModifiers(partyMemberIndex: number): Promise<void> {
|
||||||
@ -2971,10 +2967,8 @@ export default class BattleScene extends SceneBase {
|
|||||||
[this.modifierBar, this.enemyModifierBar].map(m => m.setVisible(visible));
|
[this.modifierBar, this.enemyModifierBar].map(m => m.setVisible(visible));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// TODO: Document this
|
||||||
* @param instant - Whether to instantly update any changes to party members' HP bars; default `false`
|
updateModifiers(player = true, instant?: boolean): void {
|
||||||
*/
|
|
||||||
updateModifiers(player = true, instant = false): void {
|
|
||||||
const modifiers = player ? this.modifiers : (this.enemyModifiers as PersistentModifier[]);
|
const modifiers = player ? this.modifiers : (this.enemyModifiers as PersistentModifier[]);
|
||||||
for (let m = 0; m < modifiers.length; m++) {
|
for (let m = 0; m < modifiers.length; m++) {
|
||||||
const modifier = modifiers[m];
|
const modifier = modifiers[m];
|
||||||
@ -2991,7 +2985,6 @@ export default class BattleScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Why do we silently delete missing modifiers?
|
|
||||||
const modifiersClone = modifiers.slice(0);
|
const modifiersClone = modifiers.slice(0);
|
||||||
for (const modifier of modifiersClone) {
|
for (const modifier of modifiersClone) {
|
||||||
if (!modifier.getStackCount()) {
|
if (!modifier.getStackCount()) {
|
||||||
@ -3006,13 +2999,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
updatePartyForModifiers(party: Pokemon[], instant?: boolean): Promise<void> {
|
||||||
* Update one or more Pokemon's info containers after having recieved modifiers.
|
|
||||||
* @param party - An array of {@linkcode Pokemon} to update info.
|
|
||||||
* @param instant - Whether to instantly update any changes to the party's HP bars; default `false`
|
|
||||||
* @returns A Promise that resolves once all the info containers have been updated.
|
|
||||||
*/
|
|
||||||
updatePartyForModifiers(party: Pokemon[], instant = false): Promise<void> {
|
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
Promise.allSettled(
|
Promise.allSettled(
|
||||||
party.map(p => {
|
party.map(p => {
|
||||||
@ -3023,32 +3010,23 @@ export default class BattleScene extends SceneBase {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether a given {@linkcode PersistentModifier} exists on a given side of the field.
|
|
||||||
* @param modifier - The {@linkcode PersistentModifier} to check the existence of.
|
|
||||||
* @param enemy - Whether to check the enemy (`true`) or player (`false`) party. Default is `false`.
|
|
||||||
* @returns Whether the specified modifier exists on the given side of the field.
|
|
||||||
* @remarks This also compares `pokemonId`s to confirm a match (and therefore owners).
|
|
||||||
*/
|
|
||||||
hasModifier(modifier: PersistentModifier, enemy = false): boolean {
|
hasModifier(modifier: PersistentModifier, enemy = false): boolean {
|
||||||
return (!enemy ? this.modifiers : this.enemyModifiers).includes(modifier);
|
const modifiers = !enemy ? this.modifiers : this.enemyModifiers;
|
||||||
|
return modifiers.indexOf(modifier) > -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a currently owned item. If the item is stacked, the entire item stack
|
* Removes a currently owned item. If the item is stacked, the entire item stack
|
||||||
* gets removed. This function does NOT apply in-battle effects, such as Unburden.
|
* gets removed. This function does NOT apply in-battle effects, such as Unburden.
|
||||||
* If in-battle effects are needed, use {@linkcode Pokemon.loseHeldItem} instead.
|
* If in-battle effects are needed, use {@linkcode Pokemon.loseHeldItem} instead.
|
||||||
* @param modifier - The item to be removed.
|
* @param modifier The item to be removed.
|
||||||
* @param enemy - Whether to remove from the enemy (`true`) or player (`false`) party; default `false`.
|
* @param enemy `true` to remove an item owned by the enemy rather than the player; default `false`.
|
||||||
* @returns Whether the item exists and was successfully removed
|
* @returns `true` if the item exists and was successfully removed, `false` otherwise
|
||||||
*/
|
*/
|
||||||
removeModifier(modifier: PersistentModifier, enemy = false): boolean {
|
removeModifier(modifier: PersistentModifier, enemy = false): boolean {
|
||||||
const modifiers = !enemy ? this.modifiers : this.enemyModifiers;
|
const modifiers = !enemy ? this.modifiers : this.enemyModifiers;
|
||||||
const modifierIndex = modifiers.indexOf(modifier);
|
const modifierIndex = modifiers.indexOf(modifier);
|
||||||
if (modifierIndex === -1) {
|
if (modifierIndex > -1) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
modifiers.splice(modifierIndex, 1);
|
modifiers.splice(modifierIndex, 1);
|
||||||
if (modifier instanceof PokemonFormChangeItemModifier) {
|
if (modifier instanceof PokemonFormChangeItemModifier) {
|
||||||
const pokemon = this.getPokemonById(modifier.pokemonId);
|
const pokemon = this.getPokemonById(modifier.pokemonId);
|
||||||
@ -3059,35 +3037,17 @@ export default class BattleScene extends SceneBase {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
return false;
|
||||||
* Get all modifiers of all {@linkcode Pokemon} in the given party,
|
|
||||||
* optionally filtering based on `modifierType` if provided.
|
|
||||||
* @param player Whether to search the player (`true`) or enemy (`false`) party; Defaults to `true`
|
|
||||||
* @returns An array containing all {@linkcode PersistentModifier}s on the given side of the field.
|
|
||||||
* @overload
|
|
||||||
*/
|
|
||||||
getModifiers(player?: boolean): PersistentModifier[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all modifiers of all {@linkcode Pokemon} in the given party,
|
|
||||||
* optionally filtering based on `modifierType` if provided.
|
|
||||||
* @param modifierType The type of modifier to check against; must extend {@linkcode PersistentModifier}.
|
|
||||||
* If omitted, will return all {@linkcode PersistentModifier}s regardless of type.
|
|
||||||
* @param player Whether to search the player (`true`) or enemy (`false`) party; Defaults to `true`
|
|
||||||
* @returns An array containing all modifiers matching `modifierType` on the given side of the field.
|
|
||||||
* @overload
|
|
||||||
*/
|
|
||||||
getModifiers<T extends PersistentModifier>(modifierType: Constructor<T>, player?: boolean): T[];
|
|
||||||
|
|
||||||
// NOTE: Boolean typing on 1st parameter needed to satisfy "bool only" overload
|
|
||||||
getModifiers<T extends PersistentModifier>(modifierType?: Constructor<T> | boolean, player?: boolean) {
|
|
||||||
const usePlayer: boolean = player ?? (typeof modifierType !== "boolean" || modifierType); // non-bool in 1st position = true by default
|
|
||||||
const mods = usePlayer ? this.modifiers : this.enemyModifiers;
|
|
||||||
|
|
||||||
if (typeof modifierType === "undefined" || typeof modifierType === "boolean") {
|
|
||||||
return mods;
|
|
||||||
}
|
}
|
||||||
return mods.filter((m): m is T => m instanceof modifierType);
|
|
||||||
|
/**
|
||||||
|
* Get all of the modifiers that match `modifierType`
|
||||||
|
* @param modifierType The type of modifier to apply; must extend {@linkcode PersistentModifier}
|
||||||
|
* @param player Whether to search the player (`true`) or the enemy (`false`); Defaults to `true`
|
||||||
|
* @returns the list of all modifiers that matched `modifierType`.
|
||||||
|
*/
|
||||||
|
getModifiers<T extends PersistentModifier>(modifierType: Constructor<T>, player = true): T[] {
|
||||||
|
return (player ? this.modifiers : this.enemyModifiers).filter((m): m is T => m instanceof modifierType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -176,12 +176,18 @@ export default class Battle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addPostBattleLoot(enemyPokemon: EnemyPokemon): void {
|
addPostBattleLoot(enemyPokemon: EnemyPokemon): void {
|
||||||
// Push used instead of concat to avoid extra allocation
|
|
||||||
this.postBattleLoot.push(
|
this.postBattleLoot.push(
|
||||||
...(globalScene.findModifiers(
|
...globalScene
|
||||||
|
.findModifiers(
|
||||||
m => m instanceof PokemonHeldItemModifier && m.pokemonId === enemyPokemon.id && m.isTransferable,
|
m => m instanceof PokemonHeldItemModifier && m.pokemonId === enemyPokemon.id && m.isTransferable,
|
||||||
false,
|
false,
|
||||||
) as PokemonHeldItemModifier[]),
|
)
|
||||||
|
.map(i => {
|
||||||
|
const ret = i as PokemonHeldItemModifier;
|
||||||
|
//@ts-ignore - this is awful to fix/change
|
||||||
|
ret.pokemonId = null;
|
||||||
|
return ret;
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2539,17 +2539,11 @@ export class AllyStatMultiplierAbAttr extends AbAttr {
|
|||||||
* @extends AbAttr
|
* @extends AbAttr
|
||||||
*/
|
*/
|
||||||
export class ExecutedMoveAbAttr extends AbAttr {
|
export class ExecutedMoveAbAttr extends AbAttr {
|
||||||
canApplyExecutedMove(
|
canApplyExecutedMove(_pokemon: Pokemon, _simulated: boolean): boolean {
|
||||||
_pokemon: Pokemon,
|
|
||||||
_simulated: boolean,
|
|
||||||
): boolean {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
applyExecutedMove(
|
applyExecutedMove(_pokemon: Pokemon, _simulated: boolean): void {}
|
||||||
_pokemon: Pokemon,
|
|
||||||
_simulated: boolean,
|
|
||||||
): void {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2557,7 +2551,7 @@ export class ExecutedMoveAbAttr extends AbAttr {
|
|||||||
* @extends ExecutedMoveAbAttr
|
* @extends ExecutedMoveAbAttr
|
||||||
*/
|
*/
|
||||||
export class GorillaTacticsAbAttr extends ExecutedMoveAbAttr {
|
export class GorillaTacticsAbAttr extends ExecutedMoveAbAttr {
|
||||||
constructor(showAbility: boolean = false) {
|
constructor(showAbility = false) {
|
||||||
super(showAbility);
|
super(showAbility);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2574,7 +2568,7 @@ export class GorillaTacticsAbAttr extends ExecutedMoveAbAttr {
|
|||||||
|
|
||||||
export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr {
|
export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr {
|
||||||
private stealCondition: PokemonAttackCondition | null;
|
private stealCondition: PokemonAttackCondition | null;
|
||||||
private stolenItem: PokemonHeldItemModifier;
|
private stolenItem?: PokemonHeldItemModifier;
|
||||||
|
|
||||||
constructor(stealCondition?: PokemonAttackCondition) {
|
constructor(stealCondition?: PokemonAttackCondition) {
|
||||||
super();
|
super();
|
||||||
@ -2591,35 +2585,38 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr {
|
|||||||
hitResult: HitResult,
|
hitResult: HitResult,
|
||||||
args: any[],
|
args: any[],
|
||||||
): boolean {
|
): boolean {
|
||||||
// Check which items to steal
|
|
||||||
const heldItems = this.getTargetHeldItems(defender).filter((i) => i.isTransferable);
|
|
||||||
if (
|
if (
|
||||||
!super.canApplyPostAttack(pokemon, passive, simulated, defender, move, hitResult, args) ||
|
super.canApplyPostAttack(pokemon, passive, simulated, defender, move, hitResult, args) &&
|
||||||
heldItems.length === 0 || // no items to steal
|
!simulated &&
|
||||||
hitResult >= HitResult.NO_EFFECT || // move was ineffective/protected against
|
hitResult < HitResult.NO_EFFECT &&
|
||||||
(this.stealCondition && !this.stealCondition(pokemon, defender, move)) // no condition = pass
|
(!this.stealCondition || this.stealCondition(pokemon, defender, move))
|
||||||
) {
|
) {
|
||||||
return false;
|
const heldItems = this.getTargetHeldItems(defender).filter(i => i.isTransferable);
|
||||||
}
|
if (heldItems.length) {
|
||||||
|
// Ensure that the stolen item in testing is the same as when the effect is applied
|
||||||
// pick random item and check if we can steal it
|
|
||||||
this.stolenItem = heldItems[pokemon.randBattleSeedInt(heldItems.length)];
|
this.stolenItem = heldItems[pokemon.randBattleSeedInt(heldItems.length)];
|
||||||
return globalScene.canTransferHeldItemModifier(this.stolenItem, pokemon)
|
if (globalScene.canTransferHeldItemModifier(this.stolenItem, pokemon)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.stolenItem = undefined;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
override applyPostAttack(
|
override applyPostAttack(
|
||||||
pokemon: Pokemon,
|
pokemon: Pokemon,
|
||||||
_passive: boolean,
|
_passive: boolean,
|
||||||
simulated: boolean,
|
_simulated: boolean,
|
||||||
defender: Pokemon,
|
defender: Pokemon,
|
||||||
_move: Move,
|
_move: Move,
|
||||||
_hitResult: HitResult,
|
_hitResult: HitResult,
|
||||||
_args: any[],
|
_args: any[],
|
||||||
): void {
|
): void {
|
||||||
if (simulated) {
|
const heldItems = this.getTargetHeldItems(defender).filter(i => i.isTransferable);
|
||||||
return;
|
if (!this.stolenItem) {
|
||||||
|
this.stolenItem = heldItems[pokemon.randBattleSeedInt(heldItems.length)];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (globalScene.tryTransferHeldItemModifier(this.stolenItem, pokemon, false)) {
|
if (globalScene.tryTransferHeldItemModifier(this.stolenItem, pokemon, false)) {
|
||||||
globalScene.phaseManager.queueMessage(
|
globalScene.phaseManager.queueMessage(
|
||||||
i18next.t("abilityTriggers:postAttackStealHeldItem", {
|
i18next.t("abilityTriggers:postAttackStealHeldItem", {
|
||||||
@ -2629,6 +2626,7 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
this.stolenItem = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
getTargetHeldItems(target: Pokemon): PokemonHeldItemModifier[] {
|
getTargetHeldItems(target: Pokemon): PokemonHeldItemModifier[] {
|
||||||
@ -6217,45 +6215,36 @@ export class PostBattleAbAttr extends AbAttr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class PostBattleLootAbAttr extends PostBattleAbAttr {
|
export class PostBattleLootAbAttr extends PostBattleAbAttr {
|
||||||
/** The index of the random item to steal. */
|
private randItem?: PokemonHeldItemModifier;
|
||||||
private randItemIndex = 0;
|
|
||||||
|
override canApplyPostBattle(pokemon: Pokemon, _passive: boolean, simulated: boolean, args: any[]): boolean {
|
||||||
|
const postBattleLoot = globalScene.currentBattle.postBattleLoot;
|
||||||
|
if (!simulated && postBattleLoot.length && args[0]) {
|
||||||
|
this.randItem = randSeedItem(postBattleLoot);
|
||||||
|
return globalScene.canTransferHeldItemModifier(this.randItem, pokemon, 1);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param _args - `[0]`: boolean for if the battle ended in a victory
|
* @param _args - `[0]`: boolean for if the battle ended in a victory
|
||||||
*/
|
*/
|
||||||
override canApplyPostBattle(pokemon: Pokemon, _passive: boolean, simulated: boolean, args: [boolean]): boolean {
|
override applyPostBattle(pokemon: Pokemon, _passive: boolean, _simulated: boolean, _args: any[]): void {
|
||||||
const postBattleLoot = globalScene.currentBattle.postBattleLoot;
|
const postBattleLoot = globalScene.currentBattle.postBattleLoot;
|
||||||
const wasVictory = args[0];
|
if (!this.randItem) {
|
||||||
if (simulated || postBattleLoot.length === 0 || !wasVictory) {
|
this.randItem = randSeedItem(postBattleLoot);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pick a random item and check if we are capped.
|
if (globalScene.tryTransferHeldItemModifier(this.randItem, pokemon, true, 1, true, undefined, false)) {
|
||||||
this.randItemIndex = randSeedInt(postBattleLoot.length);
|
postBattleLoot.splice(postBattleLoot.indexOf(this.randItem), 1);
|
||||||
const item = postBattleLoot[this.randItemIndex]
|
globalScene.phaseManager.queueMessage(
|
||||||
|
i18next.t("abilityTriggers:postBattleLoot", {
|
||||||
// We can't use `canTransferItemModifier` as that assumes the Pokemon in question already exists (which it does not)
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||||
const existingItem = globalScene.findModifier(
|
itemName: this.randItem.type.name,
|
||||||
(m): m is PokemonHeldItemModifier =>
|
}),
|
||||||
m instanceof PokemonHeldItemModifier && m.matchType(item) && m.pokemonId === pokemon.id,
|
);
|
||||||
pokemon.isPlayer(),
|
|
||||||
) as PokemonHeldItemModifier | undefined;
|
|
||||||
|
|
||||||
return (existingItem?.getCountUnderMax() ?? Number.MAX_SAFE_INTEGER) > 1
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempt to give the previously selected random item to the ability holder at battle end.
|
|
||||||
*/
|
|
||||||
override applyPostBattle(pokemon: Pokemon): void {
|
|
||||||
const postBattleLoot = globalScene.currentBattle.postBattleLoot;
|
|
||||||
const item = postBattleLoot[this.randItemIndex]
|
|
||||||
item.pokemonId = pokemon.id;
|
|
||||||
|
|
||||||
if (globalScene.addModifier(item, false, true)) {
|
|
||||||
postBattleLoot.splice(this.randItemIndex, 1);
|
|
||||||
globalScene.phaseManager.queueMessage(i18next.t("abilityTriggers:postBattleLoot", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), itemName: item.type.name }));
|
|
||||||
}
|
}
|
||||||
|
this.randItem = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7790,7 +7779,7 @@ export function applyPreAttackAbAttrs(
|
|||||||
export function applyExecutedMoveAbAttrs(
|
export function applyExecutedMoveAbAttrs(
|
||||||
attrType: Constructor<ExecutedMoveAbAttr>,
|
attrType: Constructor<ExecutedMoveAbAttr>,
|
||||||
pokemon: Pokemon,
|
pokemon: Pokemon,
|
||||||
simulated: boolean = false,
|
simulated = false,
|
||||||
...args: any[]
|
...args: any[]
|
||||||
): void {
|
): void {
|
||||||
applyAbAttrsInternal<ExecutedMoveAbAttr>(
|
applyAbAttrsInternal<ExecutedMoveAbAttr>(
|
||||||
@ -8401,8 +8390,7 @@ export function initAbilities() {
|
|||||||
new Ability(AbilityId.STICKY_HOLD, 3)
|
new Ability(AbilityId.STICKY_HOLD, 3)
|
||||||
.attr(BlockItemTheftAbAttr)
|
.attr(BlockItemTheftAbAttr)
|
||||||
.bypassFaint()
|
.bypassFaint()
|
||||||
.ignorable()
|
.ignorable(),
|
||||||
.edgeCase(), // may or may not proc incorrectly on user's allies
|
|
||||||
new Ability(AbilityId.SHED_SKIN, 3)
|
new Ability(AbilityId.SHED_SKIN, 3)
|
||||||
.conditionalAttr(_pokemon => !randSeedInt(3), PostTurnResetStatusAbAttr),
|
.conditionalAttr(_pokemon => !randSeedInt(3), PostTurnResetStatusAbAttr),
|
||||||
new Ability(AbilityId.GUTS, 3)
|
new Ability(AbilityId.GUTS, 3)
|
||||||
|
@ -5131,13 +5131,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
globalScene.phaseManager.queueMessage(
|
|
||||||
i18next.t("battleInfo:newKey2", {
|
|
||||||
// arguments for the locale key go here;
|
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(this),
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
for (let f = 0; f < 2; f++) {
|
for (let f = 0; f < 2; f++) {
|
||||||
const variantColors = variantColorCache[!f ? spriteKey : backSpriteKey];
|
const variantColors = variantColorCache[!f ? spriteKey : backSpriteKey];
|
||||||
const variantColorSet = new Map<number, number[]>();
|
const variantColorSet = new Map<number, number[]>();
|
||||||
@ -6006,8 +5999,9 @@ export class PlayerPokemon extends Pokemon {
|
|||||||
true,
|
true,
|
||||||
) as PokemonHeldItemModifier[];
|
) as PokemonHeldItemModifier[];
|
||||||
for (const modifier of fusedPartyMemberHeldModifiers) {
|
for (const modifier of fusedPartyMemberHeldModifiers) {
|
||||||
globalScene.tryTransferHeldItemModifier(modifier, this, false, modifier.getStackCount(), false);
|
globalScene.tryTransferHeldItemModifier(modifier, this, false, modifier.getStackCount(), true, true, false);
|
||||||
}
|
}
|
||||||
|
globalScene.updateModifiers(true, true);
|
||||||
globalScene.removePartyMemberModifiers(fusedPartyMemberIndex);
|
globalScene.removePartyMemberModifiers(fusedPartyMemberIndex);
|
||||||
globalScene.getPlayerParty().splice(fusedPartyMemberIndex, 1)[0];
|
globalScene.getPlayerParty().splice(fusedPartyMemberIndex, 1)[0];
|
||||||
const newPartyMemberIndex = globalScene.getPlayerParty().indexOf(this);
|
const newPartyMemberIndex = globalScene.getPlayerParty().indexOf(this);
|
||||||
|
@ -159,7 +159,15 @@ export class SwitchSummonPhase extends SummonPhase {
|
|||||||
) as SwitchEffectTransferModifier;
|
) as SwitchEffectTransferModifier;
|
||||||
|
|
||||||
if (batonPassModifier) {
|
if (batonPassModifier) {
|
||||||
globalScene.tryTransferHeldItemModifier(batonPassModifier, switchedInPokemon, false, 1, false);
|
globalScene.tryTransferHeldItemModifier(
|
||||||
|
batonPassModifier,
|
||||||
|
switchedInPokemon,
|
||||||
|
false,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -538,14 +538,9 @@ export default abstract class BattleInfo extends Phaser.GameObjects.Container {
|
|||||||
this.updateHpFrame();
|
this.updateHpFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Update the pokemonHp bar */
|
||||||
* Update a Pokemon's HP bar.
|
protected updatePokemonHp(pokemon: Pokemon, resolve: (r: void | PromiseLike<void>) => void, instant?: boolean): void {
|
||||||
* @param pokemon - The {@linkcode Pokemon} to whom the HP bar belongs.
|
let duration = !instant ? Phaser.Math.Clamp(Math.abs(this.lastHp - pokemon.hp) * 5, 250, 5000) : 0;
|
||||||
* @param resolve - A promise to which the HP bar will be chained unto.
|
|
||||||
* @param instant - Whether to instantly update the pokemon's HP bar; default `false`
|
|
||||||
*/
|
|
||||||
protected updatePokemonHp(pokemon: Pokemon, resolve: (r: void | PromiseLike<void>) => void, instant = false): void {
|
|
||||||
let duration = instant ? 0 : Phaser.Math.Clamp(Math.abs(this.lastHp - pokemon.hp) * 5, 250, 5000);
|
|
||||||
const speed = globalScene.hpBarSpeed;
|
const speed = globalScene.hpBarSpeed;
|
||||||
if (speed) {
|
if (speed) {
|
||||||
duration = speed >= 3 ? 0 : duration / Math.pow(2, speed);
|
duration = speed >= 3 ? 0 : duration / Math.pow(2, speed);
|
||||||
@ -568,13 +563,7 @@ export default abstract class BattleInfo extends Phaser.GameObjects.Container {
|
|||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
/**
|
async updateInfo(pokemon: Pokemon, instant?: boolean): Promise<void> {
|
||||||
* Update a Pokemon's battle info, HP bar and other effects.
|
|
||||||
* @param pokemon - The {@linkcode} Pokemon to whom this BattleInfo belongs.
|
|
||||||
* @param instant - Whether to instantly update any changes to this Pokemon's HP bar; default `false`
|
|
||||||
* @returns A Promise that resolves once the Pokemon's info has been successfully updated.
|
|
||||||
*/
|
|
||||||
async updateInfo(pokemon: Pokemon, instant = false): Promise<void> {
|
|
||||||
let resolve: (r: void | PromiseLike<void>) => void = () => {};
|
let resolve: (r: void | PromiseLike<void>) => void = () => {};
|
||||||
const promise = new Promise<void>(r => (resolve = r));
|
const promise = new Promise<void>(r => (resolve = r));
|
||||||
if (!globalScene) {
|
if (!globalScene) {
|
||||||
|
Loading…
Reference in New Issue
Block a user