From dfcc5c9e8763278e81faf0b1bf09cabf714ab51b Mon Sep 17 00:00:00 2001 From: RedstonewolfX <108761527+RedstonewolfX@users.noreply.github.com> Date: Wed, 11 Sep 2024 14:55:14 -0400 Subject: [PATCH] RNG Logging extension Copied over every file that uses any RNG function, adding more logging and hopefully fixing RNG discrepancies --- src/battle-scene.ts | 54 +++++++-------- src/battle.ts | 13 ++-- src/data/ability.ts | 24 +++---- src/data/battler-tags.ts | 2 +- src/data/berry.ts | 2 +- src/data/biomes.ts | 2 +- src/data/daily-run.ts | 2 +- src/data/egg.ts | 10 +-- src/data/move.ts | 74 +++++++++++++-------- src/data/pokemon-evolutions.ts | 4 +- src/data/pokemon-species.ts | 4 +- src/data/trainer-config.ts | 8 +-- src/data/weather.ts | 2 +- src/field/arena.ts | 68 +++---------------- src/field/pokemon-sprite-sparkle-handler.ts | 2 +- src/field/pokemon.ts | 62 +++++++++-------- src/field/trainer.ts | 10 +-- src/game-mode.ts | 6 +- src/modifier/modifier-type.ts | 42 ++++++------ src/modifier/modifier.ts | 6 +- src/phases/attempt-capture-phase.ts | 2 +- src/phases/attempt-run-phase.ts | 2 +- src/phases/egg-hatch-phase.ts | 6 +- src/phases/encounter-phase.ts | 2 +- src/phases/move-phase.ts | 2 +- src/phases/select-biome-phase.ts | 6 +- src/phases/trainer-victory-phase.ts | 2 +- src/system/game-data.ts | 18 ++--- src/ui/party-ui-handler.ts | 2 +- src/ui/title-ui-handler.ts | 2 +- src/utils.ts | 20 ++++-- 31 files changed, 223 insertions(+), 238 deletions(-) diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 5d607f90a22..15f041b8a48 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -850,9 +850,9 @@ export default class BattleScene extends SceneBase { return activeOnly ? this.infoToggles.filter(t => t?.isActive()) : this.infoToggles; } - getPokemonById(pokemonId: integer): Pokemon | undefined { + getPokemonById(pokemonId: integer): Pokemon | null { const findInParty = (party: Pokemon[]) => party.find(p => p.id === pokemonId); - return (findInParty(this.getParty()) || findInParty(this.getEnemyParty())) || undefined; + return (findInParty(this.getParty()) || findInParty(this.getEnemyParty())) ?? null; } addPlayerPokemon(species: PokemonSpecies, level: integer, abilityIndex?: integer, formIndex?: integer, gender?: Gender, shiny?: boolean, variant?: Variant, ivs?: integer[], nature?: Nature, dataSource?: Pokemon | PokemonData, postProcess?: (playerPokemon: PlayerPokemon) => void): PlayerPokemon { @@ -879,7 +879,7 @@ export default class BattleScene extends SceneBase { overrideModifiers(this, false); overrideHeldItems(this, pokemon, false); if (boss && !dataSource) { - const secondaryIvs = Utils.getIvsFromId(Utils.randSeedInt(4294967296)); + const secondaryIvs = Utils.getIvsFromId(Utils.randSeedInt(4294967296, undefined, "IVs")); for (let s = 0; s < pokemon.ivs.length; s++) { pokemon.ivs[s] = Math.round(Phaser.Math.Linear(Math.min(pokemon.ivs[s], secondaryIvs[s]), Math.max(pokemon.ivs[s], secondaryIvs[s]), 0.75)); @@ -1196,12 +1196,12 @@ export default class BattleScene extends SceneBase { this.setScoreText(txt.join(" / ")) } - newBattle(waveIndex?: integer, battleType?: BattleType, trainerData?: TrainerData, double?: boolean): Battle { + newBattle(waveIndex?: integer, battleType?: BattleType, trainerData?: TrainerData, double?: boolean): Battle | null { const _startingWave = Overrides.STARTING_WAVE_OVERRIDE || startingWave; const newWaveIndex = waveIndex || ((this.currentBattle?.waveIndex || (_startingWave - 1)) + 1); - var newDouble; - var newBattleType; - var newTrainer; + let newDouble: boolean | undefined; + let newBattleType: BattleType; + let newTrainer: Trainer | undefined; let battleConfig: FixedBattleConfig | null = null; @@ -1237,13 +1237,13 @@ export default class BattleScene extends SceneBase { const doubleChance = new Utils.IntegerHolder(newWaveIndex % 10 === 0 ? 32 : 8); this.applyModifiers(DoubleBattleChanceBoosterModifier, true, doubleChance); playerField.forEach(p => applyAbAttrs(DoubleBattleChanceAbAttr, p, null, false, doubleChance)); - doubleTrainer = !Utils.randSeedInt(doubleChance.value); + doubleTrainer = !Utils.randSeedInt(doubleChance.value, undefined, "Double battle roll"); // Add a check that special trainers can't be double except for tate and liza - they should use the normal double chance if (trainerConfigs[trainerType].trainerTypeDouble && ![ TrainerType.TATE, TrainerType.LIZA ].includes(trainerType)) { doubleTrainer = false; } } - const variant = doubleTrainer ? TrainerVariant.DOUBLE : (Utils.randSeedInt(2) ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT); + const variant = doubleTrainer ? TrainerVariant.DOUBLE : (Utils.randSeedInt(2, undefined, "Trainer gender") ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT); newTrainer = trainerData !== undefined ? trainerData.toTrainer(this) : new Trainer(this, trainerType, variant); this.field.add(newTrainer); } @@ -1254,9 +1254,9 @@ export default class BattleScene extends SceneBase { const doubleChance = new Utils.IntegerHolder(newWaveIndex % 10 === 0 ? 32 : 8); this.applyModifiers(DoubleBattleChanceBoosterModifier, true, doubleChance); playerField.forEach(p => applyAbAttrs(DoubleBattleChanceAbAttr, p, null, false, doubleChance)); - newDouble = !Utils.randSeedInt(doubleChance.value); + newDouble = !Utils.randSeedInt(doubleChance.value, undefined, "Double battle roll"); } else if (newBattleType === BattleType.TRAINER) { - newDouble = newTrainer.variant === TrainerVariant.DOUBLE; + newDouble = newTrainer?.variant === TrainerVariant.DOUBLE; } } else if (!battleConfig) { newDouble = !!double; @@ -1408,19 +1408,19 @@ export default class BattleScene extends SceneBase { case Species.TATSUGIRI: case Species.GIMMIGHOUL: case Species.PALDEA_TAUROS: - return Utils.randSeedInt(species.forms.length); + return Utils.randSeedInt(species.forms.length, undefined, "General form selection"); case Species.PIKACHU: - return Utils.randSeedInt(8); + return Utils.randSeedInt(8, undefined, "Pikachu form selection"); case Species.EEVEE: - return Utils.randSeedInt(2); + return Utils.randSeedInt(2, undefined, "Eevee form selection"); case Species.GRENINJA: - return Utils.randSeedInt(2); + return Utils.randSeedInt(2, undefined, "Greninja form selection"); case Species.ZYGARDE: - return Utils.randSeedInt(3); + return Utils.randSeedInt(3, undefined, "Zygarde form selection"); case Species.MINIOR: - return Utils.randSeedInt(6); + return Utils.randSeedInt(6, undefined, "Minior color selection"); case Species.ALCREMIE: - return Utils.randSeedInt(9); + return Utils.randSeedInt(9, undefined, "Alcremie form selection"); case Species.MEOWSTIC: case Species.INDEEDEE: case Species.BASCULEGION: @@ -1440,7 +1440,7 @@ export default class BattleScene extends SceneBase { case Species.WORMADAM: case Species.ROTOM: case Species.LYCANROC: - return Utils.randSeedInt(species.forms.length); + return Utils.randSeedInt(species.forms.length, undefined, "Non-area-specific form selection"); } return 0; } @@ -1451,7 +1451,7 @@ export default class BattleScene extends SceneBase { private getGeneratedOffsetGym(): boolean { let ret = false; this.executeWithSeedOffset(() => { - ret = !Utils.randSeedInt(2); + ret = !Utils.randSeedInt(2, undefined, "Random gym offset"); }, 0, this.seed.toString()); return ret; } @@ -1459,7 +1459,7 @@ export default class BattleScene extends SceneBase { private getGeneratedWaveCycleOffset(): integer { let ret = 0; this.executeWithSeedOffset(() => { - ret = Utils.randSeedInt(8) * 5; + ret = Utils.randSeedInt(8, undefined, "Random day/night cycle offset 5 x") * 5; }, 0, this.seed.toString()); return ret; } @@ -1481,7 +1481,7 @@ export default class BattleScene extends SceneBase { isBoss = true; } else { this.executeWithSeedOffset(() => { - isBoss = waveIndex % 10 === 0 || (this.gameMode.hasRandomBosses && Utils.randSeedInt(100) < Math.min(Math.max(Math.ceil((waveIndex - 250) / 50), 0) * 2, 30)); + isBoss = waveIndex % 10 === 0 || (this.gameMode.hasRandomBosses && Utils.randSeedInt(100, undefined, "Boss HP segments") < Math.min(Math.max(Math.ceil((waveIndex - 250) / 50), 0) * 2, 30)); }, waveIndex << 2); } if (!isBoss) { @@ -1819,7 +1819,7 @@ export default class BattleScene extends SceneBase { } return s; }))] : allSpecies.filter(s => s.isCatchable()); - return filteredSpecies[Utils.randSeedInt(filteredSpecies.length)]; + return filteredSpecies[Utils.randSeedInt(filteredSpecies.length, undefined, "Random Species")]; } generateRandomBiome(waveIndex: integer): Biome { @@ -1835,7 +1835,7 @@ export default class BattleScene extends SceneBase { biomeThresholds.push(totalWeight); } - const randInt = Utils.randSeedInt(totalWeight); + const randInt = Utils.randSeedInt(totalWeight, undefined, "Random biome"); for (const biome of biomes) { if (randInt < biomeThresholds[biome]) { @@ -1843,7 +1843,7 @@ export default class BattleScene extends SceneBase { } } - return biomes[Utils.randSeedInt(biomes.length)]; + return biomes[Utils.randSeedInt(biomes.length, undefined, "Random biome (initial roll failed)")]; } isBgmPlaying(): boolean { @@ -2665,7 +2665,7 @@ export default class BattleScene extends SceneBase { pokemonModifierChance = Math.ceil(pokemonModifierChance * this.currentBattle.trainer.getPartyMemberModifierChanceMultiplier(i)); // eslint-disable-line let count = 0; for (let c = 0; c < chances; c++) { - if (!Utils.randSeedInt(modifierChance)) { + if (!Utils.randSeedInt(modifierChance, undefined, "Modifier roll")) { count++; } } @@ -2790,7 +2790,7 @@ export default class BattleScene extends SceneBase { if (mods.length < 1) { return mods; } - const rand = Utils.randSeedInt(mods.length); + const rand = Utils.randSeedInt(mods.length, undefined, "Apply shuffled modifiers"); return [mods[rand], ...shuffleModifiers(mods.filter((_, i) => i !== rand))]; }; modifiers = shuffleModifiers(modifiers); diff --git a/src/battle.ts b/src/battle.ts index 0030b61bbd7..772773bf67d 100644 --- a/src/battle.ts +++ b/src/battle.ts @@ -387,7 +387,7 @@ export default class Battle { * @param min The minimum integer to pick, default `0` * @returns A random integer between {@linkcode min} and ({@linkcode min} + {@linkcode range} - 1) */ - randSeedInt(scene: BattleScene, range: number, min: number = 0, reason: string = "Unlabeled randSeedInt"): number { + randSeedInt(scene: BattleScene, range: number, min: number = 0, reason?: string): number { if (range <= 1) { return min; } @@ -402,8 +402,7 @@ export default class Battle { } scene.rngCounter = this.rngCounter++; scene.rngSeedOverride = this.battleSeed; - const ret = Utils.randSeedInt(range, min); - console.log("[RNG] " + reason, ret) + const ret = Utils.randSeedInt(range, min, reason); this.battleSeedState = Phaser.Math.RND.state(); Phaser.Math.RND.state(state); //scene.setScoreText("RNG: " + tempRngCounter + " (Last sim: " + this.rngCounter + ")") @@ -474,7 +473,7 @@ function getRandomTrainerFunc(trainerPool: (TrainerType | TrainerType[])[], rand scene.executeWithSeedOffset(() => { for (const trainerPoolEntry of trainerPool) { const trainerType = Array.isArray(trainerPoolEntry) - ? Utils.randSeedItem(trainerPoolEntry) + ? Utils.randSeedItem(trainerPoolEntry, "Random trainer helper function") : trainerPoolEntry; trainerTypes.push(trainerType); } @@ -482,7 +481,7 @@ function getRandomTrainerFunc(trainerPool: (TrainerType | TrainerType[])[], rand let trainerGender = TrainerVariant.DEFAULT; if (randomGender) { - trainerGender = (Utils.randInt(2) === 0) ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT; + trainerGender = (Utils.randInt(2, undefined, "Random trainer helper function") === 0) ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT; } /* 1/3 chance for evil team grunts to be double battles */ @@ -490,7 +489,7 @@ function getRandomTrainerFunc(trainerPool: (TrainerType | TrainerType[])[], rand const isEvilTeamGrunt = evilTeamGrunts.includes(trainerTypes[rand]); if (trainerConfigs[trainerTypes[rand]].hasDouble && isEvilTeamGrunt) { - return new Trainer(scene, trainerTypes[rand], (Utils.randInt(3) === 0) ? TrainerVariant.DOUBLE : trainerGender); + return new Trainer(scene, trainerTypes[rand], (Utils.randInt(3, undefined, "Evil grunt selection") === 0) ? TrainerVariant.DOUBLE : trainerGender); } return new Trainer(scene, trainerTypes[rand], trainerGender); @@ -511,7 +510,7 @@ export interface FixedBattleConfigs { */ export const classicFixedBattles: FixedBattleConfigs = { [5]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) - .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.YOUNGSTER, Utils.randSeedInt(2) ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)), + .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.YOUNGSTER, Utils.randSeedInt(2, undefined, "Youngster gender") ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)), [8]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)), [25]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) diff --git a/src/data/ability.ts b/src/data/ability.ts index b284ecdbc38..25bffda6f81 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -859,7 +859,7 @@ export class PostDefendContactApplyStatusEffectAbAttr extends PostDefendAbAttr { applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.status && (this.chance === -1 || pokemon.randSeedInt(100, undefined, "Random chance to apply effect after something makes contact") < this.chance)) { - const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length, undefined, "Selecting an effect to apply")]; + const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length, undefined, "Choosing status to apply")]; if (simulated) { return attacker.canSetStatus(effect, true, false, pokemon); } else { @@ -1674,7 +1674,7 @@ export class PostAttackApplyStatusEffectAbAttr extends PostAttackAbAttr { applyPostAttackAfterMoveTypeCheck(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { /**Status inflicted by abilities post attacking are also considered additional effects.*/ if (!attacker.hasAbilityWithAttr(IgnoreMoveEffectsAbAttr) && !simulated && pokemon !== attacker && (!this.contactRequired || move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) && pokemon.randSeedInt(100, undefined, "Chance to apply status after attacking") < this.chance && !pokemon.status) { - const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length, undefined, "Selecting a status to apply")]; + const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length, undefined, "Choosing effect to apply")]; return attacker.trySetStatus(effect, true, pokemon); } @@ -1727,7 +1727,7 @@ export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr { if (!simulated && hitResult < HitResult.NO_EFFECT && (!this.condition || this.condition(pokemon, attacker, move))) { const heldItems = this.getTargetHeldItems(attacker).filter(i => i.isTransferrable); if (heldItems.length) { - const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length, undefined, "Choosing an item to steal")]; + const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length, undefined, "Choosing item to steal (guaranteed steal)")]; pokemon.scene.tryTransferHeldItemModifier(stolenItem, pokemon, false).then(success => { if (success) { pokemon.scene.queueMessage(i18next.t("abilityTriggers:postDefendStealHeldItem", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), attackerName: attacker.name, stolenItemType: stolenItem.type.name })); @@ -2222,7 +2222,7 @@ export class PostSummonCopyAbilityAbAttr extends PostSummonAbAttr { let target: Pokemon; if (targets.length > 1) { - pokemon.scene.executeWithSeedOffset(() => target = Utils.randSeedItem(targets), pokemon.scene.currentBattle.waveIndex); + pokemon.scene.executeWithSeedOffset(() => target = Utils.randSeedItem(targets, "Target to copy ability from"), pokemon.scene.currentBattle.waveIndex); } else { target = targets[0]; } @@ -2343,7 +2343,7 @@ export class PostSummonTransformAbAttr extends PostSummonAbAttr { let target: Pokemon; if (targets.length > 1) { - pokemon.scene.executeWithSeedOffset(() => target = Utils.randSeedItem(targets), pokemon.scene.currentBattle.waveIndex); + pokemon.scene.executeWithSeedOffset(() => target = Utils.randSeedItem(targets, "Target to transform into"), pokemon.scene.currentBattle.waveIndex); } else { target = targets[0]; } @@ -2642,7 +2642,7 @@ export class ConfusionOnStatusEffectAbAttr extends PostAttackAbAttr { if (simulated) { return defender.canAddTag(BattlerTagType.CONFUSED); } else { - return defender.addTag(BattlerTagType.CONFUSED, pokemon.randSeedIntRange(2, 5, "Duration of Confusion effect"), move.id, defender.id); + return defender.addTag(BattlerTagType.CONFUSED, pokemon.randSeedIntRange(2, 5, "Chance to apply effect after attacking"), move.id, defender.id); } } return false; @@ -3413,7 +3413,7 @@ export class PostTurnLootAbAttr extends PostTurnAbAttr { return true; } - const randomIdx = Utils.randSeedInt(berriesEaten.length); + const randomIdx = Utils.randSeedInt(berriesEaten.length, undefined, "Randomly select a berry to regenerate"); const chosenBerryType = berriesEaten[randomIdx]; const chosenBerry = new BerryModifierType(chosenBerryType); berriesEaten.splice(randomIdx); // Remove berry from memory @@ -3466,12 +3466,12 @@ export class MoodyAbAttr extends PostTurnAbAttr { if (!simulated) { if (canRaise.length > 0) { - const raisedStat = canRaise[pokemon.randSeedInt(canRaise.length)]; + const raisedStat = canRaise[pokemon.randSeedInt(canRaise.length, undefined, "Choosing a random raisable stat to increase")]; canLower = canRaise.filter(s => s !== raisedStat); pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ raisedStat ], 2)); } if (canLower.length > 0) { - const loweredStat = canLower[pokemon.randSeedInt(canLower.length)]; + const loweredStat = canLower[pokemon.randSeedInt(canLower.length, undefined, "Choosing a random lowerable stat to decrease")]; pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ loweredStat ], -1)); } } @@ -3909,7 +3909,7 @@ export class PostBattleLootAbAttr extends PostBattleAbAttr { applyPostBattle(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean { const postBattleLoot = pokemon.scene.currentBattle.postBattleLoot; if (!simulated && postBattleLoot.length) { - const randItem = Utils.randSeedItem(postBattleLoot); + const randItem = Utils.randSeedItem(postBattleLoot, "Randomly selecting item to Pickup"); //@ts-ignore - TODO see below if (pokemon.scene.tryTransferHeldItemModifier(randItem, pokemon, true, 1, true)) { // TODO: fix. This is a promise!? postBattleLoot.splice(postBattleLoot.indexOf(randItem), 1); @@ -5032,7 +5032,7 @@ export function initAbilities() { .bypassFaint() .ignorable(), new Ability(Abilities.SHED_SKIN, 3) - .conditionalAttr(pokemon => !Utils.randSeedInt(3), PostTurnResetStatusAbAttr), + .conditionalAttr(pokemon => !Utils.randSeedInt(3, undefined, "Random chance to activate Shed Skin"), PostTurnResetStatusAbAttr), new Ability(Abilities.GUTS, 3) .attr(BypassBurnDamageReductionAbAttr) .conditionalAttr(pokemon => !!pokemon.status || pokemon.hasAbility(Abilities.COMATOSE), StatMultiplierAbAttr, Stat.ATK, 1.5), @@ -5247,7 +5247,7 @@ export function initAbilities() { .attr(PostDefendMoveDisableAbAttr, 30) .bypassFaint(), new Ability(Abilities.HEALER, 5) - .conditionalAttr(pokemon => pokemon.getAlly() && Utils.randSeedInt(10) < 3, PostTurnResetStatusAbAttr, true), + .conditionalAttr(pokemon => pokemon.getAlly() && Utils.randSeedInt(10, undefined, "Random chance to apply Healer") < 3, PostTurnResetStatusAbAttr, true), new Ability(Abilities.FRIEND_GUARD, 5) .ignorable() .unimplemented(), diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index 2fbee025348..6807af4c209 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -483,7 +483,7 @@ export class ConfusedTag extends BattlerTag { pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.getBattlerIndex(), undefined, CommonAnim.CONFUSION)); // 1/3 chance of hitting self with a 40 base power move - if (pokemon.randSeedInt(3, undefined, "Self-hit confusion roll") === 0) { + if (pokemon.randSeedInt(3, undefined, "Confusion chance") === 0) { const atk = pokemon.getEffectiveStat(Stat.ATK); const def = pokemon.getEffectiveStat(Stat.DEF); const damage = Utils.toDmgValue(((((2 * pokemon.level / 5 + 2) * 40 * atk / def) / 50) + 2) * (pokemon.randSeedIntRange(85, 100, "Damage roll for Confusion") / 100)); diff --git a/src/data/berry.ts b/src/data/berry.ts index 01325ee39dd..eabe93ce110 100644 --- a/src/data/berry.ts +++ b/src/data/berry.ts @@ -114,7 +114,7 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc { if (pokemon.battleData) { pokemon.battleData.berriesEaten.push(berryType); } - const randStat = Utils.randSeedInt(Stat.SPD, Stat.ATK); + const randStat = Utils.randSeedInt(Stat.SPD, Stat.ATK, "Randomly selecting a stat to raise"); const stages = new Utils.NumberHolder(2); applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, stages); pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ randStat ], stages.value)); diff --git a/src/data/biomes.ts b/src/data/biomes.ts index 0e37cc94ff5..a2b63034886 100644 --- a/src/data/biomes.ts +++ b/src/data/biomes.ts @@ -7666,7 +7666,7 @@ export function initBiomes() { if (biome === Biome.END) { const biomeList = Object.keys(Biome).filter(key => !isNaN(Number(key))); biomeList.pop(); // Removes Biome.END from the list - const randIndex = Utils.randInt(biomeList.length, 1); // Will never be Biome.TOWN + const randIndex = Utils.randInt(biomeList.length, 1, "Traversing biomes"); // Will never be Biome.TOWN biome = Biome[biomeList[randIndex]]; } const linkedBiomes: (Biome | [ Biome, integer ])[] = Array.isArray(biomeLinks[biome]) diff --git a/src/data/daily-run.ts b/src/data/daily-run.ts index 370b13ea3a3..801640a5549 100644 --- a/src/data/daily-run.ts +++ b/src/data/daily-run.ts @@ -49,7 +49,7 @@ export function getDailyRunStarters(scene: BattleScene, seed: string): Starter[] const costSpecies = Object.keys(speciesStarters) .map(s => parseInt(s) as Species) .filter(s => speciesStarters[s] === cost); - const randPkmSpecies = getPokemonSpecies(Utils.randSeedItem(costSpecies)); + const randPkmSpecies = getPokemonSpecies(Utils.randSeedItem(costSpecies, "Daily starters")); const starterSpecies = getPokemonSpecies(randPkmSpecies.getTrainerSpeciesForLevel(startingLevel, true, PartyMemberStrength.STRONGER)); starters.push(getDailyRunStarter(scene, starterSpecies, startingLevel)); } diff --git a/src/data/egg.ts b/src/data/egg.ts index ce27030ebef..ee73b65c4d0 100644 --- a/src/data/egg.ts +++ b/src/data/egg.ts @@ -151,7 +151,7 @@ export class Egg { this.checkForPityTierOverrides(eggOptions.scene!); // TODO: is this bang correct? } - this._id = eggOptions?.id ?? Utils.randInt(EGG_SEED, EGG_SEED * this._tier); + this._id = eggOptions?.id ?? Utils.randInt(EGG_SEED, EGG_SEED * this._tier, "eg"); this._sourceType = eggOptions?.sourceType ?? undefined; this._hatchWaves = eggOptions?.hatchWaves ?? this.getEggTierDefaultHatchWaves(); @@ -223,14 +223,14 @@ export class Egg { let pokemonSpecies = getPokemonSpecies(this._species); // Special condition to have Phione eggs also have a chance of generating Manaphy if (this._species === Species.PHIONE) { - pokemonSpecies = getPokemonSpecies(Utils.randSeedInt(MANAPHY_EGG_MANAPHY_RATE) ? Species.PHIONE : Species.MANAPHY); + pokemonSpecies = getPokemonSpecies(Utils.randSeedInt(MANAPHY_EGG_MANAPHY_RATE, undefined, "Chance of Manaphy Egg not scamming you") ? Species.PHIONE : Species.MANAPHY); } // Sets the hidden ability if a hidden ability exists and // the override is set or the egg hits the chance let abilityIndex: number | undefined = undefined; - const sameSpeciesEggHACheck = (this._sourceType === EggSourceType.SAME_SPECIES_EGG && !Utils.randSeedInt(SAME_SPECIES_EGG_HA_RATE)); - const gachaEggHACheck = (!(this._sourceType === EggSourceType.SAME_SPECIES_EGG) && !Utils.randSeedInt(GACHA_EGG_HA_RATE)); + const sameSpeciesEggHACheck = (this._sourceType === EggSourceType.SAME_SPECIES_EGG && !Utils.randSeedInt(SAME_SPECIES_EGG_HA_RATE, undefined, "Hidden Ability chance (Candy egg)")); + const gachaEggHACheck = (!(this._sourceType === EggSourceType.SAME_SPECIES_EGG) && !Utils.randSeedInt(GACHA_EGG_HA_RATE, undefined, "Hidden Ability chance (Gacha)")); if (pokemonSpecies.abilityHidden && (this._overrideHiddenAbility || sameSpeciesEggHACheck || gachaEggHACheck)) { abilityIndex = 2; } @@ -240,7 +240,7 @@ export class Egg { ret.shiny = this._isShiny; ret.variant = this._variantTier; - const secondaryIvs = Utils.getIvsFromId(Utils.randSeedInt(4294967295)); + const secondaryIvs = Utils.getIvsFromId(Utils.randSeedInt(4294967295, undefined, "Egg IVs")); for (let s = 0; s < ret.ivs.length; s++) { ret.ivs[s] = Math.max(ret.ivs[s], secondaryIvs[s]); diff --git a/src/data/move.ts b/src/data/move.ts index e128e3d54b6..7b19aca5bdd 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -1980,6 +1980,13 @@ export class StatusEffectAttr extends MoveEffectAttr { return false; } } + + if (user !== target && target.scene.arena.getTagOnSide(ArenaTagType.SAFEGUARD, target.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY)) { + if (move.category === MoveCategory.STATUS) { + user.scene.queueMessage(i18next.t("moveTriggers:safeguard", { targetName: getPokemonNameWithAffix(target)})); + } + return false; + } if ((!pokemon.status || (pokemon.status.effect === this.effect && moveChance < 0)) && pokemon.trySetStatus(this.effect, true, user, this.cureTurn)) { applyPostAttackAbAttrs(ConfusionOnStatusEffectAbAttr, user, target, move, null, false, this.effect); @@ -2004,7 +2011,7 @@ export class MultiStatusEffectAttr extends StatusEffectAttr { } apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - this.effect = Utils.randSeedItem(this.effects); + this.effect = Utils.randSeedItem(this.effects, "Selecting status effect to apply"); const result = super.apply(user, target, move, args); return result; } @@ -2080,6 +2087,7 @@ export class StealHeldItemChanceAttr extends MoveEffectAttr { } //*/ + console.log("realInRange direct call @ StealHeldItemChanceAttr: " + rand) if (rand >= this.chance) { return resolve(false); } @@ -2632,7 +2640,7 @@ export class StatStageChangeAttr extends MoveEffectAttr { } const moveChance = this.getMoveChance(user, target, move, this.selfTarget, true); - if (moveChance < 0 || moveChance === 100 || user.randSeedInt(100, undefined, "Chance to apply status condition") < moveChance) { + if (moveChance < 0 || moveChance === 100 || user.randSeedInt(100, undefined, "Random chance to raise stat") < moveChance) { const stages = this.getLevels(user); user.scene.unshiftPhase(new StatStageChangePhase(user.scene, (this.selfTarget ? user : target).getBattlerIndex(), this.selfTarget, this.stats, stages, this.showMessage)); return true; @@ -2718,7 +2726,7 @@ export class AcupressureStatStageChangeAttr extends MoveEffectAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean | Promise { const randStats = BATTLE_STATS.filter(s => target.getStatStage(s) < 6); if (randStats.length > 0) { - const boostStat = [randStats[user.randSeedInt(randStats.length)]]; + const boostStat = [randStats[user.randSeedInt(randStats.length, undefined, "Choosing stat to raise")]]; user.scene.unshiftPhase(new StatStageChangePhase(user.scene, target.getBattlerIndex(), this.selfTarget, boostStat, 2)); return true; } @@ -3051,7 +3059,7 @@ export class BeatUpAttr extends VariablePowerAttr { const doublePowerChanceMessageFunc = (user: Pokemon, target: Pokemon, move: Move) => { let message: string = ""; user.scene.executeWithSeedOffset(() => { - const rand = Utils.randSeedInt(100); + const rand = Utils.randSeedInt(100, undefined, "Doubled power chance (applying message)"); if (rand < move.chance) { message = i18next.t("moveTriggers:goingAllOutForAttack", {pokemonName: getPokemonNameWithAffix(user)}); } @@ -3062,7 +3070,7 @@ const doublePowerChanceMessageFunc = (user: Pokemon, target: Pokemon, move: Move export class DoublePowerChanceAttr extends VariablePowerAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { let rand: integer; - user.scene.executeWithSeedOffset(() => rand = Utils.randSeedInt(100), user.scene.currentBattle.turn << 6, user.scene.waveSeed); + user.scene.executeWithSeedOffset(() => rand = Utils.randSeedInt(100, undefined, "Doubled power chance (applying move)"), user.scene.currentBattle.turn << 6, user.scene.waveSeed); if (rand! < move.chance) { const power = args[0] as Utils.NumberHolder; power.value *= 2; @@ -3323,7 +3331,7 @@ const magnitudeMessageFunc = (user: Pokemon, target: Pokemon, move: Move) => { user.scene.executeWithSeedOffset(() => { const magnitudeThresholds = [ 5, 15, 35, 65, 75, 95 ]; - const rand = Utils.randSeedInt(100); + const rand = Utils.randSeedInt(100, undefined, "Magnitude selection (message)"); let m = 0; for (; m < magnitudeThresholds.length; m++) { @@ -3346,7 +3354,7 @@ export class MagnitudePowerAttr extends VariablePowerAttr { let rand: integer; - user.scene.executeWithSeedOffset(() => rand = Utils.randSeedInt(100), user.scene.currentBattle.turn << 6, user.scene.waveSeed); + user.scene.executeWithSeedOffset(() => rand = Utils.randSeedInt(100, undefined, "Magnitude selection (move)"), user.scene.currentBattle.turn << 6, user.scene.waveSeed); let m = 0; for (; m < magnitudeThresholds.length; m++) { @@ -3471,7 +3479,7 @@ export class PresentPowerAttr extends VariablePowerAttr { */ const firstHit = (user.turnData.hitCount === user.turnData.hitsLeft); - const powerSeed = Utils.randSeedInt(firstHit ? 100 : 80); + const powerSeed = Utils.randSeedInt(firstHit ? 100 : 80, undefined, "Present healing chance"); if (powerSeed <= 40) { (args[0] as Utils.NumberHolder).value = 40; } else if (40 < powerSeed && powerSeed <= 70) { @@ -3919,7 +3927,7 @@ export class ShellSideArmCategoryAttr extends VariableMoveCategoryAttr { } else if (atkRatio === specialRatio && args[1] == "SIM") { category.value = MoveCategory.PHYSICAL; return true; - } else if (atkRatio === specialRatio && user.randSeedInt(2, undefined, "Randomly selecting an attack type for Shell Side Arm") === 0) { + } else if (atkRatio === specialRatio && user.randSeedInt(2, undefined, "Random category for Shell Side Arm") === 0) { category.value = MoveCategory.PHYSICAL; return true; } @@ -4394,7 +4402,7 @@ export class FrenzyAttr extends MoveEffectAttr { } if (!user.getTag(BattlerTagType.FRENZY) && !user.getMoveQueue().length) { - const turnCount = user.randSeedIntRange(1, 2, "Frenzy targeting"); + const turnCount = user.randSeedIntRange(1, 2, "Frenzy duration"); new Array(turnCount).fill(null).map(() => user.getMoveQueue().push({ move: move.id, targets: [ target.getBattlerIndex() ], ignorePP: true })); user.addTag(BattlerTagType.FRENZY, turnCount, move.id, user.id); } else { @@ -4446,8 +4454,8 @@ export class AddBattlerTagAttr extends MoveEffectAttr { } const moveChance = this.getMoveChance(user, target, move, this.selfTarget, true); - if (moveChance < 0 || moveChance === 100 || user.randSeedInt(100, undefined, "Chance to apply battler tag") < moveChance) { - return (this.selfTarget ? user : target).addTag(this.tagType, user.randSeedIntRange(this.turnCountMin, this.turnCountMax, "Duration of effect"), move.id, user.id); + if (moveChance < 0 || moveChance === 100 || user.randSeedInt(100, undefined, "Chance to add Battler Tag") < moveChance) { + return (this.selfTarget ? user : target).addTag(this.tagType, user.randSeedIntRange(this.turnCountMin, this.turnCountMax, "Battler Tag duration"), move.id, user.id); } return false; @@ -4572,7 +4580,7 @@ export class JawLockAttr extends AddBattlerTagAttr { } const moveChance = this.getMoveChance(user, target, move, this.selfTarget); - if (moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance) { + if (moveChance < 0 || moveChance === 100 || user.randSeedInt(100, undefined, "Chance to apply Trap tag (Jaw Lock)") < moveChance) { /** * Add the tag to both the user and the target. * The target's tag source is considered to be the user and vice versa @@ -4666,6 +4674,17 @@ export class ConfuseAttr extends AddBattlerTagAttr { constructor(selfTarget?: boolean) { super(BattlerTagType.CONFUSED, selfTarget, false, 2, 5); } + + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + if (!this.selfTarget && target.scene.arena.getTagOnSide(ArenaTagType.SAFEGUARD, target.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY)) { + if (move.category === MoveCategory.STATUS) { + user.scene.queueMessage(i18next.t("moveTriggers:safeguard", { targetName: getPokemonNameWithAffix(target)})); + } + return false; + } + + return super.apply(user, target, move, args); + } } export class RechargeAttr extends AddBattlerTagAttr { @@ -4699,7 +4718,7 @@ export class ProtectAttr extends AddBattlerTagAttr { timesUsed++; } if (timesUsed) { - return !user.randSeedInt(Math.pow(3, timesUsed), undefined, "Chance for Protect-like move to fail"); + return !user.randSeedInt(Math.pow(3, timesUsed), undefined, "Chance for Protection move to succeed"); } return true; }); @@ -4855,7 +4874,7 @@ export class AddArenaTrapTagHitAttr extends AddArenaTagAttr { const moveChance = this.getMoveChance(user, target, move, this.selfTarget, true); const side = (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; const tag = user.scene.arena.getTagOnSide(this.tagType, side) as ArenaTrapTag; - if ((moveChance < 0 || moveChance === 100 || user.randSeedInt(100, undefined, "Chance to apply trap") < moveChance) && user.getLastXMoves(1)[0].result === MoveResult.SUCCESS) { + if ((moveChance < 0 || moveChance === 100 || user.randSeedInt(100, undefined, "Chance to add arena tag on hit") < moveChance) && user.getLastXMoves(1)[0].result === MoveResult.SUCCESS) { user.scene.arena.addTag(this.tagType, 0, move.id, user.id, side); if (!tag) { return true; @@ -5009,7 +5028,7 @@ export class RevivalBlessingAttr extends MoveEffectAttr { && user.scene.getEnemyParty().findIndex(p => p.isFainted() && !p.isBoss()) > -1) { // Selects a random fainted pokemon const faintedPokemon = user.scene.getEnemyParty().filter(p => p.isFainted() && !p.isBoss()); - const pokemon = faintedPokemon[user.randSeedInt(faintedPokemon.length, undefined, "Randomly selecting a Pokemon to revive")]; + const pokemon = faintedPokemon[user.randSeedInt(faintedPokemon.length, undefined, "Choosing Pokemon to revive")]; const slotIndex = user.scene.getEnemyParty().findIndex(p => pokemon.id === p.id); pokemon.resetStatus(); pokemon.heal(Math.min(Utils.toDmgValue(0.5 * pokemon.getMaxHp()), pokemon.getMaxHp())); @@ -5319,7 +5338,7 @@ export class RandomMovesetMoveAttr extends OverrideMoveEffectAttr { const moveset = (!this.enemyMoveset ? user : target).getMoveset(); const moves = moveset.filter(m => !m?.getMove().hasFlag(MoveFlags.IGNORE_VIRTUAL)); if (moves.length) { - const move = moves[user.randSeedInt(moves.length, undefined, "Randomly selecting a known move")]; + const move = moves[user.randSeedInt(moves.length, undefined, "Choosing random move from moveset")]; const moveIndex = moveset.findIndex(m => m?.moveId === move?.moveId); const moveTargets = getMoveTargets(user, move?.moveId!); // TODO: is this bang correct? if (!moveTargets.targets.length) { @@ -6373,7 +6392,7 @@ export class ResistLastMoveTypeAttr extends MoveEffectAttr { if (!validTypes.length) { return false; } - const type = validTypes[user.randSeedInt(validTypes.length, undefined, "Randomly selecting a type for Conversion2 that resists Type." + Utils.getEnumKeys(Type)[moveData.type])]; + const type = validTypes[user.randSeedInt(validTypes.length, undefined, "Choosing type to transform into (Conversion2)")]; user.summonData.types = [ type ]; user.scene.queueMessage(i18next.t("battle:transformedIntoType", {pokemonName: getPokemonNameWithAffix(user), type: Utils.toReadableString(Type[type])})); user.updateInfo(); @@ -7126,7 +7145,7 @@ export function initMoves() { .attr(FriendshipPowerAttr, true), new StatusMove(Moves.SAFEGUARD, Type.NORMAL, -1, 25, -1, 0, 2) .target(MoveTarget.USER_SIDE) - .unimplemented(), + .attr(AddArenaTagAttr, ArenaTagType.SAFEGUARD, 5, true, true), new StatusMove(Moves.PAIN_SPLIT, Type.NORMAL, -1, 20, -1, 0, 2) .attr(HpSplitAttr) .condition(failOnBossCondition), @@ -7315,7 +7334,7 @@ export function initMoves() { .attr(RemoveScreensAttr), new StatusMove(Moves.YAWN, Type.NORMAL, -1, 10, -1, 0, 3) .attr(AddBattlerTagAttr, BattlerTagType.DROWSY, false, true) - .condition((user, target, move) => !target.status), + .condition((user, target, move) => !target.status && !target.scene.arena.getTagOnSide(ArenaTagType.SAFEGUARD, target.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY)), new AttackMove(Moves.KNOCK_OFF, Type.DARK, MoveCategory.PHYSICAL, 65, 100, 20, -1, 0, 3) .attr(MovePowerMultiplierAttr, (user, target, move) => target.getHeldItems().filter(i => i.isTransferrable).length > 0 ? 1.5 : 1) .attr(RemoveHeldItemAttr, false), @@ -8866,8 +8885,8 @@ export function initMoves() { new AttackMove(Moves.SKITTER_SMACK, Type.BUG, MoveCategory.PHYSICAL, 70, 90, 10, 100, 0, 8) .attr(StatStageChangeAttr, [ Stat.SPATK ], -1), new AttackMove(Moves.BURNING_JEALOUSY, Type.FIRE, MoveCategory.SPECIAL, 70, 100, 5, 100, 0, 8) - .target(MoveTarget.ALL_NEAR_ENEMIES) - .partial(), + .attr(StatusIfBoostedAttr, StatusEffect.BURN) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.LASH_OUT, Type.DARK, MoveCategory.PHYSICAL, 75, 100, 5, -1, 0, 8) .attr(MovePowerMultiplierAttr, (user, _target, _move) => user.turnData.statStagesDecreased ? 2 : 1), new AttackMove(Moves.POLTERGEIST, Type.GHOST, MoveCategory.PHYSICAL, 110, 90, 5, -1, 0, 8) @@ -9316,12 +9335,11 @@ export function initMoves() { new AttackMove(Moves.HARD_PRESS, Type.STEEL, MoveCategory.PHYSICAL, -1, 100, 10, -1, 0, 9) .attr(OpponentHighHpPowerAttr, 100), new StatusMove(Moves.DRAGON_CHEER, Type.DRAGON, -1, 15, -1, 0, 9) - .attr(AddBattlerTagAttr, BattlerTagType.CRIT_BOOST, false, true) - .target(MoveTarget.NEAR_ALLY) - .partial(), + .attr(AddBattlerTagAttr, BattlerTagType.DRAGON_CHEER, false, true) + .target(MoveTarget.NEAR_ALLY), new AttackMove(Moves.ALLURING_VOICE, Type.FAIRY, MoveCategory.SPECIAL, 80, 100, 10, -1, 0, 9) - .soundBased() - .partial(), + .attr(AddBattlerTagIfBoostedAttr, BattlerTagType.CONFUSED) + .soundBased(), new AttackMove(Moves.TEMPER_FLARE, Type.FIRE, MoveCategory.PHYSICAL, 75, 100, 10, -1, 0, 9) .attr(MovePowerMultiplierAttr, (user, target, move) => user.getLastXMoves(2)[1]?.result === MoveResult.MISS || user.getLastXMoves(2)[1]?.result === MoveResult.FAIL ? 2 : 1), new AttackMove(Moves.SUPERCELL_SLAM, Type.ELECTRIC, MoveCategory.PHYSICAL, 100, 95, 15, -1, 0, 9) @@ -9344,4 +9362,4 @@ export function initMoves() { selfStatLowerMoves.push(m.id); } }); -} \ No newline at end of file +} diff --git a/src/data/pokemon-evolutions.ts b/src/data/pokemon-evolutions.ts index dd0942756b1..87458dbfdc9 100644 --- a/src/data/pokemon-evolutions.ts +++ b/src/data/pokemon-evolutions.ts @@ -1157,7 +1157,7 @@ export const pokemonEvolutions: PokemonEvolutions = { [Species.TANDEMAUS]: [ new SpeciesFormEvolution(Species.MAUSHOLD, "", "three", 25, null, new SpeciesEvolutionCondition(p => { let ret = false; - p.scene.executeWithSeedOffset(() => ret = !Utils.randSeedInt(4), p.id); + p.scene.executeWithSeedOffset(() => ret = !Utils.randSeedInt(4, undefined, "Tandemaus form selection"), p.id); return ret; })), new SpeciesEvolution(Species.MAUSHOLD, 25, null, null) @@ -1325,7 +1325,7 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesFormEvolution(Species.DUDUNSPARCE, "", "three-segment", 32, null, new SpeciesEvolutionCondition(p => { let ret = false; if (p.moveset.filter(m => m?.moveId === Moves.HYPER_DRILL).length > 0) { - p.scene.executeWithSeedOffset(() => ret = !Utils.randSeedInt(4), p.id); + p.scene.executeWithSeedOffset(() => ret = !Utils.randSeedInt(4, undefined, "Dudunsparce form selection"), p.id); } return ret; }), SpeciesWildEvolutionDelay.LONG), diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index 0c30582fa39..e79595d5119 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -761,7 +761,7 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali return this.speciesId; } - const randValue = evolutionPool.size === 1 ? 0 : Utils.randSeedInt(totalWeight); + const randValue = evolutionPool.size === 1 ? 0 : Utils.randSeedInt(totalWeight, undefined, "Random levelled species"); for (const weight of evolutionPool.keys()) { if (randValue < weight) { @@ -3340,7 +3340,7 @@ export function getPokerusStarters(scene: BattleScene): PokemonSpecies[] { date.setUTCHours(0, 0, 0, 0); scene.executeWithSeedOffset(() => { while (pokerusStarters.length < starterCount) { - const randomSpeciesId = parseInt(Utils.randSeedItem(Object.keys(speciesStarters)), 10); + const randomSpeciesId = parseInt(Utils.randSeedItem(Object.keys(speciesStarters), "Get Pokerus starters"), 10); const species = getPokemonSpecies(randomSpeciesId); if (!pokerusStarters.includes(species)) { pokerusStarters.push(species); diff --git a/src/data/trainer-config.ts b/src/data/trainer-config.ts index a6cf4247f27..30d391f60fd 100644 --- a/src/data/trainer-config.ts +++ b/src/data/trainer-config.ts @@ -994,7 +994,7 @@ function getGymLeaderPartyTemplate(scene: BattleScene) { function getRandomPartyMemberFunc(speciesPool: Species[], trainerSlot: TrainerSlot = TrainerSlot.TRAINER, ignoreEvolution: boolean = false, postProcess?: (enemyPokemon: EnemyPokemon) => void): PartyMemberFunc { return (scene: BattleScene, level: integer, strength: PartyMemberStrength) => { - let species = Utils.randSeedItem(speciesPool); + let species = Utils.randSeedItem(speciesPool, "Get random party member"); if (!ignoreEvolution) { species = getPokemonSpecies(species).getTrainerSpeciesForLevel(level, true, strength, scene.currentBattle.waveIndex); } @@ -1015,9 +1015,9 @@ function getRandomTeraModifiers(party: EnemyPokemon[], count: integer, types?: T const ret: PersistentModifier[] = []; const partyMemberIndexes = new Array(party.length).fill(null).map((_, i) => i); for (let t = 0; t < Math.min(count, party.length); t++) { - const randomIndex = Utils.randSeedItem(partyMemberIndexes); + const randomIndex = Utils.randSeedItem(partyMemberIndexes, "Get random tera modifiers"); partyMemberIndexes.splice(partyMemberIndexes.indexOf(randomIndex), 1); - ret.push(modifierTypes.TERA_SHARD().generateType([], [Utils.randSeedItem(types ? types : party[randomIndex].getTypes())])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(party[randomIndex]) as PersistentModifier); // TODO: is the bang correct? + ret.push(modifierTypes.TERA_SHARD().generateType([], [Utils.randSeedItem(types ? types : party[randomIndex].getTypes(), "Selecting Tera Type")])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(party[randomIndex]) as PersistentModifier); // TODO: is the bang correct? } return ret; } @@ -1868,7 +1868,7 @@ export const trainerConfigs: TrainerConfigs = { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; - p.formIndex = Utils.randSeedInt(5); + p.formIndex = Utils.randSeedInt(5, undefined, "Random form for Genesect"); })) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BASCULEGION, Species.JELLICENT ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); diff --git a/src/data/weather.ts b/src/data/weather.ts index afdd0a958cf..06665e5ab98 100644 --- a/src/data/weather.ts +++ b/src/data/weather.ts @@ -378,7 +378,7 @@ export function getRandomWeatherType(arena: any /* Importing from arena causes a let totalWeight = 0; weatherPool.forEach(w => totalWeight += w.weight); - const rand = Utils.randSeedInt(totalWeight); + const rand = Utils.randSeedInt(totalWeight, undefined, "Weather selection"); let w = 0; for (const weather of weatherPool) { w += weather.weight; diff --git a/src/field/arena.ts b/src/field/arena.ts index de4a9a87ebf..2f0ba3f3cb2 100644 --- a/src/field/arena.ts +++ b/src/field/arena.ts @@ -90,7 +90,7 @@ export class Arena { if (typeof luckValue !== "undefined") { luckModifier = luckValue * (isBoss ? 0.5 : 2); } - const tierValue = Utils.randSeedInt(randVal - luckModifier); + const tierValue = Utils.randSeedInt(randVal - luckModifier, undefined, "Selecting rarity tier for encounter"); let tier = !isBoss ? tierValue >= 156 ? BiomePoolTier.COMMON : tierValue >= 32 ? BiomePoolTier.UNCOMMON : tierValue >= 6 ? BiomePoolTier.RARE : tierValue >= 1 ? BiomePoolTier.SUPER_RARE : BiomePoolTier.ULTRA_RARE : tierValue >= 20 ? BiomePoolTier.BOSS : tierValue >= 6 ? BiomePoolTier.BOSS_RARE : tierValue >= 1 ? BiomePoolTier.BOSS_SUPER_RARE : BiomePoolTier.BOSS_ULTRA_RARE; @@ -118,7 +118,7 @@ export class Arena { if (!tierPool.length) { ret = this.scene.randomSpecies(waveIndex, level); } else { - const entry = tierPool[Utils.randSeedInt(tierPool.length)]; + const entry = tierPool[Utils.randSeedInt(tierPool.length, undefined, "Selecting rarity tier but for real this time")]; let species: Species; if (typeof entry === "number") { species = entry as Species; @@ -129,7 +129,7 @@ export class Arena { if (level >= levelThreshold) { const speciesIds = entry[levelThreshold]; if (speciesIds.length > 1) { - species = speciesIds[Utils.randSeedInt(speciesIds.length)]; + species = speciesIds[Utils.randSeedInt(speciesIds.length, undefined, "Randomly selecting encounter species")]; } else { species = speciesIds[0]; } @@ -175,7 +175,7 @@ export class Arena { const isBoss = !!this.trainerPool[BiomePoolTier.BOSS].length && this.scene.gameMode.isTrainerBoss(waveIndex, this.biomeType, this.scene.offsetGym); console.log(isBoss, this.trainerPool); - const tierValue = Utils.randSeedInt(!isBoss ? 512 : 64); + const tierValue = Utils.randSeedInt(!isBoss ? 512 : 64, undefined, "Selecting random trainer"); let tier = !isBoss ? tierValue >= 156 ? BiomePoolTier.COMMON : tierValue >= 32 ? BiomePoolTier.UNCOMMON : tierValue >= 6 ? BiomePoolTier.RARE : tierValue >= 1 ? BiomePoolTier.SUPER_RARE : BiomePoolTier.ULTRA_RARE : tierValue >= 20 ? BiomePoolTier.BOSS : tierValue >= 6 ? BiomePoolTier.BOSS_RARE : tierValue >= 1 ? BiomePoolTier.BOSS_SUPER_RARE : BiomePoolTier.BOSS_ULTRA_RARE; @@ -185,7 +185,7 @@ export class Arena { tier--; } const tierPool = this.trainerPool[tier] || []; - return !tierPool.length ? TrainerType.BREEDER : tierPool[Utils.randSeedInt(tierPool.length)]; + return !tierPool.length ? TrainerType.BREEDER : tierPool[Utils.randSeedInt(tierPool.length, undefined, "Selecting trainer type")]; } getSpeciesFormIndex(species: PokemonSpecies): integer { @@ -303,7 +303,7 @@ export class Arena { /** * Sets weather to the override specified in overrides.ts - * @param weather new {@linkcode WeatherType} to set + * @param weather new weather to set of type WeatherType * @returns true to force trySetWeather to return true */ trySetWeatherOverride(weather: WeatherType): boolean { @@ -315,8 +315,8 @@ export class Arena { /** * Attempts to set a new weather to the battle - * @param weather {@linkcode WeatherType} new {@linkcode WeatherType} to set - * @param hasPokemonSource boolean if the new weather is from a pokemon + * @param weather new weather to set of type WeatherType + * @param hasPokemonSource is the new weather from a pokemon * @returns true if new weather set, false if no weather provided or attempting to set the same weather as currently in use */ trySetWeather(weather: WeatherType, hasPokemonSource: boolean): boolean { @@ -587,12 +587,6 @@ export class Arena { this.ignoreAbilities = ignoreAbilities; } - /** - * Applies each `ArenaTag` in this Arena, based on which side (self, enemy, or both) is passed in as a parameter - * @param tagType Either an {@linkcode ArenaTagType} string, or an actual {@linkcode ArenaTag} class to filter which ones to apply - * @param side {@linkcode ArenaTagSide} which side's arena tags to apply - * @param args array of parameters that the called upon tags may need - */ applyTagsForSide(tagType: ArenaTagType | Constructor, side: ArenaTagSide, ...args: unknown[]): void { let tags = typeof tagType === "string" ? this.tags.filter(t => t.tagType === tagType) @@ -603,28 +597,11 @@ export class Arena { tags.forEach(t => t.apply(this, args)); } - /** - * Applies the specified tag to both sides (ie: both user and trainer's tag that match the Tag specified) - * by calling {@linkcode applyTagsForSide()} - * @param tagType Either an {@linkcode ArenaTagType} string, or an actual {@linkcode ArenaTag} class to filter which ones to apply - * @param args array of parameters that the called upon tags may need - */ applyTags(tagType: ArenaTagType | Constructor, ...args: unknown[]): void { this.applyTagsForSide(tagType, ArenaTagSide.BOTH, ...args); } - /** - * Adds a new tag to the arena - * @param tagType {@linkcode ArenaTagType} the tag being added - * @param turnCount How many turns the tag lasts - * @param sourceMove {@linkcode Moves} the move the tag came from, or `undefined` if not from a move - * @param sourceId The ID of the pokemon in play the tag came from (see {@linkcode BattleScene.getPokemonById}) - * @param side {@linkcode ArenaTagSide} which side(s) the tag applies to - * @param quiet If a message should be queued on screen to announce the tag being added - * @param targetIndex The {@linkcode BattlerIndex} of the target pokemon - * @returns `false` if there already exists a tag of this type in the Arena - */ - addTag(tagType: ArenaTagType, turnCount: number, sourceMove: Moves | undefined, sourceId: number, side: ArenaTagSide = ArenaTagSide.BOTH, quiet: boolean = false, targetIndex?: BattlerIndex): boolean { + addTag(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves | undefined, sourceId: integer, side: ArenaTagSide = ArenaTagSide.BOTH, quiet: boolean = false, targetIndex?: BattlerIndex): boolean { const existingTag = this.getTagOnSide(tagType, side); if (existingTag) { existingTag.onOverlap(this); @@ -637,7 +614,6 @@ export class Arena { return false; } - // creates a new tag object const newTag = getArenaTag(tagType, turnCount || 0, sourceMove, sourceId, targetIndex, side); if (newTag) { this.tags.push(newTag); @@ -651,11 +627,6 @@ export class Arena { return true; } - /** - * Attempts to get a tag from the Arena via {@linkcode getTagOnSide} that applies to both sides - * @param tagType The {@linkcode ArenaTagType} or {@linkcode ArenaTag} to get - * @returns either the {@linkcode ArenaTag}, or `undefined` if it isn't there - */ getTag(tagType: ArenaTagType | Constructor): ArenaTag | undefined { return this.getTagOnSide(tagType, ArenaTagSide.BOTH); } @@ -664,35 +635,16 @@ export class Arena { return !!this.getTag(tagType); } - /** - * Attempts to get a tag from the Arena from a specific side (the tag passed in has to either apply to both sides, or the specific side only) - * - * eg: `MIST` only applies to the user's side, while `MUD_SPORT` applies to both user and enemy side - * @param tagType The {@linkcode ArenaTagType} or {@linkcode ArenaTag} to get - * @param side The {@linkcode ArenaTagSide} to look at - * @returns either the {@linkcode ArenaTag}, or `undefined` if it isn't there - */ getTagOnSide(tagType: ArenaTagType | Constructor, side: ArenaTagSide): ArenaTag | undefined { return typeof(tagType) === "string" ? this.tags.find(t => t.tagType === tagType && (side === ArenaTagSide.BOTH || t.side === ArenaTagSide.BOTH || t.side === side)) : this.tags.find(t => t instanceof tagType && (side === ArenaTagSide.BOTH || t.side === ArenaTagSide.BOTH || t.side === side)); } - /** - * Uses {@linkcode findTagsOnSide} to filter (using the parameter function) for specific tags that apply to both sides - * @param tagPredicate a function mapping {@linkcode ArenaTag}s to `boolean`s - * @returns array of {@linkcode ArenaTag}s from which the Arena's tags return true and apply to both sides - */ findTags(tagPredicate: (t: ArenaTag) => boolean): ArenaTag[] { return this.findTagsOnSide(tagPredicate, ArenaTagSide.BOTH); } - /** - * Returns specific tags from the arena that pass the `tagPredicate` function passed in as a parameter, and apply to the given side - * @param tagPredicate a function mapping {@linkcode ArenaTag}s to `boolean`s - * @param side The {@linkcode ArenaTagSide} to look at - * @returns array of {@linkcode ArenaTag}s from which the Arena's tags return `true` and apply to the given side - */ findTagsOnSide(tagPredicate: (t: ArenaTag) => boolean, side: ArenaTagSide): ArenaTag[] { return this.tags.filter(t => tagPredicate(t) && (side === ArenaTagSide.BOTH || t.side === ArenaTagSide.BOTH || t.side === side)); } @@ -922,7 +874,7 @@ export class ArenaBase extends Phaser.GameObjects.Container { if (!this.player) { (this.scene as BattleScene).executeWithSeedOffset(() => { this.propValue = propValue === undefined - ? hasProps ? Utils.randSeedInt(8) : 0 + ? hasProps ? Utils.randSeedInt(8, undefined, "Selecting biome prop(?)") : 0 : propValue; this.props.forEach((prop, p) => { const propKey = `${biomeKey}_b${hasProps ? `_${p + 1}` : ""}`; diff --git a/src/field/pokemon-sprite-sparkle-handler.ts b/src/field/pokemon-sprite-sparkle-handler.ts index ccf6a098667..008a301b242 100644 --- a/src/field/pokemon-sprite-sparkle-handler.ts +++ b/src/field/pokemon-sprite-sparkle-handler.ts @@ -31,7 +31,7 @@ export default class PokemonSpriteSparkleHandler { const parent = (pokemon || s).parentContainer; const texture = s.texture; const [ width, height ] = [ texture.source[0].width, texture.source[0].height ]; - const [ pixelX, pixelY ] = [ Utils.randInt(width), Utils.randInt(height) ]; + const [ pixelX, pixelY ] = [ Utils.randInt(width, undefined, "Pixel X"), Utils.randInt(height, undefined, "Pixel Y") ]; const ratioX = s.width / width; const ratioY = s.height / height; const pixel = texture.manager.getPixel(pixelX, pixelY, texture.key, "__BASE"); diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index a30d2ea018d..43d259046e7 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -156,8 +156,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.abilityIndex = abilityIndex; // Use the provided ability index if it is defined } else { // If abilityIndex is not provided, determine it based on species and hidden ability - const hasHiddenAbility = !Utils.randSeedInt(hiddenAbilityChance.value); - const randAbilityIndex = Utils.randSeedInt(2); + const hasHiddenAbility = !Utils.randSeedInt(hiddenAbilityChance.value, undefined, "Hidden Ability chance"); + const randAbilityIndex = Utils.randSeedInt(2, undefined, "Selecting ability index"); if (species.abilityHidden && hasHiddenAbility) { // If the species has a hidden ability and the hidden ability is present this.abilityIndex = 2; @@ -210,7 +210,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.fusionLuck = dataSource.fusionLuck; this.usedTMs = dataSource.usedTMs ?? []; } else { - this.id = Utils.randSeedInt(4294967296); + this.id = Utils.randSeedInt(4294967296, undefined, "Generating a Pokemon ID to create Pokemon's IVs"); this.ivs = ivs || Utils.getIvsFromId(this.id); if (this.gender === undefined) { @@ -923,7 +923,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (naturePool === undefined) { naturePool = Utils.getEnumValues(Nature); } - const nature = naturePool[Utils.randSeedInt(naturePool.length)]; + const nature = naturePool[Utils.randSeedInt(naturePool.length, undefined, "Random nature")]; this.setNature(nature); } @@ -1451,26 +1451,22 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } let multiplier = types.map(defType => { - const multiplier = new Utils.NumberHolder(getTypeDamageMultiplier(moveType, defType)); - applyChallenges(this.scene.gameMode, ChallengeType.TYPE_EFFECTIVENESS, multiplier); if (source) { const ignoreImmunity = new Utils.BooleanHolder(false); if (source.isActive(true) && source.hasAbilityWithAttr(IgnoreTypeImmunityAbAttr)) { applyAbAttrs(IgnoreTypeImmunityAbAttr, source, ignoreImmunity, simulated, moveType, defType); } if (ignoreImmunity.value) { - if (multiplier.value === 0) { - return 1; - } + return 1; } const exposedTags = this.findTags(tag => tag instanceof ExposedTag) as ExposedTag[]; if (exposedTags.some(t => t.ignoreImmunity(defType, moveType))) { - if (multiplier.value === 0) { - return 1; - } + return 1; } } + const multiplier = new Utils.NumberHolder(getTypeDamageMultiplier(moveType, defType)); + applyChallenges(this.scene.gameMode, ChallengeType.TYPE_EFFECTIVENESS, multiplier); return multiplier.value; }).reduce((acc, cur) => acc * cur, 1) as TypeDamageMultiplier; @@ -1717,7 +1713,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (!this.shiny || (!variantData.hasOwnProperty(variantDataIndex) && !variantData.hasOwnProperty(this.species.speciesId))) { return 0; } - const rand = Utils.randSeedInt(10); + const rand = Utils.randSeedInt(10, undefined, "Random variant selection"); if (rand >= 4) { return 0; // 6/10 } else if (rand >= 1) { @@ -1733,8 +1729,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.scene.applyModifiers(HiddenAbilityRateBoosterModifier, true, hiddenAbilityChance); } - const hasHiddenAbility = !Utils.randSeedInt(hiddenAbilityChance.value); - const randAbilityIndex = Utils.randSeedInt(2); + const hasHiddenAbility = !Utils.randSeedInt(hiddenAbilityChance.value, undefined, "Whether the Pokemon has its HA or not"); + const randAbilityIndex = Utils.randSeedInt(2, undefined, "Ability slot (if no HA)"); const filter = !forStarter ? this.species.getCompatibleFusionSpeciesFilter() : species => { @@ -1907,7 +1903,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (stabMovePool.length) { const totalWeight = stabMovePool.reduce((v, m) => v + m[1], 0); - let rand = Utils.randSeedInt(totalWeight); + let rand = Utils.randSeedInt(totalWeight, undefined, "Selecting a STAB move to include"); let index = 0; while (rand > stabMovePool[index][1]) { rand -= stabMovePool[index++][1]; @@ -1918,7 +1914,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const attackMovePool = baseWeights.filter(m => allMoves[m[0]].category !== MoveCategory.STATUS); if (attackMovePool.length) { const totalWeight = attackMovePool.reduce((v, m) => v + m[1], 0); - let rand = Utils.randSeedInt(totalWeight); + let rand = Utils.randSeedInt(totalWeight, undefined, "Selecting a damage dealing move to include"); let index = 0; while (rand > attackMovePool[index][1]) { rand -= attackMovePool[index++][1]; @@ -1937,7 +1933,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { movePool = baseWeights.filter(m => !this.moveset.some(mo => m[0] === mo?.moveId)); } const totalWeight = movePool.reduce((v, m) => v + m[1], 0); - let rand = Utils.randSeedInt(totalWeight); + let rand = Utils.randSeedInt(totalWeight, undefined, "Selecting moves"); let index = 0; while (rand > movePool[index][1]) { rand -= movePool[index++][1]; @@ -3646,7 +3642,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * @param min The minimum integer to pick, default `0` * @returns A random integer between {@linkcode min} and ({@linkcode min} + {@linkcode range} - 1) */ - randSeedInt(range: integer, min: integer = 0, reason: string = "Pokémon randSeedInt"): integer { + randSeedInt(range: integer, min: integer = 0, reason?: string): integer { return this.scene.currentBattle ? this.scene.randBattleSeedInt(range, min, reason) : Utils.randSeedInt(range, min, reason); @@ -3658,7 +3654,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * @param max The maximum integer to generate * @returns a random integer between {@linkcode min} and {@linkcode max} inclusive */ - randSeedIntRange(min: integer, max: integer, reason: string = "Pokémon randSeedInt"): integer { + randSeedIntRange(min: integer, max: integer, reason?: string): integer { return this.randSeedInt((max - min) + 1, min, reason); } @@ -4269,6 +4265,7 @@ export class EnemyPokemon extends Pokemon { * @returns this Pokemon's next move in the format {move, moveTargets} */ getNextMove(): QueuedMove { + console.log("Starting getNextMove() for " + this.name) // If this Pokemon has a move already queued, return it. const queuedMove = this.getMoveQueue().length ? this.getMoveset().find(m => m?.moveId === this.getMoveQueue()[0].move) @@ -4281,9 +4278,11 @@ export class EnemyPokemon extends Pokemon { this.flyout.setText(i) } } + console.log(" Move was already selected") return { move: queuedMove.moveId, targets: this.getMoveQueue()[0].targets, ignorePP: this.getMoveQueue()[0].ignorePP }; } else { this.getMoveQueue().shift(); + console.log(" Selected move cannot be used") return this.getNextMove(); } } @@ -4295,7 +4294,8 @@ export class EnemyPokemon extends Pokemon { // If there's only 1 move in the move pool, use it. if (movePool.length === 1) { this.flyout.setText(this.getMoveset().indexOf(movePool[0])) - return { move: movePool[0]!.moveId, targets: this.getNextTargets(movePool[0]!.moveId) }; + console.log(" Only one move to select") + return { move: movePool[0]!.moveId, targets: this.getNextTargets(movePool[0]!.moveId) }; // TODO: are the bangs correct? } // If a move is forced because of Encore, use it. const encoreTag = this.getTag(EncoreTag) as EncoreTag; @@ -4303,6 +4303,7 @@ export class EnemyPokemon extends Pokemon { const encoreMove = movePool.find(m => m?.moveId === encoreTag.moveId); if (encoreMove) { this.flyout.setText(this.getMoveset().indexOf(encoreMove)) + console.log(" Locked into Encore") return { move: encoreMove.moveId, targets: this.getNextTargets(encoreMove.moveId) }; } } @@ -4311,6 +4312,7 @@ export class EnemyPokemon extends Pokemon { var i = this.scene.randBattleSeedInt(movePool.length, undefined, "Move selection roll (RANDOM)") const moveId = movePool[i]!.moveId; this.flyout.setText(i) + case AiType.RANDOM: // No enemy should spawn with this AI type in-game return { move: moveId, targets: this.getNextTargets(moveId) }; case AiType.SMART_RANDOM: case AiType.SMART: @@ -4392,22 +4394,25 @@ export class EnemyPokemon extends Pokemon { }); let r = 0; if (this.aiType === AiType.SMART_RANDOM) { - while (r < sortedMovePool.length - 1 && this.scene.randBattleSeedInt(8, undefined, "Move selection roll (SMART_RANDOM)") >= 5) { + // Has a 5/8 chance to select the best move, and a 3/8 chance to advance to the next best move (and repeat this roll) + while (r < sortedMovePool.length - 1 && this.scene.randBattleSeedInt(8, undefined, "Smart-Random AI Move Selection") >= 5) { r++; } } else if (this.aiType === AiType.SMART) { // The chance to advance to the next best move increases when the compared moves' scores are closer to each other. while (r < sortedMovePool.length - 1 && (moveScores[movePool.indexOf(sortedMovePool[r + 1])] / moveScores[movePool.indexOf(sortedMovePool[r])]) >= 0 - && this.scene.randBattleSeedInt(100, undefined, "Move selection roll (SMART)") < Math.round((moveScores[movePool.indexOf(sortedMovePool[r + 1])] / moveScores[movePool.indexOf(sortedMovePool[r])]) * 50)) { + && this.scene.randBattleSeedInt(100, undefined, "Smart AI Move Selection") < Math.round((moveScores[movePool.indexOf(sortedMovePool[r + 1])] / moveScores[movePool.indexOf(sortedMovePool[r])]) * 50)) { r++; } } console.log(movePool.map(m => m!.getName()), moveScores, r, sortedMovePool.map(m => m!.getName())); this.flyout.setText(movePool.indexOf(sortedMovePool[r])) + console.log(" Selected " + sortedMovePool[r]!.getName()) return { move: sortedMovePool[r]!.moveId, targets: moveTargets[sortedMovePool[r]!.moveId] }; } } this.flyout.setText() + console.log(" Selected Struggle") return { move: Moves.STRUGGLE, targets: this.getNextTargets(Moves.STRUGGLE) }; } @@ -4417,10 +4422,12 @@ export class EnemyPokemon extends Pokemon { * @returns The indexes of the Pokemon the given move would target */ getNextTargets(moveId: Moves): BattlerIndex[] { + console.log("Starting getNextTargets() for " + this.name + " with move " + Utils.getEnumKeys(Moves)[moveId]) const moveTargets = getMoveTargets(this, moveId); const targets = this.scene.getField(true).filter(p => moveTargets.targets.indexOf(p.getBattlerIndex()) > -1); // If the move is multi-target, return all targets' indexes if (moveTargets.multiple) { + console.log(" Multi-target move") return targets.map(p => p.getBattlerIndex()); } @@ -4444,9 +4451,10 @@ export class EnemyPokemon extends Pokemon { // Set target to BattlerIndex.ATTACKER when using a counter move // This is the same as when the player does so if (move.hasAttr(CounterDamageAttr)) { + console.log(" Counter move") return [BattlerIndex.ATTACKER]; } - + console.log(" No targets available") return []; } @@ -4480,7 +4488,7 @@ export class EnemyPokemon extends Pokemon { * then select the first target whose cumulative weight (with all previous targets' weights) * is greater than that random number. */ - const randValue = this.scene.randBattleSeedInt(totalWeight, undefined, "Random target selection"); + const randValue = this.scene.randBattleSeedInt(totalWeight, undefined, "Random move target"); let targetIndex: integer = 0; thresholds.every((t, i) => { @@ -4491,6 +4499,8 @@ export class EnemyPokemon extends Pokemon { targetIndex = i; return false; }); + console.log("Target selection thresholds", thresholds) + console.log(" Randomly selected position " + sortedBenefitScores[targetIndex][0] + " as target") return [ sortedBenefitScores[targetIndex][0] ]; } @@ -4600,7 +4610,7 @@ export class EnemyPokemon extends Pokemon { } // Pick a random stat from the leftover stats to increase its stages - const randInt = Utils.randSeedInt(totalWeight); + const randInt = Utils.randSeedInt(totalWeight, undefined, "Random stat to raise from breaking a segment"); for (const i in statThresholds) { if (randInt < statThresholds[i]) { boostedStat = leftoverStats[i]; diff --git a/src/field/trainer.ts b/src/field/trainer.ts index 878b33b8c23..e78bb2b363a 100644 --- a/src/field/trainer.ts +++ b/src/field/trainer.ts @@ -45,7 +45,7 @@ export default class Trainer extends Phaser.GameObjects.Container { this.config.partyTemplates.length - 1); if (trainerNamePools.hasOwnProperty(trainerType)) { const namePool = trainerNamePools[trainerType]; - this.name = name || Utils.randSeedItem(Array.isArray(namePool[0]) ? namePool[variant === TrainerVariant.FEMALE ? 1 : 0] : namePool); + this.name = name || Utils.randSeedItem(Array.isArray(namePool[0]) ? namePool[variant === TrainerVariant.FEMALE ? 1 : 0] : namePool, "Trainer name 1"); if (variant === TrainerVariant.DOUBLE) { if (this.config.doubleOnly) { if (partnerName) { @@ -54,7 +54,7 @@ export default class Trainer extends Phaser.GameObjects.Container { [this.name, this.partnerName] = this.name.split(" & "); } } else { - this.partnerName = partnerName || Utils.randSeedItem(Array.isArray(namePool[0]) ? namePool[1] : namePool); + this.partnerName = partnerName || Utils.randSeedItem(Array.isArray(namePool[0]) ? namePool[1] : namePool, "Trainer name 2"); } } } @@ -487,7 +487,7 @@ export default class Trainer extends Phaser.GameObjects.Container { let species: PokemonSpecies; if (this.config.speciesPools) { - const tierValue = Utils.randSeedInt(512); + const tierValue = Utils.randSeedInt(512, undefined, "Randomly selecting species for trainer party"); let tier = tierValue >= 156 ? TrainerPoolTier.COMMON : tierValue >= 32 ? TrainerPoolTier.UNCOMMON : tierValue >= 6 ? TrainerPoolTier.RARE : tierValue >= 1 ? TrainerPoolTier.SUPER_RARE : TrainerPoolTier.ULTRA_RARE; console.log(TrainerPoolTier[tier]); while (!this.config.speciesPools.hasOwnProperty(tier) || !this.config.speciesPools[tier].length) { @@ -495,7 +495,7 @@ export default class Trainer extends Phaser.GameObjects.Container { tier--; } const tierPool = this.config.speciesPools[tier]; - species = getPokemonSpecies(Utils.randSeedItem(tierPool)); + species = getPokemonSpecies(Utils.randSeedItem(tierPool, "Random party member species")); } else { species = this.scene.randomSpecies(battle.waveIndex, level, false, this.config.speciesFilter); } @@ -587,7 +587,7 @@ export default class Trainer extends Phaser.GameObjects.Container { if (maxScorePartyMemberIndexes.length > 1) { let rand: integer; - this.scene.executeWithSeedOffset(() => rand = Utils.randSeedInt(maxScorePartyMemberIndexes.length), this.scene.currentBattle.turn << 2); + this.scene.executeWithSeedOffset(() => rand = Utils.randSeedInt(maxScorePartyMemberIndexes.length, undefined, "Randomly selecting who to send out next"), this.scene.currentBattle.turn << 2); return maxScorePartyMemberIndexes[rand!]; } diff --git a/src/game-mode.ts b/src/game-mode.ts index f5dadad6f1b..2441a79b0f1 100644 --- a/src/game-mode.ts +++ b/src/game-mode.ts @@ -161,7 +161,7 @@ export class GameMode implements GameModeConfig { } else if (w < waveIndex) { arena.scene.executeWithSeedOffset(() => { const waveTrainerChance = arena.getTrainerChance(); - if (!Utils.randSeedInt(waveTrainerChance)) { + if (!Utils.randSeedInt(waveTrainerChance, undefined, "Random chance of wave being a Trainer Battle")) { allowTrainerBattle = false; } }, w); @@ -171,7 +171,7 @@ export class GameMode implements GameModeConfig { } } } - return Boolean(allowTrainerBattle && trainerChance && !Utils.randSeedInt(trainerChance)); + return Boolean(allowTrainerBattle && trainerChance && !Utils.randSeedInt(trainerChance, undefined, "Random chance of wave being a Trainer Battle")); } return false; } @@ -189,7 +189,7 @@ export class GameMode implements GameModeConfig { if (this.isDaily && this.isWaveFinal(waveIndex)) { const allFinalBossSpecies = allSpecies.filter(s => (s.subLegendary || s.legendary || s.mythical) && s.baseTotal >= 600 && s.speciesId !== Species.ETERNATUS && s.speciesId !== Species.ARCEUS); - return Utils.randSeedItem(allFinalBossSpecies); + return Utils.randSeedItem(allFinalBossSpecies, "Final Boss override"); } return null; diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index c87f8f27c4d..3ac251404ca 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -1063,7 +1063,7 @@ class AttackTypeBoosterModifierTypeGenerator extends ModifierTypeGenerator { let type: Type; - const randInt = Utils.randSeedInt(totalWeight); + const randInt = Utils.randSeedInt(totalWeight, undefined, "Generating a move type booster"); let weight = 0; var fullweights: integer[] = [] @@ -1104,7 +1104,7 @@ class BaseStatBoosterModifierTypeGenerator extends ModifierTypeGenerator { if (pregenArgs) { return new BaseStatBoosterModifierType(pregenArgs[0]); } - const randStat: PermanentStat = Utils.randSeedInt(Stat.SPD + 1); + const randStat: PermanentStat = Utils.randSeedInt(Stat.SPD + 1, undefined, "Randomly generating a Vitamin"); return new BaseStatBoosterModifierType(randStat); }); } @@ -1125,7 +1125,7 @@ class TempStatStageBoosterModifierTypeGenerator extends ModifierTypeGenerator { if (pregenArgs && (pregenArgs.length === 1) && TEMP_BATTLE_STATS.includes(pregenArgs[0])) { return new TempStatStageBoosterModifierType(pregenArgs[0]); } - const randStat: TempBattleStat = Utils.randSeedInt(Stat.ACC, Stat.ATK); + const randStat: TempBattleStat = Utils.randSeedInt(Stat.ACC, Stat.ATK, "Randomly choosing an X item"); return new TempStatStageBoosterModifierType(randStat); }); } @@ -1190,7 +1190,7 @@ class SpeciesStatBoosterModifierTypeGenerator extends ModifierTypeGenerator { } if (totalWeight !== 0) { - const randInt = Utils.randSeedInt(totalWeight, 1); + const randInt = Utils.randSeedInt(totalWeight, 1, "Randomly choosing a species booster"); let weight = 0; var fullweights: integer[] = [] @@ -1232,9 +1232,9 @@ class TmModifierTypeGenerator extends ModifierTypeGenerator { if (!tierUniqueCompatibleTms.length) { return null; } - const randTmIndex = Utils.randSeedInt(tierUniqueCompatibleTms.length); //console.log(tierUniqueCompatibleTms.map((v, i) => i == randTmIndex ? `> ${Utils.getEnumKeys(Moves)[v].toUpperCase() + Utils.getEnumKeys(Moves)[v].substring(1).toLowerCase()} <` : `${Utils.getEnumKeys(Moves)[v].toUpperCase() + Utils.getEnumKeys(Moves)[v].substring(1).toLowerCase()}`)) return new TmModifierType(tierUniqueCompatibleTms[randTmIndex], tier); + const randTmIndex = Utils.randSeedInt(tierUniqueCompatibleTms.length, undefined, "Choosing a TM to give"); }); } } @@ -1263,9 +1263,7 @@ class EvolutionItemModifierTypeGenerator extends ModifierTypeGenerator { return null; } - const idx = Utils.randSeedInt(evolutionItemPool.length) - // console.log(evolutionItemPool.map((v, i) => i == idx ? `> ${Utils.getEnumKeys(EvolutionItem)[v!]} <` : Utils.getEnumKeys(EvolutionItem)[v!])) - return new EvolutionItemModifierType(evolutionItemPool[idx]!); // TODO: is the bang correct? + return new EvolutionItemModifierType(evolutionItemPool[Utils.randSeedInt(evolutionItemPool.length, undefined, "Choosing an evolution item")]!); // TODO: is the bang correct? }); } } @@ -1321,9 +1319,7 @@ class FormChangeItemModifierTypeGenerator extends ModifierTypeGenerator { return null; } - const idx = Utils.randSeedInt(formChangeItemPool.length) - // console.log(formChangeItemPool.map((v, i) => i == idx ? `> ${Utils.getEnumKeys(FormChangeItem)[v!]} <` : Utils.getEnumKeys(FormChangeItem)[v!])) - return new FormChangeItemModifierType(formChangeItemPool[idx]!); + return new FormChangeItemModifierType(formChangeItemPool[Utils.randSeedInt(formChangeItemPool.length, undefined, "Choosing a form change item")]); }); } } @@ -1584,7 +1580,7 @@ export const modifierTypes = { if (pregenArgs && (pregenArgs.length === 1) && (pregenArgs[0] in Nature)) { return new PokemonNatureChangeModifierType(pregenArgs[0] as Nature); } - return new PokemonNatureChangeModifierType(Utils.randSeedInt(Utils.getEnumValues(Nature).length) as Nature); + return new PokemonNatureChangeModifierType(Utils.randSeedInt(Utils.getEnumValues(Nature).length, undefined, "Choosing a Mint") as Nature); }), TERA_SHARD: () => new ModifierTypeGenerator((party: Pokemon[], pregenArgs?: any[]) => { @@ -1595,11 +1591,11 @@ export const modifierTypes = { return null; } let type: Type; - if (!Utils.randSeedInt(3)) { + if (!Utils.randSeedInt(3, undefined, "Choosing whether to give a type from your party")) { const partyMemberTypes = party.map(p => p.getTypes(false, false, true)).flat(); - type = Utils.randSeedItem(partyMemberTypes); + type = Utils.randSeedItem(partyMemberTypes, "Choosing a Tera Shard type to give"); } else { - type = Utils.randSeedInt(64) ? Utils.randSeedInt(18) as Type : Type.STELLAR; + type = Utils.randSeedInt(64, undefined, "Choosing whether to give a Stellar Shard") ? Utils.randSeedInt(18, undefined, "Choosing a type (man I have no patience)") as Type : Type.STELLAR; } return new TerastallizeModifierType(type); }), @@ -1610,7 +1606,7 @@ export const modifierTypes = { } const berryTypes = Utils.getEnumValues(BerryType); let randBerryType: BerryType; - const rand = Utils.randSeedInt(12); + const rand = Utils.randSeedInt(12, undefined, "Choosing a Berry"); if (rand < 2) { randBerryType = BerryType.SITRUS; } else if (rand < 4) { @@ -1618,7 +1614,7 @@ export const modifierTypes = { } else if (rand < 6) { randBerryType = BerryType.LEPPA; } else { - randBerryType = berryTypes[Utils.randSeedInt(berryTypes.length - 3) + 2]; + randBerryType = berryTypes[Utils.randSeedInt(berryTypes.length - 3, undefined, "Choosing a berry") + 2]; } return new BerryModifierType(randBerryType); }), @@ -2720,7 +2716,7 @@ export function getDailyRunStarterModifiers(party: PlayerPokemon[], scene?: Batt const ret: Modifiers.PokemonHeldItemModifier[] = []; for (const p of party) { for (let m = 0; m < 3; m++) { - const tierValue = Utils.randSeedInt(64); + const tierValue = Utils.randSeedInt(64, undefined, "Choosing modifier tier for daily items"); let tier: ModifierTier; if (tierValue > 25) { @@ -2808,7 +2804,7 @@ function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType, Phaser.Math.RND.state(state) } } - const tierValue = Utils.randSeedInt(1024); + const tierValue = Utils.randSeedInt(1024, undefined, "Choosing a modifier tier"); if (!upgradeCount) { upgradeCount = 0; } @@ -2822,7 +2818,7 @@ function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType, const upgradeOdds = Math.floor(128 / ((partyLuckValue + 4) / 4)); let upgraded = false; do { - upgraded = Utils.randSeedInt(upgradeOdds) < 4; + upgraded = Utils.randSeedInt(upgradeOdds, undefined, "Upgrade chance") < 4; if (upgraded) { upgradeCount++; } @@ -2880,7 +2876,7 @@ function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType, } const upgradeOdds = Math.floor(32 / ((partyShinyCount + 2) / 2)); while (modifierPool.hasOwnProperty(tier + upgradeCount + 1) && modifierPool[tier + upgradeCount + 1].length) { - if (!Utils.randSeedInt(upgradeOdds)) { + if (!Utils.randSeedInt(upgradeOdds, undefined, "Upgrade chance 2")) { upgradeCount++; } else { break; @@ -2907,9 +2903,9 @@ function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType, //console.log("Ignored items for this tier", ignoredPoolIndexes[tier].map((v, i) => [ignoredPoolNames[i], v]).flat()) } } - let modifierType: ModifierType = (pool[tier][index]).modifierType; + let modifierType: ModifierType | null = (pool[tier][index]).modifierType; if (modifierType instanceof ModifierTypeGenerator) { - modifierType = (modifierType as ModifierTypeGenerator).generateType(party)!; + modifierType = (modifierType as ModifierTypeGenerator).generateType(party); if (modifierType === null) { if (player) { if (!shutUpBro) console.log(ModifierTier[tier], upgradeCount); diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index 38c23f1219d..5763933cd6d 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -796,7 +796,7 @@ export class TerastallizeModifier extends LapsingPokemonHeldItemModifier { /** * Modifier used for held items, specifically vitamins like Carbos, Hp Up, etc., that * increase the value of a given {@linkcode PermanentStat}. - * @extends PokemonHeldItemModifier + * @extends LapsingPersistentModifier * @see {@linkcode apply} */ export class BaseStatModifier extends PokemonHeldItemModifier { @@ -1494,7 +1494,7 @@ export class PreserveBerryModifier extends PersistentModifier { apply(args: any[]): boolean { if (!(args[1] as Utils.BooleanHolder).value) { - (args[1] as Utils.BooleanHolder).value = (args[0] as Pokemon).randSeedInt(10, undefined, "Chance to save a berry") < this.getStackCount() * 3; + (args[1] as Utils.BooleanHolder).value = (args[0] as Pokemon).randSeedInt(10, undefined, "Chance to preserve berry") < this.getStackCount() * 3; } return true; @@ -2428,7 +2428,7 @@ export abstract class HeldItemTransferModifier extends PokemonHeldItemModifier { return false; } - const targetPokemon = opponents[pokemon.randSeedInt(opponents.length, undefined, "Chance to steal/transfer an item")]; + const targetPokemon = opponents[pokemon.randSeedInt(opponents.length, undefined, "Chance to steal item")]; const transferredItemCount = this.getTransferredItemCount(); if (!transferredItemCount) { diff --git a/src/phases/attempt-capture-phase.ts b/src/phases/attempt-capture-phase.ts index a93adb19fc0..1c6873db5cf 100644 --- a/src/phases/attempt-capture-phase.ts +++ b/src/phases/attempt-capture-phase.ts @@ -124,7 +124,7 @@ export class AttemptCapturePhase extends PokemonPhase { shakeCounter.stop(); this.failCatch(shakeCount); } else if (shakeCount++ < 3) { - if (pokeballMultiplier === -1 || this.roll(y) < y) { + if (pokeballMultiplier === -1 || pokemon.randSeedInt(65536, undefined, "Capture roll") < y) { this.scene.playSound("se/pb_move"); } else { shakeCounter.stop(); diff --git a/src/phases/attempt-run-phase.ts b/src/phases/attempt-run-phase.ts index 2ef29c56424..ef2c21b74a3 100644 --- a/src/phases/attempt-run-phase.ts +++ b/src/phases/attempt-run-phase.ts @@ -29,7 +29,7 @@ export class AttemptRunPhase extends PokemonPhase { applyAbAttrs(RunSuccessAbAttr, playerPokemon, null, false, escapeChance); - if (playerPokemon.randSeedInt(100, undefined, "Run attempt") < escapeChance.value) { + if (playerPokemon.randSeedInt(100, undefined, "Run away chance") < escapeChance.value) { this.scene.playSound("se/flee"); LoggerTools.logShop(this.scene, this.scene.currentBattle.waveIndex, "Fled") this.scene.queueMessage(i18next.t("battle:runAwaySuccess"), null, true, 500); diff --git a/src/phases/egg-hatch-phase.ts b/src/phases/egg-hatch-phase.ts index 19bce5c37ab..2c1a6787cbb 100644 --- a/src/phases/egg-hatch-phase.ts +++ b/src/phases/egg-hatch-phase.ts @@ -391,7 +391,7 @@ export class EggHatchPhase extends Phase { repeat: intensity, duration: Utils.getFrameMs(1), onRepeat: () => { - this.doSprayParticle(Utils.randInt(8), offsetY || 0); + this.doSprayParticle(Utils.randInt(8, undefined, "%HIDE"), offsetY || 0); } }); } @@ -410,8 +410,8 @@ export class EggHatchPhase extends Phase { let f = 0; let yOffset = 0; - const speed = 3 - Utils.randInt(8); - const amp = 24 + Utils.randInt(32); + const speed = 3 - Utils.randInt(8, undefined, "%HIDE"); + const amp = 24 + Utils.randInt(32, undefined, "%HIDE"); const particleTimer = this.scene.tweens.addCounter({ repeat: -1, diff --git a/src/phases/encounter-phase.ts b/src/phases/encounter-phase.ts index 5bd9906b52c..9a957882489 100644 --- a/src/phases/encounter-phase.ts +++ b/src/phases/encounter-phase.ts @@ -309,7 +309,7 @@ export class EncounterPhase extends BattlePhase { doSummon(); } else { let message: string; - this.scene.executeWithSeedOffset(() => message = Utils.randSeedItem(encounterMessages), this.scene.currentBattle.waveIndex); + this.scene.executeWithSeedOffset(() => message = Utils.randSeedItem(encounterMessages, "Encounter message"), this.scene.currentBattle.waveIndex); message = message!; // tell TS compiler it's defined now const showDialogueAndSummon = () => { this.scene.ui.showDialogue(message, trainer?.getName(TrainerSlot.NONE, true), null, () => { diff --git a/src/phases/move-phase.ts b/src/phases/move-phase.ts index 223fb146365..f948377def4 100644 --- a/src/phases/move-phase.ts +++ b/src/phases/move-phase.ts @@ -251,7 +251,7 @@ export class MovePhase extends BattlePhase { switch (this.pokemon.status.effect) { case StatusEffect.PARALYSIS: - if (!this.pokemon.randSeedInt(4, undefined, "Paralysis chance")) { + if (!this.pokemon.randSeedInt(4, undefined, "Chance to be immobilized by Paralysis")) { activated = true; this.cancelled = true; } diff --git a/src/phases/select-biome-phase.ts b/src/phases/select-biome-phase.ts index 5da26ce02f0..2c892131df3 100644 --- a/src/phases/select-biome-phase.ts +++ b/src/phases/select-biome-phase.ts @@ -39,7 +39,7 @@ export class SelectBiomePhase extends BattlePhase { let biomes: Biome[] = []; this.scene.executeWithSeedOffset(() => { biomes = (biomeLinks[currentBiome] as (Biome | [Biome, integer])[]) - .filter(b => !Array.isArray(b) || !Utils.randSeedInt(b[1])) + .filter(b => !Array.isArray(b) || !Utils.randSeedInt(b[1], undefined, "Choosing next biome")) .map(b => !Array.isArray(b) ? b : b[0]); }, this.scene.currentBattle.waveIndex); if (biomes.length > 1 && this.scene.findModifier(m => m instanceof MapModifier)) { @@ -48,7 +48,7 @@ export class SelectBiomePhase extends BattlePhase { biomeChoices = (!Array.isArray(biomeLinks[currentBiome]) ? [biomeLinks[currentBiome] as Biome] : biomeLinks[currentBiome] as (Biome | [Biome, integer])[]) - .filter((b, i) => !Array.isArray(b) || !Utils.randSeedInt(b[1])) + .filter((b, i) => !Array.isArray(b) || !Utils.randSeedInt(b[1], undefined, "Choosing next biome for map")) .map(b => Array.isArray(b) ? b[0] : b); }, this.scene.currentBattle.waveIndex); const biomeSelectItems = biomeChoices.map(b => { @@ -67,7 +67,7 @@ export class SelectBiomePhase extends BattlePhase { delay: 1000 }); } else { - setNextBiome(biomes[Utils.randSeedInt(biomes.length)]); + setNextBiome(biomes[Utils.randSeedInt(biomes.length, undefined, "Choosing biome randomly")]); } } else if (biomeLinks.hasOwnProperty(currentBiome)) { setNextBiome(biomeLinks[currentBiome] as Biome); diff --git a/src/phases/trainer-victory-phase.ts b/src/phases/trainer-victory-phase.ts index bc91db56b12..a3433487ef0 100644 --- a/src/phases/trainer-victory-phase.ts +++ b/src/phases/trainer-victory-phase.ts @@ -38,7 +38,7 @@ export class TrainerVictoryPhase extends BattlePhase { this.scene.ui.showText(i18next.t("battle:trainerDefeated", { trainerName: this.scene.currentBattle.trainer?.getName(TrainerSlot.NONE, true) }), null, () => { const victoryMessages = this.scene.currentBattle.trainer?.getVictoryMessages()!; // TODO: is this bang correct? let message: string; - this.scene.executeWithSeedOffset(() => message = Utils.randSeedItem(victoryMessages), this.scene.currentBattle.waveIndex); + this.scene.executeWithSeedOffset(() => message = Utils.randSeedItem(victoryMessages, "Victory message"), this.scene.currentBattle.waveIndex); message = message!; // tell TS compiler it's defined now const showMessage = () => { diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 588d0f4e3fa..4e9ca6155ca 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -31,8 +31,8 @@ import { Variant } from "#app/data/variant"; import {setSettingGamepad, SettingGamepad, settingGamepadDefaults} from "./settings/settings-gamepad"; import {setSettingKeyboard, SettingKeyboard} from "#app/system/settings/settings-keyboard"; import { TerrainChangedEvent, WeatherChangedEvent } from "#app/events/arena"; -import * as Modifier from "../modifier/modifier"; import { StatusEffect } from "#app/data/status-effect"; +import { EnemyAttackStatusEffectChanceModifier } from "../modifier/modifier"; import ChallengeData from "./challenge-data"; import { Device } from "#enums/devices"; import { GameDataType } from "#enums/game-data-type"; @@ -327,8 +327,8 @@ export class GameData { this.loadSettings(); this.loadGamepadSettings(); this.loadMappingConfigs(); - this.trainerId = Utils.randInt(65536); - this.secretId = Utils.randInt(65536); + this.trainerId = Utils.randInt(65536, undefined, "Trainer ID"); + this.secretId = Utils.randInt(65536, undefined, "Secret ID"); this.starterData = {}; this.gameStats = new GameStats(); this.runHistory = {}; @@ -1085,8 +1085,10 @@ export class GameData { // TODO //scene.arena.tags = sessionData.arena.tags; + const modifiersModule = await import("../modifier/modifier"); + for (const modifierData of sessionData.modifiers) { - const modifier = modifierData.toModifier(scene, Modifier[modifierData.className]); + const modifier = modifierData.toModifier(scene, modifiersModule[modifierData.className]); if (modifier) { scene.addModifier(modifier, true); } @@ -1095,7 +1097,7 @@ export class GameData { scene.updateModifiers(true); for (const enemyModifierData of sessionData.enemyModifiers) { - const modifier = enemyModifierData.toModifier(scene, Modifier[enemyModifierData.className]); + const modifier = enemyModifierData.toModifier(scene, modifiersModule[enemyModifierData.className]); if (modifier) { scene.addEnemyModifier(modifier, true); } @@ -1251,7 +1253,7 @@ export class GameData { if (md?.className === "ExpBalanceModifier") { // Temporarily limit EXP Balance until it gets reworked md.stackCount = Math.min(md.stackCount, 4); } - if (md instanceof Modifier.EnemyAttackStatusEffectChanceModifier && md.effect === StatusEffect.FREEZE || md.effect === StatusEffect.SLEEP) { + if (md instanceof EnemyAttackStatusEffectChanceModifier && md.effect === StatusEffect.FREEZE || md.effect === StatusEffect.SLEEP) { continue; } ret.push(new PersistentModifierData(md, player)); @@ -1507,7 +1509,7 @@ export class GameData { this.scene.executeWithSeedOffset(() => { const neutralNatures = [ Nature.HARDY, Nature.DOCILE, Nature.SERIOUS, Nature.BASHFUL, Nature.QUIRKY ]; for (let s = 0; s < defaultStarterSpecies.length; s++) { - defaultStarterNatures.push(Utils.randSeedItem(neutralNatures)); + defaultStarterNatures.push(Utils.randSeedItem(neutralNatures, "Random neutral nature")); } }, 0, "default"); @@ -1862,7 +1864,7 @@ export class GameData { entry.hatchedCount = 0; } if (!entry.hasOwnProperty("natureAttr") || (entry.caughtAttr && !entry.natureAttr)) { - entry.natureAttr = this.defaultDexData?.[k].natureAttr || (1 << Utils.randInt(25, 1)); + entry.natureAttr = this.defaultDexData?.[k].natureAttr || (1 << Utils.randInt(25, 1, "Random bit shift")); } } } diff --git a/src/ui/party-ui-handler.ts b/src/ui/party-ui-handler.ts index 4a7e4bc4303..a4c7f6029fb 100644 --- a/src/ui/party-ui-handler.ts +++ b/src/ui/party-ui-handler.ts @@ -1073,7 +1073,7 @@ export default class PartyUiHandler extends MessageUiHandler { } getReleaseMessage(pokemonName: string): string { - const rand = Utils.randInt(128); + const rand = Utils.randInt(128, undefined, "Random release message"); if (rand < 20) { return i18next.t("partyUiHandler:goodbye", { pokemonName: pokemonName }); } else if (rand < 40) { diff --git a/src/ui/title-ui-handler.ts b/src/ui/title-ui-handler.ts index 67a4f7260e6..c49c039eb8f 100644 --- a/src/ui/title-ui-handler.ts +++ b/src/ui/title-ui-handler.ts @@ -85,7 +85,7 @@ export default class TitleUiHandler extends OptionSelectUiHandler { const ret = super.show(args); if (ret) { - this.splashMessage = Utils.randItem(getSplashMessages()); + this.splashMessage = Utils.randItem(getSplashMessages(), "Splash Message selection"); this.splashMessageText.setText(this.splashMessage.replace("{COUNT}", "?")); const ui = this.getUi(); diff --git a/src/utils.ts b/src/utils.ts index 557e2917d3b..8a0c56637db 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -13,7 +13,7 @@ export function randomString(length: integer, seeded: boolean = false) { let result = ""; for (let i = 0; i < length; i++) { - const randomIndex = seeded ? randSeedInt(characters.length) : Math.floor(Math.random() * characters.length); + const randomIndex = seeded ? randSeedInt(characters.length, undefined, "%HIDE") : Math.floor(Math.random() * characters.length); result += characters[randomIndex]; } @@ -44,7 +44,7 @@ export function rangemap(value: integer, min: integer, max: integer, outMin: int return ((value - min) / (max - min)) * (outMax - outMin) + outMin } -export function randGauss(stdev: number, mean: number = 0): number { +export function randGauss(stdev: number, mean: number = 0, reason?: string): number { if (!stdev) { return 0; } @@ -54,7 +54,7 @@ export function randGauss(stdev: number, mean: number = 0): number { return z * stdev + mean; } -export function randSeedGauss(stdev: number, mean: number = 0): number { +export function randSeedGauss(stdev: number, mean: number = 0, reason?: string): number { if (!stdev) { return 0; } @@ -85,7 +85,9 @@ export function randInt(range: integer, min: integer = 0, reason?: string): inte return min; } let V = Math.floor(Math.random() * range) + min; - //console.log(reason ? reason : "randInt", V) + if (reason != "%HIDE") { + console.log("[unseeded] " + (reason ? reason : "randInt"), V) + } return V; } @@ -100,7 +102,13 @@ export function randSeedInt(range: integer, min: integer = 0, reason?: string): return min; } let V = Phaser.Math.RND.integerInRange(min, (range - 1) + min); - //console.log(reason ? reason : "randSeedInt", V) + if (reason != "%HIDE") { + if (reason) { + console.log(reason, V) + } else { + console.error("unlabeled randSeedInt", V) + } + } return V; } @@ -122,7 +130,7 @@ export function randItem(items: T[], reason?: string): T { export function randSeedItem(items: T[], reason?: string): T { function rpick() { let V = Phaser.Math.RND.pick(items) - //console.log(reason ? reason : "randSeedItem") + console.log(reason ? reason : "randSeedItem") return V; } return items.length === 1