mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-20 23:32:19 +02:00
Challenge types for shop removals and reward table changes
This commit is contained in:
parent
8ba733d0c9
commit
8d29c1fb31
@ -21,6 +21,7 @@ import { TypeColor, TypeShadow } from "#enums/color";
|
|||||||
import { pokemonEvolutions } from "#app/data/balance/pokemon-evolutions";
|
import { pokemonEvolutions } from "#app/data/balance/pokemon-evolutions";
|
||||||
import { pokemonFormChanges } from "#app/data/pokemon-forms";
|
import { pokemonFormChanges } from "#app/data/pokemon-forms";
|
||||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||||
|
import type { ModifierTypeKeys, RewardTableModification } from "#app/modifier/modifier-type";
|
||||||
|
|
||||||
/** A constant for the default max cost of the starting party before a run */
|
/** A constant for the default max cost of the starting party before a run */
|
||||||
const DEFAULT_PARTY_MAX_COST = 10;
|
const DEFAULT_PARTY_MAX_COST = 10;
|
||||||
@ -105,6 +106,14 @@ export enum ChallengeType {
|
|||||||
* Negates PP Usage
|
* Negates PP Usage
|
||||||
*/
|
*/
|
||||||
NO_PP_USE,
|
NO_PP_USE,
|
||||||
|
/**
|
||||||
|
* Modifies reward table
|
||||||
|
*/
|
||||||
|
REWARD_TABLE_MODIFY,
|
||||||
|
/**
|
||||||
|
* Removes items from the shop
|
||||||
|
*/
|
||||||
|
SHOP_REMOVAL,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -457,6 +466,14 @@ export abstract class Challenge {
|
|||||||
applyNoPPUsage(_valid: Utils.BooleanHolder) {
|
applyNoPPUsage(_valid: Utils.BooleanHolder) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
applyRewardTableModify(_modifications: RewardTableModification[]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
applyShopRemovals(_removals: ModifierTypeKeys[]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChallengeCondition = (data: GameData) => boolean;
|
type ChallengeCondition = (data: GameData) => boolean;
|
||||||
@ -910,6 +927,14 @@ export class FreshStartChallenge extends Challenge {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override applyRewardTableModify(modifications: RewardTableModification[]): boolean {
|
||||||
|
modifications.push(
|
||||||
|
{ type: "EVIOLITE", tier: ModifierTier.ULTRA, maxWeight: 0 }, // No Eviolite
|
||||||
|
{ type: "MINI_BLACK_HOLE", tier: ModifierTier.MASTER, maxWeight: 0 }, // No MBH
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
override getDifficulty(): number {
|
override getDifficulty(): number {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1014,6 +1039,27 @@ export class MetronomeChallenge extends Challenge {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override applyRewardTableModify(modifications: RewardTableModification[]): boolean {
|
||||||
|
modifications.push(
|
||||||
|
{ type: "TM_COMMON", tier: ModifierTier.COMMON, maxWeight: 0 }, // Remove TMs
|
||||||
|
{ type: "ETHER", tier: ModifierTier.COMMON, maxWeight: 0 }, // Remove PP Restores
|
||||||
|
{ type: "MAX_ETHER", tier: ModifierTier.GREAT, maxWeight: 0 }, // Remove PP Restores
|
||||||
|
{ type: "ELIXIR", tier: ModifierTier.GREAT, maxWeight: 0 }, // Remove PP Restores
|
||||||
|
{ type: "MAX_ELIXIR", tier: ModifierTier.GREAT, maxWeight: 0 }, // Remove PP Restores
|
||||||
|
{ type: "PP_UP", tier: ModifierTier.GREAT, maxWeight: 0 }, // Remove PP Upgrades
|
||||||
|
{ type: "MEMORY_MUSHROOM", tier: ModifierTier.GREAT, maxWeight: 0 }, // Remove Mushrooms
|
||||||
|
{ type: "TM_GREAT", tier: ModifierTier.GREAT, maxWeight: 0 }, // Remove TMs
|
||||||
|
{ type: "TM_ULTRA", tier: ModifierTier.ULTRA, maxWeight: 0 }, // Remove TMs
|
||||||
|
{ type: "PP_MAX", tier: ModifierTier.ULTRA, maxWeight: 0 }, // Remove PP Upgrades
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
override applyShopRemovals(removals: ModifierTypeKeys[]): boolean {
|
||||||
|
removals.push("ETHER", "MAX_ETHER", "ELIXIR", "MAX_ELIXIR", "MEMORY_MUSHROOM");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static loadChallenge(source: MetronomeChallenge | any): MetronomeChallenge {
|
static loadChallenge(source: MetronomeChallenge | any): MetronomeChallenge {
|
||||||
const newChallenge = new MetronomeChallenge();
|
const newChallenge = new MetronomeChallenge();
|
||||||
newChallenge.value = source.value;
|
newChallenge.value = source.value;
|
||||||
@ -1298,6 +1344,18 @@ export function applyChallenges(
|
|||||||
valid: Utils.BooleanHolder,
|
valid: Utils.BooleanHolder,
|
||||||
): boolean;
|
): boolean;
|
||||||
|
|
||||||
|
export function applyChallenges(
|
||||||
|
gameMode: GameMode,
|
||||||
|
challengeType: ChallengeType.REWARD_TABLE_MODIFY,
|
||||||
|
modifications: RewardTableModification[],
|
||||||
|
): boolean;
|
||||||
|
|
||||||
|
export function applyChallenges(
|
||||||
|
gameMode: GameMode,
|
||||||
|
challengeType: ChallengeType.SHOP_REMOVAL,
|
||||||
|
removals: ModifierTypeKeys[],
|
||||||
|
): boolean;
|
||||||
|
|
||||||
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType, ...args: any[]): boolean {
|
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType, ...args: any[]): boolean {
|
||||||
let ret = false;
|
let ret = false;
|
||||||
gameMode.challenges.forEach(c => {
|
gameMode.challenges.forEach(c => {
|
||||||
@ -1354,6 +1412,12 @@ export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType
|
|||||||
case ChallengeType.NO_PP_USE:
|
case ChallengeType.NO_PP_USE:
|
||||||
ret ||= c.applyNoPPUsage(args[0]);
|
ret ||= c.applyNoPPUsage(args[0]);
|
||||||
break;
|
break;
|
||||||
|
case ChallengeType.REWARD_TABLE_MODIFY:
|
||||||
|
ret ||= c.applyRewardTableModify(args[0]);
|
||||||
|
break;
|
||||||
|
case ChallengeType.SHOP_REMOVAL:
|
||||||
|
ret ||= c.applyShopRemovals(args[0]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -2468,30 +2468,14 @@ const modifierPool: ModifierPool = {
|
|||||||
new WeightedModifierType(modifierTypes.LURE, lureWeightFunc(10, 2)),
|
new WeightedModifierType(modifierTypes.LURE, lureWeightFunc(10, 2)),
|
||||||
new WeightedModifierType(modifierTypes.TEMP_STAT_STAGE_BOOSTER, 4),
|
new WeightedModifierType(modifierTypes.TEMP_STAT_STAGE_BOOSTER, 4),
|
||||||
new WeightedModifierType(modifierTypes.BERRY, 2),
|
new WeightedModifierType(modifierTypes.BERRY, 2),
|
||||||
new WeightedModifierType(
|
new WeightedModifierType(modifierTypes.TM_COMMON, 2),
|
||||||
modifierTypes.TM_COMMON,
|
|
||||||
() => {
|
|
||||||
const noMoveLearning = new BooleanHolder(false);
|
|
||||||
applyChallenges(globalScene.gameMode, ChallengeType.NO_MOVE_LEARNING, noMoveLearning);
|
|
||||||
return noMoveLearning.value ? 0 : 2;
|
|
||||||
},
|
|
||||||
2,
|
|
||||||
),
|
|
||||||
].map(m => {
|
].map(m => {
|
||||||
m.setTier(ModifierTier.COMMON);
|
m.setTier(ModifierTier.COMMON);
|
||||||
return m;
|
return m;
|
||||||
}),
|
}),
|
||||||
[ModifierTier.GREAT]: [
|
[ModifierTier.GREAT]: [
|
||||||
new WeightedModifierType(modifierTypes.GREAT_BALL, () => (hasMaximumBalls(PokeballType.GREAT_BALL) ? 0 : 6), 6),
|
new WeightedModifierType(modifierTypes.GREAT_BALL, () => (hasMaximumBalls(PokeballType.GREAT_BALL) ? 0 : 6), 6),
|
||||||
new WeightedModifierType(
|
new WeightedModifierType(modifierTypes.PP_UP, 2),
|
||||||
modifierTypes.PP_UP,
|
|
||||||
() => {
|
|
||||||
const noMoveLearning = new BooleanHolder(false);
|
|
||||||
applyChallenges(globalScene.gameMode, ChallengeType.NO_PP_USE, noMoveLearning);
|
|
||||||
return noMoveLearning.value ? 0 : 2;
|
|
||||||
},
|
|
||||||
2,
|
|
||||||
),
|
|
||||||
new WeightedModifierType(
|
new WeightedModifierType(
|
||||||
modifierTypes.FULL_HEAL,
|
modifierTypes.FULL_HEAL,
|
||||||
(party: Pokemon[]) => {
|
(party: Pokemon[]) => {
|
||||||
@ -2587,11 +2571,6 @@ const modifierPool: ModifierPool = {
|
|||||||
new WeightedModifierType(
|
new WeightedModifierType(
|
||||||
modifierTypes.ELIXIR,
|
modifierTypes.ELIXIR,
|
||||||
(party: Pokemon[]) => {
|
(party: Pokemon[]) => {
|
||||||
const noMoveLearning = new BooleanHolder(false);
|
|
||||||
applyChallenges(globalScene.gameMode, ChallengeType.NO_PP_USE, noMoveLearning);
|
|
||||||
if (noMoveLearning.value) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
const thresholdPartyMemberCount = Math.min(
|
const thresholdPartyMemberCount = Math.min(
|
||||||
party.filter(
|
party.filter(
|
||||||
p =>
|
p =>
|
||||||
@ -2611,11 +2590,6 @@ const modifierPool: ModifierPool = {
|
|||||||
new WeightedModifierType(
|
new WeightedModifierType(
|
||||||
modifierTypes.MAX_ELIXIR,
|
modifierTypes.MAX_ELIXIR,
|
||||||
(party: Pokemon[]) => {
|
(party: Pokemon[]) => {
|
||||||
const noMoveLearning = new BooleanHolder(false);
|
|
||||||
applyChallenges(globalScene.gameMode, ChallengeType.NO_PP_USE, noMoveLearning);
|
|
||||||
if (noMoveLearning.value) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
const thresholdPartyMemberCount = Math.min(
|
const thresholdPartyMemberCount = Math.min(
|
||||||
party.filter(
|
party.filter(
|
||||||
p =>
|
p =>
|
||||||
@ -2648,21 +2622,11 @@ const modifierPool: ModifierPool = {
|
|||||||
2,
|
2,
|
||||||
),
|
),
|
||||||
new WeightedModifierType(modifierTypes.SOOTHE_BELL, 2),
|
new WeightedModifierType(modifierTypes.SOOTHE_BELL, 2),
|
||||||
new WeightedModifierType(
|
new WeightedModifierType(modifierTypes.TM_GREAT, 3),
|
||||||
modifierTypes.TM_GREAT,
|
|
||||||
() => {
|
|
||||||
const noMoveLearning = new BooleanHolder(false);
|
|
||||||
applyChallenges(globalScene.gameMode, ChallengeType.NO_MOVE_LEARNING, noMoveLearning);
|
|
||||||
return noMoveLearning.value ? 0 : 3;
|
|
||||||
},
|
|
||||||
3,
|
|
||||||
),
|
|
||||||
new WeightedModifierType(
|
new WeightedModifierType(
|
||||||
modifierTypes.MEMORY_MUSHROOM,
|
modifierTypes.MEMORY_MUSHROOM,
|
||||||
(party: Pokemon[]) => {
|
(party: Pokemon[]) => {
|
||||||
const noMoveLearning = new BooleanHolder(false);
|
if (!party.find(p => p.getLearnableLevelMoves().length)) {
|
||||||
applyChallenges(globalScene.gameMode, ChallengeType.NO_MOVE_LEARNING, noMoveLearning); // Yeah this is kind of dumb
|
|
||||||
if (noMoveLearning.value || !party.find(p => p.getLearnableLevelMoves().length)) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
const highestPartyLevel = party
|
const highestPartyLevel = party
|
||||||
@ -2708,15 +2672,7 @@ const modifierPool: ModifierPool = {
|
|||||||
new WeightedModifierType(modifierTypes.ULTRA_BALL, () => (hasMaximumBalls(PokeballType.ULTRA_BALL) ? 0 : 15), 15),
|
new WeightedModifierType(modifierTypes.ULTRA_BALL, () => (hasMaximumBalls(PokeballType.ULTRA_BALL) ? 0 : 15), 15),
|
||||||
new WeightedModifierType(modifierTypes.MAX_LURE, lureWeightFunc(30, 4)),
|
new WeightedModifierType(modifierTypes.MAX_LURE, lureWeightFunc(30, 4)),
|
||||||
new WeightedModifierType(modifierTypes.BIG_NUGGET, skipInLastClassicWaveOrDefault(12)),
|
new WeightedModifierType(modifierTypes.BIG_NUGGET, skipInLastClassicWaveOrDefault(12)),
|
||||||
new WeightedModifierType(
|
new WeightedModifierType(modifierTypes.PP_MAX, 3),
|
||||||
modifierTypes.PP_MAX,
|
|
||||||
() => {
|
|
||||||
const noMoveLearning = new BooleanHolder(false);
|
|
||||||
applyChallenges(globalScene.gameMode, ChallengeType.NO_PP_USE, noMoveLearning); // Yeah this is kind of dumb
|
|
||||||
return noMoveLearning.value ? 0 : 3;
|
|
||||||
},
|
|
||||||
3,
|
|
||||||
),
|
|
||||||
new WeightedModifierType(modifierTypes.MINT, 4),
|
new WeightedModifierType(modifierTypes.MINT, 4),
|
||||||
new WeightedModifierType(
|
new WeightedModifierType(
|
||||||
modifierTypes.RARE_EVOLUTION_ITEM,
|
modifierTypes.RARE_EVOLUTION_ITEM,
|
||||||
@ -2731,7 +2687,7 @@ const modifierPool: ModifierPool = {
|
|||||||
new WeightedModifierType(modifierTypes.AMULET_COIN, skipInLastClassicWaveOrDefault(3)),
|
new WeightedModifierType(modifierTypes.AMULET_COIN, skipInLastClassicWaveOrDefault(3)),
|
||||||
new WeightedModifierType(modifierTypes.EVIOLITE, (party: Pokemon[]) => {
|
new WeightedModifierType(modifierTypes.EVIOLITE, (party: Pokemon[]) => {
|
||||||
const { gameMode, gameData } = globalScene;
|
const { gameMode, gameData } = globalScene;
|
||||||
if (gameMode.isDaily || (!gameMode.isFreshStartChallenge() && gameData.isUnlocked(Unlockables.EVIOLITE))) {
|
if (gameMode.isDaily || gameData.isUnlocked(Unlockables.EVIOLITE)) {
|
||||||
return party.some(p => {
|
return party.some(p => {
|
||||||
// Check if Pokemon's species (or fusion species, if applicable) can evolve or if they're G-Max'd
|
// Check if Pokemon's species (or fusion species, if applicable) can evolve or if they're G-Max'd
|
||||||
if (
|
if (
|
||||||
@ -2861,15 +2817,7 @@ const modifierPool: ModifierPool = {
|
|||||||
new WeightedModifierType(modifierTypes.REVIVER_SEED, 4),
|
new WeightedModifierType(modifierTypes.REVIVER_SEED, 4),
|
||||||
new WeightedModifierType(modifierTypes.CANDY_JAR, skipInLastClassicWaveOrDefault(5)),
|
new WeightedModifierType(modifierTypes.CANDY_JAR, skipInLastClassicWaveOrDefault(5)),
|
||||||
new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 9),
|
new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 9),
|
||||||
new WeightedModifierType(
|
new WeightedModifierType(modifierTypes.TM_ULTRA, 11),
|
||||||
modifierTypes.TM_ULTRA,
|
|
||||||
() => {
|
|
||||||
const noMoveLearning = new BooleanHolder(false);
|
|
||||||
applyChallenges(globalScene.gameMode, ChallengeType.NO_MOVE_LEARNING, noMoveLearning); // Yeah this is kind of dumb
|
|
||||||
return noMoveLearning.value ? 0 : 11;
|
|
||||||
},
|
|
||||||
11,
|
|
||||||
),
|
|
||||||
new WeightedModifierType(modifierTypes.RARER_CANDY, 4),
|
new WeightedModifierType(modifierTypes.RARER_CANDY, 4),
|
||||||
new WeightedModifierType(modifierTypes.GOLDEN_PUNCH, skipInLastClassicWaveOrDefault(2)),
|
new WeightedModifierType(modifierTypes.GOLDEN_PUNCH, skipInLastClassicWaveOrDefault(2)),
|
||||||
new WeightedModifierType(modifierTypes.IV_SCANNER, skipInLastClassicWaveOrDefault(4)),
|
new WeightedModifierType(modifierTypes.IV_SCANNER, skipInLastClassicWaveOrDefault(4)),
|
||||||
@ -2955,11 +2903,7 @@ const modifierPool: ModifierPool = {
|
|||||||
),
|
),
|
||||||
new WeightedModifierType(
|
new WeightedModifierType(
|
||||||
modifierTypes.MINI_BLACK_HOLE,
|
modifierTypes.MINI_BLACK_HOLE,
|
||||||
() =>
|
() => (globalScene.gameMode.isDaily || globalScene.gameData.isUnlocked(Unlockables.MINI_BLACK_HOLE) ? 1 : 0),
|
||||||
globalScene.gameMode.isDaily ||
|
|
||||||
(!globalScene.gameMode.isFreshStartChallenge() && globalScene.gameData.isUnlocked(Unlockables.MINI_BLACK_HOLE))
|
|
||||||
? 1
|
|
||||||
: 0,
|
|
||||||
1,
|
1,
|
||||||
),
|
),
|
||||||
].map(m => {
|
].map(m => {
|
||||||
@ -3170,8 +3114,51 @@ const tierWeights = [768 / 1024, 195 / 1024, 48 / 1024, 12 / 1024, 1 / 1024];
|
|||||||
*/
|
*/
|
||||||
export const itemPoolChecks: Map<ModifierTypeKeys, boolean | undefined> = new Map();
|
export const itemPoolChecks: Map<ModifierTypeKeys, boolean | undefined> = new Map();
|
||||||
|
|
||||||
|
export interface RewardTableModification {
|
||||||
|
type: ModifierTypeKeys;
|
||||||
|
tier: ModifierTier;
|
||||||
|
maxWeight: number;
|
||||||
|
}
|
||||||
|
|
||||||
export function regenerateModifierPoolThresholds(party: Pokemon[], poolType: ModifierPoolType, rerollCount = 0) {
|
export function regenerateModifierPoolThresholds(party: Pokemon[], poolType: ModifierPoolType, rerollCount = 0) {
|
||||||
|
const modifications: RewardTableModification[] = [];
|
||||||
|
applyChallenges(globalScene.gameMode, ChallengeType.REWARD_TABLE_MODIFY, modifications);
|
||||||
const pool = getModifierPoolForType(poolType);
|
const pool = getModifierPoolForType(poolType);
|
||||||
|
modifications.map(mod => {
|
||||||
|
let t = mod.tier;
|
||||||
|
let dindex = pool[mod.tier].findIndex(wm => wm.modifierType.id === mod.type);
|
||||||
|
if (mod.maxWeight === 0) {
|
||||||
|
// Remove the modifier from the specified tier
|
||||||
|
pool[t].splice(dindex, 1);
|
||||||
|
} else if (dindex < 0) {
|
||||||
|
// Add the modifier to specified tier
|
||||||
|
for (t = ModifierTier.COMMON; t <= ModifierTier.MASTER && dindex < 0; t++) {
|
||||||
|
if (t === mod.tier) {
|
||||||
|
// We know it's not in that tier
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
dindex = pool[t].findIndex(wm => wm.modifierType.id === mod.type);
|
||||||
|
}
|
||||||
|
if (dindex >= 0) {
|
||||||
|
// Move the existing WMT to the specified tier with same func and specified max weight
|
||||||
|
const wmt = pool[t].splice(dindex, 1)[0];
|
||||||
|
wmt.maxWeight = mod.maxWeight;
|
||||||
|
wmt.setTier(mod.tier);
|
||||||
|
pool[mod.tier].push(wmt);
|
||||||
|
} else {
|
||||||
|
// Item isn't anywhere on the table, make a new WMT and push it
|
||||||
|
const newWMT = new WeightedModifierType(getModifierTypeFuncById(mod.type), mod.maxWeight);
|
||||||
|
newWMT.setTier(mod.tier);
|
||||||
|
pool[mod.tier].push(newWMT);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pool[t].map(wmt => {
|
||||||
|
if (wmt.modifierType.id === mod.type) {
|
||||||
|
wmt.maxWeight = mod.maxWeight;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
itemPoolChecks.forEach((_v, k) => {
|
itemPoolChecks.forEach((_v, k) => {
|
||||||
itemPoolChecks.set(k, false);
|
itemPoolChecks.set(k, false);
|
||||||
});
|
});
|
||||||
@ -3459,7 +3446,12 @@ export function getPlayerShopModifierTypeOptionsForWave(waveIndex: number, baseC
|
|||||||
[new ModifierTypeOption(modifierTypes.FULL_RESTORE(), 0, baseCost * 2.25)],
|
[new ModifierTypeOption(modifierTypes.FULL_RESTORE(), 0, baseCost * 2.25)],
|
||||||
[new ModifierTypeOption(modifierTypes.SACRED_ASH(), 0, baseCost * 10)],
|
[new ModifierTypeOption(modifierTypes.SACRED_ASH(), 0, baseCost * 10)],
|
||||||
];
|
];
|
||||||
return options.slice(0, Math.ceil(Math.max(waveIndex + 10, 0) / 30)).flat();
|
const removeShop: ModifierTypeKeys[] = [];
|
||||||
|
applyChallenges(globalScene.gameMode, ChallengeType.SHOP_REMOVAL, removeShop);
|
||||||
|
return options
|
||||||
|
.slice(0, Math.ceil(Math.max(waveIndex + 10, 0) / 30))
|
||||||
|
.flat()
|
||||||
|
.filter(s => !removeShop.includes(s.type.id as ModifierTypeKeys));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getEnemyBuffModifierForWave(
|
export function getEnemyBuffModifierForWave(
|
||||||
|
Loading…
Reference in New Issue
Block a user