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?
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
- Trainers
- Finish party pools
- Add dialogue
- Add reward for gym leader victories
- Encounters
- Add extremely rare chance of Arceus available anywhere with type change
- 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 { Command } from "./ui/command-ui-handler";
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 { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./data/pokeball";
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));
});
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())));
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
//this.scene.unshiftPhase(new SelectModifierPhase(this.scene));
@ -2478,7 +2482,7 @@ export class LevelUpPhase extends PlayerPartyMemberPokemonPhase {
pokemon.calculateStats();
pokemon.updateInfo();
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) {
const levelMoves = this.getPokemon().getLevelMoves(this.lastLevel + 1);
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 {
constructor(scene: BattleScene, message: string) {
super(scene, message, null, true);

View File

@ -80,7 +80,8 @@ export enum CommonAnim {
MISTY_TERRAIN = 2110,
ELECTRIC_TERRAIN,
GRASSY_TERRAIN,
PSYCHIC_TERRAIN
PSYCHIC_TERRAIN,
LOCK_ON = 2120
}
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)),
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'),
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.OVAL_CHARM, 2),
new WeightedModifierType(modifierTypes.ABILITY_CHARM, 2),
new WeightedModifierType(modifierTypes.IV_SCANNER, 2),
new WeightedModifierType(modifierTypes.EXP_BALANCE, 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),

View File

@ -271,8 +271,8 @@ export class DoubleBattleChanceBoosterModifier extends LapsingPersistentModifier
return false;
}
clone(): TempBattleStatBoosterModifier {
return new TempBattleStatBoosterModifier(this.type as ModifierTypes.TempBattleStatBoosterModifierType, this.battlesLeft, this.stackCount);
clone(): DoubleBattleChanceBoosterModifier {
return new DoubleBattleChanceBoosterModifier(this.type as ModifierTypes.DoubleBattleChanceBoosterModifierType, this.battlesLeft, this.stackCount);
}
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 {
constructor(type: ModifierType, stackCount?: integer) {
super(type, stackCount);

View File

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

View File

@ -68,11 +68,11 @@ export default class BattleMessageUiHandler extends MessageUiHandler {
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);
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 = '';
const stats = Utils.getEnumValues(Stat);
@ -131,27 +131,71 @@ export default class BattleMessageUiHandler extends MessageUiHandler {
super.showDialogue(text, name, delay, callback, callbackDelay, prompt, promptDelay);
}
promptLevelUpStats(partyMemberIndex: integer, prevStats: integer[], showTotals: boolean, callback?: Function): void {
if (!this.scene.showLevelUpStats)
return callback();
const newStats = (this.scene as BattleScene).getParty()[partyMemberIndex].stats;
let levelUpStatsValuesText = '';
const stats = Utils.getEnumValues(Stat);
for (let s of stats)
levelUpStatsValuesText += `${showTotals ? newStats[s] : newStats[s] - prevStats[s]}\n`;
this.levelUpStatsValuesContent.text = levelUpStatsValuesText;
this.levelUpStatsIncrContent.setVisible(!showTotals);
this.levelUpStatsContainer.setVisible(true);
this.awaitingActionInput = true;
this.onActionInput = () => {
if (!showTotals)
this.promptLevelUpStats(partyMemberIndex, null, true, callback);
else {
this.levelUpStatsContainer.setVisible(false);
if (callback)
callback();
}
};
promptLevelUpStats(partyMemberIndex: integer, prevStats: integer[], showTotals: boolean): Promise<void> {
return new Promise(resolve => {
if (!this.scene.showLevelUpStats)
return resolve();
const newStats = (this.scene as BattleScene).getParty()[partyMemberIndex].stats;
let levelUpStatsValuesText = '';
const stats = Utils.getEnumValues(Stat);
for (let s of stats)
levelUpStatsValuesText += `${showTotals ? newStats[s] : newStats[s] - prevStats[s]}\n`;
this.levelUpStatsValuesContent.text = levelUpStatsValuesText;
this.levelUpStatsIncrContent.setVisible(!showTotals);
this.levelUpStatsContainer.setVisible(true);
this.awaitingActionInput = true;
this.onActionInput = () => {
if (!showTotals)
return this.promptLevelUpStats(partyMemberIndex, null, true).then(() => resolve());
else {
this.levelUpStatsContainer.setVisible(false);
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 {

View File

@ -76,7 +76,8 @@ export default class MenuUiHandler extends UiHandler {
}
} else if (button === Button.CANCEL) {
success = true;
this.scene.ui.revertMode();
if (!this.scene.ui.revertMode())
ui.setMode(Mode.MESSAGE);
} else {
switch (button) {
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);
}
revertMode(): void {
revertMode(): boolean {
if (!this.modeChain.length)
return;
return false;
this.getHandler().clear();
this.mode = this.modeChain.pop();
return true;
}
}