From 956e00f789fa0e3f31f615c9c723f0db3cd6a99a Mon Sep 17 00:00:00 2001 From: catloversg <152669316+catloversg@users.noreply.github.com> Date: Wed, 15 Apr 2026 05:20:01 +0700 Subject: [PATCH] BUGFIX: Intelligence data is incorrectly migrated when Intelligence is not unlocked (#2660) --- src/Constants.ts | 2 +- src/PersonObjects/Person.ts | 6 +++- src/utils/SaveDataMigrationUtils.ts | 7 +++++ test/jest/Migration/Migration.test.ts | 27 ++++++++++++++++++ .../save-files/v2.8.1_SF1.1_SF10.3.gz | Bin 0 -> 8455 bytes .../save-files/v3.0.0_int_migration_bug.gz | Bin 0 -> 9421 bytes test/jest/Netscript/Singularity.test.ts | 4 +++ 7 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 test/jest/Migration/save-files/v2.8.1_SF1.1_SF10.3.gz create mode 100644 test/jest/Migration/save-files/v3.0.0_int_migration_bug.gz 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 0000000000000000000000000000000000000000..9fd16cd45a866e20134a75bc4992159812ba371e GIT binary patch literal 8455 zcmV+iA^6@OiwFP!000003hjMcbKAIec|WOV}uSr3{Mcdiz$Y53Rdvy z?r-R^;nC0s3=BW~9DWVJI_VmI82-E!7u^m&+@>AL_}k&pt+?WL_~Ga6aIsAO^ybf<*gE|U z<|xR2c?&>M6oT|8!VCrhnnUdI>&0{7CX z!&`u404FqSjFu4km9~&zxURI#DS0S2RR$z)DVfdeXJJHjg2k^=e|gF`zYAl^pCSEK z=&yX3>}O#FryN7}0}~%^z4NAH8B=coBKX525t9v|AbhgVBlPJD1Gs`gvDYKv65#a@ z3NsRCz+;HuLdyf8_a$OIibD7!iaifTQK_vs>Mj62Od$6o1dl%=210~^q&MyPF$V}s zx&a2kIzo}`%7li(I^zow#Pbkh2KamMtG@qrbUXZa3}fgY%euVequvgukmG)&Y69tZ zhjDX zSExc_+H)O;gr*qVY*GK3UVWLu((d&Ac6hUZg9%wd4EWac*ROmj@R!=$cmX0~`Z2j` z27(9{+iuX~@e-AL7MB2nxpQ-Wm`uL&5FvhJqCg2FIKeti_k#>;bCnWxKgFerxHJ@g&#~h!7^(j{rp3D)7V%dF2TzLsrSQsr3ITcC-KTZJINMXtPj@ ztTV+<`PbGZBw8W{0`yPunF!BNz)EC90fei~Wf3D@wkQ~3AV~kuH{NWB*gdif2wQAs zq`KKDVht2#{p5YtUuxEu0a!B>!YRTY{0t&?9P>A^RYy@|-6x1~wpJI zyeY2#NcO<(?cf@EWCiIu8Bp39*m?=Y$m`R|)$ga*|8qM`SP={f%_b;XB%7}5j$Okx z-1LuaCL1z^{$%Y1Vl&ct(;9o?4SyZIZ%yx8)BD!+zBRpXP48RN`_}ZnHN9_5Ew-k= za`oM|C+&sgdxEGC&b@no%M2E_uJA34Caci zqZyjvrk&hdQ|!`BMbC8kuc@kCP_4@!DK*Z{h!+-35Mv=!pkq~~Jd`s-01wwojfx7^nC)Scm>!f61sdS!{%r}+JEn9Ee{wcx! z#zLXhJZC9)tc3$!{Bi$7>MY4nH^o!%+n0Fa^j$*xI5|!~kUo&qoV@ z{X0VL#{psqNC=$+oSLz|WW@0mGWa?XPhCe6bw}Y!DwuES}B8&j`&!F!D$gLWaC#$lnA;^B5;T76i{nGl1tK z20_vSD7Z%yjiNYOpk&@C!K3*)Olc0K^Bw&=khMk&Nh^botnC&iUVLLCJ6R{r-Tdp_ z0q@=?gkIo?fz;xiJ?9QY@FSYdkQWE6$c(odLxi{6IJ-Mu0TggJrQ3^Wyc9xUYHjE5 z#@{izhX0Nc6$J22o}}%Q)Nrqe9V8j@DUoreT!75@h4{ATlss$%9U5cq#+Ysv$@jkm zpMl(3+ZldZd;D!WiU3ThXhfiE8*5QYAeR)4<4cUbZOk}I9cF?=yX%A)rz>C*BAV44ckGO{vDOYQnrUsRI(KkQus;d`ZqRLn zt~$8De$2JueZpt_24LbyVd6+(;!0tntGcCYifXxKnCO~gD2}2Sn${<8(VcCah~@GW zPJ|F}Sd<77n#C+-Y>(Zs@jRAtJ7fzuS|Hztc=SMM;5Xpp%O6)S!&!1k^VOrJvnZyy zj^@~wq8nNnEw*9Ws;elDY4)eLyRNkj7Q0Rm^8!HckudchRz1lHX~qp#PSmmaT-;PS zi*QUtY(!=w6o!QIFfg`mK+}ZN%h^sAsm8z8-qH2y0c9#OK#A5Zlb0<8lwvEEW?PC{ z(fCc(woJ=a6unQ?Mv<}~qXto%Z`Bb{JD8)TfGY0D4XTYZHpb>yZ-*yS80yN1@`w-p zQPE4gLDnL1$Z&8)Ys?k|`B4M3u0o7%;Qb3>E7gM-H+BLQjVs} zIGWVxtU9)Iy=~j9qDR`A>ID-7s{=uE>9;Yw5bBxK`p= z?n(YLbcs=+PX4=(0UFJTa1b9PCr(twvL#%l&iYmo6AsH-suD{Bf3e5v z*l5dNRBb!xAVOgra3O3&VH?%xETM031HA<%0h#aBC`V&#umxPGs``((=Itm;-EDQI z=2(`k<*HO_s&h2evK+LB95loimg>_ZgO5^-pS)jkJ$gpA?u437)Tg8fFYnJ7@ zeMWOSmL`cIsPlN{cFe=t#Y*mo#t;I1taUMp9gof_gm`pALP9BdXh6;Hh=I==SIPd> zm4f@JU|E0lKk;|8p; zKGu6TfL(~^4=(w7j@A)_;T{=HuF1T9Y*ewACEm=)fGJ6sx-!S6q83cpVoRs}*`?;d_`T=80 z0b{p!uc&5{XH!LtC?1&g$653gtFTfB3cocxU?yi-tX*NYtn)Q1_q)2y= z&7KNJdlE}GoIbA7@L)5t-z0)9bJ?rMQD;klqgu9UySh=ekQu7u8jjv4C>^yk5vJV}2P#u2Xz(g2~$jJOx_&g2&6qpD}>4aL>i zQsc8NH9ng%XqlGd+J@;m6@AChG()!xw^wLM{QtGd2U}a=VdXlRBcp*;nPYpbJUJ}qTQPscVK)$S97wxmFTU1#Z@gMioI@Dap&B7l!%w5iU(BiIt#U5wujFSDdEqLwU1RFlSt+ODY? zmZeql4pi51RMj%=K5cih_)xn}+X9f1KI(jQWnwuU&GtKYY>(~dW*+b^ETYFkUY89w z=~%~*lKocy2>Ag67{%cmNRPsC=~^{+TQgKwH62yyGj&^5SxRVB zPhsbuyO9rPhxQg_R5a^K96f5=5QS}Sv#UYk&y&H&r0(vE)CP%2!0Ye60o0gMbDk+R z=gCpyI;Ns(wp~SyYiXvgx^;5ej#hEomB?wesF7)?2e#|UNNR?YvX>mVAq#Tg5jVbD!h7t*;0VnQh-VA;f`fHs^S<` zfT@;iYPPENnCasflKcg`jyL6w_QM+CN)G>eh*`>*8{qmjzkTEsT;V;2%S9M0b34IN z*{WR#fvN_3`~&0Yjbt`-ub5~!uIf5lrFe8((_Gi=wGxk`Nz&$O3-QbYatDIZasg=P z^oFilQkjWMtHRBbEV>DvW)c8pFv7vv4Ta`J!&V}?8s>@&Q3!L8jmVl?)WBLH4M zn55Bnwlw-q%9(h@YSnaXN3Vd%u@!E=GwZ;#YcP=}3%{##)#mQ@11n1nNq`b>*LT`+f&A2c|pB;KQsR1#nDb}ZMnG&{(a zW(OHk#3+{S=$fHcd5LAY+}~3hiMq24Cd;#{i$pC1i5%8pT8>s}u)(?FERmMnq<#9s zXZX11aDt1m_$!9LIoD`s-QN}pzFI|!>bj0?+P2fDrCOJ%{&j}5ZT<4FdEDFdG-s%4 zW4(jz`bpeeFUVk0C1pQKK4JW5lTnP5Q`^cmkXMf&5fre6pd?hFTFF|-akR1O&NEl?xS#)lRST z1C_Vc!!oz6ExrMp=2+vw3VmB5{yZ66WMmA;EYE*^AwX^M_&1pcAr1U-q=7&3DvX+A zsg6@Uv_w;E)ii9SPg}Tc$ZX+tUZN-tL&W|Q*ji7M>cH8XcO1K&oXHVpZ12o zn*|(vN-5Y+7&i)5kdAnv6lKPL10G)qB{}^%%}~w&Lri-GLWK~sX;p#n>@Yy*$E4~o-y|Y zvd;+LzfiHcGMA}3D7MU^MfLL4TA^5ut2B z4$YS;#59N2iD-wu4-WoULdD>UQ?can+AjvISC17-iWN(W6=`6D!w<37^lH5k#o(Gw z?Fp#6N^i2T2BR+e6f26qJ*T@T0Ci&J-H5}?W~0rG?AWinSPaP1W+wSG>1 zD9y+tQP@xAovzN8DmiURCc0y%t;e%{48fFBGMJPoc}K?{(V@%Gkt!s;p+gb|pw=;w zzX^=yF+Mmhayps~WIRnl=|8CEUj+VlG&s+Qc*jBw7NmwSRb~j2>*uCSJJ))~f-2EB zv^p>(qVHjWuo1r-q$pmC&1?&T_TG~}Pp_517fzuU?9+)-)T!Q>My^T0p~=7@KQB%O z4%KPo6zYy4V-i+j)S;uO4<1+{FHq8~lk1{dd+*txUjz|3RtB5({SugYLtYh4Dp+YU z!AhD{plvj9iK(|YW}?ZMNuA<>A?X7vT`jyDGMa(n2;L^jQMnB1p+{WA$K4qbx8-}#bN_)i@*C3m5FG=gN(~=lv z3?D{}BG6c>eJThWeA*DUpS-qABrOK_6#cXnFVd^WlrH5+x-=w4S|G}hqpAh0cJ!&J zGF<6(Qrv>z`Dn&#AT!wc7=*5ZT!okx<<+<_*OEg?OvleT1Z}Lb8NKEuWoN?`tIQW!OF_^L}eQi%Hq$HHSdYp9SC8{FBiPr4c-_b-M3lFPR zWk?9;pbr~cS8h@uq!}RASm)waCo3B_5X?!Ff$fTuHJFka+kkh!mbJH*G1l1*U>TZj zD@HZr(o#%UvuaC5?aE_hRigE}FyzX&I&9E?g_!0rWJ8=p)%Ot~6Hdn9tU$(I@KW9` z@{H5hj~D4NZo2FkH+d?V>FAu>R8QMAOxrf=>t*a3i!3{hK(9Nq8c~8r^L6KAJ-W(c zIUQ|0pGNz`L)!~u7nI<^`8s^p=3k1BXi^c(Y*tlv6v3pbO0DTjQuybv)np_DwNP4| zvD3eXf0>bzv6TG-W-BQyKb!m2qsWw2zcr=RZ{-TVDTR^MLY3JuE6h|S#c%bxRF@@r zfK<2_`T~;L*+wQIsZGT*b8NKbIqhpmf87wXfBDQ1LE2(8+?1TZS-{Z*tlk1U>YT>x zDsq#6)`BDLSlCQeWM>xCCRmoMt{zsg**fyC0X^2(;V#ae^_nRL%l*S?bIvB^0 z=8qZD1Ttymbwkd3@{oZ3iZ9uU#1>FnC8K=4S4Xy^bgh0{BBt3rV~w@3-8R@JVa%=S z037XNYU4#`u49b%T3@9gs0&hJ+(a49O2{lF9_Fo*ce4NocPFmt**TOS~ zL|&`IN$DFMR$8krmxjblUffyfQh0q=ynI0nPNBEYV1YbXyi%5TgVlH7v;@wsCTUr^ zS{-o4okg{-w&-yiSB)lIHP4ONd=d-e{h=UYgyw?PT>$*Ipu+s8%2kG>(q-MUPrS{C zb;4{s-VGIE`7wlc+j217`NM>t6u4Igu^q5oWElm=<~v+k!e!SynjNL9+-%tqF4VtNqvTNL0E87{O=?R&e-X_>(uD0dXMQrY*7LPsj>lkR3$p zqsSvGNY|-*A|!%dans`ffv9}Tb8+Udq+`m6cYg`!J!JXg0uZrpOCPXouCAyroCqI& ziUq|(-TlehOFldwz>s$zeZvd|qM5gfyF;@ zi;H8*3d=6-`9#<~Tu0j-H}H|2&SubKlFq9Yq$>m;zH<1&C^`YOIO-JhK_?(uY~McV z`-J#Rucr`DuJ&(w&&dr1KH_fzf+<^z`OZ4|i$x5C%jk^I5ELfoGx0!>>@G0jq?h3F z8hQ}3bh0O42|ScUuqa9YXEK+x3N&mt-#{8741!V@@4JQ}VUX_>$4hkV`!w-_-wp## z6W@6SJ*8p%8R_c!7QsIv{ywDvg_q{*>l}pe3iG~cqFOK-i@tcd6w@ECkK=g=F%vuO zgy0$C6Oq1xULht{dF5`G`6gcJxuIYMgUaozv~csyT}&~gU&%6FO73#; z|DWjLZ|C!uy&)iC64Emeq|4C%15m#C6xY|c2wt2{EJe}mA6oGi3-WM@d_RC+;vnEl z=^IAHXPiEILF~ip(tdVENtn)gHtr&tA|KuX%J)>Uk*05P15j`cu@7khqiP~1umucL zop4D}26(-@#3rBj^$Am*465__*AcG&_z{ZqDy!SxFYtL-I|F6s7N#_M|j3bnOBZZq-?rhVXwCI+%X(>#Lp18IjU=S28Hw;ZkpcI?6^qV-o>Unvyz9B^6_fGivdLzOG2*Xb>{iNzx1ili? zGUm$-E)1aHtk7nqW6nT`g5*8_1=$G&2uGI$lcT}yEoZ?oMUW?3Kk%PNgOFenEddY9 z5qVQ7w@k>$q_TA({dcpC@ZqOEVuar0I|i2!#j{t@C|RiDJ1-y=8(6yicq9x-s#pWh zgXuarF(;?T3Fz(;=%}asZxYmyw0t!9-*m>-n1Qqc3Ns!#!L-5b9T(`AcPQVja7#X{OCwkWSl+)NS^x zGsCbAJ9(uT*0-C9rTKZZr5DHJV{f=;iJd&*rv5Sy;=jT53BrCVxBL`( z&F}o!Qi4-u!qA1P6P$xw!5AJ5KZA&!J}wDmCj`gQ@WW8GZHph0rWv}W36%$6cpsgk zSwZE=O$~W(#ojQZKrFY79*!dMh{*!bc`|_;ZMmW$3G&ZL{hvmI#YciYy>Df$z7&aq>qr_wxV0j&kBo(&wc5L)N@e+;4|}By3%9 pSqMrBa^7%8XgW@GEI|})1}5wWuqSoPU&CL&{ucmvR9ANr0RY_fUr+!5 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..c6ccca452d733744a5e7067dc40ec1e72232a42c GIT binary patch literal 9421 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 TrC)aV{rmp{s`5-?4jcgh_n>1y literal 0 HcmV?d00001 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).