diff --git a/src/data/backwardsCompatibility/backwardsCompatibility.js b/src/data/backwardsCompatibility/backwardsCompatibility.js index ed44cd202d2b3a2958464e9a90de42a2329437a3..07ce59668170cc28bba63d831fd0205b8b05a2d1 100644 --- a/src/data/backwardsCompatibility/backwardsCompatibility.js +++ b/src/data/backwardsCompatibility/backwardsCompatibility.js @@ -1252,8 +1252,11 @@ App.Update.slaveRecords = function(node) { nurseryDiv.append(`Checking and fixing records for nursery cribs... `); V.cribs.forEach((child) => { if (child.actualAge < 3) { - // infants are not slaves, they need their own update code (but there isn't any yet) + // infants are not slaves, they need their own update code (but there isn't much yet) // note that some infants have been *converted into* corrupted slaves by bad old BCs...no attempt is made to fix them here + if (child.spermY === undefined) { + child.spermY = normalRandInt(50, 5); + } App.Facilities.Nursery.InfantDatatypeCleanup(child); } else { App.Update.Slave(child); @@ -2033,6 +2036,9 @@ App.Update.oldVersions = function(node) { V.PC.faceShape = "normal"; } } + if (typeof V.PC.spermY === "undefined") { + V.PC.spermY = 50; // exactly + } if ((typeof V.familyTesting === "undefined") && V.releaseID < 1065) { // possibly vanilla FC; compel V.familyTesting to 0 so that the family upgrade will run on slaves diff --git a/src/data/backwardsCompatibility/updateSlaveObject.js b/src/data/backwardsCompatibility/updateSlaveObject.js index 0c05bba36abed80bbc64e9e091907baa85b73fd8..0e63c24a3c0498114559e63f64870f2c5a23a9ba 100644 --- a/src/data/backwardsCompatibility/updateSlaveObject.js +++ b/src/data/backwardsCompatibility/updateSlaveObject.js @@ -1007,6 +1007,10 @@ App.Update.Slave = function(slave, genepool = false) { delete slave.relationTarget; delete slave.recruiter; + if (slave.spermY === undefined) { + slave.spermY = normalRandInt(50, 3); // narrower range to avoid surprises + } + if (slave.geneticQuirks.albinism === 2 && !slave.albinismOverride) { induceAlbinism(slave, 2); } diff --git a/src/facilities/nursery/widgets/children/ChildState.js b/src/facilities/nursery/widgets/children/ChildState.js index 8b787dd89806b31e7088844d26d8ec40704c51a5..8de31f2d3e8fb185dbe124bb6123328325e7dd3b 100644 --- a/src/facilities/nursery/widgets/children/ChildState.js +++ b/src/facilities/nursery/widgets/children/ChildState.js @@ -1568,6 +1568,8 @@ App.Facilities.Nursery.ChildState = class ChildState { /** Slave can only ever birth girls */ girlsOnly: 0 }; + /** chance of generating sperm with a Y chromosome (yields male baby). inherited by sons, with mutation */ + this.spermY = 50; /** Counts various acts slave participated in */ this.counter = new App.Entity.ChildActionsCountersState(); /** Values provided by players */ diff --git a/src/facilities/nursery/widgets/infants/InfantState.js b/src/facilities/nursery/widgets/infants/InfantState.js index 87f0b6a7545f8a29c4dc1ad3ee40154e64d1dd5b..f50c3506b54d851f0bbd744d250c0b8ab9f8644b 100644 --- a/src/facilities/nursery/widgets/infants/InfantState.js +++ b/src/facilities/nursery/widgets/infants/InfantState.js @@ -183,6 +183,8 @@ App.Facilities.Nursery.InfantState = class InfantState { /** child can only ever birth girls */ girlsOnly: 0 }; + /** chance of generating sperm with a Y chromosome (yields male baby). inherited by sons, with mutation */ + this.spermY = 50; /** how many weeks until the child is ready for release */ this.growTime = 156; } diff --git a/src/gui/options/options.tw b/src/gui/options/options.tw index 46bd823470bfb6f6f3a1375c1257db830ed263f3..8cd9ef8151ef0e2c32b9737cd1363cc392548620 100644 --- a/src/gui/options/options.tw +++ b/src/gui/options/options.tw @@ -302,8 +302,8 @@ .addValue("Enabled", 1).on().addValue("Disabled", 0).off() .addComment("<<if $seeDicksAffectsPregnancy === 1>>Currently <<print $seeDicks>>% of children will be born male. <</if>>Will not affect existing pregnancies already in-game.")>> - <<if $seeDicksAffectsPregnancy > 0>> - <<run _options.addOption("XX slaves can have sons", "adamPrinciple") + <<if $seeDicksAffectsPregnancy === 0>> + <<run _options.addOption("XX slaves only father daughters", "adamPrinciple") .addValue("Enabled", 1).on().addValue("Disabled", 0).off() .addComment("Will not affect existing pregnancies already in-game.")>> <</if>> diff --git a/src/js/SlaveState.js b/src/js/SlaveState.js index cd6e9f7e093f671f91531c3a615866e948593623..861d83d377ff43c9abf07ddc4d492a76b27fa10f 100644 --- a/src/js/SlaveState.js +++ b/src/js/SlaveState.js @@ -2124,6 +2124,8 @@ App.Entity.SlaveState = class SlaveState { /** slave can only ever birth girls */ girlsOnly: 0 }; + /** chance of generating sperm with a Y chromosome (yields male baby). inherited by sons, with mutation */ + this.spermY = 50; /** Counts various acts slave participated in */ this.counter = new App.Entity.SlaveActionsCountersState(); /** Values provided by players */ diff --git a/src/npc/descriptions/descriptionWidgets.js b/src/npc/descriptions/descriptionWidgets.js index b9f5035a7c033ff5e749065d362e585912f14369..fb2d4a310b6ef56166ec7838e8ffa192a1b4f84b 100644 --- a/src/npc/descriptions/descriptionWidgets.js +++ b/src/npc/descriptions/descriptionWidgets.js @@ -1536,6 +1536,9 @@ App.Desc.geneticQuirkAssessment = function(slave) { if (slave.geneticQuirks.mLoss === 1 && V.geneticMappingUpgrade >= 2) { r.push(`${He} is a myotonic dystrophy carrier.`); } + if (slave.genes === "XY" && !V.seeDicksAffectsPregnancy) { + r.push(`Analysis of ${his} sperm shows that ${he} has a ${slave.spermY}% chance of fathering a son.`); + } } return r.join(` `); }; diff --git a/src/npc/generate/generateGenetics.js b/src/npc/generate/generateGenetics.js index ff7dd2751c6dafa8a83ef8b1e36b3b283e29cf02..250afa87426477062e046f46b602395e402c13e3 100644 --- a/src/npc/generate/generateGenetics.js +++ b/src/npc/generate/generateGenetics.js @@ -44,7 +44,8 @@ globalThis.generateGenetics = (function() { clone: 0, cloneID: 0, geneticQuirks: {}, - fetish: "none" + fetish: "none", + spermY: 50 }; if (actor1.ID > 0) { mother = V.genePool.find(s => s.ID === actor1.ID); @@ -114,10 +115,28 @@ globalThis.generateGenetics = (function() { genes.sexualFlaw = setSexualFlaw(father, mother); genes.behavioralFlaw = setBehavioralFlaw(father, mother); genes.fetish = setFetish(father, mother); + genes.spermY = setSpermY(father, mother); return genes; } + // get spermY value of the parent that's donating the Y chromosome + function getSpermY(father, mother) { + let sourceSpermY = 50; // default if no inherited Y chromosome (should be impossible, but the Adam Principle is optional, so it can happen) + if (father !== 0 && father.genes === "XY") { + sourceSpermY = father.spermY; + } else if (mother.genes === "XY") { + sourceSpermY = father.spermY; + } + return sourceSpermY; + } + + // generation chance of y-chormosome carrying sperm + function setSpermY(father, mother) { + // Y-linked trait, so figure out where the Y chromosome is coming from and start from there + return normalRandInt(getSpermY(father, mother), 5); // mutation + } + // gender function setGender(father, mother) { let gender; @@ -128,17 +147,26 @@ globalThis.generateGenetics = (function() { } else if (V.adamPrinciple === 1) { if (father !== 0) { if (father.genes === "XX" && mother.genes === "XX") { - gender = "XX"; + gender = "XX"; // neither parent has a Y chromosome, it's definitely a girl } else if (father.genes !== mother.genes) { - gender = jsEither(["XX", "XY"]); + gender = jsRandom(0, 99) < getSpermY(father, mother) ? "XY" : "XX"; // "normal" conception } else { - gender = jsEither(["XX", "XY", "XY", "YY"]); + // both parents have a Y chromosome that they could donate; treat them as independent events + const motherY = jsRandom(0, 99) < mother.spermY; + const fatherY = jsRandom(0, 99) < father.spermY; + if (motherY && fatherY) { + gender = "YY"; // inviable, but retain for now + } else if (!motherY && !fatherY) { + gender = "XX"; // it's a girl! + } else { + gender = "XY"; // it's a boy! + } } } else { - gender = jsEither(["XX", "XY"]); + gender = jsRandom(0, 99) < getSpermY(father, mother) ? "XY" : "XX"; } } else { - gender = jsEither(["XX", "XY"]); + gender = jsRandom(0, 99) < getSpermY(father, mother) ? "XY" : "XX"; } return gender; } @@ -1156,6 +1184,7 @@ globalThis.generateChild = function (mother, ovum, incubator=false) { child.origHColor = genes.hColor; child.skin = getGeneticSkinColor(child); child.hColor = getGeneticHairColor(child); + child.spermY = genes.spermY; child.pubicHColor = child.hColor; child.underArmHColor = child.hColor; child.eyebrowHColor = child.hColor; @@ -1209,6 +1238,7 @@ globalThis.generateChild = function (mother, ovum, incubator=false) { child.origHColor = genes.hColor; child.skin = getGeneticSkinColor(child); child.hColor = getGeneticHairColor(child); + child.spermY = genes.spermY; resetEyeColor(child, "both"); child.pubicHColor = child.hColor; child.underArmHColor = child.hColor; diff --git a/src/npc/generate/generateNewSlaveJS.js b/src/npc/generate/generateNewSlaveJS.js index 61b02bfe1717a7cdc5dce32b3aee1588e7911d77..b3c83d8531c21bc43f4a868ef00f951db0d11dd4 100644 --- a/src/npc/generate/generateNewSlaveJS.js +++ b/src/npc/generate/generateNewSlaveJS.js @@ -103,6 +103,7 @@ globalThis.GenerateNewSlave = (function() { slave.hColor = getGeneticHairColor(slave); slave.skin = getGeneticSkinColor(slave); resetEyeColor(slave, "both"); + slave.spermY = normalRandInt(50, 5); } function GenerateXXSlave() { diff --git a/src/player/js/PlayerState.js b/src/player/js/PlayerState.js index 115a70c6f1b6ae32d518a055d72e76447d3dc0ec..4efbdaf320adf2e8d164496d3c6f4216be6eab5f 100644 --- a/src/player/js/PlayerState.js +++ b/src/player/js/PlayerState.js @@ -1691,6 +1691,8 @@ App.Entity.PlayerState = class PlayerState { /** slave can only ever birth girls */ girlsOnly: 0 }; + /** chance of generating sperm with a Y chromosome (yields male baby). inherited by sons, with mutation */ + this.spermY = 50; /** Counts various thing you have done in */ this.counter = new App.Entity.PlayerActionsCountersState(); /** Values provided by players */ diff --git a/src/pregmod/managePersonalAffairs.tw b/src/pregmod/managePersonalAffairs.tw index f782157ba7d27aa190b06d30f117194d8f03e7ac..8a212bc09f387e17146aa93caeb98c42edb38c21 100644 --- a/src/pregmod/managePersonalAffairs.tw +++ b/src/pregmod/managePersonalAffairs.tw @@ -17,6 +17,15 @@ <div> You pause for a moment from your busy day to day life to return to <<if $masterSuite != 0>>$masterSuiteName<<else>>your room<</if>> to consider some things about yourself. </div> + +<<if $geneticMappingUpgrade >= 1>> + <div> + <<if $PC.genes === "XY" && $seeDicksAffectsPregnancy === 0>> + Analysis of your sperm shows that you have a <<= $PC.spermY>>% chance of fathering a son. + <</if>> + </div> +<</if>> + <div> You take yourself in a full length mirror. You are <<= addA($PC.race)>> <<if $PC.dick != 0 && $PC.vagina != -1>>futanari<<elseif $PC.dick != 0>>man<<else>>woman<</if>> with<<if $PC.markings == "freckles">> freckled<<elseif $PC.markings == "heavily freckled">> heavily freckled<</if>> <<print $PC.skin>> skin, $PC.hColor hair, <<print App.Desc.eyesColor($PC)>> and a perfect $PC.faceShape face. <<if $PC.actualAge >= 65>>