Implement Beat Up (#593)

This commit is contained in:
Alvin Zou 2024-05-19 07:22:37 -07:00 committed by GitHub
parent 1ae5847e49
commit 608a968db4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 58 additions and 2 deletions

View File

@ -916,6 +916,7 @@ export enum MultiHitType {
_3, _3,
_3_INCR, _3_INCR,
_1_TO_10, _1_TO_10,
BEAT_UP,
} }
/** /**
@ -1233,6 +1234,11 @@ export class MultiHitAttr extends MoveAttr {
hitTimes = 10; hitTimes = 10;
} }
break; break;
case MultiHitType.BEAT_UP:
// No status means the ally pokemon can contribute to Beat Up
hitTimes = user.scene.getParty().reduce((total, pokemon) => {
return total + (pokemon.id === user.id ? 1 : pokemon?.status && pokemon.status.effect !== StatusEffect.NONE ? 0 : 1)
}, 0);
} }
(args[0] as Utils.IntegerHolder).value = hitTimes; (args[0] as Utils.IntegerHolder).value = hitTimes;
return true; return true;
@ -2051,6 +2057,45 @@ export class MovePowerMultiplierAttr extends VariablePowerAttr {
} }
} }
/**
* Helper function to calculate the the base power of an ally's hit when using Beat Up.
* @param user The Pokemon that used Beat Up.
* @param allyIndex The party position of the ally contributing to Beat Up.
* @returns The base power of the Beat Up hit.
*/
const beatUpFunc = (user: Pokemon, allyIndex: number): number => {
const party = user.scene.getParty();
for (let i = allyIndex; i < party.length; i++) {
const pokemon = party[i];
// The user contributes to Beat Up regardless of status condition.
// Allies can contribute only if they do not have a non-volatile status condition.
if (pokemon.id !== user.id && pokemon?.status && pokemon.status.effect !== StatusEffect.NONE) {
continue;
}
return (pokemon.species.getBaseStat(Stat.ATK) / 10) + 5;
}
}
export class BeatUpAttr extends VariablePowerAttr {
/**
* Gets the next party member to contribute to a Beat Up hit, and calculates the base power for it.
* @param user Pokemon that used the move
* @param _target N/A
* @param _move Move with this attribute
* @param args N/A
* @returns true if the function succeeds
*/
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const power = args[0] as Utils.NumberHolder;
const allyIndex = user.turnData.hitCount - user.turnData.hitsLeft;
power.value = beatUpFunc(user, allyIndex);
return true;
}
}
const doublePowerChanceMessageFunc = (user: Pokemon, target: Pokemon, move: Move) => { const doublePowerChanceMessageFunc = (user: Pokemon, target: Pokemon, move: Move) => {
let message: string = null; let message: string = null;
user.scene.executeWithSeedOffset(() => { user.scene.executeWithSeedOffset(() => {
@ -5156,8 +5201,9 @@ export function initMoves() {
.attr(TrapAttr, BattlerTagType.WHIRLPOOL) .attr(TrapAttr, BattlerTagType.WHIRLPOOL)
.attr(HitsTagAttr, BattlerTagType.UNDERWATER, true), .attr(HitsTagAttr, BattlerTagType.UNDERWATER, true),
new AttackMove(Moves.BEAT_UP, Type.DARK, MoveCategory.PHYSICAL, -1, 100, 10, -1, 0, 2) new AttackMove(Moves.BEAT_UP, Type.DARK, MoveCategory.PHYSICAL, -1, 100, 10, -1, 0, 2)
.makesContact(false) .attr(MultiHitAttr, MultiHitType.BEAT_UP)
.unimplemented(), .attr(BeatUpAttr)
.makesContact(false),
new AttackMove(Moves.FAKE_OUT, Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 10, 100, 3, 3) new AttackMove(Moves.FAKE_OUT, Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 10, 100, 3, 3)
.attr(FlinchAttr) .attr(FlinchAttr)
.condition(new FirstMoveCondition()), .condition(new FirstMoveCondition()),

View File

@ -16,6 +16,7 @@ import { GameMode } from '../game-mode';
import { QuantizerCelebi, argbFromRgba, rgbaFromArgb } from "@material/material-color-utilities"; import { QuantizerCelebi, argbFromRgba, rgbaFromArgb } from "@material/material-color-utilities";
import { VariantSet } from './variant'; import { VariantSet } from './variant';
import i18next, { Localizable } from '../plugins/i18n'; import i18next, { Localizable } from '../plugins/i18n';
import { Stat } from "./pokemon-stat";
export enum Region { export enum Region {
NORMAL, NORMAL,
@ -192,6 +193,15 @@ export abstract class PokemonSpeciesForm {
return false; return false;
} }
/**
* Gets the species' base stat amount for the given stat.
* @param stat The desired stat.
* @returns The species' base stat amount.
*/
getBaseStat(stat: Stat): integer {
return this.baseStats[stat]
}
getBaseExp(): integer { getBaseExp(): integer {
let ret = this.baseExp; let ret = this.baseExp;
switch (this.getFormSpriteKey()) { switch (this.getFormSpriteKey()) {