diff --git a/compile.sh b/compile.sh index bede064779d42c0a1ca7dd21e4c9093b541de923..b3b903a7461b3bb9545bccc3ba8a303799260ab2 100755 --- a/compile.sh +++ b/compile.sh @@ -1,6 +1,7 @@ #!/bin/bash output=/dev/stdout +name=FC_pregmod # displays help text function displayHelp() { @@ -16,6 +17,7 @@ Options: -t, --themes Generate theme files -m, --minify Minify output files --ci CI mode + -f, --f Final file name HelpText } @@ -77,7 +79,7 @@ function compile() { fi fi - file="bin/FC_pregmod.html" + file="bin/${name}.html" # Find and insert current commit if [[ "$ci" ]]; then @@ -85,7 +87,7 @@ function compile() { elif [[ -d .git ]]; then COMMIT=$(git rev-parse --short HEAD) if [[ "$usehash" ]]; then - file="bin/FC_pregmod_${COMMIT}.html" + file="bin/${name}${COMMIT}.html" fi fi if [[ "$minify" ]]; then @@ -158,6 +160,10 @@ else --ci) ci="true" ;; + -f | --file) + name=$2 + shift + ;; *) echoError "Unknown argument $1." displayHelp diff --git a/devTools/PreCompile.sh b/devTools/PreCompile.sh deleted file mode 100755 index 248695a23d80fe295aac79642a6ead3109d96943..0000000000000000000000000000000000000000 --- a/devTools/PreCompile.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/ksh -mega-login $1 $2 #U=$1 P=$2 rDir=$3 lDir=$4 Reqs:MEGAcmd,git -while true;do gen=0;cd $4; - if [[ `echo $?` -gt 0 ]];then mkdir -p $4&&git clone -q --depth 1 https://gitgud.io/pregmodfan/fc-pregmod.git $4&&cd $4 - if [[ ! `mega-ls $3|cut -c21-24|paste -sd,` =~ `git log|head -1|cut -c8-11` ]];then gen=1;fi #stackoverflow.com/a/15394738 - fi - git fetch -q && if [ `git rev-list ...origin|wc -l` -gt 0 ];then git pull -q&&gen=1;fi #stackoverflow.com/a/17192101 - if [[ $gen > 0 ]];then rm bin/*;./compile.sh -q&&cd bin/ - mv *.h* FC-`git log -1 --format=%cd --date=format:%m-%d-%Y-%H-%M`-`git log|head -1|cut -c8-11`.html - mega-put -c *.h* $3&&mega-rm $3`mega-ls $3|head -n 1` - fi -clear;sleep 15m;done \ No newline at end of file diff --git a/devTools/switchBranch.sh b/devTools/switchBranch.sh index bca3f4fb8e95acb059433eb9d912d747dd9ebfb2..3df09c640c616f225f6abc326940861441aeb615 100644 --- a/devTools/switchBranch.sh +++ b/devTools/switchBranch.sh @@ -1,21 +1,109 @@ +#!/bin/bash # git push --set-upstream origin origin/pregmod-master / git checkout -b pregmod-master --track origin/pregmod-master +mainBranch="pregmod-master" previousBranch="Not found" + +function displayHelp() { +cat <<HelpText +Usage: $0 [OPTION]... +Always pushes commit(s) / the current branch +Order of operation: new (if enabled) -> push (if not closed after creating a new branch) -> sync (if enabled) -> change branch (if enabled) + -> delete previous branch (if enabled) + +Options: + -s, --sync : Sync upstream/$mainBranch + -d, --delete : Delete previous branch + -m, --move : Change current branch to either; + supplied / previous, the choice currently + follows the flow as written i.e supplied -> previous + -b, --branch X : Set supplied branch to X + -c, --create Y : Create the new branch Y + -h, --help : Show this help text + + e.g. + Before: + git status + On branch XYZ + Your branch is ahead of 'origin/XYZ' by 5 commits. + + git branch --list + * XYZ + $mainBranch + ..... + + During: + $0 -b $mainBranch -c -d + Branches: Supplied ($mainBranch) / previous (XYZ) + Sync Master? Y/N: N + + After: + git branch --list + * $mainBranch + ..... + + All five new commits for branch XYZ were pushed prior to the switch over and + then afterwards the local copy of branch XYZ was deleted. +HelpText +} + if [[ $(git rev-parse --quiet --abbrev-ref @{-1} 2>/dev/null) && $? -eq 0 ]]; then previousBranch=$(git rev-parse --abbrev-ref @{-1}) fi -read -p "Push commits/branch? Y/N: " commit -read -p "Sync Master? Y/N: " sync -read -p "Switch to supplied branch ($1) / previous ($previousBranch)? Y/N: " switch +if [[ "$#" -eq 0 ]]; then echo "For more options see $0 -h."; fi +while [[ "$1" ]]; do + case $1 in + -s | --sync) + sync="true" + ;; + -d | --delete) + delete="true" + ;; + -m | --move) + change="true" + ;; + -b | --branch) + tgtBranch=$2 + shift + ;; + -c | --create) + newBranch=$2 + shift + ;; + -h | --help) + displayHelp + exit 0 + ;; + *) + echo "Unknown argument $1." + displayHelp + exit 1 + ;; + esac + shift +done + +if [[ "$newBranch" ]]; then + if [[ $(git stash show 2>/dev/null | echo $?) -gt 0 ]]; then git stash save *; fi + git checkout -qb $newBranch + if [[ $(git stash show 2>/dev/null | echo $?) -gt 0 ]];then + git stash show + read -p "Pop the latest stash? (y/n): " stash + [ "$stash" == "y" ] && git stash pop; + fi + read -p "Exit? (y/n): " exit + [ "$exit" == "y" ] && exit; +fi + +git push -q 2>/dev/null || git push -qu "origin" HEAD 1>/dev/null +echo "Branches: Supplied ($tgtBranch) / previous ($previousBranch)" -if [[ $commit == "Y" ]]; then - git push -q 2>/dev/null || git push -qu origin $(git rev-parse --abbrev-ref HEAD) 1>/dev/null +if [[ "$sync" ]]; then + if [[ $(git stash show 2>/dev/null | echo $?) -gt 0 ]]; then git stash save *; fi + git checkout -q origin/$mainBranch && git reset --hard upstream/$mainBranch -q && git push -q && git checkout -q @{-1} + if [[ $(git stash show 2>/dev/null | echo $?) -gt 0 ]]; then git stash pop; fi fi -if [[ $sync == "Y" ]]; then - git stash save * && git checkout -q pregmod-master && git reset --hard upstream/pregmod-master -q && git push -q && git checkout -q @{-1} && git stash pop +if [[ "$change" ]]; then + if [[ "$tgtBranch" ]]; then git checkout -q origin/$tgtBranch; else git checkout -q @{-1}; fi fi -if [[ $switch == "Y" ]]; then - if [[ -n $1 ]];then git checkout -q $1; else git checkout -q @{-1}; fi -fi -read -p "Delete previous branch ($(git rev-parse --abbrev-ref @{-1}))? Y/N: " del -if [[ $del == "Y" ]]; then git branch -qD @{-1}; fi +if [[ "$delete" ]]; then git branch -qD @{-1}; fi diff --git a/devTools/updateTool.sh b/devTools/updateTool.sh index e2a3cb46c45c8f75e6ef7c4bb30ff36529fc3bd9..1eef102895c05b7231cd0d2e1ab6e8225eaf214f 100644 --- a/devTools/updateTool.sh +++ b/devTools/updateTool.sh @@ -1,8 +1,30 @@ -git fetch upstream -q -check=$(git rev-list HEAD..upstream/pregmod-master) # https://adamj.eu/tech/2020/01/18/a-git-check-for-missing-commits-from-a-remote/ -if [[ $check ]];then echo "Updated: Yes"; else echo "Updated: No"; fi -if [[ ($1 || $check) && $(git rev-parse --abbrev-ref HEAD) = "pregmod-master" ]];then - git reset --hard upstream/pregmod-master -q -elif [[ ($1 || $check) && $(git rev-parse --abbrev-ref HEAD) != "pregmod-master" ]]; then - git merge upstream/pregmod-master -q +#!/bin/bash +repo=upstream +branch=pregmod-master +while [[ "$1" ]]; do + case $1 in + -r | --repo) + repo=$2 + shift + ;; + -b | --branch) + branch=$2 + shift + ;; + *) + echo "Unknown argument $1." + displayHelp + exit 1 + ;; + esac + shift +done + +git fetch $repo -q +check=$(git rev-list HEAD..$repo/$branch) # https://adamj.eu/tech/2020/01/18/a-git-check-for-missing-commits-from-a-remote/ +if [[ $check && $(git rev-parse --abbrev-ref HEAD) = "$branch" ]]; then + git reset --hard $repo/$branch -q +elif [[ $check && $(git rev-parse --abbrev-ref HEAD) != "$branch" ]]; then + git merge $repo/$branch -q fi +echo "Updated: $(if [ $check ]; then echo "Yes" && exit 1; else echo "No" && exit 0; fi)" # stackoverflow.com/a/73539272 diff --git a/devTools/upload.sh b/devTools/upload.sh new file mode 100755 index 0000000000000000000000000000000000000000..0c2ff82689786842cee2fc38537da33184ebea74 --- /dev/null +++ b/devTools/upload.sh @@ -0,0 +1,98 @@ +#!/bin/bash +email=xyz1256@corp.com +password=12345678 +local=fc/ +remote=FC/ +gen=0; +runstep=0 +hash=$(git log --oneline|head -n 1|cut -c1-7) + +function displayHelp() { +cat <<HelpText +Packages required: git, megacmd + +Usage: $0 [OPTION]... +Options: + -s, --step X : Step # to manually execute e.g. 1 to run "Applying WebGL decensor patch." + -e, --email X : Set MEGA email to X. Default: $email + -p, --password X : Set MEGA password to X. Default: $password + -l, --local X : Set local (File System) folder/directory to X. Default: $local + -r, --remote X : Set remote (MEGA) folder/directory to X. Default: $remote + -h, --help : Show this help text +HelpText +} + +if [[ "$#" -eq 0 ]]; then echo -e "For more options see $0 -h.\n"; fi +while [[ "$1" ]]; do + case $1 in + -s | --step) + runstep=$2 + shift + ;; + -e | --email) + email=$2 + shift + ;; + -p | --password) + password=$2 + shift + ;; + -l | --local) + local=$2 + shift + ;; + -r | --remote) + remote=$2 + shift + ;; + -h | --help) + displayHelp + exit 0 + ;; + *) + echo "Unknown argument $1." + displayHelp + exit 1 + ;; + esac + shift +done + +find $local > /dev/null +if [[ `echo $?` > 0 ]]; then + git clone -q https://gitgud.io/pregmodfan/fc-pregmod.git --depth 1 $local + if [[ ! `mega-ls $remote|grep .html|cut -c21-29|paste -sd,` =~ $hash ]];then + gen=1; + fi # stackoverflow.com/a/15394738 +fi +cd $local + +find js/000-browserSupport.js > /dev/null +if [[ `echo $?` > 0 ]]; then + echo "creating file to work with browsers that do not support globalThis." + echo "const globalThis = eval.call(undefined, 'this');" > js/000-browserSupport.js +fi + +git fetch -q && if [[ $runstep == 0 && $(./devTools/updateTool.sh -r origin) && `echo $?` > 0 ]]; then + git reset --hard HEAD -q && git pull -q && gen=1; +fi # stackoverflow.com/a/17192101 + +if [[ $gen > 0 || $runstep == 1 ]]; then + echo "Applying WebGL decensor patch." + sed -i '1,/p.applyPanty = true/ s/p.applyPanty = true/p.applyPanty = false/' src/art/webgl/art.js + sed -i 's/p.underage = slave.age < 18 || slave.visualAge < 18/p.underage = false/' src/art/webgl/art.js + sed -i 's#p.height = Math.max(slave.height, 140); // clamp underage#p.height = slave.height;#' src/art/webgl/art.js + sed -i 's#morphs.push(["physicalAgeYoung", -(Math.max(slave.visualAge, 18)-20)/10]) // clamp underage#morphs.push(["physicalAgeYoung", -(slave.visualAge-20)/10])#' src/art/webgl/art.js +fi + +if [[ $gen > 0 || $runstep == 2 ]]; then + rm bin/*.html > /dev/null 2>&1 ; ./compile.sh -q -m -f preCompiled-FC-`git log -1 --format=%cd --date=format:%Y-%m-%d-%H-%M`-$hash +fi + +mega-login $email $password > /dev/null 2>&1 +if [[ $gen > 0 || $runstep == 3 ]]; then mega-put -c bin/*.html $remote; fi +if [[ $gen > 0 || $runstep == 4 ]]; then + if [[ `mega-ls $remote|grep .html|grep -v revert-RA|wc -l` > 2 ]]; then + mega-rm $remote`mega-ls $remote|grep .html|grep -v revert-RA|head -n 1` + fi +fi diff --git a/js/003-data/drugs/002-moddedDrugsData.js b/js/003-data/drugs/002-moddedDrugsData.js index c1769b6d1c31febe2975c7efe34bf7c608bf4a38..3cd446b65ac765be9acf52cac4e2c83b527157b4 100644 --- a/js/003-data/drugs/002-moddedDrugsData.js +++ b/js/003-data/drugs/002-moddedDrugsData.js @@ -1,26 +1,13 @@ //A new array is added to store the name and types of new drugs. Mods would add new objects to this array. -App.Mods.Drugs = []; -/*This array would contain objects, each would look like this: -{ - name: "hip enhancer", - text: "Hip Enhancer", - type: "Structural", - enable: function (slave) { - if (slave.hips < 2) return true; - else return "Hips are too wide"; - }, - effect: function(slave) { - const { he, him, his, himself, He, His } = getPronouns(slave); - if (slave.hips >= 2) { - slave.drugs = "no drugs"; - return ` ${His} hips is already as wide is possible, <span class="yellow">${his} drug regimen has been ended.</span>`; - } else { - slave.hips++; - return ` The hip enhancer <span class="lime">widens ${his} hip</span>.`; - } - } -} -/* This object contains all data of the new drug, note: -The "enable" function returns true if the drug should be allowed, or returns a string of the reason it isn't allowed. -The "type" can be any string, as to allow custom drug categories in the UI. -*/ +App.Mods.Drugs.list = []; +//See mods/custom drugs.md for documentation + +//An optional function to act as the middle man between the user and App.Mods.Drugs.list, to add optional parameters and for potential future compatibility purposes. +App.Mods.Drugs.add = function (...drugs) { + drugs.forEach(drug => { + drug.isSlaveDrug ??= true; + drug.isPCDrug ??= false; + drug.isConsumerGrade ??= false; + App.Mods.Drugs.list.push(drug); + }); +}; \ No newline at end of file diff --git a/js/003-data/gameVariableData.js b/js/003-data/gameVariableData.js index 09941ce0880df488a1785cf595e9eb594d5dfe74..42f05255f653cc801abf427e3aba014a528378bd 100644 --- a/js/003-data/gameVariableData.js +++ b/js/003-data/gameVariableData.js @@ -1247,8 +1247,6 @@ App.Data.resetOnNGPlus = { huskSlave: null, huskSlaveOrdered: 0, - targetAge: 18, // non-vanilla shit - /* Job Fulfillment Center */ JFC: { /** @type {FC.Bool} */ diff --git a/js/rulesAssistant/conditionEvaluation.js b/js/rulesAssistant/conditionEvaluation.js index ab3cc47e65f66653426b140d748851c45e77ed5d..8c6539b26d04e5b695b78b6c83f3b4a729daea9d 100644 --- a/js/rulesAssistant/conditionEvaluation.js +++ b/js/rulesAssistant/conditionEvaluation.js @@ -589,6 +589,11 @@ App.RA.Activation.populateGetters = function() { description: "Side effects from drug use. If greater than 10 will have negative consequences.", val: c => c.slave.chem }); + gm.addNumber("addict", { + name: "Aphrodisiac Addiction", + description: "No addiction: 0, Minor addiction: 1-2, Serious addiction: 3 and above", + val: c => c.slave.addict + }); gm.addNumber("boobs", { name: "Breasts", description: "0-299: Flat, 300-399: A-cup, 400-499: B-cup, 500-649: C-cup, 650-799: D-cup, 00-999: DD-cup, " + diff --git a/mods/custom drugs.md b/mods/custom drugs.md new file mode 100644 index 0000000000000000000000000000000000000000..9d7870a7b2a2d4aaeab2205ce9f3bdf99626a0f0 --- /dev/null +++ b/mods/custom drugs.md @@ -0,0 +1,69 @@ +# Custom Drugs + +To add custom drugs through modding, pass object(s) with the following properties to the `App.Mods.Drug.add` function. More than one drug can be added at a time by using multiple arguments. + +## Custom Drug Object Properties + +- `name` (String): The name of the drug, should be unique(however a PC and a slave drug under the same name will be fine) and not conflict with existing drugs. This is displayed in menus. +- `text` (String): The text used in the link to select the drug. Typically the first letter is in upper case. +- `type` (String): The category of the drug, used in the slave interaction menu. Can be an existing vanilla category(`Lips`, `Breasts`, `Nipples`, `Butt`, `Dick`/`Clit`(Will change automatically depending on slave genital type), `Fertility`, `Hormoes`, `Psych`, `Misc`), or entirely new. Not required for PC drugs. +- `isPCDrug` (Boolean, optional): If the drug is for PC instead of slaves, default to `false`. +- `isConsumerGrade` (Boolean, optional): Lists the drug as consumer grade in manage personal affairs if true, other wise listed as slave grade, default to `false`. Only used is the drug is for PC. +- `available` (Function → *boolean*): If the drug should be displayed at all. The slave object will be passed as the first parameter. +- `enable` (Function → true or *string*): If the drug link should be enabled. The slave object will be passed as the first parameter. If the drug is allowed, return `true`. If not, return a string, which will be displayed to the player as a tool tip. +- `effect` (Function → *string* or *object*): The effect of the drug. The slave object will be passed as the first parameter. The returned string will be displayed in end week report. + +## Example: +```js +App.Mods.Drugs.add( + { + name: "hip enhancer", + text: "Hip enhancer", + type: "Structural", + available: function (slave) { + return slave.indentureRestrictions < 2; + }, + enable: function (slave) { + //Disable if the slave's hip is already very wide or wider. + if (slave.hips < 2) return true; + else return "Hips are already too wide"; + }, + effect: function (slave) { + //Get the pronouns of the slaves to be used in end week report. + const { he, him, his, himself, He, His } = getPronouns(slave); + if (slave.hips >= 2) { + //If the slave's hips is already very wide, stop the drug regimen, notify in end week report. + slave.drugs = "no drugs"; + return ` ${His} hips is already as wide is possible, <span class="yellow">${his} drug regimen has been ended.</span>`; + } else { + //If not, widen hips and notify in end week report. + slave.hips++; + return ` The hip enhancer <span class="lime">widens ${his} hip</span>.`; + } + } + }, + /* More than one drug can be added at a time */ + { + //Drug name should be unique, but two drug with identical name is okay if one is for PC and one is for slaves. + name: "hip enhancer", + text: "Hip enhancer", + //PC Drugs do not require type + isPCDrug: true, + isConsumerGrade: true, + available: () => true, + enable: function (slave) { + if (slave.hips < 2) return true; + else return "Your hips are already too wide"; + }, + effect: function (slave) { + if (slave.hips >= 2) { + slave.drugs = "no drugs"; + return "Your hips is already as wide is possible, <span class=\"yellow\">your drug regimen has ended.</span>"; + } else { + slave.hips++; + return "The hip enhancer <span class=\"lime\">widens your hip</span>."; + } + } + } +); +``` \ No newline at end of file diff --git a/src/002-config/fc-version.js b/src/002-config/fc-version.js index 21d48c2c55db3c62da3080cc50b56c2aedc61b57..3e4661e463b89db0703ca061ed5fb03374e63338 100644 --- a/src/002-config/fc-version.js +++ b/src/002-config/fc-version.js @@ -2,5 +2,5 @@ App.Version = { base: "0.10.7.1", // The vanilla version the mod is based off of, this should never be changed. pmod: "4.0.0-alpha.25", commitHash: null, - release: 1195, // When getting close to 2000, please remove the check located within the onLoad() function defined at line five of src/js/eventHandlers.js. + release: 1196, // When getting close to 2000, please remove the check located within the onLoad() function defined at line five of src/js/eventHandlers.js. }; diff --git a/src/005-passages/interactPassages.js b/src/005-passages/interactPassages.js index 23695dd9e171d3c7db6290b4392dda96910bd9e4..ed27f32e8c1ebbd27a518a0d492b1db259a6571c 100644 --- a/src/005-passages/interactPassages.js +++ b/src/005-passages/interactPassages.js @@ -396,3 +396,27 @@ new App.DomPassage("Dinner Party Execution", return App.Mods.DinnerParty.Execution(); } ); + +new App.DomPassage("Inspect Tank Settings", + () => { + V.nextButton = "Continue"; + V.nextLink = "Incubator"; + return App.UI.inspectTankSettings(false); + }, ["jump-from-safe"] +); + +new App.DomPassage("Inspect Fetus Tank Settings", + () => { + V.nextButton = "Continue"; + V.nextLink = "Analyze Pregnancy"; + return App.UI.inspectTankSettings(true); + }, ["jump-from-safe"] +); + +new App.DomPassage("Inspect PC Fetus Tank Settings", + () => { + V.nextButton = "Continue"; + V.nextLink = "Analyze PC Pregnancy"; + return App.UI.inspectTankSettings(true, true); + }, ["jump-from-safe"] +); \ No newline at end of file diff --git a/src/Mods/SecExp/buildings/propagandaHub.js b/src/Mods/SecExp/buildings/propagandaHub.js index 78cb7184f6498c294bc7fd8817a49337620ecaea..de3ae88dc67493ed73bea4ed9324d45b1dc45ec6 100644 --- a/src/Mods/SecExp/buildings/propagandaHub.js +++ b/src/Mods/SecExp/buildings/propagandaHub.js @@ -1,4 +1,4 @@ -App.Mods.SecExp.propHub = (function() { +App.Mods.SecExp.propHub = (function () { return { init, GUI @@ -31,7 +31,7 @@ App.Mods.SecExp.propHub = (function() { App.Events.addParagraph(node, []); const hasOffice = V.SecExp.buildings.propHub.recruiterOffice === 1; node.append(App.UI.DOM.link( - `${hasOffice ? "Revoke" : "Grant"} ${SlaveFullName(S.Recruiter)} office privileges.`, + `${hasOffice ? "Deny" : "Grant"} ${SlaveFullName(S.Recruiter)} office privileges`, () => { V.SecExp.buildings.propHub.recruiterOffice = (hasOffice ? 0 : 1); App.UI.reload(); @@ -43,7 +43,7 @@ App.Mods.SecExp.propHub = (function() { if (V.SecExp.buildings.propHub.upgrades.campaign === 0) { node.append(makeLink( - "Set up a propaganda campaign to align your citizens with your goals", + `Set up a propaganda campaign to align your citizens with your goals`, 5000, "Will provide the focused resource each week, but will cost reputation in upkeep.", "campaign" @@ -71,7 +71,7 @@ App.Mods.SecExp.propHub = (function() { node.append("Focus on: ", App.UI.DOM.generateLinksStrip(r)); r = ["You are concentrating your propaganda efforts towards"]; - switch(V.SecExp.buildings.propHub.focus) { + switch (V.SecExp.buildings.propHub.focus) { case "social engineering": r.push("increasing the acceptance of your chosen future societies."); break; @@ -89,21 +89,21 @@ App.Mods.SecExp.propHub = (function() { if (V.SecExp.buildings.propHub.upgrades.campaign < 5) { App.UI.DOM.appendNewElement("div", node, makeLink( - "Invest more resources into the project to increase its effectiveness", + `Invest more resources into the project to increase its effectiveness`, 5000, "Will provide more of the focused resource each week but increase reputation upkeep.", "campaign", true )); } else { - App.UI.DOM.appendNewElement("div", node, "You upgraded your propaganda machine to its limits."); + App.UI.DOM.appendNewElement("div", node, "You have upgraded your propaganda machine to its limits."); } } App.Events.addParagraph(node, []); if (V.SecExp.buildings.propHub.upgrades.miniTruth === 0) { node.append(makeLink( - "Set up the authenticity department", + `Set up the authenticity department`, 5000, "Will provide authority and unlock special upgrades, but will increase upkeep.", "miniTruth", @@ -234,7 +234,7 @@ App.Mods.SecExp.propHub = (function() { return node; - function makeLink(text, price, note, type, applyHacking=true, message=null) { + function makeLink(text, price, note, type, applyHacking = true, message = null) { const r = new DocumentFragment(); r.append(App.UI.DOM.link(text, () => { diff --git a/src/Mods/SecExp/events/secExpSmilingMan0.js b/src/Mods/SecExp/events/secExpSmilingMan0.js index 6a1253f641268dbfa8cb43fbe1c54d7b97d43fbd..76e6c8cd87307acdc088f140b4136dc6f502a4a3 100644 --- a/src/Mods/SecExp/events/secExpSmilingMan0.js +++ b/src/Mods/SecExp/events/secExpSmilingMan0.js @@ -58,6 +58,5 @@ App.Events.secExpSmilingMan0 = class secExpSmilingMan0 extends App.Events.BaseEv App.Events.queueEvent(3, new App.Events.secExpSmilingMan1()); return `You do not consider this individual a threat.`; } - } }; diff --git a/src/Mods/SecExp/events/secExpSmilingMan1.js b/src/Mods/SecExp/events/secExpSmilingMan1.js index fe4e5c768467aac3a4967ebd511114e3030b03bd..da28ad022f288702b4c5edc49ab286c330faf4ef 100644 --- a/src/Mods/SecExp/events/secExpSmilingMan1.js +++ b/src/Mods/SecExp/events/secExpSmilingMan1.js @@ -62,10 +62,10 @@ App.Events.secExpSmilingMan1 = class secExpSmilingMan1 extends App.Events.BaseEv App.Events.addParagraph(node, r); App.Events.addResponses(node, [ - new App.Events.Result(`"I want them dead. Now."`, kill), - new App.Events.Result(`"I want them, dead or alive!"`, find), - new App.Events.Result(`"If we don't find him soon, we will regret it."`, findFast), - new App.Events.Result(`"He got what he wanted. Hopefully, we will be left in peace."`, peace), + new App.Events.Result(`I want them dead. Now.`, kill), + new App.Events.Result(`I want them, dead or alive!`, find), + new App.Events.Result(`If we don't find him soon, we will regret it`, findFast), + new App.Events.Result(`He got what he wanted. Hopefully, we will be left in peace.`, peace), ]); function kill() { diff --git a/src/Mods/SecExp/events/secExpSmilingMan2.js b/src/Mods/SecExp/events/secExpSmilingMan2.js index c1bc510d96ac2785f60eb5fe443ef73365f6f152..23457628ebcaefe76e6e672d53ebc92a79e5d70c 100644 --- a/src/Mods/SecExp/events/secExpSmilingMan2.js +++ b/src/Mods/SecExp/events/secExpSmilingMan2.js @@ -66,10 +66,10 @@ App.Events.secExpSmilingMan2 = class secExpSmilingMan2 extends App.Events.BaseEv App.Events.addResponses(node, [ - new App.Events.Result(`"Eliminate the threat, once and for all."`, kill), - new App.Events.Result(`"Bring him to me."`, find), - new App.Events.Result(`"Such skill on my side would be a great boon. Find him."`, findFast), - new App.Events.Result(`"He finally got what he always wanted. Let him have his victory, we have better things to do."`, peace), + new App.Events.Result(`Eliminate the threat, once and for all.`, kill), + new App.Events.Result(`Bring him to me.`, find), + new App.Events.Result(`Such skill on my side would be a great boon. Find him.`, findFast), + new App.Events.Result(`He finally got what he always wanted. Let him have his victory, we have better things to do.`, peace), ]); function kill() { diff --git a/src/Mods/SecExp/events/secExpSmilingMan3.js b/src/Mods/SecExp/events/secExpSmilingMan3.js index 7786da4794239f85a1393ad34ef846b69b33ecd2..a18b3ce48fedb652e8bfcec15099caee7b99f7b3 100644 --- a/src/Mods/SecExp/events/secExpSmilingMan3.js +++ b/src/Mods/SecExp/events/secExpSmilingMan3.js @@ -32,7 +32,7 @@ App.Events.secExpSmilingMan3 = class secExpSmilingMan3 extends App.Events.BaseEv applyGeneticColor(smileSlave); smileSlave.devotion = 5 * V.SecExp.smilingMan.relationship; smileSlave.trust = 5 * V.SecExp.smilingMan.relationship; - smileSlave.face = random(10, 50); + smileSlave.face = random(10, 60); setHealth(smileSlave, 70, 0, 0, 0, 0); smileSlave.teeth = "normal"; smileSlave.areolae = 0; diff --git a/src/Mods/SecExp/js/reportingRelatedFunctions.js b/src/Mods/SecExp/js/reportingRelatedFunctions.js index 1b91c44e38c3b35086552a57242367cfbe9a36a1..b85a1506892846e57e57d93d0c8bca38110431a3 100644 --- a/src/Mods/SecExp/js/reportingRelatedFunctions.js +++ b/src/Mods/SecExp/js/reportingRelatedFunctions.js @@ -61,7 +61,7 @@ App.Mods.SecExp.propagandaEffects = function(focus) { } else if (recruiterActive) { increase += modifier + Math.floor((S.Recruiter.intelligence + S.Recruiter.intelligenceImplant) / 16); } - t = `Your advertisement campaign outside the free city brings more people to the gates of your arcology`; + t = `Your advertisement campaign outside the free city brings more people to the gates of your arcology.`; break; case "enslavement": modifier = forcedViewing ? V.SecExp.buildings.propHub.upgrades.campaign : 1; diff --git a/src/Mods/SpecialForce/SpecialForceFS.js b/src/Mods/SpecialForce/SpecialForceFS.js index 7961d8f7a3c6794daff873126a895751516f7a85..ddc1a56771de2fa078aab24197ad87d70e5a7c5a 100644 --- a/src/Mods/SpecialForce/SpecialForceFS.js +++ b/src/Mods/SpecialForce/SpecialForceFS.js @@ -142,11 +142,11 @@ App.Mods.SF.fsIntegration = (function() { break; case 'Paternalism': dec = `Paternalism: a vision of slave improvement, including slaves' health, mental well-being, and education.`; - gift = `Paternalism is all about improving and saving human lives within the context of Free Cities existence, and you are proud to have granted The Colonel a direct manifestation of this powerful ideal via air power. The Colonel has been delivered her very own OMEGA-series MEDIVAC V/STOL aircraft. This flying monolith is very difficult to manufacture, for it is designed to reach embattled trouble zones very quickly despite its massive weight, make rapid landings in impromptu LZ's despite its massive bulk, and endure heavy fire and extreme weather to evacuate wounded personnel despite being a lightly armored aircraft. This variant of the OMEGA-series can take in hundreds of casualties for the onboard staff to stabilize, before dropping them off at the Firebase for truly intensive care. Given its prestige, ease of use, and tremendous durability, The Colonel has been known to occasionally use it to personally evacuate endangered friendly platoons in the field or sometimes even desperate refugees, whenever she needs a productive diversion from her usual duties.`; + gift = `Paternalism is all about improving and saving human lives within the context of Free Cities existence, and you are proud to have granted The Colonel a direct manifestation of this powerful ideal via air power. The Colonel has been delivered her very own OMEGA-series MEDIVAC V/STOL aircraft. This flying monolith is very difficult to manufacture, for it is designed to reach embattled trouble zones very quickly despite its massive weight, make rapid landings in impromptu LZs despite its massive bulk, and endure heavy fire and extreme weather to evacuate wounded personnel despite being a lightly armored aircraft. This variant of the OMEGA-series can take in hundreds of casualties for the onboard staff to stabilize, before dropping them off at the Firebase for truly intensive care. Given its prestige, ease of use, and tremendous durability, The Colonel has been known to occasionally use it to personally evacuate endangered friendly platoons in the field or sometimes even desperate refugees, whenever she needs a productive diversion from her usual duties.`; foods = `Firebase cuisine is prepared with exceptional care, the talented slave-cooks put lots of attention in replicating their family specialty dishes as best they can whenever asked. The troops love the food they get, and mealtimes here frequently prove to be great occasions for bonding.`; media = `When they eat, the troops are sometimes treated to weekly FC TV fantasy series broadcasts often featuring chivalrous knights and plucky heroes fighting and winning classic battles of good and evil, before said champions take to enjoying explicit, yet wholesome sex with the numerous maidens, housewives, noblewomen, and queens they rescue.`; slaves = `Every slave here is allotted regular breaks, issued protective gloves and aprons for their work, and even receive regular medical checkups. Numerous slaves have also befriended some soldiers, and even sometimes see these soldiers off on their regular deployments.`; - cages = `The new captives brought to the processing cages are all given 'slave manuals', printed in their declared native language. The manuals are meant to thoroughly inform them of how they should best serve and survive in their new lives. They are all given clean bedrolls to spare them from sleeping on the floor of their cages, and they are also given regular psychiatric and physical evaluations to ensure sound body and mind.'`; + cages = `The new captives brought to the processing cages are all given 'slave manuals', printed in their declared native language. The manuals are meant to thoroughly inform them of how they should best serve and survive in their new lives. They are all given clean bedrolls to spare them from sleeping on the floor of their cages, and they are also given regular psychiatric and physical evaluations to ensure sound body and mind.`; commonArea = `Comfort is king here. Every chair now enjoys soft fluffy padding while every table is fully adjustable in height. The large and well-maintained side dens that serve as the local slave quarters all feature simple-yet-comfortable bunk beds, proper plumbing and heating, and even their very own soft drink dispensers.`; barracks = `The barracks are certainly not the first of their kind in the Free Cities, but they are among the first to provide an actual side room for Barracks-slaves to relax in when their shifts are done. The Slave Lounge is very well furnished, with soft furniture and a large wallscreen television to maximize comfort. Sometimes the occasional soldier will even drop by when they want to spend time with some 'civvies' for a change.`; armoury = `On the largest wall in the armoury, there is a massive wallscreen. This wallscreen serves as an interactive digital plaque of commemoration. Upon it lie the listed names of every retired and deceased former member of the Firebase, and one only has to touch it to see a listee's profile, search for a specific name, or scroll up or down the immense list. If one were only to touch a name, they will see a profile pop-up containing the full life story of that soldier -- or at least as much of it as they wanted to share -- along with their full service records, with special emphasis placed on any heroic deeds in battle or valorous conduct in general. On tiny wallspeakers, triumphant music gently plays while onlookers scroll. On both flanks of the wallscreen, an honor guard stands vigil.`; @@ -784,7 +784,7 @@ App.Mods.SF.fsIntegration = (function() { } /** - * @returns {[text: DocumentFragment, type: String]} + * @returns {[text: DocumentFragment, type: string]} */ function crisis() { const t = new DocumentFragment(); diff --git a/src/arcologyBuilding/ManageArcology.js b/src/arcologyBuilding/ManageArcology.js index 9beb95126bdedede11f885a9c21888281a6de799..e2014f0cb869a8788168498e65bb9b92ea54dbe3 100644 --- a/src/arcologyBuilding/ManageArcology.js +++ b/src/arcologyBuilding/ManageArcology.js @@ -478,7 +478,7 @@ App.UI.manageArcology = function() { choices.push(link(`Decrease`, "rent", 1, 1, 10 / 9)); } else if (V.rent[classStr] > V.rentDefaults[classStr] * 0.5) { frag.append(`Average. `); - choices.push(link(`Increase`, "rent", 1.5, 0.94, 9 / 8)); + choices.push(link(`Increase`, "rent", 1.5, 0.94, 9 / 10)); choices.push(link(`Decrease`, "rent", 0.5, 1.04, 11 / 10)); } else if (V.rent[classStr] > 0) { frag.append(`Low. `); diff --git a/src/data/backwardsCompatibility/backwardsCompatibility.js b/src/data/backwardsCompatibility/backwardsCompatibility.js index cb0e4eb1a415615278ffc8af6d3473eaacbc2cf6..d61345e80f3631bed4a2f2ed3d7bade58c0a2379 100644 --- a/src/data/backwardsCompatibility/backwardsCompatibility.js +++ b/src/data/backwardsCompatibility/backwardsCompatibility.js @@ -217,6 +217,7 @@ App.Update.globalVariables = function(node) { V.incubator.name = V.incubator.name || V.incubatorName || "the Incubator"; V.incubator.organs = V.incubator.organs || V.incubatorOrgans || []; V.incubator.readySlaves = V.incubator.readySlaves || V.readySlaves || 0; + V.incubator.bulkRelease = V.incubator.bulkRelease || V.incubator.setting.bulkRelease || V.incubatorBulkRelease || 0; V.incubator.upgrade = V.incubator.upgrade || {}; V.incubator.upgrade.speed = V.incubator.upgrade.speed || V.incubatorUpgradeSpeed || 5; @@ -227,18 +228,49 @@ App.Update.globalVariables = function(node) { V.incubator.upgrade.pregAdaptation = V.incubator.upgrade.pregAdaptation || V.incubatorUpgradePregAdaptation || 0; V.incubator.upgrade.organs = V.incubator.upgrade.organs || V.incubatorUpgradeOrgans || 0; - V.incubator.setting = V.incubator.setting || {}; - V.incubator.setting.bulkRelease = V.incubator.setting.bulkRelease || V.incubatorBulkRelease || 0; + V.incubator.maleSetting = V.incubator.maleSetting || {...V.incubator.setting} || {}; + V.incubator.maleSetting.targetAge = V.incubator.maleSetting.targetAge || V.targetAge || V.minimumSlaveAge || 18; if (V.incubatorImprintSetting === 0) { - V.incubator.setting.imprint = "trust"; - } - V.incubator.setting.imprint = V.incubator.setting.imprint || V.incubatorImprintSetting || "trust"; - V.incubator.setting.weight = V.incubator.setting.weight || V.incubatorWeightSetting || 0; - V.incubator.setting.muscles = V.incubator.setting.muscles || V.incubatorMusclesSetting || 0; - V.incubator.setting.growthStims = V.incubator.setting.growthStims || V.incubatorGrowthStimsSetting || 0; - V.incubator.setting.reproduction = V.incubator.setting.reproduction || V.incubatorReproductionSetting || 0; - V.incubator.setting.pregAdaptation = V.incubator.setting.pregAdaptation || V.incubatorPregAdaptationSetting || 0; - V.incubator.setting.pregAdaptationPower = V.incubator.setting.pregAdaptationPower || V.incubatorPregAdaptationPower || 0; + V.incubator.maleSetting.imprint = "trust"; + } + V.incubator.maleSetting.imprint = V.incubator.maleSetting.imprint || V.incubator.setting.imprint || V.incubatorImprintSetting || "trust"; + V.incubator.maleSetting.weight = V.incubator.maleSetting.weight || V.incubator.setting.weight || V.incubatorWeightSetting || 0; + V.incubator.maleSetting.muscles = V.incubator.maleSetting.muscles || V.incubator.setting.muscles || V.incubatorMusclesSetting || 0; + V.incubator.maleSetting.growthStims = V.incubator.maleSetting.growthStims || V.incubator.setting.growthStims || V.incubatorGrowthStimsSetting || 0; + V.incubator.maleSetting.reproduction = V.incubator.maleSetting.reproduction || V.incubator.setting.reproduction || V.incubatorReproductionSetting || 0; + let provisionalPregAdaptation = (V.incubator.setting.pregAdaptation || V.incubatorPregAdaptationSetting || 0); + V.incubator.maleSetting.pregAdaptation = V.incubator.maleSetting.pregAdaptation || ((provisionalPregAdaptation === 2 || provisionalPregAdaptation === 3) ? 1 : 0); //Convert to boolean + V.incubator.maleSetting.pregAdaptationPower = V.incubator.maleSetting.pregAdaptationPower || V.incubator.setting.pregAdaptationPower || V.incubatorPregAdaptationPower || 0; + + V.incubator.femaleSetting = V.incubator.femaleSetting || {...V.incubator.setting} || {}; + V.incubator.femaleSetting.targetAge = V.incubator.femaleSetting.targetAge || V.targetAge || V.minimumSlaveAge || 18; + if (V.incubatorImprintSetting === 0) { + V.incubator.femaleSetting.imprint = "trust"; + } + V.incubator.femaleSetting.imprint = V.incubator.femaleSetting.imprint || V.incubator.setting.imprint || V.incubatorImprintSetting || "trust"; + V.incubator.femaleSetting.weight = V.incubator.femaleSetting.weight || V.incubator.setting.weight || V.incubatorWeightSetting || 0; + V.incubator.femaleSetting.muscles = V.incubator.femaleSetting.muscles || V.incubator.setting.muscles || V.incubatorMusclesSetting || 0; + V.incubator.femaleSetting.growthStims = V.incubator.femaleSetting.growthStims || V.incubator.setting.growthStims || V.incubatorGrowthStimsSetting || 0; + V.incubator.femaleSetting.reproduction = V.incubator.femaleSetting.reproduction || V.incubator.setting.reproduction || V.incubatorReproductionSetting || 0; + V.incubator.femaleSetting.pregAdaptation = V.incubator.femaleSetting.pregAdaptation || ((provisionalPregAdaptation === 1 || provisionalPregAdaptation === 3) ? 1 : 0); + V.incubator.femaleSetting.pregAdaptationPower = V.incubator.femaleSetting.pregAdaptationPower || V.incubator.setting.pregAdaptationPower || V.incubatorPregAdaptationPower || 0; + + for (let i = 0; i < V.incubator.tanks.length; i++) { + if (!("incubatorSettings" in V.incubator.tanks[i])) { + const setting = (V.incubator.tanks[i].genes === "XX" ? V.incubator.femaleSetting : V.incubator.maleSetting); + V.incubator.tanks[i].incubatorSettings = { + imprint: setting.imprint, + weight: setting.weight, + muscles: setting.muscles, + growthStims: setting.growthStims, + reproduction: setting.reproduction, + growTime: V.incubator.tanks[i].growTime, + pregAdaptation: setting.pregAdaptation, + pregAdaptationPower: V.incubator.tanks[i].incubatorPregAdaptationPower, + pregAdaptationInWeek: V.incubator.tanks[i].incubatorPregAdaptationInWeek + } + } + } } if (Array.isArray(V.nationalities)) { diff --git a/src/data/backwardsCompatibility/datatypeCleanup.js b/src/data/backwardsCompatibility/datatypeCleanup.js index cd8c4176e4b9c77fa830bf5d93ee0f03c068211c..ed63addf0d235213749801522bd07d97727333ec 100644 --- a/src/data/backwardsCompatibility/datatypeCleanup.js +++ b/src/data/backwardsCompatibility/datatypeCleanup.js @@ -985,6 +985,8 @@ globalThis.SlaveDatatypeCleanup = (function SlaveDatatypeCleanup() { slave.counter.slavesKnockedUp = Math.max(+slave.counter.slavesKnockedUp, 0) || 0; slave.counter.PCKnockedUp = Math.max(+slave.counter.PCKnockedUp, 0) || 0; slave.counter.bestiality = Math.max(+slave.counter.bestiality, 0) || 0; + slave.counter.PCChildrenBeared = Math.max(+slave.counter.PCChildrenBeared, 0) || 0; + slave.counter.timesBred = Math.max(+slave.counter.timesBred, 0) || 0; slave.bodySwap = Math.max(+slave.bodySwap, 0) || 0; } diff --git a/src/descriptions/arcologyDescription.js b/src/descriptions/arcologyDescription.js index fd80fa6367a633f9313a897510edce349b4433c5..c7e00a59c485ae6f896d48475069ab138d645b4e 100644 --- a/src/descriptions/arcologyDescription.js +++ b/src/descriptions/arcologyDescription.js @@ -457,9 +457,9 @@ App.Desc.playerArcology = function(lastElement) { } } - const slaves = App.Entity.facilities.brothel.employees(); + const whores = App.Entity.facilities.brothel.employees(); - if (slaves.length > 5 && slaves.every(slave => slave.face > 40)) { + if (whores.length > 5 && whores.every(slave => slave.face > 40)) { buffer.push(`${V.arcologies[0].name} is known for its beautiful whores.`); } } diff --git a/src/endWeek/economics/neighborsDevelopment.js b/src/endWeek/economics/neighborsDevelopment.js index 7c82e29e0f53090077fadb4b5aacc94e7fd294b1..a08c9868ba83b03fa13a5c96a17b21ad82ef1aa2 100644 --- a/src/endWeek/economics/neighborsDevelopment.js +++ b/src/endWeek/economics/neighborsDevelopment.js @@ -56,7 +56,9 @@ App.EndWeek.neighborsDevelopment = function() { const agent = App.currentAgent(i); if (arc.government === "your agent") { const {He} = getPronouns(agent); - r.push(`is being run by your agent <span class="deeppink">${SlaveFullName(agent)}.</span>`); + const popup = App.UI.DOM.slaveDescriptionDialog(agent, SlaveFullName(agent) + "."); + popup.classList.add("slave-name", "bold"); + r.push(`is being run by your agent`, popup); if (agent && agent.assignment !== "be your agent") { r.push(`<span class="red">BUG: ${agent} also was ${agent.assignment}!</span>`); assignJob(agent, "be your agent"); @@ -374,7 +376,7 @@ App.EndWeek.neighborsDevelopment = function() { /* FUTURE SOCIETY PROGRESS */ const societiesAdopted = FutureSocieties.activeCount(arc); - let efficiency; + let efficiency = random(-3, 3); switch (arc.government) { case "elected officials": efficiency = random(-2, 2); @@ -395,8 +397,6 @@ App.EndWeek.neighborsDevelopment = function() { case "a corporation": efficiency = random(1, 2); break; - default: - efficiency = random(-3, 3); } if (arc.rival === 1) { diff --git a/src/endWeek/player/prDiet.js b/src/endWeek/player/prDiet.js index 094cf8a9f4d59be193a1b9ccf15113e616053ceb..0e82981ad335676908cda8c005fdbef450f229a3 100644 --- a/src/endWeek/player/prDiet.js +++ b/src/endWeek/player/prDiet.js @@ -538,6 +538,9 @@ App.EndWeek.Player.diet = function(PC = V.PC) { break; case "weaning": r.push(`You stick to your prescription diet with the intent to free yourself from slave food dependency.`); + if (!PC.weaningDuration) { + PC.weaningDuration = 0; // ugly hack, probably shouldn't initialize this here + } if (PC.weaningDuration < 5) { healthDamage(PC, 100); r.push(`It gels into a dense paste in your stomach, giving you <span class="health dec">intense cramps</span> as it slowly digests.`); @@ -564,6 +567,7 @@ App.EndWeek.Player.diet = function(PC = V.PC) { PC.weight -= (-2 * PC.weaningDuration) + 28; PC.muscles -= (-2 * PC.weaningDuration) + 28; r.push(`More importantly, it is now <span class="change positive">regularly coming out the other end.</span> You're not far off from a healthy gastrointestinal tract.`); + PC.bellyFluid = 0; // needed because deflate() and SetBellySize() don't handle undigested food deflate(PC); } else { r.push(`Your body is now capable of fully digesting your food and getting rid of its waste.`); diff --git a/src/endWeek/player/prDrugs.js b/src/endWeek/player/prDrugs.js index d49c542e767ed4dfd4fc74388804b1d9aa873951..587a11fa1b740e60df127987d7a500aeb82c0fd1 100644 --- a/src/endWeek/player/prDrugs.js +++ b/src/endWeek/player/prDrugs.js @@ -64,7 +64,7 @@ App.EndWeek.Player.drugs = function(PC = V.PC) { break; case "hip wideners": r.push(`The tablets aid your body with preparing for childbirth, at the cost of <span class="health dec">leaving you ill</span> from the excess hormones.`); - healthDamage(PC, random(3, 5)) + healthDamage(PC, random(3, 5)); break; case "priapism agents": if (PC.dick === 0) { @@ -1594,16 +1594,17 @@ App.EndWeek.Player.drugs = function(PC = V.PC) { r.push(induceLactation(PC, 2)); break; - //Adds a default to handle unexpected(modded) drugs + // Adds a default to handle unexpected(modded) drugs default: - { - const drug = App.Mods.Drugs.find(e => e.name === PC.drugs); - if (drug) r += drug.effect(PC); - else { - console.error(`Drug effect of ${PC.drugs} not found!`); - PC.drugs = "no drugs"; - } + { + const drug = App.Mods.Drugs.list.filter(drug => drug.isPCDrug).find(e => e.name === PC.drugs); + if (drug) { + r.push(drug.effect(PC)); + } else { + console.error(`Drug effect of ${PC.drugs} not found!`); + PC.drugs = "no drugs"; } + } } if (["hyper breast injections", "hyper butt injections", "growth stimulants", "hyper penis enhancement", "hyper testicle enhancement", "super fertility drugs"].includes(PC.drugs)) { if (!canEatFood(PC)) { diff --git a/src/endWeek/player/prInflation.js b/src/endWeek/player/prInflation.js index 148651dfa966488572d2b7a97e6002e66f8bc5e0..0289850ef371e6511219c15939e9478672b5d6ce 100644 --- a/src/endWeek/player/prInflation.js +++ b/src/endWeek/player/prInflation.js @@ -84,7 +84,12 @@ App.EndWeek.Player.inflation = function(PC = V.PC) { r.push(`you at all. <span class="yellow">You are unable continue to inflate yourself by this means.</span>`); } } else if (PC.inflationType === "undigested food" && PC.diet !== "weaning") { - r.push(`Since you started eating slave food again, the food backing up in your system has broken down, once again <span class="yellow">leaving you with a flat belly.</span>`); + if (PC.digestiveSystem === "normal") { // successfully weaned - backup in case cheating player skips weaningDuration 10-13 period + r.push(`Having weaned yourself from slave food, your strengthened digestive system is finally able to break down the mass of undigested food inside you, <span class="yellow">leaving you with a flat belly.</span>.`); + } else { // gave up on weaning + r.push(`Since you started eating slave food again, the food backing up in your system has broken down, once again <span class="yellow">leaving you with a flat belly.</span>`); + } + PC.bellyFluid = 0; // necessary because deflate() and SetBellySize() don't handle undigested food deflate(PC); PC.weaningDuration = 0; } diff --git a/src/endWeek/reports/incubatorReport.js b/src/endWeek/reports/incubatorReport.js index a3f138fee6a7cd656f86d76022ac9c5339471aaa..42da5fd2f32bde9c66615af1d36de7065d54b495 100644 --- a/src/endWeek/reports/incubatorReport.js +++ b/src/endWeek/reports/incubatorReport.js @@ -18,13 +18,13 @@ App.EndWeek.incubatorReport = function() { tank.ovaryAge++; } } - if (tank.growTime > 0) { - tank.growTime -= V.incubator.upgrade.speed; + if (tank.incubatorSettings.growTime > 0) { + tank.incubatorSettings.growTime -= V.incubator.upgrade.speed; r.push(`<span class="pink">${tank.slaveName}'s</span> growth is currently being accelerated. ${He}`); - if (Math.round(tank.growTime/V.incubator.upgrade.speed) <= 0) { + if (Math.round(tank.incubatorSettings.growTime/V.incubator.upgrade.speed) <= 0) { r.push(`is <span class="lime">ready for release.</span> ${He} will be ejected from ${his} tank upon your approach.`); } else { - r.push(`will be ready for release in about ${Math.round(tank.growTime/V.incubator.upgrade.speed)} weeks.`); + r.push(`will be ready for release in about ${Math.round(tank.incubatorSettings.growTime/V.incubator.upgrade.speed)} weeks.`); } } else { r.push(`<span class="pink">${tank.slaveName}</span> is <span class="lime">ready for release.</span> ${He} will be ejected from ${his} tank upon your approach.`); @@ -34,7 +34,7 @@ App.EndWeek.incubatorReport = function() { r = []; if (V.incubator.upgrade.weight === 1) { - if (V.incubator.setting.weight === 1) { + if (tank.incubatorSettings.weight === 1) { if (tank.weight < 200) { if (V.incubator.upgrade.speed === 52) { tank.weight += 70; @@ -49,7 +49,7 @@ App.EndWeek.incubatorReport = function() { } } r.push(`The weight monitoring systems are overloading ${his} intake causing <span class="red">rapid weight gain.</span>`); - } else if (V.incubator.setting.weight === 2) { + } else if (tank.incubatorSettings.weight === 2) { if (tank.weight > 10) { if (V.incubator.upgrade.speed === 52) { tank.weight -= 30; @@ -79,7 +79,7 @@ App.EndWeek.incubatorReport = function() { } else { r.push(`${He} is <span class="lime">currently at a healthy weight;</span> efforts will be made to maintain it.`); } - } else if (V.incubator.setting.weight === 0) { + } else if (tank.incubatorSettings.weight === 0) { if (tank.weight > -100) { r.push(`${His} developing body <span class="red">quickly sheds its gained weight.</span>`); tank.weight -= 40; @@ -95,7 +95,7 @@ App.EndWeek.incubatorReport = function() { r = []; if (V.incubator.upgrade.muscles === 1) { - if (V.incubator.setting.muscles === 2) { + if (tank.incubatorSettings.muscles === 2) { if (tank.muscles < 100) { if (V.incubator.upgrade.speed === 52) { tank.muscles += 70; @@ -110,7 +110,7 @@ App.EndWeek.incubatorReport = function() { } } r.push(`The strength monitoring systems are overloading ${him} with steroids causing <span class="green">rapid muscle development.</span>`); - } else if (V.incubator.setting.muscles === 1) { + } else if (tank.incubatorSettings.muscles === 1) { if (tank.muscles > 10) { if (V.incubator.upgrade.speed === 52) { tank.muscles -= 30; @@ -140,7 +140,7 @@ App.EndWeek.incubatorReport = function() { } else { r.push(`${He} has <span class="lime">a healthy musculature;</span> efforts will be made to maintain it.`); } - } else if (V.incubator.setting.muscles === 0) { + } else if (tank.incubatorSettings.muscles === 0) { if (tank.muscles > -100) { r.push(`${His} developing body <span class="red">quickly loses its gained muscle.</span>`); tank.muscles -= 40; @@ -155,7 +155,7 @@ App.EndWeek.incubatorReport = function() { App.Events.addNode(entry, r, "div"); r = []; - if (V.incubator.upgrade.growthStims === 1 && V.incubator.setting.growthStims !== 0) { + if (V.incubator.upgrade.growthStims === 1 && tank.incubatorSettings.growthStims !== 0) { let heightLimit = Math.clamp((Height.forAge(tank.natural.height, tank) * 1.25), 0, 274); let heightLimitAge = Height.forAge(tank.natural.height, tank); if (tank.geneticQuirks.dwarfism === 2 && tank.geneticQuirks.gigantism !== 2) { @@ -178,12 +178,12 @@ App.EndWeek.incubatorReport = function() { if (tank.height >= heightLimit) { r.push(`The monitoring system detects ${his} body is not able to support further increases in height, so it carefully regulates stimulant injections to <span class="yellow">maintain ${his} current stature.</span>`); tank.height = heightLimit; - } else if (V.incubator.setting.growthStims === 2) { + } else if (tank.incubatorSettings.growthStims === 2) { if (tank.geneMods.NCS === 1) { r.push(`The monitoring system floods ${his} body with growth stimulants, but ${his} <span class="orange">NCS prevents an increase in ${his} growth rate.</span>`); tank.height = heightLimitAge; } else { - if (V.incubator.setting.weight >= 1 && V.incubator.setting.muscles <= 1 && V.incubator.setting.reproduction <= 1) { + if (tank.incubatorSettings.weight >= 1 && tank.incubatorSettings.muscles <= 1 && tank.incubatorSettings.reproduction <= 1) { r.push(`The monitoring system floods ${his} body with growth stimulants. ${His} caloric intake and expenditure rates are ideal for maximum response, causing <span class="green">explosive growth.</span>`); if (V.incubator.upgrade.speed === 52) { tank.height += random(3, 6); @@ -211,7 +211,7 @@ App.EndWeek.incubatorReport = function() { } } } - } else if (V.incubator.setting.growthStims === 1) { + } else if (tank.incubatorSettings.growthStims === 1) { if (tank.geneMods.NCS === 1) { r.push(`The monitoring system detects ${he} is near the expected height for ${his} <span class="orange">NCS</span> condition, so it carefully regulates stimulant injections to <span class="yellow">maintain ${his} current stature.</span>`); tank.height = heightLimitAge; @@ -254,9 +254,9 @@ App.EndWeek.incubatorReport = function() { r = []; if (V.incubator.upgrade.reproduction === 1) { const rearQuirk = tank.geneticQuirks.rearLipedema === 2 ? 2 : 1; - if (V.incubator.setting.reproduction === 2) { + if (tank.incubatorSettings.reproduction === 2) { r.push(`${His} developing body is being flooded with hormones.`); - if (V.incubator.setting.weight === 1) { + if (tank.incubatorSettings.weight === 1) { r.push(`Combined with the abundant food provided to ${him}, ${his} body grows rapidly.`); if (tank.ovaries === 1) { tank.pubertyXX = 1; @@ -388,7 +388,7 @@ App.EndWeek.incubatorReport = function() { } } } - } else if (V.incubator.setting.weight === 2) { + } else if (tank.incubatorSettings.weight === 2) { r.push(`Combined with the healthy food provided to ${him}, ${his} body grows readily.`); if (tank.ovaries === 1) { tank.pubertyXX = 1; @@ -653,7 +653,7 @@ App.EndWeek.incubatorReport = function() { } } } - } else if (V.incubator.setting.reproduction === 1) { + } else if (tank.incubatorSettings.reproduction === 1) { r.push(`${His} hormone levels are being carefully managed, <span class="green">encouraging early puberty.</span>`); if (tank.ovaries === 1) { tank.pubertyXX = 1; @@ -750,10 +750,10 @@ App.EndWeek.incubatorReport = function() { } App.Events.addNode(entry, r, "div"); - if (V.incubator.setting.reproduction === 2) { + if (tank.incubatorSettings.reproduction === 2) { tank.energy = 80; tank.need = 100; - } else if (V.incubator.setting.reproduction === 1) { + } else if (tank.incubatorSettings.reproduction === 1) { tank.energy = 50; tank.need = 20; } else { @@ -762,24 +762,24 @@ App.EndWeek.incubatorReport = function() { } r = []; - if (((V.incubator.setting.pregAdaptation === 1 && tank.genes === "XX") || (V.incubator.setting.pregAdaptation === 2 && tank.genes === "XY") || V.incubator.setting.pregAdaptation === 3) && tank.growTime > 0) { - if (tank.incubatorPregAdaptationInWeek <= 0) { + if (tank.incubatorSettings.pregAdaptation > 0 && tank.incubatorSettings.growTime > 0) { + if (tank.incubatorSettings.pregAdaptationInWeek <= 0) { r.push(`${His} physique will be mature enough on release that the incubator's reproductive capacity system would have no effect on ${him} at current settings, so it is unused.`); } else { r.push(`The incubator is working on adapting ${his} abdomen and reproductive organs for future pregnancies.`); - let weekAdapt = tank.incubatorPregAdaptationInWeek * V.incubator.upgrade.speed; + let weekAdapt = tank.incubatorSettings.pregAdaptationInWeek * V.incubator.upgrade.speed; if (isNaN(weekAdapt)) { /* NaN check AFTER multiply operation, against it result is critical here. Need to be absolutely sure about this operation, not about just tank property itself. This give me two very unpleasant hours to catch this */ - tank.incubatorPregAdaptationInWeek = (15000 / 2000 - tank.pregAdaptation) / tank.growTime; + tank.incubatorSettings.pregAdaptationInWeek = (15000 / 2000 - tank.pregAdaptation) / tank.incubatorSettings.growTime; } - weekAdapt = tank.incubatorPregAdaptationInWeek * V.incubator.upgrade.speed; + weekAdapt = tank.incubatorSettings.pregAdaptationInWeek * V.incubator.upgrade.speed; /* Now it should be fine */ - weekAdapt *= 1 + (V.incubator.setting.reproduction / 5); + weekAdapt *= 1 + (tank.incubatorSettings.reproduction / 5); weekAdapt *= 1 + (tank.hormoneBalance / 1500); tank.pregAdaptation += weekAdapt; /* here goes side effect from intense and extreme settings: */ - if (random(1, 100) <= (tank.incubatorPregAdaptationPower - 1) * (V.incubator.upgrade.speed / 2 + 1)) { + if (random(1, 100) <= (tank.incubatorSettings.pregAdaptationPower - 1) * (V.incubator.upgrade.speed / 2 + 1)) { switch (random(1, 9)) { /* side effect selection*/ case 1: if (tank.preg > -2) { @@ -788,7 +788,7 @@ App.EndWeek.incubatorReport = function() { } break; case 2: - if (((tank.ovaries === 1 || tank.mpreg === 1) && tank.preg > -3) || (tank.balls > 0 && tank.ballType != "sterile")) { + if (((tank.ovaries === 1 || tank.mpreg === 1) && tank.preg > -3) || (tank.balls > 0 && tank.ballType !== "sterile")) { if (tank.ovaries === 1 || tank.mpreg === 1) { tank.preg = -3; } diff --git a/src/endWeek/reports/personalAttention.js b/src/endWeek/reports/personalAttention.js index 47b8ece796e5e3d3de9af4b0eec698350d97ef46..1e04cfc223e81ce319d681a3598f549172d9e8fc 100644 --- a/src/endWeek/reports/personalAttention.js +++ b/src/endWeek/reports/personalAttention.js @@ -1598,7 +1598,7 @@ App.PersonalAttention.slaveReport = function(slave) { case "torture": { let FSApproves = 0; // Effectively sacrifices a slave's health to terrify your penthouse slaves. Does not affect deaf slaves. Mute slaves give no benefit. - r.push(`When you have pent up energy, you beat ${him}. When you're bored, you lash ${him}. If you even see ${him} passing out from exhaustion or pain, you shock ${him} back awake. If ${he} isn't moaning in dispair, that's all the reason you need to make ${him} bleed.`); + r.push(`When you have pent up energy, you beat ${him}. When you're bored, you lash ${him}. If you even see ${him} passing out from exhaustion or pain, you shock ${him} back awake. If ${he} isn't moaning in despair, that's all the reason you need to make ${him} bleed.`); if (V.PC.energy > 20) { r.push(`As an added insult, you opt to violently rape ${him} throughout the day; some by surprise, others drawn out so the fear of what's to come can supplement ${his} anguish.`); } diff --git a/src/endWeek/saDrugs.js b/src/endWeek/saDrugs.js index 7023dd4bf0fc1868b883fff94b3b2869fdd22171..7cc21da5fb143c05381d9179e98c4d0107359e45 100644 --- a/src/endWeek/saDrugs.js +++ b/src/endWeek/saDrugs.js @@ -1537,16 +1537,16 @@ App.SlaveAssignment.drugs = function saDrugs(slave) { } break; - //Adds a default to handle unexpected(modded) drugs - default: - { - const drug = App.Mods.Drugs.find(e => e.name === slave.drugs); - if (drug) r += drug.effect(slave); - else { - console.error(`Drug effect of ${slave.drugs} not found!`); - slave.drugs = "no drugs"; - } + // Adds a default to handle unexpected(modded) drugs + default: { + const drug = App.Mods.Drugs.list.filter(drug => !drug.isPCDrug).find(e => e.name === slave.drugs); + if (drug) { + r += drug.effect(slave); + } else { + console.error(`Drug effect of ${slave.drugs} not found!`); + slave.drugs = "no drugs"; } + } } if (slave.drugs !== "no drugs" && slave.drugs !== "appetite suppressors") { if (V.arcologies[0].FSBodyPuristLaw === 0) { diff --git a/src/endWeek/saPleaseYou.js b/src/endWeek/saPleaseYou.js index 5f0f97fd7a37c59d1def007951724906c6921ac8..72c9367a4db3da7fd98b39ccbed6bf0ed499efdf 100644 --- a/src/endWeek/saPleaseYou.js +++ b/src/endWeek/saPleaseYou.js @@ -1609,8 +1609,8 @@ App.SlaveAssignment.pleaseYou = function saPleaseYou(slave) { */ function familyBonus(slave) { let multiplier = 0; - let children; const isFucktoy = (s) => [Job.CONCUBINE, Job.MASTERSUITE, Job.FUCKTOY].includes(s.assignment); + const fucktoys = V.slaves.filter(s => isFucktoy(s)); if (areRelated(V.PC, slave)) { r.push(`Keeping your own ${relativeTerm(V.PC, slave)} as a personal ${canFuck ? `fucktoy` : `bedwarmer`} leaves quite a public impression.`); @@ -1634,20 +1634,24 @@ App.SlaveAssignment.pleaseYou = function saPleaseYou(slave) { } } - children = V.slaves.filter(s => (s.father === slave.ID || s.mother === slave.ID) && isFucktoy(s)); + const children = fucktoys.filter(s => s.father === slave.ID || s.mother === slave.ID); if (children.length > 1) { - r.push(`Since you are also keeping ${his} daughters, ${toSentence(children.map(s => s.slaveName))}, as sexual servants, you often enjoy them all at once, which leaves quite a public impression.`); + const childPronouns = getPronouns(children[0]); + const groupNoun = children.every(s => getPronouns(s).daughter === childPronouns.daughter) ? asPlural(childPronouns.daughter) : "children"; // daughters, sons, or children, as appropriate + r.push(`Since you are also keeping ${his} ${groupNoun}, ${toSentence(children.map(s => s.slaveName))}, as sexual servants, you often enjoy them all at once, which leaves quite a public impression.`); } else if (children.length > 0) { const childPronouns = getPronouns(children[0]); - r.push(`Since you are also keeping ${his} ${childPronouns.daughter} as a sexual servant, you often use them together, which leaves quite a public impression.`); + r.push(`Since you are also keeping ${his} ${childPronouns.daughter}, ${children[0].slaveName}, as a sexual servant, you often use them together, which leaves quite a public impression.`); } - children = V.slaves.filter((s) => (areSisters(slave, s) > 0) && isFucktoy(s)); - if (children.length > 1) { - r.push(`Since you are also keeping ${his} sisters, ${toSentence(children.map(s => s.slaveName))}, as sexual servants, you often enjoy them all at once, which leaves quite a public impression.`); - } else if (children.length > 0) { - const childPronouns = getPronouns(children[0]); - r.push(`Since you are also keeping ${his} ${childPronouns.sister} as a sexual servant, you often use them together, which leaves quite a public impression.`); + const siblings = fucktoys.filter(s => areSisters(slave, s) > 0); + if (siblings.length > 1) { + const sibPronouns = getPronouns(siblings[0]); + const groupNoun = siblings.every(s => getPronouns(s).sister === sibPronouns.sister) ? asPlural(sibPronouns.sister) : "siblings"; // sisters, brothers, or siblings, as appropriate + r.push(`Since you are also keeping ${his} ${groupNoun}, ${toSentence(siblings.map(s => s.slaveName))}, as sexual servants, you often enjoy them all at once, which leaves quite a public impression.`); + } else if (siblings.length > 0) { + const sibPronouns = getPronouns(siblings[0]); + r.push(`Since you are also keeping ${his} ${sibPronouns.sister}, ${siblings[0].slaveName}, as a sexual servant, you often use them together, which leaves quite a public impression.`); } return multiplier; diff --git a/src/endWeek/saRules.js b/src/endWeek/saRules.js index 2aaa6347b733a075d6e3f3dcb32a9bf74666165c..a316945fd47777fc6ebea44032a1575d343c0123 100644 --- a/src/endWeek/saRules.js +++ b/src/endWeek/saRules.js @@ -1113,7 +1113,7 @@ App.SlaveAssignment.rules = function(slave) { slave.devotion += 1; break; case "Antebellum Revivalist": - r.push(`The thick air of the greenhouse brings ${his} a deep, if temporary, class="mediumaquamarine">calm.</span>`); + r.push(`The thick air of the greenhouse brings ${his} a deep, if temporary, <span class="mediumaquamarine">calm.</span>`); slave.trust += 2; break; case "Chattel Religionist": @@ -1157,7 +1157,7 @@ App.SlaveAssignment.rules = function(slave) { slave.devotion += 1; break; case "Antebellum Revivalist": - r.push(`The thick air of the greenhouse brings ${his} a deeper, more serene, class="mediumaquamarine">calm.</span> now that ${his} mind is free from doubts about being your slave.`); + r.push(`The thick air of the greenhouse brings ${his} a deeper, more serene, <span class="mediumaquamarine">calm.</span> now that ${his} mind is free from doubts about being your slave.`); slave.trust += 4; break; case "Chattel Religionist": diff --git a/src/endWeek/saServeThePublic.js b/src/endWeek/saServeThePublic.js index a4da21e76b877ccf0d91a8126ad1912106f7dbc6..56215d47e1eceb86a9b832669f11d61ae68460df 100644 --- a/src/endWeek/saServeThePublic.js +++ b/src/endWeek/saServeThePublic.js @@ -581,7 +581,7 @@ App.SlaveAssignment.serveThePublic = function saServeThePublic(slave) { if (children.length > 1) { r += ` Since ${his} relatives, ${toSentence(children.map(s => s.slaveName))}, are public sluts too, ${he} earns extra attention.`; } else if (children.length > 0) { - r += ` Since ${his} relative, ${children[0].slaveName}, is a public slut too, ${he} earns extra attention.`; + r += ` Since ${his} ${relativeTerm(slave, children[0])}, ${children[0].slaveName}, is a public slut too, ${he} earns extra attention.`; } if (children.length > 0) { if (arcology.FSEgyptianRevivalist > 20) { diff --git a/src/endWeek/saWhore.js b/src/endWeek/saWhore.js index 319d99a4d65cc7f98db816dd719c127192926cf0..89bc93980aab1e3160c9025647f91c71a5806d27 100644 --- a/src/endWeek/saWhore.js +++ b/src/endWeek/saWhore.js @@ -665,7 +665,7 @@ App.SlaveAssignment.whore = function(slave) { r += ` Since ${his} relatives, ${toSentence(children.map(s => s.slaveName))}, are selling themselves too, ${he} earns extra ¤ by working with them.`; } else if (children.length > 0) { const relativePronouns = getPronouns(children[0]); - r += ` Since ${his} relative, ${children[0].slaveName}, is selling ${relativePronouns.objectReflexive} too, ${he} earns extra ¤ by working with ${relativePronouns.object}.`; + r += ` Since ${his} ${relativeTerm(slave, children[0])}, ${children[0].slaveName}, is selling ${relativePronouns.objectReflexive} too, ${he} earns extra ¤ by working with ${relativePronouns.object}.`; } if (children.length > 0) { if (arcology.FSEgyptianRevivalist > 20) { diff --git a/src/events/RE/reDrunkenTourist.js b/src/events/RE/reDrunkenTourist.js index a9de9618eb847f7bc62cee6920754e8824e15c14..3f41e2210165c4a2758bf70f292e63884b4219e2 100644 --- a/src/events/RE/reDrunkenTourist.js +++ b/src/events/RE/reDrunkenTourist.js @@ -46,7 +46,7 @@ App.Events.REDrunkenTourist = class REDrunkenTourist extends App.Events.BaseEven App.Events.addParagraph(frag, [ "You escort the drunken woman back to her hotel, and she asks you how long you've lived in the arcology.", "When you tell her you own the arcology, she thanks you profusely for taking the time to lead her back to her suite and presses herself up against you, trying her best to be sexy despite her impaired state.", - "She promises to spread a good word about you, and lets you know that you can come up to her room any time." + `She promises to <span class="rep inc">spread a good word about you,</span> and lets you know that you can come up to her room any time.` ]); repX(500, "event"); return frag; diff --git a/src/events/RE/reMalefactor.js b/src/events/RE/reMalefactor.js index 25ddae1dc9ca869a5cc802904d7b5cd55c729b7a..46866b331714d8833acaf11b52dffbdac28d8d9a 100644 --- a/src/events/RE/reMalefactor.js +++ b/src/events/RE/reMalefactor.js @@ -130,8 +130,7 @@ App.Events.REMalefactor = class REMalefactor extends App.Events.BaseEvent { const cost = slaveCost(slave) - 1000; App.Events.addParagraph(node, r); - App.UI.DOM.appendNewElement("p", node, `Applying enslavement as punishment will cost ${cashFormat(contractCost)}. Doing so and then selling ${him} immediately will bring in approximately ${cashFormat(cost)}.`, "note"); - + App.UI.DOM.appendNewElement("p", node, `Applying enslavement as punishment will cost ${cashFormat(contractCost)}. Doing so and then selling ${him} immediately will bring in approximately ${cashFormat(cost)}.`, ["note"]); node.append(App.Desc.longSlave(slave, {market: "generic"})); const choices = []; @@ -176,7 +175,6 @@ App.Events.REMalefactor = class REMalefactor extends App.Events.BaseEvent { function enslave() { const frag = document.createDocumentFragment(); - r = []; cashX(forceNeg(contractCost), "slaveTransfer", slave); @@ -211,7 +209,6 @@ App.Events.REMalefactor = class REMalefactor extends App.Events.BaseEvent { function stocks() { const frag = document.createDocumentFragment(); - r = []; healthDamage(slave, 10); @@ -272,7 +269,6 @@ App.Events.REMalefactor = class REMalefactor extends App.Events.BaseEvent { function arcade() { const frag = document.createDocumentFragment(); - r = []; r.push(assignJob(slave, "be confined in the arcade")); @@ -481,6 +477,9 @@ App.Events.REMalefactor = class REMalefactor extends App.Events.BaseEvent { slave.devotion = 25; slave.trust = 25; + V.RECheckInIDs.push({ID: slave.ID, type: "adoptFollowUp"}); + slave.origin = "$He was an orphan forced to live and steal on the streets until you adopted $him."; + cashX(forceNeg(contractCost), "slaveTransfer", slave); r.push(`You sit down and talk to the exhausted ${girl}, handing ${him} a contract cleverly altered to resemble adoption papers. Once ${he} comprehends what ${he} is looking at, ${he} eagerly signs it. Only once ${he} has reached the penthouse and been introduced to the slave life does ${he} realize ${he} willingly signed away ${his} freedom. Though ${he} can't complain. A warm cot and plenty of food await, which to ${him} is a huge improvement over a slow death on the streets. The public`); if (V.arcologies[0].FSPaternalist !== "unset") { @@ -536,6 +535,7 @@ App.Events.REMalefactor = class REMalefactor extends App.Events.BaseEvent { function flog() { const frag = document.createDocumentFragment(); r = []; + switch (malefactor) { case "addict": r.push(`Naturally, the wretch will be thrown out of the arcology: but an example must first be made. Free people must understand that criminals who commit outrages against them will be severely punished. The twitching, begging malefactor is stripped and flogged on the promenade before being escorted bleeding, and still twitching from withdrawal, out of the arcology. The public <span class="reputation inc">approves of this harshness.</span>`); @@ -571,6 +571,7 @@ App.Events.REMalefactor = class REMalefactor extends App.Events.BaseEvent { function ownerFlog() { const frag = document.createDocumentFragment(); r = []; + r.push(`An example must be made. Slaveownership is the cornerstone of the society you're building in your arcology, and this ${woman} attempted to undermine it. ${He} is stripped and the slaveowner whose property ${he} tried to free is handed the leathern instrument. It seems the escapee was a favorite he does not wish to mangle, so he flogs the criminal mercilessly instead. ${He} is flung out of the arcology, nearly dead. The public <span class="reputation inc">approves of this harshness,</span> and small slaveholders are <span class="green">encouraged to do business with your arcology</span> after word of the incident gets around.`); repX(500, "event", slave); V.arcologies[0].prosperity += 10; @@ -581,6 +582,7 @@ App.Events.REMalefactor = class REMalefactor extends App.Events.BaseEvent { function sell() { const frag = document.createDocumentFragment(); r = []; + cashX(cost, "slaveTransfer"); if (V.policies.cash4Babies === 1 && malefactor === "anchorBaby") { cashX(random(20, 30), "slaveTransfer"); @@ -709,7 +711,7 @@ App.Events.REMalefactor = class REMalefactor extends App.Events.BaseEvent { break; case "orphanloli": slave = GenerateNewSlave(null, {minAge: V.minimumSlaveAge, maxAge: 12, disableDisability: 1}); - slave.origin = "$He was an orphan forced to live and steal on the streets until you adopted $him."; + slave.origin = "You sentenced $him to enslavement as a punishment for suspected escapism."; slave.career = "an orphan"; slave.devotion = random(-15, 0); slave.trust = random(-75, -60); diff --git a/src/events/RE/reNickname.js b/src/events/RE/reNickname.js index 9dbccf69a815f00f68c23cd22a13a40a119bec59..71799366ead4e1237b75c552f3ab117fac7035ad 100644 --- a/src/events/RE/reNickname.js +++ b/src/events/RE/reNickname.js @@ -1171,10 +1171,10 @@ App.Events.RENickname = class RENickname extends App.Events.BaseEvent { applyDesc: `knows that you've noticed all ${his} hard work. Getting fucked day in and day out is harder than digging ditches, and ${he}'s a veteran ditchdigger.`, notApplyDesc: `understands that even though ${he}'s been fucked so much, ${he}'s still just meat; ${he} isn't special.`, }); - if (slave.energy > 95) { + if (slave.intelligence + slave.intelligenceImplant > 50) { nickMap.set("smartveteran", { nicknameArray: ["Cumdump Library", "Cumbucket Dictionary", "Dr. Whore-Pussy", "Professor Loosepussy", "Geeky Cumguzzler", "Nerdy Cumdump", "Cumguzzling Dweeb", "Public Fanny-Book", "Scholarly Cumhole", "Straight-A Cumbucket", "Veteran Sex Disciple", "Cum Beaker", "Lascivious Sage"], - situationDesc: `has been with you for a while, and ${he}'s gotten fucked hundreds of times over several weeks. ${He} treats every sexual encounter seems like an academic challenge. By researching and experimenting with the anatomy of ${his} body, ${he} has greater understanding of satisfying the sexual cravings of others. Other slaves tease ${him} for ${his} unusually academic approcach to sexual servitude.`, + situationDesc: `has been with you for a while, and ${he}'s gotten fucked hundreds of times over several weeks. ${He} treats every sexual encounter seems like an academic challenge. By researching and experimenting with the anatomy of ${his} body, ${he} has greater understanding of satisfying the sexual cravings of others. Other slaves tease ${him} for ${his} unusually academic approach to sexual servitude.`, applyDesc: `is delighted that you've noticed ${his} hard work in learning about the pleasures of the flesh. ${He} recognizes that the best way to expand ${his} knowledge is through experience, ${his} mind and body are the perfect apparatus to obtain plenty of sexual experience.`, notApplyDesc: `understands that despite ${his} intelligence and sexual experience, ${he} isn't special.`, }); diff --git a/src/events/RECI/adoptFollowUp.js b/src/events/RECI/adoptFollowUp.js new file mode 100644 index 0000000000000000000000000000000000000000..a4fa9b9fc477161927bb0b67acf927264df2e281 --- /dev/null +++ b/src/events/RECI/adoptFollowUp.js @@ -0,0 +1,86 @@ +App.Events.RECIAdoptFollowUp = class RECIAdoptFollowUp extends App.Events.BaseEvent { + eventPrerequisites() { + return []; // always valid if sufficient actors can be cast successfully + } + + actorPrerequisites() { // single event slave + return [ + [ + s => s.fetish !== Fetish.MINDBROKEN, + s => this.validSlave(s), + s => s.devotion >= 50, + s => s.trust >= 50, + ] + ]; + }; + + validSlave(slave) { + return V.RECheckInIDs.some((a) => (a.ID === slave.ID && a.type === "adoptFollowUp")); + } + + get weight() { return 5; }; // given the very restrictive qualifiers, give it a bit more weight. + + execute(node) { + /** @type {Array<App.Entity.SlaveState>} */ + const [eventSlave] = this.actors.map(a => getSlave(a)); + const { title: Master } = getEnunciation(eventSlave); + const { He, he, His, his, him } = getPronouns(eventSlave); + V.RECheckInIDs.deleteWith((s) => s.ID === eventSlave.ID && s.type === "adoptFollowUp"); + App.Events.drawEventArt(node, eventSlave); + + App.Events.addNode(node, [ + `While in your office, you receive an unscheduled visit from ${eventSlave.slaveName}.`, + `${He} seems a bit nervous and before you can ask ${him} what ${he} wants,`, + `${he} suddenly ${canTalk(eventSlave) ? `blurts out`: `attempts to convey via sign language`} a speech that seems half-prepared and half-rambling.`, + ], "p"); + + if (canTalk(eventSlave)) { + App.Events.addNode(node, [`"${Spoken(eventSlave, + `Thank you for adopting me, ${Master}! + I'm so grateful that you took me in! + Everything was bad before, I could barely get food and didn't know where I was or what to do. + You have taught me so much! + At first I thought doing the things you wanted was horrible and disgusting, but you gave me such a good life! + I don't care if I have to get fucked all the time, it's fun anyway! + I love being with you ${Master}, you made my life so much better! + You're... you're everything to me!` + )}"`], "p"); + } else { + App.Events.addNode(node, [`Profusely thanking you for adopting ${him} and how ${his} life has improved since then, despite a rocky start.`], "p"); + } + + App.Events.addResponses(node, [ + new App.Events.Result(`Reward ${him} with a loving fuck`, love, (eventSlave.anus === 0 || eventSlave.vagina === 0) ? App.UI.DOM.makeElement("span", `Virginity will be lost`, ["yellow"]) : ``), + new App.Events.Result(`This slave has forgotten ${his} place`, rape, (eventSlave.anus === 0 || eventSlave.vagina === 0) ? App.UI.DOM.makeElement("span", `Virginity will be lost`, ["yellow"]) : ``), + ]); + + function love() { + SimpleSexAct.Player(eventSlave); + eventSlave.devotion += 5; + eventSlave.trust += 5; + return App.Events.addNode(node, [ + VCheck.Simple(eventSlave), + `Wordlessly, you move towards ${eventSlave.slaveName}, who flinches slightly at your sudden presence.`, + `You grip ${his} hips, pulling ${him} in close.`, + `${His} face is beet red, and you can feel ${his} heart beating against your chest.`, + `You kiss ${him} deeply before pressing ${his} against a nearby wall and lifting ${him} so you can hilt your ${V.PC.dick > 0 ? 'cock' : 'strap-on'} deep inside.`, + `You make <span class="trust inc">slow and gentle love</span> to ${him}, savoring every moment.`, + `When you finally cum inside and gently lower ${him} back down onto the floor, ${he} hugs you and ${canTalk(eventSlave) ? `whispers,`: `stares`}`, + `"<span class="devotion inc">${canTalk(eventSlave) ? Spoken(eventSlave, `I love you, ${Master}.`) : `into your eyes lovingly.`}</span>"`, + ]); + }; + + function rape() { + SimpleSexAct.Player(eventSlave); + eventSlave.devotion -= 5; + eventSlave.trust -= 5; + return App.Events.addNode(node, [ + VCheck.Simple(eventSlave), + `You abruptly stand up from your desk and explain to ${eventSlave.slaveName} that you didn't adopt ${him}... You enslaved ${him}, and that ${he} needs to learn ${his} place and the difference.`, + `You grab ${him} and <span class="trust dec">roughly throw</span> ${him} onto the nearby couch before grabbing ${him} by the neck and shoving ${his} head into the cushions.`, + `You penetrate ${him} hard, without warning, and proceed to rape ${him} like ${he}'s never been raped before.`, + `<span class="devotion dec">By the time you are done,</span> ${he} is a whimpering, sobbing mess with a gaped out hole.`, + ]); + }; + }; +}; diff --git a/src/events/REFS/refsYouthPreferentialistEncounter.js b/src/events/REFS/refsYouthPreferentialistEncounter.js index f8e7adb43b5be53f1f7410a3863b8744d7ce0147..7ba6dbb5fa1b40e5bd4b08dba4c8346c3eaae445 100644 --- a/src/events/REFS/refsYouthPreferentialistEncounter.js +++ b/src/events/REFS/refsYouthPreferentialistEncounter.js @@ -86,7 +86,7 @@ App.Events.refsYouthPreferentialistEncounter = class refsYouthPreferentialistEnc function enslave() { cashX(-enslaveCost, "event", slave); return [ - `After ${he} regains ${his} bearings from your sexual encounter, the ${girl} slips on ${his} simple clothes and attempts to slink away from your private suite unobtrusively. ${He} makes it out the door before being confronted by a glowing array of wallscreen monitors, each displaying a visual representation of your purchase of ${his} father's considerable debt and subsequent enslavement of ${him} on the basis of that debt. Tears begin to stream down ${his} cheeks as ${he} sinks to ${hasBothLegs(slave)? `${his} knees` : "the floor"}, ${his} hopes of a long life without enslavement now dashed.`, + `After ${he} regains ${his} bearings from your sexual encounter, the ${girl} slips on ${his} simple clothes and attempts to slink away from your private suite unobtrusively. ${He} makes it out the door before being confronted by a glowing array of wallscreen monitors, each displaying a visual representation of your purchase of ${his} father's considerable debt and subsequent enslavement of ${him} on the basis of that debt. Tears begin to stream down ${his} cheeks as ${he} sinks to ${hasBothLegs(slave) ? `${his} knees` : "the floor"}, ${his} hopes of a long life without enslavement now dashed.`, App.UI.newSlaveIntro(slave) ]; } diff --git a/src/events/RESS/review/breastExpansionBlues.js b/src/events/RESS/review/breastExpansionBlues.js index 3f8a250c2a058502af301d9a09950e6c5e166a97..1cba9e4142b6e4df0a13eef9d3bc95315bcce3a9 100644 --- a/src/events/RESS/review/breastExpansionBlues.js +++ b/src/events/RESS/review/breastExpansionBlues.js @@ -76,11 +76,11 @@ App.Events.RESSBreastExpansionBlues = class RESSBreastExpansionBlues extends App } else { r.push(`rivulet of cream running from`); } - r.push(`it right now`); + r.push(`it right now.`); } else if (eventSlave.preg > eventSlave.pregData.normalBirth/2.66) { - r.push(`${He} complained of feeling like a cow without detectable irony, despite the fact that ${he} is pregnant and likely to begin lactating soon`); + r.push(`${He} complained of feeling like a cow without detectable irony, despite the fact that ${he} is pregnant and likely to begin lactating soon.`); } - r.addToLast(`. ${He} waits anxiously for your response, wondering if ${he}'ll be punished for expressing reservations about your expansion of ${his} breasts and, comically, still cradling ${his} heavy udders as ${he} does so.`); + r.push(`${He} waits anxiously for your response, wondering if ${he}'ll be punished for expressing reservations about your expansion of ${his} breasts and, comically, still cradling ${his} heavy udders as ${he} does so.`); r.toParagraph(); App.Events.addResponses(node, [ diff --git a/src/events/RESS/review/sexySuccubus.js b/src/events/RESS/review/sexySuccubus.js index 794d83e57610f18bb8af1655b5ae6bb90f2f6b1c..815400448c3393aaab91e25713c5cbc223bb556e 100644 --- a/src/events/RESS/review/sexySuccubus.js +++ b/src/events/RESS/review/sexySuccubus.js @@ -28,7 +28,7 @@ App.Events.RESSSexySuccubus = class RESSSexySuccubus extends App.Events.BaseEven const PC = V.PC; const {heP, himP, womanP, hisP} = getPronouns(PC).appendSuffix("P"); - App.Events.drawEventArt(node, eventSlave, "no clothing"); + App.Events.drawEventArt(node, eventSlave); let r = []; r.push( diff --git a/src/events/RESS/tooThinForCumDiet.js b/src/events/RESS/tooThinForCumDiet.js index 0a4e43512c20ab33b88357d46c7092d827d7638a..d80136c54249c9fe2039b5e2927015a27b0ae826 100644 --- a/src/events/RESS/tooThinForCumDiet.js +++ b/src/events/RESS/tooThinForCumDiet.js @@ -223,7 +223,7 @@ App.Events.RESSTooThinForCumDiet = class RESSTooThinForCumDiet extends App.Event } else { t.push(`self`); } - t.push(`inside ${his} butt-hole and subdue ${his} weak, struggling body against your unforgiving desk. <span class="trust dec">Horrified tears</span> stream down ${his} face with each brutal thrust as you speak into ${his} ear and remind ${him} that slaves are not allowed to dictate their needs to their owners. You know what's best for ${him}, and right now, ${his} proper role is as an eager little depository for the products of the free-cities ejaculate market. It's ${his} job to suck down cum at the whim of ${his} owner, plain and simple, until ${he}'s told otherwise. You butt-fuck the cum-fed slag until ${he} simply lays there and accepts ${his} corrective assrape.`); + t.push(`inside ${his} butthole and subdue ${his} weak, struggling body against your unforgiving desk. <span class="trust dec">Horrified tears</span> stream down ${his} face with each brutal thrust as you speak into ${his} ear and remind ${him} that slaves are not allowed to dictate their needs to their owners. You know what's best for ${him}, and right now, ${his} proper role is as an eager little depository for the products of the free cities' ejaculate market. It's ${his} job to suck down cum at the whim of ${his} owner, plain and simple, until ${he}'s told otherwise. You buttfuck the cum-fed slag until ${he} simply lays there and accepts ${his} corrective assrape.`); if (eventSlave.anus === 0) { t.push(`<span class="virginity loss">${His} ${eventSlave.butt < 5 ? 'skinny' : 'plump'} little ass is now broken in.</span>`); } diff --git a/src/events/RESS/waistlineWoes.js b/src/events/RESS/waistlineWoes.js index c33ca883c5390f9152e0e5961a2f0466c01f190c..b85188d1a07a26187ba79f0131189c10a7399859 100644 --- a/src/events/RESS/waistlineWoes.js +++ b/src/events/RESS/waistlineWoes.js @@ -56,7 +56,7 @@ App.Events.RESSWaistlineWoes = class RESSWaistlineWoes extends App.Events.BaseEv case "a gothic lolita dress": case "a hanbok": if (canTalk(eventSlave)) { - t.push(Spoken(eventSlave, `"This outift feels tight around my middle, I feel like it fit last week..."`)); + t.push(Spoken(eventSlave, `"This outfit feels tight around my middle, I feel like it fit last week..."`)); t.push(He); } t.push(`adjusts ${his} clothing, clearly uncomfortable.`); @@ -147,14 +147,14 @@ App.Events.RESSWaistlineWoes = class RESSWaistlineWoes extends App.Events.BaseEv break; case "restrictive latex": if (canTalk(eventSlave)) { - t.push(Spoken(eventSlave, `"I know it's suppose to be tight, but I feel like a sausage..."`)); + t.push(Spoken(eventSlave, `"I know it's supposed to be tight, but I feel like a sausage..."`)); t.push(He); } t.push(`tugs at the restrictive latex, clearly uncomfortable for reasons outside their intent.`); break; case "a penitent nuns habit": if (canTalk(eventSlave)) { - t.push(Spoken(eventSlave, `"I know it's suppose to be tight, but I feel like a sausage..."`)); + t.push(Spoken(eventSlave, `"I know it's supposed to be tight, but I feel like a sausage..."`)); t.push(He); } t.push(`gingerly tugs at ${his} coarse habit, clearly uncomfortable for reasons other than the chafing.`); diff --git a/src/events/RETS/reFucktoyPrefersRelative.js b/src/events/RETS/reFucktoyPrefersRelative.js index 9cc5a37c17dce51c85ff2c7d907931f055d2b49c..b6be3e3034fe318cb094a77865e409945f71b38d 100644 --- a/src/events/RETS/reFucktoyPrefersRelative.js +++ b/src/events/RETS/reFucktoyPrefersRelative.js @@ -63,6 +63,10 @@ App.Events.RETSFucktoyPrefersRelative = class RETSFucktoyPrefersRelative extends fuckhole = "mouth"; } } + if (fuckhole === "dick" && V.PC.vagina <= 0 && V.PC.anus === 0) { + // prevent loss of player virginity from this scene + fuckhole = "mouth"; + } let t = []; t.push(`You're enjoying`, contextualIntro(V.PC, fucktoy, true), `one evening in your office when`, contextualIntro(fucktoy, relative, true), `passes by stark naked (probably on ${his2} way to or from the shower). The glass walls of your office are designed to let you, and by extension everyone else inside, clearly see everything that happens in the rest of the Penthouse, as well as the comings and goings of all your slaves.`); @@ -77,6 +81,7 @@ App.Events.RETSFucktoyPrefersRelative = class RETSFucktoyPrefersRelative extends } else { t.push(`thrusting a strap-on deep into ${his} pussy. You pause your thrusts as ${he} gasps and twitches, cumming hard.`); } + seX(V.PC, "penetrative", fucktoy, "vaginal"); break; case "ass": if (V.PC.dick > 0) { @@ -84,6 +89,7 @@ App.Events.RETSFucktoyPrefersRelative = class RETSFucktoyPrefersRelative extends } else { t.push(`thrusting a strap-on deep into ${his} ass. You pause your thrusts as ${he} gasps and twitches, cumming hard.`); } + seX(V.PC, "penetrative", fucktoy, "anal"); break; case "mouth": if (V.PC.dick > 0) { @@ -91,6 +97,7 @@ App.Events.RETSFucktoyPrefersRelative = class RETSFucktoyPrefersRelative extends } else { t.push(`thrusting a strap-on deep into ${his} throat. ${His} motions waver as ${he} twitches, cumming hard.`); } + seX(V.PC, "penetrative", fucktoy, "oral"); break; case "boobs": if (V.PC.dick > 0) { @@ -100,6 +107,7 @@ App.Events.RETSFucktoyPrefersRelative = class RETSFucktoyPrefersRelative extends } else { t.push(`teasing ${his} flat chest. ${He} gasps and twitches, cumming hard.`); } + seX(V.PC, "penetrative", fucktoy, "mammary"); break; case "dick": t.push(`riding ${him}. ${He} groans as ${he} unexpectedly cums hard, filling you up.`); @@ -108,6 +116,9 @@ App.Events.RETSFucktoyPrefersRelative = class RETSFucktoyPrefersRelative extends t.push(`You wonder briefly if ${he} might have just gotten you pregnant.`); knockMeUp(V.PC, 5, 0, fucktoy.ID); } + seX(V.PC, "vaginal", fucktoy, "penetrative"); + } else { + seX(V.PC, "anal", fucktoy, "penetrative"); } break; default: diff --git a/src/events/intro/acquisition.js b/src/events/intro/acquisition.js index a27ad28d5a1ced8ccabad67d8477aea502d62cc6..4cd319a4378b44ee8447cf66fbd65586e2197d13 100644 --- a/src/events/intro/acquisition.js +++ b/src/events/intro/acquisition.js @@ -21,7 +21,6 @@ App.Intro.acquisition = function() { V.arcologies.reduce((acc, val) => (val.direction !== 0 && val.prosperity > acc.prosperity) ? val : acc, V.arcologies[1]).rival = 1; V.rival.state = 2; } - V.targetAge = V.minimumSlaveAge; V.targetAgeNursery = V.minimumSlaveAge; resetFamilyCounters(); diff --git a/src/events/randomEvent.js b/src/events/randomEvent.js index 4cd1f7f9f0eac790c9270089237279c18d3ac92e..448e75a74401df3ec809e00d3304fb1ceccd0f47 100644 --- a/src/events/randomEvent.js +++ b/src/events/randomEvent.js @@ -155,6 +155,7 @@ App.Events.getIndividualEvents = function() { new App.Events.RESSWetDreams(), new App.Events.RESSWhoreRebellious(), + new App.Events.RECIAdoptFollowUp(), new App.Events.RECIButthole(), new App.Events.RECIFeminization(), new App.Events.RECIFuta(), diff --git a/src/events/scheduled/sePlayerBirth.js b/src/events/scheduled/sePlayerBirth.js index dbb6ab0a0a264ca24305d4369afce116af7a8b7f..6f3e3db780c8fb2cd78af0bdb42bba694591bc5c 100644 --- a/src/events/scheduled/sePlayerBirth.js +++ b/src/events/scheduled/sePlayerBirth.js @@ -798,7 +798,7 @@ App.Events.SEPlayerBirth = class SEPlayerBirth extends App.Events.BaseEvent { } r.push(`aside for incubation.</span>`); if (V.incubator.tanks.length < V.incubator.capacity) { - App.Facilities.Incubator.newChild(generateChild(V.PC, birthed[0], true)); + App.Facilities.Incubator.newChild(generateChild(V.PC, birthed[0], true), birthed[0].tankSetting); } } else if (birthed[0].reserve === "nursery") { r.push(`<span class="pink">You set`); @@ -905,7 +905,7 @@ App.Events.SEPlayerBirth = class SEPlayerBirth extends App.Events.BaseEvent { } r.push(`aside for incubation.</span>`); if (V.incubator.tanks.length < V.incubator.capacity) { - App.Facilities.Incubator.newChild(generateChild(V.PC, birthed[p], true)); + App.Facilities.Incubator.newChild(generateChild(V.PC, birthed[p], true), birthed[p].tankSetting); } birthed.splice(birthed[p], 1); p--; diff --git a/src/facilities/brothel/brothel.js b/src/facilities/brothel/brothel.js index 3da97050d2eb3e941ee66d3c06d68f03d40a6922..5fc1122f4760a117878132a2619995a6c8938c4f 100644 --- a/src/facilities/brothel/brothel.js +++ b/src/facilities/brothel/brothel.js @@ -40,6 +40,7 @@ App.Facilities.Brothel.brothel = class Brothel extends App.Facilities.Facility { "Edo Revivalist": `is furnished as an Edo period pleasure house, seedy by the standards of the time. Still, girls usually keep their clothes on until they lead patrons back behind the sliding paper screens, though this does not stop silhouettes of the activities within from being visible on them.`, "Arabian Revivalist": `is furnished as an Arabian fleshmarket, with the merchandise standing on little platforms, prices visible. Customers are permitted to fondle before making a decision and dragging a girl back behind a curtain.`, "Chinese Revivalist": `is furnished as an old Chinese pleasure house, with each girl set up in her own low room. They stand outside the doors, luring customers back one by one.`, + "Antebellum Revivalist": `is furnished as an old-fashioned Southern bordello, all dark wood and red velvet. Corseted courtesans fan themselves languidly in the foyer as they entice their customers.`, // quick fix, feel free to rewrite "Chattel Religionist": `is decorated as a place of carnal worship. The air is scented by censers, and the slaves here maintain an air of holiness even when being sodomized in public.`, "Degradationist": `is decorated to look like a dungeon. The décor involves a lot of black leather and burnished steel, and the slaves on offer are mostly chained to beds and walls.`, "Repopulationist": `is clean and full of soft couches and chairs for its pregnant whores to lounge upon while showing off their assets. Several of the rooms are prepped to allow a whore to give birth in front of an audience. A supply of freshly squeezed breast milk is available on tap.`, diff --git a/src/facilities/dairy/freeRangeDairyAssignmentScene.js b/src/facilities/dairy/freeRangeDairyAssignmentScene.js index 392d26d9064dbc49fadd08cf618b01742f19b04d..b6ee3b96847280c50b324904b6cb9f84418d0c61 100644 --- a/src/facilities/dairy/freeRangeDairyAssignmentScene.js +++ b/src/facilities/dairy/freeRangeDairyAssignmentScene.js @@ -303,7 +303,7 @@ App.Facilities.Dairy.freeRangeAssignmentScene = function(slave) { if (slave.fetish === "buttslut" || slave.sexualFlaw === "anal addict") { r.push(`${He} shudders with joy.`); } - r.push(`Soon, the automatic sodomizer pumps the dildo in and out of ${his} butt-hole.`); + r.push(`Soon, the automatic sodomizer pumps the dildo in and out of ${his} butthole.`); if (slave.balls > 0 && slave.scrotum > 0) { r.push(`${His}`); if (slave.balls > 5 ) { diff --git a/src/facilities/incubator/incubatorInteract.js b/src/facilities/incubator/incubatorInteract.js index a12235ab1e82952a107e3fbb2376a897182967cd..8f0adabf99a22d2b861d81c1e354ca87712a8682 100644 --- a/src/facilities/incubator/incubatorInteract.js +++ b/src/facilities/incubator/incubatorInteract.js @@ -28,7 +28,7 @@ App.UI.incubator = function() { tabBar.addTab("You", "pc", pcContent); } tabBar.addTab("Tanks", "tanks", tanksContent); - tabBar.addTab("Settings", "settings", settingsContent); + tabBar.addTab("Default Settings", "settings", settingsContent); el.append(tabBar.render()); introDiv.after(release()); // run me late. @@ -123,7 +123,38 @@ App.UI.incubator = function() { el.append(tankP); + /* Bulk or individual release */ + let section = document.createElement("p"); + if (V.incubator.bulkRelease === 1) { + section.append(`Released children will be handled in bulk and not receive personal attention. `); + section.append( + App.UI.DOM.link( + `Individual release`, + () => { + V.incubator.bulkRelease = 0; + refresh(); + } + ) + ); + } else { + section.append(`Released children will be seen to personally. `); + section.append( + App.UI.DOM.link( + `Bulk release`, + () => { + V.incubator.bulkRelease = 1; + refresh(); + } + ) + ); + } + el.append(section); + return el; + + function refresh() { + jQuery(introDiv).empty().append(intro()); + } } function mothers() { @@ -250,6 +281,7 @@ App.UI.incubator = function() { } else { r.push(`baby.`); } + if (reservedIncubator > 0) { childrenReserved = 1; if (WL === 1) { @@ -765,7 +797,7 @@ App.UI.incubator = function() { r.push(`as it appears ${his} womb is sterile.`); } } - if ((V.incubator.setting.pregAdaptation === 1 && V.incubator.tanks[i].genes === "XX") || (V.incubator.setting.pregAdaptation === 2 && V.incubator.tanks[i].genes === "XY") || V.incubator.setting.pregAdaptation === 3) { + if (V.incubator.tanks[i].incubatorSettings.pregAdaptation === 1) { r.push(`There are probes and tubes inserted inside ${his} reproductive organs so ${V.incubator.name} may work on them.`); const safeCC = (V.incubator.tanks[i].pregAdaptation - 5) * 2000; if (safeCC > 300000) { @@ -790,11 +822,11 @@ App.UI.incubator = function() { } } App.Events.addNode(p, r, "div"); - if (V.incubator.tanks[i].growTime <= 0) { + if (V.incubator.tanks[i].incubatorSettings.growTime <= 0) { V.incubator.readySlaves = 1; appendRow(p, `${He} is ready to be released from ${his} tank.`); } else { - const weekDisplay = Math.ceil(V.incubator.tanks[i].growTime / V.incubator.upgrade.speed); + const weekDisplay = Math.ceil(V.incubator.tanks[i].incubatorSettings.growTime / V.incubator.upgrade.speed); appendRow(p, `${His} growth is currently being accelerated. ${He} will be ready for release in about ${weekDisplay} ${(weekDisplay > 1) ? `weeks` : `week`}.`); } @@ -813,49 +845,49 @@ App.UI.incubator = function() { if (V.incubator.upgrade.weight === 1) { - if (V.incubator.setting.weight === 1) { + if (V.incubator.tanks[i].incubatorSettings.weight === 1) { appendRow(p, `${His} weight is not being properly managed, saving costs but likely causing excessive weight gain.`); - } else if (V.incubator.setting.weight === 2) { + } else if (V.incubator.tanks[i].incubatorSettings.weight === 2) { appendRow(p, `${His} weight is being carefully managed; ${he} will be released at a healthy weight.`); - } else if (V.incubator.setting.weight === 0) { + } else if (V.incubator.tanks[i].incubatorSettings.weight === 0) { appendRow(p, `Weight management systems are offline; ${he} will likely be malnourished.`); } } if (V.incubator.upgrade.muscles === 1) { - if (V.incubator.setting.muscles === 2) { + if (V.incubator.tanks[i].incubatorSettings.muscles === 2) { appendRow(p, `${His} strength levels are purposefully set higher than recommended; ${he} is likely to have excessive musculature.`); - } else if (V.incubator.setting.muscles === 1) { + } else if (V.incubator.tanks[i].incubatorSettings.muscles === 1) { appendRow(p, `${His} musculature is being carefully managed; ${he} will be released with near normal strength.`); - } else if (V.incubator.setting.muscles === 0) { + } else if (V.incubator.tanks[i].incubatorSettings.muscles === 0) { appendRow(p, `Strength management systems are offline; ${he} will likely be released extremely weak.`); } } if (V.incubator.upgrade.growthStims === 1) { - if (V.incubator.setting.growthStims === 2) { + if (V.incubator.tanks[i].incubatorSettings.growthStims === 2) { appendRow(p, `${He} is being injected with higher than recommended doses of stimulants; ${he} is likely to be much taller than expected.`); - } else if (V.incubator.setting.growthStims === 1) { + } else if (V.incubator.tanks[i].incubatorSettings.growthStims === 1) { appendRow(p, `${He} is injected with the recommended dosage of stimulants; ${he} will grow to ${his} full expected height.`); - } else if (V.incubator.setting.growthStims === 0) { + } else if (V.incubator.tanks[i].incubatorSettings.growthStims === 0) { appendRow(p, `Growth stimulant injection systems are offline; ${he} will develop normally.`); } } if (V.incubator.upgrade.reproduction === 1) { - if (V.incubator.setting.reproduction === 2) { + if (V.incubator.tanks[i].incubatorSettings.reproduction === 2) { appendRow(p, `${His} hormone levels are purposefully set higher than recommended; ${his} reproductive systems are likely to be over-active.`); - } else if (V.incubator.setting.reproduction === 1) { + } else if (V.incubator.tanks[i].incubatorSettings.reproduction === 1) { appendRow(p, `${His} hormone levels are being carefully managed; ${he} will be released with fully functional reproductive organs.`); - } else if (V.incubator.setting.reproduction === 0) { + } else if (V.incubator.tanks[i].incubatorSettings.reproduction === 0) { appendRow(p, `Reproduction management systems are offline; ${he} will undergo normal puberty.`); } - if ((V.incubator.setting.pregAdaptation === 1 && V.incubator.tanks[i].genes === "XX") || (V.incubator.setting.pregAdaptation === 2 && V.incubator.tanks[i].genes === "XY") || V.incubator.setting.pregAdaptation === 3) { + if (V.incubator.tanks[i].incubatorSettings.pregAdaptation === 1) { /* Should be visible only after incubator.setting.reproduction is installed and activated*/ r = []; r.push(`${His} reproductive organs are getting`); - if (V.incubator.setting.pregAdaptationPower === 1) { + if (V.incubator.tanks[i].incubatorSettings.pregAdaptationPower === 1) { r.push(`an advanced`); - } else if (V.incubator.setting.pregAdaptationPower === 2) { + } else if (V.incubator.tanks[i].incubatorSettings.pregAdaptationPower === 2) { r.push(`an intensive`); - } else if (V.incubator.setting.pregAdaptationPower === 3) { + } else if (V.incubator.tanks[i].incubatorSettings.pregAdaptationPower === 3) { r.push(`an extreme`); } else { r.push(`a standard`); @@ -888,6 +920,7 @@ App.UI.incubator = function() { () => { V.readySlave = V.incubator.tanks[i]; V.incubator.tanks.splice(i, 1); + release(); }, [], "Incubator Retrieval Workaround" @@ -1012,6 +1045,20 @@ App.UI.incubator = function() { App.Events.addNode(p, r, "div"); } } + + App.UI.DOM.appendNewElement( + "div", + p, + App.UI.DOM.link( + `Inspect tank settings`, + () => { + V.AS = i; + }, + [], + `Inspect Tank Settings` + ) + ); + el.append(p); } } @@ -1033,91 +1080,9 @@ App.UI.incubator = function() { function tankSettings() { const el = new DocumentFragment(); - let div; - let r = []; - let section; - let linkArray; - r.push("Target age for release:"); - r.push( - App.UI.DOM.makeTextBox( - V.targetAge, - (v) => { - V.targetAge = v || V.minimumSlaveAge; - V.targetAge = Math.clamp(V.targetAge, V.minimumSlaveAge, V.retirementAge); - refresh(); - }, - true - ) - ); - linkArray = []; - linkArray.push( - App.UI.DOM.link( - `Minimum Legal Age`, - () => { - V.targetAge = V.minimumSlaveAge; - refresh(); - } - ) - ); - linkArray.push( - App.UI.DOM.link( - `Average Age of Fertility`, - () => { - V.targetAge = V.fertilityAge; - refresh(); - } - ) - ); - linkArray.push( - App.UI.DOM.link( - `Average Age of Potency`, - () => { - V.targetAge = V.potencyAge; - refresh(); - } - ) - ); - linkArray.push( - App.UI.DOM.link( - `Legal Adulthood`, - () => { - V.targetAge = 18; - refresh(); - } - ) - ); - r.push(App.UI.DOM.generateLinksStrip(linkArray)); - r.push(App.UI.DOM.makeElement("span", `Setting will not be applied to tanks in use.`, ["note"])); - App.Events.addNode(el, r, "p"); - - section = document.createElement("p"); - if (V.incubator.setting.bulkRelease === 1) { - section.append(`Released children will be handled in bulk and not receive personal attention. `); - section.append( - App.UI.DOM.link( - `Individual release`, - () => { - V.incubator.setting.bulkRelease = 0; - refresh(); - } - ) - ); - } else { - section.append(`Released children will be seen to personally. `); - section.append( - App.UI.DOM.link( - `Bulk release`, - () => { - V.incubator.setting.bulkRelease = 1; - refresh(); - } - ) - ); - } - el.append(section); - - section = document.createElement("div"); + /* Growth acceleration */ + let section = document.createElement("p"); if (V.incubator.upgrade.speed === 52) { section.append(`It has been upgraded with perfected growth accelerants; children grow at the rate of 1 week to 1 year.`); } else if (V.incubator.upgrade.speed === 18) { @@ -1169,34 +1134,13 @@ App.UI.incubator = function() { }) ); } - el.append(section); - div = document.createElement("div"); - section = document.createElement("div"); + + /* Weight monitoring */ + section = document.createElement("p"); if (V.incubator.upgrade.weight === 1) { section.append(`Advanced caloric monitoring systems have been installed in the tanks to monitor and maintain a developing child's weight.`); - div.append(section); - section = document.createElement("div"); - linkArray = []; - if (V.incubator.setting.weight === 1) { - section.append(`Weight is not being properly managed; excessive weight gain is likely.`); - } else { - linkArray.push(makeLink(`Estimate only`, () => { V.incubator.setting.weight = 1; }, refresh)); - } - - if (V.incubator.setting.weight === 2) { - section.append(`Weight is being carefully managed; children will be released at a healthy weight.`); - } else { - linkArray.push(makeLink(`Activate`, () => { V.incubator.setting.weight = 2; }, refresh)); - } - - if (V.incubator.setting.weight === 0) { - section.append(`Weight management systems are offline; children will likely be malnourished.`); - } else { - linkArray.push(makeLink(`Disable`, () => { V.incubator.setting.weight = 0; }, refresh)); - } - section.append(" ", App.UI.DOM.generateLinksStrip(linkArray)); } else { const cost = Math.trunc(20000 * V.upgradeMultiplierArcology); section.append(`There are no systems in place to control a growing child's weight; they will likely come out emaciated from the rapid growth.`); @@ -1210,37 +1154,13 @@ App.UI.incubator = function() { }) ); } + el.append(section); - div.append(section); - el.append(div); - - div = document.createElement("div"); - section = document.createElement("div"); + /* Muscles */ + section = document.createElement("p"); if (V.incubator.upgrade.muscles === 1) { section.append(`Advanced monitoring and steroid injection systems have been installed in the tanks to monitor and maintain a developing child's musculature.`); - div.append(section); - section = document.createElement("div"); - linkArray = []; - if (V.incubator.setting.muscles === 2) { - section.append(`Strength levels are purposefully set higher than recommended; excessive muscle gain is likely.`); - } else { - linkArray.push(makeLink(`Overload`, () => { V.incubator.setting.muscles = 2; }, refresh)); - } - - if (V.incubator.setting.muscles === 1) { - section.append(`Musculature is being carefully managed; children will be released with near normal strength.`); - } else { - linkArray.push(makeLink(`Activate`, () => { V.incubator.setting.muscles = 1; }, refresh)); - } - - if (V.incubator.setting.muscles === 0) { - section.append(`Strength management systems are offline; children will likely be released extremely weak.`); - } else { - linkArray.push(makeLink(`Disable`, () => { V.incubator.setting.muscles = 0; }, refresh)); - } - - section.append(" ", App.UI.DOM.generateLinksStrip(linkArray)); } else { const cost = Math.trunc(20000 * V.upgradeMultiplierArcology); section.append(`There are no systems in place to control a growing child's musculature; they will likely come out frail and weak from the rapid growth.`); @@ -1254,106 +1174,35 @@ App.UI.incubator = function() { }) ); } + el.append(section); - div.append(section); - el.append(div); - div = document.createElement("div"); - section = document.createElement("div"); + /* Height */ + section = document.createElement("p"); + if (V.incubator.upgrade.growthStims === 1) { + section.append(`Advanced monitoring and stimulant injection systems have been installed in the tanks to monitor and maintain a developing child's height.`); + } else if (V.growthStim === 1) { + const cost = Math.trunc(20000 * V.upgradeMultiplierArcology); + section.append(`There are no systems in place to control a growing child's height.`); + section.append( + makePurchase(`Upgrade the growth tanks with stimulants injection systems`, cost, "capEx", { + handler: () => { + V.incubator.upgrade.growthStims = 1; + refresh(); + }, + notes: [`will increase upkeep costs`] + }) + ); + } else { + App.UI.DOM.appendNewElement("span", section, `There are no systems in place to control a growing child's height and you lack the capability to fabricate growth stimulants.`, ["note"]); + } + el.append(section); + + /* Reproductive system */ + section = document.createElement("p"); if (V.incubator.upgrade.reproduction === 1) { section.append(`Advanced monitoring and hormone injection systems have been installed in the tanks to influence a developing child's reproductive organs.`); - div.append(section); - section = document.createElement("div"); - linkArray = []; - if (V.incubator.setting.reproduction === 2) { - section.append(`Hormone levels are purposefully set higher than recommended; over-active reproductive systems are likely.`); - } else { - linkArray.push(makeLink(`Overload`, () => { V.incubator.setting.reproduction = 2; }, refresh)); - } - - if (V.incubator.setting.reproduction === 1) { - section.append(`Hormone levels are being carefully managed; children will be released with fully functional reproductive organs.`); - } else { - linkArray.push(makeLink(`Limit`, () => { V.incubator.setting.reproduction = 1; }, refresh)); - } - - if (V.incubator.setting.reproduction === 0) { - section.append(`Reproduction management systems are offline; children will undergo normal puberty.`); - } else { - linkArray.push(makeLink(`Disable`, () => { V.incubator.setting.reproduction = 0; }, refresh)); - } - section.append(" ", App.UI.DOM.generateLinksStrip(linkArray)); - div.append(section); - el.append(div); - - if (V.incubator.upgrade.pregAdaptation === 1) { - // Should be visible only after incubator.upgrade.reproduction is installed - div = document.createElement("div"); - section = document.createElement("div"); - linkArray = []; - if (V.incubator.setting.pregAdaptation === 3) { - section.append(`Pregnancy adaptation system online: All.`); - } else { - linkArray.push(makeLink(`All`, () => { V.incubator.setting.pregAdaptation = 3; }, refresh)); - } - - if (V.incubator.setting.pregAdaptation === 2) { - section.append(`Pregnancy adaptation system online: Males only.`); - } else { - linkArray.push(makeLink(`Males`, () => { V.incubator.setting.pregAdaptation = 2; }, refresh)); - } - - if (V.incubator.setting.pregAdaptation === 1) { - section.append(`Pregnancy adaptation system online: Females only.`); - } else { - linkArray.push(makeLink(`Females`, () => { V.incubator.setting.pregAdaptation = 1; }, refresh)); - } - - if (V.incubator.setting.pregAdaptation === 0) { - section.append(`Pregnancy adaptation system offline.`); - } else { - linkArray.push(makeLink(`Disable`, () => { V.incubator.setting.pregAdaptation = 0; }, refresh)); - } - section.append(" ", App.UI.DOM.generateLinksStrip(linkArray)); - - if (V.incubator.upgrade.pregAdaptation === 1 && V.incubator.setting.pregAdaptation > 0) { - // Should be visible only after incubator.upgrade.reproduction is installed and turned on - div.append(section); - section = document.createElement("div"); - linkArray = []; - if (V.incubator.setting.pregAdaptationPower === 1) { - section.append(`Pregnancy adaptation programmed to advanced procedures. Up to triplet pregnancy should be safe for the subjects.`); - } else { - linkArray.push(makeLink(`Advanced`, () => { V.incubator.setting.pregAdaptationPower = 1; }, refresh)); - } - - if (V.incubator.setting.pregAdaptationPower === 2) { - section.append(`Pregnancy adaptation programmed to intensive procedures. Up to octuplet pregnancy should be possible for the subjects. Warning! Side effects may occur to health and mental condition.`); - } else { - linkArray.push(makeLink(`Intensive`, () => { V.incubator.setting.pregAdaptationPower = 2; }, refresh)); - } - - if (V.incubator.setting.pregAdaptationPower === 3) { - section.append(`Pregnancy adaptation programmed to extreme procedures. Normally unsustainable pregnancies may be possible for some subjects. Actual capacity will vary with genetic and other individual conditions. WARNING! Extreme side effects may occur to health and mental condition! `); - } else { - linkArray.push(makeLink(`Extreme`, () => { V.incubator.setting.pregAdaptationPower = 3; }, refresh)); - } - - if (V.incubator.setting.pregAdaptationPower === 0) { - section.append(`Pregnancy adaptation programmed to standard procedures. Normal pregnancy should be safe for subjects.`); - } else { - linkArray.push(makeLink(`Standard`, () => { V.incubator.setting.pregAdaptationPower = 0; }, refresh)); - } - section.append(" ", App.UI.DOM.generateLinksStrip(linkArray)); - div.append(section); - - section = document.createElement("div"); - App.UI.DOM.appendNewElement("span", section, `Due to the high complexity and steep risks of the procedure, settings will not be changed on tanks in use.`, "note"); - } - } - div.append(section); - el.append(div); } else { const cost = Math.trunc(50000 * V.upgradeMultiplierArcology); section.append(`There are no systems in place to control a growing child's reproductive capability.`); @@ -1366,13 +1215,53 @@ App.UI.incubator = function() { notes: [`will increase upkeep costs`] }) ); + } + el.append(section); + + + /* Preg adaptation */ + if (V.minimumSlaveAge <= 6 && (V.arcologies[0].FSRepopulationFocus >= 60 || V.BlackmarketPregAdaptation === 1)) { + /* Main prerequisite - stable repopulation FS OR documentation purchased from black market. And age gate. */ + let div = document.createElement("div"); + section = document.createElement("div"); + if (V.incubator.upgrade.pregAdaptation === 1) { + section.append(`The incubators have been upgraded with special set of manipulators, probes, nozzles and syringes coupled together with specific programs to take advantage of the accelerated growth to heighten viable reproductive capacity. These include injections of specialized serums and mechanical manipulation of the reproductive system and associated tissues, organs, muscles and bones.`); + } else { + section.append(`The highly controlled environment inside incubation tube coupled with the greatly accelerated growth process is the perfect opportunity to push the boundaries of a body's ability to sustain pregnancy. This will include injections of specialized serums and mechanical manipulation of their reproductive system through a special set of manipulators, probes, nozzles and syringes supervised by a powerful monitoring program. Costly to maintain.`); + div.append(section); + + section = document.createElement("div"); + if (V.incubator.upgrade.reproduction < 1) { + /* Now with reports - what is lacking for construction */ + section.append(`${incubatorNameCaps} lacks advanced monitoring and hormone injection systems. Construction not possible.`); + } else if (V.incubator.upgrade.organs < 1) { + section.append(`${incubatorNameCaps} lacks the ability to extract tissue samples. Construction not possible.`); + } else if (V.dispensaryUpgrade < 1) { + section.append(`${incubatorNameCaps} lacks a connection to an advanced pharmaceutical fabricator. Cutting-edge targeted serums production needed as integral part. Construction not possible.`); + } else if (V.bellyImplants < 1) { + section.append(`${incubatorNameCaps} lacks a connection with an implant manufacturing to construct fillable abdominal implants to simulate expansion. Construction not possible.`); + } else if (V.incubator.upgrade.growthStims < 1) { + section.append(`${incubatorNameCaps} lacks advanced monitoring and stimulant injection systems. Construction not possible.`); + } else { + const cost = Math.trunc(2000000 * V.upgradeMultiplierArcology); + section.append( + makePurchase(`Manufacture and install this subsystem`, cost, "capEx", { + handler: () => { + V.incubator.upgrade.pregAdaptation = 1; + refresh(); + }, + notes: [`will increase upkeep costs`] + }) + ); + } + } div.append(section); el.append(div); } - section = section = App.UI.DOM.makeElement("div", null, ["margin-top"]); - + /* Tissue sampling */ + section = document.createElement("p"); if (V.incubator.upgrade.organs === 1) { section.append(`Surgical tools have been added to the tank to be able to extract tissue samples from the occupant.`); } else if (V.organFarmUpgrade >= 1) { @@ -1390,102 +1279,270 @@ App.UI.incubator = function() { } else { App.UI.DOM.appendNewElement("span", section, `The tanks lack the ability to extract tissue samples and the dispensary lacks the ability to make use of them to fabricate organs.`, ["note"]); } + el.append(section); + + /* Rename */ + section = document.createElement("p"); + section.append(App.Facilities.rename(App.Entity.facilities.incubator, () => refresh())); el.append(section); - div = document.createElement("div"); - section = document.createElement("div"); + const tabBar = new App.UI.Tabs.TabBar("SettingsGender"); + tabBar.addTab("Male Settings", "male", tankSettingsContent("XY")); + tabBar.addTab("Female Settings", "female", tankSettingsContent("XX")); + el.append(tabBar.render()); + + return el; + + function refresh() { + jQuery(settingsContent).empty().append(tankSettings()); + jQuery(introDiv).empty().append(intro()); + jQuery(tanksContent).empty().append(tankBabies()); + } + } + + function tankSettingsContent(genes) { + const el = new DocumentFragment(); + let r = []; + let section; + let linkArray; + const setting = (genes === "XX" ? V.incubator.femaleSetting : V.incubator.maleSetting); + /* Release age */ + r.push("Target age for release:"); + r.push( + App.UI.DOM.makeTextBox( + setting.targetAge, + (v) => { + setting.targetAge = v || V.minimumSlaveAge; + setting.targetAge = Math.clamp(setting.targetAge, V.minimumSlaveAge, V.retirementAge); + refresh(); + }, + true + ) + ); + linkArray = []; + linkArray.push( + App.UI.DOM.link( + `Minimum Legal Age`, + () => { + setting.targetAge = V.minimumSlaveAge; + refresh(); + } + ) + ); + linkArray.push( + App.UI.DOM.link( + `Average Age of Fertility`, + () => { + setting.targetAge = V.fertilityAge; + refresh(); + } + ) + ); + linkArray.push( + App.UI.DOM.link( + `Average Age of Potency`, + () => { + setting.targetAge = V.potencyAge; + refresh(); + } + ) + ); + linkArray.push( + App.UI.DOM.link( + `Legal Adulthood`, + () => { + setting.targetAge = 18; + refresh(); + } + ) + ); + r.push(App.UI.DOM.generateLinksStrip(linkArray)); + r.push(App.UI.DOM.makeElement("div", `Cannot be modified after a tank's first week.`, "note")); + App.Events.addNode(el, r, "p"); + + + /* Weight */ + if (V.incubator.upgrade.weight === 1) { + section = document.createElement("p"); + linkArray = []; + + if (setting.weight === 1) { + section.append(`Weight is not being properly managed; excessive weight gain is likely.`); + } else { + linkArray.push(makeLink(`Estimate only`, () => { setting.weight = 1; }, refresh)); + } + + if (setting.weight === 2) { + section.append(`Weight is being carefully managed; children will be released at a healthy weight.`); + } else { + linkArray.push(makeLink(`Activate`, () => { setting.weight = 2; }, refresh)); + } + + if (setting.weight === 0) { + section.append(`Weight management systems are offline; children will likely be malnourished.`); + } else { + linkArray.push(makeLink(`Disable`, () => { setting.weight = 0; }, refresh)); + } + + section.append(" ", App.UI.DOM.generateLinksStrip(linkArray)); + el.append(section); + } + + + /* Muscles */ + if (V.incubator.upgrade.muscles === 1) { + section = document.createElement("p"); + linkArray = []; + + if (setting.muscles === 2) { + section.append(`Strength levels are purposefully set higher than recommended; excessive muscle gain is likely.`); + } else { + linkArray.push(makeLink(`Overload`, () => { setting.muscles = 2; }, refresh)); + } + + if (setting.muscles === 1) { + section.append(`Musculature is being carefully managed; children will be released with near normal strength.`); + } else { + linkArray.push(makeLink(`Activate`, () => { setting.muscles = 1; }, refresh)); + } + + if (setting.muscles === 0) { + section.append(`Strength management systems are offline; children will likely be released extremely weak.`); + } else { + linkArray.push(makeLink(`Disable`, () => { setting.muscles = 0; }, refresh)); + } + + section.append(" ", App.UI.DOM.generateLinksStrip(linkArray)); + el.append(section); + } + + + /* Height */ if (V.incubator.upgrade.growthStims === 1) { - section.append(`Advanced monitoring and stimulant injection systems have been installed in the tanks to monitor and maintain a developing child's height.`); - section = document.createElement("div"); + section = document.createElement("p"); linkArray = []; - if (V.incubator.setting.growthStims === 2) { - section.append(`Children are injected with higher than recommended doses of stimulants; exceeding expected final height is likely.`); + + if (setting.growthStims === 2) { + section.append(`Children are injected with higher than recommended doses of stimulants; exceeding expected final height is likely. `); } else { - linkArray.push(makeLink(`Overload`, () => { V.incubator.setting.growthStims = 2; }, refresh)); + linkArray.push(makeLink(`Overload`, () => { setting.growthStims = 2; }, refresh)); } - if (V.incubator.setting.growthStims === 1) { - section.append(`Children are injected with the recommended dosage of stimulants; they will grow to their full expected height.`); + if (setting.growthStims === 1) { + section.append(`Children are injected with the recommended dosage of stimulants; they will grow to their full expected height. `); } else { - linkArray.push(makeLink(`Limit`, () => { V.incubator.setting.growthStims = 1; }, refresh)); + linkArray.push(makeLink(`Limit`, () => { setting.growthStims = 1; }, refresh)); } - if (V.incubator.setting.growthStims === 0) { - section.append(`Growth stimulant injection systems are offline; children will develop normally.`); + if (setting.growthStims === 0) { + section.append(`Growth stimulant injection systems are offline; children will develop normally. `); } else { - linkArray.push(makeLink(`Disable`, () => { V.incubator.setting.growthStims = 0; }, refresh)); + linkArray.push(makeLink(`Disable`, () => { setting.growthStims = 0; }, refresh)); } + section.append(App.UI.DOM.generateLinksStrip(linkArray)); - } else if (V.growthStim === 1) { - const cost = Math.trunc(20000 * V.upgradeMultiplierArcology); - section.append(`There are no systems in place to control a growing child's height.`); - section.append( - makePurchase(`Upgrade the growth tanks with stimulants injection systems`, cost, "capEx", { - handler: () => { - V.incubator.upgrade.growthStims = 1; - refresh(); - }, - notes: [`will increase upkeep costs`] - }) - ); - } else { - App.UI.DOM.appendNewElement("span", section, `There are no systems in place to control a growing child's height and you lack the capability to fabricate growth stimulants.`, ["note"]); + el.append(section); } - div.append(section); - el.append(div); - if (V.minimumSlaveAge <= 6 && (V.arcologies[0].FSRepopulationFocus >= 60 || V.BlackmarketPregAdaptation === 1)) { - /* Main prerequisite - stable repopulation FS OR documentation purchased from black market. And age gate. */ - div = document.createElement("div"); + + /* Reproductive system */ + if (V.incubator.upgrade.reproduction === 1) { + section = document.createElement("p"); + linkArray = []; + + if (setting.reproduction === 2) { + section.append(`Hormone levels are purposefully set higher than recommended; over-active reproductive systems are likely.`); + } else { + linkArray.push(makeLink(`Overload`, () => { setting.reproduction = 2; }, refresh)); + } + + if (setting.reproduction === 1) { + section.append(`Hormone levels are being carefully managed; children will be released with fully functional reproductive organs.`); + } else { + linkArray.push(makeLink(`Limit`, () => { setting.reproduction = 1; }, refresh)); + } + + if (setting.reproduction === 0) { + section.append(`Reproduction management systems are offline; children will undergo normal puberty.`); + } else { + linkArray.push(makeLink(`Disable`, () => { setting.reproduction = 0; }, refresh)); + } + + section.append(" ", App.UI.DOM.generateLinksStrip(linkArray)); + el.append(section); + } + + + /* Preg adaptation */ + if (V.incubator.upgrade.reproduction === 1 && V.incubator.upgrade.pregAdaptation === 1) { section = document.createElement("div"); - if (V.incubator.upgrade.pregAdaptation === 1) { - section.append(`The incubators have been upgraded with special set of manipulators, probes, nozzles and syringes coupled together with specific programs to take advantage of the accelerated growth to heighten viable reproductive capacity. These include injections of specialized serums and mechanical manipulation of the reproductive system and associated tissues, organs, muscles and bones.`); + linkArray = []; + + if (setting.pregAdaptation === 1) { + section.append(`Pregnancy adaptation system online for ${genes === "XX" ? `females` : `males`}.`); } else { - section.append(`The highly controlled environment inside incubation tube coupled with the greatly accelerated growth process is the perfect opportunity to push the boundaries of a body's ability to sustain pregnancy. This will include injections of specialized serums and mechanical manipulation of their reproductive system through a special set of manipulators, probes, nozzles and syringes supervised by a powerful monitoring program. Costly to maintain.`); - div.append(section); + linkArray.push(makeLink(`Enable`, () => { setting.pregAdaptation = 1; }, refresh)); + } + + if (setting.pregAdaptation === 0) { + section.append(`Pregnancy adaptation system offline for ${genes === "XX" ? `females` : `males`}.`); + } else { + linkArray.push(makeLink(`Disable`, () => { setting.pregAdaptation = 0; }, refresh)); + } + section.append(" ", App.UI.DOM.generateLinksStrip(linkArray)); + el.append(section); + + if (setting.pregAdaptation > 0) { section = document.createElement("div"); - if (V.incubator.upgrade.reproduction < 1) { - /* Now with reports - what is lacking for construction */ - section.append(`${incubatorNameCaps} lacks advanced monitoring and hormone injection systems. Construction not possible.`); - } else if (V.incubator.upgrade.organs < 1) { - section.append(`${incubatorNameCaps} lacks the ability to extract tissue samples. Construction not possible.`); - } else if (V.dispensaryUpgrade < 1) { - section.append(`${incubatorNameCaps} lacks a connection to an advanced pharmaceutical fabricator. Cutting-edge targeted serums production needed as integral part. Construction not possible.`); - } else if (V.bellyImplants < 1) { - section.append(`${incubatorNameCaps} lacks a connection with an implant manufacturing to construct fillable abdominal implants to simulate expansion. Construction not possible.`); - } else if (V.incubator.upgrade.growthStims < 1) { - section.append(`${incubatorNameCaps} lacks advanced monitoring and stimulant injection systems. Construction not possible.`); + linkArray = []; + + if (setting.pregAdaptationPower === 0) { + section.append(`Pregnancy adaptation programmed to standard procedures. Normal pregnancy should be safe for subjects.`); } else { - const cost = Math.trunc(2000000 * V.upgradeMultiplierArcology); - section.append( - makePurchase(`Manufacture and install this subsystem`, cost, "capEx", { - handler: () => { - V.incubator.upgrade.pregAdaptation = 1; - refresh(); - }, - notes: [`will increase upkeep costs`] - }) - ); + linkArray.push(makeLink(`Standard`, () => { setting.pregAdaptationPower = 0; }, refresh)); + } + + if (setting.pregAdaptationPower === 1) { + section.append(`Pregnancy adaptation programmed to advanced procedures. Up to triplet pregnancy should be safe for the subjects.`); + } else { + linkArray.push(makeLink(`Advanced`, () => { setting.pregAdaptationPower = 1; }, refresh)); + } + + if (setting.pregAdaptationPower === 2) { + section.append(`Pregnancy adaptation programmed to intensive procedures. Up to octuplet pregnancy should be possible for the subjects. Warning! Side effects may occur to health and mental condition.`); + } else { + linkArray.push(makeLink(`Intensive`, () => { setting.pregAdaptationPower = 2; }, refresh)); } + + if (setting.pregAdaptationPower === 3) { + section.append(`Pregnancy adaptation programmed to extreme procedures. Normally unsustainable pregnancies may be possible for some subjects. Actual capacity will vary with genetic and other individual conditions. WARNING! Extreme side effects may occur to health and mental condition! `); + } else { + linkArray.push(makeLink(`Extreme`, () => { setting.pregAdaptationPower = 3; }, refresh)); + } + + section.append(" ", App.UI.DOM.generateLinksStrip(linkArray)); + el.append(section); } - div.append(section); - el.append(div); + + section = document.createElement("div"); + App.UI.DOM.appendNewElement("div", section, `Due to the high complexity and steep risks of this procedure, these settings cannot be changed after a tank's first week.`, "note"); + el.append(section); } - div = document.createElement("div"); - section = App.UI.DOM.makeElement("div", null, ["margin-top"]); - if (V.incubator.setting.imprint === "terror") { - section.append(`The imprinting system is currently focused on making them devoted but fearful of you. The imprinting cycle is locked upon incubation start. `); - App.UI.DOM.appendNewElement("span", section, `Only affects new infants`, ["note"]); + + /* Imprinting */ + section = document.createElement("p"); + if (setting.imprint === "terror") { + section.append(`The imprinting system is currently focused on making them devoted but fearful of you. The imprinting cycle is locked after a tank's first week. `); if (V.bodyswapAnnounced === 1) { section.append( choice( `Switch the system to focus on preparation for body-swapping`, () => { - V.incubator.setting.imprint = "husk"; + setting.imprint = "husk"; refresh(); } ) @@ -1495,19 +1552,19 @@ App.UI.incubator = function() { choice( `Switch the system to focus on attachment`, () => { - V.incubator.setting.imprint = "trust"; + setting.imprint = "trust"; refresh(); } ) ); - } else if (V.incubator.setting.imprint === "trust") { - section.append(`The imprinting system is currently focused on making them devoted and trusting of you. The imprinting cycle is locked upon incubation start.`); + } else if (setting.imprint === "trust") { + section.append(`The imprinting system is currently focused on making them devoted and trusting of you. The imprinting cycle is locked after a tank's first week.`); if (V.bodyswapAnnounced === 1) { section.append( choice( `Switch the system to focus preparation for body-swapping`, () => { - V.incubator.setting.imprint = "husk"; + setting.imprint = "husk"; refresh(); } ) @@ -1517,18 +1574,18 @@ App.UI.incubator = function() { choice( `Switch the system to focus on dependence`, () => { - V.incubator.setting.imprint = "terror"; + setting.imprint = "terror"; refresh(); } ) ); } else { - section.append(`The imprinting system is currently focused on producing complete vegetables ready to be used as hosts for body swapping. The imprinting cycle is locked upon incubation start.`); + section.append(`The imprinting system is currently focused on producing complete vegetables ready to be used as hosts for body swapping. The imprinting cycle is locked after a tank's first week.`); section.append( choice( `Switch the system to focus on dependence`, () => { - V.incubator.setting.imprint = "terror"; + setting.imprint = "terror"; refresh(); } ) @@ -1537,19 +1594,13 @@ App.UI.incubator = function() { choice( `Switch the system to focus on attachment`, () => { - V.incubator.setting.imprint = "trust"; + setting.imprint = "trust"; refresh(); } ) ); } - div.append(section); - el.append(div); - - section = document.createElement("div"); - section.append(App.Facilities.rename(App.Entity.facilities.incubator, () => refresh())); el.append(section); - return el; function refresh() { @@ -1560,12 +1611,12 @@ App.UI.incubator = function() { } function release() { - const multiple = (V.incubator.setting.bulkRelease === 1) && V.incubator.tanks.filter(t => t.growTime <= 0).length > 1; + const multiple = (V.incubator.bulkRelease === 1) && V.incubator.tanks.filter(t => t.incubatorSettings.growTime <= 0).length > 1; const getTanks = () => { if (multiple) { - V.newSlavePool = V.incubator.tanks.deleteWith(t => t.growTime <= 0); + V.newSlavePool = V.incubator.tanks.deleteWith(t => t.incubatorSettings.growTime <= 0); } else { - const baby = V.incubator.tanks.find(t => t.growTime <= 0); + const baby = V.incubator.tanks.find(t => t.incubatorSettings.growTime <= 0); V.incubator.tanks.delete(baby); V.readySlave = baby; } diff --git a/src/facilities/incubator/incubatorUtils.js b/src/facilities/incubator/incubatorUtils.js index 4b258a4c771db338cd39aacf5f3335f4fc030a86..ea4cb934abc264e4076bf5f21d1f82993d964bf8 100644 --- a/src/facilities/incubator/incubatorUtils.js +++ b/src/facilities/incubator/incubatorUtils.js @@ -2,21 +2,32 @@ * Sends a child to the Incubator if it has room * @param {App.Entity.SlaveState} child */ -App.Facilities.Incubator.newChild = function(child) { +App.Facilities.Incubator.newChild = function(child, settingsOverride = null) { let fullAdapt; - child.growTime = Math.trunc(V.targetAge * 52); - child.incubatorPregAdaptationPower = V.incubator.setting.pregAdaptationPower; - if (V.incubator.setting.pregAdaptationPower === 1) { - fullAdapt = 45000 / 2000; //22.5 - } else if (V.incubator.setting.pregAdaptationPower === 2) { - fullAdapt = 100000 / 2000; //50 - } else if (V.incubator.setting.pregAdaptationPower === 3) { - fullAdapt = 150000 / 2000; //75 + const setting = settingsOverride !== null ? settingsOverride : (child.genes === "XX" ? V.incubator.femaleSetting : V.incubator.maleSetting); + + if (setting.pregAdaptationPower === 1) { + fullAdapt = 45000 / 2000; // 22.5 + } else if (setting.pregAdaptationPower === 2) { + fullAdapt = 100000 / 2000; // 50 + } else if (setting.pregAdaptationPower === 3) { + fullAdapt = 150000 / 2000; // 75 } else { - fullAdapt = 15000 / 2000; //7.5 + fullAdapt = 15000 / 2000; // 7.5 } - child.incubatorPregAdaptationInWeek = Math.max(((fullAdapt - child.pregAdaptation) / child.growTime), 0); + V.incubator.tanks.push(child); + child.incubatorSettings = { + imprint: setting.imprint, + weight: setting.weight, + muscles: setting.muscles, + growthStims: setting.growthStims, + reproduction: setting.reproduction, + growTime: Math.trunc(setting.targetAge * 52), + pregAdaptation: setting.pregAdaptation, + pregAdaptationPower: setting.pregAdaptationPower, + pregAdaptationInWeek: Math.max(((fullAdapt - child.pregAdaptation) / Math.trunc(setting.targetAge * 52)), 0) + }; }; App.Facilities.Incubator.init = function(state) { @@ -27,6 +38,7 @@ App.Facilities.Incubator.init = function(state) { V.incubator = { capacity: 1, tanks: [], + bulkRelease: 0, name: "the Incubator", organs: [], readySlaves: 0, @@ -39,13 +51,23 @@ App.Facilities.Incubator.init = function(state) { organs: 0, pregAdaptation: 0, }, - setting: { + maleSetting: { + imprint: "trust", + targetAge: V.minimumSlaveAge, + weight: 0, + muscles: 0, + growthStims: 0, + reproduction: 0, + pregAdaptation: 0, + pregAdaptationPower: 0, + }, + femaleSetting: { imprint: "trust", + targetAge: V.minimumSlaveAge, weight: 0, muscles: 0, growthStims: 0, reproduction: 0, - bulkRelease: 0, pregAdaptation: 0, pregAdaptationPower: 0, }, diff --git a/src/facilities/incubator/inspectTankSettings.js b/src/facilities/incubator/inspectTankSettings.js new file mode 100644 index 0000000000000000000000000000000000000000..d18fb381a9f8eca633c1e63f18a0fc057dc7efb0 --- /dev/null +++ b/src/facilities/incubator/inspectTankSettings.js @@ -0,0 +1,417 @@ +App.UI.inspectTankSettings = function(isFetus, isPCMother = false) { + + // V.nextLink = "Incubator"; + // V.storedLink = "Incubator"; + let tankSetting; + let child; + let fetus; + + if (!isFetus) { + child = V.incubator.tanks[V.AS]; + tankSetting = child.incubatorSettings; + } else { + if (isPCMother) { + fetus = V.PC.womb[V.activeFetus]; + } else { + fetus = getSlave(V.AS).womb[V.activeFetus]; + } + if ("tankSetting" in fetus === false) { + fetus.tankSetting = fetus.genetics.gender === "XX" ? {...V.incubator.femaleSetting} : {...V.incubator.maleSetting}; + } + tankSetting = fetus.tankSetting; + } + const { + He, His, + he, him, his + } = (isFetus ? getPronouns(fetus.age >= 2 ? (fetus.genetics.gender === "XX" ? {pronoun: 0} : {pronoun: 1}) : {pronoun: 3}) : getPronouns(child)); + + const container = App.UI.DOM.makeElement('span', content()); + + return container; + + /** + * @returns {DocumentFragment} + */ + function content() { + const node = new DocumentFragment(); + let section; + let linkArray; + + App.UI.DOM.appendNewElement("h2", node, "Tank settings:"); + + /* Age */ + if (isFetus) { + let target = Math.round(tankSetting.targetAge); //This is fine because it will only be displayed when growTime has not been depeleted + let r = []; + r.push("Target age for release:"); + r.push( + App.UI.DOM.makeTextBox( + target, + (v) => { + target = v || V.minimumSlaveAge; + target = Math.clamp(target, V.minimumSlaveAge, V.retirementAge); + tankSetting.targetAge = target; + jQuery(container).empty().append(content()); + }, + true + ) + ); + + linkArray = []; + linkArray.push( + App.UI.DOM.link( + `Minimum Legal Age`, + () => { + target = V.minimumSlaveAge; + tankSetting.targetAge = target; + jQuery(container).empty().append(content()); + } + ) + ); + linkArray.push( + App.UI.DOM.link( + `Average Age of Fertility`, + () => { + target = V.fertilityAge; + tankSetting.targetAge = target; + jQuery(container).empty().append(content()); + } + ) + ); + linkArray.push( + App.UI.DOM.link( + `Average Age of Potency`, + () => { + target = V.potencyAge; + tankSetting.targetAge = target; + jQuery(container).empty().append(content()); + } + ) + ); + linkArray.push( + App.UI.DOM.link( + `Legal Adulthood`, + () => { + target = 18; + tankSetting.targetAge = target; + jQuery(container).empty().append(content()); + } + ) + ); + r.push(App.UI.DOM.generateLinksStrip(linkArray)); + + App.Events.addNode(node, r, "p"); + } else { + section = App.UI.DOM.makeElement("p"); + if (isFetus) { + section.append(`Target age for release: ${tankSetting.targetAge}`); + } else { + section.append(`Target age for release: ${child.physicalAge}`); //This is already set, apparently + } + section.append(App.UI.DOM.makeElement("div", `Cannot be changed on tanks in use`)); + node.append(section); + } + + /* Weight */ + section = App.UI.DOM.makeElement("p"); + if (V.incubator.upgrade.weight === 1) { + linkArray = []; + + if (tankSetting.weight === 1) { + section.append(`Weight ${isFetus ? `will not be` : `is not being`} properly managed; excessive weight gain is likely.`); + } else { + linkArray.push(makeLink(`Estimate only`, () => { tankSetting.weight = 1; })); + } + + if (tankSetting.weight === 2) { + section.append(`Weight ${isFetus ? `will be` : `is`} being carefully managed; ${he} will be released at a healthy weight.`); + } else { + linkArray.push(makeLink(`Activate`, () => { tankSetting.weight = 2; })); + } + + if (tankSetting.weight === 0) { + section.append(`Weight management systems ${isFetus ? `will be` : `are`} offline; ${he} will likely be malnourished.`); + } else { + linkArray.push(makeLink(`Disable`, () => { tankSetting.weight = 0; })); + } + + section.append(" ", App.UI.DOM.generateLinksStrip(linkArray)); + } else { + section.append(`There are no systems in place to control a growing child's weight; ${he} will likely come out emaciated from the rapid growth.`); + } + node.append(section); + + + /* Muscles */ + section = App.UI.DOM.makeElement("p"); + if (V.incubator.upgrade.muscles === 1) { + linkArray = []; + + if (tankSetting.muscles === 2) { + section.append(`Strength levels ${isFetus ? `will be` : `are`} purposefully set higher than recommended; excessive muscle gain is likely.`); + } else { + linkArray.push(makeLink(`Overload`, () => { tankSetting.muscles = 2; })); + } + + if (tankSetting.muscles === 1) { + section.append(`Musculature ${isFetus ? `will be` : `is`} being carefully managed; ${he} will be released with near normal strength.`); + } else { + linkArray.push(makeLink(`Activate`, () => { tankSetting.muscles = 1; })); + } + + if (tankSetting.muscles === 0) { + section.append(`Strength management systems ${isFetus ? `will be` : `are`} offline; ${he} will likely be released extremely weak.`); + } else { + linkArray.push(makeLink(`Disable`, () => { tankSetting.muscles = 0; })); + } + + section.append(" ", App.UI.DOM.generateLinksStrip(linkArray)); + } else { + section.append(`There are no systems in place to control a growing child's musculature; ${he} will likely come out frail and weak from the rapid growth.`); + } + node.append(section); + + + /* Height */ + section = App.UI.DOM.makeElement("p"); + if (V.incubator.upgrade.growthStims === 1) { + linkArray = []; + + if (tankSetting.growthStims === 2) { + section.append(`${He} will be injected with higher than recommended doses of stimulants; exceeding expected final height is likely. `); + } else { + linkArray.push(makeLink(`Overload`, () => { tankSetting.growthStims = 2; })); + } + + if (tankSetting.growthStims === 1) { + section.append(`${He} will be injected with the recommended dosage of stimulants; ${he} will grow to their full expected height. `); + } else { + linkArray.push(makeLink(`Limit`, () => { tankSetting.growthStims = 1; })); + } + + if (tankSetting.growthStims === 0) { + section.append(`Growth stimulant injection systems ${isFetus ? `will be` : `are`} offline; ${he} will develop normally. `); + } else { + linkArray.push(makeLink(`Disable`, () => { tankSetting.growthStims = 0; })); + } + section.append(App.UI.DOM.generateLinksStrip(linkArray)); + } else { + section.append(`There are no systems in place to control a growing child's height.`); + } + node.append(section); + + + /* Reproduction */ + section = App.UI.DOM.makeElement("p"); + if (V.incubator.upgrade.reproduction === 1) { + linkArray = []; + + if (tankSetting.reproduction === 2) { + section.append(`Hormone levels ${isFetus ? `will be` : `are`} purposefully set higher than recommended; an over-active reproductive system is likely.`); + } else { + linkArray.push(makeLink(`Overload`, () => { tankSetting.reproduction = 2; })); + } + + if (tankSetting.reproduction === 1) { + section.append(`Hormone levels ${isFetus ? `will be` : `are`} being carefully managed; ${he} will be released with fully functional reproductive organs.`); + } else { + linkArray.push(makeLink(`Limit`, () => { tankSetting.reproduction = 1; })); + } + + if (tankSetting.reproduction === 0) { + section.append(`Reproduction management systems ${isFetus ? `will be` : `are`} offline; ${he} will undergo normal puberty.`); + } else { + linkArray.push(makeLink(`Disable`, () => { tankSetting.reproduction = 0; })); + } + section.append(" ", App.UI.DOM.generateLinksStrip(linkArray)); + } else { + section.append(`There are no systems in place to control a growing child's reproductive capability.`); + } + node.append(section); + + + /* Pregnancy Adaptation */ + if (V.incubator.upgrade.reproduction === 1 && V.incubator.upgrade.pregAdaptation === 1) { + section = App.UI.DOM.makeElement("div"); + linkArray = []; + + if (tankSetting.pregAdaptation === 1) { + section.append(`Pregnancy adaptation system online.`); + } else { + linkArray.push(makeLink(`Enable`, () => { tankSetting.pregAdaptation = 1; })); + } + + if (tankSetting.pregAdaptation === 0) { + section.append(`Pregnancy adaptation system offline.`); + } else { + linkArray.push(makeLink(`Disable`, () => { tankSetting.pregAdaptation = 0; })); + } + + if (isFetus) { + section.append(" ", App.UI.DOM.generateLinksStrip(linkArray)); + } + node.append(section); + } + + section = App.UI.DOM.makeElement("div"); + if (V.incubator.upgrade.reproduction === 1 && V.incubator.upgrade.pregAdaptation === 1 && tankSetting.pregAdaptation === 1) { + linkArray = []; + + if (tankSetting.pregAdaptationPower === 0) { + section.append(`Pregnancy adaptation programmed to standard procedures. Normal pregnancy should be safe for ${him}.`); + } else { + linkArray.push(makeLink(`Standard`, () => { tankSetting.pregAdaptationPower = 0; })); + } + + if (tankSetting.pregAdaptationPower === 1) { + section.append(`Pregnancy adaptation programmed to advanced procedures. Up to triplet pregnancy should be safe for ${him}.`); + } else { + linkArray.push(makeLink(`Advanced`, () => { tankSetting.pregAdaptationPower = 1; })); + } + + if (tankSetting.pregAdaptationPower === 2) { + section.append(`Pregnancy adaptation programmed to intensive procedures. Up to octuplet pregnancy should be possible for ${him}. Warning! Side effects may occur to health and mental condition.`); + } else { + linkArray.push(makeLink(`Intensive`, () => { tankSetting.pregAdaptationPower = 2; })); + } + + if (tankSetting.pregAdaptationPower === 3) { + section.append(`Pregnancy adaptation programmed to extreme procedures. Normally unsustainable pregnancies may be possible for ${him}. Actual capacity will vary with genetic and other individual conditions. WARNING! Extreme side effects may occur to health and mental condition! `); + } else { + linkArray.push(makeLink(`Extreme`, () => { tankSetting.pregAdaptationPower = 3; })); + } + + if (isFetus) { + section.append(" ", App.UI.DOM.generateLinksStrip(linkArray)); + } + + } + + if ( V.incubator.upgrade.reproduction === 1 && V.incubator.upgrade.pregAdaptation === 1 && !isFetus) { + section.append(App.UI.DOM.makeElement("div", `Due to the high complexity and steep risks of the procedure, these settings cannot be changed on tanks in use.`)); + } + node.append(section); + + /* Imprinting */ + section = App.UI.DOM.makeElement("p"); + linkArray = []; + if (tankSetting.imprint === "terror") { + section.append(`The imprinting system ${isFetus ? `will be` : `is`} focused on making ${him} devoted but fearful of you.`); + if (isFetus) { + if (V.bodyswapAnnounced === 1) { + section.append( + choice( + `Switch the system to focus on preparation for body-swapping`, + () => { + tankSetting.imprint = "husk"; + jQuery(container).empty().append(content()); + } + ) + ); + } + section.append( + choice( + `Switch the system to focus on attachment`, + () => { + tankSetting.imprint = "trust"; + jQuery(container).empty().append(content()); + } + ) + ); + } else { + section.append(App.UI.DOM.makeElement("div", `You cannot alter this setting after ${he} has started growing.`)); + } + } else if (tankSetting.imprint === "trust") { + section.append(`The imprinting system ${isFetus ? `will be` : `is`} focused on making ${him} devoted and trusting of you.`); + if (isFetus) { + if (V.bodyswapAnnounced === 1) { + section.append( + choice( + `Switch the system to focus preparation for body-swapping`, + () => { + tankSetting.imprint = "husk"; + jQuery(container).empty().append(content()); + } + ) + ); + } + section.append( + choice( + `Switch the system to focus on dependence`, + () => { + tankSetting.imprint = "terror"; + jQuery(container).empty().append(content()); + } + ) + ); + } else { + section.append(App.UI.DOM.makeElement("div", `You cannot alter this setting after the ${he} has started growing.`)); + } + } else { + section.append(`The imprinting system ${isFetus ? `will be` : `is`} focused on producing a complete vegetable ready to be used as a host for body swapping.`); + if (isFetus) { + section.append( + choice( + `Switch the system to focus on dependence`, + () => { + tankSetting.imprint = "terror"; + jQuery(container).empty().append(content()); + } + ) + ); + section.append( + choice( + `Switch the system to focus on attachment`, + () => { + tankSetting.imprint = "trust"; + jQuery(container).empty().append(content()); + } + ) + ); + } else { + section.append(App.UI.DOM.makeElement("div", `You cannot alter this setting after the ${he} has started growing.`)); + } + } + node.append(section); + + return node; + } + + /** + * + * @param {string} title + * @param {function():void} func + * @param {string} [passage=""] + * @param {string} [note=""] + * @returns {HTMLElement} + */ + function choice(title, func, passage = "", note = "") { + const div = document.createElement("div"); + div.classList.add("choices"); + div.append( + App.UI.DOM.link( + title, + func, + [], + passage, + note + ) + ); + return div; + } + + /** + * + * @param {string} title + * @param {function():void} func + */ + function makeLink(title, func) { + return App.UI.DOM.link( + title, + () => { + func(); + jQuery(container).empty().append(content()); + } + ); + } +} \ No newline at end of file diff --git a/src/facilities/surgery/analyzePregnancy.js b/src/facilities/surgery/analyzePregnancy.js index 62bee4a25bb4856e07d95b245dad16e578e3c849..39533ebfd4494a2fdbfde7144a08e42e07ac2aa0 100644 --- a/src/facilities/surgery/analyzePregnancy.js +++ b/src/facilities/surgery/analyzePregnancy.js @@ -157,10 +157,42 @@ globalThis.analyzePregnancies = function(mother, cheat) { `Don't keep this child in ${V.incubator.name}`, () => { fetus.reserve = ""; + delete fetus.tankSetting; }, [], passage() )); + let linkArray = []; + if ("tankSetting" in fetus) { + linkArray.push(App.UI.DOM.link( + `Inspect incubator settings`, + () => { + V.AS = mother.ID; // Undefined if mother is PC, but harmlessly so + V.activeFetus = i; + }, + [], + (mother === V.PC ? `Inspect PC Fetus Tank Settings` : `Inspect Fetus Tank Settings`) + )); + linkArray.push(App.UI.DOM.link( + `Clear custom incubator settings`, + () => { + delete fetus.tankSetting; + }, + [], + passage() + )); + } else { + linkArray.push(App.UI.DOM.link( + `Set custom incubator settings`, + () => { + V.AS = mother.ID; + V.activeFetus = i; + }, + [], + (mother === V.PC ? `Inspect PC Fetus Tank Settings` : `Inspect Fetus Tank Settings`) + )); + } + App.UI.DOM.appendNewElement("div", el, App.UI.DOM.generateLinksStrip(linkArray)); } else if ((V.incubator.capacity - V.incubator.tanks.length) - FetusGlobalReserveCount("incubator") > 0) { App.UI.DOM.appendNewElement("div", el, App.UI.DOM.link( `Keep this child in ${V.incubator.name}`, @@ -189,6 +221,7 @@ globalThis.analyzePregnancies = function(mother, cheat) { `Keep this child in ${V.nurseryName}`, () => { fetus.reserve = "nursery"; + delete fetus.tankSetting; }, [], passage() @@ -215,6 +248,7 @@ globalThis.analyzePregnancies = function(mother, cheat) { } } el.append(options.render()); + return el; function fetusAbnormalities() { diff --git a/src/interaction/artificialInsemination.js b/src/interaction/artificialInsemination.js index e5feacfe5549696c5beda4b405f2d63fecc85039..a272b9a26f6f7060cdeb27f20d2376a748bfe500 100644 --- a/src/interaction/artificialInsemination.js +++ b/src/interaction/artificialInsemination.js @@ -37,19 +37,21 @@ App.UI.SlaveInteract.artificialInsemination = function() { App.UI.DOM.appendNewElement("p", f, "You have no slaves with potent sperm.", "note"); } - if (V.incubator.tanks.length > 0 && V.incubator.setting.reproduction === 2) { - App.UI.DOM.appendNewElement("h2", f, "Select an eligible incubatee to milk for semen"); - App.UI.DOM.appendNewElement("p", f, "Incubator settings are resulting in large-scale fluid secretion.", "scene-intro"); + if (V.incubator.tanks.length > 0 && V.incubator.upgrade.reproduction === 1) { r = []; any = false; for (const tank of V.incubator.tanks) { - if (tank.balls > 0 && tank.dick > 0 && canBreed(getSlave(V.AS), tank)) { + if (tank.balls > 0 && tank.dick > 0 && tank.incubatorSettings.reproduction === 2 && canBreed(getSlave(V.AS), tank)) { + if (any === false) { + App.UI.DOM.appendNewElement("h2", f, "Select an eligible incubatee to milk for semen"); + App.UI.DOM.appendNewElement("p", f, "Incubator settings are resulting in large-scale fluid secretion.", "scene-intro"); + any = true; + } r.push(App.UI.DOM.makeElement("div", App.Medicine.Surgery.makeLink( new App.Medicine.Surgery.Procedures.Insemination(getSlave(V.AS), `Use ${tank.slaveName}'s sperm.`, tank), exit, false) )); - any = true; } } diff --git a/src/interaction/siPhysicalRegimen.js b/src/interaction/siPhysicalRegimen.js index 0d38417eb1050235c4856024bf35a8f2ea22c762..d2e2a5e0154f046eaafa3be56dc548d59cd92be0 100644 --- a/src/interaction/siPhysicalRegimen.js +++ b/src/interaction/siPhysicalRegimen.js @@ -232,9 +232,9 @@ App.UI.SlaveInteract.physicalRegimen = function(slave, refresh) { } if (V.growthStim === 1) { if (canImproveHeight(slave)) { - misc.push({text: `Growth Stimulants`, updateSlave: {drugs: `growth stimulants`}}); + misc.push({text: `Growth stimulants`, updateSlave: {drugs: `growth stimulants`}}); } else { - misc.push({text: `Growth Stimulants`, disabled: `Cannot increase height further`}); + misc.push({text: `Growth stimulants`, disabled: `Cannot increase height further`}); } } if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) { @@ -266,6 +266,36 @@ App.UI.SlaveInteract.physicalRegimen = function(slave, refresh) { title.appendChild(App.UI.SlaveInteract.generateRows(drugLevelOptions, slave, "", false, refresh)); el.append(title); + // Put mod added drugs into categories: + const modDrugs = new Map(); + App.Mods.Drugs.list.filter(drug => !drug.isPCDrug && drug.available(slave)).forEach(drug => { + let typeArray; + // Allow drugs to be added to vanilla categories + switch (drug.type) { + case "Lips": typeArray = lips; break; + case "Breasts": typeArray = breasts; break; + case "Nipples": typeArray = nipples; break; + case "Butt": typeArray = butt; break; + case "Dick": + case "Clit": typeArray = dick; break; + case "Fertility": typeArray = fertility; break; + case "Hormones": typeArray = hormones; break; + case "Psych": typeArray = psych; break; + case "Misc": typeArray = misc; break; + default: + if (!modDrugs.has(drug.type)) { + modDrugs.set(drug.type, []); + } + typeArray = modDrugs.get(drug.type); + } + // Test if drug should be enabled and push to array + if (drug.enable(slave) === true) { + typeArray.push({text: drug.text, updateSlave: {drugs: drug.name}}); + } else { + typeArray.push({text: drug.text, disabled: drug.enable(slave)}); + } + }); + appendLabeledChoiceRow("Lips", lips, el); appendLabeledChoiceRow("Breasts", breasts, el); appendLabeledChoiceRow("Nipples", nipples, el); @@ -277,22 +307,8 @@ App.UI.SlaveInteract.physicalRegimen = function(slave, refresh) { appendLabeledChoiceRow("Psych", psych, el); appendLabeledChoiceRow("Misc", misc, el); - //Put mod added drugs into categories: - const extraDrugs = {}; - App.Mods.Drugs.forEach(drug => { - extraDrugs[drug.type] ??= []; - //Test for condition: - const enable = drug.enable(slave); - if (enable === true) { - extraDrugs[drug.type].push({text: drug.text, updateSlave: {drugs: drug.name}}); - } else { - extraDrugs[drug.type].push({text: drug.text, disabled: enable}); - } - }); - //Adds the rows - Object.keys(extraDrugs).forEach(key => { - appendLabeledChoiceRow(key, extraDrugs[key], el); - }); + // Add modded rows + modDrugs.forEach((drugArray, drugType) => appendLabeledChoiceRow(drugType, drugArray, el)); return el; } diff --git a/src/js/birth/birth.js b/src/js/birth/birth.js index ba9f403d81ffa946ef6055892cdf7af83c9a6924..32004166b0abf9d91ecc8f63f2e1c01b299f2065 100644 --- a/src/js/birth/birth.js +++ b/src/js/birth/birth.js @@ -1858,7 +1858,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false, artRen if (slave.fetish === Fetish.MINDBROKEN || slave.fuckdoll > 0) { r.push(`${slave.slaveName} fails to acknowledge this.`); } else if (slave.devotion > 95) { - r.push(`loves you already, but ${he}'ll`); + r.push(`${slave.slaveName} loves you already, but ${he}'ll`); r.push(App.UI.DOM.makeElement("span", `love you even more`, "hotpink")); r.push(`for this.`); slave.devotion += 4; @@ -9373,7 +9373,7 @@ globalThis.sendNewbornsToFacility = function(mom, babiesBeingBorn, sendAll) { const remainingBabies = []; for (const ovum of babiesBeingBorn) { if ((ovum.reserve === "incubator" || sendAll) && V.incubator.tanks.length < V.incubator.capacity) { - App.Facilities.Incubator.newChild(generateChild(mom, ovum, true)); + App.Facilities.Incubator.newChild(generateChild(mom, ovum, true), "tankSetting" in ovum ? ovum.tankSetting : null); } else if ((ovum.reserve === "nursery" || sendAll) && V.cribs.length < V.nurseryCribs) { App.Facilities.Nursery.newChild(generateChild(mom, ovum)); } else { diff --git a/src/js/economyJS.js b/src/js/economyJS.js index 218b9773411b34c2fd0e06286ce5f37494070b73..41d46b4307fd718f34f13c2e8b7e7ee80341a79b 100644 --- a/src/js/economyJS.js +++ b/src/js/economyJS.js @@ -642,9 +642,12 @@ globalThis.calculateCosts = (function() { } function getIncubatorSlavesCosts() { - return ((V.incubator.upgrade.weight + V.incubator.upgrade.muscles + V.incubator.upgrade.reproduction + - V.incubator.upgrade.growthStims + V.incubator.upgrade.organs + V.incubator.setting.pregAdaptationPower) * - 500 * V.incubator.tanks.length); + let sum = 0; + for (const tank of V.incubator.tanks) { + sum += ((V.incubator.upgrade.weight + V.incubator.upgrade.muscles + V.incubator.upgrade.reproduction + + V.incubator.upgrade.growthStims + V.incubator.upgrade.organs + tank.incubatorSettings.pregAdaptationPower) * 500); + } + return sum; } function getServantsQuartersCosts() { diff --git a/src/js/utilsAssessSlave.js b/src/js/utilsAssessSlave.js index 92acf147d04f30a2e72567b6308033efe807aa7f..2006095d862d07cc579082dac7ff961bd953bbe4 100644 --- a/src/js/utilsAssessSlave.js +++ b/src/js/utilsAssessSlave.js @@ -115,7 +115,7 @@ globalThis.canImproveIntelligence = function(slave) { * @returns {number} */ globalThis.maxHeight = function(slave) { - let max = Math.clamp(((Height.mean(slave) * 1.25) + slave.heightImplant * 10), 0, 274); /* max achievable height is expected height plus 25% */ + let max = Math.clamp(((slave.natural.height * 1.25) + slave.heightImplant * 10), 0, 274); /* max achievable height is expected height plus 25% */ if (slave.geneticQuirks.neoteny === 2 && slave.physicalAge > 12) { /* Limit neoteny slaves to 12 year old max height */ max = Math.clamp(((Height.mean(slave.nationality, slave.race, slave.genes, 12) * 1.25) + slave.heightImplant * 10), 0, 274); diff --git a/src/js/wombJS.js b/src/js/wombJS.js index 694197b34f9e7a5487938e976e1567c4f584c9d6..0037b11b04c6434b04008b9f72577b59eb142aee 100644 --- a/src/js/wombJS.js +++ b/src/js/wombJS.js @@ -736,6 +736,9 @@ globalThis.WombSetGenericReserve = function(actor, type, count) { if ((ft.reserve === "" || ft.reserve === type) && count > 0) { // console.log ("!trigger"); ft.reserve = type; + if (type !== "incubator") { + delete ft.tankSetting; + } count--; } }); @@ -751,6 +754,9 @@ globalThis.WombChangeReserveType = function(actor, oldType, newType) { actor.womb.forEach(function(ft) { if (ft.reserve === oldType) { ft.reserve = newType; + if (newType !== "incubator") { + delete ft.tankSetting; + } count++; } }); @@ -762,6 +768,7 @@ globalThis.WombCleanGenericReserve = function(actor, type, count) { actor.womb.forEach(function(ft) { if (ft.reserve === type && count > 0) { ft.reserve = ""; + delete ft.tankSetting; count--; } }); @@ -814,6 +821,7 @@ globalThis.WombRemoveReservedFetuses = function(actor, type) { globalThis.WombCleanAllReserve = function(actor) { actor.womb.forEach(function(ft) { ft.reserve = ""; + delete fetus.tankSetting; }); }; diff --git a/src/npc/descriptions/career.js b/src/npc/descriptions/career.js index f5c6e9c21d46a59c59ee0c1cab4c4ba8c8058734..71e5142b4c688ab3b94639ff924a298325dff8b9 100644 --- a/src/npc/descriptions/career.js +++ b/src/npc/descriptions/career.js @@ -101,7 +101,7 @@ App.Desc.career = function(slave) { } else if (App.Data.Careers.Leader.HG.includes(slave.career)) { r.push(`${career}, giving ${him} potential as a Head Girl.`); } else if (App.Data.Careers.Leader.recruiter.includes(slave.career)) { - r.push(`${career}, giving ${him} potential as a recruiter.`); + r.push(`${career}, giving ${him} potential as a Recruiter.`); } else if (App.Data.Careers.General.entertainment.includes(slave.career)) { r.push(`${career}, giving ${him} a slight edge at entertainment.`); } else if (App.Data.Careers.General.whore.includes(slave.career)) { diff --git a/src/npc/generate/generateGenetics.js b/src/npc/generate/generateGenetics.js index 738eff615368476782229069dac9b3333db282f7..5f0b207a5392a21ca379643f2c3713447d53fd2e 100644 --- a/src/npc/generate/generateGenetics.js +++ b/src/npc/generate/generateGenetics.js @@ -1223,9 +1223,10 @@ globalThis.generateChild = function(mother, ovum, incubator = false) { } } } else { + const incubatorSetting = ("tankSetting" in ovum) ? ovum.tankSetting : (genes.gender === "XX" ? V.incubator.femaleSetting : V.incubator.maleSetting); const fixedAge = { - minAge: V.targetAge, - maxAge: V.targetAge, + minAge: incubatorSetting.targetAge, + maxAge: incubatorSetting.targetAge, ageOverridesPedoMode: 1, mature: 0 }; @@ -1369,10 +1370,10 @@ globalThis.generateChild = function(mother, ovum, incubator = false) { child.canRecruit = 0; child.hStyle = "messy"; child.hLength = 300; - if (V.incubator.setting.imprint === "terror") { + if (incubatorSetting.imprint === "terror") { child.origin = "$He was conditioned from birth into mindless terror in an aging tank."; child.tankBaby = 2; - } else if (V.incubator.setting.imprint === "trust") { + } else if (incubatorSetting.imprint === "trust") { child.origin = "$He was conditioned from birth into trusting obedience in an aging tank."; child.tankBaby = 1; } else { diff --git a/src/npc/generate/newChildIntro.js b/src/npc/generate/newChildIntro.js index fd26b1ccd280c58f53d65e62225e3b39cc4f0c65..7ecf1c8c1754408d266fe5ac338d64e3563c5b94 100644 --- a/src/npc/generate/newChildIntro.js +++ b/src/npc/generate/newChildIntro.js @@ -27,7 +27,7 @@ App.UI.newChildIntro = function(slave) { } else if (slave.geneticQuirks.neoteny && slave.actualAge > 12 && V.geneticMappingUpgrade === 0) { r.push(`you have to make sure the right ${girl} was released. ${He} was supposed to be ${slave.actualAge}, not this child sitting before you. You double check the machine's logs to be certain and it turns out ${he} really is ${slave.actualAge}, just abnormally young looking for ${his} age.`); } else { - r.push(`you help ${him} to ${his} feet${(V.incubator.setting.reproduction > 1) ? `, making sure to feel up ${his} overdeveloped body,` : ``} and walk ${him} to your penthouse.`); + r.push(`you help ${him} to ${his} feet${slave.incubatorSettings.reproduction > 1 ? `, making sure to feel up ${his} overdeveloped body,` : ``} and walk ${him} to your penthouse.`); } r.push(`Though first you must decide upon a name for the new ${girl}; it won't take long to reach your office, so you have only <span class="orange">one chance to name ${him}</span> before you arrive.`); App.Events.addParagraph(el, r); @@ -736,7 +736,7 @@ App.UI.newChildIntro = function(slave) { } else if (V.PC.dick !== 0) { r.push(`${He} notices your privates differ from ${hers}, and thanks to the tank's teachings, <span class="devotion inc">can't look away.</span>`); slave.devotion += 4; - if (V.incubator.setting.reproduction > 0) { + if (slave.incubatorSettings.reproduction > 0) { r.push(`${He} seems a little alarmed at ${his} nipples and clit stiffening to the`); if (canSee(slave)) { r.push(`sight`); @@ -753,7 +753,7 @@ App.UI.newChildIntro = function(slave) { } else if (V.PC.vagina !== -1) { r.push(`${He} notices your privates differ from ${hers}, and thanks to the tank's teachings, <span class="devotion inc">can't look away.</span>`); slave.devotion += 4; - if (V.incubator.setting.reproduction > 0) { + if (slave.incubatorSettings.reproduction > 0) { r.push(`${He} seems a little alarmed at ${his} dick`); if (canAchieveErection(slave)) { r.push(`rapidly stiffening`); @@ -771,7 +771,7 @@ App.UI.newChildIntro = function(slave) { } } - if (V.incubator.setting.reproduction > 0) { + if (slave.incubatorSettings.reproduction > 0) { if (((slave.attrXX > 50) || (slave.behavioralQuirk === "adores women")) && (slave.behavioralFlaw !== "hates women") && (slave.trust >= -20)) { if (V.PC.boobs >= 900) { r.push(`${He} seems to think you're pretty, and is more willing to <span class="devotion inc">try for your approval</span> than ${he} would otherwise be. ${He} openly ogles your rack at every opportunity.`); diff --git a/src/npc/generate/newSlaveIntro.js b/src/npc/generate/newSlaveIntro.js index eef989dc4c19131ebef7471631db7f0d34818bed..9b8354445cb52400c4f7c7e2dfb0879ebd28a9c8 100644 --- a/src/npc/generate/newSlaveIntro.js +++ b/src/npc/generate/newSlaveIntro.js @@ -3074,6 +3074,20 @@ App.UI.newSlaveIntro = function(slave, slave2, {tankBorn = false, momInterest = } } r.push(VCheck.Simple(slave, 1)); + if (slave.prestige > 0) { + let some = 'Some'; + if (slave.prestige > 1) { + some = 'Many'; + } + if (slave.prestige > 2) { + some = 'Most'; + } + if (slave.prestige > 3) { + some = 'Just about all'; + } + r.push(`${some} of the citizens watching your little show recognized ${him}, <span class="reputation inc">adding to your reputation and status.</span>`); + repX(slave.prestige * 100, "event", slave); + } return r.join(" "); }, @@ -3271,7 +3285,7 @@ App.UI.newSlaveIntro = function(slave, slave2, {tankBorn = false, momInterest = } if (tankBorn) { r.push(`${He} accepts your groping, even becoming aroused by it, but might not be a breast fetishist, though ${he} <span class="hotpink">certainly enjoys the attention.</span> By the feel of ${his} nipples between your fingers, ${he} may certainly develop into one.`); - if (V.incubator.setting.reproduction === 2 && slave.boobs > 400) { + if (slave.incubatorSettings.reproduction > 1 && slave.boobs > 400) { r.push(`A loud moan and a distinct wetness in your hand quickly draw your attention to ${him}. It seems <span class="green">${he} is lactating!</span>`); slave.lactation = 1; slave.lactationDuration = 2; @@ -3441,9 +3455,12 @@ App.UI.newSlaveIntro = function(slave, slave2, {tankBorn = false, momInterest = } r.push(`As ${he} begins to moan with lust, you grip down tightly and force ${him} to the floor. You straddle ${him} and lower your dripping pussy onto ${his} face${PC.dick !== 0 ? `, your erect cock coming to rest on ${his} forehead` : ``}. You continue stroking your toy's rod as ${he} eagerly begins eating you out. As ${his} cock begins to throb, anticipating ${his} upcoming orgasm,`); - if (tankBorn && (overpowerCheck(slave, V.PC) < random(1, 100)) && (V.incubator.setting.reproduction > 0)) { - r.push(`${he} shoves you onto your back and deeply penetrates you. Before you can kick ${him} off, ${he} thrusts twice and unloads ${his} pent up orgasm deep into your pussy. ${He} pulls out with a huge smile on ${his} face and a <span class="hotpink">deep love</span> for ${his} mate. You glower at ${him} as cum pools from your stretched cunt; ${he} might not be a dom now, but ${he} may certainly become one.`); + if (tankBorn && (overpowerCheck(slave, V.PC) < random(1, 100)) && slave.incubatorSettings.reproduction > 0) { + r.push(`${he} shoves you onto your back and deeply penetrates you${PC.vagina === 0 ? `, painfully <span class="virginity loss">piercing your maidenhead</span> in the process` : ``}. Before you can kick ${him} off, ${he} thrusts twice and unloads ${his} pent up orgasm deep into your pussy. ${He} pulls out with a huge smile on ${his} face and a <span class="hotpink">deep love</span> for ${his} mate. You glower at ${him} as cum pools from your stretched cunt; ${he} might not be a dom now, but ${he} may certainly become one.`); slave.devotion += 5; + if (V.PC.vagina === 0) { + V.PC.vagina = 1; + } seX(slave, "penetrative", V.PC, "vaginal"); if (random(1, 100) > 60 && slave.fetish === Fetish.NONE) { slave.fetish = "dom"; @@ -3835,7 +3852,7 @@ App.UI.newSlaveIntro = function(slave, slave2, {tankBorn = false, momInterest = } else { r.push(`grumbling unhappily when ${he} finds no milk within.`); } - if ((overpowerCheck(slave, V.PC) < random(1, 100)) && slave.muscles > 30 && V.incubator.setting.reproduction > 0 && canAchieveErection(slave)) { + if ((overpowerCheck(slave, V.PC) < random(1, 100)) && slave.muscles > 30 && slave.incubatorSettings.reproduction > 0 && canAchieveErection(slave)) { r.push(`Suddenly, ${he} shoves you onto your back and begins enthusiastically fucking your breasts. Before you can push ${him} off, ${he} thrusts hard and unloads ${his} pent-up orgasm deep into your cleavage and across your face. ${He} sits back with a huge smile on ${his} face and a <span class="hotpink">new connection to you.</span> ${He} <span class="gold">recoils in surprise and fear</span> when you respond by slapping ${him} across the face for ${his} impudence. ${He} might not look like a dom, but ${he} may turn into one.`); slave.devotion += 5; slave.trust -= 5; diff --git a/src/npc/interaction/FSuckle.js b/src/npc/interaction/FSuckle.js index 95305395d154b56dc330d5948a5d7d4e9e43cb60..bec8e22614404262a778579203dd10b106365479 100644 --- a/src/npc/interaction/FSuckle.js +++ b/src/npc/interaction/FSuckle.js @@ -443,7 +443,7 @@ App.Interact.fSuckle = function(slave) { r.push(`beside the groaning container of ${slave.inflationType} within ${him} and`); } } else if (slave.weight > 95) { - r.push(`getting familiar with ${his} fat belly as`); + r.push(`${his} fat belly softly cushioning your cheek and`); } r.push(`${his} over-productive bosoms dripping sweet cream on your face${(slave.nipples === "inverted") ? `, the milk waiting to be sucked from the tight inverted holes above you` : ``}${(V.PC.belly >= 10000) ? ` and your belly brushing the undersides of ${his} tits` : ``}. You`); if (mood === 2) { diff --git a/src/npc/startingGirls/startingGirls.js b/src/npc/startingGirls/startingGirls.js index b0d840350e384dc5a875edfa957157ad3795e92f..a7dc89943513cc21fdc524db54d077938b553cc6 100644 --- a/src/npc/startingGirls/startingGirls.js +++ b/src/npc/startingGirls/startingGirls.js @@ -2176,7 +2176,9 @@ App.StartingGirls.stats = function(slave) { ["PCChildrenFathered", "PC's children fathered"], ["slavesKnockedUp", "Slaves knocked up"], ["PCKnockedUp", "Times knocked up PC"], - ["bestiality", "Bestiality"] + ["bestiality", "Bestiality"], + ["timesBred", "Times Bred"], + ["PCChildrenBeared", "PC's children carried"] ]); options.addOption("Set all counters to 0", "counter", slave).customButton("Reset", () => slave.counter = new App.Entity.SlaveActionsCountersState(), ""); for (const key of counters) { diff --git a/src/npc/surgery/surrogacyWorkaround.js b/src/npc/surgery/surrogacyWorkaround.js index 5c028eaf38478fa74e604c7da24648a09f124725..1b87c8a98f32059b12ee0b7330356319fb5205ed 100644 --- a/src/npc/surgery/surrogacyWorkaround.js +++ b/src/npc/surgery/surrogacyWorkaround.js @@ -72,11 +72,13 @@ App.UI.surrogacyWorkaround = function() { App.UI.DOM.appendNewElement("div", node, "You have no slaves with potent sperm."); } - if (V.incubator.tanks.length > 0 && V.incubator.setting.reproduction === 2) { - App.UI.DOM.appendNewElement("h2", node, `Incubator settings are resulting in large-scale fluid secretion. Select an eligible incubatee to milk for semen:`); - + if (V.incubator.tanks.length > 0 && V.incubator.upgrade.reproduction === 1) { for (const tank of V.incubator.tanks) { - if (tank.balls > 0 && tank.dick > 0 && canBreed(donatrix, tank)) { + if (tank.balls > 0 && tank.dick > 0 && tank.incubatorSettings.reproduction === 2 && canBreed(donatrix, tank)) { + if (eligibilityI === 0) { + App.UI.DOM.appendNewElement("h2", node, `Incubator settings are resulting in large-scale fluid secretion. Select an eligible incubatee to milk for semen:`); + eligibilityI = 1; + } App.UI.DOM.appendNewElement("div", node, App.UI.DOM.link( tank.slaveName, () => { @@ -84,7 +86,6 @@ App.UI.surrogacyWorkaround = function() { App.UI.reload(); } )); - eligibilityI = 1; } } if (eligibilityI === 0) { diff --git a/src/player/desc/pLongBoobs.js b/src/player/desc/pLongBoobs.js index 753223aa33d0ec620cde130d6fd7ff61af121fb4..c94ae65490091f53a2204ca19f96872c31436b27 100644 --- a/src/player/desc/pLongBoobs.js +++ b/src/player/desc/pLongBoobs.js @@ -506,7 +506,7 @@ App.Desc.Player.boobs = function(PC = V.PC) { r.push(obviousImplants); } else { r.push(boobShape()); - r.push(`They tend bounce everywhere when you fuck your slaves.`); + r.push(`They tend to bounce everywhere when you fuck your slaves.`); } r.push(boobVolume()); } else if (PC.boobs >= 1000) { diff --git a/src/player/js/PlayerState.js b/src/player/js/PlayerState.js index eb78926e474f9bb3e8d19ef12dfb4e6836a86ee8..69b54359cc484b3f615db634b944eeeb85c4599d 100644 --- a/src/player/js/PlayerState.js +++ b/src/player/js/PlayerState.js @@ -1353,6 +1353,8 @@ App.Entity.PlayerState = class PlayerState { * * "atrophied" */ this.digestiveSystem = "normal"; + /** progress until .digestiveSystem is swapped to "normal". Completes at 20.*/ + this.weaningDuration = 0; /** * * -2: heavy male hormones * * -1: male hormones diff --git a/src/player/managePersonalAffairs.js b/src/player/managePersonalAffairs.js index eaff820a60f6a813acca2b0c3476387fe6238578..cd0e04ff5d4d2e8d68944781ff96965c9441f9b6 100644 --- a/src/player/managePersonalAffairs.js +++ b/src/player/managePersonalAffairs.js @@ -1077,6 +1077,20 @@ App.UI.managePersonalAffairs = function() { })); } + // Modded consumer grade PC drugs + App.Mods.Drugs.list.filter(drug => drug.isPCDrug && drug.isConsumerGrade && drug.available(PC)).forEach(drug => { + if (PC.drugs !== drug.name) { + if (drug.enable(PC) === true) { + links.push(App.UI.DOM.link(drug.text, () => { + PC.drugs = drug.name; + App.UI.DOM.replace(drugsDiv, drugs); + })); + } else { + links.push(App.UI.DOM.disabledLink(drug.text, [drug.enable(PC)])); + } + } + }); + text.push(App.UI.DOM.generateLinksStrip(links)); App.Events.addNode(consumerDrugsDiv, text); @@ -1498,6 +1512,20 @@ App.UI.managePersonalAffairs = function() { } } + // Modded slave grade PC drugs + App.Mods.Drugs.list.filter(drug => drug.isPCDrug && !drug.isConsumerGrade && drug.available(PC)).forEach(drug => { + if (PC.drugs !== drug.name) { + if (drug.enable(PC) === true) { + links.push(App.UI.DOM.link(drug.text, () => { + PC.drugs = drug.name; + App.UI.DOM.replace(drugsDiv, drugs); + })); + } else { + links.push(App.UI.DOM.disabledLink(drug.text, [drug.enable(PC)])); + } + } + }); + text.push(App.UI.DOM.generateLinksStrip(links)); App.Events.addNode(slaveDrugsDiv, text); diff --git a/src/pregmod/blackMarket.js b/src/pregmod/blackMarket.js index 9260b8426b2e2785d9fcdcf0ed24eac627a0758f..1843fb90b01af4b3b994e9d84f23fd1cb4f37ec0 100644 --- a/src/pregmod/blackMarket.js +++ b/src/pregmod/blackMarket.js @@ -335,6 +335,7 @@ App.UI.blackMarket = function() { r.push(`"I'm sorry, I can't sell this product to you, even if I wanted to," he says. "I have this technology, which if applied, would make slaves appear younger than the legal age of majority. I picked it up from an exotics dealer, who picked it up from some old world government research center. And yes, I know, this is a black market, and I would be happy to sell it to you, except, you see, too many of the wrong people know I have it, and while the knowledge isn't illegal, selling or using it is. See if I sell this to you, you'd start getting younger looking slaves, and those people would try to take us both down, and since I'm not the master of an arcology, I would probably end up enslaved, and I'm not interested in that. If only the laws were more open about who could have sex with who, I could sell this to anyone interested."`); r.push(`Since the agreed upon minimum age in your Free City is greater than eight, it would draw way too much attention for you to make use of the research recipe for the Childhood Fertility <span class="orange">Induced NCS</span> (genetic engineering and hormonal blend).`); App.Events.addNode(node, r, "div"); + r = []; } else { if (V.geneticMappingUpgrade === 0) { r.push(`You lack the facilities required for such a treatment to be effective on specific individuals.`); @@ -365,6 +366,7 @@ App.UI.blackMarket = function() { if (V.cash >= NCSCash) { r.push(r.pop() + `"`); App.Events.addNode(node, r, "div"); + r = []; App.UI.DOM.appendNewElement("div", node, App.UI.DOM.link( "Purchase childhood fertility induced NCS", () => { @@ -380,6 +382,7 @@ App.UI.blackMarket = function() { } else { r.push(`Or, you know, come back with money."`); App.Events.addNode(node, r, "div"); + r = []; r.push(`You cannot afford the asking price of <span class="cash dec">${(cashFormat(NCSCash))}</span> for the Childhood Fertility <span class="orange">Induced NCS</span> (genetic engineering and hormonal blend) research recipe.`); } } else { @@ -394,6 +397,7 @@ App.UI.blackMarket = function() { App.UI.DOM.combineNodes(App.Encyclopedia.link("Childhood Fertility Induced NCS"), ".") ); App.Events.addNode(node, r, "div"); + r = []; if (V.minimumSlaveAge <= 15 && V.minimumSlaveAge > 8) { V.merchantIllegalWares.delete("childhoodFertilityInducedNCS"); }