mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2024-12-01 19:26:16 +00:00
Implement Triple Kick/Triple Axel/Population Bomb (#1341)
* Implement Triple Kick/Triple Axel/Population Bomb * Add maximum allowed base power increments * Add documentation * Fix Population Bomb, Account for Skill Link * Change multi-hit power increment behavior * Fix Typo
This commit is contained in:
parent
4d15269eec
commit
47d39388ac
102
src/data/move.ts
102
src/data/move.ts
@ -86,6 +86,10 @@ export enum MoveFlags {
|
|||||||
WIND_MOVE = 1 << 14,
|
WIND_MOVE = 1 << 14,
|
||||||
TRIAGE_MOVE = 1 << 15,
|
TRIAGE_MOVE = 1 << 15,
|
||||||
IGNORE_ABILITIES = 1 << 16,
|
IGNORE_ABILITIES = 1 << 16,
|
||||||
|
/**
|
||||||
|
* Enables all hits of a multi-hit move to be accuracy checked individually
|
||||||
|
*/
|
||||||
|
CHECK_ALL_HITS = 1 << 17,
|
||||||
}
|
}
|
||||||
|
|
||||||
type MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => boolean;
|
type MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => boolean;
|
||||||
@ -346,6 +350,11 @@ export default class Move implements Localizable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkAllHits(checkAllHits?: boolean): this {
|
||||||
|
this.setFlag(MoveFlags.CHECK_ALL_HITS, checkAllHits);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
checkFlag(flag: MoveFlags, user: Pokemon, target: Pokemon): boolean {
|
checkFlag(flag: MoveFlags, user: Pokemon, target: Pokemon): boolean {
|
||||||
switch (flag) {
|
switch (flag) {
|
||||||
case MoveFlags.MAKES_CONTACT:
|
case MoveFlags.MAKES_CONTACT:
|
||||||
@ -955,8 +964,7 @@ export enum MultiHitType {
|
|||||||
_2,
|
_2,
|
||||||
_2_TO_5,
|
_2_TO_5,
|
||||||
_3,
|
_3,
|
||||||
_3_INCR,
|
_10,
|
||||||
_1_TO_10,
|
|
||||||
BEAT_UP,
|
BEAT_UP,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1287,37 +1295,8 @@ export class MultiHitAttr extends MoveAttr {
|
|||||||
case MultiHitType._3:
|
case MultiHitType._3:
|
||||||
hitTimes = 3;
|
hitTimes = 3;
|
||||||
break;
|
break;
|
||||||
case MultiHitType._3_INCR:
|
case MultiHitType._10:
|
||||||
hitTimes = 3;
|
|
||||||
// TODO: Add power increase for every hit
|
|
||||||
break;
|
|
||||||
case MultiHitType._1_TO_10:
|
|
||||||
{
|
|
||||||
const rand = user.randSeedInt(90);
|
|
||||||
const hitValue = new Utils.IntegerHolder(rand);
|
|
||||||
applyAbAttrs(MaxMultiHitAbAttr, user, null, hitValue);
|
|
||||||
if (hitValue.value >= 81) {
|
|
||||||
hitTimes = 1;
|
|
||||||
} else if (hitValue.value >= 73) {
|
|
||||||
hitTimes = 2;
|
|
||||||
} else if (hitValue.value >= 66) {
|
|
||||||
hitTimes = 3;
|
|
||||||
} else if (hitValue.value >= 60) {
|
|
||||||
hitTimes = 4;
|
|
||||||
} else if (hitValue.value >= 54) {
|
|
||||||
hitTimes = 5;
|
|
||||||
} else if (hitValue.value >= 49) {
|
|
||||||
hitTimes = 6;
|
|
||||||
} else if (hitValue.value >= 44) {
|
|
||||||
hitTimes = 7;
|
|
||||||
} else if (hitValue.value >= 40) {
|
|
||||||
hitTimes = 8;
|
|
||||||
} else if (hitValue.value >= 36) {
|
|
||||||
hitTimes = 9;
|
|
||||||
} else {
|
|
||||||
hitTimes = 10;
|
hitTimes = 10;
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case MultiHitType.BEAT_UP:
|
case MultiHitType.BEAT_UP:
|
||||||
const party = user.isPlayer() ? user.scene.getParty() : user.scene.getEnemyParty();
|
const party = user.isPlayer() ? user.scene.getParty() : user.scene.getEnemyParty();
|
||||||
@ -2751,6 +2730,43 @@ export class WaterShurikenPowerAttr extends VariablePowerAttr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute used for multi-hit moves that increase power in increments of the
|
||||||
|
* move's base power for each hit, namely Triple Kick and Triple Axel.
|
||||||
|
* @extends VariablePowerAttr
|
||||||
|
* @see {@linkcode apply}
|
||||||
|
*/
|
||||||
|
export class MultiHitPowerIncrementAttr extends VariablePowerAttr {
|
||||||
|
/** The max number of base power increments allowed for this move */
|
||||||
|
private maxHits: integer;
|
||||||
|
|
||||||
|
constructor(maxHits: integer) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.maxHits = maxHits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increases power of move in increments of the base power for the amount of times
|
||||||
|
* the move hit. In the case that the move is extended, it will circle back to the
|
||||||
|
* original base power of the move after incrementing past the maximum amount of
|
||||||
|
* hits.
|
||||||
|
* @param user {@linkcode Pokemon} that used the move
|
||||||
|
* @param target {@linkcode Pokemon} that the move was used on
|
||||||
|
* @param move {@linkcode Move} with this attribute
|
||||||
|
* @param args [0] {@linkcode Utils.NumberHolder} for final calculated power of move
|
||||||
|
* @returns true if attribute application succeeds
|
||||||
|
*/
|
||||||
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
|
const hitsTotal = user.turnData.hitCount - Math.max(user.turnData.hitsLeft, 0);
|
||||||
|
const power = args[0] as Utils.NumberHolder;
|
||||||
|
|
||||||
|
power.value = move.power * (1 + hitsTotal % this.maxHits);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class VariableAtkAttr extends MoveAttr {
|
export class VariableAtkAttr extends MoveAttr {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -5411,12 +5427,9 @@ export function initMoves() {
|
|||||||
.attr(SketchAttr)
|
.attr(SketchAttr)
|
||||||
.ignoresVirtual(),
|
.ignoresVirtual(),
|
||||||
new AttackMove(Moves.TRIPLE_KICK, Type.FIGHTING, MoveCategory.PHYSICAL, 10, 90, 10, -1, 0, 2)
|
new AttackMove(Moves.TRIPLE_KICK, Type.FIGHTING, MoveCategory.PHYSICAL, 10, 90, 10, -1, 0, 2)
|
||||||
.attr(MultiHitAttr, MultiHitType._3_INCR)
|
.attr(MultiHitAttr, MultiHitType._3)
|
||||||
.attr(MissEffectAttr, (user: Pokemon, move: Move) => {
|
.attr(MultiHitPowerIncrementAttr, 3)
|
||||||
user.turnData.hitsLeft = 1;
|
.checkAllHits(),
|
||||||
return true;
|
|
||||||
})
|
|
||||||
.partial(),
|
|
||||||
new AttackMove(Moves.THIEF, Type.DARK, MoveCategory.PHYSICAL, 60, 100, 25, -1, 0, 2)
|
new AttackMove(Moves.THIEF, Type.DARK, MoveCategory.PHYSICAL, 60, 100, 25, -1, 0, 2)
|
||||||
.attr(StealHeldItemChanceAttr, 0.3),
|
.attr(StealHeldItemChanceAttr, 0.3),
|
||||||
new StatusMove(Moves.SPIDER_WEB, Type.BUG, -1, 10, -1, 0, 2)
|
new StatusMove(Moves.SPIDER_WEB, Type.BUG, -1, 10, -1, 0, 2)
|
||||||
@ -7268,12 +7281,9 @@ export function initMoves() {
|
|||||||
new AttackMove(Moves.FLIP_TURN, Type.WATER, MoveCategory.PHYSICAL, 60, 100, 20, -1, 0, 8)
|
new AttackMove(Moves.FLIP_TURN, Type.WATER, MoveCategory.PHYSICAL, 60, 100, 20, -1, 0, 8)
|
||||||
.attr(ForceSwitchOutAttr, true, false),
|
.attr(ForceSwitchOutAttr, true, false),
|
||||||
new AttackMove(Moves.TRIPLE_AXEL, Type.ICE, MoveCategory.PHYSICAL, 20, 90, 10, -1, 0, 8)
|
new AttackMove(Moves.TRIPLE_AXEL, Type.ICE, MoveCategory.PHYSICAL, 20, 90, 10, -1, 0, 8)
|
||||||
.attr(MultiHitAttr, MultiHitType._3_INCR)
|
.attr(MultiHitAttr, MultiHitType._3)
|
||||||
.attr(MissEffectAttr, (user: Pokemon, move: Move) => {
|
.attr(MultiHitPowerIncrementAttr, 3)
|
||||||
user.turnData.hitsLeft = 1;
|
.checkAllHits(),
|
||||||
return true;
|
|
||||||
})
|
|
||||||
.partial(),
|
|
||||||
new AttackMove(Moves.DUAL_WINGBEAT, Type.FLYING, MoveCategory.PHYSICAL, 40, 90, 10, -1, 0, 8)
|
new AttackMove(Moves.DUAL_WINGBEAT, Type.FLYING, MoveCategory.PHYSICAL, 40, 90, 10, -1, 0, 8)
|
||||||
.attr(MultiHitAttr, MultiHitType._2),
|
.attr(MultiHitAttr, MultiHitType._2),
|
||||||
new AttackMove(Moves.SCORCHING_SANDS, Type.GROUND, MoveCategory.SPECIAL, 70, 100, 10, 30, 0, 8)
|
new AttackMove(Moves.SCORCHING_SANDS, Type.GROUND, MoveCategory.SPECIAL, 70, 100, 10, 30, 0, 8)
|
||||||
@ -7516,9 +7526,9 @@ export function initMoves() {
|
|||||||
new AttackMove(Moves.SPIN_OUT, Type.STEEL, MoveCategory.PHYSICAL, 100, 100, 5, 100, 0, 9)
|
new AttackMove(Moves.SPIN_OUT, Type.STEEL, MoveCategory.PHYSICAL, 100, 100, 5, 100, 0, 9)
|
||||||
.attr(StatChangeAttr, BattleStat.SPD, -2, true),
|
.attr(StatChangeAttr, BattleStat.SPD, -2, true),
|
||||||
new AttackMove(Moves.POPULATION_BOMB, Type.NORMAL, MoveCategory.PHYSICAL, 20, 90, 10, -1, 0, 9)
|
new AttackMove(Moves.POPULATION_BOMB, Type.NORMAL, MoveCategory.PHYSICAL, 20, 90, 10, -1, 0, 9)
|
||||||
.attr(MultiHitAttr, MultiHitType._1_TO_10)
|
.attr(MultiHitAttr, MultiHitType._10)
|
||||||
.slicingMove()
|
.slicingMove()
|
||||||
.partial(),
|
.checkAllHits(),
|
||||||
new AttackMove(Moves.ICE_SPINNER, Type.ICE, MoveCategory.PHYSICAL, 80, 100, 15, -1, 0, 9)
|
new AttackMove(Moves.ICE_SPINNER, Type.ICE, MoveCategory.PHYSICAL, 80, 100, 15, -1, 0, 9)
|
||||||
.attr(ClearTerrainAttr),
|
.attr(ClearTerrainAttr),
|
||||||
new AttackMove(Moves.GLAIVE_RUSH, Type.DRAGON, MoveCategory.PHYSICAL, 120, 100, 5, -1, 0, 9)
|
new AttackMove(Moves.GLAIVE_RUSH, Type.DRAGON, MoveCategory.PHYSICAL, 120, 100, 5, -1, 0, 9)
|
||||||
|
@ -30,7 +30,7 @@ import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, get
|
|||||||
import { TempBattleStat } from "./data/temp-battle-stat";
|
import { TempBattleStat } from "./data/temp-battle-stat";
|
||||||
import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag";
|
import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag";
|
||||||
import { ArenaTagType } from "./data/enums/arena-tag-type";
|
import { ArenaTagType } from "./data/enums/arena-tag-type";
|
||||||
import { CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, IgnoreOpponentEvasionAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr, applyPostMoveUsedAbAttrs, PostMoveUsedAbAttr, HealFromBerryUseAbAttr } from "./data/ability";
|
import { CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, IgnoreOpponentEvasionAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr, applyPostMoveUsedAbAttrs, PostMoveUsedAbAttr, MaxMultiHitAbAttr, HealFromBerryUseAbAttr } from "./data/ability";
|
||||||
import { Unlockables, getUnlockableName } from "./system/unlockables";
|
import { Unlockables, getUnlockableName } from "./system/unlockables";
|
||||||
import { getBiomeKey } from "./field/arena";
|
import { getBiomeKey } from "./field/arena";
|
||||||
import { BattleType, BattlerIndex, TurnCommand } from "./battle";
|
import { BattleType, BattlerIndex, TurnCommand } from "./battle";
|
||||||
@ -2833,10 +2833,14 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
|
|
||||||
const user = this.getUserPokemon();
|
const user = this.getUserPokemon();
|
||||||
|
|
||||||
// Hit check only calculated on first hit for multi-hit moves
|
// Hit check only calculated on first hit for multi-hit moves unless flag is set to check all hits.
|
||||||
|
// However, if an ability with the MaxMultiHitAbAttr, namely Skill Link, is present, act as a normal
|
||||||
|
// multi-hit move and proceed with all hits
|
||||||
if (user.turnData.hitsLeft < user.turnData.hitCount) {
|
if (user.turnData.hitsLeft < user.turnData.hitCount) {
|
||||||
|
if (!this.move.getMove().hasFlag(MoveFlags.CHECK_ALL_HITS) || user.hasAbilityWithAttr(MaxMultiHitAbAttr)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (user.hasAbilityWithAttr(AlwaysHitAbAttr) || target.hasAbilityWithAttr(AlwaysHitAbAttr)) {
|
if (user.hasAbilityWithAttr(AlwaysHitAbAttr) || target.hasAbilityWithAttr(AlwaysHitAbAttr)) {
|
||||||
return true;
|
return true;
|
||||||
|
Loading…
Reference in New Issue
Block a user