diff --git a/src/cheats/PCCheatMenuCheatDatatypeCleanup.tw b/src/cheats/PCCheatMenuCheatDatatypeCleanup.tw
index 5f78ca87af81bba2e840704827e8dc9ee8fc1027..005c0e3a00652c292e405f25d89be27537382be0 100644
--- a/src/cheats/PCCheatMenuCheatDatatypeCleanup.tw
+++ b/src/cheats/PCCheatMenuCheatDatatypeCleanup.tw
@@ -71,6 +71,7 @@
 You perform the dark rituals, pray to the dark gods, and sell your soul for the power to reshape your body and life at will. What a cheater!
 
 <<set $PC = clone($tempSlave)>>
+<<run ibc.recalculate_id(-1)>>
 <<run PCDatatypeCleanup()>>
 <<set $upgradeMultiplierArcology = upgradeMultiplier('engineering')>>
 <<set $upgradeMultiplierMedicine = upgradeMultiplier('medicine')>>
diff --git a/src/cheats/mod_EditChildCheatDatatypeCleanupNew.tw b/src/cheats/mod_EditChildCheatDatatypeCleanupNew.tw
index 9ac0b8c1f7773a1ede8b558f13872d319296675a..57449fb187f0d00d37e25675b53595d5492a6238 100644
--- a/src/cheats/mod_EditChildCheatDatatypeCleanupNew.tw
+++ b/src/cheats/mod_EditChildCheatDatatypeCleanupNew.tw
@@ -322,6 +322,7 @@ You perform the dark rituals, pray to the dark gods, and sell your soul for the
 <br><br>This slave has been changed forever and you have lost a bit of your soul, YOU CHEATER!
 
 <<set $activeSlave = clone($tempSlave)>>
+<<run ibc.recalculate_coeff_id($activeSlave.ID)>>
 <<unset $tempSlave>>
 <<set _escn = $cribs.findIndex(function(s) { s.ID === $activeSlave.ID; })>>
 <<if def _escn>>
diff --git a/src/cheats/mod_EditSlaveCheatDatatypeCleanup.tw b/src/cheats/mod_EditSlaveCheatDatatypeCleanup.tw
index 259d748bfbaa74c177b5e2c72ed4ca88aa5e50b6..f07890401afb50ae8ecaadb056f521e72f7fa687 100644
--- a/src/cheats/mod_EditSlaveCheatDatatypeCleanup.tw
+++ b/src/cheats/mod_EditSlaveCheatDatatypeCleanup.tw
@@ -66,6 +66,7 @@ You perform the dark rituals, pray to the dark gods, and sell your soul for the
 <br><br>This slave has been changed forever and you have lost a bit of your soul, YOU CHEATER!
 
 <<set $activeSlave = clone($tempSlave)>>
+<<run ibc.recalculate_coeff_id($activeSlave.ID)>>
 <<unset $tempSlave>>
 <<set _escdc = $slaveIndices[$activeSlave.ID]>>
 <<if def _escdc>>
diff --git a/src/cheats/mod_EditSlaveCheatDatatypeCleanupNew.tw b/src/cheats/mod_EditSlaveCheatDatatypeCleanupNew.tw
index 3dd6e0e84971868e55ea3238e7bfc1ec30e46916..196caf23c024e965949b048d0024c81c1671903c 100644
--- a/src/cheats/mod_EditSlaveCheatDatatypeCleanupNew.tw
+++ b/src/cheats/mod_EditSlaveCheatDatatypeCleanupNew.tw
@@ -225,6 +225,7 @@ You perform the dark rituals, pray to the dark gods, and sell your soul for the
 <br><br>This slave has been changed forever and you have lost a bit of your soul, YOU CHEATER!
 
 <<set $activeSlave = clone($tempSlave)>>
+<<run ibc.recalculate_coeff_id($activeSlave.ID)>>
 <<unset $tempSlave>>
 <<set _escn = $slaveIndices[$activeSlave.ID]>>
 <<if def _escn>>
diff --git a/src/js/ibcJS.js b/src/js/ibcJS.js
index 06e70855537fe7b49b8bb132d969665d4b19033f..fbd652e6f55e1031dc867ea121bd72269c471bab 100644
--- a/src/js/ibcJS.js
+++ b/src/js/ibcJS.js
@@ -256,7 +256,7 @@ globalThis.ibc = (() => {
     };
 
     // Make nodes for an array of slaves
-    let nodes_slaves = slaves => {
+    let nodes_slaves = (slaves, ignore_coeffs=false) => {
         let nodes = {};
 
         // Recursively create the nodes we need, moving upwards from the given slave
@@ -293,7 +293,7 @@ globalThis.ibc = (() => {
 
             // Try to use a cached CoI for performance
             let sg = find_gp(s.ID);
-            if (sg !== null && "inbreedingCoeff" in sg && sg.inbreedingCoeff !== -1) {
+            if (!ignore_coeffs && sg !== null && "inbreedingCoeff" in sg && sg.inbreedingCoeff !== -1) {
                 nodes[s.ID]._coeff = sg.inbreedingCoeff;
             }
         };
@@ -309,12 +309,12 @@ globalThis.ibc = (() => {
 
     // Determine the coefficients of inbreeding of an array of slaves. Returns a mapping of their 
     // ID to their coefficient of inbreeding
-    let coeff_slaves = slaves => {
+    let coeff_slaves = (slaves, ignore_coeffs=false) => {
         let ret = {};
         // First, pull as many existing CoI off the slaves
         slaves.forEach(s => {
             let sg = find_gp(s.ID);
-            if (sg !== null && "inbreedingCoeff" in sg && sg.inbreedingCoeff !== -1) {
+            if (!ignore_coeffs && sg !== null && "inbreedingCoeff" in sg && sg.inbreedingCoeff !== -1) {
                 ret[s.ID] = sg.inbreedingCoeff;
             }
         });
@@ -322,7 +322,7 @@ globalThis.ibc = (() => {
         // Now do any we haven't done already
         slaves = slaves.filter(s => (!(s.ID in ret)));
         if (slaves.length > 0) {
-            let nodes = nodes_slaves(slaves);
+            let nodes = nodes_slaves(slaves, ignore_coeffs);
 
             // Compute coefficients
             slaves.forEach(s => {
@@ -334,19 +334,20 @@ globalThis.ibc = (() => {
     };
 
     // Determine the kinship between two slaves `a` and `b`
-    let kinship_slaves = (a, b) => {
-        let nodes = nodes_slaves([a, b]);
+    let kinship_slaves = (a, b, ignore_coeffs=false) => {
+        if (a === 0 || b === 0)
+            return 0;
 
-        return kinship(nodes[a.ID], nodes[b.ID]);
+        return kinship_one_many(a, [b], ignore_coeffs);
     };
 
     // Determine the coefficient of inbreeding of a single slave
-    let coeff_slave = slave => {
-        if ("inbreedingCoeff" in slave && slave.inbreedingCoeff !== -1)
+    let coeff_slave = (slave, ignore_coeffs=false) => {
+        if (!ignore_coeffs && "inbreedingCoeff" in slave && slave.inbreedingCoeff !== -1)
             return slave.inbreedingCoeff;
 
         let gp = find_gp(slave.ID);
-        if (gp !== null && "inbreedingCoeff" in gp && gp.inbreedingCoeff !== -1)
+        if (!ignore_coeffs && gp !== null && "inbreedingCoeff" in gp && gp.inbreedingCoeff !== -1)
             return gp.inbreedingCoeff;
 
         return coeff_slaves([slave])[slave.ID];
@@ -354,21 +355,140 @@ globalThis.ibc = (() => {
 
     // Determine the kinship between one and many slaves. Returns an mapping from the ID of each of
     // the slaves in `others` to its kinship with slave `a`
-    let kinship_one_many = (a, others) => {
-        let nodes = nodes_slaves(others.concat([a]));
+    let kinship_one_many = (a, others, ignore_coeffs=false) => {
+        if (a === 0) {
+            let ks = {};
+            others.forEach(s => {
+                if (s === 0)
+                    ks[s] = 0;
+                else 
+                    ks[s.ID] = 0;
+            });
+            return ks;
+        }
+
+        let nodes = nodes_slaves(others.concat([a]), ignore_coeffs);
 
         let ks = {};
         others.forEach(s => {
-            ks[s.ID] = kinship(nodes[a.ID], nodes[s.ID]);
+            if (s === -3) {
+                // Fake a slave object for the player's old master
+                s = {ID: -3, mother: 0, father: 0, inbreedingCoeff: 0};
+            }
+
+            if (s === 0)
+                ks[s] = 0;
+            else
+                ks[s.ID] = kinship(nodes[a.ID], nodes[s.ID]);
         });
 
         return ks;
     };
 
+    // Recalculate the inbreeding coefficient for all slaves dependent on the passed IDs (e.g. the
+    // slaves themselves and all of their children). This will replace the inbreeding coefficients
+    // wherever they exist with the computed values, ignoring all cached values.
+    //
+    // This should be called if parents are changed.
+    let recalculate_coeff_ids = (ids) => {
+        // These are all the slave-like objects, i.e. they have ID, mother, and father. There will
+        // be multiple elements with the same ID: we want this, since we have to replace all 
+        // occurrences of the COI for the affected slaves
+        let all_slave_like = V.slaves.concat(V.genePool).concat(V.cribs).concat(V.tanks).concat(Object.values(V.missingTable));
+        if (V.boomerangSlave !== 0)
+            all_slave_like.push(V.boomerangSlave);
+        if (V.traitor !== 0)
+            all_slave_like.push(V.traitor);
+        if (V.activeSlave !== 0)
+            all_slave_like.push(V.activeSlave);
+        all_slave_like.push(V.PC);
+        // Add a fake entry for the PC's old master
+        all_slave_like.push({ID: -3, mother: 0, father: 0, inbreedingCoeff: 0});
+       
+        // Gather the genetics of all current fetuses
+        let all_fetuses = V.slaves.filter(s => s.preg > 0).map(s => s.womb.map(i => i.genetics)).reduce((res, cur) => res.concat(cur), []);
+
+        // Recursively find all of the given ID's children, born and unborn
+        let find_children_rec = (id, cur_slaves, cur_fetuses, cur_fetus_parents) => {
+            // Add fetuses
+            all_fetuses.filter(f => (f.father === id || f.mother === id)).forEach(f => {
+                // We may have to manually add the parents later
+                let actual_f = or_null(f.father);
+                let actual_m = or_null(f.mother);
+                if (actual_f !== null)
+                    cur_fetus_parents.add(actual_f);
+                if (actual_m !== null)
+                    cur_fetus_parents.add(actual_m);
+
+                cur_fetuses.add(f);
+            });
+
+            // Recursively add slaves
+            all_slave_like.filter(s => (s.father === id || s.mother === id)).forEach(s => {
+                if (!cur_slaves.has(s.ID)) {
+                    cur_slaves.add(s.ID);
+                    find_children_rec(s.ID, cur_slaves, cur_fetuses, cur_fetus_parents);
+                }
+            });
+        };
+
+        // We only need slave IDs, since we have to update all of their entries (including GP)
+        let needed_slave_ids = new Set();
+        // Since each fetus has a unique record, a set still suffices
+        let needed_fetuses = new Set();
+        let needed_parent_ids = new Set();
+
+        // Find all the children of the IDs we need to do
+        ids.forEach(id => {
+            needed_slave_ids.add(id);
+            find_children_rec(id, needed_slave_ids, needed_fetuses, needed_parent_ids);
+        });
+
+        // Now we assemble the tree from the slaves
+        let needed_slaves = [];
+        needed_slave_ids.forEach(id => {
+            if (typeof id !== "undefined")
+                needed_slaves.push(all_slave_like.find(s => s.ID === id));
+        });
+        needed_parent_ids.forEach(id => {
+            if (typeof id !== "undefined" && !needed_slave_ids.has(id))
+                needed_slaves.push(all_slave_like.find(s => s.ID == id));
+        });
+        let nodes = nodes_slaves(needed_slaves, true);
+
+        // Now calculate the inbreeding coefficients (they're cached in the tree once calculated)
+        all_slave_like.filter(s => needed_slave_ids.has(s.ID)).forEach(s => {
+            s.inbreedingCoeff = coeff(nodes[s.ID]);
+        });
+
+        // Finally, handle all of the kinship for the fetuses
+        let kinship_cache = new Map(); // Manually cache it
+        needed_fetuses.forEach(f => {
+            if (or_null(f.mother) === null || or_null(f.father) === null) {
+                f.inbreedingCoeff = 0;
+                return;
+            }
+
+            // Use a string of the form "parent;parent" to store the cache value; since kinship is
+            // commutative, the minumum parent ID will be first
+            let kinship_str = Math.min(f.mother, f.father) + ';' + Math.max(f.mother, f.father);
+            if (!kinship_cache.has(kinship_str))
+                kinship_cache.set(kinship_str, kinship(nodes[f.mother], nodes[f.father]));
+
+            f.inbreedingCoeff = kinship_cache.get(kinship_str);
+        });
+    };
+
+    let recalculate_coeff_id = (id) => {
+        return recalculate_coeff_ids([id]);
+    };
+
     return {
         coeff: coeff_slave,
         coeff_slaves,
         kinship: kinship_slaves,
-        kinship_one_many
+        kinship_one_many,
+        recalculate_coeff_ids,
+        recalculate_coeff_id
     };
 })();