Implement Prankster ability
parent
31d0d9b84e
commit
11bd7fdbca
|
@ -19,7 +19,7 @@ import { } from "./data/move";
|
||||||
import { initMoves } from './data/move';
|
import { initMoves } from './data/move';
|
||||||
import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave } from './modifier/modifier-type';
|
import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave } from './modifier/modifier-type';
|
||||||
import AbilityBar from './ui/ability-bar';
|
import AbilityBar from './ui/ability-bar';
|
||||||
import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, applyAbAttrs, initAbilities } from './data/ability';
|
import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, IncrementMovePriorityAbAttr, applyAbAttrs, initAbilities } from './data/ability';
|
||||||
import Battle, { BattleType, FixedBattleConfig, fixedBattles } from './battle';
|
import Battle, { BattleType, FixedBattleConfig, fixedBattles } from './battle';
|
||||||
import { GameMode, GameModes, gameModes } from './game-mode';
|
import { GameMode, GameModes, gameModes } from './game-mode';
|
||||||
import FieldSpritePipeline from './pipelines/field-sprite';
|
import FieldSpritePipeline from './pipelines/field-sprite';
|
||||||
|
@ -1595,8 +1595,9 @@ export default class BattleScene extends Phaser.Scene {
|
||||||
}
|
}
|
||||||
|
|
||||||
pushMovePhase(movePhase: MovePhase, priorityOverride?: integer): void {
|
pushMovePhase(movePhase: MovePhase, priorityOverride?: integer): void {
|
||||||
const priority = priorityOverride !== undefined ? priorityOverride : movePhase.move.getMove().priority;
|
const movePriority = new Utils.IntegerHolder(priorityOverride !== undefined ? priorityOverride : movePhase.move.getMove().priority);
|
||||||
const lowerPriorityPhase = this.phaseQueue.find(p => p instanceof MovePhase && p.move.getMove().priority < priority);
|
applyAbAttrs(IncrementMovePriorityAbAttr, movePhase.pokemon, null, movePhase.move.getMove(), movePriority);
|
||||||
|
const lowerPriorityPhase = this.phaseQueue.find(p => p instanceof MovePhase && p.move.getMove().priority < movePriority.value);
|
||||||
if (lowerPriorityPhase)
|
if (lowerPriorityPhase)
|
||||||
this.phaseQueue.splice(this.phaseQueue.indexOf(lowerPriorityPhase), 0, movePhase);
|
this.phaseQueue.splice(this.phaseQueue.indexOf(lowerPriorityPhase), 0, movePhase);
|
||||||
else
|
else
|
||||||
|
|
|
@ -914,6 +914,24 @@ export class BlockOneHitKOAbAttr extends AbAttr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class IncrementMovePriorityAbAttr extends AbAttr {
|
||||||
|
private moveIncrementFunc: (move: Move) => boolean;
|
||||||
|
|
||||||
|
constructor(moveIncrementFunc: (move: Move) => boolean) {
|
||||||
|
super(true);
|
||||||
|
|
||||||
|
this.moveIncrementFunc = moveIncrementFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||||
|
if (!this.moveIncrementFunc(args[0] as Move))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
(args[0] as Utils.IntegerHolder).value++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class IgnoreContactAbAttr extends AbAttr { }
|
export class IgnoreContactAbAttr extends AbAttr { }
|
||||||
|
|
||||||
export class PreWeatherEffectAbAttr extends AbAttr {
|
export class PreWeatherEffectAbAttr extends AbAttr {
|
||||||
|
@ -2192,7 +2210,8 @@ export function initAbilities() {
|
||||||
new Ability(Abilities.SAP_SIPPER, "Sap Sipper", "Boosts the Attack stat if hit by a Grass-type move instead of taking damage.", 5)
|
new Ability(Abilities.SAP_SIPPER, "Sap Sipper", "Boosts the Attack stat if hit by a Grass-type move instead of taking damage.", 5)
|
||||||
.attr(TypeImmunityStatChangeAbAttr, Type.GRASS, BattleStat.ATK, 1)
|
.attr(TypeImmunityStatChangeAbAttr, Type.GRASS, BattleStat.ATK, 1)
|
||||||
.ignorable(),
|
.ignorable(),
|
||||||
new Ability(Abilities.PRANKSTER, "Prankster (N)", "Gives priority to a status move.", 5),
|
new Ability(Abilities.PRANKSTER, "Prankster", "Gives priority to a status move.", 5)
|
||||||
|
.attr(IncrementMovePriorityAbAttr, (move: Move) => move.category === MoveCategory.STATUS),
|
||||||
new Ability(Abilities.SAND_FORCE, "Sand Force", "Boosts the power of Rock-, Ground-, and Steel-type moves in a sandstorm.", 5)
|
new Ability(Abilities.SAND_FORCE, "Sand Force", "Boosts the power of Rock-, Ground-, and Steel-type moves in a sandstorm.", 5)
|
||||||
.attr(MoveTypePowerBoostAbAttr, Type.ROCK, 1.3)
|
.attr(MoveTypePowerBoostAbAttr, Type.ROCK, 1.3)
|
||||||
.attr(MoveTypePowerBoostAbAttr, Type.GROUND, 1.3)
|
.attr(MoveTypePowerBoostAbAttr, Type.GROUND, 1.3)
|
||||||
|
|
|
@ -540,8 +540,7 @@ export async function printMoves() {
|
||||||
} else if (matchingLine)
|
} else if (matchingLine)
|
||||||
flavorText = allMoves[move.id].effect;
|
flavorText = allMoves[move.id].effect;
|
||||||
const moveTarget = targetMap[move.target.name];
|
const moveTarget = targetMap[move.target.name];
|
||||||
const moveTm = move.id < allMoves.length ? allMoves[move.id].tm : -1;
|
moveStr += `\n new ${move.damage_class.name !== 'status' ? 'Attack' : (moveTarget === MoveTarget.USER ? 'Self' : '') + 'Status'}Move(Moves.${moveEnumName}, "${moveName}", Type.${move.type.name.toUpperCase()}${move.damage_class.name !== 'status' ? `, MoveCategory.${move.damage_class.name.toUpperCase()}` : ''}${move.damage_class.name !== 'status' ? `, ${move.power || -1}` : ''}, ${move.accuracy || -1}, ${move.pp}, "${flavorText?.replace(/\n/g, '\\n').replace(/ /g, ' ').replace(/’/g, '\'') || ''}", ${move.effect_chance || -1}, ${move.priority}, ${generationMap[move.generation.name]})`;
|
||||||
moveStr += `\n new ${move.damage_class.name !== 'status' ? 'Attack' : (moveTarget === MoveTarget.USER ? 'Self' : '') + 'Status'}Move(Moves.${moveEnumName}, "${moveName}", Type.${move.type.name.toUpperCase()}${move.damage_class.name !== 'status' ? `, MoveCategory.${move.damage_class.name.toUpperCase()}` : ''}${move.damage_class.name !== 'status' ? `, ${move.power || -1}` : ''}, ${move.accuracy || -1}, ${move.pp}, ${moveTm}, "${flavorText?.replace(/\n/g, '\\n').replace(/ /g, ' ').replace(/’/g, '\'') || ''}", ${move.effect_chance || -1}, ${move.priority}, ${generationMap[move.generation.name]})`;
|
|
||||||
const expectedTarget = move.damage_class.name !== 'status' || moveTarget !== MoveTarget.USER ? MoveTarget.NEAR_OTHER : MoveTarget.USER;
|
const expectedTarget = move.damage_class.name !== 'status' || moveTarget !== MoveTarget.USER ? MoveTarget.NEAR_OTHER : MoveTarget.USER;
|
||||||
if (matchingLine && matchingLine.length > 1) {
|
if (matchingLine && matchingLine.length > 1) {
|
||||||
const newLineIndex = matchingLine.indexOf('\n');
|
const newLineIndex = matchingLine.indexOf('\n');
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
import Pokemon from "../field/pokemon";
|
||||||
import Move from "./move";
|
import Move from "./move";
|
||||||
import { Type } from "./type";
|
import { Type } from "./type";
|
||||||
|
import * as Utils from "../utils";
|
||||||
|
import { IncrementMovePriorityAbAttr, applyAbAttrs } from "./ability";
|
||||||
|
|
||||||
export enum TerrainType {
|
export enum TerrainType {
|
||||||
NONE,
|
NONE,
|
||||||
|
@ -44,10 +47,12 @@ export class Terrain {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
isMoveTerrainCancelled(move: Move): boolean {
|
isMoveTerrainCancelled(user: Pokemon, move: Move): boolean {
|
||||||
switch (this.terrainType) {
|
switch (this.terrainType) {
|
||||||
case TerrainType.PSYCHIC:
|
case TerrainType.PSYCHIC:
|
||||||
return move.priority > 0;
|
const priority = new Utils.IntegerHolder(move.priority);
|
||||||
|
applyAbAttrs(IncrementMovePriorityAbAttr, user, null, move, priority);
|
||||||
|
return priority.value > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -17,7 +17,7 @@ import { Moves } from "../data/enums/moves";
|
||||||
import { TimeOfDay } from "../data/enums/time-of-day";
|
import { TimeOfDay } from "../data/enums/time-of-day";
|
||||||
import { Terrain, TerrainType } from "../data/terrain";
|
import { Terrain, TerrainType } from "../data/terrain";
|
||||||
import { PostTerrainChangeAbAttr, PostWeatherChangeAbAttr, applyPostTerrainChangeAbAttrs, applyPostWeatherChangeAbAttrs } from "../data/ability";
|
import { PostTerrainChangeAbAttr, PostWeatherChangeAbAttr, applyPostTerrainChangeAbAttrs, applyPostWeatherChangeAbAttrs } from "../data/ability";
|
||||||
import { PartyMemberStrength } from "../data/enums/party-member-strength";
|
import Pokemon from "./pokemon";
|
||||||
|
|
||||||
const WEATHER_OVERRIDE = WeatherType.NONE;
|
const WEATHER_OVERRIDE = WeatherType.NONE;
|
||||||
|
|
||||||
|
@ -313,8 +313,8 @@ export class Arena {
|
||||||
return this.weather && !this.weather.isEffectSuppressed(this.scene) && this.weather.isMoveWeatherCancelled(move);
|
return this.weather && !this.weather.isEffectSuppressed(this.scene) && this.weather.isMoveWeatherCancelled(move);
|
||||||
}
|
}
|
||||||
|
|
||||||
isMoveTerrainCancelled(move: Move) {
|
isMoveTerrainCancelled(user: Pokemon, move: Move) {
|
||||||
return this.terrain && this.terrain.isMoveTerrainCancelled(move);
|
return this.terrain && this.terrain.isMoveTerrainCancelled(user, move);
|
||||||
}
|
}
|
||||||
|
|
||||||
getAttackTypeMultiplier(attackType: Type, grounded: boolean): number {
|
getAttackTypeMultiplier(attackType: Type, grounded: boolean): number {
|
||||||
|
|
|
@ -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 { Abilities, CheckTrappedAbAttr, MoveAbilityBypassAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs } from "./data/ability";
|
import { Abilities, CheckTrappedAbAttr, MoveAbilityBypassAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr } 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";
|
||||||
|
@ -1768,11 +1768,17 @@ export class TurnStartPhase extends FieldPhase {
|
||||||
else if (bCommand.command === Command.FIGHT)
|
else if (bCommand.command === Command.FIGHT)
|
||||||
return -1;
|
return -1;
|
||||||
} else if (aCommand.command === Command.FIGHT) {
|
} else if (aCommand.command === Command.FIGHT) {
|
||||||
const aPriority = allMoves[aCommand.move.move].priority;
|
const aMove = allMoves[aCommand.move.move];
|
||||||
const bPriority = allMoves[bCommand.move.move].priority;
|
const bMove = allMoves[bCommand.move.move];
|
||||||
|
|
||||||
if (aPriority !== bPriority)
|
const aPriority = new Utils.IntegerHolder(aMove.priority);
|
||||||
return aPriority < bPriority ? 1 : -1;
|
const bPriority = new Utils.IntegerHolder(bMove.priority);
|
||||||
|
|
||||||
|
applyAbAttrs(IncrementMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === a), null, aMove, aPriority);
|
||||||
|
applyAbAttrs(IncrementMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === b), null, bMove, bPriority);
|
||||||
|
|
||||||
|
if (aPriority.value !== bPriority.value)
|
||||||
|
return aPriority.value < bPriority.value ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const aIndex = order.indexOf(a);
|
const aIndex = order.indexOf(a);
|
||||||
|
@ -2070,7 +2076,7 @@ export class MovePhase extends BattlePhase {
|
||||||
let failedText = null;
|
let failedText = null;
|
||||||
if (success && this.scene.arena.isMoveWeatherCancelled(this.move.getMove()))
|
if (success && this.scene.arena.isMoveWeatherCancelled(this.move.getMove()))
|
||||||
success = false;
|
success = false;
|
||||||
else if (success && this.scene.arena.isMoveTerrainCancelled(this.move.getMove())) {
|
else if (success && this.scene.arena.isMoveTerrainCancelled(this.pokemon, this.move.getMove())) {
|
||||||
success = false;
|
success = false;
|
||||||
failedText = getTerrainBlockMessage(targets[0], this.scene.arena.terrain.terrainType);
|
failedText = getTerrainBlockMessage(targets[0], this.scene.arena.terrain.terrainType);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue