Implemented moves Reflect, Light Screen and Aurora Veil
parent
37eb5c8eb0
commit
887a4176ab
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue