From a240a45318a6ab5ecffafe16f5d74e8ac350e6d5 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Fri, 29 Mar 2024 11:58:22 -0400 Subject: [PATCH] Implement False Swipe and Hold Back moves --- src/data/move.ts | 33 +++++++++++++++++++++++++++++++-- src/field/pokemon.ts | 6 ++++-- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index 04a6fe01c56..55118a1ff6d 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -556,6 +556,33 @@ export class RandomLevelDamageAttr extends FixedDamageAttr { } } +export class ModifiedDamageAttr extends MoveAttr { + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + const initialDamage = args[0] as Utils.IntegerHolder; + initialDamage.value = this.getModifiedDamage(user, target, move, initialDamage.value); + + return true; + } + + getModifiedDamage(user: Pokemon, target: Pokemon, move: Move, damage: integer): integer { + return damage; + } +} + +export class SurviveDamageAttr extends ModifiedDamageAttr { + getModifiedDamage(user: Pokemon, target: Pokemon, move: Move, damage: number): number { + return Math.min(damage, target.hp - 1); + } + + getCondition(): MoveConditionFunc { + return (user, target, move) => target.hp > 1; + } + + getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { + return target.hp > 1 ? 0 : -20; + } +} + export class RecoilAttr extends MoveEffectAttr { private useHp: boolean; private damageRatio: number; @@ -3149,7 +3176,8 @@ export function initMoves() { .attr(StatChangeAttr, BattleStat.ATK, -2), new AttackMove(Moves.ROLLOUT, "Rollout", Type.ROCK, MoveCategory.PHYSICAL, 30, 90, 20, "The user continually rolls into the target over five turns. It becomes more powerful each time it hits.", -1, 0, 2) .attr(ConsecutiveUseDoublePowerAttr, 5, true, true, Moves.DEFENSE_CURL), - new AttackMove(Moves.FALSE_SWIPE, "False Swipe (P)", Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 40, "A restrained attack that prevents the target from fainting. The target is left with at least 1 HP.", -1, 0, 2), + new AttackMove(Moves.FALSE_SWIPE, "False Swipe", Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 40, "A restrained attack that prevents the target from fainting. The target is left with at least 1 HP.", -1, 0, 2) + .attr(SurviveDamageAttr), new StatusMove(Moves.SWAGGER, "Swagger", Type.NORMAL, 85, 15, "The user enrages and confuses the target. However, this also sharply raises the target's Attack stat.", -1, 0, 2) .attr(StatChangeAttr, BattleStat.ATK, 2) .attr(ConfuseAttr), @@ -4084,7 +4112,8 @@ export function initMoves() { .attr(StatChangeAttr, BattleStat.ATK, -1), new AttackMove(Moves.NUZZLE, "Nuzzle", Type.ELECTRIC, MoveCategory.PHYSICAL, 20, 100, 20, "The user attacks by nuzzling its electrified cheeks against the target. This also leaves the target with paralysis.", 100, 0, 6) .attr(StatusEffectAttr, StatusEffect.PARALYSIS), - new AttackMove(Moves.HOLD_BACK, "Hold Back (P)", Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 40, "The user holds back when it attacks, and the target is left with at least 1 HP.", -1, 0, 6), + new AttackMove(Moves.HOLD_BACK, "Hold Back", Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 40, "The user holds back when it attacks, and the target is left with at least 1 HP.", -1, 0, 6) + .attr(SurviveDamageAttr), new AttackMove(Moves.INFESTATION, "Infestation (P)", Type.BUG, MoveCategory.SPECIAL, 20, 100, 20, "The target is infested and attacked for four to five turns. The target can't flee during this time.", 100, 0, 6), new AttackMove(Moves.POWER_UP_PUNCH, "Power-Up Punch", Type.FIGHTING, MoveCategory.PHYSICAL, 40, 100, 20, "Striking opponents over and over makes the user's fists harder. Hitting a target raises the Attack stat.", 100, 0, 6) .attr(StatChangeAttr, BattleStat.ATK, 1, true) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index ebae355f814..7b35cec07dd 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -2,7 +2,7 @@ import Phaser from 'phaser'; import BattleScene, { AnySound } from '../battle-scene'; import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from '../ui/battle-info'; 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 } from "../data/move"; +import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, VariablePowerAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, MultiHitAttr, StatusMoveTypeImmunityAttr, MoveTarget, VariableDefAttr, AttackMove, ModifiedDamageAttr } from "../data/move"; import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm } from '../data/pokemon-species'; import * as Utils from '../utils'; import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from '../data/type'; @@ -1135,6 +1135,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (this.scene.arena.terrain?.terrainType === TerrainType.MISTY && this.isGrounded() && move.type === Type.DRAGON) damage.value = Math.floor(damage.value / 2); + applyMoveAttrs(ModifiedDamageAttr, source, this, move, damage); + const fixedDamage = new Utils.IntegerHolder(0); applyMoveAttrs(FixedDamageAttr, source, this, move, fixedDamage); if (!isTypeImmune && fixedDamage.value) { @@ -1143,7 +1145,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { result = HitResult.EFFECTIVE; } - console.log('damage', damage, move.name, power.value, sourceAtk, targetDef); + console.log('damage', damage.value, move.name, power.value, sourceAtk, targetDef); if (!result) { if (!typeMultiplier.value)