diff --git a/src/npc/generate/generateGenetics.js b/src/npc/generate/generateGenetics.js index ac091e37ab16e4f9d619e15e2c83b8afb5e94f59..292a41b52e21040dcb735e7e9faf0b71059b765b 100644 --- a/src/npc/generate/generateGenetics.js +++ b/src/npc/generate/generateGenetics.js @@ -10,7 +10,6 @@ globalThis.generateGenetics = (function() { /** @type {FC.Zeroable<FC.Race>} - if father is unknown, what race was he? */ let fatherRace; - // intelligence and face parameters are the same so we can use the same distribution for both values // clamping makes edge values (-100, 100) more likely; this is expected behavior // please see https://gitgud.io/pregmodfan/fc-pregmod/issues/852 @@ -256,9 +255,9 @@ globalThis.generateGenetics = (function() { if (father !== 0) { if (mother.origRace === father.origRace) { race = mother.origRace; - } else if (mother.origRace === "catgirl"){ + } else if (mother.origRace === "catgirl") { race = "catgirl"; - } else if (father.origRace === "catgirl"){ + } else if (father.origRace === "catgirl") { race = "catgirl"; } else if (jsRandom(1, 4) === 4) { race = jsEither([father.origRace, mother.origRace]); @@ -266,9 +265,9 @@ globalThis.generateGenetics = (function() { race = "mixed race"; } } else { - if (mother.origRace === "catgirl"){ + if (mother.origRace === "catgirl") { race = "catgirl"; - } else if (father.origRace === "catgirl"){ + } else if (father.origRace === "catgirl") { race = "catgirl"; } else if (fatherRace !== 0) { if (mother.origRace === fatherRace) { @@ -370,17 +369,17 @@ globalThis.generateGenetics = (function() { if (father !== 0) { if (mother.eye.origColor === fatherEye) { eyeColor = mother.eye.origColor; - } else if (["light red", "milky white", "pale gray", "pale red", "red"].contains(mother.eye.origColor)) { + } else if (["light red", "milky white", "pale gray", "pale red", "red"].includes(mother.eye.origColor)) { eyeColor = fatherEye; - } else if (["light red", "milky white", "pale gray", "pale red", "red"].contains(fatherEye)) { + } else if (["light red", "milky white", "pale gray", "pale red", "red"].includes(fatherEye)) { eyeColor = mother.eye.origColor; - } else if (["blue", "dark blue", "deep blue", "light blue", "light grey"].contains(mother.eye.origColor)) { + } else if (["blue", "dark blue", "deep blue", "light blue", "light grey"].includes(mother.eye.origColor)) { if (jsRandom(1, 4) === 2) { eyeColor = mother.eye.origColor; } else { eyeColor = fatherEye; } - } else if (["blue", "dark blue", "deep blue", "light blue", "light grey"].contains(fatherEye)) { + } else if (["blue", "dark blue", "deep blue", "light blue", "light grey"].includes(fatherEye)) { if (jsRandom(1, 4) === 2) { eyeColor = fatherEye; } else { @@ -394,15 +393,15 @@ globalThis.generateGenetics = (function() { fatherEye = randomRaceEye(fatherRace); if (mother.eye.origColor === fatherEye) { eyeColor = mother.eye.origColor; - } else if (["light red", "milky white", "pale gray", "pale red", "red"].contains(mother.eye.origColor)) { + } else if (["light red", "milky white", "pale gray", "pale red", "red"].includes(mother.eye.origColor)) { eyeColor = fatherEye; - } else if (["blue", "dark blue", "deep blue", "light blue", "light grey"].contains(mother.eye.origColor)) { + } else if (["blue", "dark blue", "deep blue", "light blue", "light grey"].includes(mother.eye.origColor)) { if (jsRandom(1, 4) === 2) { eyeColor = mother.eye.origColor; } else { eyeColor = fatherEye; } - } else if (["blue", "dark blue", "deep blue", "light blue", "light grey"].contains(fatherEye)) { + } else if (["blue", "dark blue", "deep blue", "light blue", "light grey"].includes(fatherEye)) { if (jsRandom(1, 4) === 2) { eyeColor = fatherEye; } else { @@ -450,13 +449,13 @@ globalThis.generateGenetics = (function() { hairColor = jsRandom(1, 100) === 69 ? mother.origHColor : father.origHColor; } else if (father.origHColor === "white") { hairColor = jsRandom(1, 100) === 69 ? father.origHColor : mother.origHColor; - } else if (["black", "jet black"].contains(mother.origHColor)) { + } else if (["black", "jet black"].includes(mother.origHColor)) { hairColor = jsEither([father.origHColor, mother.origHColor, mother.origHColor, mother.origHColor, mother.origHColor, mother.origHColor, mother.origHColor, mother.origHColor]); - } else if (["black", "jet black"].contains(father.origHColor)) { + } else if (["black", "jet black"].includes(father.origHColor)) { hairColor = jsEither([father.origHColor, father.origHColor, father.origHColor, father.origHColor, father.origHColor, father.origHColor, father.origHColor, mother.origHColor]); - } else if (["brown", "chestnut", "chocolate", "dark brown"].contains(mother.origHColor)) { + } else if (["brown", "chestnut", "chocolate", "dark brown"].includes(mother.origHColor)) { hairColor = jsEither([father.origHColor, mother.origHColor, mother.origHColor, mother.origHColor]); - } else if (["brown", "chestnut", "chocolate", "dark brown"].contains(father.origHColor)) { + } else if (["brown", "chestnut", "chocolate", "dark brown"].includes(father.origHColor)) { hairColor = jsEither([father.origHColor, father.origHColor, father.origHColor, mother.origHColor]); } else { hairColor = jsEither([father.origHColor, mother.origHColor]); @@ -468,13 +467,13 @@ globalThis.generateGenetics = (function() { hairColor = mother.origHColor; } else if (mother.origHColor === "white") { hairColor = jsRandom(1, 100) === 69 ? mother.origHColor : fatherHair; - } else if (["black", "jet black"].contains(mother.origHColor)) { + } else if (["black", "jet black"].includes(mother.origHColor)) { hairColor = jsEither([fatherHair, mother.origHColor, mother.origHColor, mother.origHColor, mother.origHColor, mother.origHColor, mother.origHColor, mother.origHColor]); - } else if (["black", "jet black"].contains(fatherHair)) { + } else if (["black", "jet black"].includes(fatherHair)) { hairColor = jsEither([fatherHair, fatherHair, fatherHair, fatherHair, fatherHair, fatherHair, fatherHair, mother.origHColor]); - } else if (["brown", "chestnut", "chocolate", "dark brown"].contains(mother.origHColor)) { + } else if (["brown", "chestnut", "chocolate", "dark brown"].includes(mother.origHColor)) { hairColor = jsEither([fatherHair, mother.origHColor, mother.origHColor, mother.origHColor]); - } else if (["brown", "chestnut", "chocolate", "dark brown"].contains(fatherHair)) { + } else if (["brown", "chestnut", "chocolate", "dark brown"].includes(fatherHair)) { hairColor = jsEither([fatherHair, fatherHair, fatherHair, mother.origHColor]); } else { hairColor = jsEither([fatherHair, mother.origHColor]); @@ -488,35 +487,30 @@ globalThis.generateGenetics = (function() { // underArmHairStyle function setUnderArmHStyle(father, mother) { - let hair; - if (father !== 0) { - if (mother.underArmHStyle === "hairless" && father.underArmHStyle === "hairless") { - hair = "hairless"; - } else if (mother.underArmHStyle === "hairless" || father.underArmHStyle === "hairless") { - hair = (jsRandom(1, 5) === 3) ? "hairless" : jsEither(["bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "hairless"]); - } else { - hair = jsEither(["bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "hairless"]); - } - } else if (mother.underArmHStyle === "hairless") { - hair = (jsRandom(1, 5) === 3) ? "hairless" : jsEither(["bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "hairless"]); - } else { - hair = jsEither(["bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "hairless"]); - } - return hair; + return hairStyle(father.underArmHStyle, mother.underArmHStyle); } // pubicHairStyle function setPubicHStyle(father, mother) { + return hairStyle(father.pubicHStyle, mother.pubicHStyle); + } + + /** + * @param {string} fatherStyle + * @param {string} motherStyle + * @returns {string} + */ + function hairStyle(fatherStyle, motherStyle) { let hair; if (father !== 0) { - if (mother.pubicHStyle === "hairless" && father.pubicHStyle === "hairless") { + if (motherStyle === "hairless" && fatherStyle === "hairless") { hair = "hairless"; - } else if (mother.pubicHStyle === "hairless" || father.pubicHStyle === "hairless") { + } else if (motherStyle === "hairless" || fatherStyle === "hairless") { hair = (jsRandom(1, 5) === 3) ? "hairless" : jsEither(["bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "hairless"]); } else { hair = jsEither(["bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "hairless"]); } - } else if (mother.pubicHStyle === "hairless") { + } else if (motherStyle === "hairless") { hair = (jsRandom(1, 5) === 3) ? "hairless" : jsEither(["bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "hairless"]); } else { hair = jsEither(["bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "bushy", "hairless"]); @@ -601,8 +595,8 @@ globalThis.generateGenetics = (function() { smarts = mother.intelligence; } if (V.inbreeding === 1) { - if (jsRandom(1, 100) < inbreedingCoeff*200) { - smarts -= Math.abs(normalRandInt(5*inbreedingCoeff, 30*inbreedingCoeff, -100*inbreedingCoeff, 100*inbreedingCoeff)); + if (jsRandom(1, 100) < inbreedingCoeff * 200) { + smarts -= Math.abs(normalRandInt(5 * inbreedingCoeff, 30 * inbreedingCoeff, -100 * inbreedingCoeff, 100 * inbreedingCoeff)); } } return Math.clamp(smarts, -100, 100); @@ -639,8 +633,8 @@ globalThis.generateGenetics = (function() { face = mother.face; } if (V.inbreeding === 1 && genes.pFace === 0 && genes.uFace === 0) { - if (jsRandom(1, 100) < inbreedingCoeff*200) { - face -= Math.abs(normalRandInt(5*inbreedingCoeff, 35*inbreedingCoeff, -100*inbreedingCoeff, 100*inbreedingCoeff)); + if (jsRandom(1, 100) < inbreedingCoeff * 200) { + face -= Math.abs(normalRandInt(5 * inbreedingCoeff, 35 * inbreedingCoeff, -100 * inbreedingCoeff, 100 * inbreedingCoeff)); } } return Math.clamp(face, -100, 100); @@ -704,7 +698,8 @@ globalThis.generateGenetics = (function() { }; let chance = 0; let fatherGenes = 0; - let geneTarget = 0; + /** @type {number} */ + let geneTarget; // 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 genetic quirks, just ignore him @@ -939,108 +934,43 @@ globalThis.generateGenetics = (function() { } } - // perfect face - if (father !== 0) { - fatherGenes = father.geneticQuirks.pFace; - } - geneTarget = Math.pow(2, mother.geneticQuirks.pFace + fatherGenes); - if (geneTarget >= 2) { - chance = jsRandom(1, 16); - if (chance <= geneTarget) { - quirks.pFace = 2; - } else if (chance <= 3 * geneTarget) { - quirks.pFace = 1; - } - } + quirks.pFace = genes(father !== 0 ? father.geneticQuirks.pFace : 0, mother.geneticQuirks.pFace); // ugly face - if (father !== 0) { - fatherGenes = father.geneticQuirks.uFace; - } - geneTarget = Math.pow(2, mother.geneticQuirks.uFace + fatherGenes); - if (geneTarget >= 2) { - chance = jsRandom(1, 16); - if (chance <= geneTarget) { - quirks.uFace = 2; - } else if (chance <= 3 * geneTarget) { - quirks.uFace = 1; - } - } + quirks.uFace = genes(father !== 0 ? father.geneticQuirks.uFace : 0, mother.geneticQuirks.uFace); // gigantism - if (father !== 0) { - fatherGenes = father.geneticQuirks.gigantism; - } - geneTarget = Math.pow(2, mother.geneticQuirks.gigantism + fatherGenes); - if (geneTarget >= 2) { - chance = jsRandom(1, 16); - if (chance <= geneTarget) { - quirks.gigantism = 2; - } else if (chance <= 3 * geneTarget) { - quirks.gigantism = 1; - } - } + quirks.gigantism = genes(father !== 0 ? father.geneticQuirks.gigantism : 0, mother.geneticQuirks.gigantism); // dwarfism - if (father !== 0) { - fatherGenes = father.geneticQuirks.dwarfism; - } - geneTarget = Math.pow(2, mother.geneticQuirks.dwarfism + fatherGenes); - if (geneTarget >= 2) { - chance = jsRandom(1, 16); - if (chance <= geneTarget) { - quirks.dwarfism = 2; - } else if (chance <= 3 * geneTarget) { - quirks.dwarfism = 1; - } - } + quirks.dwarfism = genes(father !== 0 ? father.geneticQuirks.dwarfism : 0, mother.geneticQuirks.dwarfism); // neoteny + quirks.neoteny = genes( + // @ts-ignore + father !== 0 ? Math.min(father.geneticQuirks.neoteny, 2) : 0, + Math.min(mother.geneticQuirks.neoteny, 2)); // set to 3 denotes inactive to start - if (father !== 0) { - fatherGenes = father.geneticQuirks.neoteny; - } - geneTarget = Math.pow(2, Math.min(mother.geneticQuirks.neoteny, 2) + fatherGenes); - if (geneTarget >= 2) { - chance = jsRandom(1, 16); - if (chance <= geneTarget) { - quirks.neoteny = 3; - } else if (chance <= 3 * geneTarget) { - quirks.neoteny = 1; - } + if (quirks.neoteny === 2) { + quirks.neoteny = 3; } // progeria + quirks.progeria = genes( + // @ts-ignore + father !== 0 ? Math.min(father.geneticQuirks.progeria, 2) : 0, + Math.min(mother.geneticQuirks.progeria, 2)); // set to 3 denotes inactive to start - if (father !== 0) { - fatherGenes = father.geneticQuirks.progeria; - } - geneTarget = Math.pow(2, Math.min(mother.geneticQuirks.progeria, 2) + fatherGenes); - if (geneTarget >= 2) { - chance = jsRandom(1, 16); - if (chance <= geneTarget) { - quirks.progeria = 3; - } else if (chance <= 3 * geneTarget) { - quirks.progeria = 1; - } + if (quirks.progeria === 2) { + quirks.progeria = 3; } // albinism - if (father !== 0) { - fatherGenes = father.geneticQuirks.albinism; - } - geneTarget = Math.pow(2, mother.geneticQuirks.albinism + fatherGenes); - if (geneTarget >= 2) { - chance = jsRandom(1, 16); - if (chance <= geneTarget) { - quirks.albinism = 2; - } else if (chance <= 3 * geneTarget) { - quirks.albinism = 1; - } - } + quirks.albinism = genes(father !== 0 ? father.geneticQuirks.albinism : 0, mother.geneticQuirks.albinism); // heterochromia + // FIXME heterochromia is a string when active, this is not respected here. if (father !== 0) { fatherGenes = father.geneticQuirks.heterochromia; } @@ -1055,140 +985,77 @@ globalThis.generateGenetics = (function() { } // rear lipedema - if (father !== 0) { - fatherGenes = father.geneticQuirks.rearLipedema; - } - geneTarget = Math.pow(2, mother.geneticQuirks.rearLipedema + fatherGenes); - if (geneTarget >= 2) { - chance = jsRandom(1, 16); - if (chance <= geneTarget) { - quirks.rearLipedema = 2; - } else if (chance <= 3 * geneTarget) { - quirks.rearLipedema = 1; - } - } + quirks.rearLipedema = genes(father !== 0 ? father.geneticQuirks.rearLipedema : 0, mother.geneticQuirks.rearLipedema); // Gigantomastia + quirks.gigantomastia = genes( + // @ts-ignore + father !== 0 ? Math.min(father.geneticQuirks.gigantomastia, 2) : 0, + Math.min(mother.geneticQuirks.gigantomastia, 2)); // set to 3 denotes inactive to start - if (father !== 0) { - fatherGenes = father.geneticQuirks.gigantomastia; - } - geneTarget = Math.pow(2, Math.min(mother.geneticQuirks.gigantomastia, 2) + fatherGenes); - if (geneTarget >= 2) { - chance = jsRandom(1, 16); - if (chance <= geneTarget) { - quirks.gigantomastia = 3; - } else if (chance <= 3 * geneTarget) { - quirks.gigantomastia = 1; - } + if (quirks.gigantomastia === 2) { + quirks.gigantomastia = 3; } // Macromastia + quirks.macromastia = genes( + // @ts-ignore + father !== 0 ? Math.min(father.geneticQuirks.macromastia, 2) : 0, + Math.min(mother.geneticQuirks.macromastia, 2)); // set to 3 denotes inactive to start - if (father !== 0) { - fatherGenes = father.geneticQuirks.macromastia; - } - geneTarget = Math.pow(2, Math.min(mother.geneticQuirks.macromastia, 2) + fatherGenes); - if (geneTarget >= 2) { - chance = jsRandom(1, 16); - if (chance <= geneTarget) { - quirks.macromastia = 3; - } else if (chance <= 3 * geneTarget) { - quirks.macromastia = 1; - } + if (quirks.macromastia === 2) { + quirks.macromastia = 3; } // Galactorrhea + quirks.galactorrhea = genes( + // @ts-ignore + father !== 0 ? Math.min(father.geneticQuirks.galactorrhea, 2) : 0, + Math.min(mother.geneticQuirks.galactorrhea, 2)); // set to 3 denotes inactive to start - if (father !== 0) { - fatherGenes = father.geneticQuirks.galactorrhea; - } - geneTarget = Math.pow(2, Math.min(mother.geneticQuirks.galactorrhea, 2) + fatherGenes); - if (geneTarget >= 2) { - chance = jsRandom(1, 16); - if (chance <= geneTarget) { - quirks.galactorrhea = 3; - } else if (chance <= 3 * geneTarget) { - quirks.galactorrhea = 1; - } + if (quirks.galactorrhea === 2) { + quirks.galactorrhea = 3; } // myotonic hypertrophy - if (father !== 0) { - fatherGenes = father.geneticQuirks.mGain; - } - geneTarget = Math.pow(2, mother.geneticQuirks.mGain + fatherGenes); - if (geneTarget >= 2) { - chance = jsRandom(1, 16); - if (chance <= geneTarget) { - quirks.mGain = 2; - } else if (chance <= 3 * geneTarget) { - quirks.mGain = 1; - } - } + quirks.mGain = genes(father !== 0 ? father.geneticQuirks.mGain : 0, mother.geneticQuirks.mGain); // myotonic dystrophy - if (father !== 0) { - fatherGenes = father.geneticQuirks.mLoss; - } - geneTarget = Math.pow(2, mother.geneticQuirks.mLoss + fatherGenes); - if (geneTarget >= 2) { - chance = jsRandom(1, 16); - if (chance <= geneTarget) { - quirks.mLoss = 2; - } else if (chance <= 3 * geneTarget) { - quirks.mLoss = 1; - } - } + quirks.mLoss = genes(father !== 0 ? father.geneticQuirks.mLoss : 0, mother.geneticQuirks.mLoss); // hyperleptinemia - if (father !== 0) { - fatherGenes = father.geneticQuirks.wGain; - } - geneTarget = Math.pow(2, mother.geneticQuirks.wGain + fatherGenes); - if (geneTarget >= 2) { - chance = jsRandom(1, 16); - if (chance <= geneTarget) { - quirks.wGain = 2; - } else if (chance <= 3 * geneTarget) { - quirks.wGain = 1; - } - } + quirks.wGain = genes(father !== 0 ? father.geneticQuirks.wGain : 0, mother.geneticQuirks.wGain); // hypoleptinemia - if (father !== 0) { - fatherGenes = father.geneticQuirks.wLoss; - } - geneTarget = Math.pow(2, mother.geneticQuirks.wLoss + fatherGenes); - if (geneTarget >= 2) { - chance = jsRandom(1, 16); - if (chance <= geneTarget) { - quirks.wLoss = 2; - } else if (chance <= 3 * geneTarget) { - quirks.wLoss = 1; - } - } + quirks.wLoss = genes(father !== 0 ? father.geneticQuirks.wLoss : 0, mother.geneticQuirks.wLoss); // androgyny - if (father !== 0) { - fatherGenes = father.geneticQuirks.androgyny; - } - geneTarget = Math.pow(2, mother.geneticQuirks.androgyny + fatherGenes); + quirks.androgyny = genes(father !== 0 ? father.geneticQuirks.androgyny : 0, mother.geneticQuirks.androgyny); + + return clone(quirks); + } + + /** + * @param {0|1|2} fatherGenes + * @param {0|1|2} motherGenes + * @returns {number} + */ + function genes(fatherGenes, motherGenes) { + const geneTarget = Math.pow(2, motherGenes + fatherGenes); if (geneTarget >= 2) { - chance = jsRandom(1, 16); + const chance = jsRandom(1, 16); if (chance <= geneTarget) { - quirks.androgyny = 2; + return 2; } else if (chance <= 3 * geneTarget) { - quirks.androgyny = 1; + return 1; } } - return clone(quirks); + return 0; } return generateGenetics; })(); - /** * Creates a new child object based on its mother and father and whether or not it is destined for the Incubator * @param {App.Entity.SlaveState} mother The slave object carrying the child source @@ -1196,7 +1063,7 @@ globalThis.generateGenetics = (function() { * @param {boolean} [incubator=false] True if the child is destined for the incubator; false if it's destined for the nursery * @returns {App.Entity.SlaveState|App.Facilities.Nursery.InfantState} */ -globalThis.generateChild = function(mother, ovum, incubator=false) { +globalThis.generateChild = function(mother, ovum, incubator = false) { let genes = ovum.genetics; // TODO: maybe just argument this? We'll see. let child; @@ -1355,7 +1222,11 @@ globalThis.generateChild = function(mother, ovum, incubator=false) { child.anus = 0; if (child.vagina > 0) { child.vagina = 0; } if (child.fetish !== "none") { child.fetishStrength = 20; } - if (child.dick > 0) { child.foreskin = 1; child.balls = 1; child.scrotum = 1; } + if (child.dick > 0) { + child.foreskin = 1; + child.balls = 1; + child.scrotum = 1; + } if (genes.faceShape !== undefined) { child.faceShape = genes.faceShape; } if (mother.addict > 0) { child.addict = Math.trunc(mother.addict / 2); } child.career = "a slave since birth";