Implemented moves Reflect, Light Screen and Aurora Veil

pull/39/head
Jaime 2024-04-05 17:21:17 +02:00 committed by Samuel H
parent 37eb5c8eb0
commit 887a4176ab
4 changed files with 93 additions and 8 deletions

View File

@ -1,7 +1,7 @@
import { Arena } from "../field/arena"; import { Arena } from "../field/arena";
import { Type } from "./type"; import { Type } from "./type";
import * as Utils from "../utils"; import * as Utils from "../utils";
import { allMoves } from "./move"; import { MoveCategory, allMoves } from "./move";
import { getPokemonMessage } from "../messages"; import { getPokemonMessage } from "../messages";
import Pokemon, { HitResult, PokemonMove } from "../field/pokemon"; import Pokemon, { HitResult, PokemonMove } from "../field/pokemon";
import { MoveEffectPhase } from "../phases"; import { MoveEffectPhase } from "../phases";
@ -76,6 +76,75 @@ export class MistTag extends ArenaTag {
} }
} }
export class WeakenMoveScreenTag extends ArenaTag {
constructor(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves, sourceId: integer, side: ArenaTagSide) {
super(tagType, turnCount, sourceMove, sourceId);
}
apply(arena: Arena, args: any[]): boolean {
if ((args[1] as boolean)) {
(args[2] as Utils.NumberHolder).value = 2732/4096;
} else {
(args[2] as Utils.NumberHolder).value = 0.5;
}
return true;
}
}
class ReflectTag extends WeakenMoveScreenTag {
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
super(ArenaTagType.REFLECT, turnCount, Moves.REFLECT, sourceId, side);
}
apply(arena: Arena, args: any[]): boolean {
if ((args[0] as MoveCategory) === MoveCategory.PHYSICAL) {
if ((args[1] as boolean)) {
(args[2] as Utils.NumberHolder).value = 2732/4096;
} else {
(args[2] as Utils.NumberHolder).value = 0.5;
}
return true;
}
return false;
}
onAdd(arena: Arena): void {
arena.scene.queueMessage(`Reflect reduced the damage of physical moves${this.side === ArenaTagSide.PLAYER ? '\non your side' : this.side === ArenaTagSide.ENEMY ? '\non the foe\'s side' : ''}.`);
}
}
class LightScreenTag extends WeakenMoveScreenTag {
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
super(ArenaTagType.LIGHT_SCREEN, turnCount, Moves.LIGHT_SCREEN, sourceId, side);
}
apply(arena: Arena, args: any[]): boolean {
if ((args[0] as MoveCategory) === MoveCategory.SPECIAL) {
if ((args[1] as boolean)) {
(args[2] as Utils.NumberHolder).value = 2732/4096;
} else {
(args[2] as Utils.NumberHolder).value = 0.5;
}
return true;
}
return false;
}
onAdd(arena: Arena): void {
arena.scene.queueMessage(`Light Screen reduced the damage of special moves${this.side === ArenaTagSide.PLAYER ? '\non your side' : this.side === ArenaTagSide.ENEMY ? '\non the foe\'s side' : ''}.`);
}
}
class AuroraVeilTag extends WeakenMoveScreenTag {
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
super(ArenaTagType.AURORA_VEIL, turnCount, Moves.AURORA_VEIL, sourceId, side);
}
onAdd(arena: Arena): void {
arena.scene.queueMessage(`Aurora Veil reduced the damage of moves${this.side === ArenaTagSide.PLAYER ? '\non your side' : this.side === ArenaTagSide.ENEMY ? '\non the foe\'s side' : ''}.`);
}
}
export class WeakenMoveTypeTag extends ArenaTag { export class WeakenMoveTypeTag extends ArenaTag {
private weakenedType: Type; private weakenedType: Type;
@ -378,5 +447,11 @@ export function getArenaTag(tagType: ArenaTagType, turnCount: integer, sourceMov
return new TrickRoomTag(turnCount, sourceId); return new TrickRoomTag(turnCount, sourceId);
case ArenaTagType.GRAVITY: case ArenaTagType.GRAVITY:
return new GravityTag(turnCount); return new GravityTag(turnCount);
case ArenaTagType.REFLECT:
return new ReflectTag(turnCount, sourceId, side);
case ArenaTagType.LIGHT_SCREEN:
return new LightScreenTag(turnCount, sourceId, side);
case ArenaTagType.AURORA_VEIL:
return new AuroraVeilTag(turnCount, sourceId, side);
} }
} }

View File

@ -10,5 +10,8 @@ export enum ArenaTagType {
DOOM_DESIRE = "DOOM_DESIRE", DOOM_DESIRE = "DOOM_DESIRE",
STEALTH_ROCK = "STEALTH_ROCK", STEALTH_ROCK = "STEALTH_ROCK",
TRICK_ROOM = "TRICK_ROOM", TRICK_ROOM = "TRICK_ROOM",
GRAVITY = "GRAVITY" GRAVITY = "GRAVITY",
REFLECT = "REFLECT",
LIGHT_SCREEN = "LIGHT_SCREEN",
AURORA_VEIL = "AURORA_VEIL"
} }

View File

@ -3071,11 +3071,13 @@ export function initMoves() {
.attr(StatChangeAttr, BattleStat.DEF, 1, true), .attr(StatChangeAttr, BattleStat.DEF, 1, true),
new SelfStatusMove(Moves.BARRIER, "Barrier", Type.PSYCHIC, -1, 20, "The user throws up a sturdy wall that sharply raises its Defense stat.", -1, 0, 1) new SelfStatusMove(Moves.BARRIER, "Barrier", Type.PSYCHIC, -1, 20, "The user throws up a sturdy wall that sharply raises its Defense stat.", -1, 0, 1)
.attr(StatChangeAttr, BattleStat.DEF, 2, true), .attr(StatChangeAttr, BattleStat.DEF, 2, true),
new StatusMove(Moves.LIGHT_SCREEN, "Light Screen (N)", Type.PSYCHIC, -1, 30, "A wondrous wall of light is put up to reduce damage from special attacks for five turns.", -1, 0, 1) new StatusMove(Moves.LIGHT_SCREEN, "Light Screen", Type.PSYCHIC, -1, 30, "A wondrous wall of light is put up to reduce damage from special attacks for five turns.", -1, 0, 1)
.attr(AddArenaTagAttr, ArenaTagType.LIGHT_SCREEN, 5, true)
.target(MoveTarget.USER_SIDE), .target(MoveTarget.USER_SIDE),
new StatusMove(Moves.HAZE, "Haze (N)", Type.ICE, -1, 30, "The user creates a haze that eliminates every stat change among all the Pokémon engaged in battle.", -1, 0, 1) new StatusMove(Moves.HAZE, "Haze (N)", Type.ICE, -1, 30, "The user creates a haze that eliminates every stat change among all the Pokémon engaged in battle.", -1, 0, 1)
.target(MoveTarget.BOTH_SIDES), .target(MoveTarget.BOTH_SIDES),
new StatusMove(Moves.REFLECT, "Reflect (N)", Type.PSYCHIC, -1, 20, "A wondrous wall of light is put up to reduce damage from physical attacks for five turns.", -1, 0, 1) new StatusMove(Moves.REFLECT, "Reflect", Type.PSYCHIC, -1, 20, "A wondrous wall of light is put up to reduce damage from physical attacks for five turns.", -1, 0, 1)
.attr(AddArenaTagAttr, ArenaTagType.REFLECT, 5, true)
.target(MoveTarget.USER_SIDE), .target(MoveTarget.USER_SIDE),
new SelfStatusMove(Moves.FOCUS_ENERGY, "Focus Energy", Type.NORMAL, -1, 30, "The user takes a deep breath and focuses so that critical hits land more easily.", -1, 0, 1) new SelfStatusMove(Moves.FOCUS_ENERGY, "Focus Energy", Type.NORMAL, -1, 30, "The user takes a deep breath and focuses so that critical hits land more easily.", -1, 0, 1)
.attr(AddBattlerTagAttr, BattlerTagType.CRIT_BOOST, true, true), .attr(AddBattlerTagAttr, BattlerTagType.CRIT_BOOST, true, true),
@ -4415,8 +4417,9 @@ export function initMoves() {
new AttackMove(Moves.DRAGON_HAMMER, "Dragon Hammer", Type.DRAGON, MoveCategory.PHYSICAL, 90, 100, 15, "The user uses its body like a hammer to attack the target and inflict damage.", -1, 0, 7), new AttackMove(Moves.DRAGON_HAMMER, "Dragon Hammer", Type.DRAGON, MoveCategory.PHYSICAL, 90, 100, 15, "The user uses its body like a hammer to attack the target and inflict damage.", -1, 0, 7),
new AttackMove(Moves.BRUTAL_SWING, "Brutal Swing", Type.DARK, MoveCategory.PHYSICAL, 60, 100, 20, "The user swings its body around violently to inflict damage on everything in its vicinity.", -1, 0, 7) new AttackMove(Moves.BRUTAL_SWING, "Brutal Swing", Type.DARK, MoveCategory.PHYSICAL, 60, 100, 20, "The user swings its body around violently to inflict damage on everything in its vicinity.", -1, 0, 7)
.target(MoveTarget.ALL_NEAR_OTHERS), .target(MoveTarget.ALL_NEAR_OTHERS),
new StatusMove(Moves.AURORA_VEIL, "Aurora Veil (N)", Type.ICE, -1, 20, "This move reduces damage from physical and special moves for five turns. This can be used only in a hailstorm.", -1, 0, 7) new StatusMove(Moves.AURORA_VEIL, "Aurora Veil", Type.ICE, -1, 20, "This move reduces damage from physical and special moves for five turns. This can be used only in a hailstorm.", -1, 0, 7)
.condition((user, target, move) => user.scene.arena.weather?.weatherType === WeatherType.HAIL) .condition((user, target, move) => user.scene.arena.weather?.weatherType === WeatherType.HAIL && !user.scene.arena.weather?.isEffectSuppressed(user.scene))
.attr(AddArenaTagAttr, ArenaTagType.AURORA_VEIL, 5, true)
.target(MoveTarget.USER_SIDE), .target(MoveTarget.USER_SIDE),
/* Unused */ /* Unused */
new AttackMove(Moves.SINISTER_ARROW_RAID, "Sinister Arrow Raid (P)", Type.GHOST, MoveCategory.PHYSICAL, 180, -1, 1, "The user, Decidueye, creates countless arrows using its Z-Power and shoots the target with full force.", -1, 0, 7) new AttackMove(Moves.SINISTER_ARROW_RAID, "Sinister Arrow Raid (P)", Type.GHOST, MoveCategory.PHYSICAL, 180, -1, 1, "The user, Decidueye, creates countless arrows using its Z-Power and shoots the target with full force.", -1, 0, 7)

View File

@ -22,7 +22,7 @@ import { BattlerTagType } from "../data/enums/battler-tag-type";
import { Species } from '../data/enums/species'; import { Species } from '../data/enums/species';
import { WeatherType } from '../data/weather'; import { WeatherType } from '../data/weather';
import { TempBattleStat } from '../data/temp-battle-stat'; import { TempBattleStat } from '../data/temp-battle-stat';
import { WeakenMoveTypeTag } from '../data/arena-tag'; import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from '../data/arena-tag';
import { ArenaTagType } from "../data/enums/arena-tag-type"; import { ArenaTagType } from "../data/enums/arena-tag-type";
import { Biome } from "../data/enums/biome"; import { Biome } from "../data/enums/biome";
import { Abilities, Ability, BattleStatMultiplierAbAttr, BlockCritAbAttr, BypassBurnDamageReductionAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs } from '../data/ability'; import { Abilities, Ability, BattleStatMultiplierAbAttr, BlockCritAbAttr, BypassBurnDamageReductionAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs } from '../data/ability';
@ -1133,6 +1133,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const sourceAtk = new Utils.IntegerHolder(source.getBattleStat(isPhysical ? Stat.ATK : Stat.SPATK, this, null, isCritical)); const sourceAtk = new Utils.IntegerHolder(source.getBattleStat(isPhysical ? Stat.ATK : Stat.SPATK, this, null, isCritical));
const targetDef = new Utils.IntegerHolder(this.getBattleStat(isPhysical ? Stat.DEF : Stat.SPDEF, source, move, isCritical)); const targetDef = new Utils.IntegerHolder(this.getBattleStat(isPhysical ? Stat.DEF : Stat.SPDEF, source, move, isCritical));
const criticalMultiplier = isCritical ? 2 : 1; const criticalMultiplier = isCritical ? 2 : 1;
const screenMultiplier = new Utils.NumberHolder(1);
if (!isCritical) {
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) === 0;
const sourceTypes = source.getTypes(); const sourceTypes = source.getTypes();
const matchesSourceType = sourceTypes[0] === move.type || (sourceTypes.length > 1 && sourceTypes[1] === move.type); const matchesSourceType = sourceTypes[0] === move.type || (sourceTypes.length > 1 && sourceTypes[1] === move.type);
@ -1151,7 +1155,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 * ((this.scene.randBattleSeedInt(15) + 85) / 100)) * criticalMultiplier; 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;
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, this, burnDamageReductionCancelled); applyAbAttrs(BypassBurnDamageReductionAbAttr, this, burnDamageReductionCancelled);