diff --git a/.gitignore b/.gitignore index 36b4d00deeb5a33fc7831b5c2ee11b30581692de..dfacdbb2c958b4a10bb6a18b65a735c72f851fb2 100644 --- a/.gitignore +++ b/.gitignore @@ -16,76 +16,6 @@ Sessionx.vim tags [._]*.un~ -# C extensions -*.so - -# Distribution / packaging -.Python -env/ -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -*.egg-info/ -.installed.cfg -*.egg -bin/* - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*,cover -.hypothesis/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# IPython Notebook -.ipynb_checkpoints - -# pyenv -.python-version - # celery beat schedule file celerybeat-schedule @@ -112,6 +42,7 @@ yarn.lock # Visual Studio Code .vscode/settings.json +.vscode/tasks.json *.code-workspace # WebStorm @@ -126,6 +57,7 @@ yarn.lock # misc fc-pregmod +bin/* *.outline *.todo TODO.txt diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index 0a3859ac54632db02246f16bd4b628faeea26e1c..0000000000000000000000000000000000000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - // See https://go.microsoft.com/fwlink/?LinkId=733558 - // for the documentation about the tasks.json format - "version": "2.0.0", - "command": "Test build", - "tasks": [ - { - "label": "Compile", - "type": "shell", - "command": "./compile.sh", - "windows": { - "command": ".\\compile.bat" - }, - "group": "build", - "presentation": { - "reveal": "always", - "panel": "new" - }, - "problemMatcher": [] - }, - { - "label": "Run in Chrome", - "type": "process", - "command": "chrome.exe", - "windows": { - "command": "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe" - }, - "group": "test", - "args": [ - "${workspaceRoot}/bin/FC_pregmod.html", "--incognito" - ], - "problemMatcher": [], - } - ] -} diff --git a/devTools/types/FC/UI.d.ts b/devTools/types/FC/UI.d.ts index 75680e0ff630fb7da286266fc9e18b3d76623be2..fd6d22e55120a4153d7ea03f7f003aa9f8dc1279 100644 --- a/devTools/types/FC/UI.d.ts +++ b/devTools/types/FC/UI.d.ts @@ -32,3 +32,5 @@ declare namespace FC { } } } + +declare type PassageLinkMap = Pick<HTMLElementTagNameMap, 'a' | 'audio' | 'img' | 'source' | 'video'> diff --git a/devTools/types/FC/desc.d.ts b/devTools/types/FC/desc.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..c98a1e3ec8e7d62fd9faf64d2ba3350f6908fb3a --- /dev/null +++ b/devTools/types/FC/desc.d.ts @@ -0,0 +1,14 @@ +declare namespace FC { + namespace Desc { + interface LongSlaveOptions { + /** + * 0 if the slave is not for sale. Otherwise a string with the name of the market, + * partially to determine if laws apply to the market or not. + */ + market?: Zeroable<string>; + eventDescription?: boolean; + prisonCrime?: boolean; + noArt?: boolean; + } + } +} diff --git a/devTools/types/FC/gameState.d.ts b/devTools/types/FC/gameState.d.ts index 2ea8aa8634098ae9e3ef82ef3b2bccc6d302df22..d8623d645d13a8e42e22c7e867d8dfe3ac7a3664 100644 --- a/devTools/types/FC/gameState.d.ts +++ b/devTools/types/FC/gameState.d.ts @@ -172,6 +172,7 @@ declare namespace FC { milkmaidTrustBonus?: number; milkmaidHealthBonus?: number; + AS: number; HGTrainSlavesIDs?: HeadGirlTrainee[]; heroSlaveID?: number; seed?: number; diff --git a/gulpfile.js b/gulpfile.js index 295949532d6678e29695dc51bbf452414a0ebc51..e86b71450977bc75a4511cf7e9f3d09e94e97212 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -59,7 +59,11 @@ function processScripts(srcGlob, destDir, destFileName) { .pipe(addSourcemaps ? sourcemaps.init() : noop()) .pipe(concat(destFileName)) .pipe(addSourcemaps ? - sourcemaps.write(args.embedsourcemaps ? undefined : '.', {includeContent: args.sourcemapsincludecontent, sourceRoot: prefix}) : + sourcemaps.write(args.embedsourcemaps ? undefined : '.', { + includeContent: args.sourcemapsincludecontent, + sourceRoot: prefix, + sourceMappingURLPrefix: path.relative(cfg.dirs.output, destDir) + }) : noop()) .pipe(gulp.dest(destDir)); } @@ -75,7 +79,11 @@ function processStylesheets(srcGlob, destDir, destFileName) { postcss([autoprefixer({overrideBrowserslist: ['last 2 versions']})]) : noop()) .pipe(addSourcemaps ? - sourcemaps.write(args.embedsourcemaps ? undefined : '.', {includeContent: args.sourcemapsincludecontent, sourceRoot: prefix}) : + sourcemaps.write(args.embedsourcemaps ? undefined : '.', { + includeContent: args.sourcemapsincludecontent, + sourceRoot: prefix, + sourceMappingURLPrefix: path.relative(cfg.dirs.output, destDir) + }) : noop()) .pipe(gulp.dest(destDir)); } diff --git a/js/003-data/gameVariableData.js b/js/003-data/gameVariableData.js index a223343999c65f7c96dfd231391ca3858be97772..b4e328666d39397b248cf3cacc01a56b65e39169 100644 --- a/js/003-data/gameVariableData.js +++ b/js/003-data/gameVariableData.js @@ -81,6 +81,7 @@ App.Data.defaultGameStateVariables = { extremeUnderage: 0, formatNumbers: 1, fucktoyInteractionsPosition: 1, + slaveInteractLongForm: false, headGirlSoftensFlaws: 1, headGirlTrainsFlaws: 1, headGirlTrainsHealth: 1, diff --git a/src/003-assets/CSS/links.css b/src/003-assets/CSS/links.css index 85517ce2a136a4c5851d050b3db8a59c3a3b429a..654265f051a54e3cb206dd9788a6addd3fe4df5b 100644 --- a/src/003-assets/CSS/links.css +++ b/src/003-assets/CSS/links.css @@ -11,8 +11,7 @@ font-size: smaller; width: 20em; margin-left: -10em; - background-color: slategray; - color: black; + background-color: rgb(29, 30, 32); text-align: center; border-radius: 3px; padding: 3px; diff --git a/src/004-base/facility.js b/src/004-base/facility.js index 717420d7e47f59423203b93994260e5bee3f33a8..7147c506f9dc007781b18659031f2bd440021ffd 100644 --- a/src/004-base/facility.js +++ b/src/004-base/facility.js @@ -262,13 +262,14 @@ App.Entity.Facilities.Facility = class { /** Facility display name * @returns {string} */ get name() { - const res = (typeof V[this.desc.baseName] === "object") ? V[this.desc.baseName].name : V[this.desc.baseName + "Name"]; + const stateObj = V[this.desc.baseName]; + const res = (stateObj && typeof stateObj === "object") ? stateObj.name : V[this.desc.baseName + "Name"]; return res !== undefined ? res : 'the ' + this.genericName; } /** @returns {string} */ get nameCaps() { - return capFirstChar(this.desc.baseName); + return capFirstChar(this.name); } /** @returns {string} */ diff --git a/src/Corporation/manageCorporation.tw b/src/Corporation/manageCorporation.tw index 454175169ada074b595ffcf15c28e6da08488943..b221a8bb2a8633dad51a264dea6e046ac566dbc9 100644 --- a/src/Corporation/manageCorporation.tw +++ b/src/Corporation/manageCorporation.tw @@ -324,7 +324,7 @@ You own <<print num($personalShares)>> shares while another <<print num($publicS <br>You can sell some of your shares on the stock market. [[Sell 1000|Manage Corporation][cashX(corpSharePrice(), "stocksTraded"), $personalShares -= 1000, $publicShares += 1000]] <</if>> <<if $cash > corpSharePrice() && $publicShares >= 1000>> - <br>You can buy some shares from the stock market [[Buy 1000|Manage Corporation][cashX(forceNeg(corpSharePrice()), "stocksTraded"), $personalShares += 1000, $publicShares -= 1000]] + <br>You can buy some shares from the stock market. [[Buy 1000|Manage Corporation][cashX(forceNeg(corpSharePrice()), "stocksTraded"), $personalShares += 1000, $publicShares -= 1000]] <</if>> <h3>Stock Split</h3> @@ -350,7 +350,7 @@ You own <<print num($personalShares)>> shares while another <<print num($publicS <<set _splitTotal = _splitValue * ($publicShares + $personalShares) + _splitFeeValue>> <<set _splitWeek = _stockType['weeks']>> <li><<= _splitNumerator >>-for-<<= _splitDenom>> <<if _splitDenom > _splitNumerator>>inverse<</if>> stock split at @@.red;<<= cashFormat(_splitValue) >>@@ per share. - Including market fees, this will cost the corporation a total of @@.red;<<= cashFormat(_splitTotal)>>@@, + Including market fees, this will cost the corporation a total of @@.red;<<= cashFormat(_splitTotal)>>,@@ leaving the going rate for stock at @@.yellowgreen;<<= cashFormat(Math.floor(corpSharePrice(0, $personalShares * _splitMultiplier, $publicShares * _splitMultiplier))) >>@@ per 1000 shares. <<if $corp.SpecTimer == 0>> <<if $publicShares % _splitDenom != 0 || $personalShares % _splitDenom != 0>> diff --git a/src/Mods/SecExp/js/Unit.js b/src/Mods/SecExp/js/Unit.js index 77260493c86d8d4bc08eb93578944056ee953fb0..35fac5031ab627d3de6aa952931b21781ba3407a 100644 --- a/src/Mods/SecExp/js/Unit.js +++ b/src/Mods/SecExp/js/Unit.js @@ -3,7 +3,6 @@ */ App.SecExp.bulkUpgradeUnit = function(unit) { unit = Array.isArray(unit) ? unit : [unit]; - // console.log(unit); return; let el = document.createElement("a"); function upgradeUnit(x) { @@ -37,16 +36,14 @@ App.SecExp.bulkUpgradeUnit = function(unit) { return Math.ceil(cost *= 1.1); } - if (unit.length > 0) { - const price = unit.map(getCost).reduce((acc, cur) => acc + cur); - if (price > 0) { - el.append(App.UI.DOM.link(`Bulk upgrade for ${cashFormat(price)}`, () => { - unit.map(upgradeUnit).reduce((acc, cur) => acc + cur); - cashX(-price, "securityExpansion"); - }, - [], passage() - )); - } + const price = unit.map(getCost).reduce((acc, cur) => acc + cur); + if (price > 0) { + el.append(App.UI.DOM.link(`Bulk upgrade for ${cashFormat(price)}`, () => { + unit.map(upgradeUnit).reduce((acc, cur) => acc + cur); + cashX(-price, "securityExpansion"); + }, + [], passage() + )); } return el; }; diff --git a/src/Mods/SecExp/js/buildingsJS.js b/src/Mods/SecExp/js/buildingsJS.js index f12f8329c26d862345dfb15fbadb41e6f1022425..f0ac128806045d97620b2e2d746c86042e4d8f3f 100644 --- a/src/Mods/SecExp/js/buildingsJS.js +++ b/src/Mods/SecExp/js/buildingsJS.js @@ -198,10 +198,11 @@ App.SecExp.propHub = (function() { } if (V.SecExp.buildings.propHub && Object.entries(V.SecExp.buildings.propHub).length === 0) { delete V.SecExp.buildings.propHub; - } else if (V.propHub || (V.SecExp.buildings.propHub && Object.entries(V.SecExp.buildings.propHub).length > 0)){ + } else if (V.propHub || (V.SecExp.buildings.propHub && Object.entries(V.SecExp.buildings.propHub).length > 0)) { V.SecExp.buildings.propHub = V.SecExp.buildings.propHub || {}; V.SecExp.buildings.propHub.upgrades = V.SecExp.buildings.propHub.upgrades || {}; - V.SecExp.buildings.propHub.recruiterOffice = V.SecExp.buildings.propHub.recruiterOffice || V.recuriterOffice || V.RecuriterOffice || 0; + V.SecExp.buildings.propHub.recruiterOffice = V.SecExp.buildings.propHub.recruiterOffice || V.SecExp.buildings.propHub.recuriterOffice || V.recuriterOffice || V.RecuriterOffice || 0; + delete V.SecExp.buildings.propHub.recuriterOffice; V.SecExp.buildings.propHub.upgrades.campaign = V.SecExp.buildings.propHub.upgrades.campaign || V.SecExp.buildings.propHub.campaign || V.propCampaign || 0; delete V.SecExp.buildings.propHub.campaign; @@ -216,17 +217,18 @@ App.SecExp.propHub = (function() { if (V.propFocus && V.propFocus !== "none") { V.SecExp.buildings.propHub.focus = V.propFocus; } - - const vars = ['fakeNews', 'controlLeaks', 'marketInfiltration', 'blackOps']; - for(let i = 0; i < vars.length; i++) { - if (jsDef(V[vars[i]]) && V[vars[i]] > 0) { - V.SecExp.buildings.propHub[vars[i]] = V[vars[i]]; - delete V[vars[i]]; - } else { - V.SecExp.buildings.propHub.upgrades[vars[i]] = V.SecExp.buildings.propHub.upgrades[vars[i]] || V.SecExp.buildings.propHub[vars[i]] || 0; - delete V.SecExp.buildings.propHub[vars[i]]; - } - } + + V.SecExp.buildings.propHub.upgrades.fakeNews = V.SecExp.buildings.propHub.upgrades.fakeNews || V.SecExp.buildings.propHub.fakeNews || V.fakeNews || 0; + delete V.SecExp.buildings.propHub.fakeNews; + + V.SecExp.buildings.propHub.upgrades.controlLeaks = V.SecExp.buildings.propHub.upgrades.controlLeaks || V.SecExp.buildings.propHub.controlLeaks || V.controlLeaks || 0; + delete V.SecExp.buildings.propHub.controlLeaks; + + V.SecExp.buildings.propHub.upgrades.marketInfiltration = V.SecExp.buildings.propHub.upgrades.marketInfiltration || V.SecExp.buildings.propHub.marketInfiltration || V.marketInfiltration || 0; + delete V.SecExp.buildings.propHub.marketInfiltration; + + V.SecExp.buildings.propHub.upgrades.blackOps = V.SecExp.buildings.propHub.upgrades.blackOps || V.SecExp.buildings.propHub.blackOps || V.blackOps || 0; + delete V.SecExp.buildings.propHub.blackOps; } } })(); @@ -252,13 +254,19 @@ App.SecExp.barracks = (function() { } if (V.SecExp.buildings.barracks && Object.entries(V.SecExp.buildings.barracks === 0).length) { delete V.SecExp.buildings.barracks; - } else if (V.secBarracks || (V.SecExp.buildings.barracks && Object.entries(V.SecExp.buildings.barracks).length > 0)){ - V.SecExp.buildings.barracks = V.SecExp.buildings.barracks || V.SecExp.buildings.barracks.upgrades || V.secBarracksUpgrades || {}; + } else if (V.secBarracks || (V.SecExp.buildings.barracks && Object.entries(V.SecExp.buildings.barracks).length > 0)) { + V.SecExp.buildings.barracks = V.SecExp.buildings.barracks || V.secBarracksUpgrades || {}; V.SecExp.buildings.barracks.size = V.SecExp.buildings.barracks.size || 0; V.SecExp.buildings.barracks.luxury = V.SecExp.buildings.barracks.luxury || 0; V.SecExp.buildings.barracks.training = V.SecExp.buildings.barracks.training || 0; V.SecExp.buildings.barracks.loyaltyMod = V.SecExp.buildings.barracks.loyaltyMod || 0; - delete V.SecExp.buildings.barracks.upgrades; + if (V.SecExp.buildings.barracks.upgrades) { + V.SecExp.buildings.barracks.size = V.SecExp.buildings.barracks.upgrades.size; + V.SecExp.buildings.barracks.luxury = V.SecExp.buildings.barracks.upgrades.luxury; + V.SecExp.buildings.barracks.training = V.SecExp.buildings.barracks.upgrades.training; + V.SecExp.buildings.barracks.loyaltyMod = V.SecExp.buildings.barracks.upgrades.loyaltyMod; + delete V.SecExp.buildings.barracks.upgrades; + } } } })(); @@ -306,13 +314,18 @@ App.SecExp.secHub = (function() { V.SecExp.buildings.secHub = V.SecExp.buildings.secHub || {}; V.SecExp.buildings.secHub.menials = V.SecExp.buildings.secHub.menials || V.secMenials || V.secHelots || 0; V.SecExp.buildings.secHub.coldstorage = V.SecExp.buildings.secHub.coldstorage || 0; + + V.SecExp.buildings.secHub.upgrades = V.SecExp.buildings.secHub.upgrades || {}; + V.SecExp.buildings.secHub.upgrades.security = V.SecExp.buildings.secHub.upgrades.security || {}; if (V.secUpgrades) { V.SecExp.buildings.secHub.coldstorage = V.secUpgrades.coldstorage; - delete V.secUpgrades.coldstorage; + V.SecExp.buildings.secHub.upgrades.security = { + nanoCams: V.secUpgrades.nanoCams, + cyberBots: V.secUpgrades.cyberBots, + eyeScan: V.secUpgrades.eyeScan, + cryptoAnalyzer: V.secUpgrades.cryptoAnalyzer, + }; } - - V.SecExp.buildings.secHub.upgrades = V.SecExp.buildings.secHub.upgrades || {}; - V.SecExp.buildings.secHub.upgrades.security = V.SecExp.buildings.secHub.upgrades.security || V.secUpgrades || {}; V.SecExp.buildings.secHub.upgrades.crime = V.SecExp.buildings.secHub.upgrades.crime || V.crimeUpgrades || {}; V.SecExp.buildings.secHub.upgrades.intel = V.SecExp.buildings.secHub.upgrades.intel || V.intelUpgrades || {}; V.SecExp.buildings.secHub.upgrades.readiness = V.SecExp.buildings.secHub.upgrades.readiness || V.readinessUpgrades || {}; diff --git a/src/arcologyBuilding/markets.js b/src/arcologyBuilding/markets.js index 24857dda5011c948ed735fd0bab9c1d589d323da..cba926556c32453861bfd415ae747c5fb21c6a6e 100644 --- a/src/arcologyBuilding/markets.js +++ b/src/arcologyBuilding/markets.js @@ -129,7 +129,7 @@ App.Arcology.Cell.Market = class extends App.Arcology.Cell.BaseCell { this.type = "Corporate Market"; V.corp.Market = 1; V.corp.Cash -= corpCost; - }, 0, `Costs ${cashFormat(corpCost)} of the corporation's money` + }, 0, ` Costs ${cashFormat(corpCost)} of the corporation's money` )); } diff --git a/src/endWeek/masterSuiteReport.js b/src/endWeek/masterSuiteReport.js index b71d9f7fd913197620cf7ea6a074afb4ca5d6ba4..874a3b72c2ba964fefa8c39144065d04e4d750a7 100644 --- a/src/endWeek/masterSuiteReport.js +++ b/src/endWeek/masterSuiteReport.js @@ -339,11 +339,9 @@ App.EndWeek.masterSuiteReport = function() { $(msContent).append(`${He} ${App.SlaveAssignment.pleaseYou(slave)}`); if (V.servantMilkers === 1 && slave.lactation > 0 && slave.fuckdoll === 0 && slave.fetish !== "mindbroken" && canMove(slave) && slave.intelligence+slave.intelligenceImplant >= -90) { - const milkIntro = `When ${his} breasts begin to feel full and you aren't around, ${he} avails ${himself} to the penthouse milkers and `; - const milkContent = App.UI.DOM.appendNewElement("div", smallFrag, milkIntro, "indent"); const milkingResults = App.SlaveAssignment.getMilked(slave, 0.25); - $(milkContent).append(milkingResults.text); - $(milkContent).append(`gives ${milkingResults.milk} liters of milk over the week, which is sold for <span class="cash inc">${cashFormat(milkingResults.milkSale)}.</span>`); + const milkDiv = App.UI.DOM.appendNewElement("div", smallFrag, `When ${his} breasts begin to feel full and you aren't around, ${he} avails ${himself} to the penthouse milkers and gives ${milkingResults.milk} liters of milk over the week, which is sold for `, "indent"); + App.UI.DOM.appendNewElement("span", milkDiv, `${cashFormat(milkingResults.milkSale)}.`, ["cash", "inc"]); } const commonContent = App.UI.DOM.appendNewElement("div", smallFrag, '', "indent"); commonContent.append(App.SlaveAssignment.standardSlaveReport(slave, false)); diff --git a/src/endWeek/saLongTermEffects.js b/src/endWeek/saLongTermEffects.js index 58b85c2e42b3b51a69f8a050d760ea02f3932e30..e193f07b4c9f021eca8efc80354e079af0a71d78 100644 --- a/src/endWeek/saLongTermEffects.js +++ b/src/endWeek/saLongTermEffects.js @@ -35,7 +35,7 @@ App.SlaveAssignment.longTermEffects = (function() { } if (assignmentVisible(slave) && (slave.assignment !== "live with your Head Girl" || V.HGSuiteSurgery === 0)) { if (hasSurgeryRule(slave, V.defaultRules) && slave.useRulesAssistant === 1 && slave.indentureRestrictions < 2 && V.cash > 0) { - r.push(`rulesAutosurgery(slave)`); + r.push(rulesAutosurgery(slave)); } } r.push(App.SlaveAssignment.clothes(slave)); diff --git a/src/endWeek/saPregnancy.js b/src/endWeek/saPregnancy.js index 0f215860f66c0a88769cb17c80e57c829be14841..1a4ef2dad884a5bdbe3d2b236a1165b0118a2d50 100644 --- a/src/endWeek/saPregnancy.js +++ b/src/endWeek/saPregnancy.js @@ -888,7 +888,7 @@ App.SlaveAssignment.pregnancy = (function() { if (slave.fetishKnown === 1 && slave.fetishStrength <= 95) { r.push(`Such total satisfaction of ${his} pregnancy fantasies <span class="fetish inc">strengthens ${his} fetish.</span>`); slave.fetishStrength += 4; - } else { + } else if (slave.fetishKnown === 0) { r.push(`You are now well aware of ${his} <span class="fetish gain">latent pregnancy fetish.</span>`); slave.fetishKnown = 1; } diff --git a/src/endWeek/saRecruitGirls.js b/src/endWeek/saRecruitGirls.js index e855a0d2d600cb2ba186e1ab9bbf0ef64922342f..2780ac1f5b4062466dcd5aa34449c03f1da3ad8a 100644 --- a/src/endWeek/saRecruitGirls.js +++ b/src/endWeek/saRecruitGirls.js @@ -1654,8 +1654,42 @@ App.SlaveAssignment.recruitGirls = (function() { } else { pushFS(`${He} never considers promoting your household's Revivalist protocols, since you don't value your Head Girl enough to accord ${him} a separate apartment inside your walls.`); } + } else if (arcology.FSAztecRevivalist !== "unset") { + if (arcology.FSPaternalist !== "unset") { + if (slave.health.condition >= 80 && slave.bellyPreg < 1500 && slave.trust + slave.devotion >= 175) { + pushFS(`${He} allows willing members of the public to <span class="health dec">spill ${his} blood</span> in tribute to the gods.`); + healthDamage(slave, 2); + FSmatch++; + seed += 5; + arcology.FSAztecRevivalist += 0.02 * V.FSSingleSlaveRep; + } else if (slave.trust + slave.devotion < 175) { + pushFS(`${He} is willing to take part in bloodletting, but the public doesn't find that believable.`); + } else if (slave.bellyPreg >= 1500) { + pushFS(`${He} is willing to take part in bloodletting, but the public absolutely refuses to do such a thing to a pregnant $girl.`); + } else { + pushFS(`${He} is willing to take part in bloodletting, but the public finds it wrong to impose on someone not in the absolute best of health.`); + } + } else { + if (slave.health.condition >= -20 && slave.trust + slave.devotion >= 175) { + pushFS(`${He} practices public displays of <span class="health dec">bloodletting,</span> both on ${himself} and those willing, impressing onlookers with ${his} devotion to the gods.`); + healthDamage(slave, 2); + FSmatch++; + seed += 5; + arcology.FSAztecRevivalist += 0.02 * V.FSSingleSlaveRep; + } else if (slave.trust + slave.devotion < 175) { + pushFS(`${He} is willing to take part in bloodletting, but you have no reason to trust ${him} with the tools required.`); + } else { + pushFS(`${He} is willing to take part in bloodletting, but you can't allow ${him} to do so in ${his} poor health.`); + } + } + if (slaveInt > 15) { + pushFS(`${He} puts ${his} mind to work as ${he} joins citizens in their prayers to each diety.`); + FSdefend++; + seed += 1; + } else { + pushFS(`${His} poor attempts to espouse the benefits of true faith leave the crowd wondering if ${he} is next in line for sacrifice.`); + } } - /* TODO: and then there's Aztec revivalist, completely forgotten */ repX(Math.trunc(seed * 5), "futureSocieties", slave); diff --git a/src/endWeek/saRelationships.js b/src/endWeek/saRelationships.js index 7297eb64a2adb6998a2fea094e3ac1dbfe7d263a..0d088ae0d59be71c3462aefa9e898bb66244e32b 100644 --- a/src/endWeek/saRelationships.js +++ b/src/endWeek/saRelationships.js @@ -920,8 +920,10 @@ App.SlaveAssignment.relationships = (function() { } else if (slave.behavioralQuirk === "sinful") { r.push(`${His} feelings about carrying ${his} ${relationType}'s child${slave.pregType > 1 ? "ren" : ""} are <span class="devotion inc">secretly less mixed,</span> though.`); slave.devotion += 1; + } else if (slave.sexualFlaw === "breeder") { + r.push(`${He} occasionally remembers that ${he}'s carrying ${his} ${relationType}'s ${slave.pregType > 1 ? `children` : `child`}, but ${his} fetish for all things pregnancy is so strong it overpowers the deep-rooted revulsion.`); } else if (slave.devotion > 95) { - r.push(`${He} occasionally remembers that ${he}'s carrying ${his} ${relationType}'s child${slave.pregType > 1 ? "ren" : ""}, but does ${his} best to accept it by not thinking about it.`); + r.push(`${He} occasionally remembers that ${he}'s carrying ${his} ${relationType}'s ${slave.pregType > 1 ? `children` : `child`}, but does ${his} best to accept it by not thinking about it.`); } else if (slave.devotion > 50) { r.push(`${He}'s <span class="devotion dec">disgusted</span> that the`); if (slave.pregType > 1) { diff --git a/src/endWeek/saServeThePublic.js b/src/endWeek/saServeThePublic.js index 496d3a8201412650b4bf2f5935457dec7031da6a..c8ed0ec1c9457c73d445d1f0f46b0d0a4383c238 100644 --- a/src/endWeek/saServeThePublic.js +++ b/src/endWeek/saServeThePublic.js @@ -322,7 +322,7 @@ App.SlaveAssignment.serveThePublic = (function() { } else { r += ` It gets tiring `; if (hasBothLegs(slave)) { - r += `dancing all day and fucking all day, `; + r += `dancing and fucking all day, `; } else { r += `being a popular slut, `; } diff --git a/src/endWeek/saWorkAGloryHole.js b/src/endWeek/saWorkAGloryHole.js index ea7ebf8218da1889d7d1179ff74796abbc41fb02..a07186c94c548d988c2512187dfd89a3172d6167 100644 --- a/src/endWeek/saWorkAGloryHole.js +++ b/src/endWeek/saWorkAGloryHole.js @@ -176,7 +176,7 @@ App.SlaveAssignment.workAGloryHole = (function() { slave.trust -= 5; repX(forceNeg(50), "disobedience", slave); } else { - r += ` ${He} spends long hours cooped up in a small box with nothing to rest on. Even if ${he} where to try to lean against its side, it won't be long before another dick pokes through the hole demanding service. By the time ${he} is released, ${he} is <span class="red">utterly exhausted.</span>`; + r += ` ${He} spends long hours cooped up in a small box with nothing to rest on. Even if ${he} were to try to lean against its side, it won't be long before another dick pokes through the hole demanding service. By the time ${he} is released, ${he} is <span class="red">utterly exhausted.</span>`; } } tired(slave); diff --git a/src/facilities/wardrobe/wardrobeShopping.js b/src/facilities/wardrobe/wardrobeShopping.js index 3614f419b7581a5d1c514cc747eb8087be7756f9..7f9d455ad8a9af3b0420ed5addc8b2d6a008576e 100644 --- a/src/facilities/wardrobe/wardrobeShopping.js +++ b/src/facilities/wardrobe/wardrobeShopping.js @@ -191,7 +191,9 @@ App.UI.WardrobeShopping = function() { } ) ); - App.UI.DOM.appendNewElement("span", div, ` Costs ¤${cost}`, "detail"); + if (cost > 0) { + App.UI.DOM.appendNewElement("span", div, ` Costs ¤${cost}`, "detail"); + } } else { div.append( App.UI.DOM.disabledLink( diff --git a/src/gui/options/options.tw b/src/gui/options/options.tw index 6077eb0299d2bcb0170b78166a57897b41d91ad7..1ab2f1a3fe5c74e4bbb620138e7dd4a2d05b0dd9 100644 --- a/src/gui/options/options.tw +++ b/src/gui/options/options.tw @@ -151,6 +151,9 @@ <<run _options.addOption("Interactions with your fucktoys are", "fucktoyInteractionsPosition") .addValueList([["next to them", 1], ["at page bottom", 0]])>> + <<run _options.addOption("Hide tabs in Slave Interact", "slaveInteractLongForm") + .addValue("Enabled", true).on().addValue("Disabled", false).off()>> + <<run _options.addOption("Line separations are", "lineSeparations") .addValue("Shown", 1).on().addValue("Hidden", 0).off()>> diff --git a/src/gui/options/summaryOptions.tw b/src/gui/options/summaryOptions.tw index 5e360ba4f630ba9031e4be7813dfd9f71f5a7635..6b73edd5b495bceb5d7eb8e488d3e4125666ecf0 100644 --- a/src/gui/options/summaryOptions.tw +++ b/src/gui/options/summaryOptions.tw @@ -43,7 +43,7 @@ <h2>Individual panels</h2> Sample summary: -<<includeDOM App.UI.SlaveList.render([$activeSlave.ID], new Array(), App.UI.SlaveList.SlaveInteract.stdInteract)>> +<<includeDOM App.UI.SlaveList.render([$slaves.random().ID], new Array(), App.UI.SlaveList.SlaveInteract.stdInteract)>> <<set _options = (new App.UI.OptionsGroup()).enableDoubleColumn()>> diff --git a/src/gui/storyCaption.js b/src/gui/storyCaption.js index 04b939705aa9aa1e13a9f6e201d58089abf0070d..9d64c30ba8dc8d7a1c8c895e5bdd882f5e20b60e 100644 --- a/src/gui/storyCaption.js +++ b/src/gui/storyCaption.js @@ -203,7 +203,7 @@ App.UI.storyCaption = function() { if (pass === "Main") { div.append(App.UI.DOM.passageLink("Upkeep", "Costs Budget"), " | "); } else { - div.append(" Upkeep |"); + div.append(" Upkeep | "); } App.UI.DOM.appendNewElement("span", div, cashFormat(V.costs), ["cash", "dec"]); return div; diff --git a/src/interaction/siCustom.js b/src/interaction/siCustom.js new file mode 100644 index 0000000000000000000000000000000000000000..fe81a8a2ccf381ea7503fc1768650a0bfda92b6d --- /dev/null +++ b/src/interaction/siCustom.js @@ -0,0 +1,858 @@ +App.UI.SlaveInteract.custom = (function() { + let el; + let label; + let result; + let textbox; + return custom; + + function custom(slave) { + let title; + el = document.createElement('div'); + + el.appendChild(intro(slave)); + + title = document.createElement('h3'); + title.textContent = `Art`; + el.appendChild(title); + el.appendChild(customSlaveImage(slave)); + el.appendChild(customHairImage(slave)); + + title = document.createElement('h3'); + title.textContent = `Names`; + el.appendChild(title); + el.appendChild(playerTitle(slave)); + el.appendChild(slaveFullName(slave)); + + title = document.createElement('h3'); + title.textContent = `Description`; + el.appendChild(title); + el.appendChild(hair(slave)); + el.appendChild(eyeColor(slave)); + el.appendChild(customTattoo(slave)); + el.appendChild(customOriginStory(slave)); + el.appendChild(customDescription(slave)); + el.appendChild(customLabel(slave)); + + return el; + } + + function intro(slave) { + const frag = new DocumentFragment(); + let p; + p = document.createElement('p'); + p.id = "rename"; + frag.append(p); + + p = document.createElement('p'); + p.className = "scene-p"; + p.append(`You may enter custom descriptors for your slave's hair color, hair style, tattoos, or anything else here. After typing, press `); + p.appendChild(App.UI.DOM.makeElement("kbd", "enter")); + p.append(` to commit your change. These custom descriptors will appear in descriptions of your slave, but will have no gameplay effect. Changing them is free.`); + frag.append(p); + return frag; + } + + function playerTitle(slave) { + const { + // eslint-disable-next-line no-unused-vars + he, + him, + his, + hers, + himself, + boy, + He, + His + } = getPronouns(slave); + let playerTitle = document.createElement('p'); + label = document.createElement('div'); + if (slave.devotion >= -50) { + if (slave.custom.title !== "") { + label.textContent = `You have instructed ${him} to always refer to you as ${slave.custom.title}, which, should ${he} lisp, comes out as ${slave.custom.titleLisp}.`; + } else { + label.textContent = `You expect ${him} to refer to you as all your other slaves do.`; + } + result = document.createElement('div'); + result.id = "result"; + result.className = "choices"; + + let hiddenTextBox = document.createElement('span'); + let shownTextBox = document.createElement('span'); + if (slave.custom.title === "") { + hiddenTextBox.appendChild( + App.UI.DOM.link( + `Set a custom title for ${him} to address you as`, + () => { + jQuery('#result').empty().append(shownTextBox); + } + ) + ); + result.appendChild(hiddenTextBox); + shownTextBox.textContent = `Custom title: `; + textbox = App.UI.DOM.makeTextBox( + "", + v => { + slave.custom.title = v; + jQuery('#result').empty().append( + document.createTextNode(`${He}'ll try ${his} best to call you ${slave.custom.title}.`) + ); + slave.custom.titleLisp = lispReplace(slave.custom.title); + }); + shownTextBox.appendChild(textbox); + } else { + result.append(`${He}'s trying ${his} best to call you `); + textbox = App.UI.DOM.makeTextBox( + slave.custom.title, + v => { + slave.custom.title = v; + jQuery('#result').empty().append( + document.createTextNode(`${He}'ll try ${his} best to call you ${slave.custom.title}.`) + ); + slave.custom.titleLisp = lispReplace(slave.custom.title); + }); + result.appendChild(textbox); + result.appendChild( + App.UI.DOM.link( + ` Stop using a custom title`, + () => { + jQuery('#result').empty().append( + document.createTextNode(`${He} will no longer refer to you with a special title.`) + ); + slave.custom.title = ""; + slave.custom.titleLisp = ""; + } + ) + ); + } + label.appendChild(result); + } else { + label.textContent = `You must break ${his} will further before ${he} will refer to you by a new title. `; + if (SlaveStatsChecker.checkForLisp(slave)) { + if (slave.custom.titleLisp && slave.custom.titleLisp !== "") { + label.textContent += `For now, ${he} intends to keep calling you "${slave.custom.titleLisp}."`; + } + } else { + if (slave.custom.title && slave.custom.title !== "") { + label.textContent += `For now, ${he} intends to keep calling you "${slave.custom.title}."`; + } + } + } + playerTitle.appendChild(label); + return playerTitle; + } + + function slaveFullName(slave) { + const { + // eslint-disable-next-line no-unused-vars + he, + him, + his, + hers, + himself, + boy, + He, + His + } = getPronouns(slave); + let slaveFullNameNode = document.createElement('span'); + if ( + ((slave.devotion >= -50 || slave.trust < -20) && (slave.birthName !== slave.slaveName)) || + (slave.devotion > 20 || slave.trust < -20) + ) { + slaveFullNameNode.appendChild(slaveName()); + slaveFullNameNode.appendChild(slaveSurname()); + } else { + slaveFullNameNode.textContent = `You must break ${his} will further before you can successfully force a new name on ${him}.`; + slaveFullNameNode.className = "note"; + } + + return slaveFullNameNode; + + function slaveName() { + const oldName = slave.slaveName; + const oldSurname = slave.slaveSurname; + // Slave Name + let slaveNameNode = document.createElement('p'); + label = document.createElement('div'); + result = document.createElement('div'); + result.id = "result"; + result.className = "choices"; + const linkArray = []; + + label.append(`Change ${his} given name`); + if (slave.birthName !== slave.slaveName) { + label.append(` (${his} birth name was ${slave.birthName})`); + } + label.append(`: `); + + textbox = App.UI.DOM.makeTextBox( + slave.slaveName, + v => { + slave.slaveName = v; + updateName(slave, {oldName: oldName, oldSurname: oldSurname}); + }, + false, + ); + label.appendChild(textbox); + + slaveNameNode.appendChild(label); + + if (slave.slaveName === slave.birthName) { + linkArray.push(App.UI.DOM.disabledLink(`${He} has ${his} birth name`, [`Nothing to reset`])); + } else { + linkArray.push(App.UI.DOM.link( + `Restore ${his} birth name`, + () => { + slave.slaveName = slave.birthName; + updateName(slave, {oldName: oldName, oldSurname: oldSurname}); + }, + false, + )); + } + + if (V.arcologies[0].FSPastoralist !== "unset") { + if (slave.lactation > 0) { + linkArray.push(chooseThreeNames(`Choose a random cow name for ${him}`, setup.cowSlaveNames, "cow-names")); + } + } + if (V.arcologies[0].FSIntellectualDependency !== "unset") { + if (slave.intelligence + slave.intelligenceImplant < -10) { + linkArray.push(chooseThreeNames(`Give ${him} a random stripper given name`, setup.bimboSlaveNames, "bimbo-names")); + } + } + if (V.arcologies[0].FSChattelReligionist !== "unset") { + linkArray.push(chooseThreeNames(`Give ${him} a random devotional given name`, setup.chattelReligionistSlaveNames, "devotional-names")); + } + result.append(App.UI.DOM.generateLinksStrip(linkArray)); + slaveNameNode.appendChild(result); + return slaveNameNode; + + function chooseThreeNames(title, array, id) { + const el = document.createElement("span"); + el.id = id; + el.append( + App.UI.DOM.link( + title, + () => { + linkGuts(); + } + ) + ); + return el; + function linkGuts() { + // Randomize the array + const shuffled = array.sort(() => 0.5 - Math.random()); + + // Get the first three new names + const names = []; + for (let i = 0; names.length < 3; i++) { + if (i > shuffled.length) { + break; + } + if (shuffled[i] !== slave.slaveName) { + names.push(shuffled[i]); + } + } + + // return the three names as links + const nameLinks = []; + for (const name of names) { + nameLinks.push( + App.UI.DOM.link( + name, + () => { + slave.slaveName = name; + updateName(slave, {oldName: oldName, oldSurname: oldSurname}); + } + ) + ); + } + nameLinks.push( + App.UI.DOM.link( + "...", + () => { + linkGuts(); + } + ) + ); + jQuery(`#${id}`).empty().append(App.UI.DOM.generateLinksStrip(nameLinks)); + } + } + } + + function slaveSurname() { + // Slave Surname + const oldName = slave.slaveName; + const oldSurname = slave.slaveSurname; + let slaveSurnameNode = document.createElement('p'); + label = document.createElement('div'); + result = document.createElement('div'); + result.id = "result"; + result.className = "choices"; + + label.append(`Change ${his} surname`); + if (slave.birthSurname !== slave.slaveSurname) { + label.append(` (${his} birth surname was ${slave.birthSurname})`); + } + label.append(`: `); + + textbox = App.UI.DOM.makeTextBox( + slave.slaveSurname, + v => { + slave.slaveSurname = textbox.value; + updateName(slave, {oldName: oldName, oldSurname: oldSurname}); + }, + false, + ); + label.appendChild(textbox); + + slaveSurnameNode.appendChild(label); + + if (slave.slaveSurname === slave.birthSurname) { + result.append(` ${He} has ${his} birth surname`); + } else { + result.appendChild(App.UI.DOM.link( + ` Restore ${his} birth surname`, + () => { + slave.slaveSurname = slave.birthSurname; + updateName(slave, {oldName: oldName, oldSurname: oldSurname}); + }, + false, + )); + } + + if (slave.slaveSurname) { + result.append(` | `); + result.appendChild(App.UI.DOM.link( + `Take ${his} surname away`, + () => { + slave.slaveSurname = 0; + updateName(slave, {oldName: oldName, oldSurname: oldSurname}); + }, + false, + )); + } + if (slave.relationship >= 5) { + const spouse = getSlave(slave.relationshipTarget); + if (spouse.slaveSurname && slave.slaveSurname !== spouse.slaveSurname) { + result.append(` | `); + const wifePronouns = getPronouns(spouse); + result.appendChild(App.UI.DOM.link( + `Give ${him} ${his} ${wifePronouns.wife}'s surname`, + () => { + slave.slaveSurname = spouse.slaveSurname; + updateName(slave, {oldName: oldName, oldSurname: oldSurname}); + }, + false, + )); + } + } + if (slave.relationship === -3) { + if (V.PC.slaveSurname && slave.slaveSurname !== V.PC.slaveSurname) { + result.append(` | `); + result.appendChild(App.UI.DOM.link( + `Give ${him} your surname`, + () => { + slave.slaveSurname = V.PC.slaveSurname; + updateName(slave, {oldName: oldName, oldSurname: oldSurname}); + }, + false, + )); + } + } + if (V.arcologies[0].FSRomanRevivalist !== "unset") { + result.append(` | `); + result.appendChild(App.UI.DOM.link( + `Give ${him} a random full Roman name`, + () => { + slave.slaveName = setup.romanSlaveNames.random(); + slave.slaveSurname = setup.romanSlaveSurnames.random(); + updateName(slave, {oldName: oldName, oldSurname: oldSurname}); + }, + false, + )); + } else if (V.arcologies[0].FSAztecRevivalist !== "unset") { + result.append(` | `); + result.appendChild(App.UI.DOM.link( + `Give ${him} a random full Aztec name`, + () => { + slave.slaveName = setup.aztecSlaveNames.random(); + slave.slaveSurname = 0; + updateName(slave, {oldName: oldName, oldSurname: oldSurname}); + }, + false, + )); + } else if (V.arcologies[0].FSEgyptianRevivalist !== "unset") { + result.append(` | `); + result.appendChild(App.UI.DOM.link( + `Give ${him} a random full ancient Egyptian name`, + () => { + slave.slaveName = setup.ancientEgyptianSlaveNames.random(); + slave.slaveSurname = 0; + updateName(slave, {oldName: oldName, oldSurname: oldSurname}); + }, + false, + )); + } else if (V.arcologies[0].FSEdoRevivalist !== "unset") { + result.append(` | `); + result.appendChild(App.UI.DOM.link( + `Give ${him} a random full feudal Japanese name`, + () => { + slave.slaveName = setup.edoSlaveNames.random(); + slave.slaveSurname = setup.edoSlaveSurnames.random(); + updateName(slave, {oldName: oldName, oldSurname: oldSurname}); + }, + false, + )); + } + if (V.arcologies[0].FSDegradationist > -1) { + result.append(` | `); + result.appendChild(App.UI.DOM.link( + `Give ${him} a degrading full name`, + () => { + DegradingName(slave); + updateName(slave, {oldName: oldName, oldSurname: oldSurname}); + }, + false, + )); + } + slaveSurnameNode.appendChild(result); + return slaveSurnameNode; + } + function updateName(slave, {oldName: oldName, oldSurname: oldSurname}) { + App.UI.SlaveInteract.custom(slave); + App.UI.SlaveInteract.rename(slave, {oldName: oldName, oldSurname: oldSurname}); + } + } + + /** + * @param {App.Entity.SlaveState} slave + */ + function hair(slave) { + let hairNode = new DocumentFragment(); + const { + // eslint-disable-next-line no-unused-vars + he, + him, + his, + hers, + himself, + boy, + He, + His + } = getPronouns(slave); + + hairNode.appendChild(hairStyle()); + hairNode.appendChild(hairColor()); + return hairNode; + + function hairStyle() { + let hairStyleNode = document.createElement('p'); + let label = document.createElement('div'); + label.append(`Custom hair description: `); + + let textbox = App.UI.DOM.makeTextBox( + slave.hStyle, + v => { + slave.hStyle = v; + App.UI.SlaveInteract.custom(slave); + }); + label.appendChild(textbox); + + switch (slave.hStyle) { + case "tails": + case "dreadlocks": + case "cornrows": + label.append(` "${His} hair is in ${slave.hStyle}."`); + break; + case "ponytail": + label.append(` "${His} hair is in a ${slave.hStyle}."`); + break; + default: + label.append(` "${His} hair is ${slave.hStyle}."`); + break; + } + hairStyleNode.appendChild(label); + + let choices = document.createElement('div'); + choices.className = "choices"; + choices.appendChild(App.UI.DOM.makeElement('span', ` For best results, use a short, uncapitalized and unpunctuated description; for example: 'back in a ponytail'`, 'note')); + hairStyleNode.appendChild(choices); + return hairStyleNode; + } + + function hairColor() { + let hairStyleNode = document.createElement('p'); + let label = document.createElement('div'); + label.append(`Custom hair color: `); + + let textbox = App.UI.DOM.makeTextBox( + slave.hColor, + v => { + slave.hColor = v; + App.UI.SlaveInteract.custom(slave); + }); + label.appendChild(textbox); + label.append(` "${His} hair is ${slave.hColor}."`); + hairStyleNode.appendChild(label); + + let choices = document.createElement('div'); + choices.className = "choices"; + choices.appendChild(App.UI.DOM.makeElement('span', ` For best results, use a short, uncapitalized and unpunctuated description; for example: 'black with purple highlights'`, 'note')); + hairStyleNode.appendChild(choices); + return hairStyleNode; + } + } + + /** + * @param {App.Entity.SlaveState} slave + */ + function eyeColor(slave) { + let eyeColorNode = document.createElement('p'); + const { + // eslint-disable-next-line no-unused-vars + he, + him, + his, + hers, + himself, + boy, + He, + His + } = getPronouns(slave); + let label = document.createElement('div'); + if (getLenseCount(slave) > 0) { + label.textContent = `${He} is wearing ${App.Desc.eyesColor(slave, "", "lense", "lenses")}.`; + } else { + label.textContent = `${He} has ${App.Desc.eyesColor(slave)}.`; + } + eyeColorNode.appendChild(label); + + let choices = document.createElement('div'); + choices.className = "choices"; + + let eye; + let textbox; + + if (hasLeftEye(slave)) { + eye = document.createElement('div'); + eye.append(`Custom left eye color: `); + textbox = App.UI.DOM.makeTextBox( + slave.eye.left.iris, + v => { + slave.eye.left.iris = v; + App.UI.SlaveInteract.custom(slave); + }); + eye.appendChild(textbox); + choices.appendChild(eye); + } + if (hasRightEye(slave)) { + eye = document.createElement('div'); + eye.append(`Custom right eye color: `); + textbox = App.UI.DOM.makeTextBox( + slave.eye.right.iris, + v => { + slave.eye.right.iris = v; + App.UI.SlaveInteract.custom(slave); + }); + eye.appendChild(textbox); + choices.appendChild(eye); + } + choices.appendChild(App.UI.DOM.makeElement('span', `For best results, use a short, uncapitalized and unpunctuated description; for example: 'blue'`, 'note')); + eyeColorNode.appendChild(choices); + return eyeColorNode; + } + + /** + * @param {App.Entity.SlaveState} slave + */ + function customTattoo(slave) { + let el = document.createElement('p'); + const { + // eslint-disable-next-line no-unused-vars + he, + him, + his, + hers, + himself, + boy, + He, + His + } = getPronouns(slave); + el.append(`Change ${his} custom tattoo: `); + el.appendChild(App.UI.DOM.makeTextBox( + slave.custom.tattoo, + v => { + slave.custom.tattoo = v; + App.UI.SlaveInteract.custom(slave); + })); + + let choices = document.createElement('div'); + choices.className = "choices"; + choices.appendChild(App.UI.DOM.makeElement('span', `For best results, use complete sentences; for example: '${He} has blue stars tattooed along ${his} cheekbones.'`, 'note')); + el.appendChild(choices); + + return el; + } + + function customOriginStory(slave) { + let el = document.createElement('p'); + const { + // eslint-disable-next-line no-unused-vars + he, + him, + his, + hers, + himself, + boy, + He, + His + } = getPronouns(slave); + + el.append(`Change ${his} origin story: `); + el.appendChild(App.UI.DOM.makeTextBox( + slave.origin, + v => { + slave.origin = v; + App.UI.SlaveInteract.custom(slave); + })); + + let choices = document.createElement('div'); + choices.className = "choices"; + choices.appendChild(App.UI.DOM.makeElement('span', ` For best results, use complete, capitalized and punctuated sentences; for example: '${He} followed you home from the pet store.'`, 'note')); + el.appendChild(choices); + + return el; + } + + function customDescription(slave) { + let el = document.createElement('p'); + const { + // eslint-disable-next-line no-unused-vars + he, + him, + his, + hers, + himself, + boy, + He, + His + } = getPronouns(slave); + + el.append(`Change ${his} custom description: `); + el.appendChild(App.UI.DOM.makeTextBox( + pronounsForSlaveProp(slave, slave.custom.desc), + v => { + slave.custom.desc = v; + App.UI.SlaveInteract.custom(slave); + })); + + let choices = document.createElement('div'); + choices.className = "choices"; + choices.appendChild(App.UI.DOM.makeElement('span', ` For best results, use complete, capitalized and punctuated sentences; for example: '${He} has a beauty mark above ${his} left nipple.'`, 'note')); + el.appendChild(choices); + + return el; + } + + function customLabel(slave) { + let el = document.createElement('p'); + const { + // eslint-disable-next-line no-unused-vars + he, + him, + his, + hers, + himself, + boy, + He, + His + } = getPronouns(slave); + + el.append(`Change ${his} custom label: `); + el.appendChild(App.UI.DOM.makeTextBox( + slave.custom.label, + v => { + slave.custom.label = v; + App.UI.SlaveInteract.custom(slave); + })); + + let choices = document.createElement('div'); + choices.className = "choices"; + choices.appendChild(App.UI.DOM.makeElement('span', ` For best results, use a short phrase; for example: 'Breeder.'`, 'note')); + el.appendChild(choices); + + return el; + } + + + function customSlaveImage(slave) { + let el = document.createElement('p'); + const { + // eslint-disable-next-line no-unused-vars + he, + him, + his, + hers, + himself, + boy, + He, + His + } = getPronouns(slave); + el.append(`Assign ${him} a custom image: `); + + let textbox = document.createElement("INPUT"); + textbox.id = "customImageValue"; + el.appendChild(textbox); + + + let kbd = document.createElement('kbd'); + let select = document.createElement('SELECT'); + select.id = "customImageFormatSelector"; + select.style.border = "none"; + + let filetypes = [ + "png", + "jpg", + "gif", + "webm", + "webp", + "mp4" + ]; + + filetypes.forEach((fileType) => { + let el = document.createElement('OPTION'); + el.value = fileType; + el.text = fileType.toUpperCase(); + select.add(el); + }); + kbd.append(`.`); + kbd.appendChild(select); + el.appendChild(kbd); + + el.appendChild( + App.UI.DOM.link( + ` Reset`, + () => { + slave.custom.image = null; + App.UI.SlaveInteract.custom(slave); + App.Art.refreshSlaveArt(slave, 3, "art-frame"); + }, + ) + ); + + let choices = document.createElement('div'); + choices.className = "choices"; + let note = document.createElement('span'); + note.className = "note"; + note.append(`Place file in the `); + + kbd = document.createElement('kbd'); + kbd.append(`resources`); + note.appendChild(kbd); + + note.append(` folder. Choose the extension from the menu first, then enter the filename in the space and press enter. For example, for a file with the path `); + + kbd = document.createElement('kbd'); + kbd.textContent = `\\bin\\resources\\headgirl.`; + let filetypeDesc = document.createElement('span'); + filetypeDesc.id = "customImageFormatValue"; + filetypeDesc.textContent = "png"; + kbd.appendChild(filetypeDesc); + note.appendChild(kbd); + + note.append(`, choose `); + + kbd = document.createElement('kbd'); + kbd.textContent = `PNG`; + note.appendChild(kbd); + + note.append(` then enter `); + + kbd = document.createElement('kbd'); + kbd.textContent = `headgirl`; + note.appendChild(kbd); + + note.append(`.`); + choices.appendChild(note); + el.appendChild(choices); + + jQuery(function() { + function activeSlave() { + return slave; + } + + jQuery("#customImageFormatValue").text(activeSlave().custom.image === null ? "png" : activeSlave().custom.image.format); + jQuery("#customImageValue") + .val(activeSlave().custom.image === null ? + "" : activeSlave().custom.image.filename) + .on("change", function(e) { + const c = activeSlave().custom; + if (this.value.length === 0) { + c.image = null; + } else { + if (c.image === null) { + c.image = { + filename: this.value, + format: jQuery("#customImageFormatSelector").val() + }; + App.Art.refreshSlaveArt(slave, 3, "art-frame"); + } else { + c.image.filename = this.value; + App.Art.refreshSlaveArt(slave, 3, "art-frame"); + } + } + }); + jQuery("#customImageFormatSelector") + .val(activeSlave().custom.image ? activeSlave().custom.image.format : "png") + .on("change", function(e) { + if (activeSlave().custom.image !== null) { + activeSlave().custom.image.format = this.value; + } + jQuery("#customImageFormatValue").text(this.value); + }); + }); + return el; + } + + function customHairImage(slave) { + let el = document.createElement('p'); + const { + // eslint-disable-next-line no-unused-vars + he, + him, + his, + hers, + himself, + boy, + He, + His + } = getPronouns(slave); + + if (V.seeImages === 1 && V.imageChoice === 1) { + if (!slave.custom.hairVector) { + slave.custom.hairVector = 0; + } + el.append(`Assign ${him} a custom hair SVG image: `); + + el.appendChild(App.UI.DOM.makeTextBox( + slave.custom.hairVector, + v => { + slave.custom.hairVector = v; + App.UI.SlaveInteract.custom(slave); + })); + + el.appendChild( + App.UI.DOM.link( + ` Reset`, + () => { + slave.custom.hairVector = 0; + App.UI.SlaveInteract.custom(slave); + App.Art.refreshSlaveArt(slave, 3, "art-frame"); + }, + ) + ); + } + + return el; + } +})(); diff --git a/src/interaction/siDescription.js b/src/interaction/siDescription.js new file mode 100644 index 0000000000000000000000000000000000000000..50e62da56199304467ca45e263a5966d28c7cd75 --- /dev/null +++ b/src/interaction/siDescription.js @@ -0,0 +1,61 @@ +App.UI.SlaveInteract.description = function(slave) { + const el = document.createElement("p"); + el.id = "si-description"; + el.append(description()); + return el; + + function description() { + const el = new DocumentFragment(); + const descriptionLink = document.createElement("div"); + descriptionLink.style.fontStyle = "italic"; + descriptionLink.id = "description-link"; + if (V.seeDetails === 1) { + descriptionLink.append(showOptions()); + el.append(descriptionLink); + + const descriptionOptions = document.createElement("div"); + descriptionOptions.id = "description-options"; + el.append(descriptionOptions); + + el.append(App.Desc.longSlave(getSlave(V.AS), {noArt: true})); + } else { + descriptionLink.append( + App.UI.DOM.link( + "Show descriptions", + () => { + V.seeDetails = 1; + }, + [], + "Slave Interact" + ) + ); + el.append(descriptionLink); + } + + + return el; + + function showOptions() { + return App.UI.DOM.link( + "Description Options", + () => { + jQuery("#description-link").empty().append(hideOptions()); + jQuery("#description-options").empty().append(App.UI.DOM.renderPassage("Description Options")); + } + ); + } + + function hideOptions() { + return App.UI.DOM.link( + "Description Options", + () => { + jQuery("#description-link").empty().append(showOptions()); + jQuery("#description-options").empty().append(); + } + ); + } + } + function refresh() { + jQuery("#si-description").empty().append(description()); + } +}; diff --git a/src/interaction/siFamily.js b/src/interaction/siFamily.js new file mode 100644 index 0000000000000000000000000000000000000000..da003bb94def359a83b82d877523987eeba05c97 --- /dev/null +++ b/src/interaction/siFamily.js @@ -0,0 +1,18 @@ +/** + * @returns {HTMLParagraphElement} + */ +App.UI.SlaveInteract.family = function() { + let element; + const p = document.createElement("p"); + p.id= "family"; + + element = document.createElement("div"); + element.id = "family-tree"; + p.append(element); + + element = document.createElement("span"); + element.id = "family-tree-link"; + p.append(element); + + return p; +}; diff --git a/src/interaction/siFinancial.js b/src/interaction/siFinancial.js new file mode 100644 index 0000000000000000000000000000000000000000..8a278a7ea6fdc2cd83381d3b5ddb9e9d757c714c --- /dev/null +++ b/src/interaction/siFinancial.js @@ -0,0 +1,251 @@ +App.UI.SlaveInteract.financial = function(slave) { + const el = document.createElement("div"); + el.id = "si-financial"; + el.append(financialContent()); + return el; + + function financialContent() { + const el = new DocumentFragment(); + let r = []; + let linkArray; + const { + He, His, + his, him + } = getPronouns(slave); + if (V.studio === 1) { + App.UI.DOM.appendNewElement("h3", el, "Media"); + slave.porn.spending = Math.clamp(Math.ceil(slave.porn.spending / 1000) * 1000, 0, 5000); + if (slave.porn.prestige === 3) { + r.push( + App.UI.DOM.makeElement("div", `${He} is so prestigious in the realm of ${slave.porn.fameType} porn that ${his} fame is self-sustaining.`, "note") + ); + } else if (slave.porn.feed === 0) { + r.push(`The media hub is not releasing highlights of ${his} sex life.`); + r.push( + App.UI.DOM.link( + "Release", + () => { + slave.porn.feed = 1; + refresh(); + } + ) + ); + } else { + r.push(`The media hub is releasing highlights of ${his} sex life`); + if (slave.porn.spending < 500) { + r.push(`to those who can find it.`); + } else if (slave.porn.spending < 2500) { + r.push(`on several websites.`); + } else if (slave.porn.spending > 5000) { + r.push(`through your old distributor.`); + } else { + r.push(`on many websites.`); + } + if (slave.porn.spending === 0) { + linkArray = []; + linkArray.push( + App.UI.DOM.link( + "Halt", + () => { + slave.porn.feed = 0; + slave.porn.focus = "none"; + refresh(); + } + ) + ); + linkArray.push( + App.UI.DOM.link( + "Publicize", + () => { + slave.porn.spending += 1000; + refresh(); + }, + [], + "", + `Will cost ${cashFormat(1000)} weekly.` + ) + ); + r.push(App.UI.DOM.generateLinksStrip(linkArray)); + } else { + r.push( + App.UI.DOM.makeTextBox( + slave.porn.spending, + v => { + slave.porn.spending = v; + }, + true + ) + ); + r.push(`weekly is spent to publicize them.`); + + linkArray = []; + linkArray.push( + App.UI.DOM.link( + "Halt", + () => { + slave.porn.spending = 0; + slave.porn.feed = 0; + slave.porn.focus = "none"; + V.PCSlutContacts = 1; + refresh(); + } + ) + ); + if (slave.porn.spending <= 4000) { + linkArray.push( + App.UI.DOM.link( + "Increase", + () => { + slave.porn.spending += 1000; + refresh(); + }, + [], + "", + `Spending more than ${cashFormat(5000)} weekly will have no effect.` + ) + ); + } + linkArray.push( + App.UI.DOM.link( + "Decrease", + () => { + slave.porn.spending -= 1000; + refresh(); + }, + [], + "", + `Will cost ${cashFormat(1000)} weekly.` + ) + ); + r.push(App.UI.DOM.generateLinksStrip(linkArray)); + App.Events.addNode(el, r, "div"); + + if (V.PC.career === "escort") { + App.Events.addNode(el, r, "div"); + r = []; + r.push(`You retain some contacts from your past life in the industry that may be willing to cut you some discounts should you return to it.`); + if (V.PCSlutContacts !== 2) { + r.push(`You are not baring your body for all to see.`); + r.push( + App.UI.DOM.link( + `Star in porn for a discount`, + () => { + V.PCSlutContacts = 2; + refresh(); + } + ) + ); + } else { + r.push(`You are starring in hardcore porn once more.`); + r.push( + App.UI.DOM.link( + `Stop doing porn for a discount`, + () => { + V.PCSlutContacts = 1; + refresh(); + } + ) + ); + } + } + } + if (V.studioFeed === 1) { + App.Events.addNode(el, r, "div"); + r = []; + if (slave.porn.viewerCount < 100) { + r.push(`${He} lacks the fame in porn needed to discern what ${his} feed is getting tagged as.`); + } else { + if (slave.porn.prestige > 0) { + r.push(`${He} is known for ${slave.porn.fameType}${(slave.porn.prestige > 1) ? ` and viewers have grown to expect it from ${him}` : ``}.`); + } + if (slave.porn.focus === "none") { + r.push(`You are allowing ${his} viewers to guide the direction of ${his} content.`); + } else { + r.push(`You are focusing attention on the ${slave.porn.focus} aspect of ${his} content.`); + } + r.push(App.Porn.genreChoiceLinks("Slave Interact", slave)); + } + } + } + App.Events.addNode(el, r, "div"); + } + App.UI.DOM.appendNewElement("h3", el, "Financial"); + App.UI.DOM.appendNewElement("p", el, slaveExpenses(slave)); + + r = []; + linkArray = []; + if (V.slaveCostFactor > 1) { + r.push(App.UI.DOM.makeElement("span", `The slave market is bullish; the price of slaves is high.`, "yellow")); + } else if ((V.slaveCostFactor < 1)) { + r.push(App.UI.DOM.makeElement("span", `The slave market is bearish; the price of slaves is low.`, "yellow")); + } + + if (V.slaves.length < 2) { + r.push("You cannot sell your last save"); + } else if (slave.origin === "You bought ${him} from a body dump, completely broken." && (V.week - slave.weekAcquired <= 8)) { + r.push(`A discarded slave must be kept for at least two months to ensure health before being sold.`); + } else if (slave.accent > 3) { + r.push(`${His} lack of language and basic life skills is a red sign to most slave appraisers. ${He} must not act like a child to be sold without raising suspicion.`); + } else { + linkArray.push( + App.UI.DOM.link( + `Sell ${him}`, + () => { + cashX(-500, "personalBusiness", slave); + }, + [], + "Sell Slave", + `Listing ${him} for sale will cost ${cashFormat(500)}` + ) + ); + if ((V.seeAge !== 0) && (slave.indenture < 1)) { + linkArray.push( + App.UI.DOM.link( + `Retire ${him}`, + () => { + V.retiree = slave.ID; + V.retired = 1; + }, + [], + "SE retirement", + ) + ); + } + linkArray.push( + App.UI.DOM.passageLink( + `Discard ${him}`, + "Discard Confirm", + ) + ); + if (V.seeExtreme === 1 && V.arcologies[0].FSPaternalist === "unset") { + linkArray.push( + App.UI.DOM.passageLink( + `Threaten ${his} life`, + "KillSlave", + ) + ); + } + } + linkArray.push( + App.UI.DOM.passageLink( + `Export this slave`, + "Export this slave", + ) + ); + if (V.cheatMode) { + linkArray.push( + App.UI.DOM.passageLink( + `Import a slave`, + "Import Slave", + ) + ); + } + r.push(App.UI.DOM.generateLinksStrip(linkArray)); + App.Events.addNode(el, r, "p"); + return el; + } + + function refresh() { + jQuery("#si-financial").empty().append(financialContent()); + } +}; diff --git a/src/interaction/siModify.js b/src/interaction/siModify.js new file mode 100644 index 0000000000000000000000000000000000000000..11f52477e4c8a234ff52ad57aa030ba2f5984a52 --- /dev/null +++ b/src/interaction/siModify.js @@ -0,0 +1,59 @@ +/** + * @param {App.Entity.SlaveState} slave + * @returns {Node} + */ +App.UI.SlaveInteract.modify = function(slave) { + const {he, his} = getPronouns(slave); + let el = new DocumentFragment(); + + const isAgent = [Job.AGENT, Job.AGENTPARTNER].includes(slave.assignment); + + App.UI.DOM.appendNewElement('p', el, isAgent ? "Recall your agent to modify them." : "Take slave to another room.", "scene-intro"); + + if (isAgent) { + return el; + } + + /** + * Create a link with a note to send a slave to a specific room + * @param {Node} c + * @param {string} caption + * @param {string} passage + * @param {string} note + * @param {function ():void} [handler] + */ + function makeRoomLink(c, caption, passage, note, handler = () => {}) { + const res = document.createElement('div'); + c.appendChild(res); + res.appendChild(App.UI.DOM.link(caption, handler, [], passage)); + App.UI.DOM.appendNewElement('span', res, note, "note"); + return res; + } + + makeRoomLink(el, "Auto salon", "Salon", ' Modify hair (color, length, style), nails, and even skin color.'); + + makeRoomLink(el, "Body mod studio", "Body Modification", ' Mark your slave with piercings, tattoos, brands or even scars.', + () => { + V.degradation = 0; + V.tattooChoice = undefined; + }, + ); + + makeRoomLink(el, "Remote surgery", "Remote Surgery", ` Surgically modify your slave with state of the art plastic surgery and more. Alter ${his} senses, skeletal structure, organs, and even more.`); + + // Prosthetics + if (V.prostheticsUpgrade > 0) { + makeRoomLink(el, "Configure cybernetics", "Prosthetics Configuration", ` Configure prosthetics, if ${he} has been surgically implanted with interfaces that support it.`, + () => { + V.prostheticsConfig = "main"; + } + ); + } + + // Analyze Pregnancy + if (V.pregnancyMonitoringUpgrade > 0) { + makeRoomLink(el, "Internal scan", "Analyze Pregnancy", ` Full scan of abdomen and reproductive organs.`); + } + + return el; +}; \ No newline at end of file diff --git a/src/interaction/siNavigation.js b/src/interaction/siNavigation.js new file mode 100644 index 0000000000000000000000000000000000000000..c7bfe5e5b0aece2af05aeff67fd3c50636a847f9 --- /dev/null +++ b/src/interaction/siNavigation.js @@ -0,0 +1,63 @@ + + +/** + * @param {App.Entity.SlaveState} slave + * @returns {HTMLParagraphElement} + */ +App.UI.SlaveInteract.navigation = function(slave) { + const p = document.createElement("p"); + p.classList.add("center"); + + if (V.cheatMode) { + const div = document.createElement("div"); + div.classList.add("note"); + div.append(App.UI.DOM.passageLink("Cheat Edit Slave", "MOD_Edit Slave Cheat", () => { V.cheater = 1; }), + " | ", + App.UI.DOM.passageLink("Cheat Edit Slave Alternative", "MOD_Edit Slave Cheat New", () => { V.cheater = 1; })); + p.append(div); + } + + App.UI.DOM.appendNewElement("span", p, App.UI.Hotkeys.hotkeys("prev-slave"), "hotkey"); + const prevSpan = App.UI.DOM.makeElement("span", App.UI.DOM.passageLink("Prev", "Slave Interact", + () => { V.AS = App.UI.SlaveInteract.placeInLine(slave)[0]; }), "adjacent-slave"); + prevSpan.id = "prev-slave"; + p.append(" ", prevSpan); + + const centerSpan = document.createElement("span"); + centerSpan.classList.add("interact-name"); + + App.UI.DOM.appendNewElement("span", centerSpan, slave.slaveName, "slave-name"); + + const favSpan = document.createElement("span"); + favSpan.id = "fav-span"; + favSpan.append(favLink()); + + centerSpan.append(" ", favSpan); + p.append(centerSpan); + + const nextSpan = App.UI.DOM.makeElement("span", App.UI.DOM.passageLink("Next", "Slave Interact", + () => { V.AS = App.UI.SlaveInteract.placeInLine(slave)[1]; }), "adjacent-slave"); + nextSpan.id = "next-slave"; + p.append(nextSpan, " "); + App.UI.DOM.appendNewElement("span", p, App.UI.Hotkeys.hotkeys("next-slave"), "hotkey"); + + return p; + + function favLink() { + if (V.favorites.includes(slave.ID)) { + const link = App.UI.DOM.link(String.fromCharCode(0xe800), () => { + V.favorites.delete(slave.ID); + App.UI.DOM.replace("#fav-span", favLink()); + }); + link.classList.add("icons", "favorite"); + return link; + } else { + const link = App.UI.DOM.link(String.fromCharCode(0xe801), () => { + V.favorites.push(slave.ID); + App.UI.DOM.replace("#fav-span", favLink()); + }); + link.classList.add("icons", "not-favorite"); + return link; + } + } +}; diff --git a/src/interaction/siPhysicalRegimen.js b/src/interaction/siPhysicalRegimen.js new file mode 100644 index 0000000000000000000000000000000000000000..e7086dbd03e0c6cec08e797edc4af755100bf315 --- /dev/null +++ b/src/interaction/siPhysicalRegimen.js @@ -0,0 +1,1052 @@ +App.UI.SlaveInteract.physicalRegimen = function(slave) { + const el = document.createElement("p"); + el.id = "si-physical-regimen"; + el.append(physicalRegimenContent()); + return el; + + function physicalRegimenContent() { + const { + // eslint-disable-next-line no-unused-vars + he, + him, + his, + himself, + He, + His + } = getPronouns(slave); + const el = new DocumentFragment(); + el.append(drugs()); + el.append(curatives()); + el.append(aphrodisiacs()); + el.append(fertility()); + el.append(incubator()); + el.append(nursery()); + el.append(breederEligibility()); + el.append(bloating()); + el.append(hormones()); + el.append(diet()); + el.append(dietBase()); + el.append(snacks()); + return el; + + function drugs() { + let el = document.createElement('div'); + + const drugLevelOptions = []; + const lips = []; + const breasts = []; + const nipples = []; + const butt = []; + const dick = []; + const balls = []; + const fertility = []; + const hormones = []; + const psych = []; + const misc = []; + + if (slave.drugs !== "no drugs") { + drugLevelOptions.push({text: `None`, updateSlave: {drugs: `no drugs`}}); + } + if (slave.indentureRestrictions < 2) { + // Psych + if (slave.intelligence > -100 && slave.indentureRestrictions < 1) { + psych.push({text: `Psychosuppressants`, updateSlave: {drugs: `psychosuppressants`}}); + } else if (slave.intelligence > -100) { + psych.push({text: `Psychosuppressants`, disabled: `Cannot suppress indentured slave`}); + } else if (slave.indentureRestrictions < 1) { + psych.push({text: `Psychosuppressants`, disabled: `Too stupid to suppress`}); + } else { + psych.push({text: `Psychosuppressants`, disabled: `Too stupid and indentured to suppress`}); + } + if (V.arcologies[0].FSSlaveProfessionalismResearch === 1) { + if (canImproveIntelligence(slave)) { + psych.push({text: `Psychostimulants`, updateSlave: {drugs: `psychostimulants`}}); + } else { + psych.push({text: `Psychostimulants`, disabled: `Cannot improve intelligence`}); + } + } + + // Breasts + if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) { + if ((slave.boobs - slave.boobsImplant - slave.boobsMilk) > 100) { + breasts.push({text: `Reducers`, updateSlave: {drugs: `breast redistributors`}}); + } else { + breasts.push({text: `Reducers`, disabled: `Boobs are too small`}); + } + } + if (slave.boobs < 50000) { + breasts.push({text: `Enhancement`, updateSlave: {drugs: `breast injections`}}); + breasts.push({text: `Intensive enhancement`, updateSlave: {drugs: `intensive breast injections`}}); + } else { + breasts.push({text: `Enhancement`, disabled: `Boobs are too large`}); + } + if (V.arcologies[0].FSAssetExpansionistResearch === 1) { + if (slave.boobs < 50000) { + breasts.push({text: `Hyper enhancement`, updateSlave: {drugs: `hyper breast injections`}}); + } else { + breasts.push({text: `Hyper enhancement`, disabled: `Boobs are too large`}); + } + } + + // Nipples + if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) { + if (slave.nipples === "huge" || slave.nipples === "puffy" || slave.nipples === "cute") { + nipples.push({text: `Reducers`, updateSlave: {drugs: `nipple atrophiers`}}); + } else { + nipples.push({text: `Reducers`, disabled: `Nipples are ${slave.nipples}`}); + } + } + if (V.dispensary) { + if (["inverted", "partially inverted", "cute", "tiny", "puffy"].includes(slave.nipples)) { + nipples.push({text: `Enhancement`, updateSlave: {drugs: `nipple enhancers`}}); + } else if (slave.nipples === "huge") { + nipples.push({text: `Enhancement`, disabled: `Nipples are already huge`}); + } else { + nipples.push({text: `Enhancement`, disabled: `Has no effect on ${slave.nipples} nipples`}); + } + } + + // Butt + if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) { + if (slave.butt - slave.buttImplant > 0) { + butt.push({text: `Reducers`, updateSlave: {drugs: `butt redistributors`}}); + } else { + butt.push({text: `Reducers`, disabled: `Butt is too small`}); + } + } + if (slave.butt < 9) { + butt.push({text: `Enhancement`, updateSlave: {drugs: `butt injections`}}); + butt.push({text: `Intensive enhancement`, updateSlave: {drugs: `intensive butt injections`}}); + } else { + butt.push({text: `Enhancement`, disabled: `Butt is too large`}); + } + if (V.arcologies[0].FSAssetExpansionistResearch === 1) { + if (slave.butt < 20) { + butt.push({text: `Hyper enhancement`, updateSlave: {drugs: `hyper butt injections`}}); + } else { + butt.push({text: `Hyper enhancement`, disabled: `Butt is too large`}); + } + } + + // Lips + if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) { + if (slave.lips - slave.lipsImplant > 0) { + lips.push({text: `Reducers`, updateSlave: {drugs: `lip atrophiers`}}); + } else { + lips.push({text: `Reducers`, disabled: `Lips are too small`}); + } + } + if (slave.lips <= 95 || (slave.lips <= 85 && V.seeExtreme !== 1)) { + lips.push({text: `Enhancement`, updateSlave: {drugs: `lip injections`}}); + } else { + lips.push({text: `Enhancement`, disabled: `Lips are too large`}); + } + + // Fertility + fertility.push({text: `Fertility`, updateSlave: {drugs: `fertility drugs`}}); + if (V.seeHyperPreg === 1 && slave.indentureRestrictions < 1 && V.superFertilityDrugs === 1 && (slave.breedingMark !== 1 || V.propOutcome === 0 || V.eugenicsFullControl === 1 || V.arcologies[0].FSRestart === "unset")) { + fertility.push({text: `Fertility+`, updateSlave: {drugs: `super fertility drugs`}}); + } + + // Dick/clit + if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) { + if (slave.dick > 1) { + dick.push({text: `Reducers`, updateSlave: {drugs: `penis atrophiers`}}); + } else if (slave.dick === 1) { + dick.push({text: `Reducers`, disabled: `Dick is already at minimum size`}); + } + if (slave.clit > 0) { + dick.push({text: `Reducers`, updateSlave: {drugs: `clitoris atrophiers`}}); + } + } + if (slave.dick > 0) { + if (slave.dick < 10) { + dick.push({text: `Enhancement`, updateSlave: {drugs: `penis enhancement`}}); + dick.push({text: `Intensive enhancement`, updateSlave: {drugs: `intensive penis enhancement`}}); + } else { + dick.push({text: `Enhancement`, disabled: `Dick is too large`}); + } + } else { + if (slave.clit < 5) { + dick.push({text: `Enhancement`, updateSlave: {drugs: `penis enhancement`}}); + dick.push({text: `Intensive enhancement`, updateSlave: {drugs: `intensive penis enhancement`}}); + } else { + dick.push({text: `Enhancement`, disabled: `Clit is too large`}); + } + } + if (V.arcologies[0].FSAssetExpansionistResearch === 1) { + if (slave.dick > 0) { + if (slave.dick < 31) { + dick.push({text: `Hyper enhancement`, updateSlave: {drugs: `hyper penis enhancement`}}); + } else { + dick.push({text: `Hyper enhancement`, disabled: `Dick is too large`}); + } + } else { + if (slave.clit < 5) { + dick.push({text: `Hyper enhancement`, updateSlave: {drugs: `penis enhancement`}}); + } else { + dick.push({text: `Hyper enhancement`, disabled: `Clit is too large`}); + } + } + } + if (slave.dick > 0 && slave.dick < 11 && !canAchieveErection(slave) && slave.chastityPenis !== 1) { + dick.push({text: `Erectile dysfunction circumvention`, updateSlave: {drugs: `priapism agents`}}); + } + + // Balls + if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) { + if (slave.balls > 1) { + balls.push({text: `Reducers`, updateSlave: {drugs: `testicle atrophiers`}}); + } else if (slave.balls === 1) { + balls.push({text: `Reducers`, disabled: `Balls are already at minimum size`}); + } + } + if (slave.balls > 0) { + balls.push({text: `Enhancement`, updateSlave: {drugs: `testicle enhancement`}}); + balls.push({text: `Intensive enhancement`, updateSlave: {drugs: `intensive testicle enhancement`}}); + if (V.arcologies[0].FSAssetExpansionistResearch === 1) { + balls.push({text: `Hyper enhancement`, updateSlave: {drugs: `hyper testicle enhancement`}}); + } + } + + // Hormones + if (V.precociousPuberty === 1 && V.pubertyHormones === 1 && (slave.breedingMark !== 1 || V.propOutcome === 0 || V.eugenicsFullControl === 1 || V.arcologies[0].FSRestart === "unset")) { + if ((slave.ovaries === 1 || slave.mpreg === 1) && slave.pubertyXX === 0) { + hormones.push({text: `Female injections`, updateSlave: {drugs: `female hormone injections`}}); + } + if (slave.balls > 0 && slave.pubertyXY === 0) { + hormones.push({text: `Male injections`, updateSlave: {drugs: `male hormone injections`}}); + } + } + hormones.push({text: `Blockers`, updateSlave: {drugs: `hormone blockers`}}); + hormones.push({text: `Enhancement`, updateSlave: {drugs: `hormone enhancers`}}); + + // Misc + if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) { + if (slave.labia > 0) { + misc.push({text: `Labia reducers`, updateSlave: {drugs: `labia atrophiers`}}); + } + } + if (V.growthStim === 1) { + if (canImproveHeight(slave)) { + misc.push({text: `Growth Stimulants`, updateSlave: {drugs: `growth stimulants`}}); + } else { + misc.push({text: `Growth Stimulants`, disabled: `Cannot increase height further`}); + } + } + if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) { + if (slave.weight > -95) { + misc.push({text: `Weight loss pills`, updateSlave: {drugs: `appetite suppressors`}}); + } else { + misc.push({text: `Weight loss pills`, disabled: `Slave is already at low weight`}); + } + } + misc.push({text: `Steroids`, updateSlave: {drugs: `steroids`}}); + if (slave.boobs > 250 && slave.boobShape !== "saggy" && V.purchasedSagBGone === 1) { + misc.push({text: `Sag-B-Gone breast lifting cream`, updateSlave: {drugs: `sag-B-gone`}}); + } + if (V.arcologies[0].FSYouthPreferentialistResearch === 1) { + if (slave.visualAge > 18) { + misc.push({text: `Anti-aging cream`, updateSlave: {drugs: `anti-aging cream`}}); + } else { + misc.push({text: `Anti-aging cream`, disabled: `Slave already looks young enough`}); + } + } + } + + let title = document.createElement('div'); + title.textContent = `Drugs: `; + let chosenDrug = document.createElement('span'); + chosenDrug.textContent = `${capFirstChar(slave.drugs)}. `; + chosenDrug.style.fontWeight = "bold"; + title.append(chosenDrug); + title.appendChild(App.UI.SlaveInteract.generateRows(drugLevelOptions, slave, "", false, refresh)); + el.append(title); + + App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Lips", lips, slave, refresh); + App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Breasts", breasts, slave, refresh); + App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Nipples", nipples, slave, refresh); + App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Butt", butt, slave, refresh); + App.UI.SlaveInteract.appendLabeledChoiceRow(el, slave.dick > 0 ? "Dick" : "Clit", dick, slave, refresh); + App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Balls", balls, slave, refresh); + App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Fertility", fertility, slave, refresh); + App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Hormones", hormones, slave, refresh); + App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Psych", psych, slave, refresh); + App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Misc", misc, slave, refresh); + + return el; + } + + function curatives() { + const curativeOptions = []; + + curativeOptions.push({text: `None`, updateSlave: {curatives: 0}}); + curativeOptions.push({text: `Preventatives`, updateSlave: {curatives: 1}}); + curativeOptions.push({text: `Curatives`, updateSlave: {curatives: 2}}); + + let el = document.createElement('div'); + let title = document.createElement('div'); + title.append(`Health: `); + let chosenOption = document.createElement('span'); + chosenOption.style.fontWeight = "bold"; + if (slave.curatives > 1) { + chosenOption.textContent = `curatives`; + } else if (slave.curatives > 0) { + chosenOption.textContent = `preventatives`; + } else { + chosenOption.textContent = `none`; + } + title.appendChild(chosenOption); + title.append(`.`); + let link = document.createElement('div'); + link.className = "choices"; + link.appendChild(App.UI.SlaveInteract.generateRows(curativeOptions, slave, "", false, refresh)); + el.append(title); + el.append(link); + return el; + } + + function aphrodisiacs() { + const aphrodisiacOptions = []; + + aphrodisiacOptions.push({text: `None`, updateSlave: {aphrodisiacs: 0}}); + aphrodisiacOptions.push({text: `Aphrodisiacs`, updateSlave: {aphrodisiacs: 1}}); + aphrodisiacOptions.push({text: `Extreme aphrodisiacs`, updateSlave: {aphrodisiacs: 2}}); + aphrodisiacOptions.push({text: `Anaphrodisiacs`, updateSlave: {aphrodisiacs: -1}, note: `Suppresses libido`}); + + + let el = document.createElement('div'); + let title = document.createElement('div'); + title.append(`Aphrodisiacs: `); + let chosenOption = document.createElement('span'); + chosenOption.style.fontWeight = "bold"; + if (slave.aphrodisiacs > 1) { + chosenOption.textContent = `extreme`; + } else if (slave.aphrodisiacs > 0) { + chosenOption.textContent = `applied`; + } else if (slave.aphrodisiacs === -1) { + chosenOption.textContent = `anaphrodisiacs`; + } else { + chosenOption.textContent = `none`; + } + title.appendChild(chosenOption); + title.append(`.`); + let link = document.createElement('div'); + link.className = "choices"; + link.appendChild(App.UI.SlaveInteract.generateRows(aphrodisiacOptions, slave, "", false, refresh)); + el.append(title); + el.append(link); + return el; + } + + function fertility() { + let fertilityBlock = document.createElement('span'); + let linkArray = []; + if (slave.ovaries === 1 || slave.mpreg === 1 || slave.preg > 0) { + let note = ""; + if (slave.preg < -1) { + note += `${He} is sterile`; + } else if (slave.pubertyXX === 0 && slave.preg < 1) { + note += `${He} is not yet fertile`; + } else if (slave.ovaryAge >= 47 && slave.preg < 1) { + note += `${He} is too old to become pregnant`; + if (slave.preg === -1) { + slave.preg = 0; + SetBellySize(slave); + } + } else if (slave.broodmotherOnHold === 1) { + note += `${His} pregnancy implant is turned off`; + if (slave.broodmotherCountDown > 0) { + note += `${he} is expected to be completely emptied of ${his} remaining brood in ${slave.broodmotherCountDown} week`; + if (slave.broodmotherCountDown > 1) { + note += `s`; + } + note += `.`; + linkArray.push(App.UI.DOM.link( + `Turn on implant`, + () => { + slave.broodmotherOnHold = 0; + slave.broodmotherCountDown = 0; + refresh(); + }, + )); + } + } else if (slave.preg >= -1) { + fertilityBlock.append("Contraception and fertility: "); + let fertility = ""; + // fertility.id = "fertility"; + if (slave.preg === -1) { + fertility = "using contraceptives"; + } else if (slave.pregWeek < 0) { + fertility = "postpartum"; + } else if (slave.preg === 0) { + fertility = "fertile"; + } else if (slave.preg < 4 && (slave.broodmother === 0 || slave.broodmotherOnHold === 1)) { + fertility = "may be pregnant"; + } else if (slave.preg < 2) { + fertility = "1 week pregnant"; + } else { + fertility = `${Math.trunc(slave.preg * 1000) / 1000} weeks pregnant`; // * and / needed to avoid seeing something like 20.1000000008 in some cases. + if (slave.broodmother > 0) { + fertility += " broodmother"; + } + } + fertility += ". "; + App.UI.DOM.appendNewElement("span", fertilityBlock, fertility, "bold"); + + if (slave.preg === 0) { + linkArray.push(App.UI.DOM.link( + `Use contraceptives`, + () => { + slave.preg = -1; + refresh(); + }, + )); + } else if (slave.preg === -1) { + linkArray.push(App.UI.DOM.link( + `Let ${him} get pregnant`, + () => { + slave.preg = 0; + refresh(); + }, + )); + } else if (isInduced(slave)) { + note += `Hormones are being slipped into ${his} food; ${he} will give birth suddenly and rapidly this week`; + } else if ( + slave.preg > slave.pregData.normalBirth - 2 && + slave.preg > slave.pregData.minLiveBirth && + slave.broodmother === 0 && + !isInLabor(slave) + ) { + linkArray.push(App.UI.DOM.link( + `Induce labor`, + () => { + induce(slave); + refresh(); + }, + )); + linkArray.push(App.UI.DOM.passageLink(`Give ${him} a cesarean section`, "csec")); + } else if (slave.broodmother > 0) { + if (slave.broodmotherOnHold !== 1) { + linkArray.push(App.UI.DOM.link( + `Turn off implant`, + () => { + slave.broodmotherOnHold = 1; + slave.broodmotherCountDown = 38 - WombMinPreg(slave); + refresh(); + }, + )); + } + if (slave.preg > 37) { + linkArray.push(App.UI.DOM.passageLink(`Induce mass childbirth`, "BirthStorm")); + } + } else if (slave.preg > slave.pregData.minLiveBirth) { + linkArray.push(App.UI.DOM.link( + `Give ${him} a cesarean section`, + () => { + slave.broodmotherOnHold = 0; + slave.broodmotherCountDown = 0; + }, + [], + "csec" + )); + } else if (slave.preg > 0 && slave.breedingMark === 1 && V.propOutcome === 1 && V.arcologies[0].FSRestart !== "unset" && V.eugenicsFullControl !== 1 && (slave.pregSource === -1 || slave.pregSource === -6)) { + note += "You are forbidden from aborting an Elite child"; + } else if (slave.preg > 0) { + linkArray.push(App.UI.DOM.link( + `Abort ${his} pregnancy`, + () => { + slave.broodmotherOnHold = 0; + slave.broodmotherCountDown = 0; + }, + [], + "Abort" + )); + } + } + App.UI.DOM.appendNewElement("span", fertilityBlock, note, "note"); + App.UI.DOM.appendNewElement("div", fertilityBlock, App.UI.DOM.generateLinksStrip(linkArray), "choices"); + } + if ( + (slave.pregKnown === 1) && + (V.pregSpeedControl === 1) && + ( + slave.breedingMark !== 1 || + V.propOutcome === 0 || + V.eugenicsFullControl === 1 || + V.arcologies[0].FSRestart === "unset" + ) && + (slave.indentureRestrictions < 1) && + (slave.broodmother === 0) && + V.seePreg !== 0 + ) { + let title = document.createElement('div'); + let underline = document.createElement('span'); + underline.style.textDecoration = "underline"; + underline.textContent = "Pregnancy control"; + title.appendChild(underline); + title.append(": "); + + if (slave.pregControl === "labor suppressors") { + title.append("Labor is suppressed. "); + } else if (slave.pregControl === "slow gestation") { + title.append("Slowed gestation speed. "); + } else if (slave.pregControl === "speed up") { + title.append("Faster gestation speed, staffed clinic recommended. "); + } else { + title.append("Normal gestation and birth. "); + } + fertilityBlock.appendChild(title); + + linkArray = []; + if (slave.pregControl !== "none") { + linkArray.push(App.UI.DOM.link( + `Normal ${slave.preg < slave.pregData.normalBirth ? "Gestation" : "Birth"}`, + () => { + slave.pregControl = "none"; + refresh(); + }, + )); + } + if (slave.preg < slave.pregData.normalBirth) { + if (slave.pregControl !== "slow gestation") { + linkArray.push(App.UI.DOM.link( + `Slow Gestation`, + () => { + slave.pregControl = "slow gestation"; + refresh(); + }, + )); + } + if (slave.pregControl !== "speed up") { + linkArray.push(App.UI.DOM.link( + `Fast Gestation`, + () => { + slave.pregControl = "speed up"; + refresh(); + }, + )); + } + } + if (slave.preg >= slave.pregData.minLiveBirth) { + if (slave.pregControl !== "labor suppressors") { + linkArray.push(App.UI.DOM.link( + `Suppress Labor`, + () => { + slave.pregControl = "labor suppressors"; + refresh(); + }, + )); + } + } + App.UI.DOM.appendNewElement("div", fertilityBlock, App.UI.DOM.generateLinksStrip(linkArray), "choices"); + } + return fertilityBlock; + } + + function incubator() { + V.reservedChildren = FetusGlobalReserveCount("incubator"); + let _reservedIncubator = WombReserveCount(slave, "incubator"); + let _reservedNursery = WombReserveCount(slave, "nursery"); + let _WL = slave.womb.length; + let el = document.createElement('div'); + + if (V.incubator > 0) { + if (slave.preg > 0 && slave.broodmother === 0 && slave.pregKnown === 1 && slave.eggType === "human") { + if ((slave.assignment !== Job.DAIRY || V.dairyPregSetting === 0) && (slave.assignment !== Job.FARMYARD || V.farmyardBreeding === 0)) { + let title = document.createElement('div'); + let link = document.createElement('div'); + link.className = "choices"; + if (_WL - _reservedNursery === 0) { + title.textContent = `${His} children are already reserved for ${V.nurseryName}`; + title.style.fontStyle = "italic"; + } else { + const freeTanks = (V.incubator - V.tanks.length); + if (_reservedIncubator > 0) { + if (_WL === 1) { + title.textContent = `${His} child will be placed in ${V.incubatorName}. `; + } else if (_reservedIncubator < _WL) { + title.textContent = `${_reservedIncubator} of ${his} children will be placed in ${V.incubatorName}.`; + } else if (_WL === 2) { + title.textContent = `Both of ${his} children will be placed in ${V.incubatorName}. `; + } else { + title.textContent = `All ${_reservedIncubator} of ${his} children will be placed in ${V.incubatorName}. `; + } + if ((_reservedIncubator + _reservedNursery < _WL) && (V.reservedChildren < freeTanks)) { + link.appendChild( + App.UI.DOM.link(`Keep another child`, () => wombUpdateIncubator(1, true)) + ); + if (_reservedIncubator > 0) { + link.append(` | `); + link.appendChild( + App.UI.DOM.link(`Keep one less child`, () => wombUpdateIncubator(1, false)) + ); + } + if (_reservedIncubator > 1) { + link.append(` | `); + link.appendChild( + App.UI.DOM.link(`Keep none of ${his} children`, () => wombUpdateIncubator(9999, false)) + ); + } + if ((V.reservedChildren + _WL - _reservedIncubator) <= freeTanks) { + link.append(` | `); + link.appendChild( + App.UI.DOM.link(`Keep the rest of ${his} children`, () => wombUpdateIncubator(9999, true)) + ); + } + } else if ((_reservedIncubator === _WL) || (V.reservedChildren === freeTanks) || (_reservedIncubator - _reservedNursery >= 0)) { + link.appendChild( + App.UI.DOM.link(`Keep one less child`, () => wombUpdateIncubator(1, false)) + ); + if (_reservedIncubator > 1) { + link.append(` | `); + link.appendChild( + App.UI.DOM.link(`Keep none of ${his} children`, () => wombUpdateIncubator(9999, false)) + ); + } + } + } else if (V.reservedChildren < freeTanks) { + title.textContent = `${He} is pregnant and you have `; + if (freeTanks === 1) { + title.textContent += `an `; + } + let tank = document.createElement('span'); + tank.className = "lime"; + tank.textContent = `available aging tank`; + if (freeTanks > 1) { + tank.textContent += `s`; + } + tank.textContent += `.`; + let _cCount = (_WL > 1 ? "a" : "the"); + link.appendChild( + App.UI.DOM.link(`Keep ${_cCount} child`, () => wombUpdateIncubator(1, true)) + ); + title.appendChild(tank); + if ((_WL > 1) && (V.reservedChildren + _WL) <= freeTanks) { + link.append(` | `); + link.appendChild( + App.UI.DOM.link(`Keep all of ${his} children`, () => wombUpdateIncubator(9999, true)) + ); + } + } else if (V.reservedChildren === freeTanks) { + title.textContent = `You have no available tanks for ${his} children. `; + } + } + el.append(title); + el.append(link); + } + } + } + + function wombUpdateIncubator(count, addToWomb) { + if (addToWomb) { + WombAddToGenericReserve(slave, "incubator", count); + } else { + WombCleanGenericReserve(slave, "incubator", count); + } + V.reservedChildren = FetusGlobalReserveCount("incubator"); + refresh(); + } + + return el; + } + + function nursery() { + let el = document.createElement('div'); + if (V.nursery > 0) { + V.reservedChildrenNursery = FetusGlobalReserveCount("nursery"); + let reservedIncubator = WombReserveCount(slave, "incubator"); + let reservedNursery = WombReserveCount(slave, "nursery"); + let _WL = slave.womb.length; + if (slave.preg > 0 && slave.broodmother === 0 && slave.pregKnown === 1 && slave.eggType === "human") { + if ((slave.assignment !== Job.DAIRY || V.dairyPregSetting === 0) && (slave.assignment !== Job.FARMYARD || V.farmyardBreeding === 0)) { + let title = document.createElement('div'); + let link = document.createElement('div'); + link.className = "choices"; + if (_WL - reservedIncubator === 0) { + V.reservedChildren = 0; + title.textContent = `${His} children are already reserved for ${V.incubatorName}`; + title.style.fontStyle = "italic"; + } else { + const freeCribs = (V.nursery - V.cribs.length); + if (reservedNursery > 0) { + if (_WL === 1) { + title.textContent = `${His} child will be placed in ${V.nurseryName}. `; + } else if (reservedNursery < _WL) { + title.textContent = `_reservedNursery of ${his} children will be placed in ${V.nurseryName}.`; + } else if (_WL === 2) { + title.textContent = `Both of ${his} children will be placed in ${V.nurseryName}. `; + } else { + title.textContent = `All ${reservedNursery} of ${his} children will be placed in ${V.nurseryName}. `; + } + if ((reservedIncubator + reservedNursery < _WL) && (V.reservedChildrenNursery < freeCribs)) { + link.appendChild( + App.UI.DOM.link(`Keep another child`, () => wombUpdateNursery(1, true)) + ); + + if (reservedNursery > 0) { + link.append(` | `); + link.appendChild( + App.UI.DOM.link(`Keep one less child`, () => wombUpdateNursery(1, false)) + ); + } + if (reservedNursery > 1) { + link.append(` | `); + link.appendChild( + App.UI.DOM.link(`Keep none of ${his} children`, () => wombUpdateNursery(9999, false)) + ); + } + if ((V.reservedChildrenNursery + _WL - reservedNursery) <= freeCribs) { + link.append(` | `); + link.appendChild( + App.UI.DOM.link(`Keep the rest of ${his} children`, () => wombUpdateNursery(9999, true)) + ); + } + } else if ((reservedNursery === _WL) || (V.reservedChildrenNursery === freeCribs) || (reservedNursery - reservedIncubator >= 0)) { + link.appendChild( + App.UI.DOM.link(`Keep one less child`, () => wombUpdateNursery(1, false)) + ); + + if (reservedNursery > 1) { + link.append(` | `); + link.appendChild( + App.UI.DOM.link(`Keep none of ${his} children`, () => wombUpdateNursery(9999, false)) + ); + } + } + } else if (V.reservedChildrenNursery < freeCribs) { + title.textContent = `${He} is pregnant and you have `; + if (freeCribs === 1) { + title.textContent += `an `; + } + let crib = document.createElement('span'); + crib.className = "lime"; + crib.textContent = `available room`; + if (freeCribs > 1) { + crib.textContent += `s`; + } + crib.textContent += `.`; + let _cCount = (_WL > 1 ? "a" : "the"); + link.appendChild( + App.UI.DOM.link(`Keep ${_cCount} child`, () => wombUpdateNursery(1, true)) + ); + title.appendChild(crib); + if ((_WL > 1) && (V.reservedChildrenNursery + _WL) <= freeCribs) { + link.append(` | `); + link.appendChild( + App.UI.DOM.link(`Keep all of ${his} children`, () => wombUpdateNursery(9999, true)) + ); + } + } else if (V.reservedChildrenNursery === freeCribs) { + title.textContent = `You have no available rooms for ${his} children. `; + } + } + el.append(title); + el.append(link); + } + } + } + + function wombUpdateNursery(count, addToWomb) { + if (addToWomb) { + WombAddToGenericReserve(slave, "nursery", count); + } else { + WombCleanGenericReserve(slave, "nursery", count); + } V.reservedChildren = FetusGlobalReserveCount("nursery"); + refresh(); + } + + return el; + } + + function breederEligibility() { + const el = document.createElement("div"); + if (V.propOutcome === 1 && V.arcologies[0].FSRestart !== "unset") { + if (slave.breedingMark === 0 && slave.fuckdoll === 0 && slave.eggType === "human" && isFertile(slave) && slave.preg === 0) { + el.classList.add("choices"); + el.append( + App.UI.DOM.passageLink( + `Breeder Eligibility Exam`, + `BreedingTest` + ) + ); + } + } + return el; + } + + function bloating() { + let bloating = document.createElement('div'); + if (slave.inflation > 0) { + let intro = document.createElement('span'); + intro.textContent = "Required Bloating"; + intro.style.textDecoration = "underline"; + bloating.append(intro); + + bloating.append(": "); + + let requirement = document.createElement('span'); + requirement.style.fontWeight = "bold"; + requirement.id = "inflate"; + if (slave.inflation === 3) { + requirement.textContent = `${He} is required to keep 2 gallons of ${slave.inflationType} in ${him} at all times`; + } else if (slave.inflation === 2) { + requirement.textContent = `${He} is required to keep 4 liters of ${slave.inflationType} in ${him} at all times`; + } else if (slave.inflation === 1) { + requirement.textContent = `${He} is required to keep 2 liters of ${slave.inflationType} in ${him} at all times`; + } + bloating.append(requirement); + bloating.append(". "); + + let link = App.UI.DOM.link( + `Let ${him} deflate`, + () => { + deflate(slave); + refresh(); + }, + ); + bloating.append(link); + } + // make sure it updates itself after run + return bloating; + } + + function hormones() { + let el = document.createElement('div'); + const options = []; + const level = []; + + if (slave.hormones !== 0) { + level.push({text: `None`, updateSlave: {hormones: 0}}); + } + + if (slave.indentureRestrictions < 2) { + options.push({text: `Intensive Female`, updateSlave: {hormones: 2}}); + } else { + options.push({text: `Intensive Female`, disabled: `Cannot use intensive hormones on indentured slaves`}); + } + options.push({text: `Female`, updateSlave: {hormones: 1}}); + options.push({text: `Male`, updateSlave: {hormones: -1}}); + if (slave.indentureRestrictions < 2) { + options.push({text: `Intensive Male`, updateSlave: {hormones: -2}}); + } else { + options.push({text: `Intensive Male`, disabled: `Cannot use intensive hormones on indentured slaves`}); + } + + let title = document.createElement('div'); + title.textContent = `Hormones: `; + let choice = document.createElement('span'); + choice.style.fontWeight = "bold"; + switch (slave.hormones) { + case 2: { + choice.textContent = `intensive female. `; + break; + } + case 1: { + choice.textContent = `female. `; + break; + } + case 0: { + choice.textContent = `none. `; + break; + } + case -1: { + choice.textContent = `male. `; + break; + } + case -2: { + choice.textContent = `intensive male. `; + break; + } + default: { + choice.textContent = `Not set. `; + } + } + + title.append(choice); + title.appendChild(App.UI.SlaveInteract.generateRows(level, slave, "", false, refresh)); + el.append(title); + + let links = document.createElement('div'); + links.appendChild(App.UI.SlaveInteract.generateRows(options, slave, "", false, refresh)); + links.className = "choices"; + el.append(links); + + return el; + } + + function diet() { + let el = document.createElement('div'); + + let title = document.createElement('div'); + title.textContent = `Diet: `; + let choice = document.createElement('span'); + choice.style.fontWeight = "bold"; + choice.textContent = `${capFirstChar(slave.diet)}. `; + + title.append(choice); + el.append(title); + + const health = []; + health.push({text: `Healthy`, updateSlave: {diet: "healthy"}}); + if (V.dietCleanse === 1) { + if (slave.health.condition < 90 || slave.chem >= 10) { + health.push({text: `Cleanse`, updateSlave: {diet: "cleansing"}}); + } else { + health.push({text: `Cleanse`, disabled: `${He} is already healthy`}); + } + } + + const weight = []; + if (slave.weight >= -95) { + weight.push({text: `Lose weight`, updateSlave: {diet: "restricted"}}); + } else { + weight.push({text: `Lose weight`, disabled: `${He} is already underweight`}); + } + if (slave.fuckdoll === 0 && slave.fetish !== "mindbroken" && V.feeder === 1) { + if (slave.weight > 10 || slave.weight < -10) { + weight.push({text: `Correct weight`, updateSlave: {diet: "corrective"}}); + } else { + weight.push({text: `Correct weight`, disabled: `${He} is already a healthy weight`}); + } + } + if (slave.weight <= 200) { + weight.push({text: `Fatten`, updateSlave: {diet: "fattening"}}); + } else { + weight.push({text: `Fatten`, disabled: `${He} is already overweight`}); + } + + const muscle = []; + if (slave.muscles < 100 && !isAmputee(slave)) { + muscle.push({text: `Build muscle`, updateSlave: {diet: "muscle building"}}); + } else if (!isAmputee(slave)) { + muscle.push({text: `Build muscle`, disabled: `${He} is maintaining ${his} enormous musculature`}); + } else { + muscle.push({text: `Build muscle`, disabled: `${He} has no limbs and thus can't effectively build muscle`}); + } + + if ((slave.muscles > 0 || slave.fuckdoll === 0) && canWalk(slave)) { + muscle.push({text: `Slim down`, updateSlave: {diet: "slimming"}}); + } else if (!canWalk(slave)) { + muscle.push({text: `Slim down`, disabled: `${He} can't walk and thus can't trim down`}); + } else if (slave.fuckdoll > 0) { + muscle.push({text: `Slim down`, disabled: `${He} has no muscles left to lose`}); + } + + const production = []; + if (slave.balls > 0 && V.cumProDiet === 1) { + production.push({text: `Cum production`, updateSlave: {diet: "cum production"}}); + } + if (((isFertile(slave) && slave.preg === 0) || (slave.geneticQuirks.superfetation === 2 && canGetPregnant(slave) && V.geneticMappingUpgrade !== 0)) && V.dietFertility === 1) { + production.push({text: `Fertility`, updateSlave: {diet: "fertility"}}); + } + + const hormone = []; + if (V.feeder === 1) { + hormone.push({text: `Estrogen enriched`, updateSlave: {diet: "XX"}}); + hormone.push({text: `Testosterone enriched`, updateSlave: {diet: "XY"}}); + if (V.dietXXY === 1 && slave.balls > 0 && (slave.ovaries === 1 || slave.mpreg === 1)) { + hormone.push({text: `Herm hormone blend`, updateSlave: {diet: "XXY"}}); + } + } + + App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Health", health, slave, refresh); + App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Weight", weight, slave, refresh); + App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Muscle", muscle, slave, refresh); + App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Production", production, slave, refresh); + App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Hormone", hormone, slave, refresh); + + return el; + } + + function dietBase() { + let el = document.createElement('div'); + const milk = []; + const cum = []; + + // Milk + if (slave.dietCum < 2) { + milk.push({text: `Milk added`, updateSlave: {dietMilk: 1}}); + if (slave.dietCum < 2) { + milk.push({text: `Milk based`, updateSlave: {dietMilk: 2, dietCum: 0}}); + } + if (slave.dietMilk) { + milk.push({text: `Remove milk`, updateSlave: {dietMilk: 0}}); + } + } else { + milk.push({text: `Milk`, disabled: `Diet is based entirely on cum`}); + } + + // Cum + if (slave.dietMilk < 2) { + cum.push({text: `Cum added`, updateSlave: {dietCum: 1}}); + cum.push({text: `Cum based`, updateSlave: {dietCum: 2, dietMilk: 0}}); + if (slave.dietCum) { + cum.push({text: `Remove cum`, updateSlave: {dietCum: 0}}); + } + } else { + cum.push({text: `Cum`, disabled: `Diet is based entirely on milk`}); + } + + let title = document.createElement('div'); + title.textContent = `Diet base: `; + let choice = document.createElement('span'); + choice.style.fontWeight = "bold"; + if (slave.dietCum === 2) { + choice.textContent = `cum based. `; + } else if (slave.dietCum === 1 && slave.dietMilk === 0) { + choice.textContent = `cum added. `; + } else if (slave.dietCum === 1 && slave.dietMilk === 1) { + choice.textContent = `cum and milk added. `; + } else if (slave.dietMilk === 1 && slave.dietCum === 0) { + choice.textContent = `milk added. `; + } else if (slave.dietMilk === 2) { + choice.textContent = `milk based. `; + } else if (slave.dietCum === 0 && slave.dietMilk === 0) { + choice.textContent = `normal. `; + } else { + choice.textContent = `THERE HAS BEEN AN ERROR.`; + } + + title.append(choice); + el.append(title); + + App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Milk", milk, slave, refresh); + App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Cum", cum, slave, refresh); + + return el; + } + + function snacks() { + let el = document.createElement('div'); + let options = []; + + if (V.arcologies[0].FSHedonisticDecadenceResearch === 1) { + let title = document.createElement('div'); + title.textContent = `Solid Slave Food Access: `; + let choice = document.createElement('span'); + choice.style.fontWeight = "bold"; + if (slave.onDiet === 0) { + choice.textContent = `Free to stuff ${himself}.`; + } else { + choice.textContent = `On a strict diet.`; + } + title.append(choice); + el.append(title); + + options.push({text: `No access`, updateSlave: {onDiet: 1}}); + options.push({text: `Full access`, updateSlave: {onDiet: 0}}); + + let links = document.createElement('div'); + links.appendChild(App.UI.SlaveInteract.generateRows(options, slave, "", false, refresh)); + links.className = "choices"; + el.append(links); + } + + return el; + } + } + function refresh() { + jQuery("#si-physical-regimen").empty().append(physicalRegimenContent()); + } +}; diff --git a/src/interaction/siRules.js b/src/interaction/siRules.js new file mode 100644 index 0000000000000000000000000000000000000000..3e8af1a0547b59e298f9afb2b1bee3682cc9f1d5 --- /dev/null +++ b/src/interaction/siRules.js @@ -0,0 +1,389 @@ +App.UI.SlaveInteract.rules = function(slave) { + const el = document.createElement("div"); + el.id = "si-rules"; + el.append(rulesContent()); + return el; + + function rulesContent() { + const frag = new DocumentFragment(); + let p; + let div; + let array; + let choices; + const { + He, His, + he, him, his + } = getPronouns(slave); + + if (V.seePreg !== 0) { + if (V.universalRulesImpregnation === "PC") { + updateBreederLink("you", "PCExclude"); + } else if (V.universalRulesImpregnation === "HG") { + updateBreederLink("the Head Girl", "HGExclude"); + } else if (V.universalRulesImpregnation === "Stud") { + updateBreederLink("your Stud", "StudExclude"); + } + } + + function updateBreederLink(breeder, exclude) { + p = document.createElement('p'); + const exempt = slave[exclude] ? "Exempt" : "Include"; + + p.append(`Will be bred by ${breeder} when fertile. `); + p.append( + App.UI.DOM.link(`${exempt} ${him}`, () => { + slave[exclude] = slave[exclude] ^ 1; // switch 0 and 1 + refresh(); + }) + ); + frag.append(p); + } + + p = document.createElement('p'); + + array = []; + if (slave.useRulesAssistant === 0) { + App.UI.DOM.appendNewElement("span", p, `Not subject `, ["bold", "gray"]); + App.UI.DOM.appendNewElement("span", p, `to the Rules Assistant.`, "gray"); + array.push( + App.UI.DOM.link( + `Include ${him}`, + () => { + slave.useRulesAssistant = 1; + refresh(); + } + ) + ); + } else { + App.UI.DOM.appendNewElement("h3", p, `Rules Assistant`); + + if (slave.hasOwnProperty("currentRules") && slave.currentRules.length > 0) { + const ul = document.createElement("UL"); + ul.style.margin = "0"; + V.defaultRules.filter( + x => ruleApplied(slave, x) + ).map( + x => { + const li = document.createElement('li'); + li.append(x.name); + ul.append(li); + } + ); + + // set up rules display + if ($("ul").has("li").length) { + App.UI.DOM.appendNewElement("div", p, `Rules applied: `); + p.append(ul); + } else { + App.UI.DOM.appendNewElement("div", p, `There are no rules that would apply to ${him}.`, "gray"); + } + } + array.push( + App.UI.DOM.link( + `Apply rules`, + () => { + DefaultRules(slave); + refresh(); + } + ) + ); + array.push( + App.UI.DOM.link( + `Exempt ${him}`, + () => { + slave.useRulesAssistant = 0; + refresh(); + } + ) + ); + array.push(App.UI.DOM.passageLink("Rules Assistant Options", "Rules Assistant")); + } + p.append(App.UI.DOM.generateLinksStrip(array)); + frag.append(p); + + p = document.createElement('p'); + App.UI.DOM.appendNewElement("h3", p, `Other Rules`); + + // Living + if (slave.fuckdoll > 0) { + App.UI.DOM.appendNewElement("span", p, "Rules have little meaning for living sex toys", "note"); + } else { + penthouseCensus(); + p.append("Living standard: "); + App.UI.DOM.appendNewElement("span", p, slave.rules.living, "bold"); + } + if (setup.facilityCareers.includes(slave.assignment)) { + App.UI.DOM.appendNewElement("span", p, ` ${His} living conditions are managed by ${his} assignment.`, "note"); + } else if ((slave.assignment === "be your Head Girl") && (V.HGSuite === 1)) { + App.UI.DOM.appendNewElement("span", p, ` ${He} has ${his} own little luxurious room in the penthouse with everything ${he} needs to be a proper Head Girl.`, "note"); + } else if ((slave.assignment === "guard you") && (V.dojo > 1)) { + App.UI.DOM.appendNewElement("span", p, ` ${He} has a comfortable room in the armory to call ${his} own.`, "note"); + } else { + choices = [ + {value: "spare"}, + {value: "normal"}, + ]; + if (canMoveToRoom(slave) || slave.rules.living === "luxurious") { + choices.push({value: "luxurious"}); + } else { + choices.push({ + title: `Luxurious`, + disabled: ["No luxurious rooms available"] + }); + } + + p.append(listChoices(choices, "living")); + } + + // Rest + if (["be a servant", "be a subordinate slave", "get milked", "please you", "serve in the club", "serve the public", "whore", "work as a farmhand", "work in the brothel", "work a glory hole"].includes(slave.assignment) || (V.dairyRestraintsSetting < 2 && slave.assignment === "work in the dairy")) { + div = document.createElement("div"); + div.append("Sleep rules: "); + App.UI.DOM.appendNewElement("span", div, slave.rules.rest, "bold"); + choices = [ + {value: "none"}, + {value: "cruel"}, + {value: "restrictive"}, + {value: "permissive"}, + {value: "mandatory"}, + ]; + div.append(listChoices(choices, "rest")); + p.append(div); + } + + // Mobility Aids + if (slave.fuckdoll > 0) { + // Sex toys don't move around on their own// + } else if (canMove(slave)) { + div = document.createElement("div"); + div.append("Use of mobility aids: "); + App.UI.DOM.appendNewElement("span", div, slave.rules.mobility, "bold"); + choices = [ + {value: "restrictive"}, + {value: "permissive"}, + ]; + div.append(listChoices(choices, "mobility")); + p.append(div); + } + + // Punishment + div = document.createElement("div"); + div.append("Typical punishment: "); + App.UI.DOM.appendNewElement("span", div, slave.rules.punishment, "bold"); + choices = [ + {value: "confinement"}, + {value: "whipping"}, + {value: "chastity"}, + {value: "situational"}, + ]; + div.append(listChoices(choices, "punishment")); + p.append(div); + + // Reward + div = document.createElement("div"); + div.append("Typical reward: "); + App.UI.DOM.appendNewElement("span", div, slave.rules.reward, "bold"); + choices = [ + {value: "relaxation"}, + {value: "drugs"}, + {value: "orgasm"}, + {value: "situational"}, + ]; + div.append(listChoices(choices, "reward")); + p.append(div); + + // Lactation + if (slave.lactation !== 2) { + div = document.createElement("div"); + div.append("Lactation maintenance: "); + App.UI.DOM.appendNewElement("span", div, slave.rules.lactation, "bold"); + choices = [ + { + title: "Left alone", + value: "none", + }, + ]; + + if (slave.lactation === 0) { + choices.push( + { + title: "Induce lactation", + value: "induce", + } + ); + } else { + choices.push( + { + title: "Maintain lactation", + value: "maintain", + } + ); + } + div.append(listChoices(choices, "lactation")); + p.append(div); + } + + p.append(orgasm(slave)); + + if (slave.voice !== 0) { + div = document.createElement("div"); + div.append("Speech rules: "); + App.UI.DOM.appendNewElement("span", div, slave.rules.speech, "bold"); + choices = [ + {value: "restrictive"}, + {value: "permissive"}, + ]; + if (slave.accent > 0 && slave.accent < 4) { + choices.push( + {value: "accent elimination"}, + ); + } else if (slave.accent > 3) { + choices.push( + {value: "language lessons"}, + ); + } + div.append(listChoices(choices, "speech")); + p.append(div); + } + + div = document.createElement("div"); + div.append("Relationship rules: "); + App.UI.DOM.appendNewElement("span", div, slave.rules.relationship, "bold"); + choices = [ + {value: "restrictive"}, + {value: "just friends"}, + {value: "permissive"}, + ]; + div.append(listChoices(choices, "relationship")); + p.append(div); + + p.append(smartSettings(slave)); + frag.append(p); + return frag; + + function listChoices(choices, property) { + const links = []; + for (const c of choices) { + const title = c.title || capFirstChar(c.value); + if (c.disabled) { + links.push( + App.UI.DOM.disabledLink( + title, c.disabled + ) + ); + } else { + links.push( + App.UI.DOM.link( + title, + () => { + slave.rules[property] = c.value; + refresh(); + } + ) + ); + } + } + return App.UI.DOM.generateLinksStrip(links); + } + function orgasm(slave) { + let el = document.createElement('div'); + + let title = document.createElement('div'); + title.textContent = `Non-assignment orgasm rules: `; + el.append(title); + + makeLinks("Masturbation", "rules.release.masturbation"); + makeLinks("Partner", "rules.release.partner"); + makeLinks("Family", "rules.release.family"); + makeLinks("Other slaves", "rules.release.slaves"); + makeLinks("Master", "rules.release.master", true); + + function makeLinks(text, setting, master = false) { + const options = + [{text: master ? `Grant` : `Allow`, updateSlave: {[setting]: 1}}, + {text: master ? `Deny` : `Forbid`, updateSlave: {[setting]: 0}}]; + + let links = document.createElement('div'); + links.append(`${text}: `); + links.append(status(_.get(slave, setting), master)); + links.appendChild(App.UI.SlaveInteract.generateRows(options, slave)); + links.className = "choices"; + el.append(links); + } + + function status(setting, master) { + let selected = document.createElement('span'); + selected.style.fontWeight = "bold"; + let text; + if (master) { + text = setting ? "granted" : "denied"; + } else { + text = setting ? "allowed" : "denied"; + } + selected.textContent = `${text}. `; + return selected; + } + + return el; + } + + function smartSettings(slave) { + let el = document.createElement('div'); + + const {His} = getPronouns(slave); + const bodyPart = []; + const BDSM = []; + const gender = []; + const level = []; + const usingBulletVibe = slave.vaginalAccessory === "smart bullet vibrator" || slave.dickAccessory === "smart bullet vibrator"; + + if (slave.clitPiercing === 3 || usingBulletVibe) { + // Level + level.push({text: `No sex`, updateSlave: {clitSetting: `none`}}); + level.push({text: `All sex`, updateSlave: {clitSetting: `all`}}); + + // Body part + bodyPart.push({text: `Vanilla`, updateSlave: {clitSetting: `vanilla`}}); + bodyPart.push({text: `Oral`, updateSlave: {clitSetting: `oral`}}); + bodyPart.push({text: `Anal`, updateSlave: {clitSetting: `anal`}}); + bodyPart.push({text: `Boobs`, updateSlave: {clitSetting: `boobs`}}); + if (V.seePreg !== 0) { + bodyPart.push({text: `Preg`, updateSlave: {clitSetting: `pregnancy`}}); + } + // BDSM + BDSM.push({text: `Sub`, updateSlave: {clitSetting: `submissive`}}); + BDSM.push({text: `Dom`, updateSlave: {clitSetting: `dom`}}); + BDSM.push({text: `Masochism`, updateSlave: {clitSetting: `masochist`}}); + BDSM.push({text: `Sadism`, updateSlave: {clitSetting: `sadist`}}); + BDSM.push({text: `Humiliation`, updateSlave: {clitSetting: `humiliation`}}); + + // Gender + gender.push({text: `Men`, updateSlave: {clitSetting: `men`}}); + gender.push({text: `Women`, updateSlave: {clitSetting: `women`}}); + gender.push({text: `Anti-men`, updateSlave: {clitSetting: `anti-men`}}); + gender.push({text: `Anti-women`, updateSlave: {clitSetting: `anti-women`}}); + } + + let label = null; + if (slave.clitPiercing === 3) { + label = `${His} smart ${slave.dick < 1 ? "clit" : "frenulum"} piercing `; + label += (usingBulletVibe) ? `and smart bullet vibrator are set to: ` : `is set to: `; + } + if (label) { + let title = App.UI.DOM.appendNewElement('div', el, label); + let selected = App.UI.DOM.appendNewElement('span', title, `${slave.clitSetting}. `); + selected.style.fontWeight = "bold"; + } + + App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Level", level, slave); + App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Body part", bodyPart, slave); + App.UI.SlaveInteract.appendLabeledChoiceRow(el, "BDSM", BDSM, slave); + App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Gender", gender, slave); + + return el; + } + function refresh() { + jQuery("#si-rules").empty().append(rulesContent()); + } + } +}; diff --git a/src/interaction/siUtilities.js b/src/interaction/siUtilities.js new file mode 100644 index 0000000000000000000000000000000000000000..b5569e4a240d44140c4a368d415f1925e08d96cc --- /dev/null +++ b/src/interaction/siUtilities.js @@ -0,0 +1,148 @@ +/** Find the previous and next slaves' IDs based on the current sort order + * @param {App.Entity.SlaveState} slave + * @returns {[number, number]} - previous and next slave ID + */ +App.UI.SlaveInteract.placeInLine = function(slave) { + const useSlave = assignmentVisible(slave) ? ((s) => assignmentVisible(s)) : ((s) => slave.assignment === s.assignment); + const slaveList = V.slaves.filter(useSlave); + SlaveSort.slaves(slaveList); + const curSlaveIndex = slaveList.findIndex((s) => s.ID === slave.ID); + + let nextIndex; + if (curSlaveIndex + 1 > slaveList.length - 1) { + nextIndex = 0; // wrap around to first slave + } else { + nextIndex = curSlaveIndex + 1; + } + let prevIndex; + if (curSlaveIndex - 1 < 0) { + prevIndex = slaveList.length - 1; // wrap around to last slave + } else { + prevIndex = curSlaveIndex - 1; + } + + return [slaveList[prevIndex].ID, slaveList[nextIndex].ID]; +}; + +/** @typedef RowItem + * @type {object} + * @property {string} [FS] - FS requirement, if any + * @property {string} [text] - link text + * @property {object} [updateSlave] - properties to be merged onto the slave + * @property {object} [update] - properties to be merged into global state + * @property {string} [disabled] - text indicating why the option is unavailable + * @property {string} [note] + */ + +/** Append a simple row of choices with a label to a container, if there are choices to be made. + * @param {Node} parent + * @param {string} label + * @param {RowItem[]} array + * @param {App.Entity.SlaveState} slave + * @param {Function} [refresh] + */ +App.UI.SlaveInteract.appendLabeledChoiceRow = function(parent, label, array, slave, refresh) { + if (array.length > 0) { + let links = document.createElement('div'); + links.append(`${label}: `); + links.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "", false, refresh)); + links.className = "choices"; + return parent.appendChild(links); + } +}; + +/** Generate a row of choices + * @param {RowItem[]} array + * @param {App.Entity.SlaveState} slave + * @param {string} [category] - should be in the form of slave.category, the thing we want to update. + * @param {boolean} [accessCheck=false] + * @param {Function} [refresh] + * @returns {HTMLSpanElement} + */ +App.UI.SlaveInteract.generateRows = function(array, slave, category, accessCheck = false, refresh) { + let row = document.createElement('span'); + let useSep = false; + for (let i = 0; i < array.length; i++) { + let link; + const separator = document.createTextNode(` | `); + const keys = Object.keys(array[i]); + + // Test to see if there was a problem with the key + for (let j = 0; j < keys.length; j++) { + if (["FS", "text", "updateSlave", "update", "note", "disabled"].includes(keys[j])) { + continue; + } else { + array[i].text += " ERROR, THIS SCENE WAS NOT ENTERED CORRECTLY"; + console.log("Trash found while generateRows() was running: " + keys[j] + ": " + array[i][keys[j]]); + break; + } + } + // Some items will never be in App.Data.slaveWear, especially "none" if it falls in between harsh and nice data sets. Trying to look it up would cause an error, which is what access check works around. + let unlocked = false; + if (accessCheck === true) { + if (category === "chastity") { + let text = array[i].text.toLowerCase(); // Yucky. Category name does not match for chastity (since it sets multiple kinds of chastity at once). Compare using a lowercase name instead. + unlocked = isItemAccessible.entry(text, category, slave); + } else { + unlocked = isItemAccessible.entry(array[i].updateSlave[category], category, slave); + } + } + if (accessCheck === false || unlocked) { + if (i < array.length && i !== 0 && useSep === true) { // start with separator (after first loop); can't after since the last loop may not have any text. + row.appendChild(separator); + } + useSep = true; // First item may not appear and if it doesn't we don't want the second to start with a '|' + // is it just text? + if (array[i].disabled) { + link = App.UI.DOM.disabledLink(array[i].text, [array[i].disabled]); + } else if (typeof unlocked === 'string') { + link = App.UI.DOM.disabledLink(array[i].text, [unlocked]); + } else { + link = document.createElement('span'); + + // Set up the link + link.appendChild( + App.UI.DOM.link( + `${array[i].text} `, + () => { click(array[i]); }, + ) + ); + + if (array[i].FS) { + let FS = App.UI.DOM.disabledLink(`FS`, [FutureSocieties.displayAdj(array[i].FS)]); + FS.style.fontStyle = "italic"; + link.appendChild(FS); + } + + // add a note node if required + if (array[i].note) { + link.appendChild(App.UI.DOM.makeElement('span', ` ${array[i].note}`, 'note')); + } + } + row.appendChild(link); + } + } + + return row; + + /** @param {RowItem} arrayOption */ + function click(arrayOption) { + if (arrayOption.updateSlave) { + for (const slaveProperty in arrayOption.updateSlave) { + _.set(slave, slaveProperty, arrayOption.updateSlave[slaveProperty]); + } + } + if (arrayOption.update) { + Object.assign(V, arrayOption.update); + } + if (typeof refresh === "function") { + refresh(); + } else { + App.UI.SlaveInteract.refreshAll(slave); + } + } +}; + +App.UI.SlaveInteract.refreshAll = function(slave) { + App.UI.SlaveInteract.custom(slave); +}; diff --git a/src/interaction/siWardrobe.js b/src/interaction/siWardrobe.js new file mode 100644 index 0000000000000000000000000000000000000000..074312444eb65be5967386d41a7420c8947d4c11 --- /dev/null +++ b/src/interaction/siWardrobe.js @@ -0,0 +1,842 @@ +App.UI.SlaveInteract.wardrobe = function(slave) { + const el = document.createElement("p"); + el.id = "si-wardrobe"; + el.append(wardrobeContent()); + return el; + + function wardrobeContent() { + const { + // eslint-disable-next-line no-unused-vars + he, + him, + his, + } = getPronouns(slave); + const el = new DocumentFragment(); + el.append(clothes()); + el.append(collar()); + el.append(mask()); + el.append(mouth()); + el.append(armAccessory()); + el.append(shoes()); + el.append(legAccessory()); + el.append(bellyAccessory()); + el.append(buttplug()); + el.append(buttplugAttachment()); + el.append(vaginalAccessory()); + el.append(vaginalAttachment()); + el.append(dickAccessory()); + el.append(chastity()); + + App.UI.DOM.appendNewElement("h3", el, `Shopping`); + el.append(shopping()); + + return el; + + function clothes() { + let el = document.createElement('div'); + let links; + if (slave.fuckdoll === 0) { + // <<= App.Desc.clothing($activeSlave)>> + + let label = document.createElement('div'); + label.append(`Clothes: `); + + let choice = document.createElement('span'); + choice.style.fontWeight = "bold"; + choice.textContent = (`${slave.clothes} `); + label.appendChild(choice); + + // Choose her own + if (slave.clothes !== `choosing her own clothes`) { + let choiceOptionsArray = []; + choiceOptionsArray.push({text: `Let ${him} choose`, updateSlave: {clothes: `choosing her own clothes`, choosesOwnClothes: 1}}); + label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "clothes", false, refresh)); + } + el.appendChild(label); + + + let niceOptionsArray = []; + let harshOptionsArray = []; + + let clothingOption; + // Nice clothes + App.Data.slaveWear.niceClothes.forEach(item => { + clothingOption = { + text: item.name, + updateSlave: {clothes: item.value, choosesOwnClothes: 0}, + FS: item.fs + }; + niceOptionsArray.push(clothingOption); + }); + // Harsh clothes + App.Data.slaveWear.harshClothes.forEach(item => { + clothingOption = { + text: item.name, + updateSlave: {clothes: item.value, choosesOwnClothes: 0}, + FS: item.fs + }; + if (item.value !== "choosing her own clothes") { + harshOptionsArray.push(clothingOption); + } + }); + + // Sort + niceOptionsArray = niceOptionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); + harshOptionsArray = harshOptionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); + + // Nice options + links = document.createElement('div'); + links.className = "choices"; + links.append(`Nice: `); + links.appendChild(App.UI.SlaveInteract.generateRows(niceOptionsArray, slave, "clothes", true, refresh)); + el.appendChild(links); + + // Harsh options + links = document.createElement('div'); + links.className = "choices"; + links.append(`Harsh: `); + links.appendChild(App.UI.SlaveInteract.generateRows(harshOptionsArray, slave, "clothes", true, refresh)); + el.appendChild(links); + } + if (slave.fuckdoll !== 0 || slave.clothes === "restrictive latex" || slave.clothes === "a latex catsuit" || slave.clothes === "a cybersuit" || slave.clothes === "a comfortable bodysuit") { + if (V.seeImages === 1 && V.imageChoice === 1) { + // Color options + links = document.createElement('div'); + links.className = "choices"; + links.append(`Color: `); + links.appendChild(colorOptions("clothingBaseColor")); + el.appendChild(links); + } + } + + return el; + } + + function collar() { + if (slave.fuckdoll !== 0) { + return; + } + // <<= App.Desc.collar($activeSlave)>> + let el = document.createElement('div'); + + let label = document.createElement('div'); + label.append(`Collar: `); + + let choice = document.createElement('span'); + choice.style.fontWeight = "bold"; + choice.textContent = (`${slave.collar} `); + label.appendChild(choice); + + // Choose her own + if (slave.collar !== `none`) { + let choiceOptionsArray = []; + choiceOptionsArray.push({text: `None`, updateSlave: {collar: `none`}}); + label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "collar", false, refresh)); + } + + el.appendChild(label); + + let niceOptionsArray = []; + let harshOptionsArray = []; + + let clothingOption; + // Nice collar + App.Data.slaveWear.niceCollars.forEach(item => { + clothingOption = { + text: item.name, + updateSlave: {collar: item.value}, + FS: item.fs + }; + niceOptionsArray.push(clothingOption); + }); + // Harsh collar + App.Data.slaveWear.harshCollars.forEach(item => { + clothingOption = { + text: item.name, + updateSlave: {collar: item.value}, + FS: item.fs + }; + harshOptionsArray.push(clothingOption); + }); + + // Sort + niceOptionsArray = niceOptionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); + harshOptionsArray = harshOptionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); + + // Nice options + let links = document.createElement('div'); + links.className = "choices"; + links.append(`Nice: `); + links.appendChild(App.UI.SlaveInteract.generateRows(niceOptionsArray, slave, "collar", true, refresh)); + el.appendChild(links); + + // Harsh options + links = document.createElement('div'); + links.className = "choices"; + links.append(`Harsh: `); + links.appendChild(App.UI.SlaveInteract.generateRows(harshOptionsArray, slave, "collar", true, refresh)); + el.appendChild(links); + + return el; + } + + function mask() { + if (slave.fuckdoll !== 0) { + return; + } + let el = document.createElement('div'); + + let label = document.createElement('div'); + label.append(`Mask: `); + + let choice = document.createElement('span'); + choice.style.fontWeight = "bold"; + choice.textContent = (`${slave.faceAccessory} `); + label.appendChild(choice); + + // Choose her own + if (slave.faceAccessory !== `none`) { + let choiceOptionsArray = []; + choiceOptionsArray.push({text: `None`, updateSlave: {faceAccessory: `none`}}); + label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "faceAccessory", false, refresh)); + } + + el.appendChild(label); + + let array = []; + + let clothingOption; + App.Data.slaveWear.faceAccessory.forEach(item => { + clothingOption = { + text: item.name, + updateSlave: {faceAccessory: item.value}, + FS: item.fs + }; + array.push(clothingOption); + }); + + // Sort + array = array.sort((a, b) => (a.text > b.text) ? 1 : -1); + + let links = document.createElement('div'); + links.className = "choices"; + links.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "faceAccessory", true, refresh)); + el.appendChild(links); + + if (slave.eyewear === "corrective glasses" || slave.eyewear === "glasses" || slave.eyewear === "blurring glasses" || slave.faceAccessory === "porcelain mask") { + // Color options + links = document.createElement('div'); + links.className = "choices"; + links.append(`Color: `); + links.appendChild(colorOptions("glassesColor")); + let note = document.createElement('span'); + note.className = "note"; + note.textContent = ` Only glasses and porcelain masks support a custom color. If both are worn, they will share the same color.`; + links.appendChild(note); + el.appendChild(links); + } + + return el; + } + + function mouth() { + if (slave.fuckdoll !== 0) { + return; + } + let el = document.createElement('div'); + + let label = document.createElement('div'); + label.append(`Gag: `); + + let choice = document.createElement('span'); + choice.style.fontWeight = "bold"; + choice.textContent = (`${slave.mouthAccessory} `); + label.appendChild(choice); + + // Choose her own + if (slave.mouthAccessory !== `none`) { + let choiceOptionsArray = []; + choiceOptionsArray.push({text: `None`, updateSlave: {mouthAccessory: `none`}}); + label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "mouthAccessory", false, refresh)); + } + + el.appendChild(label); + + let array = []; + + let clothingOption; + // mouthAccessory + App.Data.slaveWear.mouthAccessory.forEach(item => { + clothingOption = { + text: item.name, + updateSlave: {mouthAccessory: item.value}, + FS: item.fs + }; + array.push(clothingOption); + }); + + // Sort + array = array.sort((a, b) => (a.text > b.text) ? 1 : -1); + + let links = document.createElement('div'); + links.className = "choices"; + links.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "mouthAccessory", true, refresh)); + el.appendChild(links); + + return el; + } + + function armAccessory() { + if (slave.fuckdoll !== 0) { + return; + } + + let el = document.createElement('div'); + // App.Desc.armwear(slave) + + let label = document.createElement('div'); + label.append(`Arm accessory: `); + + let choice = document.createElement('span'); + choice.style.fontWeight = "bold"; + choice.textContent = (`${slave.armAccessory} `); + label.appendChild(choice); + + let array = []; + + // Choose her own + if (slave.armAccessory !== "none") { + array.push({text: `None`, updateSlave: {armAccessory: `none`}}); + label.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "armAccessory", false, refresh)); + } + + el.appendChild(label); + + let links = document.createElement('div'); + links.className = "choices"; + array = [ + {text: "Hand gloves", updateSlave: {armAccessory: "hand gloves"}}, + {text: "Elbow gloves", updateSlave: {armAccessory: "elbow gloves"}} + ]; + links.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "armAccessory", false, refresh)); + el.appendChild(links); + + return el; + } + + function shoes() { + if (slave.fuckdoll !== 0) { + return; + } + let el = document.createElement('div'); + + let label = document.createElement('div'); + label.append(`Shoes: `); + + let choice = document.createElement('span'); + choice.style.fontWeight = "bold"; + choice.textContent = (`${slave.shoes} `); + label.appendChild(choice); + + /* We have "barefoot" in App.Data.slaveWear to cover for this + // Choose her own + if (slave.shoes !== `none`) { + let choiceOptionsArray = []; + choiceOptionsArray.push({text: `None`, updateSlave: {shoes: `none`}}); + label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "shoes", false, refresh)); + } + */ + el.appendChild(label); + + let optionsArray = []; + + let clothingOption; + App.Data.slaveWear.shoes.forEach(item => { + clothingOption = { + text: item.name, + updateSlave: {shoes: item.value}, + FS: item.fs + }; + optionsArray.push(clothingOption); + }); + + // Sort + // No sort here since we want light -> advanced. optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); + + // Options + let links = document.createElement('div'); + links.className = "choices"; + links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "shoes", true, refresh)); + el.appendChild(links); + + if (V.seeImages === 1 && V.imageChoice === 1 && slave.shoes !== "none") { + // Color options + links = document.createElement('div'); + links.className = "choices"; + links.append(`Color: `); + links.appendChild(colorOptions("shoeColor")); + el.appendChild(links); + } + + return el; + } + + function legAccessory() { + if (slave.fuckdoll !== 0) { + return; + } + + let el = document.createElement('div'); + + let label = document.createElement('div'); + label.append(`Leg accessory: `); + + let choice = document.createElement('span'); + choice.style.fontWeight = "bold"; + choice.textContent = (`${slave.legAccessory} `); + label.appendChild(choice); + + let array = []; + + // Choose her own + if (slave.legAccessory !== "none") { + array.push({text: `None`, updateSlave: {legAccessory: `none`}}); + label.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "legAccessory", false, refresh)); + } + + el.appendChild(label); + + let links = document.createElement('div'); + links.className = "choices"; + array = [ + {text: "Short stockings", updateSlave: {legAccessory: "short stockings"}}, + {text: "Long stockings", updateSlave: {legAccessory: "long stockings"}} + ]; + links.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "legAccessory", false, refresh)); + el.appendChild(links); + + return el; + } + + function bellyAccessory() { + if (slave.fuckdoll !== 0) { + return; + } + // <<waistDescription>><<= App.Desc.pregnancy($activeSlave)>><<clothingCorsetDescription>> + let choiceOptionsArray = []; + choiceOptionsArray.push({text: `None`, updateSlave: {bellyAccessory: `none`}}); + + let optionsArray = []; + + let clothingOption; + App.Data.slaveWear.bellyAccessories.forEach(item => { + clothingOption = { + text: item.name, + updateSlave: {bellyAccessory: item.value}, + FS: item.fs + }; + if (item.value !== "none") { + // skip none in set, we set the link elsewhere. + optionsArray.push(clothingOption); + } + }); + // Sort + // No sort here since we want small -> large.optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); + + let el = document.createElement('div'); + + let label = document.createElement('div'); + label.append(`Belly accessory: `); + + let choice = document.createElement('span'); + choice.style.fontWeight = "bold"; + choice.textContent = (`${slave.bellyAccessory} `); + label.appendChild(choice); + + // Choose her own + if (slave.bellyAccessory !== `none`) { + label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "bellyAccessory", false, refresh)); + } + + el.appendChild(label); + + // Options + let links = document.createElement('div'); + links.className = "choices"; + links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "bellyAccessory", true, refresh)); + if (slave.pregKnown === 1) { + let note = document.createElement('span'); + note.className = "note"; + note.textContent = ` Extreme corsets will endanger the life within ${him}.`; + links.appendChild(note); + } + el.appendChild(links); + + return el; + } + + function buttplug() { + if (slave.fuckdoll !== 0) { + return; + } + // App.Desc.buttplug(slave) + + let el = document.createElement('div'); + + let label = document.createElement('div'); + label.append(`Anal accessory: `); + + let choice = document.createElement('span'); + choice.style.fontWeight = "bold"; + choice.textContent = (`${slave.buttplug} `); + label.appendChild(choice); + + if (slave.buttplug !== `none`) { + let choiceOptionsArray = []; + choiceOptionsArray.push({text: `None`, updateSlave: {buttplug: `none`, buttplugAttachment: `none`}}); + label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "buttplug", false, refresh)); + } + el.appendChild(label); + + let optionsArray = []; + + let clothingOption; + App.Data.slaveWear.buttplugs.forEach(item => { + clothingOption = { + text: item.name, + updateSlave: {buttplug: item.value}, + FS: item.fs + }; + if (item.value !== "none") { + // skip none in set, we set the link elsewhere. + optionsArray.push(clothingOption); + } + }); + + // Sort + // No sort here since we want small -> large. optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); + + // Options + let links = document.createElement('div'); + links.className = "choices"; + links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "buttplug", true, refresh)); + el.appendChild(links); + + return el; + } + + function buttplugAttachment() { + let el = document.createElement('div'); + if (slave.fuckdoll !== 0 || slave.buttplug === "none") { + return el; + } + + let label = document.createElement('div'); + label.append(`Anal accessory attachment: `); + + let choice = document.createElement('span'); + choice.style.fontWeight = "bold"; + choice.textContent = (`${slave.buttplugAttachment} `); + label.appendChild(choice); + + if (slave.buttplugAttachment !== `none`) { + let choiceOptionsArray = []; + choiceOptionsArray.push({text: `None`, updateSlave: {buttplugAttachment: `none`}}); + label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "buttplugAttachment", false, refresh)); + } + el.appendChild(label); + + let optionsArray = []; + + let clothingOption; + App.Data.slaveWear.buttplugAttachments.forEach(item => { + clothingOption = { + text: item.name, + updateSlave: {buttplugAttachment: item.value}, + FS: item.fs + }; + if (item.value !== "none") { + // skip none in set, we set the link elsewhere. + optionsArray.push(clothingOption); + } + }); + + // Sort + optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); + + // Options + let links = document.createElement('div'); + links.className = "choices"; + links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "buttplugAttachment", true, refresh)); + el.appendChild(links); + + return el; + } + + function vaginalAccessory() { + if (slave.fuckdoll !== 0) { + return; + } + + // <<vaginalAccessoryDescription>> + + let el = document.createElement('div'); + + let label = document.createElement('div'); + label.append(`Vaginal accessory: `); + + let choice = document.createElement('span'); + choice.style.fontWeight = "bold"; + choice.textContent = (`${slave.vaginalAccessory} `); + label.appendChild(choice); + + if (slave.vaginalAccessory !== `none`) { + let choiceOptionsArray = []; + choiceOptionsArray.push({text: `None`, updateSlave: {vaginalAccessory: `none`}}); + label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "vaginalAccessory", false, refresh)); + } + el.appendChild(label); + + let optionsArray = []; + + let clothingOption; + App.Data.slaveWear.vaginalAccessories.forEach(item => { + clothingOption = { + text: item.name, + updateSlave: {vaginalAccessory: item.value}, + FS: item.fs + }; + if (item.value !== "none") { + // skip none in set, we set the link elsewhere. + optionsArray.push(clothingOption); + } + }); + + // Sort + // No sort here since we want small -> large. optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); + + // Options + let links = document.createElement('div'); + links.className = "choices"; + links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "vaginalAccessory", true, refresh)); + el.appendChild(links); + + return el; + } + + function vaginalAttachment() { + let el = document.createElement('div'); + if (slave.fuckdoll !== 0 || (["none", "bullet vibrator", "smart bullet vibrator"].includes(slave.vaginalAccessory))) { + return el; + } + + let label = document.createElement('div'); + label.append(`Vaginal accessory attachment: `); + + let choice = document.createElement('span'); + choice.style.fontWeight = "bold"; + choice.textContent = (`${slave.vaginalAttachment} `); + label.appendChild(choice); + + if (slave.vaginalAttachment !== `none`) { + let choiceOptionsArray = []; + choiceOptionsArray.push({text: `None`, updateSlave: {vaginalAttachment: `none`}}); + label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "vaginalAttachment", false, refresh)); + } + el.appendChild(label); + + let optionsArray = []; + + let clothingOption; + App.Data.slaveWear.vaginalAttachments.forEach(item => { + clothingOption = { + text: item.name, + updateSlave: {vaginalAttachment: item.value}, + FS: item.fs + }; + if (item.value !== "none") { + // skip none in set, we set the link elsewhere. + optionsArray.push(clothingOption); + } + }); + + // Sort + optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); + + // Options + let links = document.createElement('div'); + links.className = "choices"; + links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "vaginalAttachment", true, refresh)); + el.appendChild(links); + + return el; + } + + function dickAccessory() { + if (slave.fuckdoll !== 0) { + return; + } + // <<= App.Desc.dickAccessory($activeSlave)>> + let el = document.createElement('div'); + + let label = document.createElement('div'); + label.append(`Dick accessory: `); + + let choice = document.createElement('span'); + choice.style.fontWeight = "bold"; + choice.textContent = (`${slave.dickAccessory} `); + label.appendChild(choice); + + if (slave.dickAccessory !== `none`) { + let choiceOptionsArray = []; + choiceOptionsArray.push({text: `None`, updateSlave: {dickAccessory: `none`}}); + label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "dickAccessory", false, refresh)); + } + el.appendChild(label); + + let optionsArray = []; + + let clothingOption; + App.Data.slaveWear.dickAccessories.forEach(item => { + clothingOption = { + text: item.name, + updateSlave: {dickAccessory: item.value}, + FS: item.fs + }; + if (item.value !== "none") { + // skip none in set, we set the link elsewhere. + optionsArray.push(clothingOption); + } + }); + + // Sort + // No sort here since we want small -> large. optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); + + // Options + let links = document.createElement('div'); + links.className = "choices"; + links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "dickAccessory", true, refresh)); + el.appendChild(links); + + return el; + } + + function chastity() { + if (slave.fuckdoll !== 0) { + return; + } + + let el = document.createElement('div'); + + let label = document.createElement('div'); + label.append(`Chastity devices: `); + + let choice = document.createElement('span'); + choice.style.fontWeight = "bold"; + if (slave.choosesOwnChastity === 1) { + choice.textContent = `choosing ${his} own chastity `; + } else if (slave.chastityAnus === 1 && slave.chastityPenis === 1 && slave.chastityVagina === 1) { + choice.textContent = `full chastity `; + } else if (slave.chastityPenis === 1 && slave.chastityVagina === 1) { + choice.textContent = `genital chastity `; + } else if (slave.chastityAnus === 1 && slave.chastityPenis === 1) { + choice.textContent = `combined chastity cage `; + } else if (slave.chastityAnus === 1 && slave.chastityVagina === 1) { + choice.textContent = `combined chastity belt `; + } else if (slave.chastityVagina === 1) { + choice.textContent = `chastity belt `; + } else if (slave.chastityPenis === 1) { + choice.textContent = `chastity cage `; + } else if (slave.chastityAnus === 1) { + choice.textContent = `anal chastity `; + } else if (slave.chastityAnus === 0 && slave.chastityPenis === 0 && slave.chastityVagina === 0) { + choice.textContent = `none `; + } else { + choice.textContent = `THERE HAS BEEN AN ERROR `; + } + label.appendChild(choice); + + if (slave.chastityAnus !== 0 || slave.chastityPenis !== 0 || slave.chastityVagina !== 0) { + let choiceOptionsArray = []; + choiceOptionsArray.push({ + text: `None`, + updateSlave: { + choosesOwnChastity: 0, + chastityAnus: 0, + chastityPenis: 0, + chastityVagina: 0 + } + }); + label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "chastity", false, refresh)); + } + el.appendChild(label); + + let optionsArray = []; + + let clothingOption; + App.Data.slaveWear.chastityDevices.forEach(item => { + clothingOption = { + text: item.name, + updateSlave: {}, + FS: item.fs + }; + Object.assign(clothingOption.updateSlave, item.updateSlave); + if (item.value !== "none") { + // skip none in set, we set the link elsewhere. + optionsArray.push(clothingOption); + } + }); + + // Sort + // skip sort for this one too. optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); + + // Options + let links = document.createElement('div'); + links.className = "choices"; + links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "chastity", true, refresh)); + el.appendChild(links); + + return el; + } + + function shopping() { + return App.UI.DOM.passageLink( + `Go shopping for more options`, + "Wardrobe" + ); + } + + /** + * @param {string} update + * @returns {Node} + */ + function colorOptions(update) { + let el = new DocumentFragment(); + let colorChoice = App.UI.DOM.colorInput( + slave[update], + v => { + slave[update] = v; + refresh(); + } + ); + el.appendChild(colorChoice); + + if (slave[update]) { + el.appendChild( + App.UI.DOM.link( + ` Reset`, + () => { + delete slave[update]; + refresh(); + }, + ) + ); + } + return el; + } + } + function refresh() { + App.Art.refreshSlaveArt(slave, 3, "art-frame"); + jQuery("#si-wardrobe").empty().append(wardrobeContent()); + } +}; diff --git a/src/interaction/siWork.js b/src/interaction/siWork.js new file mode 100644 index 0000000000000000000000000000000000000000..eef1e0ceccfa742b4eb7ab9748247c20cb41311e --- /dev/null +++ b/src/interaction/siWork.js @@ -0,0 +1,762 @@ +App.UI.SlaveInteract.work = function(slave) { + const el = document.createElement("p"); + el.id = "si-work"; + el.append(work()); + return el; + + function work() { + let el = new DocumentFragment(); + let p; + let div; + let span; + const links = []; + const { + His, He, + his, him + } = getPronouns(slave); + + function appendLink(text, whoreClass, enabled, disabledText) { + const link = {text: text}; + if (enabled) { + link.whoreClass = whoreClass; + } else { + link.disabled = disabledText; + } + links.push(link); + } + + p = document.createElement('p'); + if (slave.assignment === Job.AGENT) { + const arc = V.arcologies.find((a) => a.leaderID === slave.ID); + p.className = "scene-intro"; + p.textContent = `${He} is serving as your Agent${arc ? ` leading ${arc.name}` : ` but is not currently assigned to an arcology`}. `; + p.appendChild(App.UI.DOM.link(`Recall and reenslave ${him}`, () => { removeJob(slave, slave.assignment, false); refresh(); })); + } else if (slave.assignment === Job.AGENTPARTNER) { + const agent = getSlave(slave.relationshipTarget); + const arc = agent ? V.arcologies.find((a) => a.leaderID === agent.ID) : null; + p.className = "scene-intro"; + p.textContent = `${He} is living with your Agent ${SlaveFullName(agent)}${arc ? ` in ${arc.name}` : ``}. `; + p.appendChild(App.UI.DOM.link(`Recall ${him}`, () => { removeJob(slave, slave.assignment, false); refresh(); })); + } else { + div = document.createElement('div'); + div.id = "mini-scene"; + p.appendChild(div); + + span = document.createElement('span'); + span.id = "useSlave"; + p.appendChild(span); + p.appendChild(useSlaveDisplay()); + } + el.append(p); + + p = document.createElement('p'); + span = document.createElement('span'); + span.className = "note"; + switch (slave.assignment) { + case Job.BODYGUARD: + span.textContent = `${He} is your Bodyguard and is not available for other work`; + break; + case Job.MADAM: + span.textContent = `${He} is the Madam and is not available for other work`; + break; + case Job.DJ: + span.textContent = `${He} is the DJ and is not available for other work`; + break; + case Job.MILKMAID: + span.textContent = `${He} is the Milkmaid and is not available for other work`; + break; + case Job.FARMER: + span.textContent = `${He} is the Farmer and is not available for other work`; + break; + case Job.STEWARD: + span.textContent = `${He} is the Stewardess and is not available for other work`; + break; + case Job.HEADGIRL: + span.textContent = `${He} is your Head Girl and is not available for other work`; + break; + case Job.RECRUITER: + span.textContent = `${He} is recruiting slaves and is not available for other work`; + break; + case Job.NURSE: + span.textContent = `${He} is the Nurse and is not available for other work`; + break; + case Job.ATTENDANT: + span.textContent = `${He} is the Attendant of the spa and is not available for other work`; + break; + case Job.MATRON: + span.textContent = `${He} is the Matron of the nursery and is not available for other work`; + break; + case Job.TEACHER: + span.textContent = `${He} is the Schoolteacher and is not available for other work`; + break; + case Job.CONCUBINE: + span.textContent = `${He} is your Concubine and is not available for other work`; + break; + case Job.WARDEN: + span.textContent = `${He} is the Wardeness and is not available for other work`; + break; + default: + // CAN BE REASSIGNED + span.classList.remove("note"); + span.id = "assignmentLinks"; + span.appendChild(assignmentBlock()); + + if ((V.brothel + V.club + V.dairy + V.farmyard + V.servantsQuarters + V.masterSuite + V.spa + V.nursery + V.clinic + V.schoolroom + V.cellblock + V.arcade + V.HGSuite) > 0) { + span.append(`Transfer to: `); + span.appendChild(App.UI.jobLinks.transfersFragment(slave.ID)); + } + + div = document.createElement('div'); + div.id = "fucktoy-pref"; + div.append(fucktoyPref()); + span.appendChild(div); + } + el.append(span); + + if (slave.assignment === Job.WHORE || slave.assignment === Job.BROTHEL) { + div = document.createElement('div'); + div.textContent = `Whoring Target: `; + span = document.createElement('span'); + span.style.fontWeight = "bold"; + + span.id = "whoreClass"; + if (!slave.whoreClass) { + span.textContent = `auto`; + } else if (slave.whoreClass === 1) { + span.textContent = `the lower class`; + } else if (slave.whoreClass === 2) { + span.textContent = `the middle class`; + } else if (slave.whoreClass === 3) { + span.textContent = `the upper class`; + } else if (slave.whoreClass === 4) { + span.textContent = `millionaires`; + } else { + span.textContent = `THERE HAS BEEN AN ERROR`; + } + div.append(span); + div.append(`. `); + + div.append(App.UI.DOM.makeElement('span', `This is the highest class they are allowed to service, when eligible `, 'note')); + + appendLink(`Auto`, 0, true); + appendLink(`Lower Class`, 1, true); + appendLink(`Middle Class`, 2, true); + appendLink(`Upper Class`, 3, true); + appendLink(`Millionaires Class`, 4, true); + div.appendChild(App.UI.DOM.generateLinksStrip(links.map(generateLink))); + + el.append(div); + } + + el.append(tutorBlock()); + return el; + + function generateLink(linkDesc) { + // is it just text? + if (linkDesc.disabled) { return App.UI.DOM.disabledLink(linkDesc.text, [linkDesc.disabled]); } + // Are they already on this whoreClass? + if (linkDesc.whoreClass === slave.whoreClass) { return document.createTextNode(linkDesc.text); } + // Set up the link + const link = App.UI.DOM.link( + linkDesc.text, + () => { + slave.whoreClass = linkDesc.whoreClass; + refresh(); + }, + ); + + // add a note node if required + if (linkDesc.note) { + App.UI.DOM.appendNewElement("span", link, linkDesc.note, "note"); + } + return link; + } + + function assignmentBlock() { + let el = document.createElement('div'); + let title = document.createElement('div'); + let separator = document.createTextNode(` | `); + title.append(`Assignment: `); + + let assign = document.createElement('span'); + assign.style.fontWeight = "bold"; + if (slave.sentence) { + assign.textContent = `${slave.assignment} (${slave.sentence} weeks). `; + } else { + assign.textContent = `${slave.assignment}. `; + } + title.appendChild(assign); + if (V.assignmentRecords[slave.ID] && V.assignmentRecords[slave.ID] !== slave.assignment) { + title.append(`Previously: `); + assign = document.createElement('span'); + assign.style.fontWeight = "bold"; + assign.textContent = `${V.assignmentRecords[slave.ID]}. `; + title.appendChild(assign); + } + if (slave.assignment === Job.SUBORDINATE) { + const target = getSlave(slave.subTarget); + let linkText = ``; + if (target) { + title.appendChild(document.createTextNode(`Serving ${target.slaveName} exclusively. `)); + linkText = `Change`; + } else if (slave.subTarget === -1) { + title.appendChild(document.createTextNode(`Serving as a Stud. `)); + linkText = `Change role`; + } else { + title.appendChild(document.createTextNode(`Serving all your other slaves. `)); + linkText = `Choose a specific slave to submit to`; + } + title.appendChild(App.UI.DOM.passageLink(linkText, "Subordinate Targeting", () => { V.returnTo = "Slave Interact"; })); + title.append(separator); + } + if (slave.assignment !== Job.CHOICE) { + title.appendChild( + App.UI.DOM.link( + `Stay on this assignment for another month`, + () => { + slave.sentence += 4; + refresh(); + }, + ) + ); + } + el.appendChild(title); + + let links = document.createElement('div'); + links.className = "choices"; + links.appendChild( + App.UI.jobLinks.assignmentsFragment( + slave.ID, passage(), + (slave, assignment) => { + assignJob(slave, assignment); + } + ) + ); + el.appendChild(links); + return el; + } + + function tutorBlock() { + let el = App.UI.DOM.makeElement("div"); + let title = App.UI.DOM.appendNewElement("div", el, `Private tutoring: `); + let tutor = tutorForSlave(slave); + + if (tutor === null) { + App.UI.DOM.appendNewElement("span", title, `none.`, "bold"); + } else { + App.UI.DOM.appendNewElement("span", title, tutor + `.`, "bold"); + } + + if (tutor != null) { + App.UI.DOM.appendNewElement("span", title, ` To progress slave needs to be assigned to: "` + Job.CLASSES + `" or "` + Job.SCHOOL + `".`, "note"); + } + + let list = ["None"]; + for (const keys of Object.keys(V.slaveTutor)) { + list.push(keys); + } + const array = list.map((s) => { + if (shouldBeEnabled(slave, s)) { + return App.UI.DOM.link(s, () => setTutorForSlave(slave, s)); + } else { + let reason = ["Already being taught this skill."]; + return App.UI.DOM.disabledLink(s, reason); + } + }); + App.UI.DOM.appendNewElement("div", el, App.UI.DOM.generateLinksStrip(array)); + + function shouldBeEnabled(slave, key) { + let tutor = tutorForSlave(slave); + if (tutor === null) { + return "None"; + } + return (tutor !== key); + } + + function setTutorForSlave(slave, tutor) { + const cur = tutorForSlave(slave); + + if (tutor !== cur && cur != null) { + V.slaveTutor[cur].delete(slave.ID); + } + + if (cur !== tutor && tutor !== "None") { + V.slaveTutor[tutor].push(slave.ID); + } + refresh(); + } + + return el; + } + + function useSlaveDisplay() { + // Goal: Be able to write the entire "use her" block with only dom fragments. + let el = document.createElement('div'); + + /* + Array of objects. Each object follows the form: { + text: "Link text", + scene: "scene to include", + goto: if another passage is needed + updateSlave: update slave itself if needed, like {trust: 2}, + update: updates V., + note: if a note must appear after the link + } + */ + const sexOptions = []; + const fillFaceOptions = []; + const fillAssOptions = []; + const dairyNameCaps = capFirstChar(V.dairyName); + // if no scene, it's just text, no link. Italicize it. + + if (slave.fuckdoll === 0) { + if (slave.vagina > -1) { + if (canDoVaginal(slave)) { + sexOptions.push({text: `Fuck ${him}`, scene: `FVagina`}); + if (canDoAnal(slave)) { + sexOptions.push({text: `Use ${his} holes`, scene: `FButt`}); + } + } else { + sexOptions.push({text: `Fuck ${him}`, disabled: `Remove ${his} chastity belt if you wish to fuck ${him}`}); + } + } + if (slave.bellyPreg >= 300000) { + if (canDoVaginal(slave) || canDoAnal(slave)) { + sexOptions.push({text: `Fuck ${him} on ${his} belly`, scene: `FBellyFuck`}); + if (V.pregInventions >= 1) { + sexOptions.push({text: `Fuck ${him} in ${his} maternity swing`, scene: `FMaternitySwing`}); + sexOptions.push({text: `Fuck ${him} with the help of ${his} assistants`, scene: `FAssistedSex`}); + sexOptions.push({text: `Fuck ${him} in your goo pool`, scene: `FPoolSex`}); + } + } + } + + if (canDoAnal(slave)) { + sexOptions.push({text: `Fuck ${his} ass`, scene: `FAnus`}); + } else { + sexOptions.push({text: `Fuck ${his} ass`, disabled: `Remove ${his} chastity belt if you wish to fuck ${his} ass`}); + } + sexOptions.push({text: `Use ${his} mouth`, scene: `FLips`}); + sexOptions.push({text: `Kiss ${him}`, scene: `FKiss`}); + if (hasAnyLegs(slave)) { + sexOptions.push({text: `Have ${him} dance for you`, scene: `FDance`}); + } + + sexOptions.push({text: `Play with ${his} tits`, scene: `FBoobs`}); + + sexOptions.push({text: `Caress ${him}`, scene: `FCaress`}); + + sexOptions.push({text: `Give ${him} a hug`, scene: `FEmbrace`}); + if (V.cheatMode === 1) { + sexOptions.push({text: `Pat ${his} head`, scene: `FPat`}); + } + + sexOptions.push({text: `Grope ${his} boobs`, scene: `FondleBoobs`}); + if (slave.nipples === "fuckable" && V.PC.dick > 0) { + sexOptions.push({text: `Fuck ${his} nipples`, scene: `FNippleFuck`}); + } + if (slave.lactation > 0 && slave.boobs >= 2000 && slave.belly < 60000 && hasAnyArms(slave)) { + sexOptions.push({text: `Drink ${his} milk`, scene: `FSuckle`}); + } + + if (canDoAnal(slave)) { + sexOptions.push({text: `Grope ${his} butt`, scene: `FondleButt`}); + } + + + if (slave.vagina > -1) { + if (canDoVaginal(slave)) { + sexOptions.push({text: `Grope ${his} pussy`, scene: `FondleVagina`}); + sexOptions.push({text: `Eat ${him} out`, scene: `FLickPussy`}); + } + } + + if (slave.dick > 0) { + if (!(slave.chastityPenis)) { + sexOptions.push({text: `Grope ${his} dick`, scene: `FondleDick`}); + if (canPenetrate(slave)) { + if (V.policies.sexualOpenness === 1 || slave.toyHole === "dick") { + sexOptions.push({text: `Ride ${his} dick`, scene: `FDick`}); + } + } + } else { + sexOptions.push({text: `Use ${his} dick`, disabled: `Remove ${his} dick chastity belt if you wish to play with ${his} cock`}); + } + } + + if (hasAnyLegs(slave) && V.PC.dick > 0) { + sexOptions.push({text: `Get a footjob`, scene: `FFeet`}); + } + + if (canGetPregnant(slave) && (slave.geneticQuirks.superfetation !== 2 || V.geneticMappingUpgrade !== 0) && (slave.fuckdoll === 0) && V.seePreg !== 0) { + if (canImpreg(slave, V.PC)) { + sexOptions.push({text: `Impregnate ${him} yourself`, scene: `FPCImpreg`}); + } + if (canImpreg(slave, slave)) { + sexOptions.push({text: `Use ${his} own seed to impregnate ${him}`, scene: `FSlaveSelfImpreg`}); + } + sexOptions.push({text: `Use another slave to impregnate ${him}`, scene: `FSlaveImpreg`}); + } + if (slave.assignment !== Job.DAIRY && slave.assignment !== Job.ARCADE && slave.assignment !== Job.CELLBLOCK) { + if (V.dairyPiping === 1) { + if ((V.milkPipeline > 88 && V.milkPipeline !== 0) || V.arcologies[0].FSPastoralistLaw === 1) { + if ((slave.inflation < 3 && slave.pregKnown === 0 && slave.bellyImplant < 1500) || slave.inflation < 1) { + if (slave.inflationType === "milk" || slave.inflationType === "none") { + fillAssOptions.push({text: `Milk`, scene: `FillUpButt`, updateSlave: {inflationType: "milk", inflationMethod: 2}}); + fillFaceOptions.push({text: `Milk`, scene: `FillUpFace`, updateSlave: {inflationType: "milk", inflationMethod: 1}}); + } + } + } else { + fillAssOptions.push({text: `Milk`, disabled: `${dairyNameCaps} is not producing enough milk to pump through the pipes`}); + fillFaceOptions.push({text: `Milk`, disabled: `${dairyNameCaps} is not producing enough milk to pump through the pipes`}); + } + if ((V.cumPipeline > 88 && V.cumPipeline !== 0) || V.arcologies[0].FSPastoralistLaw === 1) { + if ((slave.inflation < 3 && slave.pregKnown === 0 && slave.bellyImplant < 1500) || slave.inflation < 1) { + if (slave.inflationType === "cum" || slave.inflationType === "none") { + fillAssOptions.push({text: `Cum`, scene: `FillUpButt`, updateSlave: {inflationType: "cum", inflationMethod: 2}}); + fillFaceOptions.push({text: `Cum`, scene: `FillUpFace`, updateSlave: {inflationType: "cum", inflationMethod: 1}}); + } + } + } else { + fillAssOptions.push({text: `Cum`, disabled: `${dairyNameCaps} is not producing enough cum to pump through the pipes`}); + fillFaceOptions.push({text: `Cum`, disabled: `${dairyNameCaps} is not producing enough cum to pump through the pipes`}); + } + } /* dairyPiping === 1 */ + if (V.boughtItem.toys.enema === 1) { + if ((slave.inflation < 3 && slave.pregKnown === 0 && slave.bellyImplant < 1500) || slave.inflation < 1) { + if (slave.inflationType === "water" || slave.inflationType === "none") { + fillAssOptions.push({text: `Water`, scene: `FillUpButt`, updateSlave: {inflationType: "water", inflationMethod: 2}}); + } + if (V.boughtItem.toys.medicalEnema === 1) { + if (slave.inflationType === "aphrodisiac" || slave.inflationType === "none") { + fillAssOptions.push({text: `Aphrodisiacs`, scene: `FillUpButt`, updateSlave: {inflationType: "aphrodisiac", inflationMethod: 2}}); + } + if (slave.inflationType === "curative" || slave.inflationType === "none") { + fillAssOptions.push({text: `Curatives`, scene: `FillUpButt`, updateSlave: {inflationType: "curative", inflationMethod: 2}}); + } + if (slave.inflationType === "tightener" || slave.inflationType === "none") { + fillAssOptions.push({text: `Rectal tighteners`, scene: `FillUpButt`, updateSlave: {inflationType: "tightener", inflationMethod: 2}}); + } + } + } /* inflation < 3 */ + } /* enema === 1 */ + if (V.wcPiping === 1) { + if ((slave.inflation < 3 && slave.pregKnown === 0 && slave.bellyImplant < 1500) || slave.inflation < 1) { + if (slave.inflationType === "urine" || slave.inflationType === "none") { + fillAssOptions.push({text: `Urine`, scene: `FillUpButt`, updateSlave: {inflationType: "urine", inflationMethod: 2}}); + } + } + } /* wcPiping === 1 */ + } /* assigned to dairy or arcade */ + if (slave.inflation === 0 && slave.bellyImplant < 1500) { + if (slave.assignment !== Job.DAIRY && slave.assignment !== Job.ARCADE && slave.assignment !== Job.CELLBLOCK) { + if (V.boughtItem.toys.buckets === 1) { + fillFaceOptions.push({text: `Two liters of slave food`, scene: `forceFeeding`, updateSlave: {inflation: 1, inflationType: "food", inflationMethod: 1}}); + if (slave.pregKnown === 0) { + fillFaceOptions.push({text: `A gallon of slave food`, scene: `forceFeeding`, updateSlave: {inflation: 2, inflationType: "food", inflationMethod: 1}}); + fillFaceOptions.push({text: `Two gallons of slave food`, scene: `forceFeeding`, updateSlave: {inflation: 3, inflationType: "food", inflationMethod: 1}}); + } + } + fillFaceOptions.push({text: `Get another slave to do it`, goto: `SlaveOnSlaveFeedingWorkAround`}); + } + } + if (canDoVaginal(slave)) { + sexOptions.push({text: `Have another slave fuck ${his} pussy`, scene: `FSlaveSlaveVag`}); + } + if (canPenetrate(slave)) { + sexOptions.push({text: `Have another slave ride ${his} cock`, scene: `FSlaveSlaveDick`}); + } else if (slave.clit >= 4) { + sexOptions.push({text: `Have another slave ride ${his} clit-dick`, scene: `FSlaveSlaveDick`}); + } + if (V.seeBestiality) { + if (V.farmyardKennels > 0 && V.activeCanine) { + sexOptions.push({text: `Have a ${V.activeCanine.species} mount ${him}`, scene: `BeastFucked`, update: {animalType: "canine"}}); + } + if (V.farmyardStables > 0 && V.activeHooved) { + sexOptions.push({text: `Let a ${V.activeHooved.species} mount ${him}`, scene: `BeastFucked`, update: {animalType: "hooved"}}); + } + if (V.farmyardCages > 0 && V.activeFeline) { + sexOptions.push({text: `Have a ${V.activeFeline.species} mount ${him}`, scene: `BeastFucked`, update: {animalType: "feline"}}); + } + } + sexOptions.push({text: `Abuse ${him}`, scene: `FAbuse`}); + if (V.seeIncest === 1) { + const availRelatives = availableRelatives(slave); + if (availRelatives.mother) { + sexOptions.push({text: `Fuck ${him} with ${his} mother`, scene: `FRelation`, update: {partner: "mother"}}); + } else if (availRelatives.motherName !== null) { + sexOptions.push({text: `${His} mother, ${availRelatives.motherName}, is unavailable`}); + } + /* + if (availRelatives.father) { + sexOptions.push({text: `Fuck ${him} with ${his} father`, scene: `FRelation`, update: {partner: "father"}}); + } else if (availRelatives.fatherName !== null) { + sexOptions.push({text: `${His} father, ${availRelatives.motherName}, is unavailable`}); + } + */ + if (slave.daughters > 0) { + if (availRelatives.daughters === 0) { + if (slave.daughters === 1) { + sexOptions.push({text: `Fuck ${him} with ${his} daughter`, disabled: `${His} ${availRelatives.oneDaughterRel} is unavailable`}); + } else { + sexOptions.push({text: `Fuck ${him} with one of ${his} daughters`, disabled: `${His} daughters are unavailable`}); + } + } else { + if (slave.daughters === 1) { + sexOptions.push({text: `Fuck ${him} with ${his} ${availRelatives.oneDaughterRel}`, scene: `FRelation`, update: {partner: "daughter"}}); + } else { + sexOptions.push({text: `Fuck ${him} with one of ${his} daughters`, scene: `FRelation`, update: {partner: "daughter"}}); + } + /* + if (availRelatives.daughters > 1) { + sexOptions.push({text: `Fuck ${him} with ${his} daughters`, scene: `FRelation`, update: {partner: "daughter"}}); + } + */ + } + } + if (slave.sisters > 0) { + if (availRelatives.sisters === 0) { + if (slave.sisters === 1) { + sexOptions.push({text: `Fuck ${him} with ${his} sister`, disabled: `${His} ${availRelatives.oneSisterRel} is unavailable`}); + } else { + sexOptions.push({text: `Fuck ${him} with one of ${his} sisters`, disabled: `${His} sisters are unavailable`}); + } + } else { + if (slave.sisters === 1) { + sexOptions.push({text: `Fuck ${him} with ${his} ${availRelatives.oneSisterRel}`, scene: `FRelation`, update: {partner: "sister"}}); + } else { + sexOptions.push({text: `Fuck ${him} with one of ${his} sisters`, scene: `FRelation`, update: {partner: "sister"}}); + } + /* + if (availRelatives.sisters > 1) { + sexOptions.push({text: `Fuck ${him} with ${his} sisters`, scene: `FRelation`, update: {partner: "sisters}}); + } + */ + } + } + } + if (slave.relationship > 0) { + const lover = getSlave(slave.relationshipTarget); + if (isSlaveAvailable(lover)) { + sexOptions.push({text: `Fuck ${him} with ${his} ${relationshipTermShort(slave)} ${SlaveFullName(lover)}`, scene: `FRelation`, update: {partner: "relationship"}}); + } else if (lover.assignment === Job.AGENT) { + if (slave.broodmother < 2) { + sexOptions.push({text: `Send ${him} to live with your agent ${SlaveFullName(lover)}`, goto: `Agent Company`, update: {subSlave: lover}}); + } else { + sexOptions.push({text: `A hyper-broodmother cannot be sent to live with your agent`}); + } + } else { + sexOptions.push({text: `${SlaveFullName(lover)} is unavailable`}); + } + } + if (slave.rivalryTarget !== 0 && hasAllLimbs(slave)) { + const rival = getSlave(slave.relationshipTarget); + if (isSlaveAvailable(rival) && hasAnyLegs(rival)) { + sexOptions.push({text: `Abuse ${his} rival with ${him}`, scene: `FRival`}); + } + } + if (slave.fetish !== "mindbroken" && (canTalk(slave) || hasAnyArms(slave))) { + sexOptions.push({text: `Ask ${him} about ${his} feelings`, scene: `FFeelings`}); + if (V.PC.dick > 0) { + sexOptions.push({text: `Make ${him} beg`, scene: `FBeg`}); + } + } + if (slave.devotion >= 100 && slave.relationship < 0 && slave.relationship > -3) { + sexOptions.push({text: `Talk to ${him} about relationships`, goto: `Matchmaking`, update: {subSlave: 0}}); + } + let ML = V.marrying.length; + if ((V.policies.mixedMarriage === 1 || V.cheatMode === 1) && slave.relationship !== 5 && slave.relationship !== -3) { + if (V.marrying.includes(slave.ID)) { + sexOptions.push({text: `Marry ${him}`, disabled: `You are already marrying ${him} this weekend`}); + } else { + if (ML < 2) { + if (V.cheatMode === 1 || ML === 0) { + sexOptions.push({text: `Marry ${him}`, goto: "FMarry"}); + } else { + sexOptions.push({text: `Marry ${him}`, disabled: `You already have a wedding planned for this weekend`}); + } + } else { + sexOptions.push({text: `Marry ${him}`, disabled: `You can only marry up to two slaves per week`}); + } + } + } + if (V.cheatMode === 1) { + sexOptions.push({text: `Check ${his} stats`, goto: `Slave Stats`}); + } + } else { + /* IS A FUCKDOLL */ + sexOptions.push({text: `Fuck ${his} face hole`, scene: `FFuckdollOral`}); + if (canDoVaginal(slave)) { + sexOptions.push({text: `Fuck ${his} front hole`, scene: `FFuckdollVaginal`}); + } + if (canGetPregnant(slave) && (slave.geneticQuirks.superfetation !== 2 || V.geneticMappingUpgrade !== 0) && V.seePreg !== 0) { + if (canImpreg(slave, V.PC)) { + sexOptions.push({text: `Put a baby in ${him}`, scene: `FFuckdollImpreg`}); + } + } + if (canDoAnal(slave)) { + sexOptions.push({text: `Fuck ${his} rear hole`, scene: `FFuckdollAnal`}); + } + } + let activeSlaveRepSacrifice = repGainSacrifice(slave, V.arcologies[0]); + if (activeSlaveRepSacrifice > 0 && V.arcologies[0].FSPaternalist === "unset" && (slave.breedingMark === 0 || V.propOutcome === 0 || V.eugenicsFullControl === 1 || V.arcologies[0].FSRestart === "unset")) { + sexOptions.push({ + text: `Sacrifice ${him} on the altar`, + goto: `Aztec Slave Sacrifice`, + note: `This will kill ${him} and gain you ${activeSlaveRepSacrifice} reputation`, + update: {sacrificeType: "life"} + }); + } + el.append(`Use ${him}: `); + el.appendChild(generateRows(sexOptions)); + if (!jQuery.isEmptyObject(fillFaceOptions)) { + let fill = document.createElement('div'); + fill.appendChild(document.createTextNode(` Fill ${his} mouth with: `)); + fill.appendChild(generateRows(fillFaceOptions)); + el.appendChild(fill); + } + if (!jQuery.isEmptyObject(fillAssOptions)) { + let fill = document.createElement('div'); + fill.appendChild(document.createTextNode(` Fill ${his} ass with: `)); + fill.appendChild(generateRows(fillAssOptions)); + el.appendChild(fill); + } + + function generateRows(sexArray) { + let row = document.createElement('span'); + for (let i = 0; i < sexArray.length; i++) { + let link; + const separator = document.createTextNode(` | `); + const keys = Object.keys(sexArray[i]); + + // Test to see if there was a problem with the key + for (let j = 0; j < keys.length; j++) { + if (!["disabled", "goto", "note", "scene", "text", "update", "updateSlave"].includes(keys[j])) { + sexArray[i].text += " ERROR, THIS SCENE WAS NOT ENTERED CORRECTLY"; + console.log("Trash found while generateRows() was running: " + keys[j] + ": " + sexArray[i][keys[j]]); + break; + } + } + // is it just text? + if (sexArray[i].disabled) { + link = App.UI.DOM.disabledLink(sexArray[i].text, [sexArray[i].disabled]); + } else { + let passage = ""; + if (sexArray[i].goto) { + passage = sexArray[i].goto; + } + + // Set up the link + link = App.UI.DOM.link( + sexArray[i].text, + () => { click(sexArray[i]); }, + [], + passage + ); + + // add a note node if required + if (sexArray[i].note) { + link.appendChild(App.UI.DOM.makeElement('span', sexArray[i].note, 'note')); + } + } + row.appendChild(link); + if (i < sexArray.length - 1) { + row.appendChild(separator); + } + } + + return row; + + function click(sexOption) { + if (sexOption.updateSlave) { + Object.assign(slave, sexOption.updateSlave); + } + if (sexOption.update) { + Object.assign(V, sexOption.update); + } + + if (sexOption.goto) { + // just play the passage, no need to refresh anything here + Engine.play(sexOption.goto); + } else if (sexOption.scene) { + // Run scene and store render results temporarily + let frag = App.UI.DOM.renderPassage(sexOption.scene); + + // Refresh (clears scene display) + App.UI.SlaveInteract.refreshAll(slave); + + // Display scene render results + $("#mini-scene").append(frag); + } else { + // just refresh + App.UI.SlaveInteract.refreshAll(slave); + } + } + } + return el; + } + + function fucktoyPref() { + const el = document.createElement('div'); + let links = []; + + function appendLink(text, toyHole, enabled, disabledText) { + const link = {text: text}; + if (enabled) { + link.toyHole = toyHole; + } else { + link.disabled = disabledText; + } + links.push(link); + } + + if ((slave.assignment === App.Data.Facilities.penthouse.jobs.fucktoy.assignment) || (slave.assignment === App.Data.Facilities.masterSuite.jobs.fucktoy.assignment) || (slave.assignment === App.Data.Facilities.masterSuite.manager.assignment)) { + App.UI.DOM.appendNewElement("span", el, "Fucktoy use preference:", "story-label"); + el.append(` `); + + const hole = App.UI.DOM.appendNewElement('span', el, `${slave.toyHole}. `); + hole.style.fontWeight = "bold"; + + appendLink('Mouth', 'mouth', true); + appendLink('Tits', 'boobs', true); + if (slave.vagina >= 0) { + appendLink('Pussy', 'pussy', slave.vagina > 0 && canDoVaginal(slave), `Take ${his} virginity before giving ${his} pussy special attention`); + } + appendLink('Ass', 'ass', (slave.anus > 0) && canDoAnal(slave), `Take ${his} anal virginity before giving ${his} ass special attention`); + if (slave.dick > 0 && canPenetrate(slave)) { + appendLink('Dick', 'dick', true); + } + appendLink('No Preference', "all her holes", true); + } + + function generateLink(linkDesc) { + // is it just text? + if (linkDesc.disabled) { return App.UI.DOM.disabledLink(linkDesc.text, [linkDesc.disabled]); } + // Are they already on this toyHole? + if (linkDesc.toyHole === slave.toyHole) { return document.createTextNode(linkDesc.text); } + // Set up the link + const link = App.UI.DOM.link( + linkDesc.text, + () => { + slave.toyHole = linkDesc.toyHole; + jQuery('#fucktoy-pref').empty().append(fucktoyPref()); + }, + ); + + // add a note node if required + if (linkDesc.note) { + App.UI.DOM.appendNewElement("span", link, linkDesc.note, "note"); + } + return link; + } + + el.appendChild(App.UI.DOM.generateLinksStrip(links.map(generateLink))); + + return el; + } + } + + function refresh() { + jQuery("#si-work").empty().append(work()); + } +}; diff --git a/src/interaction/slaveInteract.js b/src/interaction/slaveInteract.js index dd6693e4b855d8cbce267bcdd44dbd32200e7442..ea2705d4b2dac9a5208c2100b2a2c9e1c340a6a1 100644 --- a/src/interaction/slaveInteract.js +++ b/src/interaction/slaveInteract.js @@ -1,3373 +1,196 @@ -/* eslint-disable no-unused-vars */ // TODO: remove after testing - -/** Find the previous and next slaves' IDs based on the current sort order - * @param {App.Entity.SlaveState} slave - * @returns {[number, number]} - previous and next slave ID - */ -App.UI.SlaveInteract.placeInLine = function(slave) { - const useSlave = assignmentVisible(slave) ? ((s) => assignmentVisible(s)) : ((s) => slave.assignment === s.assignment); - const slaveList = V.slaves.filter(useSlave); - SlaveSort.slaves(slaveList); - const curSlaveIndex = slaveList.findIndex((s) => s.ID === slave.ID); - - let nextIndex; - if (curSlaveIndex + 1 > slaveList.length - 1) { - nextIndex = 0; // wrap around to first slave - } else { - nextIndex = curSlaveIndex + 1; - } - let prevIndex; - if (curSlaveIndex - 1 < 0) { - prevIndex = slaveList.length - 1; // wrap around to last slave - } else { - prevIndex = curSlaveIndex - 1; - } - - return [slaveList[prevIndex].ID, slaveList[nextIndex].ID]; -}; - -/** - * @param {App.Entity.SlaveState} slave - * @returns {HTMLParagraphElement} - */ -App.UI.SlaveInteract.navigation = function(slave) { - const p = document.createElement("p"); - p.classList.add("center"); - - if (V.cheatMode) { - const div = document.createElement("div"); - div.classList.add("note"); - div.append(App.UI.DOM.passageLink("Cheat Edit Slave", "MOD_Edit Slave Cheat", () => { V.cheater = 1; }), - " | ", - App.UI.DOM.passageLink("Cheat Edit Slave Alternative", "MOD_Edit Slave Cheat New", () => { V.cheater = 1; })); - p.append(div); - } - - App.UI.DOM.appendNewElement("span", p, App.UI.Hotkeys.hotkeys("prev-slave"), "hotkey"); - const prevSpan = App.UI.DOM.makeElement("span", App.UI.DOM.passageLink("Prev", "Slave Interact", - () => { V.AS = App.UI.SlaveInteract.placeInLine(slave)[0]; }), "adjacent-slave"); - prevSpan.id = "prev-slave"; - p.append(" ", prevSpan); - - const centerSpan = document.createElement("span"); - centerSpan.classList.add("interact-name"); - - App.UI.DOM.appendNewElement("span", centerSpan, slave.slaveName, "slave-name"); - - const favSpan = document.createElement("span"); - favSpan.id = "fav-span"; - favSpan.append(favLink()); - - centerSpan.append(" ", favSpan); - p.append(centerSpan); - - const nextSpan = App.UI.DOM.makeElement("span", App.UI.DOM.passageLink("Next", "Slave Interact", - () => { V.AS = App.UI.SlaveInteract.placeInLine(slave)[1]; }), "adjacent-slave"); - nextSpan.id = "next-slave"; - p.append(nextSpan, " "); - App.UI.DOM.appendNewElement("span", p, App.UI.Hotkeys.hotkeys("next-slave"), "hotkey"); - - return p; - - function favLink() { - if (V.favorites.includes(slave.ID)) { - const link = App.UI.DOM.link(String.fromCharCode(0xe800), () => { - V.favorites.delete(slave.ID); - App.UI.DOM.replace("#fav-span", favLink()); - }); - link.classList.add("icons", "favorite"); - return link; - } else { - const link = App.UI.DOM.link(String.fromCharCode(0xe801), () => { - V.favorites.push(slave.ID); - App.UI.DOM.replace("#fav-span", favLink()); - }); - link.classList.add("icons", "not-favorite"); - return link; +App.UI.SlaveInteract.mainPage = function(slave) { + const el = new DocumentFragment(); + App.UI.tabBar.handlePreSelectedTab(V.tabChoice.SlaveInteract); + + if (!assignmentVisible(slave)) { + switch (slave.assignment) { + case "work in the brothel": + case "be the Madam": + V.nextLink = "Brothel"; + break; + case "be confined in the arcade": + V.nextLink = "Arcade"; + break; + case "serve in the club": + case "be the DJ": + V.nextLink = "Club"; + break; + case "work in the dairy": + case "be the Milkmaid": + V.nextLink = "Dairy"; + break; + case "work as a farmhand": + case "be the Farmer": + V.nextLink = "Farmyard"; + break; + case "rest in the spa": + case "be the Attendant": + V.nextLink = "Spa"; + break; + case "work as a nanny": + case "be the Matron": + V.nextLink = "Nursery"; + break; + case "learn in the schoolroom": + case "be the Schoolteacher": + V.nextLink = "Schoolroom"; + break; + case "work as a servant": + case "be the Stewardess": + V.nextLink = "Servants' Quarters"; + break; + case "serve in the master suite": + case "be your Concubine": + V.nextLink = "Master Suite"; + break; + case "be confined in the cellblock": + case "be the Wardeness": + V.nextLink = "Cellblock"; + break; + case "get treatment in the clinic": + case "be the Nurse": + V.nextLink = "Clinic"; + break; + case "live with your Head Girl": + V.nextLink = "Head Girl Suite"; + break; + case "be your agent": + case "live with your agent": + V.nextLink = "Neighbor Interact"; } } -}; - -/** - * @param {App.Entity.SlaveState} slave - * @returns {Node} - */ -App.UI.SlaveInteract.modify = function(slave) { - const {he, his} = getPronouns(slave); - let el = new DocumentFragment(); - - const isAgent = [Job.AGENT, Job.AGENTPARTNER].includes(slave.assignment); - - App.UI.DOM.appendNewElement('p', el, isAgent ? "Recall your agent to modify them." : "Take slave to another room.", "scene-intro"); - if (isAgent) { - return el; + V.encyclopedia = either("Costs Summary", "Disease in the Free Cities", "Drugs and Their Effects", "From Rebellious to Devoted", "Gender", "Independent Slaves", "Modern Anal", "Nymphomania", "Slave Couture"); + if (slave.dick > 0) { + V.encyclopedia = "Gender"; } + App.Utils.scheduleSidebarRefresh(); /** - * Create a link with a note to send a slave to a specific room - * @param {Node} c - * @param {string} caption - * @param {string} passage - * @param {string} note - * @param {function ():void} [handler] + * @typedef {Object} siCategory + * @property {string} title + * @property {string} id + * @property {Node} node + * @property {Function} [onClick] */ - function makeRoomLink(c, caption, passage, note, handler = () => {}) { - const res = document.createElement('div'); - c.appendChild(res); - res.appendChild(App.UI.DOM.link(caption, handler, [], passage)); - App.UI.DOM.appendNewElement('span', res, note, "note"); - return res; - } - makeRoomLink(el, "Auto salon", "Salon", ' Modify hair (color, length, style), nails, and even skin color.'); - - makeRoomLink(el, "Body mod studio", "Body Modification", ' Mark your slave with piercings, tattoos, brands or even scars.', - () => { - V.degradation = 0; - V.tattooChoice = undefined; + /** @type {Array<siCategory>} */ + const buttons = [ + { + title: "Description", + id: "description", + get node() { return App.UI.SlaveInteract.description(slave); } }, - ); - - makeRoomLink(el, "Remote surgery", "Remote Surgery", ` Surgically modify your slave with state of the art plastic surgery and more. Alter ${his} senses, skeletal structure, organs, and even more.`); - - // Prosthetics - if (V.prostheticsUpgrade > 0) { - makeRoomLink(el, "Configure cybernetics", "Prosthetics Configuration", ` Configure prosthetics, if ${he} has been surgically implanted with interfaces that support it.`, - () => { - V.prostheticsConfig = "main"; - } - ); - } - - // Analyze Pregnancy - if (V.pregnancyMonitoringUpgrade > 0) { - makeRoomLink(el, "Internal scan", "Analyze Pregnancy", ` Full scan of abdomen and reproductive organs.`); - } - - return el; -}; - -/** - * @param {App.Entity.SlaveState} slave - * @returns {HTMLElement} - */ -App.UI.SlaveInteract.fucktoyPref = function(slave) { - const {his} = getPronouns(slave); - const el = document.createElement('div'); - let links = []; - - function appendLink(text, toyHole, enabled, disabledText) { - const link = {text: text}; - if (enabled) { - link.toyHole = toyHole; - } else { - link.disabled = disabledText; - } - links.push(link); - } - - if ((slave.assignment === App.Data.Facilities.penthouse.jobs.fucktoy.assignment) || (slave.assignment === App.Data.Facilities.masterSuite.jobs.fucktoy.assignment) || (slave.assignment === App.Data.Facilities.masterSuite.manager.assignment)) { - App.UI.DOM.appendNewElement("span", el, "Fucktoy use preference:", "story-label"); - el.append(` `); - - const hole = App.UI.DOM.appendNewElement('span', el, `${slave.toyHole}. `); - hole.style.fontWeight = "bold"; - - appendLink('Mouth', 'mouth', true); - appendLink('Tits', 'boobs', true); - if (slave.vagina >= 0) { - appendLink('Pussy', 'pussy', slave.vagina > 0 && canDoVaginal(slave), `Take ${his} virginity before giving ${his} pussy special attention`); - } - appendLink('Ass', 'ass', (slave.anus > 0) && canDoAnal(slave), `Take ${his} anal virginity before giving ${his} ass special attention`); - if (slave.dick > 0 && canPenetrate(slave)) { - appendLink('Dick', 'dick', true); - } - appendLink('No Preference', "all her holes", true); - } - - function generateLink(linkDesc) { - // is it just text? - if (linkDesc.disabled) { return App.UI.DOM.disabledLink(linkDesc.text, [linkDesc.disabled]); } - // Are they already on this toyHole? - if (linkDesc.toyHole === slave.toyHole) { return document.createTextNode(linkDesc.text); } - // Set up the link - const link = App.UI.DOM.link( - linkDesc.text, - () => { - slave.toyHole = linkDesc.toyHole; - jQuery('#fucktoy-pref').empty().append(App.UI.SlaveInteract.fucktoyPref(slave)); - }, - ); - - // add a note node if required - if (linkDesc.note) { - App.UI.DOM.appendNewElement("span", link, linkDesc.note, "note"); - } - return link; - } - - el.appendChild(App.UI.DOM.generateLinksStrip(links.map(generateLink))); - - return el; -}; - -/** - * @param {App.Entity.SlaveState} slave - * @returns {JQuery<HTMLElement>} - */ -App.UI.SlaveInteract.work = function(slave) { - let el = new DocumentFragment(); - let p; - let div; - let span; - const links = []; - const { - He, - him - } = getPronouns(slave); - - function appendLink(text, whoreClass, enabled, disabledText) { - const link = {text: text}; - if (enabled) { - link.whoreClass = whoreClass; - } else { - link.disabled = disabledText; - } - links.push(link); - } - - p = document.createElement('p'); - if (slave.assignment === Job.AGENT) { - const arc = V.arcologies.find((a) => a.leaderID === slave.ID); - p.className = "scene-intro"; - p.textContent = `${He} is serving as your Agent${arc ? ` leading ${arc.name}` : ` but is not currently assigned to an arcology`}. `; - p.appendChild(App.UI.DOM.link(`Recall and reenslave ${him}`, () => { removeJob(slave, slave.assignment, false); App.UI.SlaveInteract.work(slave); })); - } else if (slave.assignment === Job.AGENTPARTNER) { - const agent = getSlave(slave.relationshipTarget); - const arc = agent ? V.arcologies.find((a) => a.leaderID === agent.ID) : null; - p.className = "scene-intro"; - p.textContent = `${He} is living with your Agent ${SlaveFullName(agent)}${arc ? ` in ${arc.name}` : ``}. `; - p.appendChild(App.UI.DOM.link(`Recall ${him}`, () => { removeJob(slave, slave.assignment, false); App.UI.SlaveInteract.work(slave); })); - } else { - div = document.createElement('div'); - div.id = "mini-scene"; - p.appendChild(div); - - span = document.createElement('span'); - span.id = "useSlave"; - p.appendChild(span); - p.appendChild(App.UI.SlaveInteract.useSlaveDisplay(slave)); - } - el.append(p); - - p = document.createElement('p'); - span = document.createElement('span'); - span.className = "note"; - switch (slave.assignment) { - case Job.BODYGUARD: - span.textContent = `${He} is your Bodyguard and is not available for other work`; - break; - case Job.MADAM: - span.textContent = `${He} is the Madam and is not available for other work`; - break; - case Job.DJ: - span.textContent = `${He} is the DJ and is not available for other work`; - break; - case Job.MILKMAID: - span.textContent = `${He} is the Milkmaid and is not available for other work`; - break; - case Job.FARMER: - span.textContent = `${He} is the Farmer and is not available for other work`; - break; - case Job.STEWARD: - span.textContent = `${He} is the Stewardess and is not available for other work`; - break; - case Job.HEADGIRL: - span.textContent = `${He} is your Head Girl and is not available for other work`; - break; - case Job.RECRUITER: - span.textContent = `${He} is recruiting slaves and is not available for other work`; - break; - case Job.NURSE: - span.textContent = `${He} is the Nurse and is not available for other work`; - break; - case Job.ATTENDANT: - span.textContent = `${He} is the Attendant of the spa and is not available for other work`; - break; - case Job.MATRON: - span.textContent = `${He} is the Matron of the nursery and is not available for other work`; - break; - case Job.TEACHER: - span.textContent = `${He} is the Schoolteacher and is not available for other work`; - break; - case Job.CONCUBINE: - span.textContent = `${He} is your Concubine and is not available for other work`; - break; - case Job.WARDEN: - span.textContent = `${He} is the Wardeness and is not available for other work`; - break; - default: - // CAN BE REASSIGNED - span.classList.remove("note"); - span.id = "assignmentLinks"; - span.appendChild(App.UI.SlaveInteract.assignmentBlock(slave)); - - if ((V.brothel + V.club + V.dairy + V.farmyard + V.servantsQuarters + V.masterSuite + V.spa + V.nursery + V.clinic + V.schoolroom + V.cellblock + V.arcade + V.HGSuite) > 0) { - span.append(`Transfer to: `); - span.appendChild(App.UI.jobLinks.transfersFragment(slave.ID)); - } - - div = document.createElement('div'); - div.id = "fucktoy-pref"; - div.append(App.UI.SlaveInteract.fucktoyPref(slave)); - span.appendChild(div); - } - el.append(span); - - if (slave.assignment === Job.WHORE || slave.assignment === Job.BROTHEL) { - div = document.createElement('div'); - div.textContent = `Whoring Target: `; - span = document.createElement('span'); - span.style.fontWeight = "bold"; - - span.id = "whoreClass"; - if (!slave.whoreClass) { - span.textContent = `auto`; - } else if (slave.whoreClass === 1) { - span.textContent = `the lower class`; - } else if (slave.whoreClass === 2) { - span.textContent = `the middle class`; - } else if (slave.whoreClass === 3) { - span.textContent = `the upper class`; - } else if (slave.whoreClass === 4) { - span.textContent = `millionaires`; - } else { - span.textContent = `THERE HAS BEEN AN ERROR`; - } - div.append(span); - div.append(`. `); - - div.append(App.UI.DOM.makeElement('span', `This is the highest class they are allowed to service, when eligible `, 'note')); - - appendLink(`Auto`, 0, true); - appendLink(`Lower Class`, 1, true); - appendLink(`Middle Class`, 2, true); - appendLink(`Upper Class`, 3, true); - appendLink(`Millionaires Class`, 4, true); - div.appendChild(App.UI.DOM.generateLinksStrip(links.map(generateLink))); - - el.append(div); - } - - el.append(App.UI.SlaveInteract.tutorBlock(slave)); - - function generateLink(linkDesc) { - // is it just text? - if (linkDesc.disabled) { return App.UI.DOM.disabledLink(linkDesc.text, [linkDesc.disabled]); } - // Are they already on this whoreClass? - if (linkDesc.whoreClass === slave.whoreClass) { return document.createTextNode(linkDesc.text); } - // Set up the link - const link = App.UI.DOM.link( - linkDesc.text, - () => { - slave.whoreClass = linkDesc.whoreClass; - App.UI.SlaveInteract.work(slave); - }, - ); - - // add a note node if required - if (linkDesc.note) { - App.UI.DOM.appendNewElement("span", link, linkDesc.note, "note"); - } - return link; - } - - return jQuery('#work').empty().append(el); -}; - -/** - * @param {App.Entity.SlaveState} slave - * @returns {HTMLElement} - */ -App.UI.SlaveInteract.assignmentBlock = function(slave) { - let el = document.createElement('div'); - let title = document.createElement('div'); - let separator = document.createTextNode(` | `); - title.append(`Assignment: `); - - let assign = document.createElement('span'); - assign.style.fontWeight = "bold"; - if (slave.sentence) { - assign.textContent = `${slave.assignment} (${slave.sentence} weeks). `; - } else { - assign.textContent = `${slave.assignment}. `; - } - title.appendChild(assign); - if (V.assignmentRecords[slave.ID] && V.assignmentRecords[slave.ID] !== slave.assignment) { - title.append(`Previously: `); - assign = document.createElement('span'); - assign.style.fontWeight = "bold"; - assign.textContent = `${V.assignmentRecords[slave.ID]}. `; - title.appendChild(assign); - } - if (slave.assignment === Job.SUBORDINATE) { - const target = getSlave(slave.subTarget); - let linkText = ``; - if (target) { - title.appendChild(document.createTextNode(`Serving ${target.slaveName} exclusively. `)); - linkText = `Change`; - } else if (slave.subTarget === -1) { - title.appendChild(document.createTextNode(`Serving as a Stud. `)); - linkText = `Change role`; - } else { - title.appendChild(document.createTextNode(`Serving all your other slaves. `)); - linkText = `Choose a specific slave to submit to`; + { + title: "Modify", + id: "modify", + get node() { return App.UI.SlaveInteract.modify(slave); } + }, + { + title: "Work", + id: "work", + get node() { return App.UI.SlaveInteract.work(slave); } + }, + { + title: "Appearance", + id: "appearance", + get node() { return App.UI.SlaveInteract.wardrobe(slave); } + }, + { + title: "Physical Regimen", + id: "physical-regimen", + get node() { return App.UI.SlaveInteract.physicalRegimen(slave); } + }, + { + title: "Rules", + id: "rules", + get node() { return App.UI.SlaveInteract.rules(slave); } + }, + { + title: "Financial", + id: "financial", + get node() { return App.UI.SlaveInteract.financial(slave); } + }, + { + title: "Customize", + id: "customize", + get node() { return App.UI.SlaveInteract.custom(slave); } + }, + { + title: "Family", + id: "family-tab", + onClick: () => renderFamilyTree(V.slaves, slave.ID), + get node() { return App.UI.SlaveInteract.family(); } } - title.appendChild(App.UI.DOM.passageLink(linkText, "Subordinate Targeting", () => { V.returnTo = "Slave Interact"; })); - title.append(separator); - } - if (slave.assignment !== Job.CHOICE) { - title.appendChild( - App.UI.DOM.link( - `Stay on this assignment for another month`, - () => { - slave.sentence += 4; - App.UI.SlaveInteract.work(slave); - }, - ) - ); - } - el.appendChild(title); - - let links = document.createElement('div'); - links.className = "choices"; - links.appendChild( - App.UI.jobLinks.assignmentsFragment( - slave.ID, passage(), - (slave, assignment) => { - assignJob(slave, assignment); - } - ) - ); - el.appendChild(links); - return el; -}; + ]; -/** - * @param {App.Entity.SlaveState} slave - * @returns {HTMLDivElement} - */ -App.UI.SlaveInteract.tutorBlock = function(slave) { - let el = App.UI.DOM.makeElement("div"); - let title = App.UI.DOM.appendNewElement("div", el, `Private tutoring: `); - let tutor = tutorForSlave(slave); + el.append(App.UI.SlaveInteract.navigation(slave)); - if (tutor === null) { - App.UI.DOM.appendNewElement("span", title, `none.`, "bold"); + if (V.slaveInteractLongForm) { + el.append(displayWithoutTabs()); } else { - App.UI.DOM.appendNewElement("span", title, tutor + `.`, "bold"); - } - - if (tutor != null) { - App.UI.DOM.appendNewElement("span", title, ` To progress slave needs to be assigned to: "` + Job.CLASSES + `" or "` + Job.SCHOOL + `".`, "note"); - } - - let list = ["None"]; - for (const keys of Object.keys(V.slaveTutor)) { - list.push(keys); - } - const array = list.map((s) => { - if (shouldBeEnabled(slave, s)) { - return App.UI.DOM.link(s, () => setTutorForSlave(slave, s)); - } else { - let reason = ["Already being taught this skill."]; - return App.UI.DOM.disabledLink(s, reason); - } - }); - App.UI.DOM.appendNewElement("div", el, App.UI.DOM.generateLinksStrip(array)); - - function shouldBeEnabled(slave, key) { - let tutor = tutorForSlave(slave); - if (tutor === null) { - return "None"; - } - return (tutor !== key); - } - - function setTutorForSlave(slave, tutor) { - const cur = tutorForSlave(slave); - - if (tutor !== cur && cur != null) { - V.slaveTutor[cur].delete(slave.ID); - } - - if (cur !== tutor && tutor !== "None") { - V.slaveTutor[tutor].push(slave.ID); - } - App.UI.SlaveInteract.work(slave); + el.append(displayWithTabs()); } return el; -}; - -/** - * @param {App.Entity.SlaveState} slave - */ -App.UI.SlaveInteract.drugs = function(slave) { - let el = document.createElement('div'); - const drugLevelOptions = []; - const lips = []; - const breasts = []; - const nipples = []; - const butt = []; - const dick = []; - const balls = []; - const fertility = []; - const hormones = []; - const psych = []; - const misc = []; + function displayWithTabs() { + const el = new DocumentFragment(); - if (slave.drugs !== "no drugs") { - drugLevelOptions.push({text: `None`, updateSlave: {drugs: `no drugs`}}); - } - if (slave.indentureRestrictions < 2) { - // Psych - if (slave.intelligence > -100 && slave.indentureRestrictions < 1) { - psych.push({text: `Psychosuppressants`, updateSlave: {drugs: `psychosuppressants`}}); - } else if (slave.intelligence > -100) { - psych.push({text: `Psychosuppressants`, disabled: `Cannot suppress indentured slave`}); - } else if (slave.indentureRestrictions < 1) { - psych.push({text: `Psychosuppressants`, disabled: `Too stupid to suppress`}); - } else { - psych.push({text: `Psychosuppressants`, disabled: `Too stupid and indentured to suppress`}); - } - if (V.arcologies[0].FSSlaveProfessionalismResearch === 1) { - if (canImproveIntelligence(slave)) { - psych.push({text: `Psychostimulants`, updateSlave: {drugs: `psychostimulants`}}); - } else { - psych.push({text: `Psychostimulants`, disabled: `Cannot improve intelligence`}); - } - } + const tabBar = document.createElement("div"); + tabBar.classList.add("tab-bar"); + const tabContents = new DocumentFragment(); - // Breasts - if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) { - if ((slave.boobs - slave.boobsImplant - slave.boobsMilk) > 100) { - breasts.push({text: `Reducers`, updateSlave: {drugs: `breast redistributors`}}); - } else { - breasts.push({text: `Reducers`, disabled: `Boobs are too small`}); - } - } - if (slave.boobs < 50000) { - breasts.push({text: `Enhancement`, updateSlave: {drugs: `breast injections`}}); - breasts.push({text: `Intensive enhancement`, updateSlave: {drugs: `intensive breast injections`}}); - } else { - breasts.push({text: `Enhancement`, disabled: `Boobs are too large`}); - } - if (V.arcologies[0].FSAssetExpansionistResearch === 1) { - if (slave.boobs < 50000) { - breasts.push({text: `Hyper enhancement`, updateSlave: {drugs: `hyper breast injections`}}); - } else { - breasts.push({text: `Hyper enhancement`, disabled: `Boobs are too large`}); - } + for (const item of buttons) { + tabBar.append(makeTabButton(item)); + tabContents.append(makeTabContents(item)); } - // Nipples - if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) { - if (slave.nipples === "huge" || slave.nipples === "puffy" || slave.nipples === "cute") { - nipples.push({text: `Reducers`, updateSlave: {drugs: `nipple atrophiers`}}); - } else { - nipples.push({text: `Reducers`, disabled: `Nipples are ${slave.nipples}`}); - } - } - if (V.dispensary) { - if (["inverted", "partially inverted", "cute", "tiny", "puffy"].includes(slave.nipples)) { - nipples.push({text: `Enhancement`, updateSlave: {drugs: `nipple enhancers`}}); - } else if (slave.nipples === "huge") { - nipples.push({text: `Enhancement`, disabled: `Nipples are already huge`}); - } else { - nipples.push({text: `Enhancement`, disabled: `Has no effect on ${slave.nipples} nipples`}); - } - } + el.append(tabBar); - // Butt - if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) { - if (slave.butt - slave.buttImplant > 0) { - butt.push({text: `Reducers`, updateSlave: {drugs: `butt redistributors`}}); - } else { - butt.push({text: `Reducers`, disabled: `Butt is too small`}); - } - } - if (slave.butt < 9) { - butt.push({text: `Enhancement`, updateSlave: {drugs: `butt injections`}}); - butt.push({text: `Intensive enhancement`, updateSlave: {drugs: `intensive butt injections`}}); - } else { - butt.push({text: `Enhancement`, disabled: `Butt is too large`}); - } - if (V.arcologies[0].FSAssetExpansionistResearch === 1) { - if (slave.butt < 20) { - butt.push({text: `Hyper enhancement`, updateSlave: {drugs: `hyper butt injections`}}); - } else { - butt.push({text: `Hyper enhancement`, disabled: `Butt is too large`}); - } - } + App.Events.drawEventArt(el, slave); - // Lips - if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) { - if (slave.lips - slave.lipsImplant > 0) { - lips.push({text: `Reducers`, updateSlave: {drugs: `lip atrophiers`}}); - } else { - lips.push({text: `Reducers`, disabled: `Lips are too small`}); - } - } - if (slave.lips <= 95 || (slave.lips <= 85 && V.seeExtreme !== 1)) { - lips.push({text: `Enhancement`, updateSlave: {drugs: `lip injections`}}); - } else { - lips.push({text: `Enhancement`, disabled: `Lips are too large`}); - } + el.append(tabContents); - // Fertility - fertility.push({text: `Fertility`, updateSlave: {drugs: `fertility drugs`}}); - if (V.seeHyperPreg === 1 && slave.indentureRestrictions < 1 && V.superFertilityDrugs === 1 && (slave.breedingMark !== 1 || V.propOutcome === 0 || V.eugenicsFullControl === 1 || V.arcologies[0].FSRestart === "unset")) { - fertility.push({text: `Fertility+`, updateSlave: {drugs: `super fertility drugs`}}); - } + return el; - // Dick/clit - if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) { - if (slave.dick > 1) { - dick.push({text: `Reducers`, updateSlave: {drugs: `penis atrophiers`}}); - } else if (slave.dick === 1) { - dick.push({text: `Reducers`, disabled: `Dick is already at minimum size`}); - } - if (slave.clit > 0) { - dick.push({text: `Reducers`, updateSlave: {drugs: `clitoris atrophiers`}}); - } - } - if (slave.dick > 0) { - if (slave.dick < 10) { - dick.push({text: `Enhancement`, updateSlave: {drugs: `penis enhancement`}}); - dick.push({text: `Intensive enhancement`, updateSlave: {drugs: `intensive penis enhancement`}}); - } else { - dick.push({text: `Enhancement`, disabled: `Dick is too large`}); - } - } else { - if (slave.clit < 5) { - dick.push({text: `Enhancement`, updateSlave: {drugs: `penis enhancement`}}); - dick.push({text: `Intensive enhancement`, updateSlave: {drugs: `intensive penis enhancement`}}); - } else { - dick.push({text: `Enhancement`, disabled: `Clit is too large`}); - } - } - if (V.arcologies[0].FSAssetExpansionistResearch === 1) { - if (slave.dick > 0) { - if (slave.dick < 31) { - dick.push({text: `Hyper enhancement`, updateSlave: {drugs: `hyper penis enhancement`}}); - } else { - dick.push({text: `Hyper enhancement`, disabled: `Dick is too large`}); + function makeTabButton(item) { + const btn = document.createElement("button"); + btn.className = "tab-links"; + btn.id = `tab ${item.id}`; + btn.innerHTML = item.title; + btn.onclick = (event) => { + App.UI.tabBar.openTab(event, item.id); + if (item.hasOwnProperty("onClick")){ + item.onClick(); } - } else { - if (slave.clit < 5) { - dick.push({text: `Hyper enhancement`, updateSlave: {drugs: `penis enhancement`}}); - } else { - dick.push({text: `Hyper enhancement`, disabled: `Clit is too large`}); - } - } - } - if (slave.dick > 0 && slave.dick < 11 && !canAchieveErection(slave) && slave.chastityPenis !== 1) { - dick.push({text: `Erectile dysfunction circumvention`, updateSlave: {drugs: `priapism agents`}}); - } - - // Balls - if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) { - if (slave.balls > 1) { - balls.push({text: `Reducers`, updateSlave: {drugs: `testicle atrophiers`}}); - } else if (slave.balls === 1) { - balls.push({text: `Reducers`, disabled: `Balls are already at minimum size`}); - } - } - if (slave.balls > 0) { - balls.push({text: `Enhancement`, updateSlave: {drugs: `testicle enhancement`}}); - balls.push({text: `Intensive enhancement`, updateSlave: {drugs: `intensive testicle enhancement`}}); - if (V.arcologies[0].FSAssetExpansionistResearch === 1) { - balls.push({text: `Hyper enhancement`, updateSlave: {drugs: `hyper testicle enhancement`}}); - } - } - - // Hormones - if (V.precociousPuberty === 1 && V.pubertyHormones === 1 && (slave.breedingMark !== 1 || V.propOutcome === 0 || V.eugenicsFullControl === 1 || V.arcologies[0].FSRestart === "unset")) { - if ((slave.ovaries === 1 || slave.mpreg === 1) && slave.pubertyXX === 0) { - hormones.push({text: `Female injections`, updateSlave: {drugs: `female hormone injections`}}); - } - if (slave.balls > 0 && slave.pubertyXY === 0) { - hormones.push({text: `Male injections`, updateSlave: {drugs: `male hormone injections`}}); - } - } - hormones.push({text: `Blockers`, updateSlave: {drugs: `hormone blockers`}}); - hormones.push({text: `Enhancement`, updateSlave: {drugs: `hormone enhancers`}}); - - // Misc - if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) { - if (slave.labia > 0) { - misc.push({text: `Labia reducers`, updateSlave: {drugs: `labia atrophiers`}}); - } - } - if (V.growthStim === 1) { - if (canImproveHeight(slave)) { - misc.push({text: `Growth Stimulants`, updateSlave: {drugs: `growth stimulants`}}); - } else { - misc.push({text: `Growth Stimulants`, disabled: `Cannot increase height further`}); - } - } - if (V.arcologies[0].FSSlimnessEnthusiastResearch === 1) { - if (slave.weight > -95) { - misc.push({text: `Weight loss pills`, updateSlave: {drugs: `appetite suppressors`}}); - } else { - misc.push({text: `Weight loss pills`, disabled: `Slave is already at low weight`}); - } - } - misc.push({text: `Steroids`, updateSlave: {drugs: `steroids`}}); - if (slave.boobs > 250 && slave.boobShape !== "saggy" && V.purchasedSagBGone === 1) { - misc.push({text: `Sag-B-Gone breast lifting cream`, updateSlave: {drugs: `sag-B-gone`}}); - } - if (V.arcologies[0].FSYouthPreferentialistResearch === 1) { - if (slave.visualAge > 18) { - misc.push({text: `Anti-aging cream`, updateSlave: {drugs: `anti-aging cream`}}); - } else { - misc.push({text: `Anti-aging cream`, disabled: `Slave already looks young enough`}); - } - } - } - - let title = document.createElement('div'); - title.textContent = `Drugs: `; - let chosenDrug = document.createElement('span'); - chosenDrug.textContent = `${capFirstChar(slave.drugs)} `; - chosenDrug.style.fontWeight = "bold"; - title.append(chosenDrug); - title.appendChild(App.UI.SlaveInteract.generateRows(drugLevelOptions, slave)); - el.append(title); - - App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Lips", lips, slave); - App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Breasts", breasts, slave); - App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Nipples", nipples, slave); - App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Butt", butt, slave); - App.UI.SlaveInteract.appendLabeledChoiceRow(el, slave.dick > 0 ? "Dick" : "Clit", dick, slave); - App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Balls", balls, slave); - App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Fertility", fertility, slave); - App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Hormones", hormones, slave); - App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Psych", psych, slave); - App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Misc", misc, slave); - - return jQuery('#drugs').empty().append(el); -}; - -App.UI.SlaveInteract.hormones = function(slave) { - let el = document.createElement('div'); - const options = []; - const level = []; - - if (slave.hormones !== 0) { - level.push({text: `None`, updateSlave: {hormones: 0}}); - } - - if (slave.indentureRestrictions < 2) { - options.push({text: `Intensive Female`, updateSlave: {hormones: 2}}); - } else { - options.push({text: `Intensive Female`, disabled: `Cannot use intensive hormones on indentured slaves`}); - } - options.push({text: `Female`, updateSlave: {hormones: 1}}); - options.push({text: `Male`, updateSlave: {hormones: -1}}); - if (slave.indentureRestrictions < 2) { - options.push({text: `Intensive Male`, updateSlave: {hormones: -2}}); - } else { - options.push({text: `Intensive Male`, disabled: `Cannot use intensive hormones on indentured slaves`}); - } + }; - let title = document.createElement('div'); - title.textContent = `Hormones: `; - let choice = document.createElement('span'); - choice.style.fontWeight = "bold"; - switch (slave.hormones) { - case 2: { - choice.textContent = `intensive female. `; - break; + return btn; } - case 1: { - choice.textContent = `female. `; - break; - } - case 0: { - choice.textContent = `none. `; - break; - } - case -1: { - choice.textContent = `male. `; - break; - } - case -2: { - choice.textContent = `intensive male. `; - break; - } - default: { - choice.textContent = `Not set. `; - } - } - - title.append(choice); - title.appendChild(App.UI.SlaveInteract.generateRows(level, slave)); - el.append(title); - - let links = document.createElement('div'); - links.appendChild(App.UI.SlaveInteract.generateRows(options, slave)); - links.className = "choices"; - el.append(links); - - return jQuery('#hormones').empty().append(el); -}; - -App.UI.SlaveInteract.diet = function(slave) { - const { - // eslint-disable-next-line no-unused-vars - he, - him, - his, - hers, - himself, - boy, - He, - His - } = getPronouns(slave); - let el = document.createElement('div'); - - let title = document.createElement('div'); - title.textContent = `Diet: `; - let choice = document.createElement('span'); - choice.style.fontWeight = "bold"; - choice.textContent = `${capFirstChar(slave.diet)}. `; - - title.append(choice); - el.append(title); - - const health = []; - health.push({text: `Healthy`, updateSlave: {diet: "healthy"}}); - if (V.dietCleanse === 1) { - if (slave.health.condition < 90 || slave.chem >= 10) { - health.push({text: `Cleanse`, updateSlave: {diet: "cleansing"}}); - } else { - health.push({text: `Cleanse`, disabled: `${He} is already healthy`}); - } - } - - const weight = []; - if (slave.weight >= -95) { - weight.push({text: `Lose weight`, updateSlave: {diet: "restricted"}}); - } else { - weight.push({text: `Lose weight`, disabled: `${He} is already underweight`}); - } - if (slave.fuckdoll === 0 && slave.fetish !== "mindbroken" && V.feeder === 1) { - if (slave.weight > 10 || slave.weight < -10) { - weight.push({text: `Correct weight`, updateSlave: {diet: "corrective"}}); - } else { - weight.push({text: `Correct weight`, disabled: `${He} is already a healthy weight`}); - } - } - if (slave.weight <= 200) { - weight.push({text: `Fatten`, updateSlave: {diet: "fattening"}}); - } else { - weight.push({text: `Fatten`, disabled: `${He} is already overweight`}); - } - - const muscle = []; - if (slave.muscles < 100 && !isAmputee(slave)) { - muscle.push({text: `Build muscle`, updateSlave: {diet: "muscle building"}}); - } else if (!isAmputee(slave)) { - muscle.push({text: `Build muscle`, disabled: `${He} is maintaining ${his} enormous musculature`}); - } else { - muscle.push({text: `Build muscle`, disabled: `${He} has no limbs and thus can't effectively build muscle`}); - } - - if ((slave.muscles > 0 || slave.fuckdoll === 0) && canWalk(slave)) { - muscle.push({text: `Slim down`, updateSlave: {diet: "slimming"}}); - } else if (!canWalk(slave)) { - muscle.push({text: `Slim down`, disabled: `${He} can't walk and thus can't trim down`}); - } else if (slave.fuckdoll > 0) { - muscle.push({text: `Slim down`, disabled: `${He} has no muscles left to lose`}); - } - - const production = []; - if (slave.balls > 0 && V.cumProDiet === 1) { - production.push({text: `Cum production`, updateSlave: {diet: "cum production"}}); - } - if (((isFertile(slave) && slave.preg === 0) || (slave.geneticQuirks.superfetation === 2 && canGetPregnant(slave) && V.geneticMappingUpgrade !== 0)) && V.dietFertility === 1) { - production.push({text: `Fertility`, updateSlave: {diet: "fertility"}}); - } - - const hormone = []; - if (V.feeder === 1) { - hormone.push({text: `Estrogen enriched`, updateSlave: {diet: "XX"}}); - hormone.push({text: `Testosterone enriched`, updateSlave: {diet: "XY"}}); - if (V.dietXXY === 1 && slave.balls > 0 && (slave.ovaries === 1 || slave.mpreg === 1)) { - hormone.push({text: `Herm hormone blend`, updateSlave: {diet: "XXY"}}); - } - } - - App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Health", health, slave); - App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Weight", weight, slave); - App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Muscle", muscle, slave); - App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Production", production, slave); - App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Hormone", hormone, slave); - - return jQuery('#diet').empty().append(el); -}; - -App.UI.SlaveInteract.dietBase = function(slave) { - let el = document.createElement('div'); - const milk = []; - const cum = []; - - // Milk - if (slave.dietCum < 2) { - milk.push({text: `Milk added`, updateSlave: {dietMilk: 1}}); - if (slave.dietCum < 2) { - milk.push({text: `Milk based`, updateSlave: {dietMilk: 2, dietCum: 0}}); - } - if (slave.dietMilk) { - milk.push({text: `Remove milk`, updateSlave: {dietMilk: 0}}); - } - } else { - milk.push({text: `Milk`, disabled: `Diet is based entirely on cum`}); - } - - // Cum - if (slave.dietMilk < 2) { - cum.push({text: `Cum added`, updateSlave: {dietCum: 1}}); - cum.push({text: `Cum based`, updateSlave: {dietCum: 2, dietMilk: 0}}); - if (slave.dietCum) { - cum.push({text: `Remove cum`, updateSlave: {dietCum: 0}}); - } - } else { - cum.push({text: `Cum`, disabled: `Diet is based entirely on milk`}); - } - - let title = document.createElement('div'); - title.textContent = `Diet base: `; - let choice = document.createElement('span'); - choice.style.fontWeight = "bold"; - if (slave.dietCum === 2) { - choice.textContent = `cum based. `; - } else if (slave.dietCum === 1 && slave.dietMilk === 0) { - choice.textContent = `cum added. `; - } else if (slave.dietCum === 1 && slave.dietMilk === 1) { - choice.textContent = `cum and milk added. `; - } else if (slave.dietMilk === 1 && slave.dietCum === 0) { - choice.textContent = `milk added. `; - } else if (slave.dietMilk === 2) { - choice.textContent = `milk based. `; - } else if (slave.dietCum === 0 && slave.dietMilk === 0) { - choice.textContent = `normal. `; - } else { - choice.textContent = `THERE HAS BEEN AN ERROR.`; } - title.append(choice); - el.append(title); - - App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Milk", milk, slave); - App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Cum", cum, slave); - - return jQuery('#diet-base').empty().append(el); -}; - -App.UI.SlaveInteract.snacks = function(slave) { - const { - // eslint-disable-next-line no-unused-vars - he, - him, - his, - hers, - himself, - boy, - He, - His - } = getPronouns(slave); - let el = document.createElement('div'); - let options = []; - - if (V.arcologies[0].FSHedonisticDecadenceResearch === 1) { - let title = document.createElement('div'); - title.textContent = `Solid Slave Food Access: `; - let choice = document.createElement('span'); - choice.style.fontWeight = "bold"; - if (slave.onDiet === 0) { - choice.textContent = `Free to stuff ${himself}.`; - } else { - choice.textContent = `On a strict diet.`; + function displayWithoutTabs() { + const el = new DocumentFragment(); + App.Events.drawEventArt(el, slave); + for (const item of buttons) { + App.UI.DOM.appendNewElement("h2", el, item.title); + el.append(item.node); + if (item.hasOwnProperty("onClick")){ + item.onClick(); + } } - title.append(choice); - el.append(title); - - options.push({text: `No access`, updateSlave: {onDiet: 1}}); - options.push({text: `Full access`, updateSlave: {onDiet: 0}}); - - let links = document.createElement('div'); - links.appendChild(App.UI.SlaveInteract.generateRows(options, slave)); - links.className = "choices"; - el.append(links); + return el; } + function makeTabContents(item) { + const wrapperEl = document.createElement("div"); + wrapperEl.id = item.id; + wrapperEl.classList.add("tab-content"); - return jQuery('#snacks').empty().append(el); -}; - -App.UI.SlaveInteract.useSlaveDisplay = function(slave) { - // Goal: Be able to write the entire "use her" block with only dom fragments. - let el = document.createElement('div'); - - const { - // eslint-disable-next-line no-unused-vars - he, - him, - his, - hers, - himself, - boy, - He, - His - } = getPronouns(slave); - - /* - Array of objects. Each object follows the form: { - text: "Link text", - scene: "scene to include", - goto: if another passage is needed - updateSlave: update slave itself if needed, like {trust: 2}, - update: updates V., - note: if a note must appear after the link + const classEl = document.createElement("div"); + classEl.classList.add("content"); + classEl.append(item.node); + wrapperEl.append(classEl); + return wrapperEl; } - */ - const sexOptions = []; - const fillFaceOptions = []; - const fillAssOptions = []; - const dairyNameCaps = capFirstChar(V.dairyName); - // if no scene, it's just text, no link. Italicize it. - - if (slave.fuckdoll === 0) { - if (slave.vagina > -1) { - if (canDoVaginal(slave)) { - sexOptions.push({text: `Fuck ${him}`, scene: `FVagina`}); - if (canDoAnal(slave)) { - sexOptions.push({text: `Use ${his} holes`, scene: `FButt`}); - } - } else { - sexOptions.push({text: `Fuck ${him}`, disabled: `Remove ${his} chastity belt if you wish to fuck ${him}`}); - } - } - if (slave.bellyPreg >= 300000) { - if (canDoVaginal(slave) || canDoAnal(slave)) { - sexOptions.push({text: `Fuck ${him} on ${his} belly`, scene: `FBellyFuck`}); - if (V.pregInventions >= 1) { - sexOptions.push({text: `Fuck ${him} in ${his} maternity swing`, scene: `FMaternitySwing`}); - sexOptions.push({text: `Fuck ${him} with the help of ${his} assistants`, scene: `FAssistedSex`}); - sexOptions.push({text: `Fuck ${him} in your goo pool`, scene: `FPoolSex`}); - } - } - } - - if (canDoAnal(slave)) { - sexOptions.push({text: `Fuck ${his} ass`, scene: `FAnus`}); - } else { - sexOptions.push({text: `Fuck ${his} ass`, disabled: `Remove ${his} chastity belt if you wish to fuck ${his} ass`}); - } - sexOptions.push({text: `Use ${his} mouth`, scene: `FLips`}); - sexOptions.push({text: `Kiss ${him}`, scene: `FKiss`}); - if (hasAnyLegs(slave)) { - sexOptions.push({text: `Have ${him} dance for you`, scene: `FDance`}); - } - - sexOptions.push({text: `Play with ${his} tits`, scene: `FBoobs`}); - - sexOptions.push({text: `Caress ${him}`, scene: `FCaress`}); - - sexOptions.push({text: `Give ${him} a hug`, scene: `FEmbrace`}); - if (V.cheatMode === 1) { - sexOptions.push({text: `Pat ${his} head`, scene: `FPat`}); - } - - sexOptions.push({text: `Grope ${his} boobs`, scene: `FondleBoobs`}); - if (slave.nipples === "fuckable" && V.PC.dick > 0) { - sexOptions.push({text: `Fuck ${his} nipples`, scene: `FNippleFuck`}); - } - if (slave.lactation > 0 && slave.boobs >= 2000 && slave.belly < 60000 && hasAnyArms(slave)) { - sexOptions.push({text: `Drink ${his} milk`, scene: `FSuckle`}); - } - - if (canDoAnal(slave)) { - sexOptions.push({text: `Grope ${his} butt`, scene: `FondleButt`}); - } - - - if (slave.vagina > -1) { - if (canDoVaginal(slave)) { - sexOptions.push({text: `Grope ${his} pussy`, scene: `FondleVagina`}); - sexOptions.push({text: `Eat ${him} out`, scene: `FLickPussy`}); - } - } - - if (slave.dick > 0) { - if (!(slave.chastityPenis)) { - sexOptions.push({text: `Grope ${his} dick`, scene: `FondleDick`}); - if (canPenetrate(slave)) { - if (V.policies.sexualOpenness === 1 || slave.toyHole === "dick") { - sexOptions.push({text: `Ride ${his} dick`, scene: `FDick`}); - } - } - } else { - sexOptions.push({text: `Use ${his} dick`, disabled: `Remove ${his} dick chastity belt if you wish to play with ${his} cock`}); - } - } - - if (hasAnyLegs(slave) && V.PC.dick > 0) { - sexOptions.push({text: `Get a footjob`, scene: `FFeet`}); - } - - if (canGetPregnant(slave) && (slave.geneticQuirks.superfetation !== 2 || V.geneticMappingUpgrade !== 0) && (slave.fuckdoll === 0) && V.seePreg !== 0) { - if (canImpreg(slave, V.PC)) { - sexOptions.push({text: `Impregnate ${him} yourself`, scene: `FPCImpreg`}); - } - if (canImpreg(slave, slave)) { - sexOptions.push({text: `Use ${his} own seed to impregnate ${him}`, scene: `FSlaveSelfImpreg`}); - } - sexOptions.push({text: `Use another slave to impregnate ${him}`, scene: `FSlaveImpreg`}); - } - if (slave.assignment !== Job.DAIRY && slave.assignment !== Job.ARCADE && slave.assignment !== Job.CELLBLOCK) { - if (V.dairyPiping === 1) { - if ((V.milkPipeline > 88 && V.milkPipeline !== 0) || V.arcologies[0].FSPastoralistLaw === 1) { - if ((slave.inflation < 3 && slave.pregKnown === 0 && slave.bellyImplant < 1500) || slave.inflation < 1) { - if (slave.inflationType === "milk" || slave.inflationType === "none") { - fillAssOptions.push({text: `Milk`, scene: `FillUpButt`, updateSlave: {inflationType: "milk", inflationMethod: 2}}); - fillFaceOptions.push({text: `Milk`, scene: `FillUpFace`, updateSlave: {inflationType: "milk", inflationMethod: 1}}); - } - } - } else { - fillAssOptions.push({text: `Milk`, disabled: `${dairyNameCaps} is not producing enough milk to pump through the pipes`}); - fillFaceOptions.push({text: `Milk`, disabled: `${dairyNameCaps} is not producing enough milk to pump through the pipes`}); - } - if ((V.cumPipeline > 88 && V.cumPipeline !== 0) || V.arcologies[0].FSPastoralistLaw === 1) { - if ((slave.inflation < 3 && slave.pregKnown === 0 && slave.bellyImplant < 1500) || slave.inflation < 1) { - if (slave.inflationType === "cum" || slave.inflationType === "none") { - fillAssOptions.push({text: `Cum`, scene: `FillUpButt`, updateSlave: {inflationType: "cum", inflationMethod: 2}}); - fillFaceOptions.push({text: `Cum`, scene: `FillUpFace`, updateSlave: {inflationType: "cum", inflationMethod: 1}}); - } - } - } else { - fillAssOptions.push({text: `Cum`, disabled: `${dairyNameCaps} is not producing enough cum to pump through the pipes`}); - fillFaceOptions.push({text: `Cum`, disabled: `${dairyNameCaps} is not producing enough cum to pump through the pipes`}); - } - } /* dairyPiping === 1 */ - if (V.boughtItem.toys.enema === 1) { - if ((slave.inflation < 3 && slave.pregKnown === 0 && slave.bellyImplant < 1500) || slave.inflation < 1) { - if (slave.inflationType === "water" || slave.inflationType === "none") { - fillAssOptions.push({text: `Water`, scene: `FillUpButt`, updateSlave: {inflationType: "water", inflationMethod: 2}}); - } - if (V.boughtItem.toys.medicalEnema === 1) { - if (slave.inflationType === "aphrodisiac" || slave.inflationType === "none") { - fillAssOptions.push({text: `Aphrodisiacs`, scene: `FillUpButt`, updateSlave: {inflationType: "aphrodisiac", inflationMethod: 2}}); - } - if (slave.inflationType === "curative" || slave.inflationType === "none") { - fillAssOptions.push({text: `Curatives`, scene: `FillUpButt`, updateSlave: {inflationType: "curative", inflationMethod: 2}}); - } - if (slave.inflationType === "tightener" || slave.inflationType === "none") { - fillAssOptions.push({text: `Rectal tighteners`, scene: `FillUpButt`, updateSlave: {inflationType: "tightener", inflationMethod: 2}}); - } - } - } /* inflation < 3 */ - } /* enema === 1 */ - if (V.wcPiping === 1) { - if ((slave.inflation < 3 && slave.pregKnown === 0 && slave.bellyImplant < 1500) || slave.inflation < 1) { - if (slave.inflationType === "urine" || slave.inflationType === "none") { - fillAssOptions.push({text: `Urine`, scene: `FillUpButt`, updateSlave: {inflationType: "urine", inflationMethod: 2}}); - } - } - } /* wcPiping === 1 */ - } /* assigned to dairy or arcade */ - if (slave.inflation === 0 && slave.bellyImplant < 1500) { - if (slave.assignment !== Job.DAIRY && slave.assignment !== Job.ARCADE && slave.assignment !== Job.CELLBLOCK) { - if (V.boughtItem.toys.buckets === 1) { - fillFaceOptions.push({text: `Two liters of slave food`, scene: `forceFeeding`, updateSlave: {inflation: 1, inflationType: "food", inflationMethod: 1}}); - if (slave.pregKnown === 0) { - fillFaceOptions.push({text: `A gallon of slave food`, scene: `forceFeeding`, updateSlave: {inflation: 2, inflationType: "food", inflationMethod: 1}}); - fillFaceOptions.push({text: `Two gallons of slave food`, scene: `forceFeeding`, updateSlave: {inflation: 3, inflationType: "food", inflationMethod: 1}}); - } - } - fillFaceOptions.push({text: `Get another slave to do it`, goto: `SlaveOnSlaveFeedingWorkAround`}); - } - } - if (canDoVaginal(slave)) { - sexOptions.push({text: `Have another slave fuck ${his} pussy`, scene: `FSlaveSlaveVag`}); - } - if (canPenetrate(slave)) { - sexOptions.push({text: `Have another slave ride ${his} cock`, scene: `FSlaveSlaveDick`}); - } else if (slave.clit >= 4) { - sexOptions.push({text: `Have another slave ride ${his} clit-dick`, scene: `FSlaveSlaveDick`}); - } - if (V.seeBestiality) { - if (V.farmyardKennels > 0 && V.activeCanine) { - sexOptions.push({text: `Have a ${V.activeCanine.species} mount ${him}`, scene: `BeastFucked`, update: {animalType: "canine"}}); - } - if (V.farmyardStables > 0 && V.activeHooved) { - sexOptions.push({text: `Let a ${V.activeHooved.species} mount ${him}`, scene: `BeastFucked`, update: {animalType: "hooved"}}); - } - if (V.farmyardCages > 0 && V.activeFeline) { - sexOptions.push({text: `Have a ${V.activeFeline.species} mount ${him}`, scene: `BeastFucked`, update: {animalType: "feline"}}); - } - } - sexOptions.push({text: `Abuse ${him}`, scene: `FAbuse`}); - if (V.seeIncest === 1) { - const availRelatives = availableRelatives(slave); - if (availRelatives.mother) { - sexOptions.push({text: `Fuck ${him} with ${his} mother`, scene: `FRelation`, update: {partner: "mother"}}); - } else if (availRelatives.motherName !== null) { - sexOptions.push({text: `${His} mother, ${availRelatives.motherName}, is unavailable`}); - } - /* - if (availRelatives.father) { - sexOptions.push({text: `Fuck ${him} with ${his} father`, scene: `FRelation`, update: {partner: "father"}}); - } else if (availRelatives.fatherName !== null) { - sexOptions.push({text: `${His} father, ${availRelatives.motherName}, is unavailable`}); - } - */ - if (slave.daughters > 0) { - if (availRelatives.daughters === 0) { - if (slave.daughters === 1) { - sexOptions.push({text: `Fuck ${him} with ${his} daughter`, disabled: `${His} ${availRelatives.oneDaughterRel} is unavailable`}); - } else { - sexOptions.push({text: `Fuck ${him} with one of ${his} daughters`, disabled: `${His} daughters are unavailable`}); - } - } else { - if (slave.daughters === 1) { - sexOptions.push({text: `Fuck ${him} with ${his} ${availRelatives.oneDaughterRel}`, scene: `FRelation`, update: {partner: "daughter"}}); - } else { - sexOptions.push({text: `Fuck ${him} with one of ${his} daughters`, scene: `FRelation`, update: {partner: "daughter"}}); - } - /* - if (availRelatives.daughters > 1) { - sexOptions.push({text: `Fuck ${him} with ${his} daughters`, scene: `FRelation`, update: {partner: "daughter"}}); - } - */ - } - } - if (slave.sisters > 0) { - if (availRelatives.sisters === 0) { - if (slave.sisters === 1) { - sexOptions.push({text: `Fuck ${him} with ${his} sister`, disabled: `${His} ${availRelatives.oneSisterRel} is unavailable`}); - } else { - sexOptions.push({text: `Fuck ${him} with one of ${his} sisters`, disabled: `${His} sisters are unavailable`}); - } - } else { - if (slave.sisters === 1) { - sexOptions.push({text: `Fuck ${him} with ${his} ${availRelatives.oneSisterRel}`, scene: `FRelation`, update: {partner: "sister"}}); - } else { - sexOptions.push({text: `Fuck ${him} with one of ${his} sisters`, scene: `FRelation`, update: {partner: "sister"}}); - } - /* - if (availRelatives.sisters > 1) { - sexOptions.push({text: `Fuck ${him} with ${his} sisters`, scene: `FRelation`, update: {partner: "sisters}}); - } - */ - } - } - } - if (slave.relationship > 0) { - const lover = getSlave(slave.relationshipTarget); - if (isSlaveAvailable(lover)) { - sexOptions.push({text: `Fuck ${him} with ${his} ${relationshipTermShort(slave)} ${SlaveFullName(lover)}`, scene: `FRelation`, update: {partner: "relationship"}}); - } else if (lover.assignment === Job.AGENT) { - if (slave.broodmother < 2) { - sexOptions.push({text: `Send ${him} to live with your agent ${SlaveFullName(lover)}`, goto: `Agent Company`, update: {subSlave: lover}}); - } else { - sexOptions.push({text: `A hyper-broodmother cannot be sent to live with your agent`}); - } - } else { - sexOptions.push({text: `${SlaveFullName(lover)} is unavailable`}); - } - } - if (slave.rivalryTarget !== 0 && hasAllLimbs(slave)) { - const rival = getSlave(slave.relationshipTarget); - if (isSlaveAvailable(rival) && hasAnyLegs(rival)) { - sexOptions.push({text: `Abuse ${his} rival with ${him}`, scene: `FRival`}); - } - } - if (slave.fetish !== "mindbroken" && (canTalk(slave) || hasAnyArms(slave))) { - sexOptions.push({text: `Ask ${him} about ${his} feelings`, scene: `FFeelings`}); - if (V.PC.dick > 0) { - sexOptions.push({text: `Make ${him} beg`, scene: `FBeg`}); - } - } - if (slave.devotion >= 100 && slave.relationship < 0 && slave.relationship > -3) { - sexOptions.push({text: `Talk to ${him} about relationships`, goto: `Matchmaking`, update: {subSlave: 0}}); - } - let ML = V.marrying.length; - if ((V.policies.mixedMarriage === 1 || V.cheatMode === 1) && slave.relationship !== 5 && slave.relationship !== -3) { - if (V.marrying.includes(slave.ID)) { - sexOptions.push({text: `Marry ${him}`, disabled: `You are already marrying ${him} this weekend`}); - } else { - if (ML < 2) { - if (V.cheatMode === 1 || ML === 0) { - sexOptions.push({text: `Marry ${him}`, goto: "FMarry"}); - } else { - sexOptions.push({text: `Marry ${him}`, disabled: `You already have a wedding planned for this weekend`}); - } - } else { - sexOptions.push({text: `Marry ${him}`, disabled: `You can only marry up to two slaves per week`}); - } - } - } - if (V.cheatMode === 1) { - sexOptions.push({text: `Check ${his} stats`, goto: `Slave Stats`}); - } - } else { - /* IS A FUCKDOLL */ - sexOptions.push({text: `Fuck ${his} face hole`, scene: `FFuckdollOral`}); - if (canDoVaginal(slave)) { - sexOptions.push({text: `Fuck ${his} front hole`, scene: `FFuckdollVaginal`}); - } - if (canGetPregnant(slave) && (slave.geneticQuirks.superfetation !== 2 || V.geneticMappingUpgrade !== 0) && V.seePreg !== 0) { - if (canImpreg(slave, V.PC)) { - sexOptions.push({text: `Put a baby in ${him}`, scene: `FFuckdollImpreg`}); - } - } - if (canDoAnal(slave)) { - sexOptions.push({text: `Fuck ${his} rear hole`, scene: `FFuckdollAnal`}); - } - } - let activeSlaveRepSacrifice = repGainSacrifice(slave, V.arcologies[0]); - if (activeSlaveRepSacrifice > 0 && V.arcologies[0].FSPaternalist === "unset" && (slave.breedingMark === 0 || V.propOutcome === 0 || V.eugenicsFullControl === 1 || V.arcologies[0].FSRestart === "unset")) { - sexOptions.push({ - text: `Sacrifice ${him} on the altar`, - goto: `Aztec Slave Sacrifice`, - note: `This will kill ${him} and gain you ${activeSlaveRepSacrifice} reputation`, - update: {sacrificeType: "life"} - }); - } - el.append(`Use ${him}: `); - el.appendChild(generateRows(sexOptions)); - if (!jQuery.isEmptyObject(fillFaceOptions)) { - let fill = document.createElement('div'); - fill.appendChild(document.createTextNode(` Fill ${his} mouth with: `)); - fill.appendChild(generateRows(fillFaceOptions)); - el.appendChild(fill); - } - if (!jQuery.isEmptyObject(fillAssOptions)) { - let fill = document.createElement('div'); - fill.appendChild(document.createTextNode(` Fill ${his} ass with: `)); - fill.appendChild(generateRows(fillAssOptions)); - el.appendChild(fill); - } - - function generateRows(sexArray) { - let row = document.createElement('span'); - for (let i = 0; i < sexArray.length; i++) { - let link; - const separator = document.createTextNode(` | `); - const keys = Object.keys(sexArray[i]); - - // Test to see if there was a problem with the key - for (let j = 0; j < keys.length; j++) { - if (!["disabled", "goto", "note", "scene", "text", "update", "updateSlave"].includes(keys[j])) { - sexArray[i].text += " ERROR, THIS SCENE WAS NOT ENTERED CORRECTLY"; - console.log("Trash found while generateRows() was running: " + keys[j] + ": " + sexArray[i][keys[j]]); - break; - } - } - // is it just text? - if (sexArray[i].disabled) { - link = App.UI.DOM.disabledLink(sexArray[i].text, [sexArray[i].disabled]); - } else { - let passage = ""; - if (sexArray[i].goto) { - passage = sexArray[i].goto; - } - - // Set up the link - link = App.UI.DOM.link( - sexArray[i].text, - () => { click(sexArray[i]); }, - [], - passage - ); - - // add a note node if required - if (sexArray[i].note) { - link.appendChild(App.UI.DOM.makeElement('span', sexArray[i].note, 'note')); - } - } - row.appendChild(link); - if (i < sexArray.length - 1) { - row.appendChild(separator); - } - } - - return row; - - function click(sexOption) { - if (sexOption.updateSlave) { - Object.assign(slave, sexOption.updateSlave); - } - if (sexOption.update) { - Object.assign(V, sexOption.update); - } - - if (sexOption.goto) { - // just play the passage, no need to refresh anything here - Engine.play(sexOption.goto); - } else if (sexOption.scene) { - // Run scene and store render results temporarily - let frag = App.UI.DOM.renderPassage(sexOption.scene); - - // Refresh (clears scene display) - App.UI.SlaveInteract.refreshAll(slave); - - // Display scene render results - $("#mini-scene").append(frag); - } else { - // just refresh - App.UI.SlaveInteract.refreshAll(slave); - } - } - } - return el; -}; - -App.UI.SlaveInteract.bloating = function(slave) { - const { - // eslint-disable-next-line no-unused-vars - he, - him, - his, - hers, - himself, - boy, - He, - His - } = getPronouns(slave); - let bloating = document.createElement('div'); - if (slave.inflation > 0) { - let intro = document.createElement('span'); - intro.textContent = "Required Bloating"; - intro.style.textDecoration = "underline"; - bloating.append(intro); - - bloating.append(": "); - - let requirement = document.createElement('span'); - requirement.style.fontWeight = "bold"; - requirement.id = "inflate"; - if (slave.inflation === 3) { - requirement.textContent = `${He} is required to keep 2 gallons of ${slave.inflationType} in ${him} at all times`; - } else if (slave.inflation === 2) { - requirement.textContent = `${He} is required to keep 4 liters of ${slave.inflationType} in ${him} at all times`; - } else if (slave.inflation === 1) { - requirement.textContent = `${He} is required to keep 2 liters of ${slave.inflationType} in ${him} at all times`; - } - bloating.append(requirement); - bloating.append(". "); - - let link = App.UI.DOM.link( - `Let ${him} deflate`, - () => { - deflate(slave); - App.UI.SlaveInteract.refreshAll(slave); - }, - ); - bloating.append(link); - } - // make sure it updates itself after run - return jQuery('#bloating').empty().append(bloating); -}; - -App.UI.SlaveInteract.fertility = function(slave) { - const { - // eslint-disable-next-line no-unused-vars - he, - him, - his, - hers, - himself, - boy, - He, - His - } = getPronouns(slave); - let fertilityBlock = document.createElement('span'); - let linkArray = []; - if (slave.ovaries === 1 || slave.mpreg === 1 || slave.preg > 0) { - let note = ""; - if (slave.preg < -1) { - note += `${He} is sterile`; - } else if (slave.pubertyXX === 0 && slave.preg < 1) { - note += `${He} is not yet fertile`; - } else if (slave.ovaryAge >= 47 && slave.preg < 1) { - note += `${He} is too old to become pregnant`; - if (slave.preg === -1) { - slave.preg = 0; - SetBellySize(slave); - } - } else if (slave.broodmotherOnHold === 1) { - note += `${His} pregnancy implant is turned off`; - if (slave.broodmotherCountDown > 0) { - note += `${he} is expected to be completely emptied of ${his} remaining brood in ${slave.broodmotherCountDown} week`; - if (slave.broodmotherCountDown > 1) { - note += `s`; - } - note += `.`; - linkArray.push(App.UI.DOM.link( - `Turn on implant`, - () => { - slave.broodmotherOnHold = 0; - slave.broodmotherCountDown = 0; - App.UI.SlaveInteract.refreshAll(slave); - }, - )); - } - } else if (slave.preg >= -1) { - fertilityBlock.append("Contraception and fertility: "); - let fertility = ""; - // fertility.id = "fertility"; - if (slave.preg === -1) { - fertility = "using contraceptives"; - } else if (slave.pregWeek < 0) { - fertility = "postpartum"; - } else if (slave.preg === 0) { - fertility = "fertile"; - } else if (slave.preg < 4 && (slave.broodmother === 0 || slave.broodmotherOnHold === 1)) { - fertility = "may be pregnant"; - } else if (slave.preg < 2) { - fertility = "1 week pregnant"; - } else { - fertility = `${Math.trunc(slave.preg * 1000) / 1000} weeks pregnant`; // * and / needed to avoid seeing something like 20.1000000008 in some cases. - if (slave.broodmother > 0) { - fertility += " broodmother"; - } - } - fertility += ". "; - App.UI.DOM.appendNewElement("span", fertilityBlock, fertility, "bold"); - - if (slave.preg === 0) { - linkArray.push(App.UI.DOM.link( - `Use contraceptives`, - () => { - slave.preg = -1; - App.UI.SlaveInteract.refreshAll(slave); - }, - )); - } else if (slave.preg === -1) { - linkArray.push(App.UI.DOM.link( - `Let ${him} get pregnant`, - () => { - slave.preg = 0; - App.UI.SlaveInteract.refreshAll(slave); - }, - )); - } else if (isInduced(slave)) { - note += `Hormones are being slipped into ${his} food; ${he} will give birth suddenly and rapidly this week`; - } else if ( - slave.preg > slave.pregData.normalBirth - 2 && - slave.preg > slave.pregData.minLiveBirth && - slave.broodmother === 0 && - !isInLabor(slave) - ) { - linkArray.push(App.UI.DOM.link( - `Induce labor`, - () => { - induce(slave); - App.UI.SlaveInteract.refreshAll(slave); - }, - )); - linkArray.push(App.UI.DOM.passageLink(`Give ${him} a cesarean section`, "csec")); - } else if (slave.broodmother > 0) { - if (slave.broodmotherOnHold !== 1) { - linkArray.push(App.UI.DOM.link( - `Turn off implant`, - () => { - slave.broodmotherOnHold = 1; - slave.broodmotherCountDown = 38 - WombMinPreg(slave); - App.UI.SlaveInteract.refreshAll(slave); - }, - )); - } - if (slave.preg > 37) { - linkArray.push(App.UI.DOM.passageLink(`Induce mass childbirth`, "BirthStorm")); - } - } else if (slave.preg > slave.pregData.minLiveBirth) { - linkArray.push(App.UI.DOM.link( - `Give ${him} a cesarean section`, - () => { - slave.broodmotherOnHold = 0; - slave.broodmotherCountDown = 0; - }, - [], - "csec" - )); - } else if (slave.preg > 0 && slave.breedingMark === 1 && V.propOutcome === 1 && V.arcologies[0].FSRestart !== "unset" && V.eugenicsFullControl !== 1 && (slave.pregSource === -1 || slave.pregSource === -6)) { - note += "You are forbidden from aborting an Elite child"; - } else if (slave.preg > 0) { - linkArray.push(App.UI.DOM.link( - `Abort ${his} pregnancy`, - () => { - slave.broodmotherOnHold = 0; - slave.broodmotherCountDown = 0; - }, - [], - "Abort" - )); - } - } - App.UI.DOM.appendNewElement("span", fertilityBlock, note, "note"); - App.UI.DOM.appendNewElement("div", fertilityBlock, App.UI.DOM.generateLinksStrip(linkArray), "choices"); - } - if ( - (slave.pregKnown === 1) && - (V.pregSpeedControl === 1) && - ( - slave.breedingMark !== 1 || - V.propOutcome === 0 || - V.eugenicsFullControl === 1 || - V.arcologies[0].FSRestart === "unset" - ) && - (slave.indentureRestrictions < 1) && - (slave.broodmother === 0) && - V.seePreg !== 0 - ) { - let title = document.createElement('div'); - let underline = document.createElement('span'); - underline.style.textDecoration = "underline"; - underline.textContent = "Pregnancy control"; - title.appendChild(underline); - title.append(": "); - - if (slave.pregControl === "labor suppressors") { - title.append("Labor is suppressed. "); - } else if (slave.pregControl === "slow gestation") { - title.append("Slowed gestation speed. "); - } else if (slave.pregControl === "speed up") { - title.append("Faster gestation speed, staffed clinic recommended. "); - } else { - title.append("Normal gestation and birth. "); - } - fertilityBlock.appendChild(title); - - linkArray = []; - if (slave.pregControl !== "none") { - linkArray.push(App.UI.DOM.link( - `Normal ${slave.preg < slave.pregData.normalBirth ? "Gestation" : "Birth"}`, - () => { - slave.pregControl = "none"; - App.UI.SlaveInteract.fertility(slave); - }, - )); - } - if (slave.preg < slave.pregData.normalBirth) { - if (slave.pregControl !== "slow gestation") { - linkArray.push(App.UI.DOM.link( - `Slow Gestation`, - () => { - slave.pregControl = "slow gestation"; - App.UI.SlaveInteract.fertility(slave); - }, - )); - } - if (slave.pregControl !== "speed up") { - linkArray.push(App.UI.DOM.link( - `Fast Gestation`, - () => { - slave.pregControl = "speed up"; - App.UI.SlaveInteract.fertility(slave); - }, - )); - } - } - if (slave.preg >= slave.pregData.minLiveBirth) { - if (slave.pregControl !== "labor suppressors") { - linkArray.push(App.UI.DOM.link( - `Suppress Labor`, - () => { - slave.pregControl = "labor suppressors"; - App.UI.SlaveInteract.fertility(slave); - }, - )); - } - } - App.UI.DOM.appendNewElement("div", fertilityBlock, App.UI.DOM.generateLinksStrip(linkArray), "choices"); - } - return jQuery('#fertility-block').empty().append(fertilityBlock); -}; - -App.UI.SlaveInteract.curatives = function(slave) { - const curativeOptions = []; - - curativeOptions.push({text: `None`, updateSlave: {curatives: 0}}); - curativeOptions.push({text: `Preventatives`, updateSlave: {curatives: 1}}); - curativeOptions.push({text: `Curatives`, updateSlave: {curatives: 2}}); - - let el = document.createElement('div'); - let title = document.createElement('div'); - title.append(`Health: `); - let chosenOption = document.createElement('span'); - chosenOption.style.fontWeight = "bold"; - if (slave.curatives > 1) { - chosenOption.textContent = `curatives`; - } else if (slave.curatives > 0) { - chosenOption.textContent = `preventatives`; - } else { - chosenOption.textContent = `none`; - } - title.appendChild(chosenOption); - title.append(`.`); - let link = document.createElement('div'); - link.className = "choices"; - link.appendChild(App.UI.SlaveInteract.generateRows(curativeOptions, slave)); - el.append(title); - el.append(link); - return jQuery('#curatives').empty().append(el); -}; - -App.UI.SlaveInteract.aphrodisiacs = function(slave) { - const aphrodisiacOptions = []; - - aphrodisiacOptions.push({text: `None`, updateSlave: {aphrodisiacs: 0}}); - aphrodisiacOptions.push({text: `Aphrodisiacs`, updateSlave: {aphrodisiacs: 1}}); - aphrodisiacOptions.push({text: `Extreme aphrodisiacs`, updateSlave: {aphrodisiacs: 2}}); - aphrodisiacOptions.push({text: `Anaphrodisiacs`, updateSlave: {aphrodisiacs: -1}, note: `Suppresses libido`}); - - - let el = document.createElement('div'); - let title = document.createElement('div'); - title.append(`Aphrodisiacs: `); - let chosenOption = document.createElement('span'); - chosenOption.style.fontWeight = "bold"; - if (slave.aphrodisiacs > 1) { - chosenOption.textContent = `extreme`; - } else if (slave.aphrodisiacs > 0) { - chosenOption.textContent = `applied`; - } else if (slave.aphrodisiacs === -1) { - chosenOption.textContent = `anaphrodisiacs`; - } else { - chosenOption.textContent = `none`; - } - title.appendChild(chosenOption); - title.append(`.`); - let link = document.createElement('div'); - link.className = "choices"; - link.appendChild(App.UI.SlaveInteract.generateRows(aphrodisiacOptions, slave)); - el.append(title); - el.append(link); - return jQuery('#aphrodisiacs').empty().append(el); -}; - -/** - * @param {App.Entity.SlaveState} slave - */ -App.UI.SlaveInteract.incubator = function(slave) { - const { - // eslint-disable-next-line no-unused-vars - he, - him, - his, - hers, - himself, - boy, - He, - His - } = getPronouns(slave); - V.reservedChildren = FetusGlobalReserveCount("incubator"); - let _reservedIncubator = WombReserveCount(slave, "incubator"); - let _reservedNursery = WombReserveCount(slave, "nursery"); - let _WL = slave.womb.length; - let el = document.createElement('div'); - - if (V.incubator > 0) { - if (slave.preg > 0 && slave.broodmother === 0 && slave.pregKnown === 1 && slave.eggType === "human") { - if ((slave.assignment !== Job.DAIRY || V.dairyPregSetting === 0) && (slave.assignment !== Job.FARMYARD || V.farmyardBreeding === 0)) { - let title = document.createElement('div'); - let link = document.createElement('div'); - link.className = "choices"; - if (_WL - _reservedNursery === 0) { - title.textContent = `${His} children are already reserved for ${V.nurseryName}`; - title.style.fontStyle = "italic"; - } else { - const freeTanks = (V.incubator - V.tanks.length); - if (_reservedIncubator > 0) { - if (_WL === 1) { - title.textContent = `${His} child will be placed in ${V.incubatorName}. `; - } else if (_reservedIncubator < _WL) { - title.textContent = `${_reservedIncubator} of ${his} children will be placed in ${V.incubatorName}.`; - } else if (_WL === 2) { - title.textContent = `Both of ${his} children will be placed in ${V.incubatorName}. `; - } else { - title.textContent = `All ${_reservedIncubator} of ${his} children will be placed in ${V.incubatorName}. `; - } - if ((_reservedIncubator + _reservedNursery < _WL) && (V.reservedChildren < freeTanks)) { - link.appendChild( - App.UI.DOM.link(`Keep another child`, () => wombUpdateIncubator(1, true)) - ); - if (_reservedIncubator > 0) { - link.append(` | `); - link.appendChild( - App.UI.DOM.link(`Keep one less child`, () => wombUpdateIncubator(1, false)) - ); - } - if (_reservedIncubator > 1) { - link.append(` | `); - link.appendChild( - App.UI.DOM.link(`Keep none of ${his} children`, () => wombUpdateIncubator(9999, false)) - ); - } - if ((V.reservedChildren + _WL - _reservedIncubator) <= freeTanks) { - link.append(` | `); - link.appendChild( - App.UI.DOM.link(`Keep the rest of ${his} children`, () => wombUpdateIncubator(9999, true)) - ); - } - } else if ((_reservedIncubator === _WL) || (V.reservedChildren === freeTanks) || (_reservedIncubator - _reservedNursery >= 0)) { - link.appendChild( - App.UI.DOM.link(`Keep one less child`, () => wombUpdateIncubator(1, false)) - ); - if (_reservedIncubator > 1) { - link.append(` | `); - link.appendChild( - App.UI.DOM.link(`Keep none of ${his} children`, () => wombUpdateIncubator(9999, false)) - ); - } - } - } else if (V.reservedChildren < freeTanks) { - title.textContent = `${He} is pregnant and you have `; - if (freeTanks === 1) { - title.textContent += `an `; - } - let tank = document.createElement('span'); - tank.className = "lime"; - tank.textContent = `available aging tank`; - if (freeTanks > 1) { - tank.textContent += `s`; - } - tank.textContent += `.`; - let _cCount = (_WL > 1 ? "a" : "the"); - link.appendChild( - App.UI.DOM.link(`Keep ${_cCount} child`, () => wombUpdateIncubator(1, true)) - ); - title.appendChild(tank); - if ((_WL > 1) && (V.reservedChildren + _WL) <= freeTanks) { - link.append(` | `); - link.appendChild( - App.UI.DOM.link(`Keep all of ${his} children`, () => wombUpdateIncubator(9999, true)) - ); - } - } else if (V.reservedChildren === freeTanks) { - title.textContent = `You have no available tanks for ${his} children. `; - } - } - el.append(title); - el.append(link); - } - } - } - - function wombUpdateIncubator(count, addToWomb) { - if (addToWomb) { - WombAddToGenericReserve(slave, "incubator", count); - } else { - WombCleanGenericReserve(slave, "incubator", count); - } - V.reservedChildren = FetusGlobalReserveCount("incubator"); - App.UI.SlaveInteract.refreshAll(slave); - } - - return jQuery('#incubator').empty().append(el); -}; - -App.UI.SlaveInteract.nursery = function(slave) { - const { - // eslint-disable-next-line no-unused-vars - he, - him, - his, - hers, - himself, - boy, - He, - His - } = getPronouns(slave); - let el = document.createElement('div'); - if (V.nursery > 0) { - V.reservedChildrenNursery = FetusGlobalReserveCount("nursery"); - let reservedIncubator = WombReserveCount(slave, "incubator"); - let reservedNursery = WombReserveCount(slave, "nursery"); - let _WL = slave.womb.length; - if (slave.preg > 0 && slave.broodmother === 0 && slave.pregKnown === 1 && slave.eggType === "human") { - if ((slave.assignment !== Job.DAIRY || V.dairyPregSetting === 0) && (slave.assignment !== Job.FARMYARD || V.farmyardBreeding === 0)) { - let title = document.createElement('div'); - let link = document.createElement('div'); - link.className = "choices"; - if (_WL - reservedIncubator === 0) { - V.reservedChildren = 0; - title.textContent = `${His} children are already reserved for ${V.incubatorName}`; - title.style.fontStyle = "italic"; - } else { - const freeCribs = (V.nursery - V.cribs.length); - if (reservedNursery > 0) { - if (_WL === 1) { - title.textContent = `${His} child will be placed in ${V.nurseryName}. `; - } else if (reservedNursery < _WL) { - title.textContent = `_reservedNursery of ${his} children will be placed in ${V.nurseryName}.`; - } else if (_WL === 2) { - title.textContent = `Both of ${his} children will be placed in ${V.nurseryName}. `; - } else { - title.textContent = `All ${reservedNursery} of ${his} children will be placed in ${V.nurseryName}. `; - } - if ((reservedIncubator + reservedNursery < _WL) && (V.reservedChildrenNursery < freeCribs)) { - link.appendChild( - App.UI.DOM.link(`Keep another child`, () => wombUpdateNursery(1, true)) - ); - - if (reservedNursery > 0) { - link.append(` | `); - link.appendChild( - App.UI.DOM.link(`Keep one less child`, () => wombUpdateNursery(1, false)) - ); - } - if (reservedNursery > 1) { - link.append(` | `); - link.appendChild( - App.UI.DOM.link(`Keep none of ${his} children`, () => wombUpdateNursery(9999, false)) - ); - } - if ((V.reservedChildrenNursery + _WL - reservedNursery) <= freeCribs) { - link.append(` | `); - link.appendChild( - App.UI.DOM.link(`Keep the rest of ${his} children`, () => wombUpdateNursery(9999, true)) - ); - } - } else if ((reservedNursery === _WL) || (V.reservedChildrenNursery === freeCribs) || (reservedNursery - reservedIncubator >= 0)) { - link.appendChild( - App.UI.DOM.link(`Keep one less child`, () => wombUpdateNursery(1, false)) - ); - - if (reservedNursery > 1) { - link.append(` | `); - link.appendChild( - App.UI.DOM.link(`Keep none of ${his} children`, () => wombUpdateNursery(9999, false)) - ); - } - } - } else if (V.reservedChildrenNursery < freeCribs) { - title.textContent = `${He} is pregnant and you have `; - if (freeCribs === 1) { - title.textContent += `an `; - } - let crib = document.createElement('span'); - crib.className = "lime"; - crib.textContent = `available room`; - if (freeCribs > 1) { - crib.textContent += `s`; - } - crib.textContent += `.`; - let _cCount = (_WL > 1 ? "a" : "the"); - link.appendChild( - App.UI.DOM.link(`Keep ${_cCount} child`, () => wombUpdateNursery(1, true)) - ); - title.appendChild(crib); - if ((_WL > 1) && (V.reservedChildrenNursery + _WL) <= freeCribs) { - link.append(` | `); - link.appendChild( - App.UI.DOM.link(`Keep all of ${his} children`, () => wombUpdateNursery(9999, true)) - ); - } - } else if (V.reservedChildrenNursery === freeCribs) { - title.textContent = `You have no available rooms for ${his} children. `; - } - } - el.append(title); - el.append(link); - } - } - } - - function wombUpdateNursery(count, addToWomb) { - if (addToWomb) { - WombAddToGenericReserve(slave, "nursery", count); - } else { - WombCleanGenericReserve(slave, "nursery", count); - } V.reservedChildren = FetusGlobalReserveCount("nursery"); - App.UI.SlaveInteract.refreshAll(slave); - } - - return jQuery('#nursery').empty().append(el); -}; - -App.UI.SlaveInteract.rules = function(slave) { - const frag = new DocumentFragment(); - let p; - let div; - let array; - let choices; - const { - he, him, his, hers, himself, boy, He, His - } = getPronouns(slave); - - if (V.seePreg !== 0) { - if (V.universalRulesImpregnation === "PC") { - updateBreederLink("you", "PCExclude"); - } else if (V.universalRulesImpregnation === "HG") { - updateBreederLink("the Head Girl", "HGExclude"); - } else if (V.universalRulesImpregnation === "Stud") { - updateBreederLink("your Stud", "StudExclude"); - } - } - - function updateBreederLink(breeder, exclude) { - p = document.createElement('p'); - const exempt = slave[exclude] ? "Exempt" : "Include"; - - p.append(`Will be bred by ${breeder} when fertile. `); - p.append( - App.UI.DOM.link(`${exempt} ${him}`, () => { - slave[exclude] = slave[exclude] ^ 1; // switch 0 and 1 - App.UI.SlaveInteract.rules(slave); - }) - ); - frag.append(p); - } - - p = document.createElement('p'); - - array = []; - if (slave.useRulesAssistant === 0) { - App.UI.DOM.appendNewElement("span", p, `Not subject `, ["bold", "gray"]); - App.UI.DOM.appendNewElement("span", p, `to the Rules Assistant.`, "gray"); - array.push( - App.UI.DOM.link( - `Include ${him}`, - () => { - slave.useRulesAssistant = 1; - App.UI.SlaveInteract.rules(slave); - } - ) - ); - } else { - App.UI.DOM.appendNewElement("h3", p, `Rules Assistant`); - - if (slave.hasOwnProperty("currentRules") && slave.currentRules.length > 0) { - const ul = document.createElement("UL"); - ul.style.margin = "0"; - V.defaultRules.filter( - x => ruleApplied(slave, x) - ).map( - x => { - const li = document.createElement('li'); - li.append(x.name); - ul.append(li); - } - ); - - // set up rules display - if ($("ul").has("li").length ) { - App.UI.DOM.appendNewElement("div", p, `Rules applied: `); - p.append(ul); - } else { - App.UI.DOM.appendNewElement("div", p, `There are no rules that would apply to ${him}.`, "gray"); - } - } - array.push( - App.UI.DOM.link( - `Apply rules`, - () => { - DefaultRules(slave); - App.UI.SlaveInteract.rules(slave); - } - ) - ); - array.push( - App.UI.DOM.link( - `Exempt ${him}`, - () => { - slave.useRulesAssistant = 0; - App.UI.SlaveInteract.rules(slave); - } - ) - ); - array.push(App.UI.DOM.passageLink("Rules Assistant Options", "Rules Assistant")); - } - p.append(App.UI.DOM.generateLinksStrip(array)); - frag.append(p); - - p = document.createElement('p'); - App.UI.DOM.appendNewElement("h3", p, `Other Rules`); - - // Living - if (slave.fuckdoll > 0) { - App.UI.DOM.appendNewElement("span", p, "Rules have little meaning for living sex toys", "note"); - } else { - penthouseCensus(); - p.append("Living standard: "); - App.UI.DOM.appendNewElement("span", p, slave.rules.living, "bold"); - } - if (setup.facilityCareers.includes(slave.assignment)) { - App.UI.DOM.appendNewElement("span", p, ` ${His} living conditions are managed by ${his} assignment.`, "note"); - } else if ((slave.assignment === "be your Head Girl") && (V.HGSuite === 1)) { - App.UI.DOM.appendNewElement("span", p, ` ${He} has ${his} own little luxurious room in the penthouse with everything ${he} needs to be a proper Head Girl.`, "note"); - } else if ((slave.assignment === "guard you") && (V.dojo > 1)) { - App.UI.DOM.appendNewElement("span", p, ` ${He} has a comfortable room in the armory to call ${his} own.`, "note"); - } else { - choices = [ - {value: "spare"}, - {value: "normal"}, - ]; - if (canMoveToRoom(slave) || slave.rules.living === "luxurious") { - choices.push({value: "luxurious"}); - } else { - choices.push({ - title: `Luxurious`, - disabled: ["No luxurious rooms available"] - }); - } - - p.append(listChoices(choices, "living")); - } - - // Rest - if (["be a servant", "be a subordinate slave", "get milked", "please you", "serve in the club", "serve the public", "whore", "work as a farmhand", "work in the brothel", "work a glory hole"].includes(slave.assignment) || (V.dairyRestraintsSetting < 2 && slave.assignment === "work in the dairy")) { - div = document.createElement("div"); - div.append("Sleep rules: "); - App.UI.DOM.appendNewElement("span", div, slave.rules.rest, "bold"); - choices = [ - {value: "none"}, - {value: "cruel"}, - {value: "restrictive"}, - {value: "permissive"}, - {value: "mandatory"}, - ]; - div.append(listChoices(choices, "rest")); - p.append(div); - } - - // Mobility Aids - if (slave.fuckdoll > 0) { - // Sex toys don't move around on their own// - } else if (canMove(slave)) { - div = document.createElement("div"); - div.append("Use of mobility aids: "); - App.UI.DOM.appendNewElement("span", div, slave.rules.mobility, "bold"); - choices = [ - {value: "restrictive"}, - {value: "permissive"}, - ]; - div.append(listChoices(choices, "mobility")); - p.append(div); - } - - // Punishment - div = document.createElement("div"); - div.append("Typical punishment: "); - App.UI.DOM.appendNewElement("span", div, slave.rules.punishment, "bold"); - choices = [ - {value: "confinement"}, - {value: "whipping"}, - {value: "chastity"}, - {value: "situational"}, - ]; - div.append(listChoices(choices, "punishment")); - p.append(div); - - // Reward - div = document.createElement("div"); - div.append("Typical reward: "); - App.UI.DOM.appendNewElement("span", div, slave.rules.reward, "bold"); - choices = [ - {value: "relaxation"}, - {value: "drugs"}, - {value: "orgasm"}, - {value: "situational"}, - ]; - div.append(listChoices(choices, "reward")); - p.append(div); - - // Lactation - if (slave.lactation !== 2) { - div = document.createElement("div"); - div.append("Lactation maintenance: "); - App.UI.DOM.appendNewElement("span", div, slave.rules.lactation, "bold"); - choices = [ - { - title: "Left alone", - value: "none", - }, - ]; - - if (slave.lactation === 0) { - choices.push( - { - title: "Induce lactation", - value: "induce", - } - ); - } else { - choices.push( - { - title: "Maintain lactation", - value: "maintain", - } - ); - } - div.append(listChoices(choices, "lactation")); - p.append(div); - } - - p.append(orgasm(slave)); - - if (slave.voice !== 0) { - div = document.createElement("div"); - div.append("Speech rules: "); - App.UI.DOM.appendNewElement("span", div, slave.rules.speech, "bold"); - choices = [ - {value: "restrictive"}, - {value: "permissive"}, - ]; - if (slave.accent > 0 && slave.accent < 4) { - choices.push( - {value: "accent elimination"}, - ); - } else if (slave.accent > 3) { - choices.push( - {value: "language lessons"}, - ); - } - div.append(listChoices(choices, "speech")); - p.append(div); - } - - div = document.createElement("div"); - div.append("Relationship rules: "); - App.UI.DOM.appendNewElement("span", div, slave.rules.relationship, "bold"); - choices = [ - {value: "restrictive"}, - {value: "just friends"}, - {value: "permissive"}, - ]; - div.append(listChoices(choices, "relationship")); - p.append(div); - - p.append(smartSettings(slave)); - frag.append(p); - return jQuery('#rules').empty().append(frag); - - function listChoices(choices, property) { - const links = []; - for (const c of choices) { - const title = c.title || capFirstChar(c.value); - if (c.disabled) { - links.push( - App.UI.DOM.disabledLink( - title, c.disabled - ) - ); - } else { - links.push( - App.UI.DOM.link( - title, - () => { - slave.rules[property] = c.value; - App.UI.SlaveInteract.rules(slave); - } - ) - ); - } - } - return App.UI.DOM.generateLinksStrip(links); - } - function orgasm(slave) { - let el = document.createElement('div'); - - let title = document.createElement('div'); - title.textContent = `Non-assignment orgasm rules: `; - el.append(title); - - makeLinks("Masturbation", "rules.release.masturbation"); - makeLinks("Partner", "rules.release.partner"); - makeLinks("Family", "rules.release.family"); - makeLinks("Other slaves", "rules.release.slaves"); - makeLinks("Master", "rules.release.master", true); - - function makeLinks(text, setting, master = false) { - const options = - [{text: master ? `Grant` : `Allow`, updateSlave: {[setting]: 1}}, - {text: master ? `Deny` : `Forbid`, updateSlave: {[setting]: 0}}]; - - let links = document.createElement('div'); - links.append(`${text}: `); - links.append(status(_.get(slave, setting), master)); - links.appendChild(App.UI.SlaveInteract.generateRows(options, slave)); - links.className = "choices"; - el.append(links); - } - - function status(setting, master) { - let selected = document.createElement('span'); - selected.style.fontWeight = "bold"; - let text; - if (master) { - text = setting ? "granted" : "denied"; - } else { - text = setting ? "allowed" : "denied"; - } - selected.textContent = `${text}. `; - return selected; - } - - return el; - } - - function smartSettings(slave) { - let el = document.createElement('div'); - - const {His} = getPronouns(slave); - const bodyPart = []; - const BDSM = []; - const gender = []; - const level = []; - const usingBulletVibe = slave.vaginalAccessory === "smart bullet vibrator" || slave.dickAccessory === "smart bullet vibrator"; - - if (slave.clitPiercing === 3 || usingBulletVibe) { - // Level - level.push({text: `No sex`, updateSlave: {clitSetting: `none`}}); - level.push({text: `All sex`, updateSlave: {clitSetting: `all`}}); - - // Body part - bodyPart.push({text: `Vanilla`, updateSlave: {clitSetting: `vanilla`}}); - bodyPart.push({text: `Oral`, updateSlave: {clitSetting: `oral`}}); - bodyPart.push({text: `Anal`, updateSlave: {clitSetting: `anal`}}); - bodyPart.push({text: `Boobs`, updateSlave: {clitSetting: `boobs`}}); - if (V.seePreg !== 0) { - bodyPart.push({text: `Preg`, updateSlave: {clitSetting: `pregnancy`}}); - } - // BDSM - BDSM.push({text: `Sub`, updateSlave: {clitSetting: `submissive`}}); - BDSM.push({text: `Dom`, updateSlave: {clitSetting: `dom`}}); - BDSM.push({text: `Masochism`, updateSlave: {clitSetting: `masochist`}}); - BDSM.push({text: `Sadism`, updateSlave: {clitSetting: `sadist`}}); - BDSM.push({text: `Humiliation`, updateSlave: {clitSetting: `humiliation`}}); - - // Gender - gender.push({text: `Men`, updateSlave: {clitSetting: `men`}}); - gender.push({text: `Women`, updateSlave: {clitSetting: `women`}}); - gender.push({text: `Anti-men`, updateSlave: {clitSetting: `anti-men`}}); - gender.push({text: `Anti-women`, updateSlave: {clitSetting: `anti-women`}}); - } - - let label = null; - if (slave.clitPiercing === 3) { - label = `${His} smart ${slave.dick < 1 ? "clit" : "frenulum"} piercing `; - label += (usingBulletVibe) ? `and smart bullet vibrator are set to: ` : `is set to: `; - } - if (label) { - let title = App.UI.DOM.appendNewElement('div', el, label); - let selected = App.UI.DOM.appendNewElement('span', title, `${slave.clitSetting}. `); - selected.style.fontWeight = "bold"; - } - - App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Level", level, slave); - App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Body part", bodyPart, slave); - App.UI.SlaveInteract.appendLabeledChoiceRow(el, "BDSM", BDSM, slave); - App.UI.SlaveInteract.appendLabeledChoiceRow(el, "Gender", gender, slave); - - return el; - } -}; - -App.UI.SlaveInteract.custom = (function() { - let el; - let label; - let result; - let textbox; - return custom; - - function custom(slave) { - let title; - el = document.createElement('div'); - - el.appendChild(intro(slave)); - - title = document.createElement('h3'); - title.textContent = `Art`; - el.appendChild(title); - el.appendChild(customSlaveImage(slave)); - el.appendChild(customHairImage(slave)); - - title = document.createElement('h3'); - title.textContent = `Names`; - el.appendChild(title); - el.appendChild(playerTitle(slave)); - el.appendChild(slaveFullName(slave)); - - title = document.createElement('h3'); - title.textContent = `Description`; - el.appendChild(title); - el.appendChild(hair(slave)); - el.appendChild(eyeColor(slave)); - el.appendChild(customTattoo(slave)); - el.appendChild(customOriginStory(slave)); - el.appendChild(customDescription(slave)); - el.appendChild(customLabel(slave)); - - return jQuery('#custom').empty().append(el); - } - - function intro(slave) { - const frag = new DocumentFragment(); - let p; - p = document.createElement('p'); - p.id = "rename"; - frag.append(p); - - p = document.createElement('p'); - p.className = "scene-p"; - p.append(`You may enter custom descriptors for your slave's hair color, hair style, tattoos, or anything else here. After typing, press `); - p.appendChild(App.UI.DOM.makeElement("kbd", "enter")); - p.append(` to commit your change. These custom descriptors will appear in descriptions of your slave, but will have no gameplay effect. Changing them is free.`); - frag.append(p); - return frag; - } - - function playerTitle(slave) { - const { - // eslint-disable-next-line no-unused-vars - he, - him, - his, - hers, - himself, - boy, - He, - His - } = getPronouns(slave); - let playerTitle = document.createElement('p'); - label = document.createElement('div'); - if (slave.devotion >= -50) { - if (slave.custom.title !== "") { - label.textContent = `You have instructed ${him} to always refer to you as ${slave.custom.title}, which, should ${he} lisp, comes out as ${slave.custom.titleLisp}.`; - } else { - label.textContent = `You expect ${him} to refer to you as all your other slaves do.`; - } - result = document.createElement('div'); - result.id = "result"; - result.className = "choices"; - - let hiddenTextBox = document.createElement('span'); - let shownTextBox = document.createElement('span'); - if (slave.custom.title === "") { - hiddenTextBox.appendChild( - App.UI.DOM.link( - `Set a custom title for ${him} to address you as`, - () => { - jQuery('#result').empty().append(shownTextBox); - } - ) - ); - result.appendChild(hiddenTextBox); - shownTextBox.textContent = `Custom title: `; - textbox = App.UI.DOM.makeTextBox( - "", - v => { - slave.custom.title = v; - jQuery('#result').empty().append( - document.createTextNode(`${He}'ll try ${his} best to call you ${slave.custom.title}.`) - ); - slave.custom.titleLisp = lispReplace(slave.custom.title); - }); - shownTextBox.appendChild(textbox); - } else { - result.append(`${He}'s trying ${his} best to call you `); - textbox = App.UI.DOM.makeTextBox( - slave.custom.title, - v => { - slave.custom.title = v; - jQuery('#result').empty().append( - document.createTextNode(`${He}'ll try ${his} best to call you ${slave.custom.title}.`) - ); - slave.custom.titleLisp = lispReplace(slave.custom.title); - }); - result.appendChild(textbox); - result.appendChild( - App.UI.DOM.link( - ` Stop using a custom title`, - () => { - jQuery('#result').empty().append( - document.createTextNode(`${He} will no longer refer to you with a special title.`) - ); - slave.custom.title = ""; - slave.custom.titleLisp = ""; - } - ) - ); - } - label.appendChild(result); - } else { - label.textContent = `You must break ${his} will further before ${he} will refer to you by a new title. `; - if (SlaveStatsChecker.checkForLisp(slave)) { - if (slave.custom.titleLisp && slave.custom.titleLisp !== "") { - label.textContent += `For now, ${he} intends to keep calling you "${slave.custom.titleLisp}."`; - } - } else { - if (slave.custom.title && slave.custom.title !== "") { - label.textContent += `For now, ${he} intends to keep calling you "${slave.custom.title}."`; - } - } - } - playerTitle.appendChild(label); - return playerTitle; - } - - function slaveFullName(slave) { - const { - // eslint-disable-next-line no-unused-vars - he, - him, - his, - hers, - himself, - boy, - He, - His - } = getPronouns(slave); - let slaveFullNameNode = document.createElement('span'); - if ( - ((slave.devotion >= -50 || slave.trust < -20) && (slave.birthName !== slave.slaveName)) || - (slave.devotion > 20 || slave.trust < -20) - ) { - slaveFullNameNode.appendChild(slaveName()); - slaveFullNameNode.appendChild(slaveSurname()); - } else { - slaveFullNameNode.textContent = `You must break ${his} will further before you can successfully force a new name on ${him}.`; - slaveFullNameNode.className = "note"; - } - - return slaveFullNameNode; - - function slaveName() { - const oldName = slave.slaveName; - const oldSurname = slave.slaveSurname; - // Slave Name - let slaveNameNode = document.createElement('p'); - label = document.createElement('div'); - result = document.createElement('div'); - result.id = "result"; - result.className = "choices"; - const linkArray = []; - - label.append(`Change ${his} given name`); - if (slave.birthName !== slave.slaveName) { - label.append(` (${his} birth name was ${slave.birthName})`); - } - label.append(`: `); - - textbox = App.UI.DOM.makeTextBox( - slave.slaveName, - v => { - slave.slaveName = v; - updateName(slave, {oldName: oldName, oldSurname: oldSurname}); - }, - false, - ); - label.appendChild(textbox); - - slaveNameNode.appendChild(label); - - if (slave.slaveName === slave.birthName) { - linkArray.push(App.UI.DOM.disabledLink(`${He} has ${his} birth name`, [`Nothing to reset`])); - } else { - linkArray.push(App.UI.DOM.link( - `Restore ${his} birth name`, - () => { - slave.slaveName = slave.birthName; - updateName(slave, {oldName: oldName, oldSurname: oldSurname}); - }, - false, - )); - } - - if (V.arcologies[0].FSPastoralist !== "unset") { - if (slave.lactation > 0) { - linkArray.push(chooseThreeNames(`Choose a random cow name for ${him}`, setup.cowSlaveNames, "cow-names")); - } - } - if (V.arcologies[0].FSIntellectualDependency !== "unset") { - if (slave.intelligence + slave.intelligenceImplant < -10) { - linkArray.push(chooseThreeNames(`Give ${him} a random stripper given name`, setup.bimboSlaveNames, "bimbo-names")); - } - } - if (V.arcologies[0].FSChattelReligionist !== "unset") { - linkArray.push(chooseThreeNames(`Give ${him} a random devotional given name`, setup.chattelReligionistSlaveNames, "devotional-names")); - } - result.append(App.UI.DOM.generateLinksStrip(linkArray)); - slaveNameNode.appendChild(result); - return slaveNameNode; - - function chooseThreeNames(title, array, id) { - const el = document.createElement("span"); - el.id = id; - el.append( - App.UI.DOM.link( - title, - () => { - linkGuts(); - } - ) - ); - return el; - function linkGuts() { - // Randomize the array - const shuffled = array.sort(() => 0.5 - Math.random()); - - // Get the first three new names - const names = []; - for (let i = 0; names.length < 3; i++) { - if (i > shuffled.length) { - break; - } - if (shuffled[i] !== slave.slaveName) { - names.push(shuffled[i]); - } - } - - // return the three names as links - const nameLinks = []; - for (const name of names) { - nameLinks.push( - App.UI.DOM.link( - name, - () => { - slave.slaveName = name; - updateName(slave, {oldName: oldName, oldSurname: oldSurname}); - } - ) - ); - } - nameLinks.push( - App.UI.DOM.link( - "...", - () => { - linkGuts(); - } - ) - ); - jQuery(`#${id}`).empty().append(App.UI.DOM.generateLinksStrip(nameLinks)); - } - } - } - - function slaveSurname() { - // Slave Surname - const oldName = slave.slaveName; - const oldSurname = slave.slaveSurname; - let slaveSurnameNode = document.createElement('p'); - label = document.createElement('div'); - result = document.createElement('div'); - result.id = "result"; - result.className = "choices"; - - label.append(`Change ${his} surname`); - if (slave.birthSurname !== slave.slaveSurname) { - label.append(` (${his} birth surname was ${slave.birthSurname})`); - } - label.append(`: `); - - textbox = App.UI.DOM.makeTextBox( - slave.slaveSurname, - v => { - slave.slaveSurname = textbox.value; - updateName(slave, {oldName: oldName, oldSurname: oldSurname}); - }, - false, - ); - label.appendChild(textbox); - - slaveSurnameNode.appendChild(label); - - if (slave.slaveSurname === slave.birthSurname) { - result.append(` ${He} has ${his} birth surname`); - } else { - result.appendChild(App.UI.DOM.link( - ` Restore ${his} birth surname`, - () => { - slave.slaveSurname = slave.birthSurname; - updateName(slave, {oldName: oldName, oldSurname: oldSurname}); - }, - false, - )); - } - - if (slave.slaveSurname) { - result.append(` | `); - result.appendChild(App.UI.DOM.link( - `Take ${his} surname away`, - () => { - slave.slaveSurname = 0; - updateName(slave, {oldName: oldName, oldSurname: oldSurname}); - }, - false, - )); - } - if (slave.relationship >= 5) { - const spouse = getSlave(slave.relationshipTarget); - if (spouse.slaveSurname && slave.slaveSurname !== spouse.slaveSurname) { - result.append(` | `); - const wifePronouns = getPronouns(spouse); - result.appendChild(App.UI.DOM.link( - `Give ${him} ${his} ${wifePronouns.wife}'s surname`, - () => { - slave.slaveSurname = spouse.slaveSurname; - updateName(slave, {oldName: oldName, oldSurname: oldSurname}); - }, - false, - )); - } - } - if (slave.relationship === -3) { - if (V.PC.slaveSurname && slave.slaveSurname !== V.PC.slaveSurname) { - result.append(` | `); - result.appendChild(App.UI.DOM.link( - `Give ${him} your surname`, - () => { - slave.slaveSurname = V.PC.slaveSurname; - updateName(slave, {oldName: oldName, oldSurname: oldSurname}); - }, - false, - )); - } - } - if (V.arcologies[0].FSRomanRevivalist !== "unset") { - result.append(` | `); - result.appendChild(App.UI.DOM.link( - `Give ${him} a random full Roman name`, - () => { - slave.slaveName = setup.romanSlaveNames.random(); - slave.slaveSurname = setup.romanSlaveSurnames.random(); - updateName(slave, {oldName: oldName, oldSurname: oldSurname}); - }, - false, - )); - } else if (V.arcologies[0].FSAztecRevivalist !== "unset") { - result.append(` | `); - result.appendChild(App.UI.DOM.link( - `Give ${him} a random full Aztec name`, - () => { - slave.slaveName = setup.aztecSlaveNames.random(); - slave.slaveSurname = 0; - updateName(slave, {oldName: oldName, oldSurname: oldSurname}); - }, - false, - )); - } else if (V.arcologies[0].FSEgyptianRevivalist !== "unset") { - result.append(` | `); - result.appendChild(App.UI.DOM.link( - `Give ${him} a random full ancient Egyptian name`, - () => { - slave.slaveName = setup.ancientEgyptianSlaveNames.random(); - slave.slaveSurname = 0; - updateName(slave, {oldName: oldName, oldSurname: oldSurname}); - }, - false, - )); - } else if (V.arcologies[0].FSEdoRevivalist !== "unset") { - result.append(` | `); - result.appendChild(App.UI.DOM.link( - `Give ${him} a random full feudal Japanese name`, - () => { - slave.slaveName = setup.edoSlaveNames.random(); - slave.slaveSurname = setup.edoSlaveSurnames.random(); - updateName(slave, {oldName: oldName, oldSurname: oldSurname}); - }, - false, - )); - } - if (V.arcologies[0].FSDegradationist > -1) { - result.append(` | `); - result.appendChild(App.UI.DOM.link( - `Give ${him} a degrading full name`, - () => { - DegradingName(slave); - updateName(slave, {oldName: oldName, oldSurname: oldSurname}); - }, - false, - )); - } - slaveSurnameNode.appendChild(result); - return slaveSurnameNode; - } - function updateName(slave, {oldName: oldName, oldSurname: oldSurname}) { - App.UI.SlaveInteract.custom(slave); - App.UI.SlaveInteract.rename(slave, {oldName: oldName, oldSurname: oldSurname}); - } - } - - /** - * @param {App.Entity.SlaveState} slave - */ - function hair(slave) { - let hairNode = new DocumentFragment(); - const { - // eslint-disable-next-line no-unused-vars - he, - him, - his, - hers, - himself, - boy, - He, - His - } = getPronouns(slave); - - hairNode.appendChild(hairStyle()); - hairNode.appendChild(hairColor()); - return hairNode; - - function hairStyle() { - let hairStyleNode = document.createElement('p'); - let label = document.createElement('div'); - label.append(`Custom hair description: `); - - let textbox = App.UI.DOM.makeTextBox( - slave.hStyle, - v => { - slave.hStyle = v; - App.UI.SlaveInteract.custom(slave); - }); - label.appendChild(textbox); - - switch (slave.hStyle) { - case "tails": - case "dreadlocks": - case "cornrows": - label.append(` "${His} hair is in ${slave.hStyle}."`); - break; - case "ponytail": - label.append(` "${His} hair is in a ${slave.hStyle}."`); - break; - default: - label.append(` "${His} hair is ${slave.hStyle}."`); - break; - } - hairStyleNode.appendChild(label); - - let choices = document.createElement('div'); - choices.className = "choices"; - choices.appendChild(App.UI.DOM.makeElement('span', ` For best results, use a short, uncapitalized and unpunctuated description; for example: 'back in a ponytail'`, 'note')); - hairStyleNode.appendChild(choices); - return hairStyleNode; - } - - function hairColor() { - let hairStyleNode = document.createElement('p'); - let label = document.createElement('div'); - label.append(`Custom hair color: `); - - let textbox = App.UI.DOM.makeTextBox( - slave.hColor, - v => { - slave.hColor = v; - App.UI.SlaveInteract.custom(slave); - }); - label.appendChild(textbox); - label.append(` "${His} hair is ${slave.hColor}."`); - hairStyleNode.appendChild(label); - - let choices = document.createElement('div'); - choices.className = "choices"; - choices.appendChild(App.UI.DOM.makeElement('span', ` For best results, use a short, uncapitalized and unpunctuated description; for example: 'black with purple highlights'`, 'note')); - hairStyleNode.appendChild(choices); - return hairStyleNode; - } - } - - /** - * @param {App.Entity.SlaveState} slave - */ - function eyeColor(slave) { - let eyeColorNode = document.createElement('p'); - const { - // eslint-disable-next-line no-unused-vars - he, - him, - his, - hers, - himself, - boy, - He, - His - } = getPronouns(slave); - let label = document.createElement('div'); - if (getLenseCount(slave) > 0) { - label.textContent = `${He} is wearing ${App.Desc.eyesColor(slave, "", "lense", "lenses")}.`; - } else { - label.textContent = `${He} has ${App.Desc.eyesColor(slave)}.`; - } - eyeColorNode.appendChild(label); - - let choices = document.createElement('div'); - choices.className = "choices"; - - let eye; - let textbox; - - if (hasLeftEye(slave)) { - eye = document.createElement('div'); - eye.append(`Custom left eye color: `); - textbox = App.UI.DOM.makeTextBox( - slave.eye.left.iris, - v => { - slave.eye.left.iris = v; - App.UI.SlaveInteract.custom(slave); - }); - eye.appendChild(textbox); - choices.appendChild(eye); - } - if (hasRightEye(slave)) { - eye = document.createElement('div'); - eye.append(`Custom right eye color: `); - textbox = App.UI.DOM.makeTextBox( - slave.eye.right.iris, - v => { - slave.eye.right.iris = v; - App.UI.SlaveInteract.custom(slave); - }); - eye.appendChild(textbox); - choices.appendChild(eye); - } - choices.appendChild(App.UI.DOM.makeElement('span', `For best results, use a short, uncapitalized and unpunctuated description; for example: 'blue'`, 'note')); - eyeColorNode.appendChild(choices); - return eyeColorNode; - } - - /** - * @param {App.Entity.SlaveState} slave - */ - function customTattoo(slave) { - let el = document.createElement('p'); - const { - // eslint-disable-next-line no-unused-vars - he, - him, - his, - hers, - himself, - boy, - He, - His - } = getPronouns(slave); - el.append(`Change ${his} custom tattoo: `); - el.appendChild(App.UI.DOM.makeTextBox( - slave.custom.tattoo, - v => { - slave.custom.tattoo = v; - App.UI.SlaveInteract.custom(slave); - })); - - let choices = document.createElement('div'); - choices.className = "choices"; - choices.appendChild(App.UI.DOM.makeElement('span', `For best results, use complete sentences; for example: '${He} has blue stars tattooed along ${his} cheekbones.'`, 'note')); - el.appendChild(choices); - - return el; - } - - function customOriginStory(slave) { - let el = document.createElement('p'); - const { - // eslint-disable-next-line no-unused-vars - he, - him, - his, - hers, - himself, - boy, - He, - His - } = getPronouns(slave); - - el.append(`Change ${his} origin story: `); - el.appendChild(App.UI.DOM.makeTextBox( - slave.origin, - v => { - slave.origin = v; - App.UI.SlaveInteract.custom(slave); - })); - - let choices = document.createElement('div'); - choices.className = "choices"; - choices.appendChild(App.UI.DOM.makeElement('span', ` For best results, use complete, capitalized and punctuated sentences; for example: '${He} followed you home from the pet store.'`, 'note')); - el.appendChild(choices); - - return el; - } - - function customDescription(slave) { - let el = document.createElement('p'); - const { - // eslint-disable-next-line no-unused-vars - he, - him, - his, - hers, - himself, - boy, - He, - His - } = getPronouns(slave); - - el.append(`Change ${his} custom description: `); - el.appendChild(App.UI.DOM.makeTextBox( - pronounsForSlaveProp(slave, slave.custom.desc), - v => { - slave.custom.desc = v; - App.UI.SlaveInteract.custom(slave); - })); - - let choices = document.createElement('div'); - choices.className = "choices"; - choices.appendChild(App.UI.DOM.makeElement('span', ` For best results, use complete, capitalized and punctuated sentences; for example: '${He} has a beauty mark above ${his} left nipple.'`, 'note')); - el.appendChild(choices); - - return el; - } - - function customLabel(slave) { - let el = document.createElement('p'); - const { - // eslint-disable-next-line no-unused-vars - he, - him, - his, - hers, - himself, - boy, - He, - His - } = getPronouns(slave); - - el.append(`Change ${his} custom label: `); - el.appendChild(App.UI.DOM.makeTextBox( - slave.custom.label, - v => { - slave.custom.label = v; - App.UI.SlaveInteract.custom(slave); - })); - - let choices = document.createElement('div'); - choices.className = "choices"; - choices.appendChild(App.UI.DOM.makeElement('span', ` For best results, use a short phrase; for example: 'Breeder.'`, 'note')); - el.appendChild(choices); - - return el; - } - - - function customSlaveImage(slave) { - let el = document.createElement('p'); - const { - // eslint-disable-next-line no-unused-vars - he, - him, - his, - hers, - himself, - boy, - He, - His - } = getPronouns(slave); - el.append(`Assign ${him} a custom image: `); - - let textbox = document.createElement("INPUT"); - textbox.id = "customImageValue"; - el.appendChild(textbox); - - - let kbd = document.createElement('kbd'); - let select = document.createElement('SELECT'); - select.id = "customImageFormatSelector"; - select.style.border = "none"; - - let filetypes = [ - "png", - "jpg", - "gif", - "webm", - "webp", - "mp4" - ]; - - filetypes.forEach((fileType) => { - let el = document.createElement('OPTION'); - el.value = fileType; - el.text = fileType.toUpperCase(); - select.add(el); - }); - kbd.append(`.`); - kbd.appendChild(select); - el.appendChild(kbd); - - el.appendChild( - App.UI.DOM.link( - ` Reset`, - () => { - slave.custom.image = null; - App.UI.SlaveInteract.custom(slave); - App.Art.refreshSlaveArt(slave, 3, "art-frame"); - }, - ) - ); - - let choices = document.createElement('div'); - choices.className = "choices"; - let note = document.createElement('span'); - note.className = "note"; - note.append(`Place file in the `); - - kbd = document.createElement('kbd'); - kbd.append(`resources`); - note.appendChild(kbd); - - note.append(` folder. Choose the extension from the menu first, then enter the filename in the space and press enter. For example, for a file with the path `); - - kbd = document.createElement('kbd'); - kbd.textContent = `\\bin\\resources\\headgirl.`; - let filetypeDesc = document.createElement('span'); - filetypeDesc.id = "customImageFormatValue"; - filetypeDesc.textContent = "png"; - kbd.appendChild(filetypeDesc); - note.appendChild(kbd); - - note.append(`, choose `); - - kbd = document.createElement('kbd'); - kbd.textContent = `PNG`; - note.appendChild(kbd); - - note.append(` then enter `); - - kbd = document.createElement('kbd'); - kbd.textContent = `headgirl`; - note.appendChild(kbd); - - note.append(`.`); - choices.appendChild(note); - el.appendChild(choices); - - jQuery(function() { - function activeSlave() { - return slave; - } - - jQuery("#customImageFormatValue").text(activeSlave().custom.image === null ? "png" : activeSlave().custom.image.format); - jQuery("#customImageValue") - .val(activeSlave().custom.image === null ? - "" : activeSlave().custom.image.filename) - .on("change", function(e) { - const c = activeSlave().custom; - if (this.value.length === 0) { - c.image = null; - } else { - if (c.image === null) { - c.image = { - filename: this.value, - format: jQuery("#customImageFormatSelector").val() - }; - App.Art.refreshSlaveArt(slave, 3, "art-frame"); - } else { - c.image.filename = this.value; - App.Art.refreshSlaveArt(slave, 3, "art-frame"); - } - } - }); - jQuery("#customImageFormatSelector") - .val(activeSlave().custom.image ? activeSlave().custom.image.format : "png") - .on("change", function(e) { - if (activeSlave().custom.image !== null) { - activeSlave().custom.image.format = this.value; - } - jQuery("#customImageFormatValue").text(this.value); - }); - }); - return el; - } - - function customHairImage(slave) { - let el = document.createElement('p'); - const { - // eslint-disable-next-line no-unused-vars - he, - him, - his, - hers, - himself, - boy, - He, - His - } = getPronouns(slave); - - if (V.seeImages === 1 && V.imageChoice === 1) { - if (!slave.custom.hairVector) { - slave.custom.hairVector = 0; - } - el.append(`Assign ${him} a custom hair SVG image: `); - - el.appendChild(App.UI.DOM.makeTextBox( - slave.custom.hairVector, - v => { - slave.custom.hairVector = v; - App.UI.SlaveInteract.custom(slave); - })); - - el.appendChild( - App.UI.DOM.link( - ` Reset`, - () => { - slave.custom.hairVector = 0; - App.UI.SlaveInteract.custom(slave); - App.Art.refreshSlaveArt(slave, 3, "art-frame"); - }, - ) - ); - } - - return el; - } -})(); - -/** @typedef RowItem - * @type {object} - * @property {string} [FS] - FS requirement, if any - * @property {string} [text] - link text - * @property {object} [updateSlave] - properties to be merged onto the slave - * @property {object} [update] - properties to be merged into global state - * @property {string} [disabled] - text indicating why the option is unavailable - * @property {string} [note] - */ - -/** Append a simple row of choices with a label to a container, if there are choices to be made. - * @param {Node} parent - * @param {string} label - * @param {RowItem[]} array - * @param {App.Entity.SlaveState} slave - */ -App.UI.SlaveInteract.appendLabeledChoiceRow = function(parent, label, array, slave) { - if (array.length > 0) { - let links = document.createElement('div'); - links.append(`${label}: `); - links.appendChild(App.UI.SlaveInteract.generateRows(array, slave)); - links.className = "choices"; - return parent.appendChild(links); - } -}; - -/** Generate a row of choices - * @param {RowItem[]} array - * @param {App.Entity.SlaveState} slave - * @param {string} [category] - should be in the form of slave.category, the thing we want to update. - * @param {boolean} [accessCheck=false] - * @returns {HTMLSpanElement} - */ -App.UI.SlaveInteract.generateRows = function(array, slave, category, accessCheck = false) { - let row = document.createElement('span'); - let useSep = false; - for (let i = 0; i < array.length; i++) { - let link; - const separator = document.createTextNode(` | `); - const keys = Object.keys(array[i]); - - // Test to see if there was a problem with the key - for (let j = 0; j < keys.length; j++) { - if (["FS", "text", "updateSlave", "update", "note", "disabled"].includes(keys[j])) { - continue; - } else { - array[i].text += " ERROR, THIS SCENE WAS NOT ENTERED CORRECTLY"; - console.log("Trash found while generateRows() was running: " + keys[j] + ": " + array[i][keys[j]]); - break; - } - } - // Some items will never be in App.Data.slaveWear, especially "none" if it falls in between harsh and nice data sets. Trying to look it up would cause an error, which is what access check works around. - let unlocked = false; - if (accessCheck === true) { - if (category === "chastity") { - let text = array[i].text.toLowerCase(); // Yucky. Category name does not match for chastity (since it sets multiple kinds of chastity at once). Compare using a lowercase name instead. - unlocked = isItemAccessible.entry(text, category, slave); - } else { - unlocked = isItemAccessible.entry(array[i].updateSlave[category], category, slave); - } - } - if (accessCheck === false || unlocked) { - if (i < array.length && i !== 0 && useSep === true) { // start with separator (after first loop); can't after since the last loop may not have any text. - row.appendChild(separator); - } - useSep = true; // First item may not appear and if it doesn't we don't want the second to start with a '|' - // is it just text? - if (array[i].disabled) { - link = App.UI.DOM.disabledLink(array[i].text, [array[i].disabled]); - } else if (typeof unlocked === 'string') { - link = App.UI.DOM.disabledLink(array[i].text, [unlocked]); - } else { - link = document.createElement('span'); - - // Set up the link - link.appendChild( - App.UI.DOM.link( - `${array[i].text} `, - () => { click(array[i]); }, - ) - ); - - if (array[i].FS) { - let FS = App.UI.DOM.disabledLink(`FS`, [FutureSocieties.displayAdj(array[i].FS)]); - FS.style.fontStyle = "italic"; - link.appendChild(FS); - } - - // add a note node if required - if (array[i].note) { - link.appendChild(App.UI.DOM.makeElement('span', ` ${array[i].note}`, 'note')); - } - } - row.appendChild(link); - } - } - - return row; - - /** @param {RowItem} arrayOption */ - function click(arrayOption) { - if (arrayOption.updateSlave) { - for (const slaveProperty in arrayOption.updateSlave) { - _.set(slave, slaveProperty, arrayOption.updateSlave[slaveProperty]); - } - } - if (arrayOption.update) { - Object.assign(V, arrayOption.update); - } - App.UI.Wardrobe.refreshAll(slave); - App.UI.SlaveInteract.refreshAll(slave); - } -}; - -App.UI.SlaveInteract.refreshAll = function(slave) { - App.UI.SlaveInteract.drugs(slave); - App.UI.SlaveInteract.bloating(slave); - App.UI.SlaveInteract.fertility(slave); - App.UI.SlaveInteract.curatives(slave); - App.UI.SlaveInteract.aphrodisiacs(slave); - App.UI.SlaveInteract.incubator(slave); - App.UI.SlaveInteract.nursery(slave); - App.UI.SlaveInteract.custom(slave); - App.UI.SlaveInteract.hormones(slave); - App.UI.SlaveInteract.diet(slave); - App.UI.SlaveInteract.dietBase(slave); - App.UI.SlaveInteract.snacks(slave); - App.UI.SlaveInteract.rules(slave); - App.UI.SlaveInteract.work(slave); }; diff --git a/src/interaction/wardrobeUse.js b/src/interaction/wardrobeUse.js deleted file mode 100644 index 772d8800f22d362d24390ad902940a9c8e6c0f86..0000000000000000000000000000000000000000 --- a/src/interaction/wardrobeUse.js +++ /dev/null @@ -1,888 +0,0 @@ -App.UI.Wardrobe = {}; - -App.UI.Wardrobe.clothes = function(slave) { - const { - // eslint-disable-next-line no-unused-vars - he, him, his, hers, himself, boy, He, His - } = getPronouns(slave); - - let el = document.createElement('div'); - let links; - if (slave.fuckdoll === 0) { - // <<= App.Desc.clothing($activeSlave)>> - - let label = document.createElement('div'); - label.append(`Clothes: `); - - let choice = document.createElement('span'); - choice.style.fontWeight = "bold"; - choice.textContent = (`${slave.clothes} `); - label.appendChild(choice); - - // Choose her own - if (slave.clothes !== `choosing her own clothes`) { - let choiceOptionsArray = []; - choiceOptionsArray.push({text: `Let ${him} choose`, updateSlave: {clothes: `choosing her own clothes`, choosesOwnClothes: 1}}); - label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "clothes", false)); - } - el.appendChild(label); - - - let niceOptionsArray = []; - let harshOptionsArray = []; - - let clothingOption; - // Nice clothes - App.Data.slaveWear.niceClothes.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {clothes: item.value, choosesOwnClothes: 0}, - FS: item.fs - }; - niceOptionsArray.push(clothingOption); - }); - // Harsh clothes - App.Data.slaveWear.harshClothes.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {clothes: item.value, choosesOwnClothes: 0}, - FS: item.fs - }; - if (item.value !== "choosing her own clothes") { - harshOptionsArray.push(clothingOption); - } - }); - - // Sort - niceOptionsArray = niceOptionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); - harshOptionsArray = harshOptionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); - - // Nice options - links = document.createElement('div'); - links.className = "choices"; - links.append(`Nice: `); - links.appendChild(App.UI.SlaveInteract.generateRows(niceOptionsArray, slave, "clothes", true)); - el.appendChild(links); - - // Harsh options - links = document.createElement('div'); - links.className = "choices"; - links.append(`Harsh: `); - links.appendChild(App.UI.SlaveInteract.generateRows(harshOptionsArray, slave, "clothes", true)); - el.appendChild(links); - } - if (slave.fuckdoll !== 0 || slave.clothes === "restrictive latex" || slave.clothes === "a latex catsuit" || slave.clothes === "a cybersuit" || slave.clothes === "a comfortable bodysuit") { - if (V.seeImages === 1 && V.imageChoice === 1) { - // Color options - links = document.createElement('div'); - links.className = "choices"; - links.append(`Color: `); - links.appendChild(App.UI.Wardrobe.colorOptions(slave, "clothingBaseColor")); - el.appendChild(links); - } - } - - return jQuery('#clothes').empty().append(el); -}; - -App.UI.Wardrobe.collar = function(slave) { - if (slave.fuckdoll !== 0) { - return; - } - // <<= App.Desc.collar($activeSlave)>> - let el = document.createElement('div'); - - let label = document.createElement('div'); - label.append(`Collar: `); - - let choice = document.createElement('span'); - choice.style.fontWeight = "bold"; - choice.textContent = (`${slave.collar} `); - label.appendChild(choice); - - // Choose her own - if (slave.collar !== `none`) { - let choiceOptionsArray = []; - choiceOptionsArray.push({text: `None`, updateSlave: {collar: `none`}}); - label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "collar", false)); - } - - el.appendChild(label); - - let niceOptionsArray = []; - let harshOptionsArray = []; - - let clothingOption; - // Nice collar - App.Data.slaveWear.niceCollars.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {collar: item.value}, - FS: item.fs - }; - niceOptionsArray.push(clothingOption); - }); - // Harsh collar - App.Data.slaveWear.harshCollars.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {collar: item.value}, - FS: item.fs - }; - harshOptionsArray.push(clothingOption); - }); - - // Sort - niceOptionsArray = niceOptionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); - harshOptionsArray = harshOptionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); - - // Nice options - let links = document.createElement('div'); - links.className = "choices"; - links.append(`Nice: `); - links.appendChild(App.UI.SlaveInteract.generateRows(niceOptionsArray, slave, "collar", true)); - el.appendChild(links); - - // Harsh options - links = document.createElement('div'); - links.className = "choices"; - links.append(`Harsh: `); - links.appendChild(App.UI.SlaveInteract.generateRows(harshOptionsArray, slave, "collar", true)); - el.appendChild(links); - - return jQuery('#collar').empty().append(el); -}; - -App.UI.Wardrobe.mask = function(slave) { - if (slave.fuckdoll !== 0) { - return; - } - let el = document.createElement('div'); - - let label = document.createElement('div'); - label.append(`Mask: `); - - let choice = document.createElement('span'); - choice.style.fontWeight = "bold"; - choice.textContent = (`${slave.faceAccessory} `); - label.appendChild(choice); - - // Choose her own - if (slave.faceAccessory !== `none`) { - let choiceOptionsArray = []; - choiceOptionsArray.push({text: `None`, updateSlave: {faceAccessory: `none`}}); - label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "faceAccessory", false)); - } - - el.appendChild(label); - - let array = []; - - let clothingOption; - App.Data.slaveWear.faceAccessory.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {faceAccessory: item.value}, - FS: item.fs - }; - array.push(clothingOption); - }); - - // Sort - array = array.sort((a, b) => (a.text > b.text) ? 1 : -1); - - let links = document.createElement('div'); - links.className = "choices"; - links.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "faceAccessory", true)); - el.appendChild(links); - - if (slave.eyewear === "corrective glasses" || slave.eyewear === "glasses" || slave.eyewear === "blurring glasses" || slave.faceAccessory === "porcelain mask") { - // Color options - links = document.createElement('div'); - links.className = "choices"; - links.append(`Color: `); - links.appendChild(App.UI.Wardrobe.colorOptions(slave, "glassesColor")); - let note = document.createElement('span'); - note.className = "note"; - note.textContent = ` Only glasses and porcelain masks support a custom color. If both are worn, they will share the same color.`; - links.appendChild(note); - el.appendChild(links); - } - - return jQuery('#faceAccessory').empty().append(el); -}; - -App.UI.Wardrobe.mouth = function(slave) { - if (slave.fuckdoll !== 0) { - return; - } - let el = document.createElement('div'); - - let label = document.createElement('div'); - label.append(`Gag: `); - - let choice = document.createElement('span'); - choice.style.fontWeight = "bold"; - choice.textContent = (`${slave.mouthAccessory} `); - label.appendChild(choice); - - // Choose her own - if (slave.mouthAccessory !== `none`) { - let choiceOptionsArray = []; - choiceOptionsArray.push({text: `None`, updateSlave: {mouthAccessory: `none`}}); - label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "mouthAccessory", false)); - } - - el.appendChild(label); - - let array = []; - - let clothingOption; - // mouthAccessory - App.Data.slaveWear.mouthAccessory.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {mouthAccessory: item.value}, - FS: item.fs - }; - array.push(clothingOption); - }); - - // Sort - array = array.sort((a, b) => (a.text > b.text) ? 1 : -1); - - let links = document.createElement('div'); - links.className = "choices"; - links.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "mouthAccessory", true)); - el.appendChild(links); - - return jQuery('#mouthAccessory').empty().append(el); -}; - -App.UI.Wardrobe.armAccessory = function(slave) { - if (slave.fuckdoll !== 0) { - return; - } - - let el = document.createElement('div'); - // App.Desc.armwear(slave) - - let label = document.createElement('div'); - label.append(`Arm accessory: `); - - let choice = document.createElement('span'); - choice.style.fontWeight = "bold"; - choice.textContent = (`${slave.armAccessory} `); - label.appendChild(choice); - - let array = []; - - // Choose her own - if (slave.armAccessory !== "none") { - array.push({text: `None`, updateSlave: {armAccessory: `none`}}); - label.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "armAccessory", false)); - } - - el.appendChild(label); - - let links = document.createElement('div'); - links.className = "choices"; - array = [ - {text: "Hand gloves", updateSlave: {armAccessory: "hand gloves"}}, - {text: "Elbow gloves", updateSlave: {armAccessory: "elbow gloves"}} - ]; - links.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "armAccessory", false)); - el.appendChild(links); - - return jQuery('#armAccessory').empty().append(el); -}; - -App.UI.Wardrobe.shoes = function(slave) { - if (slave.fuckdoll !== 0) { - return; - } - - const - { - // eslint-disable-next-line no-unused-vars - he, him, his, hers, himself, boy, He, His - } = getPronouns(slave); - - let el = document.createElement('div'); - - let label = document.createElement('div'); - label.append(`Shoes: `); - - let choice = document.createElement('span'); - choice.style.fontWeight = "bold"; - choice.textContent = (`${slave.shoes} `); - label.appendChild(choice); - - /* We have "barefoot" in App.Data.slaveWear to cover for this - // Choose her own - if (slave.shoes !== `none`) { - let choiceOptionsArray = []; - choiceOptionsArray.push({text: `None`, updateSlave: {shoes: `none`}}); - label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "shoes", false)); - } - */ - el.appendChild(label); - - let optionsArray = []; - - let clothingOption; - App.Data.slaveWear.shoes.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {shoes: item.value}, - FS: item.fs - }; - optionsArray.push(clothingOption); - }); - - // Sort - // No sort here since we want light -> advanced. optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); - - // Options - let links = document.createElement('div'); - links.className = "choices"; - links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "shoes", true)); - el.appendChild(links); - - if (V.seeImages === 1 && V.imageChoice === 1 && slave.shoes !== "none") { - // Color options - links = document.createElement('div'); - links.className = "choices"; - links.append(`Color: `); - links.appendChild(App.UI.Wardrobe.colorOptions(slave, "shoeColor")); - el.appendChild(links); - } - - return jQuery('#shoes').empty().append(el); -}; - -App.UI.Wardrobe.legAccessory = function(slave) { - if (slave.fuckdoll !== 0) { - return; - } - - const { - // eslint-disable-next-line no-unused-vars - he, him, his, hers, himself, boy, He, His - } = getPronouns(slave); - - let el = document.createElement('div'); - - let label = document.createElement('div'); - label.append(`Leg accessory: `); - - let choice = document.createElement('span'); - choice.style.fontWeight = "bold"; - choice.textContent = (`${slave.legAccessory} `); - label.appendChild(choice); - - let array = []; - - // Choose her own - if (slave.legAccessory !== "none") { - array.push({text: `None`, updateSlave: {legAccessory: `none`}}); - label.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "legAccessory", false)); - } - - el.appendChild(label); - - let links = document.createElement('div'); - links.className = "choices"; - array = [ - {text: "Short stockings", updateSlave: {legAccessory: "short stockings"}}, - {text: "Long stockings", updateSlave: {legAccessory: "long stockings"}} - ]; - links.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "legAccessory", false)); - el.appendChild(links); - - return jQuery('#legAccessory').empty().append(el); -}; - -App.UI.Wardrobe.bellyAccessory = function(slave) { - if (slave.fuckdoll !== 0) { - return; - } - // <<waistDescription>><<= App.Desc.pregnancy($activeSlave)>><<clothingCorsetDescription>> - - const { - // eslint-disable-next-line no-unused-vars - he, him, his, hers, himself, boy, He, His - } = getPronouns(slave); - - let choiceOptionsArray = []; - choiceOptionsArray.push({text: `None`, updateSlave: {bellyAccessory: `none`}}); - - let optionsArray = []; - - let clothingOption; - App.Data.slaveWear.bellyAccessories.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {bellyAccessory: item.value}, - FS: item.fs - }; - if (item.value !== "none") { - // skip none in set, we set the link elsewhere. - optionsArray.push(clothingOption); - } - }); - // Sort - // No sort here since we want small -> large.optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); - - let el = document.createElement('div'); - - let label = document.createElement('div'); - label.append(`Belly accessory: `); - - let choice = document.createElement('span'); - choice.style.fontWeight = "bold"; - choice.textContent = (`${slave.bellyAccessory} `); - label.appendChild(choice); - - // Choose her own - if (slave.bellyAccessory !== `none`) { - label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "bellyAccessory", false)); - } - - el.appendChild(label); - - // Options - let links = document.createElement('div'); - links.className = "choices"; - links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "bellyAccessory", true)); - if (slave.pregKnown === 1) { - let note = document.createElement('span'); - note.className = "note"; - note.textContent = ` Extreme corsets will endanger the life within ${him}.`; - links.appendChild(note); - } - el.appendChild(links); - - return jQuery('#bellyAccessory').empty().append(el); -}; - -App.UI.Wardrobe.buttplug = function(slave) { - if (slave.fuckdoll !== 0) { - return; - } - // App.Desc.buttplug(slave) - - const { - // eslint-disable-next-line no-unused-vars - he, him, his, hers, himself, boy, He, His - } = getPronouns(slave); - - let el = document.createElement('div'); - - let label = document.createElement('div'); - label.append(`Anal accessory: `); - - let choice = document.createElement('span'); - choice.style.fontWeight = "bold"; - choice.textContent = (`${slave.buttplug} `); - label.appendChild(choice); - - if (slave.buttplug !== `none`) { - let choiceOptionsArray = []; - choiceOptionsArray.push({text: `None`, updateSlave: {buttplug: `none`, buttplugAttachment: `none`}}); - label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "buttplug", false)); - } - el.appendChild(label); - - let optionsArray = []; - - let clothingOption; - App.Data.slaveWear.buttplugs.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {buttplug: item.value}, - FS: item.fs - }; - if (item.value !== "none") { - // skip none in set, we set the link elsewhere. - optionsArray.push(clothingOption); - } - }); - - // Sort - // No sort here since we want small -> large. optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); - - // Options - let links = document.createElement('div'); - links.className = "choices"; - links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "buttplug", true)); - el.appendChild(links); - - return jQuery('#buttplug').empty().append(el); -}; - -App.UI.Wardrobe.buttplugAttachment = function(slave) { - if (slave.fuckdoll !== 0) { - return; - } else if (slave.buttplug === "none") { - return jQuery('#buttplugAttachment').empty(); - } - - const { - // eslint-disable-next-line no-unused-vars - he, him, his, hers, himself, boy, He, His - } = getPronouns(slave); - - let el = document.createElement('div'); - - let label = document.createElement('div'); - label.append(`Anal accessory attachment: `); - - let choice = document.createElement('span'); - choice.style.fontWeight = "bold"; - choice.textContent = (`${slave.buttplugAttachment} `); - label.appendChild(choice); - - if (slave.buttplugAttachment !== `none`) { - let choiceOptionsArray = []; - choiceOptionsArray.push({text: `None`, updateSlave: {buttplugAttachment: `none`}}); - label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "buttplugAttachment", false)); - } - el.appendChild(label); - - let optionsArray = []; - - let clothingOption; - App.Data.slaveWear.buttplugAttachments.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {buttplugAttachment: item.value}, - FS: item.fs - }; - if (item.value !== "none") { - // skip none in set, we set the link elsewhere. - optionsArray.push(clothingOption); - } - }); - - // Sort - optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); - - // Options - let links = document.createElement('div'); - links.className = "choices"; - links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "buttplugAttachment", true)); - el.appendChild(links); - - return jQuery('#buttplugAttachment').empty().append(el); -}; - -App.UI.Wardrobe.vaginalAccessory = function(slave) { - if (slave.fuckdoll !== 0) { - return; - } - - // <<vaginalAccessoryDescription>> - const { - // eslint-disable-next-line no-unused-vars - he, him, his, hers, himself, boy, He, His - } = getPronouns(slave); - - let el = document.createElement('div'); - - let label = document.createElement('div'); - label.append(`Vaginal accessory: `); - - let choice = document.createElement('span'); - choice.style.fontWeight = "bold"; - choice.textContent = (`${slave.vaginalAccessory} `); - label.appendChild(choice); - - if (slave.vaginalAccessory !== `none`) { - let choiceOptionsArray = []; - choiceOptionsArray.push({text: `None`, updateSlave: {vaginalAccessory: `none`}}); - label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "vaginalAccessory", false)); - } - el.appendChild(label); - - let optionsArray = []; - - let clothingOption; - App.Data.slaveWear.vaginalAccessories.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {vaginalAccessory: item.value}, - FS: item.fs - }; - if (item.value !== "none") { - // skip none in set, we set the link elsewhere. - optionsArray.push(clothingOption); - } - }); - - // Sort - // No sort here since we want small -> large. optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); - - // Options - let links = document.createElement('div'); - links.className = "choices"; - links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "vaginalAccessory", true)); - el.appendChild(links); - - return jQuery('#vaginalAccessory').empty().append(el); -}; - -App.UI.Wardrobe.vaginalAttachment = function(slave) { - if (slave.fuckdoll !== 0) { - return; - } else if (["none", "bullet vibrator", "smart bullet vibrator"].includes(slave.vaginalAccessory)) { - return jQuery('#vaginalAttachment').empty(); - } - // App.Desc.vaginalAttachment(slave); - - const { - // eslint-disable-next-line no-unused-vars - he, him, his, hers, himself, boy, He, His - } = getPronouns(slave); - - let el = document.createElement('div'); - - let label = document.createElement('div'); - label.append(`Vaginal accessory attachment: `); - - let choice = document.createElement('span'); - choice.style.fontWeight = "bold"; - choice.textContent = (`${slave.vaginalAttachment} `); - label.appendChild(choice); - - if (slave.vaginalAttachment !== `none`) { - let choiceOptionsArray = []; - choiceOptionsArray.push({text: `None`, updateSlave: {vaginalAttachment: `none`}}); - label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "vaginalAttachment", false)); - } - el.appendChild(label); - - let optionsArray = []; - - let clothingOption; - App.Data.slaveWear.vaginalAttachments.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {vaginalAttachment: item.value}, - FS: item.fs - }; - if (item.value !== "none") { - // skip none in set, we set the link elsewhere. - optionsArray.push(clothingOption); - } - }); - - // Sort - optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); - - // Options - let links = document.createElement('div'); - links.className = "choices"; - links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "vaginalAttachment", true)); - el.appendChild(links); - - return jQuery('#vaginalAttachment').empty().append(el); -}; - -App.UI.Wardrobe.dickAccessory = function(slave) { - if (slave.fuckdoll !== 0) { - return; - } - // <<= App.Desc.dickAccessory($activeSlave)>> - - const { - // eslint-disable-next-line no-unused-vars - he, him, his, hers, himself, boy, He, His - } = getPronouns(slave); - - let el = document.createElement('div'); - - let label = document.createElement('div'); - label.append(`Dick accessory: `); - - let choice = document.createElement('span'); - choice.style.fontWeight = "bold"; - choice.textContent = (`${slave.dickAccessory} `); - label.appendChild(choice); - - if (slave.dickAccessory !== `none`) { - let choiceOptionsArray = []; - choiceOptionsArray.push({text: `None`, updateSlave: {dickAccessory: `none`}}); - label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "dickAccessory", false)); - } - el.appendChild(label); - - let optionsArray = []; - - let clothingOption; - App.Data.slaveWear.dickAccessories.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {dickAccessory: item.value}, - FS: item.fs - }; - if (item.value !== "none") { - // skip none in set, we set the link elsewhere. - optionsArray.push(clothingOption); - } - }); - - // Sort - // No sort here since we want small -> large. optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); - - // Options - let links = document.createElement('div'); - links.className = "choices"; - links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "dickAccessory", true)); - el.appendChild(links); - - return jQuery('#dickAccessory').empty().append(el); -}; - -App.UI.Wardrobe.chastity = function(slave) { - if (slave.fuckdoll !== 0) { - return; - } - - const { - // eslint-disable-next-line no-unused-vars - he, him, his, hers, himself, boy, He, His - } = getPronouns(slave); - - let el = document.createElement('div'); - - let label = document.createElement('div'); - label.append(`Chastity devices: `); - - let choice = document.createElement('span'); - choice.style.fontWeight = "bold"; - if (slave.choosesOwnChastity === 1) { - choice.textContent = `choosing ${his} own chastity `; - } else if (slave.chastityAnus === 1 && slave.chastityPenis === 1 && slave.chastityVagina === 1) { - choice.textContent = `full chastity `; - } else if (slave.chastityPenis === 1 && slave.chastityVagina === 1) { - choice.textContent = `genital chastity `; - } else if (slave.chastityAnus === 1 && slave.chastityPenis === 1) { - choice.textContent = `combined chastity cage `; - } else if (slave.chastityAnus === 1 && slave.chastityVagina === 1) { - choice.textContent = `combined chastity belt `; - } else if (slave.chastityVagina === 1) { - choice.textContent = `chastity belt `; - } else if (slave.chastityPenis === 1) { - choice.textContent = `chastity cage `; - } else if (slave.chastityAnus === 1) { - choice.textContent = `anal chastity `; - } else if (slave.chastityAnus === 0 && slave.chastityPenis === 0 && slave.chastityVagina === 0) { - choice.textContent = `none `; - } else { - choice.textContent = `THERE HAS BEEN AN ERROR `; - } - label.appendChild(choice); - - if (slave.chastityAnus !== 0 || slave.chastityPenis !== 0 || slave.chastityVagina !== 0) { - let choiceOptionsArray = []; - choiceOptionsArray.push({ - text: `None`, - updateSlave: { - choosesOwnChastity: 0, - chastityAnus: 0, - chastityPenis: 0, - chastityVagina: 0 - } - }); - label.appendChild(App.UI.SlaveInteract.generateRows(choiceOptionsArray, slave, "chastity", false)); - } - el.appendChild(label); - - let optionsArray = []; - - let clothingOption; - App.Data.slaveWear.chastityDevices.forEach(item => { - clothingOption = { - text: item.name, - updateSlave: {}, - FS: item.fs - }; - Object.assign(clothingOption.updateSlave, item.updateSlave); - if (item.value !== "none") { - // skip none in set, we set the link elsewhere. - optionsArray.push(clothingOption); - } - }); - - // Sort - // skip sort for this one too. optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); - - // Options - let links = document.createElement('div'); - links.className = "choices"; - links.appendChild(App.UI.SlaveInteract.generateRows(optionsArray, slave, "chastity", true)); - el.appendChild(links); - - return jQuery('#chastity').empty().append(el); -}; - -App.UI.Wardrobe.shopping = function(slave) { - return jQuery('#shopping').empty().append( - App.UI.DOM.link( - ` Go shopping for more options`, - () => {}, - [], - "Wardrobe" - ) - ); -}; - -/** - * @param {App.Entity.SlaveState} slave - * @param {string} update - * @returns {Node} - */ -App.UI.Wardrobe.colorOptions = function(slave, update) { - let el = new DocumentFragment(); - let colorChoice = App.UI.DOM.colorInput( - slave[update], - v => { - slave[update] = v; - App.UI.Wardrobe.refreshAll(slave); - } - ); - el.appendChild(colorChoice); - - if (slave[update]) { - el.appendChild( - App.UI.DOM.link( - ` Reset`, - () => { - delete slave[update]; - App.UI.Wardrobe.refreshAll(slave); - }, - ) - ); - } - return el; -}; - -App.UI.Wardrobe.refreshAll = function(slave) { - App.UI.Wardrobe.clothes(slave); - App.UI.Wardrobe.collar(slave); - App.UI.Wardrobe.mask(slave); - App.UI.Wardrobe.mouth(slave); - App.UI.Wardrobe.armAccessory(slave); - App.UI.Wardrobe.shoes(slave); - App.UI.Wardrobe.legAccessory(slave); - App.UI.Wardrobe.bellyAccessory(slave); - App.UI.Wardrobe.buttplug(slave); - App.UI.Wardrobe.buttplugAttachment(slave); - App.UI.Wardrobe.vaginalAccessory(slave); - App.UI.Wardrobe.vaginalAttachment(slave); - App.UI.Wardrobe.dickAccessory(slave); - App.UI.Wardrobe.chastity(slave); - App.Art.refreshSlaveArt(slave, 3, "art-frame"); - return; -}; diff --git a/src/js/assignJS.js b/src/js/assignJS.js index a5443a2aeaf933f5a52d7d9592ffcf967e4ae149..e97de34a35526f832da7436bfc9885799b9d9194 100644 --- a/src/js/assignJS.js +++ b/src/js/assignJS.js @@ -495,8 +495,12 @@ globalThis.removeJob = function(slave, assignment, saveRecord = false) { const idx = V.slaveIndices[slave.ID]; if (assignment === Job.PIT) { - V.pit.fighterIDs.delete(slave.ID); - V.JobIDMap[Job.PIT].delete(slave.ID); + if (V.pit) { + V.pit.fighterIDs.delete(slave.ID); + V.JobIDMap[Job.PIT].delete(slave.ID); + } else { + return; // TODO: should this return or just continue? + } } else if (assignment === Job.LURCHER) { if (V.LurcherID === slave.ID) { V.LurcherID = 0; diff --git a/src/js/birth/birth.js b/src/js/birth/birth.js index 6bd70abd8108d3ac0faf6f794ad792ed9a7460ac..f0b4f8f07a5473c6e929dc5f9930b5ecf38851da 100644 --- a/src/js/birth/birth.js +++ b/src/js/birth/birth.js @@ -37,6 +37,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) let numStillborn = 0; let babiesBeingBorn; let numBeingBorn; + let compoundCondition; const oldDevotion = slave.devotion; const babies = (slave.pregType > 1) ? `babies` : `baby`; const children = (slave.pregType > 1) ? `children` : `child`; @@ -47,16 +48,19 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) He, His, he, his, him, himself, wife, girl } = getPronouns(slave); - + if (V.seeImages && V.seeReportImages) { + App.UI.DOM.appendNewElement("div", el, App.Art.SlaveArtElement(slave, 2), ["imageRef", "medImg"]); + } el.append(titleText()); - const postBirthReactionText = postBirthReaction(); // update birthDamage at this time suddenBirthCheck(); el.append(preBirthScene()); + el.append(calcBirthDamage()); if (!slaveDead) { birthCalc(); + el.append(postBirthScene()); el.append(birthMainScene()); if (!slaveDead) { - el.append(postBirthReactionText); + el.append(postBirthReaction()); } el.append(birthBabies()); if (numStillborn) { @@ -179,167 +183,16 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) function preBirthScene() { const el = new DocumentFragment(); const r = []; - if (V.seeImages && V.seeReportImages) { - App.UI.DOM.appendNewElement("div", el, App.Art.SlaveArtElement(slave, 2), ["imageRef", "medImg"]); - } if (birthStorm) { r.push(`The remote surgery allows the removal of the pregnancy generator through conventional means, an injection to induce labor and the resulting birthing of the womb's contents.`); - if (slave.broodmother === 2) { - r.push(`${slave.slaveName}'s obscenely swollen belly begins to shudder and writhe moments after being injected with the drug as all ${his} waters break. ${He} spreads ${his}`); - if (hasBothLegs(slave)) { - r.push(`legs to either side of ${his} spasming bulk`); - } else if (!hasAnyLegs(slave)) { - r.push(`stumps`); - } else { - r.push(`leg and ${his} stump`); - } - r.push(`as wide as ${he} can with a loud moan. ${His} vaginal lips part as the first of ${his} brood is born, followed by another, and another. After hours of constant`); - } else if (slave.broodmother === 1) { - r.push(`${slave.slaveName}'s massive belly shudders and shrinks as all ${his} waters simultaneously break. ${He} spreads ${his}`); - if (hasBothLegs(slave)) { - r.push(`legs`); - } else if (!hasAnyLegs(slave)) { - r.push(`stumps`); - } else { - r.push(`leg and stump`); - } - r.push(`wide with a loud moan. ${His} vaginal lips part as the first of ${his} brood is born, followed not long after by another. After an hour of constant`); - } else { - r.push(`${slave.slaveName}'s massive belly shudders and shrinks as all ${his} waters simultaneously break. ${He} spreads ${his}`); - if (hasBothLegs(slave)) { - r.push(`legs`); - } else if (!hasAnyLegs(slave)) { - r.push(`stumps`); - } else { - r.push(`leg and stump`); - } - r.push(`wide with a loud moan. ${His} vaginal lips part as ${his} birthing begins. After an hour of intensive`); - } - - if (slave.fetish === "mindbroken") { - r.push(`birthing, ${he} shows little interest in the changes to ${his} body.`); - } else if (slave.sexualFlaw === "breeder") { - r.push(`birthing and the realization that you are taking away ${his} ideal body, ${his} perfect existence, ${his} mind`); - r.push( - App.UI.DOM.makeElement("span", `fundamentally breaks.`) - ); - slave.fetish = "mindbroken"; - } else if (slave.fetish === "pregnancy" && S.Nurse) { - r.push(`birthing and orgasming all the time, ${slave.slaveName}'s mind would have broken. However, ${S.Nurse.slaveName} had the foresight to sedate ${him} after witnessing ${his} constant orgasming. ${He} awakes to find ${his} belly deflated, no longer crammed full of life. ${He} is`); - r.push( - App.UI.DOM.makeElement("span", `disappointed`, "mediumorchid") - ); - (`that you would forbid ${him} from such a pleasure, but`); - r.push( - App.UI.DOM.makeElement("span", `understands`, "mediumaquamarine") - ); - r.push(`why it was done.`); - slave.trust += 5; - slave.devotion -= 5; - } else if (slave.fetish === "pregnancy") { - if (slave.broodmother === 2) { - r.push(`birthing and orgasming each time, ${slave.slaveName}'s mind is`); - r.push(App.UI.DOM.makeElement("span", `fundamentally broken.`, "red")); - r.push(`Being under constant pleasure for so long has destroyed all but the part of ${him} that feels pleasure. With one final push the breeding device is expelled from ${his} womb as the last spark of what was ${his} mind is extinguished.`); - slave.fetish = "mindbroken"; - } else if (slave.broodmother === 1) { - r.push(`birthing and orgasming each time, ${slave.slaveName} is reduced to a quivering, overstimulated pile. When ${he} returns to ${his} senses,`); - r.push(App.UI.DOM.makeElement("span", `${he} can only express how much ${he} wants to go again.`, "hotpink")); - slave.devotion += 4; - } else { - r.push(`birthing and orgasming all the time, ${slave.slaveName} is reduced to a quivering, overstimulated pile. When ${he} returns to ${his} senses,`); - r.push(App.UI.DOM.makeElement("span", `${he} can only express how much ${he} wants to go again.`, "hotpink")); - slave.devotion += 3; - } - } else if (slave.devotion <= 20) { - r.push(`birthing,`); - r.push(App.UI.DOM.makeElement("span", `${he} hates you for destroying ${his} body like this.`, "mediumorchid")); - r.push(`${He} is`); - r.push(App.UI.DOM.makeElement("span", `terrified of your power`, "gold")); - r.push(`over ${his} body.`); - slave.trust -= 40; - slave.devotion -= 50; - } else if (slave.devotion <= 50) { - r.push(`birthing, ${he} is dully obedient. ${He} has been broken to slave life so thoroughly that even this is neither surprising nor affecting. ${He} is`); - r.push(App.UI.DOM.makeElement("span", `terrified of your power`, "gold")); - r.push(`over ${his} body.`); - slave.trust -= 40; - } else { - r.push(`birthing, ${he} is`); - r.push(App.UI.DOM.makeElement("span", `pleased by this stark development`, "hotpink")); - r.push(`since ${he} is so attentive to your will. ${He} also expects ${he}'ll be able to fuck better now without a massive belly getting in the way.`); - slave.devotion += 4; - } - - if (slave.birthsTat > -1) { - slave.birthsTat++; - r.push(`The temporary tattoo of a child has been replaced with ${his} ${ordinalSuffix(slave.birthsTat)} permanent infant.`); - cashX(forceNeg(V.modCost), "slaveMod", slave); - } - - if (slave.broodmother === 2) { - slave.preg = -3; - if (slave.vagina < 6) { - slave.vagina = 10; - } - healthDamage(slave, 80); - } else { - if (lastPregRule(slave, V.defaultRules)) { - slave.preg = -1; - } else { - slave.preg = 0; - } - // I think, it's not logical to break her reproductive system out of repair, if she is only type 1 broodmother. In this case she have to birth only like 5-10 fully grown babies, others get progressively smaller. It's should be even smaller stress to body then for "normal" hyperpregnant with 15-20+ children - they have to birth them all at full size. - if (slave.vagina < 6) { - slave.vagina = 6; - } - healthDamage(slave, 30); - } } else if (cSection) { - r.push(`${slave.slaveName} is sedated, ${his} ${children} extracted, and taken to a bed to recover.`); - if (slave.pregSource === -1) { - if (slave.devotion <= 20 && slave.weekAcquired > 0) { - r.push(`${He}`); - r.push(App.UI.DOM.makeElement("span", `despises`, "mediumorchid")); - r.push(`you for using ${his} body to bear your children.`); - slave.devotion -= 10; - } else if (slave.devotion > 50) { - r.push(`${He}'s`); - r.push(App.UI.DOM.makeElement("span", `so proud`, "hotpink")); - r.push(`to have successfully carried children for you.`); - slave.devotion += 3; - } - } - if (slave.fetish === "pregnancy") { - r.push(`${He}'s a little disappointed ${he} didn't get to give birth, but can't wait to get pregnant again.`); - } else if (slave.devotion > 50) { - r.push(`${He} is`); - r.push(App.UI.DOM.makeElement("span", `pleased by this stark development,`, "hotpink")); - r.push(`since ${he} is so attentive to your will. ${He} also expects ${he}'ll be able to fuck better now.`); - slave.devotion += 4; - } else if (slave.devotion > 20) { - r.push(`${He} is broken enough to accept your control of ${his} pregnancies.`); - } else if (slave.devotion >= -20) { - r.push(`${He} would have preferred to give birth when ${he} was ready and is`); - r.push(App.UI.DOM.makeElement("span", `sensibly fearful`, "gold")); - r.push(`of your total power over ${his} body.`); - slave.trust -= 5; - } else { - r.push(`${He} does not understand the realities of ${his} life as a slave at a core level, so ${he}'s`); - r.push(App.UI.DOM.makeElement("span", `terrified and angry`, "mediumorchid")); - r.push(`that you decided to cut short ${his} pregnancy. ${He} is`); - r.push(App.UI.DOM.makeElement("span", `sensibly fearful`, "gold")); - r.push(`of your total power over ${his} body.`); - slave.trust -= 5; - slave.devotion -= 5; - } + r.push(`${slave.slaveName} is sedated so ${his} ${children} can be extracted.`); } else if (burstCheck(slave)) { r.push(`${slave.slaveName}'s straining womb gave out and burst, taking ${his} life.`); } else if (slave.fuckdoll === 0) { if (slave.broodmother === 0 || slave.broodmotherCountDown === 1) { if (slave.assignment !== "work in the dairy") { if (V.universalRulesCSec === 1 || (slave.mpreg === 0 && slave.vagina < 0)) { - r.push(birthDescription()); } else { if (hasAnyLegs(slave)) { // legless slaves are always carried in time if ((random(1, 20) > suddenBirth) || (V.universalRulesBirthing === 1)) { @@ -351,17 +204,9 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) r.push(`${slave.slaveName} makes ${his} way`); } r.push(`to ${his} prepared birthing area.`); - r.push(birthDescription()); - } else { // did not make it to birthing area - if (((birthDamage > 15 && random(1, 100) > 50) || (birthDamage > 20)) && (slave.assignment !== "be the Nurse" && slave.assignment !== "get treatment in the clinic")) { - r.push(deadlyBirthScene()); - } else { - r.push(suddenBirthScene()); - } // closes deadly birth - } // closes reg birth + } } else { // made it to birthing area r.push(`With childbirth approaching, ${slave.slaveName} is carried to ${his} prepared birthing area.`); - r.push(ampBirth()); } // close amp birth } // close always c-sec } else { @@ -372,16 +217,6 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } else { r.push(`cunt.`); } - r.push(`Once the ${childrenAre} secure, the basket retracts allowing access to ${his}`); - if (slave.mpreg === 1) { - r.push(`rear.`); - } else { - r.push(`vagina.`); - } - if (V.dairyPregSetting > 0) { - r.push(`The impregnation tube is promptly reinserted, bloating ${his} empty womb with fresh cum, where it will remain until ${he} is pregnant once more.`); - } - r.push(`All these events are meaningless to ${him}, as ${his} consciousness has long since been snuffed out.`); } else if (V.dairyRestraintsSetting > 1) { if (slave.fetish === "mindbroken") { r.push(`As ${slave.slaveName}'s water breaks, a mechanical basket is extended under ${his} laboring`); @@ -390,16 +225,6 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } else { r.push(`cunt.`); } - r.push(`Once the ${childrenAre} secure, the basket retracts allowing access to ${his}`); - if (slave.mpreg === 1) { - r.push(`rear.`); - } else { - r.push(`vagina.`); - } - if (V.dairyPregSetting > 0) { - r.push(`The impregnation tube is promptly reinserted, bloating ${his} empty womb with fresh cum, where it will remain until ${he} is pregnant once more.`); - } - r.push(`${He} doesn't care about any of this, as the only thoughts left in ${his} empty mind revolve around the sensations in ${his} crotch and breasts.`); } else { r.push(`As ${slave.slaveName}'s water breaks, a mechanical basket is extended under ${his} laboring`); if (slave.mpreg === 1) { @@ -413,24 +238,12 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } else { r.push(`${He} is forced to give birth, restrained, into the waiting holder.`); } - r.push(`Once the ${childrenAre} secure, the basket retracts allowing access to ${his} vagina.`); - if (V.dairyPregSetting > 0) { - r.push(`The impregnation tube is promptly reinserted, bloating ${his} empty womb with fresh cum, where it will remain until ${he} is pregnant once more. ${slave.slaveName} moans, partially with pleasure and partially with defeat, under the growing pressure within ${his} body. Tears stream down ${his} face as`); - if (slave.counter.births > 0) { - r.push(`${he} is forcibly impregnated once more.`); - } else { - r.push(`${he} attempts to shift in ${his} restraints to peek around ${his} swollen breasts, but ${he} is too well secured. ${He}'ll realize what is happening when ${his} belly grows large enough to brush against ${his} udders as the milker sucks from them${(slave.dick > 0) ? ` or ${his} dick begins rubbing its underside` : ``}.`); - } - } - r.push(`${His} mind slips slightly more as ${he} focuses on ${his} fate as nothing more than an animal destined to be milked and bare offspring until ${his} body gives out.`); - slave.trust -= 10; - slave.devotion -= 10; } } else { if (slave.fetish === "mindbroken") { - r.push(`While getting milked, ${slave.slaveName}'s water breaks. ${He} shows little interest and continues kneading ${his} breasts. Instinctively ${he} begins to push out ${his} ${babies}. ${He} pays no heed to ${his} ${children} being removed from the milking stall, instead focusing entirely on draining ${his} breasts.`); + r.push(`While getting milked, ${slave.slaveName}'s water breaks.`); } else if (slave.geneticQuirks.uterineHypersensitivity === 2) { - r.push(`While getting milked, ${slave.slaveName}'s water breaks, a moment she anxiously waited for${(slave.counter.birthsTotal > 0) ? `no matter how many times it happened before` : ``}. ${He} begins to push out ${his} ${babies} orgasming during the whole process. By the time ${he} regains ${his} senses ${his} ${children} have already been removed from the milking stall.`); + r.push(`While getting milked, ${slave.slaveName}'s water breaks, a moment she anxiously waited for${(slave.counter.birthsTotal > 0) ? `no matter how many times it happened before` : ``}.`); } else { r.push(`While getting milked, ${slave.slaveName}'s water breaks,`); if (V.dairyPregSetting > 0) { @@ -438,30 +251,16 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } else { r.push(`but`); } - r.push(`${he} continues enjoying ${his} milking. ${He} begins to push out ${his} ${babies}. ${He} catches`); - if (canSee(slave)) { - r.push(`a glimpse`); - } else if (canHear(slave)) { - r.push(`the sound`); - } else { - r.push(`the feeling`); - } - r.push(`of ${his} ${children} being removed from the milking stall before returning ${his} focus to draining ${his} breasts.`); + r.push(`${he} continues enjoying ${his} milking.`); } } } // close cow birth } else { if (!hasAnyLegs(slave)) { r.push(`With childbirth approaching, ${slave.slaveName} is carried to ${his} prepared birthing area.`); - r.push(ampBirth()); - } else if (slave.broodmother === 1) { - r.push(broodmotherBirth()); - } else { - r.push(hyperBroodmotherBirth()); } } // close broodmother birth - } else { - // Fuckdoll birth + } else if (slave.fuckdoll !== 0) { if (V.universalRulesCSec === 1 || (slave.mpreg === 0 && slave.vagina < 0)) { cSection = true; r.push(`${slave.slaveName}'s suit's systems alert that it is ready to give birth; it is taken to the remote surgery to have its ${children} extracted and for it to be cleaned up.`); @@ -685,11 +484,557 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) App.Events.addNode(el, r, "p"); return el; } - + + function calcBirthDamage() { + /* I think all this reactions should be showed only if no c'section used too. Setting it up for just in case: */ + if (!cSection && slave.assignment !== "work in the dairy") { // if not desired, this check can be easily removed or deactivated with condition set to true. + let hasDamage; + p = document.createElement("p"); + let r = []; + if (newMother) { + r.push([ + `${His} inexperience`, + App.UI.DOM.makeElement("span", `complicated ${his} first birth.`, "red") + ]); + compoundCondition = 1; + birthDamage += 2; + } + if (slave.mpreg === 1) { + if (slave.anus < 2) { + r.push([ + `${His} tight ass`, + App.UI.DOM.makeElement("span", `hindered ${his} ${(numBeingBorn > 1) ? `babies` : `baby's`} birth.`, "red") + ]); + birthDamage += 3; + } + } else { + if (slave.vagina < 2) { + r.push([ + `${His} tight vagina`, + App.UI.DOM.makeElement("span", `hindered ${his} ${(numBeingBorn > 1) ? `babies` : `baby's`} birth.`, "red") + ]); + birthDamage += 3; + } + if (slave.vaginaLube === 0) { + r.push([ + `${His} dry vagina made pushing ${his} ${children} out`, + App.UI.DOM.makeElement("span", `painful.`, "red") + ]); + birthDamage += 1; + } + } + if (slave.hips < 0) { + r.push([ + `${His} narrow hips made birth`, + App.UI.DOM.makeElement("span", `troublesome.`, "red") + ]); + birthDamage += (2 - slave.hips); + } + if (slave.weight < -95) { + r.push([ + `${His} very thin body`, + App.UI.DOM.makeElement("span", `was nearly incapable of birthing ${his} ${children}.`, "red") + ]); + birthDamage += 7; + compoundCondition = 1; + } else if (slave.weight <= -30) { + r.push([ + `${His} thin body was`, + App.UI.DOM.makeElement("span", `ill-suited to ${his} childbirth.`, "red") + ]); + birthDamage += 5; + } + if (slave.health.condition < -20) { + r.push([ + `${His} poor health made laboring`, + App.UI.DOM.makeElement("span", `exhausting.`, "red") + ]); + compoundCondition = 1; + birthDamage += (4 - (slave.health.condition / 10)); + } + if (slave.health.illness >= 3) { + r.push([ + `${His} ongoing illness`, + App.UI.DOM.makeElement("span", `already sapped most of ${his} strength.`, "red") + ]); + birthDamage += slave.health.illness; + compoundCondition = 1; + } + if (slave.physicalAge < 6) { + r.push([ + `${His} very young body was`, + App.UI.DOM.makeElement("span", `not designed to be able pass a baby.`, "red") + ]); + birthDamage += 5; + } else if (slave.physicalAge < 9) { + r.push([ + `${His} young body had`, + App.UI.DOM.makeElement("span", `a lot of trouble`, "red"), + `birthing ${his} ${babies}.` + ]); + birthDamage += 3; + } else if (slave.physicalAge < 13) { + r.push([ + `${His} young body had`, + App.UI.DOM.makeElement("span", `trouble birthing`, "red"), + `birthing ${his} ${babies}.` + ]); + birthDamage += 1; + compoundCondition = 1; + } + if (slave.health.tired > 80) { + r.push([ + `${He} was thoroughly exhausted to begin with; ${he}`, + App.UI.DOM.makeElement("span", `lacked the energy to push at all.`, "red") + ]); + birthDamage += 20; + compoundCondition = 1; + } else if (slave.health.tired > 50) { + r.push([ + `${He} was so tired, ${he}`, + App.UI.DOM.makeElement("span", `lacked the energy to effectively push.`, "red") + ]); + birthDamage += 2; + compoundCondition = 1; + } + if (slave.muscles < -95) { + r.push([ + `${He} tried and tried but ${his} frail body`, + App.UI.DOM.makeElement("span", `could not push ${his} ${children} out.`, "red") + ]); + birthDamage += 30; + compoundCondition = 1; + } else if (slave.muscles < -30) { + r.push([ + `${His} very weak body`, + App.UI.DOM.makeElement("span", `barely managed to push`, "red"), + `out ${his} ${children}` + ]); + birthDamage += 4; + compoundCondition = 1; + } else if (slave.muscles < -5) { + r.push([ + `${His} weak body`, + App.UI.DOM.makeElement("span", `struggled to push`, "red"), + `out ${his} ${children}.` + ]); + birthDamage += 2; + } + + if (slave.preg > slave.pregData.normalBirth * 1.25) { // better get her a c-sec + r.push([ + `${His} ${children} had extra time to grow`, + App.UI.DOM.makeElement("span", `greatly complicating childbirth.`, "red") + ]); + if (slave.preg >= slave.pregData.normalBirth * 1.5) { + if (slave.physicalAge < 6) { + birthDamage += 50; + } else if (slave.physicalAge < 9) { + birthDamage += 30; + } else if (slave.physicalAge < 13) { + birthDamage += 20; + } + if (slave.hips < 0) { + birthDamage += (20 - slave.hips); + } + } else if (slave.preg > slave.pregData.normalBirth * 1.25) { + if (slave.physicalAge < 6) { + birthDamage += 10; + } else if (slave.physicalAge < 9) { + birthDamage += 6; + } else { + birthDamage += 2; + } + if (slave.hips < 0) { + birthDamage += (2 - slave.hips); + } + } + compoundCondition = 1; + } + if (slave.wombImplant === "restraint") { + r.push([ + `${His} support implant`, + App.UI.DOM.makeElement("span", `weakens ${his} contractions`, "red"), + `and inhibits ${his} womb's ability to give birth.` + ]); + birthDamage += 2; + } + if (r.length > 0) { + hasDamage = true; + } + + for (const malus of r) { + App.Events.addNode(p, malus, "div"); + } + + // Bonuses + r = []; + if (slave.mpreg === 1) { + if (slave.anus >= 2) { + r.push([ + `${His}`, + App.UI.DOM.makeElement("span", `loose ass`, "green"), + `made birthing ${his} ${children} easier.` + ]); + } + birthDamage -= slave.anus; + } else { + if (slave.vagina >= 2) { + r.push([ + `${His}`, + App.UI.DOM.makeElement("span", `loose vagina`, "green"), + `made birthing ${his} ${children} easier.` + ]); + birthDamage -= slave.vagina; + } + if (slave.vaginaLube > 0) { + r.push([ + `${His}`, + App.UI.DOM.makeElement("span", `moist vagina`, "green"), + `hastened ${his} ${children}'s birth.` + ]); + birthDamage -= slave.vaginaLube; + } + } + + if (!newMother) { + r.push([ + `${He} has`, + App.UI.DOM.makeElement("span", `given birth before,`, "green"), + `so ${he} knows just what to do.` + ]); + birthDamage -= 3; + } + + if (slave.hips > 0) { + r.push([ + `${His} `, + App.UI.DOM.makeElement("span", `wide hips`, "green"), + `greatly aided childbirth.` + ]); + birthDamage -= slave.hips; + } + + if (slave.pregAdaptation >= 1000) { + r.push([ + `${His} body has`, + App.UI.DOM.makeElement("span", `completely adapted to pregnancy;`, "green"), + `when it is time to give birth, that baby is coming out fast.` + ]); + birthDamage -= 10; + } else if (slave.pregAdaptation >= 500) { + r.push([ + `${His} body is`, + App.UI.DOM.makeElement("span", `highly adapted to bearing life`, "green"), + `and birth is no small part of that.` + ]); + birthDamage -= 3; + } else if (slave.pregAdaptation >= 100) { + r.push([ + `${His} body has`, + App.UI.DOM.makeElement("span", `become quite adept at bearing children,`, "green"), + `birth included.` + ]); + birthDamage -= 1; + } + + if (slave.curatives > 0) { + r.push([ + `${His} `, + App.UI.DOM.makeElement("span", `curatives`, "green"), + `helped protect ${him}.` + ]); + birthDamage -= 3; + } + + if (App.Data.misc.nurseCareers.includes(slave.career) && slave.fetish !== "mindbroken" && slave.muscles >= -95) { + r.push([ + `Thanks to ${his}`, + App.UI.DOM.makeElement("span", `previous career,`, "green"), + `childbirth went smoothly.` + ]); + birthDamage = 0; + } else if (slave.intelligenceImplant >= 15) { + r.push([ + `${He} was`, + App.UI.DOM.makeElement("span", `taught how to handle birth`, "green"), + `in class.` + ]); + birthDamage -= 2; + } + + if (slave.geneticQuirks.uterineHypersensitivity === 2) { + if (V.geneticMappingUpgrade >= 1) { + r.push([ + `${His} hypersensitive uterus made birth`, + App.UI.DOM.makeElement("span", `a very pleasant experience,`, "green"), + `distracting from the pain.` + ]); + } else { + r.push([ + `${He} oddly climaxed multiple times during birth,`, + App.UI.DOM.makeElement("span", `keeping ${his} mind off the pain.`, "green") + ]); + } + birthDamage -= 5; + } + + if (hasDamage && r.length > 0) { + App.UI.DOM.appendNewElement("div", p, `However:`); + } + + for (const boost of r) { + App.Events.addNode(p, boost, "div"); + } + return p; + } + } + + function postBirthScene() { + const el = new DocumentFragment(); + const r = []; + if (birthStorm) { + if (slave.broodmother === 2) { + r.push(`${slave.slaveName}'s obscenely swollen belly begins to shudder and writhe moments after being injected with the drug as all ${his} waters break. ${He} spreads ${his}`); + if (hasBothLegs(slave)) { + r.push(`legs to either side of ${his} spasming bulk`); + } else if (!hasAnyLegs(slave)) { + r.push(`stumps`); + } else { + r.push(`leg and ${his} stump`); + } + r.push(`as wide as ${he} can with a loud moan. ${His} vaginal lips part as the first of ${his} brood is born, followed by another, and another. After hours of constant`); + } else if (slave.broodmother === 1) { + r.push(`${slave.slaveName}'s massive belly shudders and shrinks as all ${his} waters simultaneously break. ${He} spreads ${his}`); + if (hasBothLegs(slave)) { + r.push(`legs`); + } else if (!hasAnyLegs(slave)) { + r.push(`stumps`); + } else { + r.push(`leg and stump`); + } + r.push(`wide with a loud moan. ${His} vaginal lips part as the first of ${his} brood is born, followed not long after by another. After an hour of constant`); + } else { + r.push(`${slave.slaveName}'s massive belly shudders and shrinks as all ${his} waters simultaneously break. ${He} spreads ${his}`); + if (hasBothLegs(slave)) { + r.push(`legs`); + } else if (!hasAnyLegs(slave)) { + r.push(`stumps`); + } else { + r.push(`leg and stump`); + } + r.push(`wide with a loud moan. ${His} vaginal lips part as ${his} birthing begins. After an hour of intensive`); + } + + if (slave.fetish === "mindbroken") { + r.push(`birthing, ${he} shows little interest in the changes to ${his} body.`); + } else if (slave.sexualFlaw === "breeder") { + r.push(`birthing and the realization that you are taking away ${his} ideal body, ${his} perfect existence, ${his} mind`); + r.push( + App.UI.DOM.makeElement("span", `fundamentally breaks.`) + ); + slave.fetish = "mindbroken"; + } else if (slave.fetish === "pregnancy" && S.Nurse) { + r.push(`birthing and orgasming all the time, ${slave.slaveName}'s mind would have broken. However, ${S.Nurse.slaveName} had the foresight to sedate ${him} after witnessing ${his} constant orgasming. ${He} awakes to find ${his} belly deflated, no longer crammed full of life. ${He} is`); + r.push( + App.UI.DOM.makeElement("span", `disappointed`, "mediumorchid") + ); + (`that you would forbid ${him} from such a pleasure, but`); + r.push( + App.UI.DOM.makeElement("span", `understands`, "mediumaquamarine") + ); + r.push(`why it was done.`); + slave.trust += 5; + slave.devotion -= 5; + } else if (slave.fetish === "pregnancy") { + if (slave.broodmother === 2) { + r.push(`birthing and orgasming each time, ${slave.slaveName}'s mind is`); + r.push(App.UI.DOM.makeElement("span", `fundamentally broken.`, "red")); + r.push(`Being under constant pleasure for so long has destroyed all but the part of ${him} that feels pleasure. With one final push the breeding device is expelled from ${his} womb as the last spark of what was ${his} mind is extinguished.`); + slave.fetish = "mindbroken"; + } else if (slave.broodmother === 1) { + r.push(`birthing and orgasming each time, ${slave.slaveName} is reduced to a quivering, overstimulated pile. When ${he} returns to ${his} senses,`); + r.push(App.UI.DOM.makeElement("span", `${he} can only express how much ${he} wants to go again.`, "hotpink")); + slave.devotion += 4; + } else { + r.push(`birthing and orgasming all the time, ${slave.slaveName} is reduced to a quivering, overstimulated pile. When ${he} returns to ${his} senses,`); + r.push(App.UI.DOM.makeElement("span", `${he} can only express how much ${he} wants to go again.`, "hotpink")); + slave.devotion += 3; + } + } else if (slave.devotion <= 20) { + r.push(`birthing,`); + r.push(App.UI.DOM.makeElement("span", `${he} hates you for destroying ${his} body like this.`, "mediumorchid")); + r.push(`${He} is`); + r.push(App.UI.DOM.makeElement("span", `terrified of your power`, "gold")); + r.push(`over ${his} body.`); + slave.trust -= 40; + slave.devotion -= 50; + } else if (slave.devotion <= 50) { + r.push(`birthing, ${he} is dully obedient. ${He} has been broken to slave life so thoroughly that even this is neither surprising nor affecting. ${He} is`); + r.push(App.UI.DOM.makeElement("span", `terrified of your power`, "gold")); + r.push(`over ${his} body.`); + slave.trust -= 40; + } else { + r.push(`birthing, ${he} is`); + r.push(App.UI.DOM.makeElement("span", `pleased by this stark development`, "hotpink")); + r.push(`since ${he} is so attentive to your will. ${He} also expects ${he}'ll be able to fuck better now without a massive belly getting in the way.`); + slave.devotion += 4; + } + + if (slave.birthsTat > -1) { + slave.birthsTat++; + r.push(`The temporary tattoo of a child has been replaced with ${his} ${ordinalSuffix(slave.birthsTat)} permanent infant.`); + cashX(forceNeg(V.modCost), "slaveMod", slave); + } + + if (slave.broodmother === 2) { + slave.preg = -3; + if (slave.vagina < 6) { + slave.vagina = 10; + } + healthDamage(slave, 80); + } else { + if (lastPregRule(slave, V.defaultRules)) { + slave.preg = -1; + } else { + slave.preg = 0; + } + // I think, it's not logical to break her reproductive system out of repair, if she is only type 1 broodmother. In this case she have to birth only like 5-10 fully grown babies, others get progressively smaller. It's should be even smaller stress to body then for "normal" hyperpregnant with 15-20+ children - they have to birth them all at full size. + if (slave.vagina < 6) { + slave.vagina = 6; + } + healthDamage(slave, 30); + } + } else if (cSection) { + if (slave.pregSource === -1) { + if (slave.devotion <= 20 && slave.weekAcquired > 0) { + r.push(`${He}`); + r.push(App.UI.DOM.makeElement("span", `despises`, "mediumorchid")); + r.push(`you for using ${his} body to bear your children.`); + slave.devotion -= 10; + } else if (slave.devotion > 50) { + r.push(`${He}'s`); + r.push(App.UI.DOM.makeElement("span", `so proud`, "hotpink")); + r.push(`to have successfully carried children for you.`); + slave.devotion += 3; + } + } + if (slave.fetish === "pregnancy") { + r.push(`${He}'s a little disappointed ${he} didn't get to give birth, but can't wait to get pregnant again.`); + } else if (slave.devotion > 50) { + r.push(`${He} is`); + r.push(App.UI.DOM.makeElement("span", `pleased by this stark development,`, "hotpink")); + r.push(`since ${he} is so attentive to your will. ${He} also expects ${he}'ll be able to fuck better now.`); + slave.devotion += 4; + } else if (slave.devotion > 20) { + r.push(`${He} is broken enough to accept your control of ${his} pregnancies.`); + } else if (slave.devotion >= -20) { + r.push(`${He} would have preferred to give birth when ${he} was ready and is`); + r.push(App.UI.DOM.makeElement("span", `sensibly fearful`, "gold")); + r.push(`of your total power over ${his} body.`); + slave.trust -= 5; + } else { + r.push(`${He} does not understand the realities of ${his} life as a slave at a core level, so ${he}'s`); + r.push(App.UI.DOM.makeElement("span", `terrified and angry`, "mediumorchid")); + r.push(`that you decided to cut short ${his} pregnancy. ${He} is`); + r.push(App.UI.DOM.makeElement("span", `sensibly fearful`, "gold")); + r.push(`of your total power over ${his} body.`); + slave.trust -= 5; + slave.devotion -= 5; + } + } else if (slave.fuckdoll === 0) { + if (slave.broodmother === 0 || slave.broodmotherCountDown === 1) { + if (slave.assignment !== "work in the dairy") { + if (V.universalRulesCSec === 1 || (slave.mpreg === 0 && slave.vagina < 0)) { + r.push(birthDescription()); + } else { + if (hasAnyLegs(slave)) { // legless slaves are always carried in time + if ((random(1, 20) > suddenBirth) || (V.universalRulesBirthing === 1)) { + // did she make it to her birthing area? + r.push(birthDescription()); + } else { // did not make it to birthing area + if (((birthDamage > 15 && random(1, 100) > 50) || (birthDamage > 20)) && (slave.assignment !== "be the Nurse" && slave.assignment !== "get treatment in the clinic")) { + r.push(deadlyBirthScene()); + } else { + r.push(suddenBirthScene()); + } // closes deadly birth + } // closes reg birth + } else { // made it to birthing area + r.push(ampBirth()); + } // close amp birth + } // close always c-sec + } else { + if (V.dairyRestraintsSetting > 1 && slave.career === "a bioreactor") { + r.push(`Once the ${childrenAre} secure, the basket retracts allowing access to ${his}`); + if (slave.mpreg === 1) { + r.push(`rear.`); + } else { + r.push(`vagina.`); + } + if (V.dairyPregSetting > 0) { + r.push(`The impregnation tube is promptly reinserted, bloating ${his} empty womb with fresh cum, where it will remain until ${he} is pregnant once more.`); + } + r.push(`All these events are meaningless to ${him}, as ${his} consciousness has long since been snuffed out.`); + } else if (V.dairyRestraintsSetting > 1) { + if (slave.fetish === "mindbroken") { + r.push(`Once the ${childrenAre} secure, the basket retracts allowing access to ${his}`); + if (slave.mpreg === 1) { + r.push(`rear.`); + } else { + r.push(`vagina.`); + } + if (V.dairyPregSetting > 0) { + r.push(`The impregnation tube is promptly reinserted, bloating ${his} empty womb with fresh cum, where it will remain until ${he} is pregnant once more.`); + } + r.push(`${He} doesn't care about any of this, as the only thoughts left in ${his} empty mind revolve around the sensations in ${his} crotch and breasts.`); + } else { + r.push(`Once the ${childrenAre} secure, the basket retracts allowing access to ${his} vagina.`); + if (V.dairyPregSetting > 0) { + r.push(`The impregnation tube is promptly reinserted, bloating ${his} empty womb with fresh cum, where it will remain until ${he} is pregnant once more. ${slave.slaveName} moans, partially with pleasure and partially with defeat, under the growing pressure within ${his} body. Tears stream down ${his} face as`); + if (slave.counter.births > 0) { + r.push(`${he} is forcibly impregnated once more.`); + } else { + r.push(`${he} attempts to shift in ${his} restraints to peek around ${his} swollen breasts, but ${he} is too well secured. ${He}'ll realize what is happening when ${his} belly grows large enough to brush against ${his} udders as the milker sucks from them${(slave.dick > 0) ? ` or ${his} dick begins rubbing its underside` : ``}.`); + } + } + r.push(`${His} mind slips slightly more as ${he} focuses on ${his} fate as nothing more than an animal destined to be milked and bare offspring until ${his} body gives out.`); + slave.trust -= 10; + slave.devotion -= 10; + } + } else { + if (slave.fetish === "mindbroken") { + r.push(`${He} shows little interest and continues kneading ${his} breasts. Instinctively ${he} begins to push out ${his} ${babies}. ${He} pays no heed to ${his} ${children} being removed from the milking stall, instead focusing entirely on draining ${his} breasts.`); + } else if (slave.geneticQuirks.uterineHypersensitivity === 2) { + r.push(`${He} begins to push out ${his} ${babies} orgasming during the whole process. By the time ${he} regains ${his} senses ${his} ${children} have already been removed from the milking stall.`); + } else { + r.push(`${He} begins to push out ${his} ${babies}. ${He} catches`); + if (canSee(slave)) { + r.push(`a glimpse`); + } else if (canHear(slave)) { + r.push(`the sound`); + } else { + r.push(`the feeling`); + } + r.push(`of ${his} ${children} being removed from the milking stall before returning ${his} focus to draining ${his} breasts.`); + } + } + } // close cow birth + } else { + if (!hasAnyLegs(slave)) { + r.push(ampBirth()); + } else if (slave.broodmother === 1) { + r.push(broodmotherBirth()); + } else { + r.push(hyperBroodmotherBirth()); + } + } // close broodmother birth + } + App.Events.addNode(el, r); + return el; + } function postBirthReaction() { const el = new DocumentFragment(); let r = []; - let compoundCondition; /* ---- Postbirth reactions, body -------------------------------------------------------------------------------------------*/ if (!cSection) { // all this block only if no c'section used. r = []; @@ -714,7 +1059,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) r.push(`After several hours of labor and birth, ${his} belly sags softly.`); } } - App.Events.addNode(el, r, "p"); + App.Events.addNode(el, r, "div"); if ( (slave.mpreg === 0 && slave.vagina === 0) || (slave.mpreg === 1 && slave.anus === 0) @@ -754,7 +1099,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } } healthDamage(slave, 10); - App.Events.addNode(el, r, "p"); + App.Events.addNode(el, r, "div"); } if (slave.hips < -1) { r = []; @@ -798,7 +1143,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) healthDamage(slave, 20); slave.hips = 0; slave.hipsImplant = 0; - App.Events.addNode(el, r, "p"); + App.Events.addNode(el, r, "div"); } r = []; if (birthStorm) { @@ -852,7 +1197,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) r.push(App.UI.DOM.makeElement("span", `stretched out ${his} vagina.`, "lime")); } } - App.Events.addNode(el, r, "p"); + App.Events.addNode(el, r, "div"); if (slave.mpreg === 1) { /* r.push(`Childbirth has`) @@ -931,321 +1276,9 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) r.push(App.UI.DOM.makeElement("span", `${his} health has been slightly affected.`, "red")); surgeryDamage(slave, 5); } - App.Events.addNode(el, r, "p"); + App.Events.addNode(el, r, "div"); } - /* ------ Post birth reactions, mother experience ------------------ */ - /* I think all this reactions should be showed only if no c'section used too. Setting it up for just in case: */ - if (!cSection && slave.assignment !== "work in the dairy") { // if not desired, this check can be easily removed or deactivated with condition set to true. - p = document.createElement("p"); - if (newMother) { - App.Events.addNode( - p, - [ - `${His} inexperience`, - App.UI.DOM.makeElement("span", `complicated ${his} first birth.`, "red") - ], - "div" - ); - compoundCondition = 1; - birthDamage += 2; - } - r = []; - if (slave.mpreg === 1) { - if (slave.anus < 2) { - r.push(`${His} tight ass`); - r.push(App.UI.DOM.makeElement("span", `hindered ${his} ${(numBeingBorn > 1) ? `babies` : `baby's`} birth.`, "red")); - birthDamage += 3; - } - } else { - if (slave.vagina < 2) { - r.push(`${His} tight vagina`); - r.push(App.UI.DOM.makeElement("span", `hindered ${his} ${(numBeingBorn > 1) ? `babies` : `baby's`} birth.`, "red")); - birthDamage += 3; - } - if (slave.vaginaLube === 0) { - r.push(`${His} dry vagina made pushing ${his} ${children} out`); - r.push(App.UI.DOM.makeElement("span", `painful.`, "red")); - birthDamage += 1; - } - } - App.Events.addNode(p, r, "div"); - if (slave.hips < 0) { - App.Events.addNode( - p, - [ - `${His} narrow hips made birth`, - App.UI.DOM.makeElement("span", `troublesome.`, "red") - ], - "div" - ); - birthDamage += (2 - slave.hips); - } - if (slave.weight < -95) { - App.Events.addNode( - p, - [ - `${His} very thin body`, - App.UI.DOM.makeElement("span", `was nearly incapable of birthing ${his} ${children}.`, "red") - ], - "div" - ); - birthDamage += 7; - compoundCondition = 1; - } else if (slave.weight <= -30) { - App.Events.addNode( - p, - [ - `${His} thin body was`, - App.UI.DOM.makeElement("span", `ill-suited to ${his} childbirth.`, "red") - ], - "div" - ); - birthDamage += 5; - } - if (slave.health.condition < -20) { - App.Events.addNode( - p, - [ - `${His} poor health made laboring`, - App.UI.DOM.makeElement("span", `exhausting.`, "red") - ], - "div" - ); - compoundCondition = 1; - birthDamage += (4 - (slave.health.condition / 10)); - } - if (slave.health.illness >= 3) { - App.Events.addNode( - p, - [ - `${His} ongoing illness`, - App.UI.DOM.makeElement("span", `already sapped most of ${his} strength.`, "red") - ], - "div" - ); - birthDamage += slave.health.illness; - compoundCondition = 1; - } - r = []; - if (slave.physicalAge < 6) { - r.push(`${His} very young body was`); - r.push(App.UI.DOM.makeElement("span", `not designed to be able pass a baby.`, "red")); - birthDamage += 5; - } else if (slave.physicalAge < 9) { - r.push(`${His} young body had`); - r.push(App.UI.DOM.makeElement("span", `a lot of trouble`, "red")); - r.push(`birthing ${his} ${babies}.`); - birthDamage += 3; - } else if (slave.physicalAge < 13) { - r.push(`${His} young body had`); - r.push(App.UI.DOM.makeElement("span", `trouble birthing`, "red")); - r.push(`birthing ${his} ${babies}.`); - birthDamage += 1; - compoundCondition = 1; - } - App.Events.addNode(p, r, "div"); - r = []; - if (slave.health.tired > 80) { - r.push(`${He} was thoroughly exhausted to begin with; ${he}`); - r.push(App.UI.DOM.makeElement("span", `lacked the energy to push at all.`, "red")); - birthDamage += 20; - compoundCondition = 1; - } else if (slave.health.tired > 50) { - r.push(`${He} was so tired, ${he}`); - r.push(App.UI.DOM.makeElement("span", `lacked the energy to effectively push.`, "red")); - birthDamage += 2; - compoundCondition = 1; - } - App.Events.addNode(p, r, "div"); - r = []; - if (slave.muscles < -95) { - r.push(`${He} tried and tried but ${his} frail body`); - r.push(App.UI.DOM.makeElement("span", `could not push ${his} ${children} out.`, "red")); - birthDamage += 30; - compoundCondition = 1; - } else if (slave.muscles < -30) { - r.push(`${His} very weak body`); - r.push(App.UI.DOM.makeElement("span", `barely managed to push`, "red")); - r.push(`out ${his} ${children}`); - birthDamage += 4; - compoundCondition = 1; - } else if (slave.muscles < -5) { - r.push(`${His} weak body`); - r.push(App.UI.DOM.makeElement("span", `struggled to push`, "red")); - r.push(`out ${his} ${children}.`); - birthDamage += 2; - } - App.Events.addNode(p, r, "div"); - if (slave.preg > slave.pregData.normalBirth * 1.25) { // better get her a c-sec - App.Events.addNode( - p, - [ - `${His} ${children} had extra time to grow`, - App.UI.DOM.makeElement("span", `greatly complicating childbirth.`, "red") - ], - "div" - ); - if (slave.preg >= slave.pregData.normalBirth * 1.5) { - if (slave.physicalAge < 6) { - birthDamage += 50; - } else if (slave.physicalAge < 9) { - birthDamage += 30; - } else if (slave.physicalAge < 13) { - birthDamage += 20; - } - if (slave.hips < 0) { - birthDamage += (20 - slave.hips); - } - } else if (slave.preg > slave.pregData.normalBirth * 1.25) { - if (slave.physicalAge < 6) { - birthDamage += 10; - } else if (slave.physicalAge < 9) { - birthDamage += 6; - } else { - birthDamage += 2; - } - if (slave.hips < 0) { - birthDamage += (2 - slave.hips); - } - } - compoundCondition = 1; - } - if (slave.wombImplant === "restraint") { - App.Events.addNode( - p, - [ - `${His} support implant`, - App.UI.DOM.makeElement("span", `weakens ${his} contractions`, "red"), - `and inhibits ${his} womb's ability to give birth.` - ], - "div" - ); - birthDamage += 2; - } - el.append(p); - - r = []; - if (slave.mpreg === 1) { - if (slave.anus >= 2) { - r.push([ - `${His}`, - App.UI.DOM.makeElement("span", `loose ass`, "green"), - `made birthing ${his} ${children} easier.` - ]); - } - birthDamage -= slave.anus; - } else { - if (slave.vagina >= 2) { - r.push([ - `${His}`, - App.UI.DOM.makeElement("span", `loose vagina`, "green"), - `made birthing ${his} ${children} easier.` - ]); - birthDamage -= slave.vagina; - } - if (slave.vaginaLube > 0) { - r.push([ - `${His}`, - App.UI.DOM.makeElement("span", `moist vagina`, "green"), - `hastened ${his} ${children}'s birth.` - ]); - birthDamage -= slave.vaginaLube; - } - } - - if (!newMother) { - r.push([ - `${He} has`, - App.UI.DOM.makeElement("span", `given birth before,`, "green"), - `so ${he} knows just what to do.` - ]); - birthDamage -= 3; - } - - if (slave.hips > 0) { - r.push([ - `${His} `, - App.UI.DOM.makeElement("span", `wide hips`, "green"), - `greatly aided childbirth.` - ]); - birthDamage -= slave.hips; - } - - if (slave.pregAdaptation >= 1000) { - r.push([ - `${His} body has`, - App.UI.DOM.makeElement("span", `completely adapted to pregnancy;`, "green"), - `when it is time to give birth, that baby is coming out fast.` - ]); - birthDamage -= 10; - } else if (slave.pregAdaptation >= 500) { - r.push([ - `${His} body is`, - App.UI.DOM.makeElement("span", `highly adapted to bearing life`, "green"), - `and birth is no small part of that.` - ]); - birthDamage -= 3; - } else if (slave.pregAdaptation >= 100) { - r.push([ - `${His} body has`, - App.UI.DOM.makeElement("span", `become quite adept at bearing children,`, "green"), - `birth included.` - ]); - birthDamage -= 1; - } - - if (slave.curatives > 0) { - r.push([ - `${His} `, - App.UI.DOM.makeElement("span", `curatives`, "green"), - `helped protect ${him}.` - ]); - birthDamage -= 3; - } - - if (App.Data.misc.nurseCareers.includes(slave.career) && slave.fetish !== "mindbroken" && slave.muscles >= -95) { - r.push([ - `Thanks to ${his}`, - App.UI.DOM.makeElement("span", `previous career,`, "green"), - `childbirth went smoothly.` - ]); - birthDamage = 0; - } else if (slave.intelligenceImplant >= 15) { - r.push([ - `${He} was`, - App.UI.DOM.makeElement("span", `taught how to handle birth`, "green"), - `in class.` - ]); - birthDamage -= 2; - } - - if (slave.geneticQuirks.uterineHypersensitivity === 2) { - if (V.geneticMappingUpgrade >= 1) { - r.push([ - `${His} hypersensitive uterus made birth`, - App.UI.DOM.makeElement("span", `a very pleasant experience,`, "green"), - `distracting from the pain.` - ]); - } else { - r.push([ - `${He} oddly climaxed multiple times during birth,`, - App.UI.DOM.makeElement("span", `keeping ${his} mind off the pain.`, "green") - ]); - } - birthDamage -= 5; - } - // If we added material to r (likely) give it a title and assemble it for display - if (r.length > 0) { - p = document.createElement("p"); - App.UI.DOM.appendNewElement("div", p, `However:`); - for (const boost of r) { - App.Events.addNode(p, boost, "div"); - } - el.append(p); - } - } - /* ----- Body/mother resume -------------------------*/ p = document.createElement("p"); if (slave.assignment !== "work in the dairy" && !cSection) { /* && ${slave.broodmother} === 0 // removed - broodmother have sensations too */ @@ -1283,8 +1316,11 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } if (slave.geneticQuirks.uterineHypersensitivity === 2) { r.push(`Not only that, but`); - r.push(App.UI.DOM.makeElement("span", `the entire process was extremely pleasurable for ${him}`, "green")); - r.push(`${(numBeingBorn > 1) ? `, with orgasms growing more powerful with each baby ${he} brought to the world` : ``}. ${He} can't wait to be impregnated and give birth again,`); + r.push(App.UI.DOM.makeElement("span", `the entire process was extremely pleasurable for ${him}${(numBeingBorn > 1) ? ',' : '.'}`, "green")); + if (numBeingBorn > 1) { + r.push(`with orgasms growing more powerful with each baby ${he} brought to the world.`); + } + r.push(`${He} can't wait to be impregnated and give birth again,`); if (birthDamage > 10) { r.push(`despite the complications,`); } @@ -2143,7 +2179,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) // at assignment else in halls/etc switch (slave.assignment) { - case "rest": + case Job.REST: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { if (random(1, 20) > suddenBirth) { @@ -2206,7 +2242,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } } break; - case "be a subordinate slave": + case Job.SUBORDINATE: if (tempSub) { ({his2} = getPronouns(tempSub).appendSuffix("2")); } @@ -2270,7 +2306,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "whore": + case Job.WHORE: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { if (random(1, 20) > suddenBirth) { @@ -2312,7 +2348,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "serve the public": + case Job.PUBLIC: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { if (random(1, 20) > suddenBirth) { @@ -2430,7 +2466,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "work a glory hole": + case Job.GLORYHOLE: if (slave.fetish === "mindbroken") { if (random(1, 20) > suddenBirth) { r.push(`Since ${he} is unable to leave ${his} box, ${he} doesn't have far to go. Instinctively, ${he} begins to push out ${firstText} baby. ${His} child is quickly extracted from the box. ${He} never notices, focused entirely on the fresh cock poking through the glory hole and the sensation of ${his} still very gravid middle rubbing the wall.`); @@ -2461,7 +2497,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "get milked": + case Job.MILKED: if (slave.fetish === "mindbroken") { if (V.dairyPregSetting > 0) { r.push(`Since the dairy is designed for pregnant cows, ${he} stays hooked up to the milkers. ${He} shows little interest in ${his} coming birth, instead focusing on ${his} milky breasts. Instinctively, ${he} begins to push out ${firstText} baby. ${He} shows no interest in ${his} child being removed from the milking stall, nor when ${his} still very gravid body is hosed off.`); @@ -2500,7 +2536,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "work as a farmhand": // TODO: this needs a rewrite + case Job.FARMYARD: // TODO: this needs a rewrite if (slave.fetish === "mindbroken") { if (V.farmyardPregSetting > 0) { r.push(`Since the farmyard is designed for pregnant cows, ${he} stays hooked up to the milkers. ${He} shows little interest in ${his} coming birth, instead focusing on ${his} milky breasts. Instinctively, ${he} begins to push out ${firstText} baby. ${He} shows no interest in ${his} child being removed from the milking stall, nor when ${his} still very gravid body is hosed off.`); @@ -2539,7 +2575,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "please you": + case Job.FUCKTOY: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { if (random(1, 20) > suddenBirth) { @@ -2617,7 +2653,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "stay confined": + case Job.CONFINEMENT: if (slave.fetish === "mindbroken") { if (random(1, 20) > suddenBirth) { r.push(`Since ${he} is locked in a cell, ${he} doesn't have far to go. Instinctively, ${he} begins to push out ${firstText} baby. ${His} child is promptly taken and, after ${his} still very gravid body and the cell are hosed down, ${he} is returned to isolation.`); @@ -2638,8 +2674,8 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "work as a servant": - case "be a servant": + case Job.QUARTER: + case Job.HOUSE: if (slave.fetish === "mindbroken") { if (random(1, 20) > suddenBirth) { r.push(`${He} returns to ${his} bed and strips before slipping into it. Instinctively ${he} begins to push out ${firstText} baby. ${His} child is promptly taken and ${he} rests awhile before returning to ${his} role as your ever-pregnant maid.`); @@ -2704,7 +2740,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "serve in the master suite": + case Job.MASTERSUITE: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { if (random(1, 20) > suddenBirth) { @@ -2884,7 +2920,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "serve in the club": + case Job.CLUB: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { if (random(1, 20) > suddenBirth) { @@ -2940,7 +2976,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "choose her own job": + case Job.CHOICE: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { if (random(1, 20) > suddenBirth) { @@ -2987,7 +3023,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "rest in the spa": + case Job.SPA: if (S.Attendant) { ({he2, him2} = getPronouns(S.Attendant).appendSuffix("2")); } @@ -3040,7 +3076,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "work as a nanny": // TODO: this needs a rewrite + case Job.NURSERY: // TODO: this needs a rewrite if (V.MatronID !== 0) { ({he2} = getPronouns(S.Matron).appendSuffix("2")); } @@ -3093,7 +3129,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "learn in the schoolroom": + case Job.SCHOOL: if (S.Schoolteacher) { ({he2} = getPronouns(S.Schoolteacher).appendSuffix("2")); } @@ -3160,7 +3196,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "take classes": + case Job.CLASSES: if (random(1, 20) > suddenBirth) { r.push(`Or ${he} would have, had ${V.assistant.name} allowed it. Since ${he} can't leave the lesson, ${he} tries ${his} best to hold back the upcoming birth, not without your assistant noticing. As punishment for poor planning, especially since this will be a weekly occurrence in ${his} life, ${his} birth will be turned into a live broadcast. Blushing strongly, ${he} begins working on birthing ${firstText} baby, trying ${his} best to hide ${his} shame.`); if (slave.geneticQuirks.uterineHypersensitivity === 2) { @@ -3182,7 +3218,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "work in the brothel": + case Job.BROTHEL: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { if (random(1, 20) > suddenBirth) { @@ -3279,7 +3315,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } else { r.push(`${He} stands shaking, ${his} waters flowing down ${his}`); if (hasAnyLegs(slave)) { - r.push(`${(hasBothLegs(slave)) ? `legs` : `leg`},`); + r.push(hasBothLegs(slave) ? `legs` : `leg`); } else { r.push(`body,`); } @@ -3326,7 +3362,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be the Schoolteacher": + case Job.TEACHER: if (!canWalk(slave)) { if (random(1, 20) > suddenBirth) { r.push(`${He} calls for ${his} teaching aid to help position ${him} so the class may receive a lesson on childbirth. ${He} begins working on birthing ${firstText} baby, fully aware of ${his} watching students. ${He} demonstrates the proper ways to labor and how to deliver a baby${(slave.geneticQuirks.uterineHypersensitivity === 2) ? `even if your body is wracked by nonstop orgasm` : ``}. ${He} explains the infant's future as ${his} child taken and excuses the class for a short break in order to freshen up. Upon their return, ${he} begins a lesson on being a broodmother, as there is always a curious face locked onto ${his} still very gravid middle.`); @@ -3356,7 +3392,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be your Concubine": + case Job.CONCUBINE: if (slave.pregSource === -1 && slave.relationship === -3) { if (random(1, 20) > suddenBirth) { r.push(`You make sure to find time in your busy schedule to be at your concubine ${wife}'s side as ${he} gives birth to your children, even if it's`); @@ -3411,7 +3447,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "live with your Head Girl": + case Job.HEADGIRLSUITE: ({he2} = getPronouns(S.HeadGirl).appendSuffix("2")); if (slave.pregSource === V.HeadGirlID) { if (random(1, 20) > suddenBirth) { @@ -3458,7 +3494,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be confined in the arcade": + case Job.ARCADE: r.push(`Or ${he} would have been, if ${he} weren't locked in an arcade cabinet. A gush of liquid pours from ${slave.slaveName}'s cunt, followed by the attendant in charge of the arcade hanging an "out of order" sign on ${his} exposed rear. While ${his} mouth is filled with a customer's dick, ${his}`); if (slave.geneticQuirks.uterineHypersensitivity === 2) { r.push(`orgasming`); @@ -3466,7 +3502,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) r.push(`body instinctively births ${firstText} baby into a waiting basket. As it is carried away, ${his} rear is cleaned up and the sign removed.`); break; - case "get treatment in the clinic": + case Job.CLINIC: if (S.Nurse) { ({he2, his2} = getPronouns(S.Nurse).appendSuffix("2")); } else { @@ -3511,7 +3547,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be confined in the cellblock": + case Job.CELLBLOCK: if (slave.fetish === "mindbroken") { if (random(1, 20) > suddenBirth) { r.push(`${He} is forced into a specially designed cell to give birth in. Instinctively, ${he} begins to push out ${firstText} baby. ${His} child is promptly taken and, after ${his} still very gravid body and the cell are hosed down, ${he} is moved back into a standard cell.`); @@ -3531,7 +3567,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be the DJ": + case Job.DJ: if (random(1, 20) > suddenBirth) { r.push(`${He} heads to a private room in the back of the club accompanied by an influential patron. ${He} settles ${himself} onto his lap and begins working on ${firstText} baby, basking in his attention${UH}. Placing ${his} child outside the room, ${he} returns to pleasure ${his} tease.`); } else { @@ -3542,7 +3578,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be the Attendant": + case Job.ATTENDANT: if (random(1, 20) > suddenBirth) { r.push(`${S.Attendant.slaveName} waddles to a special pool designed to give birth in. Once ${he} is safely in the water, ${he} begins to push out ${firstText} baby,`); if (slave.geneticQuirks.uterineHypersensitivity === 2) { @@ -3557,7 +3593,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be the Madam": + case Job.MADAM: if (random(1, 20) > suddenBirth) { r.push(`${He} heads to a private room in the back of the club accompanied by an influential patron. ${He} settles ${himself} onto his lap and begins working on birthing ${firstText} baby,`); if (slave.geneticQuirks.uterineHypersensitivity === 2) { @@ -3573,7 +3609,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be the Stewardess": + case Job.STEWARD: if (random(1, 20) > suddenBirth) { r.push(`${He} strips and settles ${himself} into ${his} favorite chair while calling several servants to ${his} aid. ${He} begins to push out ${firstText} baby into the arms of ${his} waiting charges${UH}. ${His} child is promptly taken and ${he} reclines while ${his} servants clean and dress ${his} still very gravid body. Once ${he} has had enough, ${he} orders them to help ${him} up and get back to work on the penthouse.`); } else { @@ -3590,7 +3626,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be the Milkmaid": + case Job.MILKMAID: if (random(1, 20) > suddenBirth) { r.push(`${He} returns to ${his} bed and strips before slipping into it. ${He} makes ${himself} comfortable and begins working on birthing ${firstText} baby${UH}. ${He} is quite experienced in delivering ${his} cows' children, but ${he} finds it much more difficult to apply ${his} knowledge to ${himself}. ${His} child is promptly taken and, after a short rest, ${he} returns to caring for your cows, as gravid as ever.`); } else { @@ -3605,7 +3641,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be the Farmer": // TODO: this needs a rewrite + case Job.FARMER: // TODO: this needs a rewrite if (random(1, 20) > suddenBirth) { r.push(`${He} returns to ${his} bed and strips before slipping into it. ${He} makes ${himself} comfortable and begins working on birthing ${firstText} baby${UH}. ${He} is quite experienced in delivering ${his} cows' children, but ${he} finds it much more difficult to apply ${his} knowledge to ${himself}. ${His} child is promptly taken and, after a short rest, ${he} returns to caring for your cows, as gravid as ever.`); } else { @@ -3620,7 +3656,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be the Wardeness": + case Job.WARDEN: if (slave.fetish === "mindbroken") { if (random(1, 20) > suddenBirth) { r.push(`${He} enters an empty cell, strips, and seats ${himself} on the cot. ${He} instinctively begins birthing ${firstText} baby. ${His} child is promptly taken and ${he} returns to mindlessly breaking the confined slaves.`); @@ -3646,7 +3682,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be the Nurse": + case Job.NURSE: if (random(1, 20) > suddenBirth) { r.push(`${He} waddles to ${his} maternity ward and strips before settling into an open bed. ${He} makes ${himself} comfortable and begins working on birthing ${firstText} baby${UH}as ${his} assistants watch. ${His} child is promptly taken and ${he} is helped to the recovery ward until ${he} recovers enough to take over ${V.clinicName} again.`); } else { @@ -3656,7 +3692,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be your Head Girl": + case Job.HEADGIRL: if (random(1, 20) > suddenBirth) { r.push(`${He} returns to`); if (V.HGSuite === 1) { @@ -3677,7 +3713,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "guard you": + case Job.BODYGUARD: if (random(1, 20) > suddenBirth) { r.push(`Or ${he} would have, if ${he}'d stop refusing to leave your side. You lead ${him} someplace private and help ${him} undress. ${He} makes ${himself} comfortable and begins working on birthing ${firstText} baby${UH}. You call for a servant to quickly gather ${his} child as you help ${him} into the shower, making sure to wait outside for your loyal guardian to finish.`); } else { @@ -3687,7 +3723,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "recruit girls": + case Job.RECRUITER: if (random(1, 20) > suddenBirth) { r.push(`${He} returns to ${his} bed and strips before slipping into it. ${He} makes ${himself} comfortable and begins working on birthing ${firstText} baby${UH}. ${His} child is promptly taken and ${he} rests awhile before returning to finding new slaves for you.`); } else { @@ -4007,7 +4043,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) // at assignment else in halls/etc switch (slave.assignment) { - case "rest": + case Job.REST: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { r.push(`${slave.slaveName} is awoken from ${his} rest by a strong contraction. ${He} attempts to roll over, and failing that, begins to fall back to sleep as another contraction wracks ${his} body.`); @@ -4031,7 +4067,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be a subordinate slave": + case Job.SUBORDINATE: if (tempSub) { ({he2} = getPronouns(tempSub).appendSuffix("2")); } @@ -4060,7 +4096,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "whore": + case Job.WHORE: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { r.push(`While attempting to attract customers to fuck ${his} grotesquely distended body, ${slave.slaveName}'s body begins to birth another of ${his} brood.`); @@ -4092,7 +4128,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "serve the public": + case Job.PUBLIC: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { if (pbw > 80) { @@ -4200,7 +4236,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "work a glory hole": + case Job.GLORYHOLE: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { r.push(`While sucking a dick through the hole of ${his} confining box, ${slave.slaveName}'s body begins to birth another of ${his} brood. ${He} makes no effort to stop sucking the dicks presented to ${him}.`); @@ -4224,7 +4260,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "get milked": + case Job.MILKED: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { r.push(`While getting milked, ${slave.slaveName}'s body begins to birth another of ${his} brood. ${He} show little interest and continues kneading ${his} breasts.`); @@ -4250,7 +4286,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "please you": + case Job.FUCKTOY: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { r.push(`While sitting absentmindedly nearby, ${slave.slaveName}'s body begins to birth another of ${his} brood. ${He} pays no heed to it and continues waiting for you to use ${him}.`); @@ -4290,7 +4326,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "stay confined": + case Job.CONFINEMENT: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { r.push(`While waiting in confinement, ${slave.slaveName}'s body begins to birth another of ${his} brood. Since ${he} can't move, ${he} just lets things happen.`); @@ -4316,8 +4352,8 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "work as a servant": - case "be a servant": + case Job.QUARTER: + case Job.HOUSE: if (slave.fetish === "mindbroken") { if (random(0, 1) === 1) { r.push(`While giving a slave oral service, ${slave.slaveName}'s body begins to birth another of ${his} brood. ${He} disregards this development and continues working.`); @@ -4363,7 +4399,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "serve in the master suite": + case Job.MASTERSUITE: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { if (V.masterSuiteUpgradeLuxury === 1) { @@ -4437,7 +4473,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "serve in the club": + case Job.CLUB: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { r.push(`${slave.slaveName} is showing off ${his} grotesque body and trying to attract citizens by dancing as well as ${he} can. During one of ${his} dances, ${his} body begins to birth another of ${his} brood. ${He} keeps on dancing, despite ${his} condition, until ${his} contractions drag ${him} onto ${his} bloated stomach.`); @@ -4473,7 +4509,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "choose her own job": + case Job.CHOICE: if (!canWalk(slave)) { r.push(`While thinking about what job to take as an immobile womb, ${slave.slaveName}'s body begins to birth another of ${his} brood. Unable to do anything but labor, ${he} gives in to what's coming.`); r.push(clothingBirth()); @@ -4492,7 +4528,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "rest in the spa": + case Job.SPA: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { r.push(`While soaking in the spa's pool, ${slave.slaveName}'s body begins to birth another of ${his} brood. As ${he} begins to ready ${himself} for birth,`); @@ -4537,7 +4573,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "learn in the schoolroom": + case Job.SCHOOL: if (!canWalk(slave)) { r.push(`During a lesson in ${V.schoolroomName}, ${slave.slaveName}'s body begins to birth another of ${his} brood. Since this isn't the first time ${he} interrupted the lesson this week, and ${he} is too heavy to move, ${he} is allowed to give birth right where ${he} is.`); humiliation = 1; @@ -4551,7 +4587,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "take classes": + case Job.CLASSES: if (!canWalk(slave)) { r.push(`During a lesson under ${V.assistant.name}, ${slave.slaveName}'s body begins to birth another of ${his} brood. Your assistant pauses and waits for ${him} to finish, having given up after the last several times`); r.push(clothingBirth()); @@ -4563,7 +4599,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "work in the brothel": + case Job.BROTHEL: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { if (pbw > 80) { @@ -4671,7 +4707,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be your Concubine": + case Job.CONCUBINE: if (slave.fetish === "mindbroken") { } else { r.push(`${slave.slaveName} cradles ${his} swollen belly, waiting for your return, when ${his} body begins to birth another of ${his} brood. Saddened that you aren't there for the show, ${he} begins waddling off to find you. By the time ${he} reaches your office, ${he} is barely holding back ${his} child. You rise to meet ${him} and struggle to help ${him} onto the couch, just before it's to late.`); @@ -4680,7 +4716,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "live with your Head Girl": + case Job.HEADGIRLSUITE: ({he2, his2} = getPronouns(S.HeadGirl).appendSuffix("2")); if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { @@ -4705,11 +4741,11 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be confined in the arcade": + case Job.ARCADE: r.push(`A gush of liquid pours from the ${slave.slaveName}'s cunt, followed by the attendant in charge of the arcade hanging an "out of order" sign on ${his} exposed rear. While ${his} mouth is filled with a customer's dick, ${his} body instinctively births ${his} child into the waiting basket. As they are carried away, ${his} rear is cleaned up and the sign removed.`); break; - case "get treatment in the clinic": + case Job.CLINIC: if (S.Nurse) { ({he2, his2} = getPronouns(S.Nurse).appendSuffix("2")); } @@ -4722,7 +4758,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) r.push(`delivers ${his} child before taking them away. Before long ${he2} returns to attend to ${his2} patient's perpetual pregnancy.`); break; - case "be confined in the cellblock": + case Job.CELLBLOCK: if (slave.fetish === "mindbroken") { r.push(`While waiting in confinement, ${slave.slaveName}'s body begins to birth another of ${his} brood. ${He} assumes a birthing position.`); r.push(clothingBirth()); @@ -4903,7 +4939,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } } else { switch (slave.assignment) { - case "rest": + case Job.REST: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { r.push(`${He} is helped back to ${his} bed and stripped before slipping into it. Instinctively, ${he} begins to push out ${his} ${babies}. ${His} ${childrenAre} promptly taken and ${he} is encouraged to keep resting.`); @@ -4919,7 +4955,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be a subordinate slave": { + case Job.SUBORDINATE: { const domSlave = getSlave(slave.subTarget); if (domSlave) { ({he2} = getPronouns(domSlave).appendSuffix("2")); @@ -4959,7 +4995,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) break; } - case "whore": + case Job.WHORE: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { r.push(`${He} is helped back to ${his} bed and stripped before slipping into it. Instinctively, ${he} begins to push out ${his} ${babies}. ${His} ${childrenAre} promptly taken and ${he} rests awhile before returning to whoring.`); @@ -4975,7 +5011,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "serve the public": + case Job.PUBLIC: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { r.push(`${He} is helped back to ${his} bed and stripped before slipping into it. Instinctively, ${he} begins to push out ${his} ${babies}. ${His} ${childrenAre} promptly taken and ${he} rests awhile before returning to slutting.`); @@ -4991,7 +5027,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "work a glory hole": + case Job.GLORYHOLE: if (slave.fetish === "mindbroken") { r.push(`Since ${he} is unable to leave ${his} box, ${he} doesn't have far to go. Instinctively, ${he} begins to push out ${his} ${babies}. ${His} ${childrenAre} quickly extracted from the box. ${He} never notices, focused entirely on the fresh cock poking through the glory hole.`); } else { @@ -4999,7 +5035,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "get milked": + case Job.MILKED: if (slave.fetish === "mindbroken") { if (V.dairyPregSetting > 0) { r.push(`Since the dairy is designed for pregnant cows, ${he} stays hooked up to the milkers. ${He} shows little interest in ${his} coming birth, instead focusing on ${his} milky breasts. Instinctively, ${he} begins to push out ${his} ${babies}. ${He} pays no heed to ${his} ${children} being removed from the milking stall, nor when ${he} is hosed off.`); @@ -5026,7 +5062,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "work as a farmhand": + case Job.FARMYARD: animals = []; roll; if (V.canines.length > 0) { @@ -5087,7 +5123,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "please you": + case Job.FUCKTOY: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { r.push(`You strip ${him} and help ${him} onto your couch. Instinctively, ${he} begins to push out ${his} ${babies}. ${His} ${childrenAre} promptly taken and ${he} falls into a contented nap. You enjoy ${his} exhausted body until a servant comes to help clean ${him} up.`); @@ -5125,7 +5161,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "stay confined": + case Job.CONFINEMENT: if (slave.fetish === "mindbroken") { r.push(`Since ${he} is locked in a cell, ${he} doesn't have far to go. Instinctively, ${he} begins to push out ${his} ${babies}. ${His} ${childrenAre} promptly taken and, after ${he} and the cell are hosed down, ${he} is returned to isolation.`); } else { @@ -5134,8 +5170,8 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "work as a servant": - case "be a servant": + case Job.QUARTER: + case Job.HOUSE: if (slave.fetish === "mindbroken") { r.push(`${He} returns to ${his} bed and strips before slipping into it. Instinctively ${he} begins to push out ${his} ${babies}. ${His} ${childrenAre} promptly taken and ${he} rests awhile before returning to service your penthouse.`); } else { @@ -5143,7 +5179,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "serve in the master suite": + case Job.MASTERSUITE: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { if (V.masterSuiteUpgradePregnancy === 1) { @@ -5231,7 +5267,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "serve in the club": + case Job.CLUB: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { r.push(`${He} is helped into a private room in the back of the club by a group of eager patrons. Instinctively, ${he} begins to push out ${his} ${babies}, indifferent to ${his} audience. ${His} ${childrenAre} promptly taken and, following a cleaning and fresh change of clothes, the audience has their way with ${him}.`); @@ -5255,7 +5291,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "choose her own job": + case Job.CHOICE: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { r.push(`${He} is helped back to ${his} bed and stripped before slipping into it. Instinctively, ${he} begins to push out ${his} ${babies}. ${His} ${childrenAre} promptly taken and, after a short rest, ${he} waits for someone to help ${him} to ${his} next job having forgotten ${he} was choosing it.`); @@ -5271,7 +5307,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "rest in the spa": + case Job.SPA: if (S.Attendant) { r.push(S.Attendant.slaveName); if (slave.fetish === "mindbroken") { @@ -5292,7 +5328,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) r.push(`${his} helper. ${His} ${childrenAre} promptly taken and, following a cleaning, ${he} is taken back to the spa.`); break; - case "work as a nanny": + case Job.NURSERY: r.push(`${He} finishes`); if (V.nurseryChildren) { r.push(`changing the child's diaper`); @@ -5302,7 +5338,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) r.push(`and heads back to ${his} little room before stripping and getting into bed. ${He} begins the ordeal of childbirth, and after ${he} is finished, rests for a bit while ${his} ${childrenAre} collected. After a short shower, ${he} returns to ${his} duties in ${V.nurseryName}.`); break; - case "learn in the schoolroom": + case Job.SCHOOL: r.push(`Having been notified in the weeks leading up to ${his} birth, ${he}`); if (canWalk(slave)) { r.push(`heads`); @@ -5324,12 +5360,12 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) humiliation = 1; break; - case "take classes": + case Job.CLASSES: r.push(`Or ${he} would have, had ${V.assistant.name} allowed it. Since ${he} can't leave the lesson, ${he} tries ${his} best to hold back the upcoming birth, not without your assistant noticing. As punishment for poor planning, ${his} birth will be turned into a live broadcast. Blushing strongly, ${he} begins working on birthing ${his} ${babies}, trying ${his} best to hide ${his} shame${(slave.geneticQuirks.uterineHypersensitivity === 2) ? `, which isn't helped by the fact that ${he} is convulsing with orgasms in the process` : ``}. Exhausted from the birth, ${he} is permitted a short break as ${his} ${childrenAre} collected to clean ${himself} up before the lesson is continued.`); humiliation = 1; break; - case "work in the brothel": + case Job.BROTHEL: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { r.push(`${He} is helped to a private room in the back of the brothel by a group of eager patrons. Instinctively, ${he} begins to push out ${his} ${babies}, indifferent to ${his} audience. ${His} ${childrenAre} promptly taken and, following a cleaning and fresh change of clothes, the audience is allowed to have their way with ${him}.`); @@ -5345,7 +5381,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be the Schoolteacher": + case Job.TEACHER: if (!canWalk(slave)) { r.push(`The class has been wondering why ${he} was sitting strangely, nude at the front of the class the last several weeks, today they learn why. ${He} has been planning this lesson for several months now. ${He} wiggles ${himself} into a comfortable spot and begins working on birthing ${his} ${babies}, ${(slave.geneticQuirks.uterineHypersensitivity === 2) ? `convulsing with orgasms in the process, while being` : ``} fully aware of ${his} watching students. ${He} demonstrates the proper ways to labor and how to deliver a baby. ${He} explains the infant's future as ${his} ${childrenAre} taken and excuses the class for a short break in order to freshen up.`); humiliation = 1; @@ -5355,8 +5391,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - - case "be your Concubine": + case Job.CONCUBINE: if (slave.pregSource === -1 && slave.relationship === -3) { r.push(`You make sure to find time in your busy schedule to be at your concubine ${wife}'s side as ${he} gives birth to your ${children}. You gently caress ${slave.slaveName}'s body as ${he} begins to push out ${his} ${babies}${UH}. You help ${him} upright and hold your ${children} to ${his} breasts. The two of you cuddle as you watch your ${newborns} suckle from their mother. Since ${he} is quite special to you, you allow ${him} the time to pick out names before ${his} ${children} must be taken away. When the time comes to pick up the ${newborns}, the slave servant is surprised to find ${(slave.pregType === 1) ? `a name-card` : `name-cards`} affixed to their ${(slave.pregType > 1) ? `blankets` : `blanket`}.`); if (slave.fetish !== "mindbroken") { @@ -5377,7 +5412,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "live with your Head Girl": + case Job.HEADGIRLSUITE: ({He2, he2, his2} = getPronouns(S.HeadGirl).appendSuffix("2")); if (slave.pregSource === V.HeadGirlID) { r.push(`${S.HeadGirl.slaveName} makes sure that the mother of ${his2} ${children} is happy and comfortable for the upcoming birth, even if they won't be spending much time with their offspring. ${He2} carefully undresses ${slave.slaveName}, all the while whispering sweet nothings in ${his} ear. ${He} begins to push out ${his} ${babies},`); @@ -5400,11 +5435,11 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be confined in the arcade": + case Job.ARCADE: r.push(`Or ${he} would have been, if ${he} weren't locked in an arcade cabinet. A gush of liquid pours from the ${slave.slaveName}'s cunt, followed by the attendant in charge of the arcade hanging an "out of order" sign on ${his} exposed rear. While ${his} mouth is filled with a customer's dick, ${his} body instinctively births ${his} ${children} into the waiting basket${UH}. As they are carried away, ${his} rear is cleaned up and the sign removed.`); break; - case "get treatment in the clinic": + case Job.CLINIC: if (!canWalk(slave)) { r.push(`${He} is helped to the clinic's maternity ward.`); if (S.Nurse) { @@ -5436,7 +5471,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be confined in the cellblock": + case Job.CELLBLOCK: if (slave.fetish === "mindbroken") { r.push(`${He} is forced into a specially designed cell to give birth in. Instinctively, ${he} begins to push out ${his} ${babies}. ${His} ${childrenAre} promptly taken and, after ${he} and the cell are hosed down, ${he} is moved back into a standard cell.`); } else { @@ -5444,19 +5479,19 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be the DJ": + case Job.DJ: r.push(`${He} heads to a private room in the back of the club accompanied by an influential patron. ${He} settles ${himself} onto his lap and begins working on birthing ${his} ${babies}, basking in his attention${UH}. Placing ${his} ${children} outside the room, ${he} returns to pleasure ${his} tease.`); break; - case "be the Attendant": + case Job.ATTENDANT: r.push(`${S.Attendant.slaveName} waddles to a special pool designed to give birth in. Once ${he} is safely in the water, ${he} begins to push out ${his} ${babies}, something ${he} has been trained for ${(slave.geneticQuirks.uterineHypersensitivity === 2) ? `, even if ${he} was convulsing with orgasms in the process` : ``}. ${His} ${childrenAre} promptly taken and, following a cleaning, ${he} heads back to the main pool.`); break; - case "be the Matron": + case Job.MATRON: r.push(`${He} quickly waddles back to ${his} private room before stripping and calling in several slaves to assist ${him} in childbirth. ${He} has quite a bit of experience in taking care of children, but not as much in delivering them, and less so in delivering ${his} own. ${He} soon figures it out, though, and after an exhausting birthing ordeal, ${his} ${childrenAre} taken from ${him}, and ${he} is allowed a shower and a rest before returning to work.`); break; - case "be the Madam": + case Job.MADAM: r.push(`${He} heads to a private room in the back of the club accompanied by an influential patron. ${He} settles ${himself} onto his lap and begins working on birthing ${his} ${babies},`); if (slave.geneticQuirks.uterineHypersensitivity === 2) { r.push(`convulsing with orgasms in the process and`); @@ -5464,19 +5499,19 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) r.push(`basking in his attention as he strips ${him}. Placing ${his} ${children} outside the room, ${he} returns to get more intimate with ${his} catch.`); break; - case "be the Stewardess": + case Job.STEWARD: r.push(`${He} strips and settles ${himself} into ${his} favorite chair, while calling several servants to ${his} aid. ${He} begins to push out ${his} ${babies} into the arms of ${his} waiting charges${UH}. ${His} ${childrenAre} promptly taken and ${he} reclines while ${his} servants clean and dress ${him}. Once ${he} has had enough, ${he} orders them back to work on the penthouse.`); break; - case "be the Milkmaid": + case Job.MILKMAID: r.push(`${He} returns to ${his} bed and strips before slipping into it. ${He} makes ${himself} comfortable and begins working on birthing ${his} ${babies}${UH}. ${He} is quite experienced in delivering ${his} cows' children, but ${he} finds it much more difficult to apply ${his} knowledge to ${himself}. ${His} ${childrenAre} promptly taken and, after a short rest, ${he} returns to caring for your cows.`); break; - case "be the Farmer": + case Job.FARMER: r.push(`${He} heads to ${his} private room before stripping and calling in a couple of nearby slaves to aid ${him}. Though ${he} has delivered more than a few of ${his} livestocks' offspring, delivering ${his} own proves to be a slightly more difficult ordeal. ${He} manages, though, and after ${his} ${childrenAre} taken from ${him} and ${he}'s had a shower and a short rest, ${he} returns to looking after ${V.farmyardName}.`); break; - case "be the Wardeness": + case Job.WARDEN: if (slave.fetish === "mindbroken") { // FIXME: can Wardens be mindbroken? r.push(`${He} enters an empty cell, strips, and seats ${himself} on the cot. ${He} instinctively begins birthing ${his} ${babies}. ${His} ${childrenAre} promptly taken and ${he} returns to mindlessly breaking the confined slaves.`); } else { @@ -5484,11 +5519,11 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be the Nurse": + case Job.NURSE: r.push(`${He} waddles to ${his} maternity ward and strips before laying on an open bed. ${He} makes ${himself} comfortable and begins working on birthing ${his} ${babies}${UH}as ${his} assistants watch. ${His} ${childrenAre} promptly taken and ${he} is helped to the recovery ward until ${he} recovers enough to take over ${V.clinicName} again.`); break; - case "be your Head Girl": + case Job.HEADGIRL: r.push(`${He} returns to`); if (V.HGSuite === 1) { r.push(`${his} room's bed`); @@ -5506,11 +5541,11 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) r.push(`and ${he} rests awhile before returning to managing your slaves.`); break; - case "guard you": + case Job.BODYGUARD: r.push(`Or ${he} would have, if ${he}'d stop refusing to leave your side. You lead ${him} someplace private and help ${him} undress. ${He} makes ${himself} comfortable and begins working on birthing ${his} ${babies}${UH}. You call for a servant to quickly gather ${his} ${children} as you help ${him} into the shower, making sure to wait outside for your loyal guardian to finish.`); break; - case "recruit girls": + case Job.RECRUITER: r.push(`${He} returns to ${his} bed and strips before slipping into it. ${He} makes ${himself} comfortable and begins working on birthing ${his} ${babies}${UH}. ${His} ${childrenAre} promptly taken and ${he} rests awhile before returning to finding new slaves for you.`); break; @@ -5569,7 +5604,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } } else { switch (slave.assignment) { - case "rest": + case Job.REST: if (slave.fetish === "mindbroken") { r.push(`${He} is placed on ${his} bed and stripped. Instinctively, ${he} begins to push out ${his} ${babies}, indifferent to ${his} watching helper. ${His} ${childrenAre} promptly taken and ${he} is encouraged to keep resting.`); } else { @@ -5582,7 +5617,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be a subordinate slave": { + case Job.SUBORDINATE: { const domSlave = getSlave(slave.subTarget); if (domSlave) { ({he2} = getPronouns(domSlave).appendSuffix("2")); @@ -5631,9 +5666,9 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) break; } - case "whore": - case "serve the public": - case "choose her own job": + case Job.WHORE: + case Job.PUBLIC: + case Job.CHOICE: if (slave.fetish === "mindbroken") { r.push(`${He} is placed on ${his} bed and stripped. Instinctively, ${he} begins to push out ${his} ${babies}, indifferent to ${his} watching helper. ${His} ${childrenAre} promptly taken and, following a cleaning and fresh change of clothes, ${he} is carried back to ${his} station.`); } else { @@ -5646,7 +5681,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "work a glory hole": + case Job.GLORYHOLE: if (slave.fetish === "mindbroken") { r.push(`${He} is locked, nude, in a glory hole box and ordered to suck. Instinctively, ${he} begins to push out ${his} ${babies}. ${His} ${childrenAre} quickly extracted from the box. ${He} never notices, focused entirely on the fresh cock poking through the glory hole.`); } else { @@ -5654,7 +5689,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "get milked": + case Job.MILKED: if (slave.fetish === "mindbroken") { if (V.dairyPregSetting > 0) { r.push(`${He} is hooked up to a milking machine and allowed to continue ${his} assignment. ${He} shows little interest in ${his} coming birth, instead focusing on ${his} milky breasts. Instinctively, ${he} begins to push out ${his} ${babies}. ${He} shows no interest in ${his} ${children} being removed from the milking stall, nor when ${he} is hosed off.`); @@ -5680,7 +5715,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "please you": + case Job.FUCKTOY: if (slave.fetish === "mindbroken") { r.push(`${He} is stripped and placed into your waiting arms upon your couch. Instinctively, ${he} begins to push out ${his} ${babies} as you tease ${his} breasts and belly, indifferent to you and ${his} watching helper. ${His} ${childrenAre} promptly taken and, following a cleaning and a fresh change of clothes, ${he} is returned to your office.`); } else { @@ -5701,8 +5736,8 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "stay confined": - case "be confined in the cellblock": + case Job.CONFINEMENT: + case Job.CELLBLOCK: if (slave.fetish === "mindbroken") { r.push(`${He} is placed in a specially designed cell to give birth in. Instinctively, ${he} begins to push out ${his} ${babies}. ${His} ${childrenAre} promptly taken and, after ${he} and the cell are hosed down, ${he} is moved back into a standard cell.`); } else { @@ -5710,8 +5745,8 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "work as a servant": - case "be a servant": + case Job.QUARTER: + case Job.HOUSE: if (slave.fetish === "mindbroken") { r.push(`${He} is placed on ${his} cot and stripped. Instinctively, ${he} begins to push out ${his} ${babies}, indifferent to ${his} watching helper. ${His} ${childrenAre} promptly taken and, following a cleaning and fresh change of clothes, ${he} is carried back to ${his} station.`); } else { @@ -5724,7 +5759,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "serve in the master suite": + case Job.MASTERSUITE: if (slave.fetish === "mindbroken") { if (V.masterSuiteUpgradePregnancy === 1) { r.push(`${He} is carried to the birthing chamber and comfortably positioned. Instinctively, ${he} begins to push out ${his} ${babies}, indifferent to ${his} watching helper. ${His} ${childrenAre} promptly taken and, following a cleaning and fresh change of clothes, ${he} is carried back to`); @@ -5778,7 +5813,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "serve in the club": + case Job.CLUB: if (slave.fetish === "mindbroken") { r.push(`${He} is placed in a private room in the back of the club before an audience of eager patrons. Instinctively, ${he} begins to push out ${his} ${babies}, indifferent to ${his} audience. ${His} ${childrenAre} promptly taken and, following a cleaning and fresh change of clothes, the audience is allowed to have their way with ${him}.`); } else { @@ -5791,7 +5826,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "rest in the spa": + case Job.SPA: if (slave.fetish === "mindbroken") { r.push(`${He} is placed in a special flotation device and placed in a birthing pool. Instinctively, ${he} begins to push out ${his} ${babies}, indifferent to ${his} watching helper. ${His} ${childrenAre} promptly taken and, following a cleaning, ${he} is taken back to the spa.`); } else { @@ -5805,7 +5840,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "learn in the schoolroom": + case Job.SCHOOL: r.push(`${He} is placed on special seat at the front of the class and stripped. ${He} is being used as a learning aid in this lesson. Blushing strongly, ${he} begins working on birthing ${his} ${babies},`); if (slave.geneticQuirks.uterineHypersensitivity === 2) { r.push(`convulsing with orgasms in the process and`); @@ -5825,14 +5860,14 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) humiliation = 1; break; - case "take classes": + case Job.CLASSES: r.push(`Or ${he} would have been, had ${V.assistant.name} allowed it. Since ${he} can't leave the lesson, ${he} tries ${his} best to hold back the upcoming birth, not without your assistant noticing. As punishment for poor planning, ${he} is forbidden from leaving. Additionally, ${his} birth will be turned into a live broadcast.`); humiliation = 1; r.push(clothingBirth()); r.push(`Exhausted from the birth, ${he} is permitted a short break as ${his} ${childrenAre} removed to be cleaned up before the lesson is continued.`); break; - case "work in the brothel": + case Job.BROTHEL: if (slave.fetish === "mindbroken") { r.push(`${He} is placed in a private room in the back of the brothel before an audience of eager patrons. Instinctively, ${he} begins to push out ${his} ${babies}, indifferent to ${his} audience. ${His} ${childrenAre} promptly taken and, following a cleaning and fresh change of clothes, the audience is allowed to have their way with ${him}.`); } else { @@ -5845,7 +5880,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be the Schoolteacher": + case Job.TEACHER: r.push(`${He} is stripped and placed on a specially designed seat before ${his} class. ${He} has been planning this lesson for several months now. ${He} wiggles ${himself} into a comfortable spot and begins working on birthing ${his} ${babies},`); if (slave.geneticQuirks.uterineHypersensitivity === 2) { r.push(`convulsing with orgasms in the process and`); @@ -5854,7 +5889,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) humiliation = 1; break; - case "be your Concubine": + case Job.CONCUBINE: if (slave.pregSource === -1 && slave.relationship === -3) { r.push(`You make sure to find time in your busy schedule to be at your concubine ${wife}'s side as ${he} gives birth to your ${children}. You gently caress ${slave.slaveName}'s body as ${he} begins to push out your ${babies}${UH}. You help ${him} upright and hold your ${children} to ${his} ${breasts}. The two of you cuddle as you watch your ${newborns} suckle from their mother. Since ${he} is quite special to you, you allow ${him} the time to pick out names before ${his} ${children} must be taken away. When the time comes to pick up the ${newborns}, the slave servant is surprised to find`); if (slave.pregType === 1) { @@ -5875,7 +5910,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "live with your Head Girl": + case Job.HEADGIRLSUITE: ({he2} = getPronouns(S.HeadGirl).appendSuffix("2")); if (slave.pregSource === V.HeadGirlID) { r.push(`${S.HeadGirl.slaveName} makes sure that the mother of ${his2} ${children} is happy and comfortable for the upcoming birth, even if they won't be spending much time with their offspring. ${He2} carefully undresses ${slave.slaveName}, all the while whispering sweet nothings in ${his} ear. ${He} begins to push out ${his} ${babies},`); @@ -5894,11 +5929,11 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be confined in the arcade": + case Job.ARCADE: r.push(`Or ${he} would have been, if ${he} weren't locked in an arcade cabinet. A gush of liquid pours from the ${slave.slaveName}'s cunt, followed by the attendant in charge of the arcade hanging an "out of order" sign on ${his} exposed rear. While ${his} mouth is filled with a customer's dick, ${his} body instinctively births ${his} ${children} into the waiting basket. As they are carried away, ${his} rear is cleaned up and the sign removed.`); break; - case "get treatment in the clinic": + case Job.CLINIC: r.push(`${He} is taken to the clinic's maternity ward.`); if (S.Nurse) { r.push(S.Nurse.slaveName); @@ -5990,7 +6025,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } } else { switch (slave.assignment) { - case "rest": + case Job.REST: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { r.push(`${slave.slaveName} is awoken from ${his} rest by a strong contraction. ${He} rolls over and begins to fall back to sleep as another wracks ${his} body.`); @@ -6014,7 +6049,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be a subordinate slave": { + case Job.SUBORDINATE: { const domSlave = getSlave(slave.subTarget); if (domSlave) { ({he2} = getPronouns(domSlave).appendSuffix("2")); @@ -6064,7 +6099,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) break; } - case "whore": + case Job.WHORE: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { r.push(`While attempting to attract customers with ${his} gravid body, ${slave.slaveName}'s water breaks.`); @@ -6090,7 +6125,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "serve the public": + case Job.PUBLIC: if (slave.fetish === "mindbroken") { if (birthScene > 80 && canDoVaginal(slave)) { r.push(`While riding a citizen's dick, ${slave.slaveName}'s water breaks on him. Showing no signs of stopping, he shoves ${his} bulk off of him. Instinctively, ${he} begins to push out ${his} ${babies}, indifferent to who may be watching ${his} naked crotch. ${He} draws ${his} ${children} to ${his} ${breasts} before seeking out the next citizen's cock.`); @@ -6138,7 +6173,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "work a glory hole": + case Job.GLORYHOLE: if (slave.fetish === "mindbroken") { r.push(`While sucking a dick through the hole of ${his} confining box, ${slave.slaveName}'s water breaks. ${He} makes no effort to stop sucking the dicks presented to ${him}.`); r.push(clothingBirth()); @@ -6156,7 +6191,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "get milked": + case Job.MILKED: if (slave.fetish === "mindbroken") { r.push(`While getting milked, ${slave.slaveName}'s water breaks. ${He} show little regard and continues kneading ${his} breasts.`); r.push(clothingBirth()); @@ -6168,7 +6203,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "please you": + case Job.FUCKTOY: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { r.push(`While sitting absentmindedly nearby, ${slave.slaveName}'s water breaks soaking the floor under ${him}. ${He} pays no heed to it and continues waiting for you to use ${him}.`); @@ -6208,13 +6243,13 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "guard you": + case Job.BODYGUARD: r.push(`Refusing to leave your side even when on the verge of giving birth, ${slave.slaveName} continues to serve as your bodyguard despite ${his} condition. A splashing sound and a loud groan emit from behind you. Your bodyguard has gone into labor. You quickly help ${him} to the ground and prepare for the coming birth.`); r.push(clothingBirth()); r.push(`You sit by your loyal guard holding ${his} ${children} until a servant comes by to take them away. Once ${he} is thoroughly rested, you help ${him} up and lead ${him} back to the penthouse to shower and change.`); break; - case "stay confined": + case Job.CONFINEMENT: if (slave.fetish === "mindbroken") { r.push(`While waiting in confinement, ${slave.slaveName}'s water breaks. ${He} assumes a birthing position.`); r.push(clothingBirth()); @@ -6226,7 +6261,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "recruit girls": + case Job.RECRUITER: r.push(`While on a video call with a potential recruit, ${slave.slaveName}'s water breaks. ${He} attempts to play it cool and act like nothing is happening but the worsening contractions finally get to ${him}.`); humiliation = 1; r.push(clothingBirth()); @@ -6242,15 +6277,15 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be your Head Girl": + case Job.HEADGIRL: r.push(`While overseeing your other slaves, ${slave.slaveName}'s water breaks. ${He} attempts to hold back the coming birth until ${he} can catch a break in ${his} duties but ultimately fails.`); humiliation = 1; r.push(clothingBirth()); r.push(`Upon finishing, ${he} quickly collects ${his} ${children} and orders the mess to be cleaned promptly without breaking ${his} dominant appearance.`); break; - case "work as a servant": - case "be a servant": + case Job.QUARTER: + case Job.HOUSE: if (slave.fetish === "mindbroken") { if (birthScene > 50) { r.push(`While giving a slave oral service, ${slave.slaveName}'s water breaks. ${He} disregards this development and continues working.`); @@ -6307,7 +6342,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "serve in the master suite": + case Job.MASTERSUITE: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { if (V.masterSuiteUpgradeLuxury === 1) { @@ -6393,7 +6428,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "serve in the club": + case Job.CLUB: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { r.push(`${slave.slaveName} is showing off ${his} gravid body and trying to attract citizens as well as ${he} can. During one of ${his} teases, ${his} water breaks, soaking the floor. ${He} keeps on teasing, despite ${his} condition, until ${his} contractions drag ${him} to the floor.`); @@ -6430,7 +6465,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "choose her own job": + case Job.CHOICE: if (!canWalk(slave)) { r.push(`While deciding on ${his} post, ${slave.slaveName}'s water breaks. Unable to reach the prepared birthing room in time, ${he} pulls ${himself} into a secluded nook to give birth in.`); r.push(clothingBirth()); @@ -6447,7 +6482,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "rest in the spa": + case Job.SPA: if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { r.push(`While soaking in the spa's pool, ${slave.slaveName}'s water breaks. As ${he} begins to ready ${himself} for birth,`); @@ -6493,7 +6528,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "work as a nanny": + case Job.NURSERY: r.push(`In the middle of`); if (V.nurseryChildren) { r.push(`changing a baby's diaper,`); @@ -6510,7 +6545,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "learn in the schoolroom": + case Job.SCHOOL: if (S.Schoolteacher) { ({he2, his2} = getPronouns(S.Schoolteacher).appendSuffix("2")); } @@ -6537,7 +6572,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "take classes": + case Job.CLASSES: if (!canWalk(slave)) { r.push(`During a lesson under ${V.assistant.name}, ${slave.slaveName}'s water breaks. Since ${he} can't leave the lesson, ${he} tries ${his} best to hold back the upcoming birth, not without your assistant noticing. As punishment for poor planning, ${he} is forbidden from leaving. Additionally, ${his} birth will be turned into a live broadcast.`); humiliation = 1; @@ -6551,7 +6586,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "work in the brothel": + case Job.BROTHEL: if (slave.fetish === "mindbroken") { if (birthScene > 80 && canDoVaginal(slave)) { r.push(`While riding a customer's dick, ${slave.slaveName}'s water breaks on him. Showing no signs of stopping, he shoves ${his} gravid bulk off of him. Instinctively, ${he} begins to push out ${his} ${babies}, indifferent to who may be watching ${his} naked crotch. ${He} draws ${his} ${children} to ${his} ${breasts} before seeking out the next customer's cock.`); @@ -6599,28 +6634,28 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be the DJ": + case Job.DJ: r.push(`While DJing ${V.clubName}, ${slave.slaveName}'s water breaks. ${He} can't stop ${his} setlist without drawing attention so ${he} tries ${his} best to ride out the contractions. As soon as the opportunity arises, ${he} attempts to sneak off stage. However, a number of fans block ${his} progress keeping ${him} on stage. Before long the contractions are too much to bear and ${he} drops to the ground.`); humiliation = 1; r.push(clothingBirth()); r.push(`Exhausted, ${he} sits up and smiles to the crowd. ${His} show definitely drew attention to ${his} club. With a burst of energy ${he} leaps to ${his} feet, bows to the crowd, and gathers ${his} ${children}, before making ${his} way off stage. As ${he} leaves the public's gaze, ${he} shouts out with a wink "the next showing ought to be in about nine months".`); break; - case "be the Attendant": + case Job.ATTENDANT: r.push(`While tending to the guests in the spa, ${slave.slaveName}'s water breaks. The slaves quickly come to ${his} aid as the contractions get closer and closer together. Their hands are all over ${his} laboring body, unsure of what they should be doing.`); humiliation = 1; r.push(clothingBirth()); r.push(`${He} thanks ${his} charges for their less than helpful efforts and collects ${his} ${children} for removal. Upon returning, ${he} strips down and enters the pool, desperate for a break.`); break; - case "be the Matron": + case Job.MATRON: r.push(`While tending to the infants in ${V.nurseryName}, ${slave.slaveName}'s water breaks. The nannies quickly come to ${his} aid as the contractions get closer and closer together. They crowd around and watch, their curiosity getting the better of them.`); humiliation = 1; r.push(clothingBirth()); r.push(`${He} thanks ${his} assistants for their less than helpful efforts and collects ${his} ${children} for removal.`); break; - case "be the Madam": + case Job.MADAM: r.push(`While managing ${V.brothelName}, ${slave.slaveName}'s water breaks. Knowing ${he} lacks the time to leave, ${he} sets up a sign reading "Birthshow: ${cashFormat(100)} a viewer" and takes a seat.`); humiliation = 1; r.push(clothingBirth()); @@ -6628,7 +6663,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) cashX((100 * birthScene), "birth", slave); break; - case "be the Schoolteacher": + case Job.TEACHER: if (!canWalk(slave)) { r.push(`While teaching a lesson, ${slave.slaveName}'s water breaks. Sensing ${he} wouldn't be able to make it to the birthing area, ${he} instead chooses to act on the opportunity. Today's lesson will be on childbirth.`); humiliation = 1; @@ -6642,26 +6677,26 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be the Stewardess": + case Job.STEWARD: r.push(`While overseeing the house servants, ${slave.slaveName}'s water breaks. ${He} has no time to strip down so ${he} takes a seat and readies ${himself}. Commandingly, ${he} snaps ${his} fingers and orders ${his} charges to clean up the floor, assist ${him} with ${his} clothes, and be ready to take ${his} ${children} away.`); humiliation = 1; r.push(clothingBirth()); r.push(`Once ${he} catches ${his} breath, ${he} rises and takes the fresh change of clothing provided by ${his} servants before ordering them back to work.`); break; - case "be the Milkmaid": + case Job.MILKMAID: r.push(`While tending to ${his} stock, ${slave.slaveName}'s water breaks. ${He} hastily pulls ${himself} into a vacant stall and seats ${himself} in its corner.`); r.push(clothingBirth()); r.push(`Quickly, ${he} collects ${his} ${children} for removal before returning to ${V.dairyName}. The cows around ${his} stall all have a knowing look on their ${(V.dairyPregSetting > 0) ? `faces but with their own swollen bellies hanging heavily from them, they know that they soon will follow ${his} lead` : `faces`}.`); break; - case "be the Farmer": + case Job.FARMER: r.push(`While tending to some of ${his} livestock, ${slave.slaveName}'s water breaks. ${He} hastily finds a secluded corner and takes a seat on the (luckily fresh) hay.`); r.push(clothingBirth()); r.push(`Once ${he}'s finished, ${he} hands off ${his} ${children} to a nearby slave to look after for the time being before returning to what ${he} was previously doing.`); break; - case "be the Wardeness": + case Job.WARDEN: if (slave.fetish === "mindbroken") { r.push(`While punishing a slave, ${slave.slaveName}'s water breaks, soaking ${himU}. Indifferent, ${he} resumes beating ${himU} until the contractions are to much to bear. Settling to the floor, ${he} begins giving birth.`); r.push(clothingBirth()); @@ -6673,17 +6708,15 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be the Nurse": + case Job.NURSE: r.push(`While tending to your unwell slaves, ${slave.slaveName}'s water breaks. Counting the time between contractions, ${he} knows ${he} has no time to get to ${his} prepared birthing chamber. ${He} waddles into the nearest empty room and hoists ${his} gravid body into the examination chair, placing ${his} feet in the stirrups.`); r.push(clothingBirth()); r.push(`Quickly, ${he} collects ${his} ${children} for removal before retiring to the recovery ward. Within an hour of rest, ${he} is back on ${his} feet tending to ${his} charges.`); break; - case "be your Concubine": - if (slave.fetish === "mindbroken") { // TODO: WRITE BRANCH - r.push(`${slave.slaveName} cradles ${his} swollen belly, waiting for your return, when ${his} water breaks. Saddened that you aren't there for the show, ${he} begins waddling off to find you. By the time ${he} reaches your office, ${he} is barely holding back ${his} ${children}. You rise to meet ${him} and help ${him} onto the couch, just before it's too late.`); - r.push(clothingBirth()); - r.push(`Cradling your ${newborns}, the two of you rest for a spell before sending them off and spending some more intimate time together.`); + case Job.CONCUBINE: + if (slave.fetish === "mindbroken") { + r.push(`${He} is placed by your side. You strip ${him} as ${he} instinctively begins to push out ${his} ${babies}, indifferent to your wandering hands. ${His} ${childrenAre} promptly taken and, following a cleaning, a fresh change of clothes, and some private time with you, ${he} is carried back to your master suite.`); } else { r.push(`${slave.slaveName} cradles ${his} swollen belly, waiting for your return, when ${his} water breaks. Saddened that you aren't there for the show, ${he} begins waddling off to find you. By the time ${he} reaches your office, ${he} is barely holding back ${his} ${children}. You rise to meet ${him} and help ${him} onto the couch, just before it's too late.`); r.push(clothingBirth()); @@ -6691,7 +6724,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "live with your Head Girl": + case Job.HEADGIRLSUITE: ({he2} = getPronouns(S.HeadGirl).appendSuffix("2")); if (!canWalk(slave)) { if (slave.fetish === "mindbroken") { @@ -6716,11 +6749,11 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be confined in the arcade": + case Job.ARCADE: r.push(`A gush of liquid pours from the ${slave.slaveName}'s cunt, followed by the attendant in charge of the arcade hanging an "out of order" sign on ${his} exposed rear. While ${his} mouth is filled with a customer's dick, ${his} body instinctively births ${his} ${children} into the waiting basket. As they are carried away, ${his} rear is cleaned up and the sign removed.`); break; - case "get treatment in the clinic": + case Job.CLINIC: if (S.Nurse) { ({he2, his2} = getPronouns(S.Nurse).appendSuffix("2")); } @@ -6738,7 +6771,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "be confined in the cellblock": + case Job.CELLBLOCK: if (slave.fetish === "mindbroken") { r.push(`While waiting in a cell in ${V.cellblockName}, ${slave.slaveName}'s water breaks. ${He} assumes a birthing position,`); r.push(clothingBirth()); @@ -6792,7 +6825,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) r.push(`Feeling childbirth approaching, ${slave.slaveName} is helped to ${his} prepared birthing area.`); switch (slave.assignment) { - case "work a glory hole": + case Job.GLORYHOLE: r.push(`Since ${he} is unable to leave ${his} box, ${he} doesn't have far to go. ${He} quickly finishes the waiting dick before shifting ${himself} into a slightly, though not by much, more comfortable position. ${He} begins laboring on ${his} ${babies}. However, ${he} soon finds that ${he} is incapable of actually giving birth to ${his} ${children}. As blood begins to seep from ${his} nethers, ${he} desperately tries to get anyone's attention.`); App.Events.addParagraph(el, r); r = []; @@ -6805,8 +6838,8 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) r.push(`agape, is all that remains of the unfortunate ${slave.slaveName}.`); break; - case "stay confined": - case "be confined in the cellblock": + case Job.CONFINEMENT: + case Job.CELLBLOCK: r.push(`Since ${he} is locked in a cell, ${he} doesn't have far to go. Reluctantly, ${he} begins laboring on ${his} ${babies}. However, ${he} soon finds that ${he} is incapable of actually giving birth to ${his} ${children}. As blood begins to seep from ${his} nethers, ${he} desperately tries to get anyone's attention.`); App.Events.addParagraph(el, r); r = []; @@ -6819,7 +6852,7 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) r.push(`agape, is all that remains of the unfortunate ${slave.slaveName}.`); break; - case "be confined in the arcade": + case Job.ARCADE: r.push(`Or ${he} would have been, if ${he} weren't locked in an arcade cabinet. A gush of liquid pours from the ${slave.slaveName}'s cunt, followed by the attendant in charge of the arcade hanging an "out of order" sign on ${his} exposed rear. While ${his} mouth is filled with a customer's dick, ${his} body instinctively attempts laboring on ${his} ${babies}. However, ${he} soon finds that ${he} is incapable of actually giving birth to ${his} ${children}. As blood begins to seep from ${his} nethers, ${he} desperately tries to get anyone's attention. The attendant rushes to ${his} aid, but fails to get the cabinet open in time to save ${slave.slaveName}. ${He} and ${his} ${children} were an unfortunate loss.`); break; @@ -7597,6 +7630,8 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; + case "a military uniform": + case "a red army uniform": case "a hijab and blouse": case "a slutty schutzstaffel uniform": case "a dirndl": @@ -8052,25 +8087,6 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) } break; - case "a military uniform": - case "a red army uniform": - if (slave.fetish === "mindbroken") { - r.push(`${babies}, indifferent to the obvious wetness forming`); - if (slave.mpreg === 1) { - r.push(`under ${his} rear.`); - } else { - r.push(`over ${his} crotch.`); - } - } else { - r.push(`Quickly ${he} spreads ${his} legs apart and begins pushing out ${babyIntro}.`); - if (slave.fetish === "humiliation") { - r.push(`${He} is disappointed that ${his} skirt hides what's happening between ${his} legs.`); - } else { - r.push(`${He} does ${his} best to hide what's happening between ${his} legs.`); - } - } - break; - case "a schutzstaffel uniform": if (slave.fetish === "mindbroken") { r.push(`${babies}, indifferent to the obvious wetness forming`); @@ -9051,26 +9067,19 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) /** * Sends newborns to incubator or nursery * @param {App.Entity.SlaveState} mom + * @param {object[]} babiesBeingBorn ovum objects (FIXME: need defined type) + * @returns {object[]} remaining ova */ globalThis.sendNewbornsToFacility = function(mom, babiesBeingBorn) { - let numBeingBorn = babiesBeingBorn.length; - for (let cb = 0; cb < numBeingBorn; cb++) { - // if there is no reserved children, code in loop will not trigger - if (babiesBeingBorn[cb].reserve === "incubator") { - if (V.tanks.length < V.incubator) { - App.Facilities.Incubator.newChild(generateChild(mom, babiesBeingBorn[cb], true)); - } - babiesBeingBorn.splice(babiesBeingBorn[cb], 1); - cb--; - numBeingBorn--; - } else if (babiesBeingBorn[cb].reserve === "nursery") { - if (V.cribs.length < V.nursery) { - App.Facilities.Nursery.newChild(generateChild(mom, babiesBeingBorn[cb])); - } - babiesBeingBorn.splice(babiesBeingBorn[cb], 1); - cb--; - numBeingBorn--; + const remainingBabies = []; + for (const ovum of babiesBeingBorn) { + if (ovum.reserve === "incubator" && V.tanks.length < V.incubator) { + App.Facilities.Incubator.newChild(generateChild(mom, ovum, true)); + } else if (ovum.reserve === "nursery" && V.cribs.length < V.nursery) { + App.Facilities.Nursery.newChild(generateChild(mom, ovum)); + } else { + remainingBabies.push(ovum); } } - return babiesBeingBorn; + return remainingBabies; }; diff --git a/src/js/economyJS.js b/src/js/economyJS.js index 72f3ca171901942cf1606b14cd7a3895f64e32f5..cadcaf463c68551353c437bc9c2fe3673eb36074 100644 --- a/src/js/economyJS.js +++ b/src/js/economyJS.js @@ -1023,7 +1023,7 @@ globalThis.getSlaveCostArray = function(s) { } break; } - + cost = Math.trunc(cost); retval.push({text: "Living Expenses", value: cost}); cost = 0; @@ -2527,9 +2527,9 @@ globalThis.supplyPoliciesReport = function(NPCclass) { } r += `<i><br> Satisfaction is at ${V.sexDemandResult[varName]/10}%`; if (overSupply > 0) { - r += ` and the arcology provides ${overSupply/10}% more sexual services than required which <span class='red'>drives prices down</span>`; + r += ` and the arcology provides ${overSupply/10}% more sexual services than required which <span class='red'>drives prices down,</span>`; } - r += `, ${V.NPCMarketShare[varName]/10 === V.sexDemandResult[varName]/10 ? `the entire` : `${V.NPCMarketShare[varName]/10}% of the`} market is serviced by other suppliers operating inside your arcology.</i><br>`; + r += ` ${V.NPCMarketShare[varName]/10 === V.sexDemandResult[varName]/10 ? `the entire` : `${V.NPCMarketShare[varName]/10}% of the`} market is serviced by other suppliers operating inside your arcology.</i><br>`; // charge supply barriers (unreported, since it's a flat amount that you were told when you enacted the policy) const supplyCosts = [0, 1000, 5000, 20000, 60000]; diff --git a/src/js/slaveListing.js b/src/js/slaveListing.js index 8b387b2e2c058ba9a35273a8dcafd29c9a2b7a4e..653ccc8655c80dc48d781e041e4b323bcdea4b26 100644 --- a/src/js/slaveListing.js +++ b/src/js/slaveListing.js @@ -522,10 +522,11 @@ App.UI.SlaveList.SlaveInteract = {}; /** * @param {App.Entity.SlaveState} slave + * @param {string} [text] print this text instead of slave name * @returns {DocumentFragment|HTMLElement} */ -App.UI.SlaveList.SlaveInteract.stdInteract = function(slave) { - const link = App.UI.DOM.passageLink(SlaveFullName(slave), "Slave Interact", () => { +App.UI.SlaveList.SlaveInteract.stdInteract = function(slave, text) { + const link = App.UI.DOM.passageLink(text ? text : SlaveFullName(slave), "Slave Interact", () => { App.UI.SlaveList.ScrollPosition.record(); V.AS = slave.ID; }); diff --git a/src/js/slaveSummaryHelpers.js b/src/js/slaveSummaryHelpers.js index 5f1786187abec513f89be88e8f77dab382db702f..e3bdd7e521fdff02fbfdfbeb24b7fad3df28852a 100644 --- a/src/js/slaveSummaryHelpers.js +++ b/src/js/slaveSummaryHelpers.js @@ -219,21 +219,195 @@ App.UI.SlaveSummaryImpl = function() { bigButts: 0, }; + /** + * + * @param {ParentNode} container + * @param {App.Entity.SlaveState} slave + * @param {string} text + * @returns {HTMLSpanElement} + */ + function referenceSlaveWithPreview(container, slave, text) { + const res = App.UI.DOM.appendNewElement("span", container, text, "textWithTooltip"); + const tooltip = App.UI.DOM.appendNewElement("span", res, undefined, "tooltip"); + tooltip.append(App.UI.DOM.generateLinksStrip([ + App.UI.DOM.slaveDescriptionDialog(slave, "Pop-up", {eventDescription: false, noArt: true}), + App.UI.SlaveList.SlaveInteract.stdInteract(slave, "Go to") + ])); + return res; + } + + const longFamilyBits = { + and: " and ", + makeBit: s => s + '.', + daughters10: "Has tons of daughters.", + daughters5: "Has many daughters.", + daughters1: "Has several daughters.", + sisters10: "One of many sisters.", + sisters5: "Has many sisters.", + sisters1: "Has several sisters.", + emotionBind: "Emotionally bonded to you.", + emotionSlut: "Emotional slut." + }; + + const shortFamilyBits = { + and: " & ", + makeBit: s => s, + daughters10: "tons of daughters", + daughters5: "many daughters", + daughters1: "has daughters", + sisters10: "One of many sisters.", + sisters5: "Has many sisters.", + sisters1: "Has several sisters.", + emotionBind: "E Bonded", + emotionSlut: "E Slut" + }; + + /** + * @param {Node} container + * @param {App.Entity.SlaveState} slave + * @param {boolean} short + */ + function renderFamily(container, slave, short) { + let handled = 0; + const bits = short ? shortFamilyBits : longFamilyBits; + const block = makeBlock(); + const cssClassName = "lightgreen"; + if (slave.mother > 0) { + const _ssj = V.slaves.find(s => s.ID === slave.mother); + if (_ssj) { + helpers.referenceSlaveWithPreview(block, _ssj, SlaveFullName(_ssj)); + addText(block, "'s "); + let spanText = getPronouns(slave).daughter; + if (slave.relationshipTarget === _ssj.ID) { + spanText += `${bits.and}${relationshipTerm(slave)}`; + handled = 1; + } + makeSpan(block, bits.makeBit(spanText), cssClassName); + } + } else if (slave.mother === -1) { + addText(block, `Your `); + if (slave.relationship < -1) { + makeSpan(block, bits.makeBit(`${getPronouns(slave).daughter}${bits.and}${PCrelationshipTerm(slave)}`), cssClassName); + handled = 1; + } else { + makeSpan(block, bits.makeBit(getPronouns(slave).daughter), cssClassName); + } + } else if (slave.mother in V.missingTable && V.showMissingSlavesSD && V.showMissingSlaves) { + addText(block, `${V.missingTable[slave.mother].fullName}'s `); + makeSpan(block, bits.makeBit(getPronouns(slave).daughter), cssClassName); + } + if (slave.father > 0 && slave.father !== slave.mother) { + const _ssj = V.slaves.find(s => s.ID === slave.father); + if (_ssj) { + helpers.referenceSlaveWithPreview(block, _ssj, SlaveFullName(_ssj)); + addText(block, "'s "); + let spanText = getPronouns(slave).daughter; + if (slave.relationshipTarget === _ssj.ID) { + spanText += `${bits.and}${relationshipTerm(slave)}`; + handled = 1; + } + makeSpan(block, bits.makeBit(spanText), cssClassName); + } + } else if (slave.father === -1 && slave.father !== slave.mother) { + addText(block, `Your `); + if (slave.relationship < -1) { + makeSpan(block, bits.makeBit(`${getPronouns(slave).daughter}${bits.and}${PCrelationshipTerm(slave)}`), cssClassName); + handled = 1; + } else { + makeSpan(block, bits.makeBit(getPronouns(slave).daughter), cssClassName); + } + } else if (slave.father in V.missingTable && slave.father !== slave.mother && V.showMissingSlavesSD && V.showMissingSlaves) { + addText(block, `${V.missingTable[slave.father].fullName}'s `); + makeSpan(block, bits.makeBit(getPronouns(slave).daughter), cssClassName); + } + if (areSisters(V.PC, slave) > 0) { + addText(block, `Your `); + if (slave.relationship < -1) { + makeSpan(block, bits.makeBit(`${relativeTerm(V.PC, slave)}${bits.and}${PCrelationshipTerm(slave)}`), cssClassName); + handled = 1; + } else { + makeSpan(block, bits.makeBit(relativeTerm(V.PC, slave)), cssClassName); + } + } + if (slave.daughters === 1) { + const _ssj = V.slaves.find(s => s.mother === slave.ID || s.father === slave.ID); + if (_ssj) { + helpers.referenceSlaveWithPreview(block, _ssj, SlaveFullName(_ssj)); + addText(block, "'s "); + let spanText = relativeTerm(_ssj, slave); + if (slave.relationshipTarget === _ssj.ID) { + spanText += `${bits.and}${relationshipTerm(slave)}`; + handled = 1; + } + makeSpan(block, bits.makeBit(spanText), cssClassName); + } + } else if (slave.daughters > 1) { + if (slave.daughters > 10) { + makeSpan(block, bits.daughters10, cssClassName); + } else if (slave.daughters > 5) { + makeSpan(block, bits.daughters5, cssClassName); + } else { + makeSpan(block, bits.daughters1, cssClassName); + } + } + if (slave.sisters === 1) { + const _ssj = V.slaves.find(s => areSisters(s, slave) > 0); + if (_ssj) { + helpers.referenceSlaveWithPreview(block, _ssj, SlaveFullName(_ssj)); + addText(block, "'s "); + let spanText = getPronouns(slave).sister; + if (slave.relationshipTarget === _ssj.ID) { + spanText += `${bits.and}${relationshipTerm(slave)}`; + handled = 1; + } + makeSpan(block, bits.makeBit(spanText), cssClassName); + } + } else if (slave.sisters > 1) { + if (slave.sisters > 10) { + makeSpan(block, bits.sisters10, cssClassName); + } else if (slave.sisters > 5) { + makeSpan(block, bits.sisters5, cssClassName); + } else { + makeSpan(block, bits.sisters1, cssClassName); + } + } + if (slave.relationship > 0 && handled !== 1) { + const _ssj = V.slaves.find(s => s.ID === slave.relationshipTarget); + if (_ssj) { + helpers.referenceSlaveWithPreview(block, _ssj, SlaveFullName(_ssj)); + addText(block, "'s "); + makeSpan(block, bits.makeBit(relationshipTerm(slave)), cssClassName); + } + } else if (slave.relationship === -3 && !areRelated(V.PC, slave)) { + makeSpan(block, bits.makeBit(`Your ${getPronouns(slave).wife}`), cssClassName); + } else if (slave.relationship === -2) { + makeSpan(block, bits.emotionBind, cssClassName); + } else if (slave.relationship === -1) { + makeSpan(block, bits.emotionSlut, cssClassName); + } + + if (block.textContent.length > 0) { + container.appendChild(block); + } + } + return { - addText: addText, - makeSpan: makeSpan, - makeBlock: makeBlock, - makeParagraph: makeParagraph, - getExactRating: getExactRating, - getNumericRating: getNumericRating, - getMultiNumericRating: getMultiNumericRating, - makeStyledSpan: makeStyledSpan, - makeRatedStyledSpan: makeRatedStyledSpan, - makeMappedStyledSpan: makeMappedStyledSpan, - makeMappedSpan: makeMappedSpan, - firstThreeUc: firstThreeUc, - syncFSData: syncFSData, - FSData: FSData, + addText, + makeSpan, + makeBlock, + makeParagraph, + getExactRating, + getNumericRating, + getMultiNumericRating, + makeStyledSpan, + makeRatedStyledSpan, + makeMappedStyledSpan, + makeMappedSpan, + firstThreeUc, + syncFSData, + FSData, + referenceSlaveWithPreview, + renderFamily }; }(); @@ -1325,87 +1499,7 @@ App.UI.SlaveSummaryImpl = function() { * @returns {void} */ function short_family(slave, c) { - let res = ""; - let handled = 0; - if (slave.mother > 0) { - const _ssj = V.slaves.find(s => s.ID === slave.mother); - if (_ssj) { - res += `${SlaveFullName(_ssj)}'s ${getPronouns(slave).daughter}`; - if (slave.relationshipTarget === _ssj.ID) { - res += ` & ${relationshipTermShort(slave)}`; - handled = 1; - } - } - res += " "; - } else if (slave.mother === -1) { - res += `Your ${getPronouns(slave).daughter}`; - if (slave.relationship < -1) { - res += ` & ${PCrelationshipTerm(slave)}`; - handled = 1; - } - res += " "; - } else if (slave.mother in V.missingTable && V.showMissingSlavesSD && V.showMissingSlaves) { - res += `${V.missingTable[slave.mother].fullName}'s ${getPronouns(slave).daughter} `; - } - if (slave.father > 0 && slave.father !== slave.mother) { - const _ssj = V.slaves.find(s => s.ID === slave.father); - if (_ssj) { - res += `${SlaveFullName(_ssj)}'s ${getPronouns(slave).daughter}`; - if (slave.relationshipTarget === _ssj.ID && handled !== 1) { - res += ` & ${relationshipTermShort(slave)}`; - handled = 1; - } - } - res += " "; - } else if (slave.father === -1 && slave.mother !== -1) { - res += `Your ${getPronouns(slave).daughter}`; - if (slave.relationship < -1) { - res += ` & ${PCrelationshipTerm(slave)}`; - handled = 1; - } - res += " "; - } else if (slave.father in V.missingTable && slave.father !== slave.mother && V.showMissingSlavesSD && V.showMissingSlaves) { - res += `${V.missingTable[slave.father].fullName}'s ${getPronouns(slave).daughter}`; - } - if (slave.daughters === 1) { - const _ssj = V.slaves.find(s => s.mother === slave.ID || s.father === slave.ID); - if (_ssj) { - res += `${SlaveFullName(_ssj)}'s ${relativeTerm(_ssj, slave)}`; - if (slave.relationshipTarget === _ssj.ID) { - res += ` & ${relationshipTermShort(slave)}`; - handled = 1; - } - } - res += " "; - } else if (slave.daughters > 1) { - res += `multiple daughters `; - } - if (slave.sisters === 1) { - const _ssj = V.slaves.find(s => areSisters(s, slave) > 0); - if (_ssj) { - res += `${SlaveFullName(_ssj)}'s ${getPronouns(slave).sister}`; - if (slave.relationshipTarget === _ssj.ID) { - res += `& ${relationshipTermShort(slave)}`; - handled = 1; - } - } - res += " "; - } else if (slave.sisters > 1) { - res += `multiple sisters `; - } - if (slave.relationship > 0 && handled !== 1) { - const _ssj = V.slaves.find(s => s.ID === slave.relationshipTarget); - if (_ssj) { - res += `${SlaveFullName(_ssj)}'s ${relationshipTermShort(slave)}`; - } - } else if (slave.relationship === -3 && slave.mother !== -1 && slave.father !== -1) { - res += `Your ${getPronouns(slave).wife}`; - } else if (slave.relationship === -2) { - res += `E Bonded`; - } else if (slave.relationship === -1) { - res += `E Slut`; - } - helpers.makeSpan(c, res); + helpers.renderFamily(c, slave, true); } /** @@ -1430,11 +1524,14 @@ App.UI.SlaveSummaryImpl = function() { const _ssj = V.slaves.find(s => s.ID === slave.rivalryTarget); if (_ssj) { if (slave.rivalry <= 1) { - block.textContent = `Disl ${SlaveFullName(_ssj)}`; + block.textContent = 'Disl '; + helpers.referenceSlaveWithPreview(block, _ssj, SlaveFullName(_ssj)); } else if (slave.rivalry <= 2) { - block.textContent = `${SlaveFullName(_ssj)}'s rival`; + helpers.referenceSlaveWithPreview(block, _ssj, SlaveFullName(_ssj)); + addText(block, "'s rival"); } else { - block.textContent = `Hates ${SlaveFullName(_ssj)}`; + block.textContent = 'Hates '; + helpers.referenceSlaveWithPreview(block, _ssj, SlaveFullName(_ssj)); } } } @@ -1446,120 +1543,7 @@ App.UI.SlaveSummaryImpl = function() { * @returns {void} */ function long_family(slave, c) { - let handled = 0; - const block = makeBlock(); - if (slave.mother > 0) { - const _ssj = V.slaves.find(s => s.ID === slave.mother); - if (_ssj) { - addText(block, `${SlaveFullName(_ssj)}'s `); - let spanText = getPronouns(slave).daughter; - if (slave.relationshipTarget === _ssj.ID) { - spanText += ` and ${relationshipTerm(slave)}`; - handled = 1; - } - makeSpan(block, spanText + '.', "lightgreen"); - } - } else if (slave.mother === -1) { - addText(block, `Your `); - if (slave.relationship < -1) { - makeSpan(block, `${getPronouns(slave).daughter} and ${PCrelationshipTerm(slave)}.`, "lightgreen"); - handled = 1; - } else { - makeSpan(block, `${getPronouns(slave).daughter}.`, "lightgreen"); - } - } else if (slave.mother in V.missingTable && V.showMissingSlavesSD && V.showMissingSlaves) { - addText(block, `${V.missingTable[slave.mother].fullName}'s `); - makeSpan(block, `${getPronouns(slave).daughter}.`, "lightgreen"); - } - if (slave.father > 0 && slave.father !== slave.mother) { - const _ssj = V.slaves.find(s => s.ID === slave.father); - if (_ssj) { - addText(block, `${SlaveFullName(_ssj)}'s `); - let spanText = getPronouns(slave).daughter; - if (slave.relationshipTarget === _ssj.ID) { - spanText += ` and ${relationshipTerm(slave)}`; - handled = 1; - } - makeSpan(block, spanText + '.', "lightgreen"); - } - } else if (slave.father === -1 && slave.father !== slave.mother) { - addText(block, `Your `); - if (slave.relationship < -1) { - makeSpan(block, `${getPronouns(slave).daughter} and ${PCrelationshipTerm(slave)}.`, "lightgreen"); - handled = 1; - } else { - makeSpan(block, `${getPronouns(slave).daughter}.`, "lightgreen"); - } - } else if (slave.father in V.missingTable && slave.father !== slave.mother && V.showMissingSlavesSD && V.showMissingSlaves) { - addText(block, `${V.missingTable[slave.father].fullName}'s `); - makeSpan(block, `${getPronouns(slave).daughter}.`, "lightgreen"); - } - if (areSisters(V.PC, slave) > 0) { - addText(block, `Your `); - if (slave.relationship < -1) { - makeSpan(block, `${relativeTerm(V.PC, slave)} and ${PCrelationshipTerm(slave)}.`, "lightgreen"); - handled = 1; - } else { - makeSpan(block, `${relativeTerm(V.PC, slave)}.`, "lightgreen"); - } - } - if (slave.daughters === 1) { - const _ssj = V.slaves.find(s => s.mother === slave.ID || s.father === slave.ID); - if (_ssj) { - addText(block, `${SlaveFullName(_ssj)}'s `); - let spanText = relativeTerm(_ssj, slave); - if (slave.relationshipTarget === _ssj.ID) { - spanText += ` and ${relationshipTerm(slave)}`; - handled = 1; - } - makeSpan(block, spanText + '.', "lightgreen"); - } - } else if (slave.daughters > 1) { - if (slave.daughters > 10) { - makeSpan(block, "Has tons of daughters.", "lightgreen"); - } else if (slave.daughters > 5) { - makeSpan(block, "Has many daughters.", "lightgreen"); - } else { - makeSpan(block, "Has several daughters.", "lightgreen"); - } - } - if (slave.sisters === 1) { - const _ssj = V.slaves.find(s => areSisters(s, slave) > 0); - if (_ssj) { - addText(block, `${SlaveFullName(_ssj)}'s `); - let spanText = getPronouns(slave).sister; - if (slave.relationshipTarget === _ssj.ID) { - spanText += ` and ${relationshipTerm(slave)}`; - handled = 1; - } - makeSpan(block, spanText + '.', "lightgreen"); - } - } else if (slave.sisters > 1) { - if (slave.sisters > 10) { - makeSpan(block, "One of many sisters.", "lightgreen"); - } else if (slave.sisters > 5) { - makeSpan(block, "Has many sisters.", "lightgreen"); - } else { - makeSpan(block, "Has several sisters.", "lightgreen"); - } - } - if (slave.relationship > 0 && handled !== 1) { - const _ssj = V.slaves.find(s => s.ID === slave.relationshipTarget); - if (_ssj) { - addText(block, `${SlaveFullName(_ssj)}'s `); - makeSpan(block, `${relationshipTerm(slave)}.`, "lightgreen"); - } - } else if (slave.relationship === -3 && !areRelated(V.PC, slave)) { - makeSpan(block, `Your ${getPronouns(slave).wife}.`, "lightgreen"); - } else if (slave.relationship === -2) { - makeSpan(block, "Emotionally bonded to you.", "lightgreen"); - } else if (slave.relationship === -1) { - makeSpan(block, "Emotional slut.", "lightgreen"); - } - - if (block.textContent.length > 0) { - c.appendChild(block); - } + helpers.renderFamily(c, slave, false); } /** @@ -1585,13 +1569,18 @@ App.UI.SlaveSummaryImpl = function() { if (_ssj) { if (slave.rivalry <= 1) { makeSpan(block, "Dislikes", "lightsalmon"); - block.appendChild(document.createTextNode(` ${SlaveFullName(_ssj)}.`)); + addText(block, ' '); + helpers.referenceSlaveWithPreview(block, _ssj, SlaveFullName(_ssj)); + addText(block, '.'); } else if (slave.rivalry <= 2) { - block.appendChild(document.createTextNode(`${SlaveFullName(_ssj)}'s `)); + helpers.referenceSlaveWithPreview(block, _ssj, SlaveFullName(_ssj)); + addText(block, "'s "); makeSpan(block, "rival.", "lightsalmon"); } else { makeSpan(block, "Hates", "lightsalmon"); - block.appendChild(document.createTextNode(` ${SlaveFullName(_ssj)}.`)); + addText(block, ' '); + helpers.referenceSlaveWithPreview(block, _ssj, SlaveFullName(_ssj)); + addText(block, '.'); } } } diff --git a/src/js/utilsDOM.js b/src/js/utilsDOM.js index d40efec19619a9082a8fb8fbce391b6cdc19a281..1d4ab7a692dcbf311591b17218d19df44bb810f5 100644 --- a/src/js/utilsDOM.js +++ b/src/js/utilsDOM.js @@ -7,13 +7,14 @@ * * The result works in the same way as the wiki markup in the SugarCube * @see https://www.motoslave.net/sugarcube/2/docs/#markup-html-attribute + * @template {keyof PassageLinkMap} K * @param {string} linkText link text * @param {string} passage the passage name to link to * @param {passageLinkHandler} [handler] setter text (optional) * @param {string} [tooltip=''] tooltip text (optional) - * @param {string} [elementType='a'] element type (optional) default is 'a'. + * @param {K} [elementType='a'] element type (optional) default is 'a'. * Could be any of 'a', 'audio', img', 'source', 'video' - * @returns {HTMLElement} element text + * @returns {PassageLinkMap[K]} element text * * @example * // equal to [[Go to town|Town]] diff --git a/src/js/utilsSC.js b/src/js/utilsSC.js index b796c63e8d24b639e726aa4d28dee707f6908a72..6f8753fba5dd6d8c8a1a962ff854e2c1ca462bb9 100644 --- a/src/js/utilsSC.js +++ b/src/js/utilsSC.js @@ -243,10 +243,10 @@ App.UI.disabledLink = function(link, reasons) { }; /** handler function for slaveDescriptionDialog. do not call directly. */ -App.UI._showDescriptionDialog = function(slave) { +App.UI._showDescriptionDialog = function(slave, options) { Dialog.setup(SlaveFullName(slave)); const image = V.seeImages ? App.UI.DOM.makeElement("div", App.Art.SlaveArtElement(slave, 2, 0), ["imageRef", "medImg"]) : ''; - Dialog.append(image).append(App.Desc.longSlave(slave, {eventDescription: 1})); + Dialog.append(image).append(App.Desc.longSlave(slave, options)); Dialog.open(); }; @@ -254,20 +254,23 @@ App.UI._showDescriptionDialog = function(slave) { * Generates a link which shows a slave description dialog for a specified slave. * Do not call from within another dialog. * @param {App.Entity.SlaveState} slave + * @param {FC.Desc.LongSlaveOptions} options * @returns {string} link (in SC markup) */ -App.UI.slaveDescriptionDialog = function(slave) { - return App.UI.link(SlaveFullName(slave), App.UI._showDescriptionDialog, [slave]); +App.UI.slaveDescriptionDialog = function(slave, options = {eventDescription: true}) { + return App.UI.link(SlaveFullName(slave), App.UI._showDescriptionDialog, [slave, options]); }; /** * Generates a link which shows a slave description dialog for a specified slave. * Do not call from within another dialog. * @param {App.Entity.SlaveState} slave + * @param {string} [text] link text to use instead of slave name + * @param {FC.Desc.LongSlaveOptions} options * @returns {HTMLElement} link */ -App.UI.DOM.slaveDescriptionDialog = function(slave) { - return App.UI.DOM.link(SlaveFullName(slave), App.UI._showDescriptionDialog, [slave]); +App.UI.DOM.slaveDescriptionDialog = function(slave, text, options = {eventDescription: true}) { + return App.UI.DOM.link(text ? text : SlaveFullName(slave), App.UI._showDescriptionDialog, [slave, options]); }; /** diff --git a/src/js/wombJS.js b/src/js/wombJS.js index bc917e9d1a17bf624e99affcde6ecc3383deb176..e17d8f955c8ccdc082baa9695465eba88fae4dfe 100644 --- a/src/js/wombJS.js +++ b/src/js/wombJS.js @@ -337,6 +337,7 @@ globalThis.WombGetVolume = function(actor) { // most legacy code from pregJS.tw ft.volume = ((4 / 3) * (Math.PI) * (phi / 2) * (Math.pow((targetLen / 2), 3))); wombSize += ft.volume; + // wombSize += ft.genetics.geneticQuirks.polyhydramnios === 2 ? ft.volume * 1.5 : ft.volume; // oldVol = ((4 / 3) * (Math.PI) * (phi / 2) * (Math.pow((oldLen / 2), 3))); // for debug @@ -366,6 +367,7 @@ globalThis.WombGetVolume = function(actor) { // most legacy code from pregJS.tw targetData = getCurData(actor, ft.age); wombSize += targetData.size * targetData.rate; + // wombSize += ft.genetics.geneticQuirks.polyhydramnios === 2 ? targetData.size * targetData.rate * 1.5 : targetData.size * targetData.rate; }); if (wombSize < 0) { // catch for strange cases, to avoid messing with outside code. @@ -384,6 +386,7 @@ globalThis.WombGetVolume = function(actor) { // most legacy code from pregJS.tw targetData = getCurData(actor, ft.age); wombSize += targetData.size; + // wombSize += ft.genetics.geneticQuirks.polyhydramnios === 2 ? targetData.size * 1.5 : targetData.size; }); if (wombSize < 0) { // catch for strange cases, to avoid messing with outside code. diff --git a/src/npc/acquisition.tw b/src/npc/acquisition.tw index 8d359c204713713572cd7e3684b295e11e85d267..e996bd7a0b52ebd0f41d4d27cb1e8c260df626e7 100644 --- a/src/npc/acquisition.tw +++ b/src/npc/acquisition.tw @@ -845,6 +845,7 @@ The previous owner seems to have left in something of a hurry. <<set $averageDevotion = 0>> <<set _slavesContributing = 0>> <<for $i = 0; $i < $slaves.length; $i++>> + <<run updateHealth($slaves[$i])>> <<set $slaves[$i].oldDevotion = $slaves[$i].devotion>> <<set $slaves[$i].oldTrust = $slaves[$i].trust>> /* AVERAGE VALUES UPDATE */ diff --git a/src/npc/descriptions/butt/anus.js b/src/npc/descriptions/butt/anus.js index bb5c95a8782d2d796e626d40bd1df13f05626c13..09988a307e14e1651d6279ddb9625207c5b6119a 100644 --- a/src/npc/descriptions/butt/anus.js +++ b/src/npc/descriptions/butt/anus.js @@ -33,7 +33,7 @@ App.Desc.anus = function(slave, {market, eventDescription} = {}) { r.push(`base of ${his} cock.`); } } else if (slave.analArea - slave.anus > 2) { - r.push(`but it's surrounded by an oval of ${analSkinDesc} ${skinDesc} skin that occupies ${his} entire ${either("asscrack", "buttcrack")} ass.`); + r.push(`but it's surrounded by an oval of ${analSkinDesc} ${skinDesc} skin that occupies ${his} entire ${either("asscrack", "buttcrack")}.`); } else if (slave.analArea - slave.anus > 1) { r.push(`but it's surrounded by a big ring of ${analSkinDesc} ${skinDesc} skin.`); } else if (slave.analArea - slave.anus > 0) { diff --git a/src/npc/descriptions/descriptionWidgets.js b/src/npc/descriptions/descriptionWidgets.js index e6a5335b973d3b90824e01d5898906104d2675c3..482b300508135547f3bfa7ccd95c36c2ff064308 100644 --- a/src/npc/descriptions/descriptionWidgets.js +++ b/src/npc/descriptions/descriptionWidgets.js @@ -419,37 +419,37 @@ App.Desc.ageAndHealth = function(slave) { } else if (H.shortDamage >= 40) { array.push(`is <span class="red">seriously injured</span> with some lasting effects`); } else if (H.shortDamage >= 20) { - array.push(`is <span class="orange">injured</span>`); + array.push(`is <span class="orange">injured`); } else if (H.shortDamage > 5) { array.push(`seems to have suffered a <span class="yellow">minor injury</span> recently`); } if (H.longDamage >= 70) { - array.push(`is suffering heavily under accumulated <span class="red">permanent health problems</span>`); + array.push(`is suffering heavily under accumulated <span class="red">permanent health problems`); } else if (H.longDamage >= 40) { - array.push(`has some clear <span class="red">permanent health issues</span>`); + array.push(`has some clear <span class="red">permanent health issues`); } else if (H.longDamage >= 20) { - array.push(`shows signs of <span class="orange">lasting health problems</span>`); + array.push(`shows signs of <span class="orange">lasting health problems`); } else if (H.longDamage > 5) { - array.push(`carries some <span class="yellow">minor niggles</span>`); + array.push(`carries some <span class="yellow">minor niggles`); } if (H.condition < -80 && H.shortDamage !== 0 && H.longDamage !== 0) { - array.push(`has been treated so badly ${he} <span class="red">is close to the brink</span>`); + array.push(`has been treated so badly ${he} <span class="red">is close to the brink`); } else if (H.condition < -50) { - array.push(`appears to be in <span class="red">terrible condition</span>`); + array.push(`appears to be in <span class="red">terrible condition`); } else if (H.condition < -20) { - array.push(`appears to be in <span class="orange">poor condition</span>`); + array.push(`appears to be in <span class="orange">poor condition`); } else if (H.condition < 0) { - array.push('could be in <span class="yellow">better condition</span>'); + array.push('could be in <span class="yellow">better condition'); } if (array.length === 3) { - r += (` ${array[0]}, ${array[1]} and ${array[2]}.`); + r += (` ${array[0]}, ${array[1]} and ${array[2]}.</span>`); } else if (array.length === 2) { - r += (` ${array[0]} and ${array[1]}.`); + r += (` ${array[0]} and ${array[1]}.</span>`); } else if (array.length === 1) { - r += (` ${array[0]}.`); + r += (` ${array[0]}.</span>`); } } diff --git a/src/npc/descriptions/longSlave.js b/src/npc/descriptions/longSlave.js index e346ec3936a8e68fec553d6eeb09f76ea0007496..7d75b6a30e2ee9b5e1d17693bbf097e6c1dff7b0 100644 --- a/src/npc/descriptions/longSlave.js +++ b/src/npc/descriptions/longSlave.js @@ -1,13 +1,9 @@ /** * @param {App.Entity.SlaveState} slave - * @param {object} params - * @param {string|number} [params.market] 0 if the slave is not for sale. Otherwise a string with the name of the market, - * partially to determine if laws apply to the market or not. - * @param {number} [params.eventDescription] - * @param {string} [params.prisonCrime] + * @param {FC.Desc.LongSlaveOptions} params * @returns {DocumentFragment} */ -App.Desc.longSlave = function(slave = V.activeSlave, {market = 0, eventDescription = 0, prisonCrime} = {}) { +App.Desc.longSlave = function(slave = V.activeSlave, {market = 0, eventDescription = false, prisonCrime, noArt} = {}) { const { He, His, him, he, his } = getPronouns(slave); @@ -19,7 +15,7 @@ App.Desc.longSlave = function(slave = V.activeSlave, {market = 0, eventDescripti const applyLaw = applyLawCheck(market); SlaveStatClamp(slave); - if (V.seeImages === 1 && !eventDescription && passage() !== "Slave Interact") { + if (V.seeImages === 1 && !eventDescription && !noArt) { // Art span = document.createElement('span'); span.id = "art-frame"; @@ -329,7 +325,7 @@ App.Desc.longSlave = function(slave = V.activeSlave, {market = 0, eventDescripti // Fresult App.UI.DOM.appendNewElement("span", p, `sexual score `, ["lightcoral", "bold"]); App.UI.DOM.appendNewElement("span", p, `of `, ["lightcoral"]); - p.append(FResultTooltip(slave), `.`); + p.append(FResultTooltip(slave), App.UI.DOM.makeElement("span", `.`, ["lightcoral"])); } el.appendChild(p); diff --git a/src/npc/descriptions/sceneIntro.js b/src/npc/descriptions/sceneIntro.js index 136a415110203e6630ce96a8d0a5da321dac3100..869674d018a2313ef4d0e7af9bfa07d44f336a57 100644 --- a/src/npc/descriptions/sceneIntro.js +++ b/src/npc/descriptions/sceneIntro.js @@ -11,7 +11,7 @@ App.Desc.sceneIntro = function(slave, {market, eventDescription} = {}) { he, him, his, He, His, himself, wife } = getPronouns(slave); - if (eventDescription === 1) { + if (eventDescription) { r.push(`${He} is currently involved in an event, but is assigned to ${slave.assignment}.`); if (slave.assignment === "be a subordinate slave") { let lsd = getSlave(slave.subTarget); diff --git a/src/npc/generate/newSlaveIntro.js b/src/npc/generate/newSlaveIntro.js index e9aeda4a6c4a819461958bb403cd83d786a56fab..808644bb8b88ac99b18ca30789955fdfabad21e8 100644 --- a/src/npc/generate/newSlaveIntro.js +++ b/src/npc/generate/newSlaveIntro.js @@ -2913,8 +2913,8 @@ App.UI.newSlaveIntro = function(slave, slave2 = V.eventSlave) { } else { r.push(`${He} worked ${his} tongue hard and did ${his} best`); } - r.push(`You spend the rest of the day with ${him}`); r.push(r.pop() + "."); + r.push(`You spend the rest of the day with ${him}`); if (hasAnyLegs(slave)) { r.push(`kneeling`); } else { diff --git a/src/npc/interaction/fLickPussy.tw b/src/npc/interaction/fLickPussy.tw index 53a00363cd4db0e4092498361fa5312c588c5faa..95f8a73fec28a5aefa444da135664723e94da0da 100644 --- a/src/npc/interaction/fLickPussy.tw +++ b/src/npc/interaction/fLickPussy.tw @@ -20,7 +20,7 @@ You have <<= getSlave($AS).slaveName>> brought into your office and placed on your couch. <</if>> -After $he is situated, you go over to $him<<if getSlave($AS).clothes != "no clothing">> and take off $his clothing, causing $him to <<if _devotion > 50>>give you a soft smile<<else>>give you an angry glare<</if>><</if>>. You suddenly grab $his hips and pull $his crotch to your face, causing $him to <<if canTalk(getSlave($AS))>>give a shriek of surprise<<else>>shudder in surprise<</if>>. Looking at $him directly in the eyes, you begin to run your tongue along $his labia, drawing a <<if canTalk(getSlave($AS))>>soft<<else>>silent<</if>> moan from $him. The combination of the pleasure and the intense look from the _womanP $he<<if _devotion > 95>> loves <<elseif _devotion > 50>>'s accepted as $his <<= getWrittenTitle(getSlave($AS))>><<else>> hates/*not sure what to use for "reluctant"*/<</if>> makes $him blush, but you don't let up. +After $he is situated, you go over to $him<<if getSlave($AS).clothes != "no clothing">> and take off $his clothing, causing $him to <<if _devotion > 50>>give you a soft smile<<else>>give you an angry glare<</if>><</if>>. You suddenly grab $his hips and pull $his crotch to your face, causing $him to <<if canTalk(getSlave($AS))>>give a shriek of surprise<<else>>shudder in surprise<</if>>. Looking at $him directly in the eyes, you begin to run your tongue along $his labia, drawing a <<if canTalk(getSlave($AS))>>soft<<else>>silent<</if>> moan from $him. The combination of the pleasure and the intense look from <<if areRelated(getSlave($AS), $PC)>>$his <<=relativeTerm(getSlave($AS), $PC)>><<else>>the _womanP $he<<if _devotion > 95>> loves <<elseif _devotion > 50>>'s accepted as $his <<= getWrittenTitle(getSlave($AS))>><<else>> hates/*not sure what to use for "reluctant"*/<</if>><</if>> makes $him blush, but you don't let up. <<if getSlave($AS).dick == 0>> You give $his clit a few experimental tweaks, causing $his <<if canTalk(getSlave($AS))>>moans<<else>>squirming<</if>> to intensify<<if hasBothLegs(getSlave($AS))>> and $his legs to tighten around your head<</if>>. <</if>> diff --git a/src/npc/interaction/fSlaveFeed.tw b/src/npc/interaction/fSlaveFeed.tw index adbb312613d5d2ac506089f35edf094cb3a66f04..296eaebd404d9418e7c7cf036699fc73240d8908 100644 --- a/src/npc/interaction/fSlaveFeed.tw +++ b/src/npc/interaction/fSlaveFeed.tw @@ -764,17 +764,17 @@ Next, you see to <<= getSlave($AS).slaveName>>. <<elseif (getSlave($AS).devotion <= 50) || ($milkTap.devotion <= 50)>> <<if canDoVaginal(getSlave($AS))>> - You order <<= getSlave($AS).slaveName>> to lift $his ass so you can penetrate $his <<if getSlave($AS).vagina == 0>>virgin <</if>>pussy <<if $PC.dick == 0>>with a strap-on <</if>> while $he sucks $milkTap.slaveName's cock. $He submissively obeys. With every thrust into the moaning slave, you push milkTap.slaveName's dick deeper down $his throat. + You order <<= getSlave($AS).slaveName>> to lift $his ass so you can penetrate $his <<if getSlave($AS).vagina == 0>>virgin <</if>>pussy <<if $PC.dick == 0>>with a strap-on <</if>> while $he sucks $milkTap.slaveName's cock. $He submissively obeys. With every thrust into the moaning slave, you push $milkTap.slaveName's dick deeper down $his throat. <<set getSlave($AS).counter.vaginal++, $vaginalTotal++>> <<elseif canDoAnal(getSlave($AS))>> - You order <<= getSlave($AS).slaveName>> to lift $his ass so you can penetrate $his <<if getSlave($AS).anus == 0>>virgin <</if>>ass <<if $PC.dick == 0>>with a strap-on <</if>> while $he sucks $milkTap.slaveName's cock. $He submissively obeys. With every thrust into the moaning slave, you push milkTap.slaveName's dick deeper down $his throat. + You order <<= getSlave($AS).slaveName>> to lift $his ass so you can penetrate $his <<if getSlave($AS).anus == 0>>virgin <</if>>ass <<if $PC.dick == 0>>with a strap-on <</if>> while $he sucks $milkTap.slaveName's cock. $He submissively obeys. With every thrust into the moaning slave, you push $milkTap.slaveName's dick deeper down $his throat. <<set getSlave($AS).counter.anal++, $analTotal++>> <<elseif $PC.dick != 0 && getSlave($AS).butt > 4>> - You order <<= getSlave($AS).slaveName>> to lift $his ass so you can rub your dick between $his huge butt cheeks while $he sucks $milkTap.slaveName's cock. $He submissively obeys. With every thrust against the moaning slave, you push milkTap.slaveName's dick deeper down $his throat. + You order <<= getSlave($AS).slaveName>> to lift $his ass so you can rub your dick between $his huge butt cheeks while $he sucks $milkTap.slaveName's cock. $He submissively obeys. With every thrust against the moaning slave, you push $milkTap.slaveName's dick deeper down $his throat. <<elseif $PC.dick != 0 && hasBothLegs(getSlave($AS))>> - You order <<= getSlave($AS).slaveName>> to lift $his ass so you can fuck $his <<if getSlave($AS).weight > 95>>soft <</if>>thighs while $he sucks $milkTap.slaveName's cock. $He submissively obeys. With every thrust against the moaning slave, you push milkTap.slaveName's dick deeper down $his throat. + You order <<= getSlave($AS).slaveName>> to lift $his ass so you can fuck $his <<if getSlave($AS).weight > 95>>soft <</if>>thighs while $he sucks $milkTap.slaveName's cock. $He submissively obeys. With every thrust against the moaning slave, you push $milkTap.slaveName's dick deeper down $his throat. <<else>> - You order <<= getSlave($AS).slaveName>> to position $himself so you can rub your <<if $PC.dick == 0>>clit<<else>>dick<</if>> against $him while $he sucks $milkTap.slaveName's cock, since $he lacks any better way to please you. $He submissively obeys. With every thrust against the moaning slave, you push milkTap.slaveName's dick deeper down $his throat. + You order <<= getSlave($AS).slaveName>> to position $himself so you can rub your <<if $PC.dick == 0>>clit<<else>>dick<</if>> against $him while $he sucks $milkTap.slaveName's cock, since $he lacks any better way to please you. $He submissively obeys. With every thrust against the moaning slave, you push $milkTap.slaveName's dick deeper down $his throat. <</if>> You wrap an arm around <<= getSlave($AS).slaveName>>'s middle so you may feel $his stomach swell with ejaculate and place your other hand to $milkTap.slaveName's balls, knowing just how much _he2 gets backed up. <<if getSlave($AS).inflation == 3>>You cum multiple times as you feel $his belly slowly round with cum, transform into a jiggling mass, and finally grow taut under your molesting fingers<<elseif getSlave($AS).inflation == 2>>You cum several times as you feel $his belly slowly round with cum, finally transforming into a jiggling mass, under your molesting fingers<<else>>You cum as you feel $his belly slowly round with cum under your molesting fingers<</if>>. When you release $him from under your weight, $he drops to the ground panting. Both slaves enjoyed their union, though $milkTap.slaveName even more so after that many orgasms. <<if canDoVaginal(getSlave($AS)) && (getSlave($AS).vagina == 0)>> diff --git a/src/pregmod/FCTV/FCTVshows.js b/src/pregmod/FCTV/FCTVshows.js index 20c9d40a8efa013b6bd294ed408bc92ff6ca7211..c7f0116fd1bb45323ef203518dceb71ee60e5116 100644 --- a/src/pregmod/FCTV/FCTVshows.js +++ b/src/pregmod/FCTV/FCTVshows.js @@ -1658,8 +1658,8 @@ App.Data.FCTV.channels = { r.push(`<p>For a moment, the only sounds in the room were the soft 'whir' of a milker and the muffled hum of Sadie's vibrator. Annie's breath hitched from Sadie's ministrations and responded, "That's good sweetie, bring it here." The door to the bathroom swung open and Sarah walked into the room. She had lost her thong and was wearing a backpack printed with cartoon farm animals. Flexible tubing snaked out of the pack and attached two cups on her breasts. In her hands was a bottle of edible lube and a bright pink rounded cylinder with the words 'Her First Vibrator' printed in a saccharine font on the base.</p>`); r.push(`<p>Sarah looked at both her parents, then tilted her head and frowned. "You and daddy were playing that weird game again, weren't you?" Scott and Annie looked at each other; silently communicating in a way only parents can. Annie looked at her daughter and said, "When you're a bit older you're going to want to play those games too." Sarah looked unconvinced. "Anyway, you got the lube, are both your milker and vibrator charged?" Annie asked. Sarah bobbed her head. "Then why don't you lube up daddy?" Sarah bobbed her head again and knelt at the side of the bed.</p>`); r.push(`<p>Scott quickly undressed and sat at the edge of the bed. Sarah knelt between her father's legs. She began softly licking her father's cock, her tongue sliding along its length and gently swirling around its head, her mouth making lewd noises. She ran her tongue on the underside of her dad's cock, took him into her mouth and began to give him a slow blowjob.</p>`); - r.push(`<p>Scott felt himself slowly harden to full mast. He resisted the urge to pull her down till her nose touched his crotch and said, "That's good sweetheart, now use the lube." Sarah pulled herself off his cock with a lewd pop and picked up the bottle of lube. She squirted a generous amount of it into one hand, rubbed both hands together, and began to stroke his cock. "You're doing a good job sweetie, did you help mommy too?" he asked. Annie nodded "She did a very good job and was very through." Sarah preened at her parents praise and said, "It wasn't easy. I had to use a whole bottle to do mommy." Scott turned his head to his wife and raised an eyebrow. Annie gave him a lewd grin and her blush slowly spread down her chest, but said nothing.</p>`); - r.push(`<p>Scott patted his daughter's head. "Okay sweetie, take a seat." Sarah gave her dad's cock a kiss on the head, grabbed her vibrator and sat down on the couch across from the bed. She rubbed the lube on her hands over her crotch and her vibrator before licking off what remained. Scott began to stand, but paused; an impish smile spread across his face. "Before we begin, I have question for mommy." He reached into a night table and pulled out an odd remote and a Wartenberg pinwheel.</p>`); + r.push(`<p>Scott felt himself slowly harden to full mast. He resisted the urge to pull her down till her nose touched his crotch and said, "That's good sweetheart, now use the lube." Sarah pulled herself off his cock with a lewd pop and picked up the bottle of lube. She squirted a generous amount of it into one hand, rubbed both hands together, and began to stroke his cock. "You're doing a good job sweetie, did you help mommy too?" he asked. Annie nodded "She did a very good job and was very thorough." Sarah preened at her parents praise and said, "It wasn't easy. I had to use a whole bottle to do mommy." Scott turned his head to his wife and raised an eyebrow. Annie gave him a lewd grin and her blush slowly spread down her chest, but said nothing.</p>`); + r.push(`<p>Scott patted his daughter's head. "Okay sweetie, take a seat." Sarah gave her dad's cock a kiss on the head, grabbed her vibrator and sat down on the couch across from the bed. She rubbed the lube on her hands over her crotch and her vibrator before licking off what remained. Scott began to stand, but paused; an impish smile spread across his face. "Before we begin, I have a question for mommy." He reached into a night table and pulled out an odd remote and a Wartenberg pinwheel.</p>`); r.push(`<p>"Oh, and what would that be?" Annie said in a knowing tone, her eyes twinkling. Scott just grinned and pressed a button on the remote. Annie squealed as her exosuit shifted her forward onto her breasts. Scott craned his head to look behind wife. "You alright down there, Sadie?" He cocked his head a bit more and barely made out a thumbs up beyond the horizon of his wife's ass. "Good. Now-" He rolled the pinwheel across her arm to collar bone and Annie gasped. "Why did you ask Sadie to stay behind when I sent her off for clothes?"</p>`); r.push(`<p>Annie inhaled sharply and said, "I needed to cum." He ran the pinwheel slowly down her collarbone to her breast. "And what had you so worked up you needed Sadie?" Her breathing began to speed up. "I nearly threw my back out getting into my exo." He raised an eyebrow and ran the pinwheel in winding loops across her breasts, goose bumps forming in its wake. "Oh? And why would that get you so hot and bothered?" he asked in a knowing tone.</p>`); r.push(`<p>Annie's breath became more ragged and began to babble. "I'm-I'm so big, so big. I'm a breast obsessed cowslut." She held the smart material of her exo in a white knuckle grip. "I came when I couldn't see my feet anymore. I masturbated seven times when I first got stuck in a door. I once wrapped my tits around a guard rail and humped it for three hours. I came buckets to the look on Cathy's face when she met me." Annie gave him a look of pure want. "I need to cum. Mommy needs her boobs pounded." She pleaded. Scott smiled and pressed a button on the remote that caused the smart material to press Annie's breasts into a fuckable channel. He positioned himself and said, "Honesty is to be rewarded", then thrust himself into her.</p>`); @@ -1710,7 +1710,7 @@ App.Data.FCTV.channels = { r.push(`<p>Martha led them to table that, despite being designed with more generous figures in mind, groaned when Annie sat down. The waitress passed out menus as the family busied themselves with drying off. After passing out the menus, Martha gave a quick, "Be back in a sec." and walked away. As the family finished up drying off, Martha returned with a tray of empty glasses. She set out the glasses on the table, unholstered the soda gun at her hip, and began to fill them up.</p>`); r.push(`<p>Cathy just stared at the glass of milk in front of her. "It's pink." Annie handed her daughter a glass before taking a sip from her own. "And quite delicious, you should give it a try, Kitten." Sarah licked off her milk mustache and nodded, "Uh-huh, you should give it a try before you say you don't like it." Cathy took a tentative sip and then looked at her glass with new eyes. "It's strawberry flavored, how does that work?"</p>`); r.push(`<p>Scott patted Martha's breasts. "A bit of minor surgery and a regimen of various supplements. If you go upstairs you can buy drugs that do the much the same thing, if less effectively." Scott took drink from his glass before continuing. "A side benefit of research performed on behalf of the vampires of Sanguine." Cathy looked skeptical. "Vampires?" she asked. Scott waved his hand. "I'll tell you about them another time."</p>`); - r.push(`<p>Martha pulled a small notepad out her cleavage "Do you folks know what you want or do you need some time?" Scott thought for a second before responding. "Why don't you give us a moment, It's Cathy's first time here." She beamed at Cathy. "Oh, glad to have you here! I hope you enjoy yourself darlin'" She took a slender remote out of her cleavage and handed it to Cathy. "Give me a buzz when you've made up your mind." With a small wave, Martha turned sashayed away.</p>`); + r.push(`<p>Martha pulled a small notepad out of her cleavage. "Do you folks know what you want or do you need some time?" Scott thought for a second before responding. "Why don't you give us a moment, It's Cathy's first time here." She beamed at Cathy. "Oh, glad to have you here! I hope you enjoy yourself darlin'" She took a slender remote out of her cleavage and handed it to Cathy. "Give me a buzz when you've made up your mind." With a small wave, Martha turned sashayed away.</p>`); r.push(`<p>Cathy turned her attention to the menu in front of her. At a distance it didn't appear to be any different from a normal paper menu, but on closer inspection one could see it was a flexible touch screen. Scrolling down each page revealed a variety of intriguing dishes as cartoon cowslaves danced in the margins. Tapping on a dish opened a window that showed a video of the item, beside the window was a tab that enticed customers to see the cows in action. A significant part of the dessert page was dedicated extolling the virtues of growth drug laced ice cream produced by Blue Barn's partnership with Bloom Pharma. Below this were animations of cows eating ice cream and suddenly growing assets of immense size.</p>`); r.push(`<p>"Hmm, anyone know what they want?" Scott asked. June looked up from the menu. "I think I'll get my usual." Sadie yawned and said, "Same." Sarah held up her menu, jabbing finger at a picture of a black forest cake and said, "I want this." While the cake quite impressive, to the right of it was something far more attention grabbing.</p>`); r.push(`<p>A window had opened and was playing a video of the cows that helped produce the cake. A heavily pregnant cowslave was railing a far younger, but equally as pregnant cow with a strap-on. The younger cow's eyes were glassy and unfocused. The older slave let out a growl of need and began to pick up speed, their considerable breasts jiggling with each thrust. The menu was polite enough to have a blurb informing them that the cows are actresses on The Young and the Fecund. If one was feeling uncharitable, they could say that the sole video tag of "lactating lolis" was technically correct, but a woefully inadequate description.</p>`); @@ -1948,7 +1948,7 @@ App.Data.FCTV.channels = { r.push(`<p>Jessica notices her father's silent enthusiasm growing in his pants, and steps towards him. "I guess you want that too." That's the last sentence she utters before undoing her father's pants and filling her mouth with his hard cock. She moans into him as she starts sucking, causing his eyes to roll back and for him to grab the top of her head. When she finally manages to swallow him whole, he can't help but audibly moan.</p>`); r.push(`<p>"I love you, sweetie." He says, each word carrying more eroticism than the last.</p>`); r.push(`<p>"Iluvutu." She tries to reply through his member. The vibrating sensation it causes is too much, and soon cum is leaking from the corners of Jessica's mouth and one of her nostrils. Jason pops free of her, walking away into the kitchen. Jessica swallows her mouthful and asks where he's going.</p>`); - r.push(`<p>"Just getting something, so we don't have to wait to make our new family." Filled with joy, Jessica screams loud enough to put most untrained slaves to shame, and reaches up her school skirt to pull off her panties as quickly as possible. As she does, Jason digs through a cabinet until he finds a packet of stamina pills(the brand of which is conveniently facing the camera) and pops one. He picks up his daughter in a bridal carry and takes her towards the master bedroom. "If you're going to be the Mommy from now on", he coos, "then that's where you'll be sleeping." The camera follows their walk at a low angle, revealing that his daughter is so thoroughly aroused her pussy is dripping on the carpet and leaving a trail of wet dots.</p>`); + r.push(`<p>"Just getting something, so we don't have to wait to make our new family." Filled with joy, Jessica screams loud enough to put most untrained slaves to shame, and reaches up her school skirt to pull off her panties as quickly as possible. As she does, Jason digs through a cabinet until he finds a packet of stamina pills (the brand of which is conveniently facing the camera) and pops one. He picks up his daughter in a bridal carry and takes her towards the master bedroom. "If you're going to be the Mommy from now on", he coos, "then that's where you'll be sleeping." The camera follows their walk at a low angle, revealing that his daughter is so thoroughly aroused her pussy is dripping on the carpet and leaving a trail of wet dots.</p>`); r.push(`<p>He puts her down on the bed, and she moves to her hands and knees, explaining that this is how the slaves did it for the class presentation. Her father cups her thighs, slowly tracing up. He stops at her ass for a quick squeeze, producing a squeak from his daughter, and continues drifting across her body until his hands are around her waist. Hands free, he rubs his cock between her asscheeks. "Are you ready?" he asks her.</p>`); r.push(`<p>"Yes Daddy." even though she's almost whispering, her voice is filled with confidence.</p>`); r.push(`<p>Jason takes one hand off her hips and positions himself at the entrance to her pussy, sliding in the head with ease before immediately hitting a block. He leans forward until he can whisper in her ear "Deep breath, sweetie." then pushes a little harder against the resistance. "Ah..." Jessica moans, a mixture of pain and unprecedented pleasure. Finally breaking her hymen, his penis suddenly slides more than halfway into her. "AH!" He pushes the rest in before slowly sliding out, savoring every`); diff --git a/src/pregmod/FCTV/seFCTVremote.tw b/src/pregmod/FCTV/seFCTVremote.tw index c4d15cb5c6df828603b4e019972dd326d63523ad..219ba46e1e7b9caa62718486038b5130014c7817 100644 --- a/src/pregmod/FCTV/seFCTVremote.tw +++ b/src/pregmod/FCTV/seFCTVremote.tw @@ -235,14 +235,13 @@ <p id="result"> <<set _ContractCost = 1000>> <<if $cash >= _ContractCost>> - <<set $activeSlave = _slave>> <div> <<link "Enslave $him">> <<run cashX(forceNeg(_ContractCost), "slaveTransfer", _slave)>> <<replace "#result">> <<set $analTotal++>> _slave.slaveName knows $he has nowhere to turn. Sobbing, $he complies with the process. - <<includeDOM App.UI.newSlaveIntro($activeSlave)>> + <<includeDOM App.UI.newSlaveIntro(_slave)>> <</replace>> <</link>> </div> @@ -296,7 +295,7 @@ <</if>> <<run repX(500, "event", _slave)>> <<set $arcologies[0].prosperity += 2>> - <<includeDOM App.UI.newSlaveIntro($activeSlave)>> + <<includeDOM App.UI.newSlaveIntro(_slave)>> <</replace>> <</link>> </div> diff --git a/src/pregmod/theBlackMarket.tw b/src/pregmod/theBlackMarket.tw index 8006bb412fb0afd7f09c05ebcbe7953c6f348378..9ea2771d5d384abacb409334012b8d5bb9237ff3 100644 --- a/src/pregmod/theBlackMarket.tw +++ b/src/pregmod/theBlackMarket.tw @@ -239,7 +239,7 @@ He gestures to a door in the back of the stall. "The good shit's back there<<if <</if>> <br>"This is an interesting one... It's designed to prevent any sort of rupturing of the uterus, but, while that idea is great and all, it does jack shit to prevent leaks from elsewhere in the organ. The guy funding the research company was pissed when his slave bloated up like a cum-filled balloon and dropped dead, destroyed most of the development lab. Fortunately, he failed to ruin the best part of it — these blueprints. Now, you're probably wondering what good is something like this, but I've done business with a number of industrial slave farms, and they swear upon its ability to force a girl to carry far more children than physically possible; well, up until their wombs crushed their organs, that is. I supposed it'd work with anything solid, really, if you enjoy sticking things up into slave girls." <<else>> - The autosurgery lacks the finesse needed to implant something of this complexity, so designs for a supportive uterine mesh are unusable until it is upgraded. + //The autosurgery lacks the finesse needed to implant something of this complexity, so designs for a supportive uterine mesh are unusable until it is upgraded.// <</if>> <<else>> You lack the facilities needed to produce implants of this complexity, so designs for a supportive uterine mesh are currently unobtainable. diff --git a/src/uncategorized/PESS.tw b/src/uncategorized/PESS.tw index 581f494082ae712149364baf7b93496bfcc65a76..d4c61a5b43368113f1ae198400d4d5398c060b60 100644 --- a/src/uncategorized/PESS.tw +++ b/src/uncategorized/PESS.tw @@ -367,7 +367,7 @@ $He sees you examining at $him, and looks back at you submissively, too tired to <br> <<link "It can wait until after some lovemaking with the Concubine">> <<replace "#result">> - When you enter your suite, the dim light reveals $activeSlave.slaveName waiting with $his beautiful body laid across the bed. When $he <<if canSee($activeSlave)>>sees<<else>>figures out<</if>> the kind of lovemaking you're in the mood for, $he <<if hasAnyArms($activeSlave)>>spreads $his arm<<if hasBothArms($activeSlave)>>s<</if>><<else>>presents $himself<</if>> for you, smiling gently. $He kisses you lovingly, <<if !canTalk($activeSlave) && hasAnyArms($activeSlave)>>taking your hand in $hers and drawing a heart on your palm with one finger.<<elseif canTalk($activeSlave)>><<say>>ing, "<<Master>>, I love you."<<else>>giving you a sultry look<</if>> + When you enter your suite, the dim light reveals $activeSlave.slaveName waiting with $his beautiful body laid across the bed. When $he <<if canSee($activeSlave)>>sees<<else>>figures out<</if>> the kind of lovemaking you're in the mood for, $he <<if hasAnyArms($activeSlave)>>spreads $his arm<<if hasBothArms($activeSlave)>>s<</if>><<else>>presents $himself<</if>> for you, smiling gently. $He kisses you lovingly, <<if !canTalk($activeSlave) && hasAnyArms($activeSlave)>>taking your hand in $hers and drawing a heart on your palm with one finger.<<elseif canTalk($activeSlave)>><<say>>ing, "<<= capFirstChar($enunciate.title)>>, I love you."<<else>>giving you a sultry look<</if>> <<if ($PC.vagina != -1)>> $He lies on $his side <<if hasBothLegs($activeSlave)>>and raises one leg for you so you can straddle the other<<elseif !hasAnyLegs($activeSlave)>>wiggles $his hips<<else>>motions for you to straddle $his leg<</if>>, sliding up to press your pussy against $his submissive groin. You grind against $him; the stimulation is so strong that $he writhes into the sheets, panting and whining. <<if $PC.dick != 0>> diff --git a/src/uncategorized/RESS.tw b/src/uncategorized/RESS.tw index 9c3bc931d370c9007675670e848b3ca7f01bc40b..0cf72b8a1e0945bf9f2af6b42aed5e62a1d97a97 100644 --- a/src/uncategorized/RESS.tw +++ b/src/uncategorized/RESS.tw @@ -1521,7 +1521,7 @@ into your bedroom and stands before you submissively. Since $he's allowed to ask <<else>> $he says meekly, <</if>> - "<<Master>>, would you plea<<s>>e fuck me?" + "<<=capFirstChar($enunciate.title)>>, would you plea<<s>>e fuck me?" <</if>> @@ -5103,7 +5103,7 @@ brought in to you. This time <<= App.UI.slaveDescriptionDialog($activeSlave)>> h $He cocks $his hips and so that your cock is pressing against $his soaked cunt. In response to $his wordless question, you nibble $his ear and tell $him that it's $his choice. $He turns $his upper torso to <<if canSee($activeSlave)>>stare at you in surprise<<else>>so that you may see $his surprise<</if>> for a moment, and then smiles and gives you a peck on the cheek. <<if ($activeSlave.fetish == "pregnancy") && ($activeSlave.fetishKnown == 1) && isFertile($activeSlave)>> $He pushes against you until you are fully inserted into $his pussy. $He's ripe for impregnation and needs your baby in $him. You make love - <<elseif ($activeSlave.anus > 2)>> + <<elseif ($activeSlave.vagina > 2)>> $He easily slides your cock into $his loose pussy. You make love <<else>> $He hikes $himself up a bit, and then gently slides your cock into $his tight pussy. You make love diff --git a/src/uncategorized/RETS.tw b/src/uncategorized/RETS.tw index 36725399f7a733de434ca8467e24bed1f30e12dd..7ae79f08ef5722cbcad3dca74aa76b5cc3e8c684 100644 --- a/src/uncategorized/RETS.tw +++ b/src/uncategorized/RETS.tw @@ -824,7 +824,7 @@ voice. It's <<= contextualIntro($activeSlave, $subSlave, true)>>. <<elseif $subSlave.assignment == "serve in the club" || $subSlave.assignment == "serve the public">> "And my <<if _vaginal>>pu<<ss>>y<<else>>a<<ss>><</if>> i<<s>> <<s>>ore. <<C>>itizen<<s>> <<if _vaginal>>fucked me<<else>>pounded it<</if>> all day." <<else>> - "I'm tired, and I have to $subSlave.assignment tomorrow. I ju<<s>>t want to go to <<s>>leep." + "I'm tired, and I have to <<if $subSlave.assignment != "choose her own job">>$subSlave.assignment<<else>>work<</if>> tomorrow. I ju<<s>>t want to go to <<s>>leep." <</if>> _His2 objections sound a bit feigned, and _he2's obviously in no hurry to put an end to <<if areRelated($activeSlave, $subSlave)>> @@ -2065,7 +2065,7 @@ $he adds impishly. <<if canHear($subSlave)>>Hearing this<<else>>Realizing your p <</if>> <<elseif $subSlave.lactation>> <<set _belly = bellyAdjective($activeSlave)>> - $subSlave.slaveName's own breasts responded to all the stimulation by leaking all over $activeSlave.slaveName's <<if $activeSlave.belly >= 5000>> _belly <<if $activeSlave.bellyPreg >= 3000>>pregnant <</if>>belly<</if>>; as _he2 heads off to shower, $activeSlave.slaveName laughingly chides $subSlave.slaveName for making such a milky mess of _his2 own _mother. + $subSlave.slaveName's own breasts responded to all the stimulation by leaking all over $activeSlave.slaveName's <<if $activeSlave.belly >= 5000>> _belly <<if $activeSlave.bellyPreg >= 3000>>pregnant <</if>><</if>>belly; as _he2 heads off to shower, $activeSlave.slaveName laughingly chides $subSlave.slaveName for making such a milky mess of _his2 own _mother. <</if>> <<set $activeSlave.trust += 3, $subSlave.trust += 3>> <<run seX($subSlave, "oral", $activeSlave, "mammary")>> diff --git a/src/uncategorized/brothel.tw b/src/uncategorized/brothel.tw index 7b0fb089d830a08a0a5c2ae691c286f4460bcd20..5a318e8c462a0ee5c7f68740164c0d1464804f3b 100644 --- a/src/uncategorized/brothel.tw +++ b/src/uncategorized/brothel.tw @@ -249,6 +249,8 @@ made you an extra <span class="cash inc"><<print cashFormat(_adsProfit)>>,</span><<if _BL > 1>> as well as increasing business for your whores.<</if>> <<elseif _adsProfit < 0>> cost you <span class="cash dec"><<print cashFormat(_adsProfit)>>,</span><<if _BL > 1>> but still increased business for your whores.<</if>> + <<else>> + didn't make you any extra money, but didn't lose you any, either. <</if>> <div class="choices"> <<link "Manage brothel advertisements" "Brothel Advertisement">> diff --git a/src/uncategorized/brothelReport.tw b/src/uncategorized/brothelReport.tw index f38bcd56b4a58460e368b028a74658ae8137ee2d..3cfca0248129a6a359a32e3c07796afc08c6cdf1 100644 --- a/src/uncategorized/brothelReport.tw +++ b/src/uncategorized/brothelReport.tw @@ -89,12 +89,12 @@ $He forces $his <<print rivalryTerm(_S.Madam)>>, to service all the men in the brothel. <<set _slave.devotion -= 2, _slave.trust -= 2>> <<if canDoVaginal(_slave)>> - <<run seX($activeSlave, "vaginal", "public", "penetrative", 10)>> + <<run seX(_slave, "vaginal", "public", "penetrative", 10)>> <</if>> <<if canDoAnal(_slave)>> - <<run seX($activeSlave, "anal", "public", "penetrative", 12)>> + <<run seX(_slave, "anal", "public", "penetrative", 12)>> <</if>> - <<run seX($activeSlave, "anal", "public", "penetrative", 10)>> + <<run seX(_slave, "anal", "public", "penetrative", 10)>> <<if random(1,100) > 65>> <<set _S.Madam.rivalry++, _slave.rivalry++>> <</if>> diff --git a/src/uncategorized/costsBudget.js b/src/uncategorized/costsBudget.js index 6b58cab4b60fc3697f9841e4e3394b341d519933..ee5e3ae4dd59de01e669a2ac347af568a75c8607 100644 --- a/src/uncategorized/costsBudget.js +++ b/src/uncategorized/costsBudget.js @@ -17,6 +17,8 @@ App.UI.Budget.Cost = function() { // HEADER: FACILITIES createSectionHeader("Facilities"); + const f = App.Entity.facilities; // shortcut + // PENTHOUSE addToggle(generateRowGroup("Penthouse", "PENTHOUSE"), [ generateRowCategory("Rest", "slaveAssignmentRest"), @@ -44,7 +46,7 @@ App.UI.Budget.Cost = function() { // HEAD GIRL // find passage name for HGSuite - addToggle(generateRowGroup(capFirstChar(V.HGSuiteName), "HEADGIRLSUITE"), [ + addToggle(generateRowGroup(f.headGirlSuite.nameCaps, "HEADGIRLSUITE"), [ generateRowCategory("Head Girl", "slaveAssignmentHeadgirl"), generateRowCategory("Head Girl Fucktoys", "slaveAssignmentHeadgirlsuite") ]); @@ -56,12 +58,12 @@ App.UI.Budget.Cost = function() { // BODYGUARD // find passage name for Armory - addToggle(generateRowGroup("Armory", "DOJO"), [ + addToggle(generateRowGroup(f.armory.nameCaps, "DOJO"), [ generateRowCategory("Bodyguard", "slaveAssignmentBodyguard") ]); // CONCUBINE - addToggle(generateRowGroup("Master Suite", "MASTERSUITE"), [ + addToggle(generateRowGroup(f.masterSuite.nameCaps, "MASTERSUITE"), [ generateRowCategory("Master Suite Operation", "masterSuite"), generateRowCategory("Master Suite Concubine", "slaveAssignmentConcubine"), generateRowCategory("Master Suite Fucktoys", "slaveAssignmentMastersuite") @@ -74,13 +76,13 @@ App.UI.Budget.Cost = function() { ]); // ARCADE - addToggle(generateRowGroup(capFirstChar(V.arcadeName), "ARCADE"), [ + addToggle(generateRowGroup(f.arcade.nameCaps, "ARCADE"), [ generateRowCategory("Arcade Operation", "arcade"), generateRowCategory("Arcade Fuckdolls", "slaveAssignmentArcade") ]); // BROTHEL - addToggle(generateRowGroup(capFirstChar(V.brothelName), "BROTHEL"), [ + addToggle(generateRowGroup(f.brothel.nameCaps, "BROTHEL"), [ generateRowCategory("Brothel Operation", "brothel"), generateRowCategory("Brothel Madam", "slaveAssignmentMadam"), generateRowCategory("Brothel MadamVign", "slaveAssignmentMadamVign"), @@ -90,14 +92,14 @@ App.UI.Budget.Cost = function() { ]); // CELLBLOCK - addToggle(generateRowGroup(capFirstChar(V.cellblockName), "CELLBLOCK"), [ + addToggle(generateRowGroup(f.cellblock.nameCaps, "CELLBLOCK"), [ generateRowCategory("Cellblock Operation", "cellblock"), generateRowCategory("Cellblock Warden", "slaveAssignmentWarden"), generateRowCategory("Cellblock Slaves", "slaveAssignmentCellblock") ]); // CLUB - addToggle(generateRowGroup(capFirstChar(V.clubName), "CLUB"), [ + addToggle(generateRowGroup(f.club.nameCaps, "CLUB"), [ generateRowCategory("Club Operation", "club"), generateRowCategory("Club DJ", "slaveAssignmentDj"), generateRowCategory("Club DJVign", "slaveAssignmentDjVign"), @@ -107,14 +109,14 @@ App.UI.Budget.Cost = function() { ]); // CLINIC - addToggle(generateRowGroup(capFirstChar(V.clinicName), "CLINIC"), [ + addToggle(generateRowGroup(f.clinic.nameCaps, "CLINIC"), [ generateRowCategory("Clinic Operation", "clinic"), generateRowCategory("Clinic Nurse", "slaveAssignmentNurse"), generateRowCategory("Clinic Slaves", "slaveAssignmentClinic") ]); // DAIRY - addToggle(generateRowGroup(capFirstChar(V.dairyName), "DAIRY"), [ + addToggle(generateRowGroup(f.dairy.nameCaps, "DAIRY"), [ generateRowCategory("Dairy Operation", "dairy"), generateRowCategory("Dairy Milkmaid", "slaveAssignmentMilkmaid"), generateRowCategory("Dairy Cows", "slaveAssignmentDairy"), @@ -122,7 +124,7 @@ App.UI.Budget.Cost = function() { ]); // FARMYARD - addToggle(generateRowGroup(capFirstChar(V.farmyardName), "FARMYARD"), [ + addToggle(generateRowGroup(f.farmyard.nameCaps, "FARMYARD"), [ generateRowCategory("Farmyard Operation", "farmyard"), generateRowCategory("Farmyard Farmer", "slaveAssignmentFarmer"), generateRowCategory("Farmyard Farmhands", "slaveAssignmentFarmyard"), @@ -130,13 +132,13 @@ App.UI.Budget.Cost = function() { ]); // INCUBATOR - addToggle(generateRowGroup(capFirstChar(V.incubatorName), "INCUBATOR"), [ + addToggle(generateRowGroup(f.incubator.nameCaps, "INCUBATOR"), [ generateRowCategory("Incubator Operation", "incubator"), generateRowCategory("Incubator Babies", "incubatorSlaves") ]); // NURSERY - addToggle(generateRowGroup(capFirstChar(V.nurseryName), "NURSERY"), [ + addToggle(generateRowGroup(f.nursery.nameCaps, "NURSERY"), [ generateRowCategory("Nursery Operation", "nursery"), generateRowCategory("Nursery Matron", "slaveAssignmentMatron"), generateRowCategory("Nursery Nannies", "slaveAssignmentNursery"), @@ -144,7 +146,7 @@ App.UI.Budget.Cost = function() { ]); // PIT - addToggle(generateRowGroup(capFirstChar(V.pitName), "PIT"), [ + addToggle(generateRowGroup(f.pit.nameCaps, "PIT"), [ generateRowCategory("Pit Operation", "pit") ]); @@ -157,14 +159,14 @@ App.UI.Budget.Cost = function() { ]); // SCHOOLROOM - addToggle(generateRowGroup(capFirstChar(V.schoolroomName), "SCHOOLROOM"), [ + addToggle(generateRowGroup(f.schoolroom.nameCaps, "SCHOOLROOM"), [ generateRowCategory("Schoolroom Operation", "school"), generateRowCategory("Schoolroom Teacher", "slaveAssignmentTeacher"), generateRowCategory("Schoolroom Students", "slaveAssignmentSchool") ]); // SERVANTS' QUARTERS - addToggle(generateRowGroup(capFirstChar(V.servantsQuartersName), "SERVANTSQUARTERS"), [ + addToggle(generateRowGroup(f.servantsQuarters.nameCaps, "SERVANTSQUARTERS"), [ generateRowCategory("Servants' Quarters Operation", "servantsQuarters"), generateRowCategory("Servants' Quarters Steward", "slaveAssignmentSteward"), generateRowCategory("Servants' Quarters Servants", "slaveAssignmentQuarter"), @@ -172,7 +174,7 @@ App.UI.Budget.Cost = function() { ]); // SPA - addToggle(generateRowGroup(capFirstChar(V.spaName), "SPA"), [ + addToggle(generateRowGroup(f.spa.nameCaps, "SPA"), [ generateRowCategory("Spa Operation", "spa"), generateRowCategory("Spa Attendant", "slaveAssignmentAttendant"), generateRowCategory("Spa Slaves", "slaveAssignmentSpa") diff --git a/src/uncategorized/dairy.tw b/src/uncategorized/dairy.tw index 710180dd427419645b3822a02c011153045b9808..e828a013cc1894a68106deb825f887b29ebb9804 100644 --- a/src/uncategorized/dairy.tw +++ b/src/uncategorized/dairy.tw @@ -346,7 +346,7 @@ <div> <<set _Tmult0 = Math.trunc($dairy*1000*$upgradeMultiplierArcology)>> _dairyNameCaps can support $dairy milkers. - There<<if _DL == 1>>is<<else>>are<</if>> currently _DL cow<<if _DL != 1>>s<</if>>. + There <<if _DL == 1>>is<<else>>are<</if>> currently _DL cow<<if _DL != 1>>s<</if>>. <div class="choices"> [[Expand the dairy|Dairy][cashX(forceNeg(_Tmult0), "capEx"), $dairy += 5, $PC.skill.engineering += .1]] <span class="note"> diff --git a/src/uncategorized/jeSlaveDispute.tw b/src/uncategorized/jeSlaveDispute.tw index 1c17bf64e4b5a798ee73851963338a57515ac1ed..dfedb8a41eab985bef489fd720ef02c6972706d5 100644 --- a/src/uncategorized/jeSlaveDispute.tw +++ b/src/uncategorized/jeSlaveDispute.tw @@ -5,158 +5,141 @@ <<switch _event>> <<case "slave deal">> <<set _ContractCost = 5000>> - <<set $activeSlaveOneTimeMinAge = 24>> - <<set $activeSlaveOneTimeMaxAge = 42>> - <<set $one_time_age_overrides_pedo_mode = 1>> - <<set $oneTimeDisableDisability = 1>> - <<set $activeSlave = GenerateNewSlave("XX")>> - <<set $activeSlave.origin = "$He sold $himself into slavery to buy medical care for $his daughter.">> - <<set $activeSlave.devotion = random(25,30)>> - <<set $activeSlave.trust = $activeSlave.devotion-20>> - <<set $activeSlave.oldDevotion = $activeSlave.devotion>> - <<run setHealth($activeSlave, jsRandom(0, 20))>> - <<set $activeSlave.earPiercing = 1>> - <<set $activeSlave.vagina = random(1,2)>> - <<set $activeSlave.ovaries = 1>> - <<set $activeSlave.counter.birthsTotal = 1>> - <<set $activeSlave.shouldersTat = either("flowers", "tribal patterns")>> - <<set $activeSlave.stampTat = either("flowers", "tribal patterns")>> + <<set _slave = GenerateNewSlave("XX", {minAge: 24, maxAge: 42, ageOverridesPedoMode: 1, disableDisability: 1})>> + <<set _slave.origin = "$He sold $himself into slavery to buy medical care for $his daughter.">> + <<set _slave.devotion = random(25,30)>> + <<set _slave.trust = _slave.devotion-20>> + <<set _slave.oldDevotion = _slave.devotion>> + <<run setHealth(_slave, jsRandom(0, 20))>> + <<set _slave.earPiercing = 1>> + <<set _slave.vagina = random(1,2)>> + <<set _slave.ovaries = 1>> + <<set _slave.counter.birthsTotal = 1>> + <<set _slave.shouldersTat = either("flowers", "tribal patterns")>> + <<set _slave.stampTat = either("flowers", "tribal patterns")>> <<case "breeding deal">> <<set _ContractCost = 40000>> - <<set $activeSlaveOneTimeMinAge = $fertilityAge+3>> - <<set $activeSlaveOneTimeMaxAge = 24>> - <<set $one_time_age_overrides_pedo_mode = 1>> - <<set $oneTimeDisableDisability = 1>> - <<set $activeSlave = GenerateNewSlave("XX")>> - <<set $activeSlave.origin = "$He was raised to be a mother.">> - <<set $activeSlave.career = "a breeder">> - <<set $activeSlave.devotion = random(10,25)>> - <<set $activeSlave.trust = $activeSlave.devotion>> - <<run setHealth($activeSlave, jsRandom(80, 90), 0, 0, 0, jsRandom(10, 30))>> - <<set $activeSlave.anus = 0>> - <<set $activeSlave.vagina = 3>> - <<set $activeSlave.skill.anal = 0>> - <<set $activeSlave.skill.oral = 0>> - <<set $activeSlave.skill.whoring = 0>> - <<set $activeSlave.skill.vaginal = 0>> - <<set $activeSlave.skill.entertainment = 0>> - <<set $activeSlave.bellySag = 10>> - <<set $activeSlave.bellySagPreg = 10>> - <<set $activeSlave.counter.birthsTotal = 3>> - <<set $activeSlave.hips = 2>> - <<set $activeSlave.boobs = random(4,6)*100>> + <<set _slave = GenerateNewSlave("XX", {minAge: $fertilityAge+3, maxAge: 42, ageOverridesPedoMode: 1, disableDisability: 1})>> + <<set _slave.origin = "$He was raised to be a mother.">> + <<set _slave.career = "a breeder">> + <<set _slave.devotion = random(10,25)>> + <<set _slave.trust = _slave.devotion>> + <<run setHealth(_slave, jsRandom(80, 90), 0, 0, 0, jsRandom(10, 30))>> + <<set _slave.anus = 0>> + <<set _slave.vagina = 3>> + <<set _slave.skill.anal = 0>> + <<set _slave.skill.oral = 0>> + <<set _slave.skill.whoring = 0>> + <<set _slave.skill.vaginal = 0>> + <<set _slave.skill.entertainment = 0>> + <<set _slave.bellySag = 10>> + <<set _slave.bellySagPreg = 10>> + <<set _slave.counter.birthsTotal = 3>> + <<set _slave.hips = 2>> + <<set _slave.boobs = random(4,6)*100>> <<if $seePreg == 1>> - <<set $activeSlave.belly = 18000>> + <<set _slave.belly = 18000>> <</if>> <<case "slave training">> <<set _ContractCost = 10000>> - <<set $oneTimeDisableDisability = 1>> - <<set $activeSlave = GenerateNewSlave("XY")>> - <<set $activeSlave.origin = "You bought out a deal involving $him training to be an expert gelded sex slave.">> - <<set $activeSlave.devotion = random(30,40)>> - <<set $activeSlave.trust = $activeSlave.devotion>> - <<set $activeSlave.oldDevotion = $activeSlave.devotion>> - <<run setHealth($activeSlave, jsRandom(60, 80), 0, 0, 0, jsRandom(10, 30))>> - <<set $activeSlave.balls = 0>> - <<set $activeSlave.anus = 2>> - <<set $activeSlave.skill.anal = 35>> - <<set $activeSlave.skill.oral = 35>> - <<set $activeSlave.skill.whoring = 35>> - <<set $activeSlave.skill.entertainment = 35>> - <<set $activeSlave.nipplesPiercing = 1>> - <<set $activeSlave.clitPiercing = 1>> - <<set $activeSlave.dickPiercing = 1>> - <<set $activeSlave.anusPiercing = 1>> - <<set $activeSlave.lipsPiercing = 1>> - <<set $activeSlave.tonguePiercing = 1>> - <<set $activeSlave.earPiercing = 1>> - <<set $activeSlave.nosePiercing = 1>> - <<set $activeSlave.eyebrowPiercing = 1>> - <<set $activeSlave.navelPiercing = 1>> - <<set $activeSlave.boobsTat = either("advertisements", "degradation", "rude words")>> - <<set $activeSlave.buttTat = either("advertisements", "degradation", "rude words")>> - <<set $activeSlave.vaginaTat = either("advertisements", "degradation", "rude words")>> - <<set $activeSlave.dickTat = either("advertisements", "degradation", "rude words")>> - <<set $activeSlave.lipsTat = either("advertisements", "degradation", "rude words")>> - <<set $activeSlave.anusTat = either("advertisements", "degradation", "rude words")>> - <<set $activeSlave.shouldersTat = either("advertisements", "degradation", "rude words")>> - <<set $activeSlave.armsTat = either("advertisements", "degradation", "rude words")>> - <<set $activeSlave.legsTat = either("advertisements", "degradation", "rude words")>> - <<set $activeSlave.stampTat = either("advertisements", "degradation", "rude words")>> + <<set _slave = GenerateNewSlave("XY", {disableDisability: 1})>> + <<set _slave.origin = "You bought out a deal involving $him training to be an expert gelded sex slave.">> + <<set _slave.devotion = random(30,40)>> + <<set _slave.trust = _slave.devotion>> + <<set _slave.oldDevotion = _slave.devotion>> + <<run setHealth(_slave, jsRandom(60, 80), 0, 0, 0, jsRandom(10, 30))>> + <<set _slave.balls = 0>> + <<set _slave.anus = 2>> + <<set _slave.skill.anal = 35>> + <<set _slave.skill.oral = 35>> + <<set _slave.skill.whoring = 35>> + <<set _slave.skill.entertainment = 35>> + <<set _slave.nipplesPiercing = 1>> + <<set _slave.clitPiercing = 1>> + <<set _slave.dickPiercing = 1>> + <<set _slave.anusPiercing = 1>> + <<set _slave.lipsPiercing = 1>> + <<set _slave.tonguePiercing = 1>> + <<set _slave.earPiercing = 1>> + <<set _slave.nosePiercing = 1>> + <<set _slave.eyebrowPiercing = 1>> + <<set _slave.navelPiercing = 1>> + <<set _slave.boobsTat = either("advertisements", "degradation", "rude words")>> + <<set _slave.buttTat = either("advertisements", "degradation", "rude words")>> + <<set _slave.vaginaTat = either("advertisements", "degradation", "rude words")>> + <<set _slave.dickTat = either("advertisements", "degradation", "rude words")>> + <<set _slave.lipsTat = either("advertisements", "degradation", "rude words")>> + <<set _slave.anusTat = either("advertisements", "degradation", "rude words")>> + <<set _slave.shouldersTat = either("advertisements", "degradation", "rude words")>> + <<set _slave.armsTat = either("advertisements", "degradation", "rude words")>> + <<set _slave.legsTat = either("advertisements", "degradation", "rude words")>> + <<set _slave.stampTat = either("advertisements", "degradation", "rude words")>> <<case "majority deal">> <<set _ContractCost = 20000>> - <<set $activeSlaveOneTimeMinAge = $minimumSlaveAge>> - <<set $activeSlaveOneTimeMaxAge = 18>> - <<set $oneTimeDisableDisability = 1>> - <<set $activeSlave = GenerateNewSlave()>> - <<set $activeSlave.origin = "$He was raised to be a slave, since $he was mistakenly thought to be from good slave stock.">> - <<set $activeSlave.career = "a slave">> - <<set $activeSlave.devotion = random(10,15)>> - <<set $activeSlave.trust = $activeSlave.devotion>> - <<set $activeSlave.oldDevotion = $activeSlave.devotion>> - <<run setHealth($activeSlave, jsRandom(80, 90), 0, 0, 0, jsRandom(10, 30))>> - <<if $activeSlave.dick == 0>> - <<set $activeSlave.vagina = 0>> - <<set $activeSlave.ovaries = 1>> - <<elseif $activeSlave.balls == 0>> - <<set $activeSlave.balls = 1>> + <<set _slave = GenerateNewSlave("", , {minAge: $minimumSlaveAge, maxAge: 18, disableDisability: 1})>> + <<set _slave.origin = "$He was raised to be a slave, since $he was mistakenly thought to be from good slave stock.">> + <<set _slave.career = "a slave">> + <<set _slave.devotion = random(10,15)>> + <<set _slave.trust = _slave.devotion>> + <<set _slave.oldDevotion = _slave.devotion>> + <<run setHealth(_slave, jsRandom(80, 90), 0, 0, 0, jsRandom(10, 30))>> + <<if _slave.dick == 0>> + <<set _slave.vagina = 0>> + <<set _slave.ovaries = 1>> + <<elseif _slave.balls == 0>> + <<set _slave.balls = 1>> <</if>> - <<set $activeSlave.anus = 0>> - <<set $activeSlave.skill.anal = 0>> - <<set $activeSlave.skill.oral = 0>> - <<set $activeSlave.skill.whoring = 0>> - <<set $activeSlave.skill.vaginal = 0>> - <<set $activeSlave.skill.entertainment = 0>> + <<set _slave.anus = 0>> + <<set _slave.skill.anal = 0>> + <<set _slave.skill.oral = 0>> + <<set _slave.skill.whoring = 0>> + <<set _slave.skill.vaginal = 0>> + <<set _slave.skill.entertainment = 0>> <<case "indenture deal">> <<set _ContractCost = 7500>> - <<set $activeSlaveOneTimeMinAge = 24>> - <<set $activeSlaveOneTimeMaxAge = 42>> - <<set $oneTimeDisableDisability = 1>> - <<set $activeSlave = GenerateNewSlave()>> - <<run setHealth($activeSlave, jsRandom(-20, 20))>> - <<set $activeSlave.anus = 2>> - <<if $activeSlave.vagina > -1>> - <<set $activeSlave.vagina = 2>> + <<set _slave = GenerateNewSlave("", , {minAge: 24, maxAge: 42, disableDisability: 1})>> + <<run setHealth(_slave, jsRandom(-20, 20))>> + <<set _slave.anus = 2>> + <<if _slave.vagina > -1>> + <<set _slave.vagina = 2>> <</if>> - <<set $activeSlave.skill.vaginal = 15>> - <<set $activeSlave.skill.oral = 15>> - <<set $activeSlave.skill.anal = 15>> - <<set $activeSlave.skill.whoring = 0>> - <<set $activeSlave.skill.entertainment = 15>> - <<set $activeSlave.boobs += 600>> - <<set $activeSlave.boobsImplant = 600>> - <<set $activeSlave.boobsImplantType = "normal">> - <<set $activeSlave.butt += 1>> - <<set $activeSlave.buttImplant = 1>> - <<set $activeSlave.buttImplantType = "normal">> - <<set $activeSlave.lips += 10>> - <<set $activeSlave.lipsImplant = 10>> - <<set $activeSlave.lipsPiercing = 1>> - <<set $activeSlave.tonguePiercing = 1>> - <<set $activeSlave.earPiercing = 1>> - <<set $activeSlave.nosePiercing = 1>> - <<set $activeSlave.eyebrowPiercing = 1>> - <<set $activeSlave.navelPiercing = 1>> - <<set $activeSlave.nipplesPiercing = 1>> - <<set $activeSlave.clitPiercing = 1>> - <<set $activeSlave.stampTat = either("flowers", "tribal patterns")>> + <<set _slave.skill.vaginal = 15>> + <<set _slave.skill.oral = 15>> + <<set _slave.skill.anal = 15>> + <<set _slave.skill.whoring = 0>> + <<set _slave.skill.entertainment = 15>> + <<set _slave.boobs += 600>> + <<set _slave.boobsImplant = 600>> + <<set _slave.boobsImplantType = "normal">> + <<set _slave.butt += 1>> + <<set _slave.buttImplant = 1>> + <<set _slave.buttImplantType = "normal">> + <<set _slave.lips += 10>> + <<set _slave.lipsImplant = 10>> + <<set _slave.lipsPiercing = 1>> + <<set _slave.tonguePiercing = 1>> + <<set _slave.earPiercing = 1>> + <<set _slave.nosePiercing = 1>> + <<set _slave.eyebrowPiercing = 1>> + <<set _slave.navelPiercing = 1>> + <<set _slave.nipplesPiercing = 1>> + <<set _slave.clitPiercing = 1>> + <<set _slave.stampTat = either("flowers", "tribal patterns")>> <<default>> <<set _ContractCost = 10000>> - <<set $activeSlaveOneTimeMaxAge = 22>> - <<set $oneTimeDisableDisability = 1>> - <<set $activeSlave = GenerateNewSlave()>> - <<set $activeSlave.origin = "You bought out a deal for $his sale after the seller took $his virginity and the buyer no longer wanted $him.">> - <<set $activeSlave.counter.publicUse += 10>> - <<set $activeSlave.devotion = random(25,30)>> - <<set $activeSlave.trust = $activeSlave.devotion-20>> - <<set $activeSlave.oldDevotion = $activeSlave.devotion>> - <<run setHealth($activeSlave, jsRandom(0, 20))>> - <<set $activeSlave.anus = 2>> - <<if $activeSlave.dick == 0>> - <<set $activeSlave.vagina = 2>> - <<set $activeSlave.ovaries = 1>> - <<if isFertile($activeSlave) && $seePreg == 1>> - <<= knockMeUp($activeSlave, 100, 2, -2, 1)>> + <<set _slave = GenerateNewSlave("", {maxAge: 22, disableDisability: 1})>> + <<set _slave.origin = "You bought out a deal for $his sale after the seller took $his virginity and the buyer no longer wanted $him.">> + <<set _slave.counter.publicUse += 10>> + <<set _slave.devotion = random(25,30)>> + <<set _slave.trust = _slave.devotion-20>> + <<set _slave.oldDevotion = _slave.devotion>> + <<run setHealth(_slave, jsRandom(0, 20))>> + <<set _slave.anus = 2>> + <<if _slave.dick == 0>> + <<set _slave.vagina = 2>> + <<set _slave.ovaries = 1>> + <<if isFertile(_slave) && $seePreg == 1>> + <<= knockMeUp(_slave, 100, 2, -2, 1)>> <</if>> <</if>> <</switch>> @@ -164,14 +147,14 @@ /* 000-250-006 */ <<if $seeImages == 1>> <<if $imageChoice == 1>> - <div class="imageRef lrgVector"><div class="mask"> </div><<= SlaveArt($activeSlave, 2, 0)>></div> + <div class="imageRef lrgVector"><div class="mask"> </div><<= SlaveArt(_slave, 2, 0)>></div> <<else>> - <div class="imageRef lrgRender"><div class="mask"> </div><<= SlaveArt($activeSlave, 2, 0)>></div> + <div class="imageRef lrgRender"><div class="mask"> </div><<= SlaveArt(_slave, 2, 0)>></div> <</if>> <</if>> /* 000-250-006 */ -<<run App.Utils.setLocalPronouns($activeSlave)>> +<<run App.Utils.setLocalPronouns(_slave)>> <<= capFirstChar($assistant.name)>> breaks in on your sleep with an urgent message. You push a slave off you and sit up to take it. As the owner of the arcology, you perform some functions that would traditionally be the province of a government. In this anarcho-liberal polity, it's still necessary for people making deals to have someone to appeal to when disputes arise. Part of your agreement with your tenants is that you will perform this duty on deals between two tenants. The message is about just such a disagreement; they always seem to happen in the middle of the night, and they're always urgent. @@ -186,8 +169,8 @@ A small-time slave breeder is accusing a customer of reneging on their agreement. For the last nine months, one of his best breeders has been busy growing his client's future slave and now <<if $seePreg == 1>> that $he's ready to give birth, - <<set $activeSlave.belly = 0>> - <<set $activeSlave.pregWeek = -3>> + <<set _slave.belly = 0>> + <<set _slave.pregWeek = -3>> <<else>> that it's born, <</if>> @@ -245,7 +228,7 @@ <br><br> <<set $arcologies[0].prosperity += 5>> <<run repX(2500, "event")>> - <<includeDOM App.UI.newSlaveIntro($activeSlave)>> + <<includeDOM App.UI.newSlaveIntro(_slave)>> <</replace>> <</link>> //This will cost <<print cashFormat(_ContractCost)>> and give you the slave// <<case "breeding deal">> @@ -281,7 +264,7 @@ <br><br> <<set $arcologies[0].prosperity += 3>> <<run repX(300, "event")>> - <<includeDOM App.UI.newSlaveIntro($activeSlave)>> + <<includeDOM App.UI.newSlaveIntro(_slave)>> <</replace>> <</link>> //This will cost <<print cashFormat(_ContractCost)>> and give you the slave// <<case "slave training">> @@ -313,7 +296,7 @@ <br><br> <<set $arcologies[0].prosperity += 5>> <<run repX(2500, "event")>> - <<includeDOM App.UI.newSlaveIntro($activeSlave)>> + <<includeDOM App.UI.newSlaveIntro(_slave)>> <</replace>> <</link>> //This will cost <<print cashFormat(_ContractCost)>> and give you the slave// <<case "majority deal">> @@ -345,7 +328,7 @@ <br><br> <<set $arcologies[0].prosperity += 3>> <<run repX(1500, "event")>> - <<includeDOM App.UI.newSlaveIntro($activeSlave)>> + <<includeDOM App.UI.newSlaveIntro(_slave)>> <</replace>> <</link>> //This will cost <<print cashFormat(_ContractCost)>> and give you the slave// <<case "indenture deal">> @@ -371,33 +354,33 @@ <</replace>> <</link>> <br><<link "Buy out the contract and $his indenture">> - <<set $activeSlave.devotion = random(10,15)>> - <<set $activeSlave.trust = $activeSlave.devotion+4>> - <<set $activeSlave.oldDevotion = $activeSlave.devotion>> - <<set $activeSlave.indenture = random(52,78)>> - <<set $activeSlave.indentureRestrictions = 2>> - <<set $activeSlave.origin = "You took over $his indenture after $he launched a legal complaint against an abusive master.">> + <<set _slave.devotion = random(10,15)>> + <<set _slave.trust = _slave.devotion+4>> + <<set _slave.oldDevotion = _slave.devotion>> + <<set _slave.indenture = random(52,78)>> + <<set _slave.indentureRestrictions = 2>> + <<set _slave.origin = "You took over $his indenture after $he launched a legal complaint against an abusive master.">> <<run cashX(forceNeg(_ContractCost), "slaveTransfer")>> <<replace "#result">> You offer to simply buy out the indenture contract, thereby acquiring $him, to which both parties readily agree. This decision is viewed as @@.green;incredibly generous@@ by both your arcology's romantically-minded and financially-inclined citizens. For their part, your new servant is hopeful that you will be more considerate of $his health, while the former holder is just happy to have $him off his hands. <br><br> <<set $arcologies[0].prosperity += 3>> <<run repX(1500, "event")>> - <<includeDOM App.UI.newSlaveIntro($activeSlave)>> + <<includeDOM App.UI.newSlaveIntro(_slave)>> <</replace>> <</link>> //This will cost <<print cashFormat(_ContractCost)>> and give you the servant as such// <br><<link "Buy out the contract and enslave $him">> - <<set $activeSlave.origin = "$He was enslaved after you manipulated $his deal for indentured servitude.">> - <<set $activeSlave.devotion = random(-10,-15)>> - <<set $activeSlave.trust = $activeSlave.devotion+4>> - <<set $activeSlave.oldDevotion = $activeSlave.devotion>> + <<set _slave.origin = "$He was enslaved after you manipulated $his deal for indentured servitude.">> + <<set _slave.devotion = random(-10,-15)>> + <<set _slave.trust = _slave.devotion+4>> + <<set _slave.oldDevotion = _slave.devotion>> <<run cashX(forceNeg(_ContractCost), "slaveTransfer")>> <<replace "#result">> You quietly contact the trader and suggest an alternative method of settling the dispute. He is surprised, but agrees readily, chuckling at how the "recalcitrant bitch" is going to be dealt with. To $his horror, $he finds that your near-total power over deals made in your arcology has been employed to saddle $him with additional debts that, under $his indentured servitude, $he cannot hope to repay. It is then the work of ten minutes to demand payment, and when $he cannot pay, demand $his body for enslavement. The story of your cunning @@.green;impresses@@ the slave traders, but is @@.red;booed@@ by fairer-minded citizens. <br><br> <<set $arcologies[0].prosperity += 5>> <<run repX(-100, "event")>> - <<includeDOM App.UI.newSlaveIntro($activeSlave)>> + <<includeDOM App.UI.newSlaveIntro(_slave)>> <</replace>> <</link>> //This will cost <<print cashFormat(_ContractCost)>> and give you the servant as a slave// <<default>> @@ -427,7 +410,7 @@ <<replace "#result">> You offer to simply buy out the contract, taking the slave for yourself. This lets the buyer out of buying $him, and the slaveowner gets his money; but it soon becomes apparent that what both of them were really looking for is an opportunity to put one over on the other. Neither is pleased to be denied a petty victory, but they both have the sense to keep their mouths shut. The poor slave, meanwhile, appears in the penthouse entryway, @@.hotpink;hopeful@@ that $he's been lucky enough to end up in a less abusive situation. <br><br> - <<includeDOM App.UI.newSlaveIntro($activeSlave)>> + <<includeDOM App.UI.newSlaveIntro(_slave)>> <</replace>> <</link>> //This will cost <<print cashFormat(_ContractCost)>> and give you the slave// <</switch>> diff --git a/src/uncategorized/pInvasion.tw b/src/uncategorized/pInvasion.tw index 8915829ca70f2d4d98612fbd983058fa701c75ec..2fb31a157b8ebfdd9510bb60364b387ca5bf9fda 100644 --- a/src/uncategorized/pInvasion.tw +++ b/src/uncategorized/pInvasion.tw @@ -97,13 +97,13 @@ The loose militia lately organized by the arcology owners has been called out to <<for _i = 0; _i < 3; _i++>> <<if (random(0,99) < $seeDicks)>> <<set $oneTimeDisableDisability = 1>> - <<set $activeSlave = GenerateNewSlave("XY")>> + <<set _slave = GenerateNewSlave("XY")>> <<else>> <<set $oneTimeDisableDisability = 1>> - <<set $activeSlave = GenerateNewSlave("XX")>> + <<set _slave = GenerateNewSlave("XX")>> <</if>> - <<set $activeSlave.origin = "$He is an enslaved prisoner of war.">> - <<set _newSlaves.push($activeSlave)>> + <<set _slave.origin = "$He is an enslaved prisoner of war.">> + <<set _newSlaves.push(_slave)>> <</for>> <<set $menials += 5>> diff --git a/src/uncategorized/pRivalInitiation.tw b/src/uncategorized/pRivalInitiation.tw index 0bbe0dc7dbba92da63d340943aba7d38a422c15a..576f6a0b0cbc99b4b5913ab6d7cd0369b7f6dbe7 100644 --- a/src/uncategorized/pRivalInitiation.tw +++ b/src/uncategorized/pRivalInitiation.tw @@ -36,7 +36,7 @@ This is a special week, the week of your victory. <<= App.UI.slaveDescriptionDia <</replace>> <</link>> <<if $activeSlave.anus == 0>> - <br><<link "Break $his ass and then let the public use it">> + <br><<link "Break in $his asshole and then let the public use it">> <<replace "#result">> $activeSlave.slaveName, who has been fairly dignified up to this point, breaks down when $he's placed in stocks with $his ass in the air. $His sobs become screams when, for the first time in $his life, $he feels the burning sensation of a well-lubricated <<if $PC.dick != 0>>cockhead<<else>>strap-on<</if>> forcing its way past $his virgin sphincter. Raping a virgin anus is not a new pleasure for you, but the usual shrieking, struggling and spasming is all the sweeter this time. @@.green;Half the arcology@@ has used $his @@.red;poor injured butthole@@ by the end of the day; $he @@.gold;is learning to fear you,@@ and hates you @@.mediumorchid;even more@@ if possible. <<set $activeSlave.devotion -= 4, $activeSlave.trust -= 5, $activeSlave.anus = 3>> diff --git a/src/uncategorized/peCombatTraining.tw b/src/uncategorized/peCombatTraining.tw index ac6e057acb857fb219ea3198f0cf1c2112b03169..ab8168d04d47bcc89cbc5bd05035d0dba3ce9327 100644 --- a/src/uncategorized/peCombatTraining.tw +++ b/src/uncategorized/peCombatTraining.tw @@ -1,23 +1,22 @@ :: PE combat training [nobr] -<<set $nextButton = "Continue", $nextLink = "AS Dump", $returnTo = "RIE Eligibility Check">> +<<set $nextButton = "Continue", $nextLink = "RIE Eligibility Check">> -<<set $activeSlave = _S.Bodyguard>> -<<run App.Utils.setLocalPronouns($activeSlave)>> +<<run App.Utils.setLocalPronouns(S.Bodyguard)>> <span id="art-frame"> /* 000-250-006 */ <<if $seeImages == 1>> <<if $imageChoice == 1>> - <div class="imageRef lrgVector"><div class="mask"> </div><<= SlaveArt($activeSlave, 2, 0)>></div> + <div class="imageRef lrgVector"><div class="mask"> </div><<= SlaveArt(_S.Bodyguard, 2, 0)>></div> <<else>> - <div class="imageRef lrgRender"><div class="mask"> </div><<= SlaveArt($activeSlave, 2, 0)>></div> + <div class="imageRef lrgRender"><div class="mask"> </div><<= SlaveArt(_S.Bodyguard, 2, 0)>></div> <</if>> <</if>> /* 000-250-006 */ </span> -<<= App.UI.slaveDescriptionDialog($activeSlave)>> has many duties as a bodyguard, and $his schedule is carefully built to allow $him to complete them. When you're at your desk in your penthouse and there are no guests to intimidate, $his services are least needed, so $he typically uses these lulls to catch up on sleep or train. +<<= App.UI.slaveDescriptionDialog(_S.Bodyguard)>> has many duties as a bodyguard, and $his schedule is carefully built to allow $him to complete them. When you're at your desk in your penthouse and there are no guests to intimidate, $his services are least needed, so $he typically uses these lulls to catch up on sleep or train. <br><br> The feed from the small armory next door shows $him doing the latter. $He has finished working with a heavy practice sword, and has moved to the tiny, one-shooter range. $He seems frustrated, hurrying $his shots and missing unnecessarily. @@ -26,23 +25,23 @@ The feed from the small armory next door shows $him doing the latter. $He has fi <span id="result"> <<link "Instruct $him">> <<replace "#result">> - $activeSlave.slaveName starts as you enter the range and don ear protection. $He is distracted by your body against $hers as you come in close to correct $his stance, but $he concentrates hard for you. You take whatever time you can spare over the week for serious lessons. $He @@.green;is diligent and learns well,@@ and @@.mediumaquamarine;places greater trust@@ in your judgment. - <<set $activeSlave.trust += 4>> - <<set $activeSlave.skill.combat = 1>> + _S.Bodyguard.slaveName starts as you enter the range and don ear protection. $He is distracted by your body against $hers as you come in close to correct $his stance, but $he concentrates hard for you. You take whatever time you can spare over the week for serious lessons. $He @@.green;is diligent and learns well,@@ and @@.mediumaquamarine;places greater trust@@ in your judgment. + <<set _S.Bodyguard.trust += 4>> + <<set _S.Bodyguard.skill.combat = 1>> <</replace>> <</link>> <br><<link "Promise $him a sexual reward if $he improves">> <<replace "#result">> - Over the feed, you tell $activeSlave.slaveName that $he can have $his choice of sexual release if $he scores well on the next set of targets. $He concentrates desperately, trying to ignore $his mounting arousal as $he imagines enjoying <<if $activeSlave.fetish == "none">>passionate sexual<<elseif $activeSlave.fetish == "boobs">>breast<<else>>$activeSlave.fetish<</if>> play. $He barely makes the stated score, and hurries smiling in for $his reward. $He feels @@.hotpink;closer to you,@@ but is distracted from any real learning and does not become a better fighter. - <<set $activeSlave.devotion += 4>> - <<if canDoVaginal($activeSlave)>> - <<= VCheck.Vaginal($activeSlave, 1)>> - <<elseif canDoAnal($activeSlave)>> - <<= VCheck.Anal($activeSlave, 1)>> + Over the feed, you tell _S.Bodyguard.slaveName that $he can have $his choice of sexual release if $he scores well on the next set of targets. $He concentrates desperately, trying to ignore $his mounting arousal as $he imagines enjoying <<if _S.Bodyguard.fetish == "none">>passionate sexual<<elseif _S.Bodyguard.fetish == "boobs">>breast<<else>>_S.Bodyguard.fetish<</if>> play. $He barely makes the stated score, and hurries smiling in for $his reward. $He feels @@.hotpink;closer to you,@@ but is distracted from any real learning and does not become a better fighter. + <<set _S.Bodyguard.devotion += 4>> + <<if canDoVaginal(_S.Bodyguard)>> + <<= VCheck.Vaginal(_S.Bodyguard, 1)>> + <<elseif canDoAnal(_S.Bodyguard)>> + <<= VCheck.Anal(_S.Bodyguard, 1)>> <<else>> - <<set $activeSlave.counter.oral += 1>> + <<set _S.Bodyguard.counter.oral += 1>> <<set $oralTotal += 1>> <</if>> <</replace>> -<</link>><<if canDoVaginal($activeSlave) && ($activeSlave.vagina == 0)>>//This option will take virginity//<<elseif !canDoVaginal($activeSlave) && ($activeSlave.anus == 0)>> //This option will take anal virginity//<</if>> +<</link>><<if canDoVaginal(_S.Bodyguard) && (_S.Bodyguard.vagina == 0)>>//This option will take virginity//<<elseif !canDoVaginal(_S.Bodyguard) && (_S.Bodyguard.anus == 0)>> //This option will take anal virginity//<</if>> </span> diff --git a/src/uncategorized/peConcubineInterview.tw b/src/uncategorized/peConcubineInterview.tw index 7fdeee631db78aee17597bb68dc8569e4dd6fedf..8b0d44dd9f275d5b35a9462d7c4cc9852555a139 100644 --- a/src/uncategorized/peConcubineInterview.tw +++ b/src/uncategorized/peConcubineInterview.tw @@ -129,7 +129,7 @@ You receive an official communication from a popular talk show e-hosted in one o <<elseif $activeSlave.bellyImplant >= 1500>> "It'<<s>> fake. Pretty hard to tell though, i<<s>>n't it?" <<elseif $activeSlave.bellyPreg >= 1500>> - Of cour<<s>>e + "Of cour<<s>>e <<if $activeSlave.pregType > 1>> they are!" <<else>> @@ -145,7 +145,7 @@ You receive an official communication from a popular talk show e-hosted in one o <<elseif $activeSlave.bellyImplant > -1>> "It'<<s>> fake. Pretty hard to tell though, i<<s>>n't it?" <<else>> - Of cour<<s>>e + "Of cour<<s>>e <<if $activeSlave.pregType > 1>> they are!" <<else>> diff --git a/src/uncategorized/reShippingContainer.tw b/src/uncategorized/reShippingContainer.tw index 86dfa5d7787de7b8459fedd0d4af9678541eafd1..ceb352bcd667e96cdaaec1518a1a9cd4ff9e1dd1 100644 --- a/src/uncategorized/reShippingContainer.tw +++ b/src/uncategorized/reShippingContainer.tw @@ -8,12 +8,12 @@ <<set _newSlaves = []>> <<for _reShip = 0; _reShip < 5; _reShip++>> - <<set $activeSlave = GenerateNewSlave("XX")>> - <<set $activeSlave.origin = "$He arrived at your arcology in an undocumented shipping container.">> - <<set $activeSlave.devotion = random(-90,-75)>> - <<set $activeSlave.trust = -20>> - <<run setHealth($activeSlave, -10, undefined, undefined, undefined, random(50, 100))>> - <<set _newSlaves.push($activeSlave)>> + <<set _slave = GenerateNewSlave("XX")>> + <<set _slave.origin = "$He arrived at your arcology in an undocumented shipping container.">> + <<set _slave.devotion = random(-90,-75)>> + <<set _slave.trust = -20>> + <<run setHealth(_slave, -10, undefined, undefined, undefined, random(50, 100))>> + <<set _newSlaves.push(_slave)>> <</for>> <<set $menials += 25>> diff --git a/src/uncategorized/scheduledEvent.tw b/src/uncategorized/scheduledEvent.tw index edc6a4e745e2dbdaf7b701b53763cbfcb42064ee..1c88bbcd433277b278c5f69890dbdc642e04bde9 100644 --- a/src/uncategorized/scheduledEvent.tw +++ b/src/uncategorized/scheduledEvent.tw @@ -131,15 +131,14 @@ <<goto "SE coursing">> <<elseif $policies.raidingMercenaries == 1 && ($week > ($raided + 6))>> <<goto "SE raiding">> -<<elseif $pit && !$pit.fought>> - <<if ($pit.fighterIDs.length > 1 && !$pit.bodyguardFights) +<<elseif $pit && !$pit.fought && + (($pit.fighterIDs.length > 1 && !$pit.bodyguardFights) || ($pit.fighterIDs.length > 0 && ($BodyguardID !== 0 && $pit.bodyguardFights) || $pit.animal) - || $pit.slaveFightingBodyguard>> - <<if $pit.lethal>> - <<goto "SE lethal pit">> - <<else>> - <<goto "SE nonlethal pit">> - <</if>> + || $pit.slaveFightingBodyguard)>> + <<if $pit.lethal>> + <<goto "SE lethal pit">> + <<else>> + <<goto "SE nonlethal pit">> <</if>> <<elseif ($bioreactorPerfectedID != 0) && ($bioreactorsAnnounced != 1)>> <<goto "P bioreactor perfected">> diff --git a/src/uncategorized/seCoursing.tw b/src/uncategorized/seCoursing.tw index 9f05039a07478ba64787180a02da05cf5ef2dda3..665e773cc16c2656eab10ce421737e7219a034b5 100644 --- a/src/uncategorized/seCoursing.tw +++ b/src/uncategorized/seCoursing.tw @@ -353,19 +353,19 @@ You lead your lurcher _activeLurcher.slaveName out on a leash, naked just like t <</link>> <</if>> <<if $origin == "virgin">> - is an appealingly young $activeSlave.race _girl2, and has V symbols drawn over _his2 cunt and on _his2 lower back, in the interests of fairness. _He2's a @@.pink;double virgin.@@<<if !canSee(_activeLurcher)>> To accommodate your blind lurcher, a bell is fastened around _his2 neck.<</if>> + is an appealingly young $activeSlave.race _girl2, and has V symbols drawn over _his2 cunt and on _his2 lower back, in the interests of fairness. _He2's a @@.pink;double virgin. @@<<if !canSee(_activeLurcher)>>To accommodate your blind lurcher, a bell is fastened around _his2 neck.<</if>> <<elseif $origin == "heavily pregnant">> - is <<= addA($activeSlave.race)>> _girl2, young and healthy but @@.pink;heavily pregnant.@@ _He2's probably been selected to be a hare as a joke, or because someone hates _him2. <<if !canSee(_activeLurcher)>> To accommodate your blind lurcher, a bell is attached to _his2 popped navel.<</if>> + is <<= addA($activeSlave.race)>> _girl2, young and healthy but @@.pink;heavily pregnant.@@ _He2's probably been selected to be a hare as a joke, or because someone hates _him2. <<if !canSee(_activeLurcher)>>To accommodate your blind lurcher, a bell is attached to _his2 popped navel.<</if>> <<elseif $origin == "housewife">> - is <<= addA($activeSlave.race)>> _woman2, no longer young, but attractive enough in a fake sort of way. _He2 has obviously been crying, and has probably been recently enslaved from a comfortable life, like that of a @@.pink;house<<= $wife>> or a trophy $wife.@@<<if !canSee(_activeLurcher)>> To accommodate your blind lurcher, a bell is fastened around _his2 neck.<</if>> + is <<= addA($activeSlave.race)>> _woman2, no longer young, but attractive enough in a fake sort of way. _He2 has obviously been crying, and has probably been recently enslaved from a comfortable life, like that of a @@.pink;house<<= $wife>> or a trophy $wife.@@ <<if !canSee(_activeLurcher)>>To accommodate your blind lurcher, a bell is fastened around _his2 neck.<</if>> <<elseif $origin == "disobedient young">> - is a fit young $activeSlave.race _girl2, and is far more watchful and alert than _his2 fellow hares. _He2 may be a @@.pink;disobedient slave@@ here because _he2 was difficult to train.<<if !canSee(_activeLurcher)>> To accommodate your blind lurcher, a bell is fastened around _his2 neck.<</if>> + is a fit young $activeSlave.race _girl2, and is far more watchful and alert than _his2 fellow hares. _He2 may be a @@.pink;disobedient slave@@ here because _he2 was difficult to train. <<if !canSee(_activeLurcher)>>To accommodate your blind lurcher, a bell is fastened around _his2 neck.<</if>> <<elseif $origin == "disobedient young dickgirl">> - is a strong young $activeSlave.race slave who retains _his2 cock and balls, and looks determined. Perhaps _he2's a @@.pink;resistant dickgirl@@ who's been difficult to turn into a good girl.<<if !canSee(_activeLurcher)>> To accommodate your blind lurcher, a bell is fastened around _his2 cock.<</if>> + is a strong young $activeSlave.race slave who retains _his2 cock and balls, and looks determined. Perhaps _he2's a @@.pink;resistant dickgirl@@ who's been difficult to turn into a good girl. <<if !canSee(_activeLurcher)>>To accommodate your blind lurcher, a bell is fastened around _his2 cock.<</if>> <<elseif $origin == "huge balled">> - is <<= addA($activeSlave.race)>> slave whose distinguishing characteristic is a dangling scrotum and a pair of @@.pink;huge balls.@@ This impediment bumps against _his2 thighs as _he2's made ready.<<if !canSee(_activeLurcher)>> To accommodate your blind lurcher, a bell is fastened around _his2 hefty testicles.<</if>> + is <<= addA($activeSlave.race)>> slave whose distinguishing characteristic is a dangling scrotum and a pair of @@.pink;huge balls.@@ This impediment bumps against _his2 thighs as _he2's made ready. <<if !canSee(_activeLurcher)>>To accommodate your blind lurcher, a bell is fastened around _his2 hefty testicles.<</if>> <<elseif $origin == "feminized">> - is <<= addA($activeSlave.race)>> bitch with a tiny dick who has been @@.pink;heavily feminized,@@ yet seems terrified and very new to slavery. _His2 fake tits and girly behavior must be from _his2 life before _he2 was a slave.<<if !canSee(_activeLurcher)>> To accommodate your blind lurcher, a bell is fastened around _his2 neck.<</if>> + is <<= addA($activeSlave.race)>> bitch with a tiny dick who has been @@.pink;heavily feminized,@@ yet seems terrified and very new to slavery. _His2 fake tits and girly behavior must be from _his2 life before _he2 was a slave. <<if !canSee(_activeLurcher)>>To accommodate your blind lurcher, a bell is fastened around _his2 neck.<</if>> <</if>> <<set $activeSlave.origin = "Your lurcher " + _activeLurcher.slaveName + " caught $him coursing; $he was a " + $origin + " hare.">> diff --git a/src/uncategorized/seExpiration.tw b/src/uncategorized/seExpiration.tw index 95ae7fa00ccad3bad54ca2335b7b4eaf8c903f59..f69d0b9b270e61f92db4435af8cbb620c6fbd35b 100644 --- a/src/uncategorized/seExpiration.tw +++ b/src/uncategorized/seExpiration.tw @@ -4,24 +4,20 @@ <<set $expired = 1>> -<<set $activeSlave = getSlave($expiree)>> - -<<run Enunciate($activeSlave)>> -<<run App.Utils.setLocalPronouns($activeSlave)>> +<<run Enunciate(getSlave($expiree))>> +<<run App.Utils.setLocalPronouns(getSlave($expiree))>> <span id="art-frame"> -/* 000-250-006 */ -<<if $seeImages == 1>> - <<if $imageChoice == 1>> - <div class="imageRef lrgVector"><div class="mask"> </div><<= SlaveArt($activeSlave, 2, 0)>></div> - <<else>> - <div class="imageRef lrgRender"><div class="mask"> </div><<= SlaveArt($activeSlave, 2, 0)>></div> + <<if $seeImages == 1>> + <<if $imageChoice == 1>> + <div class="imageRef lrgVector"><div class="mask"> </div><<= SlaveArt(getSlave($expiree), 2, 0)>></div> + <<else>> + <div class="imageRef lrgRender"><div class="mask"> </div><<= SlaveArt(getSlave($expiree), 2, 0)>></div> + <</if>> <</if>> -<</if>> -/* 000-250-006 */ </span> -$activeSlave.slaveName's indentured servitude is ending this week, meaning that your arcology is gaining a citizen. +<<= getSlave($expiree).slaveName>>'s indentured servitude is ending this week, meaning that your arcology is gaining a citizen. <<set $lowerClass += 1>> <<set _seed = 0>> @@ -35,161 +31,164 @@ $activeSlave.slaveName's indentured servitude is ending this week, meaning that Those of your slaves who are unhappy with their lives under you are @@.mediumorchid;envious or angry@@ to see $him become free, according to their individual natures. <</if>> -<<set $activeSlave.indenture = 52>> -<<set _slaveCost = slaveCost($activeSlave)>> - -<<if $activeSlave.fetish == "mindbroken">> - - Since $he is mindbroken, there is precisely no chance that $he will be able to look after $himself. $He <<if hasAnyLegs($activeSlave)>>stands<<else>>sits<</if>> before you dumbly, betraying no reaction to the prospect of becoming free from sexual slavery. In situations like this, it is perfectly acceptable to subject $him to another indenture for $his own good. - <br><br> - - <span id="result"> - <<if $cash > 1000>> - <<link "Plead necessity and reactivate $his indenture">> - <<replace "#result">> - You plead necessity and place $him under another indenture, paying the trivial fees left over once $he has been charged for $his own forecasted upkeep. Naturally, $he offers no response at all to any of this. - <<run cashX(-1000, "event", $activeSlave)>> - <<set $lowerClass -= 1>> - <<set $expired = 0, $expiree = 0>> - <<for $i = 0; $i < $slaves.length; $i++>> - <<if $slaves[$i].indenture == 0>> - <<set $expiree = $slaves[$i].ID>> - <<break>> - <</if>> - <</for>> - <</replace>> - <</link>> //This cost <<print cashFormat(1000)>>// +<<set getSlave($expiree).indenture = 52>> +<<set _slaveCost = slaveCost(getSlave($expiree))>> + +<<if getSlave($expiree).fetish == "mindbroken">> + + Since $he is mindbroken, there is precisely no chance that $he will be able to look after $himself. $He + <<if hasAnyLegs(getSlave($expiree))>> + stands <<else>> - //You cannot afford to do this// + sits <</if>> - </span> + before you dumbly, betraying no reaction to the prospect of becoming free from sexual slavery. In situations like this, it is perfectly acceptable to subject $him to another indenture for $his own good. + + <p id="result"> + <<if $cash > 1000>> + <<link "Plead necessity and reactivate $his indenture">> + <<replace "#result">> + You plead necessity and place $him under another indenture, paying the trivial fees left over once $he has been charged for $his own forecasted upkeep. Naturally, $he offers no response at all to any of this. + <<run cashX(-1000, "event", getSlave($expiree))>> + <<set $lowerClass -= 1>> + <<set $expired = 0, $expiree = 0>> + /* Anyone else expiring? If so, set here so scheduledEvent fires for them too */ + <<for $i = 0; $i < $slaves.length; $i++>> + <<if $slaves[$i].indenture == 0>> + <<set $expiree = $slaves[$i].ID>> + <<break>> + <</if>> + <</for>> + <</replace>> + <</link>> //This cost <<print cashFormat(1000)>>// + <<else>> + //You cannot afford to do this// + <</if>> + </p> -<<elseif ($activeSlave.relationship < -1) && ($activeSlave.devotion > 95) && ($activeSlave.trust > 95)>> +<<elseif (getSlave($expiree).relationship < -1) && (getSlave($expiree).devotion > 95) && (getSlave($expiree).trust > 95)>> $He has been trying desperately hard not to think about this trying situation, but when $he comes before you on the day of $his indenture's expiration, $he can ignore it no longer. $He - <<if !hasAnyArms($activeSlave)>> + <<if !hasAnyArms(getSlave($expiree))>> wriggles disconsolately, probably wishing $he could throw $himself at your feet or cling to your knees. <<else>> throws $himself at your feet and clings to your knees, bursting into tears. <</if>> - <<if !canTalk($activeSlave)>> + <<if !canTalk(getSlave($expiree))>> $He does $his best to communicate an earnest desire to stay, and repeats over and over that $he loves you. $He begins to indicate a willingness to accept true, unlimited slavery, if that's what it takes to stay. <<else>> "Plea<<s>>e <<Master>>, don't <<s>>end me away," $he sobs. "I love you! I'll d-do anything — I'll be your <<s>>lave! Plea<<s>>e, en<<s>>lave me. I l-love you..." $he moans, trailing off into convulsive blubbering. <</if>> - <br><br> - - <span id="result"> - <<if $cash > 1000>> - <<link "Enslave $him">> - <<replace "#result">> - $He's beside $himself with joy when you accept $his plea and enslave $him. $He's given you the finest proof of loyalty a slave possibly can, having tasted a moment of freedom under the law, and thrown it away with utter contempt. - <<if hasAnyEyes($activeSlave)>> - $His <<= App.Desc.eyesColor($activeSlave)>> - <<if hasBothEyes($activeSlave)>> - <<if canSee($activeSlave)>>watch you<<else>>are wide<</if>> + + <p id="result"> + <<if $cash > 1000>> + <<link "Enslave $him">> + <<replace "#result">> + $He's beside $himself with joy when you accept $his plea and enslave $him. $He's given you the finest proof of loyalty a slave possibly can, having tasted a moment of freedom under the law, and thrown it away with utter contempt. + <<if hasAnyEyes(getSlave($expiree))>> + $His <<= App.Desc.eyesColor(getSlave($expiree))>> + <<if hasBothEyes(getSlave($expiree))>> + <<if canSee(getSlave($expiree))>>watch you<<else>>are wide<</if>> + <<else>> + <<if canSee(getSlave($expiree))>>watches you<<else>>is wide<</if>> + <</if>> + with <<else>> - <<if canSee($activeSlave)>>watches you<<else>>is wide<</if>> - <</if>> - with - <<else>> - $His face shows - <</if>> - eager anticipation, radiating gladness that the prospect of separation from you has gone. - <<set $activeSlave.indenture = -1, $activeSlave.indentureRestrictions = 0>> - <<run cashX(-1000, "event", $activeSlave)>> - <<set $lowerClass -= 1>> - <<set $expired = 0, $expiree = 0>> - <<for $i = 0; $i < $slaves.length; $i++>> - <<if $slaves[$i].indenture == 0>> - <<set $expiree = $slaves[$i].ID>> - <<break>> + $His face shows <</if>> - <</for>> - <</replace>> - <</link>> //This will cost <<print cashFormat(1000)>>// - <<else>> - //You cannot afford to do this// - <</if>> - </span> + eager anticipation, radiating gladness that the prospect of separation from you has gone. + <<set getSlave($expiree).indenture = -1, getSlave($expiree).indentureRestrictions = 0>> + <<run cashX(-1000, "event", getSlave($expiree))>> + <<set $lowerClass -= 1>> + <<set $expired = 0, $expiree = 0>> + <<for $i = 0; $i < $slaves.length; $i++>> + <<if $slaves[$i].indenture == 0>> + <<set $expiree = $slaves[$i].ID>> + <<break>> + <</if>> + <</for>> + <</replace>> + <</link>> //This will cost <<print cashFormat(1000)>>// + <<else>> + //You cannot afford to do this// + <</if>> + </p> -<<elseif ($activeSlave.devotion > 50) && ($activeSlave.trust > 50)>> +<<elseif (getSlave($expiree).devotion > 50) && (getSlave($expiree).trust > 50)>> <<set _slaveCost = Math.trunc((_slaveCost*0.5)/500)*500>> <<set _slaveCost = Math.clamp(_slaveCost, minimumSlaveCost(), 100000)>> $His feelings on this are quite mixed, since $he has come to feel that $he has a place under you. - <<if !hasAnyLegs($activeSlave)>> + <<if !hasAnyLegs(getSlave($expiree))>> Propped up <<else>> Standing before you <</if>> at the moment of $his scheduled emancipation, $he seems to be struggling to express $himself. - <<if !canTalk($activeSlave)>> + <<if !canTalk(getSlave($expiree))>> $He does $his best to communicate a willingness to remain your slave, indicating that $he wouldn't press too hard about the price if you offered $him another indenture. <<else>> "<<Master>>, um," $he <<say>>s hesitantly. "I don't mind being your <<s>>lave. Could I — would you plea<<s>>e give me another indenture? I'm, um, not too worried about the pri<<c>>e." <</if>> - <br><br> - - <span id="result"> - <<if $cash > _slaveCost>> - <<link "Offer $him a one year supplementary indenture">> - <<replace "#result">> - $He smiles almost shyly when you offer $him a one year supplementary indenture. The price is reasonable, but definitely favorable to you. $He accepts it anyway, and you transfer the money into an escrow account to be held for $him until $his new indenture is done. Your sex slave once again, $he awaits your pleasure without a hint of fear. - <<run cashX(forceNeg(_slaveCost), "slaveTransfer", $activeSlave)>> - <<set $lowerClass -= 1>> - <<set $expired = 0>><<set $expiree = 0>> - <<for $i = 0; $i < $slaves.length; $i++>> - <<if $slaves[$i].indenture == 0>> - <<set $expiree = $slaves[$i].ID>> - <<break>> - <</if>> - <</for>> - <</replace>> - <</link>> //This will cost <<print cashFormat(_slaveCost)>>// - <<else>> - //You cannot afford to do this// - <</if>> - </span> -<<elseif ($activeSlave.devotion >= -20) && ($activeSlave.trust > 20)>> + <p id="result"> + <<if $cash > _slaveCost>> + <<link "Offer $him a one year supplementary indenture">> + <<replace "#result">> + $He smiles almost shyly when you offer $him a one year supplementary indenture. The price is reasonable, but definitely favorable to you. $He accepts it anyway, and you transfer the money into an escrow account to be held for $him until $his new indenture is done. Your sex slave once again, $he awaits your pleasure without a hint of fear. + <<run cashX(forceNeg(_slaveCost), "slaveTransfer", getSlave($expiree))>> + <<set $lowerClass -= 1>> + <<set $expired = 0>><<set $expiree = 0>> + <<for $i = 0; $i < $slaves.length; $i++>> + <<if $slaves[$i].indenture == 0>> + <<set $expiree = $slaves[$i].ID>> + <<break>> + <</if>> + <</for>> + <</replace>> + <</link>> //This will cost <<print cashFormat(_slaveCost)>>// + <<else>> + //You cannot afford to do this// + <</if>> + </p> -$He approaches the moment with calculation, since $he has found more of a place in slavery than $he probably expected when $he became an indentured servant. -<<if !hasAnyLegs($activeSlave)>> - Propped up -<<else>> - Standing before you -<</if>> -at the moment of $his scheduled emancipation, $he seems willing to consider a short term continuation of service. -<br><br> - -<span id="result"> -<<if $cash > _slaveCost>> - <<link "Offer $him a one year supplementary indenture">> - <<replace "#result">> - $He looks pensive when you offer $him a one year supplementary indenture. The price reflects the market, and is a reasonable compensation for a year of sexual slavery. $He accepts it after some consideration, and you transfer the money into an escrow account to be held for $him until $his new indenture is done. Your sex slave once again, $he awaits orders with complacency. - <<run cashX(forceNeg(_slaveCost), "slaveTransfer", $activeSlave)>> - <<set $lowerClass -= 1>> - <<set $expired = 0>><<set $expiree = 0>> - <<for $i = 0; $i < $slaves.length; $i++>> - <<if $slaves[$i].indenture == 0>> - <<set $expiree = $slaves[$i].ID>> - <<break>> - <</if>> - <</for>> - <</replace>> - <</link>> //This will cost <<print cashFormat(_slaveCost)>>// -<<else>> - //You cannot afford to do this// -<</if>> -</span> +<<elseif (getSlave($expiree).devotion >= -20) && (getSlave($expiree).trust > 20)>> + + $He approaches the moment with calculation, since $he has found more of a place in slavery than $he probably expected when $he became an indentured servant. + <<if !hasAnyLegs(getSlave($expiree))>> + Propped up + <<else>> + Standing before you + <</if>> + at the moment of $his scheduled emancipation, $he seems willing to consider a short term continuation of service. + + <p id="result"> + <<if $cash > _slaveCost>> + <<link "Offer $him a one year supplementary indenture">> + <<replace "#result">> + $He looks pensive when you offer $him a one year supplementary indenture. The price reflects the market, and is a reasonable compensation for a year of sexual slavery. $He accepts it after some consideration, and you transfer the money into an escrow account to be held for $him until $his new indenture is done. Your sex slave once again, $he awaits orders with complacency. + <<run cashX(forceNeg(_slaveCost), "slaveTransfer", getSlave($expiree))>> + <<set $lowerClass -= 1>> + <<set $expired = 0>><<set $expiree = 0>> + <<for $i = 0; $i < $slaves.length; $i++>> + <<if $slaves[$i].indenture == 0>> + <<set $expiree = $slaves[$i].ID>> + <<break>> + <</if>> + <</for>> + <</replace>> + <</link>> //This will cost <<print cashFormat(_slaveCost)>>// + <<else>> + //You cannot afford to do this// + <</if>> + </p> <<else>> $He makes no effort at all to conceal $his joy at being a free $woman again. - <<if $activeSlave.origin == "$He put $himself up as collateral at a poker game, and lost.">> + <<if getSlave($expiree).origin == "$He put $himself up as collateral at a poker game, and lost.">> A bet is a bet, but that was a lonnng year. There's still room for $him in your $mercenariesTitle, but many of them have come to see $him in a new, more... intimate way. As a free $woman, $he'll have to decide if it's worth the risk and the sex to stay here and fight for you who $he loathes... or else take up arms elsewhere in an ever more uncertain world. - <<if $activeSlave.addict > 5>> + <<if getSlave($expiree).addict > 5>> They'll need to make money fast as they remain addicted to your aphrodisiacs. <</if>> <<else>> @@ -200,7 +199,12 @@ at the moment of $his scheduled emancipation, $he seems willing to consider a sh <h3>Final notes?</h3> <div class="note"> <div class="indent"> - $His most recent task was to <<print $activeSlave.assignment>><<if $assignmentRecords[$activeSlave.ID]>>, and before that to <<print $assignmentRecords[$activeSlave.ID]>><</if>>. + $His most recent task was to + <<if $assignmentRecords[$expiree]>> + <<print getSlave($expiree).assignment>>, and before that to <<print $assignmentRecords[$expiree]>>. + <<else>> + <<print getSlave($expiree).assignment>>. + <</if>> </div> <<includeDOM slaveImpactLongTerm(V.activeSlave)>> </div> \ No newline at end of file diff --git a/src/uncategorized/seWeddingDouble.tw b/src/uncategorized/seWeddingDouble.tw index 1f3eb18132b511a688b2a3680510252b21897426..b0c69db8c83c1b5c747e9f89439afc027ca3e14a 100644 --- a/src/uncategorized/seWeddingDouble.tw +++ b/src/uncategorized/seWeddingDouble.tw @@ -1899,7 +1899,7 @@ <<set _slave1.relationship = -3>> <<run seX(_slave1, "oral", "public", "penetrative", 50)>> - <<if canDoAnal($activeSlave)>> + <<if canDoAnal(_slave1)>> <<run seX(_slave1, "anal", "public", "penetrative", 50)>> <</if>> <<if canGetPregnant(_slave1) && _slave1.eggType == "human">> diff --git a/src/uncategorized/slaveInteract.tw b/src/uncategorized/slaveInteract.tw index 7dad7290954ec125da9e206c081162f41e92c1aa..aea8b167fc824af6937dd5e2a7ee5102faea00a7 100644 --- a/src/uncategorized/slaveInteract.tw +++ b/src/uncategorized/slaveInteract.tw @@ -1,353 +1,5 @@ :: Slave Interact [nobr jump-from-safe] <<set $nextButton = "Confirm changes", $nextLink = "Main">> -<<set _SL = $slaves.length, _CL = $canines.length, _HL = $hooved.length, _FL = $felines.length>> -<<run App.Utils.setLocalPronouns(getSlave($AS))>> -<<run Enunciate(getSlave($AS))>> -<style> -.active { - background-color: grey; -} -</style> -<<run App.UI.tabBar.handlePreSelectedTab($tabChoice.SlaveInteract)>> - - -<<if !assignmentVisible(getSlave($AS))>> - <<switch getSlave($AS).assignment>> - <<case "work in the brothel" "be the Madam">> - <<set $nextLink = "Brothel">> - <<case "be confined in the arcade">> - <<set $nextLink = "Arcade">> - <<case "serve in the club" "be the DJ">> - <<set $nextLink = "Club">> - <<case "work in the dairy" "be the Milkmaid">> - <<set $nextLink = "Dairy">> - <<case "work as a farmhand" "be the Farmer">> - <<set $nextLink = "Farmyard">> - <<case "rest in the spa" "be the Attendant">> - <<set $nextLink = "Spa">> - <<case "work as a nanny" "be the Matron">> - <<set $nextLink = "Nursery">> - <<case "learn in the schoolroom" "be the Schoolteacher">> - <<set $nextLink = "Schoolroom">> - <<case "work as a servant" "be the Stewardess">> - <<set $nextLink = "Servants' Quarters">> - <<case "serve in the master suite" "be your Concubine">> - <<set $nextLink = "Master Suite">> - <<case "be confined in the cellblock" "be the Wardeness">> - <<set $nextLink = "Cellblock">> - <<case "get treatment in the clinic" "be the Nurse">> - <<set $nextLink = "Clinic">> - <<case "live with your Head Girl">> - <<set $nextLink = "Head Girl Suite">> - <<case "be your agent" "live with your agent">> - <<set $nextLink = "Neighbor Interact">> - <</switch>> -<</if>> - -<<set $encyclopedia = either("Costs Summary", "Disease in the Free Cities", "Drugs and Their Effects", "From Rebellious to Devoted", "Gender", "Independent Slaves", "Modern Anal", "Nymphomania", "Slave Couture")>> -<<if getSlave($AS).dick > 0>> - <<set $encyclopedia = "Gender">> -<</if>> - -<<includeDOM App.UI.SlaveInteract.navigation(getSlave($AS))>> - -<div class="tab-bar"> - <button class="tab-links" onclick="App.UI.tabBar.openTab(event, 'Description'), jQuery('#LSD').empty().append(App.Desc.longSlave(getSlave(V.AS)))" id="tab Description">Description</button> - <button class="tab-links" onclick="App.UI.tabBar.openTab(event, 'Modify')" id="tab Modify">Modify</button> - <button class="tab-links" onclick="App.UI.tabBar.openTab(event, 'Work')" id="tab Work">Work</button> - <button class="tab-links" onclick="App.UI.tabBar.openTab(event, 'Appearance'), App.UI.Wardrobe.refreshAll(getSlave(V.AS))" id="tab Appearance">Appearance</button> - <button class="tab-links" onclick="App.UI.tabBar.openTab(event, 'PhysicalRegimen')" id="tab PhysicalRegimen">Physical Regimen</button> - <button class="tab-links" onclick="App.UI.tabBar.openTab(event, 'Rules')" id="tab Rules">Rules</button> - <button class="tab-links" onclick="App.UI.tabBar.openTab(event, 'Financial')" id="tab Financial">Financial</button> - <button class="tab-links" onclick="App.UI.tabBar.openTab(event, 'Customize'), App.UI.SlaveInteract.custom(getSlave(V.AS))" id="tab Customize">Customize</button> - <button class="tab-links" onclick="App.UI.tabBar.openTab(event, 'family-tab'), renderFamilyTree(V.slaves, V.AS)" id="tab family-tab">Family</button> -</div> - -<div id="art-frame"> - <<if $seeImages == 1>> - <<if $imageChoice == 1>> - <div class="imageRef lrgVector"><div class="mask"> </div><<= SlaveArt(getSlave($AS), 3, 0)>></div> - <<else>> - <div class="imageRef lrgRender"><div class="mask"> </div><<= SlaveArt(getSlave($AS), 3, 0)>></div> - <</if>> - <</if>> -</div> - -<div id="Description" class="tab-content"> - <div class="content"> - <<if $seeDetails == 1>> - <div style="font-style:italic"> - <<link "Description Options">> - <<replace #hideOptionPages>> - <<link "(hide)">> - <<replace #hideOptionPages>> - <</replace>> - <<replace #optionPages>> - /* Hide */ - <</replace>> - <</link>> - <</replace>> - <<replace #optionPages>> - <<include "Description Options">> - <</replace>> - <</link>> - <span id="hideOptionPages"></span> - <p id="optionPages"></p> - </div> - <span id="LSD"></span> - <<else>> - <div style="font-style:italic"> - [[Show descriptions|Slave Interact][$seeDetails = 1]] - </div> - <</if>> - </div> -</div> - -<div id="Modify" class="tab-content"> - <div class="content"> - <p id="modifySection"></p> - <script> - jQuery('#modifySection').empty().append(App.UI.SlaveInteract.modify(getSlave(V.AS))) - </script> - </div> -</div> - - -<div id="Work" class="tab-content"> - <div class="content"> - <p id="work"></p> - <script> - App.UI.SlaveInteract.work(getSlave(V.AS)) - </script> - </div> -</div> - -<div id="Appearance" class="tab-content"> - <div class="content"> - <p> - <span id="clothes"></span> - /*<script>App.UI.Wardrobe.clothes(getSlave(V.AS))</script>*/ - - <<if getSlave($AS).fuckdoll == 0>> - <span id="collar"></span> - /*<script>App.UI.Wardrobe.collar(getSlave(V.AS))</script>*/ - - <span id="faceAccessory"></span> - - <span id="mouthAccessory"></span> - - <span id="armAccessory"></span> - /*<script>App.UI.Wardrobe.armAccessory(getSlave(V.AS))</script>*/ - - <<if hasAnyLegs(getSlave($AS))>> - <span id="shoes"></span> - /*<script>App.UI.Wardrobe.shoes(getSlave(V.AS))</script>*/ - - <span id="legAccessory"></span> - /*<script>App.UI.Wardrobe.legAccessory(getSlave(V.AS))</script>*/ - <</if>> - - <span id="bellyAccessory"></span> - /*<script>App.UI.Wardrobe.bellyAccessory(getSlave(V.AS))</script>*/ - - <span id="buttplug"></span> - /*<script>App.UI.Wardrobe.buttplug(getSlave(V.AS))</script>*/ - - <<if isItemAccessible.entry("tail", "buttplugAttachment") && getSlave($AS).buttplug != "none">> - <span id="buttplugAttachment"></span> - /*<script>App.UI.Wardrobe.buttplugAttachment(getSlave(V.AS))</script>*/ - <</if>> - - <<if getSlave($AS).vagina > -1>> - <span id="vaginalAccessory"></span> - /*<script>App.UI.Wardrobe.vaginalAccessory(getSlave(V.AS))</script>*/ - <span id="vaginalAttachment"></span> - /*<script>App.UI.Wardrobe.vaginalAttachment(getSlave(V.AS))</script>*/ - <</if>> - - <<if getSlave($AS).dick > 0>> - <span id="dickAccessory"></span> - /*<script>App.UI.Wardrobe.dickAccessory(getSlave(V.AS))</script>*/ - <</if>> - - <span id="chastity"></span> - /*<script>App.UI.Wardrobe.chastity(getSlave(V.AS))</script>*/ - - <h3>Shopping</h3> - <span id="shopping"></span> - <script>App.UI.Wardrobe.shopping(getSlave(V.AS))</script> - - <</if>> /* CLOSES FUCKDOLL CHECK */ - </p> - </div> -</div> - -<div id="PhysicalRegimen" class="tab-content"> - <div class="content"> - <p> - <span id="drugs"></span> - <script>App.UI.SlaveInteract.drugs(getSlave(V.AS))</script> - - <span id="curatives"></span> - <script>App.UI.SlaveInteract.curatives(getSlave(V.AS))</script> - - <span id="aphrodisiacs"></span> - <script>App.UI.SlaveInteract.aphrodisiacs(getSlave(V.AS))</script> - - <span id="fertility-block"></span> - <script>App.UI.SlaveInteract.fertility(getSlave(V.AS))</script> - - <span id="incubator"></span> - <script>App.UI.SlaveInteract.incubator(getSlave(V.AS))</script> - - <span id="nursery"></span> - <script>App.UI.SlaveInteract.nursery(getSlave(V.AS))</script> - - <<if $propOutcome == 1 && $arcologies[0].FSRestart != "unset">> - <<if getSlave($AS).breedingMark == 0 && getSlave($AS).fuckdoll == 0 && getSlave($AS).eggType == "human" && isFertile(getSlave($AS)) && getSlave($AS).preg == 0>> - <br> - [[Breeder Eligibility Exam|BreedingTest]] - <</if>> - <</if>> - - <span id="bloating"></span> - <script>App.UI.SlaveInteract.bloating(getSlave(V.AS))</script> - - <span id="hormones"></span> - <script>App.UI.SlaveInteract.hormones(getSlave(V.AS))</script> - - <span id="diet"></span> - <script>App.UI.SlaveInteract.diet(getSlave(V.AS))</script> - - <span id="diet-base"></span> - <script>App.UI.SlaveInteract.dietBase(getSlave(V.AS))</script> - - <span id="snacks"></span> - <script>App.UI.SlaveInteract.snacks(getSlave(V.AS))</script> - </p> - </div> -</div> - -<div id="Rules" class="tab-content"> - <div class="content"> - <span id="rules"></span> - <script>App.UI.SlaveInteract.rules(getSlave(V.AS))</script> - </div> -</div> - -<div id="Financial" class="tab-content"> - <div class="content"> - - <<if $studio == 1>> - <h3>Media</h3> - <<if getSlave($AS).porn.prestige == 3>> - //$He is so prestigious in the realm of <<= getSlave($AS).porn.fameType>> porn that $his fame is self-sustaining.// - <<elseif getSlave($AS).porn.feed == 0>> - The media hub is not releasing highlights of $his sex life. [[Release|Slave Interact][getSlave($AS).porn.feed = 1]] - <<else>> - The media hub is releasing highlights of $his sex life <<if getSlave($AS).porn.spending < 500>>to those who can find it<<elseif getSlave($AS).porn.spending < 2500>>on several websites<<elseif getSlave($AS).porn.spending > 5000>>through your old distributor<<else>>on many websites<</if>>. - <<if getSlave($AS).porn.spending == 0>> - [[Halt|Slave Interact][getSlave($AS).porn.feed = 0, getSlave($AS).porn.focus = "none"]] | - [[Publicize|Slave Interact][getSlave($AS).porn.spending += 1000]] - //Will cost <<print cashFormat(1000)>> weekly.// - <<else>> - <<textbox "_newPornSpending" $slaves[$slaveIndices[$AS]].porn.spending>> weekly is spent to publicize them. [[Save changes|Slave Interact][getSlave($AS).porn.spending = Number(_newPornSpending) || 0]] | - [[Halt|Slave Interact][getSlave($AS).porn.feed = 0, getSlave($AS).porn.spending = 0, getSlave($AS).porn.focus = "none", $PCSlutContacts = 1]] | - <<if getSlave($AS).porn.spending < 5000>> - [[Increase|Slave Interact][getSlave($AS).porn.spending += 1000]] | - <</if>> - [[Decrease|Slave Interact][getSlave($AS).porn.spending -= 1000]] - <<if getSlave($AS).porn.spending > 5000>><<set _warn = 1>><</if>> - <<set getSlave($AS).porn.spending = Number(getSlave($AS).porn.spending) || 0>> - <<set getSlave($AS).porn.spending = Math.clamp(Math.ceil(getSlave($AS).porn.spending/1000)*1000, 0, 5000)>> - <<if _warn>><br>//Spending more than <<print cashFormat(5000)>> weekly will have no effect.//<</if>> - <<if $PC.career == "escort">> - <br> - You retain some contacts from your past life in the industry that may be willing to cut you some discounts should you return to it. - <<if $PCSlutContacts != 2>> - You are not baring your body for all to see. - [[Star in porn for a discount|Slave Interact][$PCSlutContacts = 2]] - <<else>> - You are starring in hardcore porn once more. - [[Stop doing porn for a discount|Slave Interact][$PCSlutContacts = 1]] - <</if>> - <</if>> - <</if>> - - <<if $studioFeed == 1>> - <br> - <<if getSlave($AS).porn.viewerCount < 100>> - $He lacks the fame in porn needed to discern what $his feed is getting tagged as. - <<else>> - <<if getSlave($AS).porn.prestige > 0>> - $He is known for <<= getSlave($AS).porn.fameType>> porn<<if getSlave($AS).porn.prestige > 1>> and viewers have grown to expect it from $him<</if>>. - <</if>> - <<if getSlave($AS).porn.focus == "none">> - You are allowing $his viewers to guide the direction of $his content. - <<else>> - You are focusing attention on the <<= getSlave($AS).porn.focus>> aspect of $his content. - <</if>> - <<includeDOM App.Porn.genreChoiceLinks("Slave Interact", getSlave($AS))>> - <</if>> - <</if>> - <</if>> - <</if>> - - <h3>Financial</h3> - <p> - <<includeDOM slaveExpenses(getSlave(V.AS))>> - </p> - - <p> - <<if ($slaveCostFactor > 1)>> - <span class="yellow">The slave market is bullish; the price of slaves is high.</span> - <<elseif ($slaveCostFactor < 1)>> - <span class="yellow">The slave market is bearish; the price of slaves is low.</span> - <</if>> - - <<if (_SL > 1)>> - <<if getSlave($AS).origin == "You bought $him from a body dump, completely broken." && ($week-getSlave($AS).weekAcquired <= 8)>> - //A discarded slave must be kept for at least two months to ensure health before being sold.// | - <<elseif getSlave($AS).accent > 3>> - //$His lack of language and basic life skills is a red sign to most slave appraisers. $He must not act like a child to be sold without raising suspicion.// | - <<else>> - <<link "Sell $him" "Sell Slave">><<run cashX(-500, "personalBusiness", getSlave($AS))>><</link>> //Listing $him for sale will cost <<print cashFormat(500)>>// | - <<if ($seeAge != 0) && (getSlave($AS).indenture < 1)>> - <<link "Retire $him" "SE retirement">><<set $retiree = getSlave($AS).ID, $retired = 1>><</link>> | - <</if>> - <</if>> - <<link "Discard $him" "Discard Confirm">><</link>> - <<if $seeExtreme == 1 && $arcologies[0].FSPaternalist == "unset">> - | <<link "Threaten $his life" "KillSlave">><</link>> - <</if>> - <<else>> - //You cannot sell or discard your last slave.// - <</if>> - - | <<link "Export this slave" "Export Slave">><</link>> - <<if $cheatMode>> - | <<link "Import a slave" "Import Slave">><</link>> - <</if>> - </p> - </div> -</div> - -<div id="Customize" class="tab-content"> - <div class="content"> - <span id="custom"></span> - <script>App.UI.SlaveInteract.custom(getSlave(V.AS))</script> - - /*<<include "Add custom descriptors">>*/ - </div> -</div> - -<div id="family-tab" class="tab-content"> - <div class="content"> - <p id="family"> - <div id="family-tree"></div> - <span id="family-tree-link"></span> - </p> - </div> -</div> +<<includeDOM App.UI.SlaveInteract.mainPage(getSlave(V.AS))>> diff --git a/src/uncategorized/subordinateTargeting.tw b/src/uncategorized/subordinateTargeting.tw index 8927368a2298d284ec0db504e4ebe2456bf7c606..edbf8d558fbe58d75c9c7ea0ba59ac106e50fcdf 100644 --- a/src/uncategorized/subordinateTargeting.tw +++ b/src/uncategorized/subordinateTargeting.tw @@ -1,41 +1,42 @@ :: Subordinate Targeting [nobr] -<<set $nextButton = "Back", $nextLink = "AS Dump">> +<<set $nextButton = "Back", $nextLink = "Slave Interact">> -<<run App.Utils.setLocalPronouns($activeSlave)>> +<<run App.Utils.setLocalPronouns(getSlave($AS))>> -<<if $activeSlave.subTarget == $activeSlave.ID>> - <<set $activeSlave.subTarget = 0>> -<<elseif $activeSlave.subTarget == -1>> - <<if $universalRulesImpregnation != "Stud" || $activeSlave.ID != $StudID>> - <<set $activeSlave.subTarget = 0>> +<<if getSlave($AS).subTarget == getSlave($AS).ID>> + <<set getSlave($AS).subTarget = 0>> +<<elseif getSlave($AS).subTarget == -1>> + <<if $universalRulesImpregnation != "Stud" || getSlave($AS).ID != $StudID>> + <<set getSlave($AS).subTarget = 0>> <</if>> <</if>> -<<if $activeSlave.assignment !== "be a subordinate slave">> - <<= assignJob($activeSlave, "be a subordinate slave")>> +<<if getSlave($AS).assignment !== "be a subordinate slave">> + <<= assignJob(getSlave($AS), "be a subordinate slave")>> <</if>> -<<set _st = $slaveIndices[$activeSlave.subTarget]>> +<<set _st = $slaveIndices[getSlave($AS).subTarget]>> +<<= getSlave($AS).slaveName>> <<if def _st>> - $activeSlave.slaveName will submit to <span class='slave-name'>$slaves[_st].slaveName</span> this week. -<<elseif $activeSlave.subTarget == -1>> - $activeSlave.slaveName is acting as your Stud and is tasked with keeping your chattel pregnant. + will submit to <span class='slave-name'>$slaves[_st].slaveName</span> this week. +<<elseif getSlave($AS).subTarget == -1>> + is acting as your Stud and is tasked with keeping your chattel pregnant. <<else>> - $activeSlave.slaveName has not been given to any particular slave, so $he will have to offer $himself to everyone this week. - <<set $activeSlave.subTarget = 0>> + has not been given to any particular slave, so $he will have to offer $himself to everyone this week. + <<set getSlave($AS).subTarget = 0>> <</if>> -<<if $activeSlave.subTarget == -1>> - <br><br><<link "Reign $him in" "Subordinate Targeting">><<set $activeSlave.subTarget = 0, $StudID = 0>><</link>> +<<if getSlave($AS).subTarget == -1>> + <br><br><<link "Reign $him in" "Subordinate Targeting">><<set getSlave($AS).subTarget = 0, $StudID = 0>><</link>> <<else>> <<if $universalRulesImpregnation == "Stud" && $StudID == 0>> - <br><br>[[Stud|Subordinate Targeting][$activeSlave.subTarget = -1, $StudID = $activeSlave.ID]] + <br><br>[[Stud|Subordinate Targeting][getSlave($AS).subTarget = -1, $StudID = getSlave($AS).ID]] <</if>> - <br><br>[[None|Subordinate Targeting][$activeSlave.subTarget = 0]] + <br><br>[[None|Subordinate Targeting][getSlave($AS).subTarget = 0]] <br><br>__Select a slave for $him to submit to, sexually:__ <<includeDOM App.UI.SlaveList.slaveSelectionList( - s => s.devotion >= -20 && s.fuckdoll === 0 && State.variables.activeSlave.ID !== s.ID && - (!isAmputee(State.variables.activeSlave) || !isAmputee(s)), - (s) => App.UI.DOM.passageLink(SlaveFullName(s), 'Subordinate Targeting', () => { V.activeSlave.subTarget = s.ID; }), + s => s.devotion >= -20 && s.fuckdoll === 0 && V.AS !== s.ID && + (!isAmputee(getSlave(V.AS)) || !isAmputee(s)), + (s) => App.UI.DOM.passageLink(SlaveFullName(s), 'Subordinate Targeting', () => { getSlave(V.AS).subTarget = s.ID; }), )>> <</if>> diff --git a/src/uncategorized/universalRules.tw b/src/uncategorized/universalRules.tw index a75d492863188a4f3231a86bb7261fc2f8cb6f6d..266afc96396f150d187fcc3073523f9d312363f8 100644 --- a/src/uncategorized/universalRules.tw +++ b/src/uncategorized/universalRules.tw @@ -202,18 +202,18 @@ One 'welcome' for a new slave is to have them branded. Where would you like such <br> It's possible that ''$brandTarget.primary'' may be missing from a slave. Choose a fallback in case it is not available: Current backup is ''$brandTarget.secondary'': /* Material copied from bodyModification, but please leave commented out any sections that may not be on ALL slaves. */ - /*<<if hasAnyEars($activeSlave)>>[[Ears|Universal Rules][$brandTarget.secondary = "ear"]]<</if>>*/ + /*<<if hasAnyEars(_slave)>>[[Ears|Universal Rules][$brandTarget.secondary = "ear"]]<</if>>*/ | [[Cheeks|Universal Rules][$brandTarget.secondary = "cheek"]] | [[Shoulders|Universal Rules][$brandTarget.secondary = "shoulder"]] | [[Breasts|Universal Rules][$brandTarget.secondary = "breast"]] - /*<<if hasAnyNaturalArms($activeSlave)>> + /*<<if hasAnyNaturalArms(_slave)>> | [[Arm, upper|Universal Rules][$brandTarget.secondary = "upper arm"]] | [[Arm, lower|Universal Rules][$brandTarget.secondary = "lower arm"]] | [[Wrist|Universal Rules][$brandTarget.secondary = "wrist"]] | [[Hand|Universal Rules][$brandTarget.secondary = "hand"]] <</if>>*/ | [[Buttocks|Universal Rules][$brandTarget.secondary = "buttock"]] - /*<<if hasAnyNaturalLegs($activeSlave)>> + /*<<if hasAnyNaturalLegs(_slave)>> | [[Thigh|Universal Rules][$brandTarget.secondary = "thigh"]] | [[Calf|Universal Rules][$brandTarget.secondary = "calf"]] | [[Ankle|Universal Rules][$brandTarget.secondary = "ankle"]] @@ -223,10 +223,10 @@ One 'welcome' for a new slave is to have them branded. Where would you like such | [[Chest|Universal Rules][$brandTarget.secondary = "chest"]] | [[Belly|Universal Rules][$brandTarget.secondary = "belly"]] | [[Pubic Mound|Universal Rules][$brandTarget.secondary = "pubic mound"]] - /*<<if $activeSlave.dick > 0>> + /*<<if _slave.dick > 0>> | [[Penis|Universal Rules][$brandTarget.secondary = "penis"]] <</if>>*/ - /*<<if $activeSlave.balls > 0 && $activeSlave.scrotum > 0>> + /*<<if _slave.balls > 0 && _slave.scrotum > 0>> | [[Testicles|Universal Rules][$brandTarget.secondary = "testicle"]] <</if>>*/ | [[Back|Universal Rules][$brandTarget.secondary = "back"]] @@ -453,18 +453,18 @@ One 'welcome' for a new slave is to have them scarred. Where would you like such <br> It's possible that ''$scarTarget.primary'' may be missing from a slave. Choose a fallback in case it is not available: Current backup is ''$scarTarget.secondary'': /* Material copied from bodyModification, but please leave commented out any sections that may not be on ALL slaves. */ - /*<<if hasAnyEars($activeSlave)>>[[Ears|Universal Rules][$scarTarget.secondary = "ear"]]<</if>>*/ + /*<<if hasAnyEars(_slave)>>[[Ears|Universal Rules][$scarTarget.secondary = "ear"]]<</if>>*/ | [[Cheeks|Universal Rules][$scarTarget.secondary = "cheek"]] | [[Shoulders|Universal Rules][$scarTarget.secondary = "shoulder"]] | [[Breasts|Universal Rules][$scarTarget.secondary = "breast"]] - /*<<if hasAnyNaturalArms($activeSlave)>> + /*<<if hasAnyNaturalArms(_slave)>> | [[Arm, upper|Universal Rules][$scarTarget.secondary = "upper arm"]] | [[Arm, lower|Universal Rules][$scarTarget.secondary = "lower arm"]] | [[Wrist|Universal Rules][$scarTarget.secondary = "wrist"]] | [[Hand|Universal Rules][$scarTarget.secondary = "hand"]] <</if>>*/ | [[Buttocks|Universal Rules][$scarTarget.secondary = "buttock"]] - /*<<if hasAnyNaturalLegs($activeSlave)>> + /*<<if hasAnyNaturalLegs(_slave)>> | [[Thigh|Universal Rules][$scarTarget.secondary = "thigh"]] | [[Calf|Universal Rules][$scarTarget.secondary = "calf"]] | [[Ankle|Universal Rules][$scarTarget.secondary = "ankle"]] @@ -474,10 +474,10 @@ One 'welcome' for a new slave is to have them scarred. Where would you like such | [[Chest|Universal Rules][$scarTarget.secondary = "chest"]] | [[Belly|Universal Rules][$scarTarget.secondary = "belly"]] | [[Pubic Mound|Universal Rules][$scarTarget.secondary = "pubic mound"]] - /*<<if $activeSlave.dick > 0>> + /*<<if _slave.dick > 0>> | [[Penis|Universal Rules][$scarTarget.secondary = "penis"]] <</if>>*/ - /*<<if $activeSlave.balls > 0 && $activeSlave.scrotum > 0>> + /*<<if _slave.balls > 0 && _slave.scrotum > 0>> | [[Testicles|Universal Rules][$scarTarget.secondary = "testicle"]] <</if>>*/ | [[Back|Universal Rules][$scarTarget.secondary = "back"]]