mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-14 12:22:19 +02:00
Sacrifical Moves (that dont require a target like explosion or self destruct) now also work if the target is flying, diving etc.
There is also a new catagorie of moves. "SacrificalMovesOnHit" for all moves that need to hit for them to be sacrifical like MEMENTO
This commit is contained in:
parent
d5681a6e03
commit
84d3350715
@ -737,17 +737,48 @@ export class RecoilAttr extends MoveEffectAttr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute used for moves which self KO the user regardless if the move hits a target
|
||||||
|
* */
|
||||||
export class SacrificialAttr extends MoveEffectAttr {
|
export class SacrificialAttr extends MoveEffectAttr {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(true, MoveEffectTrigger.PRE_APPLY);
|
super(true, MoveEffectTrigger.PRE_APPLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
user.damageAndUpdate(user.hp, HitResult.OTHER, false, true, true);
|
||||||
|
user.turnData.damageTaken += user.hp;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer {
|
||||||
|
if (user.isBoss())
|
||||||
|
return -20;
|
||||||
|
return Math.ceil(((1 - user.getHpRatio()) * 10 - 10) * (target.getAttackTypeEffectiveness(move.type, user) - 0.5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute used for moves which self KO the user but only if the move hits a target
|
||||||
|
*/
|
||||||
|
export class SacrificialAttrOnHit 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))
|
if (!super.apply(user, target, move, args))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
user.damageAndUpdate(user.hp, HitResult.OTHER, false, true, true);
|
user.damageAndUpdate(user.hp, HitResult.OTHER, false, true, true);
|
||||||
user.turnData.damageTaken += user.hp;
|
user.turnData.damageTaken += user.hp;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -4771,7 +4802,7 @@ export function initMoves() {
|
|||||||
new StatusMove(Moves.WILL_O_WISP, Type.FIRE, 85, 15, -1, 0, 3)
|
new StatusMove(Moves.WILL_O_WISP, Type.FIRE, 85, 15, -1, 0, 3)
|
||||||
.attr(StatusEffectAttr, StatusEffect.BURN),
|
.attr(StatusEffectAttr, StatusEffect.BURN),
|
||||||
new StatusMove(Moves.MEMENTO, Type.DARK, 100, 10, -1, 0, 3)
|
new StatusMove(Moves.MEMENTO, Type.DARK, 100, 10, -1, 0, 3)
|
||||||
.attr(SacrificialAttr)
|
.attr(SacrificialAttrOnHit)
|
||||||
.attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK ], -2),
|
.attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK ], -2),
|
||||||
new AttackMove(Moves.FACADE, Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 20, -1, 0, 3)
|
new AttackMove(Moves.FACADE, Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 20, -1, 0, 3)
|
||||||
.attr(MovePowerMultiplierAttr, (user, target, move) => user.status
|
.attr(MovePowerMultiplierAttr, (user, target, move) => user.status
|
||||||
@ -5305,7 +5336,7 @@ export function initMoves() {
|
|||||||
new AttackMove(Moves.SPACIAL_REND, Type.DRAGON, MoveCategory.SPECIAL, 100, 95, 5, -1, 0, 4)
|
new AttackMove(Moves.SPACIAL_REND, Type.DRAGON, MoveCategory.SPECIAL, 100, 95, 5, -1, 0, 4)
|
||||||
.attr(HighCritAttr),
|
.attr(HighCritAttr),
|
||||||
new SelfStatusMove(Moves.LUNAR_DANCE, Type.PSYCHIC, -1, 10, -1, 0, 4)
|
new SelfStatusMove(Moves.LUNAR_DANCE, Type.PSYCHIC, -1, 10, -1, 0, 4)
|
||||||
.attr(SacrificialAttr)
|
.attr(SacrificialAttrOnHit)
|
||||||
.danceMove()
|
.danceMove()
|
||||||
.triageMove()
|
.triageMove()
|
||||||
.unimplemented(),
|
.unimplemented(),
|
||||||
@ -5454,7 +5485,7 @@ export function initMoves() {
|
|||||||
.partial(),
|
.partial(),
|
||||||
new AttackMove(Moves.FINAL_GAMBIT, Type.FIGHTING, MoveCategory.SPECIAL, -1, 100, 5, -1, 0, 5)
|
new AttackMove(Moves.FINAL_GAMBIT, Type.FIGHTING, MoveCategory.SPECIAL, -1, 100, 5, -1, 0, 5)
|
||||||
.attr(UserHpDamageAttr)
|
.attr(UserHpDamageAttr)
|
||||||
.attr(SacrificialAttr),
|
.attr(SacrificialAttrOnHit),
|
||||||
new StatusMove(Moves.BESTOW, Type.NORMAL, -1, 15, -1, 0, 5)
|
new StatusMove(Moves.BESTOW, Type.NORMAL, -1, 15, -1, 0, 5)
|
||||||
.ignoresProtect()
|
.ignoresProtect()
|
||||||
.unimplemented(),
|
.unimplemented(),
|
||||||
|
@ -2,7 +2,41 @@ import BattleScene, { AnySound, bypassLogin, startingWave } from "./battle-scene
|
|||||||
import { default as Pokemon, PlayerPokemon, EnemyPokemon, PokemonMove, MoveResult, DamageResult, FieldPosition, HitResult, TurnMove } from "./field/pokemon";
|
import { default as Pokemon, PlayerPokemon, EnemyPokemon, PokemonMove, MoveResult, DamageResult, FieldPosition, HitResult, TurnMove } from "./field/pokemon";
|
||||||
import * as Utils from './utils';
|
import * as Utils from './utils';
|
||||||
import { Moves } from "./data/enums/moves";
|
import { Moves } from "./data/enums/moves";
|
||||||
import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMoveAttrs, HitsTagAttr, MissEffectAttr, MoveAttr, MoveEffectAttr, MoveFlags, MultiHitAttr, OverrideMoveEffectAttr, VariableAccuracyAttr, MoveTarget, OneHitKOAttr, getMoveTargets, MoveTargetSet, MoveEffectTrigger, CopyMoveAttr, AttackMove, SelfStatusMove, DelayedAttackAttr, RechargeAttr, PreMoveMessageAttr, HealStatusEffectAttr, IgnoreOpponentStatChangesAttr, NoEffectAttr, FixedDamageAttr, PostVictoryStatChangeAttr, OneHitKOAccuracyAttr, ForceSwitchOutAttr, VariableTargetAttr } from "./data/move";
|
import {
|
||||||
|
allMoves,
|
||||||
|
applyMoveAttrs,
|
||||||
|
BypassSleepAttr,
|
||||||
|
ChargeAttr,
|
||||||
|
applyFilteredMoveAttrs,
|
||||||
|
HitsTagAttr,
|
||||||
|
MissEffectAttr,
|
||||||
|
MoveAttr,
|
||||||
|
MoveEffectAttr,
|
||||||
|
MoveFlags,
|
||||||
|
MultiHitAttr,
|
||||||
|
OverrideMoveEffectAttr,
|
||||||
|
VariableAccuracyAttr,
|
||||||
|
MoveTarget,
|
||||||
|
OneHitKOAttr,
|
||||||
|
getMoveTargets,
|
||||||
|
MoveTargetSet,
|
||||||
|
MoveEffectTrigger,
|
||||||
|
CopyMoveAttr,
|
||||||
|
AttackMove,
|
||||||
|
SelfStatusMove,
|
||||||
|
DelayedAttackAttr,
|
||||||
|
RechargeAttr,
|
||||||
|
PreMoveMessageAttr,
|
||||||
|
HealStatusEffectAttr,
|
||||||
|
IgnoreOpponentStatChangesAttr,
|
||||||
|
NoEffectAttr,
|
||||||
|
FixedDamageAttr,
|
||||||
|
PostVictoryStatChangeAttr,
|
||||||
|
OneHitKOAccuracyAttr,
|
||||||
|
ForceSwitchOutAttr,
|
||||||
|
VariableTargetAttr,
|
||||||
|
SacrificialAttr
|
||||||
|
} from "./data/move";
|
||||||
import { Mode } from './ui/ui';
|
import { Mode } from './ui/ui';
|
||||||
import { Command } from "./ui/command-ui-handler";
|
import { Command } from "./ui/command-ui-handler";
|
||||||
import { Stat } from "./data/pokemon-stat";
|
import { Stat } from "./data/pokemon-stat";
|
||||||
@ -2271,13 +2305,20 @@ export class MovePhase extends BattlePhase {
|
|||||||
if (this.move.moveId)
|
if (this.move.moveId)
|
||||||
this.showMoveText();
|
this.showMoveText();
|
||||||
|
|
||||||
if ((moveQueue.length && moveQueue[0].move === Moves.NONE) || !targets.length) {
|
if ((moveQueue.length && moveQueue[0].move === Moves.NONE) || (!targets.length && !this.move.getMove().getAttrs(SacrificialAttr).length)) {
|
||||||
moveQueue.shift();
|
moveQueue.shift();
|
||||||
this.cancel();
|
this.cancel();
|
||||||
this.pokemon.pushMoveHistory({ move: Moves.NONE, result: MoveResult.FAIL });
|
this.pokemon.pushMoveHistory({ move: Moves.NONE, result: MoveResult.FAIL });
|
||||||
return this.end();
|
return this.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (targets.length === 0 && this.move.getMove().getAttrs(SacrificialAttr).length) {
|
||||||
|
// Add the user as a target if the move is sacrificial
|
||||||
|
targets.push(this.pokemon);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!moveQueue.length || !moveQueue.shift().ignorePP) // using .shift here clears out two turn moves once they've been used
|
if (!moveQueue.length || !moveQueue.shift().ignorePP) // using .shift here clears out two turn moves once they've been used
|
||||||
this.move.usePp(ppUsed);
|
this.move.usePp(ppUsed);
|
||||||
|
|
||||||
@ -2441,8 +2482,16 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
|
|
||||||
// Move animation only needs one target
|
// Move animation only needs one target
|
||||||
new MoveAnim(this.move.getMove().id as Moves, user, this.getTarget()?.getBattlerIndex()).play(this.scene, () => {
|
new MoveAnim(this.move.getMove().id as Moves, user, this.getTarget()?.getBattlerIndex()).play(this.scene, () => {
|
||||||
|
// Check if the user is in the targets list for sacrificial moves
|
||||||
|
if (this.move.getMove().getAttrs(SacrificialAttr).length && !targets.includes(user)) {
|
||||||
|
targets.push(user);
|
||||||
|
targetHitChecks[user.getBattlerIndex()] = true;
|
||||||
|
}
|
||||||
for (let target of targets) {
|
for (let target of targets) {
|
||||||
if (!targetHitChecks[target.getBattlerIndex()]) {
|
if (!targetHitChecks[target.getBattlerIndex()]) {
|
||||||
|
if (this.move.getMove().getAttrs(SacrificialAttr).length && target !== user) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
user.turnData.hitCount = 1;
|
user.turnData.hitCount = 1;
|
||||||
user.turnData.hitsLeft = 1;
|
user.turnData.hitsLeft = 1;
|
||||||
this.scene.queueMessage(getPokemonMessage(user, '\'s\nattack missed!'));
|
this.scene.queueMessage(getPokemonMessage(user, '\'s\nattack missed!'));
|
||||||
|
Loading…
Reference in New Issue
Block a user