More testing & RNG things

Added a dialogue to skip unimplemented moves faster, but I haven't been able to test it, so it's disabled for now

Fixed shiny luck check

Now shows exact items resulting from changes in shiny luck
This commit is contained in:
RedstonewolfX 2024-08-11 14:07:20 -04:00
parent 740277b222
commit 8caf853b8d
4 changed files with 202 additions and 96 deletions

View File

@ -130,6 +130,8 @@ 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 waveShinyFlag: boolean = false;
public waveShinyChecked: boolean = false;
public tempWaveSeed: string;
public tempRngCounter: integer = 0;
/**
@ -1281,6 +1283,11 @@ export default class BattleScene extends SceneBase {
this.restoreSeed()
}
doShinyCheck() {
this.waveShinyChecked = true;
this.waveShinyFlag = runShinyCheck(this, 1, this.currentBattle.waveIndex);
}
newBattle(waveIndex?: integer, battleType?: BattleType, trainerData?: TrainerData, double?: boolean): Battle {
const _startingWave = Overrides.STARTING_WAVE_OVERRIDE || startingWave;
const newWaveIndex = waveIndex || ((this.currentBattle?.waveIndex || (_startingWave - 1)) + 1);
@ -1291,6 +1298,8 @@ export default class BattleScene extends SceneBase {
let battleConfig: FixedBattleConfig = null;
this.resetSeed(newWaveIndex);
this.waveShinyChecked = false;
this.waveShinyFlag = false;
const playerField = this.getPlayerField();

View File

@ -120,6 +120,8 @@ export default class Move implements Localizable {
private flags: integer;
private nameAppend: string;
public implementationTag: string;
constructor(id: Moves, type: Type, category: MoveCategory, defaultMoveTarget: MoveTarget, power: integer, accuracy: integer, pp: integer, chance: integer, priority: integer, generation: integer) {
this.id = id;
@ -324,12 +326,29 @@ export default class Move implements Localizable {
return this;
}
isFullyImplemented(): boolean {
return this.implementationTag == "" || this.implementationTag == undefined;
}
isPartiallyImplemented(): boolean {
return this.implementationTag == "P";
}
isPartial(): boolean {
return this.implementationTag == "P";
}
isUnimplemented(): boolean {
return this.implementationTag == "N";
}
isNotImplemented(): boolean {
return this.implementationTag == "N";
}
/**
* Marks the move as "partial": appends texts to the move name
* @returns the called object {@linkcode Move}
*/
partial(): this {
this.nameAppend += " (P)";
this.implementationTag = "P";
return this;
}
@ -339,6 +358,7 @@ export default class Move implements Localizable {
*/
unimplemented(): this {
this.nameAppend += " (N)";
this.implementationTag = "N";
return this;
}

View File

@ -2042,18 +2042,20 @@ export function getModifierTypeFuncById(id: string): ModifierTypeFunc {
return modifierTypes[id];
}
export function getPlayerModifierTypeOptions(count: integer, party: PlayerPokemon[], modifierTiers?: ModifierTier[], scene?: BattleScene, shutUpBro?: boolean, generateAltTiers?: boolean, shinyCheckOnly?: boolean): ModifierTypeOption[] {
export function getPlayerModifierTypeOptions(count: integer, party: PlayerPokemon[], modifierTiers?: ModifierTier[], scene?: BattleScene, shutUpBro?: boolean, generateAltTiers?: boolean, advanced?: boolean): ModifierTypeOption[] {
const options: ModifierTypeOption[] = [];
const retryCount = Math.min(count * 5, 50);
new Array(count).fill(0).map((_, i) => {
let candidate = getNewModifierTypeOption(party, ModifierPoolType.PLAYER, modifierTiers?.length > i ? modifierTiers[i] : undefined, undefined, undefined, scene, shutUpBro, generateAltTiers, shinyCheckOnly);
let candidate = getNewModifierTypeOption(party, ModifierPoolType.PLAYER, modifierTiers?.length > i ? modifierTiers[i] : undefined, undefined, undefined, scene, shutUpBro, generateAltTiers, advanced);
let r = 0;
const aT = candidate.alternates
const aT2 = candidate.advancedAlternates
while (options.length && ++r < retryCount && options.filter(o => o.type.name === candidate.type.name || o.type.group === candidate.type.group).length) {
candidate = getNewModifierTypeOption(party, ModifierPoolType.PLAYER, candidate.type.tier, candidate.upgradeCount, undefined, scene, shutUpBro, generateAltTiers, shinyCheckOnly);
candidate = getNewModifierTypeOption(party, ModifierPoolType.PLAYER, candidate.type.tier, candidate.upgradeCount, undefined, scene, shutUpBro, generateAltTiers, advanced);
}
if (candidate.alternates == undefined) {
candidate.alternates = aT
candidate.advancedAlternates = aT2
}
options.push(candidate);
});
@ -2110,12 +2112,14 @@ export function getEnemyBuffModifierForWave(tier: ModifierTier, enemyModifiers:
let candidate = getNewModifierTypeOption(null, ModifierPoolType.ENEMY_BUFF, tier, undefined, undefined, scene);
let r = 0;
const aT = candidate.alternates
const aT2 = candidate.advancedAlternates
let matchingModifier: Modifiers.PersistentModifier;
while (++r < retryCount && (matchingModifier = enemyModifiers.find(m => m.type.id === candidate.type.id)) && matchingModifier.getMaxStackCount(scene) < matchingModifier.stackCount + (r < 10 ? tierStackCount : 1)) {
candidate = getNewModifierTypeOption(null, ModifierPoolType.ENEMY_BUFF, tier, undefined, undefined, scene);
}
if (candidate.alternates == undefined) {
candidate.alternates = aT
candidate.advancedAlternates = aT2
}
const modifier = candidate.type.newModifier() as Modifiers.EnemyPersistentModifier;
@ -2146,7 +2150,7 @@ export function getDailyRunStarterModifiers(party: PlayerPokemon[], scene?: Batt
return ret;
}
function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType, tier?: ModifierTier, upgradeCount?: integer, retryCount: integer = 0, scene?: BattleScene, shutUpBro?: boolean, generateAltTiers?: boolean, shinyCheckOnly?: boolean): ModifierTypeOption {
function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType, tier?: ModifierTier, upgradeCount?: integer, retryCount: integer = 0, scene?: BattleScene, shutUpBro?: boolean, generateAltTiers?: boolean, advanced?: boolean): ModifierTypeOption {
const player = !poolType;
const pool = getModifierPoolForType(poolType);
let thresholds: object;
@ -2168,6 +2172,7 @@ function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType,
break;
}
var alternateTiers = []
var alternateTierContents = []
if (tier === undefined) {
if (generateAltTiers) {
for (var luck = 0; luck <= 14; luck++) {
@ -2202,12 +2207,12 @@ function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType,
}
}
alternateTiers[luck] = tierTemp
Phaser.Math.RND.state(state)
if (advanced) {
var itemIndex = getItemIndex(thresholds, tierTemp)
var itemName = getModifierTypeSimulated(pool, tierTemp, itemIndex, party)
alternateTierContents[luck] = itemName
}
if (shinyCheckOnly) {
var O = new ModifierTypeOption(undefined, 0, 0);
O.alternates = alternateTiers;
return O;
Phaser.Math.RND.state(state)
}
}
const tierValue = Utils.randSeedInt(1024);
@ -2264,12 +2269,12 @@ function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType,
}
}
alternateTiers[luck] = tier + upgradeCountTemp
Phaser.Math.RND.state(state)
if (advanced) {
var itemIndex = getItemIndex(thresholds, tier + upgradeCountTemp)
var itemName = getModifierTypeSimulated(pool, tier + upgradeCountTemp, itemIndex, party)
alternateTierContents[luck] = itemName
}
if (shinyCheckOnly) {
var O = new ModifierTypeOption(undefined, 0, 0);
O.alternates = alternateTiers;
return O;
Phaser.Math.RND.state(state)
}
}
const upgradeOdds = Math.floor(32 / ((partyShinyCount + 2) / 2));
@ -2287,21 +2292,7 @@ function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType,
tier--;
}
if (shinyCheckOnly) {
return new ModifierTypeOption(undefined, 0, 0);
}
const tierThresholds = Object.keys(thresholds[tier]);
const totalWeight = parseInt(tierThresholds[tierThresholds.length - 1]);
const value = Utils.randSeedInt(totalWeight);
let index: integer;
for (const t of tierThresholds) {
const threshold = parseInt(t);
if (value < threshold) {
index = thresholds[tier][threshold];
break;
}
}
let index = getItemIndex(thresholds, tier);
if (index === undefined) {
return null;
@ -2328,11 +2319,53 @@ function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType,
//console.log(Option.type.name, alternateTiers)
Option.alternates = alternateTiers
}
if (alternateTierContents.length > 0) {
//console.log(Option.type.name, alternateTiers)
Option.advancedAlternates = alternateTierContents
}
if (!generateAltTiers) {
//Option.alternates = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
}
return Option;
}
/**
* Gets an item index to add to shop rewards. Used for reroll predictions.
* @param thresholds The "loot table" for this floor
* @param tier The rarity tier to pull from
* @returns An index for use in {@linkcode getModifierTypeSimulated}
*/
function getItemIndex(thresholds, tier) {
const tierThresholds = Object.keys(thresholds[tier]);
const totalWeight = parseInt(tierThresholds[tierThresholds.length - 1]);
const value = Utils.randSeedInt(totalWeight);
let index: integer;
for (const t of tierThresholds) {
const threshold = parseInt(t);
if (value < threshold) {
index = thresholds[tier][threshold];
break;
}
}
return index;
}
/**
* Uses an index (generated from {@linkcode getItemIndex}) to get a reward item
* @param pool The items to pull from, based on the PoolType specified in {@linkcode getNewModifierTypeOption}
* @param tier The rarity tier to pull from
* @param index The item index from the loot pool
* @param party The player's party, used for generating some specific items
* @returns An item name, or `[Failed to generate]` if a `ModifierTypeGenerator` was rolled, but no item was available to generate (It won't retry)
*/
function getModifierTypeSimulated(pool, tier, index, party) {
let modifierType: ModifierType = (pool[tier][index]).modifierType;
if (modifierType instanceof ModifierTypeGenerator) {
modifierType = (modifierType as ModifierTypeGenerator).generateType(party);
if (modifierType === null) {
return "[Failed to generate]"
}
}
return modifierType.name;
}
export function getDefaultModifierTypeForTier(tier: ModifierTier): ModifierType {
let modifierType: ModifierType | WeightedModifierType = modifierPool[tier || ModifierTier.COMMON][0];
@ -2347,6 +2380,7 @@ export class ModifierTypeOption {
public upgradeCount: integer;
public cost: integer;
public alternates?: integer[];
public advancedAlternates?: string[];
constructor(type: ModifierType, upgradeCount: integer, cost: number = 0) {
this.type = type;

View File

@ -1785,6 +1785,8 @@ export class EncounterPhase extends BattlePhase {
}
LoggerTools.resetWaveActions(this.scene, undefined, true)
this.scene.doShinyCheck()
if (LoggerTools.autoCheckpoints.includes(this.scene.currentBattle.waveIndex)) {
//this.scene.gameData.saveGameToAuto(this.scene)
}
@ -6199,26 +6201,6 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
const messageMode = this.scene.ui.getHandler() instanceof EvolutionSceneHandler
? Mode.EVOLUTION_SCENE
: Mode.MESSAGE;
if (emptyMoveIndex > -1) {
pokemon.setMove(emptyMoveIndex, this.moveId);
initMoveAnim(this.scene, this.moveId).then(() => {
loadMoveAnimAssets(this.scene, [this.moveId], true)
.then(() => {
this.scene.ui.setMode(messageMode).then(() => {
this.scene.playSound("level_up_fanfare");
this.scene.ui.showText(i18next.t("battle:learnMove", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name }), null, () => {
this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeMoveLearnedTrigger, true);
this.end();
}, messageMode === Mode.EVOLUTION_SCENE ? 1000 : null, true);
});
});
});
} else {
this.scene.ui.setMode(messageMode).then(() => {
this.scene.ui.showText(i18next.t("battle:learnMovePrompt", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name }), null, () => {
this.scene.ui.showText(i18next.t("battle:learnMoveLimitReached", { pokemonName: getPokemonNameWithAffix(pokemon) }), null, () => {
this.scene.ui.showText(i18next.t("battle:learnMoveReplaceQuestion", { moveName: move.name }), null, () => {
const noHandler = () => {
this.scene.ui.setMode(messageMode).then(() => {
this.scene.ui.showText(i18next.t("battle:learnMoveStopTeaching", { moveName: move.name }), null, () => {
@ -6232,14 +6214,29 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
LoggerTools.logActions(this.scene, this.scene.currentBattle.waveIndex, (actions == 0 ? "" : "") + LoggerTools.playerPokeName(this.scene, pokemon) + " | Skip " + move.name)
}
this.scene.ui.showText(i18next.t("battle:learnMoveNotLearned", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name }), null, () => this.end(), null, true);
}, () => {
}, (false ? movesFullHandler : () => {
this.scene.ui.setMode(messageMode);
this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.partyMemberIndex, this.moveId));
this.end();
});
}));
});
});
};
const noHandlerInstant = () => {
this.scene.ui.setMode(messageMode);
var W = LoggerTools.getWave(LoggerTools.getDRPD(this.scene), this.scene.currentBattle.waveIndex, this.scene)
if (W.shop != "") {
LoggerTools.logShop(this.scene, this.scene.currentBattle.waveIndex, W.shop + "; skip learning it")
} else {
var actions = LoggerTools.getActionCount(this.scene, this.scene.currentBattle.waveIndex)
LoggerTools.logActions(this.scene, this.scene.currentBattle.waveIndex, (actions == 0 ? "" : "") + LoggerTools.playerPokeName(this.scene, pokemon) + " | Skip " + move.name)
}
this.scene.ui.showText(i18next.t("battle:learnMoveNotLearned", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name }), null, () => this.end(), null, true);
};
const movesFullHandler = () => {
this.scene.ui.showText(i18next.t("battle:learnMovePrompt", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name }), null, () => {
this.scene.ui.showText(i18next.t("battle:learnMoveLimitReached", { pokemonName: getPokemonNameWithAffix(pokemon) }), null, () => {
this.scene.ui.showText(i18next.t("battle:learnMoveReplaceQuestion", { moveName: move.name }), null, () => {
this.scene.ui.setModeWithoutClear(Mode.CONFIRM, () => {
this.scene.ui.setMode(messageMode);
this.scene.ui.showText(i18next.t("battle:learnMoveForgetQuestion"), null, () => {
@ -6272,7 +6269,31 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
});
}, null, true);
}, null, true);
}
if (emptyMoveIndex > -1) {
pokemon.setMove(emptyMoveIndex, this.moveId);
initMoveAnim(this.scene, this.moveId).then(() => {
loadMoveAnimAssets(this.scene, [this.moveId], true)
.then(() => {
this.scene.ui.setMode(messageMode).then(() => {
this.scene.playSound("level_up_fanfare");
this.scene.ui.showText(i18next.t("battle:learnMove", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name }), null, () => {
this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeMoveLearnedTrigger, true);
this.end();
}, messageMode === Mode.EVOLUTION_SCENE ? 1000 : null, true);
});
});
});
} else if (move.isUnimplemented() && false) {
this.scene.ui.setMode(messageMode).then(() => {
this.scene.ui.showText(`${getPokemonNameWithAffix(pokemon)} wants to learn ${move.name}, but this move does nothing.`, null, () => {
this.scene.ui.showText(`Would you like to teach ${move.name} anyways? (This will be logged as normal)`, null, () => {
this.scene.ui.setModeWithoutClear(Mode.CONFIRM, movesFullHandler, noHandler)
})
})
});
} else {
this.scene.ui.setMode(messageMode).then(movesFullHandler);
}
}
}
@ -6757,9 +6778,12 @@ export function shinyCheckStep(scene: BattleScene, predictionCost: Utils.Integer
var isOk = true;
const typeOptions: ModifierTypeOption[] = getPlayerModifierTypeOptions(modifierCount.value, scene.getParty(), undefined, scene, true, true);
typeOptions.forEach((option, idx) => {
let lastTier = option.type.tier
if (option.alternates && option.alternates.length > 0) {
for (var i = 0; i < option.alternates.length; i++) {
if (option.alternates[i] > option.type.tier) {
if (option.alternates[i] > lastTier) {
//lastTier = option.alternates[i]
//console.log("Conflict found! (" + i + " luck, " + rerollOverride + " rolls, item " + (idx + 1) + ")")
isOk = false // Shiny Luck affects this wave in some way
}
}
@ -6774,14 +6798,25 @@ export function shinyCheckStep(scene: BattleScene, predictionCost: Utils.Integer
* @param scene The current `BattleScene`.
* @returns `true` if no changes were detected, `false` otherwise
*/
export function runShinyCheck(scene: BattleScene, wv?: integer) {
export function runShinyCheck(scene: BattleScene, mode: integer, wv?: integer) {
if (mode == 1) {
scene.emulateReset(wv)
} else {
scene.resetSeed(wv);
}
const predictionCost = new Utils.IntegerHolder(0)
var isOk = true;
for (var i = 0; i < 14 && isOk; i++) {
for (var i = 0; isOk && predictionCost.value < scene.money && i < 20; i++) {
isOk = isOk && shinyCheckStep(scene, predictionCost, i)
}
if (mode == 1) {
scene.restoreSeed(wv)
} else {
scene.resetSeed(wv);
}
if (!isOk) {
console.log("Conflict found!")
}
return isOk
}
export class SelectModifierPhase extends BattlePhase {
@ -6815,7 +6850,7 @@ export class SelectModifierPhase extends BattlePhase {
if (modifierOverride) {
//modifierCount.value = modifierOverride
}
const typeOptions: ModifierTypeOption[] = this.getModifierTypeOptions(modifierCount.value, true, true);
const typeOptions: ModifierTypeOption[] = this.getModifierTypeOptions(modifierCount.value, true, true, true);
typeOptions.forEach((option, idx) => {
//console.log(option.type.name)
})
@ -7055,7 +7090,15 @@ export class SelectModifierPhase extends BattlePhase {
for (var j = 0, currentTier = m.type.tier; j < m.alternates.length; j++) {
if (m.alternates[j] > currentTier) {
currentTier = m.alternates[j]
console.log(" At " + j + " luck: " + tierNames[currentTier] + "-tier item")
if (m.advancedAlternates) {
if (m.advancedAlternates[j] != "[Failed to generate]") {
console.log(" At " + j + " luck: " + tierNames[currentTier] + "-tier item (failed to generate item from ModifierGenerator)")
} else {
console.log(" At " + j + " luck: " + m.advancedAlternates[j])
}
} else {
console.log(" At " + j + " luck: " + tierNames[currentTier] + "-tier item (failed to generate item)")
}
}
}
} else {
@ -7092,8 +7135,8 @@ export class SelectModifierPhase extends BattlePhase {
return ModifierPoolType.PLAYER;
}
getModifierTypeOptions(modifierCount: integer, shutUpBro?: boolean, calcAllLuck?: boolean): ModifierTypeOption[] {
return getPlayerModifierTypeOptions(modifierCount, this.scene.getParty(), this.scene.lockModifierTiers ? this.modifierTiers : undefined, this.scene, shutUpBro, calcAllLuck);
getModifierTypeOptions(modifierCount: integer, shutUpBro?: boolean, calcAllLuck?: boolean, advanced?: boolean): ModifierTypeOption[] {
return getPlayerModifierTypeOptions(modifierCount, this.scene.getParty(), this.scene.lockModifierTiers ? this.modifierTiers : undefined, this.scene, shutUpBro, calcAllLuck, advanced);
}
addModifier(modifier: Modifier): Promise<boolean> {