mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-06-20 16:42:45 +02:00
* Update slumbering-snorlax-encounter.ts * Add Slumbering Snorlax to Tall Grass, remove Absolute Avarice from Plains * Update absolute-avarice-encounter.ts * Update absolute-avarice-encounter.ts * Update slumbering-snorlax-encounter.ts * Update slumbering-snorlax-encounter.ts * Update the-expert-pokemon-breeder-encounter.ts * Update slumbering-snorlax-encounter.ts nature * Update bug-type-superfan-encounter.ts move reward * Update bug-type-superfan-encounter.ts moves again * fix encounter waves * Update absolute-avarice-encounter.test.ts * add Nature import * Update bug-type-superfan-encounter.test.ts * greedent moves * test moves * Updated mysterious-chest-encounter.ts trap/reward chance * swapped Macho Brace stats, +2 / 10% for HP stats and +1 / 5% for all else * Update bug-type-superfan-encounter.ts moves * Update the-expert-pokemon-breeder-encounter.ts tera * Update bug-type-superfan-encounter.test.ts fix test
351 lines
15 KiB
TypeScript
351 lines
15 KiB
TypeScript
import { Biome } from "#enums/biome";
|
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
|
import { DarkDealEncounter } from "./encounters/dark-deal-encounter";
|
|
import { DepartmentStoreSaleEncounter } from "./encounters/department-store-sale-encounter";
|
|
import { FieldTripEncounter } from "./encounters/field-trip-encounter";
|
|
import { FightOrFlightEncounter } from "./encounters/fight-or-flight-encounter";
|
|
import { LostAtSeaEncounter } from "./encounters/lost-at-sea-encounter";
|
|
import { MysteriousChallengersEncounter } from "./encounters/mysterious-challengers-encounter";
|
|
import { MysteriousChestEncounter } from "./encounters/mysterious-chest-encounter";
|
|
import { ShadyVitaminDealerEncounter } from "./encounters/shady-vitamin-dealer-encounter";
|
|
import { SlumberingSnorlaxEncounter } from "./encounters/slumbering-snorlax-encounter";
|
|
import { TrainingSessionEncounter } from "./encounters/training-session-encounter";
|
|
import type MysteryEncounter from "./mystery-encounter";
|
|
import { SafariZoneEncounter } from "#app/data/mystery-encounters/encounters/safari-zone-encounter";
|
|
import { FieryFalloutEncounter } from "#app/data/mystery-encounters/encounters/fiery-fallout-encounter";
|
|
import { TheStrongStuffEncounter } from "#app/data/mystery-encounters/encounters/the-strong-stuff-encounter";
|
|
import { ThePokemonSalesmanEncounter } from "#app/data/mystery-encounters/encounters/the-pokemon-salesman-encounter";
|
|
import { AnOfferYouCantRefuseEncounter } from "#app/data/mystery-encounters/encounters/an-offer-you-cant-refuse-encounter";
|
|
import { DelibirdyEncounter } from "#app/data/mystery-encounters/encounters/delibirdy-encounter";
|
|
import { AbsoluteAvariceEncounter } from "#app/data/mystery-encounters/encounters/absolute-avarice-encounter";
|
|
import { ATrainersTestEncounter } from "#app/data/mystery-encounters/encounters/a-trainers-test-encounter";
|
|
import { TrashToTreasureEncounter } from "#app/data/mystery-encounters/encounters/trash-to-treasure-encounter";
|
|
import { BerriesAboundEncounter } from "#app/data/mystery-encounters/encounters/berries-abound-encounter";
|
|
import { ClowningAroundEncounter } from "#app/data/mystery-encounters/encounters/clowning-around-encounter";
|
|
import { PartTimerEncounter } from "#app/data/mystery-encounters/encounters/part-timer-encounter";
|
|
import { DancingLessonsEncounter } from "#app/data/mystery-encounters/encounters/dancing-lessons-encounter";
|
|
import { WeirdDreamEncounter } from "#app/data/mystery-encounters/encounters/weird-dream-encounter";
|
|
import { TheWinstrateChallengeEncounter } from "#app/data/mystery-encounters/encounters/the-winstrate-challenge-encounter";
|
|
import { TeleportingHijinksEncounter } from "#app/data/mystery-encounters/encounters/teleporting-hijinks-encounter";
|
|
import { BugTypeSuperfanEncounter } from "#app/data/mystery-encounters/encounters/bug-type-superfan-encounter";
|
|
import { FunAndGamesEncounter } from "#app/data/mystery-encounters/encounters/fun-and-games-encounter";
|
|
import { UncommonBreedEncounter } from "#app/data/mystery-encounters/encounters/uncommon-breed-encounter";
|
|
import { GlobalTradeSystemEncounter } from "#app/data/mystery-encounters/encounters/global-trade-system-encounter";
|
|
import { TheExpertPokemonBreederEncounter } from "#app/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter";
|
|
import { getBiomeName } from "#app/data/balance/biomes";
|
|
|
|
/**
|
|
* Spawn chance: (BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT + WIGHT_INCREMENT_ON_SPAWN_MISS * <number of missed spawns>) / MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT
|
|
*/
|
|
export const BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT = 3;
|
|
/**
|
|
* The divisor for determining ME spawns, defines the "maximum" weight required for a spawn
|
|
* If spawn_weight === MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT, 100% chance to spawn a ME
|
|
*/
|
|
export const MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT = 256;
|
|
/**
|
|
* When an ME spawn roll fails, WEIGHT_INCREMENT_ON_SPAWN_MISS is added to future rolls for ME spawn checks.
|
|
* These values are cleared whenever the next ME spawns, and spawn weight returns to BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT
|
|
*/
|
|
export const WEIGHT_INCREMENT_ON_SPAWN_MISS = 3;
|
|
/**
|
|
* Specifies the target average for total ME spawns in a single Classic run.
|
|
* Used by anti-variance mechanic to check whether a run is above or below the target on a given wave.
|
|
*/
|
|
export const AVERAGE_ENCOUNTERS_PER_RUN_TARGET = 12;
|
|
/**
|
|
* Will increase/decrease the chance of spawning a ME based on the current run's total MEs encountered vs AVERAGE_ENCOUNTERS_PER_RUN_TARGET
|
|
* Example:
|
|
* AVERAGE_ENCOUNTERS_PER_RUN_TARGET = 17 (expects avg 1 ME every 10 floors)
|
|
* ANTI_VARIANCE_WEIGHT_MODIFIER = 15
|
|
*
|
|
* On wave 20, if 1 ME has been encountered, the difference from expected average is 0 MEs.
|
|
* So anti-variance adds 0/256 to the spawn weight check for ME spawn.
|
|
*
|
|
* On wave 20, if 0 MEs have been encountered, the difference from expected average is 1 ME.
|
|
* So anti-variance adds 15/256 to the spawn weight check for ME spawn.
|
|
*
|
|
* On wave 20, if 2 MEs have been encountered, the difference from expected average is -1 ME.
|
|
* So anti-variance adds -15/256 to the spawn weight check for ME spawn.
|
|
*/
|
|
export const ANTI_VARIANCE_WEIGHT_MODIFIER = 15;
|
|
|
|
export const EXTREME_ENCOUNTER_BIOMES = [
|
|
Biome.SEA,
|
|
Biome.SEABED,
|
|
Biome.BADLANDS,
|
|
Biome.DESERT,
|
|
Biome.ICE_CAVE,
|
|
Biome.VOLCANO,
|
|
Biome.WASTELAND,
|
|
Biome.ABYSS,
|
|
Biome.SPACE,
|
|
Biome.END,
|
|
];
|
|
|
|
export const NON_EXTREME_ENCOUNTER_BIOMES = [
|
|
Biome.TOWN,
|
|
Biome.PLAINS,
|
|
Biome.GRASS,
|
|
Biome.TALL_GRASS,
|
|
Biome.METROPOLIS,
|
|
Biome.FOREST,
|
|
Biome.SWAMP,
|
|
Biome.BEACH,
|
|
Biome.LAKE,
|
|
Biome.MOUNTAIN,
|
|
Biome.CAVE,
|
|
Biome.MEADOW,
|
|
Biome.POWER_PLANT,
|
|
Biome.GRAVEYARD,
|
|
Biome.DOJO,
|
|
Biome.FACTORY,
|
|
Biome.RUINS,
|
|
Biome.CONSTRUCTION_SITE,
|
|
Biome.JUNGLE,
|
|
Biome.FAIRY_CAVE,
|
|
Biome.TEMPLE,
|
|
Biome.SLUM,
|
|
Biome.SNOWY_FOREST,
|
|
Biome.ISLAND,
|
|
Biome.LABORATORY,
|
|
];
|
|
|
|
/**
|
|
* Places where you could very reasonably expect to encounter a single human
|
|
*
|
|
* Diff from NON_EXTREME_ENCOUNTER_BIOMES:
|
|
* + BADLANDS
|
|
* + DESERT
|
|
* + ICE_CAVE
|
|
*/
|
|
export const HUMAN_TRANSITABLE_BIOMES = [
|
|
Biome.TOWN,
|
|
Biome.PLAINS,
|
|
Biome.GRASS,
|
|
Biome.TALL_GRASS,
|
|
Biome.METROPOLIS,
|
|
Biome.FOREST,
|
|
Biome.SWAMP,
|
|
Biome.BEACH,
|
|
Biome.LAKE,
|
|
Biome.MOUNTAIN,
|
|
Biome.BADLANDS,
|
|
Biome.CAVE,
|
|
Biome.DESERT,
|
|
Biome.ICE_CAVE,
|
|
Biome.MEADOW,
|
|
Biome.POWER_PLANT,
|
|
Biome.GRAVEYARD,
|
|
Biome.DOJO,
|
|
Biome.FACTORY,
|
|
Biome.RUINS,
|
|
Biome.CONSTRUCTION_SITE,
|
|
Biome.JUNGLE,
|
|
Biome.FAIRY_CAVE,
|
|
Biome.TEMPLE,
|
|
Biome.SLUM,
|
|
Biome.SNOWY_FOREST,
|
|
Biome.ISLAND,
|
|
Biome.LABORATORY,
|
|
];
|
|
|
|
/**
|
|
* Places where you could expect a town or city, some form of large civilization
|
|
*/
|
|
export const CIVILIZATION_ENCOUNTER_BIOMES = [
|
|
Biome.TOWN,
|
|
Biome.PLAINS,
|
|
Biome.GRASS,
|
|
Biome.TALL_GRASS,
|
|
Biome.METROPOLIS,
|
|
Biome.BEACH,
|
|
Biome.LAKE,
|
|
Biome.MEADOW,
|
|
Biome.POWER_PLANT,
|
|
Biome.GRAVEYARD,
|
|
Biome.DOJO,
|
|
Biome.FACTORY,
|
|
Biome.CONSTRUCTION_SITE,
|
|
Biome.SLUM,
|
|
Biome.ISLAND,
|
|
];
|
|
|
|
export const allMysteryEncounters: {
|
|
[encounterType: number]: MysteryEncounter;
|
|
} = {};
|
|
|
|
const extremeBiomeEncounters: MysteryEncounterType[] = [];
|
|
|
|
const nonExtremeBiomeEncounters: MysteryEncounterType[] = [
|
|
// MysteryEncounterType.FIELD_TRIP, Disabled
|
|
MysteryEncounterType.DANCING_LESSONS, // Is also in BADLANDS, DESERT, VOLCANO, WASTELAND, ABYSS
|
|
];
|
|
|
|
const humanTransitableBiomeEncounters: MysteryEncounterType[] = [
|
|
MysteryEncounterType.MYSTERIOUS_CHALLENGERS,
|
|
MysteryEncounterType.SHADY_VITAMIN_DEALER,
|
|
MysteryEncounterType.THE_POKEMON_SALESMAN,
|
|
// MysteryEncounterType.AN_OFFER_YOU_CANT_REFUSE, Disabled
|
|
MysteryEncounterType.THE_WINSTRATE_CHALLENGE,
|
|
MysteryEncounterType.THE_EXPERT_POKEMON_BREEDER,
|
|
];
|
|
|
|
const civilizationBiomeEncounters: MysteryEncounterType[] = [
|
|
MysteryEncounterType.DEPARTMENT_STORE_SALE,
|
|
MysteryEncounterType.PART_TIMER,
|
|
MysteryEncounterType.FUN_AND_GAMES,
|
|
MysteryEncounterType.GLOBAL_TRADE_SYSTEM,
|
|
];
|
|
|
|
/**
|
|
* To add an encounter to every biome possible, use this array
|
|
*/
|
|
const anyBiomeEncounters: MysteryEncounterType[] = [
|
|
MysteryEncounterType.FIGHT_OR_FLIGHT,
|
|
MysteryEncounterType.DARK_DEAL,
|
|
MysteryEncounterType.MYSTERIOUS_CHEST,
|
|
MysteryEncounterType.TRAINING_SESSION,
|
|
MysteryEncounterType.DELIBIRDY,
|
|
MysteryEncounterType.A_TRAINERS_TEST,
|
|
MysteryEncounterType.TRASH_TO_TREASURE,
|
|
MysteryEncounterType.BERRIES_ABOUND,
|
|
MysteryEncounterType.CLOWNING_AROUND,
|
|
MysteryEncounterType.WEIRD_DREAM,
|
|
MysteryEncounterType.TELEPORTING_HIJINKS,
|
|
MysteryEncounterType.BUG_TYPE_SUPERFAN,
|
|
MysteryEncounterType.UNCOMMON_BREED,
|
|
];
|
|
|
|
/**
|
|
* ENCOUNTER BIOME MAPPING
|
|
* To add an Encounter to a biome group, instead of cluttering the map, use the biome group arrays above
|
|
*
|
|
* Adding specific Encounters to the mysteryEncountersByBiome map is for specific cases and special circumstances
|
|
* that biome groups do not cover
|
|
*/
|
|
export const mysteryEncountersByBiome = new Map<Biome, MysteryEncounterType[]>([
|
|
[Biome.TOWN, []],
|
|
[Biome.PLAINS, [MysteryEncounterType.SLUMBERING_SNORLAX]],
|
|
[Biome.GRASS, [MysteryEncounterType.SLUMBERING_SNORLAX, MysteryEncounterType.ABSOLUTE_AVARICE]],
|
|
[Biome.TALL_GRASS, [MysteryEncounterType.SLUMBERING_SNORLAX, MysteryEncounterType.ABSOLUTE_AVARICE]],
|
|
[Biome.METROPOLIS, []],
|
|
[Biome.FOREST, [MysteryEncounterType.SAFARI_ZONE, MysteryEncounterType.ABSOLUTE_AVARICE]],
|
|
[Biome.SEA, [MysteryEncounterType.LOST_AT_SEA]],
|
|
[Biome.SWAMP, [MysteryEncounterType.SAFARI_ZONE]],
|
|
[Biome.BEACH, []],
|
|
[Biome.LAKE, []],
|
|
[Biome.SEABED, []],
|
|
[Biome.MOUNTAIN, []],
|
|
[Biome.BADLANDS, [MysteryEncounterType.DANCING_LESSONS]],
|
|
[Biome.CAVE, [MysteryEncounterType.THE_STRONG_STUFF]],
|
|
[Biome.DESERT, [MysteryEncounterType.DANCING_LESSONS]],
|
|
[Biome.ICE_CAVE, []],
|
|
[Biome.MEADOW, []],
|
|
[Biome.POWER_PLANT, []],
|
|
[Biome.VOLCANO, [MysteryEncounterType.FIERY_FALLOUT, MysteryEncounterType.DANCING_LESSONS]],
|
|
[Biome.GRAVEYARD, []],
|
|
[Biome.DOJO, []],
|
|
[Biome.FACTORY, []],
|
|
[Biome.RUINS, []],
|
|
[Biome.WASTELAND, [MysteryEncounterType.DANCING_LESSONS]],
|
|
[Biome.ABYSS, [MysteryEncounterType.DANCING_LESSONS]],
|
|
[Biome.SPACE, [MysteryEncounterType.THE_EXPERT_POKEMON_BREEDER]],
|
|
[Biome.CONSTRUCTION_SITE, []],
|
|
[Biome.JUNGLE, [MysteryEncounterType.SAFARI_ZONE]],
|
|
[Biome.FAIRY_CAVE, []],
|
|
[Biome.TEMPLE, []],
|
|
[Biome.SLUM, []],
|
|
[Biome.SNOWY_FOREST, []],
|
|
[Biome.ISLAND, []],
|
|
[Biome.LABORATORY, []],
|
|
]);
|
|
|
|
export function initMysteryEncounters() {
|
|
allMysteryEncounters[MysteryEncounterType.MYSTERIOUS_CHALLENGERS] = MysteriousChallengersEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.MYSTERIOUS_CHEST] = MysteriousChestEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.DARK_DEAL] = DarkDealEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.FIGHT_OR_FLIGHT] = FightOrFlightEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.TRAINING_SESSION] = TrainingSessionEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.SLUMBERING_SNORLAX] = SlumberingSnorlaxEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.DEPARTMENT_STORE_SALE] = DepartmentStoreSaleEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.SHADY_VITAMIN_DEALER] = ShadyVitaminDealerEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.FIELD_TRIP] = FieldTripEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.SAFARI_ZONE] = SafariZoneEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.LOST_AT_SEA] = LostAtSeaEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.FIERY_FALLOUT] = FieryFalloutEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.THE_STRONG_STUFF] = TheStrongStuffEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.THE_POKEMON_SALESMAN] = ThePokemonSalesmanEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.AN_OFFER_YOU_CANT_REFUSE] = AnOfferYouCantRefuseEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.DELIBIRDY] = DelibirdyEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.ABSOLUTE_AVARICE] = AbsoluteAvariceEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.A_TRAINERS_TEST] = ATrainersTestEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.TRASH_TO_TREASURE] = TrashToTreasureEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.BERRIES_ABOUND] = BerriesAboundEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.CLOWNING_AROUND] = ClowningAroundEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.PART_TIMER] = PartTimerEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.DANCING_LESSONS] = DancingLessonsEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.WEIRD_DREAM] = WeirdDreamEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.THE_WINSTRATE_CHALLENGE] = TheWinstrateChallengeEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.TELEPORTING_HIJINKS] = TeleportingHijinksEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.BUG_TYPE_SUPERFAN] = BugTypeSuperfanEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.FUN_AND_GAMES] = FunAndGamesEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.UNCOMMON_BREED] = UncommonBreedEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.GLOBAL_TRADE_SYSTEM] = GlobalTradeSystemEncounter;
|
|
allMysteryEncounters[MysteryEncounterType.THE_EXPERT_POKEMON_BREEDER] = TheExpertPokemonBreederEncounter;
|
|
|
|
// Add extreme encounters to biome map
|
|
extremeBiomeEncounters.forEach(encounter => {
|
|
EXTREME_ENCOUNTER_BIOMES.forEach(biome => {
|
|
const encountersForBiome = mysteryEncountersByBiome.get(biome);
|
|
if (encountersForBiome && !encountersForBiome.includes(encounter)) {
|
|
encountersForBiome.push(encounter);
|
|
}
|
|
});
|
|
});
|
|
// Add non-extreme encounters to biome map
|
|
nonExtremeBiomeEncounters.forEach(encounter => {
|
|
NON_EXTREME_ENCOUNTER_BIOMES.forEach(biome => {
|
|
const encountersForBiome = mysteryEncountersByBiome.get(biome);
|
|
if (encountersForBiome && !encountersForBiome.includes(encounter)) {
|
|
encountersForBiome.push(encounter);
|
|
}
|
|
});
|
|
});
|
|
// Add human encounters to biome map
|
|
humanTransitableBiomeEncounters.forEach(encounter => {
|
|
HUMAN_TRANSITABLE_BIOMES.forEach(biome => {
|
|
const encountersForBiome = mysteryEncountersByBiome.get(biome);
|
|
if (encountersForBiome && !encountersForBiome.includes(encounter)) {
|
|
encountersForBiome.push(encounter);
|
|
}
|
|
});
|
|
});
|
|
// Add civilization encounters to biome map
|
|
civilizationBiomeEncounters.forEach(encounter => {
|
|
CIVILIZATION_ENCOUNTER_BIOMES.forEach(biome => {
|
|
const encountersForBiome = mysteryEncountersByBiome.get(biome);
|
|
if (encountersForBiome && !encountersForBiome.includes(encounter)) {
|
|
encountersForBiome.push(encounter);
|
|
}
|
|
});
|
|
});
|
|
|
|
// Add ANY biome encounters to biome map
|
|
let _encounterBiomeTableLog = "";
|
|
mysteryEncountersByBiome.forEach((biomeEncounters, biome) => {
|
|
anyBiomeEncounters.forEach(encounter => {
|
|
if (!biomeEncounters.includes(encounter)) {
|
|
biomeEncounters.push(encounter);
|
|
}
|
|
});
|
|
|
|
_encounterBiomeTableLog += `${getBiomeName(biome).toUpperCase()}: [${biomeEncounters
|
|
.map(type => MysteryEncounterType[type].toString().toLowerCase())
|
|
.sort()
|
|
.join(", ")}]\n`;
|
|
});
|
|
|
|
//console.debug("All Mystery Encounters by Biome:\n" + encounterBiomeTableLog);
|
|
}
|