Implemented explosive moves and Damp (#290)
* Implemented explosives * Add Aftermath and Magic Guard interactions * Adjust AI score for Mind Blown/Steel Beampull/301/head
parent
06f6797ece
commit
9f3bef0142
|
@ -869,6 +869,13 @@ export class MoveTypeChangePowerMultiplierAbAttr extends VariableMoveTypeAbAttr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class FieldPreventExplosiveMovesAbAttr extends AbAttr {
|
||||||
|
apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise<boolean> {
|
||||||
|
cancelled.value = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class MoveTypeChangeAttr extends PreAttackAbAttr {
|
export class MoveTypeChangeAttr extends PreAttackAbAttr {
|
||||||
private newType: Type;
|
private newType: Type;
|
||||||
private powerMultiplier: number;
|
private powerMultiplier: number;
|
||||||
|
@ -2057,6 +2064,11 @@ export class PostFaintContactDamageAbAttr extends PostFaintAbAttr {
|
||||||
|
|
||||||
applyPostFaint(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
applyPostFaint(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
|
||||||
if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) {
|
if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) {
|
||||||
|
const cancelled = new Utils.BooleanHolder(false);
|
||||||
|
pokemon.scene.getField(true).map(p=>applyAbAttrs(FieldPreventExplosiveMovesAbAttr, p, cancelled))
|
||||||
|
if (cancelled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
attacker.damageAndUpdate(Math.ceil(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER);
|
attacker.damageAndUpdate(Math.ceil(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2468,8 +2480,8 @@ export function initAbilities() {
|
||||||
.attr(BlockOneHitKOAbAttr)
|
.attr(BlockOneHitKOAbAttr)
|
||||||
.ignorable(),
|
.ignorable(),
|
||||||
new Ability(Abilities.DAMP, 3)
|
new Ability(Abilities.DAMP, 3)
|
||||||
.ignorable()
|
.attr(FieldPreventExplosiveMovesAbAttr)
|
||||||
.unimplemented(),
|
.ignorable(),
|
||||||
new Ability(Abilities.LIMBER, 3)
|
new Ability(Abilities.LIMBER, 3)
|
||||||
.attr(StatusEffectImmunityAbAttr, StatusEffect.PARALYSIS)
|
.attr(StatusEffectImmunityAbAttr, StatusEffect.PARALYSIS)
|
||||||
.ignorable(),
|
.ignorable(),
|
||||||
|
|
|
@ -12,7 +12,7 @@ import * as Utils from "../utils";
|
||||||
import { WeatherType } from "./weather";
|
import { WeatherType } from "./weather";
|
||||||
import { ArenaTagSide, ArenaTrapTag } from "./arena-tag";
|
import { ArenaTagSide, ArenaTrapTag } from "./arena-tag";
|
||||||
import { ArenaTagType } from "./enums/arena-tag-type";
|
import { ArenaTagType } from "./enums/arena-tag-type";
|
||||||
import { UnswappableAbilityAbAttr, UncopiableAbilityAbAttr, UnsuppressableAbilityAbAttr, NoTransformAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPreSwitchOutAbAttrs, PreSwitchOutAbAttr, applyPostDefendAbAttrs, PostDefendContactApplyStatusEffectAbAttr, MoveAbilityBypassAbAttr, ReverseDrainAbAttr } from "./ability";
|
import { UnswappableAbilityAbAttr, UncopiableAbilityAbAttr, UnsuppressableAbilityAbAttr, NoTransformAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPreSwitchOutAbAttrs, PreSwitchOutAbAttr, applyPostDefendAbAttrs, PostDefendContactApplyStatusEffectAbAttr, MoveAbilityBypassAbAttr, ReverseDrainAbAttr, FieldPreventExplosiveMovesAbAttr } from "./ability";
|
||||||
import { Abilities } from "./enums/abilities";
|
import { Abilities } from "./enums/abilities";
|
||||||
import { allAbilities } from './ability';
|
import { allAbilities } from './ability';
|
||||||
import { PokemonHeldItemModifier } from "../modifier/modifier";
|
import { PokemonHeldItemModifier } from "../modifier/modifier";
|
||||||
|
@ -725,6 +725,40 @@ export class SacrificialAttr extends MoveEffectAttr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class HalfSacrificialAttr extends MoveEffectAttr {
|
||||||
|
constructor() {
|
||||||
|
super(true, MoveEffectTrigger.PRE_APPLY);
|
||||||
|
}
|
||||||
|
|
||||||
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
|
if (!super.apply(user, target, move, args))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const cancelled = new Utils.BooleanHolder(false);
|
||||||
|
applyAbAttrs(BlockNonDirectDamageAbAttr, user, cancelled);
|
||||||
|
if (!cancelled){
|
||||||
|
user.damageAndUpdate(Math.ceil(user.getMaxHp()/2), HitResult.OTHER, false, true, true);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer {
|
||||||
|
if (user.isBoss())
|
||||||
|
return -10;
|
||||||
|
return Math.ceil(((1 - user.getHpRatio()/2) * 10 - 10) * (target.getAttackTypeEffectiveness(move.type) - 0.5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ExplosiveAttr extends MoveEffectAttr {
|
||||||
|
getCondition(): MoveCondition | MoveConditionFunc {
|
||||||
|
return (user, target, move) =>{
|
||||||
|
const cancelled = new Utils.BooleanHolder(false);
|
||||||
|
user.scene.getField(true).map(p=>applyAbAttrs(FieldPreventExplosiveMovesAbAttr, p, cancelled));
|
||||||
|
return !cancelled.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export enum MultiHitType {
|
export enum MultiHitType {
|
||||||
_2,
|
_2,
|
||||||
_2_TO_5,
|
_2_TO_5,
|
||||||
|
@ -4000,6 +4034,7 @@ export function initMoves() {
|
||||||
.attr(CopyMoveAttr)
|
.attr(CopyMoveAttr)
|
||||||
.ignoresVirtual(),
|
.ignoresVirtual(),
|
||||||
new AttackMove(Moves.SELF_DESTRUCT, Type.NORMAL, MoveCategory.PHYSICAL, 200, 100, 5, -1, 0, 1)
|
new AttackMove(Moves.SELF_DESTRUCT, Type.NORMAL, MoveCategory.PHYSICAL, 200, 100, 5, -1, 0, 1)
|
||||||
|
.attr(ExplosiveAttr)
|
||||||
.attr(SacrificialAttr)
|
.attr(SacrificialAttr)
|
||||||
.makesContact(false)
|
.makesContact(false)
|
||||||
.target(MoveTarget.ALL_NEAR_OTHERS),
|
.target(MoveTarget.ALL_NEAR_OTHERS),
|
||||||
|
@ -4090,6 +4125,7 @@ export function initMoves() {
|
||||||
new AttackMove(Moves.CRABHAMMER, Type.WATER, MoveCategory.PHYSICAL, 100, 90, 10, -1, 0, 1)
|
new AttackMove(Moves.CRABHAMMER, Type.WATER, MoveCategory.PHYSICAL, 100, 90, 10, -1, 0, 1)
|
||||||
.attr(HighCritAttr),
|
.attr(HighCritAttr),
|
||||||
new AttackMove(Moves.EXPLOSION, Type.NORMAL, MoveCategory.PHYSICAL, 250, 100, 5, -1, 0, 1)
|
new AttackMove(Moves.EXPLOSION, Type.NORMAL, MoveCategory.PHYSICAL, 250, 100, 5, -1, 0, 1)
|
||||||
|
.attr(ExplosiveAttr)
|
||||||
.attr(SacrificialAttr)
|
.attr(SacrificialAttr)
|
||||||
.makesContact(false)
|
.makesContact(false)
|
||||||
.target(MoveTarget.ALL_NEAR_OTHERS),
|
.target(MoveTarget.ALL_NEAR_OTHERS),
|
||||||
|
@ -5622,7 +5658,8 @@ export function initMoves() {
|
||||||
.partial(),
|
.partial(),
|
||||||
/* End Unused */
|
/* End Unused */
|
||||||
new AttackMove(Moves.MIND_BLOWN, Type.FIRE, MoveCategory.SPECIAL, 150, 100, 5, -1, 0, 7)
|
new AttackMove(Moves.MIND_BLOWN, Type.FIRE, MoveCategory.SPECIAL, 150, 100, 5, -1, 0, 7)
|
||||||
.attr(RecoilAttr, true, 0.5)
|
.attr(ExplosiveAttr)
|
||||||
|
.attr(HalfSacrificialAttr)
|
||||||
.target(MoveTarget.ALL_NEAR_OTHERS),
|
.target(MoveTarget.ALL_NEAR_OTHERS),
|
||||||
new AttackMove(Moves.PLASMA_FISTS, Type.ELECTRIC, MoveCategory.PHYSICAL, 100, 100, 15, -1, 0, 7)
|
new AttackMove(Moves.PLASMA_FISTS, Type.ELECTRIC, MoveCategory.PHYSICAL, 100, 100, 15, -1, 0, 7)
|
||||||
.punchingMove()
|
.punchingMove()
|
||||||
|
@ -5837,7 +5874,7 @@ export function initMoves() {
|
||||||
new AttackMove(Moves.ETERNABEAM, Type.DRAGON, MoveCategory.SPECIAL, 160, 90, 5, -1, 0, 8)
|
new AttackMove(Moves.ETERNABEAM, Type.DRAGON, MoveCategory.SPECIAL, 160, 90, 5, -1, 0, 8)
|
||||||
.attr(RechargeAttr),
|
.attr(RechargeAttr),
|
||||||
new AttackMove(Moves.STEEL_BEAM, Type.STEEL, MoveCategory.SPECIAL, 140, 95, 5, -1, 0, 8)
|
new AttackMove(Moves.STEEL_BEAM, Type.STEEL, MoveCategory.SPECIAL, 140, 95, 5, -1, 0, 8)
|
||||||
.attr(RecoilAttr, true, 0.5),
|
.attr(HalfSacrificialAttr),
|
||||||
new AttackMove(Moves.EXPANDING_FORCE, Type.PSYCHIC, MoveCategory.SPECIAL, 80, 100, 10, -1, 0, 8)
|
new AttackMove(Moves.EXPANDING_FORCE, Type.PSYCHIC, MoveCategory.SPECIAL, 80, 100, 10, -1, 0, 8)
|
||||||
.partial(),
|
.partial(),
|
||||||
new AttackMove(Moves.STEEL_ROLLER, Type.STEEL, MoveCategory.PHYSICAL, 130, 100, 5, -1, 0, 8)
|
new AttackMove(Moves.STEEL_ROLLER, Type.STEEL, MoveCategory.PHYSICAL, 130, 100, 5, -1, 0, 8)
|
||||||
|
@ -5858,8 +5895,10 @@ export function initMoves() {
|
||||||
.attr(StatusEffectAttr, StatusEffect.POISON)
|
.attr(StatusEffectAttr, StatusEffect.POISON)
|
||||||
.partial(),
|
.partial(),
|
||||||
new AttackMove(Moves.MISTY_EXPLOSION, Type.FAIRY, MoveCategory.SPECIAL, 100, 100, 5, -1, 0, 8)
|
new AttackMove(Moves.MISTY_EXPLOSION, Type.FAIRY, MoveCategory.SPECIAL, 100, 100, 5, -1, 0, 8)
|
||||||
|
.attr(ExplosiveAttr)
|
||||||
|
.attr(SacrificialAttr)
|
||||||
.target(MoveTarget.ALL_NEAR_OTHERS)
|
.target(MoveTarget.ALL_NEAR_OTHERS)
|
||||||
.partial(),
|
.attr(MovePowerMultiplierAttr, (user, target, move) => user.scene.arena.getTerrainType() === TerrainType.MISTY && user.isGrounded() ? 1.5 : 1),
|
||||||
new AttackMove(Moves.GRASSY_GLIDE, Type.GRASS, MoveCategory.PHYSICAL, 55, 100, 20, -1, 0, 8)
|
new AttackMove(Moves.GRASSY_GLIDE, Type.GRASS, MoveCategory.PHYSICAL, 55, 100, 20, -1, 0, 8)
|
||||||
.partial(),
|
.partial(),
|
||||||
new AttackMove(Moves.RISING_VOLTAGE, Type.ELECTRIC, MoveCategory.SPECIAL, 70, 100, 20, -1, 0, 8)
|
new AttackMove(Moves.RISING_VOLTAGE, Type.ELECTRIC, MoveCategory.SPECIAL, 70, 100, 20, -1, 0, 8)
|
||||||
|
|
|
@ -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 } 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, ExplosiveAttr } from "../data/move";
|
||||||
import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, starterPassiveAbilities } from '../data/pokemon-species';
|
import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, 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';
|
||||||
|
@ -1229,6 +1229,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
if (types.find(t => move.isTypeImmune(t)))
|
if (types.find(t => move.isTypeImmune(t)))
|
||||||
typeMultiplier.value = 0;
|
typeMultiplier.value = 0;
|
||||||
|
|
||||||
|
applyMoveAttrs(ExplosiveAttr, source, null, battlerMove.getMove());
|
||||||
switch (moveCategory) {
|
switch (moveCategory) {
|
||||||
case MoveCategory.PHYSICAL:
|
case MoveCategory.PHYSICAL:
|
||||||
case MoveCategory.SPECIAL:
|
case MoveCategory.SPECIAL:
|
||||||
|
|
Loading…
Reference in New Issue