[Balance] Change IV Scanner to single stack (#5299)

* Make IV Scanner max stack 1

* Apply suggestions from code review

Co-authored-by: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com>

---------

Co-authored-by: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com>
Co-authored-by: damocleas <damocleas25@gmail.com>
This commit is contained in:
AJ Fontaine 2025-02-11 17:35:24 -05:00 committed by GitHub
parent 195a3936b3
commit 03011c4601
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 15 additions and 43 deletions

View File

@ -315,7 +315,7 @@ async function summonSafariPokemon() {
const ivScannerModifier = globalScene.findModifier(m => m instanceof IvScannerModifier); const ivScannerModifier = globalScene.findModifier(m => m instanceof IvScannerModifier);
if (ivScannerModifier) { if (ivScannerModifier) {
globalScene.pushPhase(new ScanIvsPhase(pokemon.getBattlerIndex(), Math.min(ivScannerModifier.getStackCount() * 2, 6))); globalScene.pushPhase(new ScanIvsPhase(pokemon.getBattlerIndex()));
} }
} }

View File

@ -165,9 +165,9 @@ export abstract class PersistentModifier extends Modifier {
public stackCount: number; public stackCount: number;
public virtualStackCount: number; public virtualStackCount: number;
constructor(type: ModifierType, stackCount?: number) { constructor(type: ModifierType, stackCount: number = 1) {
super(type); super(type);
this.stackCount = stackCount === undefined ? 1 : stackCount; this.stackCount = stackCount;
this.virtualStackCount = 0; this.virtualStackCount = 0;
} }
@ -3295,7 +3295,7 @@ export class ContactHeldItemTransferChanceModifier extends HeldItemTransferModif
export class IvScannerModifier extends PersistentModifier { export class IvScannerModifier extends PersistentModifier {
constructor(type: ModifierType, stackCount?: number) { constructor(type: ModifierType, stackCount?: number) {
super(type, stackCount); super(type);
} }
match(modifier: Modifier): boolean { match(modifier: Modifier): boolean {
@ -3303,7 +3303,7 @@ export class IvScannerModifier extends PersistentModifier {
} }
clone(): IvScannerModifier { clone(): IvScannerModifier {
return new IvScannerModifier(this.type, this.stackCount); return new IvScannerModifier(this.type);
} }
/** /**
@ -3311,11 +3311,11 @@ export class IvScannerModifier extends PersistentModifier {
* @returns always `true` * @returns always `true`
*/ */
override apply(): boolean { override apply(): boolean {
return true; return true; //Dude are you kidding me
} }
getMaxStackCount(): number { getMaxStackCount(): number {
return 3; return 1;
} }
} }

View File

@ -478,7 +478,7 @@ export class EncounterPhase extends BattlePhase {
})); }));
const ivScannerModifier = globalScene.findModifier(m => m instanceof IvScannerModifier); const ivScannerModifier = globalScene.findModifier(m => m instanceof IvScannerModifier);
if (ivScannerModifier) { if (ivScannerModifier) {
enemyField.map(p => globalScene.pushPhase(new ScanIvsPhase(p.getBattlerIndex(), Math.min(ivScannerModifier.getStackCount() * 2, 6)))); enemyField.map(p => globalScene.pushPhase(new ScanIvsPhase(p.getBattlerIndex())));
} }
} }

View File

@ -396,7 +396,7 @@ export class MysteryEncounterBattlePhase extends Phase {
if (encounterMode !== MysteryEncounterMode.TRAINER_BATTLE) { if (encounterMode !== MysteryEncounterMode.TRAINER_BATTLE) {
const ivScannerModifier = globalScene.findModifier(m => m instanceof IvScannerModifier); const ivScannerModifier = globalScene.findModifier(m => m instanceof IvScannerModifier);
if (ivScannerModifier) { if (ivScannerModifier) {
enemyField.map(p => globalScene.pushPhase(new ScanIvsPhase(p.getBattlerIndex(), Math.min(ivScannerModifier.getStackCount() * 2, 6)))); enemyField.map(p => globalScene.pushPhase(new ScanIvsPhase(p.getBattlerIndex())));
} }
} }

View File

@ -1,7 +1,6 @@
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import type { BattlerIndex } from "#app/battle"; import type { BattlerIndex } from "#app/battle";
import { CommonBattleAnim, CommonAnim } from "#app/data/battle-anims"; import { PERMANENT_STATS, Stat } from "#app/enums/stat";
import { Stat } from "#app/enums/stat";
import { getPokemonNameWithAffix } from "#app/messages"; import { getPokemonNameWithAffix } from "#app/messages";
import { getTextColor, TextStyle } from "#app/ui/text"; import { getTextColor, TextStyle } from "#app/ui/text";
import { Mode } from "#app/ui/ui"; import { Mode } from "#app/ui/ui";
@ -9,21 +8,14 @@ import i18next from "i18next";
import { PokemonPhase } from "./pokemon-phase"; import { PokemonPhase } from "./pokemon-phase";
export class ScanIvsPhase extends PokemonPhase { export class ScanIvsPhase extends PokemonPhase {
private shownIvs: number;
constructor(battlerIndex: BattlerIndex, shownIvs: number) { constructor(battlerIndex: BattlerIndex) {
super(battlerIndex); super(battlerIndex);
this.shownIvs = shownIvs;
} }
start() { start() {
super.start(); super.start();
if (!this.shownIvs) {
return this.end();
}
const pokemon = this.getPokemon(); const pokemon = this.getPokemon();
let enemyIvs: number[] = []; let enemyIvs: number[] = [];
@ -34,12 +26,11 @@ export class ScanIvsPhase extends PokemonPhase {
for (let e = 0; e < enemyField.length; e++) { for (let e = 0; e < enemyField.length; e++) {
enemyIvs = enemyField[e].ivs; enemyIvs = enemyField[e].ivs;
const currentIvs = globalScene.gameData.dexData[enemyField[e].species.getRootSpeciesId()].ivs; // we are using getRootSpeciesId() here because we want to check against the baby form, not the mid form if it exists const currentIvs = globalScene.gameData.dexData[enemyField[e].species.getRootSpeciesId()].ivs; // we are using getRootSpeciesId() here because we want to check against the baby form, not the mid form if it exists
const ivsToShow = globalScene.ui.getMessageHandler().getTopIvs(enemyIvs, this.shownIvs);
statsContainer = enemyField[e].getBattleInfo().getStatsValueContainer().list as Phaser.GameObjects.Sprite[]; statsContainer = enemyField[e].getBattleInfo().getStatsValueContainer().list as Phaser.GameObjects.Sprite[];
statsContainerLabels = statsContainer.filter(m => m.name.indexOf("icon_stat_label") >= 0); statsContainerLabels = statsContainer.filter(m => m.name.indexOf("icon_stat_label") >= 0);
for (let s = 0; s < statsContainerLabels.length; s++) { for (let s = 0; s < statsContainerLabels.length; s++) {
const ivStat = Stat[statsContainerLabels[s].frame.name]; const ivStat = Stat[statsContainerLabels[s].frame.name];
if (enemyIvs[ivStat] > currentIvs[ivStat] && ivsToShow.indexOf(Number(ivStat)) >= 0) { if (enemyIvs[ivStat] > currentIvs[ivStat] && PERMANENT_STATS.indexOf(Number(ivStat)) >= 0) {
const hexColour = enemyIvs[ivStat] === 31 ? getTextColor(TextStyle.PERFECT_IV, false, uiTheme) : getTextColor(TextStyle.SUMMARY_GREEN, false, uiTheme); const hexColour = enemyIvs[ivStat] === 31 ? getTextColor(TextStyle.PERFECT_IV, false, uiTheme) : getTextColor(TextStyle.SUMMARY_GREEN, false, uiTheme);
const hexTextColour = Phaser.Display.Color.HexStringToColor(hexColour).color; const hexTextColour = Phaser.Display.Color.HexStringToColor(hexColour).color;
statsContainerLabels[s].setTint(hexTextColour); statsContainerLabels[s].setTint(hexTextColour);
@ -53,9 +44,7 @@ export class ScanIvsPhase extends PokemonPhase {
globalScene.ui.setMode(Mode.CONFIRM, () => { globalScene.ui.setMode(Mode.CONFIRM, () => {
globalScene.ui.setMode(Mode.MESSAGE); globalScene.ui.setMode(Mode.MESSAGE);
globalScene.ui.clearText(); globalScene.ui.clearText();
new CommonBattleAnim(CommonAnim.LOCK_ON, pokemon, pokemon).play(false, () => { globalScene.ui.getMessageHandler().promptIvs(pokemon.id, pokemon.ivs).then(() => this.end());
globalScene.ui.getMessageHandler().promptIvs(pokemon.id, pokemon.ivs, this.shownIvs).then(() => this.end());
});
}, () => { }, () => {
globalScene.ui.setMode(Mode.MESSAGE); globalScene.ui.setMode(Mode.MESSAGE);
globalScene.ui.clearText(); globalScene.ui.clearText();

View File

@ -6,7 +6,6 @@ import { addWindow } from "./ui-theme";
import type BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext"; import type BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext";
import { Button } from "#enums/buttons"; import { Button } from "#enums/buttons";
import i18next from "i18next"; import i18next from "i18next";
import type { Stat } from "#app/enums/stat";
import { PERMANENT_STATS, getStatKey } from "#app/enums/stat"; import { PERMANENT_STATS, getStatKey } from "#app/enums/stat";
export default class BattleMessageUiHandler extends MessageUiHandler { export default class BattleMessageUiHandler extends MessageUiHandler {
@ -191,13 +190,12 @@ export default class BattleMessageUiHandler extends MessageUiHandler {
}); });
} }
promptIvs(pokemonId: number, ivs: number[], shownIvsCount: number): Promise<void> { promptIvs(pokemonId: number, ivs: number[]): Promise<void> {
return new Promise(resolve => { return new Promise(resolve => {
globalScene.executeWithSeedOffset(() => { globalScene.executeWithSeedOffset(() => {
let levelUpStatsValuesText = ""; let levelUpStatsValuesText = "";
const shownStats = this.getTopIvs(ivs, shownIvsCount);
for (const s of PERMANENT_STATS) { for (const s of PERMANENT_STATS) {
levelUpStatsValuesText += `${shownStats.includes(s) ? this.getIvDescriptor(ivs[s], s, pokemonId) : "???"}\n`; levelUpStatsValuesText += `${this.getIvDescriptor(ivs[s], s, pokemonId)}\n`;
} }
this.levelUpStatsValuesContent.text = levelUpStatsValuesText; this.levelUpStatsValuesContent.text = levelUpStatsValuesText;
this.levelUpStatsIncrContent.setVisible(false); this.levelUpStatsIncrContent.setVisible(false);
@ -211,21 +209,6 @@ export default class BattleMessageUiHandler extends MessageUiHandler {
}); });
} }
getTopIvs(ivs: number[], shownIvsCount: number): Stat[] {
let shownStats: Stat[] = [];
if (shownIvsCount < 6) {
const statsPool = PERMANENT_STATS.slice();
// Sort the stats from highest to lowest iv
statsPool.sort((s1, s2) => ivs[s2] - ivs[s1]);
for (let i = 0; i < shownIvsCount; i++) {
shownStats.push(statsPool[i]);
}
} else {
shownStats = PERMANENT_STATS.slice();
}
return shownStats;
}
getIvDescriptor(value: number, typeIv: number, pokemonId: number): string { getIvDescriptor(value: number, typeIv: number, pokemonId: number): string {
const starterSpecies = globalScene.getPokemonById(pokemonId)!.species.getRootSpeciesId(); // we are using getRootSpeciesId() here because we want to check against the baby form, not the mid form if it exists const starterSpecies = globalScene.getPokemonById(pokemonId)!.species.getRootSpeciesId(); // we are using getRootSpeciesId() here because we want to check against the baby form, not the mid form if it exists
const starterIvs: number[] = globalScene.gameData.dexData[starterSpecies].ivs; const starterIvs: number[] = globalScene.gameData.dexData[starterSpecies].ivs;