Add IV Scanner item

This commit is contained in:
Flashfyre 2023-11-12 12:49:06 -05:00
parent fcd62209ba
commit 9f17273d87
11 changed files with 4235 additions and 36 deletions

2
.gitignore vendored
View File

@ -24,3 +24,5 @@ dist-ssr
*.sw? *.sw?
public/images/trainer/convert/* public/images/trainer/convert/*
src/data/battle-anim-raw-data.ts
src/data/battle-anim-data.ts

View File

@ -23,6 +23,8 @@
- Valuable items for money - Valuable items for money
- Trainers - Trainers
- Finish party pools - Finish party pools
- Add dialogue
- Add reward for gym leader victories
- Encounters - Encounters
- Add extremely rare chance of Arceus available anywhere with type change - Add extremely rare chance of Arceus available anywhere with type change
- Balancing - Balancing

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@ import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMov
import { Mode } from './ui/ui'; import { Mode } from './ui/ui';
import { Command } from "./ui/command-ui-handler"; import { Command } from "./ui/command-ui-handler";
import { Stat } from "./data/pokemon-stat"; import { Stat } from "./data/pokemon-stat";
import { BerryModifier, ContactHeldItemTransferChanceModifier, EnemyAttackStatusEffectChanceModifier, EnemyInstantReviveChanceModifier, EnemyPersistentModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, FusePokemonModifier, HealingBoosterModifier, HitHealModifier, LapsingPersistentModifier, MapModifier, Modifier, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, SwitchEffectTransferModifier, TempBattleStatBoosterModifier, TurnHealModifier, TurnHeldItemTransferModifier, MoneyMultiplierModifier, MoneyInterestModifier } from "./modifier/modifier"; import { BerryModifier, ContactHeldItemTransferChanceModifier, EnemyAttackStatusEffectChanceModifier, EnemyInstantReviveChanceModifier, EnemyPersistentModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, FusePokemonModifier, HealingBoosterModifier, HitHealModifier, LapsingPersistentModifier, MapModifier, Modifier, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, SwitchEffectTransferModifier, TempBattleStatBoosterModifier, TurnHealModifier, TurnHeldItemTransferModifier, MoneyMultiplierModifier, MoneyInterestModifier, IvScannerModifier } from "./modifier/modifier";
import PartyUiHandler, { PartyOption, PartyUiMode } from "./ui/party-ui-handler"; import PartyUiHandler, { PartyOption, PartyUiMode } from "./ui/party-ui-handler";
import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./data/pokeball"; import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./data/pokeball";
import { CommonAnim, CommonBattleAnim, MoveAnim, initMoveAnim, loadMoveAnimAssets } from "./data/battle-anims"; import { CommonAnim, CommonBattleAnim, MoveAnim, initMoveAnim, loadMoveAnimAssets } from "./data/battle-anims";
@ -388,8 +388,12 @@ export class EncounterPhase extends BattlePhase {
this.scene.unshiftPhase(new ShinySparklePhase(this.scene, BattlerIndex.ENEMY + e)); this.scene.unshiftPhase(new ShinySparklePhase(this.scene, BattlerIndex.ENEMY + e));
}); });
if (this.scene.currentBattle.battleType !== BattleType.TRAINER) if (this.scene.currentBattle.battleType !== BattleType.TRAINER) {
enemyField.map(p => this.scene.pushPhase(new PostSummonPhase(this.scene, p.getBattlerIndex()))); enemyField.map(p => this.scene.pushPhase(new PostSummonPhase(this.scene, p.getBattlerIndex())));
const ivScannerModifier = this.scene.findModifier(m => m instanceof IvScannerModifier);
if (ivScannerModifier)
enemyField.map(p => this.scene.pushPhase(new ScanIvsPhase(this.scene, p.getBattlerIndex(), Math.min(ivScannerModifier.getStackCount(), 6))));
}
// TODO: Remove // TODO: Remove
//this.scene.unshiftPhase(new SelectModifierPhase(this.scene)); //this.scene.unshiftPhase(new SelectModifierPhase(this.scene));
@ -2478,7 +2482,7 @@ export class LevelUpPhase extends PlayerPartyMemberPokemonPhase {
pokemon.calculateStats(); pokemon.calculateStats();
pokemon.updateInfo(); pokemon.updateInfo();
this.scene.playSoundWithoutBgm('level_up_fanfare', 1500); this.scene.playSoundWithoutBgm('level_up_fanfare', 1500);
this.scene.ui.showText(`${this.getPokemon().name} grew to\nLv. ${this.level}!`, null, () => this.scene.ui.getMessageHandler().promptLevelUpStats(this.partyMemberIndex, prevStats, false, () => this.end()), null, true); this.scene.ui.showText(`${this.getPokemon().name} grew to\nLv. ${this.level}!`, null, () => this.scene.ui.getMessageHandler().promptLevelUpStats(this.partyMemberIndex, prevStats, false).then(() => this.end()), null, true);
if (this.level <= 100) { if (this.level <= 100) {
const levelMoves = this.getPokemon().getLevelMoves(this.lastLevel + 1); const levelMoves = this.getPokemon().getLevelMoves(this.lastLevel + 1);
for (let lm of levelMoves) for (let lm of levelMoves)
@ -3122,6 +3126,39 @@ export class ShinySparklePhase extends PokemonPhase {
} }
} }
export class ScanIvsPhase extends PokemonPhase {
private shownIvs: integer;
constructor(scene: BattleScene, battlerIndex: BattlerIndex, shownIvs: integer) {
super(scene, battlerIndex);
this.shownIvs = shownIvs;
}
start() {
super.start();
if (!this.shownIvs)
return this.end();
const pokemon = this.getPokemon();
this.scene.ui.showText(`Use IV Scanner on ${pokemon.name}?`, null, () => {
this.scene.ui.setMode(Mode.CONFIRM, () => {
this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.clearText();
new CommonBattleAnim(CommonAnim.LOCK_ON, pokemon, pokemon).play(this.scene, () => {
this.scene.ui.getMessageHandler().promptIvs(pokemon.id, pokemon.ivs, this.shownIvs).then(() => this.end());
});
}, () => {
this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.clearText();
this.end();
});
});
}
}
export class TestMessagePhase extends MessagePhase { export class TestMessagePhase extends MessagePhase {
constructor(scene: BattleScene, message: string) { constructor(scene: BattleScene, message: string) {
super(scene, message, null, true); super(scene, message, null, true);

View File

@ -80,7 +80,8 @@ export enum CommonAnim {
MISTY_TERRAIN = 2110, MISTY_TERRAIN = 2110,
ELECTRIC_TERRAIN, ELECTRIC_TERRAIN,
GRASSY_TERRAIN, GRASSY_TERRAIN,
PSYCHIC_TERRAIN PSYCHIC_TERRAIN,
LOCK_ON = 2120
} }
export class AnimConfig { export class AnimConfig {

View File

@ -710,6 +710,8 @@ export const modifierTypes = {
SHINY_CHARM: () => new ModifierType('Shiny Charm', 'Dramatically increases the chance of a wild Pokémon being shiny', (type, _args) => new Modifiers.ShinyRateBoosterModifier(type)), SHINY_CHARM: () => new ModifierType('Shiny Charm', 'Dramatically increases the chance of a wild Pokémon being shiny', (type, _args) => new Modifiers.ShinyRateBoosterModifier(type)),
ABILITY_CHARM: () => new ModifierType('Ability Charm', 'Dramatically increases the chance of a wild Pokémon having a hidden ability', (type, _args) => new Modifiers.HiddenAbilityRateBoosterModifier(type)), ABILITY_CHARM: () => new ModifierType('Ability Charm', 'Dramatically increases the chance of a wild Pokémon having a hidden ability', (type, _args) => new Modifiers.HiddenAbilityRateBoosterModifier(type)),
IV_SCANNER: () => new ModifierType('IV Scanner', 'Allows scanning the IVs of wild Pokémon', (type, _args) => new Modifiers.IvScannerModifier(type), 'scanner'),
DNA_SPLICERS: () => new FusePokemonModifierType('DNA Splicers'), DNA_SPLICERS: () => new FusePokemonModifierType('DNA Splicers'),
REVERSE_DNA_SPLICERS: () => new UnfusePokemonModifierType('Reverse DNA Splicers', 'dna_splicers'), REVERSE_DNA_SPLICERS: () => new UnfusePokemonModifierType('Reverse DNA Splicers', 'dna_splicers'),
@ -819,6 +821,7 @@ const modifierPool = {
new WeightedModifierType(modifierTypes.EXP_CHARM, 4), new WeightedModifierType(modifierTypes.EXP_CHARM, 4),
new WeightedModifierType(modifierTypes.OVAL_CHARM, 2), new WeightedModifierType(modifierTypes.OVAL_CHARM, 2),
new WeightedModifierType(modifierTypes.ABILITY_CHARM, 2), new WeightedModifierType(modifierTypes.ABILITY_CHARM, 2),
new WeightedModifierType(modifierTypes.IV_SCANNER, 2),
new WeightedModifierType(modifierTypes.EXP_BALANCE, 1), new WeightedModifierType(modifierTypes.EXP_BALANCE, 1),
new WeightedModifierType(modifierTypes.COIN_CASE, 1), new WeightedModifierType(modifierTypes.COIN_CASE, 1),
new WeightedModifierType(modifierTypes.REVERSE_DNA_SPLICERS, (party: Pokemon[]) => party[0].scene.gameMode !== GameMode.SPLICED_ENDLESS && party.filter(p => p.fusionSpecies).length ? 3 : 0), new WeightedModifierType(modifierTypes.REVERSE_DNA_SPLICERS, (party: Pokemon[]) => party[0].scene.gameMode !== GameMode.SPLICED_ENDLESS && party.filter(p => p.fusionSpecies).length ? 3 : 0),

View File

@ -271,8 +271,8 @@ export class DoubleBattleChanceBoosterModifier extends LapsingPersistentModifier
return false; return false;
} }
clone(): TempBattleStatBoosterModifier { clone(): DoubleBattleChanceBoosterModifier {
return new TempBattleStatBoosterModifier(this.type as ModifierTypes.TempBattleStatBoosterModifierType, this.battlesLeft, this.stackCount); return new DoubleBattleChanceBoosterModifier(this.type as ModifierTypes.DoubleBattleChanceBoosterModifierType, this.battlesLeft, this.stackCount);
} }
getArgs(): any[] { getArgs(): any[] {
@ -1392,6 +1392,28 @@ export class ContactHeldItemTransferChanceModifier extends HeldItemTransferModif
} }
} }
export class IvScannerModifier extends PersistentModifier {
constructor(type: ModifierType, stackCount?: integer) {
super(type, stackCount);
}
match(modifier: Modifier): boolean {
return modifier instanceof IvScannerModifier;
}
clone(): IvScannerModifier {
return new IvScannerModifier(this.type, this.stackCount);
}
apply(args: any[]): boolean {
return true;
}
getMaxStackCount(): integer {
return 5;
}
}
export class ExtraModifierModifier extends PersistentModifier { export class ExtraModifierModifier extends PersistentModifier {
constructor(type: ModifierType, stackCount?: integer) { constructor(type: ModifierType, stackCount?: integer) {
super(type, stackCount); super(type, stackCount);

View File

@ -95,10 +95,12 @@ export function initAutoPlay() {
}; };
const originalMessageUiHandlerPromptLevelUpStats = messageUiHandler.promptLevelUpStats; const originalMessageUiHandlerPromptLevelUpStats = messageUiHandler.promptLevelUpStats;
messageUiHandler.promptLevelUpStats = function (partyMemberIndex: integer, prevStats: integer[], showTotals: boolean, callback?: Function) { messageUiHandler.promptLevelUpStats = function (partyMemberIndex: integer, prevStats: integer[], showTotals: boolean): Promise<void> {
originalMessageUiHandlerPromptLevelUpStats.apply(this, [ partyMemberIndex, prevStats, showTotals, callback ]); return new Promise(resolve => {
if (thisArg.auto) originalMessageUiHandlerPromptLevelUpStats.apply(this, [ partyMemberIndex, prevStats, showTotals ]).then(() => resolve());
thisArg.time.delayedCall(20, () => this.processInput(Button.ACTION)); if (thisArg.auto)
thisArg.time.delayedCall(20, () => this.processInput(Button.ACTION));
});
}; };
const originalCommandUiHandlerShow = commandUiHandler.show; const originalCommandUiHandlerShow = commandUiHandler.show;

View File

@ -68,11 +68,11 @@ export default class BattleMessageUiHandler extends MessageUiHandler {
this.levelUpStatsContainer = levelUpStatsContainer; this.levelUpStatsContainer = levelUpStatsContainer;
const levelUpStatsBg = this.scene.add.nineslice((this.scene.game.canvas.width / 6), -100, 'window', null, 118, 100, 6, 6, 6, 6); const levelUpStatsBg = this.scene.add.nineslice((this.scene.game.canvas.width / 6), -100, 'window', null, 128, 100, 6, 6, 6, 6);
levelUpStatsBg.setOrigin(1, 0); levelUpStatsBg.setOrigin(1, 0);
levelUpStatsContainer.add(levelUpStatsBg); levelUpStatsContainer.add(levelUpStatsBg);
const levelUpStatsLabelsContent = addTextObject(this.scene, (this.scene.game.canvas.width / 6) - 111, -94, '', TextStyle.WINDOW, { maxLines: 6 }); const levelUpStatsLabelsContent = addTextObject(this.scene, (this.scene.game.canvas.width / 6) - 121, -94, '', TextStyle.WINDOW, { maxLines: 6 });
let levelUpStatsLabelText = ''; let levelUpStatsLabelText = '';
const stats = Utils.getEnumValues(Stat); const stats = Utils.getEnumValues(Stat);
@ -131,27 +131,71 @@ export default class BattleMessageUiHandler extends MessageUiHandler {
super.showDialogue(text, name, delay, callback, callbackDelay, prompt, promptDelay); super.showDialogue(text, name, delay, callback, callbackDelay, prompt, promptDelay);
} }
promptLevelUpStats(partyMemberIndex: integer, prevStats: integer[], showTotals: boolean, callback?: Function): void { promptLevelUpStats(partyMemberIndex: integer, prevStats: integer[], showTotals: boolean): Promise<void> {
if (!this.scene.showLevelUpStats) return new Promise(resolve => {
return callback(); if (!this.scene.showLevelUpStats)
const newStats = (this.scene as BattleScene).getParty()[partyMemberIndex].stats; return resolve();
let levelUpStatsValuesText = ''; const newStats = (this.scene as BattleScene).getParty()[partyMemberIndex].stats;
const stats = Utils.getEnumValues(Stat); let levelUpStatsValuesText = '';
for (let s of stats) const stats = Utils.getEnumValues(Stat);
levelUpStatsValuesText += `${showTotals ? newStats[s] : newStats[s] - prevStats[s]}\n`; for (let s of stats)
this.levelUpStatsValuesContent.text = levelUpStatsValuesText; levelUpStatsValuesText += `${showTotals ? newStats[s] : newStats[s] - prevStats[s]}\n`;
this.levelUpStatsIncrContent.setVisible(!showTotals); this.levelUpStatsValuesContent.text = levelUpStatsValuesText;
this.levelUpStatsContainer.setVisible(true); this.levelUpStatsIncrContent.setVisible(!showTotals);
this.awaitingActionInput = true; this.levelUpStatsContainer.setVisible(true);
this.onActionInput = () => { this.awaitingActionInput = true;
if (!showTotals) this.onActionInput = () => {
this.promptLevelUpStats(partyMemberIndex, null, true, callback); if (!showTotals)
else { return this.promptLevelUpStats(partyMemberIndex, null, true).then(() => resolve());
this.levelUpStatsContainer.setVisible(false); else {
if (callback) this.levelUpStatsContainer.setVisible(false);
callback(); resolve();
} }
}; };
});
}
promptIvs(pokemonId: integer, ivs: integer[], shownIvsCount: integer): Promise<void> {
return new Promise(resolve => {
this.scene.executeWithSeedOffset(() => {
let levelUpStatsValuesText = '';
const stats = Utils.getEnumValues(Stat);
let shownStats: Stat[] = [];
if (shownIvsCount < 6) {
let statsPool = stats.slice(0);
for (let i = 0; i < shownIvsCount; i++) {
const shownStat = Phaser.Math.RND.pick(statsPool);
shownStats.push(shownStat);
statsPool.splice(statsPool.indexOf(shownStat), 1);
}
} else
shownStats = stats;
for (let s of stats)
levelUpStatsValuesText += `${shownStats.indexOf(s) > -1 ? this.getIvDescriptor(ivs[s]) : '???'}\n`;
this.levelUpStatsValuesContent.text = levelUpStatsValuesText;
this.levelUpStatsIncrContent.setVisible(false);
this.levelUpStatsContainer.setVisible(true);
this.awaitingActionInput = true;
this.onActionInput = () => {
this.levelUpStatsContainer.setVisible(false);
resolve();
};
}, pokemonId);
});
}
getIvDescriptor(value: integer): string {
if (value > 30)
return 'Perfect';
if (value === 30)
return 'Fantastic';
if (value > 20)
return 'Very Good';
if (value > 10)
return 'Pretty Good';
if (value)
return 'Decent';
return 'No Good';
} }
showNameText(name: string): void { showNameText(name: string): void {

View File

@ -76,7 +76,8 @@ export default class MenuUiHandler extends UiHandler {
} }
} else if (button === Button.CANCEL) { } else if (button === Button.CANCEL) {
success = true; success = true;
this.scene.ui.revertMode(); if (!this.scene.ui.revertMode())
ui.setMode(Mode.MESSAGE);
} else { } else {
switch (button) { switch (button) {
case Button.UP: case Button.UP:

View File

@ -292,11 +292,12 @@ export default class UI extends Phaser.GameObjects.Container {
return this.setModeInternal(mode, false, false, true, args); return this.setModeInternal(mode, false, false, true, args);
} }
revertMode(): void { revertMode(): boolean {
if (!this.modeChain.length) if (!this.modeChain.length)
return; return false;
this.getHandler().clear(); this.getHandler().clear();
this.mode = this.modeChain.pop(); this.mode = this.modeChain.pop();
return true;
} }
} }