mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-06-20 16:42:45 +02:00
Added utility function randSeedFloat
basically just `Phaser.math.RND.realInRange(0, 1)`
This commit is contained in:
parent
f33396a3a5
commit
4c3447c851
@ -8,6 +8,7 @@ import {
|
|||||||
shiftCharCodes,
|
shiftCharCodes,
|
||||||
randSeedItem,
|
randSeedItem,
|
||||||
randInt,
|
randInt,
|
||||||
|
randSeedFloat,
|
||||||
} from "#app/utils/common";
|
} from "#app/utils/common";
|
||||||
import Trainer, { TrainerVariant } from "./field/trainer";
|
import Trainer, { TrainerVariant } from "./field/trainer";
|
||||||
import type { GameMode } from "./game-mode";
|
import type { GameMode } from "./game-mode";
|
||||||
@ -150,7 +151,7 @@ export default class Battle {
|
|||||||
randSeedGaussForLevel(value: number): number {
|
randSeedGaussForLevel(value: number): number {
|
||||||
let rand = 0;
|
let rand = 0;
|
||||||
for (let i = value; i > 0; i--) {
|
for (let i = value; i > 0; i--) {
|
||||||
rand += Phaser.Math.RND.realInRange(0, 1);
|
rand += randSeedFloat();
|
||||||
}
|
}
|
||||||
return rand / value;
|
return rand / value;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { HitResult, MoveResult, PlayerPokemon } from "#app/field/pokemon";
|
import { HitResult, MoveResult, PlayerPokemon } from "#app/field/pokemon";
|
||||||
import { BooleanHolder, NumberHolder, toDmgValue, isNullOrUndefined, randSeedItem, randSeedInt, type Constructor } from "#app/utils/common";
|
import { BooleanHolder, NumberHolder, toDmgValue, isNullOrUndefined, randSeedItem, randSeedInt, type Constructor, randSeedFloat } from "#app/utils/common";
|
||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
import { BattlerTagLapseType, GroundedTag } from "#app/data/battler-tags";
|
import { BattlerTagLapseType, GroundedTag } from "#app/data/battler-tags";
|
||||||
import { getNonVolatileStatusEffects, getStatusEffectDescriptor, getStatusEffectHealText } from "#app/data/status-effect";
|
import { getNonVolatileStatusEffects, getStatusEffectDescriptor, getStatusEffectHealText } from "#app/data/status-effect";
|
||||||
@ -4071,8 +4071,8 @@ export class PostTurnRestoreBerryAbAttr extends PostTurnAbAttr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Clamp procChance to [0, 1]. Skip if didn't proc (less than pass)
|
// Clamp procChance to [0, 1]. Skip if didn't proc (less than pass)
|
||||||
const pass = Phaser.Math.RND.realInRange(0, 1);
|
const pass = randSeedFloat();
|
||||||
return Phaser.Math.Clamp(this.procChance(pokemon), 0, 1) >= pass;
|
return Phaser.Math.Clamp(this.procChance(pokemon), 1, 0) >= pass;
|
||||||
}
|
}
|
||||||
|
|
||||||
override applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void {
|
override applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void {
|
||||||
|
@ -29,7 +29,7 @@ import {
|
|||||||
} from "../status-effect";
|
} from "../status-effect";
|
||||||
import { getTypeDamageMultiplier } from "../type";
|
import { getTypeDamageMultiplier } from "../type";
|
||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
import { BooleanHolder, NumberHolder, isNullOrUndefined, toDmgValue, randSeedItem, randSeedInt, getEnumValues, toReadableString, type Constructor } from "#app/utils/common";
|
import { BooleanHolder, NumberHolder, isNullOrUndefined, toDmgValue, randSeedItem, randSeedInt, getEnumValues, toReadableString, type Constructor, randSeedFloat } from "#app/utils/common";
|
||||||
import { WeatherType } from "#enums/weather-type";
|
import { WeatherType } from "#enums/weather-type";
|
||||||
import type { ArenaTrapTag } from "../arena-tag";
|
import type { ArenaTrapTag } from "../arena-tag";
|
||||||
import { ArenaTagSide, WeakenMoveTypeTag } from "../arena-tag";
|
import { ArenaTagSide, WeakenMoveTypeTag } from "../arena-tag";
|
||||||
@ -2549,8 +2549,8 @@ export class StealHeldItemChanceAttr extends MoveEffectAttr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
const rand = Phaser.Math.RND.realInRange(0, 1);
|
const rand = randSeedFloat();
|
||||||
if (rand >= this.chance) {
|
if (rand > this.chance) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const heldItems = this.getTargetHeldItems(target).filter((i) => i.isTransferable);
|
const heldItems = this.getTargetHeldItems(target).filter((i) => i.isTransferable);
|
||||||
|
@ -8,7 +8,14 @@ import type { AnySound } from "#app/battle-scene";
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type { GameMode } from "#app/game-mode";
|
import type { GameMode } from "#app/game-mode";
|
||||||
import { DexAttr, type StarterMoveset } from "#app/system/game-data";
|
import { DexAttr, type StarterMoveset } from "#app/system/game-data";
|
||||||
import { isNullOrUndefined, capitalizeString, randSeedInt, randSeedGauss, randSeedItem } from "#app/utils/common";
|
import {
|
||||||
|
isNullOrUndefined,
|
||||||
|
capitalizeString,
|
||||||
|
randSeedInt,
|
||||||
|
randSeedGauss,
|
||||||
|
randSeedItem,
|
||||||
|
randSeedFloat,
|
||||||
|
} from "#app/utils/common";
|
||||||
import { uncatchableSpecies } from "#app/data/balance/biomes";
|
import { uncatchableSpecies } from "#app/data/balance/biomes";
|
||||||
import { speciesEggMoves } from "#app/data/balance/egg-moves";
|
import { speciesEggMoves } from "#app/data/balance/egg-moves";
|
||||||
import { GrowthRate } from "#app/data/exp";
|
import { GrowthRate } from "#app/data/exp";
|
||||||
@ -749,7 +756,7 @@ export abstract class PokemonSpeciesForm {
|
|||||||
let paletteColors: Map<number, number> = new Map();
|
let paletteColors: Map<number, number> = new Map();
|
||||||
|
|
||||||
const originalRandom = Math.random;
|
const originalRandom = Math.random;
|
||||||
Math.random = () => Phaser.Math.RND.realInRange(0, 1);
|
Math.random = randSeedFloat;
|
||||||
|
|
||||||
globalScene.executeWithSeedOffset(
|
globalScene.executeWithSeedOffset(
|
||||||
() => {
|
() => {
|
||||||
@ -772,6 +779,7 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
|
|||||||
readonly mythical: boolean;
|
readonly mythical: boolean;
|
||||||
readonly species: string;
|
readonly species: string;
|
||||||
readonly growthRate: GrowthRate;
|
readonly growthRate: GrowthRate;
|
||||||
|
/** The chance (as a decimal) for this Species to be male, or `null` for genderless species */
|
||||||
readonly malePercent: number | null;
|
readonly malePercent: number | null;
|
||||||
readonly genderDiffs: boolean;
|
readonly genderDiffs: boolean;
|
||||||
readonly canChangeForm: boolean;
|
readonly canChangeForm: boolean;
|
||||||
@ -881,16 +889,14 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Pick and return a random {@linkcode Gender} for a {@linkcode Pokemon}.
|
* Pick and return a random {@linkcode Gender} for a {@linkcode Pokemon}.
|
||||||
* @param id The personality value of the pokemon being generated.
|
* @returns A randomly rolled gender based on this Species' {@linkcode malePercent}.
|
||||||
* @returns THe selected gender for this Pokemon, rolled based on its PID.
|
|
||||||
*/
|
*/
|
||||||
generateGender(id: number): Gender {
|
generateGender(): Gender {
|
||||||
if (isNullOrUndefined(this.malePercent)) {
|
if (isNullOrUndefined(this.malePercent)) {
|
||||||
return Gender.GENDERLESS;
|
return Gender.GENDERLESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
const genderChance = (id % 256) * 0.390625;
|
if (randSeedFloat() <= this.malePercent) {
|
||||||
if (genderChance < this.malePercent) {
|
|
||||||
return Gender.MALE;
|
return Gender.MALE;
|
||||||
}
|
}
|
||||||
return Gender.FEMALE;
|
return Gender.FEMALE;
|
||||||
@ -1139,7 +1145,7 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (noEvolutionChance === 1 || Phaser.Math.RND.realInRange(0, 1) < noEvolutionChance) {
|
if (noEvolutionChance === 1 || randSeedFloat() <= noEvolutionChance) {
|
||||||
return this.speciesId;
|
return this.speciesId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ import {
|
|||||||
getStarterValueFriendshipCap,
|
getStarterValueFriendshipCap,
|
||||||
speciesStarterCosts,
|
speciesStarterCosts,
|
||||||
} from "#app/data/balance/starters";
|
} from "#app/data/balance/starters";
|
||||||
import { NumberHolder, randSeedInt, getIvsFromId, BooleanHolder, randSeedItem, isNullOrUndefined, getEnumValues, toDmgValue, fixedInt, rgbaToInt, rgbHexToRgba, rgbToHsv, deltaRgb, isBetween, type nil, type Constructor } from "#app/utils/common";
|
import { NumberHolder, randSeedInt, getIvsFromId, BooleanHolder, randSeedItem, isNullOrUndefined, getEnumValues, toDmgValue, fixedInt, rgbaToInt, rgbHexToRgba, rgbToHsv, deltaRgb, isBetween, type nil, type Constructor, randSeedFloat } from "#app/utils/common";
|
||||||
import type { TypeDamageMultiplier } from "#app/data/type";
|
import type { TypeDamageMultiplier } from "#app/data/type";
|
||||||
import { getTypeDamageMultiplier, getTypeRgb } from "#app/data/type";
|
import { getTypeDamageMultiplier, getTypeRgb } from "#app/data/type";
|
||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
@ -6046,7 +6046,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
let fusionPaletteColors: Map<number, number>;
|
let fusionPaletteColors: Map<number, number>;
|
||||||
|
|
||||||
const originalRandom = Math.random;
|
const originalRandom = Math.random;
|
||||||
Math.random = () => Phaser.Math.RND.realInRange(0, 1);
|
Math.random = randSeedFloat;
|
||||||
|
|
||||||
globalScene.executeWithSeedOffset(
|
globalScene.executeWithSeedOffset(
|
||||||
() => {
|
() => {
|
||||||
|
@ -15,7 +15,7 @@ import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
|
|||||||
import type { VoucherType } from "#app/system/voucher";
|
import type { VoucherType } from "#app/system/voucher";
|
||||||
import { Command } from "#app/ui/command-ui-handler";
|
import { Command } from "#app/ui/command-ui-handler";
|
||||||
import { addTextObject, TextStyle } from "#app/ui/text";
|
import { addTextObject, TextStyle } from "#app/ui/text";
|
||||||
import { BooleanHolder, hslToHex, isNullOrUndefined, NumberHolder, toDmgValue } from "#app/utils/common";
|
import { BooleanHolder, hslToHex, isNullOrUndefined, NumberHolder, randSeedFloat, toDmgValue } from "#app/utils/common";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { BerryType } from "#enums/berry-type";
|
import { BerryType } from "#enums/berry-type";
|
||||||
import type { Moves } from "#enums/moves";
|
import type { Moves } from "#enums/moves";
|
||||||
@ -3365,7 +3365,7 @@ export class ContactHeldItemTransferChanceModifier extends HeldItemTransferModif
|
|||||||
}
|
}
|
||||||
|
|
||||||
getTransferredItemCount(): number {
|
getTransferredItemCount(): number {
|
||||||
return Phaser.Math.RND.realInRange(0, 1) < this.chance * this.getStackCount() ? 1 : 0;
|
return randSeedFloat() <= this.chance * this.getStackCount() ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
getTransferMessage(pokemon: Pokemon, targetPokemon: Pokemon, item: ModifierType): string {
|
getTransferMessage(pokemon: Pokemon, targetPokemon: Pokemon, item: ModifierType): string {
|
||||||
@ -3643,7 +3643,7 @@ export class EnemyAttackStatusEffectChanceModifier extends EnemyPersistentModifi
|
|||||||
* @returns `true` if the {@linkcode Pokemon} was affected
|
* @returns `true` if the {@linkcode Pokemon} was affected
|
||||||
*/
|
*/
|
||||||
override apply(enemyPokemon: Pokemon): boolean {
|
override apply(enemyPokemon: Pokemon): boolean {
|
||||||
if (Phaser.Math.RND.realInRange(0, 1) < this.chance * this.getStackCount()) {
|
if (randSeedFloat() <= this.chance * this.getStackCount()) {
|
||||||
return enemyPokemon.trySetStatus(this.effect, true);
|
return enemyPokemon.trySetStatus(this.effect, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3683,16 +3683,16 @@ export class EnemyStatusEffectHealChanceModifier extends EnemyPersistentModifier
|
|||||||
* @returns `true` if the {@linkcode Pokemon} was healed
|
* @returns `true` if the {@linkcode Pokemon} was healed
|
||||||
*/
|
*/
|
||||||
override apply(enemyPokemon: Pokemon): boolean {
|
override apply(enemyPokemon: Pokemon): boolean {
|
||||||
if (enemyPokemon.status && Phaser.Math.RND.realInRange(0, 1) < this.chance * this.getStackCount()) {
|
if (!enemyPokemon.status || randSeedFloat() > this.chance * this.getStackCount()) {
|
||||||
globalScene.queueMessage(
|
return false;
|
||||||
getStatusEffectHealText(enemyPokemon.status.effect, getPokemonNameWithAffix(enemyPokemon)),
|
|
||||||
);
|
|
||||||
enemyPokemon.resetStatus();
|
|
||||||
enemyPokemon.updateInfo();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
globalScene.queueMessage(
|
||||||
|
getStatusEffectHealText(enemyPokemon.status.effect, getPokemonNameWithAffix(enemyPokemon)),
|
||||||
|
);
|
||||||
|
enemyPokemon.resetStatus();
|
||||||
|
enemyPokemon.updateInfo();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
getMaxStackCount(): number {
|
getMaxStackCount(): number {
|
||||||
@ -3771,7 +3771,7 @@ export class EnemyFusionChanceModifier extends EnemyPersistentModifier {
|
|||||||
* @returns `true` if the {@linkcode EnemyPokemon} is a fusion
|
* @returns `true` if the {@linkcode EnemyPokemon} is a fusion
|
||||||
*/
|
*/
|
||||||
override apply(isFusion: BooleanHolder): boolean {
|
override apply(isFusion: BooleanHolder): boolean {
|
||||||
if (Phaser.Math.RND.realInRange(0, 1) >= this.chance * this.getStackCount()) {
|
if (randSeedFloat() > this.chance * this.getStackCount()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,8 +57,8 @@ export function randSeedGauss(stdev: number, mean = 0): number {
|
|||||||
if (!stdev) {
|
if (!stdev) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
const u = 1 - Phaser.Math.RND.realInRange(0, 1);
|
const u = 1 - randSeedFloat();
|
||||||
const v = Phaser.Math.RND.realInRange(0, 1);
|
const v = randSeedFloat();
|
||||||
const z = Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v);
|
const z = Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v);
|
||||||
return z * stdev + mean;
|
return z * stdev + mean;
|
||||||
}
|
}
|
||||||
@ -87,9 +87,9 @@ export function randInt(range: number, min = 0): number {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a random number using the global seed, or the current battle's seed if called via `Battle.randSeedInt`
|
* Generate a random integer using the global seed, or the current battle's seed if called via `Battle.randSeedInt`
|
||||||
* @param range How large of a range of random numbers to choose from. If {@linkcode range} <= 1, returns {@linkcode min}
|
* @param range - How large of a range of random numbers to choose from. If {@linkcode range} <= 1, returns {@linkcode min}
|
||||||
* @param min The minimum integer to pick, default `0`
|
* @param min - The minimum integer to pick, default `0`
|
||||||
* @returns A random integer between {@linkcode min} and ({@linkcode min} + {@linkcode range} - 1)
|
* @returns A random integer between {@linkcode min} and ({@linkcode min} + {@linkcode range} - 1)
|
||||||
*/
|
*/
|
||||||
export function randSeedInt(range: number, min = 0): number {
|
export function randSeedInt(range: number, min = 0): number {
|
||||||
@ -108,6 +108,14 @@ export function randIntRange(min: number, max: number): number {
|
|||||||
return randInt(max - min, min);
|
return randInt(max - min, min);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate and return a random real number between `0` and `1` using the global seed.
|
||||||
|
* @returns A random floating-point number between `0` and `1`
|
||||||
|
*/
|
||||||
|
export function randSeedFloat(): number {
|
||||||
|
return Phaser.Math.RND.frac();
|
||||||
|
}
|
||||||
|
|
||||||
export function randItem<T>(items: T[]): T {
|
export function randItem<T>(items: T[]): T {
|
||||||
return items.length === 1 ? items[0] : items[randInt(items.length)];
|
return items.length === 1 ? items[0] : items[randInt(items.length)];
|
||||||
}
|
}
|
||||||
@ -502,12 +510,19 @@ export function capitalizeString(str: string, sep: string, lowerFirstChar = true
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isNullOrUndefined(object: any): object is null | undefined {
|
/**
|
||||||
return object === null || object === undefined;
|
* Report whether a given value is nullish (`null`/`undefined`).
|
||||||
|
* @param val - The value whose nullishness is being checked
|
||||||
|
* @returns `true` if `val` is either `null` or `undefined`
|
||||||
|
*/
|
||||||
|
export function isNullOrUndefined(val: any): val is null | undefined {
|
||||||
|
return val === null || val === undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Capitalizes the first letter of a string
|
* Capitalize the first letter of a string.
|
||||||
|
* @param str - The string whose first letter is being capitalized
|
||||||
|
* @return The original string with its first letter capitalized
|
||||||
*/
|
*/
|
||||||
export function capitalizeFirstLetter(str: string) {
|
export function capitalizeFirstLetter(str: string) {
|
||||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||||
|
Loading…
Reference in New Issue
Block a user