From 6accb0bae9b1627126dfba41875fd0a2381268be Mon Sep 17 00:00:00 2001 From: Opaque02 <66582645+Opaque02@users.noreply.github.com> Date: Sat, 13 Jul 2024 14:35:46 +1000 Subject: [PATCH 01/12] Adding start of Choice of Balance ME and aura system --- src/battle-scene.ts | 16 +- src/battle.ts | 9 +- .../dialogue/choice-of-balance-dialogue.ts | 34 +++ .../encounters/choice-of-balance.ts | 210 ++++++++++++++++++ .../encounters/fight-or-flight.ts | 2 + .../mystery-encounter-data.ts | 82 +++++++ .../mystery-encounter-dialogue.ts | 2 + .../mystery-encounters/mystery-encounters.ts | 2 + src/enums/mystery-encounter-type.ts | 3 +- src/locales/en/mystery-encounter.ts | 38 ++++ src/overrides.ts | 16 +- src/phases.ts | 9 +- src/system/game-data.ts | 12 +- 13 files changed, 415 insertions(+), 20 deletions(-) create mode 100644 src/data/mystery-encounters/dialogue/choice-of-balance-dialogue.ts create mode 100644 src/data/mystery-encounters/encounters/choice-of-balance.ts diff --git a/src/battle-scene.ts b/src/battle-scene.ts index f67adce1e022..e68daeb0bba0 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -69,7 +69,7 @@ import { TimedEventManager } from "#app/timed-event-manager.js"; import i18next from "i18next"; import MysteryEncounter, { MysteryEncounterTier, MysteryEncounterVariant } from "./data/mystery-encounters/mystery-encounter"; import { mysteryEncountersByBiome, allMysteryEncounters, BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT, AVERAGE_ENCOUNTERS_PER_RUN_TARGET, WIGHT_INCREMENT_ON_SPAWN_MISS } from "./data/mystery-encounters/mystery-encounters"; -import { MysteryEncounterData } from "#app/data/mystery-encounters/mystery-encounter-data"; +import { MysteryEncounterData, MysteryEncounterAuras, getAuraName, AuraType } from "#app/data/mystery-encounters/mystery-encounter-data"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1"; @@ -216,6 +216,7 @@ export default class BattleScene extends SceneBase { public pokemonInfoContainer: PokemonInfoContainer; private party: PlayerPokemon[]; public mysteryEncounterData: MysteryEncounterData = new MysteryEncounterData(null); + public mysteryEncounterAuras: MysteryEncounterAuras = new MysteryEncounterAuras(); public lastMysteryEncounter: MysteryEncounter; /** Combined Biome and Wave count text */ private biomeWaveText: Phaser.GameObjects.Text; @@ -2150,12 +2151,23 @@ export default class BattleScene extends SceneBase { } addMoney(amount: integer): void { - this.money = Math.min(this.money + amount, Number.MAX_SAFE_INTEGER); + const mysteryMoneyAura = this.mysteryEncounterAuras.FindAura(getAuraName(AuraType.MONEY)); + const mysteryMoneyMult = 1 + (mysteryMoneyAura.length > 0 ? mysteryMoneyAura[0].auraStrength : 0); + this.money = Math.min(this.money + Math.floor(amount * mysteryMoneyMult), Number.MAX_SAFE_INTEGER); this.updateMoneyText(); this.animateMoneyChanged(true); this.validateAchvs(MoneyAchv); } + getFormattedMoneyString(moneyAmount: number): string { + const userLocale = navigator.language || "en-US"; + const mysteryMoneyAura = this.mysteryEncounterAuras.FindAura(getAuraName(AuraType.MONEY)); + const mysteryMoneyMult = 1 + (mysteryMoneyAura.length > 0 ? mysteryMoneyAura[0].auraStrength : 0); + const formattedMoneyAmount = (moneyAmount.value * mysteryMoneyMult).toLocaleString(userLocale); + const message = i18next.t("battle:moneyWon", { moneyAmount: formattedMoneyAmount }); + return message; + } + getWaveMoneyAmount(moneyMultiplier: number): integer { const waveIndex = this.currentBattle.waveIndex; const waveSetIndex = Math.ceil(waveIndex / 10) - 1; diff --git a/src/battle.ts b/src/battle.ts index 30543933f490..ead5fc218f0c 100644 --- a/src/battle.ts +++ b/src/battle.ts @@ -13,7 +13,7 @@ import { Moves } from "#enums/moves"; import { PlayerGender } from "#enums/player-gender"; import { Species } from "#enums/species"; import { TrainerType } from "#enums/trainer-type"; -import i18next from "#app/plugins/i18n"; +//import i18next from "#app/plugins/i18n"; import MysteryEncounter, { MysteryEncounterVariant } from "./data/mystery-encounters/mystery-encounter"; export enum BattleType { @@ -177,9 +177,10 @@ export default class Battle { scene.addMoney(moneyAmount.value); - const userLocale = navigator.language || "en-US"; - const formattedMoneyAmount = moneyAmount.value.toLocaleString(userLocale); - const message = i18next.t("battle:moneyPickedUp", { moneyAmount: formattedMoneyAmount }); + //const userLocale = navigator.language || "en-US"; + //const formattedMoneyAmount = moneyAmount.value.toLocaleString(userLocale); + //const message = i18next.t("battle:moneyPickedUp", { moneyAmount: formattedMoneyAmount }); + const message = this.scene.getFormattedMoneyString(moneyAmount.value); scene.queueMessage(message, null, true); scene.currentBattle.moneyScattered = 0; diff --git a/src/data/mystery-encounters/dialogue/choice-of-balance-dialogue.ts b/src/data/mystery-encounters/dialogue/choice-of-balance-dialogue.ts new file mode 100644 index 000000000000..5f7d76cab87b --- /dev/null +++ b/src/data/mystery-encounters/dialogue/choice-of-balance-dialogue.ts @@ -0,0 +1,34 @@ +import MysteryEncounterDialogue from "#app/data/mystery-encounters/mystery-encounter-dialogue"; + +export const ChoiceOfBalanceDialogue: MysteryEncounterDialogue = { + intro: [ + { + text: "mysteryEncounter:choice_of_balance_intro_message" + } + ], + encounterOptionsDialogue: { + title: "mysteryEncounter:choice_of_balance_title", + description: "mysteryEncounter:choice_of_balance_description", + query: "mysteryEncounter:choice_of_balance_query", + options: [ + { + buttonLabel: "mysteryEncounter:choice_of_balance_option_1_label", + buttonTooltip: "mysteryEncounter:choice_of_balance_option_1_tooltip", + selected: [ + { + text: "mysteryEncounter:choice_of_balance_option_selected_message" + } + ] + }, + { + buttonLabel: "mysteryEncounter:choice_of_balance_option_2_label", + buttonTooltip: "mysteryEncounter:choice_of_balance_option_2_tooltip", + selected: [ + { + text: "mysteryEncounter:choice_of_balance_option_selected_message" + } + ] + } + ] + } +}; diff --git a/src/data/mystery-encounters/encounters/choice-of-balance.ts b/src/data/mystery-encounters/encounters/choice-of-balance.ts new file mode 100644 index 000000000000..aee340a72fea --- /dev/null +++ b/src/data/mystery-encounters/encounters/choice-of-balance.ts @@ -0,0 +1,210 @@ +import { + getHighestLevelPlayerPokemon, + koPlayerPokemon, + leaveEncounterWithoutBattle, + queueEncounterMessage, + setEncounterRewards, + showEncounterText +} from "#app/data/mystery-encounters/mystery-encounter-utils"; +import { ModifierTier } from "#app/modifier/modifier-tier"; +import { GameOverPhase } from "#app/phases"; +import { randSeedInt } from "#app/utils"; +import { MysteryEncounterType } from "#enums/mystery-encounter-type"; +import BattleScene from "../../../battle-scene"; +import MysteryEncounter, { MysteryEncounterBuilder, MysteryEncounterTier } from "../mystery-encounter"; +import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option"; +//import { AuraType, getAuraName } from "#app/data/mystery-encounters/mystery-encounter-data"; + +export const ChoiceOfBalanceEncounter: MysteryEncounter = MysteryEncounterBuilder + .withEncounterType(MysteryEncounterType.CHOICE_OF_BALANCE) + .withEncounterTier(MysteryEncounterTier.GREAT) + .withIntroSpriteConfigs([ + { + spriteKey: "686", + fileRoot: "pokemon", + hasShadow: true, + x: 4, + y: 8, + scale: 2.5, + disableAnimation: true // Re-enabled after option select + } + ]) + .withHideIntroVisuals(false) + .withSceneWaveRangeRequirement(10, 180) // waves 10 to 180 + .withOption(new MysteryEncounterOptionBuilder() + .withOptionPhase(async (scene: BattleScene) => { + // Open the chest + let roll = randSeedInt(100); + const negativeRewards = getNegativeRewards(2); + const positiveRewards = getPositiveRewards(2); + console.log(negativeRewards); + console.log(positiveRewards); + roll = 100; + if (roll > 60) { + // Choose between 2 COMMON / 2 GREAT tier items (40%) + setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.COMMON, ModifierTier.COMMON, ModifierTier.GREAT, ModifierTier.GREAT] }); + // Display result message then proceed to rewards + queueEncounterMessage(scene, "mysteryEncounter:mysterious_chest_option_1_normal_result"); + leaveEncounterWithoutBattle(scene); + } else if (roll > 40) { + // Choose between 3 ULTRA tier items (20%) + setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA] }); + // Display result message then proceed to rewards + queueEncounterMessage(scene, "mysteryEncounter:mysterious_chest_option_1_good_result"); + leaveEncounterWithoutBattle(scene); + } else if (roll > 36) { + // Choose between 2 ROGUE tier items (4%) + setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE] }); + // Display result message then proceed to rewards + queueEncounterMessage(scene, "mysteryEncounter:mysterious_chest_option_1_great_result"); + leaveEncounterWithoutBattle(scene); + } else if (roll > 35) { + // Choose 1 MASTER tier item (1%) + setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.MASTER] }); + // Display result message then proceed to rewards + queueEncounterMessage(scene, "mysteryEncounter:mysterious_chest_option_1_amazing_result"); + leaveEncounterWithoutBattle(scene); + } else { + // Your highest level unfainted Pok�mon gets OHKO. Progress with no rewards (35%) + const highestLevelPokemon = getHighestLevelPlayerPokemon(scene, true); + koPlayerPokemon(highestLevelPokemon); + + scene.currentBattle.mysteryEncounter.setDialogueToken("pokeName", highestLevelPokemon.name); + // Show which Pokemon was KOed, then leave encounter with no rewards + // Does this synchronously so that game over doesn't happen over result message + await showEncounterText(scene, "mysteryEncounter:mysterious_chest_option_1_bad_result") + .then(() => { + if (scene.getParty().filter(p => p.isAllowedInBattle()).length === 0) { + // All pokemon fainted, game over + scene.clearPhaseQueue(); + scene.unshiftPhase(new GameOverPhase(scene)); + } else { + leaveEncounterWithoutBattle(scene); + } + }); + } + }) + .build() + ) + .withOptionPhase(async (scene: BattleScene) => { + // Leave encounter with no rewards or exp + leaveEncounterWithoutBattle(scene, true); + return true; + }) + .build(); + +export enum NegativeRewards { + INCOME, + LUCK, + PLAYER_STATS, + ENEMY_STATS, + ADD_POKEMON, + DAMAGE_TO_PLAYER, + NO_REROLL +} + +export enum PositiveRewards { + INCOME = 1000, // starting at 1000 for positive so we can tell them apart between the negatives later + LUCK, + PLAYER_STATS, + ENEMY_STATS, + PP, + INSTANT_MONEY, + INSTANT_CANDY +} + +export function getNegativeRewards(totalOptions: number): number[] { + const negativeOptions = []; + const numNegatives = Object.keys(NegativeRewards).filter(nr => !isNaN(Number(nr))); + while (negativeOptions.length < totalOptions) { + const roll = randSeedInt(numNegatives.length); + if (!negativeOptions.includes(roll)) { + negativeOptions.push(NegativeRewards[roll]); + } + } + return negativeOptions; +} + +export function getPositiveRewards(totalOptions: number): number[] { + const positiveOptions = []; + const numPositives = Object.values(PositiveRewards).filter(pr => !isNaN(Number(pr))); + while (positiveOptions.length < totalOptions) { + const roll = randSeedInt(numPositives.length); + if (!positiveOptions.includes(roll)) { + positiveOptions.push(PositiveRewards[numPositives[roll]]); + } + } + return positiveOptions; +} + +export class RewardOption { + public negativeOption: number; + public positiveOption: number; + + constructor(negativeOption: number, positiveOption: number) { + this.negativeOption = negativeOption; + this.positiveOption = positiveOption; + } + + generateMessage(): string { + const negativeInfo = this.getRewardInfo(this.negativeOption); + //const positiveInfo = this.getRewardInfo(this.positiveOption); + let outputMessage = this.descriptorText(negativeInfo[1]); + console.log(this.formattedStrengths(NegativeRewards.ADD_POKEMON)); + outputMessage += this.descriptorText("for"); + outputMessage = negativeInfo[1]; + return outputMessage; + + } + + getRewardInfo(reward: number): [index: number, dialogueName: string, auraStrength: number, auraDuration: number] { + //if (Object.values(PositiveRewards).includes(reward) || Object.values(NegativeRewards).includes(reward)) { + return statMessageIndex.find(r => r[0] === reward); + //return statMessageIndex.filter(r => r[0] === reward)[1]; + //} + } + + private formattedStrengths(strength: number): string { + let newStrength: string; + switch (strength) { + case NegativeRewards.INCOME: + case NegativeRewards.DAMAGE_TO_PLAYER: + case PositiveRewards.INCOME: + case PositiveRewards.PP: + newStrength = String(Math.abs(strength * 100)); + case NegativeRewards.LUCK: + case NegativeRewards.PLAYER_STATS: + case NegativeRewards.ENEMY_STATS: + case PositiveRewards.LUCK: + case PositiveRewards.PLAYER_STATS: + case PositiveRewards.ENEMY_STATS: + case NegativeRewards.PLAYER_STATS: + newStrength = String(Math.abs(strength)); + case NegativeRewards.ADD_POKEMON: + case NegativeRewards.NO_REROLL: + newStrength = ""; + } + return newStrength; + } + + private descriptorText(text: string) { + return "mysteryEncounter:choice_of_balance_" + text; + } +} + +const statMessageIndex: [index: number, dialogueName: string, auraStrength: number, auraDuration: number][] = [ + [NegativeRewards.INCOME, "choice_of_balance_negative_income", -0.4, 5], + [NegativeRewards.LUCK, "choice_of_balance_negative_luck", 0, 15], + [NegativeRewards.PLAYER_STATS, "choice_of_balance_negative_player_stats", -1, 10], + [NegativeRewards.ENEMY_STATS, "choice_of_balance_negative_enemy_stats", 1, 8], + [NegativeRewards.ADD_POKEMON, "choice_of_balance_negative_add_pokemon", 0, 15], + [NegativeRewards.DAMAGE_TO_PLAYER, "choice_of_balance_negative_damage_to_player", 0.1, 5], + [NegativeRewards.NO_REROLL, "choice_of_balance_negative_no_reroll", 0, 7], + [PositiveRewards.INCOME, "choice_of_balance_positive_income", 0.7, -1], + [PositiveRewards.LUCK, "choice_of_balance_positive_luck", 5, -1], + [PositiveRewards.PLAYER_STATS, "choice_of_balance_positive_player_stats", 1, 13], + [PositiveRewards.ENEMY_STATS, "choice_of_balance_positive_enemy_stats", -1, 12], + [PositiveRewards.PP, "choice_of_balance_positive_pp_chance", 0.2, 40], + [PositiveRewards.INSTANT_MONEY, "choice_of_balance_positive_instant_money", 5000, 0], + [PositiveRewards.INSTANT_CANDY, "choice_of_balance_positive_instant_candy", 0, 0] +]; diff --git a/src/data/mystery-encounters/encounters/fight-or-flight.ts b/src/data/mystery-encounters/encounters/fight-or-flight.ts index 506b450aa989..b368bad4c6bb 100644 --- a/src/data/mystery-encounters/encounters/fight-or-flight.ts +++ b/src/data/mystery-encounters/encounters/fight-or-flight.ts @@ -24,6 +24,7 @@ import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import BattleScene from "../../../battle-scene"; import MysteryEncounter, { MysteryEncounterBuilder, MysteryEncounterTier } from "../mystery-encounter"; import { MoveRequirement } from "../mystery-encounter-requirements"; +import { AuraType, getAuraName } from "#app/data/mystery-encounters/mystery-encounter-data"; const validMovesForSteal = [ Moves.PLUCK, @@ -102,6 +103,7 @@ export const FightOrFlightEncounter: MysteryEncounter = MysteryEncounterBuilder // Pick battle const item = scene.currentBattle.mysteryEncounter.misc as ModifierTypeOption; setEncounterRewards(scene, { guaranteedModifierTypeOptions: [item], fillRemaining: false }); + scene.mysteryEncounterAuras.AddAura([-1], 0.7, 5, getAuraName(AuraType.MONEY), 0); await initBattleWithEnemyConfig(scene, scene.currentBattle.mysteryEncounter.enemyPartyConfigs[0]); }) .withOptionPhase(async (scene: BattleScene) => { diff --git a/src/data/mystery-encounters/mystery-encounter-data.ts b/src/data/mystery-encounters/mystery-encounter-data.ts index 7162450bfc59..e233ad1183fd 100644 --- a/src/data/mystery-encounters/mystery-encounter-data.ts +++ b/src/data/mystery-encounters/mystery-encounter-data.ts @@ -14,3 +14,85 @@ export class MysteryEncounterData { } } } + +export class MysteryEncounterAuras { + public playerAura: Aura[]; + + constructor() { + this.playerAura = []; + } + + AddAura(target: number[], auraStrength: number, duration: number, auraType: string, team: number) { + this.playerAura.push(new Aura(target, auraStrength, duration, auraType, team)); + } + + UpdateAurasDurations() { + for (let i = 0; i < this.playerAura.length; i++) { + this.playerAura[i].duration -= 1; + } + this.playerAura = this.playerAura.filter(aura => aura.duration !== 0); + } + + FindAura(auraType: string) { + return this.playerAura.filter(auras => auras.auraType === auraType); + } +} + +class Aura { + public target: number[]; // this can be used to target specific pokemon (using an array of pokemon ID) or all pokemon (using [-1]) + public auraStrength: number; // this is the amount boosted/reduced - can be positive or negative + public duration: number; // this is how many waves the aura lasts for; use a number > 0 for timed auras, or -1 for auras for the rest of the game + public auraType: string; // this is the aura type - for now, for example, what stat will be changed + public team: number; // this is the team. I think this will eventually be an enum - something like Team.PLAYER, Team.ENEMY, Team.ALL to target the player, enemy or everyone respectively. + + constructor(target: number[], auraStrength: number, duration: number, auraType: string, team: number) { + this.target = target; + this.auraStrength = auraStrength; + this.duration = duration; + this.auraType = auraType; + this.team = team; + } +} + +export enum TeamTarget { + ALL, + PLAYER, + ENEMY +} + +export enum AuraType { + MONEY, + ATK, + SPATK, + DEF, + SPDEF, + SPD, + EVA, + ACC, + XP +} + +export function getAuraName(aura: AuraType) { + switch (aura) { + case AuraType.MONEY: + return "MONEY"; + case AuraType.ATK: + return "ATK"; + case AuraType.SPATK: + return "SP. ATK"; + case AuraType.DEF: + return "DEF"; + case AuraType.SPDEF: + return "SP. DEF"; + case AuraType.SPD: + return "SPEED"; + case AuraType.ACC: + return "ACC"; + case AuraType.EVA: + return "EVA"; + case AuraType.XP: + return "XP"; + default: + return "???"; + } +} diff --git a/src/data/mystery-encounters/mystery-encounter-dialogue.ts b/src/data/mystery-encounters/mystery-encounter-dialogue.ts index 1e2dfe850451..cc4373213995 100644 --- a/src/data/mystery-encounters/mystery-encounter-dialogue.ts +++ b/src/data/mystery-encounters/mystery-encounter-dialogue.ts @@ -7,6 +7,7 @@ import { TrainingSessionDialogue } from "#app/data/mystery-encounters/dialogue/t import { SleepingSnorlaxDialogue } from "./dialogue/sleeping-snorlax-dialogue"; import { DepartmentStoreSaleDialogue } from "#app/data/mystery-encounters/dialogue/department-store-sale-dialogue"; import { ShadyVitaminDealerDialogue } from "#app/data/mystery-encounters/dialogue/shady-vitamin-dealer"; +import { ChoiceOfBalanceDialogue } from "#app/data/mystery-encounters/dialogue/choice-of-balance-dialogue"; import { TextStyle } from "#app/ui/text"; export class TextDisplay { @@ -92,4 +93,5 @@ export function initMysteryEncounterDialogue() { allMysteryEncounterDialogue[MysteryEncounterType.SLEEPING_SNORLAX] = SleepingSnorlaxDialogue; allMysteryEncounterDialogue[MysteryEncounterType.DEPARTMENT_STORE_SALE] = DepartmentStoreSaleDialogue; allMysteryEncounterDialogue[MysteryEncounterType.SHADY_VITAMIN_DEALER] = ShadyVitaminDealerDialogue; + allMysteryEncounterDialogue[MysteryEncounterType.CHOICE_OF_BALANCE] = ChoiceOfBalanceDialogue; } diff --git a/src/data/mystery-encounters/mystery-encounters.ts b/src/data/mystery-encounters/mystery-encounters.ts index e4a748d3a233..6dc8d45fe78d 100644 --- a/src/data/mystery-encounters/mystery-encounters.ts +++ b/src/data/mystery-encounters/mystery-encounters.ts @@ -4,6 +4,7 @@ import { MysteriousChallengersEncounter } from "./encounters/mysterious-challeng import { MysteriousChestEncounter } from "./encounters/mysterious-chest"; import { FightOrFlightEncounter } from "#app/data/mystery-encounters/encounters/fight-or-flight"; import { TrainingSessionEncounter } from "#app/data/mystery-encounters/encounters/training-session"; +import { ChoiceOfBalanceEncounter } from "#app/data/mystery-encounters/encounters/choice-of-balance"; import { Biome } from "#enums/biome"; import { SleepingSnorlaxEncounter } from "./encounters/sleeping-snorlax"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; @@ -95,6 +96,7 @@ export function initMysteryEncounters() { allMysteryEncounters[MysteryEncounterType.SLEEPING_SNORLAX] = SleepingSnorlaxEncounter; allMysteryEncounters[MysteryEncounterType.DEPARTMENT_STORE_SALE] = DepartmentStoreSaleEncounter; allMysteryEncounters[MysteryEncounterType.SHADY_VITAMIN_DEALER] = ShadyVitaminDealerEncounter; + allMysteryEncounters[MysteryEncounterType.CHOICE_OF_BALANCE] = ChoiceOfBalanceEncounter; // Append encounters that can occur in any biome to biome map const anyBiomeEncounters: MysteryEncounterType[] = Object.keys(MysteryEncounterType).filter(e => !isNaN(Number(e))).map(k => Number(k) as MysteryEncounterType); diff --git a/src/enums/mystery-encounter-type.ts b/src/enums/mystery-encounter-type.ts index 6e2815babcaa..948479f4e318 100644 --- a/src/enums/mystery-encounter-type.ts +++ b/src/enums/mystery-encounter-type.ts @@ -6,5 +6,6 @@ export enum MysteryEncounterType { SLEEPING_SNORLAX, TRAINING_SESSION, DEPARTMENT_STORE_SALE, - SHADY_VITAMIN_DEALER + SHADY_VITAMIN_DEALER, + CHOICE_OF_BALANCE } diff --git a/src/locales/en/mystery-encounter.ts b/src/locales/en/mystery-encounter.ts index ac04eed2688b..36a580f52a43 100644 --- a/src/locales/en/mystery-encounter.ts +++ b/src/locales/en/mystery-encounter.ts @@ -34,6 +34,44 @@ export const mysteryEncounter: SimpleTranslationEntries = { "mysterious_chest_option_1_bad_result": `Oh no!@d{32}\nThe chest was trapped! $Your @ec{pokeName} jumps in front of you\nbut is KOed in the process.`, + "choice_of_balance_intro_message": `You feel a strange pull in a certain direction. + $Heading towards it, you see a weird glow in the distance. + $It's an...@d{64} Inkay?! You accidentally make\nsome noise and scare it off... + $...but not before it inks you with a psychic shot!`, + "choice_of_balance_title": "The Choice of Balance", + "choice_of_balance_description": "You've been inked by inkay and feel a little woozy. You can't really tell what's good and what's not?", + "choice_of_balance_query": "What will you choose?", + "choice_of_balance_option_1_label": "Option A", + "choice_of_balance_option_1_tooltip": "@[SUMMARY_BLUE]{(35%) Something terrible}\n@[SUMMARY_GREEN]{(40%) Okay Rewards}\n@[SUMMARY_GREEN]{(20%) Good Rewards}\n@[SUMMARY_GREEN]{(4%) Great Rewards}\n@[SUMMARY_GREEN]{(1%) Amazing Rewards}", + "choice_of_balance_option_2_label": "Option B", + "choice_of_balance_option_2_tooltip": "(-) No Rewards", + "choice_of_balance_option_selected_message": "You hope you've made the right decision...", + "choice_of_balance_negative_income": "Reduce income by", + "choice_of_balance_negative_luck": "Set luck to", + "choice_of_balance_negative_player_stats": "Reduce STAT by", + "choice_of_balance_negative_enemy_stats": "Increase enemy STAT by", + "choice_of_balance_negative_add_pokemon": "Unable to add pokemon", + "choice_of_balance_negative_damage_to_player": "Increase DMG taken by", + "choice_of_balance_negative_no_reroll": "No shop rerolls", + "choice_of_balance_positive_income": "Increase income by", + "choice_of_balance_positive_luck": "Increase luck by", + "choice_of_balance_positive_player_stats": "Increase STAT by", + "choice_of_balance_positive_enemy_stats": "Reduce enemy STAT by", + "choice_of_balance_positive_pp_chance": "Reduce PP usage chance", + "choice_of_balance_positive_instant_money": "Gain money", + "choice_of_balance_positive_instant_candy": "Gain candy", + "choice_of_balance_then": "THEN:", + "choice_of_balance_for": "for", + "choice_of_balance_waves": "waves", + "choice_of_balance_rest_of_run": "for the rest of this run", + //"choice_of_balance_option_2_selected_message": "You hurry along your way,\nwith a slight feeling of regret.", + //"choice_of_balance_option_1_normal_result": "Just some normal tools and items.", + //"choice_of_balance_option_1_good_result": "Some pretty nice tools and items.", + //"choice_of_balance_option_1_great_result": "A couple great tools and items!", + //"choice_of_balance_option_1_amazing_result": "Whoa! An amazing item!", + //"choice_of_balance_option_1_bad_result": `Oh no!@d{32}\nThe chest was trapped! + //$Your @ec{pokeName} jumps in front of you\nbut is KOed in the process.`, + "fight_or_flight_intro_message": "Something shiny is sparkling\non the ground near that Pokémon!", "fight_or_flight_title": "Fight or Flight", "fight_or_flight_description": "It looks like there's a strong Pokémon guarding an item. Battling is the straightforward approach, but this Pokémon looks strong. You could also try to sneak around, though the Pokémon might catch you.", diff --git a/src/overrides.ts b/src/overrides.ts index ce7061736916..e205fee8e568 100644 --- a/src/overrides.ts +++ b/src/overrides.ts @@ -35,22 +35,22 @@ export const SEED_OVERRIDE: string = ""; export const WEATHER_OVERRIDE: WeatherType = WeatherType.NONE; export const DOUBLE_BATTLE_OVERRIDE: boolean = false; export const SINGLE_BATTLE_OVERRIDE: boolean = false; -export const STARTING_WAVE_OVERRIDE: integer = 0; +export const STARTING_WAVE_OVERRIDE: integer = 11; export const STARTING_BIOME_OVERRIDE: Biome = Biome.TOWN; export const ARENA_TINT_OVERRIDE: TimeOfDay = null; // Multiplies XP gained by this value including 0. Set to null to ignore the override -export const XP_MULTIPLIER_OVERRIDE: number = null; +export const XP_MULTIPLIER_OVERRIDE: number = 10; // default 1000 export const STARTING_MONEY_OVERRIDE: integer = 0; export const FREE_CANDY_UPGRADE_OVERRIDE: boolean = false; export const POKEBALL_OVERRIDE: { active: boolean, pokeballs: PokeballCounts } = { - active: false, + active: true, pokeballs: { [PokeballType.POKEBALL]: 5, [PokeballType.GREAT_BALL]: 0, [PokeballType.ULTRA_BALL]: 0, [PokeballType.ROGUE_BALL]: 0, - [PokeballType.MASTER_BALL]: 0, + [PokeballType.MASTER_BALL]: 99, } }; @@ -71,7 +71,7 @@ export const POKEBALL_OVERRIDE: { active: boolean, pokeballs: PokeballCounts } = export const STARTER_FORM_OVERRIDES: Partial> = {}; // default 5 or 20 for Daily -export const STARTING_LEVEL_OVERRIDE: integer = 0; +export const STARTING_LEVEL_OVERRIDE: integer = 100; /** * SPECIES OVERRIDE * will only apply to the first starter in your party or each enemy pokemon @@ -118,9 +118,9 @@ export const EGG_GACHA_PULL_COUNT_OVERRIDE: number = 0; */ // 1 to 256, set to null to ignore -export const MYSTERY_ENCOUNTER_RATE_OVERRIDE: number = null; +export const MYSTERY_ENCOUNTER_RATE_OVERRIDE: number = 256; export const MYSTERY_ENCOUNTER_TIER_OVERRIDE: MysteryEncounterTier = null; -export const MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType = null; +export const MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType = MysteryEncounterType.CHOICE_OF_BALANCE; /** * MODIFIER / ITEM OVERRIDES @@ -143,7 +143,7 @@ interface ModifierOverride { count?: integer type?: TempBattleStat|Stat|Nature|Type|BerryType|SpeciesStatBoosterItem } -export const STARTING_MODIFIER_OVERRIDE: Array = []; +export const STARTING_MODIFIER_OVERRIDE: Array = [{name: "EXP_SHARE", count: 5}]; export const OPP_MODIFIER_OVERRIDE: Array = []; export const STARTING_HELD_ITEMS_OVERRIDE: Array = []; diff --git a/src/phases.ts b/src/phases.ts index 091629b31d5a..ac174b9e7e4c 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2676,6 +2676,8 @@ export class BattleEndPhase extends BattlePhase { } } + this.scene.mysteryEncounterAuras.UpdateAurasDurations(); + this.scene.updateModifiers().then(() => this.end()); } } @@ -4234,9 +4236,10 @@ export class MoneyRewardPhase extends BattlePhase { this.scene.addMoney(moneyAmount.value); - const userLocale = navigator.language || "en-US"; - const formattedMoneyAmount = moneyAmount.value.toLocaleString(userLocale); - const message = i18next.t("battle:moneyWon", { moneyAmount: formattedMoneyAmount }); + //const userLocale = navigator.language || "en-US"; + //const formattedMoneyAmount = moneyAmount.value.toLocaleString(userLocale); + //const message = i18next.t("battle:moneyWon", { moneyAmount: formattedMoneyAmount }); + const message = this.scene.getFormattedMoneyString(moneyAmount.value); this.scene.ui.showText(message, null, () => this.end(), null, true); } diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 871e2458bbda..3920d70ded56 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -40,7 +40,7 @@ import { GameDataType } from "#enums/game-data-type"; import { Moves } from "#enums/moves"; import { PlayerGender } from "#enums/player-gender"; import { Species } from "#enums/species"; -import { MysteryEncounterData } from "../data/mystery-encounters/mystery-encounter-data"; +import { MysteryEncounterData, MysteryEncounterAuras /*, AuraType, getAuraName*/ } from "../data/mystery-encounters/mystery-encounter-data"; import MysteryEncounter from "../data/mystery-encounters/mystery-encounter"; export const defaultStarterSpecies: Species[] = [ @@ -126,6 +126,7 @@ export interface SessionSaveData { challenges: ChallengeData[]; mysteryEncounter: MysteryEncounter; mysteryEncounterData: MysteryEncounterData; + mysteryEncounterAuras: MysteryEncounterAuras } interface Unlocks { @@ -842,7 +843,8 @@ export class GameData { timestamp: new Date().getTime(), challenges: scene.gameMode.challenges.map(c => new ChallengeData(c)), mysteryEncounter: scene.currentBattle.mysteryEncounter, - mysteryEncounterData: scene.mysteryEncounterData + mysteryEncounterData: scene.mysteryEncounterData, + mysteryEncounterAuras: scene.mysteryEncounterAuras } as SessionSaveData; } @@ -935,6 +937,8 @@ export class GameData { scene.mysteryEncounterData = sessionData?.mysteryEncounterData ? sessionData?.mysteryEncounterData : new MysteryEncounterData(null); + scene.mysteryEncounterAuras = sessionData?.mysteryEncounterAuras ? sessionData?.mysteryEncounterAuras : new MysteryEncounterAuras(); + scene.newArena(sessionData.arena.biome); const battleType = sessionData.battleType || 0; @@ -1162,6 +1166,10 @@ export class GameData { return new MysteryEncounterData(v); } + if (k === "mysteryEncounterAuras") { + return new MysteryEncounterAuras(); + } + return v; }) as SessionSaveData; } From 13b4f1d6bb841506013f5b42c84002610b47080d Mon Sep 17 00:00:00 2001 From: Opaque02 <66582645+Opaque02@users.noreply.github.com> Date: Sat, 13 Jul 2024 15:27:47 +1000 Subject: [PATCH 02/12] Removed unused dialogue file --- .../dialogue/choice-of-balance-dialogue.ts | 34 ------------------- 1 file changed, 34 deletions(-) delete mode 100644 src/data/mystery-encounters/dialogue/choice-of-balance-dialogue.ts diff --git a/src/data/mystery-encounters/dialogue/choice-of-balance-dialogue.ts b/src/data/mystery-encounters/dialogue/choice-of-balance-dialogue.ts deleted file mode 100644 index 5f7d76cab87b..000000000000 --- a/src/data/mystery-encounters/dialogue/choice-of-balance-dialogue.ts +++ /dev/null @@ -1,34 +0,0 @@ -import MysteryEncounterDialogue from "#app/data/mystery-encounters/mystery-encounter-dialogue"; - -export const ChoiceOfBalanceDialogue: MysteryEncounterDialogue = { - intro: [ - { - text: "mysteryEncounter:choice_of_balance_intro_message" - } - ], - encounterOptionsDialogue: { - title: "mysteryEncounter:choice_of_balance_title", - description: "mysteryEncounter:choice_of_balance_description", - query: "mysteryEncounter:choice_of_balance_query", - options: [ - { - buttonLabel: "mysteryEncounter:choice_of_balance_option_1_label", - buttonTooltip: "mysteryEncounter:choice_of_balance_option_1_tooltip", - selected: [ - { - text: "mysteryEncounter:choice_of_balance_option_selected_message" - } - ] - }, - { - buttonLabel: "mysteryEncounter:choice_of_balance_option_2_label", - buttonTooltip: "mysteryEncounter:choice_of_balance_option_2_tooltip", - selected: [ - { - text: "mysteryEncounter:choice_of_balance_option_selected_message" - } - ] - } - ] - } -}; From 0479f44ccbfd11438fe9bc430f8eaf2a1ee66d15 Mon Sep 17 00:00:00 2001 From: Opaque02 <66582645+Opaque02@users.noreply.github.com> Date: Sun, 14 Jul 2024 01:40:45 +1000 Subject: [PATCH 03/12] Extra code changes --- .../encounters/choice-of-balance-encounter.ts | 163 ++++++++++++++---- .../mystery-encounters/mystery-encounter.ts | 13 +- src/locales/en/mystery-encounter.ts | 5 +- 3 files changed, 142 insertions(+), 39 deletions(-) diff --git a/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts b/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts index f9760fa6738e..cb2ba84907c8 100644 --- a/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts +++ b/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts @@ -6,10 +6,12 @@ import { setEncounterRewards, showEncounterText, } from "#app/data/mystery-encounters/mystery-encounter-utils"; +import { mysteryEncounter } from "#app/locales/en/mystery-encounter"; import { ModifierTier } from "#app/modifier/modifier-tier"; import { GameOverPhase } from "#app/phases"; import { randSeedInt } from "#app/utils"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; +import i18next from "i18next"; import BattleScene from "../../../battle-scene"; import IMysteryEncounter, { MysteryEncounterBuilder, @@ -19,6 +21,23 @@ import { EncounterOptionMode, MysteryEncounterOptionBuilder } from "../mystery-e //import { AuraType, getAuraName } from "#app/data/mystery-encounters/mystery-encounter-data"; const namespace = "mysteryEncounter:choice_of_balance"; +const options = 2 + randSeedInt(1); + +function generateRewards(numOptions: number): number[] { + const negativeRewards = getNegativeRewards(numOptions); + const positiveRewards = getPositiveRewards(numOptions); + const rewardArray = []; + for (let i = 0; i < negativeRewards.length; i++) { + rewardArray.push(new RewardOption(negativeRewards[i], positiveRewards[i])); + } + mysteryEncounter["choice_of_balance_option_1_tooltip"] = rewardArray[0].generateMessage(); // this will need changing eventually; this is NOT a good way to do it + mysteryEncounter["choice_of_balance_option_2_tooltip"] = rewardArray[1].generateMessage(); // this will need changing eventually; this is NOT a good way to do it + //const test = rewardArray[0]; + //console.log(test.generateMessage()); + //console.log(negativeRewards); + //console.log(positiveRewards); + return rewardArray; +} export const ChoiceOfBalanceEncounter: IMysteryEncounter = MysteryEncounterBuilder .withEncounterType(MysteryEncounterType.CHOICE_OF_BALANCE) @@ -41,9 +60,21 @@ export const ChoiceOfBalanceEncounter: IMysteryEncounter = MysteryEncounterBuild text: `${namespace}_intro_message`, } ]) + .withOnInit((scene: BattleScene) => { + const encounter = scene.currentBattle.mysteryEncounter; + encounter.misc = []; + console.log(encounter); + + console.log("Number of options generated", options); + + const rewardsArray = generateRewards(options); + encounter.misc.push(rewardsArray); + return true; + }) .withTitle(`${namespace}_title`) .withDescription(`${ namespace }_description`) .withQuery(`${namespace}_query`) + .withExtraInfo(options === 3) .withOption( new MysteryEncounterOptionBuilder() .withOptionMode(EncounterOptionMode.DEFAULT) @@ -59,10 +90,16 @@ export const ChoiceOfBalanceEncounter: IMysteryEncounter = MysteryEncounterBuild .withOptionPhase(async (scene: BattleScene) => { // Open the chest let roll = randSeedInt(100); - const negativeRewards = getNegativeRewards(2); - const positiveRewards = getPositiveRewards(2); - console.log(negativeRewards); - console.log(positiveRewards); + //const negativeRewards = getNegativeRewards(numOptions); + //const positiveRewards = getPositiveRewards(numOptions); + //let rewardArray = []; + //for (var i = 0; i < negativeRewards.length; i++) { + // rewardArray.push(new RewardOption(negativeRewards[i], positiveRewards[i])); + //} + //const test = rewardArray[0]; + //console.log(test.generateMessage()); + //console.log(negativeRewards); + //console.log(positiveRewards); roll = 100; if (roll > 60) { // Choose between 2 COMMON / 2 GREAT tier items (40%) @@ -125,6 +162,21 @@ export const ChoiceOfBalanceEncounter: IMysteryEncounter = MysteryEncounterBuild leaveEncounterWithoutBattle(scene, true); return true; }) + .withSimpleOption( + { + buttonLabel: `${namespace}_option_2_label`, + buttonTooltip: `${namespace}_option_2_tooltip`, + selected: [ + { + text: `${namespace}_option_2_selected_message`, + }, + ], + }, + async (scene: BattleScene) => { + // Leave encounter with no rewards or exp + leaveEncounterWithoutBattle(scene, true); + return true; + }) .build(); export enum NegativeRewards { @@ -153,7 +205,7 @@ export function getNegativeRewards(totalOptions: number): number[] { while (negativeOptions.length < totalOptions) { const roll = randSeedInt(numNegatives.length); if (!negativeOptions.includes(roll)) { - negativeOptions.push(NegativeRewards[roll]); + negativeOptions.push(roll); } } return negativeOptions; @@ -164,8 +216,8 @@ export function getPositiveRewards(totalOptions: number): number[] { const numPositives = Object.values(PositiveRewards).filter(pr => !isNaN(Number(pr))); while (positiveOptions.length < totalOptions) { const roll = randSeedInt(numPositives.length); - if (!positiveOptions.includes(roll)) { - positiveOptions.push(PositiveRewards[numPositives[roll]]); + if (!positiveOptions.includes(numPositives[roll])) { + positiveOptions.push(numPositives[roll]); } } return positiveOptions; @@ -181,13 +233,31 @@ export class RewardOption { } generateMessage(): string { - const negativeInfo = this.getRewardInfo(this.negativeOption); - //const positiveInfo = this.getRewardInfo(this.positiveOption); - let outputMessage = this.descriptorText(negativeInfo[1]); - console.log(this.formattedStrengths(NegativeRewards.ADD_POKEMON)); - outputMessage += this.descriptorText("for"); - outputMessage = negativeInfo[1]; - return outputMessage; + const [negativeType, negativeText, negativeStrength, negativeDuration] = this.getRewardInfo(this.negativeOption); + const [positiveType, positiveText, positiveStrength, positiveDuration] = this.getRewardInfo(this.positiveOption); + const outputMessage: string[] = []; + outputMessage.push(this.getDescriptorText(negativeText)); + if (this.formattedStrengths(negativeType, negativeStrength) !== "") { + outputMessage.push(this.formattedStrengths(negativeType, negativeStrength)); + } + outputMessage.push(this.getDescriptorText("for")); + outputMessage.push(this.formattedWaves(negativeDuration)); + outputMessage.push(this.getDescriptorText("then")); + outputMessage.push(this.getDescriptorText(positiveText)); + if (this.formattedStrengths(positiveType, positiveStrength) !== "") { + outputMessage.push(this.formattedStrengths(positiveType, positiveStrength)); + } + if (positiveDuration !== 0) { + outputMessage.push(this.getDescriptorText("for")); + } + outputMessage.push(this.formattedWaves(positiveDuration)); + + //outputMessage = outputMessage.filter() + + //console.log(this.formattedStrengths(NegativeRewards.ADD_POKEMON)); + //outputMessage += this.getDescriptorText("for"); + //outputMessage = negativeInfo[1]; + return outputMessage.join(" "); } @@ -198,14 +268,17 @@ export class RewardOption { //} } - private formattedStrengths(strength: number): string { + private formattedStrengths(type: number, strength: number): string { let newStrength: string; - switch (strength) { + switch (type) { + // These are for percentages case NegativeRewards.INCOME: case NegativeRewards.DAMAGE_TO_PLAYER: case PositiveRewards.INCOME: case PositiveRewards.PP: - newStrength = String(Math.abs(strength * 100)); + newStrength = String(Math.abs(strength * 100)) + "%"; + break; + // These are for single numbers (i.e. stat stage increase/decrease, luck increase/decrease etc) case NegativeRewards.LUCK: case NegativeRewards.PLAYER_STATS: case NegativeRewards.ENEMY_STATS: @@ -214,31 +287,55 @@ export class RewardOption { case PositiveRewards.ENEMY_STATS: case NegativeRewards.PLAYER_STATS: newStrength = String(Math.abs(strength)); + break; + // These are for exceptions that don't have a strength case NegativeRewards.ADD_POKEMON: case NegativeRewards.NO_REROLL: + case PositiveRewards.INSTANT_CANDY: newStrength = ""; + break; + // These are for money rewards + case PositiveRewards.INSTANT_MONEY: + newStrength = "$" + String(strength); + break; + default: + console.log("Missing formattedStrengths!!!"); + newStrength = "Missing formattedStrengths"; + break; } return newStrength; } - private descriptorText(text: string) { - return "mysteryEncounter:choice_of_balance_" + text; + private formattedWaves(duration: number): string { + let waveDuration: string; + if (duration < 0) { + waveDuration = this.getDescriptorText("rest_of_run"); + } else if (duration === 0) { + waveDuration = this.getDescriptorText("instantly"); + } else if (duration > 0) { + waveDuration = String(duration) + " " + this.getDescriptorText("waves"); + } + return waveDuration; + } + + private getDescriptorText(text: string) { + return i18next.t(namespace + "_" + text); } } const statMessageIndex: [index: number, dialogueName: string, auraStrength: number, auraDuration: number][] = [ - [NegativeRewards.INCOME, "choice_of_balance_negative_income", -0.4, 5], - [NegativeRewards.LUCK, "choice_of_balance_negative_luck", 0, 15], - [NegativeRewards.PLAYER_STATS, "choice_of_balance_negative_player_stats", -1, 10], - [NegativeRewards.ENEMY_STATS, "choice_of_balance_negative_enemy_stats", 1, 8], - [NegativeRewards.ADD_POKEMON, "choice_of_balance_negative_add_pokemon", 0, 15], - [NegativeRewards.DAMAGE_TO_PLAYER, "choice_of_balance_negative_damage_to_player", 0.1, 5], - [NegativeRewards.NO_REROLL, "choice_of_balance_negative_no_reroll", 0, 7], - [PositiveRewards.INCOME, "choice_of_balance_positive_income", 0.7, -1], - [PositiveRewards.LUCK, "choice_of_balance_positive_luck", 5, -1], - [PositiveRewards.PLAYER_STATS, "choice_of_balance_positive_player_stats", 1, 13], - [PositiveRewards.ENEMY_STATS, "choice_of_balance_positive_enemy_stats", -1, 12], - [PositiveRewards.PP, "choice_of_balance_positive_pp_chance", 0.2, 40], - [PositiveRewards.INSTANT_MONEY, "choice_of_balance_positive_instant_money", 5000, 0], - [PositiveRewards.INSTANT_CANDY, "choice_of_balance_positive_instant_candy", 0, 0] + [NegativeRewards.INCOME, "negative_income", -0.4, 5], + [NegativeRewards.LUCK, "negative_luck", 0, 15], + [NegativeRewards.PLAYER_STATS, "negative_player_stats", -1, 10], + [NegativeRewards.ENEMY_STATS, "negative_enemy_stats", 1, 8], + [NegativeRewards.ADD_POKEMON, "negative_add_pokemon", 0, 15], + [NegativeRewards.DAMAGE_TO_PLAYER, "negative_damage_to_player", 0.1, 5], + [NegativeRewards.NO_REROLL, "negative_no_reroll", 0, 7], + [PositiveRewards.INCOME, "positive_income", 0.7, -1], + [PositiveRewards.LUCK, "positive_luck", 5, -1], + [PositiveRewards.PLAYER_STATS, "positive_player_stats", 1, 13], + [PositiveRewards.ENEMY_STATS, "positive_enemy_stats", -1, 12], + [PositiveRewards.PP, "positive_pp_chance", 0.2, 40], + [PositiveRewards.INSTANT_MONEY, "positive_instant_money", 5000, 0], + [PositiveRewards.INSTANT_CANDY, "positive_instant_candy", 0, 0] ]; diff --git a/src/data/mystery-encounters/mystery-encounter.ts b/src/data/mystery-encounters/mystery-encounter.ts index e02639939b8b..da29106f2fe4 100644 --- a/src/data/mystery-encounters/mystery-encounter.ts +++ b/src/data/mystery-encounters/mystery-encounter.ts @@ -377,13 +377,17 @@ export class MysteryEncounterBuilder implements Partial { * @param option - MysteryEncounterOption to add, can use MysteryEncounterOptionBuilder to create instance * @returns */ - withOption(option: MysteryEncounterOption): this & Pick { + withOption(option: MysteryEncounterOption, hidden?: boolean): this & Pick { + const hiddenOption = hidden || false; if (this.options[0] === null) { return Object.assign(this, { options: [option, this.options[0]] }); } else if (this.options[1] === null) { return Object.assign(this, { options: [this.options[0], option] }); } else { - this.options.push(option); + if (!hiddenOption) { + this.options.push(option); + //return Object.assign(this, { options: this.options }); + } return Object.assign(this, { options: this.options }); } } @@ -396,8 +400,9 @@ export class MysteryEncounterBuilder implements Partial { * @param callback - {@linkcode OptionPhaseCallback} * @returns */ - withSimpleOption(dialogue: OptionTextDisplay, callback: OptionPhaseCallback) { - return this.withOption(new MysteryEncounterOptionBuilder().withOptionMode(EncounterOptionMode.DEFAULT).withDialogue(dialogue).withOptionPhase(callback).build()); + withSimpleOption(dialogue: OptionTextDisplay, callback: OptionPhaseCallback, hidden?: boolean) { + const hiddenOption = hidden || false; + return this.withOption(new MysteryEncounterOptionBuilder().withOptionMode(EncounterOptionMode.DEFAULT).withDialogue(dialogue).withOptionPhase(callback).build(), hiddenOption); } /** diff --git a/src/locales/en/mystery-encounter.ts b/src/locales/en/mystery-encounter.ts index e29ad5909970..2ac8231dfd31 100644 --- a/src/locales/en/mystery-encounter.ts +++ b/src/locales/en/mystery-encounter.ts @@ -39,7 +39,7 @@ export const mysteryEncounter: SimpleTranslationEntries = { "choice_of_balance_intro_message": `You feel a strange pull in a certain direction. $Heading towards it, you see a weird glow in the distance. $It's an...@d{64} Inkay?! You accidentally make\nsome noise and scare it off... - $...but not before it inks you with a psychic shot!`, + $...but not before dazzling you with its flashing spots!`, "choice_of_balance_title": "The Choice of Balance", "choice_of_balance_description": "You've been inked by inkay and feel a little woozy. You can't really tell what's good and what's not?", "choice_of_balance_query": "What will you choose?", @@ -61,11 +61,12 @@ export const mysteryEncounter: SimpleTranslationEntries = { "choice_of_balance_positive_enemy_stats": "Reduce enemy STAT by", "choice_of_balance_positive_pp_chance": "Reduce PP usage chance", "choice_of_balance_positive_instant_money": "Gain money", - "choice_of_balance_positive_instant_candy": "Gain candy", + "choice_of_balance_positive_instant_candy": "Gain a rarer candy", "choice_of_balance_then": "THEN:", "choice_of_balance_for": "for", "choice_of_balance_waves": "waves", "choice_of_balance_rest_of_run": "for the rest of this run", + "choice_of_balance_instantly": "instantly", //"choice_of_balance_option_2_selected_message": "You hurry along your way,\nwith a slight feeling of regret.", //"choice_of_balance_option_1_normal_result": "Just some normal tools and items.", //"choice_of_balance_option_1_good_result": "Some pretty nice tools and items.", From 75c81a0b035a87b765704f0c5e386c34b025c421 Mon Sep 17 00:00:00 2001 From: Opaque02 <66582645+Opaque02@users.noreply.github.com> Date: Mon, 15 Jul 2024 01:23:08 +1000 Subject: [PATCH 04/12] Added more code surrounding auras --- src/battle-scene.ts | 12 +- .../encounters/choice-of-balance-encounter.ts | 198 ++++++++++-------- .../mystery-encounter-data.ts | 45 +++- .../mystery-encounters/mystery-encounter.ts | 14 +- src/locales/en/mystery-encounter.ts | 12 +- src/modifier/modifier-type.ts | 12 +- 6 files changed, 174 insertions(+), 119 deletions(-) diff --git a/src/battle-scene.ts b/src/battle-scene.ts index ca6847dbd629..eaa4c57ba996 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -2151,9 +2151,9 @@ export default class BattleScene extends SceneBase { } addMoney(amount: integer): void { - const mysteryMoneyAura = this.mysteryEncounterAuras.FindAura(getAuraName(AuraType.MONEY)); - const mysteryMoneyMult = 1 + (mysteryMoneyAura.length > 0 ? mysteryMoneyAura[0].auraStrength : 0); - this.money = Math.min(this.money + Math.floor(amount * mysteryMoneyMult), Number.MAX_SAFE_INTEGER); + const mysteryIncomeAura = this.mysteryEncounterAuras.FindAura(getAuraName(AuraType.INCOME)); + const mysteryIncomeMult = 1 + (mysteryIncomeAura.length > 0 ? this.mysteryEncounterAuras.FindAuraTotals(getAuraName(AuraType.INCOME)) : 0); + this.money = Math.min(this.money + Math.floor(amount * mysteryIncomeMult), Number.MAX_SAFE_INTEGER); this.updateMoneyText(); this.animateMoneyChanged(true); this.validateAchvs(MoneyAchv); @@ -2161,9 +2161,9 @@ export default class BattleScene extends SceneBase { getFormattedMoneyString(moneyAmount: number): string { const userLocale = navigator.language || "en-US"; - const mysteryMoneyAura = this.mysteryEncounterAuras.FindAura(getAuraName(AuraType.MONEY)); - const mysteryMoneyMult = 1 + (mysteryMoneyAura.length > 0 ? mysteryMoneyAura[0].auraStrength : 0); - const formattedMoneyAmount = (moneyAmount.value * mysteryMoneyMult).toLocaleString(userLocale); + const mysteryIncomeAura = this.mysteryEncounterAuras.FindAura(getAuraName(AuraType.INCOME)); + const mysteryIncomeMult = 1 + (mysteryIncomeAura.length > 0 ? this.mysteryEncounterAuras.FindAuraTotals(getAuraName(AuraType.INCOME)) : 0); + const formattedMoneyAmount = (moneyAmount * mysteryIncomeMult).toLocaleString(userLocale); const message = i18next.t("battle:moneyWon", { moneyAmount: formattedMoneyAmount }); return message; } diff --git a/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts b/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts index cb2ba84907c8..7454a831c4dc 100644 --- a/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts +++ b/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts @@ -1,14 +1,15 @@ -import { - getHighestLevelPlayerPokemon, - koPlayerPokemon, - leaveEncounterWithoutBattle, - queueEncounterMessage, - setEncounterRewards, - showEncounterText, -} from "#app/data/mystery-encounters/mystery-encounter-utils"; -import { mysteryEncounter } from "#app/locales/en/mystery-encounter"; -import { ModifierTier } from "#app/modifier/modifier-tier"; -import { GameOverPhase } from "#app/phases"; +//import { +// getHighestLevelPlayerPokemon, +// koPlayerPokemon, +// leaveEncounterWithoutBattle, +// queueEncounterMessage, +// setEncounterRewards, +// showEncounterText, +//} from "#app/data/mystery-encounters/mystery-encounter-utils"; +import { leaveEncounterWithoutBattle } from "#app/data/mystery-encounters/mystery-encounter-utils"; +//import { mysteryEncounter } from "#app/locales/en/mystery-encounter"; +//import { ModifierTier } from "#app/modifier/modifier-tier"; +//import { GameOverPhase } from "#app/phases"; import { randSeedInt } from "#app/utils"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import i18next from "i18next"; @@ -18,24 +19,18 @@ import IMysteryEncounter, { MysteryEncounterTier, } from "../mystery-encounter"; import { EncounterOptionMode, MysteryEncounterOptionBuilder } from "../mystery-encounter-option"; -//import { AuraType, getAuraName } from "#app/data/mystery-encounters/mystery-encounter-data"; +import { Aura, AuraType, getAuraName } from "#app/data/mystery-encounters/mystery-encounter-data"; const namespace = "mysteryEncounter:choice_of_balance"; -const options = 2 + randSeedInt(1); -function generateRewards(numOptions: number): number[] { +function generateRewards(numOptions: number): RewardOption[] { const negativeRewards = getNegativeRewards(numOptions); const positiveRewards = getPositiveRewards(numOptions); const rewardArray = []; for (let i = 0; i < negativeRewards.length; i++) { rewardArray.push(new RewardOption(negativeRewards[i], positiveRewards[i])); } - mysteryEncounter["choice_of_balance_option_1_tooltip"] = rewardArray[0].generateMessage(); // this will need changing eventually; this is NOT a good way to do it - mysteryEncounter["choice_of_balance_option_2_tooltip"] = rewardArray[1].generateMessage(); // this will need changing eventually; this is NOT a good way to do it - //const test = rewardArray[0]; - //console.log(test.generateMessage()); - //console.log(negativeRewards); - //console.log(positiveRewards); + return rewardArray; } @@ -65,22 +60,49 @@ export const ChoiceOfBalanceEncounter: IMysteryEncounter = MysteryEncounterBuild encounter.misc = []; console.log(encounter); - console.log("Number of options generated", options); + const options = 2 + randSeedInt(2); // this makes a random number between 2 and 3 for the options const rewardsArray = generateRewards(options); - encounter.misc.push(rewardsArray); + + for (let i = 0; i < rewardsArray.length; i++) { + rewardsArray[i].generateStats(); + rewardsArray[i].generateAuras(); + if (rewardsArray[i].negativeStat > 0) { + if (rewardsArray[i].negativeOption === NegativeRewards.ENEMY_STATS) { + encounter.setDialogueToken("negativeEnemySTAT", getAuraName(rewardsArray[i].negativeStat)); + } else if (rewardsArray[i].negativeOption === NegativeRewards.PLAYER_STATS) { + encounter.setDialogueToken("negativePlayerSTAT", getAuraName(rewardsArray[i].negativeStat)); + } + } + if (rewardsArray[i].positiveStat > 0) { + if (rewardsArray[i].positiveOption === PositiveRewards.ENEMY_STATS) { + encounter.setDialogueToken("positiveEnemySTAT", getAuraName(rewardsArray[i].positiveStat)); + } else if (rewardsArray[i].positiveOption === PositiveRewards.PLAYER_STATS) { + encounter.setDialogueToken("positivePlayerSTAT", getAuraName(rewardsArray[i].positiveStat)); + } + } + encounter.misc.push(rewardsArray[i]); + } + + encounter.setDialogueToken("dynamic1", rewardsArray[0].generateMessage()); + encounter.setDialogueToken("dynamic2", rewardsArray[1].generateMessage()); + if (options === 3) { + encounter.setDialogueToken("dynamic3", rewardsArray[2].generateMessage()); + } else if (options === 2 && encounter.options.length === 3) { + encounter.options.pop(); + } + return true; }) .withTitle(`${namespace}_title`) .withDescription(`${ namespace }_description`) .withQuery(`${namespace}_query`) - .withExtraInfo(options === 3) .withOption( new MysteryEncounterOptionBuilder() .withOptionMode(EncounterOptionMode.DEFAULT) .withDialogue({ buttonLabel: `${namespace}_option_1_label`, - buttonTooltip: `${ namespace }_option_1_tooltip`, + buttonTooltip: `${ namespace }_dynamic_option_1`, selected: [ { text: `${namespace}_option_1_selected_message`, @@ -88,69 +110,17 @@ export const ChoiceOfBalanceEncounter: IMysteryEncounter = MysteryEncounterBuild ], }) .withOptionPhase(async (scene: BattleScene) => { - // Open the chest - let roll = randSeedInt(100); - //const negativeRewards = getNegativeRewards(numOptions); - //const positiveRewards = getPositiveRewards(numOptions); - //let rewardArray = []; - //for (var i = 0; i < negativeRewards.length; i++) { - // rewardArray.push(new RewardOption(negativeRewards[i], positiveRewards[i])); - //} - //const test = rewardArray[0]; - //console.log(test.generateMessage()); - //console.log(negativeRewards); - //console.log(positiveRewards); - roll = 100; - if (roll > 60) { - // Choose between 2 COMMON / 2 GREAT tier items (40%) - setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.COMMON, ModifierTier.COMMON, ModifierTier.GREAT, ModifierTier.GREAT] }); - // Display result message then proceed to rewards - queueEncounterMessage(scene, `${namespace}_option_1_normal_result`); - leaveEncounterWithoutBattle(scene); - } else if (roll > 40) { - // Choose between 3 ULTRA tier items (20%) - setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA] }); - // Display result message then proceed to rewards - queueEncounterMessage(scene, `${namespace}_option_1_good_result`); - leaveEncounterWithoutBattle(scene); - } else if (roll > 36) { - // Choose between 2 ROGUE tier items (4%) - setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE] }); - // Display result message then proceed to rewards - queueEncounterMessage(scene, `${namespace}_option_1_great_result`); - leaveEncounterWithoutBattle(scene); - } else if (roll > 35) { - // Choose 1 MASTER tier item (1%) - setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.MASTER] }); - // Display result message then proceed to rewards - queueEncounterMessage(scene, `${namespace}_option_1_amazing_result`); - leaveEncounterWithoutBattle(scene); - } else { - // Your highest level unfainted Pok�mon gets OHKO. Progress with no rewards (35%) - const highestLevelPokemon = getHighestLevelPlayerPokemon(scene, true); - koPlayerPokemon(highestLevelPokemon); - - scene.currentBattle.mysteryEncounter.setDialogueToken("pokeName", highestLevelPokemon.name); - // Show which Pokemon was KOed, then leave encounter with no rewards - // Does this synchronously so that game over doesn't happen over result message - await showEncounterText(scene, `${namespace}_option_1_bad_result`) - .then(() => { - if (scene.getParty().filter(p => p.isAllowedInBattle()).length === 0) { - // All pokemon fainted, game over - scene.clearPhaseQueue(); - scene.unshiftPhase(new GameOverPhase(scene)); - } else { - leaveEncounterWithoutBattle(scene); - } - }); - } + // Leave encounter with no rewards or exp + //[const negativeAura, const positiveAura] + leaveEncounterWithoutBattle(scene, true); + return true; }) .build() ) .withSimpleOption( { buttonLabel: `${namespace}_option_2_label`, - buttonTooltip: `${namespace}_option_2_tooltip`, + buttonTooltip: `${namespace}_dynamic_option_2`, selected: [ { text: `${namespace}_option_2_selected_message`, @@ -164,11 +134,11 @@ export const ChoiceOfBalanceEncounter: IMysteryEncounter = MysteryEncounterBuild }) .withSimpleOption( { - buttonLabel: `${namespace}_option_2_label`, - buttonTooltip: `${namespace}_option_2_tooltip`, + buttonLabel: `${namespace}_option_3_label`, + buttonTooltip: `${namespace}_dynamic_option_3`, selected: [ { - text: `${namespace}_option_2_selected_message`, + text: `${namespace}_option_3_selected_message`, }, ], }, @@ -226,6 +196,10 @@ export function getPositiveRewards(totalOptions: number): number[] { export class RewardOption { public negativeOption: number; public positiveOption: number; + public negativeStat = -1; + public positiveStat = -1; + public negativeAura: Aura; + public positiveAura: Aura; constructor(negativeOption: number, positiveOption: number) { this.negativeOption = negativeOption; @@ -251,14 +225,7 @@ export class RewardOption { outputMessage.push(this.getDescriptorText("for")); } outputMessage.push(this.formattedWaves(positiveDuration)); - - //outputMessage = outputMessage.filter() - - //console.log(this.formattedStrengths(NegativeRewards.ADD_POKEMON)); - //outputMessage += this.getDescriptorText("for"); - //outputMessage = negativeInfo[1]; return outputMessage.join(" "); - } getRewardInfo(reward: number): [index: number, dialogueName: string, auraStrength: number, auraDuration: number] { @@ -285,7 +252,6 @@ export class RewardOption { case PositiveRewards.LUCK: case PositiveRewards.PLAYER_STATS: case PositiveRewards.ENEMY_STATS: - case NegativeRewards.PLAYER_STATS: newStrength = String(Math.abs(strength)); break; // These are for exceptions that don't have a strength @@ -321,6 +287,54 @@ export class RewardOption { private getDescriptorText(text: string) { return i18next.t(namespace + "_" + text); } + + generateStats() { + const statArray = [AuraType.ATK, AuraType.SPATK, AuraType.DEF, AuraType.SPDEF, AuraType.SPD, AuraType.EVA, AuraType.ACC]; + if (this.negativeStat < 0 && (this.negativeOption === NegativeRewards.ENEMY_STATS || this.negativeOption === NegativeRewards.PLAYER_STATS)) { + this.negativeStat = statArray[randSeedInt(statArray.length)]; + } + if (this.positiveStat < 0 && (this.positiveOption === PositiveRewards.PLAYER_STATS || this.positiveOption === PositiveRewards.ENEMY_STATS)) { + this.positiveStat = statArray[randSeedInt(statArray.length)]; + } + } + + generateAuras() { + const [negativeType, negativeText, negativeStrength, negativeDuration] = this.getRewardInfo(this.negativeOption); + const [positiveType, positiveText, positiveStrength, positiveDuration] = this.getRewardInfo(this.positiveOption); + console.log(negativeText + ", " + positiveText); + this.negativeAura = new Aura([-1], negativeStrength, negativeDuration, getAuraName(this.convertRewardsToAura(negativeType)), 0, 0); + this.positiveAura = new Aura([-1], positiveStrength, positiveDuration, getAuraName(this.convertRewardsToAura(positiveType)), 0, negativeDuration); + } + + convertRewardsToAura(reward: number): number { + const statArray = [AuraType.ATK, AuraType.SPATK, AuraType.DEF, AuraType.SPDEF, AuraType.SPD, AuraType.EVA, AuraType.ACC]; + switch (reward) { + case NegativeRewards.INCOME: + return AuraType.INCOME; + case NegativeRewards.LUCK: + return AuraType.LUCK; + case NegativeRewards.PLAYER_STATS: + case NegativeRewards.ENEMY_STATS: + return statArray[this.negativeStat]; + case NegativeRewards.ADD_POKEMON: + case NegativeRewards.DAMAGE_TO_PLAYER: + case NegativeRewards.NO_REROLL: + return -1; + case PositiveRewards.INCOME: + return AuraType.INCOME; + case PositiveRewards.LUCK: + return AuraType.LUCK; + case PositiveRewards.PLAYER_STATS: + case PositiveRewards.ENEMY_STATS: + return statArray[this.positiveStat]; + case PositiveRewards.PP: + return -1; + case PositiveRewards.INSTANT_MONEY: + return AuraType.MONEY; + case PositiveRewards.INSTANT_CANDY: + return -1; + } + } } const statMessageIndex: [index: number, dialogueName: string, auraStrength: number, auraDuration: number][] = [ diff --git a/src/data/mystery-encounters/mystery-encounter-data.ts b/src/data/mystery-encounters/mystery-encounter-data.ts index e233ad1183fd..cc46562ba4bf 100644 --- a/src/data/mystery-encounters/mystery-encounter-data.ts +++ b/src/data/mystery-encounters/mystery-encounter-data.ts @@ -2,6 +2,7 @@ import { MysteryEncounterTier } from "#app/data/mystery-encounters/mystery-encou import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT } from "#app/data/mystery-encounters/mystery-encounters"; import { isNullOrUndefined } from "#app/utils"; +//import { time } from "console"; export class MysteryEncounterData { encounteredEvents: [MysteryEncounterType, MysteryEncounterTier][] = []; @@ -22,35 +23,59 @@ export class MysteryEncounterAuras { this.playerAura = []; } - AddAura(target: number[], auraStrength: number, duration: number, auraType: string, team: number) { - this.playerAura.push(new Aura(target, auraStrength, duration, auraType, team)); + AddAura(target: number[], auraStrength: number, duration: number, auraType: string, team: number, timeUntilActive: number = 0) { + this.playerAura.push(new Aura(target, auraStrength, duration, auraType, team, timeUntilActive)); } UpdateAurasDurations() { for (let i = 0; i < this.playerAura.length; i++) { - this.playerAura[i].duration -= 1; + if (this.playerAura[i].timeUntilActive !== 0) { + this.playerAura[i].timeUntilActive -= 1; + } else { + if (this.playerAura[i].duration > 0) { + this.playerAura[i].duration -= 1; + } + } } this.playerAura = this.playerAura.filter(aura => aura.duration !== 0); } - FindAura(auraType: string) { + FindAuraTotals(auraType: string): number { + let total = 0; + const filteredAuras = this.FindAura(auraType); + if (filteredAuras.length > 0) { + for (let i = 0; i < filteredAuras.length; i++) { + const auraValue = filteredAuras[i].auraStrength; + if (auraType === getAuraName(AuraType.LUCK) && auraValue === 0) { // this is used to check if luck has "Set to 0" + total = 0.5; + break; + } + total += filteredAuras[i].timeUntilActive > 0 ? 0 : auraValue; // this checks to make sure the aura is active before adding it to our totals + } + } + return total; + } + + FindAura(auraType: string): Aura[] { return this.playerAura.filter(auras => auras.auraType === auraType); } } -class Aura { +export class Aura { public target: number[]; // this can be used to target specific pokemon (using an array of pokemon ID) or all pokemon (using [-1]) public auraStrength: number; // this is the amount boosted/reduced - can be positive or negative public duration: number; // this is how many waves the aura lasts for; use a number > 0 for timed auras, or -1 for auras for the rest of the game public auraType: string; // this is the aura type - for now, for example, what stat will be changed public team: number; // this is the team. I think this will eventually be an enum - something like Team.PLAYER, Team.ENEMY, Team.ALL to target the player, enemy or everyone respectively. + public timeUntilActive: number; // this will be the amount of waves until an aura is active; for example, a positive aura being activated when a negative one runs out. - constructor(target: number[], auraStrength: number, duration: number, auraType: string, team: number) { + constructor(target: number[], auraStrength: number, duration: number, auraType: string, team: number, timeUntilActive: number) { this.target = target; this.auraStrength = auraStrength; this.duration = duration; this.auraType = auraType; this.team = team; + this.timeUntilActive = timeUntilActive; } } @@ -61,6 +86,7 @@ export enum TeamTarget { } export enum AuraType { + INCOME, MONEY, ATK, SPATK, @@ -69,11 +95,14 @@ export enum AuraType { SPD, EVA, ACC, + LUCK, XP } export function getAuraName(aura: AuraType) { switch (aura) { + case AuraType.INCOME: + return "INCOME"; case AuraType.MONEY: return "MONEY"; case AuraType.ATK: @@ -90,8 +119,10 @@ export function getAuraName(aura: AuraType) { return "ACC"; case AuraType.EVA: return "EVA"; + case AuraType.LUCK: + return "LUCK"; case AuraType.XP: - return "XP"; + return "EXP"; default: return "???"; } diff --git a/src/data/mystery-encounters/mystery-encounter.ts b/src/data/mystery-encounters/mystery-encounter.ts index da29106f2fe4..f4221d0e7ce8 100644 --- a/src/data/mystery-encounters/mystery-encounter.ts +++ b/src/data/mystery-encounters/mystery-encounter.ts @@ -143,6 +143,7 @@ export default class IMysteryEncounter implements IMysteryEncounter { this.hideIntroVisuals = !isNullOrUndefined(this.hideIntroVisuals) ? this.hideIntroVisuals : true; // Reset any dirty flags or encounter data + this.options = [...this.options]; this.lockEncounterRewardTiers = true; this.dialogueTokens = {}; this.enemyPartyConfigs = []; @@ -377,17 +378,13 @@ export class MysteryEncounterBuilder implements Partial { * @param option - MysteryEncounterOption to add, can use MysteryEncounterOptionBuilder to create instance * @returns */ - withOption(option: MysteryEncounterOption, hidden?: boolean): this & Pick { - const hiddenOption = hidden || false; + withOption(option: MysteryEncounterOption): this & Pick { if (this.options[0] === null) { return Object.assign(this, { options: [option, this.options[0]] }); } else if (this.options[1] === null) { return Object.assign(this, { options: [this.options[0], option] }); } else { - if (!hiddenOption) { - this.options.push(option); - //return Object.assign(this, { options: this.options }); - } + this.options.push(option); return Object.assign(this, { options: this.options }); } } @@ -400,9 +397,8 @@ export class MysteryEncounterBuilder implements Partial { * @param callback - {@linkcode OptionPhaseCallback} * @returns */ - withSimpleOption(dialogue: OptionTextDisplay, callback: OptionPhaseCallback, hidden?: boolean) { - const hiddenOption = hidden || false; - return this.withOption(new MysteryEncounterOptionBuilder().withOptionMode(EncounterOptionMode.DEFAULT).withDialogue(dialogue).withOptionPhase(callback).build(), hiddenOption); + withSimpleOption(dialogue: OptionTextDisplay, callback: OptionPhaseCallback) { + return this.withOption(new MysteryEncounterOptionBuilder().withOptionMode(EncounterOptionMode.DEFAULT).withDialogue(dialogue).withOptionPhase(callback).build()); } /** diff --git a/src/locales/en/mystery-encounter.ts b/src/locales/en/mystery-encounter.ts index 2ac8231dfd31..f3c52301063c 100644 --- a/src/locales/en/mystery-encounter.ts +++ b/src/locales/en/mystery-encounter.ts @@ -45,20 +45,24 @@ export const mysteryEncounter: SimpleTranslationEntries = { "choice_of_balance_query": "What will you choose?", "choice_of_balance_option_1_label": "Option A", "choice_of_balance_option_1_tooltip": "@[SUMMARY_BLUE]{(35%) Something terrible}\n@[SUMMARY_GREEN]{(40%) Okay Rewards}\n@[SUMMARY_GREEN]{(20%) Good Rewards}\n@[SUMMARY_GREEN]{(4%) Great Rewards}\n@[SUMMARY_GREEN]{(1%) Amazing Rewards}", + "choice_of_balance_dynamic_option_1": "{{dynamic1}}", "choice_of_balance_option_2_label": "Option B", "choice_of_balance_option_2_tooltip": "(-) No Rewards", + "choice_of_balance_dynamic_option_2": "{{dynamic2}}", + "choice_of_balance_option_3_label": "Option C", + "choice_of_balance_dynamic_option_3": "{{dynamic3}}", "choice_of_balance_option_selected_message": "You hope you've made the right decision...", "choice_of_balance_negative_income": "Reduce income by", "choice_of_balance_negative_luck": "Set luck to", - "choice_of_balance_negative_player_stats": "Reduce STAT by", - "choice_of_balance_negative_enemy_stats": "Increase enemy STAT by", + "choice_of_balance_negative_player_stats": "Reduce {{negativePlayerSTAT}} by", + "choice_of_balance_negative_enemy_stats": "Increase enemy {{negativeEnemySTAT}} by", "choice_of_balance_negative_add_pokemon": "Unable to add pokemon", "choice_of_balance_negative_damage_to_player": "Increase DMG taken by", "choice_of_balance_negative_no_reroll": "No shop rerolls", "choice_of_balance_positive_income": "Increase income by", "choice_of_balance_positive_luck": "Increase luck by", - "choice_of_balance_positive_player_stats": "Increase STAT by", - "choice_of_balance_positive_enemy_stats": "Reduce enemy STAT by", + "choice_of_balance_positive_player_stats": "Increase {{positivePlayerSTAT}} by", + "choice_of_balance_positive_enemy_stats": "Reduce enemy {{positiveEnemySTAT}} by", "choice_of_balance_positive_pp_chance": "Reduce PP usage chance", "choice_of_balance_positive_instant_money": "Gain money", "choice_of_balance_positive_instant_candy": "Gain a rarer candy", diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 250b2953fdf2..364e2442fd26 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -27,6 +27,7 @@ import { BattlerTagType } from "#enums/battler-tag-type"; import { BerryType } from "#enums/berry-type"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; +import { getAuraName, AuraType } from "#app/data/mystery-encounters/mystery-encounter-data"; const outputModifierData = false; const useMaxWeightForOutput = false; @@ -2088,8 +2089,17 @@ export class ModifierTypeOption { } export function getPartyLuckValue(party: Pokemon[]): integer { + const mysteryLuckAura = party[0].scene.mysteryEncounterAuras.FindAura(getAuraName(AuraType.LUCK)); + let auraLuck = 0; + if (mysteryLuckAura.length > 0) { + const auraTotalLuck = party[0].scene.mysteryEncounterAuras.FindAuraTotals(getAuraName(AuraType.LUCK)); + if (auraTotalLuck === 0.5) { /// this means that there are luck related auras, but the luck is forcibly being set to 0, so we need to return 0 here + return 0; + } + auraLuck += auraTotalLuck; + } const luck = Phaser.Math.Clamp(party.map(p => p.isFainted() ? 0 : p.getLuck()) - .reduce((total: integer, value: integer) => total += value, 0), 0, 14); + .reduce((total: integer, value: integer) => total += value, 0) + auraLuck, 0, 14); return luck || 0; } From d631564749eb2d0e10e6b9c6665f9f1ff7642e74 Mon Sep 17 00:00:00 2001 From: Opaque02 <66582645+Opaque02@users.noreply.github.com> Date: Mon, 15 Jul 2024 12:22:56 +1000 Subject: [PATCH 05/12] Testing nested i18next values --- .../encounters/choice-of-balance-encounter.ts | 4 ++-- .../mystery-encounters/mystery-encounter-data.ts | 10 ++++++++-- src/locales/en/mystery-encounter.ts | 12 ++++++++---- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts b/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts index 7454a831c4dc..94ca5407aae5 100644 --- a/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts +++ b/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts @@ -328,11 +328,11 @@ export class RewardOption { case PositiveRewards.ENEMY_STATS: return statArray[this.positiveStat]; case PositiveRewards.PP: - return -1; + return AuraType.PP; case PositiveRewards.INSTANT_MONEY: return AuraType.MONEY; case PositiveRewards.INSTANT_CANDY: - return -1; + return AuraType.CANDY; } } } diff --git a/src/data/mystery-encounters/mystery-encounter-data.ts b/src/data/mystery-encounters/mystery-encounter-data.ts index cc46562ba4bf..5a9ea1870c15 100644 --- a/src/data/mystery-encounters/mystery-encounter-data.ts +++ b/src/data/mystery-encounters/mystery-encounter-data.ts @@ -33,7 +33,7 @@ export class MysteryEncounterAuras { this.playerAura[i].timeUntilActive -= 1; } else { if (this.playerAura[i].duration > 0) { - this.playerAura[i].duration -= 1; + this.playerAura[i].duration -= 1; // may need to add a thing here so that if the aura is an instant aura to make it activate instead of dropping off straight away } } } @@ -96,7 +96,9 @@ export enum AuraType { EVA, ACC, LUCK, - XP + XP, + CANDY, + PP } export function getAuraName(aura: AuraType) { @@ -123,6 +125,10 @@ export function getAuraName(aura: AuraType) { return "LUCK"; case AuraType.XP: return "EXP"; + case AuraType.CANDY: + return "CANDY"; + case AuraType.PP: + return "PP"; default: return "???"; } diff --git a/src/locales/en/mystery-encounter.ts b/src/locales/en/mystery-encounter.ts index f3c52301063c..d65385e42a42 100644 --- a/src/locales/en/mystery-encounter.ts +++ b/src/locales/en/mystery-encounter.ts @@ -54,15 +54,19 @@ export const mysteryEncounter: SimpleTranslationEntries = { "choice_of_balance_option_selected_message": "You hope you've made the right decision...", "choice_of_balance_negative_income": "Reduce income by", "choice_of_balance_negative_luck": "Set luck to", - "choice_of_balance_negative_player_stats": "Reduce {{negativePlayerSTAT}} by", - "choice_of_balance_negative_enemy_stats": "Increase enemy {{negativeEnemySTAT}} by", + "choice_of_balance_negative_player_stats": "Reduce $t(choice_of_balance_negativePlayerSTAT) by", + "choice_of_balance_negative_enemy_stats": "Increase enemy $t(choice_of_balance_negativeEnemySTAT) by", + "choice_of_balance_negative_negativePlayerSTAT": "{{negativePlayerSTAT}}", + "choice_of_balance_negative_negativeEnemySTAT": "{{negativeEnemySTAT}}", "choice_of_balance_negative_add_pokemon": "Unable to add pokemon", "choice_of_balance_negative_damage_to_player": "Increase DMG taken by", "choice_of_balance_negative_no_reroll": "No shop rerolls", "choice_of_balance_positive_income": "Increase income by", "choice_of_balance_positive_luck": "Increase luck by", - "choice_of_balance_positive_player_stats": "Increase {{positivePlayerSTAT}} by", - "choice_of_balance_positive_enemy_stats": "Reduce enemy {{positiveEnemySTAT}} by", + "choice_of_balance_positive_player_stats": "Increase $t(choice_of_balance_positive_positivePlayerSTAT) by", + "choice_of_balance_positive_enemy_stats": "Reduce enemy $t(choice_of_balance_positive_positiveEnemySTAT) by", + "choice_of_balance_positive_positivePlayerSTAT": "{{positivePlayerSTAT}}", + "choice_of_balance_positive_positiveEnemySTAT": "{{positiveEnemySTAT}}", "choice_of_balance_positive_pp_chance": "Reduce PP usage chance", "choice_of_balance_positive_instant_money": "Gain money", "choice_of_balance_positive_instant_candy": "Gain a rarer candy", From 02643ef4fceabbae661db32ac7b7e678ea8fe17b Mon Sep 17 00:00:00 2001 From: Opaque02 <66582645+Opaque02@users.noreply.github.com> Date: Wed, 17 Jul 2024 17:36:08 +1000 Subject: [PATCH 06/12] Updated code to make stats work --- src/battle-scene.ts | 10 +-- .../encounters/choice-of-balance-encounter.ts | 4 +- .../mystery-encounter-data.ts | 89 ++++++++++++++----- src/field/pokemon.ts | 4 + src/modifier/modifier-type.ts | 6 +- src/phases.ts | 7 ++ 6 files changed, 87 insertions(+), 33 deletions(-) diff --git a/src/battle-scene.ts b/src/battle-scene.ts index eaa4c57ba996..6ca9238c5122 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -69,7 +69,7 @@ import { TimedEventManager } from "#app/timed-event-manager.js"; import i18next from "i18next"; import IMysteryEncounter, { MysteryEncounterTier, MysteryEncounterVariant } from "./data/mystery-encounters/mystery-encounter"; import { mysteryEncountersByBiome, allMysteryEncounters, BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT, AVERAGE_ENCOUNTERS_PER_RUN_TARGET, WIGHT_INCREMENT_ON_SPAWN_MISS } from "./data/mystery-encounters/mystery-encounters"; -import { MysteryEncounterData, MysteryEncounterAuras, getAuraName, AuraType } from "#app/data/mystery-encounters/mystery-encounter-data"; +import { MysteryEncounterData, MysteryEncounterAuras, AuraType } from "#app/data/mystery-encounters/mystery-encounter-data"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1"; @@ -2151,8 +2151,8 @@ export default class BattleScene extends SceneBase { } addMoney(amount: integer): void { - const mysteryIncomeAura = this.mysteryEncounterAuras.FindAura(getAuraName(AuraType.INCOME)); - const mysteryIncomeMult = 1 + (mysteryIncomeAura.length > 0 ? this.mysteryEncounterAuras.FindAuraTotals(getAuraName(AuraType.INCOME)) : 0); + const mysteryIncomeAura = this.mysteryEncounterAuras.FindAura(AuraType.INCOME); + const mysteryIncomeMult = 1 + (mysteryIncomeAura.length > 0 ? this.mysteryEncounterAuras.FindAuraTotals(AuraType.INCOME) : 0); this.money = Math.min(this.money + Math.floor(amount * mysteryIncomeMult), Number.MAX_SAFE_INTEGER); this.updateMoneyText(); this.animateMoneyChanged(true); @@ -2161,8 +2161,8 @@ export default class BattleScene extends SceneBase { getFormattedMoneyString(moneyAmount: number): string { const userLocale = navigator.language || "en-US"; - const mysteryIncomeAura = this.mysteryEncounterAuras.FindAura(getAuraName(AuraType.INCOME)); - const mysteryIncomeMult = 1 + (mysteryIncomeAura.length > 0 ? this.mysteryEncounterAuras.FindAuraTotals(getAuraName(AuraType.INCOME)) : 0); + const mysteryIncomeAura = this.mysteryEncounterAuras.FindAura(AuraType.INCOME); + const mysteryIncomeMult = 1 + (mysteryIncomeAura.length > 0 ? this.mysteryEncounterAuras.FindAuraTotals(AuraType.INCOME) : 0); const formattedMoneyAmount = (moneyAmount * mysteryIncomeMult).toLocaleString(userLocale); const message = i18next.t("battle:moneyWon", { moneyAmount: formattedMoneyAmount }); return message; diff --git a/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts b/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts index 94ca5407aae5..008a1878ea06 100644 --- a/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts +++ b/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts @@ -302,8 +302,8 @@ export class RewardOption { const [negativeType, negativeText, negativeStrength, negativeDuration] = this.getRewardInfo(this.negativeOption); const [positiveType, positiveText, positiveStrength, positiveDuration] = this.getRewardInfo(this.positiveOption); console.log(negativeText + ", " + positiveText); - this.negativeAura = new Aura([-1], negativeStrength, negativeDuration, getAuraName(this.convertRewardsToAura(negativeType)), 0, 0); - this.positiveAura = new Aura([-1], positiveStrength, positiveDuration, getAuraName(this.convertRewardsToAura(positiveType)), 0, negativeDuration); + this.negativeAura = new Aura([-1], negativeStrength, negativeDuration, this.convertRewardsToAura(negativeType), 0, 0); + this.positiveAura = new Aura([-1], positiveStrength, positiveDuration, this.convertRewardsToAura(positiveType), 0, negativeDuration); } convertRewardsToAura(reward: number): number { diff --git a/src/data/mystery-encounters/mystery-encounter-data.ts b/src/data/mystery-encounters/mystery-encounter-data.ts index 5a9ea1870c15..e3fe69f426d1 100644 --- a/src/data/mystery-encounters/mystery-encounter-data.ts +++ b/src/data/mystery-encounters/mystery-encounter-data.ts @@ -2,7 +2,7 @@ import { MysteryEncounterTier } from "#app/data/mystery-encounters/mystery-encou import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT } from "#app/data/mystery-encounters/mystery-encounters"; import { isNullOrUndefined } from "#app/utils"; -//import { time } from "console"; +import { EnemyPokemon, PlayerPokemon } from "field/pokemon"; export class MysteryEncounterData { encounteredEvents: [MysteryEncounterType, MysteryEncounterTier][] = []; @@ -17,36 +17,41 @@ export class MysteryEncounterData { } export class MysteryEncounterAuras { - public playerAura: Aura[]; + public auraList: Aura[]; constructor() { - this.playerAura = []; + this.auraList = []; } - AddAura(target: number[], auraStrength: number, duration: number, auraType: string, team: number, timeUntilActive: number = 0) { - this.playerAura.push(new Aura(target, auraStrength, duration, auraType, team, timeUntilActive)); + AddAura(target: number[], auraStrength: number, duration: number, auraType: number, team: number, timeUntilActive: number = 0) { + this.auraList.push(new Aura(target, auraStrength, duration, auraType, team, timeUntilActive)); } UpdateAurasDurations() { - for (let i = 0; i < this.playerAura.length; i++) { - if (this.playerAura[i].timeUntilActive !== 0) { - this.playerAura[i].timeUntilActive -= 1; + for (let i = 0; i < this.auraList.length; i++) { + if (this.auraList[i].timeUntilActive !== 0) { + this.auraList[i].timeUntilActive -= 1; } else { - if (this.playerAura[i].duration > 0) { - this.playerAura[i].duration -= 1; // may need to add a thing here so that if the aura is an instant aura to make it activate instead of dropping off straight away + if (this.auraList[i].duration > 0) { + this.auraList[i].duration -= 1; // may need to add a thing here so that if the aura is an instant aura to make it activate instead of dropping off straight away } } } - this.playerAura = this.playerAura.filter(aura => aura.duration !== 0); + this.auraList = this.auraList.filter(aura => aura.duration !== 0); } - FindAuraTotals(auraType: string): number { + /* this method will find all auras of a certain type and add up their total strengths. + * For example, if you wanted to find the total strength of all luck related auras + * or all income related auras. Note that this make the percentage additive. + * This does not filter by pokemon or team + */ + FindAuraTotals(auraType: number): number { let total = 0; const filteredAuras = this.FindAura(auraType); if (filteredAuras.length > 0) { for (let i = 0; i < filteredAuras.length; i++) { const auraValue = filteredAuras[i].auraStrength; - if (auraType === getAuraName(AuraType.LUCK) && auraValue === 0) { // this is used to check if luck has "Set to 0" + if (auraType === AuraType.LUCK && auraValue === 0) { // this is used to check if luck has "Set to 0" total = 0.5; break; } @@ -56,8 +61,44 @@ export class MysteryEncounterAuras { return total; } - FindAura(auraType: string): Aura[] { - return this.playerAura.filter(auras => auras.auraType === auraType); + FindAura(auraType: number): Aura[] { // this method will find all auras of a certain type (for example, all income related auras) + return this.auraList.filter(auras => auras.auraType === auraType); + } + + FindAurasByPokemon(pokemon: PlayerPokemon | EnemyPokemon, auraType?: number): Aura[] { // this method finds an aura by pokemon, with optional filtering for type + const allAuras: Aura[] = []; + const pokemonId = pokemon.id; + const isPlayer = pokemon.isPlayer(); + auraType = auraType || 0; + for (let i = 0; i < this.auraList.length; i++) { + const auraTeam = this.auraList[i].team; + if (this.auraList[i].auraType === auraType || auraType === 0) { + if (this.auraList[i].target.includes(pokemonId) || this.auraList[i].target[0] === 0) { // the target[0] being 0 is our way of saying it's for all valid pokemon + if ((auraTeam === TeamTarget.ALL || auraTeam === TeamTarget.PLAYER) && isPlayer) { + allAuras.push(this.auraList[i]); + continue; + } + if ((auraTeam === TeamTarget.ALL || auraTeam === TeamTarget.ENEMY) && !isPlayer) { + allAuras.push(this.auraList[i]); + continue; + } + } + } + } + return allAuras; + } + + UpdateStats(pokemon: PlayerPokemon | EnemyPokemon) { + const pokemonAuras = this.FindAurasByPokemon(pokemon); + const pokemonSummonData = pokemon.summonData ? pokemon.summonData : pokemon.getPrimeSummonData(); + if (pokemonAuras.length > 0) { + for (const i = 0; i < pokemonSummonData.battleStats.length; i++) { + const mysteryStatAura = pokemonAuras.filter(aura => aura.auraType === auraStatMap[i]); + const totalStatChange = mysteryStatAura.reduce((accumulator, current) => accumulator + current.auraStrength, 0); + pokemonSummonData.battleStats[i] += mysteryStatAura.length > 0 ? totalStatChange : 0; + } + } + pokemon.updateInfo(); } } @@ -65,11 +106,11 @@ export class Aura { public target: number[]; // this can be used to target specific pokemon (using an array of pokemon ID) or all pokemon (using [-1]) public auraStrength: number; // this is the amount boosted/reduced - can be positive or negative public duration: number; // this is how many waves the aura lasts for; use a number > 0 for timed auras, or -1 for auras for the rest of the game - public auraType: string; // this is the aura type - for now, for example, what stat will be changed - public team: number; // this is the team. I think this will eventually be an enum - something like Team.PLAYER, Team.ENEMY, Team.ALL to target the player, enemy or everyone respectively. + public auraType: number; // this is the aura type - for now, for example, what stat will be changed + public team: number; // this is the team using the team enum of Team.PLAYER, Team.ENEMY, Team.ALL to target the player, enemy or everyone respectively. public timeUntilActive: number; // this will be the amount of waves until an aura is active; for example, a positive aura being activated when a negative one runs out. - constructor(target: number[], auraStrength: number, duration: number, auraType: string, team: number, timeUntilActive: number) { + constructor(target: number[], auraStrength: number, duration: number, auraType: number, team: number, timeUntilActive: number) { this.target = target; this.auraStrength = auraStrength; this.duration = duration; @@ -80,21 +121,21 @@ export class Aura { } export enum TeamTarget { + ENEMY = -1, ALL, - PLAYER, - ENEMY + PLAYER } export enum AuraType { INCOME, MONEY, ATK, - SPATK, DEF, + SPATK, SPDEF, - SPD, - EVA, ACC, + EVA, + SPD, LUCK, XP, CANDY, @@ -133,3 +174,5 @@ export function getAuraName(aura: AuraType) { return "???"; } } + +export const auraStatMap = [AuraType.ATK, AuraType.DEF, AuraType.SPATK, AuraType.SPDEF, AuraType.ACC, AuraType.EVA, AuraType.SPD]; diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 081199310844..b725c613730b 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -2632,6 +2632,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.summonDataPrimer = summonDataPrimer; } + getPrimeSummonData(): PokemonSummonData { + return this.summonDataPrimer; + } + resetSummonData(): void { if (this.summonData?.speciesForm) { this.summonData.speciesForm = null; diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 364e2442fd26..95c058b08a60 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -27,7 +27,7 @@ import { BattlerTagType } from "#enums/battler-tag-type"; import { BerryType } from "#enums/berry-type"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import { getAuraName, AuraType } from "#app/data/mystery-encounters/mystery-encounter-data"; +import { AuraType } from "#app/data/mystery-encounters/mystery-encounter-data"; const outputModifierData = false; const useMaxWeightForOutput = false; @@ -2089,10 +2089,10 @@ export class ModifierTypeOption { } export function getPartyLuckValue(party: Pokemon[]): integer { - const mysteryLuckAura = party[0].scene.mysteryEncounterAuras.FindAura(getAuraName(AuraType.LUCK)); + const mysteryLuckAura = party[0].scene.mysteryEncounterAuras.FindAura(AuraType.LUCK); let auraLuck = 0; if (mysteryLuckAura.length > 0) { - const auraTotalLuck = party[0].scene.mysteryEncounterAuras.FindAuraTotals(getAuraName(AuraType.LUCK)); + const auraTotalLuck = party[0].scene.mysteryEncounterAuras.FindAuraTotals(AuraType.LUCK); if (auraTotalLuck === 0.5) { /// this means that there are luck related auras, but the luck is forcibly being set to 0, so we need to return 0 here return 0; } diff --git a/src/phases.ts b/src/phases.ts index cd889a11c5b4..d4b44e9ff122 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -975,6 +975,13 @@ export class EncounterPhase extends BattlePhase { } const enemyField = this.scene.getEnemyField(); + const playerField = this.scene.getPlayerField(); + for (const i = 0; i < enemyField.length; i++) { + this.scene.mysteryEncounterAuras.UpdateStats(enemyField[i]); + } + for (const i = 0; i < playerField.length; i++) { + this.scene.mysteryEncounterAuras.UpdateStats(playerField[i]); + } this.scene.tweens.add({ targets: [this.scene.arenaEnemy, this.scene.currentBattle.trainer, enemyField, this.scene.currentBattle?.mysteryEncounter?.introVisuals, this.scene.arenaPlayer, this.scene.trainer].flat(), x: (_target, _key, value, fieldIndex: integer) => fieldIndex < 3 + (enemyField.length) ? value + 300 : value - 300, From 92c7ec44128a5479c814e509afbab8b301d03f63 Mon Sep 17 00:00:00 2001 From: Opaque02 <66582645+Opaque02@users.noreply.github.com> Date: Wed, 17 Jul 2024 20:46:36 +1000 Subject: [PATCH 07/12] Changed inkay to misdreavus --- .../encounters/choice-of-balance-encounter.ts | 33 +++++++++++++++++-- .../mystery-encounter-data.ts | 2 +- src/locales/en/mystery-encounter.ts | 20 +++++------ src/phases.ts | 4 +-- 4 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts b/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts index 008a1878ea06..04884ba07a50 100644 --- a/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts +++ b/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts @@ -39,13 +39,40 @@ export const ChoiceOfBalanceEncounter: IMysteryEncounter = MysteryEncounterBuild .withEncounterTier(MysteryEncounterTier.GREAT) .withIntroSpriteConfigs([ { - spriteKey: "686", + spriteKey: "200", fileRoot: "pokemon", hasShadow: true, x: 4, - y: 8, - scale: 2.5, + y: -16, + scale: 1, disableAnimation: true // Re-enabled after option select + }, + { + spriteKey: "amulet_coin", + fileRoot: "items", + hasShadow: true, + x: 35, + y: -3, + scale: 0.75, + isItem: true, + }, + { + spriteKey: "cracked_pot", + fileRoot: "items", + hasShadow: true, + x: 20, + y: -14, + scale: 0.75, + isItem: true, + }, + { + spriteKey: "griseous_core", + fileRoot: "items", + hasShadow: true, + x: -6, + y: -1, + scale: 0.75, + isItem: true, } ]) .withHideIntroVisuals(false) diff --git a/src/data/mystery-encounters/mystery-encounter-data.ts b/src/data/mystery-encounters/mystery-encounter-data.ts index e3fe69f426d1..120ad9b8d016 100644 --- a/src/data/mystery-encounters/mystery-encounter-data.ts +++ b/src/data/mystery-encounters/mystery-encounter-data.ts @@ -92,7 +92,7 @@ export class MysteryEncounterAuras { const pokemonAuras = this.FindAurasByPokemon(pokemon); const pokemonSummonData = pokemon.summonData ? pokemon.summonData : pokemon.getPrimeSummonData(); if (pokemonAuras.length > 0) { - for (const i = 0; i < pokemonSummonData.battleStats.length; i++) { + for (let i = 0; i < pokemonSummonData.battleStats.length; i++) { const mysteryStatAura = pokemonAuras.filter(aura => aura.auraType === auraStatMap[i]); const totalStatChange = mysteryStatAura.reduce((accumulator, current) => accumulator + current.auraStrength, 0); pokemonSummonData.battleStats[i] += mysteryStatAura.length > 0 ? totalStatChange : 0; diff --git a/src/locales/en/mystery-encounter.ts b/src/locales/en/mystery-encounter.ts index d65385e42a42..e1aa64189b50 100644 --- a/src/locales/en/mystery-encounter.ts +++ b/src/locales/en/mystery-encounter.ts @@ -37,11 +37,11 @@ export const mysteryEncounter: SimpleTranslationEntries = { $Your {{pokeName}} jumps in front of you\nbut is KOed in the process.`, "choice_of_balance_intro_message": `You feel a strange pull in a certain direction. - $Heading towards it, you see a weird glow in the distance. - $It's an...@d{64} Inkay?! You accidentally make\nsome noise and scare it off... - $...but not before dazzling you with its flashing spots!`, + $Heading towards it, you hear some weird sounds in the distance. + $It's a...@d{64} Misdreavus?! It locks eyes with you and seems to smirk at you. + $It moves aside, and you see some items nearby - Misdreavus wants you to take one!`, "choice_of_balance_title": "The Choice of Balance", - "choice_of_balance_description": "You've been inked by inkay and feel a little woozy. You can't really tell what's good and what's not?", + "choice_of_balance_description": "Misdreavus wants you to take one of their items. You can feel from here that while they hold great power, they're slighly cursed. You can tell the curse will wear off shortly", "choice_of_balance_query": "What will you choose?", "choice_of_balance_option_1_label": "Option A", "choice_of_balance_option_1_tooltip": "@[SUMMARY_BLUE]{(35%) Something terrible}\n@[SUMMARY_GREEN]{(40%) Okay Rewards}\n@[SUMMARY_GREEN]{(20%) Good Rewards}\n@[SUMMARY_GREEN]{(4%) Great Rewards}\n@[SUMMARY_GREEN]{(1%) Amazing Rewards}", @@ -56,17 +56,17 @@ export const mysteryEncounter: SimpleTranslationEntries = { "choice_of_balance_negative_luck": "Set luck to", "choice_of_balance_negative_player_stats": "Reduce $t(choice_of_balance_negativePlayerSTAT) by", "choice_of_balance_negative_enemy_stats": "Increase enemy $t(choice_of_balance_negativeEnemySTAT) by", - "choice_of_balance_negative_negativePlayerSTAT": "{{negativePlayerSTAT}}", - "choice_of_balance_negative_negativeEnemySTAT": "{{negativeEnemySTAT}}", + "choice_of_balance_negativePlayerSTAT": "{{negativePlayerSTAT}}", + "choice_of_balance_negativeEnemySTAT": "{{negativeEnemySTAT}}", "choice_of_balance_negative_add_pokemon": "Unable to add pokemon", "choice_of_balance_negative_damage_to_player": "Increase DMG taken by", "choice_of_balance_negative_no_reroll": "No shop rerolls", "choice_of_balance_positive_income": "Increase income by", "choice_of_balance_positive_luck": "Increase luck by", - "choice_of_balance_positive_player_stats": "Increase $t(choice_of_balance_positive_positivePlayerSTAT) by", - "choice_of_balance_positive_enemy_stats": "Reduce enemy $t(choice_of_balance_positive_positiveEnemySTAT) by", - "choice_of_balance_positive_positivePlayerSTAT": "{{positivePlayerSTAT}}", - "choice_of_balance_positive_positiveEnemySTAT": "{{positiveEnemySTAT}}", + "choice_of_balance_positive_player_stats": "Increase $t(choice_of_balance_positivePlayerSTAT) by", + "choice_of_balance_positive_enemy_stats": "Reduce enemy $t(choice_of_balance_positiveEnemySTAT) by", + "choice_of_balance_positivePlayerSTAT": "{{positivePlayerSTAT}}", + "choice_of_balance_positiveEnemySTAT": "{{positiveEnemySTAT}}", "choice_of_balance_positive_pp_chance": "Reduce PP usage chance", "choice_of_balance_positive_instant_money": "Gain money", "choice_of_balance_positive_instant_candy": "Gain a rarer candy", diff --git a/src/phases.ts b/src/phases.ts index d4b44e9ff122..53a74edc32c1 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -976,10 +976,10 @@ export class EncounterPhase extends BattlePhase { const enemyField = this.scene.getEnemyField(); const playerField = this.scene.getPlayerField(); - for (const i = 0; i < enemyField.length; i++) { + for (let i = 0; i < enemyField.length; i++) { this.scene.mysteryEncounterAuras.UpdateStats(enemyField[i]); } - for (const i = 0; i < playerField.length; i++) { + for (let i = 0; i < playerField.length; i++) { this.scene.mysteryEncounterAuras.UpdateStats(playerField[i]); } this.scene.tweens.add({ From f1ea6b2d6bb44814bc28d6476cf4c02a14718fc1 Mon Sep 17 00:00:00 2001 From: Opaque02 <66582645+Opaque02@users.noreply.github.com> Date: Wed, 17 Jul 2024 23:13:39 +1000 Subject: [PATCH 08/12] Fixed text nesting issues --- .../encounters/choice-of-balance-encounter.ts | 49 ++++++++++--------- .../mystery-encounter-data.ts | 23 +++++++-- src/locales/en/mystery-encounter.ts | 36 ++++++-------- src/phases.ts | 2 +- 4 files changed, 62 insertions(+), 48 deletions(-) diff --git a/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts b/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts index 04884ba07a50..d64eb39373fc 100644 --- a/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts +++ b/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts @@ -19,7 +19,7 @@ import IMysteryEncounter, { MysteryEncounterTier, } from "../mystery-encounter"; import { EncounterOptionMode, MysteryEncounterOptionBuilder } from "../mystery-encounter-option"; -import { Aura, AuraType, getAuraName } from "#app/data/mystery-encounters/mystery-encounter-data"; +import { Aura, AuraType, getAuraName, auraStatMap } from "#app/data/mystery-encounters/mystery-encounter-data"; const namespace = "mysteryEncounter:choice_of_balance"; @@ -87,7 +87,7 @@ export const ChoiceOfBalanceEncounter: IMysteryEncounter = MysteryEncounterBuild encounter.misc = []; console.log(encounter); - const options = 2 + randSeedInt(2); // this makes a random number between 2 and 3 for the options + const options = 3; const rewardsArray = generateRewards(options); @@ -113,11 +113,7 @@ export const ChoiceOfBalanceEncounter: IMysteryEncounter = MysteryEncounterBuild encounter.setDialogueToken("dynamic1", rewardsArray[0].generateMessage()); encounter.setDialogueToken("dynamic2", rewardsArray[1].generateMessage()); - if (options === 3) { - encounter.setDialogueToken("dynamic3", rewardsArray[2].generateMessage()); - } else if (options === 2 && encounter.options.length === 3) { - encounter.options.pop(); - } + encounter.setDialogueToken("dynamic3", rewardsArray[2].generateMessage()); return true; }) @@ -132,7 +128,7 @@ export const ChoiceOfBalanceEncounter: IMysteryEncounter = MysteryEncounterBuild buttonTooltip: `${ namespace }_dynamic_option_1`, selected: [ { - text: `${namespace}_option_1_selected_message`, + text: `${namespace}_option_selected_message`, }, ], }) @@ -150,7 +146,7 @@ export const ChoiceOfBalanceEncounter: IMysteryEncounter = MysteryEncounterBuild buttonTooltip: `${namespace}_dynamic_option_2`, selected: [ { - text: `${namespace}_option_2_selected_message`, + text: `${namespace}_option_selected_message`, }, ], }, @@ -165,7 +161,22 @@ export const ChoiceOfBalanceEncounter: IMysteryEncounter = MysteryEncounterBuild buttonTooltip: `${namespace}_dynamic_option_3`, selected: [ { - text: `${namespace}_option_3_selected_message`, + text: `${namespace}_option_selected_message`, + }, + ], + }, + async (scene: BattleScene) => { + // Leave encounter with no rewards or exp + leaveEncounterWithoutBattle(scene, true); + return true; + }) + .withSimpleOption( + { + buttonLabel: `${namespace}_option_4_label`, + buttonTooltip: `${namespace}_option_4_description`, + selected: [ + { + text: `${namespace}_option_leave_selected_message`, }, ], }, @@ -181,8 +192,7 @@ export enum NegativeRewards { LUCK, PLAYER_STATS, ENEMY_STATS, - ADD_POKEMON, - DAMAGE_TO_PLAYER, + PP, NO_REROLL } @@ -267,7 +277,7 @@ export class RewardOption { switch (type) { // These are for percentages case NegativeRewards.INCOME: - case NegativeRewards.DAMAGE_TO_PLAYER: + case NegativeRewards.PP: case PositiveRewards.INCOME: case PositiveRewards.PP: newStrength = String(Math.abs(strength * 100)) + "%"; @@ -282,7 +292,6 @@ export class RewardOption { newStrength = String(Math.abs(strength)); break; // These are for exceptions that don't have a strength - case NegativeRewards.ADD_POKEMON: case NegativeRewards.NO_REROLL: case PositiveRewards.INSTANT_CANDY: newStrength = ""; @@ -334,7 +343,6 @@ export class RewardOption { } convertRewardsToAura(reward: number): number { - const statArray = [AuraType.ATK, AuraType.SPATK, AuraType.DEF, AuraType.SPDEF, AuraType.SPD, AuraType.EVA, AuraType.ACC]; switch (reward) { case NegativeRewards.INCOME: return AuraType.INCOME; @@ -342,9 +350,7 @@ export class RewardOption { return AuraType.LUCK; case NegativeRewards.PLAYER_STATS: case NegativeRewards.ENEMY_STATS: - return statArray[this.negativeStat]; - case NegativeRewards.ADD_POKEMON: - case NegativeRewards.DAMAGE_TO_PLAYER: + return auraStatMap[this.negativeStat]; case NegativeRewards.NO_REROLL: return -1; case PositiveRewards.INCOME: @@ -353,7 +359,7 @@ export class RewardOption { return AuraType.LUCK; case PositiveRewards.PLAYER_STATS: case PositiveRewards.ENEMY_STATS: - return statArray[this.positiveStat]; + return auraStatMap[this.positiveStat]; case PositiveRewards.PP: return AuraType.PP; case PositiveRewards.INSTANT_MONEY: @@ -369,14 +375,13 @@ const statMessageIndex: [index: number, dialogueName: string, auraStrength: numb [NegativeRewards.LUCK, "negative_luck", 0, 15], [NegativeRewards.PLAYER_STATS, "negative_player_stats", -1, 10], [NegativeRewards.ENEMY_STATS, "negative_enemy_stats", 1, 8], - [NegativeRewards.ADD_POKEMON, "negative_add_pokemon", 0, 15], - [NegativeRewards.DAMAGE_TO_PLAYER, "negative_damage_to_player", 0.1, 5], [NegativeRewards.NO_REROLL, "negative_no_reroll", 0, 7], + [NegativeRewards.PP, "negative_pp_chance", -0.1, 10], [PositiveRewards.INCOME, "positive_income", 0.7, -1], [PositiveRewards.LUCK, "positive_luck", 5, -1], [PositiveRewards.PLAYER_STATS, "positive_player_stats", 1, 13], [PositiveRewards.ENEMY_STATS, "positive_enemy_stats", -1, 12], [PositiveRewards.PP, "positive_pp_chance", 0.2, 40], [PositiveRewards.INSTANT_MONEY, "positive_instant_money", 5000, 0], - [PositiveRewards.INSTANT_CANDY, "positive_instant_candy", 0, 0] + [PositiveRewards.INSTANT_CANDY, "positive_instant_candy", 0, 0], ]; diff --git a/src/data/mystery-encounters/mystery-encounter-data.ts b/src/data/mystery-encounters/mystery-encounter-data.ts index 120ad9b8d016..4ea8a500c12d 100644 --- a/src/data/mystery-encounters/mystery-encounter-data.ts +++ b/src/data/mystery-encounters/mystery-encounter-data.ts @@ -3,6 +3,7 @@ import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT } from "#app/data/mystery-encounters/mystery-encounters"; import { isNullOrUndefined } from "#app/utils"; import { EnemyPokemon, PlayerPokemon } from "field/pokemon"; +import BattleScene from "../../battle-scene"; export class MysteryEncounterData { encounteredEvents: [MysteryEncounterType, MysteryEncounterTier][] = []; @@ -27,17 +28,20 @@ export class MysteryEncounterAuras { this.auraList.push(new Aura(target, auraStrength, duration, auraType, team, timeUntilActive)); } - UpdateAurasDurations() { + UpdateAurasDurations(scene: BattleScene) { for (let i = 0; i < this.auraList.length; i++) { if (this.auraList[i].timeUntilActive !== 0) { this.auraList[i].timeUntilActive -= 1; } else { if (this.auraList[i].duration > 0) { this.auraList[i].duration -= 1; // may need to add a thing here so that if the aura is an instant aura to make it activate instead of dropping off straight away + if (this.auraList[i].isInstant() && this.auraList[i].duration === 0 && this.auraList[i].timeUntilActive === 0) { + this.TriggerInstantAura(this.auraList[i], scene); + } } } } - this.auraList = this.auraList.filter(aura => aura.duration !== 0); + this.auraList = this.auraList.filter(aura => aura.duration !== 0 && aura.timeUntilActive !== 0); } /* this method will find all auras of a certain type and add up their total strengths. @@ -100,6 +104,12 @@ export class MysteryEncounterAuras { } pokemon.updateInfo(); } + + TriggerInstantAura(aura: Aura, scene: BattleScene) { + if (aura.auraType === AuraType.MONEY) { + scene.addMoney(aura.auraStrength); + } + } } export class Aura { @@ -118,6 +128,10 @@ export class Aura { this.team = team; this.timeUntilActive = timeUntilActive; } + + isInstant() { + return this.auraType === AuraType.MONEY || this.auraType === AuraType.CANDY; + } } export enum TeamTarget { @@ -139,7 +153,8 @@ export enum AuraType { LUCK, XP, CANDY, - PP + PP, + PASSIVE } export function getAuraName(aura: AuraType) { @@ -170,6 +185,8 @@ export function getAuraName(aura: AuraType) { return "CANDY"; case AuraType.PP: return "PP"; + case AuraType.PASSIVE: + return "PASSIVE"; default: return "???"; } diff --git a/src/locales/en/mystery-encounter.ts b/src/locales/en/mystery-encounter.ts index e1aa64189b50..7b5c12ec4452 100644 --- a/src/locales/en/mystery-encounter.ts +++ b/src/locales/en/mystery-encounter.ts @@ -44,44 +44,36 @@ export const mysteryEncounter: SimpleTranslationEntries = { "choice_of_balance_description": "Misdreavus wants you to take one of their items. You can feel from here that while they hold great power, they're slighly cursed. You can tell the curse will wear off shortly", "choice_of_balance_query": "What will you choose?", "choice_of_balance_option_1_label": "Option A", - "choice_of_balance_option_1_tooltip": "@[SUMMARY_BLUE]{(35%) Something terrible}\n@[SUMMARY_GREEN]{(40%) Okay Rewards}\n@[SUMMARY_GREEN]{(20%) Good Rewards}\n@[SUMMARY_GREEN]{(4%) Great Rewards}\n@[SUMMARY_GREEN]{(1%) Amazing Rewards}", - "choice_of_balance_dynamic_option_1": "{{dynamic1}}", + "choice_of_balance_dynamic_option_1": "$t({{dynamic1}})", "choice_of_balance_option_2_label": "Option B", "choice_of_balance_option_2_tooltip": "(-) No Rewards", - "choice_of_balance_dynamic_option_2": "{{dynamic2}}", + "choice_of_balance_dynamic_option_2": "$t({{dynamic2}})", "choice_of_balance_option_3_label": "Option C", - "choice_of_balance_dynamic_option_3": "{{dynamic3}}", + "choice_of_balance_dynamic_option_3": "$t({{dynamic3}})", + "choice_of_balance_option_4_label": "Leave", + "choice_of_balance_option_4_description": "No rewards", "choice_of_balance_option_selected_message": "You hope you've made the right decision...", + "choice_of_balance_option_leave_selected_message": "You decide to leave - you don't want to risk taking something too cursed", "choice_of_balance_negative_income": "Reduce income by", "choice_of_balance_negative_luck": "Set luck to", - "choice_of_balance_negative_player_stats": "Reduce $t(choice_of_balance_negativePlayerSTAT) by", - "choice_of_balance_negative_enemy_stats": "Increase enemy $t(choice_of_balance_negativeEnemySTAT) by", - "choice_of_balance_negativePlayerSTAT": "{{negativePlayerSTAT}}", - "choice_of_balance_negativeEnemySTAT": "{{negativeEnemySTAT}}", + "choice_of_balance_negative_player_stats": "Reduce {{negativePlayerSTAT}} by", + "choice_of_balance_negative_enemy_stats": "Increase enemy {{negativeEnemySTAT}} by", + "choice_of_balance_negative_pp_chance": "Increase PP usage chance by", "choice_of_balance_negative_add_pokemon": "Unable to add pokemon", "choice_of_balance_negative_damage_to_player": "Increase DMG taken by", "choice_of_balance_negative_no_reroll": "No shop rerolls", "choice_of_balance_positive_income": "Increase income by", "choice_of_balance_positive_luck": "Increase luck by", - "choice_of_balance_positive_player_stats": "Increase $t(choice_of_balance_positivePlayerSTAT) by", - "choice_of_balance_positive_enemy_stats": "Reduce enemy $t(choice_of_balance_positiveEnemySTAT) by", - "choice_of_balance_positivePlayerSTAT": "{{positivePlayerSTAT}}", - "choice_of_balance_positiveEnemySTAT": "{{positiveEnemySTAT}}", - "choice_of_balance_positive_pp_chance": "Reduce PP usage chance", + "choice_of_balance_positive_player_stats": "Increase {{positivePlayerSTAT}} by", + "choice_of_balance_positive_enemy_stats": "Reduce enemy {{positiveEnemySTAT}} by", + "choice_of_balance_positive_pp_chance": "Reduce PP usage chance by", "choice_of_balance_positive_instant_money": "Gain money", "choice_of_balance_positive_instant_candy": "Gain a rarer candy", - "choice_of_balance_then": "THEN:", + "choice_of_balance_then": "After this effect:", "choice_of_balance_for": "for", - "choice_of_balance_waves": "waves", + "choice_of_balance_waves": "waves\\n", "choice_of_balance_rest_of_run": "for the rest of this run", "choice_of_balance_instantly": "instantly", - //"choice_of_balance_option_2_selected_message": "You hurry along your way,\nwith a slight feeling of regret.", - //"choice_of_balance_option_1_normal_result": "Just some normal tools and items.", - //"choice_of_balance_option_1_good_result": "Some pretty nice tools and items.", - //"choice_of_balance_option_1_great_result": "A couple great tools and items!", - //"choice_of_balance_option_1_amazing_result": "Whoa! An amazing item!", - //"choice_of_balance_option_1_bad_result": `Oh no!@d{32}\nThe chest was trapped! - //$Your @ec{pokeName} jumps in front of you\nbut is KOed in the process.`, "fight_or_flight_intro_message": "Something shiny is sparkling\non the ground near that Pokémon!", "fight_or_flight_title": "Fight or Flight", diff --git a/src/phases.ts b/src/phases.ts index 53a74edc32c1..574d53402839 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2683,7 +2683,7 @@ export class BattleEndPhase extends BattlePhase { } } - this.scene.mysteryEncounterAuras.UpdateAurasDurations(); + this.scene.mysteryEncounterAuras.UpdateAurasDurations(this.scene); this.scene.updateModifiers().then(() => this.end()); } From dfbc12947e6649c8b97480cc77d4666b53f05197 Mon Sep 17 00:00:00 2001 From: Opaque02 <66582645+Opaque02@users.noreply.github.com> Date: Thu, 18 Jul 2024 21:27:28 +1000 Subject: [PATCH 09/12] Added the ability for ME rewards to give you auras, and the start of modifiers --- .../encounters/choice-of-balance-encounter.ts | 6 +++++ .../mystery-encounter-data.ts | 17 +++++++----- src/modifier/modifier-type.ts | 18 ++++++++++++- src/modifier/modifier.ts | 26 +++++++++++++++++++ 4 files changed, 60 insertions(+), 7 deletions(-) diff --git a/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts b/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts index d64eb39373fc..7d79c9fc55ba 100644 --- a/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts +++ b/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts @@ -135,6 +135,8 @@ export const ChoiceOfBalanceEncounter: IMysteryEncounter = MysteryEncounterBuild .withOptionPhase(async (scene: BattleScene) => { // Leave encounter with no rewards or exp //[const negativeAura, const positiveAura] + scene.mysteryEncounterAuras.AddAura(scene.currentBattle.mysteryEncounter.misc[0].negativeAura); + scene.mysteryEncounterAuras.AddAura(scene.currentBattle.mysteryEncounter.misc[0].positiveAura); leaveEncounterWithoutBattle(scene, true); return true; }) @@ -152,6 +154,8 @@ export const ChoiceOfBalanceEncounter: IMysteryEncounter = MysteryEncounterBuild }, async (scene: BattleScene) => { // Leave encounter with no rewards or exp + scene.mysteryEncounterAuras.AddAura(scene.currentBattle.mysteryEncounter.misc[1].negativeAura); + scene.mysteryEncounterAuras.AddAura(scene.currentBattle.mysteryEncounter.misc[1].positiveAura); leaveEncounterWithoutBattle(scene, true); return true; }) @@ -167,6 +171,8 @@ export const ChoiceOfBalanceEncounter: IMysteryEncounter = MysteryEncounterBuild }, async (scene: BattleScene) => { // Leave encounter with no rewards or exp + scene.mysteryEncounterAuras.AddAura(scene.currentBattle.mysteryEncounter.misc[2].negativeAura); + scene.mysteryEncounterAuras.AddAura(scene.currentBattle.mysteryEncounter.misc[2].positiveAura); leaveEncounterWithoutBattle(scene, true); return true; }) diff --git a/src/data/mystery-encounters/mystery-encounter-data.ts b/src/data/mystery-encounters/mystery-encounter-data.ts index 4ea8a500c12d..3ef8f5488365 100644 --- a/src/data/mystery-encounters/mystery-encounter-data.ts +++ b/src/data/mystery-encounters/mystery-encounter-data.ts @@ -24,24 +24,29 @@ export class MysteryEncounterAuras { this.auraList = []; } - AddAura(target: number[], auraStrength: number, duration: number, auraType: number, team: number, timeUntilActive: number = 0) { - this.auraList.push(new Aura(target, auraStrength, duration, auraType, team, timeUntilActive)); + + //AddAura(targetOrAura: number[] | Aura, auraStrength: number, duration: number, auraType: number, team: number, timeUntilActive: number = 0) { + // this.auraList.push(new Aura(targetOrAura, auraStrength, duration, auraType, team, timeUntilActive)); + //} + + AddAura(aura: Aura) { + this.auraList.push(aura); } UpdateAurasDurations(scene: BattleScene) { for (let i = 0; i < this.auraList.length; i++) { if (this.auraList[i].timeUntilActive !== 0) { - this.auraList[i].timeUntilActive -= 1; + this.auraList[i].timeUntilActive -= 1; // removes a turn from the timeUntilActive } else { if (this.auraList[i].duration > 0) { - this.auraList[i].duration -= 1; // may need to add a thing here so that if the aura is an instant aura to make it activate instead of dropping off straight away - if (this.auraList[i].isInstant() && this.auraList[i].duration === 0 && this.auraList[i].timeUntilActive === 0) { + this.auraList[i].duration -= 1; // removes a counter from the duration + if (this.auraList[i].isInstant() && this.auraList[i].duration === 0 && this.auraList[i].timeUntilActive === 0) { // this checks if the aura is an instant effect this.TriggerInstantAura(this.auraList[i], scene); } } } } - this.auraList = this.auraList.filter(aura => aura.duration !== 0 && aura.timeUntilActive !== 0); + this.auraList = this.auraList.filter(aura => aura.duration !== 0 && aura.timeUntilActive !== 0); // this updates our list to make sure to only have things that are peristent or still counting down } /* this method will find all auras of a certain type and add up their total strengths. diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 95c058b08a60..8ac203b1a6c0 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -27,7 +27,7 @@ import { BattlerTagType } from "#enums/battler-tag-type"; import { BerryType } from "#enums/berry-type"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import { AuraType } from "#app/data/mystery-encounters/mystery-encounter-data"; +import { Aura, AuraType } from "#app/data/mystery-encounters/mystery-encounter-data"; const outputModifierData = false; const useMaxWeightForOutput = false; @@ -413,6 +413,20 @@ export class RememberMoveModifierType extends PokemonModifierType { } } +export class AuraModifierType extends ModifierType { + private myAuraData: any; + + constructor(localeKey: string, iconImage: string, myAuraData?: Aura) { + super(localeKey, iconImage, () => new Modifiers.AuraModifier(this, myAuraData)); + + this.myAuraData = myAuraData; + } + + getDescription(scene: BattleScene): string { + return i18next.t("modifierType:ModifierType.AugmentModifierType.description", { myAuraData: this.myAuraData }); + } +} + export class DoubleBattleChanceBoosterModifierType extends ModifierType { public battleCount: integer; @@ -1203,6 +1217,8 @@ export const modifierTypes = { SUPER_REPEL: () => new DoubleBattleChanceBoosterModifierType('Super Repel', 10), MAX_REPEL: () => new DoubleBattleChanceBoosterModifierType('Max Repel', 25),*/ + AURA_STAT: () => new AuraModifierType("aura_stat_EVA", "lucarionite"), + LURE: () => new DoubleBattleChanceBoosterModifierType("modifierType:ModifierType.LURE", "lure", 5), SUPER_LURE: () => new DoubleBattleChanceBoosterModifierType("modifierType:ModifierType.SUPER_LURE", "super_lure", 10), MAX_LURE: () => new DoubleBattleChanceBoosterModifierType("modifierType:ModifierType.MAX_LURE", "max_lure", 25), diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index 6f098ade124b..2eade154b07f 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -323,6 +323,32 @@ export abstract class LapsingPersistentModifier extends PersistentModifier { } } +export class AuraModifier extends LapsingPersistentModifier { + constructor(type: ModifierTypes.AuraModifierType, battlesLeft: number) { + super(type, battlesLeft); + } + + match(modifier: Modifier): boolean { + if (modifier instanceof AuraModifier) { + // Check type id to not match different tiers of lures + return modifier.type.id === this.type.id && modifier.battlesLeft === this.battlesLeft; + } + return false; + } + + clone(): AuraModifier { + return new AuraModifier(this.type as ModifierTypes.AuraModifierType, this.battlesLeft); + } + + getArgs(): any[] { + return [this.battlesLeft]; + } + + apply(args: any[]): boolean { + return true; + } +} + export class DoubleBattleChanceBoosterModifier extends LapsingPersistentModifier { constructor(type: ModifierTypes.DoubleBattleChanceBoosterModifierType, battlesLeft: integer, stackCount?: integer) { super(type, battlesLeft, stackCount); From bbc9497201f6d4e5bfbb6699c59e1ca46f4a8139 Mon Sep 17 00:00:00 2001 From: Opaque02 <66582645+Opaque02@users.noreply.github.com> Date: Thu, 18 Jul 2024 21:49:51 +1000 Subject: [PATCH 10/12] Fixed bad merge --- .../encounters/choice-of-balance-encounter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts b/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts index 7d79c9fc55ba..3844ad75f074 100644 --- a/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts +++ b/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts @@ -6,7 +6,7 @@ // setEncounterRewards, // showEncounterText, //} from "#app/data/mystery-encounters/mystery-encounter-utils"; -import { leaveEncounterWithoutBattle } from "#app/data/mystery-encounters/mystery-encounter-utils"; +import { leaveEncounterWithoutBattle } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; //import { mysteryEncounter } from "#app/locales/en/mystery-encounter"; //import { ModifierTier } from "#app/modifier/modifier-tier"; //import { GameOverPhase } from "#app/phases"; From 018c2905b2dc5944560a2e716063cb96f91e4e8f Mon Sep 17 00:00:00 2001 From: Opaque02 <66582645+Opaque02@users.noreply.github.com> Date: Sat, 20 Jul 2024 12:33:12 +1000 Subject: [PATCH 11/12] Updated dialogue to be more user readable --- .../encounters/choice-of-balance-encounter.ts | 64 +++++++++---------- src/locales/en/mystery-encounter.ts | 15 ++--- src/plugins/i18n.ts | 7 ++ 3 files changed, 45 insertions(+), 41 deletions(-) diff --git a/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts b/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts index 3844ad75f074..146cb1fb14d3 100644 --- a/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts +++ b/src/data/mystery-encounters/encounters/choice-of-balance-encounter.ts @@ -1,4 +1,4 @@ -//import { +//import { // getHighestLevelPlayerPokemon, // koPlayerPokemon, // leaveEncounterWithoutBattle, @@ -125,7 +125,7 @@ export const ChoiceOfBalanceEncounter: IMysteryEncounter = MysteryEncounterBuild .withOptionMode(EncounterOptionMode.DEFAULT) .withDialogue({ buttonLabel: `${namespace}_option_1_label`, - buttonTooltip: `${ namespace }_dynamic_option_1`, + buttonTooltip: `${ namespace }_dynamic_tooltip_1`, selected: [ { text: `${namespace}_option_selected_message`, @@ -145,7 +145,7 @@ export const ChoiceOfBalanceEncounter: IMysteryEncounter = MysteryEncounterBuild .withSimpleOption( { buttonLabel: `${namespace}_option_2_label`, - buttonTooltip: `${namespace}_dynamic_option_2`, + buttonTooltip: `${namespace}_dynamic_tooltip_2`, selected: [ { text: `${namespace}_option_selected_message`, @@ -162,7 +162,7 @@ export const ChoiceOfBalanceEncounter: IMysteryEncounter = MysteryEncounterBuild .withSimpleOption( { buttonLabel: `${namespace}_option_3_label`, - buttonTooltip: `${namespace}_dynamic_option_3`, + buttonTooltip: `${namespace}_dynamic_tooltip_3`, selected: [ { text: `${namespace}_option_selected_message`, @@ -252,23 +252,33 @@ export class RewardOption { generateMessage(): string { const [negativeType, negativeText, negativeStrength, negativeDuration] = this.getRewardInfo(this.negativeOption); const [positiveType, positiveText, positiveStrength, positiveDuration] = this.getRewardInfo(this.positiveOption); - const outputMessage: string[] = []; - outputMessage.push(this.getDescriptorText(negativeText)); - if (this.formattedStrengths(negativeType, negativeStrength) !== "") { - outputMessage.push(this.formattedStrengths(negativeType, negativeStrength)); - } - outputMessage.push(this.getDescriptorText("for")); - outputMessage.push(this.formattedWaves(negativeDuration)); - outputMessage.push(this.getDescriptorText("then")); - outputMessage.push(this.getDescriptorText(positiveText)); - if (this.formattedStrengths(positiveType, positiveStrength) !== "") { - outputMessage.push(this.formattedStrengths(positiveType, positiveStrength)); + let outputMessage: string; + + const formattedNegativeStrength = this.formattedStrengths(negativeType, negativeStrength); + const formattedPositiveStrength = this.formattedStrengths(positiveType, positiveStrength); + if (negativeDuration > 0) { + // this is a normal reward; the output message uses {{description}}, {{strength}} and {{duration}} to describe a reward + outputMessage = i18next.t("mysteryEncounter:choice_of_balance_text_template_normal", { descriptor: this.getDescriptorText(negativeText), strength: formattedNegativeStrength !== "" ? " " + formattedNegativeStrength : "", duration: negativeDuration }); + } else if (negativeDuration === 0) { + // this is an instant reward; the output message uses {{description}} and {{strength}} to describe a reward + outputMessage = i18next.t("mysteryEncounter:choice_of_balance_text_template_instant", { descriptor: this.getDescriptorText(negativeText), strength: formattedNegativeStrength !== "" ? " " + formattedNegativeStrength : "" }); + } else if (negativeDuration < 0) { + // this is a reward that lasts the rest of the run; the output message uses {{description}} and {{strength}} to describe a reward + outputMessage = i18next.t("mysteryEncounter:choice_of_balance_text_template_permanent", { descriptor: this.getDescriptorText(negativeText), strength: formattedNegativeStrength !== "" ? " " + formattedNegativeStrength : "" }); } - if (positiveDuration !== 0) { - outputMessage.push(this.getDescriptorText("for")); + outputMessage += " " + i18next.t(this.getDescriptorText("then")) + " "; + + if (positiveDuration > 0) { + // this is a normal reward; the output message uses {{description}}, {{strength}} and {{duration}} to describe a reward + outputMessage += i18next.t("mysteryEncounter:choice_of_balance_text_template_normal", { descriptor: this.getDescriptorText(positiveText), strength: formattedPositiveStrength !== "" ? " " + formattedPositiveStrength : "", duration: positiveDuration }); + } else if (positiveDuration === 0) { + // this is an instant reward; the output message uses {{description}} and {{strength}} to describe a reward + outputMessage += i18next.t("mysteryEncounter:choice_of_balance_text_template_instant", { descriptor: this.getDescriptorText(positiveText), strength: formattedPositiveStrength !== "" ? " " + formattedPositiveStrength : "" }); + } else if (positiveDuration < 0) { + // this is a reward that lasts the rest of the run; the output message uses {{description}} and {{strength}} to describe a reward + outputMessage += i18next.t("mysteryEncounter:choice_of_balance_text_template_permanent", { descriptor: this.getDescriptorText(positiveText), strength: formattedPositiveStrength !== "" ? " " + formattedPositiveStrength : "" }); } - outputMessage.push(this.formattedWaves(positiveDuration)); - return outputMessage.join(" "); + return outputMessage;//.join(" "); } getRewardInfo(reward: number): [index: number, dialogueName: string, auraStrength: number, auraDuration: number] { @@ -286,7 +296,7 @@ export class RewardOption { case NegativeRewards.PP: case PositiveRewards.INCOME: case PositiveRewards.PP: - newStrength = String(Math.abs(strength * 100)) + "%"; + newStrength = i18next.t("{{percentageValue, percent}}", { percentageValue: strength }); break; // These are for single numbers (i.e. stat stage increase/decrease, luck increase/decrease etc) case NegativeRewards.LUCK: @@ -304,7 +314,7 @@ export class RewardOption { break; // These are for money rewards case PositiveRewards.INSTANT_MONEY: - newStrength = "$" + String(strength); + newStrength = i18next.t("{{moneyValue, money}}", { moneyValue: strength }); break; default: console.log("Missing formattedStrengths!!!"); @@ -314,18 +324,6 @@ export class RewardOption { return newStrength; } - private formattedWaves(duration: number): string { - let waveDuration: string; - if (duration < 0) { - waveDuration = this.getDescriptorText("rest_of_run"); - } else if (duration === 0) { - waveDuration = this.getDescriptorText("instantly"); - } else if (duration > 0) { - waveDuration = String(duration) + " " + this.getDescriptorText("waves"); - } - return waveDuration; - } - private getDescriptorText(text: string) { return i18next.t(namespace + "_" + text); } diff --git a/src/locales/en/mystery-encounter.ts b/src/locales/en/mystery-encounter.ts index c9be2b9576c7..70019c3ebb29 100644 --- a/src/locales/en/mystery-encounter.ts +++ b/src/locales/en/mystery-encounter.ts @@ -48,16 +48,19 @@ export const mysteryEncounter = { "choice_of_balance_description": "Misdreavus wants you to take one of their items. You can feel from here that while they hold great power, they're slighly cursed. You can tell the curse will wear off shortly", "choice_of_balance_query": "What will you choose?", "choice_of_balance_option_1_label": "Option A", - "choice_of_balance_dynamic_option_1": "$t({{dynamic1}})", + "choice_of_balance_dynamic_tooltip_1": "$t({{dynamic1}})", "choice_of_balance_option_2_label": "Option B", "choice_of_balance_option_2_tooltip": "(-) No Rewards", - "choice_of_balance_dynamic_option_2": "$t({{dynamic2}})", + "choice_of_balance_dynamic_tooltip_2": "$t({{dynamic2}})", "choice_of_balance_option_3_label": "Option C", - "choice_of_balance_dynamic_option_3": "$t({{dynamic3}})", + "choice_of_balance_dynamic_tooltip_3": "$t({{dynamic3}})", "choice_of_balance_option_4_label": "Leave", "choice_of_balance_option_4_description": "No rewards", "choice_of_balance_option_selected_message": "You hope you've made the right decision...", "choice_of_balance_option_leave_selected_message": "You decide to leave - you don't want to risk taking something too cursed", + "choice_of_balance_text_template_normal": "{{descriptor}}{{strength}} for {{duration}} waves.", + "choice_of_balance_text_template_instant": "{{descriptor}}{{strength}} instantly", + "choice_of_balance_text_template_permanent": "{{descriptor}}{{strength}} for the rest of this run", "choice_of_balance_negative_income": "Reduce income by", "choice_of_balance_negative_luck": "Set luck to", "choice_of_balance_negative_player_stats": "Reduce {{negativePlayerSTAT}} by", @@ -71,13 +74,9 @@ export const mysteryEncounter = { "choice_of_balance_positive_player_stats": "Increase {{positivePlayerSTAT}} by", "choice_of_balance_positive_enemy_stats": "Reduce enemy {{positiveEnemySTAT}} by", "choice_of_balance_positive_pp_chance": "Reduce PP usage chance by", - "choice_of_balance_positive_instant_money": "Gain money", + "choice_of_balance_positive_instant_money": "Gain", "choice_of_balance_positive_instant_candy": "Gain a rarer candy", "choice_of_balance_then": "After this effect:", - "choice_of_balance_for": "for", - "choice_of_balance_waves": "waves\\n", - "choice_of_balance_rest_of_run": "for the rest of this run", - "choice_of_balance_instantly": "instantly", "fight_or_flight_intro_message": "Something shiny is sparkling\non the ground near that Pokémon!", "fight_or_flight_title": "Fight or Flight", diff --git a/src/plugins/i18n.ts b/src/plugins/i18n.ts index 1b4bfdbb16a5..08010e44c397 100644 --- a/src/plugins/i18n.ts +++ b/src/plugins/i18n.ts @@ -144,6 +144,13 @@ export async function initI18n(): Promise { return `@[MONEY]{₽${numberFormattedString}}`; }); + // Input: {{percentageValue, percent}} - this will be a percentage as a decimal - i.e. 0.2 + // Output: {20%} + i18next.services.formatter.add("percent", (value, lng, options) => { + const percentFormattedString = Intl.NumberFormat(lng, options).format(Math.abs(value) * 100); + return `${percentFormattedString}%`; + }); + await initFonts(); } From c825f1ffa735a9f2c86e7826b0a9d76f25d91f5e Mon Sep 17 00:00:00 2001 From: Opaque02 <66582645+Opaque02@users.noreply.github.com> Date: Mon, 12 Aug 2024 11:55:59 +1000 Subject: [PATCH 12/12] Final push with attemps at modifiers before starting new branch --- .../mystery-encounter-data.ts | 30 +++++- src/modifier/modifier-type.ts | 21 +++- src/modifier/modifier.ts | 102 +++++++++++++++--- src/overrides.ts | 2 +- 4 files changed, 137 insertions(+), 18 deletions(-) diff --git a/src/data/mystery-encounters/mystery-encounter-data.ts b/src/data/mystery-encounters/mystery-encounter-data.ts index 3ef8f5488365..da635e00caaa 100644 --- a/src/data/mystery-encounters/mystery-encounter-data.ts +++ b/src/data/mystery-encounters/mystery-encounter-data.ts @@ -4,6 +4,7 @@ import { BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT } from "#app/data/mystery-encounter import { isNullOrUndefined } from "#app/utils"; import { EnemyPokemon, PlayerPokemon } from "field/pokemon"; import BattleScene from "../../battle-scene"; +import { TempBattleStat } from "#app/data/temp-battle-stat"; export class MysteryEncounterData { encounteredEvents: [MysteryEncounterType, MysteryEncounterTier][] = []; @@ -159,7 +160,8 @@ export enum AuraType { XP, CANDY, PP, - PASSIVE + PASSIVE, + CRIT } export function getAuraName(aura: AuraType) { @@ -192,9 +194,35 @@ export function getAuraName(aura: AuraType) { return "PP"; case AuraType.PASSIVE: return "PASSIVE"; + case AuraType.CRIT: + return "CRIT"; default: return "???"; } } +export function ConvertAuraToBattleStat(auraType: AuraType): Number { + switch (auraType) { + case AuraType.ATK: + return TempBattleStat.ATK; + case AuraType.DEF: + return TempBattleStat.DEF; + case AuraType.SPATK: + return TempBattleStat.SPATK; + case AuraType.SPDEF: + return TempBattleStat.SPDEF; + case AuraType.ACC: + return TempBattleStat.ACC; + case AuraType.EVA: + return -1; + case AuraType.SPD: + return TempBattleStat.SPD; + case AuraType.CRIT: + return TempBattleStat.CRIT; + default: + return -1; + } +} + export const auraStatMap = [AuraType.ATK, AuraType.DEF, AuraType.SPATK, AuraType.SPDEF, AuraType.ACC, AuraType.EVA, AuraType.SPD]; + diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 8ac203b1a6c0..a3f8f7516916 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -413,11 +413,24 @@ export class RememberMoveModifierType extends PokemonModifierType { } } -export class AuraModifierType extends ModifierType { - private myAuraData: any; +export class LapsingAuraModifierType extends ModifierType { + private myAuraData: Aura; constructor(localeKey: string, iconImage: string, myAuraData?: Aura) { - super(localeKey, iconImage, () => new Modifiers.AuraModifier(this, myAuraData)); + super(localeKey, iconImage, () => new Modifiers.LapsingAuraModifier(this, myAuraData)); + this.myAuraData = myAuraData; + } + + getDescription(scene: BattleScene): string { + return i18next.t("modifierType:ModifierType.AugmentModifierType.description", { myAuraData: this.myAuraData }); + } +} + +export class PersistentAuraModifierType extends ModifierType { + private myAuraData: Aura; + + constructor(localeKey: string, iconImage: string, myAuraData?: Aura) { + super(localeKey, iconImage, () => new Modifiers.PersistentAuraModifier(this, myAuraData)); this.myAuraData = myAuraData; } @@ -1217,7 +1230,7 @@ export const modifierTypes = { SUPER_REPEL: () => new DoubleBattleChanceBoosterModifierType('Super Repel', 10), MAX_REPEL: () => new DoubleBattleChanceBoosterModifierType('Max Repel', 25),*/ - AURA_STAT: () => new AuraModifierType("aura_stat_EVA", "lucarionite"), + AURA_STAT: () => new LapsingAuraModifierType("aura_stat_EVA", "lucarionite"), LURE: () => new DoubleBattleChanceBoosterModifierType("modifierType:ModifierType.LURE", "lure", 5), SUPER_LURE: () => new DoubleBattleChanceBoosterModifierType("modifierType:ModifierType.SUPER_LURE", "super_lure", 10), diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index 2eade154b07f..ba2ee70ab1f9 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -28,6 +28,7 @@ import i18next from "i18next"; import { allMoves } from "#app/data/move.js"; import { Abilities } from "#app/enums/abilities.js"; +import { Aura, AuraType, ConvertAuraToBattleStat } from "#app/data/mystery-encounters/mystery-encounter-data"; export type ModifierPredicate = (modifier: Modifier) => boolean; @@ -323,30 +324,107 @@ export abstract class LapsingPersistentModifier extends PersistentModifier { } } -export class AuraModifier extends LapsingPersistentModifier { - constructor(type: ModifierTypes.AuraModifierType, battlesLeft: number) { - super(type, battlesLeft); +export class LapsingAuraModifier extends LapsingPersistentModifier { + private aura: Aura; + + constructor(type: ModifierTypes.LapsingAuraModifierType, aura: Aura) { + super(type, aura.duration); + this.aura = aura; } - match(modifier: Modifier): boolean { - if (modifier instanceof AuraModifier) { - // Check type id to not match different tiers of lures - return modifier.type.id === this.type.id && modifier.battlesLeft === this.battlesLeft; + clone(): LapsingAuraModifier { + return new LapsingAuraModifier(this.type as ModifierTypes.LapsingAuraModifierType, this.aura); + } + + getArgs(): any[] { + return [this.aura]; + } + + lapse(): boolean { + + return true; + } + + shouldApply(args: any[]): boolean { + return true; + } + + apply(args: any[]): boolean { // args[0] will be an aura + const aura = args[0] as Aura; + //if (pokemon) { // this is for pokemon specific auras + switch (aura.auraType) { + case AuraType.ATK: + case AuraType.DEF: + case AuraType.SPATK: + case AuraType.SPDEF: + case AuraType.ACC: + case AuraType.EVA: // need to deal with EVA since there's no temp version of it + case AuraType.SPD: + case AuraType.CRIT: + const tempBattleStat = args[0] as TempBattleStat; + const auraType = ConvertAuraToBattleStat(this.aura.auraType); + if (auraType >= 0) { + if (tempBattleStat === auraType as TempBattleStat) { + const currentStatLevel = args[1] as Utils.IntegerHolder; + currentStatLevel.value = Math.min(currentStatLevel.value + aura.auraStrength, 6); + return true; + } + + return false; + } + break; + case AuraType.XP: + // do XP stuff + break; + case AuraType.PP: + // do PP stuff + break; + case AuraType.PASSIVE: + //do passive stuff + break; } - return false; + //} + //else { // this is for player/team specific auras + switch (aura.auraType) { + case AuraType.INCOME: + // do income stuff + break; + case AuraType.MONEY: + // do instant money stuff + break; + case AuraType.LUCK: + // do luck stuff + break; + case AuraType.XP: + // do XP stuff + break; + case AuraType.CANDY: + // do instant candy stuff + break; + } + //} + + return true; + } +} - clone(): AuraModifier { - return new AuraModifier(this.type as ModifierTypes.AuraModifierType, this.battlesLeft); +export class PersistentAuraModifier extends PersistentModifier { + constructor(type: ModifierType, stackCount?: number) { + super(type, stackCount); } - getArgs(): any[] { - return [this.battlesLeft]; + clone(): PersistentAuraModifier { + return new PersistentAuraModifier(this.type, this.stackCount); } apply(args: any[]): boolean { return true; } + + getMaxStackCount(): number { // auras don't stack + return 1; + } } export class DoubleBattleChanceBoosterModifier extends LapsingPersistentModifier { diff --git a/src/overrides.ts b/src/overrides.ts index e6bed4930ff2..dca1d47937ce 100644 --- a/src/overrides.ts +++ b/src/overrides.ts @@ -117,7 +117,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_RATE_OVERRIDE: number = 0; export const MYSTERY_ENCOUNTER_TIER_OVERRIDE: MysteryEncounterTier = null; export const MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType = MysteryEncounterType.CHOICE_OF_BALANCE;