mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-21 07:42:25 +02:00
Update abilities using promises and trySet...
functions
This commit is contained in:
parent
17232d73b0
commit
953a1e4652
@ -2699,15 +2699,17 @@ export default class BattleScene extends SceneBase {
|
||||
* @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(itemModifier: PokemonHeldItemModifier, target: Pokemon, playSound: boolean, transferQuantity: number = 1, instant?: boolean, ignoreUpdate?: boolean, itemLost: boolean = true): Promise<boolean> {
|
||||
tryTransferHeldItemModifier(_itemModifier: PokemonHeldItemModifier, target: Pokemon, playSound: boolean, transferQuantity: number = 1, instant?: boolean, ignoreUpdate?: boolean, itemLost: boolean = true, simulated: boolean = false): Promise<boolean> {
|
||||
return new Promise(resolve => {
|
||||
const source = itemModifier.pokemonId ? itemModifier.getPokemon() : null;
|
||||
const source = _itemModifier.pokemonId ? _itemModifier.getPokemon() : null;
|
||||
const cancelled = new Utils.BooleanHolder(false);
|
||||
const removeFunc: (modifier: PersistentModifier, enemy: boolean | undefined) => boolean = simulated ? (modifier, enemy) => this.canRemoveModifier(modifier, enemy) : (modifier, enemy) => this.removeModifier(modifier, enemy);
|
||||
Utils.executeIf(!!source && source.isPlayer() !== target.isPlayer(), () => applyAbAttrs(BlockItemTheftAbAttr, source! /* checked in condition*/, cancelled)).then(() => {
|
||||
if (cancelled.value) {
|
||||
return resolve(false);
|
||||
}
|
||||
const newItemModifier = itemModifier.clone() as PokemonHeldItemModifier;
|
||||
const newItemModifier = _itemModifier.clone() as PokemonHeldItemModifier;
|
||||
const itemModifier = simulated ? _itemModifier.clone() : _itemModifier;
|
||||
newItemModifier.pokemonId = target.id;
|
||||
const matchingModifier = this.findModifier(m => m instanceof PokemonHeldItemModifier
|
||||
&& (m as PokemonHeldItemModifier).matchType(itemModifier) && m.pokemonId === target.id, target.isPlayer()) as PokemonHeldItemModifier;
|
||||
@ -2727,9 +2729,12 @@ export default class BattleScene extends SceneBase {
|
||||
newItemModifier.stackCount = countTaken;
|
||||
}
|
||||
removeOld = !itemModifier.stackCount;
|
||||
if (!removeOld || !source || this.removeModifier(itemModifier, !source.isPlayer())) {
|
||||
if (!removeOld || !source || removeFunc(simulated ? _itemModifier : itemModifier, !source.isPlayer())) {
|
||||
const addModifier = () => {
|
||||
if (!matchingModifier || this.removeModifier(matchingModifier, !target.isPlayer())) {
|
||||
if (!matchingModifier || removeFunc(matchingModifier, !target.isPlayer())) {
|
||||
if (simulated) {
|
||||
return resolve(true);
|
||||
}
|
||||
if (target.isPlayer()) {
|
||||
this.addModifier(newItemModifier, ignoreUpdate, playSound, false, instant).then(() => {
|
||||
if (source && itemLost) {
|
||||
@ -2749,7 +2754,7 @@ export default class BattleScene extends SceneBase {
|
||||
resolve(false);
|
||||
}
|
||||
};
|
||||
if (source && source.isPlayer() !== target.isPlayer() && !ignoreUpdate) {
|
||||
if (!simulated && source && source.isPlayer() !== target.isPlayer() && !ignoreUpdate) {
|
||||
this.updateModifiers(source.isPlayer(), instant).then(() => addModifier());
|
||||
} else {
|
||||
addModifier();
|
||||
@ -2909,6 +2914,11 @@ export default class BattleScene extends SceneBase {
|
||||
});
|
||||
}
|
||||
|
||||
canRemoveModifier(modifier: PersistentModifier, enemy: boolean = false): boolean {
|
||||
const modifiers = !enemy ? this.modifiers : this.enemyModifiers;
|
||||
return modifiers.indexOf(modifier) > -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
@ -591,7 +591,7 @@ export class FullHpResistTypeAbAttr extends PreDefendAbAttr {
|
||||
}
|
||||
|
||||
export class PostDefendAbAttr extends AbAttr {
|
||||
canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean {
|
||||
canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean | Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -869,7 +869,7 @@ export class PostDefendTerrainChangeAbAttr extends PostDefendAbAttr {
|
||||
}
|
||||
|
||||
override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||
return hitResult < HitResult.NO_EFFECT && !move.hitsSubstitute(attacker, pokemon);
|
||||
return hitResult < HitResult.NO_EFFECT && !move.hitsSubstitute(attacker, pokemon) && globalScene.arena.canSetTerrain(this.terrainType);
|
||||
}
|
||||
|
||||
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, _args: any[]): boolean {
|
||||
@ -1048,7 +1048,8 @@ export class PostDefendWeatherChangeAbAttr extends PostDefendAbAttr {
|
||||
}
|
||||
|
||||
override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean {
|
||||
return (!(this.condition && !this.condition(pokemon, attacker, move) || move.hitsSubstitute(attacker, pokemon)) && !globalScene.arena.weather?.isImmutable());
|
||||
return (!(this.condition && !this.condition(pokemon, attacker, move) || move.hitsSubstitute(attacker, pokemon))
|
||||
&& !globalScene.arena.weather?.isImmutable() && globalScene.arena.canSetWeather(this.weatherType));
|
||||
}
|
||||
|
||||
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean {
|
||||
@ -1619,7 +1620,7 @@ export class PostAttackAbAttr extends AbAttr {
|
||||
* applying the effect of any inherited class. This can be changed by providing a different {@link attackCondition} to the constructor. See {@link ConfusionOnStatusEffectAbAttr}
|
||||
* for an example of an effect that does not require a damaging move.
|
||||
*/
|
||||
canApplyPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean {
|
||||
canApplyPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean | Promise<boolean> {
|
||||
// When attackRequired is true, we require the move to be an attack move and to deal damage before checking secondary requirements.
|
||||
// If attackRequired is false, we always defer to the secondary requirements.
|
||||
return this.attackCondition(pokemon, defender, move);
|
||||
@ -1674,14 +1675,21 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr {
|
||||
this.stealCondition = stealCondition ?? null;
|
||||
}
|
||||
|
||||
canApplyPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean {
|
||||
return super.canApplyPostAttack(pokemon, passive, simulated, defender, move, hitResult, args); // && SUCCESS CHECK
|
||||
canApplyPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult, args: any[]): Promise<boolean> {
|
||||
return new Promise<boolean>(resolve => {
|
||||
if (!super.canApplyPostAttack(pokemon, passive, simulated, defender, move, hitResult, args)) {
|
||||
return resolve(false);
|
||||
}
|
||||
|
||||
canStealHeldItem(pokemon, passive, simulated, defender, move, hitResult, this.stealCondition, args).then(success => {
|
||||
resolve(success);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
applyPostAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult, args: any[]): Promise<boolean> {
|
||||
return new Promise<boolean>(resolve => {
|
||||
if (!simulated && hitResult < HitResult.NO_EFFECT && (!this.stealCondition || this.stealCondition(pokemon, defender, move))) {
|
||||
const heldItems = this.getTargetHeldItems(defender).filter(i => i.isTransferable);
|
||||
const heldItems = getTargetHeldItems(defender).filter(i => i.isTransferable);
|
||||
if (heldItems.length) {
|
||||
const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)];
|
||||
globalScene.tryTransferHeldItemModifier(stolenItem, pokemon, false).then(success => {
|
||||
@ -1692,15 +1700,9 @@ export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr {
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
resolve(simulated);
|
||||
});
|
||||
}
|
||||
|
||||
getTargetHeldItems(target: Pokemon): PokemonHeldItemModifier[] {
|
||||
return globalScene.findModifiers(m => m instanceof PokemonHeldItemModifier
|
||||
&& m.pokemonId === target.id, target.isPlayer()) as PokemonHeldItemModifier[];
|
||||
}
|
||||
}
|
||||
|
||||
export class PostAttackApplyStatusEffectAbAttr extends PostAttackAbAttr {
|
||||
@ -1776,12 +1778,21 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr {
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
// SUCCESS CHECK
|
||||
override canApplyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): Promise<boolean> {
|
||||
return new Promise<boolean>(resolve => {
|
||||
if (move.hitsSubstitute(attacker, pokemon)) {
|
||||
return resolve(false);
|
||||
}
|
||||
|
||||
canStealHeldItem(pokemon, passive, simulated, attacker, move, hitResult, this.condition, args).then(success => {
|
||||
resolve(success);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, _args: any[]): Promise<boolean> {
|
||||
return new Promise<boolean>(resolve => {
|
||||
if (!simulated && hitResult < HitResult.NO_EFFECT && (!this.condition || this.condition(pokemon, attacker, move)) && !move.hitsSubstitute(attacker, pokemon)) {
|
||||
const heldItems = this.getTargetHeldItems(attacker).filter(i => i.isTransferable);
|
||||
const heldItems = getTargetHeldItems(attacker).filter(i => i.isTransferable);
|
||||
if (heldItems.length) {
|
||||
const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)];
|
||||
globalScene.tryTransferHeldItemModifier(stolenItem, pokemon, false).then(success => {
|
||||
@ -1792,15 +1803,9 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr {
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
resolve(simulated);
|
||||
});
|
||||
}
|
||||
|
||||
getTargetHeldItems(target: Pokemon): PokemonHeldItemModifier[] {
|
||||
return globalScene.findModifiers(m => m instanceof PokemonHeldItemModifier
|
||||
&& m.pokemonId === target.id, target.isPlayer()) as PokemonHeldItemModifier[];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1841,7 +1846,8 @@ export class SynchronizeStatusAbAttr extends PostSetStatusAbAttr {
|
||||
StatusEffect.TOXIC
|
||||
]);
|
||||
|
||||
return (sourcePokemon && syncStatuses.has(effect)) ?? false;
|
||||
// synchronize does not need to check canSetStatus because the ability shows even if it fails to set the status
|
||||
return ((sourcePokemon ?? false) && syncStatuses.has(effect));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2307,7 +2313,7 @@ export class PostSummonWeatherChangeAbAttr extends PostSummonAbAttr {
|
||||
const weatherReplaceable = (this.weatherType === WeatherType.HEAVY_RAIN ||
|
||||
this.weatherType === WeatherType.HARSH_SUN ||
|
||||
this.weatherType === WeatherType.STRONG_WINDS) || !globalScene.arena.weather?.isImmutable();
|
||||
return weatherReplaceable;
|
||||
return weatherReplaceable && globalScene.arena.canSetWeather(this.weatherType);
|
||||
}
|
||||
|
||||
applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean {
|
||||
@ -2328,6 +2334,10 @@ export class PostSummonTerrainChangeAbAttr extends PostSummonAbAttr {
|
||||
this.terrainType = terrainType;
|
||||
}
|
||||
|
||||
canApplyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean {
|
||||
return globalScene.arena.canSetTerrain(this.terrainType);
|
||||
}
|
||||
|
||||
applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean {
|
||||
if (simulated) {
|
||||
return globalScene.arena.terrain?.terrainType !== this.terrainType;
|
||||
@ -3889,7 +3899,7 @@ export class PostBiomeChangeWeatherChangeAbAttr extends PostBiomeChangeAbAttr {
|
||||
}
|
||||
|
||||
canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean {
|
||||
return (globalScene.arena.weather?.isImmutable() && globalScene.arena.weather?.weatherType !== this.weatherType) ?? false;
|
||||
return ((globalScene.arena.weather?.isImmutable() ?? false) && globalScene.arena.canSetWeather(this.weatherType));
|
||||
}
|
||||
|
||||
apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
@ -3915,7 +3925,7 @@ export class PostBiomeChangeTerrainChangeAbAttr extends PostBiomeChangeAbAttr {
|
||||
}
|
||||
|
||||
canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean {
|
||||
return globalScene.arena.terrain?.terrainType !== this.terrainType;
|
||||
return globalScene.arena.canSetTerrain(this.terrainType);
|
||||
}
|
||||
|
||||
apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
@ -5020,10 +5030,17 @@ async function applyAbAttrsInternal<TAttr extends AbAttr>(
|
||||
const ability = passive ? pokemon.getPassiveAbility() : pokemon.getAbility();
|
||||
for (const attr of ability.getAttrs(attrType)) {
|
||||
const condition = attr.getCondition();
|
||||
if ((condition && !condition(pokemon)) || successFunc && !successFunc(attr, passive)) {
|
||||
if ((condition && !condition(pokemon))) {
|
||||
continue;
|
||||
}
|
||||
let success = successFunc(attr, passive);
|
||||
if (success instanceof Promise) {
|
||||
success = await success;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
continue;
|
||||
}
|
||||
globalScene.setPhaseQueueSplice();
|
||||
|
||||
if (attr.showAbility && !simulated) {
|
||||
@ -5514,6 +5531,31 @@ function getPokemonWithWeatherBasedForms() {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if a target's held item can be stolen
|
||||
*
|
||||
* Common to attrs for {@linkcode Abilities.MAGICIAN} and {@linkcode Abilities.PICKPOCKET}
|
||||
*/
|
||||
async function canStealHeldItem(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, condition: any, args: any[]): Promise<boolean> {
|
||||
if (!simulated && hitResult < HitResult.NO_EFFECT && (!condition || condition(pokemon, attacker, move))) {
|
||||
const heldItems = getTargetHeldItems(attacker).filter(i => i.isTransferable);
|
||||
if (heldItems.length) {
|
||||
return globalScene.tryTransferHeldItemModifier(heldItems[pokemon.randSeedInt(heldItems.length)], pokemon, false, 1, false, false, true, true);
|
||||
}
|
||||
}
|
||||
return simulated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the held items of a pokemon
|
||||
* @param target Target Pokemon
|
||||
* @returns List of {@linkcode target}'s held items
|
||||
*/
|
||||
function getTargetHeldItems(target: Pokemon): PokemonHeldItemModifier[] {
|
||||
return globalScene.findModifiers(m => m instanceof PokemonHeldItemModifier
|
||||
&& m.pokemonId === target.id, target.isPlayer()) as PokemonHeldItemModifier[];
|
||||
}
|
||||
|
||||
export const allAbilities = [ new Ability(Abilities.NONE, 3) ];
|
||||
|
||||
export function initAbilities() {
|
||||
|
@ -249,6 +249,11 @@ export class Arena {
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Returns weather or not the weather can be changed to {@linkcode weather} */
|
||||
canSetWeather(weather: WeatherType): boolean {
|
||||
return !(this.weather?.weatherType === (weather || undefined));
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to set a new weather to the battle
|
||||
* @param weather {@linkcode WeatherType} new {@linkcode WeatherType} to set
|
||||
@ -260,7 +265,7 @@ export class Arena {
|
||||
return this.trySetWeatherOverride(Overrides.WEATHER_OVERRIDE);
|
||||
}
|
||||
|
||||
if (this.weather?.weatherType === (weather || undefined)) {
|
||||
if (!this.canSetWeather(weather)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -314,8 +319,13 @@ export class Arena {
|
||||
});
|
||||
}
|
||||
|
||||
/** Returns whether or not the terrain can be set to {@linkcode terrain} */
|
||||
canSetTerrain(terrain: TerrainType): boolean {
|
||||
return !(this.terrain?.terrainType === (terrain || undefined));
|
||||
}
|
||||
|
||||
trySetTerrain(terrain: TerrainType, hasPokemonSource: boolean, ignoreAnim: boolean = false): boolean {
|
||||
if (this.terrain?.terrainType === (terrain || undefined)) {
|
||||
if (!this.canSetTerrain(terrain)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
import { type PokeballCounts } from "#app/battle-scene";
|
||||
import { Gender } from "#app/data/gender";
|
||||
import { Variant } from "#app/data/variant";
|
||||
import { BerryType } from "#app/enums/berry-type";
|
||||
import { type ModifierOverride } from "#app/modifier/modifier-type";
|
||||
import { Unlockables } from "#app/system/unlockables";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
@ -32,7 +33,14 @@ import { WeatherType } from "#enums/weather-type";
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
const overrides = {} satisfies Partial<InstanceType<typeof DefaultOverrides>>;
|
||||
const overrides = {
|
||||
OPP_HELD_ITEMS_OVERRIDE: [{ name: "BERRY", type: BerryType.GANLON, count: 3 }],
|
||||
ABILITY_OVERRIDE: Abilities.PICKPOCKET,
|
||||
OPP_LEVEL_OVERRIDE: 1,
|
||||
STARTING_LEVEL_OVERRIDE: 100,
|
||||
OPP_MOVESET_OVERRIDE: Moves.TACKLE,
|
||||
MOVESET_OVERRIDE: Moves.SPLASH
|
||||
} satisfies Partial<InstanceType<typeof DefaultOverrides>>;
|
||||
|
||||
/**
|
||||
* If you need to add Overrides values for local testing do that inside {@linkcode overrides}
|
||||
|
Loading…
Reference in New Issue
Block a user