From 141313472f8e4823eb8ec94e59b5dfc2b35a7c66 Mon Sep 17 00:00:00 2001 From: Frankly George <54015-franklygeorge@users.noreply.gitgud.io> Date: Fri, 11 Oct 2024 20:10:44 +0000 Subject: [PATCH] Fix #5440 --- src/002-config/fc-version.js | 2 +- src/data/dataUtils.js | 52 ++++- .../releases/1267_fixEyeColorsInFetuses.js | 12 ++ src/events/RE/reRelativeRecruiter.js | 4 +- src/events/intro/acquisition.js | 4 +- src/events/nonRandom/pregnancyNotice.js | 1 - src/interaction/siCustom.js | 5 +- src/js/eventHandlers.js | 9 + src/js/extendedFamilyModeJS.js | 4 +- src/js/ibcJS.js | 2 +- src/js/states/001-GenePoolRecord.js | 197 +++++++++--------- src/npc/generate/generateGenetics.js | 24 ++- src/npc/surgery/bodySwap/huskSlaveSwap.js | 2 +- src/npc/surgery/bodySwap/slaveSlaveSwap.js | 4 +- src/pregmod/editGenetics.js | 5 +- 15 files changed, 190 insertions(+), 137 deletions(-) create mode 100644 src/data/patches/releases/1267_fixEyeColorsInFetuses.js diff --git a/src/002-config/fc-version.js b/src/002-config/fc-version.js index 7676d245b18..e87e0c2765c 100644 --- a/src/002-config/fc-version.js +++ b/src/002-config/fc-version.js @@ -10,5 +10,5 @@ App.Version = { * The release numbers got messed up, this is corrected in `src/js/eventHandlers.js` and `/src/data/patches/patch.js`. * The two line above and this line should be safe to remove after release 2001. */ - release: 1266, + release: 1267, }; diff --git a/src/data/dataUtils.js b/src/data/dataUtils.js index ebe05fbaacf..c9c5bcb8f7f 100644 --- a/src/data/dataUtils.js +++ b/src/data/dataUtils.js @@ -25,7 +25,30 @@ App.Utils.setNonexistentProperties = function(obj, props) { * @param {...object} defaultObjs one or more objects to add the properties from. */ App.Utils.assignMissingDefaults = (obj, ...defaultObjs) => { - _.defaultsDeep(obj, ...defaultObjs); + if (obj === undefined || obj == null) { + throw new Error(`assignMissingDefaults() expects param in position 1 to be an object`); + } + /** @type {object[]} */ + const defaults = [...defaultObjs]; + for (const index in defaults) { + if (defaults[index] === undefined || defaults[index] == null) { + throw new Error(`assignMissingDefaults() expects param in position ${Number(index) +2} to be an object`); + } + } + for (const defaultObj of defaults) { + for (const key of Object.keys(defaultObj)) { + if (obj[key] === undefined) { + obj[key] = clone(defaultObj[key]); + } else if ( + obj[key] != null && typeof obj[key] === "object" && + defaultObj[key] != null && typeof defaultObj[key] === "object" && + !Array.isArray(defaultObj[key]) + ) { + App.Utils.assignMissingDefaults(obj[key], defaultObj[key]); + } + } + } + return obj; // we return the obj so that is some idiot (like me) tries to assign the result of this call to something it will work as they expect }; /** @@ -59,17 +82,32 @@ App.Utils.setExistentProperties = function(obj, props) { * @param {...object} defaultObjs one or more objects to use the properties and values from */ App.Utils.overwriteWithDefaults = (obj, ...defaultObjs) => { + if (obj === undefined || obj == null) { + throw new Error(`overwriteWithDefaults() expects and object`); + } /** @type {object[]} */ const defaults = [...defaultObjs]; - defaults.forEach((defaultObj) => { - Object.keys(defaultObj).forEach((key) => { - if (typeof obj[key] === "object" && typeof defaultObj[key] === "object" && !Array.isArray(defaultObj[key])) { - obj[key] = App.Utils.overwriteWithDefaults(obj[key] ?? {}, defaultObj[key]); + for (const index in defaults) { + if (defaults[index] === undefined || defaults[index] == null) { + throw new Error(`overwriteWithDefaults() expects param in position ${Number(index) +2} to be an object`); + } + } + for (const defaultObj of defaults) { + if (defaultObj === undefined || obj == null) { continue; } + for (const key of Object.keys(defaultObj)) { + if (obj[key] != null && typeof obj[key] === "object" && + defaultObj[key] != null && typeof defaultObj[key] === "object" && + !Array.isArray(defaultObj[key]) + ) { + App.Utils.overwriteWithDefaults(obj[key] ?? {}, defaultObj[key]); + } else if (Array.isArray(obj[key]) && Array.isArray(defaultObj[key])) { + obj[key] = Array.from(clone(defaultObj[key])); } else { obj[key] = defaultObj[key]; } - }); - }); + } + } + return obj; // we return the obj so that is some idiot (like me) tries to assign the result of this call to something it will work as they expect }; /** diff --git a/src/data/patches/releases/1267_fixEyeColorsInFetuses.js b/src/data/patches/releases/1267_fixEyeColorsInFetuses.js new file mode 100644 index 00000000000..2be2431286a --- /dev/null +++ b/src/data/patches/releases/1267_fixEyeColorsInFetuses.js @@ -0,0 +1,12 @@ +App.Patch.register({ + releaseID: 1267, + descriptionOfChanges: "Adds eye color to fetuses if it is missing due to bugs in getGenePoolRecord()", + fetus: (div, fetus, mother) => { + if (fetus.genetics.eyeColor === undefined) { + const motherColor = getGenePoolRecord(mother).eye.origColor; + fetus.genetics.eyeColor = motherColor; + App.Patch.log(`Setting undefined eye color to '${motherColor}'`); + } + return fetus; + } +}); diff --git a/src/events/RE/reRelativeRecruiter.js b/src/events/RE/reRelativeRecruiter.js index 23e3ded0fad..2101790d96a 100644 --- a/src/events/RE/reRelativeRecruiter.js +++ b/src/events/RE/reRelativeRecruiter.js @@ -41,7 +41,7 @@ App.Events.RERelativeRecruiter = class RERelativeRecruiter extends App.Events.Ba /** find all eligible target relatives for a slave; one will be selected randomly (or by cheating) * @param {FC.SlaveState} slave who's doing the recruiting (should be first actor) - * @param {FC.GenePoolRecord} [gp] genepool entry for this slave, if known + * @param {ReadonlyDeep<FC.GenePoolRecord>} [gp] genepool entry for this slave, if known * @returns {string[]} */ _getTargetRelativeChoices(slave, gp) { @@ -621,7 +621,7 @@ App.Events.RERelativeRecruiter = class RERelativeRecruiter extends App.Events.Ba * @param {number} [parentIDs.father] */ function setUnknownParents(slave, parentIDs = {}) { - const gp = isInGenePool(slave) ? getGenePoolRecord(slave, false, true) : undefined; + const gp = isInGenePool(slave) ? getGenePoolRecordWriteMode(slave) : undefined; if (parentIDs.mother) { slave.mother = parentIDs.mother; diff --git a/src/events/intro/acquisition.js b/src/events/intro/acquisition.js index dae2e7c7cb3..422d51c57d4 100644 --- a/src/events/intro/acquisition.js +++ b/src/events/intro/acquisition.js @@ -605,14 +605,14 @@ App.Intro.acquisition = function() { for (const slave of getSlaves()) { if (slave.newGamePlus === 0) { slave.inbreedingCoeff = -1; - getGenePoolRecord(slave, false, true).inbreedingCoeff = -1; + getGenePoolRecordWriteMode(slave).inbreedingCoeff = -1; coeffSlaves.push(slave); } } const ibcoeffs = ibc.coeff_slaves(coeffSlaves); for (const slave of coeffSlaves) { slave.inbreedingCoeff = ibcoeffs[slave.ID]; - getGenePoolRecord(slave, false, true).inbreedingCoeff = ibcoeffs[slave.ID]; + getGenePoolRecordWriteMode(slave).inbreedingCoeff = ibcoeffs[slave.ID]; } } diff --git a/src/events/nonRandom/pregnancyNotice.js b/src/events/nonRandom/pregnancyNotice.js index b0edbfa4230..8ec311ad2fc 100644 --- a/src/events/nonRandom/pregnancyNotice.js +++ b/src/events/nonRandom/pregnancyNotice.js @@ -443,7 +443,6 @@ App.Events.PregnancyNotice.Event = (node, mother) => { const twins = getFetusTwins(fetus); /** @type {FC.SlaveState} */ - // @ts-expect-error As long as generateChild's code is not changed incubator = true will return a SlaveState object const fakeChild = generateChild(mother, fetus, true); // Age fake child up to the ideal age while (fakeChild.actualAge < V.idealAge) { diff --git a/src/interaction/siCustom.js b/src/interaction/siCustom.js index 1d8ebe98feb..e71995b5517 100644 --- a/src/interaction/siCustom.js +++ b/src/interaction/siCustom.js @@ -548,14 +548,11 @@ App.UI.SlaveInteract.custom = function(slave, refresh) { } function updateName(slave, {oldName: oldName, oldSurname: oldSurname}) { - // @ts-ignore you shouldn't access V.genePool directly because it isn't supposed to change; this is an exception; For normal use use getGenePoolRecord() - let genepoolRec = isInGenePool(slave) ? getGenePoolRecord(slave, false, true) : undefined; + let genepoolRec = isInGenePool(slave) ? getGenePoolRecordWriteMode(slave) : undefined; if (genepoolRec) { genepoolRec.slaveName = slave.slaveName; genepoolRec.slaveSurname = slave.slaveSurname; App.UI.SlaveInteract.rename(slave, {oldName: oldName, oldSurname: oldSurname}); - } else { - console.error(`slave with ID ${slave.ID} is missing its gene pool record`); } refresh(); } diff --git a/src/js/eventHandlers.js b/src/js/eventHandlers.js index f5834988d59..4ecc7fafc64 100644 --- a/src/js/eventHandlers.js +++ b/src/js/eventHandlers.js @@ -24,6 +24,15 @@ App.EventHandlers = function() { * @param {TwineSugarCube.SaveObject} save */ function onSave(save) { + try { + // make sure all genePool records are sparse before saving + // this saves storage space; in some cases by a crazy amount + for (const record of Object.values(V.genePool)) { + makeSparseGeneRecord(/** @type {FC.GenePoolRecord} */ (record)); + } + } catch (ex) { + console.error(ex); + } if (App.Utils.isEndWeek() && V.endweekSaveWarning && Dialog.isOpen()) { $(document).one(':dialogclosed', () => { Dialog.create("Saving during End Week"); diff --git a/src/js/extendedFamilyModeJS.js b/src/js/extendedFamilyModeJS.js index 03ffdf47b60..54c21bf727c 100644 --- a/src/js/extendedFamilyModeJS.js +++ b/src/js/extendedFamilyModeJS.js @@ -32,7 +32,7 @@ globalThis.getRelative = function(ID) { return slave; } // ex-slave - const genePool = getGenePoolRecord(ID); + const genePool = getGenePoolRecordWriteMode(ID); if (genePool) { return genePool; } @@ -512,7 +512,7 @@ globalThis.resetFamilyCounters = function() { * @param {Relative} slave */ globalThis.setMissingParents = function(slave) { - const gp = isInGenePool(slave.ID) ? getGenePoolRecord(slave.ID, false, true) : undefined; + const gp = isInGenePool(slave.ID) ? getGenePoolRecordWriteMode(slave.ID) : undefined; if (!specificMom(slave)) { slave.mother = V.missingParentID; if (gp) { diff --git a/src/js/ibcJS.js b/src/js/ibcJS.js index 03530d9a74a..d0541022825 100644 --- a/src/js/ibcJS.js +++ b/src/js/ibcJS.js @@ -32,7 +32,7 @@ globalThis.ibc = (() => { if (Array.isArray(V.genePool)) { record = V.genePool.find((s) => { return s.ID === id; }); } else { - record = getGenePoolRecord(id, true); + record = getGenePoolRecordWriteMode(id); } } record = record || ((id in V.missingTable) ? V.missingTable[id] : null) || null; diff --git a/src/js/states/001-GenePoolRecord.js b/src/js/states/001-GenePoolRecord.js index b09d57dbb79..b1e1494d7ba 100644 --- a/src/js/states/001-GenePoolRecord.js +++ b/src/js/states/001-GenePoolRecord.js @@ -3,6 +3,7 @@ * This houses App.Entity.GenePoolRecord and the functions that you should use to manipulate the gene pool. * The gene pool is read only and should not be accessed directly. Use the functions below to access it. * @see getGenePoolRecord use this to get a record from the gene pool. + * @see getGenePoolRecordWriteMode use this to edit a record in the gene pool. * @see isInGenePool use this to check if a record is in the gene pool already; gene pool records must have unique slave IDs * @see addToGenePool use this to add a HumanState object to the gene pool; this will throw an error if a record already exist for the HumanState * @see deleteGenePoolRecord use this to remove the record from the gene pool; by default this will keep records that are still needed @@ -10,75 +11,24 @@ * @see App.Entity.GenePoolRecord the class that defines what a GenePoolRecord is. Handle with care */ - /** * Returns a read only record from the gene pool, will return undefined if there is no valid record. + * Use `getGenePoolRecordWriteMode()` if you need to edit records. + * @see getGenePoolRecordWriteMode + * @param {FC.HumanState|number} key The HumanState object or ID to get the record for. + * @returns {ReadonlyDeep<FC.GenePoolRecord>} + */ +globalThis.getGenePoolRecord = (key) => { + return _getGenePoolRecord(key, false, false); +}; + +/** + * Returns a read/write record from the gene pool, will return undefined if there is no valid record. * @param {FC.HumanState|number} key The HumanState object or ID to get the record for. - * @param {boolean} [missingOkay=false] if true then we won't warn if the record is missing, use sparingly. - * @param {boolean} [write=false] if true allow writing to the record, is this sparingly and with caution. * @returns {FC.GenePoolRecord} */ -globalThis.getGenePoolRecord = (key, missingOkay=false, write=false) => { - /** @type {string} */ - let ID; - if (typeof key === "number") { - ID = String(key); - } else if (typeof key === "object" && "ID" in key) { - ID = String(key.ID); - } else { - throw new Error(`key must be an FC.HumanState object or valid HumanState.ID! Got: ${Serial.stringify(key)}`); - } - if (ID === "0") { - console.warn(new Error("getGenePoolRecord: actors with an ID equal to 0 cannot exist in the gene pool")); - return undefined; - } - if (ID in V.genePool) { - const handler = { - /** - * @param {Partial<FC.GenePoolRecord> & {_canWrite: boolean}} target - * @param {string} key - * @param {*} value - * @returns {boolean} - */ - set(target, key, value) { - if (write === true) { - target[key] = value; - return true; - } - throw new Error(`Attempt to set '${String(key)}' in read only gene pool record with ID '${ID}' to '${value}' was blocked`); - }, - /** - * @param {Partial<FC.GenePoolRecord>} target - * @param {keyof FC.GenePoolRecord} key - * @returns {*} - */ - get(target, key) { - const handle = (obj) => { - if (typeof obj === 'object' && obj !== null) { - return new Proxy(obj, handler); - } else { - return obj; - } - }; - if (key in target) { - return handle(target[key]); - } else if (key in V.genePoolDefaults) { - return handle(V.genePoolDefaults[key]); - } else { - const newRecord = new App.Entity.GenePoolRecord(); - if (key in newRecord) { - return handle(newRecord[key]); - } - } - } - }; - return /** @type {FC.GenePoolRecord} */ (new Proxy(V.genePool[ID], handler)); - } else { - if (!missingOkay) { - console.warn(`Gene pool record missing for ID '${ID}'`); - } - return undefined; - } +globalThis.getGenePoolRecordWriteMode = (key) => { + return _getGenePoolRecord(key, false, true); }; /** @@ -103,40 +53,12 @@ globalThis.isInGenePool = (key) => { }; /** - * Adds a clone of the given human to the genePool as a valid FC.GenePoolRecord. - * Throws an error if they are already in the pool. - * If unsure, use `isInGenePool()` first to check. - * @see isInGenePool - * @param {FC.HumanState} actor + * Makes the given GenePoolRecord sparse saving storage space. + * If record is undefined then we do nothing. + * @param {FC.GenePoolRecord} record */ -globalThis.addToGenePool = (actor) => { - const record = _.cloneDeep(actor); - const player = asPlayer(record); - const slave = asSlave(record); - if (player) { - App.Verify.playerState( - player, - `<Player with ID '${record.ID}' passed to addToGenePool()>`, - undefined, - "V.genePool", - ); - } else if (slave) { - App.Verify.slaveState( - `<Slave with ID '${record.ID}' passed to addToGenePool()>`, - slave, - "V.genePool" - ); - } else { - console.error(`addToGenePool: actor with ID '${record.ID}' is not a valid SlaveState or PlayerState object`); - // TODO:@franklygeorge double check that all the keys from new App.Entity.GenePoolRecord() exist on actor - // TODO:@franklygeorge if not then throw an error; once you write that code change the console.error above to console.warn - } - - if (record.ID === 0) { - console.error(new Error("addToGenePool: actors with an ID equal to 0 cannot be added to the gene pool")); - return; - } - +globalThis.makeSparseGeneRecord = (record) => { + if (record === undefined) { return; } /** * DANGER * strip keys from obj that aren't in template, recursively @@ -182,6 +104,47 @@ globalThis.addToGenePool = (actor) => { } }; + // strip the record down to a valid GenePoolRecord + stripKeys(record, new App.Entity.GenePoolRecord()); + // remove all default keys from GenePoolRecord + removeDefaults(record, V.genePoolDefaults); +}; + +/** + * Adds a clone of the given human to the genePool as a valid FC.GenePoolRecord. + * Throws an error if they are already in the pool. + * If unsure, use `isInGenePool()` first to check. + * @see isInGenePool + * @param {FC.HumanState} actor + */ +globalThis.addToGenePool = (actor) => { + const record = _.cloneDeep(actor); + const player = asPlayer(record); + const slave = asSlave(record); + if (player) { + App.Verify.playerState( + player, + `<Player with ID '${record.ID}' passed to addToGenePool()>`, + undefined, + "V.genePool", + ); + } else if (slave) { + App.Verify.slaveState( + `<Slave with ID '${record.ID}' passed to addToGenePool()>`, + slave, + "V.genePool" + ); + } else { + console.error(`addToGenePool: actor with ID '${record.ID}' is not a valid SlaveState or PlayerState object`); + // TODO:@franklygeorge double check that all the keys from new App.Entity.GenePoolRecord() exist on actor + // TODO:@franklygeorge if not then throw an error; once you write that code change the console.error above to console.warn + } + + if (record.ID === 0) { + console.error(new Error("addToGenePool: actors with an ID equal to 0 cannot be added to the gene pool")); + return; + } + if (record.ID in V.genePool) { throw new Error(`There is already a genePool record for ID '${record.ID}'`); } @@ -189,10 +152,7 @@ globalThis.addToGenePool = (actor) => { // cull the contents of womb from the record record.womb = []; - // strip the record down to a valid GenePoolRecord - stripKeys(record, new App.Entity.GenePoolRecord()); - // remove all default keys from GenePoolRecord - removeDefaults(record, V.genePoolDefaults); + makeSparseGeneRecord(record); // @ts-expect-error V.genePool is set to read only. This is the one of the few lines that should be writing to it V.genePool[String(record.ID)] = record; @@ -249,6 +209,41 @@ globalThis.deleteGenePoolRecord = (actor, force=false) => { } }; +/** + * Use `getGenePoolRecord()` or `getGenePoolRecordWriteMode()` instead of calling this directly + * @see getGenePoolRecord + * @see getGenePoolRecordWriteMode + * @param {FC.HumanState|number} key The HumanState object or ID to get the record for. + * @param {boolean} [missingOkay=false] if true then we won't warn if the record is missing, use sparingly. + * @param {boolean} [write=false] if true allow writing to the record. + * @returns {FC.GenePoolRecord} + */ +globalThis._getGenePoolRecord = (key, missingOkay=false, write=false) => { + /** @type {string} */ + let ID; + if (typeof key === "number") { + ID = String(key); + } else if (typeof key === "object" && "ID" in key) { + ID = String(key.ID); + } else { + throw new Error(`key must be an FC.HumanState object or valid HumanState.ID! Got: ${Serial.stringify(key)}`); + } + if (ID in V.genePool) { + // this implementation means that write=true will convert the record from a sparse object into a full one. + // this should be okay since validation will reconvert it to sparse later, but it is not ideal + // the reason for doing this is that proxies are an absolute pain if you need to fill in values with defaults recursively. + // this also means that if someone tries to write to this with write=false there will be no error or warning to indindcate that something is wrong + const record = write ? V.genePool[ID] : clone(V.genePool[ID]); + App.Utils.assignMissingDefaults(record, V.genePoolDefaults, new App.Entity.GenePoolRecord()); + return /** @type {FC.GenePoolRecord} */ (record); + } else { + if (!missingOkay) { + console.warn(`Gene pool record missing for ID '${ID}'`); + } + return undefined; + } +}; + /** * This defines properties that are shared between the gene pool and all HumanState objects. * The values here should be the default for SlaveState objects. diff --git a/src/npc/generate/generateGenetics.js b/src/npc/generate/generateGenetics.js index e4af097d88d..3d58a778ca2 100644 --- a/src/npc/generate/generateGenetics.js +++ b/src/npc/generate/generateGenetics.js @@ -2,11 +2,11 @@ // Generates a child's genetics based off mother and father and returns it as an object to be attached to an ovum globalThis.generateGenetics = (function() { - /** @type {FC.GenePoolRecord} */ + /** @type {ReadonlyDeep<FC.GenePoolRecord>} */ let mother; /** @type {FC.Zeroable<FC.GenePoolRecord>} */ let activeMother; - /** @type {FC.Zeroable<FC.GenePoolRecord>} */ + /** @type {FC.Zeroable<ReadonlyDeep<FC.GenePoolRecord>>} */ let father; /** @type {FC.Zeroable<FC.GenePoolRecord>} */ let activeFather; @@ -122,8 +122,8 @@ globalThis.generateGenetics = (function() { } /** set expected adult height for the fetus - * @param {FC.Zeroable<FC.GenePoolRecord>} father - * @param {FC.GenePoolRecord} mother + * @param {FC.Zeroable<ReadonlyDeep<FC.GenePoolRecord>>} father + * @param {ReadonlyDeep<FC.GenePoolRecord>} mother * @param {string} gender * @param {FC.Race} race * @param {string} nationality @@ -153,8 +153,8 @@ globalThis.generateGenetics = (function() { } /** set breast size potential for the fetus - * @param {FC.GenePoolRecord} mother - * @param {FC.Zeroable<FC.GenePoolRecord>} father + * @param {ReadonlyDeep<FC.GenePoolRecord>} mother + * @param {FC.Zeroable<ReadonlyDeep<FC.GenePoolRecord>>} father * @returns {number} */ function setBoobPotential(mother, father) { @@ -338,8 +338,8 @@ globalThis.generateGenetics = (function() { } /** - * @param {FC.Zeroable<FC.GenePoolRecord>} father - * @param {FC.GenePoolRecord} mother + * @param {FC.Zeroable<ReadonlyDeep<FC.GenePoolRecord>>} father + * @param {ReadonlyDeep<FC.GenePoolRecord>} mother * @param {FC.Race} race */ function setSkin(father, mother, race) { @@ -429,6 +429,10 @@ globalThis.generateGenetics = (function() { */ function validGeneticEyeColor(eyeColor) { switch (eyeColor) { + case undefined: + console.error(new Error(`validGeneticEyeColor was given 'undefined' instead of a string! Setting the eye color to 'brown'`)); + eyeColor = "brown"; + break; case "blind blue": eyeColor = "deep blue"; break; @@ -443,8 +447,8 @@ globalThis.generateGenetics = (function() { // eyeColor function setEyeColor(father, mother) { let eyeColor; - /** @type {FC.Zeroable<string>} */ - let fatherEye = 0; + /** @type {string} */ + let fatherEye; // during BC WombInit, the mother has been updated but the father might not have been yet. // if the father is defined but doesn't have eyes, see if maybe he has an old eye color diff --git a/src/npc/surgery/bodySwap/huskSlaveSwap.js b/src/npc/surgery/bodySwap/huskSlaveSwap.js index 0e00486cd02..59d85bce329 100644 --- a/src/npc/surgery/bodySwap/huskSlaveSwap.js +++ b/src/npc/surgery/bodySwap/huskSlaveSwap.js @@ -9,7 +9,7 @@ App.UI.SlaveInteract.huskSlaveSwap = function() { App.UI.DOM.appendNewElement("p", node, `You strap ${target.slaveName}, and the body to which ${he} will be transferred, into the remote surgery and stand back as it goes to work.`); bodySwap(target, asSlave(V.activeSlave), false); - const gps = isInGenePool(V.activeSlave) ? getGenePoolRecord(V.activeSlave, false, true) : undefined; + const gps = isInGenePool(V.activeSlave) ? getGenePoolRecordWriteMode(V.activeSlave) : undefined; // special exception to swap genePool since the temporary body lacks an entry. Otherwise we could just call bodySwap using the genePool entries gps.race = target.race; gps.origRace = target.origRace; diff --git a/src/npc/surgery/bodySwap/slaveSlaveSwap.js b/src/npc/surgery/bodySwap/slaveSlaveSwap.js index 629dc291687..306d20a7c10 100644 --- a/src/npc/surgery/bodySwap/slaveSlaveSwap.js +++ b/src/npc/surgery/bodySwap/slaveSlaveSwap.js @@ -7,11 +7,11 @@ App.UI.SlaveInteract.slaveSlaveSwap = function() { const ss2 = getSlave(V.swappingSlave); const ss2Clone = clone(ss2); - const gps1 = /** @type {FC.SlaveState} */ (getGenePoolRecord(ss1)); + const gps1 = /** @type {FC.SlaveState} */ (getGenePoolRecordWriteMode(ss1)); App.Utils.assignMissingDefaults(gps1, clone(ss1)); const gps1Clone = clone(gps1); - const gps2 = /** @type {FC.SlaveState} */ (getGenePoolRecord(ss2)); + const gps2 = /** @type {FC.SlaveState} */ (getGenePoolRecordWriteMode(ss2)); App.Utils.assignMissingDefaults(gps2, clone(ss2)); const gps2Clone = clone(gps2); diff --git a/src/pregmod/editGenetics.js b/src/pregmod/editGenetics.js index a1ebe570402..2751d1f0856 100644 --- a/src/pregmod/editGenetics.js +++ b/src/pregmod/editGenetics.js @@ -646,7 +646,7 @@ App.UI.editGenetics = function() { /* The PC */ return birthFullName(V.PC) + ' (PC)'; } else { - let parent = getGenePoolRecord(id, undefined, true); + const parent = getGenePoolRecordWriteMode(id); return parent ? birthFullName(parent) : App.Events.makeNode([ @@ -715,8 +715,7 @@ App.UI.editGenetics = function() { el.on('click', function() { jQuery('button.selectedslave').removeClass('selectedslave'); el.addClass('selectedslave'); - // @ts-ignore you shouldn't access V.genePool directly because it isn't supposed to change; this is an exception; For normal use use getGenePoolRecord() - let slave = getGenePoolRecord(id, undefined, true); + let slave = getGenePoolRecordWriteMode(id); geneDetails.html(geneDetailsFunction(slave)); let numberEditorOpen = function() { -- GitLab