diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 1c5656f92d2..2088b945838 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -129,6 +129,7 @@ export default class BattleScene extends SceneBase { public doBiomePanels: boolean = false; public disableDailyShinies: boolean = true; // Disables shiny luck in Daily Runs to prevent affecting RNG public quickloadDisplayMode: string = "Dailies"; + public chaosmode: boolean = false; /** * Determines the condition for a notification should be shown for Candy Upgrades * - 0 = 'Off' diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index 2b488f330c4..c848b9c7785 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -28,7 +28,7 @@ export enum Region { PALDEA } -export function getPokemonSpecies(species: Species): PokemonSpecies { +export function getPokemonSpecies(species: any): PokemonSpecies { // If a special pool (named trainers) is used here it CAN happen that they have a array as species (which means choose one of those two). So we catch that with this code block if (Array.isArray(species)) { // Pick a random species from the list diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 99ff0bd633f..227521b9f05 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -134,6 +134,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { : (species.abilityHidden && hasHiddenAbility ? species.ability2 ? 2 : 1 : species.ability2 ? randAbilityIndex : 0); if (formIndex !== undefined) { this.formIndex = formIndex; + } else if (species.formIndex != undefined) { + this.formIndex = species.formIndex } if (gender !== undefined) { this.gender = gender; diff --git a/src/logger.ts b/src/logger.ts index 80a78a20c2d..c3c0d3d287b 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -759,7 +759,10 @@ export function getWave(drpd: DRPD, floor: integer, scene: BattleScene): Wave { } } if (wv == undefined) { - if (scene.gameMode.modeId != GameModes.DAILY) { + if (scene.gameMode.modeId != GameModes.DAILY || true) { + if (scene.gameMode.modeId == GameModes.DAILY) { + console.log(";-;") + } drpd.waves.push({ id: floor, reload: false, diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 09748ad4906..5f82d650ec1 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -11,7 +11,7 @@ import * as Utils from "../utils"; import { TempBattleStat, getTempBattleStatBoosterItemName, getTempBattleStatName } from "../data/temp-battle-stat"; import { getBerryEffectDescription, getBerryName } from "../data/berry"; import { Unlockables } from "../system/unlockables"; -import { StatusEffect, getStatusEffectDescriptor } from "../data/status-effect"; +import { Status, StatusEffect, getStatusEffectDescriptor } from "../data/status-effect"; import { SpeciesFormKey } from "../data/pokemon-species"; import BattleScene from "../battle-scene"; import { VoucherType, getVoucherTypeIcon, getVoucherTypeName } from "../system/voucher"; @@ -1978,40 +1978,115 @@ export function getPlayerModifierTypeOptions(count: integer, party: PlayerPokemo return options; } -export function getPlayerShopModifierTypeOptionsForWave(waveIndex: integer, baseCost: integer): ModifierTypeOption[] { +export function getPlayerShopModifierTypeOptionsForWave(scene: BattleScene, waveIndex: integer, baseCost: integer): ModifierTypeOption[] { if (!(waveIndex % 10)) { return []; } + var maxdmg = 0 + var maxdmg_percent = 0 + var hasStatus = false // A member of the party has a status condition (Full Heal, Full Restore) + var hasFainted = false // A member of the party has zero health (Revive, Max Revive) + var multiFainted = false // At least two Pokemon have zero health (Sacred Ash) + var hasPPUsed = false // At least one Pokemon has used at least 1 PP (Ether) + var hasPPUsedOver10 = false // At least one Pokemon has used more than 10 PP on a single move (Max Ether, Max Elexir) + var hasPPUsedMulti = false // At least one Pokemon has used at least 1 PP on multiple moves (Elexir, Max Elexir) + var party = scene.getParty() + party.forEach(p => { + maxdmg = Math.max(maxdmg, p.getMaxHp() - p.hp) + maxdmg_percent = Math.max(maxdmg_percent, 1 - (p.hp/p.getMaxHp())) + if (p.status) + switch (p.status.effect) { + case StatusEffect.NONE: + break; // No status effect + case StatusEffect.POISON: + case StatusEffect.TOXIC: + case StatusEffect.PARALYSIS: + case StatusEffect.SLEEP: + case StatusEffect.FREEZE: + case StatusEffect.BURN: + hasStatus = true; + break; + case StatusEffect.FAINT: + if (hasFainted) + multiFainted = true; + hasFainted = true; + break; + } + p.moveset.forEach(m => { + if (m.ppUsed > 0 && hasPPUsed) + hasPPUsedMulti = true + if (m.ppUsed > 0) + hasPPUsed = true + if (m.ppUsed >= 10) + hasPPUsedOver10 = true + }) + }) + const options = [ - [ - new ModifierTypeOption(modifierTypes.POTION(), 0, baseCost * 0.2), - new ModifierTypeOption(modifierTypes.ETHER(), 0, baseCost * 0.4), - new ModifierTypeOption(modifierTypes.REVIVE(), 0, baseCost * 2) + [ // 0 + //new ModifierTypeOption(modifierTypes.POTION(), 0, baseCost * 0.2), + //new ModifierTypeOption(modifierTypes.ETHER(), 0, baseCost * 0.4), + //new ModifierTypeOption(modifierTypes.REVIVE(), 0, baseCost * 2) ], - [ - new ModifierTypeOption(modifierTypes.SUPER_POTION(), 0, baseCost * 0.45), - new ModifierTypeOption(modifierTypes.FULL_HEAL(), 0, baseCost), + [ // 1 + //new ModifierTypeOption(modifierTypes.SUPER_POTION(), 0, baseCost * 0.45), + //new ModifierTypeOption(modifierTypes.FULL_HEAL(), 0, baseCost), ], - [ - new ModifierTypeOption(modifierTypes.ELIXIR(), 0, baseCost), - new ModifierTypeOption(modifierTypes.MAX_ETHER(), 0, baseCost) + [ // 2 + //new ModifierTypeOption(modifierTypes.ELIXIR(), 0, baseCost), + //new ModifierTypeOption(modifierTypes.MAX_ETHER(), 0, baseCost) ], - [ - new ModifierTypeOption(modifierTypes.HYPER_POTION(), 0, baseCost * 0.8), - new ModifierTypeOption(modifierTypes.MAX_REVIVE(), 0, baseCost * 2.75) + [ // 3 + //new ModifierTypeOption(modifierTypes.HYPER_POTION(), 0, baseCost * 0.8), + //new ModifierTypeOption(modifierTypes.MAX_REVIVE(), 0, baseCost * 2.75) ], - [ - new ModifierTypeOption(modifierTypes.MAX_POTION(), 0, baseCost * 1.5), - new ModifierTypeOption(modifierTypes.MAX_ELIXIR(), 0, baseCost * 2.5) + [ // 4 + //new ModifierTypeOption(modifierTypes.MAX_POTION(), 0, baseCost * 1.5), + //new ModifierTypeOption(modifierTypes.MAX_ELIXIR(), 0, baseCost * 2.5) ], - [ - new ModifierTypeOption(modifierTypes.FULL_RESTORE(), 0, baseCost * 2.25) + [ // 5 + //new ModifierTypeOption(modifierTypes.FULL_RESTORE(), 0, baseCost * 2.25) ], - [ - new ModifierTypeOption(modifierTypes.SACRED_ASH(), 0, baseCost * 10) + [ // 6 + //new ModifierTypeOption(modifierTypes.SACRED_ASH(), 0, baseCost * 10) ] ]; + // Assemble the shop by removing items that would just be a waste of money + + // HP Restore + if (maxdmg > 0) // If any Pokemon has taken any damage, add Potion + options[0].push(new ModifierTypeOption(modifierTypes.POTION(), 0, baseCost * 0.2)) + if (maxdmg >= 20 || maxdmg_percent >= 0.1) // If Potion isn't enough, add Super Potion + options[1].push(new ModifierTypeOption(modifierTypes.SUPER_POTION(), 0, baseCost * 0.45)) + if (maxdmg >= 50 || maxdmg_percent >= 0.2) // If Super Potion isn't enough, add Hyper Potion + options[3].push(new ModifierTypeOption(modifierTypes.HYPER_POTION(), 0, baseCost * 0.8)) + if (maxdmg >= 200 || maxdmg_percent >= 0.5) // If Hyper Potion isn't enough, add Max Potion + options[4].push(new ModifierTypeOption(modifierTypes.MAX_POTION(), 0, baseCost * 1.5)) + + // Status Restore + if ((maxdmg >= 200 || maxdmg_percent >= 0.5) && hasStatus) // If Hyper Potion isn't enough, and you have a status condition, add Full Restore + options[5].push(new ModifierTypeOption(modifierTypes.FULL_RESTORE(), 0, baseCost * 2.25)) + if (hasStatus) // If you have a status condition, add Full Heal + options[1].push(new ModifierTypeOption(modifierTypes.FULL_HEAL(), 0, baseCost)) + + // PP Restore + if (hasPPUsed) // If you have used any PP (you probably have), add Ether + options[0].push(new ModifierTypeOption(modifierTypes.ETHER(), 0, baseCost * 0.4)) + if (hasPPUsedOver10) // If you used at least 10 PP, add Max Ether + options[2].push(new ModifierTypeOption(modifierTypes.MAX_ETHER(), 0, baseCost)) + if (hasPPUsedMulti) // If you have used PP from multiple moves, add Elexir + options[2].push(new ModifierTypeOption(modifierTypes.ELIXIR(), 0, baseCost)) + if (hasPPUsedOver10 && hasPPUsedMulti) // If you have used multiple moves' PP, and have used more than 10 in at least one, add Max Elexir + options[4].push(new ModifierTypeOption(modifierTypes.MAX_ELIXIR(), 0, baseCost * 2.5)) + + // Revives + if (hasFainted) { // If a Pokemon has fainted, add Revive and Max Revive + options[0].push(new ModifierTypeOption(modifierTypes.REVIVE(), 0, baseCost * 2)) + options[3].push(new ModifierTypeOption(modifierTypes.MAX_REVIVE(), 0, baseCost * 2.75)) + } + if (multiFainted) // If multiple Pokemon are fainted, add Sacred Ash + options[6].push(new ModifierTypeOption(modifierTypes.SACRED_ASH(), 0, baseCost * 10)) return options.slice(0, Math.ceil(Math.max(waveIndex + 10, 0) / 30)).flat(); } diff --git a/src/phases.ts b/src/phases.ts index 3c60d3288bc..f835c7848ce 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -49,7 +49,7 @@ import { OptionSelectConfig, OptionSelectItem } from "./ui/abstact-option-select import { SaveSlotUiMode } from "./ui/save-slot-select-ui-handler"; import { fetchDailyRunSeed, getDailyRunStarters } from "./data/daily-run"; import { GameMode, GameModes, getGameMode } from "./game-mode"; -import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "./data/pokemon-species"; +import PokemonSpecies, { allSpecies, getPokemonSpecies, getPokemonSpeciesForm, speciesStarters } from "./data/pokemon-species"; import i18next from "./plugins/i18n"; import * as Overrides from "./overrides"; import { TextStyle, addTextObject } from "./ui/text"; @@ -613,7 +613,7 @@ export class TitlePhase extends Phase { } }) break; - case this.scene.quickloadDisplayMode == "Both" && ls2 != undefined: + case (this.scene.quickloadDisplayMode == "Both" || this.scene.quickloadDisplayMode == "On") && ls2 != undefined: ls2.forEach(lastsave2 => { options.push({ label: (lastsave2.description ? lastsave2.description : "[???]"), @@ -703,7 +703,6 @@ export class TitlePhase extends Phase { handler: () => { this.scene.biomeChangeMode = false //return this.logRenameMenu() - // this.scene.ui.setOverlayMode(Mode.LOG_HANDLER, (k: string) => { if (k === undefined) { @@ -715,7 +714,6 @@ export class TitlePhase extends Phase { this.showOptions(); }); return true; - // } }) options.push({ @@ -1398,11 +1396,40 @@ export class EncounterPhase extends BattlePhase { battle.enemyParty[e] = battle.trainer.genPartyMember(e); } else { LoggerTools.rarityslot[0] = e - const enemySpecies = this.scene.randomSpecies(battle.waveIndex, level, true); + var enemySpecies = this.scene.randomSpecies(battle.waveIndex, level, true); + if (this.scene.chaosmode) { + enemySpecies = getPokemonSpecies(allSpecies.map(p => p.speciesId)) + if (enemySpecies.forms.length > 0) { + enemySpecies.formIndex = Math.max(0, Math.floor(Math.random() * (enemySpecies.forms.length + 0)) - 0) + } + switch (this.scene.gameMode.modeId) { + case GameModes.CLASSIC: + case GameModes.CHALLENGE: + if (this.scene.currentBattle.waveIndex == 200) { + enemySpecies = getPokemonSpecies(Species.ETERNATUS) + enemySpecies.formIndex = 0 + } + break; + case GameModes.ENDLESS: + case GameModes.SPLICED_ENDLESS: + if (this.scene.currentBattle.waveIndex % 250 == 0) { + enemySpecies = getPokemonSpecies(Species.ETERNATUS) + enemySpecies.formIndex = 0 + if (this.scene.currentBattle.waveIndex % 1000 == 0) { + enemySpecies.formIndex = 1 + } + } + break; + case GameModes.DAILY: + // idk + break; + } + } battle.enemyParty[e] = this.scene.addEnemyPokemon(enemySpecies, level, TrainerSlot.NONE, !!this.scene.getEncounterBossSegments(battle.waveIndex, level, enemySpecies)); if (this.scene.currentBattle.battleSpec === BattleSpec.FINAL_BOSS) { battle.enemyParty[e].ivs = new Array(6).fill(31); } + //battle.enemyParty[e].formIndex = enemySpecies.formIndex this.scene.getParty().slice(0, !battle.double ? 1 : 2).reverse().forEach(playerPokemon => { applyAbAttrs(SyncEncounterNatureAbAttr, playerPokemon, null, battle.enemyParty[e]); }); @@ -6487,7 +6514,7 @@ export class SelectModifierPhase extends BattlePhase { modifierType = typeOptions[cursor].type; break; default: - const shopOptions = getPlayerShopModifierTypeOptionsForWave(this.scene.currentBattle.waveIndex, this.scene.getWaveMoneyAmount(1)); + const shopOptions = getPlayerShopModifierTypeOptionsForWave(this.scene, this.scene.currentBattle.waveIndex, this.scene.getWaveMoneyAmount(1)); const shopOption = shopOptions[rowCursor > 2 || shopOptions.length <= SHOP_OPTIONS_ROW_LIMIT ? cursor : cursor + SHOP_OPTIONS_ROW_LIMIT]; modifierType = shopOption.type; cost = shopOption.cost; diff --git a/src/ui/fight-ui-handler.ts b/src/ui/fight-ui-handler.ts index bc7cc0a15d0..26749827aff 100644 --- a/src/ui/fight-ui-handler.ts +++ b/src/ui/fight-ui-handler.ts @@ -671,6 +671,15 @@ export default class FightUiHandler extends UiHandler { } dmgLow = out[0] * minHits dmgHigh = out[1] * maxHits + var qSuffix = "" + if (target.isBoss()) { + var bossSegs = (target as EnemyPokemon).bossSegments + //dmgLow /= bossSegs + //dmgHigh /= bossSegs + //qSuffix = "?" + } + var dmgLowP = Math.round((dmgLow)/target.getBattleStat(Stat.HP)*100) + var dmgHighP = Math.round((dmgHigh)/target.getBattleStat(Stat.HP)*100) /* if (user.hasAbility(Abilities.PARENTAL_BOND)) { // Second hit deals 0.25x damage @@ -689,13 +698,11 @@ export default class FightUiHandler extends UiHandler { return "---" } if (scene.damageDisplay == "Value") - return target.getMoveEffectiveness(user, move) + "x - " + (Math.round(dmgLow) == Math.round(dmgHigh) ? Math.round(dmgLow).toString() : Math.round(dmgLow) + "-" + Math.round(dmgHigh)) + koText - dmgLow = Math.round((dmgLow)/target.getBattleStat(Stat.HP)*100) - dmgHigh = Math.round((dmgHigh)/target.getBattleStat(Stat.HP)*100) + return target.getMoveEffectiveness(user, move) + "x - " + (Math.round(dmgLow) == Math.round(dmgHigh) ? Math.round(dmgLow).toString() + qSuffix : Math.round(dmgLow) + "-" + Math.round(dmgHigh) + qSuffix) + koText if (scene.damageDisplay == "Percent") - return target.getMoveEffectiveness(user, move) + "x - " + (dmgLow == dmgHigh ? dmgLow + "%" : dmgLow + "%-" + dmgHigh + "%") + koText + return target.getMoveEffectiveness(user, move) + "x - " + (dmgLowP == dmgHighP ? dmgLowP + "%" + qSuffix : dmgLowP + "%-" + dmgHighP + "%" + qSuffix) + koText if (scene.damageDisplay == "Off") - return target.getMoveEffectiveness(user, move) + "x" + return target.getMoveEffectiveness(user, move) + "x" + ((Math.floor(dmgLow) >= target.hp) ? " (KO)" : "") } setCursor(cursor: integer): boolean { diff --git a/src/ui/log-select-ui-handler.ts b/src/ui/log-select-ui-handler.ts index 777d0d9cbd9..3c3890f12a6 100644 --- a/src/ui/log-select-ui-handler.ts +++ b/src/ui/log-select-ui-handler.ts @@ -121,6 +121,11 @@ export default class LogSelectUiHandler extends MessageUiHandler { } } else if (button === Button.CANCEL) { this.quitCallback(undefined); + } else if (button === Button.LEFT) { + this.scene.chaosmode = !this.scene.chaosmode + console.log("Toggled Chaos Mode " + (this.scene.chaosmode ? "ON" : "OFF")) + this.showText("Toggled Chaos Mode " + (this.scene.chaosmode ? "ON" : "OFF") + "\n(press LEFT to toggle)", undefined, () => {this.saveSlotSelectMessageBoxContainer.setVisible(false)}, 6000) + success = true } else { switch (button) { case Button.UP: @@ -310,7 +315,7 @@ class SessionSlot extends Phaser.GameObjects.Container { return; const iconContainer = this.scene.add.container(26 * i, 0); iconContainer.setScale(0.75); - console.log(p.id, Utils.getEnumKeys(Species)[Utils.getEnumValues(Species).indexOf(p.id)]) + //console.log(p.id, Utils.getEnumKeys(Species)[Utils.getEnumValues(Species).indexOf(p.id)], Utils.getEnumKeys(Species)[allSpecies[Utils.getEnumValues(Species).indexOf(p.id)].speciesId]) //if (Utils.getEnumValues(Species)[p.id] == undefined) //return; @@ -318,7 +323,7 @@ class SessionSlot extends Phaser.GameObjects.Container { //if (getPokemonSpecies(Utils.getEnumValues(Species)[p.id]) == undefined) //return; - const icon = this.scene.addPkIcon(allSpecies[Utils.getEnumValues(Species).indexOf(p.id)], 0, 0, 0, 0, 0); + const icon = this.scene.addPkIcon(getPokemonSpecies(Utils.getEnumValues(Species)[allSpecies[Utils.getEnumValues(Species).indexOf(p.id)].speciesId]), 0, 0, 0, 0, 0); const text = addTextObject(this.scene, 32, 20, ``, TextStyle.PARTY, { fontSize: "54px", color: "#f8f8f8" }); text.setShadow(0, 0, null); diff --git a/src/ui/modifier-select-ui-handler.ts b/src/ui/modifier-select-ui-handler.ts index 3cfd103b4e2..7097504f60d 100644 --- a/src/ui/modifier-select-ui-handler.ts +++ b/src/ui/modifier-select-ui-handler.ts @@ -36,6 +36,8 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { private cursorObj: Phaser.GameObjects.Image; + private tO: ModifierTypeOption[]; + constructor(scene: BattleScene) { super(scene, Mode.CONFIRM); @@ -158,8 +160,9 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { this.updateRerollCostText(); const typeOptions = args[1] as ModifierTypeOption[]; + this.tO = typeOptions const shopTypeOptions = !this.scene.gameMode.hasNoShop - ? getPlayerShopModifierTypeOptionsForWave(this.scene.currentBattle.waveIndex, this.scene.getWaveMoneyAmount(1)) + ? getPlayerShopModifierTypeOptionsForWave(this.scene, this.scene.currentBattle.waveIndex, this.scene.getWaveMoneyAmount(1)) : []; const optionsYOffset = shopTypeOptions.length >= SHOP_OPTIONS_ROW_LIMIT ? -8 : -24;