small ME balance changes
This commit is contained in:
parent
162a3b1d5b
commit
ed8d502cf4
|
@ -22,7 +22,7 @@ import {
|
|||
getModifierPoolForType,
|
||||
getModifierType,
|
||||
getPartyLuckValue,
|
||||
modifierTypes
|
||||
modifierTypes, PokemonHeldItemModifierType
|
||||
} from "./modifier/modifier-type";
|
||||
import AbilityBar from "./ui/ability-bar";
|
||||
import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, ChangeMovePriorityAbAttr, PostBattleInitAbAttr, applyAbAttrs, applyPostBattleInitAbAttrs } from "./data/ability";
|
||||
|
@ -2521,13 +2521,19 @@ export default class BattleScene extends SceneBase {
|
|||
party.forEach((enemyPokemon: EnemyPokemon, i: integer) => {
|
||||
if (heldModifiersConfigs && i < heldModifiersConfigs.length && heldModifiersConfigs[i] && heldModifiersConfigs[i].length > 0) {
|
||||
heldModifiersConfigs[i].forEach(mt => {
|
||||
const stackCount = mt.stackCount ?? 1;
|
||||
// const isTransferable = mt.isTransferable ?? true;
|
||||
const modifier = mt.modifierType.newModifier(enemyPokemon);
|
||||
modifier.stackCount = stackCount;
|
||||
// TODO: set isTransferable
|
||||
// modifier.setIsTransferable(isTransferable);
|
||||
this.addEnemyModifier(modifier, true);
|
||||
if (mt.modifier instanceof PokemonHeldItemModifierType) {
|
||||
const stackCount = mt.stackCount ?? 1;
|
||||
// const isTransferable = mt.isTransferable ?? true;
|
||||
const modifier = mt.modifier.newModifier(enemyPokemon);
|
||||
modifier.stackCount = stackCount;
|
||||
// TODO: set isTransferable
|
||||
// modifier.setIsTransferable(isTransferable);
|
||||
this.addEnemyModifier(modifier, true);
|
||||
} else {
|
||||
const modifier = mt.modifier as PokemonHeldItemModifier;
|
||||
modifier.pokemonId = enemyPokemon.id;
|
||||
this.addEnemyModifier(modifier, true);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
const isBoss = enemyPokemon.isBoss() || (this.currentBattle.battleType === BattleType.TRAINER && !!this.currentBattle.trainer?.config.isBoss);
|
||||
|
|
|
@ -13,6 +13,8 @@ import { IEggOptions } from "#app/data/egg";
|
|||
import { EggSourceType } from "#enums/egg-source-types";
|
||||
import { EggTier } from "#enums/egg-type";
|
||||
import { PartyHealPhase } from "#app/phases/party-heal-phase";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:aTrainersTest";
|
||||
|
@ -136,7 +138,7 @@ export const ATrainersTestEncounter: MysteryEncounter =
|
|||
},
|
||||
async (scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
// Spawn standard trainer battle with memory mushroom reward
|
||||
// Battle the stat trainer for an Egg and great rewards
|
||||
const config: EnemyPartyConfig = encounter.enemyPartyConfigs[0];
|
||||
|
||||
await transitionMysteryEncounterIntroVisuals(scene);
|
||||
|
@ -149,7 +151,7 @@ export const ATrainersTestEncounter: MysteryEncounter =
|
|||
tier: EggTier.ULTRA
|
||||
};
|
||||
encounter.setDialogueToken("eggType", i18next.t(`${namespace}.eggTypes.epic`));
|
||||
setEncounterRewards(scene, { fillRemaining: true }, [eggOptions]);
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SACRED_ASH], guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ULTRA], fillRemaining: true }, [eggOptions]);
|
||||
|
||||
return initBattleWithEnemyConfig(scene, config);
|
||||
}
|
||||
|
|
|
@ -141,11 +141,11 @@ export const DancingLessonsEncounter: MysteryEncounter =
|
|||
species: species,
|
||||
dataSource: oricorioData,
|
||||
isBoss: true,
|
||||
// Gets +1 to all stats on battle start
|
||||
// Gets +1 to all stats except SPD on battle start
|
||||
tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON],
|
||||
mysteryEncounterBattleEffects: (pokemon: Pokemon) => {
|
||||
queueEncounterMessage(pokemon.scene, `${namespace}.option.1.boss_enraged`);
|
||||
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [BattleStat.ATK, BattleStat.DEF, BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD], 1));
|
||||
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [BattleStat.ATK, BattleStat.DEF, BattleStat.SPATK, BattleStat.SPDEF], 1));
|
||||
}
|
||||
}],
|
||||
};
|
||||
|
|
|
@ -12,6 +12,7 @@ import { getRandomPlayerPokemon, getRandomSpeciesByStarterTier } from "#app/data
|
|||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase";
|
||||
import { PokemonFormChangeItemModifier, PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||
|
||||
/** i18n namespace for encounter */
|
||||
const namespace = "mysteryEncounter:darkDeal";
|
||||
|
@ -125,25 +126,27 @@ export const DarkDealEncounter: MysteryEncounter =
|
|||
// Removes random pokemon (including fainted) from party and adds name to dialogue data tokens
|
||||
// Will never return last battle able mon and instead pick fainted/unable to battle
|
||||
const removedPokemon = getRandomPlayerPokemon(scene, false, true);
|
||||
// Get all the pokemon's held items
|
||||
const modifiers = removedPokemon.getHeldItems().filter(m => !(m instanceof PokemonFormChangeItemModifier));
|
||||
scene.removePokemonFromPlayerParty(removedPokemon);
|
||||
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
encounter.setDialogueToken("pokeName", removedPokemon.getNameToRender());
|
||||
|
||||
// Store removed pokemon types
|
||||
encounter.misc = [
|
||||
removedPokemon.species.type1,
|
||||
];
|
||||
if (removedPokemon.species.type2) {
|
||||
encounter.misc.push(removedPokemon.species.type2);
|
||||
}
|
||||
encounter.misc = {
|
||||
removedTypes: removedPokemon.getTypes(),
|
||||
modifiers
|
||||
};
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Give the player 5 Rogue Balls
|
||||
const encounter = scene.currentBattle.mysteryEncounter!;
|
||||
scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.ROGUE_BALL));
|
||||
|
||||
// Start encounter with random legendary (7-10 starter strength) that has level additive
|
||||
const bossTypes = scene.currentBattle.mysteryEncounter!.misc as Type[];
|
||||
const bossTypes: Type[] = encounter.misc.removedTypes;
|
||||
const bossModifiers: PokemonHeldItemModifier[] = encounter.misc.modifiers;
|
||||
// Starter egg tier, 35/50/10/5 %odds for tiers 6/7/8/9+
|
||||
const roll = randSeedInt(100);
|
||||
const starterTier: number | [number, number] =
|
||||
|
@ -152,6 +155,11 @@ export const DarkDealEncounter: MysteryEncounter =
|
|||
const pokemonConfig: EnemyPokemonConfig = {
|
||||
species: bossSpecies,
|
||||
isBoss: true,
|
||||
modifierConfigs: bossModifiers.map(m => {
|
||||
return {
|
||||
modifier: m
|
||||
};
|
||||
})
|
||||
};
|
||||
if (!isNullOrUndefined(bossSpecies.forms) && bossSpecies.forms.length > 0) {
|
||||
pokemonConfig.formIndex = 0;
|
||||
|
|
|
@ -6,7 +6,7 @@ import MysteryEncounter, { MysteryEncounterBuilder } from "../mystery-encounter"
|
|||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { Species } from "#enums/species";
|
||||
import { Nature } from "#app/data/nature";
|
||||
import Pokemon, { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
||||
import Pokemon, { PokemonMove } from "#app/field/pokemon";
|
||||
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||
import { modifyPlayerPokemonBST } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
import { Moves } from "#enums/moves";
|
||||
|
@ -30,6 +30,7 @@ export const TheStrongStuffEncounter: MysteryEncounter =
|
|||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.THE_STRONG_STUFF)
|
||||
.withEncounterTier(MysteryEncounterTier.COMMON)
|
||||
.withSceneWaveRangeRequirement(10, 180) // waves 10 to 180
|
||||
.withScenePartySizeRequirement(3, 6) // Must have at least 3 pokemon in party
|
||||
.withHideWildIntroMessage(true)
|
||||
.withAutoHideIntroVisuals(false)
|
||||
.withIntroSpriteConfigs([
|
||||
|
@ -124,35 +125,21 @@ export const TheStrongStuffEncounter: MysteryEncounter =
|
|||
transitionMysteryEncounterIntroVisuals(scene, true, true, 50);
|
||||
});
|
||||
|
||||
// -20 to all base stats of highest BST, +10 to all base stats of rest of party
|
||||
// Get highest BST mon
|
||||
const party = scene.getParty();
|
||||
let highestBst: PlayerPokemon | null = null;
|
||||
let statTotal = 0;
|
||||
for (const pokemon of party) {
|
||||
if (!highestBst) {
|
||||
highestBst = pokemon;
|
||||
statTotal = pokemon.getSpeciesForm().getBaseStatTotal();
|
||||
continue;
|
||||
}
|
||||
|
||||
const total = pokemon.getSpeciesForm().getBaseStatTotal();
|
||||
if (total > statTotal) {
|
||||
highestBst = pokemon;
|
||||
statTotal = total;
|
||||
}
|
||||
}
|
||||
|
||||
if (!highestBst) {
|
||||
highestBst = party[0];
|
||||
}
|
||||
|
||||
modifyPlayerPokemonBST(highestBst, -20);
|
||||
for (const pokemon of party) {
|
||||
if (highestBst.id === pokemon.id) {
|
||||
continue;
|
||||
}
|
||||
// -15 to all base stats of highest BST (halved for HP), +10 to all base stats of rest of party (halved for HP)
|
||||
// Sort party by bst (inverted to pop 2 highest off end)
|
||||
const sortedParty = scene.getParty().slice(0)
|
||||
.sort((pokemon1, pokemon2) => {
|
||||
const pokemon1Bst = pokemon1.calculateBaseStats().reduce((a, b) => a + b, 0);
|
||||
const pokemon2Bst = pokemon2.calculateBaseStats().reduce((a, b) => a + b, 0);
|
||||
return pokemon1Bst - pokemon2Bst;
|
||||
});
|
||||
|
||||
const highestBst = sortedParty.pop()!;
|
||||
const highestBst2 = sortedParty.pop()!;
|
||||
modifyPlayerPokemonBST(highestBst, -15);
|
||||
modifyPlayerPokemonBST(highestBst2, -15);
|
||||
// +10 for the rest
|
||||
for (const pokemon of sortedParty) {
|
||||
modifyPlayerPokemonBST(pokemon, 10);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ const namespace = "mysteryEncounter:theWinstrateChallenge";
|
|||
export const TheWinstrateChallengeEncounter: MysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.THE_WINSTRATE_CHALLENGE)
|
||||
.withEncounterTier(MysteryEncounterTier.ROGUE)
|
||||
.withSceneWaveRangeRequirement(80, 180)
|
||||
.withSceneWaveRangeRequirement(100, 180)
|
||||
.withIntroSpriteConfigs([
|
||||
{
|
||||
spriteKey: "vito",
|
||||
|
|
|
@ -4,7 +4,7 @@ import { getNatureName, Nature } from "#app/data/nature";
|
|||
import { speciesStarters } from "#app/data/pokemon-species";
|
||||
import { getStatName } from "#app/data/pokemon-stat";
|
||||
import Pokemon, { PlayerPokemon } from "#app/field/pokemon";
|
||||
import { PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||
import { PokemonFormChangeItemModifier, PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||
import { AbilityAttr } from "#app/system/game-data";
|
||||
import PokemonData from "#app/system/pokemon-data";
|
||||
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||
|
@ -247,9 +247,10 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
|||
playerPokemon.setNature(encounter.misc.chosenNature);
|
||||
scene.gameData.setPokemonCaught(playerPokemon, false);
|
||||
|
||||
// Add pokemon and mods back
|
||||
// Add pokemon and modifiers back
|
||||
scene.getParty().push(playerPokemon);
|
||||
for (const mod of modifiers.value) {
|
||||
mod.pokemonId = playerPokemon.id;
|
||||
scene.addModifier(mod, true, false, false, true);
|
||||
}
|
||||
scene.updateModifiers(true);
|
||||
|
@ -385,10 +386,10 @@ function getEnemyConfig(scene: BattleScene, playerPokemon: PlayerPokemon, segmen
|
|||
playerPokemon.resetSummonData();
|
||||
|
||||
// Passes modifiers by reference
|
||||
modifiers.value = scene.findModifiers((m) => m instanceof PokemonHeldItemModifier && (m as PokemonHeldItemModifier).pokemonId === playerPokemon.id) as PokemonHeldItemModifier[];
|
||||
modifiers.value = playerPokemon.getHeldItems().filter(m => !(m instanceof PokemonFormChangeItemModifier));
|
||||
const modifierConfigs = modifiers.value.map((mod) => {
|
||||
return {
|
||||
modifierType: mod.type
|
||||
modifier: mod
|
||||
};
|
||||
}) as HeldModifierConfig[];
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ const SOUND_EFFECT_WAIT_TIME = 700;
|
|||
export const TrashToTreasureEncounter: MysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.TRASH_TO_TREASURE)
|
||||
.withEncounterTier(MysteryEncounterTier.ULTRA)
|
||||
.withSceneWaveRangeRequirement(10, 180)
|
||||
.withSceneWaveRangeRequirement(60, 180)
|
||||
.withMaxAllowedEncounters(1)
|
||||
.withIntroSpriteConfigs([
|
||||
{
|
||||
|
|
|
@ -94,6 +94,7 @@ const STANDARD_BST_TRANSFORM_BASE_VALUES = [40, 50];
|
|||
export const WeirdDreamEncounter: MysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.WEIRD_DREAM)
|
||||
.withEncounterTier(MysteryEncounterTier.ROGUE)
|
||||
.withSceneWaveRangeRequirement(10, 180)
|
||||
.withIntroSpriteConfigs([
|
||||
{
|
||||
spriteKey: "girawitch",
|
||||
|
@ -111,7 +112,6 @@ export const WeirdDreamEncounter: MysteryEncounter =
|
|||
text: `${namespace}.intro_dialogue`,
|
||||
},
|
||||
])
|
||||
.withSceneWaveRangeRequirement(10, 180)
|
||||
.withTitle(`${namespace}.title`)
|
||||
.withDescription(`${namespace}.description`)
|
||||
.withQuery(`${namespace}.query`)
|
||||
|
|
|
@ -10,7 +10,7 @@ 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 { DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, PokemonBaseStatModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempBattleStatBoosterModifier, StatBoosterModifier, CritBoosterModifier, TerastallizeModifier, PokemonBaseStatTotalModifier, PokemonIncrementingStatModifier } from "../modifier/modifier";
|
||||
import { DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, PokemonBaseStatModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempBattleStatBoosterModifier, StatBoosterModifier, CritBoosterModifier, TerastallizeModifier, PokemonBaseStatTotalModifier, PokemonIncrementingStatModifier, PokemonBaseStatFlatModifier } from "../modifier/modifier";
|
||||
import { PokeballType } from "../data/pokeball";
|
||||
import { Gender } from "../data/gender";
|
||||
import { initMoveAnim, loadMoveAnimAssets } from "../data/battle-anims";
|
||||
|
@ -778,19 +778,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
if (!this.stats) {
|
||||
this.stats = [ 0, 0, 0, 0, 0, 0 ];
|
||||
}
|
||||
const baseStats = this.getSpeciesForm().baseStats.slice(0);
|
||||
this.scene.applyModifiers(PokemonBaseStatTotalModifier, this.isPlayer(), this, baseStats);
|
||||
if (this.fusionSpecies) {
|
||||
const fusionBaseStats = this.getFusionSpeciesForm().baseStats;
|
||||
for (let s = 0; s < this.stats.length; s++) {
|
||||
baseStats[s] = Math.ceil((baseStats[s] + fusionBaseStats[s]) / 2);
|
||||
}
|
||||
} else if (this.scene.gameMode.isSplicedOnly) {
|
||||
for (let s = 0; s < this.stats.length; s++) {
|
||||
baseStats[s] = Math.ceil(baseStats[s] / 2);
|
||||
}
|
||||
}
|
||||
this.scene.applyModifiers(PokemonBaseStatModifier, this.isPlayer(), this, baseStats);
|
||||
const baseStats = this.calculateBaseStats();
|
||||
const stats = Utils.getEnumValues(Stat);
|
||||
for (const s of stats) {
|
||||
const isHp = s === Stat.HP;
|
||||
|
@ -822,6 +810,27 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
this.scene.applyModifier(PokemonIncrementingStatModifier, this.isPlayer(), this, this.stats);
|
||||
}
|
||||
|
||||
calculateBaseStats(): number[] {
|
||||
const baseStats = this.getSpeciesForm().baseStats.slice(0);
|
||||
// Shuckle Juice
|
||||
this.scene.applyModifiers(PokemonBaseStatTotalModifier, this.isPlayer(), this, baseStats);
|
||||
// Old Gateau
|
||||
this.scene.applyModifiers(PokemonBaseStatFlatModifier, this.isPlayer(), this, baseStats);
|
||||
if (this.fusionSpecies) {
|
||||
const fusionBaseStats = this.getFusionSpeciesForm().baseStats;
|
||||
for (let s = 0; s < this.stats.length; s++) {
|
||||
baseStats[s] = Math.ceil((baseStats[s] + fusionBaseStats[s]) / 2);
|
||||
}
|
||||
} else if (this.scene.gameMode.isSplicedOnly) {
|
||||
for (let s = 0; s < this.stats.length; s++) {
|
||||
baseStats[s] = Math.ceil(baseStats[s] / 2);
|
||||
}
|
||||
}
|
||||
// Vitamins
|
||||
this.scene.applyModifiers(PokemonBaseStatModifier, this.isPlayer(), this, baseStats);
|
||||
return baseStats;
|
||||
}
|
||||
|
||||
getNature(): Nature {
|
||||
return this.natureOverride !== -1 ? this.natureOverride : this.nature;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
||||
import { PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||
|
||||
export default interface HeldModifierConfig {
|
||||
modifierType: PokemonHeldItemModifierType;
|
||||
modifier: PokemonHeldItemModifierType | PokemonHeldItemModifier;
|
||||
stackCount?: number;
|
||||
isTransferable?: boolean;
|
||||
}
|
||||
|
|
|
@ -132,9 +132,9 @@ class DefaultOverrides {
|
|||
// -------------------------
|
||||
|
||||
/** 1 to 256, set to null to ignore */
|
||||
readonly MYSTERY_ENCOUNTER_RATE_OVERRIDE: number | null = null;
|
||||
readonly MYSTERY_ENCOUNTER_RATE_OVERRIDE: number | null = 256;
|
||||
readonly MYSTERY_ENCOUNTER_TIER_OVERRIDE: MysteryEncounterTier | null = null;
|
||||
readonly MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType | null = null;
|
||||
readonly MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType | null = MysteryEncounterType.DARK_DEAL;
|
||||
|
||||
// -------------------------
|
||||
// MODIFIER / ITEM OVERRIDES
|
||||
|
|
|
@ -119,7 +119,7 @@ describe("Dancing Lessons - Mystery Encounter", () => {
|
|||
expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name);
|
||||
expect(enemyField.length).toBe(1);
|
||||
expect(enemyField[0].species.speciesId).toBe(Species.ORICORIO);
|
||||
expect(enemyField[0].summonData.battleStats).toEqual([1, 1, 1, 1, 1, 0, 0]);
|
||||
expect(enemyField[0].summonData.battleStats).toEqual([1, 1, 1, 1, 0, 0, 0]);
|
||||
const moveset = enemyField[0].moveset.map(m => m?.moveId);
|
||||
expect(moveset.some(m => m === Moves.REVELATION_DANCE)).toBeTruthy();
|
||||
|
||||
|
|
Loading…
Reference in New Issue