diff --git a/src/Constants.ts b/src/Constants.ts index e790a9d05..e02abedb1 100644 --- a/src/Constants.ts +++ b/src/Constants.ts @@ -7,7 +7,7 @@ export const CONSTANTS = { VersionString: "3.0.0dev", isDevBranch: true, isInTestEnvironment: globalThis.process?.env?.JEST_WORKER_ID !== undefined, - VersionNumber: 48, + VersionNumber: 49, /** Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience * and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then diff --git a/src/PersonObjects/Person.ts b/src/PersonObjects/Person.ts index 741886f7d..c04468a1f 100644 --- a/src/PersonObjects/Person.ts +++ b/src/PersonObjects/Person.ts @@ -147,6 +147,10 @@ export abstract class Person implements IPerson { } overrideIntelligence(): void { + // Do not set anything if the player has not unlocked Intelligence. + if (Player.sourceFileLvl(5) === 0 && Player.bitNodeN !== 5) { + return; + } const persistentIntelligenceSkill = this.calculateSkill(this.persistentIntelligenceData.exp, 1); // Reset exp and skill to the persistent values if there is no limit (intelligenceOverride) or the limit is greater // than or equal to the persistent skill. @@ -172,7 +176,7 @@ export abstract class Person implements IPerson { * Don't change sourceFileLvl to activeSourceFileLvl. When the player has int level, the ability to gain more int is * a permanent benefit. */ - if (Player.sourceFileLvl(5) > 0 || this.skills.intelligence > 0 || Player.bitNodeN === 5) { + if (Player.sourceFileLvl(5) > 0 || Player.bitNodeN === 5) { this.exp.intelligence += exp; this.skills.intelligence = Math.floor(this.calculateSkill(this.exp.intelligence, 1)); this.persistentIntelligenceData.exp += exp; diff --git a/src/utils/SaveDataMigrationUtils.ts b/src/utils/SaveDataMigrationUtils.ts index c8706aada..bfaf637f7 100644 --- a/src/utils/SaveDataMigrationUtils.ts +++ b/src/utils/SaveDataMigrationUtils.ts @@ -637,4 +637,11 @@ Error: ${e}`, if (ver < 48) { showAPIBreaks("3.0.0", breakingChanges300); } + if (ver < 49 && Player.sourceFileLvl(5) === 0 && Player.bitNodeN !== 5) { + for (const person of [Player, ...Player.sleeves]) { + person.persistentIntelligenceData.exp = 0; + person.exp.intelligence = 0; + person.skills.intelligence = 0; + } + } } diff --git a/test/jest/Migration/Migration.test.ts b/test/jest/Migration/Migration.test.ts index 7c2e06c3f..6d78f02c8 100644 --- a/test/jest/Migration/Migration.test.ts +++ b/test/jest/Migration/Migration.test.ts @@ -105,4 +105,31 @@ describe("v3", () => { `bitburnerSave_backup_2.8.1_${Math.round(lastUpdate / 1000)}.json.gz`, ); }); + + describe("Intelligence migration bug", () => { + test("No change in exp and skill level", async () => { + const saveData = new Uint8Array(fs.readFileSync("test/jest/Migration/save-files/v2.8.1_SF1.1_SF10.3.gz")); + const mockedDownload = await loadGameFromSaveData(saveData); + + for (const person of [Player, ...Player.sleeves]) { + expect(person.persistentIntelligenceData.exp).toStrictEqual(0); + expect(person.exp.intelligence).toStrictEqual(0); + expect(person.skills.intelligence).toStrictEqual(0); + } + + expect(mockedDownload).toHaveBeenCalledWith(saveData, "bitburnerSave_backup_2.8.1_1776173824.json.gz"); + }); + test("Reset wrong exp and skill level", async () => { + const saveData = new Uint8Array(fs.readFileSync("test/jest/Migration/save-files/v3.0.0_int_migration_bug.gz")); + const mockedDownload = await loadGameFromSaveData(saveData); + + for (const person of [Player, ...Player.sleeves]) { + expect(person.persistentIntelligenceData.exp).toStrictEqual(0); + expect(person.exp.intelligence).toStrictEqual(0); + expect(person.skills.intelligence).toStrictEqual(0); + } + + expect(mockedDownload).not.toHaveBeenCalled(); + }); + }); }); diff --git a/test/jest/Migration/save-files/v2.8.1_SF1.1_SF10.3.gz b/test/jest/Migration/save-files/v2.8.1_SF1.1_SF10.3.gz new file mode 100644 index 000000000..9fd16cd45 Binary files /dev/null and b/test/jest/Migration/save-files/v2.8.1_SF1.1_SF10.3.gz differ diff --git a/test/jest/Migration/save-files/v3.0.0_int_migration_bug.gz b/test/jest/Migration/save-files/v3.0.0_int_migration_bug.gz new file mode 100644 index 000000000..c6ccca452 Binary files /dev/null and b/test/jest/Migration/save-files/v3.0.0_int_migration_bug.gz differ diff --git a/test/jest/Netscript/Singularity.test.ts b/test/jest/Netscript/Singularity.test.ts index e2c5b5925..bf457cbd0 100644 --- a/test/jest/Netscript/Singularity.test.ts +++ b/test/jest/Netscript/Singularity.test.ts @@ -55,8 +55,12 @@ function testIntelligenceOverride( setUpBeforePrestige = () => {}, ): void { Player.sourceFiles.set(5, 1); + // The intelligence skill level starts at 0. + expect(Player.skills.intelligence).toStrictEqual(0); + prestigeSourceFile(true); // Start without exp. expect(Player.exp.intelligence).toStrictEqual(0); + // When having SF5 and the skill level is 0, it's set to 1. expect(Player.skills.intelligence).toStrictEqual(1); expect(Player.persistentIntelligenceData.exp).toStrictEqual(0); // Gain 1e6 exp (skill = 242).