From d1294caeb60b9a291a2558900a841e3d407d5019 Mon Sep 17 00:00:00 2001 From: star-krieg <113486223+star-krieg@users.noreply.github.com> Date: Sun, 1 Dec 2024 03:28:29 +0800 Subject: [PATCH] [Balance] Candy friendship changes (#4947) Changes: - Increase default value for friendship gain from winning a battle (from 2 to 3) - Increase Classic candy friendship multiplier (from 2 to 3) - Increase Rare Candy friendship gain (from 5 to 6) - Decrease value for friendship decrease from losing a battle (from 10 to 5) - Update Candy friendship thresholds for getting candy for some starter costs. - Change Soothe Bell from Rogue to Great (Weight: 2 in Great) - Adjust Map weight to account for change (Weight: 1 to 2) - Clowning around ME: When shuffling items, soothe bells will get replaced by a random Ultra Tier item - Clowning around ME: When shuffling items, no item will get replaced by a Soothe Bell Commit history: * Candy friendship changes Update default value for friendship gain from battle and adjust Soothe Bell tier to Great * Update modifier-type.ts * Update friendship constants * Clowning around encounter no longer consider soothe bell rogue tier * Expert Breeder ME test will no longer fail if candy gain per battle is changed --------- Co-authored-by: Starkrieg Co-authored-by: damocleas Co-authored-by: Moka Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> --- src/data/balance/starters.ts | 18 +++++++++--------- .../encounters/clowning-around-encounter.ts | 5 +++-- src/modifier/modifier-type.ts | 4 ++-- .../clowning-around-encounter.test.ts | 5 ++++- .../the-expert-breeder-encounter.test.ts | 10 +++++++--- 5 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/data/balance/starters.ts b/src/data/balance/starters.ts index d6a1f0c3eaf..a4a3c9d011c 100644 --- a/src/data/balance/starters.ts +++ b/src/data/balance/starters.ts @@ -3,10 +3,10 @@ import { Species } from "#enums/species"; export const POKERUS_STARTER_COUNT = 5; // #region Friendship constants -export const CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER = 2; -export const FRIENDSHIP_GAIN_FROM_BATTLE = 2; -export const FRIENDSHIP_GAIN_FROM_RARE_CANDY = 5; -export const FRIENDSHIP_LOSS_FROM_FAINT = 10; +export const CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER = 3; +export const FRIENDSHIP_GAIN_FROM_BATTLE = 3; +export const FRIENDSHIP_GAIN_FROM_RARE_CANDY = 6; +export const FRIENDSHIP_LOSS_FROM_FAINT = 5; /** * Function to get the cumulative friendship threshold at which a candy is earned @@ -16,19 +16,19 @@ export const FRIENDSHIP_LOSS_FROM_FAINT = 10; export function getStarterValueFriendshipCap(starterCost: number): number { switch (starterCost) { case 1: - return 20; + return 25; case 2: - return 40; + return 50; case 3: - return 60; + return 75; case 4: return 100; case 5: - return 140; + return 150; case 6: return 200; case 7: - return 280; + return 300; case 8: case 9: return 450; diff --git a/src/data/mystery-encounters/encounters/clowning-around-encounter.ts b/src/data/mystery-encounters/encounters/clowning-around-encounter.ts index ae6cabd4dae..6bd6856604b 100644 --- a/src/data/mystery-encounters/encounters/clowning-around-encounter.ts +++ b/src/data/mystery-encounters/encounters/clowning-around-encounter.ts @@ -276,6 +276,8 @@ export const ClowningAroundEncounter: MysteryEncounter = generateItemsOfTier(scene, mostHeldItemsPokemon, numBerries, "Berries"); // Shuffle Transferable held items in the same tier (only shuffles Ultra and Rogue atm) + // For the purpose of this ME, Soothe Bells and Lucky Eggs are counted as Ultra tier + // And Golden Eggs as Rogue tier let numUltra = 0; let numRogue = 0; items.filter(m => m.isTransferable && !(m instanceof BerryModifier)) @@ -285,7 +287,7 @@ export const ClowningAroundEncounter: MysteryEncounter = if (type.id === "GOLDEN_EGG" || tier === ModifierTier.ROGUE) { numRogue += m.stackCount; scene.removeModifier(m); - } else if (type.id === "LUCKY_EGG" || tier === ModifierTier.ULTRA) { + } else if (type.id === "LUCKY_EGG" || type.id === "SOOTHE_BELL" || tier === ModifierTier.ULTRA) { numUltra += m.stackCount; scene.removeModifier(m); } @@ -456,7 +458,6 @@ function generateItemsOfTier(scene: BattleScene, pokemon: PlayerPokemon, numItem [ modifierTypes.LEFTOVERS, 4 ], [ modifierTypes.SHELL_BELL, 4 ], [ modifierTypes.SOUL_DEW, 10 ], - [ modifierTypes.SOOTHE_BELL, 3 ], [ modifierTypes.SCOPE_LENS, 1 ], [ modifierTypes.BATON, 1 ], [ modifierTypes.FOCUS_BAND, 5 ], diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 901aa422c61..04776afc624 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -1702,7 +1702,8 @@ const modifierPool: ModifierPool = { new WeightedModifierType(modifierTypes.EVOLUTION_ITEM, (party: Pokemon[]) => { return Math.min(Math.ceil(party[0].scene.currentBattle.waveIndex / 15), 8); }, 8), - new WeightedModifierType(modifierTypes.MAP, (party: Pokemon[]) => party[0].scene.gameMode.isClassic && party[0].scene.currentBattle.waveIndex < 180 ? 1 : 0, 1), + new WeightedModifierType(modifierTypes.MAP, (party: Pokemon[]) => party[0].scene.gameMode.isClassic && party[0].scene.currentBattle.waveIndex < 180 ? 2 : 0, 2), + new WeightedModifierType(modifierTypes.SOOTHE_BELL, 2), new WeightedModifierType(modifierTypes.TM_GREAT, 3), new WeightedModifierType(modifierTypes.MEMORY_MUSHROOM, (party: Pokemon[]) => { if (!party.find(p => p.getLearnableLevelMoves().length)) { @@ -1800,7 +1801,6 @@ const modifierPool: ModifierPool = { new WeightedModifierType(modifierTypes.SOUL_DEW, 7), //new WeightedModifierType(modifierTypes.OVAL_CHARM, 6), new WeightedModifierType(modifierTypes.CATCHING_CHARM, (party: Pokemon[]) => !party[0].scene.gameMode.isFreshStartChallenge() && party[0].scene.gameData.getSpeciesCount(d => !!d.caughtAttr) > 100 ? 4 : 0, 4), - new WeightedModifierType(modifierTypes.SOOTHE_BELL, 4), new WeightedModifierType(modifierTypes.ABILITY_CHARM, skipInClassicAfterWave(189, 6)), new WeightedModifierType(modifierTypes.FOCUS_BAND, 5), new WeightedModifierType(modifierTypes.KINGS_ROCK, 3), diff --git a/src/test/mystery-encounter/encounters/clowning-around-encounter.test.ts b/src/test/mystery-encounter/encounters/clowning-around-encounter.test.ts index a403a306b3d..e7ea6eea0ea 100644 --- a/src/test/mystery-encounter/encounters/clowning-around-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/clowning-around-encounter.test.ts @@ -266,6 +266,9 @@ describe("Clowning Around - Mystery Encounter", () => { // 5 Lucky Egg on lead (ultra) itemType = generateModifierType(scene, modifierTypes.LUCKY_EGG) as PokemonHeldItemModifierType; await addItemToPokemon(scene, scene.getPlayerParty()[0], 5, itemType); + // 3 Soothe Bell on lead (great tier, but counted as ultra by this ME) + itemType = generateModifierType(scene, modifierTypes.SOOTHE_BELL) as PokemonHeldItemModifierType; + await addItemToPokemon(scene, scene.getPlayerParty()[0], 3, itemType); // 5 Soul Dew on lead (rogue) itemType = generateModifierType(scene, modifierTypes.SOUL_DEW) as PokemonHeldItemModifierType; await addItemToPokemon(scene, scene.getPlayerParty()[0], 5, itemType); @@ -286,7 +289,7 @@ describe("Clowning Around - Mystery Encounter", () => { const rogueCountAfter = leadItemsAfter .filter(m => m.type.tier === ModifierTier.ROGUE) .reduce((a, b) => a + b.stackCount, 0); - expect(ultraCountAfter).toBe(10); + expect(ultraCountAfter).toBe(13); expect(rogueCountAfter).toBe(7); const secondItemsAfter = scene.getPlayerParty()[1].getHeldItems(); diff --git a/src/test/mystery-encounter/encounters/the-expert-breeder-encounter.test.ts b/src/test/mystery-encounter/encounters/the-expert-breeder-encounter.test.ts index 7fc2490fcc9..87ccff71e22 100644 --- a/src/test/mystery-encounter/encounters/the-expert-breeder-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/the-expert-breeder-encounter.test.ts @@ -18,6 +18,7 @@ import { TheExpertPokemonBreederEncounter } from "#app/data/mystery-encounters/e import { TrainerType } from "#enums/trainer-type"; import { EggTier } from "#enums/egg-type"; import { PostMysteryEncounterPhase } from "#app/phases/mystery-encounter-phases"; +import { FRIENDSHIP_GAIN_FROM_BATTLE } from "#app/data/balance/starters"; const namespace = "mysteryEncounters/theExpertPokemonBreeder"; const defaultParty = [ Species.LAPRAS, Species.GENGAR, Species.ABRA ]; @@ -182,7 +183,10 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { await game.phaseInterceptor.to(PostMysteryEncounterPhase); const friendshipAfter = scene.currentBattle.mysteryEncounter!.misc.pokemon1.friendship; - expect(friendshipAfter).toBe(friendshipBefore + 20 + 2); // +2 extra for friendship gained from winning battle + // 20 from ME + extra from winning battle (that extra is not accurate to what happens in game. + // The Pokemon normally gets FRIENDSHIP_GAIN_FROM_BATTLE 3 times, once for each defeated Pokemon + // but due to how skipBattleRunMysteryEncounterRewardsPhase is implemented, it only receives it once) + expect(friendshipAfter).toBe(friendshipBefore + 20 + FRIENDSHIP_GAIN_FROM_BATTLE); }); }); @@ -261,7 +265,7 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { await game.phaseInterceptor.to(PostMysteryEncounterPhase); const friendshipAfter = scene.currentBattle.mysteryEncounter!.misc.pokemon2.friendship; - expect(friendshipAfter).toBe(friendshipBefore + 20 + 2); // +2 extra for friendship gained from winning battle + expect(friendshipAfter).toBe(friendshipBefore + 20 + FRIENDSHIP_GAIN_FROM_BATTLE); // 20 from ME + extra for friendship gained from winning battle }); }); @@ -340,7 +344,7 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { await game.phaseInterceptor.to(PostMysteryEncounterPhase); const friendshipAfter = scene.currentBattle.mysteryEncounter!.misc.pokemon3.friendship; - expect(friendshipAfter).toBe(friendshipBefore + 20 + 2); // +2 extra for friendship gained from winning battle + expect(friendshipAfter).toBe(friendshipBefore + 20 + FRIENDSHIP_GAIN_FROM_BATTLE); // 20 + extra for friendship gained from winning battle }); }); });