RNG Logging extension

Copied over every file that uses any RNG function, adding more logging and hopefully fixing RNG discrepancies
This commit is contained in:
RedstonewolfX 2024-09-11 14:55:14 -04:00
parent f0ec8b4a87
commit dfcc5c9e87
31 changed files with 223 additions and 238 deletions

View File

@ -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);

View File

@ -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)

View File

@ -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(),

View File

@ -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));

View File

@ -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));

View File

@ -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])

View File

@ -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));
}

View File

@ -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]);

View File

@ -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<boolean> {
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)

View File

@ -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),

View File

@ -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);

View File

@ -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();

View File

@ -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;

View File

@ -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<ArenaTag>, 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<ArenaTag>, ...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>): 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<ArenaTag>, 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}` : ""}`;

View File

@ -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");

View File

@ -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];

View File

@ -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!];
}

View File

@ -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;

View File

@ -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);

View File

@ -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) {

View File

@ -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();

View File

@ -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);

View File

@ -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,

View File

@ -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, () => {

View File

@ -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;
}

View File

@ -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);

View File

@ -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 = () => {

View File

@ -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"));
}
}
}

View File

@ -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) {

View File

@ -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();

View File

@ -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<T>(items: T[], reason?: string): T {
export function randSeedItem<T>(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