[Refactor/Bug] Use Bit Shifting & Masking (#3278)

This commit is contained in:
Amani H. 2024-08-01 22:20:27 -04:00 committed by GitHub
parent 89d38a3b6b
commit aeafe0fddd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 39 additions and 59 deletions

View File

@ -435,7 +435,7 @@ export abstract class PokemonSpeciesForm {
for (const moveId of moveset) { for (const moveId of moveset) {
if (speciesEggMoves.hasOwnProperty(rootSpeciesId)) { if (speciesEggMoves.hasOwnProperty(rootSpeciesId)) {
const eggMoveIndex = speciesEggMoves[rootSpeciesId].findIndex(m => m === moveId); const eggMoveIndex = speciesEggMoves[rootSpeciesId].findIndex(m => m === moveId);
if (eggMoveIndex > -1 && eggMoves & Math.pow(2, eggMoveIndex)) { if (eggMoveIndex > -1 && (eggMoves & (1 << eggMoveIndex))) {
continue; continue;
} }
} }

View File

@ -1389,8 +1389,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return false; return false;
} }
const rand1 = Utils.binToDec(Utils.decToBin(this.id).substring(0, 16)); const rand1 = (this.id & 0xFFFF0000) >>> 16;
const rand2 = Utils.binToDec(Utils.decToBin(this.id).substring(16, 32)); const rand2 = (this.id & 0x0000FFFF);
const E = this.scene.gameData.trainerId ^ this.scene.gameData.secretId; const E = this.scene.gameData.trainerId ^ this.scene.gameData.secretId;
const F = rand1 ^ rand2; const F = rand1 ^ rand2;

View File

@ -1576,11 +1576,11 @@ export class PokemonNatureChangeModifier extends ConsumablePokemonModifier {
const pokemon = args[0] as Pokemon; const pokemon = args[0] as Pokemon;
pokemon.natureOverride = this.nature; pokemon.natureOverride = this.nature;
let speciesId = pokemon.species.speciesId; let speciesId = pokemon.species.speciesId;
pokemon.scene.gameData.dexData[speciesId].natureAttr |= Math.pow(2, this.nature + 1); pokemon.scene.gameData.dexData[speciesId].natureAttr |= 1 << (this.nature + 1);
while (pokemonPrevolutions.hasOwnProperty(speciesId)) { while (pokemonPrevolutions.hasOwnProperty(speciesId)) {
speciesId = pokemonPrevolutions[speciesId]; speciesId = pokemonPrevolutions[speciesId];
pokemon.scene.gameData.dexData[speciesId].natureAttr |= Math.pow(2, this.nature + 1); pokemon.scene.gameData.dexData[speciesId].natureAttr |= 1 << (this.nature + 1);
} }
return true; return true;

View File

@ -349,7 +349,7 @@ export class GameData {
this.scene.ui.savingIcon.show(); this.scene.ui.savingIcon.show();
const data = this.getSystemSaveData(); const data = this.getSystemSaveData();
const maxIntAttrValue = Math.pow(2, 31); const maxIntAttrValue = 0x80000000;
const systemData = JSON.stringify(data, (k: any, v: any) => typeof v === "bigint" ? v <= maxIntAttrValue ? Number(v) : v.toString() : v); const systemData = JSON.stringify(data, (k: any, v: any) => typeof v === "bigint" ? v <= maxIntAttrValue ? Number(v) : v.toString() : v);
localStorage.setItem(`data_${loggedInUser.username}`, encrypt(systemData, bypassLogin)); localStorage.setItem(`data_${loggedInUser.username}`, encrypt(systemData, bypassLogin));
@ -1163,7 +1163,7 @@ export class GameData {
} }
const sessionData = useCachedSession ? this.parseSessionData(decrypt(localStorage.getItem(`sessionData${scene.sessionSlotId ? scene.sessionSlotId : ""}_${loggedInUser.username}`), bypassLogin)) : this.getSessionSaveData(scene); const sessionData = useCachedSession ? this.parseSessionData(decrypt(localStorage.getItem(`sessionData${scene.sessionSlotId ? scene.sessionSlotId : ""}_${loggedInUser.username}`), bypassLogin)) : this.getSessionSaveData(scene);
const maxIntAttrValue = Math.pow(2, 31); const maxIntAttrValue = 0x80000000;
const systemData = useCachedSystem ? this.parseSystemData(decrypt(localStorage.getItem(`data_${loggedInUser.username}`), bypassLogin)) : this.getSystemSaveData(); const systemData = useCachedSystem ? this.parseSystemData(decrypt(localStorage.getItem(`data_${loggedInUser.username}`), bypassLogin)) : this.getSystemSaveData();
const request = { const request = {
@ -1368,7 +1368,7 @@ export class GameData {
const entry = data[defaultStarterSpecies[ds]] as DexEntry; const entry = data[defaultStarterSpecies[ds]] as DexEntry;
entry.seenAttr = defaultStarterAttr; entry.seenAttr = defaultStarterAttr;
entry.caughtAttr = defaultStarterAttr; entry.caughtAttr = defaultStarterAttr;
entry.natureAttr = Math.pow(2, defaultStarterNatures[ds] + 1); entry.natureAttr = 1 << (defaultStarterNatures[ds] + 1);
for (const i in entry.ivs) { for (const i in entry.ivs) {
entry.ivs[i] = 10; entry.ivs[i] = 10;
} }
@ -1435,10 +1435,10 @@ export class GameData {
dexEntry.caughtAttr |= dexAttr; dexEntry.caughtAttr |= dexAttr;
if (speciesStarters.hasOwnProperty(species.speciesId)) { if (speciesStarters.hasOwnProperty(species.speciesId)) {
this.starterData[species.speciesId].abilityAttr |= pokemon.abilityIndex !== 1 || pokemon.species.ability2 this.starterData[species.speciesId].abilityAttr |= pokemon.abilityIndex !== 1 || pokemon.species.ability2
? Math.pow(2, pokemon.abilityIndex) ? 1 << pokemon.abilityIndex
: AbilityAttr.ABILITY_HIDDEN; : AbilityAttr.ABILITY_HIDDEN;
} }
dexEntry.natureAttr |= Math.pow(2, pokemon.nature + 1); dexEntry.natureAttr |= 1 << (pokemon.nature + 1);
const hasPrevolution = pokemonPrevolutions.hasOwnProperty(species.speciesId); const hasPrevolution = pokemonPrevolutions.hasOwnProperty(species.speciesId);
const newCatch = !caughtAttr; const newCatch = !caughtAttr;
@ -1474,7 +1474,7 @@ export class GameData {
} }
if (!hasPrevolution && (!pokemon.scene.gameMode.isDaily || hasNewAttr || fromEgg)) { if (!hasPrevolution && (!pokemon.scene.gameMode.isDaily || hasNewAttr || fromEgg)) {
this.addStarterCandy(species, (1 * (pokemon.isShiny() ? 5 * Math.pow(2, pokemon.variant || 0) : 1)) * (fromEgg || pokemon.isBoss() ? 2 : 1)); this.addStarterCandy(species, (1 * (pokemon.isShiny() ? 5 * (1 << (pokemon.variant ?? 0)) : 1)) * (fromEgg || pokemon.isBoss() ? 2 : 1));
} }
} }
@ -1545,7 +1545,7 @@ export class GameData {
this.starterData[speciesId].eggMoves = 0; this.starterData[speciesId].eggMoves = 0;
} }
const value = Math.pow(2, eggMoveIndex); const value = 1 << eggMoveIndex;
if (this.starterData[speciesId].eggMoves & value) { if (this.starterData[speciesId].eggMoves & value) {
resolve(false); resolve(false);
@ -1637,7 +1637,7 @@ export class GameData {
getSpeciesDefaultNature(species: PokemonSpecies): Nature { getSpeciesDefaultNature(species: PokemonSpecies): Nature {
const dexEntry = this.dexData[species.speciesId]; const dexEntry = this.dexData[species.speciesId];
for (let n = 0; n < 25; n++) { for (let n = 0; n < 25; n++) {
if (dexEntry.natureAttr & Math.pow(2, n + 1)) { if (dexEntry.natureAttr & (1 << (n + 1))) {
return n as Nature; return n as Nature;
} }
} }
@ -1645,7 +1645,7 @@ export class GameData {
} }
getSpeciesDefaultNatureAttr(species: PokemonSpecies): integer { getSpeciesDefaultNatureAttr(species: PokemonSpecies): integer {
return Math.pow(2, this.getSpeciesDefaultNature(species)); return 1 << (this.getSpeciesDefaultNature(species));
} }
getDexAttrLuck(dexAttr: bigint): integer { getDexAttrLuck(dexAttr: bigint): integer {
@ -1655,7 +1655,7 @@ export class GameData {
getNaturesForAttr(natureAttr: integer): Nature[] { getNaturesForAttr(natureAttr: integer): Nature[] {
const ret: Nature[] = []; const ret: Nature[] = [];
for (let n = 0; n < 25; n++) { for (let n = 0; n < 25; n++) {
if (natureAttr & Math.pow(2, n + 1)) { if (natureAttr & (1 << (n + 1))) {
ret.push(n); ret.push(n);
} }
} }
@ -1697,7 +1697,7 @@ export class GameData {
} }
getFormAttr(formIndex: integer): bigint { getFormAttr(formIndex: integer): bigint {
return BigInt(Math.pow(2, 7 + formIndex)); return BigInt(1 << (7 + formIndex));
} }
consolidateDexData(dexData: DexData): void { consolidateDexData(dexData: DexData): void {
@ -1707,7 +1707,7 @@ export class GameData {
entry.hatchedCount = 0; entry.hatchedCount = 0;
} }
if (!entry.hasOwnProperty("natureAttr") || (entry.caughtAttr && !entry.natureAttr)) { if (!entry.hasOwnProperty("natureAttr") || (entry.caughtAttr && !entry.natureAttr)) {
entry.natureAttr = this.defaultDexData[k].natureAttr || Math.pow(2, Utils.randInt(25, 1)); entry.natureAttr = this.defaultDexData[k].natureAttr || (1 << Utils.randInt(25, 1));
} }
} }
} }

View File

@ -216,7 +216,7 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container {
this.pokemonGenderText.setShadowColor(getGenderColor(pokemon.gender, true)); this.pokemonGenderText.setShadowColor(getGenderColor(pokemon.gender, true));
this.pokemonGenderText.setVisible(true); this.pokemonGenderText.setVisible(true);
const newGender = BigInt(Math.pow(2, pokemon.gender)) * DexAttr.MALE; const newGender = BigInt(1 << pokemon.gender) * DexAttr.MALE;
this.pokemonGenderNewText.setText("(+)"); this.pokemonGenderNewText.setText("(+)");
this.pokemonGenderNewText.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false, this.scene.uiTheme)); this.pokemonGenderNewText.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false, this.scene.uiTheme));
this.pokemonGenderNewText.setShadowColor(getTextColor(TextStyle.SUMMARY_BLUE, true, this.scene.uiTheme)); this.pokemonGenderNewText.setShadowColor(getTextColor(TextStyle.SUMMARY_BLUE, true, this.scene.uiTheme));
@ -229,7 +229,7 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container {
if (pokemon.species.forms?.[pokemon.formIndex]?.formName) { if (pokemon.species.forms?.[pokemon.formIndex]?.formName) {
this.pokemonFormLabelText.setVisible(true); this.pokemonFormLabelText.setVisible(true);
this.pokemonFormText.setVisible(true); this.pokemonFormText.setVisible(true);
const newForm = BigInt(Math.pow(2, pokemon.formIndex)) * DexAttr.DEFAULT_FORM; const newForm = BigInt(1 << pokemon.formIndex) * DexAttr.DEFAULT_FORM;
if ((newForm & caughtAttr) === BigInt(0)) { if ((newForm & caughtAttr) === BigInt(0)) {
this.pokemonFormLabelText.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false, this.scene.uiTheme)); this.pokemonFormLabelText.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false, this.scene.uiTheme));
@ -266,7 +266,7 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container {
*/ */
const opponentPokemonOneNormalAbility = (pokemon.species.getAbilityCount() === 2); const opponentPokemonOneNormalAbility = (pokemon.species.getAbilityCount() === 2);
const opponentPokemonAbilityIndex = (opponentPokemonOneNormalAbility && pokemon.abilityIndex === 1) ? 2 : pokemon.abilityIndex; const opponentPokemonAbilityIndex = (opponentPokemonOneNormalAbility && pokemon.abilityIndex === 1) ? 2 : pokemon.abilityIndex;
const opponentPokemonAbilityAttr = Math.pow(2, opponentPokemonAbilityIndex); const opponentPokemonAbilityAttr = 1 << opponentPokemonAbilityIndex;
const rootFormHasHiddenAbility = pokemon.scene.gameData.starterData[pokemon.species.getRootSpeciesId()].abilityAttr & opponentPokemonAbilityAttr; const rootFormHasHiddenAbility = pokemon.scene.gameData.starterData[pokemon.species.getRootSpeciesId()].abilityAttr & opponentPokemonAbilityAttr;
@ -281,7 +281,7 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container {
this.pokemonNatureText.setText(getNatureName(pokemon.getNature(), true, false, false, this.scene.uiTheme)); this.pokemonNatureText.setText(getNatureName(pokemon.getNature(), true, false, false, this.scene.uiTheme));
const dexNatures = pokemon.scene.gameData.dexData[pokemon.species.speciesId].natureAttr; const dexNatures = pokemon.scene.gameData.dexData[pokemon.species.speciesId].natureAttr;
const newNature = Math.pow(2, pokemon.nature + 1); const newNature = 1 << (pokemon.nature + 1);
if (!(dexNatures & newNature)) { if (!(dexNatures & newNature)) {
this.pokemonNatureLabelText.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false, this.scene.uiTheme)); this.pokemonNatureLabelText.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false, this.scene.uiTheme));
@ -305,8 +305,8 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container {
this.pokemonShinyIcon.on("pointerover", () => (this.scene as BattleScene).ui.showTooltip(null, `${i18next.t("common:shinyOnHover")}${shinyDescriptor ? ` (${shinyDescriptor})` : ""}`, true)); this.pokemonShinyIcon.on("pointerover", () => (this.scene as BattleScene).ui.showTooltip(null, `${i18next.t("common:shinyOnHover")}${shinyDescriptor ? ` (${shinyDescriptor})` : ""}`, true));
this.pokemonShinyIcon.on("pointerout", () => (this.scene as BattleScene).ui.hideTooltip()); this.pokemonShinyIcon.on("pointerout", () => (this.scene as BattleScene).ui.hideTooltip());
const newShiny = BigInt(Math.pow(2, (pokemon.shiny ? 1 : 0))); const newShiny = BigInt(1 << (pokemon.shiny ? 1 : 0));
const newVariant = BigInt(Math.pow(2, pokemon.variant + 4)); const newVariant = BigInt(1 << (pokemon.variant + 4));
this.pokemonShinyNewIcon.setText("(+)"); this.pokemonShinyNewIcon.setText("(+)");
this.pokemonShinyNewIcon.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false, this.scene.uiTheme)); this.pokemonShinyNewIcon.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false, this.scene.uiTheme));

View File

@ -2611,7 +2611,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.speciesStarterMoves.push(...levelMoves.filter(lm => lm[0] > 0 && lm[0] <= 5).map(lm => lm[1])); this.speciesStarterMoves.push(...levelMoves.filter(lm => lm[0] > 0 && lm[0] <= 5).map(lm => lm[1]));
if (speciesEggMoves.hasOwnProperty(species.speciesId)) { if (speciesEggMoves.hasOwnProperty(species.speciesId)) {
for (let em = 0; em < 4; em++) { for (let em = 0; em < 4; em++) {
if (this.scene.gameData.starterData[species.speciesId].eggMoves & Math.pow(2, em)) { if (this.scene.gameData.starterData[species.speciesId].eggMoves & (1 << em)) {
this.speciesStarterMoves.push(speciesEggMoves[species.speciesId][em]); this.speciesStarterMoves.push(speciesEggMoves[species.speciesId][em]);
} }
} }
@ -2623,7 +2623,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
? speciesMoveData as StarterMoveset ? speciesMoveData as StarterMoveset
: (speciesMoveData as StarterFormMoveData)[formIndex] : (speciesMoveData as StarterFormMoveData)[formIndex]
: null; : null;
const availableStarterMoves = this.speciesStarterMoves.concat(speciesEggMoves.hasOwnProperty(species.speciesId) ? speciesEggMoves[species.speciesId].filter((_, em: integer) => this.scene.gameData.starterData[species.speciesId].eggMoves & Math.pow(2, em)) : []); const availableStarterMoves = this.speciesStarterMoves.concat(speciesEggMoves.hasOwnProperty(species.speciesId) ? speciesEggMoves[species.speciesId].filter((_, em: integer) => this.scene.gameData.starterData[species.speciesId].eggMoves & (1 << em)) : []);
this.starterMoveset = (moveData || (this.speciesStarterMoves.slice(0, 4) as StarterMoveset)).filter(m => availableStarterMoves.find(sm => sm === m)) as StarterMoveset; this.starterMoveset = (moveData || (this.speciesStarterMoves.slice(0, 4) as StarterMoveset)).filter(m => availableStarterMoves.find(sm => sm === m)) as StarterMoveset;
// Consolidate move data if it contains an incompatible move // Consolidate move data if it contains an incompatible move
if (this.starterMoveset.length < 4 && this.starterMoveset.length < availableStarterMoves.length) { if (this.starterMoveset.length < 4 && this.starterMoveset.length < availableStarterMoves.length) {
@ -2680,7 +2680,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
for (let em = 0; em < 4; em++) { for (let em = 0; em < 4; em++) {
const eggMove = hasEggMoves ? allMoves[speciesEggMoves[species.speciesId][em]] : null; const eggMove = hasEggMoves ? allMoves[speciesEggMoves[species.speciesId][em]] : null;
const eggMoveUnlocked = eggMove && this.scene.gameData.starterData[species.speciesId].eggMoves & Math.pow(2, em); const eggMoveUnlocked = eggMove && this.scene.gameData.starterData[species.speciesId].eggMoves & (1 << em);
this.pokemonEggMoveBgs[em].setFrame(Type[eggMove ? eggMove.type : Type.UNKNOWN].toString().toLowerCase()); this.pokemonEggMoveBgs[em].setFrame(Type[eggMove ? eggMove.type : Type.UNKNOWN].toString().toLowerCase());
this.pokemonEggMoveLabels[em].setText(eggMove && eggMoveUnlocked ? eggMove.name : "???"); this.pokemonEggMoveLabels[em].setText(eggMove && eggMoveUnlocked ? eggMove.name : "???");
} }

View File

@ -165,40 +165,20 @@ export function getPlayTimeString(totalSeconds: integer): string {
return `${days.padStart(2, "0")}:${hours.padStart(2, "0")}:${minutes.padStart(2, "0")}:${seconds.padStart(2, "0")}`; return `${days.padStart(2, "0")}:${hours.padStart(2, "0")}:${minutes.padStart(2, "0")}:${seconds.padStart(2, "0")}`;
} }
export function binToDec(input: string): integer { /**
const place: integer[] = []; * Generates IVs from a given {@linkcode id} by extracting 5 bits at a time
const binary: string[] = []; * starting from the least significant bit up to the 30th most significant bit.
* @param id 32-bit number
let decimalNum = 0; * @returns An array of six numbers corresponding to 5-bit chunks from {@linkcode id}
*/
for (let i = 0; i < input.length; i++) { export function getIvsFromId(id: number): number[] {
binary.push(input[i]);
place.push(Math.pow(2, i));
decimalNum += place[i] * parseInt(binary[i]);
}
return decimalNum;
}
export function decToBin(input: integer): string {
let bin = "";
let intNum = input;
while (intNum > 0) {
bin = intNum % 2 ? `1${bin}` : `0${bin}`;
intNum = Math.floor(intNum * 0.5);
}
return bin;
}
export function getIvsFromId(id: integer): integer[] {
return [ return [
binToDec(decToBin(id).substring(0, 5)), (id & 0x3E000000) >>> 25,
binToDec(decToBin(id).substring(5, 10)), (id & 0x01F00000) >>> 20,
binToDec(decToBin(id).substring(10, 15)), (id & 0x000F8000) >>> 15,
binToDec(decToBin(id).substring(15, 20)), (id & 0x00007C00) >>> 10,
binToDec(decToBin(id).substring(20, 25)), (id & 0x000003E0) >>> 5,
binToDec(decToBin(id).substring(25, 30)) (id & 0x0000001F)
]; ];
} }