diff --git a/js/002-config/fc-js-init.js b/js/002-config/fc-js-init.js index 1710cf940dfaf83d07d879f2b7744cf63bd8abc6..a9df5e5e41e8d8c85b5f4504ab3c797a44db9b40 100644 --- a/js/002-config/fc-js-init.js +++ b/js/002-config/fc-js-init.js @@ -57,8 +57,6 @@ App.Medicine.Modification = {}; App.Medicine.Modification.Brands = {}; App.Medicine.Modification.Select = {}; App.Medicine.OrganFarm = {}; -/** @type {Object.<string, App.Medicine.OrganFarm.Organ>} */ -App.Medicine.OrganFarm.Organs = {}; App.Medicine.Salon = {}; App.Medicine.Surgery = {}; App.RA = {}; diff --git a/src/004-base/organFarmBase.js b/js/medicine/1-organFarmBase.js similarity index 92% rename from src/004-base/organFarmBase.js rename to js/medicine/1-organFarmBase.js index 9913f2fdd1a5b2c075a5abc2f0c503733d8b12e7..03051204f3cedbc9040f13cc1924604e08b1670b 100644 --- a/src/004-base/organFarmBase.js +++ b/js/medicine/1-organFarmBase.js @@ -1,7 +1,6 @@ App.Medicine.OrganFarm.Organ = class { /** * @param {Object} params - * @param {string} params.type - unique type of organ, used as key * @param {string} params.name - display name * @param {string|function(App.Entity.SlaveState):string} [params.tooltip] - full sentence, uncapitalized and unpunctuated * @param {number} params.cost - how much it costs to grow the organ @@ -12,10 +11,9 @@ App.Medicine.OrganFarm.Organ = class { * @param {boolean} [params.displayMultipleActions=false] allow multiple implant links to be displayed */ constructor({ - type, name, tooltip = "", cost, time, canGrow = () => true, dependencies = [], + name, tooltip = "", cost, time, canGrow = () => true, dependencies = [], displayMultipleActions = false, actions = [] }) { - this.type = type; this.name = name; this.tooltip = tooltip; this.cost = cost; @@ -27,8 +25,6 @@ App.Medicine.OrganFarm.Organ = class { this.displayMultipleActions = displayMultipleActions; /** @type {App.Medicine.OrganFarm.OrganImplantAction[]} */ this.implantActions = actions; - - App.Medicine.OrganFarm.Organs[type] = this; } }; diff --git a/src/npc/surgery/reproductiveOrgans.js b/js/medicine/2-reproductiveOrgans.js similarity index 88% rename from src/npc/surgery/reproductiveOrgans.js rename to js/medicine/2-reproductiveOrgans.js index 9d0ac8edfe92d4f787b6a0ce85f1adbd9d24c9d0..27c13db5de8458dac788c155e034c57639a7a818 100644 --- a/src/npc/surgery/reproductiveOrgans.js +++ b/js/medicine/2-reproductiveOrgans.js @@ -4,17 +4,27 @@ App.Medicine.OrganFarm.TesticlesImplantAction = class extends App.Medicine.Organ * @param {string} params.name * @param {string} [params.tooltip] * @param {boolean} params.animal + * @param {string} [params.surgeryType] * @param {boolean} [params.autoImplant] * @param {function(App.Entity.SlaveState):boolean} params.canImplant * @param {function(App.Entity.SlaveState):string} params.implantError * @param {function(App.Entity.SlaveState):void} params.implant */ - constructor({name, tooltip = "", animal, autoImplant = true, canImplant, implantError, implant}) { + constructor({ + name, + tooltip = "", + animal, + surgeryType = animal ? "addAnimalBalls" : "addBalls", + autoImplant = true, + canImplant, + implantError, + implant + }) { super({ name: name, tooltip: tooltip, healthImpact: 20, - surgeryType: animal ? "addAnimalBalls" : "addBalls", + surgeryType: surgeryType, autoImplant: autoImplant, canImplant: s => (!this.animal || V.animalTesticles > 0) && canImplant(s), implantError: s => (this.animal && V.animalTesticles === 0) ? "" : implantError(s), @@ -27,13 +37,12 @@ App.Medicine.OrganFarm.TesticlesImplantAction = class extends App.Medicine.Organ App.Medicine.OrganFarm.Testicles = class extends App.Medicine.OrganFarm.Organ { /** * @param {Object} params - * @param {string} params.type * @param {string} params.name * @param {FC.AnimalKind} params.ballType */ - constructor({type, name, ballType}) { + constructor({name, ballType}) { super({ - type: type, name: name, + name: name, tooltip: "will add a prostate if one is not already present; requires a penis for successful implantation", cost: 5000, time: 10, canGrow: () => (this.ballType === "human" || V.animalTesticles > 0), dependencies: ["penis"], @@ -71,7 +80,9 @@ App.Medicine.OrganFarm.Testicles = class extends App.Medicine.OrganFarm.Organ { new App.Medicine.OrganFarm.TesticlesImplantAction({ name: "Implant", tooltip: "you can forgo standard procedure and implant testicles directly into their abdomen", - animal: ballType !== "human", surgeryType: "addTesticles", autoImplant: false, + animal: ballType !== "human", + surgeryType: "addTesticles", + autoImplant: false, canImplant: slave => (slave.dick === 0 && slave.balls <= 0), implantError: slave => ((slave.balls > 0) ? "This slave already has testicles." : ""), implant: slave => { @@ -94,11 +105,8 @@ App.Medicine.OrganFarm.Testicles = class extends App.Medicine.OrganFarm.Organ { } }), new App.Medicine.OrganFarm.TesticlesImplantAction({ - name: "Replace", - tooltip: "you can replace the existing testicles with a new pair", - healthImpact: 20, - surgeryType: "addTesticles", - autoImplant: false, + name: "Replace", tooltip: "you can replace the existing testicles with a new pair", + animal: ballType !== "human", surgeryType: "addTesticles", autoImplant: false, canImplant: slave => (slave.balls > 0 && slave.ballType !== this.ballType), implantError: slave => (slave.balls > 0 ? `This slave already has ${this.ballType} testicles.` : ""), implant: slave => { @@ -149,14 +157,13 @@ App.Medicine.OrganFarm.OvariesImplantAction = class extends App.Medicine.OrganFa App.Medicine.OrganFarm.Ovaries = class extends App.Medicine.OrganFarm.Organ { /** * @param {object} params - * @param {string} params.type * @param {string} params.name * @param {FC.AnimalKind} params.eggType * @param {string} params.pregData */ - constructor({type, name, eggType, pregData}) { + constructor({name, eggType, pregData}) { super({ - type: type, name: name, tooltip: "requires a vagina for successful implantation", + name: name, tooltip: "requires a vagina for successful implantation", cost: 10000, time: 10, canGrow: () => (this.eggType === "human" || V.animalOvaries > 0), actions: [ @@ -172,7 +179,13 @@ App.Medicine.OrganFarm.Ovaries = class extends App.Medicine.OrganFarm.Organ { s.ovaries = 1; s.eggType = this.eggType; s.preg = 0; - s.pregData = clone(setup.pregData[this.pregData]); + /** + * @type {FC.PregnancyData} + */ + // @ts-ignore + const data = {}; + deepAssign(data, App.Data.misc.pregData[this.pregData]); + s.pregData = data; if (s.pubertyXX === 0 && s.physicalAge >= V.fertilityAge) { if (V.precociousPuberty === 1) { s.pubertyAgeXX = s.physicalAge + 1; @@ -192,7 +205,13 @@ App.Medicine.OrganFarm.Ovaries = class extends App.Medicine.OrganFarm.Organ { implant: s => { s.eggType = this.eggType; s.preg = 0; - s.pregData = clone(setup.pregData[this.pregData]); + /** + * @type {FC.PregnancyData} + */ + // @ts-ignore + const data = {}; + deepAssign(data, App.Data.misc.pregData[this.pregData]); + s.pregData = data; if (s.pubertyXX === 0 && s.physicalAge >= V.fertilityAge) { if (V.precociousPuberty === 1) { s.pubertyAgeXX = s.physicalAge + 1; @@ -229,7 +248,13 @@ App.Medicine.OrganFarm.AnalWombImplantAction = class extends App.Medicine.OrganF s.mpreg = 1; s.eggType = this.eggType; s.preg = 0; - s.pregData = clone(setup.pregData[this.pregData]); + /** + * @type {FC.PregnancyData} + */ + // @ts-ignore + const data = {}; + deepAssign(data, App.Data.misc.pregData[this.pregData]); + s.pregData = data; if (s.pubertyXX === 0 && s.physicalAge >= V.fertilityAge) { if (V.precociousPuberty === 1) { s.pubertyAgeXX = s.physicalAge + 1; @@ -247,14 +272,13 @@ App.Medicine.OrganFarm.AnalWombImplantAction = class extends App.Medicine.OrganF App.Medicine.OrganFarm.AnalWomb = class extends App.Medicine.OrganFarm.Organ { /** * @param {object} params - * @param {string} params.type * @param {string} params.name * @param {FC.AnimalKind} params.eggType * @param {string} params.pregData */ - constructor({type, name, eggType, pregData}) { + constructor({name, eggType, pregData}) { super({ - type: type, name: name, + name: name, tooltip: "the slave must not have female reproductive organs for successful implantation", cost: 20000, time: 10, canGrow: () => (V.arcologies[0].FSGenderRadicalistResearch === 1 && (eggType === "human" || V.animalMpreg > 0)), diff --git a/js/medicine/3-organMap.js b/js/medicine/3-organMap.js new file mode 100644 index 0000000000000000000000000000000000000000..3cf4fc2b3f302f3433544c1ee2335f5cb005deb4 --- /dev/null +++ b/js/medicine/3-organMap.js @@ -0,0 +1,438 @@ +/** + * Organs will usually be displayed in this order. + * +/** @type {Map<string, App.Medicine.OrganFarm.Organ>} */ +App.Medicine.OrganFarm.Organs = new Map([ + ["penis", + new App.Medicine.OrganFarm.Organ({ + name: "Penis", cost: 5000, time: 5, + canGrow: () => (V.seeDicks !== 0 || V.makeDicks === 1), + actions: [ + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Implant", healthImpact: 20, surgeryType: "addDick", + canImplant: slave => (slave.dick <= 0), + implantError: () => "this slave already has a penis", + implant: slave => { + if (slave.prostate === 0) { + slave.prostate = 1; + } + slave.dick = 2; + slave.clit = 0; + slave.foreskin = slave.dick; + } + }) + ] + })], + ["testicles", + new App.Medicine.OrganFarm.Testicles({ + name: "Testicles", ballType: "human" + })], + ["pigTesticles", + new App.Medicine.OrganFarm.Testicles({ + name: "Pig testicles", ballType: "pig" + })], + ["dogTesticles", + new App.Medicine.OrganFarm.Testicles({ + name: "Dog testicles", ballType: "dog" + })], + ["horseTesticles", + new App.Medicine.OrganFarm.Testicles({ + name: "Horse testicles", ballType: "horse" + })], + ["cowTesticles", + new App.Medicine.OrganFarm.Testicles({ + name: "Cow testicles", ballType: "cow" + })], + ["scrotum", + new App.Medicine.OrganFarm.Organ({ + name: "Scrotum", tooltip: "requires balls for successful implantation", cost: 2500, time: 5, + dependencies: ["testicles", "pigTesticles", "dogTesticles", "horseTesticles", "cowTesticles"], + actions: [ + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Graft on", healthImpact: 10, surgeryType: "addScrotum", + canImplant: slave => (slave.scrotum <= 0 && slave.balls > 0), + implantError: slave => (slave.scrotum > 0) ? "This slave already has a scrotum." : "This slave lacks the balls necessary to accept a scrotum.", + implant: slave => { + slave.scrotum = slave.balls; + } + }) + ] + })], + ["foreskin", + new App.Medicine.OrganFarm.Organ({ + name: "Foreskin", cost: 2500, time: 5, + actions: [ + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Graft on", healthImpact: 10, surgeryType: "addForeskin", + canImplant: slave => (slave.foreskin <= 0), + implantError: slave => `This slave already has a ${slave.dick > 0 ? "foreskin" : "clitoral hood"}.`, + implant: slave => { + if (slave.dick > 0) { + slave.foreskin = slave.dick; + } else if (slave.clit > 0) { + slave.foreskin = slave.clit; + } else { + slave.foreskin = 1; + } + } + }) + ] + })], + ["prostate", + new App.Medicine.OrganFarm.Organ({ + name: "Prostate", cost: 5000, time: 5, + actions: [ + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Implant", healthImpact: 20, surgeryType: "addProstate", + canImplant: s => (s.prostate === 0), + implantError: () => "This slave already has a prostate.", + implant: s => { + s.prostate = 1; + } + }) + ] + })], + ["ovaries", + new App.Medicine.OrganFarm.Ovaries({ + name: "Ovaries", eggType: "human", pregData: "human" + })], + ["freshOvaries", + new App.Medicine.OrganFarm.Organ({ + name: "Younger Ovaries", + tooltip: "requires a womb for successful implantation", + cost: 10000, time: 10, + canGrow: () => (V.youngerOvaries === 1), + dependencies: ["ovaries", "pigOvaries", "dogOvaries", "horseOvaries", "cowOvaries", "mpreg", "mpregPig", "mpregDog", "mpregHorse", "mpregCow"], + actions: [ + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Implant", healthImpact: 20, surgeryType: "freshOvaries", + canImplant: s => ((s.mpreg !== 0 || s.ovaries !== 0) && s.bellyImplant === -1 && s.physicalAge < 70), + implantError: s => (s.physicalAge >= 70) ? "This slave's body is too old to handle pregnancy." : "This slave lacks a viable womb.", + implant: s => { + if (s.ovaryAge >= 47) { + s.ovaryAge = 45; + } else { + s.ovaryAge = -2; // It shouldn't matter if this goes negative as it is just a signal for menopause to occur. + } + if (s.preg < 0) { + s.preg = 0; + } + if (s.pubertyXX === 0 && s.physicalAge >= V.fertilityAge) { + if (V.precociousPuberty === 1) { + s.pubertyAgeXX = s.physicalAge + 1; + } else { + s.pubertyXX = 1; + } + } + } + }) + ] + })], + ["asexualReproOvaries", + new App.Medicine.OrganFarm.Organ({ + name: "Asexual reproduction modification", + tooltip: "requires existing ovaries for successful implantation", + cost: 10000, time: 10, + canGrow: () => (V.asexualReproduction === 1), + dependencies: ["ovaries", "pigOvaries", "dogOvaries", "horseOvaries", "cowOvaries", "mpreg", "mpregPig", "mpregDog", "mpregHorse", "mpregCow"], + actions: [ + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Implant", healthImpact: 20, surgeryType: "asexualReproOvaries", + canImplant: s => (s.mpreg !== 0 || s.ovaries !== 0), + implantError: () => "This slave lacks ovaries.", + implant: s => { + if (s.preg < 0) { + s.preg = 0; + } + s.eggType = "human"; + /** + * @type {FC.PregnancyData} + */ + // @ts-ignore + const data = {}; + deepAssign(data, App.Data.misc.pregData.human); + s.pregData = data; + if (s.pubertyXX === 0 && s.physicalAge >= V.fertilityAge) { + if (V.precociousPuberty === 1) { + s.pubertyAgeXX = s.physicalAge + 1; + } else { + s.pubertyXX = 1; + } + } + s.ovaImplant = "asexual"; + } + }) + ] + })], + ["pigOvaries", + new App.Medicine.OrganFarm.Ovaries({ + name: "Pig ovaries", eggType: "pig", pregData: "pig" + })], + ["dogOvaries", + new App.Medicine.OrganFarm.Ovaries({ + name: "Dog ovaries", eggType: "dog", pregData: "canineM", + })], + ["horseOvaries", + new App.Medicine.OrganFarm.Ovaries({ + name: "Horse ovaries", eggType: "horse", pregData: "equine", + })], + ["cowOvaries", + new App.Medicine.OrganFarm.Ovaries({ + name: "Cow ovaries", eggType: "cow", pregData: "cow" + })], + ["leftEye", + new App.Medicine.OrganFarm.Organ({ + name: "Left Eye", cost: 5000, time: 10, + tooltip: s => getLeftEyeVision(s) === 2 ? "would not improve this slave" : "", + actions: [ + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Implant", healthImpact: 10, surgeryType: "newEyes", + canImplant: s => (getLeftEyeVision(s) === 0 && getBestVision(s) !== 0 && getLeftEyeType(s) !== 2), + implantError: s => getLeftEyeVision(s) !== 0 ? "Slave has a working left eye." : "", + implant: s => { + eyeSurgery(s, "left", "normal"); + } + }), + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Implant", healthImpact: 10, surgeryType: "unblind", + canImplant: s => (getBestVision(s) === 0 && getLeftEyeType(s) !== 2), + implantError: () => "", + implant: s => { + eyeSurgery(s, "left", "normal"); + } + }), + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Replace", tooltip: "replace the existing ocular implant with an organic eye", + healthImpact: 10, surgeryType: "newEyes", autoImplant: false, + canImplant: s => (getLeftEyeType(s) === 2), + implantError: () => "", + implant: s => { + eyeSurgery(s, "left", "normal"); + } + }) + ] + })], + ["rightEye", + new App.Medicine.OrganFarm.Organ({ + name: "Right Eye", cost: 5000, time: 10, + tooltip: s => getRightEyeVision(s) === 2 ? "would not improve this slave" : "", + actions: [ + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Implant", healthImpact: 10, surgeryType: "newEyes", + canImplant: s => (getRightEyeVision(s) === 0 && getBestVision(s) !== 0 && getRightEyeType(s) !== 2), + implantError: s => getRightEyeVision(s) !== 0 ? "Slave has a working right eye." : "", + implant: s => { + eyeSurgery(s, "right", "normal"); + } + }), + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Implant", healthImpact: 10, surgeryType: "unblind", + canImplant: s => (getBestVision(s) === 0 && getRightEyeType(s) !== 2), + implantError: () => "", + implant: s => { + eyeSurgery(s, "right", "normal"); + } + }), + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Replace", tooltip: "replace the existing ocular implant with an organic eye", + healthImpact: 20, surgeryType: "newEyes", autoImplant: false, + canImplant: s => (getRightEyeType(s) === 2), + implantError: () => "", + implant: s => { + eyeSurgery(s, "right", "normal"); + } + }) + ] + })], + ["ears", + new App.Medicine.OrganFarm.Organ({ + name: "Normal Ears", cost: 1000, time: 2, + actions: [ + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Attach", healthImpact: 15, surgeryType: "earMinor", + canImplant: s => (s.earShape === "none"), + implantError: () => "This slave already has ears.", + implant: s => { + s.earShape = "normal"; + if (s.hears === -1) { + s.hears = 0; + } + } + }), + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Replace", tooltip: "replace current ears with normal human ears", + healthImpact: 20, surgeryType: "earMinor", autoImplant: false, + canImplant: s => (s.earShape !== "normal"), + implantError: () => "This slave already has normal ears.", + implant: s => { + s.earShape = "normal"; + } + }) + ] + })], + ["topEars", + new App.Medicine.OrganFarm.Organ({ + name: "Top Ears", cost: 1000, time: 2, + canGrow: () => (V.surgeryUpgrade >= 1), + actions: [ + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Attach", healthImpact: 10, surgeryType: "earMinor", + canImplant: s => (s.earT === "none"), + implantError: () => "This slave already has ears at the top of the head.", + implant: s => { + s.earT = "normal"; + s.earTColor = "hairless"; + } + }), + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Replace", tooltip: "replace current top ears with normal ears", + healthImpact: 20, surgeryType: "earMinor", autoImplant: false, + canImplant: s => (s.earT !== "normal"), + implantError: () => "This slave already has normal ears at the top of the head.", + implant: s => { + s.earT = "normal"; + s.earTColor = "hairless"; + } + }) + ] + })], + ["cochleae", + new App.Medicine.OrganFarm.Organ({ + name: "Cochleae", cost: 8000, time: 6, + actions: [ + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Implant", healthImpact: 20, surgeryType: "undeafen", + canImplant: s => (s.hears <= -2 && s.earImplant === 0), + implantError: () => "This slave already has working ears.", + implant: s => { + s.hears = 0; + } + }), + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Replace", tooltip: "remove cochlear implants before implanting organic cochleae", + healthImpact: 20, surgeryType: "newEars", autoImplant: false, + canImplant: s => (s.earImplant === 1), + implantError: () => "", + implant: s => { + s.hears = 0; + s.earImplant = 0; + } + }) + ] + })], + ["voicebox", + new App.Medicine.OrganFarm.Organ({ + name: "Vocal Cords", cost: 5000, time: 5, + actions: [ + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Implant", healthImpact: 10, surgeryType: "restoreVoice", + canImplant: s => (s.voice === 0 && s.electrolarynx === 0), + implantError: () => "This slave is not mute.", + implant: s => { + if (s.ovaries === 1 && s.hormoneBalance >= 200) { + s.voice = 3; + } else if (s.balls > 0 || s.hormoneBalance < -20) { + s.voice = 1; + } else { + s.voice = 2; + } + } + }), + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Replace", tooltip: "remove electrolarynx and implant organic vocal cords", + healthImpact: 20, surgeryType: "newVoice", autoImplant: false, + canImplant: s => (s.electrolarynx === 1), + implantError: () => "", + implant: s => { + s.electrolarynx = 0; + if (s.ovaries === 1 && s.hormoneBalance >= 200) { + s.voice = 3; + } else if (s.balls > 0 || s.hormoneBalance < -20) { + s.voice = 1; + } else { + s.voice = 2; + } + } + }) + ] + })], + ["hair", + new App.Medicine.OrganFarm.Organ({ + name: "Hair Follicles", cost: 500, time: 2, displayMultipleActions: true, + actions: [ + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Scalp", healthImpact: 10, surgeryType: "restoreHairHead", + canImplant: s => (s.bald !== 0), + implantError: () => "This slave already has hair.", + implant: s => { + s.bald = 0; + s.hLength = 1; + s.hStyle = "neat"; + s.hColor = getGeneticHairColor(s); + } + }), + /* So apparently hair is tracked via the .earTColor variable with no differential between possible hair origin. Not worth the variable, currently. + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Ears", healthImpact: 5, + surgeryType: "addHairEarsH", autoImplant: false, + canImplant: s => (s.earTShape !== "normal"), + implantError: "", + implant: s => { + s.earTColor = getGeneticHairColor(s); + } + }), + */ + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Brow", healthImpact: 5, + surgeryType: "restoreHairBrow", autoImplant: false, + canImplant: s => (s.eyebrowHStyle === "bald"), + implantError: () => "", + implant: s => { + s.eyebrowHStyle = "natural"; + s.eyebrowFullness = "natural"; + s.eyebrowHColor = getGeneticHairColor(s); + } + }), + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Axillary", healthImpact: 5, + surgeryType: "restoreHairPits", autoImplant: false, + canImplant: s => (s.underArmHStyle === "bald" || s.underArmHStyle === "hairless"), + implantError: () => "", + implant: s => { + s.underArmHStyle = "bushy"; + s.underArmHColor = getGeneticHairColor(s); + } + }), + new App.Medicine.OrganFarm.OrganImplantAction({ + name: "Pubic", healthImpact: 5, + surgeryType: "restoreHairPubes", autoImplant: false, + canImplant: s => (s.pubicHStyle === "bald" || s.pubicHStyle === "hairless"), + implantError: () => "", + implant: s => { + s.pubicHStyle = "very bushy"; + s.pubicHColor = getGeneticHairColor(s); + } + }) + ] + })], + ["mpreg", + new App.Medicine.OrganFarm.AnalWomb({ + name: "Anal womb and ovaries", eggType: "human", pregData: "human", + })], + ["mpregPig", + new App.Medicine.OrganFarm.AnalWomb({ + name: "Anal pig womb and ovaries", eggType: "pig", pregData: "pig", + })], + ["mpregDog", + new App.Medicine.OrganFarm.AnalWomb({ + name: "Anal dog womb and ovaries", eggType: "dog", pregData: "canineM", + })], + ["mpregHorse", + new App.Medicine.OrganFarm.AnalWomb({ + name: "Anal horse womb and ovaries", eggType: "horse", pregData: "equine", + })], + ["mpregCow", + new App.Medicine.OrganFarm.AnalWomb({ + name: "Anal cow womb and ovaries", eggType: "cow", pregData: "cow", + })], +]); diff --git a/src/interaction/multiImplant.js b/src/interaction/multiImplant.js new file mode 100644 index 0000000000000000000000000000000000000000..be65676c7da4a594297ea53e90323c92803e29e7 --- /dev/null +++ b/src/interaction/multiImplant.js @@ -0,0 +1,66 @@ +App.UI.multiImplant = function() { + const frag = document.createDocumentFragment(); + + let r = []; + r.push("You head down to your"); + if (V.surgeryUpgrade === 1) { + r.push("heavily upgraded and customized"); + } + r.push("remote surgery and start having the slaves with"); + if (V.completedOrgans.length > 0 && V.adjustProstheticsCompleted > 0) { + r.push("organs or prosthetics"); + } else if (V.completedOrgans.length > 1) { + r.push("organs"); + } else if (V.adjustProstheticsCompleted > 1) { + r.push("prosthetics"); + } + r.push("that are ready be sent down."); + + App.UI.DOM.appendNewElement("p", frag, r.join(" ")); + + App.UI.DOM.appendNewElement("h1", frag, "Implant Organs"); + + let F = App.Medicine.OrganFarm; + for (const slave of V.slaves) { + let sortedOrgans = F.getSortedOrgans(slave); + if (sortedOrgans.length === 0) { + continue; + } + + App.UI.DOM.appendNewElement("h2", frag, slave.slaveName); + + for (let j = 0; j < sortedOrgans.length; j++) { + App.UI.DOM.appendNewElement("h3", frag, F.Organs.get(sortedOrgans[j]).name); + + let actions = F.Organs.get(sortedOrgans[j]).implantActions; + let manual = false, success = false, cancel = false; + for (let k = 0; k < actions.length; k++) { + if (!actions[k].autoImplant) { + if (actions[k].canImplant(slave)) { + manual = true; + } + continue; + } + if (!actions[k].canImplant(slave)) { + let error = actions[k].implantError(slave); + if (error !== "") { + App.UI.DOM.appendNewElement("div", frag, error, "warning"); + } + } else if (slave.health.health - actions[k].healthImpact < -75) { + App.UI.Dom.appendNewElement("div", frag, "Estimated health impact too high, skipping further surgeries."); + cancel = true; + break; + } else { + App.Medicine.OrganFarm.implant(slave, sortedOrgans[j], k); + App.UI.DOM.appendNewElement("p", frag, App.UI.SlaveInteract.surgeryDegradation(slave)); + success = true; + } + } + if (cancel) { break; } + if (!success && manual) { + App.UI.Dom.appendNewElement("div", frag, `Cannot implant ${F.Organs.get(sortedOrgans[j]).name.toLowerCase()} automatically, try implanting manually in the remote surgery.`, "note"); + } + } + } + return frag; +}; diff --git a/src/npc/surgery/organFarm.js b/src/npc/surgery/organFarm.js index b5f8925104ae658a8662ba74139ef402a3209786..7583c84553fdf29bfbf0d9b83feb3db305db972b 100644 --- a/src/npc/surgery/organFarm.js +++ b/src/npc/surgery/organFarm.js @@ -1,14 +1,13 @@ /** * @param {App.Entity.SlaveState} slave - * @returns {string} + * @returns {HTMLDivElement} */ App.Medicine.OrganFarm.growActions = function(slave) { - const organOrder = App.Medicine.OrganFarm.organDisplayOrder; const O = App.Medicine.OrganFarm.Organs; // find already being grown/ready to implant organs const slaveOrgans = {}; - organOrder.forEach(organ => slaveOrgans[organ] = 0); + O.forEach((organ, key) => slaveOrgans[key] = 0); V.completedOrgans.forEach(organ => { if (organ.ID === slave.ID) { slaveOrgans[organ.type] = -1; @@ -30,42 +29,48 @@ App.Medicine.OrganFarm.growActions = function(slave) { } } - const {His, him} = getPronouns(slave); + const div = document.createElement("div"); + div.classList.add("grid-2columns-auto"); // create entries for each organ - let grow = ""; - let wait = []; - for (const organId of organOrder) { - if (slaveOrgans[organId] === 0) { - const organ = O[organId]; + let growing = []; + let any = false; + O.forEach((organ, key) => { + if (slaveOrgans[key] === 0) { if (organ.canGrow(slave)) { - grow += `<div>${App.UI.link(organ.name, App.Medicine.OrganFarm.growOrgan, [slave, organId], "Remote Surgery")}</div>`; + App.UI.DOM.appendNewElement("div", div, App.UI.DOM.passageLink(organ.name, "Remote Surgery", () => { + App.Medicine.OrganFarm.growOrgan(slave, key); + })); + const tooltip = typeof organ.tooltip === "string" ? organ.tooltip : organ.tooltip(slave); - grow += `<div class="detail">Costs ${cashFormat(organ.cost)}${tooltip !== "" ? ` and ${tooltip}` : ""}.</div>`; + App.UI.DOM.appendNewElement("div", div, `Costs ${cashFormat(organ.cost)}${tooltip !== "" ? ` and ${tooltip}` : ""}.`, "detail"); } - } else if (slaveOrgans[organId] > 0) { + any = true; + } else if (slaveOrgans[key] > 0) { // in growth organs at the end of the list - wait.push({ - time: slaveOrgans[organId], - text: `${His} ${O[organId].name.toLowerCase()} will be ready for implantation in ${weeksLeft(slaveOrgans[organId])} weeks.` + growing.push({ + time: slaveOrgans[key], + organ: organ.name, + text: `Ready for implantation in ${weeksLeft(slaveOrgans[key])} weeks.` }); + any = true; } - } + }); - // put everything in one string - let r = ""; - if (grow !== "") { - r += `The fabricator is ready to grow an organ for ${him}. Extract tissue to begin growing:<div class="grid-2columns-auto">${grow}</div>`; - } - if (wait !== []) { + if (growing !== []) { // nearer to completion => higher up - wait.sort((a, b) => a.time - b.time); - for (let i = 0; i < wait.length; i++) { - r += `<div>${wait[i].text}</div>`; + growing.sort((a, b) => a.time - b.time); + for (let i = 0; i < growing.length; i++) { + App.UI.DOM.appendNewElement("div", div, growing[i].organ); + App.UI.DOM.appendNewElement("div", div, growing[i].text); } } - return r; + if (any) { + return div; + } else { + return null; + } }; /** @@ -73,7 +78,7 @@ App.Medicine.OrganFarm.growActions = function(slave) { * @param {string} organType */ App.Medicine.OrganFarm.growOrgan = function(slave, organType) { - const organ = App.Medicine.OrganFarm.Organs[organType]; + const organ = App.Medicine.OrganFarm.Organs.get(organType); V.organs.push({type: organType, weeksToCompletion: organ.time, ID: slave.ID}); @@ -85,7 +90,7 @@ App.Medicine.OrganFarm.growOrgan = function(slave, organType) { * @param {string} organType */ App.Medicine.OrganFarm.growIncubatorOrgan = function(slave, organType) { - const organ = App.Medicine.OrganFarm.Organs[organType]; + const organ = App.Medicine.OrganFarm.Organs.get(organType); V.incubatorOrgans.push({type: organType, weeksToCompletion: organ.time, ID: slave.ID}); @@ -105,11 +110,11 @@ App.Medicine.OrganFarm.implantActions = function(slave) { grid.classList.add("grid-2columns-auto"); for (const organ of slaveOrgans) { - App.UI.DOM.appendNewElement("div", grid, F.Organs[organ.type].name); + App.UI.DOM.appendNewElement("div", grid, F.Organs.get(organ.type).name); let links = []; - for (let i = 0; i < F.Organs[organ.type].implantActions.length; i++) { - const action = F.Organs[organ.type].implantActions[i]; + for (let i = 0; i < F.Organs.get(organ.type).implantActions.length; i++) { + const action = F.Organs.get(organ.type).implantActions[i]; if (action.canImplant(slave)) { const link = App.UI.DOM.link( action.name, @@ -126,7 +131,7 @@ App.Medicine.OrganFarm.implantActions = function(slave) { link.classList.add("hasTooltip"); } links.push(link); - if (!F.Organs[organ.type].displayMultipleActions) { + if (!F.Organs.get(organ.type).displayMultipleActions) { break; // there can only be one implant action } } else { @@ -161,7 +166,7 @@ App.Medicine.OrganFarm.implantActions = function(slave) { * @param {number} actionIndex */ App.Medicine.OrganFarm.implant = function(slave, type, actionIndex) { - const A = App.Medicine.OrganFarm.Organs[type].implantActions[actionIndex]; + const A = App.Medicine.OrganFarm.Organs.get(type).implantActions[actionIndex]; A.implant(slave); surgeryDamage(slave, A.healthImpact); @@ -201,10 +206,10 @@ App.Medicine.OrganFarm.getSortedOrgans = function(slave) { organs.push(organ.type); } }); - organs.forEach(o => { - F.Organs[o].dependencies.forEach(d => { - if (organs.includes(d)) { /* inefficient, is there a better way? */ - dependencies.push([d, o]); + organs.forEach(organKey => { + F.Organs.get(organKey).dependencies.forEach(dependencyKey => { + if (organs.includes(dependencyKey)) { /* inefficient, is there a better way? */ + dependencies.push([dependencyKey, organKey]); } }); }); @@ -230,8 +235,11 @@ App.Medicine.OrganFarm.fullMenu = function(slave) { const growActions = App.Medicine.OrganFarm.growActions(slave); let anyAction = false; - if (growActions !== "") { - $(fragment).append(Wikifier.wikifyEval(`<h3>Grow new organs</h3><div class="indent">${growActions}</div>`)); + if (growActions != null) { + const {him} = getPronouns(slave); + App.UI.DOM.appendNewElement("h3", fragment, "Grow new organs"); + App.UI.DOM.appendNewElement("div", fragment, `The fabricator is ready to grow an organ for ${him}. Extract tissue to begin growing:`); + App.UI.DOM.appendNewElement("div", fragment, growActions, "choices"); anyAction = true; } @@ -250,6 +258,11 @@ App.Medicine.OrganFarm.fullMenu = function(slave) { return fragment; }; +/** + * Returns a list of currently growing and finished organs. + * + * @returns {DocumentFragment} + */ App.Medicine.OrganFarm.currentlyGrowing = function() { function weeksToCompletion(weeks) { if (V.organFarmUpgrade === 1) { @@ -261,60 +274,68 @@ App.Medicine.OrganFarm.currentlyGrowing = function() { } } - let r = ""; - + /** + * @type {Array<string|HTMLSpanElement>} + */ let growLines = []; + /** + * @type {Array<string|HTMLSpanElement>} + */ let finishLines = []; V.organs.forEach(o => { const slave = getSlave(o.ID); if (slave !== undefined) { - growLines.push(`${slave.slaveName}'s ${App.Medicine.OrganFarm.Organs[o.type].name}, ${ - weeksToCompletion(o.weeksToCompletion)} week(s) left.`); + const weeks = weeksToCompletion(o.weeksToCompletion); + growLines.push(`${slave.slaveName}'s ${App.Medicine.OrganFarm.Organs.get(o.type).name}, ${weeks} ${weeks > 1 ? "weeks" : "week"} left.`); } else { - growLines.push(`<span class="error">ERROR: No slave with ID ${o.ID} found.</span>`); + growLines.push(App.UI.DOM.makeElement("span", `ERROR: No slave with ID ${o.ID} found.`, "error")); } }); V.incubatorOrgans.forEach(o => { const tank = V.tanks.find((t) => t.ID === o.ID); if (tank !== undefined) { if (o.weeksToCompletion <= 0) { - finishLines.push(`${tank.slaveName}'s ${App.Medicine.OrganFarm.Organs[o.type].name}.`); + finishLines.push(`${tank.slaveName}'s ${App.Medicine.OrganFarm.Organs.get(o.type).name}.`); } else { - growLines.push(`${tank.slaveName}'s ${App.Medicine.OrganFarm.Organs[o.type].name}, ${ + growLines.push(`${tank.slaveName}'s ${App.Medicine.OrganFarm.Organs.get(o.type).name}, ${ weeksToCompletion(o.weeksToCompletion)} week(s) left.`); } } else { - growLines.push(`<span class="error">ERROR: No tank with ID ${o.ID} found.</span>`); + growLines.push(App.UI.DOM.makeElement("span", `ERROR: No tank with ID ${o.ID} found.`, "error")); } }); V.completedOrgans.forEach(o => { const slave = getSlave(o.ID); if (slave !== undefined) { - finishLines.push(`${slave.slaveName}'s ${App.Medicine.OrganFarm.Organs[o.type].name}.`); + finishLines.push(`${slave.slaveName}'s ${App.Medicine.OrganFarm.Organs.get(o.type).name}.`); } else { - finishLines.push(`<span class="error">ERROR: No slave with ID ${o.ID} found.</span>`); + growLines.push(App.UI.DOM.makeElement("span", `ERROR: No slave with ID ${o.ID} found.`, "error")); } }); + const frag = document.createDocumentFragment(); + if (growLines.length > 0) { - r += "<h3>Growing Organs</h3>"; + App.UI.DOM.appendNewElement("h3", frag, "Growing Organs"); + + growLines.forEach(l => { + App.UI.DOM.appendNewElement("div", frag, l); + }); } - growLines.forEach(l => { - r += `<div>${l}</div>`; - }); if (finishLines.length > 0) { - r += "<h3>Finished Organs</h3>"; + App.UI.DOM.appendNewElement("h3", frag, "Finished Organs"); + + finishLines.forEach(l => { + App.UI.DOM.appendNewElement("div", frag, l); + }); } - finishLines.forEach(l => { - r += `<div>${l}</div>`; - }); if (growLines.length === 0 && finishLines.length === 0) { - r += `<div><span class="detail">Organs must be genetically matched to their host slave. To begin growing organs for a slave, take them to the Remote Surgery.</span></div>`; + App.UI.DOM.appendNewElement("div", frag, "Organs must be genetically matched to their host slave. To begin growing organs for a slave, take them to the Remote Surgery.", "detail"); } - return r; + return frag; }; diff --git a/src/npc/surgery/organs.js b/src/npc/surgery/organs.js deleted file mode 100644 index 1d3fe6ac61fb815eb32dab3a97eb1fa35db07b34..0000000000000000000000000000000000000000 --- a/src/npc/surgery/organs.js +++ /dev/null @@ -1,442 +0,0 @@ -/** - * Organs will usually be displayed in this order. - * If an organ is not part of this array, it will be unreachable. - * - * @type {string[]} - */ -App.Medicine.OrganFarm.organDisplayOrder = ["penis", "testicles", "scrotum", "pigTesticles", "dogTesticles", "horseTesticles", "cowTesticles", "foreskin", "prostate", "ovaries", "asexualReproOvaries", "pigOvaries", "dogOvaries", "horseOvaries", "cowOvaries", "freshOvaries", "leftEye", "rightEye", "ears", "topEars", "cochleae", "voicebox", "hair", "mpreg", "mpregPig", "mpregDog", "mpregHorse", "mpregCow"]; - -App.Medicine.OrganFarm.init = function() { - new App.Medicine.OrganFarm.Organ({ - type: "penis", name: "Penis", cost: 5000, time: 5, - canGrow: () => (V.seeDicks !== 0 || V.makeDicks === 1), - actions: [ - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Implant", healthImpact: 20, surgeryType: "addDick", - canImplant: slave => (slave.dick <= 0), - implantError: () => "this slave already has a penis", - implant: slave => { - if (slave.prostate === 0) { - slave.prostate = 1; - } - slave.dick = 2; - slave.clit = 0; - slave.foreskin = slave.dick; - } - }) - ] - }); - - new App.Medicine.OrganFarm.Organ({ - type: "foreskin", name: "Foreskin", cost: 2500, time: 5, - actions: [ - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Graft on", healthImpact: 10, surgeryType: "addForeskin", - canImplant: slave => (slave.foreskin <= 0), - implantError: slave => `This slave already has a ${slave.dick > 0 ? "foreskin" : "clitoral hood"}.`, - implant: slave => { - if (slave.dick > 0) { - slave.foreskin = slave.dick; - } else if (slave.clit > 0) { - slave.foreskin = slave.clit; - } else { - slave.foreskin = 1; - } - } - }) - ] - }); - - new App.Medicine.OrganFarm.Testicles({ - type: "testicles", name: "Testicles", ballType: "human" - }); - new App.Medicine.OrganFarm.Testicles({ - type: "pigTesticles", name: "Pig testicles", ballType: "pig" - }); - new App.Medicine.OrganFarm.Testicles({ - type: "dogTesticles", name: "Dog testicles", ballType: "dog" - }); - new App.Medicine.OrganFarm.Testicles({ - type: "horseTesticles", name: "Horse testicles", ballType: "horse" - }); - new App.Medicine.OrganFarm.Testicles({ - type: "cowTesticles", name: "Cow testicles", ballType: "cow" - }); - - new App.Medicine.OrganFarm.Organ({ - type: "scrotum", name: "Scrotum", tooltip: "requires balls for successful implantation", cost: 2500, time: 5, - dependencies: ["testicles", "pigTesticles", "dogTesticles", "horseTesticles", "cowTesticles"], - actions: [ - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Graft on", healthImpact: 10, surgeryType: "addScrotum", - canImplant: slave => (slave.scrotum <= 0 && slave.balls > 0), - implantError: slave => (slave.scrotum > 0) ? "This slave already has a scrotum." : "This slave lacks the balls necessary to accept a scrotum.", - implant: slave => { - slave.scrotum = slave.balls; - } - }) - ] - }); - - new App.Medicine.OrganFarm.Ovaries({ - type: "ovaries", name: "Ovaries", eggType: "human", pregData: "human" - }); - new App.Medicine.OrganFarm.Ovaries({ - type: "pigOvaries", name: "Pig ovaries", eggType: "pig", pregData: "pig" - }); - new App.Medicine.OrganFarm.Ovaries({ - type: "dogOvaries", - name: "Dog ovaries", - eggType: "dog", - pregData: "canineM", - }); - new App.Medicine.OrganFarm.Ovaries({ - type: "horseOvaries", - name: "Horse ovaries", - eggType: "horse", - pregData: "equine", - }); - new App.Medicine.OrganFarm.Ovaries({ - type: "cowOvaries", name: "Cow ovaries", eggType: "cow", pregData: "cow" - }); - - new App.Medicine.OrganFarm.AnalWomb({ - type: "mpreg", - name: "Anal womb and ovaries", - eggType: "human", - pregData: "human", - }); - new App.Medicine.OrganFarm.AnalWomb({ - type: "mpregPig", - name: "Anal pig womb and ovaries", - eggType: "pig", - pregData: "pig", - }); - new App.Medicine.OrganFarm.AnalWomb({ - type: "mpregDog", - name: "Anal dog womb and ovaries", - eggType: "dog", - pregData: "canineM", - }); - new App.Medicine.OrganFarm.AnalWomb({ - type: "mpregHorse", - name: "Anal horse womb and ovaries", - eggType: "horse", - pregData: "equine", - }); - new App.Medicine.OrganFarm.AnalWomb({ - type: "mpregCow", - name: "Anal cow womb and ovaries", - eggType: "cow", - pregData: "cow", - }); - - new App.Medicine.OrganFarm.Organ({ - type: "freshOvaries", name: "Younger Ovaries", - tooltip: "requires a womb for successful implantation", - cost: 10000, time: 10, - canGrow: () => (V.youngerOvaries === 1), - dependencies: ["ovaries", "pigOvaries", "dogOvaries", "horseOvaries", "cowOvaries", "mpreg", "mpregPig", "mpregDog", "mpregHorse", "mpregCow"], - actions: [ - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Implant", healthImpact: 20, surgeryType: "freshOvaries", - canImplant: s => ((s.mpreg !== 0 || s.ovaries !== 0) && s.bellyImplant === -1 && s.physicalAge < 70), - implantError: s => (s.physicalAge >= 70) ? "This slave's body is too old to handle pregnancy." : "This slave lacks a viable womb.", - implant: s => { - if (s.ovaryAge >= 47) { - s.ovaryAge = 45; - } else { - s.ovaryAge = -2; // It shouldn't matter if this goes negative as it is just a signal for menopause to occur. - } - if (s.preg < 0) { - s.preg = 0; - } - if (s.pubertyXX === 0 && s.physicalAge >= V.fertilityAge) { - if (V.precociousPuberty === 1) { - s.pubertyAgeXX = s.physicalAge + 1; - } else { - s.pubertyXX = 1; - } - } - } - }) - ] - }); - - new App.Medicine.OrganFarm.Organ({ - type: "asexualReproOvaries", name: "Asexual reproduction modification", - tooltip: "requires existing ovaries for successful implantation", - cost: 10000, time: 10, - canGrow: () => (V.asexualReproduction === 1), - dependencies: ["ovaries", "pigOvaries", "dogOvaries", "horseOvaries", "cowOvaries", "mpreg", "mpregPig", "mpregDog", "mpregHorse", "mpregCow"], - actions: [ - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Implant", healthImpact: 20, surgeryType: "asexualReproOvaries", - canImplant: s => (s.mpreg !== 0 || s.ovaries !== 0), - implantError: () => "This slave lacks ovaries.", - implant: s => { - if (s.preg < 0) { - s.preg = 0; - } - s.eggType = "human"; - s.pregData = clone(setup.pregData.human); - if (s.pubertyXX === 0 && s.physicalAge >= V.fertilityAge) { - if (V.precociousPuberty === 1) { - s.pubertyAgeXX = s.physicalAge + 1; - } else { - s.pubertyXX = 1; - } - } - s.ovaImplant = "asexual"; - } - }) - ] - }); - - new App.Medicine.OrganFarm.Organ({ - type: "prostate", name: "Prostate", cost: 5000, time: 5, - actions: [ - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Implant", healthImpact: 20, surgeryType: "addProstate", - canImplant: s => (s.prostate === 0), - implantError: () => "This slave already has a prostate.", - implant: s => { - s.prostate = 1; - } - }) - ] - }); - - new App.Medicine.OrganFarm.Organ({ - type: "leftEye", name: "Left Eye", cost: 5000, time: 10, - tooltip: s => getLeftEyeVision(s) === 2 ? "would not improve this slave" : "", - actions: [ - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Implant", healthImpact: 10, surgeryType: "newEyes", - canImplant: s => (getLeftEyeVision(s) === 0 && getBestVision(s) !== 0 && getLeftEyeType(s) !== 2), - implantError: s => getLeftEyeVision(s) !== 0 ? "Slave has a working left eye." : "", - implant: s => { - eyeSurgery(s, "left", "normal"); - } - }), - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Implant", healthImpact: 10, surgeryType: "unblind", - canImplant: s => (getBestVision(s) === 0 && getLeftEyeType(s) !== 2), - implantError: () => "", - implant: s => { - eyeSurgery(s, "left", "normal"); - } - }), - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Replace", tooltip: "replace the existing ocular implant with an organic eye", - healthImpact: 10, surgeryType: "newEyes", autoImplant: false, - canImplant: s => (getLeftEyeType(s) === 2), - implantError: () => "", - implant: s => { - eyeSurgery(s, "left", "normal"); - } - }) - ] - }); - new App.Medicine.OrganFarm.Organ({ - type: "rightEye", name: "Right Eye", cost: 5000, time: 10, - tooltip: s => getRightEyeVision(s) === 2 ? "would not improve this slave" : "", - actions: [ - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Implant", healthImpact: 10, surgeryType: "newEyes", - canImplant: s => (getRightEyeVision(s) === 0 && getBestVision(s) !== 0 && getRightEyeType(s) !== 2), - implantError: s => getRightEyeVision(s) !== 0 ? "Slave has a working right eye." : "", - implant: s => { - eyeSurgery(s, "right", "normal"); - } - }), - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Implant", healthImpact: 10, surgeryType: "unblind", - canImplant: s => (getBestVision(s) === 0 && getRightEyeType(s) !== 2), - implantError: () => "", - implant: s => { - eyeSurgery(s, "right", "normal"); - } - }), - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Replace", tooltip: "replace the existing ocular implant with an organic eye", - healthImpact: 20, surgeryType: "newEyes", autoImplant: false, - canImplant: s => (getRightEyeType(s) === 2), - implantError: () => "", - implant: s => { - eyeSurgery(s, "right", "normal"); - } - }) - ] - }); - - new App.Medicine.OrganFarm.Organ({ - type: "ears", name: "Normal Ears", cost: 1000, time: 2, - actions: [ - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Attach", healthImpact: 15, surgeryType: "earMinor", - canImplant: s => (s.earShape === "none"), - implantError: () => "This slave already has ears.", - implant: s => { - s.earShape = "normal"; - if (s.hears === -1) { - s.hears = 0; - } - } - }), - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Replace", tooltip: "replace current ears with normal human ears", - healthImpact: 20, surgeryType: "earMinor", autoImplant: false, - canImplant: s => (s.earShape !== "normal"), - implantError: () => "This slave already has normal ears.", - implant: s => { - s.earShape = "normal"; - } - }) - ] - }); - new App.Medicine.OrganFarm.Organ({ - type: "topEars", name: "Top Ears", cost: 1000, time: 2, - canGrow: () => (V.surgeryUpgrade >= 1), - actions: [ - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Attach", healthImpact: 10, surgeryType: "earMinor", - canImplant: s => (s.earT === "none"), - implantError: () => "This slave already has ears at the top of the head.", - implant: s => { - s.earT = "normal"; - s.earTColor = "hairless"; - } - }), - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Replace", tooltip: "replace current top ears with normal ears", - healthImpact: 20, surgeryType: "earMinor", autoImplant: false, - canImplant: s => (s.earT !== "normal"), - implantError: () => "This slave already has normal ears at the top of the head.", - implant: s => { - s.earT = "normal"; - s.earTColor = "hairless"; - } - }) - ] - }); - - new App.Medicine.OrganFarm.Organ({ - type: "cochleae", name: "Cochleae", cost: 8000, time: 6, - actions: [ - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Implant", healthImpact: 20, surgeryType: "undeafen", - canImplant: s => (s.hears <= -2 && s.earImplant === 0), - implantError: () => "This slave already has working ears.", - implant: s => { - s.hears = 0; - } - }), - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Replace", tooltip: "remove cochlear implants before implanting organic cochleae", - healthImpact: 20, surgeryType: "newEars", autoImplant: false, - canImplant: s => (s.earImplant === 1), - implantError: () => "", - implant: s => { - s.hears = 0; - s.earImplant = 0; - } - }) - ] - }); - - new App.Medicine.OrganFarm.Organ({ - type: "voicebox", name: "Vocal Cords", cost: 5000, time: 5, - actions: [ - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Implant", healthImpact: 10, surgeryType: "restoreVoice", - canImplant: s => (s.voice === 0 && s.electrolarynx === 0), - implantError: () => "This slave is not mute.", - implant: s => { - if (s.ovaries === 1 && s.hormoneBalance >= 200) { - s.voice = 3; - } else if (s.balls > 0 || s.hormoneBalance < -20) { - s.voice = 1; - } else { - s.voice = 2; - } - } - }), - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Replace", tooltip: "remove electrolarynx and implant organic vocal cords", - healthImpact: 20, surgeryType: "newVoice", autoImplant: false, - canImplant: s => (s.electrolarynx === 1), - implantError: () => "", - implant: s => { - s.electrolarynx = 0; - if (s.ovaries === 1 && s.hormoneBalance >= 200) { - s.voice = 3; - } else if (s.balls > 0 || s.hormoneBalance < -20) { - s.voice = 1; - } else { - s.voice = 2; - } - } - }) - ] - }); - - new App.Medicine.OrganFarm.Organ({ - type: "hair", name: "Hair Follicles", cost: 500, time: 2, displayMultipleActions: true, - actions: [ - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Scalp", healthImpact: 10, surgeryType: "restoreHairHead", - canImplant: s => (s.bald !== 0), - implantError: () => "This slave already has hair.", - implant: s => { - s.bald = 0; - s.hLength = 1; - s.hStyle = "neat"; - s.hColor = getGeneticHairColor(s); - } - }), - /* So apparently hair is tracked via the .earTColor variable with no differential between possible hair origin. Not worth the variable, currently. - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Ears", healthImpact: 5, - surgeryType: "addHairEarsH", autoImplant: false, - canImplant: s => (s.earTShape !== "normal"), - implantError: "", - implant: s => { - s.earTColor = getGeneticHairColor(s); - } - }), - */ - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Brow", healthImpact: 5, - surgeryType: "restoreHairBrow", autoImplant: false, - canImplant: s => (s.eyebrowHStyle === "bald"), - implantError: () => "", - implant: s => { - s.eyebrowHStyle = "natural"; - s.eyebrowFullness = "natural"; - s.eyebrowHColor = getGeneticHairColor(s); - } - }), - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Axillary", healthImpact: 5, - surgeryType: "restoreHairPits", autoImplant: false, - canImplant: s => (s.underArmHStyle === "bald" || s.underArmHStyle === "hairless"), - implantError: () => "", - implant: s => { - s.underArmHStyle = "bushy"; - s.underArmHColor = getGeneticHairColor(s); - } - }), - new App.Medicine.OrganFarm.OrganImplantAction({ - name: "Pubic", healthImpact: 5, - surgeryType: "restoreHairPubes", autoImplant: false, - canImplant: s => (s.pubicHStyle === "bald" || s.pubicHStyle === "hairless"), - implantError: () => "", - implant: s => { - s.pubicHStyle = "very bushy"; - s.pubicHColor = getGeneticHairColor(s); - } - }) - ] - }); -}; diff --git a/src/pregmod/organFarm.tw b/src/pregmod/organFarm.tw index 5caf33806cf54a2b60825b9182cdfcf71b339b6e..f4ff696b9377d7441b1695dee5a26a7cc4c44e91 100644 --- a/src/pregmod/organFarm.tw +++ b/src/pregmod/organFarm.tw @@ -115,7 +115,7 @@ <h2>Organ Production</h2> <p> - <<= App.Medicine.OrganFarm.currentlyGrowing()>> + <<includeDOM App.Medicine.OrganFarm.currentlyGrowing()>> </p> <h2>Future Societies Research</h2> diff --git a/src/uncategorized/multiImplant.tw b/src/uncategorized/multiImplant.tw index 3f07842a777d8509ec79a340b279a159d8719253..5e377d7b3ca713cef14eb5d3b8a6d11c26979f80 100644 --- a/src/uncategorized/multiImplant.tw +++ b/src/uncategorized/multiImplant.tw @@ -1,62 +1,6 @@ :: Multiple Organ Implant [nobr] -You head down to your -<<if $surgeryUpgrade == 1>> - heavily upgraded and customized -<</if>> -remote surgery and start having the slaves with -<<if ($completedOrgans.length > 0) && ($adjustProstheticsCompleted > 0)>> - organs or prosthetics -<<elseif ($completedOrgans.length > 1)>> - organs -<<elseif ($adjustProstheticsCompleted > 1)>> - prosthetics -<</if>> -that are ready be sent down. - -<h1>Implant Organs</h1> - -<<set _F = App.Medicine.OrganFarm>> -<<for _i = 0; _i < $slaves.length; _i++>> - <<set $AS = $slaves[_i].ID>> - <<set _sortedOrgans = _F.getSortedOrgans(getSlave($AS))>> - <<if _sortedOrgans.length === 0>><<continue>><</if>> - - <h2><<= getSlave($AS).slaveName>></h2> - - <<for _k = 0; _k < _sortedOrgans.length; _k++>> - <h3><<print _F.Organs[_sortedOrgans[_k]].name>></h3> - <<set _actions = _F.Organs[_sortedOrgans[_k]].implantActions>> - <<set _manual = false, _success = false, _break = false>> - <<for _l = 0; _l < _actions.length; _l++>> - <<if !_actions[_l].autoImplant>> - <<if _actions[_l].canImplant(getSlave($AS))>> - <<set _manual = true>> - <</if>> - <<continue>> - <</if>> - <<if !_actions[_l].canImplant(getSlave($AS))>> - <<set _error = _actions[_l].implantError(getSlave($AS))>> - <<if _error !== "">> - @@.red;ERROR: <<print _error>>@@<br> - <</if>> - <<elseif getSlave($AS).health.health - _actions[_l].healthImpact < -75>> - Estimated health impact too high, skipping further surgeries. - <<set _break = true>> - <<break>> - <<else>> - <<run App.Medicine.OrganFarm.implant(getSlave($AS), _sortedOrgans[_k], _l)>> - <<includeDOM App.UI.SlaveInteract.surgeryDegradation(getSlave($AS))>><br><br> - <<set _success = true>> - <</if>> - <</for>> - <<if _break>><<break>><</if>> - <<if !_success && _manual>> - //Cannot implant <<print _F.Organs[_sortedOrgans[_k]].name.toLowerCase()>> automatically, try implanting manually in the remote surgery.// - <</if>> - <</for>> -<</for>> - +<<includeDOM App.UI.multiImplant()>> <h1>Implant prosthetics</h1> diff --git a/src/zz1-last/init.js b/src/zz1-last/init.js index 6e14d81e03be8bf26a0d685622f62188440731ed..4c7ae0dde773797c8114151db19f787b4d7619fe 100644 --- a/src/zz1-last/init.js +++ b/src/zz1-last/init.js @@ -1,4 +1,3 @@ -App.Medicine.OrganFarm.init(); App.Art.cacheArtData(); App.Corporate.Init();