[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);
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 virtualStackCount: number;
constructor(type: ModifierType, stackCount?: number) {
constructor(type: ModifierType, stackCount: number = 1) {
super(type);
this.stackCount = stackCount === undefined ? 1 : stackCount;
this.stackCount = stackCount;
this.virtualStackCount = 0;
}
@ -3295,7 +3295,7 @@ export class ContactHeldItemTransferChanceModifier extends HeldItemTransferModif
export class IvScannerModifier extends PersistentModifier {
constructor(type: ModifierType, stackCount?: number) {
super(type, stackCount);
super(type);
}
match(modifier: Modifier): boolean {
@ -3303,7 +3303,7 @@ export class IvScannerModifier extends PersistentModifier {
}
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`
*/
override apply(): boolean {
return true;
return true; //Dude are you kidding me
}
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);
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) {
const ivScannerModifier = globalScene.findModifier(m => m instanceof 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 type { BattlerIndex } from "#app/battle";
import { CommonBattleAnim, CommonAnim } from "#app/data/battle-anims";
import { Stat } from "#app/enums/stat";
import { PERMANENT_STATS, Stat } from "#app/enums/stat";
import { getPokemonNameWithAffix } from "#app/messages";
import { getTextColor, TextStyle } from "#app/ui/text";
import { Mode } from "#app/ui/ui";
@ -9,21 +8,14 @@ import i18next from "i18next";
import { PokemonPhase } from "./pokemon-phase";
export class ScanIvsPhase extends PokemonPhase {
private shownIvs: number;
constructor(battlerIndex: BattlerIndex, shownIvs: number) {
constructor(battlerIndex: BattlerIndex) {
super(battlerIndex);
this.shownIvs = shownIvs;
}
start() {
super.start();
if (!this.shownIvs) {
return this.end();
}
const pokemon = this.getPokemon();
let enemyIvs: number[] = [];
@ -34,12 +26,11 @@ export class ScanIvsPhase extends PokemonPhase {
for (let e = 0; e < enemyField.length; e++) {
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 ivsToShow = globalScene.ui.getMessageHandler().getTopIvs(enemyIvs, this.shownIvs);
statsContainer = enemyField[e].getBattleInfo().getStatsValueContainer().list as Phaser.GameObjects.Sprite[];
statsContainerLabels = statsContainer.filter(m => m.name.indexOf("icon_stat_label") >= 0);
for (let s = 0; s < statsContainerLabels.length; s++) {
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 hexTextColour = Phaser.Display.Color.HexStringToColor(hexColour).color;
statsContainerLabels[s].setTint(hexTextColour);
@ -53,9 +44,7 @@ export class ScanIvsPhase extends PokemonPhase {
globalScene.ui.setMode(Mode.CONFIRM, () => {
globalScene.ui.setMode(Mode.MESSAGE);
globalScene.ui.clearText();
new CommonBattleAnim(CommonAnim.LOCK_ON, pokemon, pokemon).play(false, () => {
globalScene.ui.getMessageHandler().promptIvs(pokemon.id, pokemon.ivs, this.shownIvs).then(() => this.end());
});
globalScene.ui.getMessageHandler().promptIvs(pokemon.id, pokemon.ivs).then(() => this.end());
}, () => {
globalScene.ui.setMode(Mode.MESSAGE);
globalScene.ui.clearText();

View File

@ -6,7 +6,6 @@ import { addWindow } from "./ui-theme";
import type BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext";
import { Button } from "#enums/buttons";
import i18next from "i18next";
import type { Stat } from "#app/enums/stat";
import { PERMANENT_STATS, getStatKey } from "#app/enums/stat";
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 => {
globalScene.executeWithSeedOffset(() => {
let levelUpStatsValuesText = "";
const shownStats = this.getTopIvs(ivs, shownIvsCount);
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.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 {
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;