implement max spawns per run for individual encounters, tweak spawn rates
This commit is contained in:
parent
841efe16c7
commit
1a95f06795
|
@ -1071,13 +1071,14 @@ export default class BattleScene extends SceneBase {
|
|||
this.field.add(newTrainer);
|
||||
}
|
||||
|
||||
// Check for mystery encounter
|
||||
// Can only occur in place of a standard wild battle, waves 10-180
|
||||
// TODO: remove this once spawn rates are finalized
|
||||
// let testStartingWeight = 0;
|
||||
// while (testStartingWeight < 20) {
|
||||
// while (testStartingWeight < 3) {
|
||||
// calculateMEAggregateStats(this, testStartingWeight);
|
||||
// testStartingWeight += 1;
|
||||
// }
|
||||
// Check for mystery encounter
|
||||
// Can only occur in place of a standard wild battle, waves 10-180
|
||||
if (this.gameMode.hasMysteryEncounters && newBattleType === BattleType.WILD && !this.gameMode.isBoss(newWaveIndex) && newWaveIndex < 180 && newWaveIndex > 10) {
|
||||
const roll = Utils.randSeedInt(256);
|
||||
|
||||
|
@ -2651,7 +2652,7 @@ export default class BattleScene extends SceneBase {
|
|||
}
|
||||
|
||||
// Common / Uncommon / Rare / Super Rare
|
||||
const tierWeights = [61, 40, 21, 6];
|
||||
const tierWeights = [64, 40, 21, 3];
|
||||
|
||||
// Adjust tier weights by previously encountered events to lower odds of only common/uncommons in run
|
||||
this.mysteryEncounterData.encounteredEvents.forEach(val => {
|
||||
|
@ -2681,10 +2682,23 @@ export default class BattleScene extends SceneBase {
|
|||
// If no valid encounters exist at tier, checks next tier down, continuing until there are some encounters available
|
||||
while (availableEncounters.length === 0 && tier >= 0) {
|
||||
availableEncounters = biomeMysteryEncounters
|
||||
.filter((encounterType) =>
|
||||
allMysteryEncounters[encounterType]?.meetsRequirements(this) &&
|
||||
allMysteryEncounters[encounterType].encounterTier === tier &&
|
||||
(isNullOrUndefined(previousEncounter) || encounterType !== previousEncounter))
|
||||
.filter((encounterType) => {
|
||||
if (allMysteryEncounters[encounterType].encounterTier !== tier) { // Encounter is in tier
|
||||
return false;
|
||||
}
|
||||
if (!allMysteryEncounters[encounterType]?.meetsRequirements(this)) { // Meets encounter requirements
|
||||
return false;
|
||||
}
|
||||
if (!isNullOrUndefined(previousEncounter) && encounterType === previousEncounter) { // Previous encounter was not this one
|
||||
return false;
|
||||
}
|
||||
if (this.mysteryEncounterData.encounteredEvents?.length > 0 && // Encounter has not exceeded max allowed encounters
|
||||
allMysteryEncounters[encounterType].maxAllowedEncounters > 0
|
||||
&& this.mysteryEncounterData.encounteredEvents.filter(e => e[0] === encounterType).length >= allMysteryEncounters[encounterType].maxAllowedEncounters) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.map((m) => (allMysteryEncounters[m]));
|
||||
tier--;
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ export default interface IMysteryEncounter {
|
|||
hideBattleIntroMessage?: boolean;
|
||||
hideIntroVisuals?: boolean;
|
||||
catchAllowed?: boolean;
|
||||
maxAllowedEncounters?: number;
|
||||
doEncounterExp?: (scene: BattleScene) => boolean;
|
||||
doEncounterRewards?: (scene: BattleScene) => boolean;
|
||||
onInit?: (scene: BattleScene) => boolean;
|
||||
|
@ -144,6 +145,8 @@ export default class IMysteryEncounter implements IMysteryEncounter {
|
|||
}
|
||||
this.encounterTier = this.encounterTier ? this.encounterTier : MysteryEncounterTier.COMMON;
|
||||
this.dialogue = this.dialogue ?? {};
|
||||
// Default max is 1 for ROGUE encounters, 3 for others
|
||||
this.maxAllowedEncounters = this.maxAllowedEncounters ?? this.encounterTier === MysteryEncounterTier.ROGUE ? 1 : 3;
|
||||
this.encounterVariant = MysteryEncounterVariant.DEFAULT;
|
||||
this.requirements = this.requirements ? this.requirements : [];
|
||||
this.hideBattleIntroMessage = !isNullOrUndefined(this.hideBattleIntroMessage) ? this.hideBattleIntroMessage : false;
|
||||
|
@ -435,9 +438,9 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
|||
* If not specified, defaults to COMMON
|
||||
* Tiers are:
|
||||
* COMMON 32/64 odds
|
||||
* UNCOMMON 16/64 odds
|
||||
* RARE 10/64 odds
|
||||
* SUPER_RARE 6/64 odds
|
||||
* GREAT 16/64 odds
|
||||
* ULTRA 10/64 odds
|
||||
* ROGUE 6/64 odds
|
||||
* ULTRA_RARE Not currently used
|
||||
* @param encounterTier
|
||||
* @returns
|
||||
|
@ -446,6 +449,15 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
|||
return Object.assign(this, { encounterTier: encounterTier });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum number of times that an encounter can spawn in a given Classic run
|
||||
* @param maxAllowedEncounters
|
||||
* @returns
|
||||
*/
|
||||
withMaxAllowedEncounters(maxAllowedEncounters: number): this & Required<Pick<IMysteryEncounter, "maxAllowedEncounters">> {
|
||||
return Object.assign(this, { maxAllowedEncounters: maxAllowedEncounters });
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies a requirement for an encounter
|
||||
* For example, passing requirement as "new WaveCountRequirement([2, 180])" would create a requirement that the encounter can only be spawned between waves 2 and 180
|
||||
|
|
|
@ -632,7 +632,7 @@ export function calculateMEAggregateStats(scene: BattleScene, baseSpawnWeight: n
|
|||
|
||||
// Calculate encounter rarity
|
||||
// Common / Uncommon / Rare / Super Rare (base is out of 128)
|
||||
const tierWeights = [61, 40, 21, 6];
|
||||
const tierWeights = [64, 40, 21, 3];
|
||||
|
||||
// Adjust tier weights by currently encountered events (pity system that lowers odds of multiple common/uncommons)
|
||||
tierWeights[0] = tierWeights[0] - 6 * numEncounters[0];
|
||||
|
|
Loading…
Reference in New Issue