updating AI for Slumbering Snorlax ME, and small ME balance changes
This commit is contained in:
parent
6affced66a
commit
888f971c45
|
@ -1,16 +1,15 @@
|
|||
import { ChargeAnim, MoveChargeAnim, initMoveAnim, loadMoveAnimAssets } from "./battle-anims";
|
||||
import { EncoreTag, GulpMissileTag, HelpingHandTag, SemiInvulnerableTag, ShellTrapTag, StockpilingTag, TrappedTag, SubstituteTag, TypeBoostTag } from "./battler-tags";
|
||||
import { ChargeAnim, initMoveAnim, loadMoveAnimAssets, MoveChargeAnim } from "./battle-anims";
|
||||
import { EncoreTag, GulpMissileTag, HelpingHandTag, SemiInvulnerableTag, ShellTrapTag, StockpilingTag, SubstituteTag, TrappedTag, TypeBoostTag } from "./battler-tags";
|
||||
import { getPokemonNameWithAffix } from "../messages";
|
||||
import Pokemon, { AttackMoveResult, EnemyPokemon, HitResult, MoveResult, PlayerPokemon, PokemonMove, TurnMove } from "../field/pokemon";
|
||||
import { StatusEffect, getStatusEffectHealText, isNonVolatileStatusEffect, getNonVolatileStatusEffects } from "./status-effect";
|
||||
import { getNonVolatileStatusEffects, getStatusEffectHealText, isNonVolatileStatusEffect, StatusEffect } from "./status-effect";
|
||||
import { getTypeDamageMultiplier, Type } from "./type";
|
||||
import { Constructor } from "#app/utils";
|
||||
import { Constructor, NumberHolder } from "#app/utils";
|
||||
import * as Utils from "../utils";
|
||||
import { WeatherType } from "./weather";
|
||||
import { ArenaTagSide, ArenaTrapTag, WeakenMoveTypeTag } from "./arena-tag";
|
||||
import { UnswappableAbilityAbAttr, UncopiableAbilityAbAttr, UnsuppressableAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, MoveAbilityBypassAbAttr, ReverseDrainAbAttr, FieldPreventExplosiveMovesAbAttr, ForceSwitchOutImmunityAbAttr, BlockItemTheftAbAttr, applyPostAttackAbAttrs, ConfusionOnStatusEffectAbAttr, HealFromBerryUseAbAttr, IgnoreProtectOnContactAbAttr, IgnoreMoveEffectsAbAttr, applyPreDefendAbAttrs, MoveEffectChanceMultiplierAbAttr, WonderSkinAbAttr, applyPreAttackAbAttrs, MoveTypeChangeAbAttr, UserFieldMoveTypePowerBoostAbAttr, FieldMoveTypePowerBoostAbAttr, AllyMoveCategoryPowerBoostAbAttr, VariableMovePowerAbAttr } from "./ability";
|
||||
import { allAbilities } from "./ability";
|
||||
import { PokemonHeldItemModifier, BerryModifier, PreserveBerryModifier, PokemonMoveAccuracyBoosterModifier, AttackTypeBoosterModifier, PokemonMultiHitModifier } from "../modifier/modifier";
|
||||
import { allAbilities, AllyMoveCategoryPowerBoostAbAttr, applyAbAttrs, applyPostAttackAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, BlockItemTheftAbAttr, BlockNonDirectDamageAbAttr, BlockOneHitKOAbAttr, BlockRecoilDamageAttr, ConfusionOnStatusEffectAbAttr, FieldMoveTypePowerBoostAbAttr, FieldPreventExplosiveMovesAbAttr, ForceSwitchOutImmunityAbAttr, HealFromBerryUseAbAttr, IgnoreContactAbAttr, IgnoreMoveEffectsAbAttr, IgnoreProtectOnContactAbAttr, MaxMultiHitAbAttr, MoveAbilityBypassAbAttr, MoveEffectChanceMultiplierAbAttr, MoveTypeChangeAbAttr, ReverseDrainAbAttr, UncopiableAbilityAbAttr, UnsuppressableAbilityAbAttr, UnswappableAbilityAbAttr, UserFieldMoveTypePowerBoostAbAttr, VariableMovePowerAbAttr, WonderSkinAbAttr } from "./ability";
|
||||
import { AttackTypeBoosterModifier, BerryModifier, PokemonHeldItemModifier, PokemonMoveAccuracyBoosterModifier, PokemonMultiHitModifier, PreserveBerryModifier } from "../modifier/modifier";
|
||||
import { BattlerIndex, BattleType } from "../battle";
|
||||
import { TerrainType } from "./terrain";
|
||||
import { ModifierPoolType } from "#app/modifier/modifier-type";
|
||||
|
@ -25,7 +24,7 @@ import { Biome } from "#enums/biome";
|
|||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import { MoveUsedEvent } from "#app/events/battle-scene";
|
||||
import { Stat, type BattleStat, type EffectiveStat, BATTLE_STATS, EFFECTIVE_STATS, getStatKey } from "#app/enums/stat";
|
||||
import { BATTLE_STATS, type BattleStat, EFFECTIVE_STATS, type EffectiveStat, getStatKey, Stat } from "#app/enums/stat";
|
||||
import { PartyStatusCurePhase } from "#app/phases/party-status-cure-phase";
|
||||
import { BattleEndPhase } from "#app/phases/battle-end-phase";
|
||||
import { MoveEndPhase } from "#app/phases/move-end-phase";
|
||||
|
@ -36,7 +35,6 @@ import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
|||
import { SwitchPhase } from "#app/phases/switch-phase";
|
||||
import { SwitchSummonPhase } from "#app/phases/switch-summon-phase";
|
||||
import { SpeciesFormChangeRevertWeatherFormTrigger } from "./pokemon-forms";
|
||||
import { NumberHolder } from "#app/utils";
|
||||
import { GameMode } from "#app/game-mode";
|
||||
import { applyChallenges, ChallengeType } from "./challenge";
|
||||
|
||||
|
@ -2417,6 +2415,10 @@ export class BypassSleepAttr extends MoveAttr {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer {
|
||||
return user.status && user.status.effect === StatusEffect.SLEEP ? 100 : -10;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,8 +15,6 @@ 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";
|
||||
import { MessagePhase } from "#app/phases/message-phase";
|
||||
import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase";
|
||||
|
||||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:aTrainersTest";
|
||||
|
@ -153,19 +151,7 @@ export const ATrainersTestEncounter: MysteryEncounter =
|
|||
tier: EggTier.ULTRA
|
||||
};
|
||||
encounter.setDialogueToken("eggType", i18next.t(`${namespace}.eggTypes.epic`));
|
||||
if (scene.gameData.eggs.length >= 99) {
|
||||
// Eggs already full, give 2 10x Voucher instead
|
||||
encounter.dialogue.outro = [];
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SACRED_ASH], guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ULTRA], fillRemaining: true }, undefined, () => {
|
||||
scene.unshiftPhase(new MessagePhase(scene, i18next.t(`${namespace}.egg_list_full_dialogue`), undefined, true, undefined, i18next.t(`trainerNames:${encounter.misc.trainerNameKey}`)));
|
||||
scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.VOUCHER_PREMIUM));
|
||||
scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.VOUCHER_PREMIUM));
|
||||
});
|
||||
} else {
|
||||
encounter.dialogue.outro = [{ text: `${namespace}.outro` }];
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SACRED_ASH], guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ULTRA], fillRemaining: true }, [eggOptions]);
|
||||
}
|
||||
|
||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SACRED_ASH], guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ULTRA], fillRemaining: true }, [eggOptions]);
|
||||
return initBattleWithEnemyConfig(scene, config);
|
||||
}
|
||||
)
|
||||
|
@ -187,17 +173,13 @@ export const ATrainersTestEncounter: MysteryEncounter =
|
|||
tier: EggTier.GREAT
|
||||
};
|
||||
encounter.setDialogueToken("eggType", i18next.t(`${namespace}.eggTypes.rare`));
|
||||
if (scene.gameData.eggs.length >= 99) {
|
||||
// Eggs already full, give 2 10x Voucher instead
|
||||
encounter.dialogue.outro = [];
|
||||
scene.unshiftPhase(new MessagePhase(scene, i18next.t(`${namespace}.egg_list_full_dialogue`), undefined, true, undefined, i18next.t(`trainerNames:${encounter.misc.trainerNameKey}`)));
|
||||
scene.unshiftPhase(new ModifierRewardPhase(scene, modifierTypes.VOUCHER_PLUS));
|
||||
setEncounterRewards(scene, { fillRemaining: false, rerollMultiplier: -1 });
|
||||
} else {
|
||||
encounter.dialogue.outro = [{ text: `${namespace}.outro` }];
|
||||
setEncounterRewards(scene, { fillRemaining: false, rerollMultiplier: -1 }, [eggOptions]);
|
||||
}
|
||||
setEncounterRewards(scene, { fillRemaining: false, rerollMultiplier: -1 }, [eggOptions]);
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
}
|
||||
)
|
||||
.withOutroDialogue([
|
||||
{
|
||||
text: `${namespace}.outro`
|
||||
}
|
||||
])
|
||||
.build();
|
||||
|
|
|
@ -42,7 +42,7 @@ export const DelibirdyEncounter: MysteryEncounter =
|
|||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.DELIBIRDY)
|
||||
.withEncounterTier(MysteryEncounterTier.GREAT)
|
||||
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
||||
.withSceneRequirement(new MoneyRequirement(0, 2)) // Must have enough money for it to spawn at the very least
|
||||
.withSceneRequirement(new MoneyRequirement(0, 1.5)) // Must have enough money for it to spawn at the very least
|
||||
.withPrimaryPokemonRequirement(new CombinationPokemonRequirement( // Must also have either option 2 or 3 available to spawn
|
||||
new HeldItemRequirement(OPTION_2_ALLOWED_MODIFIERS),
|
||||
new HeldItemRequirement(OPTION_3_DISALLOWED_MODIFIERS, 1, true)
|
||||
|
@ -109,7 +109,7 @@ export const DelibirdyEncounter: MysteryEncounter =
|
|||
.withOption(
|
||||
MysteryEncounterOptionBuilder
|
||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withSceneMoneyRequirement(0, 2) // Must have money to spawn
|
||||
.withSceneMoneyRequirement(0, 1.5) // Must have money to spawn
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}.option.1.label`,
|
||||
buttonTooltip: `${namespace}.option.1.tooltip`,
|
||||
|
|
|
@ -25,7 +25,7 @@ const namespace = "mysteryEncounter:safariZone";
|
|||
|
||||
const TRAINER_THROW_ANIMATION_TIMES = [512, 184, 768];
|
||||
|
||||
const SAFARI_MONEY_MULTIPLIER = 2.75;
|
||||
const SAFARI_MONEY_MULTIPLIER = 2;
|
||||
|
||||
/**
|
||||
* Safari Zone encounter.
|
||||
|
|
|
@ -7,17 +7,18 @@ import { StatusEffect } from "#app/data/status-effect";
|
|||
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||
import { MoveRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
||||
import { EnemyPartyConfig, EnemyPokemonConfig, initBattleWithEnemyConfig, loadCustomMovesForEncounter, leaveEncounterWithoutBattle, setEncounterExp, setEncounterRewards, generateModifierType, } from "../utils/encounter-phase-utils";
|
||||
import { EnemyPartyConfig, EnemyPokemonConfig, generateModifierType, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, loadCustomMovesForEncounter, setEncounterExp, setEncounterRewards, } from "../utils/encounter-phase-utils";
|
||||
import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { BattlerIndex } from "#app/battle";
|
||||
import { PokemonMove } from "#app/field/pokemon";
|
||||
import { AiType, PokemonMove } from "#app/field/pokemon";
|
||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { PartyHealPhase } from "#app/phases/party-heal-phase";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
|
||||
import { BerryType } from "#enums/berry-type";
|
||||
import { MysteryEncounterPokemonData } from "#app/data/mystery-encounters/mystery-encounter-pokemon-data";
|
||||
|
||||
/** i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:slumberingSnorlax";
|
||||
|
@ -39,7 +40,7 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter =
|
|||
fileRoot: "pokemon",
|
||||
hasShadow: true,
|
||||
tint: 0.25,
|
||||
scale: 1.5,
|
||||
scale: 1.25,
|
||||
repeat: true,
|
||||
y: 5,
|
||||
},
|
||||
|
@ -70,6 +71,8 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter =
|
|||
stackCount: 2
|
||||
},
|
||||
],
|
||||
mysteryEncounterPokemonData: new MysteryEncounterPokemonData({ spriteScale: 1.25 }),
|
||||
aiType: AiType.SMART // Required to ensure Snorlax uses Sleep Talk while it is asleep
|
||||
};
|
||||
const config: EnemyPartyConfig = {
|
||||
levelAdditiveModifier: 0.5,
|
||||
|
|
|
@ -25,8 +25,8 @@ import { getEncounterPokemonLevelForWave } from "#app/data/mystery-encounters/ut
|
|||
/** the i18n namespace for this encounter */
|
||||
const namespace = "mysteryEncounter:teleportingHijinks";
|
||||
|
||||
const MONEY_COST_MULTIPLIER = 2.5;
|
||||
const BIOME_CANDIDATES = [Biome.SPACE, Biome.FAIRY_CAVE, Biome.LABORATORY, Biome.ISLAND];
|
||||
const MONEY_COST_MULTIPLIER = 1.75;
|
||||
const BIOME_CANDIDATES = [Biome.SPACE, Biome.FAIRY_CAVE, Biome.LABORATORY, Biome.ISLAND, Biome.WASTELAND, Biome.DOJO];
|
||||
const MACHINE_INTERFACING_TYPES = [Type.ELECTRIC, Type.STEEL];
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,7 +20,7 @@ import { Abilities } from "#enums/abilities";
|
|||
/** the i18n namespace for this encounter */
|
||||
const namespace = "mysteryEncounter:pokemonSalesman";
|
||||
|
||||
const MAX_POKEMON_PRICE_MULTIPLIER = 6;
|
||||
const MAX_POKEMON_PRICE_MULTIPLIER = 4;
|
||||
|
||||
/**
|
||||
* Pokemon Salesman encounter.
|
||||
|
|
|
@ -3,7 +3,7 @@ import { biomeLinks, BiomePoolTier } from "#app/data/biomes";
|
|||
import MysteryEncounterOption from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||
import { AVERAGE_ENCOUNTERS_PER_RUN_TARGET, WEIGHT_INCREMENT_ON_SPAWN_MISS } from "#app/data/mystery-encounters/mystery-encounters";
|
||||
import { showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||
import Pokemon, { FieldPosition, PlayerPokemon, PokemonMove, PokemonSummonData } from "#app/field/pokemon";
|
||||
import Pokemon, { AiType, FieldPosition, PlayerPokemon, PokemonMove, PokemonSummonData } from "#app/field/pokemon";
|
||||
import { CustomModifierSettings, ModifierPoolType, ModifierType, ModifierTypeGenerator, ModifierTypeOption, modifierTypes, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type";
|
||||
import { MysteryEncounterBattlePhase, MysteryEncounterBattleStartCleanupPhase, MysteryEncounterPhase, MysteryEncounterRewardsPhase } from "#app/phases/mystery-encounter-phases";
|
||||
import PokemonData from "#app/system/pokemon-data";
|
||||
|
@ -85,6 +85,7 @@ export interface EnemyPokemonConfig {
|
|||
modifierConfigs?: HeldModifierConfig[];
|
||||
tags?: BattlerTagType[];
|
||||
dataSource?: PokemonData;
|
||||
aiType?: AiType;
|
||||
}
|
||||
|
||||
export interface EnemyPartyConfig {
|
||||
|
@ -288,6 +289,11 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
|
|||
enemyPokemon.summonData.gender = config.gender!;
|
||||
}
|
||||
|
||||
// Set AI type
|
||||
if (!isNullOrUndefined(config.aiType)) {
|
||||
enemyPokemon.aiType = config.aiType;
|
||||
}
|
||||
|
||||
// Set moves
|
||||
if (config?.moveSet && config.moveSet.length > 0) {
|
||||
const moves = config.moveSet.map(m => new PokemonMove(m));
|
||||
|
|
|
@ -723,10 +723,10 @@ export function getGoldenBugNetSpecies(): PokemonSpecies {
|
|||
const roll = randSeedInt(totalWeight);
|
||||
|
||||
let w = 0;
|
||||
for (const species of GOLDEN_BUG_NET_SPECIES_POOL) {
|
||||
w += species[1];
|
||||
for (const speciesWeightPair of GOLDEN_BUG_NET_SPECIES_POOL) {
|
||||
w += speciesWeightPair[1];
|
||||
if (roll < w) {
|
||||
return getPokemonSpecies(species);
|
||||
return getPokemonSpecies(speciesWeightPair[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -152,5 +152,5 @@
|
|||
"mystery_encounter_fun_and_games": "PMD EoS Guildmaster Wigglytuff",
|
||||
"mystery_encounter_gen_5_gts": "BW GTS",
|
||||
"mystery_encounter_gen_6_gts": "XY GTS",
|
||||
"mystery_encounter_delibirdy": "Firel - Delibir-dy!"
|
||||
"mystery_encounter_delibirdy": "Firel - DeliDelivery!"
|
||||
}
|
||||
|
|
|
@ -43,6 +43,5 @@
|
|||
"epic": "an Epic Egg",
|
||||
"legendary": "a Legendary Egg"
|
||||
},
|
||||
"egg_list_full_dialogue": "Oh, it looks like you don't have room to carry another egg.$Here, take this instead!",
|
||||
"outro": "{{statTrainerName}} gave you {{eggType}}!"
|
||||
}
|
|
@ -21,6 +21,8 @@ const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA];
|
|||
const defaultBiome = Biome.CAVE;
|
||||
const defaultWave = 45;
|
||||
|
||||
const TRANSPORT_BIOMES = [Biome.SPACE, Biome.ISLAND, Biome.LABORATORY, Biome.FAIRY_CAVE, Biome.WASTELAND, Biome.DOJO];
|
||||
|
||||
describe("Teleporting Hijinks - Mystery Encounter", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
@ -183,7 +185,7 @@ describe("Teleporting Hijinks - Mystery Encounter", () => {
|
|||
await runMysteryEncounterToEnd(game, 1, undefined, true);
|
||||
|
||||
expect(previousBiome).not.toBe(scene.arena.biomeType);
|
||||
expect([Biome.SPACE, Biome.ISLAND, Biome.LABORATORY, Biome.FAIRY_CAVE]).toContain(scene.arena.biomeType);
|
||||
expect(TRANSPORT_BIOMES).toContain(scene.arena.biomeType);
|
||||
});
|
||||
|
||||
it("should start a battle against an enraged boss", { retry: 5 }, async () => {
|
||||
|
@ -246,7 +248,7 @@ describe("Teleporting Hijinks - Mystery Encounter", () => {
|
|||
await runMysteryEncounterToEnd(game, 2, undefined, true);
|
||||
|
||||
expect(previousBiome).not.toBe(scene.arena.biomeType);
|
||||
expect([Biome.SPACE, Biome.ISLAND, Biome.LABORATORY, Biome.FAIRY_CAVE]).toContain(scene.arena.biomeType);
|
||||
expect(TRANSPORT_BIOMES).toContain(scene.arena.biomeType);
|
||||
});
|
||||
|
||||
it("should start a battle against an enraged boss", async () => {
|
||||
|
|
Loading…
Reference in New Issue