mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-06-20 16:42:45 +02:00
Merge 70ff67f012
into 4b70fab608
This commit is contained in:
commit
81e87aca69
@ -836,7 +836,8 @@ export default class BattleScene extends SceneBase {
|
||||
/**
|
||||
* Returns an array of Pokemon on both sides of the battle - player first, then enemy.
|
||||
* Does not actually check if the pokemon are on the field or not, and always has length 4 regardless of battle type.
|
||||
* @param activeOnly - Whether to consider only active pokemon; default `false`
|
||||
* @param activeOnly - Whether to consider only active pokemon (as described by {@linkcode Pokemon.isActive()}); default `false`.
|
||||
* If `true`, will also remove all `null` values from the array.
|
||||
* @returns An array of {@linkcode Pokemon}, as described above.
|
||||
*/
|
||||
public getField(activeOnly = false): Pokemon[] {
|
||||
@ -849,9 +850,9 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Used in doubles battles to redirect moves from one pokemon to another when one faints or is removed from the field
|
||||
* @param removedPokemon {@linkcode Pokemon} the pokemon that is being removed from the field (flee, faint), moves to be redirected FROM
|
||||
* @param allyPokemon {@linkcode Pokemon} the pokemon that will have the moves be redirected TO
|
||||
* Attempt to redirect a move in double battles from a fainted/removed Pokemon to its ally.
|
||||
* @param removedPokemon - The {@linkcode Pokemon} having been removed from the field.
|
||||
* @param allyPokemon - The {@linkcode Pokemon} allied with the removed Pokemon; will have moves redirected to it
|
||||
*/
|
||||
redirectPokemonMoves(removedPokemon: Pokemon, allyPokemon: Pokemon): void {
|
||||
// failsafe: if not a double battle just return
|
||||
@ -877,10 +878,10 @@ export default class BattleScene extends SceneBase {
|
||||
|
||||
/**
|
||||
* Returns the ModifierBar of this scene, which is declared private and therefore not accessible elsewhere
|
||||
* @param isEnemy Whether to return the enemy's modifier bar
|
||||
* @returns {ModifierBar}
|
||||
* @param isEnemy - Whether to return the enemy modifier bar instead of the player bar; default `false`
|
||||
* @returns The {@linkcode ModifierBar} for the given side of the field
|
||||
*/
|
||||
getModifierBar(isEnemy?: boolean): ModifierBar {
|
||||
getModifierBar(isEnemy = false): ModifierBar {
|
||||
return isEnemy ? this.enemyModifierBar : this.modifierBar;
|
||||
}
|
||||
|
||||
@ -1434,10 +1435,12 @@ export default class BattleScene extends SceneBase {
|
||||
|
||||
if (!waveIndex && lastBattle) {
|
||||
const isNewBiome = this.isNewBiome(lastBattle);
|
||||
/** Whether to reset and recall pokemon */
|
||||
const resetArenaState =
|
||||
isNewBiome ||
|
||||
[BattleType.TRAINER, BattleType.MYSTERY_ENCOUNTER].includes(this.currentBattle.battleType) ||
|
||||
this.currentBattle.battleSpec === BattleSpec.FINAL_BOSS;
|
||||
|
||||
for (const enemyPokemon of this.getEnemyParty()) {
|
||||
enemyPokemon.destroy();
|
||||
}
|
||||
@ -1812,7 +1815,7 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
|
||||
resetSeed(waveIndex?: number): void {
|
||||
const wave = waveIndex || this.currentBattle?.waveIndex || 0;
|
||||
const wave = waveIndex ?? this.currentBattle?.waveIndex ?? 0;
|
||||
this.waveSeed = shiftCharCodes(this.seed, wave);
|
||||
Phaser.Math.RND.sow([this.waveSeed]);
|
||||
console.log("Wave Seed:", this.waveSeed, wave);
|
||||
|
@ -201,19 +201,35 @@ export class Ability implements Localizable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark an ability as partially implemented.
|
||||
* Partial abilities are expected to have some of their core functionality implemented, but may lack
|
||||
* certain notable features or interactions with other moves or abilities.
|
||||
* @returns `this`
|
||||
*/
|
||||
partial(): this {
|
||||
this.nameAppend += " (P)";
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark an ability as unimplemented.
|
||||
* Unimplemented abilities are ones which have _none_ of their basic functionality enabled.
|
||||
* @returns `this`
|
||||
*/
|
||||
unimplemented(): this {
|
||||
this.nameAppend += " (N)";
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal flag used for developers to document edge cases. When using this, please be sure to document the edge case.
|
||||
* @returns the ability
|
||||
* Mark an ability as having one or more edge cases.
|
||||
* It may lack certain niche interactions with other moves/abilities, but still functions
|
||||
* as intended in most cases.
|
||||
* Does not show up in game and is solely for internal dev use.
|
||||
*
|
||||
* When using this, make sure to **document the edge case** (or else this becomes pointless).
|
||||
* @returns `this`
|
||||
*/
|
||||
edgeCase(): this {
|
||||
return this;
|
||||
@ -674,7 +690,6 @@ export class TypeImmunityAbAttr extends PreDefendAbAttr {
|
||||
* @param _move {@linkcode Move} The attacking move.
|
||||
* @param _cancelled {@linkcode BooleanHolder} - A holder for a boolean value indicating if the move was cancelled.
|
||||
* @param args [0] {@linkcode NumberHolder} gets set to 0 if move is immuned by an ability.
|
||||
* @param args [1] - Whether the move is simulated.
|
||||
*/
|
||||
override applyPreDefend(
|
||||
_pokemon: Pokemon,
|
||||
@ -2106,6 +2121,10 @@ export class FieldPreventExplosiveMovesAbAttr extends AbAttr {
|
||||
export class FieldMultiplyStatAbAttr extends AbAttr {
|
||||
private stat: Stat;
|
||||
private multiplier: number;
|
||||
/**
|
||||
* Whether this ability can stack with others of the same type for this stat.
|
||||
* @defaultValue `false`
|
||||
*/
|
||||
private canStack: boolean;
|
||||
|
||||
constructor(stat: Stat, multiplier: number, canStack = false) {
|
||||
@ -2130,15 +2149,18 @@ export class FieldMultiplyStatAbAttr extends AbAttr {
|
||||
this.canStack ||
|
||||
(!hasApplied.value &&
|
||||
this.stat === stat &&
|
||||
checkedPokemon.getAbilityAttrs("FieldMultiplyStatAbAttr").every(attr => attr.stat !== stat))
|
||||
// targets with the same stat-changing ability as this are unaffected
|
||||
checkedPokemon
|
||||
.getAbilityAttrs("FieldMultiplyStatAbAttr")
|
||||
.every(attr => attr.stat !== stat))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* applyFieldStat: Tries to multiply a Pokemon's Stat
|
||||
* @param _pokemon {@linkcode Pokemon} the Pokemon using this ability
|
||||
* @param _passive {@linkcode boolean} unused
|
||||
* @param _stat {@linkcode Stat} the type of the checked stat
|
||||
* Tries to multiply a Pokemon's Stat.
|
||||
* @param pokemon {@linkcode Pokemon} the Pokemon using this ability
|
||||
* @param passive {@linkcode boolean} unused
|
||||
* @param stat {@linkcode Stat} the type of the checked stat
|
||||
* @param statValue {@linkcode NumberHolder} the value of the checked stat
|
||||
* @param _checkedPokemon {@linkcode Pokemon} the Pokemon this ability is targeting
|
||||
* @param hasApplied {@linkcode BooleanHolder} whether or not another multiplier has been applied to this stat
|
||||
@ -2169,7 +2191,7 @@ export class MoveTypeChangeAbAttr extends PreAttackAbAttr {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the move type change attribute can be applied
|
||||
* Determine if the move type change attribute can be applied.
|
||||
*
|
||||
* Can be applied if:
|
||||
* - The ability's condition is met, e.g. pixilate only boosts normal moves,
|
||||
@ -2179,9 +2201,9 @@ export class MoveTypeChangeAbAttr extends PreAttackAbAttr {
|
||||
* @param pokemon - The pokemon that has the move type changing ability and is using the attacking move
|
||||
* @param _passive - Unused
|
||||
* @param _simulated - Unused
|
||||
* @param _defender - The pokemon being attacked (unused)
|
||||
* @param move - The move being used
|
||||
* @param _args - args[0] holds the type that the move is changed to, args[1] holds the multiplier
|
||||
* @param _defender - Unused
|
||||
* @param move - The {@linkcode Move} being used
|
||||
* @param _args - Unused
|
||||
* @returns whether the move type change attribute can be applied
|
||||
*/
|
||||
override canApplyPreAttack(
|
||||
@ -2294,12 +2316,13 @@ export class PokemonTypeChangeAbAttr extends PreAttackAbAttr {
|
||||
}
|
||||
|
||||
/**
|
||||
* Class for abilities that convert single-strike moves to two-strike moves (i.e. Parental Bond).
|
||||
* @param damageMultiplier the damage multiplier for the second strike, relative to the first.
|
||||
* Class for abilities that add additional strikes to single-target moves.
|
||||
* Used by {@linkcode Moves.PARENTAL_BOND | Parental Bond}.
|
||||
*
|
||||
* @param damageMultiplier - The damage multiplier for the added strike, relative to the first.
|
||||
*/
|
||||
export class AddSecondStrikeAbAttr extends PreAttackAbAttr {
|
||||
private damageMultiplier: number;
|
||||
|
||||
constructor(damageMultiplier: number) {
|
||||
super(false);
|
||||
|
||||
@ -2312,32 +2335,32 @@ export class AddSecondStrikeAbAttr extends PreAttackAbAttr {
|
||||
_simulated: boolean,
|
||||
_defender: Pokemon | null,
|
||||
move: Move,
|
||||
_args: any[],
|
||||
_args: [NumberHolder?, NumberHolder?],
|
||||
): boolean {
|
||||
return move.canBeMultiStrikeEnhanced(pokemon, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* If conditions are met, this doubles the move's hit count (via args[1])
|
||||
* or multiplies the damage of secondary strikes (via args[2])
|
||||
* @param pokemon the {@linkcode Pokemon} using the move
|
||||
* @param _passive n/a
|
||||
* @param _defender n/a
|
||||
* @param _move the {@linkcode Move} used by the ability source
|
||||
* @param args Additional arguments:
|
||||
* - `[0]` the number of strikes this move currently has ({@linkcode NumberHolder})
|
||||
* - `[1]` the damage multiplier for the current strike ({@linkcode NumberHolder})
|
||||
* Increases the move's hit count or modifies the move's damage.
|
||||
* @param pokemon - The {@linkcode Pokemon} using the move
|
||||
* @param passive - Unused
|
||||
* @param defender - Unused
|
||||
* @param move - The {@linkcode Move} being used
|
||||
* @param args -
|
||||
* - `[0]` - A {@linkcode NumberHolder} holding the move's current strike count
|
||||
* - `[1]` - A {@linkcode NumberHolder} holding the current strike's damage multiplier.
|
||||
*/
|
||||
// TODO: Review if these args can be undefined when called (and remove the ? if not)
|
||||
override applyPreAttack(
|
||||
pokemon: Pokemon,
|
||||
_passive: boolean,
|
||||
_simulated: boolean,
|
||||
_defender: Pokemon,
|
||||
_move: Move,
|
||||
args: any[],
|
||||
args: [NumberHolder?, NumberHolder?],
|
||||
): void {
|
||||
const hitCount = args[0] as NumberHolder;
|
||||
const multiplier = args[1] as NumberHolder;
|
||||
const hitCount = args[0];
|
||||
const multiplier = args[1];
|
||||
if (hitCount?.value) {
|
||||
hitCount.value += 1;
|
||||
}
|
||||
@ -2623,8 +2646,9 @@ export class PostAttackAbAttr extends AbAttr {
|
||||
|
||||
/**
|
||||
* By default, this method checks that the move used is a damaging attack before
|
||||
* 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.
|
||||
* applying the effect of any inherited class.
|
||||
* This can be changed by providing a different {@linkcode attackCondition} to the constructor
|
||||
* (see {@linkcode ConfusionOnStatusEffectAbAttr} for an example of this being used).
|
||||
*/
|
||||
canApplyPostAttack(
|
||||
pokemon: Pokemon,
|
||||
@ -4389,22 +4413,35 @@ export class ProtectStatAbAttr extends PreStatStageChangeAbAttr {
|
||||
}
|
||||
|
||||
/**
|
||||
* This attribute applies confusion to the target whenever the user
|
||||
* directly poisons them with a move, e.g. Poison Puppeteer.
|
||||
* Called in {@linkcode StatusEffectAttr}.
|
||||
* Attribute to apply confusion to the target whenever the user directly statuses them with a move.
|
||||
*
|
||||
* Used by {@linkcode Abilities.POISON_PUPPETEER}
|
||||
*
|
||||
* Called in {@linkcode StatusEffectAttr}
|
||||
* @extends PostAttackAbAttr
|
||||
* @see {@linkcode applyPostAttack}
|
||||
*/
|
||||
export class ConfusionOnStatusEffectAbAttr extends PostAttackAbAttr {
|
||||
/** List of effects to apply confusion after */
|
||||
private effects: StatusEffect[];
|
||||
private effects: ReadonlySet<StatusEffect>;
|
||||
|
||||
constructor(...effects: StatusEffect[]) {
|
||||
/** This effect does not require a damaging move */
|
||||
super((_user, _target, _move) => true);
|
||||
this.effects = effects;
|
||||
super(() => true);
|
||||
this.effects = new Set(effects);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the target was inflicted by the correct status condition from this Pokemon
|
||||
* and can be confused.
|
||||
* @param pokemon - {The @linkcode Pokemon} with this ability
|
||||
* @param passive - N/A
|
||||
* @param defender - The {@linkcode Pokemon} being targeted (will be confused)
|
||||
* @param move - The {@linkcode Move} that applied the status effect
|
||||
* @param hitResult - N/A
|
||||
* @param args `[0]` - The {@linkcode StatusEffect} applied by the move
|
||||
* @returns `true` if the target can be confused after being statused.
|
||||
*/
|
||||
override canApplyPostAttack(
|
||||
pokemon: Pokemon,
|
||||
passive: boolean,
|
||||
@ -4412,24 +4449,24 @@ export class ConfusionOnStatusEffectAbAttr extends PostAttackAbAttr {
|
||||
defender: Pokemon,
|
||||
move: Move,
|
||||
hitResult: HitResult | null,
|
||||
args: any[],
|
||||
args: [StatusEffect],
|
||||
): boolean {
|
||||
return (
|
||||
super.canApplyPostAttack(pokemon, passive, simulated, defender, move, hitResult, args) &&
|
||||
this.effects.indexOf(args[0]) > -1 &&
|
||||
this.effects.has(args[0]) &&
|
||||
!defender.isFainted() &&
|
||||
defender.canAddTag(BattlerTagType.CONFUSED)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies confusion to the target pokemon.
|
||||
* @param pokemon {@link Pokemon} attacking
|
||||
* @param _passive N/A
|
||||
* @param defender {@link Pokemon} defending
|
||||
* @param move {@link Move} used to apply status effect and confusion
|
||||
* @param _hitResult N/A
|
||||
* @param _args [0] {@linkcode StatusEffect} applied by move
|
||||
* Apply confusion to the target pokemon.
|
||||
* @param pokemon - {@linkcode Pokemon} with the ability
|
||||
* @param passive N/A
|
||||
* @param defender - {@linkcode Pokemon} being targeted (will be confused)
|
||||
* @param move - N/A
|
||||
* @param hitResult - N/A
|
||||
* @param args - N/A
|
||||
*/
|
||||
override applyPostAttack(
|
||||
pokemon: Pokemon,
|
||||
@ -4609,12 +4646,12 @@ export class ConditionalUserFieldProtectStatAbAttr extends PreStatStageChangeAbA
|
||||
|
||||
/**
|
||||
* Determine whether the {@linkcode ConditionalUserFieldProtectStatAbAttr} can be applied.
|
||||
* @param _pokemon The pokemon with the ability
|
||||
* @param _passive unused
|
||||
* @param _simulated Unused
|
||||
* @param stat The stat being affected
|
||||
* @param cancelled Holds whether the stat change was already prevented.
|
||||
* @param args Args[0] is the target pokemon of the stat change.
|
||||
* @param pokemon - The pokemon with the ability
|
||||
* @param passive - unused
|
||||
* @param simulated - Unused
|
||||
* @param stat - The {@linkcode Stat} being affected
|
||||
* @param cancelled - {@linkcode BooleanHolder} containing whether the stat change was already prevented
|
||||
* @param args - `[0]`: The {@linkcode Pokemon} receiving the stat change
|
||||
* @returns `true` if the ability can be applied
|
||||
*/
|
||||
override canApplyPreStatStageChange(
|
||||
@ -4623,7 +4660,7 @@ export class ConditionalUserFieldProtectStatAbAttr extends PreStatStageChangeAbA
|
||||
_simulated: boolean,
|
||||
stat: BattleStat,
|
||||
cancelled: BooleanHolder,
|
||||
args: [Pokemon, ...any],
|
||||
args: [Pokemon],
|
||||
): boolean {
|
||||
const target = args[0];
|
||||
if (!target) {
|
||||
@ -4637,12 +4674,12 @@ export class ConditionalUserFieldProtectStatAbAttr extends PreStatStageChangeAbA
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the {@linkcode ConditionalUserFieldStatusEffectImmunityAbAttr} to an interaction
|
||||
* @param _pokemon The pokemon the stat change is affecting (unused)
|
||||
* @param _passive unused
|
||||
* @param _simulated unused
|
||||
* @param stat The stat being affected
|
||||
* @param cancelled Will be set to true if the stat change is prevented
|
||||
* Apply the {@linkcode ConditionalUserFieldStatusEffectImmunityAbAttr} to block status effect application
|
||||
* @param _pokemon - unused
|
||||
* @param _passive - unused
|
||||
* @param _simulated - unused
|
||||
* @param stat - unused
|
||||
* @param cancelled - A {@linkcode BooleanHolder} containing status effect immunity; will be set to `true`
|
||||
* @param _args unused
|
||||
*/
|
||||
override applyPreStatStageChange(
|
||||
@ -4862,17 +4899,22 @@ export class ConditionalCritAbAttr extends AbAttr {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _pokemon {@linkcode Pokemon} user.
|
||||
* @param args [0] {@linkcode BooleanHolder} If true critical hit is guaranteed.
|
||||
* [1] {@linkcode Pokemon} Target.
|
||||
* [2] {@linkcode Move} used by ability user.
|
||||
* Apply this ability by enabling guaranteed critical hits.
|
||||
* @param pokemon - The {@linkcode Pokemon} with the ability (unused).
|
||||
* @param passive - Unused
|
||||
* @param simulated - Unused
|
||||
* @param cancelled - Unused
|
||||
* @param args -
|
||||
* - `[0]` A {@linkcode BooleanHolder} containing whether critical hits are guaranteed.
|
||||
* - `[1]` The {@linkcode Pokemon} being targeted (unused)
|
||||
* - `[2]` The {@linkcode Move} used by the ability holder (unused)
|
||||
*/
|
||||
override apply(
|
||||
_pokemon: Pokemon,
|
||||
_passive: boolean,
|
||||
_simulated: boolean,
|
||||
_cancelled: BooleanHolder,
|
||||
args: any[],
|
||||
args: [BooleanHolder, Pokemon, Move, ...any],
|
||||
): void {
|
||||
(args[0] as BooleanHolder).value = true;
|
||||
}
|
||||
@ -5588,7 +5630,7 @@ export class PostTurnStatusHealAbAttr extends PostTurnAbAttr {
|
||||
|
||||
/**
|
||||
* After the turn ends, resets the status of either the ability holder or their ally
|
||||
* @param allyTarget Whether to target ally, defaults to false (self-target)
|
||||
* @param allyTarget - Whether to target the ability holder's ally; default `false` (self-target)
|
||||
*/
|
||||
export class PostTurnResetStatusAbAttr extends PostTurnAbAttr {
|
||||
private allyTarget: boolean;
|
||||
@ -5871,7 +5913,7 @@ export class PostTurnFormChangeAbAttr extends PostTurnAbAttr {
|
||||
}
|
||||
|
||||
/**
|
||||
* Attribute used for abilities (Bad Dreams) that damages the opponents for being asleep
|
||||
* Attribute used for abilities (Bad Dreams) that damages sleeping opponents during turn end.
|
||||
*/
|
||||
export class PostTurnHurtIfSleepingAbAttr extends PostTurnAbAttr {
|
||||
override canApplyPostTurn(pokemon: Pokemon, _passive: boolean, _simulated: boolean, _args: any[]): boolean {
|
||||
@ -5884,26 +5926,32 @@ export class PostTurnHurtIfSleepingAbAttr extends PostTurnAbAttr {
|
||||
!opp.switchOutStatus,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deals damage to all sleeping opponents equal to 1/8 of their max hp (min 1)
|
||||
* @param pokemon {@linkcode Pokemon} with this ability
|
||||
* @param _passive N/A
|
||||
* @param simulated `true` if applying in a simulated call.
|
||||
* @param _args N/A
|
||||
* Damages all sleeping opponents on turn end equal to 1/8 of their respective max hp (min 1)
|
||||
* @param pokemon - The {@linkcode Pokemon} with this ability
|
||||
* @param passive - Unused
|
||||
* @param simulated - Whether to suppress changes to game state during calculations.
|
||||
* @param args - Unused
|
||||
*/
|
||||
override applyPostTurn(pokemon: Pokemon, _passive: boolean, simulated: boolean, _args: any[]): void {
|
||||
for (const opp of pokemon.getOpponents()) {
|
||||
if (
|
||||
(opp.status?.effect === StatusEffect.SLEEP || opp.hasAbility(AbilityId.COMATOSE)) &&
|
||||
!opp.hasAbilityWithAttr("BlockNonDirectDamageAbAttr") &&
|
||||
!opp.switchOutStatus
|
||||
) {
|
||||
if (!simulated) {
|
||||
opp.damageAndUpdate(toDmgValue(opp.getMaxHp() / 8), { result: HitResult.INDIRECT });
|
||||
globalScene.phaseManager.queueMessage(
|
||||
i18next.t("abilityTriggers:badDreams", { pokemonName: getPokemonNameWithAffix(opp) }),
|
||||
);
|
||||
}
|
||||
if (simulated) {
|
||||
return;
|
||||
}
|
||||
|
||||
// grab all on-field, sleeping opponents and hurt them if they aren't immune to passive damage
|
||||
for (const opp of pokemon.getOpponents(true)) {
|
||||
if (opp.status?.effect !== StatusEffect.SLEEP && !opp.hasAbility(AbilityId.COMATOSE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const cancelled = new BooleanHolder(false);
|
||||
applyAbAttrs("BlockNonDirectDamageAbAttr", opp, cancelled, false);
|
||||
if (!cancelled) {
|
||||
opp.damageAndUpdate(toDmgValue(opp.getMaxHp() / 8), { result: HitResult.INDIRECT });
|
||||
globalScene.phaseManager.queueMessage(
|
||||
i18next.t("abilityTriggers:badDreams", { pokemonName: getPokemonNameWithAffix(opp) }),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6899,7 +6947,8 @@ export class IgnoreTypeImmunityAbAttr extends AbAttr {
|
||||
}
|
||||
|
||||
/**
|
||||
* Ignores the type immunity to Status Effects of the defender if the defender is of a certain type
|
||||
* Attribute to ignore type-based immunities to Status Effect if the defender is of a certain type.
|
||||
* Used by {@linkcode Abilities.CORROSION}.
|
||||
*/
|
||||
export class IgnoreTypeStatusEffectImmunityAbAttr extends AbAttr {
|
||||
private statusEffect: StatusEffect[];
|
||||
|
@ -22,6 +22,8 @@ import { MoveId } from "#enums/move-id";
|
||||
import { ArenaTagSide } from "#enums/arena-tag-side";
|
||||
import { MoveUseMode } from "#enums/move-use-mode";
|
||||
|
||||
// TODO: Add a class for tags that explicitly REQUIRE a source move (as currently we have a lot of bangs)
|
||||
|
||||
export abstract class ArenaTag {
|
||||
constructor(
|
||||
public tagType: ArenaTagType,
|
||||
@ -50,8 +52,17 @@ export abstract class ArenaTag {
|
||||
|
||||
onOverlap(_arena: Arena, _source: Pokemon | null): void {}
|
||||
|
||||
/**
|
||||
* Trigger this {@linkcode ArenaTag}'s effect, reducing its duration as applicable.
|
||||
* Will ignore durations of all tags with durations `<=0`.
|
||||
* @param _arena - The {@linkcode Arena} at the moment the tag is being lapsed.
|
||||
* Unused by default but can be used by sub-classes.
|
||||
* @returns `true` if this tag should be kept; `false` if it should be removed.
|
||||
*/
|
||||
lapse(_arena: Arena): boolean {
|
||||
return this.turnCount < 1 || !!--this.turnCount;
|
||||
// TODO: Rather than treating negative duration tags as being indefinite,
|
||||
// make all duration based classes inherit from their own sub-class
|
||||
return this.turnCount < 1 || --this.turnCount > 0;
|
||||
}
|
||||
|
||||
getMoveName(): string | null {
|
||||
|
@ -76,10 +76,13 @@ export class BattlerTag {
|
||||
|
||||
/**
|
||||
* Tick down this {@linkcode BattlerTag}'s duration.
|
||||
* @returns `true` if the tag should be kept (`turnCount > 0`)
|
||||
* @param _pokemon - The {@linkcode Pokemon} whom this tag belongs to.
|
||||
* Unused by default but can be used by super classes.
|
||||
* @param _lapseType - The {@linkcode BattlerTagLapseType} being lapsed.
|
||||
* Unused by default but can be used by super classes.
|
||||
* @returns `true` if the tag should be kept (`turnCount` > 0`)
|
||||
*/
|
||||
lapse(_pokemon: Pokemon, _lapseType: BattlerTagLapseType): boolean {
|
||||
// TODO: Maybe flip this (return `true` if tag needs removal)
|
||||
return --this.turnCount > 0;
|
||||
}
|
||||
|
||||
@ -125,7 +128,7 @@ export interface TerrainBattlerTag {
|
||||
|
||||
/**
|
||||
* Base class for tags that restrict the usage of moves. This effect is generally referred to as "disabling" a move
|
||||
* in-game. This is not to be confused with {@linkcode MoveId.DISABLE}.
|
||||
* in-game (not to be confused with {@linkcode MoveId.DISABLE}).
|
||||
*
|
||||
* Descendants can override {@linkcode isMoveRestricted} to restrict moves that
|
||||
* match a condition. A restricted move gets cancelled before it is used.
|
||||
|
@ -169,8 +169,8 @@ export default abstract class Move implements Localizable {
|
||||
|
||||
/**
|
||||
* Get all move attributes that match `attrType`
|
||||
* @param attrType any attribute that extends {@linkcode MoveAttr}
|
||||
* @returns Array of attributes that match `attrType`, Empty Array if none match.
|
||||
* @param attrType - The constructor of a {@linkcode MoveAttr} to check.
|
||||
* @returns An array containing all attributes matching `attrType`, or an empty array if none match.
|
||||
*/
|
||||
getAttrs<T extends MoveAttrString>(attrType: T): (MoveAttrMap[T])[] {
|
||||
const targetAttr = MoveAttrs[attrType];
|
||||
@ -182,8 +182,8 @@ export default abstract class Move implements Localizable {
|
||||
|
||||
/**
|
||||
* Check if a move has an attribute that matches `attrType`
|
||||
* @param attrType any attribute that extends {@linkcode MoveAttr}
|
||||
* @returns true if the move has attribute `attrType`
|
||||
* @param attrType - The constructor of a {@linkcode MoveAttr}
|
||||
* @returns Whether this move has an attribute matching `attrType`
|
||||
*/
|
||||
hasAttr(attrType: MoveAttrString): boolean {
|
||||
const targetAttr = MoveAttrs[attrType];
|
||||
@ -195,23 +195,25 @@ export default abstract class Move implements Localizable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes as input a boolean function and returns the first MoveAttr in attrs that matches true
|
||||
* @param attrPredicate
|
||||
* @returns the first {@linkcode MoveAttr} element in attrs that makes the input function return true
|
||||
* Find the first attribute that matches a given predicate function.
|
||||
* @param attrPredicate - The predicate function to search `MoveAttr`s by.
|
||||
* @returns The first {@linkcode MoveAttr} for which `attrPredicate` returns `true`.
|
||||
*/
|
||||
findAttr(attrPredicate: (attr: MoveAttr) => boolean): MoveAttr {
|
||||
return this.attrs.find(attrPredicate)!; // TODO: is the bang correct?
|
||||
// TODO: Remove bang and make return type `MoveAttr | undefined`,
|
||||
// as well as add overload for functions of type `x is T`
|
||||
return this.attrs.find(attrPredicate)!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new MoveAttr to the move (appends to the attr array)
|
||||
* if the MoveAttr also comes with a condition, also adds that to the conditions array: {@linkcode MoveCondition}
|
||||
* @param AttrType {@linkcode MoveAttr} the constructor of a MoveAttr class
|
||||
* @param args the args needed to instantiate a the given class
|
||||
* @returns the called object {@linkcode Move}
|
||||
* Adds a new MoveAttr to this move (appends to the attr array).
|
||||
* If the MoveAttr also comes with a condition, it is added to its {@linkcode MoveCondition} array.
|
||||
* @param attrType - The {@linkcode MoveAttr} to add
|
||||
* @param args - The arguments needed to instantiate the given class
|
||||
* @returns `this`
|
||||
*/
|
||||
attr<T extends Constructor<MoveAttr>>(AttrType: T, ...args: ConstructorParameters<T>): this {
|
||||
const attr = new AttrType(...args);
|
||||
attr<T extends Constructor<MoveAttr>>(attrType: T, ...args: ConstructorParameters<T>): this {
|
||||
const attr = new attrType(...args);
|
||||
this.attrs.push(attr);
|
||||
let attrCondition = attr.getCondition();
|
||||
if (attrCondition) {
|
||||
@ -225,11 +227,13 @@ export default abstract class Move implements Localizable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new MoveAttr to the move (appends to the attr array)
|
||||
* if the MoveAttr also comes with a condition, also adds that to the conditions array: {@linkcode MoveCondition}
|
||||
* Almost identical to {@link attr}, except you are passing in a MoveAttr object, instead of a constructor and it's arguments
|
||||
* @param attrAdd {@linkcode MoveAttr} the attribute to add
|
||||
* @returns the called object {@linkcode Move}
|
||||
* Adds a new MoveAttr to this move (appends to the attr array).
|
||||
* If the MoveAttr also comes with a condition, it is added to its {@linkcode MoveCondition} array.
|
||||
*
|
||||
* Similar to {@linkcode attr}, except this takes an already instantiated {@linkcode MoveAttr} object
|
||||
* as opposed to a constructor and its arguments.
|
||||
* @param attrAdd - The {@linkcode MoveAttr} to add
|
||||
* @returns `this`
|
||||
*/
|
||||
addAttr(attrAdd: MoveAttr): this {
|
||||
this.attrs.push(attrAdd);
|
||||
@ -246,8 +250,8 @@ export default abstract class Move implements Localizable {
|
||||
|
||||
/**
|
||||
* Sets the move target of this move
|
||||
* @param moveTarget {@linkcode MoveTarget} the move target to set
|
||||
* @returns the called object {@linkcode Move}
|
||||
* @param moveTarget - The {@linkcode MoveTarget} to set
|
||||
* @returns `this`
|
||||
*/
|
||||
target(moveTarget: MoveTarget): this {
|
||||
this.moveTarget = moveTarget;
|
||||
@ -255,13 +259,13 @@ export default abstract class Move implements Localizable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter function that returns if this Move has a MoveFlag
|
||||
* @param flag {@linkcode MoveFlags} to check
|
||||
* @returns boolean
|
||||
* Getter function that returns if this Move has a given MoveFlag.
|
||||
* @param flag - The {@linkcode MoveFlags} to check
|
||||
* @returns Whether this Move has the specified flag.
|
||||
*/
|
||||
hasFlag(flag: MoveFlags): boolean {
|
||||
// internally it is taking the bitwise AND (MoveFlags are represented as bit-shifts) and returning False if result is 0 and true otherwise
|
||||
return !!(this.flags & flag);
|
||||
// Flags are internally represented as bitmasks, so we check by taking the bitwise AND.
|
||||
return (this.flags & flag) !== MoveFlags.NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -306,12 +310,12 @@ export default abstract class Move implements Localizable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the move is immune to certain types.
|
||||
* Checks if the target is immune to this Move's type.
|
||||
* Currently looks at cases of Grass types with powder moves and Dark types with moves affected by Prankster.
|
||||
* @param {Pokemon} user the source of this move
|
||||
* @param {Pokemon} target the target of this move
|
||||
* @param {PokemonType} type the type of the move's target
|
||||
* @returns boolean
|
||||
* @param user - The {@linkcode Pokemon} using the move
|
||||
* @param target - The {@linkcode Pokemon} targeted by the move
|
||||
* @param type - The {@linkcode PokemonType} of the move
|
||||
* @returns Whether the move is blocked by the target's type
|
||||
*/
|
||||
isTypeImmune(user: Pokemon, target: Pokemon, type: PokemonType): boolean {
|
||||
if (this.moveTarget === MoveTarget.USER) {
|
||||
@ -335,8 +339,8 @@ export default abstract class Move implements Localizable {
|
||||
|
||||
/**
|
||||
* Checks if the move would hit its target's Substitute instead of the target itself.
|
||||
* @param user The {@linkcode Pokemon} using this move
|
||||
* @param target The {@linkcode Pokemon} targeted by this move
|
||||
* @param user - The {@linkcode Pokemon} using this move
|
||||
* @param target - The {@linkcode Pokemon} targeted by this move
|
||||
* @returns `true` if the move can bypass the target's Substitute; `false` otherwise.
|
||||
*/
|
||||
hitsSubstitute(user: Pokemon, target?: Pokemon): boolean {
|
||||
@ -355,13 +359,14 @@ export default abstract class Move implements Localizable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a move condition to the move
|
||||
* @param condition {@linkcode MoveCondition} or {@linkcode MoveConditionFunc}, appends to conditions array a new MoveCondition object
|
||||
* @returns the called object {@linkcode Move}
|
||||
* Adds a condition to this move (in addition to any provided by its prior {@linkcode MoveAttr}s).
|
||||
* The move will fail upon use if at least 1 of its conditions is not met.
|
||||
* @param condition - The {@linkcode MoveCondition} or {@linkcode MoveConditionFunc} to add to the conditions array.
|
||||
* @returns `this`
|
||||
*/
|
||||
condition(condition: MoveCondition | MoveConditionFunc): this {
|
||||
if (typeof condition === "function") {
|
||||
condition = new MoveCondition(condition as MoveConditionFunc);
|
||||
condition = new MoveCondition(condition);
|
||||
}
|
||||
this.conditions.push(condition);
|
||||
|
||||
@ -369,16 +374,22 @@ export default abstract class Move implements Localizable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal dev flag for documenting edge cases. When using this, please document the known edge case.
|
||||
* @returns the called object {@linkcode Move}
|
||||
* Mark a move as having one or more edge cases.
|
||||
* The move may lack certain niche interactions with other moves/abilities,
|
||||
* but still functions as intended in most cases.
|
||||
*
|
||||
* When using this, **make sure to document the edge case** (or else this becomes pointless).
|
||||
* @returns `this`
|
||||
*/
|
||||
edgeCase(): this {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the move as "partial": appends texts to the move name
|
||||
* @returns the called object {@linkcode Move}
|
||||
* Mark this move as partially implemented.
|
||||
* Partial moves are expected to have some core functionality implemented, but may lack
|
||||
* certain notable features or interactions with other moves or abilities.
|
||||
* @returns `this`
|
||||
*/
|
||||
partial(): this {
|
||||
this.nameAppend += " (P)";
|
||||
@ -386,8 +397,10 @@ export default abstract class Move implements Localizable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the move as "unimplemented": appends texts to the move name
|
||||
* @returns the called object {@linkcode Move}
|
||||
* Mark this move as unimplemented.
|
||||
* Unimplemented moves are ones which have _none_ of their basic functionality enabled,
|
||||
* and cannot be used.
|
||||
* @returns `this`
|
||||
*/
|
||||
unimplemented(): this {
|
||||
this.nameAppend += " (N)";
|
||||
@ -959,10 +972,8 @@ export class AttackMove extends Move {
|
||||
constructor(id: MoveId, type: PokemonType, category: MoveCategory, power: number, accuracy: number, pp: number, chance: number, priority: number, generation: number) {
|
||||
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;
|
||||
*/
|
||||
// > All damaging Fire-type moves can... thaw a frozen target, regardless of whether or not they have a chance to burn.
|
||||
// - https://bulbapedia.bulbagarden.net/wiki/Freeze_(status_condition)
|
||||
if (this.type === PokemonType.FIRE) {
|
||||
this.addAttr(new HealStatusEffectAttr(false, StatusEffect.FREEZE));
|
||||
}
|
||||
@ -2567,9 +2578,12 @@ export class PsychoShiftEffectAttr extends MoveEffectAttr {
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the effect of Psycho Shift to its target
|
||||
* Psycho Shift takes the user's status effect and passes it onto the target. The user is then healed after the move has been successfully executed.
|
||||
* @returns `true` if Psycho Shift's effect is able to be applied to the target
|
||||
* Applies the effect of {@linkcode Moves.PSYCHO_SHIFT} to its target.
|
||||
* Psycho Shift takes the user's status effect and passes it onto the target.
|
||||
* The user is then healed after the move has been successfully executed.
|
||||
* @param user - The {@linkcode Pokemon} using the move
|
||||
* @param target - The {@linkcode Pokemon} targeted by the move.
|
||||
* @returns - Whether the effect was successfully applied to the target.
|
||||
*/
|
||||
apply(user: Pokemon, target: Pokemon, _move: Move, _args: any[]): boolean {
|
||||
const statusToApply: StatusEffect | undefined = user.status?.effect ?? (user.hasAbility(AbilityId.COMATOSE) ? StatusEffect.SLEEP : undefined);
|
||||
@ -2901,6 +2915,12 @@ export class HealStatusEffectAttr extends MoveEffectAttr {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attribute to add the {@linkcode BattlerTagType.BYPASS_SLEEP | BYPASS_SLEEP Battler Tag} for 1 turn to the user before move use.
|
||||
* Used by {@linkcode Moves.SNORE} and {@linkcode Moves.SLEEP_TALK}.
|
||||
*/
|
||||
// TODO: Should this use a battler tag?
|
||||
// TODO: Give this `userSleptOrComatoseCondition` by default
|
||||
export class BypassSleepAttr extends MoveAttr {
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
if (user.status?.effect === StatusEffect.SLEEP) {
|
||||
@ -2918,7 +2938,7 @@ export class BypassSleepAttr extends MoveAttr {
|
||||
* @param move
|
||||
*/
|
||||
getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number {
|
||||
return user.status && user.status.effect === StatusEffect.SLEEP ? 200 : -10;
|
||||
return user.status?.effect === StatusEffect.SLEEP ? 200 : -10;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5436,7 +5456,10 @@ export class NoEffectAttr extends MoveAttr {
|
||||
}
|
||||
}
|
||||
|
||||
const crashDamageFunc = (user: Pokemon, move: Move) => {
|
||||
/**
|
||||
* Function to deal Crash Damage (1/2 max hp) to the user on apply.
|
||||
*/
|
||||
const crashDamageFunc: UserMoveConditionFunc = (user: Pokemon, move: Move) => {
|
||||
const cancelled = new BooleanHolder(false);
|
||||
applyAbAttrs("BlockNonDirectDamageAbAttr", user, cancelled);
|
||||
if (cancelled.value) {
|
||||
@ -7075,7 +7098,8 @@ export class CopyMoveAttr extends CallMoveAttr {
|
||||
/**
|
||||
* Attribute used for moves that cause the target to repeat their last used move.
|
||||
*
|
||||
* Used for [Instruct](https://bulbapedia.bulbagarden.net/wiki/Instruct_(move)).
|
||||
* Used by {@linkcode Moves.INSTRUCT | Instruct}.
|
||||
* @see [Instruct on Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Instruct_(move))
|
||||
*/
|
||||
export class RepeatMoveAttr extends MoveEffectAttr {
|
||||
private movesetMove: PokemonMove;
|
||||
|
@ -36,13 +36,13 @@ export class PokemonMove {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the move can be selected or performed by a Pokemon, without consideration for the move's targets.
|
||||
* Checks whether this move can be selected/performed by a Pokemon, without consideration for the move's targets.
|
||||
* The move is unusable if it is out of PP, restricted by an effect, or unimplemented.
|
||||
*
|
||||
* @param pokemon - {@linkcode Pokemon} that would be using this move
|
||||
* @param ignorePp - If `true`, skips the PP check
|
||||
* @param ignoreRestrictionTags - If `true`, skips the check for move restriction tags (see {@link MoveRestrictionBattlerTag})
|
||||
* @returns `true` if the move can be selected and used by the Pokemon, otherwise `false`.
|
||||
* @param pokemon - The {@linkcode Pokemon} attempting to use this move
|
||||
* @param ignorePp - Whether to ignore checking if the move is out of PP; default `false`
|
||||
* @param ignoreRestrictionTags - Whether to skip checks for {@linkcode MoveRestrictionBattlerTag}s; default `false`
|
||||
* @returns Whether this {@linkcode PokemonMove} can be selected by this Pokemon.
|
||||
*/
|
||||
isUsable(pokemon: Pokemon, ignorePp = false, ignoreRestrictionTags = false): boolean {
|
||||
// TODO: Add Sky Drop's 1 turn stall
|
||||
|
@ -403,12 +403,12 @@ export async function applyModifierTypeToPlayerPokemon(
|
||||
// Check if the Pokemon has max stacks of that item already
|
||||
const modifier = modType.newModifier(pokemon);
|
||||
const existing = globalScene.findModifier(
|
||||
m =>
|
||||
(m): m is PokemonHeldItemModifier =>
|
||||
m instanceof PokemonHeldItemModifier &&
|
||||
m.type.id === modType.id &&
|
||||
m.pokemonId === pokemon.id &&
|
||||
m.matchType(modifier),
|
||||
) as PokemonHeldItemModifier;
|
||||
) as PokemonHeldItemModifier | undefined;
|
||||
|
||||
// At max stacks
|
||||
if (existing && existing.getStackCount() >= existing.getMaxStackCount()) {
|
||||
|
@ -1,3 +1,7 @@
|
||||
/**
|
||||
* A list of possible flags that various moves may have.
|
||||
* Represented internally as a bitmask.
|
||||
*/
|
||||
export enum MoveFlags {
|
||||
NONE = 0,
|
||||
MAKES_CONTACT = 1 << 0,
|
||||
|
@ -1,3 +1,7 @@
|
||||
/**
|
||||
* The index of a given Pokemon on-field.
|
||||
* Used as an index into `globalScene.getField`, as well as for most target-specifying effects.
|
||||
*/
|
||||
export enum BattlerIndex {
|
||||
ATTACKER = -1,
|
||||
PLAYER,
|
||||
|
@ -391,7 +391,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
this.ivs = ivs || getIvsFromId(this.id);
|
||||
|
||||
if (this.gender === undefined) {
|
||||
this.generateGender();
|
||||
this.gender = this.species.generateGender();
|
||||
}
|
||||
|
||||
if (this.formIndex === undefined) {
|
||||
@ -453,7 +453,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param useIllusion - Whether we want the fake name or the real name of the Pokemon (for Illusion ability).
|
||||
* Return the name that will be displayed when this Pokemon is sent out into battle.
|
||||
* @param useIllusion - Whether to consider this Pokemon's illusion if present; default `true`
|
||||
* @returns The name to render for this {@linkcode Pokemon}.
|
||||
*/
|
||||
getNameToRender(useIllusion = true) {
|
||||
const name: string =
|
||||
@ -462,7 +464,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
!useIllusion && this.summonData.illusion ? this.summonData.illusion.basePokemon.nickname : this.nickname;
|
||||
try {
|
||||
if (nickname) {
|
||||
return decodeURIComponent(escape(atob(nickname)));
|
||||
return decodeURIComponent(escape(atob(nickname))); // TODO: Remove `atob` and `escape`... eventually...
|
||||
}
|
||||
return name;
|
||||
} catch (err) {
|
||||
@ -471,11 +473,13 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
}
|
||||
|
||||
getPokeball(useIllusion = false) {
|
||||
if (useIllusion) {
|
||||
return this.summonData.illusion?.pokeball ?? this.pokeball;
|
||||
}
|
||||
return this.pokeball;
|
||||
/**
|
||||
* Return this Pokemon's {@linkcode PokeballType}.
|
||||
* @param useIllusion - Whether to consider this Pokemon's illusion if present; default `true`
|
||||
* @returns The {@linkcode PokeballType} that will be shown when this Pokemon is sent out into battle.
|
||||
*/
|
||||
getPokeball(useIllusion = false): PokeballType {
|
||||
return useIllusion && this.summonData.illusion ? this.summonData.illusion.pokeball : this.pokeball;
|
||||
}
|
||||
|
||||
init(): void {
|
||||
@ -532,17 +536,17 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
|
||||
/**
|
||||
* Checks if a pokemon is fainted (ie: its `hp <= 0`).
|
||||
* It's usually better to call {@linkcode isAllowedInBattle()}
|
||||
* @param checkStatus `true` to also check that the pokemon's status is {@linkcode StatusEffect.FAINT}
|
||||
* @returns `true` if the pokemon is fainted
|
||||
* Usually should not be called directly in favor of calling {@linkcode isAllowedInBattle()}.
|
||||
* @param checkStatus - Whether to also check that the pokemon's status is {@linkcode StatusEffect.FAINT}; default `false`
|
||||
* @returns Whether this Pokemon is fainted, as described above.
|
||||
*/
|
||||
public isFainted(checkStatus = false): boolean {
|
||||
return this.hp <= 0 && (!checkStatus || this.status?.effect === StatusEffect.FAINT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this pokemon is both not fainted and allowed to be in battle based on currently active challenges.
|
||||
* @returns {boolean} `true` if pokemon is allowed in battle
|
||||
* Check if this pokemon is both not fainted and allowed to be used based on currently active challenges.
|
||||
* @returns Whether this Pokemon is allowed to partake in battle.
|
||||
*/
|
||||
public isAllowedInBattle(): boolean {
|
||||
return !this.isFainted() && this.isAllowedInChallenge();
|
||||
@ -550,8 +554,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
|
||||
/**
|
||||
* Check if this pokemon is allowed based on any active challenges.
|
||||
* It's usually better to call {@linkcode isAllowedInBattle()}
|
||||
* @returns {boolean} `true` if pokemon is allowed in battle
|
||||
* Usually should not be called directly in favor of consulting {@linkcode isAllowedInBattle()}.
|
||||
* @returns Whether this Pokemon is allowed under the current challenge conditions.
|
||||
*/
|
||||
public isAllowedInChallenge(): boolean {
|
||||
const challengeAllowed = new BooleanHolder(true);
|
||||
@ -561,8 +565,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
|
||||
/**
|
||||
* Checks if this {@linkcode Pokemon} is allowed in battle (ie: not fainted, and allowed under any active challenges).
|
||||
* @param onField `true` to also check if the pokemon is currently on the field; default `false`
|
||||
* @returns `true` if the pokemon is "active", as described above.
|
||||
* @param onField - Whether to also check if the pokemon is currently on the field; default `false`
|
||||
* @returns Whether this pokemon is considered "active", as described above.
|
||||
* Returns `false` if there is no active {@linkcode BattleScene} or the pokemon is disallowed.
|
||||
*/
|
||||
public isActive(onField = false): boolean {
|
||||
@ -717,7 +721,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
abstract getBattlerIndex(): BattlerIndex;
|
||||
|
||||
/**
|
||||
* @param useIllusion - Whether we want the illusion or not.
|
||||
* Load all assets needed for this Pokemon's use in battle
|
||||
* @param ignoreOverride - Whether to ignore overrides caused by {@linkcode Moves.TRANSFORM | Transform}; default `true`
|
||||
* @param useIllusion - Whether to consider this pokemon's active illusion; default `false`
|
||||
* @returns A promise that resolves once all the corresponding assets have been loaded.
|
||||
*/
|
||||
async loadAssets(ignoreOverride = true, useIllusion = false): Promise<void> {
|
||||
/** Promises that are loading assets and can be run concurrently. */
|
||||
@ -846,11 +853,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to process variant sprite.
|
||||
*
|
||||
* @param cacheKey the cache key for the variant color sprite
|
||||
* @param useExpSprite should the experimental sprite be used
|
||||
* @param battleSpritePath the filename of the sprite
|
||||
* Attempt to process variant sprite color caches.
|
||||
* @param cacheKey - the cache key for the variant color sprite
|
||||
* @param useExpSprite - Whether experimental sprites should be used if present
|
||||
* @param battleSpritePath - the filename of the sprite
|
||||
*/
|
||||
async populateVariantColorCache(cacheKey: string, useExpSprite: boolean, battleSpritePath: string) {
|
||||
const spritePath = `./images/pokemon/variant/${useExpSprite ? "exp/" : ""}${battleSpritePath}.json`;
|
||||
@ -897,7 +903,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
return this.fusionSpecies.forms[this.fusionFormIndex].formKey;
|
||||
}
|
||||
|
||||
getSpriteAtlasPath(ignoreOverride?: boolean): string {
|
||||
// TODO: Add more documentation for all these attributes.
|
||||
// They may be all similar, but what each one actually _does_ is quite unclear at first glance
|
||||
|
||||
getSpriteAtlasPath(ignoreOverride = false): string {
|
||||
const spriteId = this.getSpriteId(ignoreOverride).replace(/\_{2}/g, "/");
|
||||
return `${/_[1-3]$/.test(spriteId) ? "variant/" : ""}${spriteId}`;
|
||||
}
|
||||
@ -1041,10 +1050,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this {@linkcode Pokemon}'s {@linkcode PokemonSpeciesForm}.
|
||||
* @param ignoreOverride - Whether to ignore overridden species from {@linkcode MoveId.TRANSFORM}, default `false`.
|
||||
* This overrides `useIllusion` if `true`.
|
||||
* @param useIllusion - `true` to use the speciesForm of the illusion; default `false`.
|
||||
* Return this Pokemon's {@linkcode PokemonSpeciesForm | SpeciesForm}.
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode Moves.TRANSFORM | Transform}; default `false`
|
||||
* and overrides `useIllusion`.
|
||||
* @param useIllusion - Whether to consider this Pokemon's illusion if present; default `false`.
|
||||
* @returns This Pokemon's {@linkcode PokemonSpeciesForm}.
|
||||
*/
|
||||
getSpeciesForm(ignoreOverride = false, useIllusion = false): PokemonSpeciesForm {
|
||||
if (!ignoreOverride && this.summonData.speciesForm) {
|
||||
@ -1063,9 +1073,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {boolean} useIllusion - Whether we want the fusionSpeciesForm of the illusion or not.
|
||||
* Return the {@linkcode PokemonSpeciesForm | SpeciesForm} of this Pokemon's fusion counterpart.
|
||||
* @param ignoreOverride - Whether to ignore species overrides caused by {@linkcode Moves.TRANSFORM | Transform}; default `false`
|
||||
* @param useIllusion - Whether to consider the species of this Pokemon's illusion; default `false`.
|
||||
* @returns The {@linkcode PokemonSpeciesForm} of this Pokemon's fusion counterpart.
|
||||
*/
|
||||
getFusionSpeciesForm(ignoreOverride?: boolean, useIllusion = false): PokemonSpeciesForm {
|
||||
getFusionSpeciesForm(ignoreOverride = false, useIllusion = false): PokemonSpeciesForm {
|
||||
const fusionSpecies: PokemonSpecies =
|
||||
useIllusion && this.summonData.illusion ? this.summonData.illusion.fusionSpecies! : this.fusionSpecies!;
|
||||
const fusionFormIndex =
|
||||
@ -1393,16 +1406,17 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
* Calculates and retrieves the final value of a stat considering any held
|
||||
* items, move effects, opponent abilities, and whether there was a critical
|
||||
* hit.
|
||||
* @param stat the desired {@linkcode EffectiveStat}
|
||||
* @param opponent the target {@linkcode Pokemon}
|
||||
* @param move the {@linkcode Move} being used
|
||||
* @param ignoreAbility determines whether this Pokemon's abilities should be ignored during the stat calculation
|
||||
* @param ignoreOppAbility during an attack, determines whether the opposing Pokemon's abilities should be ignored during the stat calculation.
|
||||
* @param ignoreAllyAbility during an attack, determines whether the ally Pokemon's abilities should be ignored during the stat calculation.
|
||||
* @param isCritical determines whether a critical hit has occurred or not (`false` by default)
|
||||
* @param simulated if `true`, nullifies any effects that produce any changes to game state from triggering
|
||||
* @param ignoreHeldItems determines whether this Pokemon's held items should be ignored during the stat calculation, default `false`
|
||||
* @returns the final in-battle value of a stat
|
||||
* @param stat - The desired {@linkcode EffectiveStat | Stat} to check.
|
||||
* @param opponent - The {@linkcode Pokemon} being targeted, if applicable.
|
||||
* @param move - The {@linkcode Move} being used, if any. Used to check ability ignoring effects and similar.
|
||||
* @param ignoreAbility - Whether to ignore ability effects of the user; default `false`.
|
||||
* @param ignoreOppAbility - Whether to ignore ability effects of the target; default `false`.
|
||||
* @param ignoreAllyAbility - Whether to ignore ability effects of the user's allies; default `false`.
|
||||
* @param isCritical - Whether a critical hit has occurred or not; default `false`.
|
||||
* If `true`, will nullify offensive stat drops or defensive stat boosts.
|
||||
* @param simulated - Whether to nullify any effects that produce changes to game state during calculations; default `true`
|
||||
* @param ignoreHeldItems - Whether to ignore the user's held items during stat calculation; default `false`.
|
||||
* @returns The final in-battle value for the given stat.
|
||||
*/
|
||||
getEffectiveStat(
|
||||
stat: EffectiveStat,
|
||||
@ -1423,6 +1437,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
// The Ruin abilities here are never ignored, but they reveal themselves on summon anyway
|
||||
const fieldApplied = new BooleanHolder(false);
|
||||
for (const pokemon of globalScene.getField(true)) {
|
||||
// TODO: remove `canStack` toggle from abilitiy as breaking out renders it useless
|
||||
applyFieldStatMultiplierAbAttrs(
|
||||
"FieldMultiplyStatAbAttr",
|
||||
pokemon,
|
||||
@ -1436,6 +1451,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ignoreAbility) {
|
||||
applyStatMultiplierAbAttrs("StatMultiplierAbAttr", this, stat, statValue, simulated);
|
||||
}
|
||||
@ -1628,9 +1644,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param useIllusion - Whether we want the fake or real gender (illusion ability).
|
||||
* Return this Pokemon's {@linkcode Gender}.
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode Moves.TRANSFORM | Transform}; default `false`
|
||||
* @param useIllusion - Whether to consider this pokemon's illusion if present; default `false`
|
||||
* @returns the {@linkcode Gender} of this {@linkcode Pokemon}.
|
||||
*/
|
||||
getGender(ignoreOverride?: boolean, useIllusion = false): Gender {
|
||||
getGender(ignoreOverride = false, useIllusion = false): Gender {
|
||||
if (useIllusion && this.summonData.illusion) {
|
||||
return this.summonData.illusion.gender;
|
||||
}
|
||||
@ -1641,9 +1660,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param useIllusion - Whether we want the fake or real gender (illusion ability).
|
||||
* Return this Pokemon's fusion's {@linkcode Gender}.
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode Moves.TRANSFORM | Transform}; default `false`
|
||||
* @param useIllusion - Whether to consider this pokemon's illusion if present; default `false`
|
||||
* @returns The {@linkcode Gender} of this {@linkcode Pokemon}'s fusion.
|
||||
*/
|
||||
getFusionGender(ignoreOverride?: boolean, useIllusion = false): Gender {
|
||||
getFusionGender(ignoreOverride = false, useIllusion = false): Gender {
|
||||
if (useIllusion && this.summonData.illusion?.fusionGender) {
|
||||
return this.summonData.illusion.fusionGender;
|
||||
}
|
||||
@ -1654,15 +1676,19 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param useIllusion - Whether we want the fake or real shininess (illusion ability).
|
||||
* Check whether this Pokemon is shiny.
|
||||
* @param useIllusion - Whether to consider this pokemon's illusion if present; default `false`
|
||||
* @returns Whether this Pokemon is shiny at least once.
|
||||
*/
|
||||
isShiny(useIllusion = false): boolean {
|
||||
if (!useIllusion && this.summonData.illusion) {
|
||||
return !!(
|
||||
return (
|
||||
this.summonData.illusion.basePokemon?.shiny ||
|
||||
(this.summonData.illusion.fusionSpecies && this.summonData.illusion.basePokemon?.fusionShiny)
|
||||
(this.summonData.illusion.fusionSpecies && this.summonData.illusion.basePokemon?.fusionShiny) ||
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
return this.shiny || (this.isFusion(useIllusion) && this.fusionShiny);
|
||||
}
|
||||
|
||||
@ -1681,9 +1707,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param useIllusion - Whether we want the fake or real shininess (illusion ability).
|
||||
* @returns `true` if the {@linkcode Pokemon} is shiny and the fusion is shiny as well, `false` otherwise
|
||||
* Check whether this Pokemon is doubly shiny (both normal and fusion are shiny).
|
||||
* @param useIllusion - Whether to consider this pokemon's illusion if present; default `false`
|
||||
* @returns Whether this pokemon's base and fusion counterparts are both shiny.
|
||||
*/
|
||||
isDoubleShiny(useIllusion = false): boolean {
|
||||
if (!useIllusion && this.summonData.illusion?.basePokemon) {
|
||||
@ -1693,11 +1719,15 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
this.summonData.illusion.basePokemon.fusionShiny
|
||||
);
|
||||
}
|
||||
|
||||
return this.isFusion(useIllusion) && this.shiny && this.fusionShiny;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param useIllusion - Whether we want the fake or real variant (illusion ability).
|
||||
* Return this Pokemon's {@linkcode Variant | shiny variant}.
|
||||
* Only meaningful if this pokemon is actually shiny.
|
||||
* @param useIllusion - Whether to consider this pokemon's illusion if present; default `false`
|
||||
* @returns The shiny variant of this Pokemon.
|
||||
*/
|
||||
getVariant(useIllusion = false): Variant {
|
||||
if (!useIllusion && this.summonData.illusion) {
|
||||
@ -1705,9 +1735,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
? this.summonData.illusion.basePokemon!.variant
|
||||
: (Math.max(this.variant, this.fusionVariant) as Variant);
|
||||
}
|
||||
|
||||
return !this.isFusion(true) ? this.variant : (Math.max(this.variant, this.fusionVariant) as Variant);
|
||||
}
|
||||
|
||||
// TODO: Clarify how this differs from {@linkcode getVariant}
|
||||
getBaseVariant(doubleShiny: boolean): Variant {
|
||||
if (doubleShiny) {
|
||||
return this.summonData.illusion?.basePokemon?.variant ?? this.variant;
|
||||
@ -1715,19 +1747,28 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
return this.getVariant();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return this pokemon's overall luck value, based on its shininess (1 pt per variant lvl).
|
||||
* @returns The luck value of this Pokemon.
|
||||
*/
|
||||
getLuck(): number {
|
||||
return this.luck + (this.isFusion() ? this.fusionLuck : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this {@linkcode Pokemon} is currently fused with anything.
|
||||
* @param useIllusion - Whether to consider this pokemon's illusion if present; default `false`
|
||||
* @returns Whether this Pokemon is currently fused with another species.
|
||||
*/
|
||||
isFusion(useIllusion = false): boolean {
|
||||
if (useIllusion && this.summonData.illusion) {
|
||||
return !!this.summonData.illusion.fusionSpecies;
|
||||
}
|
||||
return !!this.fusionSpecies;
|
||||
return useIllusion && this.summonData.illusion ? !!this.summonData.illusion.fusionSpecies : !!this.fusionSpecies;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param useIllusion - Whether we want the fake name or the real name of the Pokemon (for Illusion ability).
|
||||
* Return this {@linkcode Pokemon}'s name.
|
||||
* @param useIllusion - Whether to consider this pokemon's illusion if present; default `false`
|
||||
* @returns This Pokemon's name.
|
||||
* @see {@linkcode getNameToRender} - gets this Pokemon's display name.
|
||||
*/
|
||||
getName(useIllusion = false): string {
|
||||
return !useIllusion && this.summonData.illusion?.basePokemon
|
||||
@ -1736,19 +1777,19 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the {@linkcode Pokemon} has a fusion with the specified {@linkcode SpeciesId}.
|
||||
* @param species the pokemon {@linkcode SpeciesId} to check
|
||||
* @returns `true` if the {@linkcode Pokemon} has a fusion with the specified {@linkcode SpeciesId}, `false` otherwise
|
||||
* Check whether this {@linkcode Pokemon} has a fusion with the specified {@linkcode SpeciesId}.
|
||||
* @param species - The {@linkcode SpeciesId} to check against.
|
||||
* @returns Whether this Pokemon is currently fused with the specified {@linkcode SpeciesId}.
|
||||
*/
|
||||
hasFusionSpecies(species: SpeciesId): boolean {
|
||||
return this.fusionSpecies?.speciesId === species;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the {@linkcode Pokemon} has is the specified {@linkcode SpeciesId} or is fused with it.
|
||||
* @param species the pokemon {@linkcode SpeciesId} to check
|
||||
* @param formKey If provided, requires the species to be in that form
|
||||
* @returns `true` if the pokemon is the species or is fused with it, `false` otherwise
|
||||
* Check whether this {@linkcode Pokemon} either is or is fused with the given {@linkcode SpeciesId}.
|
||||
* @param species - The {@linkcode SpeciesId} to check against.
|
||||
* @param formKey - If provided, will require the species to be in the given form.
|
||||
* @returns Whether this Pokemon has this species as either its base or fusion counterpart.
|
||||
*/
|
||||
hasSpecies(species: SpeciesId, formKey?: string): boolean {
|
||||
if (isNullOrUndefined(formKey)) {
|
||||
@ -1763,7 +1804,13 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
|
||||
abstract isBoss(): boolean;
|
||||
|
||||
getMoveset(ignoreOverride?: boolean): PokemonMove[] {
|
||||
/**
|
||||
* Return all the {@linkcode PokemonMove}s that make up this Pokemon's moveset.
|
||||
* Takes into account player/enemy moveset overrides (which will also override PP count).
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode Moves.TRANSFORM | Transform}; default `false`
|
||||
* @returns An array of {@linkcode PokemonMove}, as described above.
|
||||
*/
|
||||
getMoveset(ignoreOverride = false): PokemonMove[] {
|
||||
const ret = !ignoreOverride && this.summonData.moveset ? this.summonData.moveset : this.moveset;
|
||||
|
||||
// Overrides moveset based on arrays specified in overrides.ts
|
||||
@ -1785,11 +1832,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks which egg moves have been unlocked for the {@linkcode Pokemon} based
|
||||
* on the species it was met at or by the first {@linkcode Pokemon} in its evolution
|
||||
* Check which egg moves have been unlocked for this {@linkcode Pokemon}.
|
||||
* Looks at either the species it was met at or the first {@linkcode Species} in its evolution
|
||||
* line that can act as a starter and provides those egg moves.
|
||||
* @returns an array of {@linkcode MoveId}, the length of which is determined by how many
|
||||
* egg moves are unlocked for that species.
|
||||
* @returns An array of all {@linkcode MoveId}s that are egg moves and unlocked for this Pokemon.
|
||||
*/
|
||||
getUnlockedEggMoves(): MoveId[] {
|
||||
const moves: MoveId[] = [];
|
||||
@ -1806,13 +1852,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all possible learnable level moves for the {@linkcode Pokemon},
|
||||
* Get all possible learnable level moves for the {@linkcode Pokemon},
|
||||
* excluding any moves already known.
|
||||
*
|
||||
* Available egg moves are only included if the {@linkcode Pokemon} was
|
||||
* in the starting party of the run and if Fresh Start is not active.
|
||||
* @returns an array of {@linkcode MoveId}, the length of which is determined
|
||||
* by how many learnable moves there are for the {@linkcode Pokemon}.
|
||||
* @returns An array of {@linkcode MoveId}s, as described above.
|
||||
*/
|
||||
public getLearnableLevelMoves(): MoveId[] {
|
||||
let levelMoves = this.getLevelMoves(1, true, false, true).map(lm => lm[1]);
|
||||
@ -1827,12 +1872,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the types of a pokemon
|
||||
* @param includeTeraType - `true` to include tera-formed type; Default: `false`
|
||||
* @param forDefend - `true` if the pokemon is defending from an attack; Default: `false`
|
||||
* @param ignoreOverride - If `true`, ignore ability changing effects; Default: `false`
|
||||
* @param useIllusion - `true` to return the types of the illusion instead of the actual types; Default: `false`
|
||||
* @returns array of {@linkcode PokemonType}
|
||||
* Evaluate and return this Pokemon's typing.
|
||||
* @param includeTeraType - Whether to use this Pokemon's tera type if Terastallized; default `false`
|
||||
* @param forDefend - Whether this Pokemon is currently receiving an attack; default `false`
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode Moves.TRANSFORM | Transform}; default `false`
|
||||
* @param useIllusion - Whether to consider this Pokemon's illusion if present; default `false`
|
||||
* @returns An array of {@linkcode PokemonType}s corresponding to this Pokemon's typing (real or percieved).
|
||||
*/
|
||||
public getTypes(
|
||||
includeTeraType = false,
|
||||
@ -1928,7 +1973,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
// remove UNKNOWN if other types are present
|
||||
if (types.length > 1 && types.includes(PokemonType.UNKNOWN)) {
|
||||
if (types.length > 1) {
|
||||
const index = types.indexOf(PokemonType.UNKNOWN);
|
||||
if (index !== -1) {
|
||||
types.splice(index, 1);
|
||||
@ -1949,24 +1994,25 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the pokemon's typing includes the specified type
|
||||
* @param type - {@linkcode PokemonType} to check
|
||||
* @param includeTeraType - `true` to include tera-formed type; Default: `true`
|
||||
* @param forDefend - `true` if the pokemon is defending from an attack; Default: `false`
|
||||
* @param ignoreOverride - If `true`, ignore ability changing effects; Default: `false`
|
||||
* @returns `true` if the Pokemon's type matches
|
||||
* Check if this Pokemon's typing includes the specified type.
|
||||
* @param type - The {@linkcode PokemonType} to check
|
||||
* @param includeTeraType - Whether to use this Pokemon's tera type if Terastallized; default `false`
|
||||
* @param forDefend - Whether this Pokemon is currently receiving an attack; default `false`
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode Moves.TRANSFORM | Transform}; default `false`
|
||||
* @returns Whether this Pokemon is of the specified type.
|
||||
*/
|
||||
public isOfType(type: PokemonType, includeTeraType = true, forDefend = false, ignoreOverride = false): boolean {
|
||||
return this.getTypes(includeTeraType, forDefend, ignoreOverride).some(t => t === type);
|
||||
return this.getTypes(includeTeraType, forDefend, ignoreOverride).includes(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the non-passive ability of the pokemon. This accounts for fusions and ability changing effects.
|
||||
* This should rarely be called, most of the time {@linkcode hasAbility} or {@linkcode hasAbilityWithAttr} are better used as
|
||||
* those check both the passive and non-passive abilities and account for ability suppression.
|
||||
* @see {@linkcode hasAbility} {@linkcode hasAbilityWithAttr} Intended ways to check abilities in most cases
|
||||
* @param ignoreOverride - If `true`, ignore ability changing effects; Default: `false`
|
||||
* @returns The non-passive {@linkcode Ability} of the pokemon
|
||||
* Get this Pokemon's non-passive {@linkcode Ability}, factoring in fusions, overrides and ability-changing effects.
|
||||
|
||||
* Should rarely be called directly in favor of {@linkcode hasAbility} or {@linkcode hasAbilityWithAttr},
|
||||
* both of which check both ability slots and account for suppression.
|
||||
* @see {@linkcode hasAbility} and {@linkcode hasAbilityWithAttr} are the intended ways to check abilities in most cases
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode Moves.TRANSFORM | Transform}; default `false`
|
||||
* @returns The non-passive {@linkcode Ability} of this Pokemon.
|
||||
*/
|
||||
public getAbility(ignoreOverride = false): Ability {
|
||||
if (!ignoreOverride && this.summonData.ability) {
|
||||
@ -2143,13 +2189,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a pokemon has the specified ability and it's in effect. Accounts for all the various
|
||||
* effects which can affect whether an ability will be present or in effect, and both passive and
|
||||
* non-passive. This is the primary way to check whether a pokemon has a particular ability.
|
||||
* @param ability The ability to check for
|
||||
* Check whether a pokemon has the specified ability in effect, either as a normal or passive ability.
|
||||
* Accounts for all the various effects which can disable or modify abilities.
|
||||
* @param ability - The {@linkcode Abilities | Ability} to check for
|
||||
* @param canApply - Whether to check if the ability is currently active; default `true`
|
||||
* @param ignoreOverride Whether to ignore ability changing effects; default `false`
|
||||
* @returns `true` if the ability is present and active
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode Moves.TRANSFORM | Transform}; default `false`
|
||||
* @returns Whether this {@linkcode Pokemon} has the given ability
|
||||
*/
|
||||
public hasAbility(ability: AbilityId, canApply = true, ignoreOverride = false): boolean {
|
||||
if (this.getAbility(ignoreOverride).id === ability && (!canApply || this.canApplyAbility())) {
|
||||
@ -2159,14 +2204,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a pokemon has an ability with the specified attribute and it's in effect.
|
||||
* Accounts for all the various effects which can affect whether an ability will be present or
|
||||
* in effect, and both passive and non-passive. This is one of the two primary ways to check
|
||||
* whether a pokemon has a particular ability.
|
||||
* @param attrType The {@link AbAttr | ability attribute} to check for
|
||||
* Check whether this pokemon has an ability with the specified attribute in effect, either as a normal or passive ability.
|
||||
* Accounts for all the various effects which can disable or modify abilities.
|
||||
* @param attrType - The {@linkcode AbAttr | attribute} to check for
|
||||
* @param canApply - Whether to check if the ability is currently active; default `true`
|
||||
* @param ignoreOverride Whether to ignore ability changing effects; default `false`
|
||||
* @returns `true` if an ability with the given {@linkcode AbAttr} is present and active
|
||||
* @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode Moves.TRANSFORM | Transform}; default `false`
|
||||
* @returns Whether this Pokemon has an ability with the given {@linkcode AbAttr}.
|
||||
*/
|
||||
public hasAbilityWithAttr(attrType: AbAttrString, canApply = true, ignoreOverride = false): boolean {
|
||||
if ((!canApply || this.canApplyAbility()) && this.getAbility(ignoreOverride).hasAttr(attrType)) {
|
||||
@ -2188,7 +2231,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
const autotomizedTag = this.getTag(AutotomizedTag);
|
||||
let weightRemoved = 0;
|
||||
if (!isNullOrUndefined(autotomizedTag)) {
|
||||
weightRemoved = 100 * autotomizedTag!.autotomizeCount;
|
||||
weightRemoved = 100 * autotomizedTag.autotomizeCount;
|
||||
}
|
||||
const minWeight = 0.1;
|
||||
const weight = new NumberHolder(this.species.weight - weightRemoved);
|
||||
@ -3323,10 +3366,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
*
|
||||
* Note that this does not apply to evasion or accuracy
|
||||
* @see {@linkcode getAccuracyMultiplier}
|
||||
* @param stat the desired {@linkcode EffectiveStat}
|
||||
* @param opponent the target {@linkcode Pokemon}
|
||||
* @param move the {@linkcode Move} being used
|
||||
* @param ignoreOppAbility determines whether the effects of the opponent's abilities (i.e. Unaware) should be ignored (`false` by default)
|
||||
* @param stat - The {@linkcode EffectiveStat} to calculate
|
||||
* @param opponent - The {@linkcode Pokemon} being targeted
|
||||
* @param move - The {@linkcode Move} being used
|
||||
* @param ignoreOppAbility determines whether the effects of the opponent's abilities (i.e. Unaware) should be ignored (`false` by default)
|
||||
* @param isCritical determines whether a critical hit has occurred or not (`false` by default)
|
||||
* @param simulated determines whether effects are applied without altering game state (`true` by default)
|
||||
* @param ignoreHeldItems determines whether this Pokemon's held items should be ignored during the stat calculation, default `false`
|
||||
@ -4277,6 +4320,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return this Pokemon's move history.
|
||||
* Entries are sorted in order of OLDEST to NEWEST
|
||||
* @returns An array of {@linkcode TurnMove}, as described above.
|
||||
* @see {@linkcode getLastXMoves}
|
||||
*/
|
||||
public getMoveHistory(): TurnMove[] {
|
||||
return this.summonData.moveHistory;
|
||||
}
|
||||
@ -4290,19 +4339,20 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of the most recent move entries in this Pokemon's move history.
|
||||
* The retrieved move entries are sorted in order from NEWEST to OLDEST.
|
||||
* @param moveCount The number of move entries to retrieve.
|
||||
* If negative, retrieve the Pokemon's entire move history (equivalent to reversing the output of {@linkcode getMoveHistory()}).
|
||||
* Default is `1`.
|
||||
* @returns A list of {@linkcode TurnMove}, as specified above.
|
||||
* Return a list of the most recent move entries in this {@linkcode Pokemon}'s move history.
|
||||
* The retrieved move entries are sorted in order from **NEWEST** to **OLDEST**.
|
||||
* @param moveCount - The maximum number of move entries to retrieve.
|
||||
* If negative, retrieves the Pokemon's entire move history (equivalent to reversing the output of {@linkcode getMoveHistory()}).
|
||||
* Default is `1`.
|
||||
* @returns An array of {@linkcode TurnMove}, as specified above.
|
||||
*/
|
||||
// TODO: Update documentation in dancer PR to mention "getLastNonVirtualMove"
|
||||
getLastXMoves(moveCount = 1): TurnMove[] {
|
||||
const moveHistory = this.getMoveHistory();
|
||||
if (moveCount >= 0) {
|
||||
if (moveCount > 0) {
|
||||
return moveHistory.slice(Math.max(moveHistory.length - moveCount, 0)).reverse();
|
||||
}
|
||||
return moveHistory.slice(0).reverse();
|
||||
return moveHistory.slice().reverse();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -5435,13 +5485,15 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduces one of this Pokemon's held item stacks by 1, and removes the item if applicable.
|
||||
* Reduces one of this Pokemon's held item stacks by 1, removing it if applicable.
|
||||
* Does nothing if this Pokemon is somehow not the owner of the held item.
|
||||
* @param heldItem The item stack to be reduced by 1.
|
||||
* @param forBattle If `false`, do not trigger in-battle effects (such as Unburden) from losing the item. For example, set this to `false` if the Pokemon is giving away the held item for a Mystery Encounter. Default is `true`.
|
||||
* @returns `true` if the item was removed successfully, `false` otherwise.
|
||||
* @param heldItem - The item stack to be reduced.
|
||||
* @param forBattle - Whether to trigger in-battle effects (such as Unburden) after losing the item. Default: `true`
|
||||
* Should be `false` for all item loss occurring outside of battle (MEs, etc.).
|
||||
* @returns Whether the item was removed successfully.
|
||||
*/
|
||||
public loseHeldItem(heldItem: PokemonHeldItemModifier, forBattle = true): boolean {
|
||||
// TODO: What does a -1 pokemon id mean?
|
||||
if (heldItem.pokemonId !== -1 && heldItem.pokemonId !== this.id) {
|
||||
return false;
|
||||
}
|
||||
@ -6113,22 +6165,23 @@ export class EnemyPokemon extends Pokemon {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the pokemons boss status. If true initializes the boss segments either from the arguments
|
||||
* or through the the Scene.getEncounterBossSegments function
|
||||
* Set this {@linkcode EnemyPokemon}'s boss status.
|
||||
*
|
||||
* @param boss if the pokemon is a boss
|
||||
* @param bossSegments amount of boss segments (health-bar segments)
|
||||
* @param boss - Whether this pokemon should be a boss; default `true`
|
||||
* @param bossSegments - Optional amount amount of health bar segments to give;
|
||||
* will be generated by {@linkcode BattleScene.getEncounterBossSegments} if omitted
|
||||
*/
|
||||
setBoss(boss = true, bossSegments = 0): void {
|
||||
if (boss) {
|
||||
this.bossSegments =
|
||||
bossSegments ||
|
||||
globalScene.getEncounterBossSegments(globalScene.currentBattle.waveIndex, this.level, this.species, true);
|
||||
this.bossSegmentIndex = this.bossSegments - 1;
|
||||
} else {
|
||||
setBoss(boss = true, bossSegments?: number): void {
|
||||
if (!boss) {
|
||||
this.bossSegments = 0;
|
||||
this.bossSegmentIndex = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
this.bossSegments =
|
||||
bossSegments ??
|
||||
globalScene.getEncounterBossSegments(globalScene.currentBattle.waveIndex, this.level, this.species, true);
|
||||
this.bossSegmentIndex = this.bossSegments - 1;
|
||||
}
|
||||
|
||||
generateAndPopulateMoveset(formIndex?: number): void {
|
||||
@ -6896,8 +6949,9 @@ export class PokemonTurnData {
|
||||
/** How many times the current move should hit the target(s) */
|
||||
public hitCount = 0;
|
||||
/**
|
||||
* - `-1` = Calculate how many hits are left
|
||||
* - `0` = Move is finished
|
||||
* - `-1`: Calculate how many hits are left
|
||||
* - `0`: Move is finished
|
||||
* - Anything `>0`: Number of hits left to check (barring early interrupts)
|
||||
*/
|
||||
public hitsLeft = -1;
|
||||
public totalDamageDealt = 0;
|
||||
|
@ -53,25 +53,11 @@ const iconOverflowIndex = 24;
|
||||
export const modifierSortFunc = (a: Modifier, b: Modifier): number => {
|
||||
const itemNameMatch = a.type.name.localeCompare(b.type.name);
|
||||
const typeNameMatch = a.constructor.name.localeCompare(b.constructor.name);
|
||||
const aId = a instanceof PokemonHeldItemModifier && a.pokemonId ? a.pokemonId : 4294967295;
|
||||
const bId = b instanceof PokemonHeldItemModifier && b.pokemonId ? b.pokemonId : 4294967295;
|
||||
const aId = a instanceof PokemonHeldItemModifier ? a.pokemonId : -1;
|
||||
const bId = b instanceof PokemonHeldItemModifier ? b.pokemonId : -1;
|
||||
|
||||
//First sort by pokemonID
|
||||
if (aId < bId) {
|
||||
return 1;
|
||||
}
|
||||
if (aId > bId) {
|
||||
return -1;
|
||||
}
|
||||
if (aId === bId) {
|
||||
//Then sort by item type
|
||||
if (typeNameMatch === 0) {
|
||||
return itemNameMatch;
|
||||
//Finally sort by item name
|
||||
}
|
||||
return typeNameMatch;
|
||||
}
|
||||
return 0;
|
||||
// First sort by pokemon ID, then by item type and then name
|
||||
return aId - bId || typeNameMatch || itemNameMatch;
|
||||
};
|
||||
|
||||
export class ModifierBar extends Phaser.GameObjects.Container {
|
||||
@ -758,7 +744,7 @@ export abstract class PokemonHeldItemModifier extends PersistentModifier {
|
||||
return 1;
|
||||
}
|
||||
|
||||
getMaxStackCount(forThreshold?: boolean): number {
|
||||
getMaxStackCount(forThreshold = false): number {
|
||||
const pokemon = this.getPokemon();
|
||||
if (!pokemon) {
|
||||
return 0;
|
||||
@ -2815,6 +2801,7 @@ export class PokemonMultiHitModifier extends PokemonHeldItemModifier {
|
||||
damageMultiplier.value *= 1 - 0.25 * this.getStackCount();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pokemon.turnData.hitCount - pokemon.turnData.hitsLeft !== this.getStackCount() + 1) {
|
||||
// Deal 25% damage for each remaining Multi Lens hit
|
||||
damageMultiplier.value *= 0.25;
|
||||
|
@ -87,7 +87,7 @@ export class CommandPhase extends FieldPhase {
|
||||
}
|
||||
|
||||
// Checks if the Pokemon is under the effects of Encore. If so, Encore can end early if the encored move has no more PP.
|
||||
const encoreTag = this.getPokemon().getTag(BattlerTagType.ENCORE) as EncoreTag;
|
||||
const encoreTag = this.getPokemon().getTag(BattlerTagType.ENCORE) as EncoreTag | undefined;
|
||||
if (encoreTag) {
|
||||
this.getPokemon().lapseTag(BattlerTagType.ENCORE);
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ export class SelectStarterPhase extends Phase {
|
||||
|
||||
/**
|
||||
* Initialize starters before starting the first battle
|
||||
* @param starters {@linkcode Pokemon} with which to start the first battle
|
||||
* @param starters - Array of {@linkcode Starter}s with which to start the battle
|
||||
*/
|
||||
initBattle(starters: Starter[]) {
|
||||
const party = globalScene.getPlayerParty();
|
||||
|
@ -204,7 +204,7 @@ export class TitlePhase extends Phase {
|
||||
globalScene.eventManager.startEventChallenges();
|
||||
|
||||
globalScene.setSeed(seed);
|
||||
globalScene.resetSeed(0);
|
||||
globalScene.resetSeed();
|
||||
|
||||
globalScene.money = globalScene.gameMode.getStartingMoney();
|
||||
|
||||
@ -283,6 +283,7 @@ export class TitlePhase extends Phase {
|
||||
console.error("Failed to load daily run:\n", err);
|
||||
});
|
||||
} else {
|
||||
// Grab first 10 chars of ISO date format (YYYY-MM-DD) and convert to base64
|
||||
let seed: string = btoa(new Date().toISOString().substring(0, 10));
|
||||
if (!isNullOrUndefined(Overrides.DAILY_RUN_SEED_OVERRIDE)) {
|
||||
seed = Overrides.DAILY_RUN_SEED_OVERRIDE;
|
||||
|
@ -1248,7 +1248,8 @@ export class GameData {
|
||||
// (or prevent them from being null)
|
||||
// If the value is able to *not exist*, it should say so in the code
|
||||
const sessionData = JSON.parse(dataStr, (k: string, v: any) => {
|
||||
// TODO: Add pre-parse migrate scripts
|
||||
// TODO: Move this to occur _after_ migrate scripts (and refactor all non-assignment duties into migrate scripts)
|
||||
// This should ideally be just a giant assign block
|
||||
switch (k) {
|
||||
case "party":
|
||||
case "enemyParty": {
|
||||
|
@ -277,7 +277,7 @@ export default class FightUiHandler extends UiHandler implements InfoToggle {
|
||||
|
||||
const ppPercentLeft = pp / maxPP;
|
||||
|
||||
//** Determines TextStyle according to percentage of PP remaining */
|
||||
/** Determines TextStyle according to percentage of PP remaining */
|
||||
let ppColorStyle = TextStyle.MOVE_PP_FULL;
|
||||
if (ppPercentLeft > 0.25 && ppPercentLeft <= 0.5) {
|
||||
ppColorStyle = TextStyle.MOVE_PP_HALF_FULL;
|
||||
@ -287,7 +287,7 @@ export default class FightUiHandler extends UiHandler implements InfoToggle {
|
||||
ppColorStyle = TextStyle.MOVE_PP_EMPTY;
|
||||
}
|
||||
|
||||
//** Changes the text color and shadow according to the determined TextStyle */
|
||||
/** Changes the text color and shadow according to the determined TextStyle */
|
||||
this.ppText.setColor(this.getTextColor(ppColorStyle, false));
|
||||
this.ppText.setShadowColor(this.getTextColor(ppColorStyle, true));
|
||||
this.moveInfoOverlay.show(pokemonMove.getMove());
|
||||
|
Loading…
Reference in New Issue
Block a user