From 991f097e9e2488192dd7a6d8084365e49aa9200b Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Thu, 2 May 2024 17:48:08 -0400 Subject: [PATCH 1/2] Rebalance friendship and add starter friendship with candy reward --- src/data/pokemon-species.ts | 26 +++++++++++++++++++++++++- src/field/pokemon.ts | 27 +++++++++++++++++++++++++-- src/modifier/modifier-type.ts | 2 +- src/modifier/modifier.ts | 9 ++++----- src/phases.ts | 15 +++++---------- src/system/game-data.ts | 5 ++++- 6 files changed, 64 insertions(+), 20 deletions(-) diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index 2f8edefa403..c67f0c14b47 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -367,8 +367,8 @@ export abstract class PokemonSpeciesForm { loadAssets(scene: BattleScene, female: boolean, formIndex?: integer, shiny?: boolean, variant?: Variant, startLoad?: boolean): Promise { return new Promise(resolve => { const spriteKey = this.getSpriteKey(female, formIndex, shiny, variant); - scene.load.audio(this.getCryKey(formIndex), `audio/cry/${this.getCryKey(formIndex)}.m4a`); scene.loadPokemonAtlas(spriteKey, this.getSpriteAtlasPath(female, formIndex, shiny, variant)); + scene.load.audio(this.getCryKey(formIndex), `audio/cry/${this.getCryKey(formIndex)}.m4a`); scene.load.once(Phaser.Loader.Events.COMPLETE, () => { const originalWarn = console.warn; // Ignore warnings for missing frames, because there will be a lot @@ -3156,6 +3156,30 @@ export const noStarterFormKeys: string[] = [ SpeciesFormKey.ETERNAMAX ].map(k => k.toString()); +export function getStarterValueFriendshipCap(value: integer): integer { + switch (value) { + case 1: + return 20; + case 2: + return 40; + case 3: + return 60; + case 4: + return 100; + case 5: + return 140; + case 6: + return 200; + case 7: + return 280; + case 8: + case 9: + return 450; + default: + return 600; + } +} + export const starterPassiveAbilities = { [Species.BULBASAUR]: Abilities.SOLAR_POWER, [Species.CHARMANDER]: Abilities.INTIMIDATE, diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index daa7876853b..08482bbd914 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -5,12 +5,12 @@ import { variantData } from '#app/data/variant'; import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from '../ui/battle-info'; import { Moves } from "../data/enums/moves"; import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, VariablePowerAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, MultiHitAttr, StatusMoveTypeImmunityAttr, MoveTarget, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveTypeAttr, VariableMoveCategoryAttr } from "../data/move"; -import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, starterPassiveAbilities } from '../data/pokemon-species'; +import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, getStarterValueFriendshipCap, speciesStarters, starterPassiveAbilities } from '../data/pokemon-species'; import * as Utils from '../utils'; import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from '../data/type'; import { getLevelTotalExp } from '../data/exp'; import { Stat } from '../data/pokemon-stat'; -import { AttackTypeBoosterModifier, DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, PokemonBaseStatModifier, PokemonHeldItemModifier, PokemonMultiHitModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempBattleStatBoosterModifier, TerastallizeModifier } from '../modifier/modifier'; +import { AttackTypeBoosterModifier, DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, PokemonBaseStatModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonMultiHitModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempBattleStatBoosterModifier, TerastallizeModifier } from '../modifier/modifier'; import { PokeballType } from '../data/pokeball'; import { Gender } from '../data/gender'; import { initMoveAnim, loadMoveAnimAssets } from '../data/battle-anims'; @@ -2367,6 +2367,29 @@ export class PlayerPokemon extends Pokemon { }, PartyUiHandler.FilterNonFainted); }); } + + addFriendship(friendship: integer): void { + const starterSpeciesId = this.species.getRootSpeciesId(); + const starterData = this.scene.gameData.starterData[starterSpeciesId]; + const amount = new Utils.IntegerHolder(friendship); + const starterAmount = new Utils.IntegerHolder(friendship * (this.scene.gameMode.isClassic ? 2 : 1)); + if (amount.value > 0) { + this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, this, amount); + this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, this, starterAmount); + + this.friendship = Math.min(this.friendship + amount.value, 255); + if (this.friendship === 255) + this.scene.validateAchv(achvs.MAX_FRIENDSHIP); + starterData.friendship = (starterData.friendship || 0) + starterAmount.value; + if (starterData.friendship >= getStarterValueFriendshipCap(speciesStarters[starterSpeciesId])) { + this.scene.gameData.addStarterCandy(getPokemonSpecies(starterSpeciesId), 1); + starterData.friendship = 0; + } + } else { + this.friendship = Math.max(this.friendship + amount.value, 0); + starterData.friendship = Math.max((starterData.friendship || 0) + starterAmount.value, 0); + } + } getPossibleEvolution(evolution: SpeciesFormEvolution): Promise { return new Promise(resolve => { diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 6237e8b5a50..4229b8be3b7 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -1058,7 +1058,6 @@ const modifierPool: ModifierPool = { new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 10), new WeightedModifierType(modifierTypes.TM_ULTRA, 8), new WeightedModifierType(modifierTypes.RARER_CANDY, 4), - new WeightedModifierType(modifierTypes.SOOTHE_BELL, (party: Pokemon[]) => party.find(p => (pokemonEvolutions.hasOwnProperty(p.species.speciesId) && pokemonEvolutions[p.species.speciesId].find(e => e.condition && e.condition instanceof SpeciesFriendshipEvolutionCondition)) || p.moveset.find(m => m.moveId === Moves.RETURN)) ? 16 : 0, 16), new WeightedModifierType(modifierTypes.GOLDEN_PUNCH, 2), new WeightedModifierType(modifierTypes.IV_SCANNER, 4), new WeightedModifierType(modifierTypes.EXP_CHARM, 8), @@ -1078,6 +1077,7 @@ const modifierPool: ModifierPool = { new WeightedModifierType(modifierTypes.BATON, 2), new WeightedModifierType(modifierTypes.SOUL_DEW, 8), //new WeightedModifierType(modifierTypes.OVAL_CHARM, 6), + new WeightedModifierType(modifierTypes.SOOTHE_BELL, 4), new WeightedModifierType(modifierTypes.ABILITY_CHARM, 6), new WeightedModifierType(modifierTypes.FOCUS_BAND, 5), new WeightedModifierType(modifierTypes.KINGS_ROCK, 3), diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index d8fad1466b9..88b009d3a48 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -1111,9 +1111,7 @@ export class PokemonLevelIncrementModifier extends ConsumablePokemonModifier { pokemon.levelExp = 0; } - const friendshipIncrease = new Utils.IntegerHolder(5); - pokemon.scene.applyModifier(PokemonFriendshipBoosterModifier, true, pokemon, friendshipIncrease); - pokemon.friendship = Math.min(pokemon.friendship + friendshipIncrease.value, 255); + pokemon.addFriendship(5); pokemon.scene.unshiftPhase(new LevelUpPhase(pokemon.scene, pokemon.scene.getParty().indexOf(pokemon), pokemon.level - levelCount.value, pokemon.level)); @@ -1392,13 +1390,14 @@ export class PokemonFriendshipBoosterModifier extends PokemonHeldItemModifier { } apply(args: any[]): boolean { - (args[1] as Utils.IntegerHolder).value *= 1 + 0.5 * this.getStackCount(); + const friendship = args[1] as Utils.IntegerHolder; + friendship.value = Math.floor(friendship.value * (1 + 0.5 * this.getStackCount())); return true; } getMaxHeldItemCount(pokemon: Pokemon): integer { - return 5; + return 3; } } diff --git a/src/phases.ts b/src/phases.ts index 2ffa25aef0f..4c2f5536268 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -6,7 +6,7 @@ import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMov import { Mode } from './ui/ui'; import { Command } from "./ui/command-ui-handler"; import { Stat } from "./data/pokemon-stat"; -import { BerryModifier, ContactHeldItemTransferChanceModifier, EnemyAttackStatusEffectChanceModifier, EnemyPersistentModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, FusePokemonModifier, HealingBoosterModifier, HitHealModifier, LapsingPersistentModifier, MapModifier, Modifier, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, SwitchEffectTransferModifier, TempBattleStatBoosterModifier, TurnHealModifier, TurnHeldItemTransferModifier, MoneyMultiplierModifier, MoneyInterestModifier, IvScannerModifier, PokemonFriendshipBoosterModifier, LapsingPokemonHeldItemModifier, PokemonMultiHitModifier, PokemonMoveAccuracyBoosterModifier } from "./modifier/modifier"; +import { BerryModifier, ContactHeldItemTransferChanceModifier, EnemyAttackStatusEffectChanceModifier, EnemyPersistentModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, FusePokemonModifier, HealingBoosterModifier, HitHealModifier, LapsingPersistentModifier, MapModifier, Modifier, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, SwitchEffectTransferModifier, TempBattleStatBoosterModifier, TurnHealModifier, TurnHeldItemTransferModifier, MoneyMultiplierModifier, MoneyInterestModifier, IvScannerModifier, LapsingPokemonHeldItemModifier, PokemonMultiHitModifier, PokemonMoveAccuracyBoosterModifier } from "./modifier/modifier"; import PartyUiHandler, { PartyOption, PartyUiMode } from "./ui/party-ui-handler"; import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./data/pokeball"; import { CommonAnim, CommonBattleAnim, MoveAnim, initMoveAnim, loadMoveAnimAssets } from "./data/battle-anims"; @@ -3154,8 +3154,8 @@ export class FaintPhase extends PokemonPhase { this.scene.getField(true).filter(p => p !== pokemon).forEach(p => p.removeTagsBySourceId(pokemon.id)); pokemon.faintCry(() => { - const friendshipDecrease = new Utils.IntegerHolder(10); - pokemon.friendship = Math.max(pokemon.friendship - friendshipDecrease.value, 0); + if (pokemon instanceof PlayerPokemon) + pokemon.addFriendship(-10); pokemon.hideInfo(); this.scene.playSound('faint'); this.scene.tweens.add({ @@ -3226,13 +3226,8 @@ export class VictoryPhase extends PokemonPhase { for (let partyMember of expPartyMembers) { const pId = partyMember.id; const participated = participantIds.has(pId); - if (participated) { - const friendshipIncrease = new Utils.IntegerHolder(2); - this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, partyMember, friendshipIncrease); - partyMember.friendship = Math.min(partyMember.friendship + friendshipIncrease.value, 255); - if (partyMember.friendship === 255) - this.scene.validateAchv(achvs.MAX_FRIENDSHIP); - } + if (participated) + partyMember.addFriendship(2); else if (!expShareModifier) { partyMemberExp.push(0); continue; diff --git a/src/system/game-data.ts b/src/system/game-data.ts index e11c2dcc572..b7495a1eac9 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -169,6 +169,7 @@ export interface StarterDataEntry { moveset: StarterMoveset | StarterFormMoveData; eggMoves: integer; candyCount: integer; + friendship: integer; abilityAttr: integer; passiveAttr: integer; valueReduction: integer; @@ -988,6 +989,7 @@ export class GameData { moveset: null, eggMoves: 0, candyCount: 0, + friendship: 0, abilityAttr: defaultStarterSpecies.includes(speciesId) ? AbilityAttr.ABILITY_1 : 0, passiveAttr: 0, valueReduction: 0 @@ -1035,6 +1037,7 @@ export class GameData { const hasPrevolution = pokemonPrevolutions.hasOwnProperty(species.speciesId); const newCatch = !caughtAttr; + const hasNewAttr = (caughtAttr & dexAttr) !== dexAttr; if (incrementCount) { if (!fromEgg) { @@ -1057,7 +1060,7 @@ export class GameData { this.gameStats.shinyPokemonHatched++; } - if (!hasPrevolution) + if (!hasPrevolution && (!pokemon.scene.gameMode.isDaily || hasNewAttr)) this.addStarterCandy(species, (1 * (pokemon.isShiny() ? 5 * Math.pow(2, pokemon.variant || 0) : 1)) * (fromEgg || pokemon.isBoss() ? 2 : 1)); } From fec87718300aa5d0bd56f1679ed853815316a33d Mon Sep 17 00:00:00 2001 From: Benjamin Odom Date: Thu, 2 May 2024 16:49:22 -0500 Subject: [PATCH 2/2] Fix Shedinja Luck and Crash Shedinja wasn't taking the luck value from Ninjask so when it calculated its luck it just took the entire fused Pokemon's luck somehow. This has been fixed so it takes both the first and second part of the fusion's luck values instead. Also fixes an issue where Shedinja crashed the game if it was the second part of a fusion combo. Now the correct pokemon species gets checked against and the correct pokemon evolution occurs to create Shedinja. --- src/field/pokemon.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 08482bbd914..c5036ce72c6 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -2457,12 +2457,17 @@ export class PlayerPokemon extends Pokemon { private handleSpecialEvolutions(evolution: SpeciesFormEvolution) { const isFusion = evolution instanceof FusionSpeciesFormEvolution; - if ((!isFusion ? this.species : this.fusionSpecies).speciesId === Species.NINCADA && evolution.speciesId === Species.NINJASK) { - const newEvolution = pokemonEvolutions[this.species.speciesId][1]; + + const evoSpecies = (!isFusion ? this.species : this.fusionSpecies) + if (evoSpecies.speciesId === Species.NINCADA && evolution.speciesId === Species.NINJASK) { + const newEvolution = pokemonEvolutions[evoSpecies.speciesId][1]; + if (newEvolution.condition.predicate(this)) { const newPokemon = this.scene.addPlayerPokemon(this.species, this.level, this.abilityIndex, this.formIndex, undefined, this.shiny, this.variant, this.ivs, this.nature); newPokemon.natureOverride = this.natureOverride; newPokemon.moveset = this.moveset.slice(); + newPokemon.luck = this.luck; + newPokemon.fusionSpecies = this.fusionSpecies; newPokemon.fusionFormIndex = this.fusionFormIndex; newPokemon.fusionAbilityIndex = this.fusionAbilityIndex; @@ -2470,8 +2475,9 @@ export class PlayerPokemon extends Pokemon { newPokemon.fusionVariant = this.fusionVariant; newPokemon.fusionGender = this.fusionGender; newPokemon.fusionLuck = this.fusionLuck; + this.scene.getParty().push(newPokemon); - newPokemon.evolve(newEvolution); + newPokemon.evolve(!isFusion ? newEvolution : new FusionSpeciesFormEvolution(this.id, newEvolution)); const modifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier && (m as PokemonHeldItemModifier).pokemonId === this.id, true) as PokemonHeldItemModifier[]; modifiers.forEach(m => {