Compare commits

...

2 Commits

8 changed files with 69 additions and 8 deletions

View File

@@ -7,7 +7,7 @@ export const CONSTANTS = {
VersionString: "3.0.0dev", VersionString: "3.0.0dev",
isDevBranch: true, isDevBranch: true,
isInTestEnvironment: globalThis.process?.env?.JEST_WORKER_ID !== undefined, 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 /** 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 * and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then

View File

@@ -9,6 +9,10 @@ import Tabs from "@mui/material/Tabs";
import Tab from "@mui/material/Tab"; import Tab from "@mui/material/Tab";
import { useCycleRerender } from "../../ui/React/hooks"; import { useCycleRerender } from "../../ui/React/hooks";
import Button from "@mui/material/Button";
import { Router } from "../../ui/GameRoot";
import { Page } from "../../ui/Router";
import { Factions } from "../../Faction/Factions";
/** React Component for all the gang stuff. */ /** React Component for all the gang stuff. */
export function GangRoot(): React.ReactElement { export function GangRoot(): React.ReactElement {
@@ -18,7 +22,7 @@ export function GangRoot(): React.ReactElement {
})(); })();
const [value, setValue] = React.useState(0); const [value, setValue] = React.useState(0);
function handleChange(event: React.SyntheticEvent, tab: number): void { function handleChange(__event: React.SyntheticEvent, tab: number): void {
setValue(tab); setValue(tab);
} }
@@ -26,11 +30,26 @@ export function GangRoot(): React.ReactElement {
return ( return (
<Context.Gang.Provider value={gang}> <Context.Gang.Provider value={gang}>
<Tabs variant="fullWidth" value={value} onChange={handleChange} sx={{ minWidth: "fit-content", maxWidth: "45%" }}> <div style={{ display: "flex" }}>
<Tabs
variant="fullWidth"
value={value}
onChange={handleChange}
sx={{ minWidth: "fit-content", maxWidth: "45%" }}
>
<Tab label="Management" /> <Tab label="Management" />
<Tab label="Equipment" /> <Tab label="Equipment" />
<Tab label="Territory" /> <Tab label="Territory" />
</Tabs> </Tabs>
<Button
style={{ marginLeft: "20px" }}
onClick={() => {
Router.toPage(Page.Faction, { faction: Factions[gang.facName] });
}}
>
Faction
</Button>
</div>
{value === 0 && <ManagementSubpage />} {value === 0 && <ManagementSubpage />}
{value === 1 && <EquipmentsSubpage />} {value === 1 && <EquipmentsSubpage />}
{value === 2 && <TerritorySubpage />} {value === 2 && <TerritorySubpage />}

View File

@@ -147,6 +147,10 @@ export abstract class Person implements IPerson {
} }
overrideIntelligence(): void { 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); 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 // 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. // 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 * Don't change sourceFileLvl to activeSourceFileLvl. When the player has int level, the ability to gain more int is
* a permanent benefit. * 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.exp.intelligence += exp;
this.skills.intelligence = Math.floor(this.calculateSkill(this.exp.intelligence, 1)); this.skills.intelligence = Math.floor(this.calculateSkill(this.exp.intelligence, 1));
this.persistentIntelligenceData.exp += exp; this.persistentIntelligenceData.exp += exp;

View File

@@ -637,4 +637,11 @@ Error: ${e}`,
if (ver < 48) { if (ver < 48) {
showAPIBreaks("3.0.0", breakingChanges300); 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;
}
}
} }

View File

@@ -105,4 +105,31 @@ describe("v3", () => {
`bitburnerSave_backup_2.8.1_${Math.round(lastUpdate / 1000)}.json.gz`, `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();
});
});
}); });

Binary file not shown.

View File

@@ -55,8 +55,12 @@ function testIntelligenceOverride(
setUpBeforePrestige = () => {}, setUpBeforePrestige = () => {},
): void { ): void {
Player.sourceFiles.set(5, 1); Player.sourceFiles.set(5, 1);
// The intelligence skill level starts at 0.
expect(Player.skills.intelligence).toStrictEqual(0);
prestigeSourceFile(true);
// Start without exp. // Start without exp.
expect(Player.exp.intelligence).toStrictEqual(0); 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.skills.intelligence).toStrictEqual(1);
expect(Player.persistentIntelligenceData.exp).toStrictEqual(0); expect(Player.persistentIntelligenceData.exp).toStrictEqual(0);
// Gain 1e6 exp (skill = 242). // Gain 1e6 exp (skill = 242).