From ff0e4fbdf048f07d3f7239d5b127c384d3e8b3ee Mon Sep 17 00:00:00 2001 From: Xavion3 Date: Tue, 4 Jun 2024 05:43:52 +1000 Subject: [PATCH] Implement Pity System (#1752) * Implement Pity System * Add comments and optimised worst case slightly --- src/egg-hatch-phase.ts | 16 +++++++++++++++- src/system/game-data.ts | 13 ++++++++++++- src/ui/egg-gacha-ui-handler.ts | 14 ++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/egg-hatch-phase.ts b/src/egg-hatch-phase.ts index f13097ac7eb..320b768e1e5 100644 --- a/src/egg-hatch-phase.ts +++ b/src/egg-hatch-phase.ts @@ -497,11 +497,19 @@ export class EggHatchPhase extends Phase { const ignoredSpecies = [ Species.PHIONE, Species.MANAPHY, Species.ETERNATUS ]; - const speciesPool = Object.keys(speciesStarters) + let speciesPool = Object.keys(speciesStarters) .filter(s => speciesStarters[s] >= minStarterValue && speciesStarters[s] <= maxStarterValue) .map(s => parseInt(s) as Species) .filter(s => !pokemonPrevolutions.hasOwnProperty(s) && getPokemonSpecies(s).isObtainable() && ignoredSpecies.indexOf(s) === -1); + // If this is the 10th egg without unlocking something new, attempt to force it. + if (this.scene.gameData.unlockPity[this.egg.tier] >= 9) { + const lockedPool = speciesPool.filter(s => !this.scene.gameData.dexData[s].caughtAttr); + if (lockedPool.length) { // Skip this if everything is unlocked + speciesPool = lockedPool; + } + } + /** * Pokemon that are cheaper in their tier get a weight boost. Regionals get a weight penalty * 1 cost mons get 2x @@ -536,6 +544,12 @@ export class EggHatchPhase extends Phase { } } + if (!!this.scene.gameData.dexData[species].caughtAttr) { + this.scene.gameData.unlockPity[this.egg.tier] = Math.min(this.scene.gameData.unlockPity[this.egg.tier] + 1, 10); + } else { + this.scene.gameData.unlockPity[this.egg.tier] = 0; + } + const pokemonSpecies = getPokemonSpecies(species); ret = this.scene.addPlayerPokemon(pokemonSpecies, 1, undefined, undefined, undefined, false); diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 35b6bc1435c..433ab13fd70 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -100,6 +100,8 @@ interface SystemSaveData { eggs: EggData[]; gameVersion: string; timestamp: integer; + eggPity: integer[]; + unlockPity: integer[]; } export interface SessionSaveData { @@ -248,6 +250,8 @@ export class GameData { public voucherUnlocks: VoucherUnlocks; public voucherCounts: VoucherCounts; public eggs: Egg[]; + public eggPity: integer[]; + public unlockPity: integer[]; constructor(scene: BattleScene) { this.scene = scene; @@ -272,6 +276,8 @@ export class GameData { [VoucherType.GOLDEN]: 0 }; this.eggs = []; + this.eggPity = [0, 0, 0, 0]; + this.unlockPity = [0, 0, 0, 0]; this.initDexData(); this.initStarterData(); } @@ -290,7 +296,9 @@ export class GameData { voucherCounts: this.voucherCounts, eggs: this.eggs.map(e => new EggData(e)), gameVersion: this.scene.game.config.gameVersion, - timestamp: new Date().getTime() + timestamp: new Date().getTime(), + eggPity: this.eggPity.slice(0), + unlockPity: this.unlockPity.slice(0) }; } @@ -473,6 +481,9 @@ export class GameData { ? systemData.eggs.map(e => e.toEgg()) : []; + this.eggPity = systemData.eggPity ? systemData.eggPity.slice(0) : [0, 0, 0, 0]; + this.unlockPity = systemData.unlockPity ? systemData.unlockPity.slice(0) : [0, 0, 0, 0]; + this.dexData = Object.assign(this.dexData, systemData.dexData); this.consolidateDexData(this.dexData); this.defaultDexData = null; diff --git a/src/ui/egg-gacha-ui-handler.ts b/src/ui/egg-gacha-ui-handler.ts index 9536df7dbed..f0e55e04801 100644 --- a/src/ui/egg-gacha-ui-handler.ts +++ b/src/ui/egg-gacha-ui-handler.ts @@ -378,6 +378,20 @@ export default class EggGachaUiHandler extends MessageUiHandler { } else if (pullCount >= 10 && !tiers.filter(t => t >= EggTier.GREAT).length) { tiers[Utils.randInt(tiers.length)] = EggTier.GREAT; } + for (let i = 0; i < pullCount; i++) { + this.scene.gameData.eggPity[EggTier.GREAT] += 1; + this.scene.gameData.eggPity[EggTier.ULTRA] += 1; + this.scene.gameData.eggPity[EggTier.MASTER] += 1 + tierValueOffset; + // These numbers are roughly the 80% mark. That is, 80% of the time you'll get an egg before this gets triggered. + if (this.scene.gameData.eggPity[EggTier.MASTER] >= 412 && tiers[i] === EggTier.COMMON) { + tiers[i] = EggTier.MASTER; + } else if (this.scene.gameData.eggPity[EggTier.ULTRA] >= 59 && tiers[i] === EggTier.COMMON) { + tiers[i] = EggTier.ULTRA; + } else if (this.scene.gameData.eggPity[EggTier.GREAT] >= 9 && tiers[i] === EggTier.COMMON) { + tiers[i] = EggTier.GREAT; + } + this.scene.gameData.eggPity[tiers[i]] = 0; + } const timestamp = new Date().getTime();