From 0556e1ad50e4c1b606242561e71861cdf7452748 Mon Sep 17 00:00:00 2001 From: "Amani H." <109637146+xsn34kzx@users.noreply.github.com> Date: Sun, 1 Dec 2024 17:24:47 -0500 Subject: [PATCH] [Balance] Adjust Flame/Toxic Orb Weight Functions (#4954) * [Balance] Adjust Flame/Toxic Orb Weight Functions * Adjust Booleans * Add Documentation * Implement More Granularity * Minor `if` Change --- src/field/pokemon.ts | 15 +++++++-- src/modifier/modifier-type.ts | 62 ++++++++++++++++++++++++++++------- 2 files changed, 63 insertions(+), 14 deletions(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 6aa4bd46a68..accd39e1f94 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -3501,12 +3501,21 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return this.gender !== Gender.GENDERLESS && pokemon.gender === (this.gender === Gender.MALE ? Gender.FEMALE : Gender.MALE); } - canSetStatus(effect: StatusEffect | undefined, quiet: boolean = false, overrideStatus: boolean = false, sourcePokemon: Pokemon | null = null): boolean { + /** + * Checks if a status effect can be applied to the Pokemon. + * + * @param effect The {@linkcode StatusEffect} whose applicability is being checked + * @param quiet Whether in-battle messages should trigger or not + * @param overrideStatus Whether the Pokemon's current status can be overriden + * @param sourcePokemon The Pokemon that is setting the status effect + * @param ignoreField Whether any field effects (weather, terrain, etc.) should be considered + */ + canSetStatus(effect: StatusEffect | undefined, quiet: boolean = false, overrideStatus: boolean = false, sourcePokemon: Pokemon | null = null, ignoreField: boolean = false): boolean { if (effect !== StatusEffect.FAINT) { if (overrideStatus ? this.status?.effect === effect : this.status) { return false; } - if (this.isGrounded() && this.scene.arena.terrain?.terrainType === TerrainType.MISTY) { + if (this.isGrounded() && (!ignoreField && this.scene.arena.terrain?.terrainType === TerrainType.MISTY)) { return false; } } @@ -3556,7 +3565,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } break; case StatusEffect.FREEZE: - if (this.isOfType(Type.ICE) || (this.scene?.arena?.weather?.weatherType && [ WeatherType.SUNNY, WeatherType.HARSH_SUN ].includes(this.scene.arena.weather.weatherType))) { + if (this.isOfType(Type.ICE) || (!ignoreField && (this.scene?.arena?.weather?.weatherType && [ WeatherType.SUNNY, WeatherType.HARSH_SUN ].includes(this.scene.arena.weather.weatherType)))) { return false; } break; diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 04776afc624..57b3ced1813 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -1751,19 +1751,59 @@ const modifierPool: ModifierPool = { || (p.isFusion() && checkedSpecies.includes(p.getFusionSpeciesForm(true).speciesId)))) ? 12 : 0; }, 12), new WeightedModifierType(modifierTypes.TOXIC_ORB, (party: Pokemon[]) => { - const checkedAbilities = [ Abilities.QUICK_FEET, Abilities.GUTS, Abilities.MARVEL_SCALE, Abilities.TOXIC_BOOST, Abilities.POISON_HEAL, Abilities.MAGIC_GUARD ]; - const checkedMoves = [ Moves.FACADE, Moves.TRICK, Moves.FLING, Moves.SWITCHEROO, Moves.PSYCHO_SHIFT ]; - // If a party member doesn't already have one of these two orbs and has one of the above moves or abilities, the orb can appear - return party.some(p => !p.getHeldItems().some(i => i instanceof TurnStatusEffectModifier) - && (checkedAbilities.some(a => p.hasAbility(a, false, true)) - || p.getMoveset(true).some(m => m && checkedMoves.includes(m.moveId)))) ? 10 : 0; + return party.some(p => { + const moveset = p.getMoveset(true).filter(m => !isNullOrUndefined(m)).map(m => m.moveId); + + const canSetStatus = p.canSetStatus(StatusEffect.TOXIC, true, true, null, true); + const isHoldingOrb = p.getHeldItems().some(i => i.type.id === "FLAME_ORB" || i.type.id === "TOXIC_ORB"); + + // Moves that take advantage of obtaining the actual status effect + const hasStatusMoves = [ Moves.FACADE, Moves.PSYCHO_SHIFT ] + .some(m => moveset.includes(m)); + // Moves that take advantage of being able to give the target a status orb + // TODO: Take moves from comment they are implemented + const hasItemMoves = [ /* Moves.TRICK, Moves.FLING, Moves.SWITCHEROO */ ] + .some(m => moveset.includes(m)); + // Abilities that take advantage of obtaining the actual status effect + const hasRelevantAbilities = [ Abilities.QUICK_FEET, Abilities.GUTS, Abilities.MARVEL_SCALE, Abilities.TOXIC_BOOST, Abilities.POISON_HEAL, Abilities.MAGIC_GUARD ] + .some(a => p.hasAbility(a, false, true)); + + if (!isHoldingOrb) { + if (canSetStatus) { + return hasRelevantAbilities || hasStatusMoves; + } else { + return hasItemMoves; + } + } + return false; + }) ? 10 : 0; }, 10), new WeightedModifierType(modifierTypes.FLAME_ORB, (party: Pokemon[]) => { - const checkedAbilities = [ Abilities.QUICK_FEET, Abilities.GUTS, Abilities.MARVEL_SCALE, Abilities.FLARE_BOOST, Abilities.MAGIC_GUARD ]; - const checkedMoves = [ Moves.FACADE, Moves.TRICK, Moves.FLING, Moves.SWITCHEROO, Moves.PSYCHO_SHIFT ]; - // If a party member doesn't already have one of these two orbs and has one of the above moves or abilities, the orb can appear - return party.some(p => !p.getHeldItems().some(i => i instanceof TurnStatusEffectModifier) - && (checkedAbilities.some(a => p.hasAbility(a, false, true)) || p.getMoveset(true).some(m => m && checkedMoves.includes(m.moveId)))) ? 10 : 0; + return party.some(p => { + const moveset = p.getMoveset(true).filter(m => !isNullOrUndefined(m)).map(m => m.moveId); + const canSetStatus = p.canSetStatus(StatusEffect.BURN, true, true, null, true); + const isHoldingOrb = p.getHeldItems().some(i => i.type.id === "FLAME_ORB" || i.type.id === "TOXIC_ORB"); + + // Moves that take advantage of obtaining the actual status effect + const hasStatusMoves = [ Moves.FACADE, Moves.PSYCHO_SHIFT ] + .some(m => moveset.includes(m)); + // Moves that take advantage of being able to give the target a status orb + // TODO: Take moves from comment they are implemented + const hasItemMoves = [ /* Moves.TRICK, Moves.FLING, Moves.SWITCHEROO */ ] + .some(m => moveset.includes(m)); + // Abilities that take advantage of obtaining the actual status effect + const hasRelevantAbilities = [ Abilities.QUICK_FEET, Abilities.GUTS, Abilities.MARVEL_SCALE, Abilities.FLARE_BOOST, Abilities.MAGIC_GUARD ] + .some(a => p.hasAbility(a, false, true)); + + if (!isHoldingOrb) { + if (canSetStatus) { + return hasRelevantAbilities || hasStatusMoves; + } else { + return hasItemMoves; + } + } + return false; + }) ? 10 : 0; }, 10), new WeightedModifierType(modifierTypes.WHITE_HERB, (party: Pokemon[]) => { const checkedAbilities = [ Abilities.WEAK_ARMOR, Abilities.CONTRARY, Abilities.MOODY, Abilities.ANGER_SHELL, Abilities.COMPETITIVE, Abilities.DEFIANT ];