mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-09-23 06:53:27 +02:00
Even more array improvements
This commit is contained in:
parent
8003215c39
commit
ac2f09ad33
@ -7,8 +7,8 @@ import type { TrainerPartyTemplate } from "#trainers/trainer-party-template";
|
||||
|
||||
export type PartyTemplateFunc = () => TrainerPartyTemplate;
|
||||
export type PartyMemberFunc = (level: number, strength: PartyMemberStrength) => EnemyPokemon;
|
||||
export type GenModifiersFunc = (party: EnemyPokemon[]) => PersistentModifier[];
|
||||
export type GenAIFunc = (party: EnemyPokemon[]) => void;
|
||||
export type GenModifiersFunc = (party: readonly EnemyPokemon[]) => PersistentModifier[];
|
||||
export type GenAIFunc = (party: readonly EnemyPokemon[]) => void;
|
||||
|
||||
export interface TrainerTierPools {
|
||||
[key: number]: SpeciesId[];
|
||||
|
@ -526,24 +526,25 @@ export class FixedBattleConfig {
|
||||
|
||||
/**
|
||||
* Helper function to generate a random trainer for evil team trainers and the elite 4/champion
|
||||
* @param trainerPool The TrainerType or list of TrainerTypes that can possibly be generated
|
||||
* @param randomGender whether or not to randomly (50%) generate a female trainer (for use with evil team grunts)
|
||||
* @param seedOffset the seed offset to use for the random generation of the trainer
|
||||
* @returns the generated trainer
|
||||
* @param trainerPool - An array of trainer types to choose from. If an entry is an array, a random trainer type will be chosen from that array
|
||||
* @param randomGender - Whether or not to randomly (50%) generate a female trainer (for use with evil team grunts)
|
||||
* @param seedOffset - The seed offset to use for the random generation of the trainer
|
||||
* @returns A function to get a random trainer
|
||||
*/
|
||||
export function getRandomTrainerFunc(
|
||||
trainerPool: (TrainerType | TrainerType[])[],
|
||||
trainerPool: readonly (TrainerType | readonly TrainerType[])[],
|
||||
randomGender = false,
|
||||
seedOffset = 0,
|
||||
): GetTrainerFunc {
|
||||
return () => {
|
||||
const rand = randSeedInt(trainerPool.length);
|
||||
const trainerTypes: TrainerType[] = [];
|
||||
const trainerTypes: TrainerType[] = new Array(trainerPool.length);
|
||||
|
||||
globalScene.executeWithSeedOffset(() => {
|
||||
for (const trainerPoolEntry of trainerPool) {
|
||||
for (let i = 0; i < trainerPool.length; i++) {
|
||||
const trainerPoolEntry = trainerPool[i];
|
||||
const trainerType = Array.isArray(trainerPoolEntry) ? randSeedItem(trainerPoolEntry) : trainerPoolEntry;
|
||||
trainerTypes.push(trainerType);
|
||||
trainerTypes[i] = trainerType;
|
||||
}
|
||||
}, seedOffset);
|
||||
|
||||
|
@ -23,7 +23,7 @@ export const TYPE_BOOST_ITEM_BOOST_PERCENT = 20;
|
||||
/**
|
||||
* The default species that a new player can choose from
|
||||
*/
|
||||
export const defaultStarterSpecies: SpeciesId[] = [
|
||||
export const defaultStarterSpecies: readonly SpeciesId[] = [
|
||||
SpeciesId.BULBASAUR,
|
||||
SpeciesId.CHARMANDER,
|
||||
SpeciesId.SQUIRTLE,
|
||||
|
@ -5,6 +5,7 @@ import { PokemonType } from "#enums/pokemon-type";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { TimeOfDay } from "#enums/time-of-day";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import type { Mutable } from "#types/type-helpers";
|
||||
import { randSeedInt } from "#utils/common";
|
||||
import { getEnumValues } from "#utils/enums";
|
||||
import { toCamelCase } from "#utils/strings";
|
||||
@ -88,19 +89,19 @@ export enum BiomePoolTier {
|
||||
export const uncatchableSpecies: SpeciesId[] = [];
|
||||
|
||||
interface SpeciesTree {
|
||||
[key: number]: SpeciesId[]
|
||||
readonly [key: number]: SpeciesId[]
|
||||
}
|
||||
|
||||
export interface PokemonPools {
|
||||
[key: number]: (SpeciesId | SpeciesTree)[]
|
||||
readonly [key: number]: (SpeciesId | SpeciesTree)[]
|
||||
}
|
||||
|
||||
interface BiomeTierPokemonPools {
|
||||
[key: number]: PokemonPools
|
||||
readonly [key: number]: PokemonPools
|
||||
}
|
||||
|
||||
interface BiomePokemonPools {
|
||||
[key: number]: BiomeTierPokemonPools
|
||||
readonly [key: number]: BiomeTierPokemonPools
|
||||
}
|
||||
|
||||
export interface BiomeTierTod {
|
||||
@ -110,17 +111,17 @@ export interface BiomeTierTod {
|
||||
}
|
||||
|
||||
export interface CatchableSpecies{
|
||||
[key: number]: BiomeTierTod[]
|
||||
readonly [key: number]: readonly BiomeTierTod[]
|
||||
}
|
||||
|
||||
export const catchableSpecies: CatchableSpecies = {};
|
||||
|
||||
export interface BiomeTierTrainerPools {
|
||||
[key: number]: TrainerType[]
|
||||
readonly [key: number]: readonly TrainerType[]
|
||||
}
|
||||
|
||||
export interface BiomeTrainerPools {
|
||||
[key: number]: BiomeTierTrainerPools
|
||||
readonly [key: number]: BiomeTierTrainerPools
|
||||
}
|
||||
|
||||
export const biomePokemonPools: BiomePokemonPools = {
|
||||
@ -7621,12 +7622,10 @@ export function initBiomes() {
|
||||
? biomeLinks[biome] as (BiomeId | [ BiomeId, number ])[]
|
||||
: [ biomeLinks[biome] as BiomeId ];
|
||||
for (const linkedBiomeEntry of linkedBiomes) {
|
||||
const linkedBiome = !Array.isArray(linkedBiomeEntry)
|
||||
? linkedBiomeEntry as BiomeId
|
||||
: linkedBiomeEntry[0];
|
||||
const biomeChance = !Array.isArray(linkedBiomeEntry)
|
||||
? 1
|
||||
: linkedBiomeEntry[1];
|
||||
const linkedBiome = Array.isArray(linkedBiomeEntry)
|
||||
? linkedBiomeEntry[0] : linkedBiomeEntry as BiomeId;
|
||||
const biomeChance = Array.isArray(linkedBiomeEntry)
|
||||
? linkedBiomeEntry[1] : 1;
|
||||
if (!biomeDepths.hasOwnProperty(linkedBiome) || biomeChance < biomeDepths[linkedBiome][1] || (depth < biomeDepths[linkedBiome][0] && biomeChance === biomeDepths[linkedBiome][1])) {
|
||||
biomeDepths[linkedBiome] = [ depth + 1, biomeChance ];
|
||||
traverseBiome(linkedBiome, depth + 1);
|
||||
@ -7638,15 +7637,15 @@ export function initBiomes() {
|
||||
biomeDepths[BiomeId.END] = [ Object.values(biomeDepths).map(d => d[0]).reduce((max: number, value: number) => Math.max(max, value), 0) + 1, 1 ];
|
||||
|
||||
for (const biome of getEnumValues(BiomeId)) {
|
||||
biomePokemonPools[biome] = {};
|
||||
biomeTrainerPools[biome] = {};
|
||||
(biomePokemonPools[biome] as Mutable<typeof biomePokemonPools[number]>) = {};
|
||||
(biomeTrainerPools[biome] as Mutable<typeof biomeTrainerPools[number]>) = {};
|
||||
|
||||
for (const tier of getEnumValues(BiomePoolTier)) {
|
||||
biomePokemonPools[biome][tier] = {};
|
||||
biomeTrainerPools[biome][tier] = [];
|
||||
(biomePokemonPools[biome][tier] as Mutable<typeof biomePokemonPools[number][number]>) = {};
|
||||
(biomeTrainerPools[biome][tier] as Mutable<typeof biomeTrainerPools[number][number]>) = [];
|
||||
|
||||
for (const tod of getEnumValues(TimeOfDay)) {
|
||||
biomePokemonPools[biome][tier][tod] = [];
|
||||
(biomePokemonPools[biome][tier][tod] as Mutable<typeof biomePokemonPools[number][number][number]>) = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7663,8 +7662,9 @@ export function initBiomes() {
|
||||
uncatchableSpecies.push(speciesId);
|
||||
}
|
||||
|
||||
type mutableSpecies = Mutable<typeof catchableSpecies[SpeciesId]>;
|
||||
// array of biome options for the current species
|
||||
catchableSpecies[speciesId] = [];
|
||||
(catchableSpecies[speciesId] as mutableSpecies) = [];
|
||||
|
||||
for (const b of biomeEntries) {
|
||||
const biome = b[0];
|
||||
@ -7675,7 +7675,7 @@ export function initBiomes() {
|
||||
: [ b[2] ]
|
||||
: [ TimeOfDay.ALL ];
|
||||
|
||||
catchableSpecies[speciesId].push({
|
||||
(catchableSpecies[speciesId] as mutableSpecies).push({
|
||||
biome: biome as BiomeId,
|
||||
tier: tier as BiomePoolTier,
|
||||
tod: timesOfDay as TimeOfDay[]
|
||||
@ -7735,12 +7735,13 @@ export function initBiomes() {
|
||||
};
|
||||
for (let s = 1; s < entry.length; s++) {
|
||||
const speciesId = entry[s];
|
||||
// biome-ignore lint/nursery/noShadow: one-off
|
||||
const prevolution = entry.flatMap((s: string | number) => pokemonEvolutions[s]).find(e => e && e.speciesId === speciesId);
|
||||
const level = prevolution.level - (prevolution.level === 1 ? 1 : 0) + (prevolution.wildDelay * 10) - (tier >= BiomePoolTier.BOSS ? 10 : 0);
|
||||
if (!newEntry.hasOwnProperty(level)) {
|
||||
newEntry[level] = [ speciesId ];
|
||||
} else {
|
||||
if (newEntry.hasOwnProperty(level)) {
|
||||
newEntry[level].push(speciesId);
|
||||
} else {
|
||||
newEntry[level] = [ speciesId ];
|
||||
}
|
||||
}
|
||||
biomeTierTimePool[e] = newEntry;
|
||||
@ -7763,7 +7764,7 @@ export function initBiomes() {
|
||||
}
|
||||
|
||||
const biomeTierPool = biomeTrainerPools[biome][tier];
|
||||
biomeTierPool.push(trainerType);
|
||||
(biomeTierPool as Mutable<typeof biomeTierPool>).push(trainerType);
|
||||
}
|
||||
//outputPools();
|
||||
}
|
||||
|
@ -2154,8 +2154,8 @@ export class HighestStatBoostTag extends AbilityBattlerTag {
|
||||
}
|
||||
|
||||
export class WeatherHighestStatBoostTag extends HighestStatBoostTag {
|
||||
#weatherTypes: WeatherType[];
|
||||
public get weatherTypes(): WeatherType[] {
|
||||
readonly #weatherTypes: readonly WeatherType[];
|
||||
public get weatherTypes(): readonly WeatherType[] {
|
||||
return this.#weatherTypes;
|
||||
}
|
||||
|
||||
@ -2166,8 +2166,8 @@ export class WeatherHighestStatBoostTag extends HighestStatBoostTag {
|
||||
}
|
||||
|
||||
export class TerrainHighestStatBoostTag extends HighestStatBoostTag {
|
||||
#terrainTypes: TerrainType[];
|
||||
public get terrainTypes(): TerrainType[] {
|
||||
readonly #terrainTypes: readonly TerrainType[];
|
||||
public get terrainTypes(): readonly TerrainType[] {
|
||||
return this.#terrainTypes;
|
||||
}
|
||||
|
||||
|
@ -485,14 +485,14 @@ export class Egg {
|
||||
* and being the same each time
|
||||
*/
|
||||
let totalWeight = 0;
|
||||
const speciesWeights: number[] = [];
|
||||
for (const speciesId of speciesPool) {
|
||||
const speciesWeights = new Array<number>(speciesPool.length);
|
||||
for (const [idx, speciesId] of speciesPool.entries()) {
|
||||
// Accounts for species that have starter costs outside of the normal range for their EggTier
|
||||
const speciesCostClamped = Phaser.Math.Clamp(speciesStarterCosts[speciesId], minStarterValue, maxStarterValue);
|
||||
const weight = Math.floor(
|
||||
(((maxStarterValue - speciesCostClamped) / (maxStarterValue - minStarterValue + 1)) * 1.5 + 1) * 100,
|
||||
);
|
||||
speciesWeights.push(totalWeight + weight);
|
||||
speciesWeights[idx] = totalWeight + weight;
|
||||
totalWeight += weight;
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@ import { SpeciesId } from "#enums/species-id";
|
||||
import { WeatherType } from "#enums/weather-type";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import type { Constructor, nil } from "#types/common";
|
||||
import type { Mutable } from "#types/type-helpers";
|
||||
|
||||
export type SpeciesFormChangeConditionPredicate = (p: Pokemon) => boolean;
|
||||
export type SpeciesFormChangeConditionEnforceFunc = (p: Pokemon) => void;
|
||||
@ -116,7 +117,7 @@ function getSpeciesDependentFormChangeCondition(species: SpeciesId): SpeciesForm
|
||||
}
|
||||
|
||||
interface PokemonFormChanges {
|
||||
[key: string]: SpeciesFormChange[];
|
||||
[key: string]: readonly SpeciesFormChange[];
|
||||
}
|
||||
|
||||
// biome-ignore format: manually formatted
|
||||
@ -608,6 +609,6 @@ export function initPokemonForms() {
|
||||
);
|
||||
}
|
||||
}
|
||||
formChanges.push(...newFormChanges);
|
||||
(formChanges as Mutable<typeof formChanges>).push(...newFormChanges);
|
||||
}
|
||||
}
|
||||
|
@ -240,9 +240,9 @@ export class SpeciesFormChangeWeatherTrigger extends SpeciesFormChangeTrigger {
|
||||
/** The ability that triggers the form change */
|
||||
public ability: AbilityId;
|
||||
/** The list of weathers that trigger the form change */
|
||||
public weathers: WeatherType[];
|
||||
public readonly weathers: readonly WeatherType[];
|
||||
|
||||
constructor(ability: AbilityId, weathers: WeatherType[]) {
|
||||
constructor(ability: AbilityId, weathers: readonly WeatherType[]) {
|
||||
super();
|
||||
this.ability = ability;
|
||||
this.weathers = weathers;
|
||||
@ -278,9 +278,9 @@ export class SpeciesFormChangeRevertWeatherFormTrigger extends SpeciesFormChange
|
||||
/** The ability that triggers the form change*/
|
||||
public ability: AbilityId;
|
||||
/** The list of weathers that will also trigger a form change to original form */
|
||||
public weathers: WeatherType[];
|
||||
public readonly weathers: readonly WeatherType[];
|
||||
|
||||
constructor(ability: AbilityId, weathers: WeatherType[]) {
|
||||
constructor(ability: AbilityId, weathers: readonly WeatherType[]) {
|
||||
super();
|
||||
this.ability = ability;
|
||||
this.weathers = weathers;
|
||||
@ -310,9 +310,10 @@ export class SpeciesFormChangeRevertWeatherFormTrigger extends SpeciesFormChange
|
||||
}
|
||||
|
||||
export function getSpeciesFormChangeMessage(pokemon: Pokemon, formChange: SpeciesFormChange, preName: string): string {
|
||||
const isMega = formChange.formKey.indexOf(SpeciesFormKey.MEGA) > -1;
|
||||
const isGmax = formChange.formKey.indexOf(SpeciesFormKey.GIGANTAMAX) > -1;
|
||||
const isEmax = formChange.formKey.indexOf(SpeciesFormKey.ETERNAMAX) > -1;
|
||||
const formKey = formChange.formKey;
|
||||
const isMega = formKey.indexOf(SpeciesFormKey.MEGA) > -1;
|
||||
const isGmax = formKey.indexOf(SpeciesFormKey.GIGANTAMAX) > -1;
|
||||
const isEmax = formKey.indexOf(SpeciesFormKey.ETERNAMAX) > -1;
|
||||
const isRevert = !isMega && formChange.formKey === pokemon.species.forms[0].formKey;
|
||||
if (isMega) {
|
||||
return i18next.t("battlePokemonForm:megaChange", {
|
||||
|
@ -2140,7 +2140,8 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
* Suppresses an ability and calls its onlose attributes
|
||||
*/
|
||||
public suppressAbility() {
|
||||
[true, false].forEach(passive => applyOnLoseAbAttrs({ pokemon: this, passive }));
|
||||
applyOnLoseAbAttrs({ pokemon: this, passive: true });
|
||||
applyOnLoseAbAttrs({ pokemon: this, passive: false });
|
||||
this.summonData.abilitySuppressed = true;
|
||||
}
|
||||
|
||||
|
@ -642,14 +642,14 @@ export class Trainer extends Phaser.GameObjects.Container {
|
||||
}
|
||||
}
|
||||
|
||||
genModifiers(party: EnemyPokemon[]): PersistentModifier[] {
|
||||
genModifiers(party: readonly EnemyPokemon[]): PersistentModifier[] {
|
||||
if (this.config.genModifiersFunc) {
|
||||
return this.config.genModifiersFunc(party);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
genAI(party: EnemyPokemon[]) {
|
||||
genAI(party: readonly EnemyPokemon[]) {
|
||||
if (this.config.genAIFuncs) {
|
||||
this.config.genAIFuncs.forEach(f => f(party));
|
||||
}
|
||||
|
@ -277,7 +277,7 @@ export class ModifierType {
|
||||
}
|
||||
}
|
||||
|
||||
type ModifierTypeGeneratorFunc = (party: Pokemon[], pregenArgs?: any[]) => ModifierType | null;
|
||||
type ModifierTypeGeneratorFunc = (party: readonly Pokemon[], pregenArgs?: any[]) => ModifierType | null;
|
||||
|
||||
export class ModifierTypeGenerator extends ModifierType {
|
||||
private genTypeFunc: ModifierTypeGeneratorFunc;
|
||||
@ -287,7 +287,7 @@ export class ModifierTypeGenerator extends ModifierType {
|
||||
this.genTypeFunc = genTypeFunc;
|
||||
}
|
||||
|
||||
generateType(party: Pokemon[], pregenArgs?: any[]) {
|
||||
generateType(party: readonly Pokemon[], pregenArgs?: any[]) {
|
||||
const ret = this.genTypeFunc(party, pregenArgs);
|
||||
if (ret) {
|
||||
ret.id = this.id;
|
||||
@ -2360,7 +2360,11 @@ const tierWeights = [768 / 1024, 195 / 1024, 48 / 1024, 12 / 1024, 1 / 1024];
|
||||
*/
|
||||
export const itemPoolChecks: Map<ModifierTypeKeys, boolean | undefined> = new Map();
|
||||
|
||||
export function regenerateModifierPoolThresholds(party: Pokemon[], poolType: ModifierPoolType, rerollCount = 0) {
|
||||
export function regenerateModifierPoolThresholds(
|
||||
party: readonly Pokemon[],
|
||||
poolType: ModifierPoolType,
|
||||
rerollCount = 0,
|
||||
) {
|
||||
const pool = getModifierPoolForType(poolType);
|
||||
itemPoolChecks.forEach((_v, k) => {
|
||||
itemPoolChecks.set(k, false);
|
||||
@ -2906,7 +2910,7 @@ export class ModifierTypeOption {
|
||||
* @param party The player's party.
|
||||
* @returns A number between 0 and 14 based on the party's total luck value, or a random number between 0 and 14 if the player is in Daily Run mode.
|
||||
*/
|
||||
export function getPartyLuckValue(party: Pokemon[]): number {
|
||||
export function getPartyLuckValue(party: readonly Pokemon[]): number {
|
||||
if (globalScene.gameMode.isDaily) {
|
||||
const DailyLuck = new NumberHolder(0);
|
||||
globalScene.executeWithSeedOffset(
|
||||
|
@ -12,7 +12,7 @@ export abstract class BattlePhase extends Phase {
|
||||
const tintSprites = globalScene.currentBattle.trainer.getTintSprites();
|
||||
for (let i = 0; i < sprites.length; i++) {
|
||||
const visible = !trainerSlot || !i === (trainerSlot === TrainerSlot.TRAINER) || sprites.length < 2;
|
||||
[sprites[i], tintSprites[i]].map(sprite => {
|
||||
[sprites[i], tintSprites[i]].forEach(sprite => {
|
||||
if (visible) {
|
||||
sprite.x = trainerSlot || sprites.length < 2 ? 0 : i ? 16 : -16;
|
||||
}
|
||||
|
@ -18,59 +18,59 @@ export enum EventType {
|
||||
}
|
||||
|
||||
interface EventBanner {
|
||||
bannerKey?: string;
|
||||
xOffset?: number;
|
||||
yOffset?: number;
|
||||
scale?: number;
|
||||
availableLangs?: string[];
|
||||
readonly bannerKey?: string;
|
||||
readonly xOffset?: number;
|
||||
readonly yOffset?: number;
|
||||
readonly scale?: number;
|
||||
readonly availableLangs?: readonly string[];
|
||||
}
|
||||
|
||||
interface EventEncounter {
|
||||
species: SpeciesId;
|
||||
blockEvolution?: boolean;
|
||||
formIndex?: number;
|
||||
readonly species: SpeciesId;
|
||||
readonly blockEvolution?: boolean;
|
||||
readonly formIndex?: number;
|
||||
}
|
||||
|
||||
interface EventMysteryEncounterTier {
|
||||
mysteryEncounter: MysteryEncounterType;
|
||||
tier?: MysteryEncounterTier;
|
||||
disable?: boolean;
|
||||
readonly mysteryEncounter: MysteryEncounterType;
|
||||
readonly tier?: MysteryEncounterTier;
|
||||
readonly disable?: boolean;
|
||||
}
|
||||
|
||||
interface EventWaveReward {
|
||||
wave: number;
|
||||
type: string;
|
||||
readonly wave: number;
|
||||
readonly type: string;
|
||||
}
|
||||
|
||||
type EventMusicReplacement = [string, string];
|
||||
type EventMusicReplacement = readonly [string, string];
|
||||
|
||||
interface EventChallenge {
|
||||
challenge: Challenges;
|
||||
value: number;
|
||||
readonly challenge: Challenges;
|
||||
readonly value: number;
|
||||
}
|
||||
|
||||
interface TimedEvent extends EventBanner {
|
||||
name: string;
|
||||
eventType: EventType;
|
||||
shinyMultiplier?: number;
|
||||
classicFriendshipMultiplier?: number;
|
||||
luckBoost?: number;
|
||||
upgradeUnlockedVouchers?: boolean;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
eventEncounters?: EventEncounter[];
|
||||
delibirdyBuff?: string[];
|
||||
weather?: WeatherPoolEntry[];
|
||||
mysteryEncounterTierChanges?: EventMysteryEncounterTier[];
|
||||
luckBoostedSpecies?: SpeciesId[];
|
||||
boostFusions?: boolean; //MODIFIER REWORK PLEASE
|
||||
classicWaveRewards?: EventWaveReward[]; // Rival battle rewards
|
||||
trainerShinyChance?: number; // Odds over 65536 of trainer mon generating as shiny
|
||||
music?: EventMusicReplacement[];
|
||||
dailyRunChallenges?: EventChallenge[];
|
||||
readonly name: string;
|
||||
readonly eventType: EventType;
|
||||
readonly shinyMultiplier?: number;
|
||||
readonly classicFriendshipMultiplier?: number;
|
||||
readonly luckBoost?: number;
|
||||
readonly upgradeUnlockedVouchers?: boolean;
|
||||
readonly startDate: Date;
|
||||
readonly endDate: Date;
|
||||
readonly eventEncounters?: readonly EventEncounter[];
|
||||
readonly delibirdyBuff?: readonly string[];
|
||||
readonly weather?: readonly WeatherPoolEntry[];
|
||||
readonly mysteryEncounterTierChanges?: readonly EventMysteryEncounterTier[];
|
||||
readonly luckBoostedSpecies?: readonly SpeciesId[];
|
||||
readonly boostFusions?: boolean; //MODIFIER REWORK PLEASE
|
||||
readonly classicWaveRewards?: readonly EventWaveReward[]; // Rival battle rewards
|
||||
readonly trainerShinyChance?: number; // Odds over 65536 of trainer mon generating as shiny
|
||||
readonly music?: readonly EventMusicReplacement[];
|
||||
readonly dailyRunChallenges?: readonly EventChallenge[];
|
||||
}
|
||||
|
||||
const timedEvents: TimedEvent[] = [
|
||||
const timedEvents: readonly TimedEvent[] = [
|
||||
{
|
||||
name: "Winter Holiday Update",
|
||||
eventType: EventType.SHINY,
|
||||
@ -385,7 +385,8 @@ const timedEvents: TimedEvent[] = [
|
||||
|
||||
export class TimedEventManager {
|
||||
isActive(event: TimedEvent) {
|
||||
return event.startDate < new Date() && new Date() < event.endDate;
|
||||
const now = new Date();
|
||||
return event.startDate < now && now < event.endDate;
|
||||
}
|
||||
|
||||
activeEvent(): TimedEvent | undefined {
|
||||
@ -427,19 +428,17 @@ export class TimedEventManager {
|
||||
|
||||
getEventBannerLangs(): string[] {
|
||||
const ret: string[] = [];
|
||||
ret.push(...timedEvents.find(te => this.isActive(te) && te.availableLangs != null)?.availableLangs!);
|
||||
ret.push(...(timedEvents.find(te => this.isActive(te) && te.availableLangs != null)?.availableLangs ?? []));
|
||||
return ret;
|
||||
}
|
||||
|
||||
getEventEncounters(): EventEncounter[] {
|
||||
const ret: EventEncounter[] = [];
|
||||
timedEvents
|
||||
.filter(te => this.isActive(te))
|
||||
.map(te => {
|
||||
if (te.eventEncounters != null) {
|
||||
ret.push(...te.eventEncounters);
|
||||
}
|
||||
});
|
||||
for (const te of timedEvents) {
|
||||
if (this.isActive(te) && te.eventEncounters != null) {
|
||||
ret.push(...te.eventEncounters);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -472,13 +471,11 @@ export class TimedEventManager {
|
||||
*/
|
||||
getDelibirdyBuff(): string[] {
|
||||
const ret: string[] = [];
|
||||
timedEvents
|
||||
.filter(te => this.isActive(te))
|
||||
.map(te => {
|
||||
if (te.delibirdyBuff != null) {
|
||||
ret.push(...te.delibirdyBuff);
|
||||
}
|
||||
});
|
||||
for (const te of timedEvents) {
|
||||
if (this.isActive(te) && te.delibirdyBuff != null) {
|
||||
ret.push(...te.delibirdyBuff);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -488,39 +485,35 @@ export class TimedEventManager {
|
||||
*/
|
||||
getWeather(): WeatherPoolEntry[] {
|
||||
const ret: WeatherPoolEntry[] = [];
|
||||
timedEvents
|
||||
.filter(te => this.isActive(te))
|
||||
.map(te => {
|
||||
if (te.weather != null) {
|
||||
ret.push(...te.weather);
|
||||
}
|
||||
});
|
||||
for (const te of timedEvents) {
|
||||
if (this.isActive(te) && te.weather != null) {
|
||||
ret.push(...te.weather);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
getAllMysteryEncounterChanges(): EventMysteryEncounterTier[] {
|
||||
const ret: EventMysteryEncounterTier[] = [];
|
||||
timedEvents
|
||||
.filter(te => this.isActive(te))
|
||||
.map(te => {
|
||||
if (te.mysteryEncounterTierChanges != null) {
|
||||
ret.push(...te.mysteryEncounterTierChanges);
|
||||
}
|
||||
});
|
||||
for (const te of timedEvents) {
|
||||
if (this.isActive(te) && te.mysteryEncounterTierChanges != null) {
|
||||
ret.push(...te.mysteryEncounterTierChanges);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
getEventMysteryEncountersDisabled(): MysteryEncounterType[] {
|
||||
const ret: MysteryEncounterType[] = [];
|
||||
timedEvents
|
||||
.filter(te => this.isActive(te) && te.mysteryEncounterTierChanges != null)
|
||||
.map(te => {
|
||||
te.mysteryEncounterTierChanges?.map(metc => {
|
||||
for (const te of timedEvents) {
|
||||
if (this.isActive(te) && te.mysteryEncounterTierChanges != null) {
|
||||
for (const metc of te.mysteryEncounterTierChanges) {
|
||||
if (metc.disable) {
|
||||
ret.push(metc.mysteryEncounter);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -529,15 +522,15 @@ export class TimedEventManager {
|
||||
normal: MysteryEncounterTier,
|
||||
): MysteryEncounterTier {
|
||||
let ret = normal;
|
||||
timedEvents
|
||||
.filter(te => this.isActive(te) && te.mysteryEncounterTierChanges != null)
|
||||
.map(te => {
|
||||
te.mysteryEncounterTierChanges?.map(metc => {
|
||||
for (const te of timedEvents) {
|
||||
if (this.isActive(te) && te.mysteryEncounterTierChanges != null) {
|
||||
for (const metc of te.mysteryEncounterTierChanges) {
|
||||
if (metc.mysteryEncounter === encounterType) {
|
||||
ret = metc.tier ?? normal;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -551,15 +544,16 @@ export class TimedEventManager {
|
||||
}
|
||||
|
||||
getEventLuckBoostedSpecies(): SpeciesId[] {
|
||||
const ret: SpeciesId[] = [];
|
||||
timedEvents
|
||||
.filter(te => this.isActive(te))
|
||||
.map(te => {
|
||||
if (te.luckBoostedSpecies != null) {
|
||||
ret.push(...te.luckBoostedSpecies.filter(s => !ret.includes(s)));
|
||||
const ret = new Set<SpeciesId>();
|
||||
|
||||
for (const te of timedEvents) {
|
||||
if (this.isActive(te) && te.luckBoostedSpecies != null) {
|
||||
for (const s of te.luckBoostedSpecies) {
|
||||
ret.add(s);
|
||||
}
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return Array.from(ret);
|
||||
}
|
||||
|
||||
areFusionsBoosted(): boolean {
|
||||
@ -574,45 +568,50 @@ export class TimedEventManager {
|
||||
*/
|
||||
getFixedBattleEventRewards(wave: number): string[] {
|
||||
const ret: string[] = [];
|
||||
timedEvents
|
||||
.filter(te => this.isActive(te) && te.classicWaveRewards != null)
|
||||
.map(te => {
|
||||
ret.push(...te.classicWaveRewards!.filter(cwr => cwr.wave === wave).map(cwr => cwr.type));
|
||||
});
|
||||
for (const te of timedEvents) {
|
||||
if (this.isActive(te) && te.classicWaveRewards != null) {
|
||||
ret.push(...te.classicWaveRewards.filter(cwr => cwr.wave === wave).map(cwr => cwr.type));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Gets the extra shiny chance for trainers due to event (odds/65536)
|
||||
/**
|
||||
* Get the extra shiny chance for trainers due to event
|
||||
*/
|
||||
getClassicTrainerShinyChance(): number {
|
||||
let ret = 0;
|
||||
const tsEvents = timedEvents.filter(te => this.isActive(te) && te.trainerShinyChance != null);
|
||||
tsEvents.map(t => (ret += t.trainerShinyChance!));
|
||||
for (const te of timedEvents) {
|
||||
const shinyChance = te.trainerShinyChance;
|
||||
if (shinyChance && this.isActive(te)) {
|
||||
ret += shinyChance;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
getEventBgmReplacement(bgm: string): string {
|
||||
let ret = bgm;
|
||||
timedEvents.map(te => {
|
||||
for (const te of timedEvents) {
|
||||
if (this.isActive(te) && te.music != null) {
|
||||
te.music.map(mr => {
|
||||
for (const mr of te.music) {
|
||||
if (mr[0] === bgm) {
|
||||
console.log(`it is ${te.name} so instead of ${mr[0]} we play ${mr[1]}`);
|
||||
ret = mr[1];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Activates any challenges on {@linkcode globalScene.gameMode} for the currently active event
|
||||
* Activate any challenges on {@linkcode globalScene.gameMode} for the currently active event
|
||||
*/
|
||||
startEventChallenges(): void {
|
||||
const challenges = this.activeEvent()?.dailyRunChallenges;
|
||||
challenges?.forEach((eventChal: EventChallenge) =>
|
||||
globalScene.gameMode.setChallengeValue(eventChal.challenge, eventChal.value),
|
||||
);
|
||||
for (const eventChal of this.activeEvent()?.dailyRunChallenges ?? []) {
|
||||
globalScene.gameMode.setChallengeValue(eventChal.challenge, eventChal.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,8 +240,8 @@ export class PokedexPageUiHandler extends MessageUiHandler {
|
||||
private passive: AbilityId;
|
||||
private hasPassive: boolean;
|
||||
private hasAbilities: number[];
|
||||
private biomes: BiomeTierTod[];
|
||||
private preBiomes: BiomeTierTod[];
|
||||
private biomes: readonly BiomeTierTod[];
|
||||
private preBiomes: readonly BiomeTierTod[];
|
||||
private baseStats: number[];
|
||||
private baseTotal: number;
|
||||
private evolutions: SpeciesFormEvolution[];
|
||||
@ -893,7 +893,7 @@ export class PokedexPageUiHandler extends MessageUiHandler {
|
||||
}
|
||||
|
||||
// Function to ensure that forms appear in the appropriate biome and tod
|
||||
sanitizeBiomes(biomes: BiomeTierTod[], speciesId: number): BiomeTierTod[] {
|
||||
sanitizeBiomes(biomes: readonly BiomeTierTod[], speciesId: number): readonly BiomeTierTod[] {
|
||||
if (speciesId === SpeciesId.BURMY || speciesId === SpeciesId.WORMADAM) {
|
||||
return biomes.filter(b => {
|
||||
const formIndex = (() => {
|
||||
|
@ -16,22 +16,23 @@ interface hasPokemon {
|
||||
* @returns The sorted array of {@linkcode Pokemon}
|
||||
*/
|
||||
export function sortInSpeedOrder<T extends Pokemon | hasPokemon>(pokemonList: T[], shuffleFirst = true): T[] {
|
||||
pokemonList = shuffleFirst ? shufflePokemonList(pokemonList) : pokemonList;
|
||||
if (shuffleFirst) {
|
||||
shufflePokemonList(pokemonList);
|
||||
}
|
||||
sortBySpeed(pokemonList);
|
||||
return pokemonList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuffle the list of pokemon *in place*
|
||||
* @param pokemonList - The array of Pokemon or objects containing Pokemon
|
||||
* @returns The shuffled array
|
||||
* @returns The same array instance that was passed in, shuffled.
|
||||
*/
|
||||
function shufflePokemonList<T extends Pokemon | hasPokemon>(pokemonList: T[]): T[] {
|
||||
// This is seeded with the current turn to prevent an inconsistency where it
|
||||
// was varying based on how long since you last reloaded
|
||||
globalScene.executeWithSeedOffset(
|
||||
() => {
|
||||
pokemonList = randSeedShuffle(pokemonList);
|
||||
},
|
||||
() => randSeedShuffle(pokemonList),
|
||||
globalScene.currentBattle.turn * 1000 + pokemonList.length,
|
||||
globalScene.waveSeed,
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user