mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-10-09 14:47:12 +02:00
Converted White Herb
This commit is contained in:
parent
cf19a01c37
commit
41a4c9ec2d
@ -39,7 +39,7 @@ export class PokemonItemManager {
|
||||
return itemType in this.getHeldItems() ? this.heldItems[itemType].stack : 0;
|
||||
}
|
||||
|
||||
addHeldItem(itemType: HeldItems, addStack = 1) {
|
||||
add(itemType: HeldItems, addStack = 1) {
|
||||
const maxStack = allHeldItems[itemType].getMaxStackCount();
|
||||
|
||||
if (this.hasItem(itemType)) {
|
||||
@ -49,4 +49,12 @@ export class PokemonItemManager {
|
||||
this.heldItems[itemType] = { stack: Math.min(addStack, maxStack), disabled: false };
|
||||
}
|
||||
}
|
||||
|
||||
remove(itemType: HeldItems, removeStack = 1) {
|
||||
this.heldItems[itemType].stack -= removeStack;
|
||||
|
||||
if (this.heldItems[itemType].stack <= 0) {
|
||||
delete this.heldItems[itemType];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -107,3 +107,20 @@ export class HeldItem {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
export class ConsumableHeldItem extends HeldItem {
|
||||
applyConsumable(_pokemon: Pokemon): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
apply(pokemon: Pokemon): boolean {
|
||||
const consumed = this.applyConsumable(pokemon);
|
||||
|
||||
if (consumed) {
|
||||
pokemon.heldItemManager.remove(this.type, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
70
src/items/held-items/reset-negative-stat-stage.ts
Normal file
70
src/items/held-items/reset-negative-stat-stage.ts
Normal file
@ -0,0 +1,70 @@
|
||||
import type Pokemon from "#app/field/pokemon";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { BATTLE_STATS } from "#enums/stat";
|
||||
import i18next from "i18next";
|
||||
import { ConsumableHeldItem } from "../held-item";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { allHeldItems } from "../all-held-items";
|
||||
|
||||
/**
|
||||
* Modifier used for held items, namely White Herb, that restore adverse stat
|
||||
* stages in battle.
|
||||
* @extends PokemonHeldItemModifier
|
||||
* @see {@linkcode apply}
|
||||
*/
|
||||
export class ResetNegativeStatStageHeldItem extends ConsumableHeldItem {
|
||||
get name(): string {
|
||||
return i18next.t("modifierType:ModifierType.WHITE_HERB.name");
|
||||
}
|
||||
|
||||
get description(): string {
|
||||
return i18next.t("modifierType:ModifierType.WHITE_HERB.description");
|
||||
}
|
||||
|
||||
get icon(): string {
|
||||
return "shell_bell";
|
||||
}
|
||||
/**
|
||||
* Goes through the holder's stat stages and, if any are negative, resets that
|
||||
* stat stage back to 0.
|
||||
* @param pokemon {@linkcode Pokemon} that holds the item
|
||||
* @returns `true` if any stat stages were reset, false otherwise
|
||||
*/
|
||||
applyConsumable(pokemon: Pokemon): boolean {
|
||||
let statRestored = false;
|
||||
|
||||
for (const s of BATTLE_STATS) {
|
||||
if (pokemon.getStatStage(s) < 0) {
|
||||
pokemon.setStatStage(s, 0);
|
||||
statRestored = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (statRestored) {
|
||||
globalScene.queueMessage(
|
||||
i18next.t("modifier:resetNegativeStatStageApply", {
|
||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||
typeName: this.name,
|
||||
}),
|
||||
);
|
||||
}
|
||||
return statRestored;
|
||||
}
|
||||
|
||||
getMaxHeldItemCount(_pokemon: Pokemon): number {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Do we need this to return true/false?
|
||||
export function applyResetNegativeStatStageHeldItem(pokemon: Pokemon): boolean {
|
||||
let applied = false;
|
||||
if (pokemon) {
|
||||
for (const item of Object.keys(pokemon.heldItemManager.getHeldItems())) {
|
||||
if (allHeldItems[item] instanceof ResetNegativeStatStageHeldItem) {
|
||||
applied ||= allHeldItems[item].apply(pokemon);
|
||||
}
|
||||
}
|
||||
}
|
||||
return applied;
|
||||
}
|
@ -2096,6 +2096,14 @@ export const modifierTypes = {
|
||||
"reviver_seed",
|
||||
(type, args) => new PokemonInstantReviveModifier(type, (args[0] as Pokemon).id),
|
||||
),
|
||||
|
||||
WHITE_HERB_REWARD: () =>
|
||||
new PokemonHeldItemReward(
|
||||
HeldItems.WHITE_HERB,
|
||||
(type, args) => new ResetNegativeStatStageModifier(type, (args[0] as Pokemon).id),
|
||||
),
|
||||
|
||||
// TODO: Remove the old one
|
||||
WHITE_HERB: () =>
|
||||
new PokemonHeldItemModifierType(
|
||||
"modifierType:ModifierType.WHITE_HERB",
|
||||
@ -3140,7 +3148,7 @@ const wildModifierPool: ModifierPool = {
|
||||
}),
|
||||
[ModifierTier.ULTRA]: [
|
||||
new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 10),
|
||||
new WeightedModifierType(modifierTypes.WHITE_HERB, 0),
|
||||
new WeightedModifierType(modifierTypes.WHITE_HERB_REWARD, 0),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.ULTRA);
|
||||
return m;
|
||||
@ -3685,13 +3693,12 @@ export function getEnemyHeldItemsForWave(
|
||||
poolType: ModifierPoolType.WILD | ModifierPoolType.TRAINER,
|
||||
upgradeChance = 0,
|
||||
): PokemonHeldItemReward[] {
|
||||
const ret = new Array(count)
|
||||
.fill(0)
|
||||
.map(
|
||||
() =>
|
||||
getNewModifierTypeOption(party, poolType, undefined, upgradeChance && !randSeedInt(upgradeChance) ? 1 : 0)
|
||||
?.type as PokemonHeldItemReward,
|
||||
);
|
||||
const ret = new Array(count).fill(0).map(
|
||||
() =>
|
||||
// TODO: Change this to get held items (this function really could just return a list of ids honestly)
|
||||
getNewModifierTypeOption(party, poolType, undefined, upgradeChance && !randSeedInt(upgradeChance) ? 1 : 0)
|
||||
?.type as PokemonHeldItemReward,
|
||||
);
|
||||
if (!(waveIndex % 1000)) {
|
||||
// TODO: Change this line with the actual held item when implemented
|
||||
ret.push(getModifierType(modifierTypes.MINI_BLACK_HOLE) as PokemonHeldItemReward);
|
||||
@ -3740,13 +3747,53 @@ export function getDailyRunStarterModifiers(party: PlayerPokemon[]): PokemonHeld
|
||||
function getNewModifierTypeOption(
|
||||
party: Pokemon[],
|
||||
poolType: ModifierPoolType,
|
||||
tier?: ModifierTier,
|
||||
baseTier?: ModifierTier,
|
||||
upgradeCount?: number,
|
||||
retryCount = 0,
|
||||
allowLuckUpgrades = true,
|
||||
): ModifierTypeOption | null {
|
||||
const player = !poolType;
|
||||
const pool = getModifierPoolForType(poolType);
|
||||
const thresholds = getPoolThresholds(poolType);
|
||||
|
||||
const tier = determineTier(party, player, baseTier, upgradeCount, retryCount, allowLuckUpgrades);
|
||||
|
||||
const tierThresholds = Object.keys(thresholds[tier]);
|
||||
const totalWeight = Number.parseInt(tierThresholds[tierThresholds.length - 1]);
|
||||
const value = randSeedInt(totalWeight);
|
||||
let index: number | undefined;
|
||||
for (const t of tierThresholds) {
|
||||
const threshold = Number.parseInt(t);
|
||||
if (value < threshold) {
|
||||
index = thresholds[tier][threshold];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (player) {
|
||||
console.log(index, ignoredPoolIndexes[tier].filter(i => i <= index).length, ignoredPoolIndexes[tier]);
|
||||
}
|
||||
let modifierType: ModifierType | null = pool[tier][index].modifierType;
|
||||
if (modifierType instanceof ModifierTypeGenerator) {
|
||||
modifierType = (modifierType as ModifierTypeGenerator).generateType(party);
|
||||
if (modifierType === null) {
|
||||
if (player) {
|
||||
console.log(ModifierTier[tier], upgradeCount);
|
||||
}
|
||||
return getNewModifierTypeOption(party, poolType, tier, upgradeCount, ++retryCount);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(modifierType, !player ? "(enemy)" : "");
|
||||
|
||||
return new ModifierTypeOption(modifierType as ModifierType, upgradeCount!); // TODO: is this bang correct?
|
||||
}
|
||||
|
||||
function getPoolThresholds(poolType: ModifierPoolType) {
|
||||
let thresholds: object;
|
||||
switch (poolType) {
|
||||
case ModifierPoolType.PLAYER:
|
||||
@ -3765,6 +3812,17 @@ function getNewModifierTypeOption(
|
||||
thresholds = dailyStarterModifierPoolThresholds;
|
||||
break;
|
||||
}
|
||||
return thresholds;
|
||||
}
|
||||
|
||||
function determineTier(
|
||||
party: Pokemon[],
|
||||
player: boolean,
|
||||
tier?: ModifierTier,
|
||||
upgradeCount?: number,
|
||||
retryCount = 0,
|
||||
allowLuckUpgrades = true,
|
||||
): ModifierTier {
|
||||
if (tier === undefined) {
|
||||
const tierValue = randSeedInt(1024);
|
||||
if (!upgradeCount) {
|
||||
@ -3819,40 +3877,7 @@ function getNewModifierTypeOption(
|
||||
retryCount = 0;
|
||||
tier--;
|
||||
}
|
||||
|
||||
const tierThresholds = Object.keys(thresholds[tier]);
|
||||
const totalWeight = Number.parseInt(tierThresholds[tierThresholds.length - 1]);
|
||||
const value = randSeedInt(totalWeight);
|
||||
let index: number | undefined;
|
||||
for (const t of tierThresholds) {
|
||||
const threshold = Number.parseInt(t);
|
||||
if (value < threshold) {
|
||||
index = thresholds[tier][threshold];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (player) {
|
||||
console.log(index, ignoredPoolIndexes[tier].filter(i => i <= index).length, ignoredPoolIndexes[tier]);
|
||||
}
|
||||
let modifierType: ModifierType | null = pool[tier][index].modifierType;
|
||||
if (modifierType instanceof ModifierTypeGenerator) {
|
||||
modifierType = (modifierType as ModifierTypeGenerator).generateType(party);
|
||||
if (modifierType === null) {
|
||||
if (player) {
|
||||
console.log(ModifierTier[tier], upgradeCount);
|
||||
}
|
||||
return getNewModifierTypeOption(party, poolType, tier, upgradeCount, ++retryCount);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(modifierType, !player ? "(enemy)" : "");
|
||||
|
||||
return new ModifierTypeOption(modifierType as ModifierType, upgradeCount!); // TODO: is this bang correct?
|
||||
return tier;
|
||||
}
|
||||
|
||||
export function getDefaultModifierTypeForTier(tier: ModifierTier): ModifierType {
|
||||
|
@ -359,7 +359,7 @@ export class SelectModifierPhase extends BattlePhase {
|
||||
(slotIndex: number, _option: PartyOption) => {
|
||||
if (slotIndex < 6) {
|
||||
globalScene.ui.setMode(UiMode.MODIFIER_SELECT, this.isPlayer()).then(() => {
|
||||
party[slotIndex].heldItemManager.addHeldItem(reward.itemId);
|
||||
party[slotIndex].heldItemManager.add(reward.itemId);
|
||||
globalScene.ui.clearText();
|
||||
globalScene.ui.setMode(UiMode.MESSAGE);
|
||||
super.end();
|
||||
|
@ -15,7 +15,6 @@ import { ArenaTagSide, MistTag } from "#app/data/arena-tag";
|
||||
import type { ArenaTag } from "#app/data/arena-tag";
|
||||
import type Pokemon from "#app/field/pokemon";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { ResetNegativeStatStageModifier } from "#app/modifier/modifier";
|
||||
import { handleTutorial, Tutorial } from "#app/tutorial";
|
||||
import { NumberHolder, BooleanHolder, isNullOrUndefined } from "#app/utils/common";
|
||||
import i18next from "i18next";
|
||||
@ -23,6 +22,7 @@ import { PokemonPhase } from "./pokemon-phase";
|
||||
import { Stat, type BattleStat, getStatKey, getStatStageChangeDescriptionKey } from "#enums/stat";
|
||||
import { OctolockTag } from "#app/data/battler-tags";
|
||||
import { ArenaTagType } from "#app/enums/arena-tag-type";
|
||||
import { applyResetNegativeStatStageHeldItem } from "#app/items/held-items/reset-negative-stat-stage";
|
||||
|
||||
export type StatStageChangeCallback = (
|
||||
target: Pokemon | null,
|
||||
@ -239,14 +239,9 @@ export class StatStageChangePhase extends PokemonPhase {
|
||||
);
|
||||
if (!(existingPhase instanceof StatStageChangePhase)) {
|
||||
// Apply White Herb if needed
|
||||
const whiteHerb = globalScene.applyModifier(
|
||||
ResetNegativeStatStageModifier,
|
||||
this.player,
|
||||
pokemon,
|
||||
) as ResetNegativeStatStageModifier;
|
||||
// If the White Herb was applied, consume it
|
||||
const whiteHerb = applyResetNegativeStatStageHeldItem(pokemon);
|
||||
// If the White Herb was applied, update scene modifiers
|
||||
if (whiteHerb) {
|
||||
pokemon.loseHeldItem(whiteHerb);
|
||||
globalScene.updateModifiers(this.player);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user