This commit is contained in:
Madmadness65 2025-01-16 20:55:23 -08:00 committed by GitHub
commit 8a14fab8f5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 44 additions and 37 deletions

View File

@ -9,10 +9,10 @@ import { Nature } from "#enums/nature";
import { Biome } from "#enums/biome";
import { Moves } from "#enums/moves";
import { Species } from "#enums/species";
import { TimeOfDay } from "#enums/time-of-day";
import { DamageMoneyRewardModifier, ExtraModifierModifier, MoneyMultiplierModifier, TempExtraModifierModifier } from "#app/modifier/modifier";
import { SpeciesFormKey } from "#enums/species-form-key";
import { TimeOfDay } from "#enums/time-of-day";
import { DamageMoneyRewardModifier, ExtraModifierModifier, MoneyMultiplierModifier, SpeciesStatBoosterModifier, TempExtraModifierModifier } from "#app/modifier/modifier";
import type { SpeciesStatBoosterModifierType } from "#app/modifier/modifier-type";
export enum SpeciesWildEvolutionDelay {
NONE,
@ -1572,8 +1572,8 @@ export const pokemonEvolutions: PokemonEvolutions = {
new SpeciesEvolution(Species.DUSKNOIR, 1, EvolutionItem.REAPER_CLOTH, null, SpeciesWildEvolutionDelay.VERY_LONG)
],
[Species.CLAMPERL]: [
new SpeciesEvolution(Species.HUNTAIL, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition(p => p.gender === Gender.MALE, p => p.gender = Gender.MALE /* Deep Sea Tooth */), SpeciesWildEvolutionDelay.VERY_LONG),
new SpeciesEvolution(Species.GOREBYSS, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition(p => p.gender === Gender.FEMALE, p => p.gender = Gender.FEMALE /* Deep Sea Scale */), SpeciesWildEvolutionDelay.VERY_LONG)
new SpeciesEvolution(Species.HUNTAIL, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition(p => !!globalScene.findModifier(m => m instanceof SpeciesStatBoosterModifier && (m.type as SpeciesStatBoosterModifierType).key === "DEEP_SEA_TOOTH")), SpeciesWildEvolutionDelay.VERY_LONG),
new SpeciesEvolution(Species.GOREBYSS, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition(p => !!globalScene.findModifier(m => m instanceof SpeciesStatBoosterModifier && (m.type as SpeciesStatBoosterModifierType).key === "DEEP_SEA_SCALE")), SpeciesWildEvolutionDelay.VERY_LONG)
],
[Species.BOLDORE]: [
new SpeciesEvolution(Species.GIGALITH, 1, EvolutionItem.LINKING_CORD, null, SpeciesWildEvolutionDelay.VERY_LONG)

View File

@ -584,7 +584,7 @@ export type SpeciesStatBoosterItem = keyof typeof SpeciesStatBoosterModifierType
* @implements GeneratedPersistentModifierType
*/
export class SpeciesStatBoosterModifierType extends PokemonHeldItemModifierType implements GeneratedPersistentModifierType {
private key: SpeciesStatBoosterItem;
public key: SpeciesStatBoosterItem;
constructor(key: SpeciesStatBoosterItem) {
const item = SpeciesStatBoosterModifierTypeGenerator.items[key];
@ -1023,13 +1023,15 @@ class TempStatStageBoosterModifierTypeGenerator extends ModifierTypeGenerator {
class SpeciesStatBoosterModifierTypeGenerator extends ModifierTypeGenerator {
/** Object comprised of the currently available species-based stat boosting held items */
public static readonly items = {
LIGHT_BALL: { stats: [ Stat.ATK, Stat.SPATK ], multiplier: 2, species: [ Species.PIKACHU ]},
THICK_CLUB: { stats: [ Stat.ATK ], multiplier: 2, species: [ Species.CUBONE, Species.MAROWAK, Species.ALOLA_MAROWAK ]},
METAL_POWDER: { stats: [ Stat.DEF ], multiplier: 2, species: [ Species.DITTO ]},
QUICK_POWDER: { stats: [ Stat.SPD ], multiplier: 2, species: [ Species.DITTO ]},
LIGHT_BALL: { stats: [ Stat.ATK, Stat.SPATK ], multiplier: 2, species: [ Species.PIKACHU ], rare: true },
THICK_CLUB: { stats: [ Stat.ATK ], multiplier: 2, species: [ Species.CUBONE, Species.MAROWAK, Species.ALOLA_MAROWAK ], rare: true },
METAL_POWDER: { stats: [ Stat.DEF ], multiplier: 2, species: [ Species.DITTO ], rare: true },
QUICK_POWDER: { stats: [ Stat.SPD ], multiplier: 2, species: [ Species.DITTO ], rare: true },
DEEP_SEA_SCALE: { stats: [ Stat.SPDEF ], multiplier: 2, species: [ Species.CLAMPERL ], rare: false },
DEEP_SEA_TOOTH: { stats: [ Stat.SPATK ], multiplier: 2, species: [ Species.CLAMPERL ], rare: false },
};
constructor() {
constructor(rare: boolean) {
super((party: Pokemon[], pregenArgs?: any[]) => {
const items = SpeciesStatBoosterModifierTypeGenerator.items;
if (pregenArgs && (pregenArgs.length === 1) && (pregenArgs[0] in items)) {
@ -1056,6 +1058,9 @@ class SpeciesStatBoosterModifierTypeGenerator extends ModifierTypeGenerator {
if (!hasItem) {
if (checkedSpecies.includes(speciesId) || (!!fusionSpeciesId && checkedSpecies.includes(fusionSpeciesId))) {
if (values[i].rare === true) {
rare === true;
}
// Add weight if party member has a matching species or, if applicable, a matching fusion species
weights[i]++;
} else if (checkedSpecies.includes(Species.PIKACHU) && hasFling) {
@ -1339,7 +1344,7 @@ export type GeneratorModifierOverride = {
count?: number;
} & (
| {
name: keyof Pick<typeof modifierTypes, "SPECIES_STAT_BOOSTER">;
name: keyof Pick<typeof modifierTypes, "SPECIES_STAT_BOOSTER" | "RARE_SPECIES_STAT_BOOSTER">;
type?: SpeciesStatBoosterItem;
}
| {
@ -1367,7 +1372,7 @@ export type GeneratorModifierOverride = {
type?: EvolutionItem;
}
| {
name: keyof Pick<typeof modifierTypes, "FORM_CHANGE_ITEM">;
name: keyof Pick<typeof modifierTypes, "FORM_CHANGE_ITEM" | "RARE_FORM_CHANGE_ITEM">;
type?: FormChangeItem;
}
| {
@ -1438,7 +1443,8 @@ export const modifierTypes = {
SUPER_LURE: () => new DoubleBattleChanceBoosterModifierType("modifierType:ModifierType.SUPER_LURE", "super_lure", 15),
MAX_LURE: () => new DoubleBattleChanceBoosterModifierType("modifierType:ModifierType.MAX_LURE", "max_lure", 30),
SPECIES_STAT_BOOSTER: () => new SpeciesStatBoosterModifierTypeGenerator(),
SPECIES_STAT_BOOSTER: () => new SpeciesStatBoosterModifierTypeGenerator(false),
RARE_SPECIES_STAT_BOOSTER: () => new SpeciesStatBoosterModifierTypeGenerator(true),
TEMP_STAT_STAGE_BOOSTER: () => new TempStatStageBoosterModifierTypeGenerator(),
@ -1705,6 +1711,7 @@ const modifierPool: ModifierPool = {
new WeightedModifierType(modifierTypes.DIRE_HIT, 4),
new WeightedModifierType(modifierTypes.SUPER_LURE, lureWeightFunc(15, 4)),
new WeightedModifierType(modifierTypes.NUGGET, skipInLastClassicWaveOrDefault(5)),
new WeightedModifierType(modifierTypes.SPECIES_STAT_BOOSTER, 4),
new WeightedModifierType(modifierTypes.EVOLUTION_ITEM, () => {
return Math.min(Math.ceil(globalScene.currentBattle.waveIndex / 15), 8);
}, 8),
@ -1748,7 +1755,7 @@ const modifierPool: ModifierPool = {
}
return 0;
}),
new WeightedModifierType(modifierTypes.SPECIES_STAT_BOOSTER, 12),
new WeightedModifierType(modifierTypes.RARE_SPECIES_STAT_BOOSTER, 12),
new WeightedModifierType(modifierTypes.LEEK, (party: Pokemon[]) => {
const checkedSpecies = [ Species.FARFETCHD, Species.GALAR_FARFETCHD, Species.SIRFETCHD ];
// If a party member doesn't already have a Leek and is one of the relevant species, Leek can appear

View File

@ -29,7 +29,7 @@ describe("Items - Light Ball", () => {
});
it("LIGHT_BALL activates in battle correctly", async() => {
game.override.startingHeldItems([{ name: "SPECIES_STAT_BOOSTER", type: "LIGHT_BALL" }]);
game.override.startingHeldItems([{ name: "RARE_SPECIES_STAT_BOOSTER", type: "LIGHT_BALL" }]);
const consoleSpy = vi.spyOn(console, "log");
await game.startBattle([
Species.PIKACHU
@ -83,7 +83,7 @@ describe("Items - Light Ball", () => {
expect(spAtkValue.value / spAtkStat).toBe(1);
// Giving Eviolite to party member and testing if it applies
game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "LIGHT_BALL" ])!.newModifier(partyMember), true);
game.scene.addModifier(modifierTypes.RARE_SPECIES_STAT_BOOSTER().generateType([], [ "LIGHT_BALL" ])!.newModifier(partyMember), true);
game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue);
game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.SPATK, spAtkValue);
@ -122,7 +122,7 @@ describe("Items - Light Ball", () => {
expect(spAtkValue.value / spAtkStat).toBe(1);
// Giving Eviolite to party member and testing if it applies
game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "LIGHT_BALL" ])!.newModifier(partyMember), true);
game.scene.addModifier(modifierTypes.RARE_SPECIES_STAT_BOOSTER().generateType([], [ "LIGHT_BALL" ])!.newModifier(partyMember), true);
game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue);
game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.SPATK, spAtkValue);
@ -161,7 +161,7 @@ describe("Items - Light Ball", () => {
expect(spAtkValue.value / spAtkStat).toBe(1);
// Giving Eviolite to party member and testing if it applies
game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "LIGHT_BALL" ])!.newModifier(partyMember), true);
game.scene.addModifier(modifierTypes.RARE_SPECIES_STAT_BOOSTER().generateType([], [ "LIGHT_BALL" ])!.newModifier(partyMember), true);
game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue);
game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.SPATK, spAtkValue);
@ -189,7 +189,7 @@ describe("Items - Light Ball", () => {
expect(spAtkValue.value / spAtkStat).toBe(1);
// Giving Eviolite to party member and testing if it applies
game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "LIGHT_BALL" ])!.newModifier(partyMember), true);
game.scene.addModifier(modifierTypes.RARE_SPECIES_STAT_BOOSTER().generateType([], [ "LIGHT_BALL" ])!.newModifier(partyMember), true);
game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue);
game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.SPATK, spAtkValue);

View File

@ -29,7 +29,7 @@ describe("Items - Metal Powder", () => {
});
it("METAL_POWDER activates in battle correctly", async() => {
game.override.startingHeldItems([{ name: "SPECIES_STAT_BOOSTER", type: "METAL_POWDER" }]);
game.override.startingHeldItems([{ name: "RARE_SPECIES_STAT_BOOSTER", type: "METAL_POWDER" }]);
const consoleSpy = vi.spyOn(console, "log");
await game.startBattle([
Species.DITTO
@ -79,7 +79,7 @@ describe("Items - Metal Powder", () => {
expect(defValue.value / defStat).toBe(1);
// Giving Eviolite to party member and testing if it applies
game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "METAL_POWDER" ])!.newModifier(partyMember), true);
game.scene.addModifier(modifierTypes.RARE_SPECIES_STAT_BOOSTER().generateType([], [ "METAL_POWDER" ])!.newModifier(partyMember), true);
game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.DEF, defValue);
expect(defValue.value / defStat).toBe(2);
@ -112,7 +112,7 @@ describe("Items - Metal Powder", () => {
expect(defValue.value / defStat).toBe(1);
// Giving Eviolite to party member and testing if it applies
game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "METAL_POWDER" ])!.newModifier(partyMember), true);
game.scene.addModifier(modifierTypes.RARE_SPECIES_STAT_BOOSTER().generateType([], [ "METAL_POWDER" ])!.newModifier(partyMember), true);
game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.DEF, defValue);
expect(defValue.value / defStat).toBe(2);
@ -145,7 +145,7 @@ describe("Items - Metal Powder", () => {
expect(defValue.value / defStat).toBe(1);
// Giving Eviolite to party member and testing if it applies
game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "METAL_POWDER" ])!.newModifier(partyMember), true);
game.scene.addModifier(modifierTypes.RARE_SPECIES_STAT_BOOSTER().generateType([], [ "METAL_POWDER" ])!.newModifier(partyMember), true);
game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.DEF, defValue);
expect(defValue.value / defStat).toBe(2);
@ -167,7 +167,7 @@ describe("Items - Metal Powder", () => {
expect(defValue.value / defStat).toBe(1);
// Giving Eviolite to party member and testing if it applies
game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "METAL_POWDER" ])!.newModifier(partyMember), true);
game.scene.addModifier(modifierTypes.RARE_SPECIES_STAT_BOOSTER().generateType([], [ "METAL_POWDER" ])!.newModifier(partyMember), true);
game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.DEF, defValue);
expect(defValue.value / defStat).toBe(1);

View File

@ -29,7 +29,7 @@ describe("Items - Quick Powder", () => {
});
it("QUICK_POWDER activates in battle correctly", async() => {
game.override.startingHeldItems([{ name: "SPECIES_STAT_BOOSTER", type: "QUICK_POWDER" }]);
game.override.startingHeldItems([{ name: "RARE_SPECIES_STAT_BOOSTER", type: "QUICK_POWDER" }]);
const consoleSpy = vi.spyOn(console, "log");
await game.startBattle([
Species.DITTO
@ -79,7 +79,7 @@ describe("Items - Quick Powder", () => {
expect(spdValue.value / spdStat).toBe(1);
// Giving Eviolite to party member and testing if it applies
game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "QUICK_POWDER" ])!.newModifier(partyMember), true);
game.scene.addModifier(modifierTypes.RARE_SPECIES_STAT_BOOSTER().generateType([], [ "QUICK_POWDER" ])!.newModifier(partyMember), true);
game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.SPD, spdValue);
expect(spdValue.value / spdStat).toBe(2);
@ -112,7 +112,7 @@ describe("Items - Quick Powder", () => {
expect(spdValue.value / spdStat).toBe(1);
// Giving Eviolite to party member and testing if it applies
game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "QUICK_POWDER" ])!.newModifier(partyMember), true);
game.scene.addModifier(modifierTypes.RARE_SPECIES_STAT_BOOSTER().generateType([], [ "QUICK_POWDER" ])!.newModifier(partyMember), true);
game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.SPD, spdValue);
expect(spdValue.value / spdStat).toBe(2);
@ -145,7 +145,7 @@ describe("Items - Quick Powder", () => {
expect(spdValue.value / spdStat).toBe(1);
// Giving Eviolite to party member and testing if it applies
game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "QUICK_POWDER" ])!.newModifier(partyMember), true);
game.scene.addModifier(modifierTypes.RARE_SPECIES_STAT_BOOSTER().generateType([], [ "QUICK_POWDER" ])!.newModifier(partyMember), true);
game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.SPD, spdValue);
expect(spdValue.value / spdStat).toBe(2);
@ -167,7 +167,7 @@ describe("Items - Quick Powder", () => {
expect(spdValue.value / spdStat).toBe(1);
// Giving Eviolite to party member and testing if it applies
game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "QUICK_POWDER" ])!.newModifier(partyMember), true);
game.scene.addModifier(modifierTypes.RARE_SPECIES_STAT_BOOSTER().generateType([], [ "QUICK_POWDER" ])!.newModifier(partyMember), true);
game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.SPD, spdValue);
expect(spdValue.value / spdStat).toBe(1);

View File

@ -29,7 +29,7 @@ describe("Items - Thick Club", () => {
});
it("THICK_CLUB activates in battle correctly", async() => {
game.override.startingHeldItems([{ name: "SPECIES_STAT_BOOSTER", type: "THICK_CLUB" }]);
game.override.startingHeldItems([{ name: "RARE_SPECIES_STAT_BOOSTER", type: "THICK_CLUB" }]);
const consoleSpy = vi.spyOn(console, "log");
await game.startBattle([
Species.CUBONE
@ -79,7 +79,7 @@ describe("Items - Thick Club", () => {
expect(atkValue.value / atkStat).toBe(1);
// Giving Eviolite to party member and testing if it applies
game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true);
game.scene.addModifier(modifierTypes.RARE_SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true);
game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue);
expect(atkValue.value / atkStat).toBe(2);
@ -101,7 +101,7 @@ describe("Items - Thick Club", () => {
expect(atkValue.value / atkStat).toBe(1);
// Giving Eviolite to party member and testing if it applies
game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true);
game.scene.addModifier(modifierTypes.RARE_SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true);
game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue);
expect(atkValue.value / atkStat).toBe(2);
@ -123,7 +123,7 @@ describe("Items - Thick Club", () => {
expect(atkValue.value / atkStat).toBe(1);
// Giving Eviolite to party member and testing if it applies
game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true);
game.scene.addModifier(modifierTypes.RARE_SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true);
game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue);
expect(atkValue.value / atkStat).toBe(2);
@ -160,7 +160,7 @@ describe("Items - Thick Club", () => {
expect(atkValue.value / atkStat).toBe(1);
// Giving Eviolite to party member and testing if it applies
game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true);
game.scene.addModifier(modifierTypes.RARE_SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true);
game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue);
expect(atkValue.value / atkStat).toBe(2);
@ -197,7 +197,7 @@ describe("Items - Thick Club", () => {
expect(atkValue.value / atkStat).toBe(1);
// Giving Eviolite to party member and testing if it applies
game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true);
game.scene.addModifier(modifierTypes.RARE_SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true);
game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue);
expect(atkValue.value / atkStat).toBe(2);
@ -219,7 +219,7 @@ describe("Items - Thick Club", () => {
expect(atkValue.value / atkStat).toBe(1);
// Giving Eviolite to party member and testing if it applies
game.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true);
game.scene.addModifier(modifierTypes.RARE_SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true);
game.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue);
expect(atkValue.value / atkStat).toBe(1);