Hydro Steam (#231)
* Hydro Steam, Spirit Shackle, U-turn fix Match formatting to project style Co-authored-by: Samuel H <flashfireex@gmail.com> * Fix Hydro Steam power up in Sun, even harsh sun if type changes * Fix issue with Hydro Steam outside sun * Add comments to IgnoreWeatherTypeDebuffAttr for documentation * Move U-turn fix to another PR --------- Co-authored-by: Samuel H <flashfireex@gmail.com>pull/676/head
parent
2bc1cfb0fc
commit
7219556e77
|
@ -888,6 +888,33 @@ export class SacrificialFullRestoreAttr extends SacrificialAttr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute used for moves which ignore type-based debuffs from weather, namely Hydro Steam.
|
||||||
|
* Called during damage calculation after getting said debuff from getAttackTypeMultiplier in the Pokemon class.
|
||||||
|
*/
|
||||||
|
export class IgnoreWeatherTypeDebuffAttr extends MoveAttr {
|
||||||
|
public weather: WeatherType;
|
||||||
|
constructor(weather: WeatherType){
|
||||||
|
super();
|
||||||
|
this.weather = weather;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Changes the type-based weather modifier if this move's power would be reduced by it
|
||||||
|
* @param user Pokemon that used the move
|
||||||
|
* @param target N/A
|
||||||
|
* @param move Move with this attribute
|
||||||
|
* @param args Utils.NumberHolder for arenaAttackTypeMultiplier
|
||||||
|
* @returns true if the function succeeds
|
||||||
|
*/
|
||||||
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
|
const weatherModifier=args[0] as Utils.NumberHolder;
|
||||||
|
//If the type-based attack power modifier due to weather (e.g. Water moves in Sun) is below 1, set it to 1
|
||||||
|
if (user.scene.arena.weather?.weatherType === this.weather)
|
||||||
|
weatherModifier.value = Math.max(weatherModifier.value, 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export abstract class WeatherHealAttr extends HealAttr {
|
export abstract class WeatherHealAttr extends HealAttr {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(0.5);
|
super(0.5);
|
||||||
|
@ -6666,7 +6693,8 @@ export function initMoves() {
|
||||||
.attr(MovePowerMultiplierAttr, (user, target, move) => user.scene.arena.getTerrainType() === TerrainType.ELECTRIC && user.isGrounded() ? 1.5 : 1)
|
.attr(MovePowerMultiplierAttr, (user, target, move) => user.scene.arena.getTerrainType() === TerrainType.ELECTRIC && user.isGrounded() ? 1.5 : 1)
|
||||||
.slicingMove(),
|
.slicingMove(),
|
||||||
new AttackMove(Moves.HYDRO_STEAM, Type.WATER, MoveCategory.SPECIAL, 80, 100, 15, -1, 0, 9)
|
new AttackMove(Moves.HYDRO_STEAM, Type.WATER, MoveCategory.SPECIAL, 80, 100, 15, -1, 0, 9)
|
||||||
.partial(),
|
.attr(IgnoreWeatherTypeDebuffAttr, WeatherType.SUNNY)
|
||||||
|
.attr(MovePowerMultiplierAttr, (user, target, move) => [WeatherType.SUNNY, WeatherType.HARSH_SUN].includes(user.scene.arena.weather?.weatherType) && !user.scene.arena.weather?.isEffectSuppressed(user.scene) ? 1.5 : 1),
|
||||||
new AttackMove(Moves.RUINATION, Type.DARK, MoveCategory.SPECIAL, -1, 90, 10, -1, 0, 9)
|
new AttackMove(Moves.RUINATION, Type.DARK, MoveCategory.SPECIAL, -1, 90, 10, -1, 0, 9)
|
||||||
.attr(TargetHalfHpDamageAttr),
|
.attr(TargetHalfHpDamageAttr),
|
||||||
new AttackMove(Moves.COLLISION_COURSE, Type.FIGHTING, MoveCategory.PHYSICAL, 100, 100, 5, -1, 0, 9)
|
new AttackMove(Moves.COLLISION_COURSE, Type.FIGHTING, MoveCategory.PHYSICAL, 100, 100, 5, -1, 0, 9)
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { Variant, VariantSet, variantColorCache } from '#app/data/variant';
|
||||||
import { variantData } from '#app/data/variant';
|
import { variantData } from '#app/data/variant';
|
||||||
import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from '../ui/battle-info';
|
import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from '../ui/battle-info';
|
||||||
import { Moves } from "../data/enums/moves";
|
import { Moves } from "../data/enums/moves";
|
||||||
import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, VariablePowerAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, MultiHitAttr, StatusMoveTypeImmunityAttr, MoveTarget, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveTypeAttr, VariableMoveCategoryAttr, CounterDamageAttr } from "../data/move";
|
import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, VariablePowerAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, MultiHitAttr, StatusMoveTypeImmunityAttr, MoveTarget, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveTypeAttr, VariableMoveCategoryAttr, CounterDamageAttr, IgnoreWeatherTypeDebuffAttr } from "../data/move";
|
||||||
import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, getStarterValueFriendshipCap, speciesStarters, starterPassiveAbilities } from '../data/pokemon-species';
|
import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, getStarterValueFriendshipCap, speciesStarters, starterPassiveAbilities } from '../data/pokemon-species';
|
||||||
import * as Utils from '../utils';
|
import * as Utils from '../utils';
|
||||||
import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from '../data/type';
|
import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from '../data/type';
|
||||||
|
@ -1338,7 +1338,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
source.removeTag(typeBoost.tagType);
|
source.removeTag(typeBoost.tagType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const arenaAttackTypeMultiplier = this.scene.arena.getAttackTypeMultiplier(type, source.isGrounded());
|
const arenaAttackTypeMultiplier = new Utils.NumberHolder(this.scene.arena.getAttackTypeMultiplier(type, source.isGrounded()));
|
||||||
|
applyMoveAttrs(IgnoreWeatherTypeDebuffAttr, source, this, move, arenaAttackTypeMultiplier);
|
||||||
if (this.scene.arena.getTerrainType() === TerrainType.GRASSY && this.isGrounded() && type === Type.GROUND && move.moveTarget === MoveTarget.ALL_NEAR_OTHERS)
|
if (this.scene.arena.getTerrainType() === TerrainType.GRASSY && this.isGrounded() && type === Type.GROUND && move.moveTarget === MoveTarget.ALL_NEAR_OTHERS)
|
||||||
power.value /= 2;
|
power.value /= 2;
|
||||||
applyMoveAttrs(VariablePowerAttr, source, this, move, power);
|
applyMoveAttrs(VariablePowerAttr, source, this, move, power);
|
||||||
|
@ -1383,7 +1384,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
if (!isCritical) {
|
if (!isCritical) {
|
||||||
this.scene.arena.applyTagsForSide(WeakenMoveScreenTag, this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY, move.category, this.scene.currentBattle.double, screenMultiplier);
|
this.scene.arena.applyTagsForSide(WeakenMoveScreenTag, this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY, move.category, this.scene.currentBattle.double, screenMultiplier);
|
||||||
}
|
}
|
||||||
const isTypeImmune = (typeMultiplier.value * arenaAttackTypeMultiplier) === 0;
|
const isTypeImmune = (typeMultiplier.value * arenaAttackTypeMultiplier.value) === 0;
|
||||||
const sourceTypes = source.getTypes();
|
const sourceTypes = source.getTypes();
|
||||||
const matchesSourceType = sourceTypes[0] === type || (sourceTypes.length > 1 && sourceTypes[1] === type);
|
const matchesSourceType = sourceTypes[0] === type || (sourceTypes.length > 1 && sourceTypes[1] === type);
|
||||||
let stabMultiplier = new Utils.NumberHolder(1);
|
let stabMultiplier = new Utils.NumberHolder(1);
|
||||||
|
@ -1401,7 +1402,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
applyMoveAttrs(VariableDefAttr, source, this, move, targetDef);
|
applyMoveAttrs(VariableDefAttr, source, this, move, targetDef);
|
||||||
|
|
||||||
if (!isTypeImmune) {
|
if (!isTypeImmune) {
|
||||||
damage.value = Math.ceil(((((2 * source.level / 5 + 2) * power.value * sourceAtk.value / targetDef.value) / 50) + 2) * stabMultiplier.value * typeMultiplier.value * arenaAttackTypeMultiplier * screenMultiplier.value * ((this.scene.randBattleSeedInt(15) + 85) / 100) * criticalMultiplier.value);
|
damage.value = Math.ceil(((((2 * source.level / 5 + 2) * power.value * sourceAtk.value / targetDef.value) / 50) + 2) * stabMultiplier.value * typeMultiplier.value * arenaAttackTypeMultiplier.value * screenMultiplier.value * ((this.scene.randBattleSeedInt(15) + 85) / 100) * criticalMultiplier.value);
|
||||||
if (isPhysical && source.status && source.status.effect === StatusEffect.BURN) {
|
if (isPhysical && source.status && source.status.effect === StatusEffect.BURN) {
|
||||||
const burnDamageReductionCancelled = new Utils.BooleanHolder(false);
|
const burnDamageReductionCancelled = new Utils.BooleanHolder(false);
|
||||||
applyAbAttrs(BypassBurnDamageReductionAbAttr, source, burnDamageReductionCancelled);
|
applyAbAttrs(BypassBurnDamageReductionAbAttr, source, burnDamageReductionCancelled);
|
||||||
|
|
Loading…
Reference in New Issue