Implement Parental Bond

pull/780/head
Jaime 2024-05-12 18:17:09 +02:00
parent 79a87e1c65
commit 14d3396f6a
3 changed files with 53 additions and 7 deletions

View File

@ -913,6 +913,34 @@ export class PostStatChangeStatChangeAbAttr extends PostStatChangeAbAttr {
} }
} }
export class PreHitAbAttr extends AbAttr {
apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
return false;
}
}
export class ExtraHitMoveAbAttr extends PreHitAbAttr {
private extraHits: integer;
private powerMultiplier: number;
constructor(extraHits: integer, powerMultiplier: number){
super(true);
this.extraHits = extraHits;
this.powerMultiplier = powerMultiplier;
}
apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
const hits = (args[0] as number[]);
if (this.extraHits > 0) {
for (let i = 0; i < this.extraHits; i++)
hits.push(this.powerMultiplier);
return true;
}
return false;
}
}
export class PreAttackAbAttr extends AbAttr { export class PreAttackAbAttr extends AbAttr {
applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean | Promise<boolean> { applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean | Promise<boolean> {
return false; return false;
@ -3285,7 +3313,7 @@ export function initAbilities() {
new Ability(Abilities.AERILATE, 6) new Ability(Abilities.AERILATE, 6)
.attr(MoveTypeChangePowerMultiplierAbAttr, Type.NORMAL, Type.FLYING, 1.2), .attr(MoveTypeChangePowerMultiplierAbAttr, Type.NORMAL, Type.FLYING, 1.2),
new Ability(Abilities.PARENTAL_BOND, 6) new Ability(Abilities.PARENTAL_BOND, 6)
.unimplemented(), .attr(ExtraHitMoveAbAttr, 1, 0.25),
new Ability(Abilities.DARK_AURA, 6) new Ability(Abilities.DARK_AURA, 6)
.attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => getPokemonMessage(pokemon, ' is radiating a Dark Aura!')) .attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => getPokemonMessage(pokemon, ' is radiating a Dark Aura!'))
.attr(FieldMoveTypePowerBoostAbAttr, Type.DARK, 4 / 3), .attr(FieldMoveTypePowerBoostAbAttr, Type.DARK, 4 / 3),

View File

@ -1415,7 +1415,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return (this.isPlayer() ? this.scene.getPlayerField() : this.scene.getEnemyField())[this.getFieldIndex() ? 0 : 1]; return (this.isPlayer() ? this.scene.getPlayerField() : this.scene.getEnemyField())[this.getFieldIndex() ? 0 : 1];
} }
apply(source: Pokemon, battlerMove: PokemonMove): HitResult { apply(source: Pokemon, battlerMove: PokemonMove, extraHitModifier: number = 1): HitResult {
let result: HitResult; let result: HitResult;
const move = battlerMove.getMove(); const move = battlerMove.getMove();
let damage = new Utils.NumberHolder(0); let damage = new Utils.NumberHolder(0);
@ -1541,7 +1541,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
applyMoveAttrs(VariableDefAttr, source, this, move, targetDef); applyMoveAttrs(VariableDefAttr, source, this, move, targetDef);
if (!isTypeImmune) { if (!isTypeImmune) {
damage.value = Math.ceil(((((2 * source.level / 5 + 2) * power.value * sourceAtk.value / targetDef.value) / 50) + 2) * stabMultiplier.value * typeMultiplier.value * arenaAttackTypeMultiplier.value * screenMultiplier.value * ((this.scene.randBattleSeedInt(15) + 85) / 100) * criticalMultiplier.value); damage.value = Math.ceil(((((2 * source.level / 5 + 2) * power.value * sourceAtk.value / targetDef.value) / 50) + 2) * stabMultiplier.value * typeMultiplier.value * arenaAttackTypeMultiplier.value * screenMultiplier.value * extraHitModifier * ((this.scene.randBattleSeedInt(15) + 85) / 100) * criticalMultiplier.value);
if (isPhysical && source.status && source.status.effect === StatusEffect.BURN) { if (isPhysical && source.status && source.status.effect === StatusEffect.BURN) {
const burnDamageReductionCancelled = new Utils.BooleanHolder(false); const burnDamageReductionCancelled = new Utils.BooleanHolder(false);
applyAbAttrs(BypassBurnDamageReductionAbAttr, source, burnDamageReductionCancelled); applyAbAttrs(BypassBurnDamageReductionAbAttr, source, burnDamageReductionCancelled);
@ -3310,6 +3310,7 @@ export class PokemonTurnData {
public damageDealt: integer = 0; public damageDealt: integer = 0;
public damageTaken: integer = 0; public damageTaken: integer = 0;
public attacksReceived: AttackMoveResult[] = []; public attacksReceived: AttackMoveResult[] = [];
public multipliersExtraHits: number[] = [];
} }
export enum AiType { export enum AiType {

View File

@ -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, 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, applyPostBattleInitAbAttrs, PostBattleInitAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr } from "./data/ability"; import { CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, 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, applyPostBattleInitAbAttrs, PostBattleInitAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr, ExtraHitMoveAbAttr } 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";
@ -2399,12 +2399,14 @@ export class MovePhase extends BattlePhase {
export class MoveEffectPhase extends PokemonPhase { export class MoveEffectPhase extends PokemonPhase {
public move: PokemonMove; public move: PokemonMove;
protected targets: BattlerIndex[]; protected targets: BattlerIndex[];
public multiHitId: integer;
constructor(scene: BattleScene, battlerIndex: BattlerIndex, targets: BattlerIndex[], move: PokemonMove) { constructor(scene: BattleScene, battlerIndex: BattlerIndex, targets: BattlerIndex[], move: PokemonMove, multiHitId: integer = 0) {
super(scene, battlerIndex); super(scene, battlerIndex);
this.move = move; this.move = move;
this.targets = targets; this.targets = targets;
this.multiHitId = multiHitId;
} }
start() { start() {
@ -2432,6 +2434,15 @@ export class MoveEffectPhase extends PokemonPhase {
applyMoveAttrs(MultiHitAttr, user, this.getTarget(), this.move.getMove(), hitCount); applyMoveAttrs(MultiHitAttr, user, this.getTarget(), this.move.getMove(), hitCount);
if (this.move.getMove() instanceof AttackMove && !this.move.getMove().getAttrs(FixedDamageAttr).length) if (this.move.getMove() instanceof AttackMove && !this.move.getMove().getAttrs(FixedDamageAttr).length)
this.scene.applyModifiers(PokemonMultiHitModifier, user.isPlayer(), user, hitCount, new Utils.IntegerHolder(0)); this.scene.applyModifiers(PokemonMultiHitModifier, user.isPlayer(), user, hitCount, new Utils.IntegerHolder(0));
// Check for abilities that add extra hits with damage multipliers for them
if (this.move.getMove() instanceof AttackMove) {
const multipliersHits: number[] = [];
applyAbAttrs(ExtraHitMoveAbAttr, user, null, multipliersHits);
user.turnData.multipliersExtraHits = multipliersHits;
hitCount.value *= (multipliersHits.length + 1);
}
user.turnData.hitsLeft = user.turnData.hitCount = hitCount.value; user.turnData.hitsLeft = user.turnData.hitCount = hitCount.value;
} }
@ -2475,7 +2486,9 @@ export class MoveEffectPhase extends PokemonPhase {
moveHistoryEntry.result = MoveResult.SUCCESS; moveHistoryEntry.result = MoveResult.SUCCESS;
const hitResult = !isProtected ? target.apply(user, this.move) : HitResult.NO_EFFECT; const multiHitMultiplier = this.multiHitId ? user.turnData.multipliersExtraHits[this.multiHitId - 1] ?? 1 : 1;
const hitResult = !isProtected ? target.apply(user, this.move, multiHitMultiplier) : HitResult.NO_EFFECT;
this.scene.triggerPokemonFormChange(user, SpeciesFormChangePostMoveTrigger); this.scene.triggerPokemonFormChange(user, SpeciesFormChangePostMoveTrigger);
@ -2622,7 +2635,11 @@ export class MoveEffectPhase extends PokemonPhase {
} }
getNewHitPhase() { getNewHitPhase() {
return new MoveEffectPhase(this.scene, this.battlerIndex, this.targets, this.move); const hitId = new Utils.IntegerHolder(0);
const user = this.getUserPokemon();
if (user)
hitId.value = (this.multiHitId + 1) % (user.turnData.multipliersExtraHits.length + 1);
return new MoveEffectPhase(this.scene, this.battlerIndex, this.targets, this.move, hitId.value);
} }
} }