diff --git a/public/images/mystery-encounters/berry_juice.json b/public/images/mystery-encounters/berry_juice.json index 88242213344..1a5331368ad 100644 --- a/public/images/mystery-encounters/berry_juice.json +++ b/public/images/mystery-encounters/berry_juice.json @@ -10,7 +10,7 @@ "scale": 1, "frames": [ { - "filename": "Bag_Berry_Juice_Sprite.png", + "filename": "0001.png", "rotated": false, "trimmed": true, "sourceSize": { diff --git a/src/data/mystery-encounters/encounters/mysterious-chest-encounter.ts b/src/data/mystery-encounters/encounters/mysterious-chest-encounter.ts index 9a0a42af2c8..63ceea1dac9 100644 --- a/src/data/mystery-encounters/encounters/mysterious-chest-encounter.ts +++ b/src/data/mystery-encounters/encounters/mysterious-chest-encounter.ts @@ -28,7 +28,7 @@ export const MysteriousChestEncounter: IMysteryEncounter = hasShadow: true, x: 4, y: 10, - yShadowOffset: 3, + yShadow: 3, disableAnimation: true, // Re-enabled after option select }, ]) diff --git a/src/data/mystery-encounters/encounters/safari-zone-encounter.ts b/src/data/mystery-encounters/encounters/safari-zone-encounter.ts index 2b7a013dd22..aa7fd19391f 100644 --- a/src/data/mystery-encounters/encounters/safari-zone-encounter.ts +++ b/src/data/mystery-encounters/encounters/safari-zone-encounter.ts @@ -31,7 +31,7 @@ export const SafariZoneEncounter: IMysteryEncounter = hasShadow: true, x: 4, y: 10, - yShadowOffset: 3 + yShadow: 3 }, ]) .withIntroDialogue([ diff --git a/src/data/mystery-encounters/encounters/shady-vitamin-dealer-encounter.ts b/src/data/mystery-encounters/encounters/shady-vitamin-dealer-encounter.ts index 7e32ca87c55..b1beee30247 100644 --- a/src/data/mystery-encounters/encounters/shady-vitamin-dealer-encounter.ts +++ b/src/data/mystery-encounters/encounters/shady-vitamin-dealer-encounter.ts @@ -31,7 +31,7 @@ export const ShadyVitaminDealerEncounter: IMysteryEncounter = repeat: true, x: 12, y: -5, - yShadowOffset: -5 + yShadow: -5 }, { spriteKey: "b2w2_veteran_m", @@ -39,7 +39,7 @@ export const ShadyVitaminDealerEncounter: IMysteryEncounter = hasShadow: true, x: -12, y: 3, - yShadowOffset: 3 + yShadow: 3 }, ]) .withIntroDialogue([ diff --git a/src/data/mystery-encounters/encounters/juiced_shuckle-juice-encounter.ts b/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts similarity index 50% rename from src/data/mystery-encounters/encounters/juiced_shuckle-juice-encounter.ts rename to src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts index e30e3612761..019eac98d7c 100644 --- a/src/data/mystery-encounters/encounters/juiced_shuckle-juice-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts @@ -1,4 +1,4 @@ -import { EnemyPartyConfig, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterRewards } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; +import { EnemyPartyConfig, hideMysteryEncounterIntroVisuals, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterRewards } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { modifierTypes, } from "#app/modifier/modifier-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import BattleScene from "../../../battle-scene"; @@ -6,35 +6,44 @@ import IMysteryEncounter, { MysteryEncounterBuilder, MysteryEncounterTier, } fro import { getPokemonSpecies } from "#app/data/pokemon-species"; import { Species } from "#enums/species"; import { Nature } from "#app/data/nature"; +import { PlayerPokemon } from "#app/field/pokemon"; +import { showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; /** the i18n namespace for the encounter */ -const namespace = "mysteryEncounter:oneForAll"; +const namespace = "mysteryEncounter:theStrongStuff"; -export const JuicedShuckleJuiceEncounter: IMysteryEncounter = +export const TheStrongStuffEncounter: IMysteryEncounter = MysteryEncounterBuilder.withEncounterType( - MysteryEncounterType.JUICED_SHUCKLE_JUICE + MysteryEncounterType.THE_STRONG_STUFF ) .withEncounterTier(MysteryEncounterTier.COMMON) .withSceneWaveRangeRequirement(10, 180) // waves 10 to 180 .withHideWildIntroMessage(true) + .withHideIntroVisuals(false) .withIntroSpriteConfigs([ + { + spriteKey: "berry_juice", + fileRoot: "mystery-encounters", + hasShadow: true, + scale: 1.5, + x: -15, + y: 3, + yShadow: 0 + }, { spriteKey: Species.SHUCKLE.toString(), fileRoot: "pokemon", hasShadow: true, repeat: true, - scale: 2 - }, - { - spriteKey: "berry_juice", - fileRoot: "mystery-encounters", - hasShadow: true, - scale: 2 + scale: 1.5, + x: 20, + y: 10, + yShadow: 7 }, ]) // Set in onInit() .withIntroDialogue([ { - text: `${namespace}_intro_message`, + text: `${namespace}:intro`, }, ]) .withOnInit((scene: BattleScene) => { @@ -58,35 +67,39 @@ export const JuicedShuckleJuiceEncounter: IMysteryEncounter = return true; }) - .withTitle(`${namespace}_title`) - .withDescription(`${namespace}_description`) - .withQuery(`${namespace}_query`) + .withTitle(`${namespace}:title`) + .withDescription(`${namespace}:description`) + .withQuery(`${namespace}:query`) .withSimpleOption( { - buttonLabel: `${namespace}_option_1_label`, - buttonTooltip: `${namespace}_option_1_tooltip`, + buttonLabel: `${namespace}:option:1:label`, + buttonTooltip: `${namespace}:option:1:tooltip`, selected: [ { - text: `${namespace}_option_1_selected`, - }, - ], + text: `${namespace}:option:1:selected` + } + ] }, async (scene: BattleScene) => { - // Leave encounter with no rewards or exp - // const encounter = scene.currentBattle.mysteryEncounter; + const encounter = scene.currentBattle.mysteryEncounter; + // Do blackout and hide intro visuals during blackout + scene.time.delayedCall(700, () => { + hideMysteryEncounterIntroVisuals(scene); + }); + // -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 = null; + let highestBst: PlayerPokemon = null; let statTotal = 0; for (const pokemon of party) { if (!highestBst) { highestBst = pokemon; - statTotal = pokemon.summonData.stats.reduce((i, n) => n + i); + statTotal = pokemon.getSpeciesForm().getBaseStatTotal(); continue; } - const total = pokemon.summonData.stats.reduce((i, n) => n + i); + const total = pokemon.getSpeciesForm().getBaseStatTotal(); if (total > statTotal) { highestBst = pokemon; statTotal = total; @@ -97,7 +110,25 @@ export const JuicedShuckleJuiceEncounter: IMysteryEncounter = highestBst = party[0]; } + console.log("BST pre change: " + highestBst.getSpeciesForm().baseStats); + highestBst.getSpeciesForm().baseStats = [...highestBst.getSpeciesForm().baseStats].map(v => v - 20); + console.log("Species BST: " + getPokemonSpecies(highestBst.getSpeciesForm().speciesId).baseStats); + console.log("Pokemon BST: " + highestBst.getSpeciesForm().baseStats); + highestBst.calculateStats(); + highestBst.updateInfo(); + for (const pokemon of party) { + if (highestBst.id === pokemon.id) { + continue; + } + pokemon.getSpeciesForm().baseStats = [...pokemon.getSpeciesForm().baseStats].map(v => v + 10); + // pokemon.summonData.getSpeciesForm()Form.baseStats = pokemon.getSpeciesForm().baseStats; + pokemon.calculateStats(); + pokemon.updateInfo(); + } + + encounter.setDialogueToken("highBstPokemon", highestBst.name); + await showEncounterText(scene, `${namespace}:option:1:selected_2`, null, true); leaveEncounterWithoutBattle(scene, true); return true; @@ -105,11 +136,11 @@ export const JuicedShuckleJuiceEncounter: IMysteryEncounter = ) .withSimpleOption( { - buttonLabel: `${namespace}_option_2_label`, - buttonTooltip: `${namespace}_option_2_tooltip`, + buttonLabel: `${namespace}:option:2:label`, + buttonTooltip: `${namespace}:option:2:tooltip`, selected: [ { - text: `${namespace}_option_2_selected_message`, + text: `${namespace}:option:2:selected`, }, ], }, diff --git a/src/data/mystery-encounters/encounters/training-session-encounter.ts b/src/data/mystery-encounters/encounters/training-session-encounter.ts index 1c0c3633883..fd4c7d0e7cc 100644 --- a/src/data/mystery-encounters/encounters/training-session-encounter.ts +++ b/src/data/mystery-encounters/encounters/training-session-encounter.ts @@ -35,7 +35,7 @@ export const TrainingSessionEncounter: IMysteryEncounter = hasShadow: true, y: 6, x: 5, - yShadowOffset: -2 + yShadow: -2 }, ]) .withIntroDialogue([ diff --git a/src/data/mystery-encounters/mystery-encounters.ts b/src/data/mystery-encounters/mystery-encounters.ts index e70c00d90c8..6d16be83d22 100644 --- a/src/data/mystery-encounters/mystery-encounters.ts +++ b/src/data/mystery-encounters/mystery-encounters.ts @@ -12,6 +12,7 @@ import { SleepingSnorlaxEncounter } from "./encounters/sleeping-snorlax-encounte import { TrainingSessionEncounter } from "./encounters/training-session-encounter"; import IMysteryEncounter from "./mystery-encounter"; import { SafariZoneEncounter } from "#app/data/mystery-encounters/encounters/safari-zone-encounter"; +import { TheStrongStuffEncounter } from "#app/data/mystery-encounters/encounters/the-strong-stuff-encounter"; // Spawn chance: (BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT + WIGHT_INCREMENT_ON_SPAWN_MISS * ) / 256 export const BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT = 1; @@ -220,6 +221,7 @@ export function initMysteryEncounters() { allMysteryEncounters[MysteryEncounterType.FIELD_TRIP] = FieldTripEncounter; allMysteryEncounters[MysteryEncounterType.SAFARI_ZONE] = SafariZoneEncounter; allMysteryEncounters[MysteryEncounterType.LOST_AT_SEA] = LostAtSeaEncounter; + allMysteryEncounters[MysteryEncounterType.THE_STRONG_STUFF] = TheStrongStuffEncounter; // Add extreme encounters to biome map extremeBiomeEncounters.forEach(encounter => { diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index 2b488f330c4..26af9155687 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -221,6 +221,14 @@ export abstract class PokemonSpeciesForm { return false; } + /** + * Gets the BST for the species + * @returns The species' BST. + */ + getBaseStatTotal(): integer { + return this.baseStats.reduce((i, n) => n + i); + } + /** * Gets the species' base stat amount for the given stat. * @param stat The desired stat. diff --git a/src/enums/mystery-encounter-type.ts b/src/enums/mystery-encounter-type.ts index 7a9938091c1..7f8ed906fa7 100644 --- a/src/enums/mystery-encounter-type.ts +++ b/src/enums/mystery-encounter-type.ts @@ -10,5 +10,5 @@ export enum MysteryEncounterType { FIELD_TRIP, SAFARI_ZONE, LOST_AT_SEA, //might be generalized later on - JUICED_SHUCKLE_JUICE + THE_STRONG_STUFF } diff --git a/src/field/mystery-encounter-intro.ts b/src/field/mystery-encounter-intro.ts index bacf107f482..4767e58d79f 100644 --- a/src/field/mystery-encounter-intro.ts +++ b/src/field/mystery-encounter-intro.ts @@ -39,7 +39,7 @@ export class MysteryEncounterSpriteConfig { /** Y offset */ y?: number; /** Y shadow offset */ - yShadowOffset?: number; + yShadow?: number; /** Sprite scale. `0` - `n` */ scale?: number; /** If you are using an item sprite, set to `true` */ @@ -70,10 +70,10 @@ export default class MysteryEncounterIntroVisuals extends Phaser.GameObjects.Con return; } - const getSprite = (spriteKey: string, hasShadow?: boolean, yShadowOffset?: number) => { + const getSprite = (spriteKey: string, hasShadow?: boolean, yShadow?: number) => { const ret = this.scene.addFieldSprite(0, 0, spriteKey); ret.setOrigin(0.5, 1); - ret.setPipeline(this.scene.spritePipeline, { tone: [0.0, 0.0, 0.0, 0.0], hasShadow: !!hasShadow, yShadowOffset: yShadowOffset ?? 0 }); + ret.setPipeline(this.scene.spritePipeline, { tone: [0.0, 0.0, 0.0, 0.0], hasShadow: !!hasShadow, yShadowOffset: yShadow ?? 0 }); return ret; }; @@ -92,13 +92,13 @@ export default class MysteryEncounterIntroVisuals extends Phaser.GameObjects.Con const spacingValue = Math.round((maxX - minX) / Math.max(this.spriteConfigs.filter(s => !s.x && !s.y).length, 1)); this.spriteConfigs?.forEach((config) => { - const { spriteKey, isItem, hasShadow, scale, x, y, yShadowOffset, alpha } = config; + const { spriteKey, isItem, hasShadow, scale, x, y, yShadow, alpha } = config; let sprite: GameObjects.Sprite; let tintSprite: GameObjects.Sprite; if (!isItem) { - sprite = getSprite(spriteKey, hasShadow, yShadowOffset); + sprite = getSprite(spriteKey, hasShadow, yShadow); tintSprite = getSprite(spriteKey); } else { sprite = getItemSprite(spriteKey); diff --git a/src/locales/en/mystery-encounter.ts b/src/locales/en/mystery-encounter.ts index 47c601cc9db..5effff0b02a 100644 --- a/src/locales/en/mystery-encounter.ts +++ b/src/locales/en/mystery-encounter.ts @@ -1,4 +1,5 @@ import { lostAtSea } from "./mystery-encounters/lost-at-sea"; +import { theStrongStuffDialogue } from "#app/locales/en/mystery-encounters/the-strong-stuff-dialogue"; /** * Patterns that can be used: @@ -241,4 +242,5 @@ export const mysteryEncounter = { "sleeping_snorlax_option_3_good_result": "Your {{option3PrimaryName}} uses {{option3PrimaryMove}}! @s{item_fanfare}It steals Leftovers off the sleeping Snorlax and you make out like bandits!", lostAtSea, + theStrongStuff: theStrongStuffDialogue, } as const; diff --git a/src/locales/en/mystery-encounters/the-strong-stuff-dialogue.ts b/src/locales/en/mystery-encounters/the-strong-stuff-dialogue.ts new file mode 100644 index 00000000000..a165c9718a8 --- /dev/null +++ b/src/locales/en/mystery-encounters/the-strong-stuff-dialogue.ts @@ -0,0 +1,25 @@ +export const theStrongStuffDialogue = { + intro: "It's a massive Shuckle and what appears\nto be an equally large stash of... juice?", + title: "The Strong Stuff", + description: "The Shuckle that blocks your path looks incredibly strong. Meanwhile, the juice next to it is emanating power of some kind.\n\nThe Shuckle extends its feelers in your direction. It seems like it wants to touch you, but is that really a good idea?", + query: "What will you do?", + option: { + 1: { + label: "Let it touch you", + tooltip: "(?) Something awful or amazing might happen", + selected: "You black out.", + selected_2: `@f{150}When you awaken, the Shuckle is gone\nand juice stash completely drained. + $Your {{highBstPokemon}} feels a\nterrible lethargy come over it! + $It's base stats were reduced by 20 in each stat! + $Your remaining Pokémon feel an incredible vigor, though! + $Their base stats are increased by 10 in each stat!` + }, + 2: { + label: "Battle the Shuckle", + tooltip: "(-) Hard Battle\n(+) Special Rewards", + selected: + "{{option2PrimaryName}} flies ahead of your boat, guiding you back on track.\n{{option2PrimaryName}} seems to also have gotten stronger in this time of need.", + }, + }, + outro: "You are back on track." +}; diff --git a/src/overrides.ts b/src/overrides.ts index 7272f68bcb4..d16895b27fa 100644 --- a/src/overrides.ts +++ b/src/overrides.ts @@ -119,7 +119,7 @@ export const EGG_GACHA_PULL_COUNT_OVERRIDE: number = 0; // 1 to 256, set to null to ignore export const MYSTERY_ENCOUNTER_RATE_OVERRIDE: number = 256; export const MYSTERY_ENCOUNTER_TIER_OVERRIDE: MysteryEncounterTier = null; -export const MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType = MysteryEncounterType.SLEEPING_SNORLAX; +export const MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType = MysteryEncounterType.THE_STRONG_STUFF; /** * MODIFIER / ITEM OVERRIDES diff --git a/src/ui/message-ui-handler.ts b/src/ui/message-ui-handler.ts index 05c91ca1643..cdd8b20b09d 100644 --- a/src/ui/message-ui-handler.ts +++ b/src/ui/message-ui-handler.ts @@ -32,7 +32,8 @@ export default abstract class MessageUiHandler extends AwaitableUiHandler { const charVarMap = new Map(); const delayMap = new Map(); const soundMap = new Map(); - const actionPattern = /@(c|d|s)\{(.*?)\}/; + const fadeMap = new Map(); + const actionPattern = /@(c|d|s|f)\{(.*?)\}/; let actionMatch: RegExpExecArray; while ((actionMatch = actionPattern.exec(text))) { switch (actionMatch[1]) { @@ -45,6 +46,9 @@ export default abstract class MessageUiHandler extends AwaitableUiHandler { case "s": soundMap.set(actionMatch.index, actionMatch[2]); break; + case "f": + fadeMap.set(actionMatch.index, parseInt(actionMatch[2])); + break; } text = text.slice(0, actionMatch.index) + text.slice(actionMatch.index + actionMatch[2].length + 4); } @@ -103,6 +107,7 @@ export default abstract class MessageUiHandler extends AwaitableUiHandler { const charVar = charVarMap.get(charIndex); const charSound = soundMap.get(charIndex); const charDelay = delayMap.get(charIndex); + const charFade = fadeMap.get(charIndex); this.message.setText(text.slice(0, charIndex)); const advance = () => { if (charVar) { @@ -134,6 +139,19 @@ export default abstract class MessageUiHandler extends AwaitableUiHandler { advance(); } }); + } else if (charFade) { + this.textTimer.paused = true; + this.scene.time.delayedCall(150, () => { + this.scene.ui.fadeOut(750).then(() => { + const delay = Utils.getFrameMs(charFade); + this.scene.time.delayedCall(delay, () => { + this.scene.ui.fadeIn(500).then(() => { + this.textTimer.paused = false; + advance(); + }); + }); + }); + }); } else { advance(); }