diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8064061a64772bfa2221f3e5c00909bf9d73e7b4..a5e6496aadbeea4378afc5930f5af8c965704b15 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,7 +6,7 @@ workflow: .official-releases: rules: - - if: $CI_COMMIT_TAG =~ /\A\d+\.\d+\.\d+\z/ + - if: $CI_COMMIT_TAG =~ /\A\d+\.\d+\.\d+/ stages: - build @@ -27,7 +27,7 @@ build: image: debian:latest rules: # official release - - if: $CI_COMMIT_TAG =~ /\A\d+\.\d+\.\d+\z/ + - if: $CI_COMMIT_TAG =~ /\A\d+\.\d+\.\d+/ # latest - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH script: diff --git a/CHANGELOG.md b/CHANGELOG.md index 297aa3daaaeb8012192a74750547a63e4ada0f20..e5957a7b35e7a4b796e76cc53d84b09881a7455c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,14 +6,28 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ## Unreleased +## 0.10.7.1-4.0.0-alpha.2 - 2021-05-23 + +* more fixes + +## 0.10.7.1-4.0.0.alpha.1 - 2021-05-22 + +* fixes + +## 0.10.7.1-4.0.0.alpha.0 - 2021-05-22 + +* Base 4.0.0 foundation added +* Age based player careers implemented (4.0.0) * Reminders system improvements * Elohiem's webgl art update 2 & 3 * added new hairstyles (bangs, hime, drills) * added slave distribution presets (PLC, Japan/Korea, Carribean) * heavy reconstruction of the event systems * REFI conversion complete +* Cheat mode and debug mode controls for event selection * fixes * RA UI tweaks +* tooltips now managed by Tippy ## 0.10.7.1-3.9.6 - 2021-04-02 diff --git a/css/facilities/spa.css b/css/facilities/spa.css new file mode 100644 index 0000000000000000000000000000000000000000..c336fa2e2b8761c8500cd2ed08ce40cdfe7f474b --- /dev/null +++ b/css/facilities/spa.css @@ -0,0 +1,8 @@ +.spa-intro, +.spa-expand, +.spa-upgrades, +.spa-attendant, +.spa-slaves, +.spa-rename { + margin-bottom: 1em; +} diff --git a/css/gui/encyclopedia.css b/css/gui/encyclopedia.css index 9cd84398b514dfad886a5eef12650c5f4a6fc474..6ca860782e9ad394ef990160b91611365cd6540e 100644 --- a/css/gui/encyclopedia.css +++ b/css/gui/encyclopedia.css @@ -1,3 +1,14 @@ .encyclopedia.topic { font-weight: bold; } + +/* mark text that is a link/button somewhere else */ +/* Click <span class="encyclopedia interaction">X</span> to do Y */ +.encyclopedia.interaction { + background: #203e6c; + border-radius: 5px; + border: hidden; + padding: 2px 4px; + white-space: nowrap; + font-size: smaller; +} diff --git a/devTools/types/FC/human.d.ts b/devTools/types/FC/human.d.ts index 543ac50e627e69136a716fbd9b564a83201eea33..02bf6beaabf8558641b5c2b85e46c1fbcf52f8dd 100644 --- a/devTools/types/FC/human.d.ts +++ b/devTools/types/FC/human.d.ts @@ -221,7 +221,26 @@ declare global { | "size queen">; type BreastShape = "normal" | "perky" | "saggy" | "torpedo-shaped" | "downward-facing" | "wide-set" | "spherical"; - type HairStyle = "afro"| "braided" | "cornrows" | "curled" | "dreadlocks" | "eary" | "bun" | "messy bun" | "ponytail" | "tails" | "drills" | "luxurious" | "messy" | "neat" | "permed" | "bangs" | "hime" | "strip" | "up" | "shaved" | "trimmed" | "buzzcut" | "bald" | "undercut"; + type Clothes = "a ball gown" | "a bimbo outfit" | "a biyelgee costume" | "a bra" | "a bunny outfit" | "a burkini" | + "a burqa" | "a button-up shirt" | "a button-up shirt and panties" | "a chattel habit" | "a cheerleader outfit" | "a comfortable bodysuit" | + "a courtesan dress" | "a cybersuit" | "a dirndl" | "a fallen nuns habit" | "a Fuckdoll suit" | "a gothic lolita dress" | "a halter top dress" | + "a hanbok" | "a hijab and abaya" | "a hijab and blouse" | "a huipil" | "a kimono" | "a klan robe" | "a latex catsuit" | "a leotard" | + "a long qipao" | "a maternity dress" | "a military uniform" | "a mini dress" | "a monokini" | "a mounty outfit" | "a nice maid outfit" | + "a nice nurse outfit" | "a nice pony outfit" | "a niqab and abaya" | "a one-piece swimsuit" | "a penitent nuns habit" | "a police uniform" | + "a red army uniform" | "a Santa dress" | "a scalemail bikini" | "a schoolgirl outfit" | "a schutzstaffel uniform" | "a skimpy loincloth" | + "a slave gown" | "a slutty klan robe" | "a slutty maid outfit" | "a slutty nurse outfit" | "a slutty outfit" | "a slutty pony outfit" | + "a slutty qipao" | "a slutty schutzstaffel uniform" | "a sports bra" | "a string bikini" | "a striped bra" | "a succubus outfit" | + "a sweater" | "a sweater and cutoffs" | "a sweater and panties" | "a t-shirt" | "a t-shirt and jeans" | "a t-shirt and panties" | + "a t-shirt and thong" | "a tank-top" | "a tank-top and panties" | "a thong" | "a toga" | "a tube top" | "a tube top and thong" | + "an apron" | "an oversized t-shirt" | "an oversized t-shirt and boyshorts" | "attractive lingerie" | "attractive lingerie for a pregnant woman" | + "battlearmor" | "Imperial Plate" | "a tight Imperial bodysuit" | "battledress" | "body oil" | "boyshorts" | "chains" | "choosing her own clothes" | + "clubslut netting" | "conservative clothing" | "cutoffs" | "cutoffs and a t-shirt" | "harem gauze" | "jeans" | "kitty lingerie" | + "leather pants" | "leather pants and a tube top" | "leather pants and pasties" | "lederhosen" | "nice business attire" | "no clothing" | + "overalls" | "panties" | "panties and pasties" | "pasties" | "restrictive latex" | "shibari ropes" | "slutty business attire" | + "slutty jewelry" | "spats and a tank top" | "sport shorts" | "sport shorts and a sports bra" | "sport shorts and a t-shirt" | + "stretch pants and a crop-top" | "striped panties" | "striped underwear" | "uncomfortable straps" | "Western clothing"; + type HairStyle = "afro"| "braided" | "cornrows" | "curled" | "dreadlocks" | "eary" | "bun" | "messy bun" | "ponytail" | "tails" | + "drills" | "luxurious" | "messy" | "neat" | "permed" | "bangs" | "hime" | "strip" | "up" | "shaved" | "trimmed" | "buzzcut" | "bald" | "undercut"; type Diet = "healthy" | "restricted" | "corrective" | "muscle building" | "fattening" | "slimming" | "XX" | "XY" | "XXY" | "cum production" | "cleansing" | "fertility" | "high caloric"; type Drug = "no drugs" | diff --git a/js/003-data/gameVariableData.js b/js/003-data/gameVariableData.js index e1cebc9bf31f26d2c27a825565e79546585b189a..ce97e37f3e67a773b31d9905e1e10191a265f0cd 100644 --- a/js/003-data/gameVariableData.js +++ b/js/003-data/gameVariableData.js @@ -76,6 +76,7 @@ App.Data.defaultGameStateVariables = { dangerousPregnancy: 0, debugMode: 0, debugModeCustomFunction: 0, + debugModeEventSelection: 0, difficultySwitch: 0, disableLisping: 0, displayAssignments: 1, diff --git a/js/003-data/policiesData.js b/js/003-data/policiesData.js index 1724e461df317c96bbeef91cca238254591a3cb2..de5939cdf8df054fbd2e8bba7992f21b8e101891 100644 --- a/js/003-data/policiesData.js +++ b/js/003-data/policiesData.js @@ -1127,7 +1127,7 @@ App.Data.Policies.Selection = { V.arcologies[0].FSSlimnessEnthusiastLaw === 0 && V.arcologies[0].FSHedonisticDecadenceLaw2 === 0 && V.arcologies[0].FSPhysicalIdealistLaw === 0 && - V.arcologies[0].FSGenderFundamentalist > 20 + V.arcologies[0].FSGenderRadicalist > 20 ); }, } diff --git a/player variables documentation - Pregmod.txt b/player variables documentation - Pregmod.txt index 1eddbc1385ad5c208599a727f86fa3316b49d45d..d8fd24f46feb390f6093293bbf6c92c4cb7be7fb 100644 --- a/player variables documentation - Pregmod.txt +++ b/player variables documentation - Pregmod.txt @@ -541,6 +541,21 @@ face: 100 +lips: + +lip size (0-100) +0 - 10 - thin +11 - 20 - normal +21 - 40 - pretty +41 - 70 - plush +71 - 95 - huge (lisps) +96 - 100- facepussy (mute) + +lipsImplant: + +how large her lip implants are +See .lips + reservedChildren: how many of your children will be added to the incubator diff --git a/src/002-config/fc-version.js b/src/002-config/fc-version.js index 5d0c318ff3484e04543706ca3428502ca6761555..2f2d540f2fbb6c4994a03913d1ca9485f34f296b 100644 --- a/src/002-config/fc-version.js +++ b/src/002-config/fc-version.js @@ -1,6 +1,6 @@ App.Version = { base: "0.10.7.1", // The vanilla version the mod is based off of, this should never be changed. - pmod: "3.9.6", + pmod: "4.0.0-alpha.0", commitHash: null, - release: 1128 // When getting close to 2000, please remove the check located within the onLoad() function defined at line five of src/js/eventHandlers.js. + release: 1130 // When getting close to 2000, please remove the check located within the onLoad() function defined at line five of src/js/eventHandlers.js. }; diff --git a/src/005-passages/facilitiesPassages.js b/src/005-passages/facilitiesPassages.js index d111733c1d5b89dd4af44a8c6951b9eacf8efe32..96780671218e4ceb7cc159aabcb00946d789fba6 100644 --- a/src/005-passages/facilitiesPassages.js +++ b/src/005-passages/facilitiesPassages.js @@ -1,8 +1,12 @@ /* ### Standard Facilities ### */ -new App.DomPassage("Pit", () => { return App.Facilities.Pit.pit(); }, ["jump-to-safe", "jump-from-safe"]); +new App.DomPassage("Farmyard", () => { return App.Facilities.Farmyard.farmyard(); }, ["jump-to-safe", "jump-from-safe"]); new App.DomPassage("Incubator", () => { return App.UI.incubator(); }, ["jump-to-safe", "jump-from-safe"]); +new App.DomPassage("Pit", () => { return App.Facilities.Pit.pit(); }, ["jump-to-safe", "jump-from-safe"]); + +new App.DomPassage("Spa", () => { return App.Facilities.Spa.spa(); }, ["jump-to-safe", "jump-from-safe"]); + /* ### Slave Interact Facilities ### */ new App.DomPassage("Wardrobe", () => { diff --git a/src/005-passages/interactPassages.js b/src/005-passages/interactPassages.js index cc3673cb1a6786656b20785e1ba7daa3e525d89e..bab037625e48943f339c9b1ee53441e3bbd2a919 100644 --- a/src/005-passages/interactPassages.js +++ b/src/005-passages/interactPassages.js @@ -161,47 +161,6 @@ new App.DomPassage("Aztec Slave Sacrifice Life", } ); -new App.DomPassage("fLips", - () => { - return App.Interact.fLips(getSlave(V.AS)); - } -); - -new App.DomPassage("fBoobs", - () => { - return App.Interact.fBoobs(getSlave(V.AS)); - } -); - -new App.DomPassage("fVagina", - () => { - return App.Interact.fVagina(getSlave(V.AS)); - } -); - -new App.DomPassage("fRival", - () => { - return App.Interact.fRival(getSlave(V.AS)); - } -); -new App.DomPassage("fButt", - () => { - return App.Interact.fButt(getSlave(V.AS)); - } -); - -new App.DomPassage("fDick", - () => { - return App.Interact.fDick(getSlave(V.AS)); - } -); - -new App.DomPassage("fAnus", - () => { - return App.Interact.fAnus(getSlave(V.AS)); - } -); - new App.DomPassage("Abort", () => { V.nextButton = "Back"; diff --git a/src/Mods/SecExp/events/attackReport.js b/src/Mods/SecExp/events/attackReport.js index f2d2e87c5e6d76e7fa9afaa76c479671e90f767a..c93b29fefbc491d5723231802623b767d282babb 100644 --- a/src/Mods/SecExp/events/attackReport.js +++ b/src/Mods/SecExp/events/attackReport.js @@ -1708,36 +1708,43 @@ App.Events.attackReport = function() { captives = Math.trunc(captives); if (captives > 0) { + let candidates = 0; r.push(`During the battle ${captives} attackers were captured.`); - /* - if (random(1,100) <= 25) { - roll = random(1,100); + if (random(1, 100) <= 25) { + candidates = 1; + const roll = random(1, 100); if (roll <= 33) { - r.push(`Three of them have the potential to be sex slaves.`); candidates = 3; - } else if (roll <= 66) { - r.push(`Two of them have the potential to be sex slaves.`); candidates = 2; - } else { - r.push(`One of them have the potential to be sex slaves.`); - candidates = 1; } + r.push(`${capFirstChar(num(candidates, true))} of them have the potential to be sex slaves.`); } - */ + const sell = function() { cashX((menialPrice * captives), "menialTransfer"); return `Captives sold`; }; const keep = function() { - V.menials += captives; - return `Captives added as menial slaves`; + V.menials += (captives - candidates); + for (let i = 0; i < candidates; i++) { + const generateFemale = random(0, 99) < V.seeDicks; + let slave = GenerateNewSlave((generateFemale ? "XY" : "XX"), {minAge: 16, maxAge: 32, disableDisability: 1}); + slave.weight = (generateFemale ? random(-20, 30) : random(0, 30)); + slave.muscles = (generateFemale ? random(15, 80) : random(25, 80)); + slave.waist = (generateFemale ? random(10, 80) : random(-20, 20)); + slave.skill.combat = 1; + const {He} = getPronouns(slave); + slave.origin = `${He} is an enslaved ${V.SecExp.war.attacker.type} soldier captured during a battle.`; + newSlave(slave); // skip New Slave Intro + } + return `All captives added as slaves.`; }; App.Events.addResponses(node, [ new App.Events.Result(`sell them all immediately`, sell), - new App.Events.Result(`sell them all immediately`, keep), + new App.Events.Result(`keep them as slaves`, keep), ]); } diff --git a/src/Mods/SecExp/js/secExp.js b/src/Mods/SecExp/js/secExp.js index be6f467b4c9e93574b4b590acb2393ee124793ed..00183102f1b2670ff4e3c92306462d83daadbdcc 100644 --- a/src/Mods/SecExp/js/secExp.js +++ b/src/Mods/SecExp/js/secExp.js @@ -351,9 +351,9 @@ App.SecExp.initTrade = function() { } else if (V.terrain === "ravine") { init -= jsRandom(5, 5); } - if (["BlackHat", "capitalist", "celebrity", "wealth"].includes(V.PC.career)) { + if (isPCCareerInCategory("wealth") || isPCCareerInCategory("capitalist") || isPCCareerInCategory("celebrity") || isPCCareerInCategory("BlackHat")) { init += jsRandom(5, 5); - } else if (["escort", "gang", "servant"].includes(V.PC.career)) { + } else if (isPCCareerInCategory("escort") || isPCCareerInCategory("gang") || isPCCareerInCategory("servant")) { init -= jsRandom(5, 5); } V.SecExp.core.trade = init; diff --git a/src/data/backwardsCompatibility/backwardsCompatibility.js b/src/data/backwardsCompatibility/backwardsCompatibility.js index a202550464b45fb8c33116926dcff1511fd35754..5973ea3894dc67824d18940dc36885124c14bb57 100644 --- a/src/data/backwardsCompatibility/backwardsCompatibility.js +++ b/src/data/backwardsCompatibility/backwardsCompatibility.js @@ -256,7 +256,7 @@ App.Update.globalVariables = function(node) { // PC { - PCDatatypeCleanup(); + PCDatatypeCleanup(V.PC); V.enduringTrust = Number(V.enduringTrust) || 0; V.enduringDevotion = Number(V.enduringDevotion) || 0; V.averageTrust = Number(V.averageTrust) || 0; diff --git a/src/data/backwardsCompatibility/datatypeCleanup.js b/src/data/backwardsCompatibility/datatypeCleanup.js index 8e934c7070f1ab93a54e1eb9dc44c38f18705254..f29bd8ed39c7b2301f3be2829b7afe074fdd92f5 100644 --- a/src/data/backwardsCompatibility/datatypeCleanup.js +++ b/src/data/backwardsCompatibility/datatypeCleanup.js @@ -579,7 +579,7 @@ globalThis.SlaveDatatypeCleanup = (function SlaveDatatypeCleanup() { slave.hLength = Math.clamp(+slave.hLength, 0, 300) || 60; } if (typeof slave.hStyle !== "string") { - slave.hStyle = "long"; + slave.hStyle = "neat"; } slave.haircuts = Math.clamp(+slave.haircuts, 0, 1) || 0; slave.bald = Math.clamp(+slave.bald, 0, 1) || 0; @@ -1200,194 +1200,485 @@ globalThis.SlaveDatatypeCleanup = (function SlaveDatatypeCleanup() { } })(); -/* Make sure any new PC variables put into use are added to this! */ -globalThis.PCDatatypeCleanup = function() { - const PC = V.PC; +/* See slave datatype cleanup for details */ +globalThis.PCDatatypeCleanup = (function PCDatatypeCleanup() { + "use strict"; - if (PC.title !== 0) { - PC.title = Math.clamp(+PC.title, 0, 1) || 1; - } - if (PC.dick !== 0) { - PC.dick = Math.clamp(+PC.dick, 0, 5) || 4; - } - if (PC.vagina !== -1) { - PC.vagina = Math.clamp(+PC.vagina, 0, 5) || 0; - } - if (typeof PC.genes !== "string") { - PC.genes = "XY"; - } - if (typeof PC.nationality !== "string") { - PC.nationality = "Stateless"; - } - if (typeof PC.race !== "string") { - PC.race = "white"; - } - if (typeof PC.skin !== "string") { - PC.skin = "light"; - } - if (typeof PC.markings !== "string") { - PC.markings = "none"; - } - if (typeof PC.hColor !== "string") { - PC.hColor = "blonde"; - } - if (typeof PC.eye.origColor !== "string") { - PC.eye.origColor = "blue"; - } - PC.belly = Math.max(+PC.belly, 0) || 0; - PC.fertPeak = Math.clamp(+PC.fertPeak, 0, 4) || 0; - PC.pregMood = Math.clamp(+PC.pregMood, 0, 2) || 0; - PC.boobs = Math.clamp(+PC.boobs, 100, 1500) || 100; - PC.boobsImplant = Math.clamp(+PC.boobsImplant, 0, 1000) || 0; - PC.butt = Math.clamp(+PC.butt, 0, 5) || 2; - PC.buttImplant = Math.clamp(+PC.buttImplant, 0, 5) || 0; - PC.balls = Math.clamp(+PC.balls, 0, 100) || 0; - PC.ballsImplant = Math.clamp(+PC.ballsImplant, 0, 100) || 0; - PC.prostate = Math.clamp(+PC.prostate, 0, 1) || 0; - PC.degeneracy = Math.max(+PC.degeneracy, 0) || 0; - PC.birthWeek = Math.clamp(+PC.birthWeek, 0, 51) || 0; - if (PC.sexualEnergy !== 0) { - PC.sexualEnergy = +PC.sexualEnergy || 4; - } - if (typeof PC.refreshment !== "string") { - PC.refreshment = "cigar"; + return PCDatatypeCleanup; + + /** + * @param {App.Entity.PlayerState} PC + */ + function PCDatatypeCleanup(PC) { + PCAgeDatatypeCleanup(PC); + PCPhysicalDatatypeCleanup(PC); + PCFaceDatatypeCleanup(PC); + PCHairDatatypeCleanup(PC); + PCBoobsDatatypeCleanup(PC); + PCButtDatatypeCleanup(PC); + PCPregnancyDatatypeCleanup(PC); + PCBellyDatatypeCleanup(PC); + PCGenitaliaDatatypeCleanup(PC); + PCImplantsDatatypeCleanup(PC); + PCCosmeticsDatatypeCleanup(PC); + PCDietDatatypeCleanup(PC); + PCRelationDatatypeCleanup(PC); + PCSkillsDatatypeCleanup(PC); + PCStatCountDatatypeCleanup(PC); + PCPreferencesDatatypeCleanup(PC); + PCRulesDatatypeCleanup(PC); + PCCustomStatsDatatypeCleanup(PC); + PCMiscellaneousDatatypeCleanup(PC); + App.Entity.Utils.migratePronouns(PC); + generatePlayerPronouns(PC); } - if (!(V.ver.startsWith("0.10"))) { - if (V.PC.refreshment === "cigar") { - V.PC.refreshmentType = 0; + + /** + * @param {App.Entity.PlayerState} PC + */ + function PCAgeDatatypeCleanup(PC) { + if (PC.birthWeek > 51) { + PC.birthWeek = PC.birthWeek % 52; + } + PC.birthWeek = Math.clamp(+PC.birthWeek, 0, 51) || 0; + if (PC.age > 0) { + PC.actualAge = Math.clamp(+PC.actualAge, 10, 80) || PC.age; /* if undefined, this sets to PC.age */ + delete PC.age; } else { - V.PC.refreshmentType = 1; - } - } - PC.refreshmentType = Math.clamp(+PC.refreshmentType, 0, 6) || 0; - PC.skill.trading = Math.clamp(+PC.skill.trading, -100, 100) || 0; - PC.skill.warfare = Math.clamp(+PC.skill.warfare, -100, 100) || 0; - PC.skill.slaving = Math.clamp(+PC.skill.slaving, -100, 100) || 0; - PC.skill.engineering = Math.clamp(+PC.skill.engineering, -100, 100) || 0; - PC.skill.medicine = Math.clamp(+PC.skill.medicine, -100, 100) || 0; - PC.skill.hacking = Math.clamp(+PC.skill.hacking, -100, 100) || 0; - PC.skill.cumTap = Math.max(+PC.skill.cumTap, 0) || 0; - PC.mother = +PC.mother || 0; - PC.father = +PC.father || 0; - PC.labor = Math.clamp(+PC.labor, 0, 1) || 0; - PC.counter.birthsTotal = Math.max(+PC.counter.birthsTotal, 0) || 0; - PC.counter.birthElite = Math.max(+PC.counter.birthElite, 0) || 0; - PC.counter.birthMaster = Math.max(+PC.counter.birthMaster, 0) || 0; - PC.counter.birthDegenerate = Math.max(+PC.counter.birthDegenerate, 0) || 0; - PC.counter.birthClient = Math.max(+PC.counter.birthClient, 0) || 0; - PC.counter.birthOther = Math.max(+PC.counter.birthOther, 0) || 0; - PC.counter.birthArcOwner = Math.max(+PC.counter.birthArcOwner, 0) || 0; - PC.counter.birthCitizen = Math.max(+PC.counter.birthCitizen, 0) || 0; - PC.counter.birthSelf = Math.max(+PC.counter.birthSelf, 0) || 0; - PC.counter.birthLab = Math.max(+PC.counter.birthLab, 0) || 0; - PC.counter.birthFutaSis = Math.max(+PC.counter.birthFutaSis, 0) || 0; - PC.counter.slavesFathered = Math.max(+PC.counter.slavesFathered, 0) || 0; - PC.counter.slavesKnockedUp = Math.max(+PC.counter.slavesKnockedUp, 0) || 0; - PC.counter.storedCum = Math.max(+PC.counter.storedCum, 0) || 0; - PC.intelligence = 100; - PC.face = 100; - PC.actualAge = Math.clamp(+PC.actualAge, 14, 80) || 35; - PC.physicalAge = Math.clamp(+PC.physicalAge, 14, 80) || PC.actualAge; - PC.visualAge = Math.clamp(+PC.visualAge, 14, 80) || PC.actualAge; - PC.ovaryAge = Math.clamp(+PC.ovaryAge, 14, 80) || PC.physicalAge; - if (V.playerAging !== 0) { - V.playerAging = Math.clamp(+V.playerAging, 0, 2) || 2; - } - PC.newVag = Math.clamp(+PC.newVag, 0, 1) || 0; - PC.fertDrugs = Math.clamp(+PC.fertDrugs, 0, 1) || 0; - PC.forcedFertDrugs = Math.max(+PC.forcedFertDrugs, 0) || 0; - PC.staminaPills = Math.clamp(+PC.staminaPills, 0, 1) || 0; - PC.mpreg = 0; /* So knockMeUp() may be used with the PC */ - PC.lactation = Math.max(+PC.lactation, 0) || 0; - PC.lactationDuration = Math.max(+PC.lactationDuration, 0) || 0; - PC.muscles = Math.clamp(+PC.muscles, -100, 100) || 50; - PC.hLength = Math.clamp(+PC.hLength, 0, 150) || 2; - PC.voice = Math.clamp(+PC.voice, 1, 3) || 1; - if (typeof PC.health === "number") { - const condition = PC.health; - PC.health = {}; - PC.health.condition = condition; - } - PC.health.condition = Math.clamp(PC.health.condition, -100, 100) || 0; - if (PC.majorInjury !== undefined) { - if (PC.majorInjury > 0) { - PC.health.shortDamage = Math.max(PC.majorInjury * 20, 30); + PC.actualAge = Math.clamp(+PC.actualAge, 10, Infinity) || 35; + } + PC.physicalAge = Math.clamp(+PC.physicalAge, 14, 80) || PC.actualAge; + PC.visualAge = Math.clamp(+PC.visualAge, 14, 80) || PC.actualAge; + PC.ovaryAge = Math.clamp(+PC.ovaryAge, 14, 80) || PC.physicalAge; + if (V.playerAging !== 0) { + V.playerAging = Math.clamp(+V.playerAging, 0, 2) || 2; + } + PC.pubertyAgeXX = Math.max(+PC.pubertyAgeXX, 0) || 13; + PC.pubertyAgeXY = Math.max(+PC.pubertyAgeXY, 0) || 13; + if (typeof PC.health === "number") { + const condition = PC.health; + PC.health = {}; + PC.health.condition = condition; + } + PC.health.condition = Math.clamp(PC.health.condition, -100, 100) || 0; + if (PC.majorInjury !== undefined) { + if (PC.majorInjury > 0) { + PC.health.shortDamage = Math.max(PC.majorInjury * 20, 30); + } else { + PC.health.shortDamage = 0; + } + delete PC.majorInjury; } else { - PC.health.shortDamage = 0; + PC.health.shortDamage = Math.max(+PC.health.shortDamage, 0) || 0; } - delete PC.majorInjury; - } else { + PC.health.longDamage = Math.max(+PC.health.longDamage, 0) || 0; + PC.health.illness = Math.max(+PC.health.illness, 0) || 0; + PC.health.tired = Math.clamp(+PC.health.tired, 0, 100) || 0; + PC.health.health = Math.clamp(PC.health.condition - PC.health.shortDamage - PC.health.longDamage, -100, 100) || 0; + } + + /** + * @param {App.Entity.PlayerState} PC + */ + function PCPhysicalDatatypeCleanup(PC) { + if (PC.title !== 0) { + PC.title = Math.clamp(+PC.title, 0, 1) || 1; + } + if (typeof PC.genes !== "string") { + PC.genes = "XY"; + } + if (typeof PC.nationality !== "string") { + PC.nationality = "Stateless"; + } + if (typeof PC.race !== "string") { + PC.race = "white"; + } + if (typeof PC.origRace !== "string") { + PC.origRace = PC.race; + } + if (typeof PC.skin !== "string") { + PC.skin = "light"; + } + if (typeof PC.origSkin !== "string") { + PC.origSkin = PC.skin; + } + + // why is this duplicated? + PC.health.condition = Math.clamp(PC.health.condition, -100, 200) || 0; PC.health.shortDamage = Math.max(+PC.health.shortDamage, 0) || 0; + PC.health.longDamage = Math.max(+PC.health.longDamage, 0) || 0; + PC.health.illness = Math.max(+PC.health.illness, 0) || 0; + PC.health.tired = Math.clamp(+PC.health.tired, 0, 100) || 0; + PC.health.health = Math.clamp(PC.health.condition - PC.health.shortDamage - PC.health.longDamage, -100, 100) || 0; + + PC.muscles = Math.clamp(+PC.muscles, -100, 100) || 0; + PC.weight = Math.clamp(+PC.weight, -100, 200) || 0; + PC.waist = Math.clamp(+PC.waist, -100, 100) || 0; + PC.height = Math.round(Math.max(+PC.height, 0)) || Math.round(Height.mean(PC)); + PC.shoulders = Math.clamp(+PC.shoulders, -2, 2) || 0; + PC.hips = Math.clamp(+PC.hips, -2, 3) || 0; } - PC.health.longDamage = Math.max(+PC.health.longDamage, 0) || 0; - PC.health.illness = Math.max(+PC.health.illness, 0) || 0; - PC.health.tired = Math.clamp(+PC.health.tired, 0, 100) || 0; - PC.health.health = Math.clamp(PC.health.condition - PC.health.shortDamage - PC.health.longDamage, -100, 100) || 0; - if (typeof PC.rules.living !== "string") { - PC.rules.living = "normal"; + + /** + * @param {App.Entity.PlayerState} PC + */ + function PCFaceDatatypeCleanup(PC) { + if (typeof PC.eye.origColor !== "string") { + PC.eye.origColor = "blue"; + } + PC.face = 100; + if (PC.lips !== 0) { + PC.lips = Math.clamp(+PC.lips, 0, 100) || 15; + } } - if (typeof PC.rules.lactation !== "string") { - PC.rules.lactation = "none"; + + /** + * @param {App.Entity.PlayerState} PC + */ + function PCHairDatatypeCleanup(PC) { + if (typeof PC.hColor !== "string") { + PC.hColor = "blonde"; + } + if (typeof PC.origHColor !== "string") { + PC.origHColor = PC.hColor; + } + if (PC.hLength !== 0) { + PC.hLength = Math.clamp(+PC.hLength, 0, 300) || 2; + } + if (typeof PC.hStyle !== "string") { + PC.hStyle = "neat"; + } + if (typeof PC.pubicHColor !== "string") { + PC.pubicHColor = PC.hColor; + } + if (typeof PC.pubicHStyle !== "string") { + PC.pubicHStyle = "hairless"; + } + if (typeof PC.underArmHColor !== "string") { + PC.underArmHColor = PC.hColor; + } + if (typeof PC.underArmHStyle !== "string") { + PC.underArmHStyle = "hairless"; + } + if (typeof PC.eyebrowHColor !== "string") { + PC.eyebrowHColor = PC.hColor; + } + if (typeof PC.eyebrowHStyle !== "string") { + PC.eyebrowHStyle = "natural"; + } + if (typeof PC.eyebrowFullness !== "string") { + PC.eyebrowFullness = "natural"; + } } - if (typeof PC.rules.rest !== "string") { - PC.rules.rest = "permissive"; + + /** + * @param {App.Entity.PlayerState} PC + */ + function PCBoobsDatatypeCleanup(PC) { + PC.boobs = Math.max(+PC.boobs, 200) || 200; + if (typeof PC.boobShape !== "string") { + PC.boobShape = "normal"; + } + if (PC.boobShape === "spherical" && PC.boobsImplant === 0) { + PC.boobShape = "normal"; + } + if (typeof PC.nipples !== "string") { + PC.nipples = "tiny"; + } + PC.areolae = Math.clamp(+PC.areolae, 0, 4) || 0; + PC.lactation = Math.max(+PC.lactation, 0) || 0; + PC.lactationDuration = Math.max(+PC.lactationDuration, 0) || 0; + if (PC.boobsMilk > 0 && PC.boobs - PC.boobsMilk - PC.boobsImplant < 0) { + // should never get here, but if it does, just immediately abort! + PC.boobsMilk = 0; + } + PC.lactationAdaptation = Math.clamp(+PC.lactationAdaptation, 0, 100) || 0; } - App.Entity.Utils.migratePronouns(PC); - generatePlayerPronouns(PC); - if (PC.age !== undefined) { - delete PC.age; + /** + * @param {App.Entity.PlayerState} PC + */ + function PCButtDatatypeCleanup(PC) { + if (PC.butt !== 0) { + PC.butt = Math.clamp(+PC.butt, 0, 20) || 2; + } + PC.anus = Math.clamp(+PC.anus, 0, 4) || 0; + PC.analArea = Math.max(+PC.analArea, 0) || 0; } - if (PC.indenture !== undefined) { - delete PC.indenture; + + /** + * @param {App.Entity.PlayerState} PC + */ + function PCPregnancyDatatypeCleanup(PC) { + PC.induce = Math.clamp(+PC.induce, 0, 1) || 0; + PC.labor = Math.clamp(+PC.labor, 0, 1) || 0; + PC.prematureBirth = Math.clamp(+PC.prematureBirth, 0, 1) || 0; + PC.ovaries = Math.clamp(+PC.ovaries, 0, 1) || 0; + PC.vasectomy = Math.clamp(+PC.vasectomy, 0, 1) || 0; + PC.mpreg = Math.clamp(+PC.mpreg, 0, 1) || 0; + if (PC.pregAdaptation !== 0) { + PC.pregAdaptation = Math.max(+PC.pregAdaptation, 0) || 50; + } + if (PC.pubertyXX === 0 && (PC.ovaries > 0 || PC.mpreg > 0) && PC.preg === -1) { + PC.preg = 0; // no contraceptives for prepubescent slaves + } + PC.fertPeak = Math.clamp(+PC.fertPeak, 0, 4) || 0; + PC.pregSource = +PC.pregSource || 0; + PC.pregMood = Math.clamp(+PC.pregMood, 0, 2) || 0; + PC.fertDrugs = Math.clamp(+PC.fertDrugs, 0, 1) || 0; + PC.forcedFertDrugs = Math.max(+PC.forcedFertDrugs, 0) || 0; + WombNormalizePreg(PC); } - if (PC.indentureRestrictions !== undefined) { - delete PC.indentureRestrictions; + + /** + * @param {App.Entity.PlayerState} PC + */ + function PCBellyDatatypeCleanup(PC) { + PC.inflation = Math.clamp(+PC.inflation, 0, 3) || 0; + if (typeof PC.inflationType !== "string") { + PC.inflationType = "none"; + } + PC.inflationMethod = Math.clamp(+PC.inflationMethod, 0, 3) || 0; + PC.milkSource = Math.max(+PC.milkSource, 0) || 0; + PC.cumSource = Math.max(+PC.cumSource, 0) || 0; + if (PC.bellyImplant !== 0) { + PC.bellyImplant = Math.max(+PC.bellyImplant, -1) || -1; + } + PC.cervixImplant = Math.clamp(+PC.cervixImplant, 0, 3) || 0; + PC.bellySag = Math.max(+PC.bellySag, 0) || 0; + PC.bellySagPreg = Math.max(+PC.bellySagPreg, 0) || PC.bellySag; + PC.bellyPain = Math.clamp(+PC.bellyPain, 0, 2) || 0; + SetBellySize(PC); } - if (PC.boobsImplant > 0) { - // update with 4.0.0 - PC.boobsImplantType = "normal"; - } else { - PC.boobsImplantType = "none"; + + /** + * @param {App.Entity.PlayerState} PC + */ + function PCGenitaliaDatatypeCleanup(PC) { + PC.newVag = Math.clamp(+PC.newVag, 0, 1) || 0; + if (PC.vagina !== -1) { + PC.vagina = Math.clamp(+PC.vagina, 0, 10) || 1; + } + PC.vaginaLube = Math.clamp(+PC.vaginaLube, 0, 2) || 0; + PC.labia = Math.clamp(+PC.labia, 0, 3) || 0; + PC.clit = Math.clamp(+PC.clit, 0, 5) || 0; + PC.foreskin = Math.max(+PC.foreskin, 0) || 0; + if (PC.dick !== 0) { + PC.dick = Math.max(+PC.dick, 1) || 4; + PC.prostate = Math.clamp(+PC.prostate, 0, 1) || 1; + PC.balls = Math.max(+PC.balls, 0) || 3; + } else { + PC.prostate = Math.clamp(+PC.prostate, 0, 1) || 0; + PC.balls = Math.max(+PC.balls, 0) || 0; + } + if (PC.scrotum !== 0) { + PC.scrotum = Math.max(+PC.scrotum, 0) || PC.balls; + } } - if (PC.buttImplant > 0) { - PC.buttImplantType = "normal"; - } else { - PC.buttImplantType = "none"; + + /** + * @param {App.Entity.PlayerState} PC + */ + function PCImplantsDatatypeCleanup(PC) { + PC.ageImplant = Math.clamp(+PC.ageImplant, 0, 1) || 0; + PC.faceImplant = Math.clamp(+PC.faceImplant, 0, 100) || 0; + PC.lipsImplant = Math.clamp(+PC.lipsImplant, 0, 100) || 0; + PC.voiceImplant = Math.clamp(+PC.voiceImplant, -1, 1) || 0; + PC.boobsImplant = Math.clamp(+PC.boobsImplant, 0, PC.boobs) || 0; + if (PC.boobsImplant === 0) { + PC.boobsImplantType = "none"; + } else if (PC.boobsImplant > 0 && PC.boobsImplantType === "none") { + if (PC.boobsImplant > 10000) { + PC.boobsImplantType = "hyper fillable"; + } else if (PC.boobsImplant > 2200) { + PC.boobsImplantType = "advanced fillable"; + } else if (PC.boobsImplant > 1000) { + PC.boobsImplantType = "fillable"; + } else { + PC.boobsImplantType = "normal"; + } + } + PC.breastMesh = Math.clamp(+PC.breastMesh, 0, 1) || 0; + PC.buttImplant = Math.clamp(+PC.buttImplant, 0, Math.min(PC.butt, 20)) || 0; + if (typeof PC.buttImplantType !== "string") { + if (PC.buttImplant === 0) { + PC.buttImplantType = "none"; + } else if (PC.buttImplant > 0) { + PC.buttImplantType = "normal"; + } + } + PC.heightImplant = Math.clamp(+PC.heightImplant, -10, 10) || 0; + PC.earImplant = Math.clamp(+PC.earImplant, 0, 1) || 0; + PC.shouldersImplant = Math.clamp(+PC.shouldersImplant, -10, 10) || 0; + PC.hipsImplant = Math.clamp(+PC.hipsImplant, -10, 10) || 0; + PC.ballsImplant = Math.clamp(+PC.ballsImplant, 0, 100) || 0; } - if (V.PC.customTitle === "") { - V.PC.customTitle = undefined; - V.PC.customTitleLisp = undefined; + + /** + * @param {App.Entity.PlayerState} PC + */ + function PCCosmeticsDatatypeCleanup(PC) { + if (typeof PC.clothes !== "string") { + PC.clothes = "nice business attire"; + } + if (typeof PC.eyewear !== "string") { + PC.eyewear = "none"; + } + if (typeof PC.markings !== "string") { + PC.markings = "none"; + } } - if (typeof V.PC.counter.oral === "undefined") { - V.PC.counter.oral = 0; + + /** + * @param {App.Entity.PlayerState} PC + */ + function PCDietDatatypeCleanup(PC) { + if (typeof PC.refreshment !== "string") { + PC.refreshment = "cigar"; + } + if (!(V.ver.startsWith("0.10"))) { + if (PC.refreshment === "cigar") { + PC.refreshmentType = 0; + } else { + PC.refreshmentType = 1; + } + } + PC.refreshmentType = Math.clamp(+PC.refreshmentType, 0, 6) || 0; + if (typeof PC.diet !== "string") { + PC.diet = "healthy"; + } + PC.hormones = Math.clamp(+PC.hormones, -2, 2) || 0; + PC.hormoneBalance = Math.clamp(+PC.hormoneBalance, -500, 500) || 0; + if (typeof PC.drugs !== "string") { + PC.drugs = "no drugs"; + } + PC.aphrodisiacs = Math.clamp(+PC.aphrodisiacs, -1, 2) || 0; + PC.staminaPills = Math.clamp(+PC.staminaPills, 0, 1) || 0; } - if (typeof V.PC.counter.vaginal === "undefined") { - V.PC.counter.vaginal = 0; + + /** + * @param {App.Entity.PlayerState} PC + */ + function PCRelationDatatypeCleanup(PC) { + PC.mother = +PC.mother || 0; + PC.father = +PC.father || 0; } - if (typeof V.PC.counter.anal === "undefined") { - V.PC.counter.anal = 0; + + /** + * @param {App.Entity.PlayerState} PC + */ + function PCSkillsDatatypeCleanup(PC) { + PC.skill.trading = Math.clamp(+PC.skill.trading, -100, 100) || 0; + PC.skill.warfare = Math.clamp(+PC.skill.warfare, -100, 100) || 0; + PC.skill.slaving = Math.clamp(+PC.skill.slaving, -100, 100) || 0; + PC.skill.engineering = Math.clamp(+PC.skill.engineering, -100, 100) || 0; + PC.skill.medicine = Math.clamp(+PC.skill.medicine, -100, 100) || 0; + PC.skill.hacking = Math.clamp(+PC.skill.hacking, -100, 100) || 0; + PC.skill.cumTap = Math.max(+PC.skill.cumTap, 0) || 0; } - if (typeof V.PC.counter.mammary === "undefined") { - V.PC.counter.mammary = 0; + + /** + * @param {App.Entity.PlayerState} PC + */ + function PCStatCountDatatypeCleanup(PC) { + PC.counter.oral = Math.max(+PC.counter.oral, 0) || 0; + PC.counter.vaginal = Math.max(+PC.counter.vaginal, 0) || 0; + PC.counter.anal = Math.max(+PC.counter.anal, 0) || 0; + PC.counter.mammary = Math.max(+PC.counter.mammary, 0) || 0; + PC.counter.penetrative = Math.max(+PC.counter.penetrative, 0) || 0; + PC.counter.milk = Math.max(+PC.counter.milk, 0) || 0; + PC.counter.cum = Math.max(+PC.counter.cum, 0) || 0; + PC.counter.birthsTotal = Math.max(+PC.counter.birthsTotal, 0) || 0; + PC.counter.birthElite = Math.max(+PC.counter.birthElite, 0) || 0; + PC.counter.birthMaster = Math.max(+PC.counter.birthMaster, 0) || 0; + PC.counter.birthDegenerate = Math.max(+PC.counter.birthDegenerate, 0) || 0; + PC.counter.birthClient = Math.max(+PC.counter.birthClient, 0) || 0; + PC.counter.birthOther = Math.max(+PC.counter.birthOther, 0) || 0; + PC.counter.birthArcOwner = Math.max(+PC.counter.birthArcOwner, 0) || 0; + PC.counter.birthCitizen = Math.max(+PC.counter.birthCitizen, 0) || 0; + PC.counter.birthSelf = Math.max(+PC.counter.birthSelf, 0) || 0; + PC.counter.birthLab = Math.max(+PC.counter.birthLab, 0) || 0; + PC.counter.birthFutaSis = Math.max(+PC.counter.birthFutaSis, 0) || 0; + PC.counter.abortions = Math.max(+PC.counter.abortions, 0) || 0; + PC.counter.miscarriages = Math.max(+PC.counter.miscarriages, 0) || 0; + PC.counter.slavesFathered = Math.max(+PC.counter.slavesFathered, 0) || 0; + PC.counter.slavesKnockedUp = Math.max(+PC.counter.slavesKnockedUp, 0) || 0; + PC.counter.storedCum = Math.max(+PC.counter.storedCum, 0) || 0; + PC.bodySwap = Math.max(+PC.bodySwap, 0) || 0; } - if (typeof V.PC.counter.penetrative === "undefined") { - V.PC.counter.penetrative = 0; + + /** + * @param {App.Entity.PlayerState} PC + */ + function PCPreferencesDatatypeCleanup(PC) { + if (PC.sexualEnergy !== 0) { + PC.sexualEnergy = +PC.sexualEnergy || 4; + } + PC.energy = Math.clamp(+PC.energy, 0, 100) || 80; + PC.need = Math.max(+PC.need, 0) || 0; + PC.degeneracy = Math.max(+PC.degeneracy, 0) || 0; } - WombInit(V.PC); - if (typeof V.PC.ID === "undefined") { - V.PC.ID = -1; + + /** + * @param {App.Entity.PlayerState} PC + */ + function PCRulesDatatypeCleanup(PC) { + if (typeof PC.rules.living !== "string") { + PC.rules.living = "normal"; + } + if (typeof PC.rules.lactation !== "string") { + PC.rules.lactation = "none"; + } + if (typeof PC.rules.rest !== "string") { + PC.rules.rest = "permissive"; + } } - if (typeof V.PC.partners !== "object") { - V.PC.partners = new Set(); + + /** + * @param {App.Entity.PlayerState} PC + */ + function PCCustomStatsDatatypeCleanup(PC) { + if (PC.customTitle === "") { + PC.customTitle = undefined; + PC.customTitleLisp = undefined; + } } - /* None of these are in use */ - PC.bellyPreg = PC.belly; - PC.ageImplant = 0; - PC.voiceImplant = 0; - PC.accent = 0; -}; + /** + * @param {App.Entity.PlayerState} PC + */ + function PCMiscellaneousDatatypeCleanup(PC) { + if (typeof PC.ID === "undefined") { + PC.ID = -1; + } + PC.chem = Math.max(+PC.chem, 0) || 0; + PC.addict = Math.max(+PC.addict, 0) || 0; + PC.intelligence = 100; + PC.intelligenceImplant = Math.clamp(+PC.intelligenceImplant, -15, 30) || 30; + PC.hears = Math.clamp(+PC.hears, -2, 0) || 0; + PC.smells = Math.clamp(+PC.smells, -1, 0) || 0; + PC.tastes = Math.clamp(+PC.tastes, -1, 0) || 0; + PC.PLimb = Math.clamp(+PC.PLimb, 0, 2) || 0; + if (PC.voice !== 0) { + PC.voice = Math.clamp(+PC.voice, 0, 3) || 1; + } + PC.electrolarynx = Math.clamp(+PC.electrolarynx, 0, 1) || 0; + if (typeof PC.origBodyOwner !== "string") { + PC.origBodyOwner = ""; + } + PC.origBodyOwnerID = Math.max(+PC.origBodyOwnerID, 0) || 0; + if (PC.indenture !== undefined) { + delete PC.indenture; + } + if (PC.indentureRestrictions !== undefined) { + delete PC.indentureRestrictions; + } + if (typeof PC.partners !== "object") { + PC.partners = new Set(); + } + PC.accent = 0; // Might not use? Would be related to changing languages. Might not work out. + } +})(); globalThis.EconomyDatatypeCleanup = function() { V.AProsperityCap = Math.max(+V.AProsperityCap, 0) || 0; @@ -2295,10 +2586,6 @@ App.Entity.Utils.PCCheatCleanup = function() { V.PC.pregWeek = 0; } - if (V.PC.boobs < 300) { - V.PC.boobs = 100; - V.PC.boobsImplant = 0; - } if (V.PC.boobsImplant > V.PC.boobs) { V.PC.boobsImplant = V.PC.boobs; } @@ -2330,7 +2617,7 @@ App.Entity.Utils.PCCheatCleanup = function() { } ibc.recalculate_coeff_id(-1); - PCDatatypeCleanup(); + PCDatatypeCleanup(V.PC); V.upgradeMultiplierArcology = upgradeMultiplier('engineering'); V.upgradeMultiplierMedicine = upgradeMultiplier('medicine'); V.upgradeMultiplierTrade = upgradeMultiplier('trading'); diff --git a/src/endWeek/nextWeek/nextWeek.js b/src/endWeek/nextWeek/nextWeek.js index a9926dd3060bea79f6ed066009f08a6f5e15228f..fe29fa942a6840f5e1ca0b0bb399aaac1bb0af8a 100644 --- a/src/endWeek/nextWeek/nextWeek.js +++ b/src/endWeek/nextWeek/nextWeek.js @@ -37,6 +37,9 @@ App.EndWeek.nextWeek = function() { } else if (V.PC.fertPeak !== 0) { V.PC.fertPeak = 0; } + if (V.PC.health.shortDamage > 0) { + V.PC.health.shortDamage--; + } // Adding random changes to the economy if (V.difficultySwitch === 1) { diff --git a/src/endWeek/saSocialEffects.js b/src/endWeek/saSocialEffects.js index a912b739f2be87e32fa1883c74e5123a83073dc9..105927457cb6151899aaae7b7412b2eabf48c6cd 100644 --- a/src/endWeek/saSocialEffects.js +++ b/src/endWeek/saSocialEffects.js @@ -333,7 +333,7 @@ App.SlaveAssignment.saSocialEffects = function(slave) { V.failedElite += (5 + slave.pregType); } } - if (slave.balls > 0 && slave.pubertyXY === 1 && slave.vasectomy === 0) { + if (slave.balls > 0 && slave.pubertyXY === 1 && slave.vasectomy === 0 && slave.ballType !== "sterile") { t.push(new SocialEffect("Eugenics", -slave.balls, "Working testicles", `Society <span class="red">disapproves</span> of ${his} working testicles.`)); } else if (slave.dick > 0 && slave.balls > 0 && slave.vasectomy === 1) { @@ -520,6 +520,9 @@ App.SlaveAssignment.saSocialEffects = function(slave) { } else if ([Job.HEADGIRL, Job.ATTENDANT, Job.FARMER, Job.MADAM, Job.MATRON, Job.NURSE, Job.TEACHER, Job.STEWARD, Job.BODYGUARD].includes(slave.assignment)) { t.push(new SocialEffect("Intellectual Dependency", 0, `Intelligence required by job`, `Society understands the value of intelligence in ${his} appointed position and is willing to overlook it.`)); + } else if ([Job.ARCADE, Job.GLORYHOLE].includes(slave.assignment) && (slave.intelligence + slave.intelligenceImplant > 10)) { + t.push(new SocialEffect("Intellectual Dependency", 1, `Smart Fuckmeat`, + `Society finds it <span class="green">amusing</span> to see a smart slave being reduced to nothing but a set of holes; ${his} intelligence will not bore anyone here.`)); } else if ((slave.intelligence + slave.intelligenceImplant > 10)) { t.push(new SocialEffect("Intellectual Dependency", -1, `Too smart`, `Society <span class="red">disapproves</span> of ${slave.slaveName}'s sharp mind; this holds back acceptance of the idea that slaves should be dumb and dependent.`)); @@ -527,6 +530,9 @@ App.SlaveAssignment.saSocialEffects = function(slave) { if (slave.energy > 95) { t.push(new SocialEffect("Intellectual Dependency", 1, `Nymphomania`, `Society <span class="green">approves</span> of ${slave.slaveName}'s bottomless lust, showing the public one more way a slave may be reliant on ${his} owner.`)); + } else if ([Job.ARCADE, Job.GLORYHOLE].includes(slave.assignment) && (slave.energy <= 60)) { + t.push(new SocialEffect("Intellectual Dependency", 0, `Low Libido Fuckmeat`, + `Society doesn't notice ${slave.slaveName}'s low libido when ${he}'s reduced to nothing more than a fuckhole.`)); } else if ((slave.energy <= 60)) { t.push(new SocialEffect("Intellectual Dependency", -1, `Low libido`, `Society <span class="red">disapproves</span> of ${slave.slaveName}'s restrained libido; to the public, this gives ${him} too much freedom to focus on things other than sex.`)); @@ -674,9 +680,15 @@ App.SlaveAssignment.saSocialEffects = function(slave) { `Society <span class="green">approves</span> of your owning a Fuckdoll.`)); transformed += 5; // total transformation } - if (transformed === 0) { + if (transformed === 0 && [Job.ARCADE, Job.GLORYHOLE].includes(slave.assignment)) { + t.push(new SocialEffect("Transformation Fetishist", -1, `Totally unmodified fuckmeat`, + `Society <span class="red">would prefer</span> ${slave.slaveName}'s body to be a little more interesting but agrees that a simple fuckhole probably doesn't deserve much investment.`)); + } else if (transformed === 0) { t.push(new SocialEffect("Transformation Fetishist", -2, `Totally unmodified`, `Society <span class="red">strongly disapproves</span> of ${slave.slaveName}'s complete lack of any obvious transformations; ${he} does not advance the ideal of body modification.`)); + } else if (transformed === 1 && [Job.ARCADE, Job.GLORYHOLE].includes(slave.assignment)) { + t.push(new SocialEffect("Transformation Fetishist", 0, `Slightly modified fuckmeat`, + `Society accepts the minimal amount of modification ${slave.slaveName} has undergone; it's not a smart investment improving a lowly fuckhole's appearance, after all.`)); } else if (transformed === 1) { t.push(new SocialEffect("Transformation Fetishist", -1, `Too few modifications`, `Society <span class="red">disapproves</span> of ${slave.slaveName}'s mostly-natural appearance; more transformations would help advance the ideal of body modification.`)); @@ -742,7 +754,10 @@ App.SlaveAssignment.saSocialEffects = function(slave) { `Society <span class="green">approves</span> of ${his} expanded lips.`)); assets++; } - if (assets === 0) { + if (assets === 0 && [Job.ARCADE, Job.GLORYHOLE].includes(slave.assignment)) { + t.push(new SocialEffect("Asset Expansionist", 0, `Unexceptional fuckmeat`, + `Society is not thrilled about ${his} small assets but accepts ${his} role as a mere fuckhole; of course it would be better if ${he} were spilling out of the unit, but why waste the money on a worthless slab of fuckmeat?`)); + } else if (assets === 0) { t.push(new SocialEffect("Asset Expansionist", -1, `Unexceptional assets`, `Society <span class="red">is disappointed</span> by ${his} normal-sized (or even petite, by expansionist standards) assets.`)); } diff --git a/src/events/PE/concubineInterview.js b/src/events/PE/concubineInterview.js index 7676299c764d35e00de154b85a529415b02075ee..e19fae7bf0df0bb99a49463ca9e40224e429aee3 100644 --- a/src/events/PE/concubineInterview.js +++ b/src/events/PE/concubineInterview.js @@ -305,9 +305,9 @@ App.Events.PEConcubineInterview = class PEConcubineInterview extends App.Events. case "Imperial Plate": t.push(`ultra-heavy armor.`); break; - case "a skirt": - t.push(`dress.`); - break; + // case "skirt" //FIXME: skirts are not a thing apparently + // t.push(`dress.`); + // break; case "a mounty outfit": case "a police uniform": t.push(`uniform.`); diff --git a/src/events/RE/reBusyMasterSuite.js b/src/events/RE/reBusyMasterSuite.js new file mode 100644 index 0000000000000000000000000000000000000000..b8019a831df03e8d91c6a4a72f0c0bc164147389 --- /dev/null +++ b/src/events/RE/reBusyMasterSuite.js @@ -0,0 +1,332 @@ +App.Events.REBusyMasterSuite = class REBusyMasterSuite extends App.Events.BaseEvent { + eventPrerequisites() { + return [ + () => V.ConcubineID !== 0 + ]; + } + + actorPrerequisites() { + const req = [ + s => s.fuckdoll === 0, + s => s.assignment === Job.MASTERSUITE, + s => ( + (canDoAnal(s) && s.anus > 0) || + (canDoVaginal(s) && s.vagina > 0) + ), + ]; + + return [ // Need at least three actors. Grab more later. + req, + req, + req, + ]; + } + + execute(node) { + const msSlaves = V.slaves.filter((s) => s.fuckdoll === 0 && s.assignment === Job.MASTERSUITE) + .map((s) => { + /** @type {Array<FC.SlaveActs|"none">} */ + let options = []; + if (canDoAnal(s) && s.anus > 0) { + options.push("anal"); + } + if (canDoVaginal(s) && s.vagina > 0) { + options.push("vaginal"); + } + if (options.length === 0) { + options.push("none"); + } + return {slave: s, mode: options.pluck()}; + }); + const [participants, nonparticipants] = _.partition(msSlaves, s => s.mode !== "none"); + const bottomSlave = participants.first().slave; + let r = []; + + const { + He, + he, his, him, himself + } = getPronouns(S.Concubine); + + const { + his2, him2, he2 + } = getPronouns(bottomSlave).appendSuffix("2"); + + r.push(`You have an extended meeting with a prominent citizen planned, from the start of business in the morning until you're done. That's likely to be in the late evening, since he's probably going to get into technical business proposals, and ${S.Concubine.slaveName} knows it. ${He} is surprised, therefore, when a minor business emergency calls your would-be interlocutor away, canceling the meeting and sending you home hours earlier than you'd planned. ${He}`); + if (canTalk(S.Concubine)) { + r.push(`giggles helplessly`); + } else { + r.push(`signs humorously`); + } + r.push(`at the surprise when you walk into your suite. Apparently, ${he} decided to while away the hours until you got back by having some truly grandiose group sex with all the slaves you have in the suite.`); + + App.Events.addParagraph(node, r); + r = []; + + r.push(`${He} had to turn to greet you as you entered, since ${he} was facing away from the entry, and the reason why is rather obvious. Up near the opposite wall, ${bottomSlave.slaveName} is on the floor with ${his2} face down and ${his2} ass up.`); + + App.Events.addParagraph(node, r); + + /** helper function for train...identify the hole being penetrated by the next slave + * @param {App.Entity.SlaveState} slave + * @param {FC.SlaveActs} mode + */ + function hole(slave, mode) { + if (mode === "vaginal") { + if (slave.vagina > 2) { + return "loose pussy"; + } else if (slave.vagina > 1) { + return "pussy"; + } else { + return "tight pussy"; + } + } else if (mode === "anal") { + if (slave.anus > 2) { + return "asspussy"; + } else if (slave.anus > 1) { + return "asshole"; + } else { + return "tight butt"; + } + } + } + + /** helper function for train...identify the tool being used by the next slave to penetrate this slave + * @param {App.Entity.SlaveState} slave + * @param {FC.SlaveActs} mode + * @param {App.Entity.SlaveState} nextSlave + */ + function penetrator(slave, mode, nextSlave) { + let t = ``; + if (canPenetrate(nextSlave)) { + t += nextSlave.slaveName + "'s "; + if (nextSlave.dick > 3) { + t += "painfully big"; + } else { + t = "hard"; + } + t += " dick"; + } else { + t += "a "; + const size = (mode === "vaginal" ? slave.vagina : slave.anus); + if (size > 2) { + t += "huge"; + } else if (size > 1) { + t += "big"; + } else { + t += "moderate"; + } + t += " strap-on worn by " + nextSlave.slaveName; + } + return t; + } + + App.Events.addParagraph(node, [ + /* build the train from all participating slaves */ + participants.reduce((acc, cur, i, arr) => { + let r = ``; + const {mode, slave} = cur; + if (mode === "none") { + throw new Error("Non-participating slave is participating"); // impossible, but needed for typechecking + } + const nextSlave = (i + 1 >= arr.length) ? S.Concubine : arr[i + 1].slave; + + if (i === 0) { + return r; /* bottom slave already accounted for */ + } else if (i !== arr.length - 1) { + /* middle slaves */ + r += `${slave.slaveName}'s ${hole(slave, mode)} is filled by ${penetrator(slave, mode, nextSlave)}, `; + if (nextSlave.belly >= 150000) { + r += `whose middle is so obscenely distended that ${slave.slaveName} is struggling to support it.`; + } else if (nextSlave.belly >= 10000 || nextSlave.weight >= 160) { + r += `whose middle is resting on ${slave.slaveName}'s ${slave.skin} back.`; + } else if (nextSlave.boobs > 10000) { + r += `whose tits are so unreasonably large they're resting on ${slave.slaveName}'s ${slave.skin} back.`; + } else if (slave.butt > 4) { + r += `well cushioned by ${slave.slaveName}'s huge ass.`; + } else if (nextSlave.nipples === "huge") { + r += `who is bending to rub ${getPronouns(nextSlave).his} enormous hard nipples across ${slave.slaveName}'s ${slave.skin} back.`; + } else if (nextSlave.lips > 40) { + r += `who is bending forward to nibble along ${slave.slaveName}'s ${slave.skin} neck.`; + } else if (hasAnyArms(nextSlave)) { + r += `who is reaching around to grope ${slave.slaveName}'s ${slave.skin} chest.`; + } else { + r += `who is propped up against ${slave.slaveName}'s ${slave.skin} butt.`; + } + } else { + /* top slave */ + r += `Finally, ${slave.slaveName}'s ${hole(slave, mode)} is filled by ${penetrator(slave, mode, nextSlave)}, who has paused ${his} thrusting to issue a preemptory order to the slaves to stay where they are, before turning to greet you cheerfully.`; + } + seX(nextSlave, "penetrative", slave, mode, 1); + return acc + ` ` + r; + }, ``) + ]); + /* and now describe what the non-participating slaves are doing */ + if (nonparticipants.length > 0) { + App.Events.addParagraph(node, [ + `${toSentence(nonparticipants.map((s) => s.slave.slaveName))} can't participate in the train, so ${S.Concubine.slaveName} has them busy lying under the slaves who are, offering what oral stimulation they can manage.` + ]); + for (const s of nonparticipants) { + actX(s.slave, "oral"); + } + } + + const top = participants.last(); + + /** @type {FC.SlaveActs|"none"} */ + let concubineMode = "none"; + let concubineHole; + if (canDoAnal(S.Concubine) && S.Concubine.anus > 0) { + concubineMode = "anal"; + if (S.Concubine.anus > 2) { + concubineHole = "loose anus"; + } else if (S.Concubine.anus > 1) { + concubineHole = "asshole"; + } else { + concubineHole = "tight little asshole"; + } + } else if (canDoVaginal(S.Concubine) && S.Concubine.vagina > 0) { + concubineMode = "vaginal"; + if (S.Concubine.vagina > 2) { + concubineHole = "loose pussy"; + } else if (S.Concubine.vagina > 1) { + concubineHole = "pussy"; + } else { + concubineHole = "tight little pussy"; + } + } + + const responses = []; + if (concubineMode !== "none") { + responses.push(new App.Events.Result("Slide in behind the concubine for some action", behindConcubine)); + } + responses.push(new App.Events.Result("Slide in up at the head of the bed for some oral", bedHead)); + App.Events.addResponses(node, responses); + + function behindConcubine() { + const frag = document.createDocumentFragment(); + const r = []; + r.push(`${S.Concubine.slaveName} anticipates you, and is already sliding ${himself} partway out of ${top.slave.slaveName} and cocking ${his} hips to spread ${his}`); + if (S.Concubine.butt > 15) { + r.push(`immeasurable`); + } else if (S.Concubine.butt > 10) { + r.push(`expansive`); + } else if (S.Concubine.butt > 7) { + r.push(`enormous`); + } else if (S.Concubine.butt > 5) { + r.push(`huge`); + } else if (S.Concubine.butt > 2) { + r.push(`healthy`); + } else { + r.push(`trim`); + } + r.push(`buttocks as wide as ${he} can without disentangling ${himself} from the sex train. Up on the bed ${he}'s at just the right height, and ${he} winks ${his} ${concubineHole}`); + if (canTalk(S.Concubine)) { + r.push(`invitingly, laughing at the sheer decadence of it.`); + } else { + r.push(`invitingly.`); + } + + if (V.PC.dick === 0) { + r.push(`You pull on a strap-on and push it`); + } else { + r.push(`You push yourself`); + } + r.push(`home with some force, your concubine's extreme state of arousal leaving ${his} ass very relaxed and welcoming; the thrust shoves ${him} forward to hilt ${himself} in ${top.slave.slaveName}, and so on down the line, producing more giggling, some squealing, and much scrabbling for balance. It takes a while to find the rhythm, and while you wait for the inevitable tangles to be fixed you decide to challenge yourself. You reach around and`); + if (S.Concubine.boobs > 10000) { + r.push(`sink your hands into ${S.Concubine.slaveName}'s massive boobs,`); + } else if (S.Concubine.boobs > 1000) { + r.push(`heft ${S.Concubine.slaveName}'s heavy boobs,`); + } else if (S.Concubine.boobs > 300) { + r.push(`tease ${S.Concubine.slaveName}'s healthy breasts,`); + } else { + r.push(`massage ${S.Concubine.slaveName}'s flat chest,`); + } + r.push(`nibbling ${his} ${S.Concubine.skin} neck, and generally torturing ${him} with stimulation until ${he} climaxes to ${his} beloved ${getWrittenTitle(S.Concubine)}. When ${he} does, you extract yourself and pull ${him} unceremoniously off ${top.slave.slaveName}, replacing ${him} in ${top.slave.slaveName}'s`); + + if (top.mode === "anal") { + r.push(`butt.`); + } else { + r.push(`pussy.`); + } + r.push(`You work your way down the line, orgasm by orgasm, delaying your own climax until the exhausted ${bottomSlave.slaveName} manages yet another orgasm by heroic efforts, and you're done. As you roll off ${him2}, panting, there is scattered applause and much congratulation from your harem of <span class="trust inc">trusting slaves.</span>`); + S.Concubine.trust += 5; + if (concubineMode !== "none") { + seX(V.PC, "penetrative", S.Concubine, concubineMode); + } + for (const s of msSlaves) { + s.slave.trust += 1; + if (s.mode !== "none") { + seX(V.PC, "penetrative", s.slave, s.mode); + } + } + if (canImpreg(bottomSlave, V.PC)) { + knockMeUp(bottomSlave, 10, 1, V.PC.ID); + } + + App.Events.addParagraph(frag, r); + return frag; + } + + function bedHead() { + const frag = document.createDocumentFragment(); + const r = []; + r.push(`${bottomSlave.slaveName}'s ${App.Desc.eyesColor(bottomSlave)} widen when you push ${him2} upright for a moment and slide in under ${him2}, but ${he2} wraps ${his2}`); + if (bottomSlave.lips > 95) { + r.push(`facepussy`); + } else if (bottomSlave.lips > 70) { + r.push(`dick sucking lips`); + } else if (bottomSlave.lips > 20) { + r.push(`pretty lips`); + } else { + r.push(`lips`); + } + r.push(`around your`); + if (V.PC.dick === 0) { + r.push(`clit`); + } else { + r.push(`cock`); + if (V.PC.vagina !== -1) { + r.push(`and starts stroking your pussy`); + } + } + r.push(`eagerly enough, even as ${msSlaves[1].slave.slaveName} goes back to fucking ${him2}. The sex train is fairly gentle, since anything too fast would disintegrate the gymnastic arrangement, but ${bottomSlave.slaveName} is still getting enough stimulation that ${he2} whimpers quietly into your`); + if (V.PC.vagina !== -1) { + r.push(`pussy,`); + } else { + r.push(`dick,`); + } + r.push(`a nice feeling. The blowjob is`); + if (bottomSlave.skill.oral >= 100) { + r.push(`masterful, despite the distraction,`); + } else if (bottomSlave.skill.oral > 10) { + r.push(`serviceable, despite the distraction,`); + } else { + r.push(`only mediocre, but serviceable enough,`); + } + r.push(`so you let ${him2} work for a while before gently shoving ${him2} off the side of the bed and telling ${him2} to get to the back of the line. The slaves all shuffle forward awkwardly, and inadvertently block your view so that you hear rather than see ${bottomSlave.slaveName} start groping your concubine ${S.Concubine.slaveName}'s`); + if (S.Concubine.butt > 15) { + r.push(`immeasurable`); + } else if (S.Concubine.butt > 10) { + r.push(`expansive`); + } else if (S.Concubine.butt > 7) { + r.push(`enormous`); + } else if (S.Concubine.butt > 5) { + r.push(`huge`); + } else if (S.Concubine.butt > 2) { + r.push(`healthy`); + } else { + r.push(`trim`); + } + r.push(`ass down near the foot of the bed. You climax, on occasion, but are enjoying yourself so immensely that you let the slaves continue the rotation until you're entirely spent, and they're entirely exhausted. You reach for a tablet to get some work done, in the center of a pile of sweaty, tired slaves, all of whom are resting with at least one body part in contact with their <span class="devotion inc">beloved</span> ${properMaster()}.`); + S.Concubine.devotion += 5; + seX(V.PC, "penetrative", S.Concubine, "oral"); + for (const s of msSlaves) { + s.slave.devotion += 1; + seX(V.PC, "penetrative", s.slave, "oral", 2); + } + + App.Events.addParagraph(frag, r); + return frag; + } + } +}; diff --git a/src/events/RE/reNickname.js b/src/events/RE/reNickname.js index 8dff51b9311c1d3b6a97121de148d83e9a51fa46..cbf2cc4f0eb5842e52337cbf2a21159f264d938d 100644 --- a/src/events/RE/reNickname.js +++ b/src/events/RE/reNickname.js @@ -335,10 +335,10 @@ App.Events.RENickname = class RENickname extends App.Events.BaseEvent { const r = []; const {nicknameArray, situationDesc, applyDesc, notApplyDesc} = _this.data(slave, seed); let nickname = either(...nicknameArray); - const catEl = App.UI.DOM.makeElement("div", selectCategory(V.cheatMode)); + const catEl = App.UI.DOM.makeElement("div", selectCategory(V.debugMode > 0 && V.debugModeEventSelection > 0)); r.push(catEl); r.push(App.UI.DOM.slaveDescriptionDialog(slave), situationDesc); - const nickEl = App.UI.DOM.makeElement("span", selectNickname(V.cheatMode)); + const nickEl = App.UI.DOM.makeElement("span", selectNickname(V.debugMode > 0 && V.debugModeEventSelection > 0)); r.push(`You begin to overhear your other slaves refer to ${him} as`, nickEl); App.Events.addParagraph(el, r); @@ -1650,7 +1650,7 @@ App.Events.RENickname = class RENickname extends App.Events.BaseEvent { nicknameArray = ["Barely Legal"]; } } - situationDesc = `is yet underage by old world standards, and some older slaves do not let ${him} forget that.`; + situationDesc = `is still considered underage by old world standards, and some older slaves do not let ${him} forget that.`; applyDesc = `understands that far from being a mockery, your sanction has turned an intended insult into a reference to the appeal of ${his} years.`; notApplyDesc = `understands that despite ${his} young age ${he} must do ${his} best to fuck like the most veteran of whores.`; diff --git a/src/events/RE/reRelativeRecruiter.js b/src/events/RE/reRelativeRecruiter.js index 340d7aaeb9305fd083d4f63a3ccf9ff2a21fbf00..bbf5c1a9e6e0a28e23277a0c1ecc7e5240277df0 100644 --- a/src/events/RE/reRelativeRecruiter.js +++ b/src/events/RE/reRelativeRecruiter.js @@ -172,7 +172,7 @@ App.Events.RERelativeRecruiter = class RERelativeRecruiter extends App.Events.Ba let _this = this; // fuck javascript's half-assed classes let cost = 0; // will be filled out later - let cheatDiv = App.UI.DOM.makeElement("div", (V.cheatMode === 1) ? cheatModeSelectors() : ''); + let cheatDiv = App.UI.DOM.makeElement("div", (V.debugMode > 0 && V.debugModeEventSelection > 0) ? cheatModeSelectors() : ''); node.appendChild(cheatDiv); let eventTextDiv = App.UI.DOM.makeElement("div", eventText()); diff --git a/src/events/RE/reRoyalBlood.js b/src/events/RE/reRoyalBlood.js index 775ab9641a222d49a4a9d5d33a03a5256885b59c..f647a70bfe6aa814557b61e0742b32e32a8d14c9 100644 --- a/src/events/RE/reRoyalBlood.js +++ b/src/events/RE/reRoyalBlood.js @@ -1,7 +1,7 @@ App.Events.RERoyalBlood = class RERoyalBlood extends App.Events.BaseEvent { eventPrerequisites() { return [ - () => (V.rep - 10000 > random(1, 12500) || V.cheatMode !== 0) + () => ((V.rep - 10000 > random(1, 12500)) || (V.debugMode > 0 && V.debugModeEventSelection > 0)) ]; } diff --git a/src/events/RESS/arcadeSadist.js b/src/events/RESS/arcadeSadist.js index 61f9962cc1e8fff23eb5cb7943008f0ab7f447e7..d7682055679a556766359bdc5430e3abaee89730 100644 --- a/src/events/RESS/arcadeSadist.js +++ b/src/events/RESS/arcadeSadist.js @@ -169,7 +169,7 @@ App.Events.RESSArcadeSadist = class RESSArcadeSadist extends App.Events.BaseEven if (canDoVaginal(eventSlave)) { r.push(`pussy,`); seX(eventSlave, "vaginal", V.PC, "penetrative"); - } else if (eventSlave.dick > 0 && eventSlave.chstityPenis === 0) { + } else if (eventSlave.dick > 0 && eventSlave.chastityPenis === 0) { r.push(`dick,`); } else { r.push(`body,`); diff --git a/src/events/RESS/forbiddenMasturbation.js b/src/events/RESS/forbiddenMasturbation.js new file mode 100644 index 0000000000000000000000000000000000000000..01b1eb45bb8ab2266f250f702ea4c70cb73bc704 --- /dev/null +++ b/src/events/RESS/forbiddenMasturbation.js @@ -0,0 +1,604 @@ +App.Events.RESSForbiddenMasturbation = class RESSForbiddenMasturbation extends App.Events.BaseEvent { + eventPrerequisites() { + return []; // always valid if sufficient actors can be cast successfully + } + + actorPrerequisites() { + return [ + [ // single event slave + s => s.fetish !== "mindbroken", + s => s.rules.release.masturbation === 0, + s => !App.Utils.hasNonassignmentSex(s), + s => s.need > 0, + s => s.devotion <= 95, + s => s.trust >= -20, + s => (s.chastityPenis !== 1 || s.dick === 0), + hasAnyArms, + hasAnyLegs, + ] + ]; + } + + execute(node) { + /** @type {Array<App.Entity.SlaveState>} */ + let [eventSlave] = this.actors.map(a => getSlave(a)); + const { + He, he, His, his, him, himself + } = getPronouns(eventSlave); + const {title: Master} = getEnunciation(eventSlave); + const {hisA, himselfA, HisA} = getPronouns(assistant.pronouns().main).appendSuffix('A'); + const bellyAdj = bellyAdjective(eventSlave); + const knees = hasBothLegs(eventSlave) ? "knees" : "knee"; + + let offHand = "nothing"; + + V.nextLink = "Next Week"; + + App.Events.drawEventArt(node, eventSlave); + + let r = []; + if (V.assistant.personality > 0) { + r.push(`There is an alert from ${V.assistant.name}, in ${hisA} deliciously feminine voice: "${properMaster()},`, contextualIntro(V.PC, eventSlave, "DOM"), `is masturbating. Ooh, ${he}'s breaking the rules, ${properMaster()}!" ${HisA} avatar`); + switch (V.assistant.appearance) { + case "monstergirl": + r.push(`strokes ${hisA} dicks suggestively.`); + break; + case "shemale": + r.push(`shifts uncomfortably, ${hisA} cock rock hard.`); + break; + case "amazon": + r.push(`struts back and forth indignantly, ${hisA} bone bangles rattling.`); + break; + case "businesswoman": + r.push(`licks ${hisA} cherry-red lips suggestively.`); + break; + case "fairy": + case "pregnant fairy": + r.push(`giggles uncontrollably.`); + break; + case "hypergoddess": + case "goddess": + r.push(`tutting disapprovingly, despite ${hisA} blushing.`); + break; + case "loli": + r.push(`stares innocently at the scene.`); + break; + case "preggololi": + r.push(`stares at the scene, blushing, while a hand caresses ${hisA} large belly.`); + break; + case "angel": + r.push(`is covering ${hisA} face, occasionally peeping through _hisA fingers.`); + break; + case "cherub": + r.push(`is trying ${hisA} hardest to look away, but keeps glancing back at the scene.`); + break; + case "incubus": + r.push(`is openly jacking off to the sight.`); + break; + case "succubus": + r.push(`is groping ${himselfA} to the sight.`); + break; + case "imp": + r.push(`is hovering while viciously fingering ${hisA} cunt.`); + break; + case "witch": + r.push(`is pretending to read from ${hisA} spell book, but is obviously watching over the top of it.`); + break; + case "ERROR_1606_APPEARANCE_FILE_CORRUPT": + r.push(`is mimicking ${hisA} actions nearly perfectly.`); + break; + case "schoolgirl": + r.push(`giggles nervously.`); + break; + default: + r.push(`spins accusingly.`); + } + } else { + r.push(`There is a gentle alert from ${V.assistant.name}: "${properMaster()},`, contextualIntro(V.PC, eventSlave, "DOM"), `is masturbating in violation of the rules."`); + } + r.push(`A video feed appears.`); + if (eventSlave.chastityVagina && eventSlave.chastityPenis === 1) { + r.push(`In ${his} combination chastity, all ${he} can manage is furious nipple-${eventSlave.nipples !== "fuckable" ? "rubbing" : "fisting"}`); + if (hasBothArms(eventSlave) && canDoAnal(eventSlave)) { + r.push(`and some furtive fingering of ${his} asshole`); + offHand = "anal"; + } + r.push(r.pop() + `.`); + } else if (eventSlave.chastityVagina && eventSlave.dick === 0) { + r.push(`In ${his} chastity belt, all ${he} can manage is furious nipple-${eventSlave.nipples !== "fuckable" ? "rubbing" : "fisting"}`); + if (hasBothArms(eventSlave) && canDoAnal(eventSlave)) { + r.push(`and some furtive fingering of ${his} asshole`); + offHand = "anal"; + } + r.push(r.pop() + `.`); + } else if (eventSlave.chastityPenis === 1 && eventSlave.vagina === -1) { + r.push(`In ${his} chastity cage, all ${he} can manage is furious nipple-${eventSlave.nipples !== "fuckable" ? "rubbing" : "fisting"}`); + if (hasBothArms(eventSlave) && canDoAnal(eventSlave)) { + r.push(`and some furtive fingering of ${his} asshole`); + offHand = "anal"; + } + r.push(r.pop() + `.`); + } else if (eventSlave.dick > 0 && ((eventSlave.hormoneBalance >= 100) || (eventSlave.balls > 0 && eventSlave.ballType === "sterile") || (eventSlave.balls === 0))) { + r.push(`Since ${he}'s impotent`); + if (eventSlave.balls === 0) { + r.push(`due to ${his} lack of balls,`); + } else if (eventSlave.ballType === "sterile") { + r.push(`due to ${his} useless balls,`); + } else { + r.push(`from hormone treatment,`); + } + r.push(`all ${he} can manage is rubbing ${his} soft dick`); + if (hasBothArms(eventSlave)) { + if (canDoVaginal(eventSlave)) { + r.push(`and some furtive fingering of ${his} pussy.`); + offHand = "pussy"; + } else if (canDoAnal(eventSlave)) { + r.push(`and some furtive fingering of ${his} asshole.`); + offHand = "anal"; + } else { + r.push(`and some ${eventSlave.nipples !== "fuckable" ? `furious tweaking of ${his} nipples` : `furtive fingering of ${his} nipplecunts`}`); + offHand = "nipples"; + } + } + r.push(r.pop() + `.`); + } else if (!canAchieveErection(eventSlave) && eventSlave.dick > 6) { + r.push(`Since ${his} dick requires far too much blood to get erect, ${he}'s furiously massaging the semi-engorged monster.`); + } else if (!canAchieveErection(eventSlave) && eventSlave.dick > 0) { + r.push(`Since ${he}'s can't get it up, all ${he} can manage is rubbing ${his} soft dick`); + if (hasBothArms(eventSlave)) { + if (canDoVaginal(eventSlave)) { + r.push(`and some furtive fingering of ${his} pussy.`); + offHand = "pussy"; + } else if (canDoAnal(eventSlave)) { + r.push(`and some furtive fingering of ${his} asshole.`); + offHand = "anal"; + } else { + r.push(`and some ${eventSlave.nipples !== "fuckable" ? `furious tweaking of ${his} nipples` : `furtive fingering of ${his} nipplecunts`}`); + offHand = "nipples"; + } + } + r.push(r.pop() + `.`); + } else if (eventSlave.vagina === -1 && eventSlave.dick === 0) { + r.push(`${He}'s rubbing ${his} perineum desperately`); + if (hasBothArms(eventSlave)) { + if (canDoAnal(eventSlave)) { + r.push(`with one hand, and ${his} anus with the other,`); + offHand = "anal"; + } else { + r.push(`with one hand, and a nipple with the other,`); + offHand = "nipples"; + } + } + r.push(`since ${he} lacks external genitalia.`); + } else if (eventSlave.vagina === -1) { + r.push(`${He}'s furiously jacking off.`); + } else if (eventSlave.clit >= 3) { + r.push(`${He}'s furiously jacking off ${his} clitdick.`); + } else { + r.push(`${He}'s furiously polishing ${his} pearl.`); + } + r.push(`${He}'s chosen to do it in a dark corner and looks like ${he}'s hurrying; ${he} clearly knows this is forbidden.`); + App.Events.addParagraph(node, r); + r = []; + + r.push(`${eventSlave.slaveName} does not hear your`); + if (canHear(eventSlave)) { + r.push(`approach until you're very close.`); + } else { + r.push(`approach, but soon realizes your presence.`); + } + r.push(`${He} starts and tries to look normal.`); + if (!canTalk(eventSlave)) { + r.push(`${He} nervously gestures that ${he} wasn't doing anything.`); + } else { + r.push(Spoken(eventSlave, `"I wasn't doing anything, ${(eventSlave.rudeTitle === 1) ? PoliteRudeTitle(eventSlave) : Master}!"`), `${he} lies.`); + } + + App.Events.addParagraph(node, r); + const unknownOradvanceableFetish = eventSlave.fetishKnown !== 1 || eventSlave.fetishStrength <= 95; + const responses = [new App.Events.Result(`Let ${him} earn relief`, relief)]; + if (eventSlave.fetish !== "cumslut" || unknownOradvanceableFetish) { + responses.push(new App.Events.Result(`when ${he} sucks`, sucks)); + } + if (eventSlave.fetish !== "boobs" || unknownOradvanceableFetish) { + responses.push(new App.Events.Result(`during nipple play`, nipple)); + } + if ((eventSlave.fetish !== "pregnancy" || unknownOradvanceableFetish) && eventSlave.belly >= 5000) { + responses.push(new App.Events.Result(`while fondling ${his} belly`, belly)); + } + if (canDoAnal(eventSlave) && eventSlave.fetish !== "buttslut" || unknownOradvanceableFetish) { + responses.push(new App.Events.Result(`when ${he} takes it up the ass`, ass, (eventSlave.anus === 0 ? `This option will take ${his} anal virginity` : null))); + } + if (eventSlave.fetish !== "humiliation" || unknownOradvanceableFetish) { + responses.push(new App.Events.Result(`in public`, inPublic)); + } + if (eventSlave.fetish !== "submissive" || unknownOradvanceableFetish) { + responses.push(new App.Events.Result(`while submitting to a spanking`, spanking)); + } + if (eventSlave.fetish !== "masochist" || unknownOradvanceableFetish) { + responses.push(new App.Events.Result(`while in pain`, pain)); + } + + if (responses.length > 1) { + responses.splice(1, 0, new App.Events.Result(null, null, `Punish ${him}, but then let ${him} get off:`)); // Hack for providing a headline to certain responses + } + App.Events.addResponses(node, responses); + + function relief() { + r = []; + + r.push(`${He}'s extremely relieved that you're not going to punish ${him} for the rulebreaking when you tell ${him} that ${he} can touch ${himself} if ${he}`); + if (eventSlave.belly >= 300000) { + r.push(`leans over ${his} ${bellyAdj} belly`); + } else { + r.push(`gets on ${his} ${knees}`); + } + r.push(`and sucks you off. ${He} does a decent job, playing with ${himself} all the while. ${He}'s learned that ${he} can get away with infractions if ${he}'s willing to suck dick afterward. ${His} resistance to your will <span class="devotion dec">has increased.</span>`); + eventSlave.devotion -= 5; + seX(eventSlave, "oral", V.PC, "penetrative"); + return r; + } + + function sucks() { + r = []; + if (V.PC.belly >= 10000) { + if (eventSlave.belly >= 300000) { + r.push(`You tip ${him} over ${his} ${bellyAdj}`); + if (eventSlave.bellyPreg >= 3000) { + r.push(`pregnancy,`); + } else { + r.push(`middle,`); + } + r.push(`do your best to get close beside ${him},`); + } else if (eventSlave.belly >= 5000) { + r.push(`You order ${him} to bend over beside you so your pregnancy doesn't obstruct you as badly`); + } else { + r.push(`You lean back, pull ${him} over your knee and under your gravid dome of a middle`); + } + } else { + if (eventSlave.belly >= 300000) { + r.push(`You tip ${him} over ${his} ${bellyAdj}`); + if (eventSlave.bellyPreg >= 3000) { + r.push(`pregnancy`); + } else { + r.push(`middle`); + } + } else if (eventSlave.belly >= 5000) { + r.push(`You spread your legs to give ${his}`); + if (eventSlave.bellyPreg >= 3000) { + r.push(`pregnancy`); + } else { + r.push(`bloated middle`); + } + r.push(`room as you pull ${him} onto your lap`); + } else { + r.push(`You pull ${him} down over your knee`); + } + } + r.push(`and spank ${his} ${eventSlave.skin} buttocks until they're warm to the touch. It's not a sexual punishment, it's too painful for that; by the end, ${eventSlave.slaveName} has cried ${himself} out and is limp in your hands. You pull ${him} up to face you and give ${him} your instructions: from now on, ${he} can come to you and ask to`); + if (V.PC.dick !== 0 && V.PC.vagina !== -1) { + r.push(`blow you and perform cunnilingus on you,`); + } else if (V.PC.dick !== 0) { + r.push(`blow you,`); + } else if (V.PC.vagina !== -1) { + r.push(`and perform cunnilingus on you,`); + } + r.push(`and masturbate while ${he} does. ${He} nods through ${his} tears and flees. In an hour or so, though, ${he} finds you and asks to`); + if (V.PC.vagina !== -1) { + r.push(`give you oral.`); + } else { + r.push(`suck your cock.`); + } + r.push(`When you pretend indifference, ${he} abjectly begs. Soon, ${he}'s down on ${his} ${knees}, crying a little with shame as ${he} masturbates furiously.`); + seX(eventSlave, "oral", V.PC, "penetrative", 5); + if (eventSlave.fetish === "cumslut" && eventSlave.fetishKnown === 1) { + eventSlave.fetishStrength += 4; + r.push(`<span class="fetish inc">${His} enjoyment of`); + if (V.PC.dick === 0) { + r.push(`giving head`); + } else { + r.push(`sucking cock`); + } + r.push(`has increased.</span>`); + } else if (eventSlave.fetish === "cumslut") { + eventSlave.fetishKnown = 1; + r.push(`<span class="fetish gain">${His} enjoyment of`); + if (V.PC.dick === 0) { + r.push(`giving head`); + } else { + r.push(`sucking cock`); + } + r.push(`is now clear to you.</span>`); + } else if (random(1, 100) > 50) { + eventSlave.fetish = "cumslut"; + eventSlave.fetishKnown = 1; + eventSlave.fetishStrength = 65; + r.push(`Before ${he} realizes what's happening, <span class="fetish gain">${he}'s getting aroused at the thought of`); + if (V.PC.dick === 0) { + r.push(`giving head.</span>`); + } else { + r.push(`sucking cock.</span>`); + } + } + return r; + } + + function nipple() { + r = []; + if (V.PC.belly >= 10000) { + if (eventSlave.belly >= 300000) { + r.push(`You tip ${him} over ${his} ${bellyAdj}`); + if (eventSlave.bellyPreg >= 3000) { + r.push(`pregnancy,`); + } else { + r.push(`middle,`); + } + r.push(`do your best to get close beside ${him}, and grope ${him} thoroughly, bringing ${him} to the painful edge of orgasm. Just when ${he}'s about to tip over the edge, the stimulation stops and you flip ${him} onto ${his} back, lower your gravid body down to ${his} level and start playing with ${his} nipples.`); + } else if (eventSlave.belly >= 5000) { + r.push(`You order ${him} to bend over beside you so your pregnancy doesn't obstruct you as badly and grope ${him} thoroughly, bringing ${him} to the painful edge of orgasm. Just when ${he}'s about to tip over the edge, the stimulation stops and you haul ${him} upright and start playing with ${his} nipples.`); + } else { + r.push(`You lean back, pull ${him} over your knee and under your gravid dome of a middle and grope ${him} thoroughly, bringing ${him} to the painful edge of orgasm. Just when ${he}'s about to tip over the edge, the stimulation stops and you haul ${him} upright and start playing with ${his} nipples.`); + } + } else { + if (eventSlave.belly >= 300000) { + r.push(`You tip ${him} over ${his} ${bellyAdj}`); + if (eventSlave.bellyPreg >= 3000) { + r.push(`pregnancy`); + } else { + r.push(`middle`); + } + r.push(`and grope ${him} thoroughly, bringing ${him} to the painful edge of orgasm. Just when ${he}'s about to tip over the edge, the stimulation stops and you haul ${him} up into your lap, ${his} stomach spreading your legs, and start playing with ${his} nipples.`); + } else if (eventSlave.belly >= 5000) { + r.push(`You spread your legs to give ${his}`); + if (eventSlave.bellyPreg >= 3000) { + r.push(`pregnancy`); + } else { + r.push(`bloated middle`); + } + r.push(`room as you pull ${him} onto your lap and grope ${him} thoroughly, bringing ${him} to the painful edge of orgasm. Just when ${he}'s about to tip over the edge, the stimulation stops and you haul ${him} up into your lap and start playing with ${his} nipples.`); + } else { + r.push(`You pull ${him} down over your knee and grope ${him} thoroughly, bringing ${him} to the painful edge of orgasm. Just when ${he}'s about to tip over the edge, the stimulation stops and you haul ${him} up into your lap and start playing with ${his} nipples.`); + } + } + r.push(`${He} writhes and sobs at the orgasm denial, since the nipple play is just barely enough to keep ${him} at a high level of arousal without giving relief. You switch back and forth until ${he} finally goes over into muscle-spasming climax during nipple stimulation alone.`); + seX(eventSlave, "mammary", V.PC, "penetrative"); + if (eventSlave.fetish === "boobs" && eventSlave.fetishKnown === 1) { + eventSlave.fetishStrength += 4; + r.push(`<span class="fetish inc">${His} enjoyment of breast play has increased.</span>`); + } else if (eventSlave.fetish === "boobs") { + eventSlave.fetishKnown = 1; + r.push(`<span class="fetish gain">${His} enjoyment of breast play is now clear to you.</span>`); + } else if (random(1, 100) > 50) { + eventSlave.fetish = "boobs"; + eventSlave.fetishKnown = 1; + eventSlave.fetishStrength = 65; + r.push(`Before ${he} realizes what's happening, <span class="fetish gain">${he}'s getting aroused at every brush against ${his} breasts.</span>`); + } + return r; + } + + function belly() { + r= []; + r.push(`You`); + if (eventSlave.belly >= 300000) { + r.push(`roll ${him} onto ${his} back`); + } else { + r.push(`pull ${him} into a sitting position on your lap`); + } + r.push(`and grope ${his} ${bellyAdj}`); + if (eventSlave.bellyPreg >= 3000) { + r.push(`pregnancy`); + } else { + r.push(`stomach`); + } + r.push(`thoroughly, allowing ${him} to reach the painful edge of orgasm. You feel ${his} belly shudder as ${he} reaches climax under your ministrations. You tease ${his}`); + if (eventSlave.belly >= 10001) { + r.push(`popped`); + } + r.push(`navel as ${he} comes down from ${his} masturbation session.`); + if (eventSlave.fetish === "pregnancy" && eventSlave.fetishKnown === 1) { + eventSlave.fetishStrength += 4; + r.push(`<span class="fetish inc">${His} enjoyment of pregnancy has increased.</span>`); + } else if (eventSlave.fetish === "pregnancy") { + eventSlave.fetishKnown = 1; + r.push(`<span class="fetish gain">${His} enjoyment of pregnancy is now clear to you.</span>`); + } else if (random(1, 100) > 50) { + eventSlave.fetish = "pregnancy"; + eventSlave.fetishKnown = 1; + eventSlave.fetishStrength = 65; + r.push(`Before ${he} realizes what's happening, <span class="fetish gain">${he}'s getting aroused at`); + if (eventSlave.pregKnown === 1) { + r.push(`every thought about ${his} pregnancy`); + } else { + r.push(`the very thought of being pregnant`); + } + r.push(r.pop() + `.</span>`); + } + return r; + } + + function ass() { + r= []; + r.push(`You`); + if (V.PC.belly >= 10000) { + if (eventSlave.belly >= 300000) { + r.push(`tip ${him} over ${his} ${bellyAdj}`); + if (eventSlave.bellyPreg >= 3000) { + r.push(`pregnancy,`); + } else { + r.push(`middle,`); + } + r.push(`do your best to get close beside ${him},`); + } else if (eventSlave.belly >= 5000) { + r.push(`order ${him} to bend over beside you so your pregnancy doesn't obstruct you as badly`); + } else { + r.push(`lean back, pull ${him} over your knee and under your gravid dome of a middle`); + } + } else { + if (eventSlave.belly >= 300000) { + r.push(`tip ${him} over ${his} ${bellyAdj}`); + if (eventSlave.bellyPreg >= 3000) { + r.push(`pregnancy`); + } else { + r.push(`middle`); + } + } else if (eventSlave.belly >= 5000) { + r.push(`spread your legs to give ${his}`); + if (eventSlave.bellyPreg >= 3000) { + r.push(`pregnancy`); + } else { + r.push(`bloated middle`); + } + r.push(`room as you pull ${him} onto your lap`); + } else { + r.push(`pull ${him} down over your knee`); + } + } + r.push(`and spank ${his} ${eventSlave.skin} buttocks until they're warm to the touch. It's not a sexual punishment, it's too painful for that; by the end, ${eventSlave.slaveName} has cried ${himself} out and is limp in your hands. You pull ${him} up to face you and give ${him} your instructions: from now on, ${he} can come to you and ask you to assrape ${him}, and masturbate while ${he} takes`); + if (V.PC.dick === 0) { + r.push(`anal penetration.`); + } else { + r.push(`cock.`); + } + r.push(`${He} nods through ${his} tears and flees. In an hour or so, though, ${he} finds you and haltingly asks you to buttfuck ${him}. When you pretend indifference, ${he} offers you ${his} anus and abjectly begs you to stick`); + if (V.PC.dick === 0) { + r.push(`a strap-on`); + } else { + r.push(`your cock`); + } + r.push(`up ${his} butt. Soon, ${he}'s down on all fours, crying a little with mixed shame and anal pain as ${he} masturbates furiously.`); + r.push(VCheck.Anal(eventSlave, 5)); + if (eventSlave.fetish === "buttslut" && eventSlave.fetishKnown === 1) { + eventSlave.fetishStrength += 4; + r.push(`<span class="fetish inc">${His} enjoyment of anal has increased.</span>`); + } else if (eventSlave.fetish === "buttslut") { + eventSlave.fetishKnown = 1; + r.push(`<span class="fetish gain">${His} enjoyment of anal is now clear to you.</span>`); + } else if (random(1, 100) > 50) { + eventSlave.fetish = "buttslut"; + eventSlave.fetishKnown = 1; + eventSlave.fetishStrength = 65; + r.push(`Before ${he} realizes what's happening, <span class="fetish gain">${he}'s getting aroused at the thought of anal sex.</span>`); + } + return r; + } + + function inPublic() { + r= []; + r.push(`You bring ${him} out`); + if (App.Entity.facilities.club.established) { + r.push(`to ${App.Entity.facilities.club.nameCaps}`); + } else { + r.push(`onto the street`); + } + r.push(`and secure ${him} upright with a set of vibrators attached to all of ${his} erogenous zones. There's a lot of them, and they're extremely powerful; when you test the setup, ${he} wriggles with the intensity of the stimulation, and is about to climax when you shut it down. Without telling ${him}, you slave the vibrators to a program originally designed for VIP security details. It uses the cameras scattered through the area to detect when passersby are looking at ${him}. The more eyes on ${him}, the stronger the vibrations.`); + if (eventSlave.fetish === "humiliation" && eventSlave.fetishKnown === 1) { + eventSlave.fetishStrength += 4; + r.push(`<span class="fetish inc">${His} enjoyment of humiliation has increased.</span>`); + } else if (eventSlave.fetish === "humiliation") { + eventSlave.fetishKnown = 1; + r.push(`<span class="fetish gain">${His} enjoyment of humiliation is now clear to you.</span>`); + } else if (random(1, 100) > 50) { + eventSlave.fetish = "humiliation"; + eventSlave.fetishKnown = 1; + eventSlave.fetishStrength = 65; + r.push(`Before ${he} realizes what's happening, <span class="fetish gain">${he}'s starting to long for humiliation.</span>`); + } + return r; + } + + function spanking() { + r= []; + r.push(`You tell ${him} that ${he} can get ${himself} off while ${he}'s being spanked, and that's it: you don't tell ${him} to offer ${his} bottom, much less start spanking ${him}. ${He} doesn't understand for a long moment, but before long ${he}'s begging abjectly for a spanking, and has ${his} buttocks presented, quivering with simultaneous arousal and fear of pain. The pain comes soon enough, with a delicious crack of palm on flesh`); + if (eventSlave.voice === 0) { + r.push(`and a hoarse grunt, the most noise ${he} can make.`); + } else { + r.push(`and a shriek of agony.`); + } + r.push(`${He} masturbates furiously, but you're an accomplished spanker, and you repeatedly cause ${him} just enough pain to prevent climax. Eventually ${he} gets off in part because of, rather than in spite of, the lengthy beating.`); + if (eventSlave.fetish === "submissive" && eventSlave.fetishKnown === 1) { + eventSlave.fetishStrength += 4; + r.push(`<span class="fetish inc">${His} enjoyment of submission has increased.</span>`); + } else if (eventSlave.fetish === "submissive") { + eventSlave.fetishKnown = 1; + r.push(`<span class="fetish gain">${His} enjoyment of submission is now clear to you.</span>`); + } else if (random(1, 100) > 50) { + eventSlave.fetish = "submissive"; + eventSlave.fetishKnown = 1; + eventSlave.fetishStrength = 65; + r.push(`Before ${he} realizes what's happening, <span class="fetish gain">${he} starts to associate submitting to you with getting off.</span>`); + } + return r; + } + + function pain() { + r = []; + r.push(`You order ${him} to`); + if ((eventSlave.heels === 1 && shoeHeelCategory(eventSlave) === 0) || !canStand(eventSlave)) { + r.push(`kneel`); + } else if (shoeHeelCategory(eventSlave) > 1 || canMove(eventSlave)) { + r.push(`teeter`); + } else { + r.push(`stand`); + } + if (hasBothArms(eventSlave)) { + r.push(`with ${his} arms`); + } else { + r.push(`with ${his} arm`); + } + if (hasBothLegs(eventSlave)) { + r.push(`over ${his} head and ${his} legs splayed,`); + } else { + r.push(`over ${his} head and ${his} leg bent,`); + } + r.push(`and tell ${him} that if ${he} moves or resists, ${his} punishment will begin again from the start.`); + if ((eventSlave.chastityVagina || eventSlave.chastityPenis === 1)) { + if (offHand === "anal") { + r.push(`${He} was touching ${his} nipples and ass, so you flick and torture ${his} nipples and give ${him} a severe spanking.`); + } else { + r.push(`${He} was playing with ${his} nipples, so you flick and torture them, enjoying ${his} agony.`); + } + } else if (!canAchieveErection(eventSlave) && eventSlave.dick > 6) { + r.push(`${He} was playing with ${his} oversized cock, so you kick and swat at the swollen monster, enjoying the way it spasms.`); + } else if (eventSlave.dick > 0 && !canAchieveErection(eventSlave)) { + if (offHand === "anal") { + r.push(`${He} was touching ${his} limp dick and ass, so you slap and torture ${his} offending dick and give ${him} a severe spanking.`); + } else if (offHand === "pussy") { + r.push(`${He} was touching ${his} limp dick and pussy, so you slap and torture ${his} offending dick and labia.`); + } else if (offHand === "nipples") { + r.push(`${He} was playing with ${his} limp dick and nipples, so you slap and torture ${his} offending dick while pinching and twisting nipples.`); + } else { + r.push(`${He} was playing with ${his} limp dick, so you slap and torture ${his} worthless cock, enjoying ${his} agony.`); + } + } else if (eventSlave.vagina === -1 && eventSlave.dick === 0) { + if (offHand === "anal") { + r.push(`${He} was desperately rubbing ${his} perineum and anus, the most sensitive parts ${he} has left, so you slap that part of ${him} repeatedly, enjoying the way it spasms.`); + } else if (offHand === "nipples") { + r.push(`${He} was desperately rubbing ${his} perineum and nipples, the most sensitive parts ${he} has left, so you slap those parts of ${him} repeatedly, enjoying the way they spasm.`); + } + } else if (eventSlave.vagina === -1 || eventSlave.clit >= 3) { + r.push(`${He} was jacking it, so you force ${him} to get ${himself} hard for punishment and then deliver a series of agonizing slaps and flicks to ${his} offending member.`); + } else if (eventSlave.labia > 1) { + r.push(`${His} generous pussylips bear a sheen of incriminating moisture, so you slap and flick them, causing ${him} intense agony.`); + } else { + r.push(`You deliver a series of agonizing slaps to ${his} mons.`); + } + r.push(`You have to start over twice. By the end, ${he}'s managed to orgasm to all the stimulation, but ${he}'s crying and desperately promising never to touch ${himself} again without your permission. ${His} submission to you <span class="devotion inc">has increased.</span>`); + eventSlave.devotion += 4; + if (eventSlave.fetish === "masochist" && eventSlave.fetishKnown === 1) { + eventSlave.fetishStrength += 4; + r.push(`<span class="fetish inc">${His} enjoyment of pain has increased.</span>`); + } else if (eventSlave.fetish === "masochist") { + eventSlave.fetishKnown = 1; + r.push(`<span class="fetish gain">${His} enjoyment of pain is now clear to you.</span>`); + } else if (random(1, 100) > 50) { + eventSlave.fetish = "masochist"; + eventSlave.fetishKnown = 1; + eventSlave.fetishStrength = 65; + r.push(`Before ${he} realizes what's happening, <span class="fetish gain">${he}'s getting aroused at the thought of ${his} ${getWrittenTitle(eventSlave)} beating ${him}.</span>`); + } + return r; + } + } +}; + diff --git a/src/events/RESS/modestClothes.js b/src/events/RESS/modestClothes.js new file mode 100644 index 0000000000000000000000000000000000000000..381f3a28a963a2c4ddc7ef82c253c3d42d46eccd --- /dev/null +++ b/src/events/RESS/modestClothes.js @@ -0,0 +1,353 @@ +App.Events.RESSModestClothes = class RESSModestClothes extends App.Events.BaseEvent { + eventPrerequisites() { + return []; // always valid if sufficient actors can be cast successfully + } + + actorPrerequisites() { + return [ + [ // single event slave + s => s.fetish !== "mindbroken", + hasAnyArms, + canWalk, + canTalk, + canHear, + s => s.devotion > 20, + s => s.trust > 20, + s => s.rules.speech !== "restrictive", + s => s.choosesOwnClothes !== 1, + s => s.assignment !== Job.QUARTER, + s => getExposure(s) === 0, + ] + ]; + } + + execute(node) { + /** @type {Array<App.Entity.SlaveState>} */ + let [eventSlave] = this.actors.map(a => getSlave(a)); + const { + His, He, he, his, him, himself, girl + } = getPronouns(eventSlave); + const {title: Master, say} = getEnunciation(eventSlave); + + V.nextLink = "Next Week"; + + let artDiv = document.createElement("div"); // named container so we can replace it later + App.Events.drawEventArt(artDiv, eventSlave, "no clothing"); + node.appendChild(artDiv); + const clothes = Spoken(eventSlave, eventSlave.clothes); + const desc = SlaveTitle(eventSlave); + + let r = []; + + r.push(`Near the end of ${his} weekly inspection,`); + r.push(contextualIntro(V.PC, eventSlave, "DOM")); + r.push(`asks you a question. The inspection happens to have been at the start of ${his} day, and after you're done with ${him}, ${he}'ll be heading off to get dressed. ${He}'s naked for inspection, of course,`); + if (eventSlave.fetishKnown && eventSlave.fetish === "humiliation") { + r.push(`which has the humiliation fetishist ${desc} decently aroused.`); + } else { + r.push(`but ${he}'s a good ${desc}, and ${he} trusts you, so ${he} has no problem at all with being seen nude.`); + } + r.push(`In fact, that's what ${he} asks you about.`); + App.Events.addParagraph(node, r); + r = []; + + r.push(Spoken(eventSlave, `"${Master},"`), `${he} ${say}s,`, Spoken(eventSlave, `"may I please wear something a little more revealing, just for today?"`)); + if (eventSlave.trust > 95) { + r.push(`${He} trusts you completely, enough to have confidence that you'll understand ${he} isn't questioning you.`); + } else { + r.push(`${He} bites ${his} lip, realizing that ${he} might have come across as questioning you.`); + } + switch (eventSlave.clothes) { + case "a nice maid outfit": + r.push(Spoken(eventSlave, `"Wearing a proper maid's outfit is nice,"`)); + break; + case "a nice nurse outfit": + r.push(Spoken(eventSlave, `"Wearing a proper nurse's outfit is nice,"`)); + break; + case "nice business attire": + r.push(Spoken(eventSlave, `"Wearing a suit is nice,"`)); + break; + case "battledress": + r.push(Spoken(eventSlave, `"Wearing a ${clothes} is nice,"`)); + break; + default: + r.push(Spoken(eventSlave, `"Wearing ${clothes} is nice,"`)); + } + if (eventSlave.trust > 95) { + r.push(`${he} allows.`); + } else { + r.push(`${he} hurries to add.`); + } + if (eventSlave.fetishKnown && eventSlave.fetish === "humiliation") { + r.push(Spoken(eventSlave, `"It's not really embarrassing, though. It would be so sexy to be, um, falling out of my clothes.`)); + } else if (eventSlave.fetishKnown && eventSlave.fetish === "buttslut") { + r.push(Spoken(eventSlave, `"But they cover my asshole.`)); + } else if (eventSlave.fetishKnown && eventSlave.fetish === "boobs") { + r.push(Spoken(eventSlave, `"But they cover my boobs.`)); + } else if (eventSlave.fetishKnown && eventSlave.fetish === "pregnancy" && eventSlave.bellyPreg >= 1500) { + r.push(Spoken(eventSlave, `"But it covers up my pregnancy.`)); + } else if (eventSlave.assignment === Job.WHORE) { + r.push(Spoken(eventSlave, `"But I also like being a prostitute, ${Master}. It'd be fun to try looking like a total whore.`)); + } else if (eventSlave.assignment === Job.PUBLIC) { + r.push(Spoken(eventSlave, `"But I also like being a public slut, ${Master}. It'd be fun to really flaunt it.`)); + } else { + r.push(Spoken(eventSlave, `"But it'd be fun and different to wear something really naughty.`)); + } + r.push(Spoken(eventSlave, `May I please try out something skimpier today?"`)); + + App.Events.addParagraph(node, r); + App.Events.addResponses(node, [ + new App.Events.Result(`No`, no), + new App.Events.Result(`Show ${him} how much you like ${his} usual outfit`, usual), + new App.Events.Result(`Put ${him} in a string bikini`, bikini), + new App.Events.Result(`Force uncomfortable straps on ${him}`, straps), + ]); + + function no() { + eventSlave.trust += 2; + return `You tell ${him} no. ${He}'s a good enough slave that making a simple request and having you return a straightforward negative without punishment <span class="trust inc">makes ${him} just slightly more trusting.</span> It's nice to be allowed to ask things.`; + } + + function usual() { + $(artDiv).empty(); + App.Events.drawEventArt(artDiv, eventSlave, eventSlave.clothes); + const frag = document.createDocumentFragment(); + let clothesDesc; + switch (eventSlave.clothes) { + case "a long qipao": + case "a slutty qipao": + clothesDesc = `qipao`; + break; + case "a penitent nuns habit": + clothesDesc = `habit`; + break; + case "a slave gown": + case "a ball gown": + clothesDesc = `gown`; + break; + case "a comfortable bodysuit": + clothesDesc = `bodysuit`; + break; + case "a nice nurse outfit": + clothesDesc = `nurse outfit`; + break; + case "a schoolgirl outfit": + clothesDesc = `school clothes`; + break; + case "a nice maid outfit": + clothesDesc = `maid outfit`; + break; + case "a slutty maid outfit": + clothesDesc = `skimpy maid outfit`; + break; + case "a biyelgee costume": + case "a dirndl": + case "a halter top dress": + case "a mini dress": + case "a maternity dress": + clothesDesc = `dress`; + break; + case "a military uniform": + case "a mounty outfit": + case "a red army uniform": + case "a schutzstaffel uniform": + case "a slutty schutzstaffel uniform": + clothesDesc = `uniform`; + break; + case "spats and a tank top": + clothesDesc = `spats`; + break; + case "a burkini": + case "a monokini": + clothesDesc = `swimsuit`; + break; + case "a chattel habit": + case "a fallen nuns habit": + clothesDesc = `slutty habit`; + break; + case "a succubus outfit": + clothesDesc = `succubus getup`; + break; + case "a hijab and blouse": + case "conservative clothing": + clothesDesc = `conservative clothes`; + break; + default: + clothesDesc = App.Data.clothes.get(eventSlave.clothes).name.toLowerCase(); + } + + r = []; + r.push(`You tell ${him} to go get dressed as usual. ${His} face falls a little, but there was no condemnation in your tone, and ${he} hurries off,`); + if (eventSlave.dick > 6) { + r.push(`monstrous cock dangling.`); + } else if (eventSlave.balls > 4) { + r.push(`big balls dangling.`); + } else if (eventSlave.bellyFluid >= 5000 || eventSlave.weight > 95) { + r.push(`big belly jiggling.`); + } else if (eventSlave.belly >= 5000) { + r.push(`as fast as ${his} swollen belly will allow.`); + } else if ((eventSlave.boobsImplant / eventSlave.boobs) >= .60) { + r.push(`fake tits bouncing.`); + } else if (eventSlave.butt > 4) { + r.push(`${his} big booty jiggling.`); + } else if (eventSlave.boobs > 2000) { + r.push(`udders jiggling.`); + } else { + r.push(`giving you a nice view of ${his} naked rear.`); + } + r.push(`${He} returns quickly, in ${his} proper ${clothesDesc}.`); + r.push(`You tell ${him} that you like how ${he} looks, and that ${he}'s pretty. ${He} wasn't expecting such a blunt compliment, and`); + if (canSee(eventSlave)) { + r.push(`${his} ${App.Desc.eyesColor(eventSlave)} flick down to`); + } else { + r.push(`${he} faces`); + } + r.push(`the ground for a moment as ${he} blushes.`, Spoken(eventSlave, `"T-thank you, ${Master},"`), `${he} stutters.`); + App.Events.addParagraph(frag, r); + r = []; + + r.push(`You add that ${he} looks so good that ${he} had better take ${his} nice clean`); + r.push(`${clothesDesc} off again, because`); + if (canDoVaginal(eventSlave) && eventSlave.vagina !== 0) { + r.push(`you're going to`); + if (V.PC.dick) { + r.push(`fuck`); + r.push(VCheck.Vaginal(eventSlave, 1)); + } else { + r.push(`trib`); + seX(eventSlave, "vaginal", V.PC, "vaginal"); + if (canFemImpreg(eventSlave, V.PC)) { + knockMeUp(eventSlave, 10, 0, -1); + } + } + r.push(`${him} senseless.`); + } else if (canDoAnal(eventSlave) && eventSlave.anus !== 0) { + if (eventSlave.prostate) { + r.push(`you're going to fuck ${his} butt until ${he} cums.`); + } else { + r.push(`you're going to fuck ${his} butt.`); + } + r.push(VCheck.Anal(eventSlave, 1)); + } else { + r.push(`${he}'s going to`); + if (V.PC.dick) { + r.push(`suck your dick until you cover ${him} in cum.`); + seX(eventSlave, "oral", V.PC, "penetrative"); + } else { + r.push(`eat you out until ${he}'s got your pussyjuice running down ${his} chin.`); + seX(eventSlave, "oral", V.PC, "vaginal"); + } + } + r.push(`${He} giggles at the sudden lewdness, and quickly strips naked again, complimented and <span class="devotion inc">eager to be used.</span>`); + App.Events.addParagraph(frag, r); + eventSlave.devotion += 5; + return frag; + } + + function bikini() { + $(artDiv).empty(); + App.Events.drawEventArt(artDiv, eventSlave, "a string bikini"); + const belly = bellyAdjective(eventSlave); + + r = []; + r.push(`You tell ${him} that the wardrobe's sorting system will present ${him} with a new outfit, just for today. ${He}'s to go try it on and come right back, to see how it fits.`); + r.push(Spoken(eventSlave, `"Thanks, ${Master}!"`), `${he} ${say}s brightly, and hurries off to see what's in store for ${him}. ${He} might be a slave and a ${desc} but ${girl}s everywhere love trying on new clothes. ${He} makes an entrance when ${he} comes back, spinning around to show off. ${He}'s wearing the briefest possible string bikini. The top, rather than having patches of material to cover ${his} nipples, forms a string triangle around them, framing them but not covering them. The bottom is a single string in front,`); + if (eventSlave.dick) { + r.push(`which looks rather sad and alone, pushed aside by ${his} dick as it is.`); + } else if (eventSlave.balls > 2) { + r.push(`which allow ${his} balls to spill to either side.`); + } else if (eventSlave.labia) { + r.push(`and it's embraced completely by ${his} generous pussylips.`); + } else { + r.push(`and it threatens to disappear inside ${his} pussylips.`); + } + r.push(Spoken(eventSlave, `"This feels so hot, ${Master},"`), `${he} ${say}s, and`); + if (eventSlave.fetishKnown && eventSlave.fetish === "humiliation") { + r.push(`blushes cutely. ${He} looks up at you,`); + if (canSee(eventSlave)) { + r.push(`sees`); + } else { + r.push(`feels`); + } + r.push(`the way you're staring at ${him}, and hangs ${his} head, blushing even harder.`); + } else if (eventSlave.fetishKnown && eventSlave.fetish === "buttslut") { + r.push(`turns around again, bending a little and cocking ${his} hips to show off the way the string between ${his} buttocks totally fails to conceal ${his}`); + if (eventSlave.anus > 2) { + r.push(`huge soft asspussy.`); + } else if (eventSlave.anus > 1) { + r.push(`nice butthole.`); + } else { + r.push(`tight little anus.`); + } + } else if (eventSlave.fetishKnown && eventSlave.fetish === "boobs") { + r.push(`bounces ${his}`); + if (eventSlave.boobsImplant) { + r.push(`fake tits.`); + } else if (eventSlave.boobs > 8000) { + r.push(`earth-shattering tits.`); + } else if (eventSlave.boobs > 2000) { + r.push(`huge boobs.`); + } else if (eventSlave.boobs > 400) { + r.push(`boobs.`); + } else { + r.push(`petite chest.`); + } + r.push(`Giggling, ${he} bounces harder, and ${his} nipples escape from ${his} top, such as it is.`); + } else if (eventSlave.fetishKnown && eventSlave.fetish === "pregnancy" && eventSlave.bellyPreg >= 1500) { + r.push(`and attempts to pull the strings over the front of ${his} belly. Without delay, they slide right back to the sides of the ${belly} dome, eliciting a giggle from the preggo slut.`); + } else if (eventSlave.assignment === Job.WHORE || eventSlave.assignment === Job.PUBLIC) { + r.push(`sneaks a hand under the string around ${his} waist, tugging ${his} bottom up`); + if (eventSlave.vagina !== -1) { + r.push(`until the string between ${his} legs is pulled up into the entrance of ${his} womanhood.`); + } else { + r.push(`and turning sideways to suggest ${his} ass.`); + } + if (eventSlave.assignment === Job.WHORE) { + r.push(Spoken(eventSlave, `"Guys'll pay money for this,"`)); + } else { + r.push(Spoken(eventSlave, `"Guys'll line up to fuck this,"`)); + } + r.push(`${he} giggles.`); + } else { + r.push(`bounces a little, smiling.`, Spoken(eventSlave, `"I'm basically naked,"`), `${he} giggles.`); + r.push(Spoken(eventSlave, `"Today is going to be fun. The other ${girl}s'll be jealous you wanted me to look so slutty. Love you, ${Master}."`)); + } + r.push(`${He}'s happy you indulged ${him}, and <span class="trust inc">satisfied that you think ${he}'s cute</span> enough to have around (practically) nude.`); + eventSlave.trust += 5; + return r; + } + + function straps() { + $(artDiv).empty(); + App.Events.drawEventArt(artDiv, eventSlave, "uncomfortable straps"); + const belly = bellyAdjective(eventSlave); + r = []; + + r.push(`You tell ${him} that the wardrobe's sorting system will present ${him} with a new outfit, just for today. ${He}'s to go try it on and come right back, to see how it fits.`); + r.push(Spoken(eventSlave, `"Thanks, ${Master}!"`), `${he} ${say}s brightly, and hurries off to see what's in store for ${him}. ${He} might be a slave and a ${desc} but ${girl}s everywhere love trying on new clothes. ${He}'s wrong to be so enthusiastic. ${He} comes obediently back, wearing a set of cruelly uncomfortable leather straps in the general shape of a bikini, but much tighter and more restrictive. It isn't at all what ${he} was expecting, but ${he} did ${his} best to obey. ${He}'s <span class="trust dec">tightened ${his} own straps down</span> until they're just short of cutting off circulation, in an obvious effort to please you. You ask ${him} how ${he} likes ${his} outfit.`); + r.push(Spoken(eventSlave, `"It's nice, ${Master},"`), `${he} ${say}s, but ${he} sounds a little sad.`); + if (eventSlave.fetishKnown && eventSlave.fetish === "humiliation") { + r.push(Spoken(eventSlave, `"I'm just a worthless humiliation slut. I love having steel rings around my holes like this,"`), `${he} adds.`); + } else if (eventSlave.fetishKnown && eventSlave.fetish === "buttslut") { + r.push(`${He} turns to show you ${his} asshole, framed by a steel ring that spreads ${his} buttocks to keep it nice and defenseless.`); + r.push(Spoken(eventSlave, `"I know my backpussy's the best thing about me,"`), `${he} adds.`); + } else if (eventSlave.fetishKnown && eventSlave.fetish === "boobs") { + r.push(`${He} does ${his} best to thrust out ${his} chest, making the straps creak.`); + r.push(Spoken(eventSlave, `"I know I'm, I'm just, just a pair of boobs,"`), `${he} adds.`); + } else if (eventSlave.fetishKnown && eventSlave.fetish === "pregnancy" && eventSlave.bellyPreg >= 1500) { + r.push(`${He} does ${his} best to thrust out ${his} ${belly} belly, making the straps creak ominously.`); + r.push(Spoken(eventSlave, `"I know I'm, I'm just, just a baby maker,"`), `${he} adds.`); + } else if (eventSlave.assignment === Job.WHORE || eventSlave.assignment === Job.PUBLIC) { + r.push(`${He} hangs ${his} head.`); + r.push(Spoken(eventSlave, `"I feel like a worthless ${eventSlave.assignment === Job.WHORE ? `whore` : `bitch`},"`), `${he} adds.`, Spoken(eventSlave, `"Guess I am."`)); + } else { + r.push(`${He} indicates the steel rings that frame ${his} holes and keep them defenseless.`); + r.push(Spoken(eventSlave, `"I know I'm just a collection of fuckholes,"`), `${he} adds.`); + } + r.push(`${He} sounds like ${he}'s trying to convince ${himself}, but ${his} <span class="devotion inc">abasement is not feigned.</span>`); + eventSlave.devotion += 5; + eventSlave.trust -= 5; + return r; + } + } +}; diff --git a/src/events/RESS/whoreRebellious.js b/src/events/RESS/whoreRebellious.js new file mode 100644 index 0000000000000000000000000000000000000000..d973352082d223248d5621c44f049bde4bb3c170 --- /dev/null +++ b/src/events/RESS/whoreRebellious.js @@ -0,0 +1,193 @@ +App.Events.RESSWhoreRebellious = class RESSWhoreRebellious extends App.Events.BaseEvent { + eventPrerequisites() { + return []; // always valid if sufficient actors can be cast successfully + } + + actorPrerequisites() { + return [ + [ // single event slave + s => s.fetish !== "mindbroken", + s => s.assignment === Job.WHORE, + s => s.devotion < -20, + s => s.trust >= -20, + s => (canDoAnal(s) || canDoVaginal(s)) + ] + ]; + } + + execute(node) { + /** @type {Array<App.Entity.SlaveState>} */ + let [eventSlave] = this.actors.map(a => getSlave(a)); + const { + He, he, His, his, him, himself, girl + } = getPronouns(eventSlave); + + V.nextLink = "Next Week"; + + App.Events.drawEventArt(node, eventSlave, "restrictive latex"); // TODO: Add mouth-plug? + + + let r = []; + + r.push(App.UI.DOM.slaveDescriptionDialog(eventSlave)); + r.push(`is kicked out of bed early in the morning. ${He}'s not yet obedient, but ${he} has to earn ${his} keep anyway. This means selling ${his} body, or in ${his} particular case, having ${his} unwilling body sold. ${He} knows the score and allows ${himself} to be stuffed into a special latex public whore suit. ${He}'s learned the hard way that resisting being suited up just means ${he}'ll be painfully punished before being suited up.`); + App.Events.addParagraph(node, r); + r = []; + + r.push(`The suit is quite special. It is made of thick, durable latex with temperature regulation and anchor points for restraint. It is specially crafted to be able to accommodate its wearer's ${eventSlave.boobs > 250 ? "tits" : "breast"}, belly,`); + if (V.seeDicks !== 0) { + r.push(`dick, balls,`); + } + r.push(`and rear, however large. It has a hole at ${his} mouth that holds ${his} jaws well open, with a plug to fill it completely when not in use. ${He} breathes through a port at ${his} nose that muffles all noise, in and out.`); + if (eventSlave.dick > 0) { + r.push(`${His} cock is neglected inside the latex, with no means of access.`); + } + if (eventSlave.vagina !== -1) { + r.push(`There's a hole over ${his} pussy, of course.`); + } + r.push(`Finally, there's a hole over ${his} anus.`); + App.Events.addParagraph(node, r); + r = []; + + r.push(`${He} will spend the day restrained in public, with your other slaves periodically stopping by to hydrate ${him} and wash out ${his} holes.`); + + App.Events.addParagraph(node, r); + App.Events.addResponses(node, [ + new App.Events.Result(`Increase ${his} assignment to 24 hours a day`, H24, virginityWarning()), + new App.Events.Result(`Take the first and last every day`, firstLast, virginityWarning()), + (V.arcade > 0) + ? new App.Events.Result(`Sentence ${him} to a month in the arcade`, arcade) + : new App.Events.Result(), + ]); + + function virginityWarning() { + if ((eventSlave.anus === 0 && canDoAnal(eventSlave)) || (eventSlave.vagina === 0 && canDoVaginal(eventSlave))) { + return `This option will take ${his} virginity`; + } + return null; + } + + function popCherry() { + if (eventSlave.vagina === 0 && canDoVaginal(eventSlave) && eventSlave.anus === 0 && canDoAnal(eventSlave)) { + eventSlave.anus++; + eventSlave.vagina++; + VCheck.Both(eventSlave, 1); + return `You made sure to claim <span class="virginity loss">both ${his} virginity and anal cherry</span> before anyone else could.`; + } else if (eventSlave.vagina === 0 && canDoVaginal(eventSlave)) { + eventSlave.vagina++; + VCheck.Vaginal(eventSlave, 1); + return `You made sure to claim <span class="virginity loss">${his} virginity</span> before anyone else could.`; + } else if (eventSlave.anus === 0 && canDoAnal(eventSlave)) { + eventSlave.anus++; + VCheck.Anal(eventSlave, 1); + return `You made sure to claim <span class="virginity loss">${his} anal cherry</span> before anyone else could.`; + } + } + + function H24() { + r = []; + r.push(`You give ${contextualIntro(V.PC, eventSlave)} no indication that ${his} public use assignment is about to change. Late in the day, when ${his} shift would normally end, another of your slaves simply maintains ${him} as usual and then leaves ${him} be. ${eventSlave.slaveName} is so deprived of any way to tell time that ${he} doesn't realize ${he}'s been left for some time. The first indication ${he} gets that something's different is when liquid food is squirted down ${his} throat the next morning. When ${he}'s finally stripped out of the suit at the end of the week, ${he}'s pale and wan and ${his} holes are puffy and red. <span class="health dec">${His} health was damaged.</span> However, ${his} permanent presence became quite noted. <span class="reputation inc">Your reputation has increased.</span> And when ${he}'s out of the suit, ${he} instantly begs you to allow ${him} to do anything to save ${himself} from more of that. <span class="trust dec">${His} fear of you has increased.</span>`); + r.push(popCherry()); + repX(500, "event", eventSlave); + healthDamage(eventSlave, 10); + eventSlave.trust -= 10; + if (canDoVaginal(eventSlave)) { + seX(eventSlave, "vaginal", "public", "penetrative", 10); + if (!canDoAnal(eventSlave)) { + seX(eventSlave, "vaginal", "public", "penetrative", 10); + } + if (canGetPregnant(eventSlave) && eventSlave.eggType === "human") { + r.push(knockMeUp(eventSlave, 10, 2, -2)); + } + } + if (canDoAnal(eventSlave)) { + seX(eventSlave, "anal", "public", "penetrative", 10); + if (!canDoVaginal(eventSlave)) { + seX(eventSlave, "anal", "public", "penetrative", 10); + } + if (canGetPregnant(eventSlave) && eventSlave.eggType === "human") { + r.push(knockMeUp(eventSlave, 10, 1, -2)); + } + } + seX(eventSlave, "oral", "public", "penetrative", 10); + return r; + } + + function firstLast() { + r = []; + r.push(`When ${contextualIntro(V.PC, eventSlave)} feels a cock entering ${his} mouth right after ${he}'s suited up, ${he} knows it's you and wriggles as best ${he} can in the suit. It doesn't help much, and ${his} struggles don't prevent you from moving from ${his} mouth to ${his} ass, either. At the end of the day, on the other hand, the`); + // There is a function planned for this in the male slave overhaul. DO NOT FORGET IT! + if (girl === "girl") { + r.push(`female-shaped`); + } else { + r.push(`male-shaped`); + } + r.push(`latex form is completely still and quiescent as you`); + if (V.PC.dick === 0) { + r.push(`use a couple of fingers to brutally molest`); + } else { + r.push(`molest`); + } + r.push(`each of its holes. It takes`); + if (canDoVaginal(eventSlave)) { + r.push(`a serious vaginal reaming`); + } else { + r.push(`viciously hard anal penetration`); + } + r.push(`to elicit any response at all, and even then, it's just the slightest hint of a moan. <span class="trust dec">${His} fear of you has increased.</span>`); + r.push(popCherry()); + eventSlave.trust -= 5; + if (canDoVaginal(eventSlave)) { + seX(eventSlave, "vaginal", "public", "penetrative", 6); + if (!canDoAnal(eventSlave)) { + seX(eventSlave, "vaginal", "public", "penetrative", 3); + } + if (canGetPregnant(eventSlave) && eventSlave.eggType === "human") { + r.push(knockMeUp(eventSlave, 10, 2, -2)); + } + } + if (canDoAnal(eventSlave)) { + seX(eventSlave, "anal", "public", "penetrative", 6); + if (!canDoVaginal(eventSlave)) { + seX(eventSlave, "anal", "public", "penetrative", 3); + } + if (canGetPregnant(eventSlave) && eventSlave.eggType === "human") { + r.push(knockMeUp(eventSlave, 10, 1, -2)); + } + } + seX(eventSlave, "oral", "public", "penetrative", 7); + + return r; + } + + function arcade() { + r = []; + r.push(`When ${he} realizes what ${his} punishment is, ${contextualIntro(V.PC, eventSlave)} ${canTalk(eventSlave) ? "screams and " : ""}begs, but you are obdurate.`); + if (eventSlave.muscles > 30) { + r.push(`${His} powerful form has to be sedated for immurement in the arcade.`); + } else if ((eventSlave.weight >= 190)) { + r.push(`${He} is so massively fat that immuring ${him} in the arcade is a struggle, even when ${he} isn't trying to.`); + } else if (eventSlave.belly >= 120000) { + r.push(`${He} is so enormously gravid that immuring ${him} in the arcade is a hassle, even though ${his} ${bellyAdjective(eventSlave)} middle limits ${his} ability to struggle.`); + } else if ((eventSlave.weight >= -10)) { + r.push(`${His} desperate struggles make immuring ${him} in the arcade difficult.`); + } else if (eventSlave.belly >= 1500) { + r.push(`${His}`); + if (eventSlave.bellyPreg >= 3000) { + r.push(`pregnant`); + } else { + r.push(bellyAdjective(eventSlave)); + } + r.push(`body makes it slightly difficult to fit ${him} properly into the restraints for immurement in the arcade.`); + } else if (eventSlave.muscles < -15) { + r.push(`${His} weak body makes immuring ${him} in the arcade pathetically easy.`); + } else { + r.push(`${His} thin form makes immuring ${him} in the arcade pathetically easy.`); + } + r.push(`After ${he}'s properly confined, the only sign of ${his} discomfiture is a slight movement of ${his} butt as ${he} wriggles desperately against ${his} restraints.`); + r.push(assignJob(eventSlave, Job.ARCADE)); + eventSlave.sentence = 4; + return r; + } + } +}; diff --git a/src/events/debugEvent.js b/src/events/debugEvent.js index b234a208670a411d4996e248d23a287d82a6e1c1..044296df3cd22972560e1af6f1ffa9e53945eadf 100644 --- a/src/events/debugEvent.js +++ b/src/events/debugEvent.js @@ -27,8 +27,20 @@ App.Events.debugEvent = function(eventName) { function makeActorList() { const actors = document.createDocumentFragment(); const actorReqs = event.actorPrerequisites(); - for (let i = 0; i < actorReqs.length; ++i) { - let tab = App.UI.DOM.appendNewElement("div", actors); // TODO: put these in tabs? + if (actorReqs.length === 1) { + actors.append(singleActorList(0)); + } else { + const tabBar = new App.UI.Tabs.TabBar("Options"); + for (let i = 0; i < actorReqs.length; ++i) { + tabBar.addTab(`Actor ${i}`, `actor${i}`, singleActorList(i)); + } + actors.append(tabBar.render()); + } + + return actors; + + function singleActorList(i) { + let tab = App.UI.DOM.makeElement("div"); for (const slave of V.slaves) { let slaveDiv = App.UI.DOM.appendNewElement("div", tab, App.UI.DOM.makeElement("span", SlaveFullName(slave), "slave-name")); let slaveFails = false; @@ -42,8 +54,8 @@ App.Events.debugEvent = function(eventName) { } App.UI.DOM.appendNewElement("hr", tab); } + return tab; } - return actors; } function castSlave(slave, index) { diff --git a/src/events/intro/introSummary.js b/src/events/intro/introSummary.js index 4841494db14a3bddc92cbc3eb37678d63ff37afc..d1b201b38fa65a75671c694152c8ce1d447ad94e 100644 --- a/src/events/intro/introSummary.js +++ b/src/events/intro/introSummary.js @@ -3,7 +3,7 @@ App.Intro.summary = function() { V.neighboringArcologies = variableAsNumber(V.neighboringArcologies, 0, 8, 3); V.FSCreditCount = variableAsNumber(V.FSCreditCount, 4, 7, 5); - V.PC.actualAge = variableAsNumber(V.PC.actualAge, 14, 80, 35); + V.PC.actualAge = variableAsNumber(V.PC.actualAge, 10, 80, 35); V.PC.birthWeek = variableAsNumber(V.PC.birthWeek, 0, 51, 0); el.append(introContent()); @@ -372,28 +372,30 @@ App.Intro.summary = function() { } else if (V.PC.rumor === "force") { V.PC.muscles += 20; } - } + // I hope this works + PCDatatypeCleanup(V.PC); - if (V.PC.dick !== 0) { - V.PC.geneticQuirks.wellHung = 2; - } else { - V.PC.balls = 0; - V.PC.scrotum = 0; - V.PC.prostate = 0; - } - if (V.PC.title === 0) { - V.PC.hLength = 15; - V.PC.waist = -20; - V.PC.voice = 2; - V.PC.shoulders = -1; - V.PC.hips = 1; - } - if (V.PC.vagina === -1) { - V.PC.ovaries = 0; - } else if (V.PC.vagina > 0) { - V.PC.vaginaLube = 1; + if (V.PC.dick >= 3) { + V.PC.geneticQuirks.wellHung = 2; + } + if (V.PC.title === 0) { + V.PC.hLength = 15; + V.PC.waist = -20; + V.PC.voice = 2; + } + if (V.PC.eye.right.vision === 1 || V.PC.eye.left.vision === 1) { + V.PC.eyewear = "corrective glasses"; + } + if (V.PC.pubertyXX === 0 && V.PC.pubertyXY === 0) { + if (V.PC.age < 11) { + V.PC.energy = 20; + } else if (V.PC.age < 12) { + V.PC.energy = 30; + } else if (V.PC.age < 13) { + V.PC.energy = 40; + } + } } - V.PC.ovaryAge = V.PC.physicalAge; V.PC.birthName = V.PC.slaveName; V.PC.birthSurname = V.PC.slaveSurname; diff --git a/src/events/intro/pcAppearance.js b/src/events/intro/pcAppearance.js index 47f9ba6e9f959aa667032a0587569ec817ce169d..188d9d15eaee76c9fb3cc0a1f9d6d1027df84b4e 100644 --- a/src/events/intro/pcAppearance.js +++ b/src/events/intro/pcAppearance.js @@ -1,6 +1,8 @@ App.UI.Player = {}; -App.UI.Player.appearance = function(options) { +App.UI.Player.appearance = function(options, summary = false) { + let option; + options.addOption("Your nationality is", "nationality", V.PC).showTextBox() .addValueList(App.Data.misc.baseNationalities) .addComment("For best result capitalize it.").pulldown(); @@ -13,6 +15,23 @@ App.UI.Player.appearance = function(options) { .addValueList(Array.from(App.Data.misc.filterRaces, (k => [k[1], k[0]]))); } + options.addOption("You are genetically", "genes", V.PC) + .addValue("XY").addValue("XX"); + + options.addOption(`You are`, "height", V.PC).showTextBox({unit: "cm"}) + .addRange(145, 150, "<", "Petite") + .addRange(155, 160, "<", "Short") + .addRange(165, 170, "<", "Average") + .addRange(180, 185, "<", "Tall") + .addRange(190, 185, ">=", "Very tall") + .addComment(`Average height for a ${V.PC.actualAge} year old is ${heightToEitherUnit(Math.round(Height.mean(V.PC)))}`); + option = options.addCustomOption() + .addButton( + "Make average", + () => resyncSlaveHight(V.PC), + "" + ); + options.addOption("Your skin tone is", "skin", V.PC).showTextBox() .addValueList(makeAList(App.Medicine.Modification.naturalSkins)); @@ -21,12 +40,6 @@ App.UI.Player.appearance = function(options) { .addValueList(makeAList(App.Medicine.Modification.naturalSkins)); } - options.addOption("Your body", "markings", V.PC) - .addValueList([["Is clear of blemishes", "none"], ["Has light freckling", "freckles"], ["Has heavy freckling", "heavily freckled"]]); - - options.addOption("Your genetic eye color is", "origColor", V.PC.eye).showTextBox() - .addValueList(makeAList(App.Medicine.Modification.eyeColor.map(color => color.value))); - if (V.cheatMode) { options.addOption("Your original hair is", "origHColor", V.PC).showTextBox() .addValueList(makeAList(App.Medicine.Modification.Color.Primary.map(color => color.value))); @@ -35,11 +48,440 @@ App.UI.Player.appearance = function(options) { .addValueList(makeAList(App.Medicine.Modification.Color.Primary.map(color => color.value))); } + options.addOption("Your genetic eye color is", "origColor", V.PC.eye).showTextBox() + .addValueList(makeAList(App.Medicine.Modification.eyeColor.map(color => color.value))); + + options.addOption("You", "vision", V.PC.eye.right) + .addValueList([ + ["Need glasses to see properly", 1, () => { V.PC.eye.right.vision = 1; V.PC.eye.left.vision = 1; }], + ["have normal vision", 2, () => { V.PC.eye.right.vision = 2; V.PC.eye.left.vision = 2; }] + ]); + + options.addOption("Your face is", "faceShape", V.PC) + .addValueList([ + ["Normal", "normal"], + ["Androgynous", "androgynous"], + ["Masculine", "masculine"], + ["Cute", "cute"], + ["Sensual", "sensual"], + ["Exotic", "exotic"] + ]); + + options.addOption("Your body", "markings", V.PC) + .addValueList([["Is clear of blemishes", "none"], ["Has light freckling", "freckles"], ["Has heavy freckling", "heavily freckled"]]); + + options.addOption("You have", "lips", V.PC).addValue("Thin lips", 5) + .addValueList([ + ["Normal lips", 15], + ["Kissable lips", 25], + ["Plush lips", 45], + ]); + + /* Handled by career currently + options.addOption("You are", "weight", V.PC).addValue("Very thin", -50); + options.addValueList([ + ["Thin", -20], + ["Healthy", 0], + ["Curvy", 20], + ["Chubby", 60], + ["Fat", 100], + ]) + .showTextBox(); + */ + + option = options.addOption("Your shoulders are", "shoulders", V.PC).addValue("Very narrow", -2); + option.addValueList([ + ["Narrow", -1], + ["Average", 0], + ]); + if (V.PC.physicalAge > 13) { + option.addValue("Broad", 1); + } + if (V.PC.physicalAge > 18) { + option.addValue("Very broad", 2); + } + + if (V.PC.boobs >= 200 || summary) { + if (V.PC.title === 1 && V.PC.boobs <= 200) { + option = options.addOption("Your chest is", "boobs", V.PC).addValue("Manly", 200, () => { V.PC.boobsImplant = 0; V.PC.boobsImplantType = "none"; }); + } else { + option = options.addOption("Your breasts are", "boobs", V.PC).addValue("Non-existent", 200, () => { V.PC.boobsImplant = 0; V.PC.boobsImplantType = "none"; }); + } + option.addValueList([ + ["A-cups", 300], + ["B-cups", 400], + ["C-cups", 500], + ]); + if (V.PC.physicalAge <= 13) { + option.addValueList([ + ["hefty D-cups", 650], + ["heavy DD-cups", 900], + ]); + } else { + option.addValueList([ + ["D-cups", 650], + ["DD-cups", 900], + ["F-cups", 1100], + ["G-cups", 1300] + ]); + } + option.showTextBox({unit: "CCs"}); + if (V.PC.boobs >= 500) { + options.addOption("Your breasts are", "boobsImplant", V.PC) + .addValueList([ + ["All natural", 0, () => { V.PC.boobsImplant = 0; V.PC.boobsImplantType = "none"; }], + ["Fake", V.PC.boobs / 2, () => V.PC.boobsImplantType = "normal"] + ]); + } + if (V.PC.boobsImplant > 0) { + option = options.addOption("You have", "boobsImplantType", V.PC).addValue("Regular implants", "normal"); + if (V.PC.boobsImplant > 400) { + option.addValue("string implants", "string"); + } + if (V.PC.boobsImplant > 600) { + option.addValue("Fillable implants", "fillable"); + } + } + if (V.PC.boobs >= 300) { + option = options.addOption("Your nipples are", "nipples", V.PC).addValue("Tiny", "tiny"); + option.addValue("Cute", "cute"); + if (V.PC.boobs >= 500) { + option.addValue("Puffy", "puffy"); + option.addValue("Partially inverted", "partially inverted"); + } + if (V.PC.boobs >= 1000) { + option.addValue("Inverted", "inverted"); + option.addValue("Huge", "huge"); + } + } + } + + option = options.addOption("Your hips are", "hips", V.PC).addValue("Very narrow", -2); + option.addValueList([ + ["Narrow", -1], + ["Average", 0], + ]); + if (V.PC.physicalAge > 13) { + option.addValue("Wide", 1); + } + if (V.PC.physicalAge > 18) { + option.addValue("Very Wide", 2); + } + + + option = options.addOption("Your butt is", "butt", V.PC).addValue("Flat", 0, () => { V.PC.buttImplant = 0; V.PC.buttImplantType = "none"; }); + option.addValueList([ + ["Small", 1], + ["Plump", 2], + ["Big", 3], + ]); + if (V.PC.physicalAge > 13) { + option.addValue("Huge", 4); + } + if (V.PC.physicalAge > 18) { + option.addValueList([ + ["Enormous", 5], + ["Gigantic", 6], + ]); + } + if (V.PC.butt >= 3) { + options.addOption("Your ass is", "buttImplant", V.PC) + .addValueList([ + ["All natural", 0, () => V.PC.buttImplantType = "none"], + ["Fake", Math.round(V.PC.butt / 2), () => V.PC.buttImplantType = "normal"] + ]); + } + if (V.PC.buttImplant > 0) { + option = options.addOption("You have", "buttImplantType", V.PC).addValue("Regular implants", "normal"); + if (V.PC.buttImplant > 1) { + option.addValue("string implants", "string"); + option.addValue("Fillable implants", "fillable"); + } + } + + if (V.PC.dick !== 0) { + option = options.addOption("Your dick is", "dick", V.PC).addValue("Tiny", 1, () => V.PC.foreskin = 2); + option.addValueList([ + ["Small", 2, () => V.PC.foreskin = 3], + ["Average", 3, () => V.PC.foreskin = 3], + ["Big", 4, () => V.PC.foreskin = 4], + ]); + if (V.PC.physicalAge > 13) { + option.addValue("Huge", 5, () => V.PC.foreskin = 5); + } + if (V.PC.physicalAge > 18) { + option.addValue("Gigantic", 6, () => V.PC.foreskin = 5); + } + options.addOption("You are", "foreskin", V.PC) + .addValueList([ + ["Cut", 0], + ["Uncut", V.PC.dick] + ]) + .showTextBox() + .addComment("Any value above 0 is uncircumcised. For comfort, keep equal or one greater than dick size."); + } + + if (V.PC.balls !== 0) { + option = options.addOption("Your balls are", "balls", V.PC).addValue("Small", 2, () => V.PC.scrotum = 2); + option.addValueList([ + ["Average", 3, () => V.PC.scrotum = 4], + ["Large", 4, () => V.PC.scrotum = 5], + ]); + if (V.PC.physicalAge > 13) { + option.addValue("Massive", 5, () => V.PC.scrotum = 5); + } + if (V.PC.physicalAge > 18) { + option.addValue("Huge", 6, () => V.PC.scrotum = 6); + } + option.addComment("Small balls may be located internally."); + if (V.PC.balls <= 2) { + options.addOption("Your balls are", "scrotum", V.PC) + .addValueList([ + ["Internal", 0], + ["External", V.PC.balls] + ]) + .showTextBox() + .addComment("Any value above 0 is external. For comfort, keep equal or one greater than ball size."); + } + if (V.PC.physicalAge < 14) { + options.addOption("You are", "pubertyXY", V.PC) + .addValueList([["Not producing potent sperm yet", 0], ["Producing potent sperm", 1]]); + } + } + + if (V.PC.vagina !== -1) { + if (V.PC.dick === 0 && V.PC.physicalAge > 13) { + options.addOption("Your clit is", "clit", V.PC) + .addValueList([["Normal", 0], ["Large", 1], ["Huge", 2]]); + } + if (V.PC.physicalAge <= 18) { + options.addOption("You are", "vagina", V.PC) + .addValueList([["A virgin", 0], ["Not a virgin", 1]]); + if (V.PC.physicalAge < 14 && V.PC.preg <= 0) { + options.addOption("You have", "pubertyXX", V.PC) + .addValueList([["Not had your first period", 0], ["Had your first period", 1]]); + } + } + } + + options.addOption("You are", "anus", V.PC) + .addValueList([["An anal virgin", 0], ["Not an anal virgin", 1]]); + function makeAList(iterable) { return Array.from(iterable, (k => [capFirstChar(k), k])); } }; +App.UI.Player.syncAgeBasedParameters = function() { + V.PC.actualAge = Math.clamp(V.PC.actualAge, 10, 80); + V.PC.physicalAge = V.PC.actualAge; + V.PC.visualAge = V.PC.actualAge; + V.PC.ovaryAge = V.PC.actualAge; + V.PC.height = Math.round(Height.random(V.PC, {limitMult: [2, 4]})); + if (V.PC.genes === "XY") { + if (V.PC.physicalAge <= 13) { + V.PC.hips = -2; + V.PC.shoulders = -1; + V.PC.butt = 0; + V.PC.boobs = 100; + if (V.PC.vagina !== -1) { + V.PC.vagina = 0; + V.PC.vaginaLube = 0; + if (V.PC.preg <= 0) { + V.PC.pubertyXX = 0; + } + } + V.PC.pregAdaptation = 10; + if (V.PC.dick !== 0) { + V.PC.dick = 2; + V.PC.balls = 2; + V.PC.scrotum = V.PC.balls + 1; + V.PC.foreskin = V.PC.dick; + V.PC.pubertyXY = 0; + } + } else if (V.PC.physicalAge <= 18) { + V.PC.hips = -2; + V.PC.shoulders = 0; + V.PC.butt = 1; + V.PC.boobs = 200; + if (V.PC.vagina !== -1) { + V.PC.vagina = 1; + V.PC.vaginaLube = 0; + V.PC.pubertyXX = 1; + } + V.PC.pregAdaptation = 15; + if (V.PC.dick !== 0) { + V.PC.dick = 3; + V.PC.balls = 3; + V.PC.scrotum = V.PC.balls; + V.PC.foreskin = V.PC.dick; + V.PC.pubertyXY = 1; + } + } else { + V.PC.hips = -1; + V.PC.shoulders = 1; + V.PC.butt = 2; + V.PC.boobs = 200; + if (V.PC.vagina !== -1) { + V.PC.vagina = 1; + V.PC.vaginaLube = 1; + V.PC.pubertyXX = 1; + } + V.PC.pregAdaptation = 20; + if (V.PC.dick !== 0) { + V.PC.dick = 4; + V.PC.balls = 3; + V.PC.scrotum = V.PC.balls + 1; + V.PC.foreskin = V.PC.dick; + V.PC.pubertyXY = 1; + } + } + } else { + if (V.PC.physicalAge <= 13) { + V.PC.hips = -2; + V.PC.shoulders = -2; + V.PC.butt = 0; + V.PC.boobs = 350; + if (V.PC.vagina !== -1) { + V.PC.vagina = 0; + V.PC.vaginaLube = 0; + if (V.PC.preg <= 0) { + V.PC.pubertyXX = 0; + } + } + V.PC.pregAdaptation = 30; + if (V.PC.dick !== 0) { + V.PC.dick = 2; + V.PC.balls = 2; + V.PC.scrotum = V.PC.balls + 1; + V.PC.foreskin = V.PC.dick; + V.PC.pubertyXY = 0; + } + } else if (V.PC.physicalAge <= 18) { + V.PC.hips = 0; + V.PC.shoulders = -1; + V.PC.butt = 1; + V.PC.boobs = 600; + if (V.PC.vagina !== -1) { + V.PC.vagina = 1; + V.PC.vaginaLube = 1; + V.PC.pubertyXX = 1; + } + V.PC.pregAdaptation = 50; + if (V.PC.dick !== 0) { + V.PC.dick = 3; + V.PC.balls = 3; + V.PC.scrotum = V.PC.balls; + V.PC.foreskin = V.PC.dick; + V.PC.pubertyXY = 1; + } + } else { + V.PC.hips = 1; + V.PC.shoulders = 0; + V.PC.butt = 2; + V.PC.boobs = 900; + if (V.PC.vagina !== -1) { + V.PC.vagina = 1; + V.PC.vaginaLube = 1; + V.PC.pubertyXX = 1; + } + V.PC.pregAdaptation = 50; + if (V.PC.dick !== 0) { + V.PC.dick = 4; + V.PC.balls = 3; + V.PC.scrotum = V.PC.balls + 1; + V.PC.foreskin = V.PC.dick; + V.PC.pubertyXY = 1; + } + } + if (V.PC.boobs < 250) { + V.PC.nipples = "tiny"; + } else if (V.PC.boobs < 1000) { + V.PC.nipples = "cute"; + } else { + V.PC.nipples = "puffy"; + } + } +}; + +App.UI.Player.assignCareerByAge = function(selection) { + let career; + + if (V.disableForcedCareers || V.PC.actualAge >= 22) { + career = selection; + } else if (selection === "wealth") { + if (V.PC.actualAge < 14) { + career = "rich kid"; + } else { + career = "trust fund"; + } + } else if (selection === "capitalist") { + if (V.PC.actualAge < 14) { + career = "business kid"; + } else { + career = "entrepreneur"; + } + } else if (selection === "mercenary") { + if (V.PC.actualAge < 14) { + career = "child soldier"; + } else { + career = "recruit"; + } + } else if (selection === "slaver") { + if (V.PC.actualAge < 14) { + career = "slave tender"; + } else { + career = "slave overseer"; + } + } else if (selection === "engineer") { + if (V.PC.actualAge < 14) { + career = "worksite helper"; + } else { + career = "construction"; + } + } else if (selection === "medicine") { + if (V.PC.actualAge < 14) { + career = "nurse"; + } else { + career = "medical assistant"; + } + } else if (selection === "celebrity") { + if (V.PC.actualAge < 14) { + career = "child star"; + } else { + career = "rising star"; + } + } else if (selection === "BlackHat") { + if (V.PC.actualAge < 14) { + career = "script kiddy"; + } else { + career = "hacker"; + } + } else if (selection === "escort") { + if (V.PC.actualAge < 14) { + career = "child prostitute"; + } else { + career = "prostitute"; + } + } else if (selection === "servant") { + if (V.PC.actualAge < 14) { + career = "child servant"; + } else { + career = "handmaiden"; + } + } else if (selection === "gang") { + if (V.PC.actualAge < 14) { + career = "street urchin"; + } else { + career = "hoodlum"; + } + } + + V.disableForcedCareers = null; + + return career; +}; + App.UI.Player.refreshmentChoice = function(options) { let option = options.addOption("Your preferred refreshment is", "refreshmentType", V.PC); for (const [key, value] of App.Data.player.refreshmentType) { @@ -112,6 +554,12 @@ App.UI.Player.design = function() { .addRange(55, 65, "<", "Well into middle age").addRange(70, 65, ">=", "Old"); options.addOption(`Your birthday was <strong>${V.PC.birthWeek}</strong> weeks ago.`, "birthWeek", V.PC).showTextBox(); + option = options.addCustomOption() + .addButton( + "Adjust body to match age", + () => App.UI.Player.syncAgeBasedParameters(), + "" + ); } } else { r = []; @@ -123,15 +571,19 @@ App.UI.Player.design = function() { } r.push(`and everyone that matters calls you ${PlayerName()}.`); - r.push(`You are ${V.PC.actualAge} years old which is`); + r.push(`You are ${V.PC.actualAge} years old, which is`); if (V.PC.actualAge >= 65) { r.push(`<strong>old</strong>.`); } else if (V.PC.actualAge >= 50) { r.push(`<strong>well into middle age</strong>.`); } else if (V.PC.actualAge >= 35) { r.push(`<strong>entering middle age</strong>.`); - } else { + } else if (V.PC.actualAge >= 22) { r.push(`<strong>surprisingly young</strong>.`); + } else if (V.PC.actualAge >= 14) { + r.push(`<strong>exceedingly young</strong>.`); + } else { + r.push(`<strong>merely a child</strong>.`); } App.Events.addNode(el, r, "p"); } @@ -161,21 +613,51 @@ App.UI.Player.design = function() { // Appearance if (allowEdits) { - App.UI.Player.appearance(options); + if (V.PC.vagina !== -1 && V.PC.dick !== 0) { + State.temporary.vaginaPenis = 2; + } else if (V.PC.vagina !== -1) { + State.temporary.vaginaPenis = 1; + } else { + State.temporary.vaginaPenis = 0; + } - options.addOption("Your face is", "faceShape", V.PC) - .addValueList([ - ["Normal", "normal"], - ["Androgynous", "androgynous"], - ["Masculine", "masculine"], - ["Cute", "cute"], - ["Sensual", "sensual"], - ["Exotic", "exotic"] - ]); + option = options.addOption("You have a", "vaginaPenis", State.temporary) + .addValue("Penis", 0, () => { + V.PC.preg = 0; + V.PC.pregType = 0; + V.PC.dick = 4; + V.PC.balls = 3; + V.PC.scrotum = 3; + V.PC.prostate = 1; + V.PC.vagina = -1; + V.PC.ovaries = 0; + }).addValue("Vagina", 1, () => { + V.PC.dick = 0; + V.PC.balls = 0; + V.PC.scrotum = 0; + V.PC.prostate = 0; + V.PC.vagina = 1; + V.PC.ovaries = 1; + }).addValue("Penis and Vagina", 2, () => { + V.PC.dick = 4; + V.PC.balls = 3; + V.PC.scrotum = 3; + V.PC.prostate = 1; + V.PC.vagina = 1; + V.PC.ovaries = 1; + }); + if (State.temporary.vaginaPenis === 0) { + option.addComment("Standard sex scenes; easiest reputation maintenance."); + } else if (State.temporary.vaginaPenis === 1) { + option.addComment("Sex scene variations; most difficult reputation maintenance."); + } else { + option.addComment("Sex scene variations; more difficult reputation maintenance; some unique opportunities, especially with breasts."); + } + App.UI.Player.appearance(options, true); } else { r = []; - r.push(`You are a ${V.PC.nationality} ${V.PC.race} with`); + r.push(`You are a ${heightToEitherUnit(V.PC.height)} tall ${V.PC.nationality} ${V.PC.race} with`); if (V.PC.markings === "heavily freckled") { r.push(`heavily freckled`); } else if (V.PC.markings === "freckles") { @@ -183,7 +665,18 @@ App.UI.Player.design = function() { } else { r.push(`clear`); } - r.push(`${V.PC.skin} skin, ${V.PC.hColor} hair and ${App.Desc.eyesColor(V.PC)}. You have a ${V.PC.faceShape} face.`); + r.push(`${V.PC.skin} skin, ${V.PC.hColor} hair and ${App.Desc.eyesColor(V.PC)}. You have a ${V.PC.faceShape}`); + if (V.PC.lips > 95) { + r.push(`face with way too much lip; you can't shut your mouth properly anymore.`); + } else if (V.PC.lips > 70) { + r.push(`face with truly massive lips.`); + } else if (V.PC.lips > 40) { + r.push(`face with plump lips.`); + } else if (V.PC.lips > 20) { + r.push(`face with full lips.`); + } else { + r.push(`face.`); + } App.Events.addNode(el, r, "p"); } @@ -209,40 +702,35 @@ App.UI.Player.design = function() { ["Servant", "servant"], ["Gang leader", "gang"]] ); + option = options.addCustomOption() + .addButton( + "Adjust career for age", + () => V.PC.career = App.UI.Player.assignCareerByAge(V.PC.career), + "" + ); if (V.secExpEnabled > 0) { - switch (V.PC.career) { - case "capitalist": - option.addComment(`<div><span class="yellowgreen">The propaganda hub's upgrades will be cheaper.</span></div>`); - break; - case "mercenary": - option.addComment(`<div><span class="green">Easier to maintain security</span> and <span class="yellowgreen">the security HQ's upgrades will be cheaper.</span></div>`); - break; - case "slaver": - option.addComment(`<div><span class="green">Easier to maintain authority</span> and <span class="yellowgreen">the security HQ's upgrades will be cheaper.</span></div>`); - break; - case "engineer": - option.addComment(`<div><span class="yellowgreen">construction and upgrade of facilities will be cheaper.</span></div>`); - break; - case "medicine": - option.addComment(`<div><span class="yellowgreen">Drug upgrades will be cheaper.</span></div>`); - break; - case "celebrity": - option.addComment(`<div><span class="yellowgreen">The propaganda hub's upgrades will be cheaper.</span></div>`); - break; - case "escort": - option.addComment(`<div><span class="red">Harder to maintain authority.</span></div>`); - break; - case "servant": - option.addComment(`<div><span class="red">Harder to maintain authority.</span></div>`); - break; - case "gang": - option.addComment(`<div><span class="green">Easier to maintain authority</span> and <span class="yellowgreen">the security HQ's upgrades will be cheaper.</span></div>`); - break; - case "BlackHat": - option.addComment(`<div><span class="red">Harder to maintain authority.</span></div>`); - break; - default: - option.addComment(`<div><span class="red">Harder to maintain authority,</span> but <span class="yellowgreen">the propaganda hub's upgrades will be cheaper.</span></div>`); + if (isPCCareerInCategory("capitalist")) { + option.addComment(`<div><span class="yellowgreen">The propaganda hub's upgrades will be cheaper.</span></div>`); + } else if (isPCCareerInCategory("mercenary")) { + option.addComment(`<div><span class="green">Easier to maintain security</span> and <span class="yellowgreen">the security HQ's upgrades will be cheaper.</span></div>`); + } else if (isPCCareerInCategory("slaver")) { + option.addComment(`<div><span class="green">Easier to maintain authority</span> and <span class="yellowgreen">the security HQ's upgrades will be cheaper.</span></div>`); + } else if (isPCCareerInCategory("engineer")) { + option.addComment(`<div><span class="yellowgreen">construction and upgrade of facilities will be cheaper.</span></div>`); + } else if (isPCCareerInCategory("medicine")) { + option.addComment(`<div><span class="yellowgreen">Drug upgrades will be cheaper.</span></div>`); + } else if (isPCCareerInCategory("celebrity")) { + option.addComment(`<div><span class="yellowgreen">The propaganda hub's upgrades will be cheaper.</span></div>`); + } else if (isPCCareerInCategory("escort")) { + option.addComment(`<div><span class="red">Harder to maintain authority.</span></div>`); + } else if (isPCCareerInCategory("servant")) { + option.addComment(`<div><span class="red">Harder to maintain authority.</span></div>`); + } else if (isPCCareerInCategory("gang")) { + option.addComment(`<div><span class="green">Easier to maintain authority</span> and <span class="yellowgreen">the security HQ's upgrades will be cheaper.</span></div>`); + } else if (isPCCareerInCategory("BlackHat")) { + option.addComment(`<div><span class="red">Harder to maintain authority.</span></div>`); + } else { + option.addComment(`<div><span class="red">Harder to maintain authority,</span> but <span class="yellowgreen">the propaganda hub's upgrades will be cheaper.</span></div>`); } } } @@ -261,39 +749,81 @@ App.UI.Player.design = function() { r = []; switch (V.PC.career) { case "wealth": + case "trust fund": + case "rich kid": r.push(`Prior to being an arcology owner, you were a member of the idle wealthy.`); break; case "capitalist": r.push(`Prior to being an arcology owner, you were a business leader.`); break; + case "entrepreneur": + case "business kid": + r.push(`Prior to being an arcology owner, you were a cunning entrepreneur.`); + break; case "mercenary": + case "recruit": r.push(`Prior to being an arcology owner, you were a mercenary.`); break; + case "child soldier": + r.push(`Prior to being an arcology owner, you were a disposable conscript.`); + break; case "slaver": + case "slave overseer": r.push(`Prior to being an arcology owner, you were a slaver.`); break; + case "slave tender": + r.push(`Prior to being an arcology owner, you were a slaver tasked with looking after fresh captures.`); + break; case "engineer": r.push(`Prior to being an arcology owner, you were an engineer.`); break; + case "construction": + case "worksite helper": + r.push(`Prior to being an arcology owner, you built buildings.`); + break; case "medicine": r.push(`Prior to being an arcology owner, you were a surgeon.`); break; + case "medical assistant": + r.push(`Prior to being an arcology owner, you assisted with surgeries.`); + break; + case "nurse": + r.push(`Prior to being an arcology owner, you were a nurse.`); + break; case "celebrity": r.push(`Prior to being an arcology owner, you were a minor celebrity.`); break; + case "rising star": + r.push(`Prior to being an arcology owner, you were an up-and-coming star.`); + break; + case "child star": + r.push(`Prior to being an arcology owner, you were a child actor.`); + break; case "BlackHat": + case "hacker": + case "script kiddy": r.push(`Prior to being an arcology owner, you specialized in cracking databases and making mockeries of cyber security.`); break; case "arcology owner": r.push(`Being an arcology owner defines your life now.`); break; case "escort": + case "prostitute": r.push(`Prior to being an arcology owner, you knew how to survive off your looks and body.`); break; + case "child prostitute": + r.push(`Prior to being an arcology owner, you had no choice but to sell your body to survive.`); + break; case "servant": + case "handmaiden": + case "child servant": r.push(`Prior to being an arcology owner, you served a well-off`); - if (V.PC.counter.birthMaster >= 2) { + if (V.PC.counter.birthMaster >= 8) { + r.push(`master as his breeder.`); + } else if (V.PC.counter.birthMaster >= 2) { r.push(`master and bore him several children.`); + } else if (V.PC.counter.birthMaster >= 1) { + r.push(`master and bore him a child.`); } else { r.push(`master.`); } @@ -301,6 +831,12 @@ App.UI.Player.design = function() { case "gang": r.push(`Prior to being an arcology owner, you were the leader of a ruthless gang.`); break; + case "hoodlum": + r.push(`Prior to being an arcology owner, you were a troublemaker in a gang.`); + break; + case "street urchin": + r.push(`Prior to being an arcology owner, you lived a hard life on the streets.`); + break; } r.push(`Word in the arcology is you acquired it through`); @@ -330,47 +866,7 @@ App.UI.Player.design = function() { if (allowEdits) { options = new App.UI.OptionsGroup(); - if (V.PC.vagina !== -1 && V.PC.dick !== 0) { - State.temporary.vaginaPenis = 2; - } else if (V.PC.vagina !== -1) { - State.temporary.vaginaPenis = 1; - } else { - State.temporary.vaginaPenis = 0; - } - - option = options.addOption("You have a", "vaginaPenis", State.temporary) - .addValue("Penis", 0, () => { - V.PC.preg = 0; - V.PC.pregType = 0; - V.PC.dick = 4; - V.PC.balls = 3; - V.PC.scrotum = 3; - V.PC.prostate = 1; - V.PC.vagina = -1; - V.PC.ovaries = 0; - }).addValue("Vagina", 1, () => { - V.PC.dick = 0; - V.PC.balls = 0; - V.PC.scrotum = 0; - V.PC.prostate = 0; - V.PC.vagina = 1; - V.PC.ovaries = 1; - }).addValue("Penis and Vagina", 2, () => { - V.PC.dick = 4; - V.PC.balls = 3; - V.PC.scrotum = 3; - V.PC.prostate = 1; - V.PC.vagina = 1; - V.PC.ovaries = 1; - }); - if (State.temporary.vaginaPenis === 0) { - option.addComment("Standard sex scenes; easiest reputation maintenance."); - } else if (State.temporary.vaginaPenis === 1) { - option.addComment("Sex scene variations; most difficult reputation maintenance."); - } else { - option.addComment("Sex scene variations; more difficult reputation maintenance; some unique opportunities, especially with breasts."); - } - + // obsolete? if (V.cheatMode) { options.addOption("Vagina", "vagina", V.PC).showTextBox(); options.addOption("New vagina", "newVag", V.PC).showTextBox(); @@ -385,7 +881,7 @@ App.UI.Player.design = function() { options.addOption("Balls implant", "ballsImplant", V.PC).showTextBox(); } - if (V.PC.vagina !== -1) { + if (V.PC.vagina !== -1 && V.PC.pubertyXX === 1) { option = options.addOption("You are", "preg", V.PC) .addValue("Taking contraceptives", -1, () => { V.PC.pregType = 0; V.PC.labor = 0; }) .addValue("Not taking contraceptives", 0, () => { V.PC.pregType = 0; V.PC.labor = 0; }) @@ -438,83 +934,201 @@ App.UI.Player.design = function() { } } - if (V.PC.title === 1 && V.PC.boobs <= 100) { - option = options.addOption("Your chest is", "boobs", V.PC).addValue("Manly", 100, () => V.PC.boobsImplant = 0); + el.append(options.render()); + } else { + r = []; + + if (V.PC.boobs >= 300) { + r.push(`You have a`); + if (V.PC.title > 0) { + r.push(`masculine`); + } else { + r.push(`feminine`); + } + r.push(`body with`); + if (V.PC.shoulders > 1) { + r.push(`very broad shoulders`); + } else if (V.PC.shoulders > 0) { + r.push(`broad shoulders`); + } else if (V.PC.shoulders < -1) { + r.push(`very narrow shoulders`); + } else if (V.PC.shoulders < 0) { + r.push(`narrow shoulders`); + } + if (V.PC.shoulders !== 0) { + r.push(`and`); + } + let breastShapeDesc; + if (V.PC.boobShape === "saggy") { + breastShapeDesc = ` that sag a bit`; + } else if (V.PC.boobShape === "spherical") { + breastShapeDesc = ` that might just be a little too much implant now.`; + } + if (V.PC.boobs >= 1400) { + r.push(`giant${(V.PC.boobsImplant !== 0) ? `, fake` : ``} cow tits${breastShapeDesc}.`); + } else if (V.PC.boobs >= 1200) { + r.push(`huge`); + if (V.PC.boobsImplant !== 0) { + r.push(`fake`); + } + r.push(`breasts${breastShapeDesc}.`); + } else if (V.PC.boobs >= 1000) { + r.push(`big`); + if (V.PC.boobsImplant !== 0) { + r.push(`fake`); + } + r.push(`breasts${breastShapeDesc}.`); + } else if (V.PC.boobs >= 800) { + r.push(`noticeable breasts${breastShapeDesc}.`); + } else if (V.PC.boobs >= 650) { + r.push(`unremarkable breasts${breastShapeDesc}.`); + } else if (V.PC.boobs >= 500) { + r.push(`average breasts${breastShapeDesc}.`); + } else { + r.push(`small breasts${breastShapeDesc}.`); + } } else { - option = options.addOption("Your breasts are", "boobs", V.PC).addValue("Flat", 100, () => V.PC.boobsImplant = 0); + if (V.PC.title > 0) { + r.push(`You have a manly chest.`); + } else { + r.push(`You are flat as a board.`); + } } - option.addValueList([ - ["C-cups", 500], - ["DD-cups", 900], - ["F-cups", 1100], - ["G-cups", 1300] - ]); - option.showTextBox("CCs"); - - if (V.PC.boobs >= 500) { - options.addOption("Your breasts are", "boobsImplant", V.PC) - .addValueList([ - ["All natural", 0], - ["Fake", 400] - ]) - .showTextBox("CCs"); + r.push(`Around back, you have`); + if (V.PC.butt > 10) { + r.push(`a disproportionate swelling of flesh`); + } else if (V.PC.butt > 7) { + r.push(`an absurdly large butt`); + } else if (V.PC.butt > 6) { + r.push(`a ridiculous ass`); + } else if (V.PC.butt > 5) { + r.push(`a gigantic ass`); + } else if (V.PC.butt > 4) { + r.push(`an enormous ass`); + } else if (V.PC.butt > 3) { + r.push(`a huge ass`); + } else if (V.PC.butt > 2) { + r.push(`a big butt`); + } else if (V.PC.butt > 1) { + r.push(`a shapely rear`); + } else if (V.PC.butt > 0) { + r.push(`a trim rear`); + } else { + r.push(`a flat ass`); } - - if (V.cheatMode) { - if (V.PC.boobs >= 500) { - options.addOption("Your breasts are", "lactation", V.PC) - .addValueList([ - ["Lactating", 1], - ["Not Lactating", 0] - ]); - } + r.push(`attached to a pair of`); + if (V.PC.hips > 2) { + r.push(`inhumanly wide hips.`); + } else if (V.PC.hips > 1) { + r.push(`very wide hips.`); + } else if (V.PC.hips > 0) { + r.push(`wide hips.`); + } else if (V.PC.hips > -1) { + r.push(`average hips.`); + } else if (V.PC.hips > -2) { + r.push(`narrow hips.`); + } else { + r.push(`very narrow hips.`); } - options.addOption("Your butt size", "butt", V.PC) - .addValueList([ - ["Normal", 2], - ["Big", 3], - ["Huge", 4], - ["Enormous", 5], - ]) - .showTextBox(); - - options.addOption("Your butt is", "buttImplant", V.PC) - .addValueList([ - ["All natural", 0], - ["Fake", 1] - ]) - .showTextBox("CCs"); - - - options.addOption("You are genetically", "genes", V.PC) - .addValue("XY").addValue("XX"); - - el.append(options.render()); - } else { - r = []; - r.push(`You have a`); - if (V.PC.vagina !== -1 && V.PC.dick !== 0) { - r.push(`penis and vagina`); - } else if (V.PC.dick !== 0) { - r.push(`penis.`); - } else if (V.PC.vagina !== -1) { - r.push(`vagina`); + r.push(`Between your legs, you have`); + if (V.PC.dick !== 0) { + if (V.PC.dick === 1) { + r.push(`a tiny, humiliating`); + } else if (V.PC.dick === 2) { + r.push(`a small`); + } else if (V.PC.dick === 3) { + r.push(`an average`); + } else if (V.PC.dick === 4) { + r.push(`a big`); + } else if (V.PC.dick === 5) { + r.push(`a huge`); + } else if (V.PC.dick === 6) { + r.push(`a pussy wrecking`); + } else if (V.PC.dick === 7) { + r.push(`a massive, unusable`); + } else if (V.PC.dick === 8) { + r.push(`an imposing, if unusable,`); + } else if (V.PC.dick === 9) { + r.push(`a monster of a`); + } else if (V.PC.dick === 10) { + r.push(`an inhuman`); + } else { + r.push(`an unusable slab of sensitive flesh you call a`); + } + r.push(`dick`); + if (V.PC.balls !== 0) { + r.push(r.pop() + ","); + } + if (V.PC.balls === 1) { + if (V.PC.scrotum === 0) { + r.push(`a tiny pair of internal balls`); + } else { + r.push(`vestigial testicles`); + } + } else if (V.PC.balls === 2) { + if (V.PC.scrotum === 0) { + r.push(`a pair of internal balls`); + } else { + r.push(`a pair of small testicles`); + } + } else if (V.PC.balls === 3) { + r.push(`a pair of average testicles`); + } else if (V.PC.balls === 4) { + r.push(`a dangling pair of large balls`); + } else if (V.PC.balls === 5) { + r.push(`a dangling pair of heavy testicles`); + } else if (V.PC.balls === 6) { + r.push(`a heavy pair of huge balls`); + } else if (V.PC.balls === 7) { + r.push(`a ponderous set of giant testicles`); + } else if (V.PC.balls === 8) { + r.push(`a ponderous set of enormous testicles`); + } else if (V.PC.balls === 9) { + r.push(`a monstrous pair of testicles`); + } else { + r.push(`an inhuman pair of testicles`); + } + if (V.PC.vagina !== -1) { + r.push(`and`); + } else { + r.push(r.pop() + "."); + } } if (V.PC.vagina !== -1) { - r.push(`and are`); + if (V.PC.vagina === 0) { + r.push(`an unsullied`); + } else if (V.PC.vagina === 1 || V.PC.newVag === 1) { + // nothing + } else if (V.PC.vagina === 2) { + r.push(`an experienced`); + } else if (V.PC.vagina === 3) { + r.push(`a loose`); + } else if (V.PC.vagina === 4) { + r.push(`a very well-traveled`); + } else { + r.push(`a ruined`); + } + r.push(`vagina.`); + } + if (V.PC.vagina !== -1 && V.PC.mpreg !== 0) { + r.push(`You are`); if (V.PC.pregWeek < 0) { - r.push(`recovering from your last pregnancy.`); + r.push(`currently recovering from your last pregnancy.`); } else if (V.PC.preg === -2) { - r.push(`infertile.`); + r.push(`infertile and can't get pregnant.`); } else if (V.PC.preg === -1) { - r.push(`taking contraceptives.`); + r.push(`taking contraceptives to avoid potential pregnancy.`); } else if (V.PC.preg === 0) { - r.push(`fertile.`); + if (V.PC.pubertyXX === 0) { + r.push(`not yet fertile.`); + } else { + r.push(`fertile and capable of becoming pregnant.`); + } } else if (V.PC.preg > 37) { - r.push(`extremely pregnant.`); + r.push(`extremely pregnant and likely to give birth soon.`); } else if (V.PC.preg > 0) { - r.push(`pregnant.`); + r.push(`currently pregnant.`); } linkArray = []; @@ -548,44 +1162,6 @@ App.UI.Player.design = function() { } } - if (V.PC.boobs >= 300) { - r.push(`You have a`); - if (V.PC.title > 0) { - r.push(`masculine`); - } else { - r.push(`feminine`); - } - r.push(`body with`); - if (V.PC.boobs >= 1400) { - r.push(`giant${(V.PC.boobsImplant !== 0) ? `, fake` : ``} cow tits.`); - } else if (V.PC.boobs >= 1200) { - r.push(`huge`); - if (V.PC.boobsImplant !== 0) { - r.push(`fake`); - } - r.push(`breasts.`); - } else if (V.PC.boobs >= 1000) { - r.push(`big`); - if (V.PC.boobsImplant !== 0) { - r.push(`fake`); - } - r.push(`breasts.`); - } else if (V.PC.boobs >= 800) { - r.push(`noticeable breasts.`); - } else if (V.PC.boobs >= 650) { - r.push(`unremarkable breasts.`); - } else if (V.PC.boobs >= 500) { - r.push(`average breasts.`); - } else { - r.push(`small breasts.`); - } - } else { - if (V.PC.title > 0) { - r.push(`You have a manly chest.`); - } else { - r.push(`You are flat as a board.`); - } - } App.Events.addNode(el, r, "p"); } diff --git a/src/events/intro/pcAppearanceIntro.tw b/src/events/intro/pcAppearanceIntro.tw index 3854ab1ddaba89663f214985123f95b35b00ad02..e982aa0d9f2fba6a8a77381876e23bbf9fe15557 100644 --- a/src/events/intro/pcAppearanceIntro.tw +++ b/src/events/intro/pcAppearanceIntro.tw @@ -3,7 +3,7 @@ <p> Race and appearance are largely irrelevant in the Free Cities; there are only the free and the enslaved. <div class="indent note"> - Appearance only, no effect on gameplay (unless you make a big deal out of it). + Appearance only, will mostly have a superficial effect (unless you make a big deal out of it). </div> </p> <<set _options = new App.UI.OptionsGroup()>> @@ -11,5 +11,9 @@ <<includeDOM _options.render()>> <p> - [[Finish player character customization|PC Experience Intro][resetEyeColor($PC)]] + <<if isFertile(V.PC)>> + [[Continue player character customization|PC Preg Intro][resetEyeColor($PC)]] + <<else>> + [[Finish player character customization|PC Experience Intro][resetEyeColor($PC)]] + <</if>> </p> diff --git a/src/events/intro/pcBodyIntro.js b/src/events/intro/pcBodyIntro.js index 187dd896654d64c5c0566bd03ea4b485aac01227..1dd639982445185ea0ed73fe42d1ceb5bc6e9023 100644 --- a/src/events/intro/pcBodyIntro.js +++ b/src/events/intro/pcBodyIntro.js @@ -1,7 +1,6 @@ App.Intro.PCBodyIntro = function() { + V.PC.actualAge = Math.clamp(V.PC.actualAge, 14, 80); - V.PC.physicalAge = V.PC.actualAge; - V.PC.visualAge = V.PC.actualAge; const el = new DocumentFragment(); let r = []; @@ -42,7 +41,7 @@ App.Intro.PCBodyIntro = function() { // Chest options.addOption("Under my suit jacket", "boobs", V.PC) - .addValue((V.PC.title > 0) ? `Masculine muscles` : `A flat chest`, 100) + .addValue((V.PC.title > 0) ? `Masculine muscles` : `A flat chest`, 200) .addValue("Feminine breasts", 900) .addComment("These options will affect scenes. Sporting breasts will increase difficulty"); @@ -121,19 +120,23 @@ App.Intro.PCBodyIntro = function() { App.UI.DOM.appendNewElement("div", el, `How old are you?`, ["intro", "question"]); const r = []; - r.push(`I'm`); + r.push(`You're`); if (V.PC.actualAge >= 65) { - r.push(`getting up in years. I've made a legacy for myself, and I'm not done yet.`); + r.push(`getting up in years. You've made a legacy for myself, and not done with life just yet.`); } else if (V.PC.actualAge >= 50) { - r.push(`well into middle age. I've made a name for myself, and I've still got it.`); + r.push(`well into middle age. You've made a name for myself, and still got your groove.`); } else if (V.PC.actualAge >= 35) { - r.push(`entering middle age. I'm accomplished, and I retain some youthful vigor.`); + r.push(`entering middle age. You're accomplished, and retain some youthful vigor.`); + } else if (V.PC.actualAge >= 22) { + r.push(`surprisingly young. You'll need to prove myself, but you've got energy to burn.`); + } else if (V.PC.actualAge >= 14) { + r.push(`exceedingly young. You're nobody, but you're full of youthful vigor and ready to make the world yours.`); } else { - r.push(`surprisingly young. I'll need to prove myself, but I've got energy to burn.`); + r.push(`just a child. You may be emancipated, but society won't accept you as a leader.`); } - r.push(`My age:`); + r.push(`Your age:`); options.addOption(r.join(" "), "actualAge", V.PC).showTextBox() - .addComment(`Older player characters start with more reputation and maintain reputation somewhat more easily, but have slightly less sexual energy.`); + .addComment(`Older player characters start with more reputation and maintain reputation somewhat more easily, but have slightly less sexual energy. Exceedingly young characters will not be accepted by society, even more so if underage, and will face additional hurdles and complications.`); el.append(options.render()); @@ -156,12 +159,17 @@ App.Intro.PCBodyIntro = function() { function endScene() { const el = document.createElement("p"); - const linkTitle = "Confirm player character customization"; - if (V.PC.vagina !== -1) { - el.append(App.UI.DOM.passageLink(linkTitle, "PC Preg Intro")); - } else { - el.append(App.UI.DOM.passageLink(linkTitle, "PC Appearance Intro")); - } + el.append( + App.UI.DOM.link( + "Confirm player character overview", + () => { + App.UI.Player.syncAgeBasedParameters(); + }, + [], + "PC Appearance Intro" + ) + ); + return el; } }; diff --git a/src/events/intro/pcExperienceIntro.tw b/src/events/intro/pcExperienceIntro.tw index 422ae0db6cbf415fac6867c2f070259de93e027b..137604a09654c94de2023a77bb4342327cc7eb83 100644 --- a/src/events/intro/pcExperienceIntro.tw +++ b/src/events/intro/pcExperienceIntro.tw @@ -3,6 +3,10 @@ <<if $PC.career == "arcology owner">> <<goto "PC Rumor Intro">> <<else>> + <<if !$disableForcedCareers>> + <<set $disableForcedCareers = $PC.actualAge >= 22 ? 1 : 0>> + <</if>> + <p> You're a relative unknown in the Free Cities, but it's clear you're already accomplished. The meek and average cannot aspire to acquire arcologies. You've got all the necessary skills to take over an arcology and succeed as its owner, but you should be able to leverage the skills and experience you retain from your past, too. <span class="intro question"> @@ -11,7 +15,7 @@ </p> <div> - [[Idle wealth|PC Rumor Intro][$PC.career = "wealth"]] + [[Idle wealth|PC Rumor Intro][$PC.career = App.UI.Player.assignCareerByAge("wealth")]] </div> <div class="indent note"> Start with <span class="cash inc">extra money.</span> @@ -22,7 +26,7 @@ </div> <div> - [[Venture capitalism|PC Rumor Intro][$PC.career = "capitalist"]] + [[Venture capitalism|PC Rumor Intro][$PC.career = App.UI.Player.assignCareerByAge("capitalist")]] </div> <div class="indent note"> You will be more @@.green;effective at business pursuits.@@ @@ -33,7 +37,7 @@ </div> <div> - [[Private military work|PC Rumor Intro][$PC.career = "mercenary"]] + [[Private military work|PC Rumor Intro][$PC.career = App.UI.Player.assignCareerByAge("mercenary")]] </div> <div class="indent note"> You retain mercenary contacts @@ -46,7 +50,7 @@ </div> <div> - [[Slaving|PC Rumor Intro][$PC.career = "slaver"]] + [[Slaving|PC Rumor Intro][$PC.career = App.UI.Player.assignCareerByAge("slaver")]] </div> <div class="indent note"> Your slave breaking experience will be useful. @@ -57,21 +61,21 @@ </div> <div> - [[Arcology engineering|PC Rumor Intro][$PC.career = "engineer"]] + [[Engineering|PC Rumor Intro][$PC.career = App.UI.Player.assignCareerByAge("engineer")]] </div> <div class="indent note"> <span class="cash inc">Upgrading the arcology will be cheaper.</span> Also, the arcology will start with <span class="cash inc">basic economic upgrades</span> already installed. </div> <div> - [[Slave surgery|PC Rumor Intro][$PC.career = "medicine"]] + [[Surgery|PC Rumor Intro][$PC.career = App.UI.Player.assignCareerByAge("medicine")]] </div> <div class="indent note"> Surgery will be <span class="cash inc">cheaper</span> and @@.green;healthier@@ and <span class="cash inc">drug upgrades will be cheaper.</span> Your starting slaves will have free implants available. </div> <div> - [[Minor celebrity|PC Rumor Intro][$PC.career = "celebrity"]] + [[Minor celebrity|PC Rumor Intro][$PC.career = App.UI.Player.assignCareerByAge("celebrity")]] </div> <div class="indent note"> Start with @@.green;extra reputation.@@ @@ -82,7 +86,7 @@ </div> <div> - [[High class escort|PC Rumor Intro][$PC.career = "escort"]] + [[Sex industry|PC Rumor Intro][$PC.career = App.UI.Player.assignCareerByAge("escort")]] </div> <div class="indent note"> As an ex-whore, you will find it @@.red;hard to maintain reputation@@<<if $showSecExp == 1>>, @@.red;in addition to authority@@<</if>>. @@ -90,7 +94,7 @@ </div> <div> - [[Servant|PC Rumor Intro][$PC.career = "servant"]] + [[Servant|PC Rumor Intro][$PC.career = App.UI.Player.assignCareerByAge("servant")]] </div> <div class="indent note"> As an ex-servant, you will find it @@.red;hard to maintain reputation@@<<if $showSecExp == 1>>, @@.red;in addition to authority@@<</if>>. @@ -98,10 +102,10 @@ </div> <div> - [[Gang Leader|PC Rumor Intro][$PC.career = "gang"]] + [[Gang affiliation|PC Rumor Intro][$PC.career = App.UI.Player.assignCareerByAge("gang")]] </div> <div class="indent note"> - As an ex-gang leader, you know how to haggle slaves. + As an ex-gang member, you know how to haggle slaves. <<if $showSecExp == 1>> In addition, asserting your authority @@.green;will be easier@@ and <span class="cash inc">security HQ upgrades will be cheaper.</span> <</if>> @@ -109,10 +113,10 @@ </div> <div> - [[Incursion Specialist|PC Rumor Intro][$PC.career = "BlackHat"]] + [[Incursion Specialist|PC Rumor Intro][$PC.career = App.UI.Player.assignCareerByAge("BlackHat")]] </div> <div class="indent note"> - As an ex-hacker for hire, you know how to gain access computer systems and other devices. @@.green;Certain upgrades will be cheaper@@ and you may find alternative approaches to problems. + As an ex-hacker, you know how to gain access computer systems and other devices. @@.green;Certain upgrades will be cheaper@@ and you may find alternative approaches to problems. <<if $showSecExp == 1>> However, you will @@.red;find authority quite hard@@ to maintain. <</if>> @@ -130,4 +134,29 @@ <<set $showSecExp = 1>> <</link>> <</if>> +</p> + +<p> + <<if $disableForcedCareers != 1>> + <<link "Disable forced career choices" "PC Experience Intro">> + <<set $disableForcedCareers = 1>> + <</link>> + <div class="indent note"> + <<if $PC.actualAge < 14>> + Due to your young age, you will be given the child variant of your chosen career line. + <<elseif $PC.actualAge < 22>> + Due to your age, you will be given the inexperienced variant of your chosen career line. + <</if>> + Over time and with effort, you will be capable of achieving everything of importance in the adult careers. + </div> + <<else>> + <<if $PC.actualAge < 22>> + <<link "Enable forced career choices" "PC Experience Intro">> + <<set $disableForcedCareers = 0>> + <</link>> + <div class="indent note"> + Use age based careers. + </div> + <</if>> + <</if>> </p> \ No newline at end of file diff --git a/src/events/intro/pcPregIntro.tw b/src/events/intro/pcPregIntro.tw index 71d6886523392ae37b5375261bf849c69ec9a7ef..78ffe760712e87a063df04f0cf8f60a1c576f4a7 100644 --- a/src/events/intro/pcPregIntro.tw +++ b/src/events/intro/pcPregIntro.tw @@ -54,5 +54,5 @@ </div> </p> <p> - [[Confirm player character customization|PC Appearance Intro]] + [[Confirm player character customization|PC Experience Intro]] </p> diff --git a/src/events/legacy/RECI.tw b/src/events/legacy/RECI.tw index 86254cbb1751f59e88f8c4ed55416342a0091c08..6a8f1360c601d2aac042e354ab440b3abab499f0 100644 --- a/src/events/legacy/RECI.tw +++ b/src/events/legacy/RECI.tw @@ -27,7 +27,7 @@ <<if Array.isArray($RECIevent)>> <<set $activeSlave = $eventSlave>> - <<if $cheatMode == 1>> + <<if ($debugMode > 0 && $debugModeEventSelection > 0)>> <<set $nextButton = "Back", $nextLink = "Nonrandom Event", $returnTo = "Nonrandom Event">> /* if user just clicks spacebar */ ''A random check-in event would have been selected from the following:'' <br> @@ -83,7 +83,7 @@ <br>ERROR: bad RECI event $RECIevent <</switch>> -<<if $cheatMode == 1>> +<<if ($debugMode > 0 && $debugModeEventSelection > 0)>> <br><br>DEBUG: [[Go back to Nonrandom Event|Nonrandom Event][$activeSlave = 0, $eventSlave = 0]] <</if>> diff --git a/src/events/legacy/REFI.tw b/src/events/legacy/REFI.tw index 9c1c5341c73717d282f91b5ce9b25d8dcd39232b..ee7edebe8298df89f329fc94818f58c468880baf 100644 --- a/src/events/legacy/REFI.tw +++ b/src/events/legacy/REFI.tw @@ -25,7 +25,7 @@ <<if Array.isArray($REFIevent)>> <<set $activeSlave = $eventSlave>> - <<if $cheatMode == 1>> + <<if ($debugMode > 0 && $debugModeEventSelection > 0)>> <<set $nextButton = "Back", $nextLink = "Nonrandom Event", $returnTo = "Nonrandom Event">> /* if user just clicks spacebar */ ''A random fetish interest event would have been selected from the following:'' <br> @@ -43,7 +43,7 @@ <<set $nextButton = "Continue", $nextLink = "AS Dump", $returnTo = "RIE Eligibility Check">> <span id="result"> -<<if $cheatMode == 1>> +<<if ($debugMode > 0 && $debugModeEventSelection > 0)>> <br><br>DEBUG: [[Go back to Nonrandom Event|Nonrandom Event][$activeSlave = 0, $eventSlave = 0]] <</if>> diff --git a/src/events/legacy/RETS.tw b/src/events/legacy/RETS.tw index d72dea312921662a38205799a31126cb9cc7e5b4..eed6401c9cf1be515af691c24f3cb0307a07f80b 100644 --- a/src/events/legacy/RETS.tw +++ b/src/events/legacy/RETS.tw @@ -27,7 +27,7 @@ <<if Array.isArray($RETSevent)>> <<set $activeSlave = $eventSlave>> - <<if $cheatMode == 1>> + <<if ($debugMode > 0 && $debugModeEventSelection > 0)>> <<set $nextButton = "Back", $nextLink = "Nonrandom Event", $returnTo = "Nonrandom Event">> /* if user just clicks spacebar */ ''A random two slave event would have been selected from the following:'' <br> @@ -47,7 +47,7 @@ <br><br> <span id="result"> -<<if $cheatMode == 1>> +<<if ($debugMode > 0 && $debugModeEventSelection > 0)>> <br><br>DEBUG: [[Go back to Nonrandom Event|Nonrandom Event][$activeSlave = 0, $eventSlave = 0]] <</if>> diff --git a/src/events/nonRandom/pAbducted.js b/src/events/nonRandom/pAbducted.js index 4067dd1b46a36f9635ab6bdc7c18a1dc14ce351e..18eb7c21c7445626c2e7084d961244a9a9681b02 100644 --- a/src/events/nonRandom/pAbducted.js +++ b/src/events/nonRandom/pAbducted.js @@ -87,7 +87,8 @@ App.Events.pAbducted = class pAbducted extends App.Events.BaseEvent { cashX(-1000, "event"); } continueButton(node); - // injury code here + V.PC.health.shortDamage = 2; + V.PC.health.longDamage = 1; } else { r.push(`Once your vision is obscured, your attacker sweeps your legs and tosses you into a waiting crate.`); r.push(Spoken(abductor, `"Be a good little ${girlP} and keep quiet. Wouldn't want anything bad to happen to ya, eh? I'd really hate to damage the merchandise."`)); diff --git a/src/events/nonRandomEvent.js b/src/events/nonRandomEvent.js index 7f4d2661dc738f2dc49ab40d0de42b7449c8363d..030f53b00797033b40a7d39ad97772d2c7914ba9 100644 --- a/src/events/nonRandomEvent.js +++ b/src/events/nonRandomEvent.js @@ -151,13 +151,13 @@ App.Events.playNonrandomEvent = function() { const clearEvent = () => { V.event = null; }; if (V.event instanceof App.Events.BaseEvent) { - // we've deserialized a saved game with an event active, or a cheater has picked one, so just play it immediately + // we've deserialized a saved game with an event active, or a player has picked one, so just play it immediately V.event.execute(d); V.passageSwitchHandler = clearEvent; } else { - if (V.cheatMode) { + if (V.debugMode > 0 && V.debugModeEventSelection > 0) { V.nextButton = "Refresh"; - // show all the scheduled, nonrandom, and queued events, and allow the cheater to play them in any order and skip the remainder + // show all the scheduled, nonrandom, and queued events, and allow the player to play them in any order and skip the remainder App.UI.DOM.appendNewElement("h2", d, "Scheduled and Nonrandom Events"); App.UI.DOM.appendNewElement("div", d, "These scheduled and nonrandom events still need to play this week, in this order."); App.UI.DOM.appendNewElement("div", d, "WARNING: playing certain scheduled events out of order, or skipping them, can break your game! Be careful!", ["note", "warning"]); diff --git a/src/events/randomEvent.js b/src/events/randomEvent.js index 072492877bc35bd021dc4240f5b47066157c3503..e70f70bc215c00497f952dcc69bcf543d416125a 100644 --- a/src/events/randomEvent.js +++ b/src/events/randomEvent.js @@ -23,12 +23,14 @@ App.Events.getIndividualEvents = function() { new App.Events.RESSDevotedVirgin(), new App.Events.RESSDevotedWaist(), new App.Events.RESSEscapee(), + new App.Events.RESSForbiddenMasturbation(), new App.Events.RESSFrighteningDick(), new App.Events.RESSHotPC(), new App.Events.RESSImScared(), new App.Events.RESSKitchenMolestation(), new App.Events.RESSLazyEvening(), new App.Events.RESSMeanGirls(), + new App.Events.RESSModestClothes(), new App.Events.RESSMoistPussy(), new App.Events.RESSMuscles(), new App.Events.RESSObedientAddict(), @@ -44,6 +46,7 @@ App.Events.getIndividualEvents = function() { new App.Events.RESSSuppositoryResistance(), new App.Events.RESSTooThinForCumDiet(), new App.Events.RESSWaistlineWoes(), + new App.Events.RESSWhoreRebellious(), new App.Events.RECIButthole(), new App.Events.RECIFeminization(), @@ -114,6 +117,7 @@ App.Events.getNonindividualEvents = function() { new App.Events.RENickname().setType("RNIE"), new App.Events.RERecruit(), + new App.Events.REBusyMasterSuite(), ]; }; diff --git a/src/events/reRecruit.js b/src/events/reRecruit.js index 7fa8670531e6eb57689a5cc454e85becdaa6d9ae..85b20f5e756dc3faaf49a08ad2135d1dd7b8ad92 100644 --- a/src/events/reRecruit.js +++ b/src/events/reRecruit.js @@ -82,21 +82,21 @@ App.Events.RERecruit = class RERecruit extends App.Events.BaseEvent { get weight() { let weight = 1; // one generic recruit event guaranteed to always be possible - if ((random(1, 100) < V.rep/200) || V.cheatMode) { + if ((random(1, 100) < V.rep/200) || (V.debugMode && V.debugModeEventSelection)) { weight++; } if (V.policies.proRecruitment === 1) { - if ((random(1, 100) < V.rep/200) || V.cheatMode) { + if ((random(1, 100) < V.rep/200) || (V.debugMode && V.debugModeEventSelection)) { weight++; } } if (V.policies.enslavementRep !== -1) { - if ((random(1, 100) < V.rep/300) || V.cheatMode) { + if ((random(1, 100) < V.rep/300) || (V.debugMode && V.debugModeEventSelection)) { weight++; } } if (V.policies.enslavementCash !== -1) { - if ((random(1, 100) < V.rep/300) || V.cheatMode) { + if ((random(1, 100) < V.rep/300) || (V.debugMode && V.debugModeEventSelection)) { weight++; } } @@ -110,7 +110,7 @@ App.Events.RERecruit = class RERecruit extends App.Events.BaseEvent { execute(node) { V.encyclopedia = "Enslaving People"; V.nextLink = "RIE Eligibility Check"; - if (V.cheatMode) { + if (V.debugMode && V.debugModeEventSelection) { const el = App.UI.DOM.appendNewElement("span", node); App.UI.DOM.appendNewElement("span", el, `One of the following recruitment events would have appeared: `); const select = App.UI.DOM.appendNewElement("select", el); diff --git a/src/events/reRecruit/cleaningHouse.js b/src/events/reRecruit/cleaningHouse.js index 3f118cb986e6466fc8e804a4ecfa2f7c2110c22a..74b9e574efd204e1b5c646e5e151c515d6f0d2b0 100644 --- a/src/events/reRecruit/cleaningHouse.js +++ b/src/events/reRecruit/cleaningHouse.js @@ -8,7 +8,7 @@ App.Events.recCleaningHouse = class recCleaningHouse extends App.Events.BaseEven () => V.seeDicks !== 100, () => V.seePreg !== 0, () => V.rep > 16000, - () => (random(1, 100) < V.rep/1000) || V.cheatMode === 1, + () => (random(1, 100) < V.rep/1000) || (V.debugMode > 0 && V.debugModeEventSelection > 0), () => V.cash >= 50000 ]; } diff --git a/src/events/reRecruit/embryoAppropriation.js b/src/events/reRecruit/embryoAppropriation.js index bd84aa19653a09cd0243af36cc7d1bb829fcbef3..8c3fcecd1e6a8a72ecfeff1afac2e9d8e7f1318a 100644 --- a/src/events/reRecruit/embryoAppropriation.js +++ b/src/events/reRecruit/embryoAppropriation.js @@ -7,7 +7,7 @@ App.Events.recEmbryoAppropriation = class recEmbryoAppropriation extends App.Eve return [ () => V.seeDicks !== 100, () => V.seePreg !== 0, - () => (V.PC.skill.medicine > 50 && V.PC.skill.hacking > 75 && (random(0, 100) > 75 || V.cheatMode === 1)), + () => (V.PC.skill.medicine > 50 && V.PC.skill.hacking > 75 && (random(0, 100) > 75 || (V.debugMode > 0 && V.debugModeEventSelection > 0))), ]; } diff --git a/src/events/reRecruit/forbiddenLove.js b/src/events/reRecruit/forbiddenLove.js index eb40a4e5ac0af8736312f10c52a90477526ac0be..eaf87801e40be1492ba8b22d1dde979cd0b29adc 100644 --- a/src/events/reRecruit/forbiddenLove.js +++ b/src/events/reRecruit/forbiddenLove.js @@ -7,7 +7,7 @@ App.Events.recForbiddenLove = class recForbiddenLove extends App.Events.BaseEven return [ () => V.seeDicks !== 0, () => V.rep > 16000, - () => (random(1, 100) < V.rep/1000) || V.cheatMode === 1, + () => (random(1, 100) < V.rep/1000) || (V.debugMode > 0 && V.debugModeEventSelection > 0), () => V.cash >= 100000 ]; } diff --git a/src/events/reRecruit/handsomePC.js b/src/events/reRecruit/handsomePC.js index f95046967625778ea520b6ab63cb92b935f0ba3f..5262e01542ef9aad784ab5d2548fca3c79a70bd6 100644 --- a/src/events/reRecruit/handsomePC.js +++ b/src/events/reRecruit/handsomePC.js @@ -9,7 +9,7 @@ App.Events.recHandsomePC = class recHandsomePC extends App.Events.BaseEvent { () => V.PC.vagina === -1, () => V.PC.boobs < 300, () => V.PC.title === 1, - () => (V.rep/250) > (random(1, 100) || V.cheatMode === 1), + () => (V.rep/250) > (random(1, 100) || (V.debugMode > 0 && V.debugModeEventSelection > 0)), ]; } diff --git a/src/events/reRecruit/heldPOW.js b/src/events/reRecruit/heldPOW.js index a4231e122e28de46bde1158f1b86f68b0980ab1a..abb79b2fb4a51f98055537ba68e4da4ebf9d91a1 100644 --- a/src/events/reRecruit/heldPOW.js +++ b/src/events/reRecruit/heldPOW.js @@ -6,7 +6,7 @@ App.Events.recHeldPOW = class recHeldPOW extends App.Events.BaseEvent { eventPrerequisites() { return [ () => V.seeDicks !== 100, - () => (V.PC.skill.hacking >= 50 && (random(0, 100) < V.PC.skill.hacking) || V.cheatMode === 1), + () => (V.PC.skill.hacking >= 50 && (random(0, 100) < V.PC.skill.hacking) || (V.debugMode > 0 && V.debugModeEventSelection > 0)), ]; } diff --git a/src/events/reRecruit/homelessBreakIn.js b/src/events/reRecruit/homelessBreakIn.js index 69ef3aedc90a0a1e5bcde5b99e52fcf1001887a8..b9156e6cd1c3fb78793c6073723546c0f49fe7a3 100644 --- a/src/events/reRecruit/homelessBreakIn.js +++ b/src/events/reRecruit/homelessBreakIn.js @@ -6,7 +6,7 @@ App.Events.recHomelessBreakIn = class recHomelessBreakIn extends App.Events.Base eventPrerequisites() { return [ () => V.week > 46, - () => ((V.rep/100) > random(1, 100)) || V.cheatMode === 1 + () => ((V.rep/100) > random(1, 100)) || (V.debugMode > 0 && V.debugModeEventSelection > 0) ]; } diff --git a/src/events/reRecruit/immigrant.js b/src/events/reRecruit/immigrant.js index 11c2fb5d24a50a434389f6507e817305bd390a73..1177933fe66a7fe90db7cbfdb2230df9227c7f4e 100644 --- a/src/events/reRecruit/immigrant.js +++ b/src/events/reRecruit/immigrant.js @@ -5,7 +5,7 @@ App.Events.recImmigrant = class recImmigrant extends App.Events.BaseEvent { eventPrerequisites() { return [ - () => ((V.rep/250) > (random(1, 100) || V.cheatMode === 1)) + () => ((V.rep/250) > (random(1, 100) || (V.debugMode > 0 && V.debugModeEventSelection > 0))) ]; } diff --git a/src/events/reRecruit/overwhelmedFarmgirl.js b/src/events/reRecruit/overwhelmedFarmgirl.js index 1f99b38648b9892efbd0a908d16e2743c3b96f05..7c1705b5e02eea4de8232a7b9f237c1c42a74e1f 100644 --- a/src/events/reRecruit/overwhelmedFarmgirl.js +++ b/src/events/reRecruit/overwhelmedFarmgirl.js @@ -8,7 +8,7 @@ App.Events.recOverwhelmedFarmgirl = class recOverwhelmedFarmgirl extends App.Eve () => V.seeDicks !== 100, () => V.seePreg !== 0, () => V.seeHyperPreg === 1, - () => V.cheatMode === 1, + () => (V.debugMode > 0 && V.debugModeEventSelection > 0), ]; } diff --git a/src/events/reRecruit/princelyBetrayal.js b/src/events/reRecruit/princelyBetrayal.js index 138929b260816a4b885f9c0e93593b226d77216b..d5377e9904cae7eaf85f1bc4f4f763d43fc60428 100644 --- a/src/events/reRecruit/princelyBetrayal.js +++ b/src/events/reRecruit/princelyBetrayal.js @@ -7,7 +7,7 @@ App.Events.recPrincelyBetrayal = class recPrincelyBetrayal extends App.Events.Ba return [ () => V.seeDicks !== 0, () => V.rep > 16000, - () => ((random(1, 100) < V.rep/1000) || V.cheatMode === 1), + () => ((random(1, 100) < V.rep/1000) || (V.debugMode > 0 && V.debugModeEventSelection > 0)), () => V.cash >= 100000 ]; } diff --git a/src/events/reRecruit/repoNanny.js b/src/events/reRecruit/repoNanny.js index ec61d6e2db955f6edc9ad143ef6f0d3e3a14c352..3a987d7220f6eccb5a86b0af7634b9c20add35df 100644 --- a/src/events/reRecruit/repoNanny.js +++ b/src/events/reRecruit/repoNanny.js @@ -47,6 +47,7 @@ App.Events.recRepoNanny = class recRepoNanny extends App.Events.BaseEvent { r.push(`With a few keystrokes, you wire the payment to the repo company, then wait for ${his} delivery. After being brought into your penthouse by security, the legalities and biometric scanning with ${him} are taken care off fairly quickly and without fuss. Stepping towards you after the chime announcing a successful registration as your property, ${slave.slaveName} lowers ${his} head obediently and asks,`); r.push(Spoken(slave, `"${Master}, I — umm... what will be required of me? I'm really good with children and... and I can sing. Also, I've —"`)); r.push(`The fearful tremble in ${his} voice tells you that ${he}'s more than a little afraid of what you might have planned for ${him}. Waving off the slave's frightened babbling, you tell ${him} that you'll decide what to do with ${him} when you feel like it.`); + r.push(App.UI.newSlaveIntro(slave)); App.Events.addNode(el, r); return el; } diff --git a/src/events/reRecruit/rogueCyborg.js b/src/events/reRecruit/rogueCyborg.js index 6c6eb054d48bc17f0d61b4deb7cd754bdf5159bd..386e0ff53794895a012e8f8e959fffbdb7efb115 100644 --- a/src/events/reRecruit/rogueCyborg.js +++ b/src/events/reRecruit/rogueCyborg.js @@ -7,7 +7,7 @@ App.Events.recRogueCyborg = class recRogueCyborg extends App.Events.BaseEvent { return [ () => V.seeDicks !== 100, () => V.PC.skill.hacking >= 100, - () => (random(0, 100) > 95 || V.cheatMode === 1), + () => (random(0, 100) > 95 || (V.debugMode > 0 && V.debugModeEventSelection > 0)), () => V.cash >= 100000 ]; } diff --git a/src/events/reRecruit/shemalePC.js b/src/events/reRecruit/shemalePC.js index e97f242293798b7846ca64a70f3a8c081b6b9bf7..5bb69ea45a0c51ffe0eb9f55d7fdff15e984a260 100644 --- a/src/events/reRecruit/shemalePC.js +++ b/src/events/reRecruit/shemalePC.js @@ -7,7 +7,7 @@ App.Events.recShemalePC = class recShemalePC extends App.Events.BaseEvent { return [ () => V.PC.dick !== 0, () => V.PC.boobs >= 300, - () => (V.rep/250) > (random(1, 100) || V.cheatMode === 1), + () => (V.rep/250) > (random(1, 100) || (V.debugMode > 0 && V.debugModeEventSelection > 0)), ]; } diff --git a/src/events/reRecruit/starvingMigrant.js b/src/events/reRecruit/starvingMigrant.js index 0f27f265d7fcb572b7797f696b857a234ee08f17..a2f5360e3de23f7e341260cf367e92b468361c17 100644 --- a/src/events/reRecruit/starvingMigrant.js +++ b/src/events/reRecruit/starvingMigrant.js @@ -6,7 +6,7 @@ App.Events.recStarvingMigrant = class recStarvingMigrant extends App.Events.Base eventPrerequisites() { return [ () => V.week > 46, - () => ((V.rep/100) > (random(1, 100)) || V.cheatMode === 1) + () => ((V.rep/100) > (random(1, 100)) || (V.debugMode > 0 && V.debugModeEventSelection > 0)) ]; } diff --git a/src/events/reRecruit/wanderingHomeless.js b/src/events/reRecruit/wanderingHomeless.js index 08a67b93fe7d93b982cfd8d78ec6d4cbaed078ae..6111929fd58f8596a06d5281c54e33a5caeb44fe 100644 --- a/src/events/reRecruit/wanderingHomeless.js +++ b/src/events/reRecruit/wanderingHomeless.js @@ -7,7 +7,7 @@ App.Events.recWanderingHomeless = class recWanderingHomeless extends App.Events. return [ () => V.seeDicks !== 100, () => V.seePreg !== 0, - () => (random(1, 1000) < 5) || V.cheatMode === 1, + () => (random(1, 1000) < 5) || (V.debugMode > 0 && V.debugModeEventSelection > 0), ]; } diff --git a/src/events/reRecruit/womanlyPC.js b/src/events/reRecruit/womanlyPC.js index 13fcf8e2e19ff0d51cb58cd957818279c4220c59..697f34190040da0c34705949965c9460fd33ceb5 100644 --- a/src/events/reRecruit/womanlyPC.js +++ b/src/events/reRecruit/womanlyPC.js @@ -8,7 +8,7 @@ App.Events.recWomanlyPC = class recWomanlyPC extends App.Events.BaseEvent { () => V.PC.dick === 0, () => V.PC.boobs >= 300, () => V.PC.title === 0, - () => (V.rep/250) > (random(1, 100) || V.cheatMode === 1), + () => (V.rep/250) > (random(1, 100) || (V.debugMode > 0 && V.debugModeEventSelection > 0)), ]; } diff --git a/src/events/scheduled/seWedding.js b/src/events/scheduled/seWedding.js index ba2a0a2cc854bdb0a5a97c818e22fddfd8cece94..7992d3ec2f9c12f8fb25845fc729717a52cb31d8 100644 --- a/src/events/scheduled/seWedding.js +++ b/src/events/scheduled/seWedding.js @@ -22,8 +22,11 @@ App.Events.SEWedding = class SEWedding extends App.Events.BaseEvent { const { HeC, - heC, hisC, himC, wivesC + heC, hisC, himC } = getPronouns(solo ? slave1 : {pronoun: App.Data.Pronouns.Kind.plural}).appendSuffix("C"); // "C" is for collective. Used for flexibility in scenes that may have just one slave, or more than one. "she/they bow before you." + const wivesC = solo ? + getPronouns(slave1).wife : + getPronouns({pronoun: App.Data.Pronouns.Kind.plural}).wives; const belly = bellyAdjective(slave1); const ML = V.marrying.length; @@ -770,7 +773,7 @@ App.Events.SEWedding = class SEWedding extends App.Events.BaseEvent { r.push(`You'll fuck them repeatedly over the next few days, ensuring`); if (brides.every(b => b.devotion < -20)) { r.push(`impregnation, despite their protests.`); - } else if (brides.some(b => b)) { + } else if (brides.some(b => b.devotion < -20)) { const lowDevNames = brides .filter(slave => slave.devotion < -20) .map(slave => slave.slaveName); @@ -1628,7 +1631,7 @@ App.Events.SEWedding = class SEWedding extends App.Events.BaseEvent { const r = []; let _c = 0; let _h = 0; - r.push(`You also proclaim your new slave ${wives} ${namesString} ${V.PC.slaveSurname}.`); + r.push(`You also proclaim your new slave ${wivesC} ${namesString} ${V.PC.slaveSurname}.`); for (const slave of brides) { _c += 1; if (canHear(slave)) { @@ -1637,9 +1640,9 @@ App.Events.SEWedding = class SEWedding extends App.Events.BaseEvent { } r.push(`The new Mrs. ${V.PC.slaveSurname}${(_c > 1) ? `s` : ``}`); if (_h > 0) { - r.push((_c === 1) ? `hear` : `hears`); + r.push((_c === 1) ? `hears` : `hear`); } else { - r.push((_c === 1) ? `understand` : `understands`); + r.push((_c === 1) ? `understands` : `understand`); } r.push(`this, of course, and`); const nameCheck = !solo && brides.every(b => b.slaveSurname !== V.PC.slaveSurname); @@ -1657,7 +1660,7 @@ App.Events.SEWedding = class SEWedding extends App.Events.BaseEvent { let meanwhile; for (const slave of brides) { const {he, his, him} = getPronouns(slave); - if (_c > 1 && slave.slaveSurname !== V.PC.slaveSurname) { + if (slave.slaveSurname !== V.PC.slaveSurname) { if (!meanwhile) { r.push(slave.slaveName); } else { @@ -1665,41 +1668,26 @@ App.Events.SEWedding = class SEWedding extends App.Events.BaseEvent { } meanwhile = true; if (slave.fetish === "mindbroken") { - if (_c < 1) { - r.push(slave.slaveName); - } - r.push(`shows no reaction. Like many things, names mean nothing to ${him} now. Your guests, on the other hand, appreciate the gift.`); + r.push(`${slave.slaveName} shows no reaction. Like many things, names mean nothing to ${him} now. Your guests, on the other hand, appreciate the gift.`); } else if (slave.devotion + slave.trust >= 175) { - if (_c < 1) { - r.push(slave.slaveName); - } if (V.weddingPlanned === 3) { r.push(`breaks down again. Not only is ${he} to be blessed with your child, but ${he}'s to take your surname as well.`); } else { r.push(`breaks down again; it's like a dream come true.`); } } else if (slave.devotion < -20 && slave.trust > 20) { - if (_c < 1) { - r.push(slave.slaveName); - } if (V.weddingPlanned === 3) { r.push(`scoffs audibly. Just another burden for ${him} to carry; like the child soon to be growing in ${his} womb.`); } else { r.push(`scoffs audibly; just another burden for ${him} to carry.`); } } else if (slave.devotion < -20) { - if (_c < 1) { - r.push(slave.slaveName); - } if (V.weddingPlanned === 3) { r.push(`breaks down again. Not only are you binding ${him} to you with your child, but with your name as well.`); } else { r.push(`breaks down again; this is nothing more than another unwanted link to you.`); } } else { - if (_c < 1) { - r.push(slave.slaveName); - } r.push(`nods acceptingly. Your will is ${his} will, after all.`); } } @@ -1755,7 +1743,7 @@ App.Events.SEWedding = class SEWedding extends App.Events.BaseEvent { function ringCeremony() { const r = []; - if (brides.every(b => hasAnyArms(b))) { + if (!solo && brides.every(b => hasAnyArms(b))) { r.push(`on each slave's`); if (brides.every((b) => b.devotion < -20 && b.trust <= 20)) { r.push(`trembling`); @@ -1766,9 +1754,9 @@ App.Events.SEWedding = class SEWedding extends App.Events.BaseEvent { for (const slave of brides) { const {he} = getPronouns(slave); if (!hasAnyArms(slave)) { - r.push(`on a cord around ${slave.slaveName}'s neck, since ${he} lacks fingers to wear it on`); + ring.push(`on a cord around ${slave.slaveName}'s neck, since ${he} lacks fingers to wear it on`); } else { - r.push(`on ${slave.slaveName}'s ${(slave.devotion < -20 && slave.trust <= 20) ? `trembling ` : ``}finger`); + ring.push(`on ${slave.slaveName}'s ${(slave.devotion < -20 && slave.trust <= 20) ? `trembling ` : ``}middle finger`); } } r.push(`${toSentence(ring, " and another ring ")}.`); diff --git a/src/facilities/bodyModification/bodyModification.js b/src/facilities/bodyModification/bodyModification.js index 7cb155dd010df61ea9ddf0dfcc040d25904b2fc9..a06dd16588aa407dc25bbab05cf489fccf194070 100644 --- a/src/facilities/bodyModification/bodyModification.js +++ b/src/facilities/bodyModification/bodyModification.js @@ -518,7 +518,7 @@ App.UI.bodyModification = function(slave, cheat = false) { } ) ); - if (cheat) { + if (V.cheatMode && cheat) { // check both cheat gates so it does not show in SG. const options = new App.UI.OptionsGroup(); options.addOption("Breeding mark", "breedingMark", slave) .addValue("On", 1).on() diff --git a/src/facilities/cellblock/WardenessSelect.js b/src/facilities/cellblock/WardenessSelect.js index ab9b749520f639806bb2db72f841b5958d28ba8e..b9dfea914f6dada4b993c7ab2a302fed9c2d865a 100644 --- a/src/facilities/cellblock/WardenessSelect.js +++ b/src/facilities/cellblock/WardenessSelect.js @@ -4,7 +4,7 @@ App.Facilities.WardenessSelect = function() { if (S.Wardeness) { f.append(`Wardeness: ${SlaveFullName(S.Wardeness)}, helps breaking your prisoners. `); f.append(App.UI.DOM.link("Remove Wardeness", () => { - removeJob(S.Wardeness, Job.WARDENESS); + removeJob(S.Wardeness, Job.WARDEN); }, [], "Cellblock" )); diff --git a/src/facilities/farmyard/animals/animals.js b/src/facilities/farmyard/animals/animals.js index ad525d0a2b0ace954f0c65352fc9e8c842a10204..fa0b4e0185c6be724ae334e5f7bf7f3e7cf1ad4d 100644 --- a/src/facilities/farmyard/animals/animals.js +++ b/src/facilities/farmyard/animals/animals.js @@ -103,8 +103,8 @@ App.Facilities.Farmyard.animals = function() { const frag = new DocumentFragment(); - const domesticDiv = App.UI.DOM.appendNewElement("div", frag, '', "farmyard-domestic"); - const exoticDiv = App.UI.DOM.appendNewElement("div", frag, '', "farmyard-exotic"); + const domesticDiv = App.UI.DOM.appendNewElement("div", frag, '', 'farmyard-domestic'); + const exoticDiv = App.UI.DOM.appendNewElement("div", frag, '', 'farmyard-exotic'); const hrMargin = '0'; @@ -119,10 +119,10 @@ App.Facilities.Farmyard.animals = function() { V.returnTo = "Farmyard Animals"; V.encyclopedia = "Farmyard"; - App.UI.DOM.appendNewElement("span", domesticDiv, 'Domestic Animals', "farmyard-heading"); + App.UI.DOM.appendNewElement("span", domesticDiv, 'Domestic Animals', 'farmyard-heading'); if (V.farmyardKennels > 1 || V.farmyardStables > 1 || V.farmyardCages > 1) { - App.UI.DOM.appendNewElement("span", exoticDiv, 'Exotic Animals', "farmyard-heading"); + App.UI.DOM.appendNewElement("span", exoticDiv, 'Exotic Animals', 'farmyard-heading'); } if (V.farmyardKennels) { @@ -157,15 +157,15 @@ App.Facilities.Farmyard.animals = function() { - // MARK: Domestic Animals + // Domestic Animals function domesticCanines() { - const canineDiv = App.UI.DOM.makeElement("div", '', "farmyard-animals"); + const canineDiv = App.UI.DOM.makeElement("div", '', 'farmyard-animals'); const hr = document.createElement("hr"); hr.style.margin = hrMargin; - App.UI.DOM.appendNewElement("span", canineDiv, 'Dogs', "farmyard-animal-type"); + App.UI.DOM.appendNewElement("span", canineDiv, 'Dogs', 'farmyard-animal-type'); canineDiv.append(hr, animalList(canine, domestic, 5000, canine)); @@ -173,12 +173,12 @@ App.Facilities.Farmyard.animals = function() { } function domesticHooved() { - const hoovedDiv = App.UI.DOM.makeElement("div", '', "farmyard-animals"); + const hoovedDiv = App.UI.DOM.makeElement("div", '', 'farmyard-animals'); const hr = document.createElement("hr"); hr.style.margin = hrMargin; - App.UI.DOM.appendNewElement("span", hoovedDiv, 'Hooved Animals', "farmyard-animal-type"); + App.UI.DOM.appendNewElement("span", hoovedDiv, 'Hooved Animals', 'farmyard-animal-type'); hoovedDiv.append(hr, animalList(hooved, domestic, 20000, hooved)); @@ -186,12 +186,12 @@ App.Facilities.Farmyard.animals = function() { } function domesticFelines() { - const felineDiv = App.UI.DOM.makeElement("div", '', "farmyard-animals"); + const felineDiv = App.UI.DOM.makeElement("div", '', 'farmyard-animals'); const hr = document.createElement("hr"); hr.style.margin = hrMargin; - App.UI.DOM.appendNewElement("span", felineDiv, 'Cats', "farmyard-animal-type"); + App.UI.DOM.appendNewElement("span", felineDiv, 'Cats', 'farmyard-animal-type'); felineDiv.append(hr, animalList(feline, domestic, 1000, feline)); @@ -200,15 +200,15 @@ App.Facilities.Farmyard.animals = function() { - // MARK: Exotic Animals + // Exotic Animals function exoticCanines() { - const canineDiv = App.UI.DOM.makeElement("div", '', "farmyard-animals"); + const canineDiv = App.UI.DOM.makeElement("div", '', 'farmyard-animals'); const hr = document.createElement("hr"); hr.style.margin = hrMargin; - App.UI.DOM.appendNewElement("span", canineDiv, 'Canines', "farmyard-animal-type"); + App.UI.DOM.appendNewElement("span", canineDiv, 'Canines', 'farmyard-animal-type'); canineDiv.append(hr, animalList(canine, exotic, 50000, canine)); @@ -216,12 +216,12 @@ App.Facilities.Farmyard.animals = function() { } function exoticHooved() { - const hoovedDiv = App.UI.DOM.makeElement("div", '', "farmyard-animals"); + const hoovedDiv = App.UI.DOM.makeElement("div", '', 'farmyard-animals'); const hr = document.createElement("hr"); hr.style.margin = hrMargin; - App.UI.DOM.appendNewElement("span", hoovedDiv, 'Hooved Animals', "farmyard-animal-type"); + App.UI.DOM.appendNewElement("span", hoovedDiv, 'Hooved Animals', 'farmyard-animal-type'); hoovedDiv.append(hr, animalList(hooved, exotic, 75000, hooved)); @@ -229,12 +229,12 @@ App.Facilities.Farmyard.animals = function() { } function exoticFelines() { - const felineDiv = App.UI.DOM.makeElement("div", '', "farmyard-animals"); + const felineDiv = App.UI.DOM.makeElement("div", '', 'farmyard-animals'); const hr = document.createElement("hr"); hr.style.margin = hrMargin; - App.UI.DOM.appendNewElement("span", felineDiv, 'Felines', "farmyard-animal-type"); + App.UI.DOM.appendNewElement("span", felineDiv, 'Felines', 'farmyard-animal-type'); felineDiv.append(hr, animalList(feline, exotic, 100000, feline)); @@ -243,7 +243,7 @@ App.Facilities.Farmyard.animals = function() { - // MARK: Helper Functions + // Helper Functions /** * Creates either a link or note text depending on parameters given @@ -316,11 +316,11 @@ App.Facilities.Farmyard.animals = function() { const addAnimalDiv = document.createElement("div"); const dickDiv = document.createElement("div"); const deadlinessDiv = document.createElement("div"); - const addDiv = App.UI.DOM.makeElement("div", null, ["animal-add"]); + const addDiv = App.UI.DOM.makeElement("div", null, ['animal-add']); const animal = new App.Entity.Animal(null, null, "canine", "domestic"); - App.UI.DOM.appendNewElement("div", addAnimalDiv, `Add a New Animal`, ["farmyard-heading"]); + App.UI.DOM.appendNewElement("div", addAnimalDiv, `Add a New Animal`, ['farmyard-heading']); addAnimalDiv.append( name(), @@ -496,13 +496,13 @@ App.Facilities.Farmyard.animals = function() { const dickSizeDiv = document.createElement("div"); dickSizeDiv.append( - `How large is ${animal.name ? `${animal.articleAn} ${animal.name}` : `the animal`}'s dick? `, + `How large is ${animal.name ? `${animal.articleAn} male ${animal.name}` : `a male`}'s penis? `, App.UI.DOM.makeTextBox(animal.dick.size || 2, value => { animal.setDick(value, animal.dick.desc || null); App.UI.DOM.replace(dickSizeDiv, dickSize); }, true), - App.UI.DOM.makeElement("span", `1 is smallest, and default is 2. `, ["note"]), + App.UI.DOM.makeElement("span", `1 is smallest, and default is 2. `, ['note']), ); return dickSizeDiv; @@ -518,7 +518,7 @@ App.Facilities.Farmyard.animals = function() { App.UI.DOM.replace(dickDescDiv, dickDesc); }), - App.UI.DOM.makeElement("span", `Default is 'large'. `, ["note"]), + App.UI.DOM.makeElement("span", `Default is 'large'. `, ['note']), ); return dickDescDiv; @@ -531,7 +531,7 @@ App.Facilities.Farmyard.animals = function() { App.UI.DOM.makeTextBox(5, value => { animal.setDick(value); }, true), - App.UI.DOM.makeElement("span", `Default is 5. `, ["note"]), + App.UI.DOM.makeElement("span", `Default is 5. `, ['note']), ); return deadlinessDiv; @@ -613,7 +613,7 @@ App.Facilities.Farmyard.animals.init = function() { .setDick(5, 'huge'), new Animal("elephant", "elephant", hooved, exotic) .setArticle(an) - .setDick(6, 'enormous'), // not exactly true to life, but more fun + .setDick(6, 'enormous'), // not exactly true to life, but more interesting new Animal("Abbysinian", cat, feline, domestic) .setArticle(an), diff --git a/src/facilities/farmyard/farmyard.js b/src/facilities/farmyard/farmyard.js index 137e46ac40784b9846bc30fc00c83d41d45c2084..63c2fe6c8abdf7acf72ef666ace27cb27ed7bb9b 100644 --- a/src/facilities/farmyard/farmyard.js +++ b/src/facilities/farmyard/farmyard.js @@ -1,18 +1,21 @@ App.Facilities.Farmyard.farmyard = function() { const frag = new DocumentFragment(); - const introDiv = document.createElement("div"); - const expandDiv = document.createElement("div"); - const menialsDiv = document.createElement("div"); - const rulesDiv = document.createElement("div"); - const upgradesDiv = document.createElement("div"); - const animalsDiv = document.createElement("div"); - const kennelsDiv = document.createElement("div"); - const stablesDiv = document.createElement("div"); - const cagesDiv = document.createElement("div"); - const removeHousingDiv = document.createElement("div"); - - const farmyardNameCaps = capFirstChar(V.farmyardName); + const introDiv = App.UI.DOM.makeElement("div", null, ['farmyard-intro']); + const expandDiv = App.UI.DOM.makeElement("div", null, ['farmyard-expand']); + const menialsDiv = App.UI.DOM.makeElement("div", null, ['farmyard-menials']); + const rulesDiv = App.UI.DOM.makeElement("div", null, ['farmyard-rules']); + const upgradesDiv = App.UI.DOM.makeElement("div", null, ['farmyard-upgrades']); + const kennelsDiv = App.UI.DOM.makeElement("div", null, ['farmyard-kennels']); + const stablesDiv = App.UI.DOM.makeElement("div", null, ['farmyard-stables']); + const cagesDiv = App.UI.DOM.makeElement("div", null, ['farmyard-cages']); + const removeHousingDiv = App.UI.DOM.makeElement("div", null, ['farmyard-remove']); + const renameDiv = App.UI.DOM.makeElement("div", null, ['farmyard-rename']); + const slavesDiv = App.UI.DOM.makeElement("div", null, ['farmyard-slaves']); + + let farmyardNameCaps = capFirstChar(V.farmyardName); + + const count = App.Entity.facilities.farmyard.totalEmployeesCount; V.nextButton = "Back to Main"; V.nextLink = "Main"; @@ -25,200 +28,186 @@ App.Facilities.Farmyard.farmyard = function() { menials(), rules(), upgrades(), - animals(), + kennels(), + stables(), + cages(), + removeHousing(), + rename(), + slaves(), ); - App.UI.DOM.appendNewElement("div", frag, App.UI.SlaveList.stdFacilityPage(App.Entity.facilities.farmyard), "farmyard-slaves"); - - App.UI.SlaveList.ScrollPosition.restore(); - - frag.appendChild(App.Facilities.rename(App.Entity.facilities.farmyard, () => { - App.UI.DOM.replace(introDiv, intro); - App.UI.DOM.replace(expandDiv, expand); - App.UI.DOM.replace(menialsDiv, menials); - App.UI.DOM.replace(rulesDiv, rules); - App.UI.DOM.replace(upgradesDiv, upgrades); - App.UI.DOM.replace(animalsDiv, animals); - })); - return frag; function intro() { - introDiv.classList.add("farmyard-intro", "scene-intro"); + const text = []; - const desc = App.UI.DOM.appendNewElement("div", introDiv, `${farmyardNameCaps} is an oasis of growth in the midst of the jungle of steel and concrete that is ${V.arcologies[0].name}. Animals are kept in pens, tended to by your slaves, while ${V.farmyardUpgrades.hydroponics + text.push(`${farmyardNameCaps} is an oasis of growth in the midst of the jungle of steel and concrete that is ${V.arcologies[0].name}. Animals are kept in pens, tended to by your slaves, while ${V.farmyardUpgrades.hydroponics ? `rows of hydroponics equipment` : `makeshift fields`} grow crops. `); - const count = App.Entity.facilities.farmyard.totalEmployeesCount; - switch (V.farmyardDecoration) { case "Roman Revivalist": - desc.append(`Its red tiles and white stone walls are the very picture of a Roman farm villa's construction, as are the marble statues and reliefs. Saturn and Ceres look over the prosperity of the fields${V.seeBestiality ? `. Mercury watches over the health of the animals, and Feronia ensures strong litters in your slaves.` : `, and Mercury watches over the health of the animals.`} The slaves here are all looked after well, as they have one of the most important jobs in ${V.arcologies[0].name}.`); + text.push(`Its red tiles and white stone walls are the very picture of a Roman farm villa's construction, as are the marble statues and reliefs. Saturn and Ceres look over the prosperity of the fields${V.seeBestiality ? `. Mercury watches over the health of the animals, and Feronia ensures strong litters in your slaves.` : `, and Mercury watches over the health of the animals.`} The slaves here are all looked after well, as they have one of the most important jobs in ${V.arcologies[0].name}.`); break; case "Neo-Imperialist": - desc.append(`Its high-tech, sleek black design invocates an embracement of the future, tempered by the hanging banners displaying your family crest as the rightful lord and master of these farms. Serf-like peasants work tirelessly in the fields, both to grow crops and oversee the slaves beneath them. Despite the harsh nature of the fieldwork, the slaves here are all looked after well, as they have one of the most important jobs in ${V.arcologies[0].name}.`); + text.push(`Its high-tech, sleek black design invocates an embracement of the future, tempered by the hanging banners displaying your family crest as the rightful lord and master of these farms. Serf-like peasants work tirelessly in the fields, both to grow crops and oversee the slaves beneath them. Despite the harsh nature of the fieldwork, the slaves here are all looked after well, as they have one of the most important jobs in ${V.arcologies[0].name}.`); break; case "Aztec Revivalist": - desc.append(`It can't completely recreate the floating farms in the ancient Aztec fashion, but it comes as close as it can, shallow pseudo-canals dividing each field into multiple sections. Smooth stone and colorful murals cover the walls, depicting bloody stories of gods and mortals alike.`); + text.push(`It can't completely recreate the floating farms in the ancient Aztec fashion, but it comes as close as it can, shallow pseudo-canals dividing each field into multiple sections. Smooth stone and colorful murals cover the walls, depicting bloody stories of gods and mortals alike.`); break; case "Egyptian Revivalist": - desc.append(`It does its best to capture the wide open nature of ancient Egyptian farms, including mimicking the irrigation systems fed by the Nile. The stone walls are decorated with murals detailing its construction and your prowess in general, ${V.seeBestiality ? `with animal-bloated slaves featured prominently.` : `hieroglyphs spelling out a volumes of praise.`}`); + text.push(`It does its best to capture the wide open nature of ancient Egyptian farms, including mimicking the irrigation systems fed by the Nile. The stone walls are decorated with murals detailing its construction and your prowess in general, ${V.seeBestiality ? `with animal-bloated slaves featured prominently.` : `hieroglyphs spelling out volumes of praise.`}`); break; case "Edo Revivalist": - desc.append(`It does its best to mimic the rice patties and thatch roofed buildings of the Edo period despite the wide variety of crops tended by various slaves. Not every crop can thrive in flooded fields, but the ones that can take advantage of your attention to detail.`); + text.push(`It does its best to mimic the rice patties and thatch roofed buildings of the Edo period despite the wide variety of crops tended by various slaves. Not every crop can thrive in flooded fields, but the ones that can take advantage of your attention to detail.`); break; case "Arabian Revivalist": - desc.append(`Large plots of olive trees and date palms line the outer edges of the main crop area, while a combination of wheat, flax, and barley occupies the interior space. Irrigation canals snake through the area, ensuring every inch of cropland is well-watered.`); + text.push(`Large plots of olive trees and date palms line the outer edges of the main crop area, while a combination of wheat, flax, and barley occupies the interior space. Irrigation canals snake through the area, ensuring every inch of cropland is well-watered.`); break; case "Chinese Revivalist": - desc.append(`It does its best to capture the terraces that covered the ancient Chinese hills and mountains, turning every floor into ribbons of fields following a slight incline. Slaves wade through crops that can handle flooding and splash through the irrigation of the others when they aren't tending to${V.seeBestiality ? ` or breeding with` : ``} your animals.`); + text.push(`It does its best to capture the terraces that covered the ancient Chinese hills and mountains, turning every floor into ribbons of fields following a slight incline. Slaves wade through crops that can handle flooding and splash through the irrigation of the others when they aren't tending to${V.seeBestiality ? ` or breeding with` : ``} your animals.`); break; case "Chattel Religionist": - desc.append(`It runs like a well oiled machine, slaves bent in humble service as they tend crops grown on the Prophet's command, or see to the animals' needs. Their clothing is tucked up and out of the way as they see to their tasks, keeping them clean as they work ${V.seeBestiality ? `around animal-bloated bellies ` : ``}as divine will dictates.`); + text.push(`It runs like a well oiled machine, slaves bent in humble service as they tend crops grown on the Prophet's command, or see to the animals' needs. Their clothing is tucked up and out of the way as they see to their tasks, keeping them clean as they work ${V.seeBestiality ? `around animal-bloated bellies ` : ``}as divine will dictates.`); break; case "Degradationist": - desc.append(`It is constructed less as a converted warehouse and more as something to visit, allowing guests to enjoy the spectacle of slaves ${V.seeBestiality ? `being pounded by eager animals` : `elbow deep in scrubbing animal waste`} to their satisfaction.`); + text.push(`It is constructed less as a converted warehouse and more as something to visit, allowing guests to enjoy the spectacle of slaves ${V.seeBestiality ? `being pounded by eager animals` : `elbow deep in scrubbing animal waste`} to their satisfaction.`); break; case "Repopulationist": - desc.append(`It teems with life, both in the belly of every animal and the belly of every slave, though the latter makes tending the fields difficult. They're ordered to take care, as they carry the future ${V.seeBestiality ? `of this farm` : `of the arcology`} in their bellies.`); + text.push(`It teems with life, both in the belly of every animal and the belly of every slave, though the latter makes tending the fields difficult. They're ordered to take care, as they carry the future ${V.seeBestiality ? `of this farm` : `of the arcology`} in their bellies.`); break; case "Eugenics": - desc.append(`It holds a wide variety of crops and animals, but the best of the best is easy to find. They're set apart from the others, given only the best care and supplies${V.seeBestiality ? ` and bred with only the highest quality slaves` : ``}, while the sub-par stock is neglected off to the side.`); + text.push(`It holds a wide variety of crops and animals, but the best of the best is easy to find. They're set apart from the others, given only the best care and supplies${V.seeBestiality ? ` and bred with only the highest quality slaves` : ``}, while the sub-par stock is neglected off to the side.`); break; case "Asset Expansionist": - desc.append(`It is not easy to look after animals and till fields with such enormous body parts, but your slaves are diligent regardless, working hard to provide food and livestock for the arcology.`); + text.push(`It is not easy to look after animals and till fields with such enormous body parts, but your slaves are diligent regardless, working hard to provide food and livestock for the arcology.`); break; case "Transformation Fetishist": - // desc.append(`TODO:`); + // text.push(`TODO:`); break; case "Gender Radicalist": - // desc.append(`TODO:`); + // text.push(`TODO:`); break; case "Gender Fundamentalist": - // desc.append(`TODO:`); + // text.push(`TODO:`); break; case "Physical Idealist": - desc.append(`Its animals are in exceptional shape, their coats unable to hide how muscular they are, requiring your slaves to be equally toned to control them. There's plenty of space for their exercise as well${V.seeBestiality ? ` and an abundance of curatives for the slaves full of their fierce, kicking offspring` : ``}.`); + text.push(`Its animals are in exceptional shape, their coats unable to hide how muscular they are, requiring your slaves to be equally toned to control them. There's plenty of space for their exercise as well${V.seeBestiality ? ` and an abundance of curatives for the slaves full of their fierce, kicking offspring` : ``}.`); break; case "Supremacist": - desc.append(`It is a clean and orderly operation, stables and cages mucked by a multitude of inferior slaves, along with grooming your animals and harvesting your crops.`); + text.push(`It is a clean and orderly operation, stables and cages mucked by a multitude of inferior slaves, along with grooming your animals and harvesting your crops.`); break; case "Subjugationist": - desc.append(`It is a clean and orderly operation, stables and cages mucked by a multitude of ${V.arcologies[0].FSSubjugationistRace} slaves, while the others are tasked with grooming your animals and harvesting your crops.`); + text.push(`It is a clean and orderly operation, stables and cages mucked by a multitude of ${V.arcologies[0].FSSubjugationistRace} slaves, while the others are tasked with grooming your animals and harvesting your crops.`); break; case "Paternalist": - desc.append(`It's full of healthy animals, crops, and slaves, the former's every need diligently looked after by the latter. The fields flourish to capacity under such care, and the animals give the distinct impression of happiness${V.seeBestiality ? ` — some more than others if the growing bellies of your slaves are anything to go by, the only indication that such rutting takes place` : ``}.`); + text.push(`It's full of healthy animals, crops, and slaves, the former's every need diligently looked after by the latter. The fields flourish to capacity under such care, and the animals give the distinct impression of happiness${V.seeBestiality ? ` — some more than others if the growing bellies of your slaves are anything to go by, the only indication that such rutting takes place` : ``}.`); break; case "Pastoralist": - // desc.append(`TODO:`); + // text.push(`TODO:`); break; case "Maturity Preferentialist": - // desc.append(`TODO:`); + // text.push(`TODO:`); break; case "Youth Preferentialist": - // desc.append(`TODO:`); + // text.push(`TODO:`); break; case "Body Purist": - // desc.append(`TODO:`); + // text.push(`TODO:`); break; case "Slimness Enthusiast": - desc.append(`It features trim animals and slaves alike, not a pound of excess among them. The feed for both livestock and crops are carefully maintained to ensure optimal growth without waste, letting them flourish without being weighed down.`); + text.push(`It features trim animals and slaves alike, not a pound of excess among them. The feed for both livestock and crops are carefully maintained to ensure optimal growth without waste, letting them flourish without being weighed down.`); break; case "Hedonistic": - desc.append(`It features wider gates and stalls, for both the humans visiting or tending the occupants, and the animals starting to mimic their handlers${V.seeBestiality ? ` and company` : ``}, with plenty of seats along the way.`); + text.push(`It features wider gates and stalls, for both the humans visiting or tending the occupants, and the animals starting to mimic their handlers${V.seeBestiality ? ` and company` : ``}, with plenty of seats along the way.`); break; case "Slave Professionalism": - // desc.append(`TODO:`); + // text.push(`TODO:`); break; case "Intellectual Dependency": - // desc.append(`TODO:`); + // text.push(`TODO:`); break; default: - desc.append(`It is very much a converted warehouse still, sectioned off in various 'departments'${V.farmyardUpgrades.machinery ? ` with machinery placed where it can be` : V.farmyardUpgrades.hydroponics ? ` and plumbing for the hydroponics system running every which way` : ``}.`); + text.push(`It is very much a converted warehouse still, sectioned off in various 'departments'${V.farmyardUpgrades.machinery ? ` with machinery placed where it can be` : V.farmyardUpgrades.hydroponics ? ` and plumbing for the hydroponics system running every which way` : ``}.`); break; } if (count > 2) { - desc.append(` ${farmyardNameCaps} is bustling with activity. Farmhands are hurrying about, on their way to feed animals and maintain farming equipment.`); + text.push(`${farmyardNameCaps} is bustling with activity. Farmhands are hurrying about, on their way to feed animals and maintain farming equipment.`); } else if (count) { - desc.append(` ${farmyardNameCaps} is working steadily. Farmhands are moving about, looking after the animals and crops.`); + text.push(`${farmyardNameCaps} is working steadily. Farmhands are moving about, looking after the animals and crops.`); } else if (S.Farmer) { - desc.append(` ${S.Farmer.slaveName} is alone in ${V.farmyardName}, and has nothing to do but look after the animals and crops.`); + text.push(`${S.Farmer.slaveName} is alone in ${V.farmyardName}, and has nothing to do but look after the animals and crops.`); } else { - desc.append(` ${farmyardNameCaps} is empty and quiet.`); + text.push(`${farmyardNameCaps} is empty and quiet.`); } - App.UI.DOM.appendNewElement("div", desc, App.UI.DOM.passageLink(`Decommission ${V.farmyardName}`, "Main", () => { - if (V.farmMenials) { - V.menials += V.farmMenials; - V.farmMenials = 0; - } + App.UI.DOM.appendNewElement("div", introDiv, text.join(' '), ['scene-intro']); - V.farmyardName = "the Farmyard"; - V.farmyard = 0; - V.farmyardDecoration = "standard"; + if (count === 0) { + App.UI.DOM.appendNewElement("div", introDiv, App.UI.DOM.passageLink(`Decommission ${V.farmyardName}`, "Main", () => { + if (V.farmMenials) { + V.menials += V.farmMenials; + V.farmMenials = 0; + } - V.farmMenials = 0; - V.farmMenialsSpace = 0; + V.farmyardName = "the Farmyard"; + V.farmyard = 0; + V.farmyardDecoration = "standard"; - V.farmyardShows = 0; - V.farmyardBreeding = 0; - V.farmyardCrops = 0; + V.farmMenials = 0; + V.farmMenialsSpace = 0; - V.farmyardKennels = 0; - V.farmyardStables = 0; - V.farmyardCages = 0; + V.farmyardShows = 0; + V.farmyardBreeding = 0; + V.farmyardCrops = 0; - if (V.pit) { - V.pit.animal = null; - } + V.farmyardKennels = 0; + V.farmyardStables = 0; + V.farmyardCages = 0; - V.farmyardUpgrades = { - pump: 0, - fertilizer: 0, - hydroponics: 0, - machinery: 0, - seeds: 0 - }; + if (V.pit) { + V.pit.animal = null; + } - clearAnimalsPurchased(); - App.Arcology.cellUpgrade(V.building, App.Arcology.Cell.Manufacturing, "Farmyard", "Manufacturing"); - })); + V.farmyardUpgrades = { + pump: 0, + fertilizer: 0, + hydroponics: 0, + machinery: 0, + seeds: 0 + }; + + clearAnimalsPurchased(); + App.Arcology.cellUpgrade(V.building, App.Arcology.Cell.Manufacturing, "Farmyard", "Manufacturing"); + }), ['indent']); + } return introDiv; } function expand() { - expandDiv.classList.add("farmyard-expand"); + const cost = Math.trunc(V.farmyard * 1000 * V.upgradeMultiplierArcology); - const upgradeCost = Math.trunc(V.farmyard * 1000 * V.upgradeMultiplierArcology); - const farmhands = App.Entity.facilities.farmyard.totalEmployeesCount; + expandDiv.append(`It can support ${num(V.farmyard)} farmhands. There ${count === 1 ? `is currently ${count} farmhand` : `are currently ${count} farmhands`} in ${V.farmyardName}.`); - App.UI.DOM.appendNewElement('div', expandDiv, `It can support ${V.farmyard} farmhands. Currently there ${farmhands === 1 ? `is` : `are`} ${farmhands} ${farmhands === 1 ? `farmhand` : `farmhands`} in ${V.farmyardName}. `); - - App.UI.DOM.appendNewElement('div', expandDiv, App.UI.DOM.link(`Expand ${V.farmyardName}`, () => { - cashX(forceNeg(upgradeCost), "capEx"); + App.UI.DOM.appendNewElement("div", expandDiv, App.UI.DOM.link(`Expand ${V.farmyardName}`, () => { + cashX(forceNeg(cost), "capEx"); V.farmyard += 5; V.PC.skill.engineering += .1; App.UI.DOM.replace(expandDiv, expand); }, - null, - '', - `Costs ${cashFormat(upgradeCost)} and will increase upkeep costs`), - ['indent']); + [], '', `Costs ${cashFormat(cost)} and increases the capacity of ${V.farmyardName} by 5.`), ['indent']); - if (App.Entity.facilities.farmyard.totalEmployeesCount) { - App.UI.DOM.appendNewElement("div", expandDiv, removeFacilityWorkers("farmyard"), "indent"); + if (count > 0) { + App.UI.DOM.appendNewElement("div", expandDiv, removeFacilityWorkers("farmyard"), 'indent'); } return expandDiv; } function menials() { - menialsDiv.classList.add("farmyard-menials"); - menialsDiv.append(transferMenials(), buyMenials(), houseMenials()); return menialsDiv; @@ -364,120 +353,35 @@ App.Facilities.Farmyard.farmyard = function() { cashX(forceNeg(unitCost), "farmyard"); V.farmMenialsSpace += 100; }, - null, - '', - `Costs ${cashFormat(unitCost)} and will increase upkeep costs`), - ['indent']); + [], '', `Costs ${cashFormat(unitCost)} and increases housing by 100.`), ['indent']); } return frag; } function rules() { - rulesDiv.classList.add("farmyard-rules"); + if (App.Entity.facilities.farmyard.employeesIDs().size > 0 && (V.farmyardKennels || V.farmyardStables || V.farmyardCages)) { // TODO: redo this with V.farmyardShowgirls + const options = new App.UI.OptionsGroup(); - if (App.Entity.facilities.farmyard.employeesIDs().size > 0) { // TODO: redo this with V.farmyardShowgirls - if (V.farmyardShows && (V.canine || V.hooved || V.feline)) { - const rule = makeRule( - ['Slaves', 'are putting on shows with animals'], - 'are', - "End shows", - [], - ["farmyardShows", "farmyardBreeding", "farmyardRestraints"] - ); - - rulesDiv.append(rule); + options.addOption(`Slaves ${V.farmyardShows ? `are` : `are not`} putting on shows.`, "farmyardShows") + .addValue(`Begin shows`, 1) + .addValue(`End shows`, 0); + if (V.farmyardShows && (V.canine || V.hooved || V.feline)) { if (V.seeBestiality) { + options.addOption(`Slaves ${V.farmyardBreeding ? `are` : `are not`} being bred with animals.`, "farmyardBreeding") + .addValue(`Begin breeding`, 1) + .addValue(`End breeding`, 0); + if (V.farmyardBreeding) { - const rule = makeRule( - ['Slaves', 'are being bred with animals'], - 'are', - "End breeding", - ["farmyardShows"], - ["farmyardBreeding", "farmyardRestraints"] - ); - - rulesDiv.append(rule); - - if (V.farmyardRestraints) { - const rule = makeRule( - 'are being restrained', - 'All of the slaves', - "Restrain only disobedient slaves", - ["farmyardShows", "farmyardBreeding"], - ["farmyardRestraints"] - ); - - rulesDiv.append(rule); - } else { - const rule = makeRule( - 'are being restrained', - 'Only disobedient slaves', - "Restrain all slaves", - ["farmyardShows", "farmyardBreeding", "farmyardRestraints"], - [] - ); - - rulesDiv.append(rule); - } - } else { - const rule = makeRule( - ['Slaves', 'being bred with animals'], - 'are not', - "Begin breeding", - ["farmyardShows", "farmyardBreeding"], - ["farmyardRestraints"] - ); - - rulesDiv.append(rule); + options.addOption(`${V.farmyardRestraints ? `All of the slaves` : `Only disobedient slaves`} are being restrained.`, "farmyardRestraints") + .addValue(`Restrain all slaves`, 1) + .addValue(`Restrain only disobedient slaves`, 0); } } - } else { - const rule = makeRule( - ['Slaves', 'putting on shows with animals'], - 'are not', - "Begin shows", - ["farmyardShows"], - ["farmyardBreeding", "farmyardRestraints"] - ); - - rulesDiv.append(rule); - } - } - - /** - * Creates a new rule button - * @param {string|string[]} descText The base description for the rule - * @param {string} boldText The part in bold - * @param {string} linkText The link text - * @param {string[]} enabled Variables to be set to 1 - * @param {string[]} disabled Variables to be set to 0 - */ - function makeRule(descText, boldText, linkText, enabled, disabled) { - const frag = new DocumentFragment(); - - const desc = document.createElement("div"); - const bold = App.UI.DOM.makeElement("span", boldText, "bold"); - const link = document.createElement("span"); - - if (Array.isArray(descText)) { - desc.append(`${descText[0]} `, bold, ` ${descText[1]}. `); - } else { - desc.append(bold, ` ${descText}. `); } - link.append(App.UI.DOM.link(linkText, () => { - enabled.forEach(i => V[i] = 1); - disabled.forEach(i => V[i] = 0); - - App.UI.DOM.replace(rulesDiv, rules); - })); - - desc.append(link); - frag.append(desc); - - return frag; + rulesDiv.append(options.render()); } return rulesDiv; @@ -496,9 +400,9 @@ App.Facilities.Farmyard.farmyard = function() { App.UI.DOM.appendNewElement("div", upgradesDiv, `${farmyardNameCaps} is currently using the basic water pump that it came with.`); upgradesDiv.append(createUpgrade( - "Upgrade the water pump", + `Upgrade the water pump`, pumpCost, - 'slightly decreases upkeep costs', + `slightly decreases upkeep costs`, "pump" )); } else { @@ -506,9 +410,9 @@ App.Facilities.Farmyard.farmyard = function() { if (!farmyardUpgrades.fertilizer) { upgradesDiv.append(createUpgrade( - "Use a higher-quality fertilizer", + `Use a higher-quality fertilizer`, fertilizerCost, - 'moderately increases crop yield and slightly increases upkeep costs', + `moderately increases crop yield and slightly increases upkeep costs`, "fertilizer" )); } else { @@ -516,9 +420,9 @@ App.Facilities.Farmyard.farmyard = function() { if (!farmyardUpgrades.hydroponics) { upgradesDiv.append(createUpgrade( - "Purchase an advanced hydroponics system", + `Purchase an advanced hydroponics system`, hydroponicsCost, - 'moderately decreases upkeep costs', + `moderately decreases upkeep costs`, "hydroponics" )); } else { @@ -526,9 +430,9 @@ App.Facilities.Farmyard.farmyard = function() { if (!farmyardUpgrades.seeds) { upgradesDiv.append(createUpgrade( - "Purchase genetically modified seeds", + `Purchase genetically modified seeds`, seedsCost, - 'moderately increases crop yield and slightly increases upkeep costs', + `moderately increases crop yield and slightly increases upkeep costs`, "seeds" )); } else { @@ -536,9 +440,9 @@ App.Facilities.Farmyard.farmyard = function() { if (!farmyardUpgrades.machinery) { upgradesDiv.append(createUpgrade( - "Upgrade the machinery", + `Upgrade the machinery`, machineryCost, - 'moderately increases crop yield and slightly increases upkeep costs', + `moderately increases crop yield and slightly increases upkeep costs`, "machinery" )); } else { @@ -564,10 +468,7 @@ App.Facilities.Farmyard.farmyard = function() { App.UI.DOM.replace(upgradesDiv, upgrades); }, - null, - '', - `Costs ${cashFormat(price)} and ${effect}.`), - ['indent']); + [], '', `Costs ${cashFormat(price)} and ${effect}.`), ['indent']); return frag; } @@ -575,21 +476,8 @@ App.Facilities.Farmyard.farmyard = function() { return upgradesDiv; } - function animals() { - animalsDiv.classList.add("farmyard-animals"); - - animalsDiv.append(kennels(), stables(), cages()); - - if (V.farmyardKennels || V.farmyardStables || V.farmyardCages) { - animalsDiv.append(removeHousing()); - } - - return animalsDiv; - } - function kennels() { - const baseCost = Math.trunc(5000 * V.upgradeMultiplierArcology); - const upgradedCost = Math.trunc(10000 * V.upgradeMultiplierArcology); + const cost = Math.trunc(5000 * V.upgradeMultiplierArcology); const CL = V.canine.length; @@ -609,29 +497,24 @@ App.Facilities.Farmyard.farmyard = function() { : `all kinds of canines`; if (V.farmyardKennels === 0) { - kennelsDiv.append(App.UI.DOM.link(`Add kennels`, () => { - cashX(forceNeg(baseCost), "farmyard"); + App.UI.DOM.appendNewElement("div", kennelsDiv, App.UI.DOM.link(`Add kennels`, () => { + cashX(forceNeg(cost), "farmyard"); V.farmyardKennels = 1; + V.PC.skill.engineering += .1; - App.UI.DOM.replace(kennelsDiv, kennels); - }, - null, - '', - `Costs ${cashFormat(baseCost)}, will incur upkeep costs, and unlocks domestic canines`)); + refresh(); + }, [], '', `Costs ${cashFormat(cost)}, will incur upkeep costs, and unlocks domestic canines.`), ['indent']); } else if (V.farmyardKennels === 1) { kennelsDiv.append(App.UI.DOM.passageLink("Kennels", "Farmyard Animals"), ` have been built in one corner of ${V.farmyardName}, and are currently ${CL < 1 ? `empty` : `occupied by ${dogs}`}.`); if (V.rep > 10000) { App.UI.DOM.appendNewElement("div", kennelsDiv, App.UI.DOM.link("Upgrade kennels", () => { - cashX(forceNeg(upgradedCost), "farmyard"); + cashX(forceNeg(cost * 2), "farmyard"); V.farmyardKennels = 2; + V.PC.skill.engineering += .1; - App.UI.DOM.replace(kennelsDiv, kennels); - }, - null, - '', - `Costs ${cashFormat(upgradedCost)} will incur additional upkeep costs, and unlocks exotic canines`), - ['indent']); + refresh(); + }, [], '', `Costs ${cashFormat(cost * 2)} will incur additional upkeep costs, and unlocks exotic canines.`), ['indent']); } else { App.UI.DOM.appendNewElement("div", stablesDiv, App.UI.DOM.disabledLink("Upgrade kennels", [`You must be more reputable to be able to house exotic canines.`]), @@ -645,8 +528,7 @@ App.Facilities.Farmyard.farmyard = function() { } function stables() { - const baseCost = Math.trunc(5000 * V.upgradeMultiplierArcology); - const upgradedCost = Math.trunc(10000 * V.upgradeMultiplierArcology); + const cost = Math.trunc(5000 * V.upgradeMultiplierArcology); const HL = V.hooved.length; @@ -657,28 +539,23 @@ App.Facilities.Farmyard.farmyard = function() { if (V.farmyardStables === 0) { App.UI.DOM.appendNewElement("div", stablesDiv, App.UI.DOM.link("Add stables", () => { - cashX(forceNeg(baseCost), "farmyard"); + cashX(forceNeg(cost), "farmyard"); V.farmyardStables = 1; + V.PC.skill.engineering += .1; - App.UI.DOM.replace(stablesDiv, stables); - }, - null, - '', - `Costs ${cashFormat(baseCost)}, will incur upkeep costs, and unlocks domestic hooved animals`)); + refresh(); + }, [], '', `Costs ${cashFormat(cost)}, will incur upkeep costs, and unlocks domestic hooved animals.`), ['indent']); } else if (V.farmyardStables === 1) { stablesDiv.append(App.UI.DOM.passageLink("Stables", "Farmyard Animals"), ` have been built in one corner of ${V.farmyardName}, and are currently ${HL < 1 ? `empty` : `occupied by ${hooved}`}.`); if (V.rep > 10000) { App.UI.DOM.appendNewElement("div", stablesDiv, App.UI.DOM.link("Upgrade stables", () => { - cashX(forceNeg(upgradedCost), "farmyard"); + cashX(forceNeg(cost * 2), "farmyard"); V.farmyardStables = 2; + V.PC.skill.engineering += .1; - App.UI.DOM.replace(stablesDiv, stables); - }, - null, - '', - `Costs ${cashFormat(upgradedCost)}, will incur additional upkeep costs, and unlocks exotic hooved animals`), - ['indent']); + refresh(); + }, [], '', `Costs ${cashFormat(cost * 2)}, will incur additional upkeep costs, and unlocks exotic hooved animals.`), ['indent']); } else { App.UI.DOM.appendNewElement("div", stablesDiv, App.UI.DOM.disabledLink("Upgrade stables", [`You must be more reputable to be able to house exotic hooved animals.`]), @@ -692,8 +569,7 @@ App.Facilities.Farmyard.farmyard = function() { } function cages() { - const baseCost = Math.trunc(5000 * V.upgradeMultiplierArcology); - const upgradedCost = Math.trunc(10000 * V.upgradeMultiplierArcology); + const cost = Math.trunc(5000 * V.upgradeMultiplierArcology); const FL = V.feline.length; @@ -713,29 +589,24 @@ App.Facilities.Farmyard.farmyard = function() { : `all kinds of felines`; if (V.farmyardCages === 0) { - cagesDiv.append(App.UI.DOM.link("Add cages", () => { - cashX(forceNeg(baseCost), "farmyard"); + App.UI.DOM.appendNewElement("div", cagesDiv, App.UI.DOM.link("Add cages", () => { + cashX(forceNeg(cost), "farmyard"); V.farmyardCages = 1; + V.PC.skill.engineering += .1; - App.UI.DOM.replace(cagesDiv, cages); - }, - null, - '', - `Costs ${cashFormat(baseCost)}, will incur upkeep costs, and unlocks domestic felines`)); + refresh(); + }, [], '', `Costs ${cashFormat(cost)}, will incur upkeep costs, and unlocks domestic felines.`), ['indent']); } else if (V.farmyardCages === 1) { cagesDiv.append(App.UI.DOM.passageLink("Cages", "Farmyard Animals"), ` have been built in one corner of ${V.farmyardName}, and are currently ${FL < 1 ? `empty` : `occupied by ${cats}`}.`); if (V.rep > 10000) { App.UI.DOM.appendNewElement("div", cagesDiv, App.UI.DOM.link("Upgrade cages", () => { - cashX(forceNeg(upgradedCost), "farmyard"); + cashX(forceNeg(cost * 2), "farmyard"); V.farmyardCages = 2; + V.PC.skill.engineering += .1; - App.UI.DOM.replace(cagesDiv, cages); - }, - null, - '', - `Costs ${cashFormat(upgradedCost)}, will increase upkeep costs, and unlocks exotic felines`), - ['indent']); + refresh(); + }, [], '', `Costs ${cashFormat(cost * 2)}, will increase upkeep costs, and unlocks exotic felines.`), ['indent']); } else { App.UI.DOM.appendNewElement("div", cagesDiv, App.UI.DOM.disabledLink("Upgrade cages", [`You must be more reputable to be able to house exotic felines.`]), @@ -749,27 +620,25 @@ App.Facilities.Farmyard.farmyard = function() { } function removeHousing() { - removeHousingDiv.classList.add("farmyard-remove"); - - const removeHousingPrice = ((V.farmyardKennels + V.farmyardStables + V.farmyardCages) * 5000) * V.upgradeMultiplierArcology; + const cost = ((V.farmyardKennels + V.farmyardStables + V.farmyardCages) * 5000) * V.upgradeMultiplierArcology; - App.UI.DOM.appendNewElement("div", removeHousingDiv, App.UI.DOM.link("Remove the animal housing", () => { - V.farmyardKennels = 0; - V.farmyardStables = 0; - V.farmyardCages = 0; + if (V.farmyardKennels || V.farmyardStables || V.farmyardCages) { + App.UI.DOM.appendNewElement("div", removeHousingDiv, App.UI.DOM.link("Remove the animal housing", () => { + V.farmyardKennels = 0; + V.farmyardStables = 0; + V.farmyardCages = 0; - V.farmyardShows = 0; - V.farmyardBreeding = 0; - V.farmyardRestraints = 0; + V.farmyardShows = 0; + V.farmyardBreeding = 0; + V.farmyardRestraints = 0; - clearAnimalsPurchased(); - cashX(forceNeg(removeHousingPrice), "farmyard"); + clearAnimalsPurchased(); + cashX(forceNeg(cost), "farmyard"); - App.UI.DOM.replace(removeHousingDiv, removeHousing); - }, - null, - '', - `Will cost ${cashFormat(removeHousingPrice)}`)); + refresh(); + }, + [], '', `Will cost ${cashFormat(cost)}.`), ['indent']); + } return removeHousingDiv; } @@ -783,4 +652,34 @@ App.Facilities.Farmyard.farmyard = function() { V.active.hooved = null; V.active.feline = null; } + + function rename() { + renameDiv.append(frag.appendChild(App.Facilities.rename(App.Entity.facilities.farmyard, () => { + farmyardNameCaps = capFirstChar(V.farmyardName); + + refresh(); + }))); + + return renameDiv; + } + + function slaves() { + slavesDiv.append(App.UI.DOM.appendNewElement("div", frag, App.UI.SlaveList.stdFacilityPage(App.Entity.facilities.farmyard), 'farmyard-slaves')); + + return slavesDiv; + } + + function refresh() { + App.UI.DOM.replace(introDiv, intro); + App.UI.DOM.replace(expandDiv, expand); + App.UI.DOM.replace(menialsDiv, menials); + App.UI.DOM.replace(rulesDiv, rules); + App.UI.DOM.replace(upgradesDiv, upgrades); + App.UI.DOM.replace(kennelsDiv, kennels); + App.UI.DOM.replace(stablesDiv, stables); + App.UI.DOM.replace(cagesDiv, cages); + App.UI.DOM.replace(removeHousingDiv, removeHousing); + App.UI.DOM.replace(renameDiv, rename); + App.UI.DOM.replace(slavesDiv, slaves); + } }; diff --git a/src/facilities/farmyard/farmyard.tw b/src/facilities/farmyard/farmyard.tw deleted file mode 100644 index c7f495ae5e62b3e2b6eb07feb32ee61e6f293d70..0000000000000000000000000000000000000000 --- a/src/facilities/farmyard/farmyard.tw +++ /dev/null @@ -1,7 +0,0 @@ -:: Farmyard [nobr jump-to-safe jump-from-safe] - -/* TODO: add "plots" of "crops" */ -/* TODO: allow slaves that can't walk to put on shows */ -/* TODO: write placeholders */ - -<<includeDOM App.Facilities.Farmyard.farmyard()>> diff --git a/src/facilities/incubator/incubatorInteract.js b/src/facilities/incubator/incubatorInteract.js index 9b57a3fe331332addaf70a257e3c0ce089afaf21..d5b12f2cf04d824b4dd2d60642932a62a84182ef 100644 --- a/src/facilities/incubator/incubatorInteract.js +++ b/src/facilities/incubator/incubatorInteract.js @@ -1566,6 +1566,7 @@ App.UI.incubator = function() { function refresh() { jQuery(settingsContent).empty().append(tankSettings()); jQuery(introSpan).empty().append(intro()); + jQuery(tanksContent).empty().append(tankBabies()); } } diff --git a/src/facilities/spa/spa.js b/src/facilities/spa/spa.js new file mode 100644 index 0000000000000000000000000000000000000000..5b26c11e11ac21035c817657351298257bb84647 --- /dev/null +++ b/src/facilities/spa/spa.js @@ -0,0 +1,246 @@ +App.Facilities.Spa.spa = function() { + const frag = new DocumentFragment(); + + const introDiv = App.UI.DOM.makeElement("div", null, ['spa-intro']); + const expandDiv = App.UI.DOM.makeElement("div", null, ['spa-expand']); + const upgradesDiv = App.UI.DOM.makeElement("div", null, ['spa-upgrades']); + const attendantDiv = App.UI.DOM.makeElement("div", null, ['spa-attendant']); + const slavesDiv = App.UI.DOM.makeElement("div", null, ['spa-slaves']); + const renameDiv = App.UI.DOM.makeElement("div", null, ['spa-rename']); + + let spaNameCaps = capFirstChar(V.spaName); + + const count = App.Entity.facilities.spa.employeesIDs().size; + + V.nextButton = "Back to Main"; + V.nextLink = "Main"; + V.returnTo = "Spa"; + V.encyclopedia = "Spa"; + + frag.append( + intro(), + expand(), + upgrades(), + attendant(), + slaves(), + rename(), + ); + + return frag; + + function intro() { + const text = []; + + const spaUtilization = 1 - (V.spaSpots / (V.spa * 20)); + + text.push(spaNameCaps); + + switch (V.spaDecoration) { + case "Roman Revivalist": + text.push(`is built as a Roman bath. The flooring is pleasantly warm due to a modernized version of hypocaust heating, and is covered in mosaic depicting slaves enjoying sex.`); + break; + case "Neo-Imperialist": + text.push(`is built as a modern Imperial garden. Bright green plants mix with the pulsating lights of high technology, and clear, sleek windows fog up with the steam of a central bath heated by the latest hydraulic technology.`); + break; + case "Aztec Revivalist": + text.push(`is built as an Aztec bathhouse. Water steams from the middle of the room and the air is heavy with the scent of herbs and essences. The idols by the door glisten with moisture.`); + break; + case "Egyptian Revivalist": + text.push(`is decorated like an Egyptian water garden. All but the hottest pools include aquatic plants around their edges, and the atmosphere is heavy with perfume.`); + break; + case "Edo Revivalist": + text.push(`is decorated like a traditional onsen. The stone-lined pools are surrounded by meticulously kept gardens, and there are proper provisions for bathing in the old Japanese style.`); + break; + case "Arabian Revivalist": + text.push(`looks like a dream of an Arabian palace garden. Every surface is richly tiled in vibrant colors, and the beguiling scents of perfumes from the Levant hang in the air.`); + break; + case "Chinese Revivalist": + text.push(`is gloomy and hot, filled with an oppressive steam that immediately dulls the senses. Though relaxation is possible and indeed easy here, it is a stultifying relaxation whose humid warmth seems to suppress independence.`); + break; + case "Chattel Religionist": + text.push(`is dedicated to the purification of the body and the spirit. The pools are arranged for the completion of self-purification procedures which include ritual masturbation.`); + break; + case "Degradationist": + text.push(`is utilitarian. There are waterproof cameras positioned throughout the spa so that anyone who wants to can watch the nude slaves. One wall has a screen showing the current viewer count to keep the slaves aware of this.`); + break; + case "Asset Expansionist": + text.push(`is utilitarian. It is equipped with all sorts of devices to help slaves care for huge assets, including lifts to help them in and out of the water, and all around showers to help clean and moisturize difficult to reach spots.`); + break; + case "Transformation Fetishist": + text.push(`is utilitarian. It is equipped with special devices to help speed surgical recovery, including a series of baths designed to prevent scarring.`); + break; + case "Repopulationist": + text.push(`is comfortable, with waterproof cushions lining the pools. It is equipped with all sorts of devices to aid pregnant slaves, including lifts to help them in and out of the water, baths just for their feet, and all around showers to help clean and moisturize difficult to reach spots.`); + break; + case "Eugenics": + text.push(`is comfortable, albeit split in half. One side for the lower classes' slaves, and the other for the Elite and their pets.`); + break; + case "Gender Radicalist": + text.push(`is comfortable, with waterproof cushions lining the pools. There are screens on the walls showing slave girls with all different varieties of genitalia orgasming from penetration, to keep the idea at the forefront of the slaves' minds.`); + break; + case "Gender Fundamentalist": + text.push(`is comfortable, with waterproof cushions lining the pools. There are screens on the walls showing light entertainment featuring a lot of beautiful women and handsome men for the slaves' edification.`); + break; + case "Physical Idealist": + text.push(`is not the gym, but it does have some workout equipment, mostly low-impact machines designed to speed recovery. There are special hot baths to ease sore muscles.`); + break; + case "Supremacist": + text.push(`is comfortable, with waterproof cushions lining the pools. There are screens on the walls showing light entertainment featuring $arcologies[0].FSSupremacistRace main characters.`); + break; + case "Subjugationist": + text.push(`is comfortable, with waterproof cushions lining the pools. There are screens on the walls showing light entertainment featuring $arcologies[0].FSSubjugationistRace characters in comic relief roles.`); + break; + case "Paternalist": + text.push(`is comfortable, with waterproof cushions lining the pools. There are screens on the walls showing light entertainment written by and intended for smart, loyal slaves.`); + break; + case "Pastoralist": + text.push(`is utilitarian. It is equipped with all sorts of devices to help slaves care for huge assets, including lifts to help them in and out of the water, and all around showers to help clean and moisturize difficult to reach spots.`); + break; + case "Maturity Preferentialist": + text.push(`is comfortable, but surprisingly businesslike. It's all about beautification here; there's a bewildering array of mud baths, resting pools, and massage setups, all designed to keep mature slaves looking their very best.`); + break; + case "Youth Preferentialist": + text.push(`is comfortable and fun. There are hot tubs and massage tables for slaves who feel like relaxing, but there's also a colder pool with pool toys for slaves who want to play. It even has a small waterslide.`); + break; + case "Body Purist": + text.push(`is comfortable, with waterproof cushions lining the pools. Everything is designed for the slaves' comfort; there are even special mud baths to perfect skin clarity.`); + break; + case "Slimness Enthusiast": + text.push(`is comfortable, with waterproof cushions lining the pools. Everything is designed for the slaves' comfort; there are even special mud baths to perfect skin clarity.`); + break; + case "Hedonistic": + text.push(`is comfortable, with waterproof cushions lining the pools. It is equipped with all sorts of devices to aid hefty slaves, including lifts to help them in and out of the water, specialized moisturizers to keep their skin healthy and smooth, and all around showers to help clean difficult to reach spots and between folds. ${V.arcologies[0].FSHedonisticDecadenceResearch === 1 ? `Platters of food and treats are readily available around the tubs so that relaxing slaves never have to strain to grab a bite to eat` : `Feeders connected to the slave food reserves line the pools so that so that relaxing slaves never have to strain to suck down their fill of food`}.`); + break; + case "Intellectual Dependency": + text.push(`is comfortable, fun and, most importantly, safe; even the dumbest slave can enjoy the pools without worrying their ${properTitle()}. There are screens on the walls showing simple entertainment designed to arouse more than titillate.`); + break; + case "Slave Professionalism": + text.push(`is comfortable, with waterproof cushions lining the pools. It is a place where a weary slave can rest their mind after a hards day's work. There are screens on the walls showing documentaries intended for smart, skilled slaves.`); + break; + case "Petite Admiration": + text.push(`is comfortable, but designed with short slaves in mind. The pools are shallow and easy to slip in and out of; taller slaves are likely to find them more frustrating than enjoyable.`); + break; + case "Statuesque Glorification": + text.push(`is comfortable, but designed with tall slaves in mind. The pools are deep; too deep for a short slave to find relaxing.`); + break; + default: + text.push(`is well-appointed, with massage tables, hot tubs, and a cold pool.`); + break; + } + + if (spaUtilization >= 1) { + text.push(`It's crowded in here. Slaves are relaxing in the warm water, splashing around or just floating. Here and there some of the more sex-starved are in the early stages of intercourse, but most prefer to take time off from it all. Unfortunately there is not enough space for all of your slaves to enjoy the spa.`); + } else if (spaUtilization >= 0.5 || (count / V.spa > 0.5)) { + text.push(`It's busy in here. Slaves are relaxing in the warm water, splashing around or just floating. Here and there some of the more sex-starved are in the early stages of intercourse, but most prefer to take time off from it all.`); + } else if (spaUtilization > 0 || count > 0) { + text.push(`It's sparsely populated; though the few slaves here have little company they like having the water to themselves.`); + } else if (S.Attendant) { + const {his} = getPronouns(S.Attendant); + text.push(`${S.Attendant.slaveName} is alone here, and has nothing to do but keep the place (and ${his} own soft, wet body) spotlessly clean.`); + } else { + text.push(`It's empty and quiet.`); + } + + App.UI.DOM.appendNewElement("div", introDiv, text.join(' '), ['scene-intro']); + + if (count === 0 && !S.Attendant) { + introDiv.append(App.UI.DOM.makeElement("div", App.UI.DOM.passageLink(`Decommission ${V.spaName}`, "Main", () => { + V.spa = 0; + V.spaDecoration = "standard"; + V.spaUpgrade = 0; + V.spaFix = 0; + }), ["indent"])); + } + + return introDiv; + } + + function expand() { + const cost = Math.trunc(V.spa * 1000 * V.upgradeMultiplierArcology); + + expandDiv.append(`${spaNameCaps} can house ${V.spa} slaves while they recuperate here. There ${count === 1 ? `is currently ${count} slave` : `are currently ${count} slaves`} recuperating in ${V.spaName}.`); + + App.UI.DOM.appendNewElement("div", expandDiv, App.UI.DOM.link(`Expand ${V.spaName}`, () => { + cashX(forceNeg(cost), "capEx"); + V.spa += 5; + V.PC.skill.engineering += .1; + + refresh(); + }, [], '', `Costs ${cashFormat(cost)} and increases the capacity of ${V.spaName} by 5.`), ["indent"]); + + if (count > 0) { + expandDiv.append(removeFacilityWorkers("spa", "rest", "rest")); + } + + return expandDiv; + } + + function upgrades() { + if (V.spaUpgrade === 1) { + upgradesDiv.append(`${spaNameCaps} has been upgraded with state of the art temperature treatment options, from hot and cold mineral water pools to baking saunas and dense steam rooms.`); + } else { + const cost = Math.trunc(V.spa * 1000 * V.upgradeMultiplierArcology); + + upgradesDiv.append(`${spaNameCaps} is a standard spa.`); + + App.UI.DOM.appendNewElement("div", upgradesDiv, App.UI.DOM.link(`Upgrade ${V.spaName} with saunas, steam rooms, and mineral water baths`, () => { + cashX(forceNeg(cost), "capEx"); + V.spaUpgrade = 1; + + refresh(); + }, [], '', `Costs ${cashFormat(cost)} and increases the effectiveness of ${V.spaName}.`), ["indent"]); + } + + return upgradesDiv; + } + + function attendant() { + if (S.Attendant) { + const {him, he, his} = getPronouns(S.Attendant); + + const options = new App.UI.OptionsGroup(); + + if (V.spaFix === 2) { + attendantDiv.append(`${S.Attendant.slaveName} is focusing only on the health and wellness of the slaves under ${his} care, obeying your orders to avoid attempting to right mental flaws.`); + } else if (V.spaFix === 1) { + attendantDiv.append(`${S.Attendant.slaveName} is focusing on the health and wellness of the slaves under ${his} care, as well as trying to bring mindbroken slaves back, while ignoring any mental hang-ups a slave may have.`); + } else { + attendantDiv.append(`${S.Attendant.slaveName} is not following any special orders and is tending to your slaves as ${he} sees fit.`); + } + + options.addOption(``, "spaFix") + .addValue(`Order ${him} to not fix any flaws`, 2) + .addValue(`Order ${him} to only fix mindbroken slaves`, 1) + .addValue(`Let ${him} tend as ${he} sees fit`, 0); + + App.UI.DOM.appendNewElement("div", attendantDiv, options.render(), ['indent']); + } + + return attendantDiv; + } + + function slaves() { + slavesDiv.append(App.UI.SlaveList.stdFacilityPage(App.Entity.facilities.spa, true)); + + return slavesDiv; + } + + function rename() { + renameDiv.append(App.Facilities.rename(App.Entity.facilities.spa, () => { + spaNameCaps = capFirstChar(V.spaName); + + refresh(); + })); + + return renameDiv; + } + + function refresh() { + App.UI.DOM.replace(introDiv, intro); + App.UI.DOM.replace(expandDiv, expand); + App.UI.DOM.replace(upgradesDiv, upgrades); + App.UI.DOM.replace(attendantDiv, attendant); + App.UI.DOM.replace(slavesDiv, slaves); + App.UI.DOM.replace(renameDiv, rename); + } +}; diff --git a/src/facilities/surgery/surgeryPassageStructural.js b/src/facilities/surgery/surgeryPassageStructural.js index ec79ab27381b82cdd64d1187148169a716b17ed9..d8e9f58d21d1d9820837339598d577821240908e 100644 --- a/src/facilities/surgery/surgeryPassageStructural.js +++ b/src/facilities/surgery/surgeryPassageStructural.js @@ -236,7 +236,7 @@ App.UI.surgeryPassageStructural = function(slave, cheat = false) { } else if (slave.heightImplant >= 1) { if (slave.height < (Height.mean(slave) + 15) && V.surgeryUpgrade === 1) { linkArray.push(makeLink( - "Advanced height gain surger", + "Advanced height gain surgery", "height", increaseHeight )); diff --git a/src/gui/Encyclopedia/encyclopedia.tw b/src/gui/Encyclopedia/encyclopedia.tw index 8bec530a64d37e17818470fdcf6d9474fbbfb5be..edffac124be14157666322313a29a1dee2fa2dcb 100644 --- a/src/gui/Encyclopedia/encyclopedia.tw +++ b/src/gui/Encyclopedia/encyclopedia.tw @@ -51,168 +51,9 @@ $encyclopedia <br><<= App.Encyclopedia.Dialog.linkSC("Credits", "Credits")>> </div> -/********** -Design Your Master TODO unify with "Design Your Master" article -**********/ -<<case "Design Your Master in SecExp">> - This happens at the start of a game of FC: it is not possible to change the PC during the main game. The player must select a career background, a rumored method of acquiring the arcology, and their age group; then choose between some broad body and gender options. - - <br><br>''Wealth'' is a choice for both the ''career background'' and ''rumored method of acquiring the arcology'' options. Both provide you with @@.yellowgreen;<<print cashFormat(10000)>>@@ each for a total of @@.yellowgreen;<<print cashFormat(30000)>>@@ if both are chosen. As a ''background option'' it means that your starting slaves will have two free levels of sex skills available and maintaining @@.darkviolet;<<= App.Encyclopedia.Dialog.linkSC("authority", "Security Expansion")>>@@ will be harder, but upgrades in the propaganda hub will be @@.yellowgreen;<<= App.Encyclopedia.Dialog.linkSC("cheaper", "Money")>>@@. - - <br><br>__Career background options__ - <br>Being an ex- - <br>''business owner'' (also referred to as capitalist) enhances the business-focused personal attention, increasing the @@.yellowgreen;<<= App.Encyclopedia.Dialog.linkSC("money", "Money")>>@@ it produces and improving arcology prosperity when business-focused personal attention is selected. Also, upgrades in the propaganda hub will be @@.yellowgreen;<<= App.Encyclopedia.Dialog.linkSC("cheaper", "Money")>>@@ and your starting slaves will have a free level of prostitution skill available. - Starts having already mastered <<= App.Encyclopedia.Dialog.linkSC("Trading", "PC Skills")>>. - - <br><br>''private security contractor'' (also referred to as a //mercenary background//) greatly reduces the cost of keeping mercenaries in your employ. Upgrades in the security HQ will be @@.yellowgreen;<<= App.Encyclopedia.Dialog.linkSC("cheaper", "Money")>>.@@ - Your starting slaves will have free @@.mediumaquamarine;<<= App.Encyclopedia.Dialog.linkSC("trust", "Trust")>>@@ available. - Starts having already mastered <<= App.Encyclopedia.Dialog.linkSC("Warfare", "PC Skills")>>. - - <br><br>''slave driver'' enhances slave-focused personal attention, adding bonus @@.hotpink;<<= App.Encyclopedia.Dialog.linkSC("devotion", "From Rebellious to Devoted")>>@@ or @@.mediumaquamarine;<<= App.Encyclopedia.Dialog.linkSC("trust", "Trust")>>@@ to many training applications or preventing their loss. @@.darkviolet;<<= App.Encyclopedia.Dialog.linkSC("Authority", "Security Expansion")>>@@ will be easier to maintain. Plus upgrades in the security HQ will be @@.yellowgreen;<<= App.Encyclopedia.Dialog.linkSC("cheaper", "Money")>>.@@ - Starting slaves will be cheaper, in addition having already mastered <<= App.Encyclopedia.Dialog.linkSC("Slaving", "PC Skills")>>. - - <br><br>''arcology engineer'' provides a significant discount on many @@.yellowgreen;arcology upgrades and expansions.@@ In addition to the arcology starting off with @@.green;basic economic upgrades@@ already installed. Starts having already mastered <<= App.Encyclopedia.Dialog.linkSC("Engineering", "PC Skills")>>. - - <br><br>''doctor'' allows the player character to perform surgery personally, providing a @@.yellowgreen;discount on surgery costs@@ and a @@.green;reduction to resulting health damage.@@ Additionally, slaves may react differently to surgery if the player character performs it and starting slaves will have free implants available. Starts having already mastered <<= App.Encyclopedia.Dialog.linkSC("Medicine", "PC Skills")>>. - - <br><br>''escort'' provides a one-time bonus to a slave's entertainment, whoring, and two sexual skills when a new slave is acquired. Furthermore, society will not take lightly to being run by an ex-whore, and you will receive heavy @@.green;<<= App.Encyclopedia.Dialog.linkSC("reputation", "Arcologies and Reputation")>>@@ and @@.darkviolet;<<= App.Encyclopedia.Dialog.linkSC("authority", "Security Expansion")>>@@ losses each week. You can spend your free time selling your body for @@.yellowgreen;<<= App.Encyclopedia.Dialog.linkSC("money", "Money")>>,@@ at the cost of a large amount of @@.green;<<= App.Encyclopedia.Dialog.linkSC("reputation", "Arcologies and Reputation")>>.@@ - - <br><br>''celebrity'' provides extra @@.green;<<= App.Encyclopedia.Dialog.linkSC("reputation", "Arcologies and Reputation")>>@@ at game start and upgrades in the propaganda hub will be @@.yellowgreen;<<= App.Encyclopedia.Dialog.linkSC("cheaper", "Money")>>@@. - Starting slaves will have a free level of entertainment skill available. - - <br><br>''servant'' provides a one-time bonus to a slave's @@.mediumaquamarine;<<= App.Encyclopedia.Dialog.linkSC("trust", "Trust")>>@@ and @@.hotpink;<<= App.Encyclopedia.Dialog.linkSC("devotion", "From Rebellious to Devoted")>>.@@ Furthermore, society will not approve of being run by an ex-servant, and you will face @@.green;<<= App.Encyclopedia.Dialog.linkSC("reputation", "Arcologies and Reputation")>>@@ and @@.darkviolet;<<= App.Encyclopedia.Dialog.linkSC("authority", "Security Expansion")>>@@ losses each week. You can spend your free time, putting your previous experience to use, by greatly reducing the costs of your penthouse. You also passively reduce costs when not focusing on doing so. - - <br><br>''gang leader'' provides a one-time bonus to a slave's health and a free level of combat skill. Furthermore, society will not approve of being run by a gang-banger, and you will face @@.green;<<= App.Encyclopedia.Dialog.linkSC("reputation", "Arcologies and Reputation")>>@@ losses each week. New slaves will likely have heard of your previous exploits and fear you. - You know how to haggle slaves and assert your @@.darkviolet;<<= App.Encyclopedia.Dialog.linkSC("authority", "Security Expansion")>>.@@ Plus upgrades in the security HQ will be @@.yellowgreen;<<= App.Encyclopedia.Dialog.linkSC("cheaper", "Money")>>@@. - You can spend your free time, putting your previous experience to use, proving another source of income however this isn't guaranteed. - - <br><br>''incursion specialist'' provides starting slaves with a free level of @@.cyan;intelligence.@@ Also certain upgrades may be @@.yellowgreen;<<= App.Encyclopedia.Dialog.linkSC("cheaper", "Money")>>@@ and you may find alternative approaches to problems, but you will find @@.darkviolet;<<= App.Encyclopedia.Dialog.linkSC("authority", "Security Expansion")>>@@ quite hard to maintain. - Starts having already mastered <<= App.Encyclopedia.Dialog.linkSC("Hacking", "PC Skills")>>. - - <br><br> - <<= App.Encyclopedia.Dialog.linkSC("Hide SecExp details", "Design Your Master")>>. - - <br><br>__Rumored acquisition options__ - <br>''Hard Work'' provides a one-time bonus to both @@.hotpink;<<= App.Encyclopedia.Dialog.linkSC("devotion", "From Rebellious to Devoted")>>@@ and @@.mediumaquamarine;<<= App.Encyclopedia.Dialog.linkSC("trust", "Trust")>>@@ when a new slave is acquired. - - <br><br>''Force'' means that if a slave does not have enough @@.hotpink;<<= App.Encyclopedia.Dialog.linkSC("devotion", "From Rebellious to Devoted")>>@@ to obey when acquired, this option will terrify her and reduce her @@.mediumaquamarine;<<= App.Encyclopedia.Dialog.linkSC("trust", "Trust")>>@@ to the point where she should comply. - - <br><br>''Social Engineering'' means that you will start with the first societal option unlocked, since you manipulated the arcology's citizens. - - <br><br>''Luck'' provides extra @@.green;<<= App.Encyclopedia.Dialog.linkSC("reputation", "Arcologies and Reputation")>>@@ at game start, but no ongoing advantages once the main game begins. - - <br><br>__Age groups__ - <br>Older PCs enjoy easier @@.green;<<= App.Encyclopedia.Dialog.linkSC("reputation", "Arcologies and Reputation")>>@@ maintenance, but possess lower <<= App.Encyclopedia.Dialog.linkSC("sexual energy", "Sexual Energy")>> while younger PC's are the opposite. - - <br><br>__Body and gender options__ - <br>All PC body changes will alter scenes, but their main mechanical effect is on @@.green;<<= App.Encyclopedia.Dialog.linkSC("reputation", "Arcologies and Reputation")>>@@ maintenance. Feminine options will make it harder to maintain @@.green;<<= App.Encyclopedia.Dialog.linkSC("reputation", "Arcologies and Reputation")>>@@ without providing any gameplay advantage, making playing as a feminine PC a form of increased difficulty. There are other minor gameplay differences including differing slave reactions to the PC based on attraction, but these are fairly minor. - /********** BEING IN CHARGE **********/ -<<case "Being in Charge">> - //Future room for lore text// - - <br><br> - Choose a more particular entry below: - <br> - -<<case "Arcologies and Reputation">> - Arcologies are the urban buildings of the future: almost completely self-contained, almost completely self sufficient. In the anarcho-liberal 'paradise' of the Free Cities, as owner of your own arcology you are like a modern-day feudal suzerain, lord and master. - - <br><br>Your arcology is a flared structure, needle thin at the top where you live in your penthouse, and broad at the base. The base below ground contains storage and machinery. The lowest aboveground levels are commercial; above them are the residential areas. The entire structure is jacketed in dense gardens and solar arrays, cleverly structured to create naturally lit corridors and beautiful park-like balconies. - - <br><br>— Owner's Report - - <br><br>//You may wish to improve your arcology, but should be able to ignore its development, if you wish.// - - <br><br>//Your @@.green;<<= App.Encyclopedia.Dialog.linkSC("reputation", "Arcologies and Reputation")>>@@ is, of course, already quite impressive. The @@.green;<<= App.Encyclopedia.Dialog.linkSC("reputation", "Arcologies and Reputation")>>@@ tracked in the sidebar is specifically your @@.green;<<= App.Encyclopedia.Dialog.linkSC("reputation", "Arcologies and Reputation")>>@@ as a slaveowner. It can be raised through decadent actions that display your munificence and opulence. Some random events can increase it, but the most reliable way to improve your @@.green;<<= App.Encyclopedia.Dialog.linkSC("reputation", "Arcologies and Reputation")>>@@ is to send sexually skilled slaves out into the arcology to offer free sexual services. This assignment is very similar to prostitution, but produces @@.green;<<= App.Encyclopedia.Dialog.linkSC("reputation", "Arcologies and Reputation")>>@@ rather than @@.yellowgreen;<<= App.Encyclopedia.Dialog.linkSC("money", "Money")>>@@.// - - <br><br>//As your @@.green;<<= App.Encyclopedia.Dialog.linkSC("reputation", "Arcologies and Reputation")>>@@ develops, you may have the opportunity to guide the future of your arcology's society. Successfully doing so will increase your @@.green;<<= App.Encyclopedia.Dialog.linkSC("reputation", "Arcologies and Reputation")>>@@ in turn, which will duly enable you to further shape society. Managing societal development well will have a recursive effect on your @@.green;<<= App.Encyclopedia.Dialog.linkSC("reputation", "Arcologies and Reputation")>>,@@ and can drive it to great heights.// - - <br><br>//The benefits of high @@.green;<<= App.Encyclopedia.Dialog.linkSC("reputation", "Arcologies and Reputation")>>@@ are numerous. Many business and enslavement opportunities will open to you once you are reputable. Some of the most advanced technology is only available to those with impeccable @@.green;<<= App.Encyclopedia.Dialog.linkSC("reputations", "Arcologies and Reputation")>>@@ as slaveowners, and many of the finer slave markets will only consider reputable buyers. You may eventually become so renowned that merely branding a slave with your mark will increase her value on the open market.// - - <br><br>//However, your @@.green;<<= App.Encyclopedia.Dialog.linkSC("reputation", "Arcologies and Reputation")>>@@ will not look after itself. At a certain point, you will become so reputable that continual effort will be necessary to maintain your renown. The old world question "What have you done for me lately?" is asked with twice the force in the Free Cities! You will quickly find that this natural decay of @@.green;<<= App.Encyclopedia.Dialog.linkSC("reputation", "Arcologies and Reputation")>>@@ can overwhelm your efforts to improve it by the end of the week. A concerted strategy will be necessary to overcome this.// - - -<<case "Random Events">> - At the end of every turn, a random event may occur. Almost all random events are tied to necessary preconditions. For example, events concerning @@.mediumorchid;<<= App.Encyclopedia.Dialog.linkSC("rebellious", "From Rebellious to Devoted")>>@@ slaves will stop happening if all the player's slaves become obedient. - - <br><br>Usually, a situation will be presented and the player may choose one of two or three resolutions. Please note that the player may also to choose none of these by using the "continue" button in the sidebar; in effect, this usually means the player's character has simply declined to involve himself. - - <br><br>Almost all choices will result in small effects. The most common are changes to a slave's attitude towards the player's character, but there are others. - - <br><br>Finally, there are events that can result in the player being offered the chance to acquire new slaves, some of which can be unique or valuable. Generally, these events offer this livestock at an extremely discounted price. These events will appear more often the higher the player's @@.green;<<= App.Encyclopedia.Dialog.linkSC("reputation", "Arcologies and Reputation")>>@@ becomes. - - -<<case "Costs Summary">> - Aphrodisiacs are @@.yellowgreen;<<= App.Encyclopedia.Dialog.linkSC("cheap", "Money")>>@@ and cost @@.yellowgreen;<<print cashFormat($drugsCost)>>@@ weekly; curatives are expensive and cost @@.yellowgreen;<<print cashFormat(($drugsCost*3))>>@@ weekly; while all other drug regimes cost @@.yellowgreen;<<print cashFormat(($drugsCost*2))>>.@@ Standard hormone regimens cost @@.yellowgreen;<<print Math.trunc($drugsCost*1*0.5)>>@@ while intensive hormone treatment costs @@.yellowgreen;<<print Math.trunc($drugsCost*2*0.5)>>.@@ Contraceptives cost @@.yellowgreen;<<print Math.trunc($drugsCost*0.5)>>.@@ - - <br><br> - Slaves on spare living standards are fed a bland diet and obliged to sleep on bedrolls. Keeping a slave under restrictive rules costs @@.yellowgreen;<<print cashFormat($rulesCost)>>@@ weekly. - - <br><br> - Slaves enjoying luxurious living standards on the other hand are fed a tasty diet and permitted to sleep in comfortable beds, and are generally pampered. The increased luxury of permissive rules costs @@.yellowgreen;<<print cashFormat(($rulesCost*3))>>@@ weekly. - - <br><br> - Some arcology upgrades may have associated upkeep costs as well. - - -<<case "Rules Assistant">> - ''The Rules Assistant'' is a system to apply multiple rule sets to multiple slaves at once. You can apply rules to slaves based on slave ''@@.hotpink;<<= App.Encyclopedia.Dialog.linkSC("devotion", "From Rebellious to Devoted")>>@@'', ''@@.mediumaquamarine;<<= App.Encyclopedia.Dialog.linkSC("trust", "Trust")>>@@'', ''sex drive'', ''health'', ''<<= App.Encyclopedia.Dialog.linkSC("weight", "Weight")>>'', ''<<= App.Encyclopedia.Dialog.linkSC("muscles", "Musculature")>>'', ''lactation'', ''pregnancy'', ''number of fetuses'', ''abdominal implants'' and ''age''. - - <br><br>__Rule settings:__ - Rules can be used to control certain aspects of slaves everyday lives, for example to automatically give slaves a certain clothing option, collar, footwear or allow slaves to choose their own outfit. They can be used to give unhealthy slaves curatives to improve their health or to put slaves on a diet so that their <<= App.Encyclopedia.Dialog.linkSC("weight", "Weight")>> can be closer to the ideal weight. Rules set to 'No default setting' will not apply that particular condition to slaves. - Rules can also be renamed to be more indicative of their intended purpose. - - <br><br>__Rule activation:__ - In order to apply a rule to slaves, the activation will need to be set. Choose an activation type (@@.hotpink;<<= App.Encyclopedia.Dialog.linkSC("devotion", "From Rebellious to Devoted")>>,@@ @@.mediumaquamarine;<<= App.Encyclopedia.Dialog.linkSC("trust", "Trust")>>,@@ sex drive, <<= App.Encyclopedia.Dialog.linkSC("health", "Health")>>, <<= App.Encyclopedia.Dialog.linkSC("weight", "Weight")>>, <<= App.Encyclopedia.Dialog.linkSC("muscles", "Musculature")>>, lactation, pregnancy, fetuses, implant size, or age) and then choose the level at which to apply. For example to apply a rule to obedient slaves, choose '@@.hotpink;<<= App.Encyclopedia.Dialog.linkSC("devotion", "From Rebellious to Devoted")>>@@' for the activation and 4 or more for the lower limit by selecting '>='. - - <br><br>__Selecting or excluding slaves from a rule:__ - Slaves can be selected for a rule by selecting slaves from the list so that a rule can apply only to them. Slaves can similarly be excluded from a rule. - - <br><br>__Applying a rule to specific assignments:__ - You can apply a rule only to slaves on individual assignments by selecting them under 'Apply to assignments'. For example a rule can give aphrodisiacs to slaves on whoring assignments. ''This is mutually exclusive to automatically giving an assignment to slaves''. - - <br><br>__Automatically giving an assignment:__ - A rule can be set to automatically set a slave to an assignment when activated. For example a @@.hotpink;<<= App.Encyclopedia.Dialog.linkSC("devoted", "From Rebellious to Devoted")>>@@ slave can be set to automatically be put on the whoring assignment. ''This is mutually exclusive to applying a rule to assignments''. - - <br><br>__Applying a rule to facilities:__ - You can apply a rule to slaves in any or all facilities as long as that facility has been constructed. The rule will only apply to slaves within the selected facilities. ''This is mutually exclusive to automatically putting slaves into a facility''. - - <br><br>__Automatically assigning slaves to a facility:__ - A rule can be set to automatically put a slave into a facility when activated. For example disobedient slaves can be set to automatically be confined in the arcade if it has been constructed. ''This is mutually exclusive to applying a rule to facilities''. - - <br><br>__Saving a rule:__ - If you are finished setting up a rule ''make sure to save it'' by clicking 'Save rule' at the bottom before clicking another link otherwise your settings will be lost. - - <br><br>__Applying a rule:__ - Clicking on 'Apply rules' will automatically save the current rule and apply all rules to slaves at once. - - <br><br>__Adding or removing a rule:__ - The game starts with 3 basic default rule settings but more can be added and/or removed as needed. To add a new rule, click 'Add a new rule' at the bottom, removing a rule is the same by clicking 'Remove rule'. - - -<<case "The Corporation">> - Once you are fairly reputable and have a large sum of cash in the bank, you will receive a brief end of turn event that unlocks the ability to found a corporation dedicated to slaving. Once this happens, you can incorporate from the 'Manage Corporation' link on the sidebar, and once you've done that, you can manage your corporation every week from the same place. - - <br><br>__Shares__ - Buying shares from the corporation or issuing new shares will create new shares in the corporation. If you buy them yourself, cash will be transferred from you to the corporation in return for the shares; if you direct the corporation to issue new public shares, @@.yellowgreen;<<= App.Encyclopedia.Dialog.linkSC("money", "Money")>>@@ will come into the corporation from the market. If you direct the corporation to buy back shares from the public, cash will be transferred from the corporation to reduce the number of public shares, which will increase your ownership percentage. You are not permitted to give up majority ownership of the corporation. Selling your shares or buying publicly held shares are both transactions between you and your shares and shareholders and their shares. All transactions impact the stock price. - - <br><br>__Divisions__ - The corporation consists of divisions. Starting up your corporation requires you to choose a single division as starting point and you will be able to expand into linked divisions once you have grown sufficiently in size. There are 3 general categories of divisions; acquisition, modification and exploitation. The first consists of legal and extralegal enslavement and they feed fresh slaves into either your corporation or the market at large. Investing in one of these is a good starting point when slave prices are high. Do note that each slave acquired and sold reduces the demand for slaves on the market. This means little at first, but when large enough will impact the market significantly.<br> - The second category consists of slave breaking, physical slave modifications and slave training. These divisions either take improvable slaves from your acquisition divisions or the slave market and improve them. Slaves can go from breaking to physical modifications to training and become highly valuable slaves by the end of it. If the slave market is balanced or you are looking for a safe initial investment these divisions are a good choice. Their market impact is neutral, buying slaves reduces supply but selling them back onto the market reduces demand by the same amount.<br> - The final category consists of an arcade, menial services, dairy and escort division. These divisions require a particular quality of slave and then put them to work in their respective fields. As these divisions operate they will have to write off some of their slaves and replace them with fresh ones, you can provide these slaves through your acquisition or modification divisions or the market. Whenever prices are low these divisions operate at a higher margin, making them a great first division when slave prices are low. Do note that each slave bought from the market reduces the supply of slaves. As these divisions grow and write off more and more slaves each week, replenishing them from the market will begin to impact the market significantly. - - <br><br>__Management__ - Your first division will automatically buy and/or sell slaves in order to do business and make money. It is up to the player to decide when to expand the division's capacity, but investing aggressively early will pay off in the long run. Once your corporation has gotten a little time to grow its value (the sum of slave value, division value, cash on hand and dividends reserved) the end of week report will prompt you that a new division can be added. This requires a significant cash investment so you may have to save up a little. Adding divisions comes with efficiency benefits, but also adds overhead costs. Adding a second division will hardly slow you down, but as you grow these costs grow ever larger; depending on the number of divisions, but also the size of them.<br> - Any new division will have at least one direct link to your current divisions, meaning it can either use slaves from a division or provide them to another division. New divisions are not automatically set to buy and/or sell slaves from the market. It is expected the player either manually moves slaves between divisions or sets up automatic links between them using several rules.<br> - You have the ability to reduce the size of your divisions or dissolve them entirely. While this only recoups 80% of the investment it may sometimes be prudent to do so, i.e. in case market conditions have become unfavorable for the division and/or overhead costs are becoming oppressively high. Also note that divisions become less efficient the larger they get (even without considering overhead), eventually growing it further will hurt your profit, not improve it. You will want to cut your losses early or otherwise suffer the consequences.<br> - In order to personally benefit monetarily from your corporation you will have to decide how much of its profit will be set aside to be paid out as dividends. Setting low or no dividends allows for rapid development, while siphoning a lot of profits away from the corporation will slow it down significantly. Please note that the corporation does not pay out every week but only every quarter (13 weeks). - - <br><br>__Slave Sales__ - Once a corporation is created, it will get its own establishment in the slave market. As the corporation's value increase, it can be given direction about what kind of slaves it should train and how it should train them, which will affect the slaves seen in the corporate catalog. As with divisions; the higher your corporation's value, the more specializations you are allowed to choose. Your corporation's divisions determine which specialization options are available. Each division has a unique specialization associated with it while many others are slightly more general and linked to either acquisition or modification. All kinds of restrictions may apply depending on Future Society choices and the size of your divisions. Several specializations can be enhanced beyond the first choice, but again you may need to satisfy certain conditions first.<br> - If the corporation's slaves have qualities that make them especially appealing to an arcology's citizens, the corporation will enjoy increased profits, and the <<= App.Encyclopedia.Dialog.linkSC("future society", "Future Societies")>> creating the demand will progress more rapidly due to the supply of appealing slaves. All arcologies present in the Free City will interact with the corporation this way, making shares in a corporation which supplies girls that appeal to the whole city extremely lucrative. <<case "Demand for Sex">> The Free Cities naturally facilitate a healthy sex industry which provides lucrative business opportunities. But you are not the only one who can provide sexual services and you may find yourself in competition for the large, but ultimately limited, amount of sexual desires within the arcology. Clever manipulations can influence both the demand as well as the supply to improve the attractiveness of your arcology and fill your coffers. @@ -223,36 +64,6 @@ BEING IN CHARGE <br><br>Slaves assigned as whores can be used to satisfy any of the different classes of citizens, if they are desirable and skilled enough, that is. Slaves assigned to serve the public are suitable for the sexual relief of the lower half of your citizenry and the arcade generally only serves the very bottom of your arcology. -<<case "Sexual Energy">> - <<setPlayerPronouns>> - Though you're (naturally) a virile, oversexed oligarch, even your reserves of sexual energy are not infinite. They're impressive, but not infinite. Since one turn represents one week, the game does not allow the player direct control over every sexual interaction between the player character and _hisP slaves. Put another way, the game assumes there's an impressive amount of off-screen sex going on between the <<= properMaster()>> and _hisP chattel. - - <br><br>The player character's sexual energy can have gameplay effects. Though of course all slaves are at the <<= properMaster()>>'s sexual beck and call, some assignments and training methods involve close sexual attention by the player character. If a large number of slaves are subject to this, the player character's attention will be somewhat diluted, and the effects on each slave will be reduced. Slaves assigned to be __fucktoys__ and serve in the __master suite__ count towards a hidden estimation of the player character's sexual foci. With two or fewer such slaves, the player character's sexual attention on these slaves will be intense and have intense effects. With five or more, the player character may have some difficulty in using every slave every day, diluting the mental effects of being the <<= properMaster()>>'s personal sex toy. - - <br><br>It is possible to raise these limits by focusing on sexual decadence for the week. By paying less attention to business and not using sexual training on specific slaves, the player character will have more energy to spare and can offer intense sexual attention to three slaves or give sexual attention to up to seven slaves without dilution. - - <br><br>There exist several other ways to raise the player's sexual energy as well. - -<<case "PC Skills">> - <br><br>''Trading'' signifies how efficient you are at making exchanges. Provides more passive income the higher it is. - Can be increased through acquiring slaves. - - <br>''Warfare'' is an indication your combat prowess. Cuts cost of housing mercs in half. - Can be increased through use in relevant situations. - - <br>''Hacking'' is an indication of your effectiveness at manipulating computer systems. Higher levels make technological upgrades @@.yellowgreen;<<= App.Encyclopedia.Dialog.linkSC("cheaper", "Money")>>@@ or free, provides a boost situations where fame is measured digitally. - Can be increased through choosing to 'Sell your intrusion services to the highest bidder' once the option becomes available after having 'some' skill and purchasing technological upgrades. - - <br>''Slaving'' improves your effectiveness as a slave driver. At max level it allows you to more easily spot <<= App.Encyclopedia.Dialog.linkSC("gingering", "Gingering")>>. - Can be increased through acquiring performing the duties of a slave driver. - - <br>''Engineering'' is a sign of how effective you are building and maintenance. Mastering the skill reduces the cost of @@.yellowgreen;arcology upgrades and expansions.@@ - Can be increased through purchasing arcology upgrades or expanding facility capacity. If the <<= App.Encyclopedia.Dialog.linkSC("Security Expansion", "Security Expansion")>> mod is enabled, the skill is also increased by repairing your arcology. - - <br>''Medicine'' shows how effective you are treating wounds. Max level reduces a slave's health and @@.mediumaquamarine;<<= App.Encyclopedia.Dialog.linkSC("trust", "Trust")>>@@ loss during surgery. - - In addition to the above methods of increasing a skill (if any), all of them can be learnt by retaining a trainer<<if $SF.Toggle && $SF.Active >= 1>> or by talking to/learning from The Colonel<</if>>. - /********** SLAVES **********/ diff --git a/src/gui/Encyclopedia/encyclopediaBeingInCharge.js b/src/gui/Encyclopedia/encyclopediaBeingInCharge.js new file mode 100644 index 0000000000000000000000000000000000000000..a8c11fcbbd9207d71fb5c45b815c9656c77e4dfb --- /dev/null +++ b/src/gui/Encyclopedia/encyclopediaBeingInCharge.js @@ -0,0 +1,296 @@ +App.Encyclopedia.addArticle("Being in Charge", function() { + const f = new DocumentFragment(); + App.UI.DOM.appendNewElement("p", f, "Future room for lore text", "scene-intro"); + App.UI.DOM.appendNewElement("p", f, "Choose a more particular entry below:"); + return f; +}, "beingInCharge"); + +App.Encyclopedia.addArticle("Arcologies and Reputation", function() { + const f = new DocumentFragment(); + let r; + + App.UI.DOM.appendNewElement("p", f, "Arcologies are the urban buildings of the future: almost completely self-contained, almost completely self sufficient. In the anarcho-liberal 'paradise' of the Free Cities, as owner of your own arcology you are like a modern-day feudal suzerain, lord and master."); + + App.UI.DOM.appendNewElement("p", f, "Your arcology is a flared structure, needle thin at the top where you live in your penthouse, and broad at the base. The base below ground contains storage and machinery. The lowest aboveground levels are commercial; above them are the residential areas. The entire structure is jacketed in dense gardens and solar arrays, cleverly structured to create naturally lit corridors and beautiful park-like balconies."); + + App.UI.DOM.appendNewElement("p", f, "— Owner's Report"); + + const p = document.createElement("p"); + p.classList.add("scene-intro"); + + App.UI.DOM.appendNewElement("p", p, "You may wish to improve your arcology, but should be able to ignore its development, if you wish."); + + r = []; + r.push("Your <span class='reputation inc'>reputation</span> is, of course, already quite impressive. The <span class='reputation inc'>reputation</span> tracked in the sidebar is specifically your <span class='reputation inc'>reputation</span> as a slaveowner. It can be raised through decadent actions that display your munificence and opulence. Some random events can increase it, but the most reliable way to improve your <span class='reputation inc'>reputation</span> is to send sexually skilled slaves out into the arcology to offer free sexual services. This assignment is very similar to prostitution, but produces <span class='reputation inc'>reputation</span> rather than"); + r.push(App.UI.DOM.makeElement("span", App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("money", "Money"), "."), "cash")); + App.Events.addParagraph(p, r); + + r = []; + r.push("As your <span class='reputation inc'>reputation</span> develops, you may have the opportunity to guide the future of your arcology's society. Successfully doing so will increase your <span class='reputation inc'>reputation</span> in turn, which will duly enable you to further shape society. Managing societal development well will have a recursive effect on your <span class='reputation inc'>reputation,</span> and can drive it to great heights."); + App.Events.addParagraph(p, r); + + r = []; + r.push("The benefits of high <span class='reputation inc'>reputation</span> are numerous. Many business and enslavement opportunities will open to you once you are reputable. Some of the most advanced technology is only available to those with impeccable <span class='reputation inc'>reputations</span> as slaveowners, and many of the finer slave markets will only consider reputable buyers. You may eventually become so renowned that merely branding a slave with your mark will increase her value on the open market."); + App.Events.addParagraph(p, r); + + r = []; + r.push("However, your <span class='reputation inc'>reputation</span> will not look after itself. At a certain point, you will become so reputable that continual effort will be necessary to maintain your renown. The old world question <span class='clear-formatting'>\"What have you done for me lately?\"</span> is asked with twice the force in the Free Cities! You will quickly find that this natural decay of <span class='reputation inc'>reputation</span> can overwhelm your efforts to improve it by the end of the week. A concerted strategy will be necessary to overcome this."); + App.Events.addParagraph(p, r); + f.append(p); + + return f; +}, "beingInCharge"); + +App.Encyclopedia.addArticle("Random Events", function() { + const f = new DocumentFragment(); + let r; + + r = []; + r.push("At the end of every turn, a random event may occur. Almost all random events are tied to necessary preconditions. For example, events concerning"); + r.push(App.Encyclopedia.Dialog.linkDOM("rebellious", "From Rebellious to Devoted", "devotion resistant")); + r.push("slaves will stop happening if all the player's slaves become obedient."); + App.Events.addParagraph(f, r); + + r = []; + r.push("Usually, a situation will be presented and the player may choose one of two or three resolutions. Please note that the player may also to choose none of these by using the <span class='encyclopedia interaction'>Continue</span> button in the sidebar; in effect, this usually means the player's character has simply declined to involve himself."); + App.Events.addParagraph(f, r); + + r = []; + r.push("Almost all choices will result in small effects. The most common are changes to a slave's attitude towards the player's character, but there are others."); + App.Events.addParagraph(f, r); + + r = []; + r.push("Finally, there are events that can result in the player being offered the chance to acquire new slaves, some of which can be unique or valuable. Generally, these events offer this livestock at an extremely discounted price. These events will appear more often the higher the player's"); + r.push(App.Encyclopedia.Dialog.linkDOM("reputation", "Arcologies and Reputation", "reputation inc")); + r.push("becomes."); + App.Events.addParagraph(f, r); + + return f; +}, "beingInCharge"); + +App.Encyclopedia.addArticle("Costs Summary", function() { + const f = new DocumentFragment(); + let r; + + const basicDrugCost = 100; + const basicRulesCost = 100; + + r = []; + r.push("Aphrodisiacs are"); + r.push(App.Encyclopedia.Dialog.linkDOM("cheap", "Money", "cash")); + r.push(`and cost <span class='cash'>${cashFormat(basicDrugCost)}</span> weekly; curatives are expensive and cost <span class='cash'>${cashFormat((basicDrugCost * 3))}</span> weekly; while all other drug regimes cost <span class='cash'>${cashFormat((basicDrugCost * 2))}.</span> Standard hormone regimens cost <span class='cash'>${Math.trunc(basicDrugCost * 0.5)}</span> while intensive hormone treatment costs <span class='cash'>${Math.trunc(basicDrugCost * 2 * 0.5)}.</span> Contraceptives cost <span class='cash'>${Math.trunc(basicDrugCost * 0.5)}.</span>`); + App.Events.addParagraph(f, r); + + r = []; + r.push(`Slaves on spare living standards are fed a bland diet and obliged to sleep on bedrolls. Keeping a slave under restrictive rules costs <span class='cash'>${cashFormat(basicRulesCost)}</span> weekly.`); + App.Events.addParagraph(f, r); + + r = []; + r.push(`Slaves enjoying luxurious living standards on the other hand are fed a tasty diet and permitted to sleep in comfortable beds, and are generally pampered. The increased luxury of permissive rules costs <span class='cash'>${cashFormat((basicRulesCost * 3))}</span> weekly.`); + App.Events.addParagraph(f, r); + + App.UI.DOM.appendNewElement("p", f, "Costs given are only the base costs, they can be affected by a variety of modifiers, for example economy settings, player background and arcology upgrades. Some upgrades may have associated upkeep costs as well."); + + return f; +}, "beingInCharge"); + +App.Encyclopedia.addArticle("Rules Assistant", function() { + const f = new DocumentFragment(); + let r; + + r = []; + r.push(App.Encyclopedia.topic("The Rules Assistant")); + r.push("is a system to apply multiple rule sets to multiple slaves at once. You can apply rules to slaves based on slave"); + r.push(App.UI.DOM.makeElement("span", App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("devotion", "From Rebellious to Devoted"), ","), ["devotion", "accept"])); + r.push(App.UI.DOM.makeElement("span", App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("trust", "Trust"), ","), ["trust", "careful"])); + r.push("sex drive, health,"); + r.push(App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("weight", "Weight"), ",")); + r.push(App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("muscles", "Musculature"), ",")); + r.push("lactation, pregnancy, number of fetuses, abdominal implants and age."); + App.Events.addParagraph(f, r); + + r = []; + r.push(App.Encyclopedia.topic("Rule settings")); + r.push("Rules can be used to control certain aspects of slaves everyday lives, for example to automatically give slaves a certain clothing option, collar, footwear or allow slaves to choose their own outfit. They can be used to give unhealthy slaves curatives to improve their health or to put slaves on a diet so that their"); + r.push(App.Encyclopedia.Dialog.linkDOM("weight", "Weight")); + r.push("can be closer to the ideal weight. Rules set to <span class='encyclopedia interaction'>No default setting</span> will not apply that particular condition to slaves. Rules can also be renamed to be more indicative of their intended purpose."); + App.Events.addParagraph(f, r); + + r = []; + r.push(App.Encyclopedia.topic("Rule activation")); + r.push("In order to apply a rule to slaves, the activation will need to be set. Choose an activation type"); + r.push(App.UI.DOM.combineNodes("(", + App.UI.DOM.makeElement("span", App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("devotion", "From Rebellious to Devoted"), ","), ["devotion", "accept"]))); + r.push(App.UI.DOM.makeElement("span", App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("trust", "Trust"), ","), ["trust", "careful"])); + r.push("sex drive,"); + r.push(App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("health", "Health"), ",")); + r.push(App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("weight", "Weight"), ",")); + r.push(App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("muscles", "Musculature"), ",")); + r.push("lactation, pregnancy, fetuses, implant size, or age) and then choose the level at which to apply. For example to apply a rule to obedient slaves, choose"); + r.push(App.Encyclopedia.Dialog.linkDOM("devotion", "From Rebellious to Devoted", "devotion accept")); + r.push("for the activation and 4 or more for the lower limit by selecting <span class='encyclopedia interaction'>>=</span>."); + App.Events.addParagraph(f, r); + + r = []; + r.push(App.Encyclopedia.topic("Selecting or excluding slaves from a rule")); + r.push("Slaves can be selected for a rule by selecting slaves from the list so that a rule can apply only to them. Slaves can similarly be excluded from a rule."); + App.Events.addParagraph(f, r); + + r = []; + r.push(App.Encyclopedia.topic("Applying a rule to specific assignments")); + r.push("You can apply a rule only to slaves on individual assignments by selecting them under <span class='encyclopedia interaction'>Apply to assignments.</span> For example a rule can give aphrodisiacs to slaves on whoring assignments. <span class='note'>This is mutually exclusive to automatically giving an assignment to slaves.</span>"); + App.Events.addParagraph(f, r); + + r = []; + r.push(App.Encyclopedia.topic("Automatically giving an assignment")); + r.push("A rule can be set to automatically set a slave to an assignment when activated. For example a"); + r.push(App.Encyclopedia.Dialog.linkDOM("devoted", "From Rebellious to Devoted", "devotion accept")); + r.push("slave can be set to automatically be put on the whoring assignment. <span class='note'>This is mutually exclusive to applying a rule to assignments.</span>"); + App.Events.addParagraph(f, r); + + r = []; + r.push(App.Encyclopedia.topic("Applying a rule to facilities")); + r.push("You can apply a rule to slaves in any or all facilities as long as that facility has been constructed. The rule will only apply to slaves within the selected facilities. <span class='note'>This is mutually exclusive to automatically putting slaves into a facility.</span>"); + App.Events.addParagraph(f, r); + + r = []; + r.push(App.Encyclopedia.topic("Automatically assigning slaves to a facility")); + r.push("A rule can be set to automatically put a slave into a facility when activated. For example disobedient slaves can be set to automatically be confined in the arcade if it has been constructed. <span class='note'>This is mutually exclusive to applying a rule to facilities.</span>"); + App.Events.addParagraph(f, r); + + r = []; + r.push(App.Encyclopedia.topic("Saving a rule")); + r.push("If you are finished setting up a rule <em>make sure to save it</em> by clicking <span class='encyclopedia interaction'>Save rule</span> at the bottom before clicking another link otherwise your settings will be lost."); + App.Events.addParagraph(f, r); + + r = []; + r.push(App.Encyclopedia.topic("Applying a rule")); + r.push("Clicking on <span class='encyclopedia interaction'>Apply rules</span> will automatically save the current rule and apply all rules to slaves at once."); + App.Events.addParagraph(f, r); + + r = []; + r.push(App.Encyclopedia.topic("Adding or removing a rule")); + r.push("The game starts with 3 basic default rule settings but more can be added and/or removed as needed. To add a new rule, click <span class='encyclopedia interaction'>Add a new rule</span> at the bottom, removing a rule is the same by clicking <span class='encyclopedia interaction'>Remove rule</span>."); + App.Events.addParagraph(f, r); + + return f; +}, "beingInCharge"); + +App.Encyclopedia.addArticle("The Corporation", function() { + const f = new DocumentFragment(); + let r; + + r = []; + r.push("Once you are fairly reputable and have a large sum of cash in the bank, you will receive a brief end of turn event that unlocks the ability to found a corporation dedicated to slaving. Once this happens, you can incorporate from the <span class='encyclopedia interaction'>Manage Corporation</span> link on the sidebar, and once you've done that, you can manage your corporation every week from the same place."); + App.Events.addParagraph(f, r); + + App.UI.DOM.appendNewElement("h3", f, "Shares"); + r = []; + r.push("Buying shares from the corporation or issuing new shares will create new shares in the corporation. If you buy them yourself, cash will be transferred from you to the corporation in return for the shares; if you direct the corporation to issue new public shares,"); + r.push(App.Encyclopedia.Dialog.linkDOM("money", "Money", "cash")); + r.push("will come into the corporation from the market. If you direct the corporation to buy back shares from the public, cash will be transferred from the corporation to reduce the number of public shares, which will increase your ownership percentage. You are not permitted to give up majority ownership of the corporation. Selling your shares or buying publicly held shares are both transactions between you and your shares and shareholders and their shares. All transactions impact the stock price."); + App.Events.addParagraph(f, r); + + App.UI.DOM.appendNewElement("h3", f, "Divisions"); + App.UI.DOM.appendNewElement("p", f, "The corporation consists of divisions. Starting up your corporation requires you to choose a single division as starting point and you will be able to expand into linked divisions once you have grown sufficiently in size. There are 3 general categories of divisions; acquisition, modification and exploitation. The first consists of legal and extralegal enslavement and they feed fresh slaves into either your corporation or the market at large. Investing in one of these is a good starting point when slave prices are high. Do note that each slave acquired and sold reduces the demand for slaves on the market. This means little at first, but when large enough will impact the market significantly."); + App.UI.DOM.appendNewElement("p", f, "The second category consists of slave breaking, physical slave modifications and slave training. These divisions either take improvable slaves from your acquisition divisions or the slave market and improve them. Slaves can go from breaking to physical modifications to training and become highly valuable slaves by the end of it. If the slave market is balanced or you are looking for a safe initial investment these divisions are a good choice. Their market impact is neutral, buying slaves reduces supply but selling them back onto the market reduces demand by the same amount."); + App.UI.DOM.appendNewElement("p", f, "The final category consists of an arcade, menial services, dairy and escort division. These divisions require a particular quality of slave and then put them to work in their respective fields. As these divisions operate they will have to write off some of their slaves and replace them with fresh ones, you can provide these slaves through your acquisition or modification divisions or the market. Whenever prices are low these divisions operate at a higher margin, making them a great first division when slave prices are low. Do note that each slave bought from the market reduces the supply of slaves. As these divisions grow and write off more and more slaves each week, replenishing them from the market will begin to impact the market significantly."); + + App.UI.DOM.appendNewElement("h3", f, "Management"); + App.UI.DOM.appendNewElement("p", f, "Your first division will automatically buy and/or sell slaves in order to do business and make money. It is up to you to decide when to expand the division's capacity, but investing aggressively early will pay off in the long run. Once your corporation has gotten a little time to grow its value (the sum of slave value, division value, cash on hand and dividends reserved) the end of week report will prompt you that a new division can be added. This requires a significant cash investment so you may have to save up a little. Adding divisions comes with efficiency benefits, but also adds overhead costs. Adding a second division will hardly slow you down, but as you grow these costs grow ever larger; depending on the number of divisions, but also the size of them."); + App.UI.DOM.appendNewElement("p", f, "Any new division will have at least one direct link to your current divisions, meaning it can either use slaves from a division or provide them to another division. New divisions are not automatically set to buy and/or sell slaves from the market. It is expected you either manually move slaves between divisions or sets up automatic links between them using several rules."); + App.UI.DOM.appendNewElement("p", f, "You have the ability to reduce the size of your divisions or dissolve them entirely. While this only recoups 80% of the investment it may sometimes be prudent to do so, i.e. in case market conditions have become unfavorable for the division and/or overhead costs are becoming oppressively high. Also note that divisions become less efficient the larger they get (even without considering overhead), eventually growing it further will hurt your profit, not improve it. You will want to cut your losses early or otherwise suffer the consequences."); + App.UI.DOM.appendNewElement("p", f, "In order to personally benefit monetarily from your corporation you will have to decide how much of its profit will be set aside to be paid out as dividends. Setting low or no dividends allows for rapid development, while siphoning a lot of profits away from the corporation will slow it down significantly. Please note that the corporation does not pay out every week but only every quarter (13 weeks)."); + + App.UI.DOM.appendNewElement("h3", f, "Slave Sales"); + App.UI.DOM.appendNewElement("p", f, "Once a corporation is created, it will get its own establishment in the slave market. As the corporation's value increase, it can be given direction about what kind of slaves it should train and how it should train them, which will affect the slaves seen in the corporate catalog. As with divisions; the higher your corporation's value, the more specializations you are allowed to choose. Your corporation's divisions determine which specialization options are available. Each division has a unique specialization associated with it while many others are slightly more general and linked to either acquisition or modification. All kinds of restrictions may apply depending on Future Society choices and the size of your divisions. Several specializations can be enhanced beyond the first choice, but again you may need to satisfy certain conditions first."); + r = []; + r.push("If the corporation's slaves have qualities that make them especially appealing to an arcology's citizens, the corporation will enjoy increased profits, and the"); + r.push(App.Encyclopedia.Dialog.linkDOM("future society", "Future Societies")); + r.push("creating the demand will progress more rapidly due to the supply of appealing slaves. All arcologies present in the Free City will interact with the corporation this way, making shares in a corporation which supplies girls that appeal to the whole city extremely lucrative."); + App.Events.addParagraph(f, r); + + return f; +}, "beingInCharge"); + +App.Encyclopedia.addArticle("Sexual Energy", function() { + const f = new DocumentFragment(); + let r; + + App.UI.DOM.appendNewElement("p", f, `Though you're (naturally) a virile, oversexed oligarch, even your reserves of sexual energy are not infinite. They're impressive, but not infinite. Since one turn represents one week, the game does not allow you direct control over every sexual interaction between you character and your slaves. Put another way, the game assumes there's an impressive amount of off-screen sex going on between the you and your chattel.`); + + r = []; + r.push(`Your sexual energy can have gameplay effects. Though of course all slaves are at the owner's sexual beck and call, some assignments and training methods involve close sexual attention by yourself. If a large number of slaves are subject to this, your attention will be somewhat diluted, and the effects on each slave will be reduced. Slaves assigned to be <em>fucktoys</em> and serve in the <em>master suite</em> count towards a hidden estimation of your sexual foci. With two or fewer such slaves, the your sexual attention on these slaves will be intense and have intense effects. With five or more, the you may have some difficulty in using every slave every day, diluting the mental effects of being one's personal sex toy.`); + App.Events.addParagraph(f, r); + + App.UI.DOM.appendNewElement("p", f, `It is possible to raise these limits by focusing on sexual decadence for the week. By paying less attention to business and not using sexual training on specific slaves, you will have more energy to spare and can offer intense sexual attention to three slaves or give sexual attention to up to seven slaves without dilution.`); + + App.UI.DOM.appendNewElement("p", f, `There exist several other ways to raise your sexual energy as well.`); + + return f; +}, "beingInCharge"); + +App.Encyclopedia.addArticle("PC Skills", function() { + const f = new DocumentFragment(); + let r; + + r = []; + r.push(App.Encyclopedia.topic("Trading")); + r.push("signifies how efficient you are at making exchanges. Provides more passive income the higher it is. Can be increased through acquiring slaves."); + App.Events.addParagraph(f, r); + + r = []; + r.push(App.Encyclopedia.topic("Warfare")); + r.push("is an indication your combat prowess. Cuts cost of housing mercs in half. Can be increased through use in relevant situations."); + App.Events.addParagraph(f, r); + + r = []; + r.push(App.Encyclopedia.topic("Hacking")); + r.push("is an indication of your effectiveness at manipulating computer systems. Higher levels make technological upgrades"); + r.push(App.Encyclopedia.Dialog.linkDOM("cheaper", "Money", "cash")); + r.push("or free, provides a boost situations where fame is measured digitally. Can be increased through choosing to <span class='encyclopedia interaction'>Sell your intrusion services to the highest bidder</span> once the option becomes available after having <em>some</em> skill and purchasing technological upgrades."); + App.Events.addParagraph(f, r); + + r = []; + r.push(App.Encyclopedia.topic("Slaving")); + r.push("improves your effectiveness as a slave driver. At max level it allows you to more easily spot"); + r.push(App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("gingering", "Gingering"), ".")); + r.push("Can be increased through acquiring performing the duties of a slave driver."); + App.Events.addParagraph(f, r); + + r = []; + r.push(App.Encyclopedia.topic("Engineering")); + r.push("is a sign of how effective you are building and maintenance. Mastering the skill reduces the cost of <span class='cash'>arcology upgrades and expansions.</span> Can be increased through purchasing arcology upgrades or expanding facility capacity. If the"); + r.push(App.Encyclopedia.Dialog.linkDOM("Security Expansion", "Security Expansion")); + r.push("mod is enabled, the skill is also increased by repairing your arcology."); + App.Events.addParagraph(f, r); + + r = []; + r.push(App.Encyclopedia.topic("Medicine")); + r.push("shows how effective you are treating wounds. Max level reduces a slave's health and"); + r.push(App.Encyclopedia.Dialog.linkDOM("trust", "Trust", "trust careful")); + r.push("loss during surgery."); + App.Events.addParagraph(f, r); + + r = []; + r.push("In addition to the above methods of increasing a skill (if any), all of them can be learnt by retaining a trainer"); + if (V.SF.Toggle && V.SF.Active >= 1) { + r.push("or by talking to/learning from The Colonel"); + } + r.push(r.pop() + "."); + App.Events.addParagraph(f, r); + + return f; +}, "beingInCharge"); + +App.Encyclopedia.addCategory("beingInCharge", function() { + const links = []; + links.push(App.Encyclopedia.Dialog.linkDOM("Arcologies and Reputation", "Arcologies and Reputation")); + links.push(App.Encyclopedia.Dialog.linkDOM("Random Events", "Random Events")); + links.push(App.Encyclopedia.Dialog.linkDOM("Costs Summary", "Costs Summary")); + links.push(App.Encyclopedia.Dialog.linkDOM("Rules Assistant", "Rules Assistant")); + links.push(App.Encyclopedia.Dialog.linkDOM("The Corporation", "The Corporation")); + links.push(App.Encyclopedia.Dialog.linkDOM("Sexual Energy", "Sexual Energy")); + links.push(App.Encyclopedia.Dialog.linkDOM("PC Skills", "PC Skills")); + return App.UI.DOM.generateLinksStrip(links); +}); diff --git a/src/gui/Encyclopedia/encyclopediaBody.js b/src/gui/Encyclopedia/encyclopediaBody.js index ff8f91b403040c29dec8c5f8a6f56ec5a1111d35..79a36bb0b964819483a0142c58cfdbed9dadeee7 100644 --- a/src/gui/Encyclopedia/encyclopediaBody.js +++ b/src/gui/Encyclopedia/encyclopediaBody.js @@ -279,20 +279,20 @@ App.Encyclopedia.addArticle("Ovaries", function() { }, "body"); App.Encyclopedia.addArticle("Pregnancy", function() { - return App.UI.DOM.combineNodes( - `Slaves require both `, - App.Encyclopedia.Dialog.linkDOM("vaginas", "Vaginas"), - ` and `, - App.Encyclopedia.Dialog.linkDOM("ovaries", "Ovaries"), - ` to become`, - App.Encyclopedia.topic("pregnant."), - `However, it's rumored that Gender Radicalist societies have developed a method for `, - App.Encyclopedia.Dialog.linkDOM("male impregnation", "Gender Radicalism Research"), - `. Fertile slaves can be impregnated by the player character or a slave with `, - App.Encyclopedia.Dialog.linkDOM("testicles", "Testicles"), - ` from the fertile slave's individual menu. Otherwise, slaves with vaginas and ovaries who aren't wearing chastity belts or taking contraceptives, and have not had their tubes tied via surgery, will likely become pregnant if performing sexual jobs or if allowed to have sex with slaves with balls. Pregnancy has a number of minor physical effects and will induce `, - App.Encyclopedia.Dialog.linkDOM("lactation", "Lactation") - ); + const fragment = new DocumentFragment(); + let r = []; + r.push(`Slaves require both`); + r.push(App.Encyclopedia.Dialog.linkDOM("vaginas", "Vaginas")); + r.push(`and`); + r.push(App.Encyclopedia.Dialog.linkDOM("ovaries", "Ovaries")); + r.push(`to become pregnant. However, it's rumored that Gender Radicalist societies have developed a method for `); + r.push(App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("male impregnation", "Gender Radicalism Research"), ".")); + r.push(`Fertile slaves can be impregnated by the player character or a slave with`); + r.push(App.Encyclopedia.Dialog.linkDOM("testicles", "Testicles")); + r.push(`from the fertile slave's individual menu. Otherwise, slaves with vaginas and ovaries who aren't wearing chastity belts or taking contraceptives, and have not had their tubes tied via surgery, will likely become pregnant if performing sexual jobs or if allowed to have sex with slaves with balls. Pregnancy has a number of minor physical effects and will induce`); + r.push(App.Encyclopedia.Dialog.linkDOM("lactation", "Lactation")); + App.Events.addParagraph(fragment, r); + return fragment; }, "body"); App.Encyclopedia.addArticle("Skin Distinctions", function() { diff --git a/src/gui/Encyclopedia/encyclopediaGuide.js b/src/gui/Encyclopedia/encyclopediaGuide.js index c24e5237ad0681ccbbf56e62020b36f3cf005532..709fa33450b06f95dd3edf6a60b4e54590aaec48 100644 --- a/src/gui/Encyclopedia/encyclopediaGuide.js +++ b/src/gui/Encyclopedia/encyclopediaGuide.js @@ -327,152 +327,228 @@ App.Encyclopedia.addArticle("Tips and Tricks", function() { }, "guide"); App.Encyclopedia.addArticle("Design Your Master", function() { - const f = new DocumentFragment(); - let r; - - r = []; - r.push("This happens at the start of a game of FC: it is not possible to change the PC during the main game. The player must select a career background, a rumored method of acquiring the arcology, and their age group; then choose between some broad body and gender options."); - App.Events.addParagraph(f, r); - - r = []; - r.push(`<strong>Wealth</strong> is a choice for both the <strong>career background</strong> and <strong>rumored method of acquiring the arcology</strong> options. Both provide you with <span class="cash">${cashFormat(10000)}</span> each for a total of <span class="cash">${cashFormat(30000)}</span> if both are chosen. As a <strong>background option</strong> it means that your starting slaves will have two free levels of sex skills available.`); - App.Events.addParagraph(f, r); - - App.UI.DOM.appendNewElement("h3", f, "Career background options"); - const p = document.createElement("p"); - p.append("Being an ex-"); - let ul = document.createElement("ul"); - - r = []; - r.push("<strong>business owner</strong> <span class='note'>(also referred to as capitalist)</span> enhances the business-focused personal attention, increasing the"); - r.push(App.Encyclopedia.Dialog.linkDOM("money", "Money", "cash")); - r.push("it produces and improving arcology prosperity when business-focused personal attention is selected. Also, your starting slaves will have a free level of prostitution skill available. Starts having already mastered"); - r.push(App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("Trading", "PC Skills"), ".")); - App.Events.addNode(ul, r, "li"); - - r = []; - r.push("<strong>private security contractor</strong> <span class='note'>(also referred to as mercenary background)</span> greatly reduces the cost of keeping mercenaries in your employ. Your starting slaves will have free"); - r.push(App.Encyclopedia.Dialog.linkDOM("trust", "Trust", "trust careful")); - r.push("available. Starts having already mastered"); - r.push(App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("Warfare", "PC Skills"), ".")); - App.Events.addNode(ul, r, "li"); - - r = []; - r.push("<strong>slave driver</strong> enhances slave-focused personal attention, adding bonus"); - r.push(App.Encyclopedia.Dialog.linkDOM("devotion", "From Rebellious to Devoted", "devotion accept")); - r.push("or"); - r.push(App.Encyclopedia.Dialog.linkDOM("trust", "Trust", "trust careful")); - r.push("to many training applications or preventing their loss. Starting slaves will be cheaper, in addition having already mastered"); - r.push(App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("Slaving", "PC Skills"), ".")); - App.Events.addNode(ul, r, "li"); - - r = []; - r.push("<strong>arcology engineer</strong> provides a significant discount on many <span class='cash'>arcology upgrades and expansions.</span> In addition to the arcology starting off with <span class='positive'>basic economic upgrades</span> already installed. Starts having already mastered"); - r.push(App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("Engineering", "PC Skills"), ".")); - App.Events.addNode(ul, r, "li"); - - r = []; - r.push("<strong>doctor</strong> allows the player character to perform surgery personally, providing a <span class='cash'>discount on surgery costs</span> and a <span class='positive'>reduction to resulting health damage.</span> Additionally, slaves may react differently to surgery if the player character performs it and starting slaves will have free implants available. Starts having already mastered"); - r.push(App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("Medicine", "PC Skills"), ".")); - App.Events.addNode(ul, r, "li"); - - r = []; - r.push("<strong>escort</strong> provides a one-time bonus to a slave's entertainment, whoring, and two sexual skills when a new slave is acquired. Furthermore, society will not take lightly to being run by an ex-whore, and you will receive heavy"); - r.push(App.Encyclopedia.Dialog.linkDOM("reputation", "Arcologies and Reputation", "reputation inc")); - r.push("losses each week. You can spend your free time selling your body for"); - r.push(App.UI.DOM.makeElement("span", App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("money", "Money"), ","), "cash")); - r.push("at the cost of a large amount of"); - r.push(App.UI.DOM.makeElement("span", App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("reputation", "Arcologies and Reputation"), "."), ["reputation", "inc"])); - App.Events.addNode(ul, r, "li"); - - r = []; - r.push("<strong>celebrity</strong> provides extra"); - r.push(App.Encyclopedia.Dialog.linkDOM("reputation", "Arcologies and Reputation", "reputation inc")); - r.push("at game start. Starting slaves will have a free level of entertainment skill available."); - App.Events.addNode(ul, r, "li"); - - r = []; - r.push("<strong>servant</strong> provides a one-time bonus to a slave's"); - r.push(App.Encyclopedia.Dialog.linkDOM("trust", "Trust", "trust careful")); - r.push("and"); - r.push(App.UI.DOM.makeElement("span", App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("devotion", "From Rebellious to Devoted"), "."), ["devotion", "accept"])); - r.push("Furthermore, society will not approve of being run by an ex-servant, and you will face"); - r.push(App.Encyclopedia.Dialog.linkDOM("reputation", "Arcologies and Reputation", "reputation inc")); - r.push("losses each week. You can spend your free time, putting your previous experience to use, by greatly reducing the costs of your penthouse. You also passively reduce costs when not focusing on doing so."); - App.Events.addNode(ul, r, "li"); - - r = []; - r.push("<strong>gang leader</strong> provides a one-time bonus to a slave's health and a free level of combat skill. Furthermore, society will not approve of being run by a gang-banger, and you will face"); - r.push(App.Encyclopedia.Dialog.linkDOM("reputation", "Arcologies and Reputation", "reputation inc")); - r.push("losses each week. New slaves will likely have heard of your previous exploits and fear you. You know how to haggle slaves. You can spend your free time putting your previous experience to use, proving another source of income however this isn't guaranteed."); - App.Events.addNode(ul, r, "li"); - - r = []; - r.push("<strong>incursion specialist</strong> provides starting slaves with a free level of <span class='intelligent'>intelligence.</span> Also certain upgrades may be"); - r.push(App.Encyclopedia.Dialog.linkDOM("cheaper", "Money", "cash")); - r.push("and you may find alternative approaches to problems. Starts having already mastered"); - r.push(App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("Hacking", "PC Skills"), ".")); - App.Events.addNode(ul, r, "li"); - - p.append(ul); - f.append(p); - - r = []; - r.push("Players using the"); - r.push(App.Encyclopedia.Dialog.linkDOM("Security Expansion", "Security Expansion")); - r.push("mod may want to view this page with"); - r.push(App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("additional details", "Design Your Master in SecExp"), ".")); - App.Events.addParagraph(f, r); - - App.UI.DOM.appendNewElement("h3", f, "Rumored acquisition options"); - ul = document.createElement("ul"); - r = []; - r.push("<strong>Hard Work</strong> provides a one-time bonus to both"); - r.push(App.Encyclopedia.Dialog.linkDOM("devotion", "From Rebellious to Devoted", "devotion accept")); - r.push("and"); - r.push(App.Encyclopedia.Dialog.linkDOM("trust", "Trust", "trust accept")); - r.push("when a new slave is acquired."); - App.Events.addNode(ul, r, "li"); - - r = []; - r.push("<strong>Force</strong> means that if a slave does not have enough"); - r.push(App.Encyclopedia.Dialog.linkDOM("devotion", "From Rebellious to Devoted", "devotion accept")); - r.push("to obey when acquired, this option will terrify her and reduce her"); - r.push(App.Encyclopedia.Dialog.linkDOM("trust", "Trust", "trust accept")); - r.push("to the point where she should comply."); - App.Events.addNode(ul, r, "li"); - - r = []; - r.push("<strong>Social Engineering</strong> means that you will start with the first societal option unlocked, since you manipulated the arcology's citizens."); - App.Events.addNode(ul, r, "li"); - - r = []; - r.push("<strong>Luck</strong> provides extra"); - r.push(App.Encyclopedia.Dialog.linkDOM("reputation", "Arcologies and Reputation", "reputation inc")); - r.push("at game start, but no ongoing advantages once the main game begins."); - App.Events.addNode(ul, r, "li"); - - App.UI.DOM.appendNewElement("p", f, ul); - - App.UI.DOM.appendNewElement("h3", f, "Age groups"); - r = []; - r.push("Older PCs enjoy easier"); - r.push(App.Encyclopedia.Dialog.linkDOM("reputation", "Arcologies and Reputation", "reputation inc")); - r.push("maintenance, but possess lower"); - r.push(App.Encyclopedia.Dialog.linkDOM("sexual energy", "Sexual Energy")); - r.push("while younger PC's are the opposite."); - App.Events.addParagraph(f, r); - - App.UI.DOM.appendNewElement("h3", f, "Body and gender options"); - r = []; - r.push("All PC body changes will alter scenes, but their main mechanical effect is on"); - r.push(App.Encyclopedia.Dialog.linkDOM("reputation", "Arcologies and Reputation", "reputation inc")); - r.push("maintenance. Feminine options will make it harder to maintain"); - r.push(App.Encyclopedia.Dialog.linkDOM("reputation", "Arcologies and Reputation", "reputation inc")); - r.push("without providing any gameplay advantage, making playing as a feminine PC a form of increased difficulty. There are other minor gameplay differences including differing slave reactions to the PC based on attraction, but these are fairly minor."); - App.Events.addParagraph(f, r); - - return f; + const outer = document.createElement("p"); + const showSecExp = V.secExpEnabled > 0; + + outer.append(content(showSecExp)); + + return outer; + + /** + * @param {boolean} showSecExp + * @returns {DocumentFragment} + */ + function content(showSecExp) { + const f = new DocumentFragment(); + let r; + + r = []; + r.push("This happens at the start of a game of FC: it is not possible to change the PC during the main game. The player must select a career background, a rumored method of acquiring the arcology, and their age group; then choose between some broad body and gender options."); + App.Events.addParagraph(f, r); + + r = []; + r.push(`<strong>Wealth</strong> is a choice for both the <strong>career background</strong> and <strong>rumored method of acquiring the arcology</strong> options. Both provide you with <span class="cash">${cashFormat(10000)}</span> each for a total of <span class="cash">${cashFormat(30000)}</span> if both are chosen. As a <strong>background option</strong> it means that your starting slaves will have two free levels of sex skills available`); + if (showSecExp) { + r.push("and maintaining"); + r.push(App.Encyclopedia.Dialog.linkDOM("authority", "Security Expansion", "darkviolet")); + r.push("will be harder, but upgrades in the propaganda hub will be"); + r.push(App.UI.DOM.makeElement("span", App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("cheaper", "Money"), "."), "cash")); + } else { + r.push(r.pop() + "."); + } + App.Events.addParagraph(f, r); + + App.UI.DOM.appendNewElement("h3", f, "Career background options"); + const p = document.createElement("p"); + p.append("Being an ex-"); + let ul = document.createElement("ul"); + + r = []; + r.push("<strong>business owner</strong> <span class='note'>(also referred to as capitalist)</span> enhances the business-focused personal attention, increasing the"); + r.push(App.Encyclopedia.Dialog.linkDOM("money", "Money", "cash")); + r.push("it produces and improving arcology prosperity when business-focused personal attention is selected. Also,"); + if (showSecExp) { + r.push("upgrades in the propaganda hub will be"); + r.push(App.Encyclopedia.Dialog.linkDOM("cheaper", "Money", "cash")); + r.push("and"); + } + r.push("your starting slaves will have a free level of prostitution skill available. Starts having already mastered"); + r.push(App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("Trading", "PC Skills"), ".")); + App.Events.addNode(ul, r, "li"); + + r = []; + r.push("<strong>private security contractor</strong> <span class='note'>(also referred to as mercenary background)</span> greatly reduces the cost of keeping mercenaries in your employ."); + if (showSecExp) { + r.push("Upgrades in the security HQ will be"); + r.push(App.UI.DOM.makeElement("span", App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("cheaper", "Money"), "."), "cash")); + } + r.push("Your starting slaves will have free"); + r.push(App.Encyclopedia.Dialog.linkDOM("trust", "Trust", "trust careful")); + r.push("available. Starts having already mastered"); + r.push(App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("Warfare", "PC Skills"), ".")); + App.Events.addNode(ul, r, "li"); + + r = []; + r.push("<strong>slave driver</strong> enhances slave-focused personal attention, adding bonus"); + r.push(App.Encyclopedia.Dialog.linkDOM("devotion", "From Rebellious to Devoted", "devotion accept")); + r.push("or"); + r.push(App.Encyclopedia.Dialog.linkDOM("trust", "Trust", "trust careful")); + r.push("to many training applications or preventing their loss."); + if (showSecExp) { + r.push(App.Encyclopedia.Dialog.linkDOM("Authority", "Security Expansion", "darkviolet")); + r.push("will be easier to maintain. Plus upgrades in the security HQ will be"); + r.push(App.UI.DOM.makeElement("span", App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("cheaper", "Money"), "."), "cash")); + } + r.push("Starting slaves will be cheaper, in addition having already mastered"); + r.push(App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("Slaving", "PC Skills"), ".")); + App.Events.addNode(ul, r, "li"); + + r = []; + r.push("<strong>arcology engineer</strong> provides a significant discount on many <span class='cash'>arcology upgrades and expansions.</span> In addition to the arcology starting off with <span class='positive'>basic economic upgrades</span> already installed. Starts having already mastered"); + r.push(App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("Engineering", "PC Skills"), ".")); + App.Events.addNode(ul, r, "li"); + + r = []; + r.push("<strong>doctor</strong> allows the player character to perform surgery personally, providing a <span class='cash'>discount on surgery costs</span> and a <span class='positive'>reduction to resulting health damage.</span> Additionally, slaves may react differently to surgery if the player character performs it and starting slaves will have free implants available. Starts having already mastered"); + r.push(App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("Medicine", "PC Skills"), ".")); + App.Events.addNode(ul, r, "li"); + + r = []; + r.push("<strong>escort</strong> provides a one-time bonus to a slave's entertainment, whoring, and two sexual skills when a new slave is acquired. Furthermore, society will not take lightly to being run by an ex-whore, and you will receive heavy"); + r.push(App.Encyclopedia.Dialog.linkDOM("reputation", "Arcologies and Reputation", "reputation inc")); + if (showSecExp) { + r.push("and"); + r.push(App.Encyclopedia.Dialog.linkDOM("authority", "Security Expansion", "darkviolet")); + } + r.push("losses each week. You can spend your free time selling your body for"); + r.push(App.UI.DOM.makeElement("span", App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("money", "Money"), ","), "cash")); + r.push("at the cost of a large amount of"); + r.push(App.UI.DOM.makeElement("span", App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("reputation", "Arcologies and Reputation"), "."), ["reputation", "inc"])); + App.Events.addNode(ul, r, "li"); + + r = []; + r.push("<strong>celebrity</strong> provides extra"); + r.push(App.Encyclopedia.Dialog.linkDOM("reputation", "Arcologies and Reputation", "reputation inc")); + r.push("at game start"); + if (showSecExp) { + r.push("and upgrades in the propaganda hub will be"); + r.push(App.UI.DOM.makeElement("span", App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("cheaper", "Money"), "."), "cash")); + } else { + r.push(r.pop() + "."); + } + r.push("Starting slaves will have a free level of entertainment skill available."); + App.Events.addNode(ul, r, "li"); + + r = []; + r.push("<strong>servant</strong> provides a one-time bonus to a slave's"); + r.push(App.Encyclopedia.Dialog.linkDOM("trust", "Trust", "trust careful")); + r.push("and"); + r.push(App.UI.DOM.makeElement("span", App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("devotion", "From Rebellious to Devoted"), "."), ["devotion", "accept"])); + r.push("Furthermore, society will not approve of being run by an ex-servant, and you will face"); + r.push(App.Encyclopedia.Dialog.linkDOM("reputation", "Arcologies and Reputation", "reputation inc")); + if (showSecExp) { + r.push("and"); + r.push(App.Encyclopedia.Dialog.linkDOM("authority", "Security Expansion", "darkviolet")); + } + r.push("losses each week. You can spend your free time, putting your previous experience to use, by greatly reducing the costs of your penthouse. You also passively reduce costs when not focusing on doing so."); + App.Events.addNode(ul, r, "li"); + + r = []; + r.push("<strong>gang leader</strong> provides a one-time bonus to a slave's health and a free level of combat skill. Furthermore, society will not approve of being run by a gang-banger, and you will face"); + r.push(App.Encyclopedia.Dialog.linkDOM("reputation", "Arcologies and Reputation", "reputation inc")); + r.push("losses each week. New slaves will likely have heard of your previous exploits and fear you."); + if (showSecExp) { + r.push("You know how to haggle slaves and assert your"); + r.push(App.UI.DOM.makeElement("span", App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("authority", "Security Expansion"), "."), "darkviolet")); + r.push("Plus upgrades in the security HQ will be"); + r.push(App.UI.DOM.makeElement("span", App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("cheaper", "Money"), "."), "cash")); + } + r.push("You know how to haggle slaves. You can spend your free time putting your previous experience to use, proving another source of income however this isn't guaranteed."); + App.Events.addNode(ul, r, "li"); + + r = []; + r.push("<strong>incursion specialist</strong> provides starting slaves with a free level of <span class='intelligent'>intelligence.</span> Also certain upgrades may be"); + r.push(App.Encyclopedia.Dialog.linkDOM("cheaper", "Money", "cash")); + r.push("and you may find alternative approaches to"); + if (showSecExp) { + r.push("problems, but you will find"); + r.push(App.Encyclopedia.Dialog.linkDOM("authority", "Security Expansion", "darkviolet")); + r.push("quite hard to maintain."); + } else { + r.push("problems."); + } + r.push("Starts having already mastered"); + r.push(App.UI.DOM.combineNodes(App.Encyclopedia.Dialog.linkDOM("Hacking", "PC Skills"), ".")); + App.Events.addNode(ul, r, "li"); + + p.append(ul); + f.append(p); + + r = []; + let text; + if (showSecExp) { + text = "Hide SecExp details"; + } else { + r.push("Players using the"); + r.push(App.Encyclopedia.Dialog.linkDOM("Security Expansion", "Security Expansion")); + r.push("mod may want to view this page with"); + text = "additional details"; + } + r.push(App.UI.DOM.combineNodes(App.UI.DOM.link(text, () => { + $(outer).empty().append(content(!showSecExp)); + }), ".")); + App.Events.addParagraph(f, r); + + App.UI.DOM.appendNewElement("h3", f, "Rumored acquisition options"); + ul = document.createElement("ul"); + r = []; + r.push("<strong>Hard Work</strong> provides a one-time bonus to both"); + r.push(App.Encyclopedia.Dialog.linkDOM("devotion", "From Rebellious to Devoted", "devotion accept")); + r.push("and"); + r.push(App.Encyclopedia.Dialog.linkDOM("trust", "Trust", "trust accept")); + r.push("when a new slave is acquired."); + App.Events.addNode(ul, r, "li"); + + r = []; + r.push("<strong>Force</strong> means that if a slave does not have enough"); + r.push(App.Encyclopedia.Dialog.linkDOM("devotion", "From Rebellious to Devoted", "devotion accept")); + r.push("to obey when acquired, this option will terrify her and reduce her"); + r.push(App.Encyclopedia.Dialog.linkDOM("trust", "Trust", "trust accept")); + r.push("to the point where she should comply."); + App.Events.addNode(ul, r, "li"); + + r = []; + r.push("<strong>Social Engineering</strong> means that you will start with the first societal option unlocked, since you manipulated the arcology's citizens."); + App.Events.addNode(ul, r, "li"); + + r = []; + r.push("<strong>Luck</strong> provides extra"); + r.push(App.Encyclopedia.Dialog.linkDOM("reputation", "Arcologies and Reputation", "reputation inc")); + r.push("at game start, but no ongoing advantages once the main game begins."); + App.Events.addNode(ul, r, "li"); + + App.UI.DOM.appendNewElement("p", f, ul); + + App.UI.DOM.appendNewElement("h3", f, "Age groups"); + r = []; + r.push("Older PCs enjoy easier"); + r.push(App.Encyclopedia.Dialog.linkDOM("reputation", "Arcologies and Reputation", "reputation inc")); + r.push("maintenance, but possess lower"); + r.push(App.Encyclopedia.Dialog.linkDOM("sexual energy", "Sexual Energy")); + r.push("while younger PC's are the opposite."); + App.Events.addParagraph(f, r); + + App.UI.DOM.appendNewElement("h3", f, "Body and gender options"); + r = []; + r.push("All PC body changes will alter scenes, but their main mechanical effect is on"); + r.push(App.Encyclopedia.Dialog.linkDOM("reputation", "Arcologies and Reputation", "reputation inc")); + r.push("maintenance. Feminine options will make it harder to maintain"); + r.push(App.Encyclopedia.Dialog.linkDOM("reputation", "Arcologies and Reputation", "reputation inc")); + r.push("without providing any gameplay advantage, making playing as a feminine PC a form of increased difficulty. There are other minor gameplay differences including differing slave reactions to the PC based on attraction, but these are fairly minor."); + App.Events.addParagraph(f, r); + + return f; + } }, "guide"); App.Encyclopedia.addCategory("guide", function() { diff --git a/src/gui/Encyclopedia/encyclopediaRelatedLinks.tw b/src/gui/Encyclopedia/encyclopediaRelatedLinks.tw index dbf0e17244ea73b6179c50409250c34cd2befd42..6a04d89ac537a24e6928a720f69ac8161857219c 100644 --- a/src/gui/Encyclopedia/encyclopediaRelatedLinks.tw +++ b/src/gui/Encyclopedia/encyclopediaRelatedLinks.tw @@ -13,18 +13,6 @@ <<switch $encyclopedia>> -/********** -BEING IN CHARGE -**********/ -<<case "Arcologies and Reputation" "Being in Charge" "Costs Summary" "PC Skills" "Random Events" "Rules Assistant" "Sexual Energy" "The Corporation">> - <<= App.Encyclopedia.Dialog.linkSC("Arcologies and Reputation", "Arcologies and Reputation")>> - | <<= App.Encyclopedia.Dialog.linkSC("Random Events", "Random Events")>> - | <<= App.Encyclopedia.Dialog.linkSC("Costs Summary", "Costs Summary")>> - | <<= App.Encyclopedia.Dialog.linkSC("Rules Assistant", "Rules Assistant")>> - | <<= App.Encyclopedia.Dialog.linkSC("The Corporation", "The Corporation")>> - | <<= App.Encyclopedia.Dialog.linkSC("Sexual Energy", "Sexual Energy")>> - | <<= App.Encyclopedia.Dialog.linkSC("PC Skills", "PC Skills")>> - /********** SLAVES **********/ diff --git a/src/gui/mainMenu/AlphaDisclaimer.tw b/src/gui/mainMenu/AlphaDisclaimer.tw index a911ece80df19776e74e4e23ff5982471fda3f82..0a8d2f9cf61d42b6e21fabcc7c99e37b5094920c 100644 --- a/src/gui/mainMenu/AlphaDisclaimer.tw +++ b/src/gui/mainMenu/AlphaDisclaimer.tw @@ -32,6 +32,9 @@ <div class="note"> version: $ver, mod version: $pmodVer, build: $releaseID<<if App.Version.commitHash>>, commit: <<= App.Version.commitHash>><</if>> </div> + <span style="font-weight:Bold"> /* remove me with 4.0.0! */ + 4.0.0 is in alpha release. This means the new player content has minimal implementation. + </span> <div id="version"> <<link "More version info">> <<replace "#version">> diff --git a/src/gui/options/options.js b/src/gui/options/options.js index 6a7cffa56466401ecea9bf75c8667f54f845626a..c01f554a9ad0e6e7b26a903da870fdf129d606c2 100644 --- a/src/gui/options/options.js +++ b/src/gui/options/options.js @@ -507,11 +507,13 @@ App.UI.optionsPassage = function() { options.addOption("DebugMode is", "debugMode") .addValue("Enabled", 1).on().addValue("Disabled", 0).off() - .addComment("This will add a Display Variables and Bug Report passage to the sidebar."); + .addComment("This will add passages to Display Variables and create Bug Reports to the sidebar."); if (V.debugMode > 0) { - options.addOption("The custom function part of debug mode is", "debugModeCustomFunction") + options.addOption("<span class='choices'>The custom function part of debug mode is</span>", "debugModeCustomFunction") .addValue("Enabled", 1).on().addValue("Disabled", 0).off(); + options.addOption("<span class='choices'>Event selection is</span>", "debugModeEventSelection") + .addValue("Manual", 1).on().addValue("Automatic", 0).off(); } option = options.addCustomOption("Genetics array") @@ -536,7 +538,7 @@ App.UI.optionsPassage = function() { options.addOption("CheatMode is", "cheatMode") .addValue("Enabled", 1).on().addValue("Disabled", 0).off() - .addComment("This will allow manual selection of events and unlock some options that would usually be restricted by progress."); + .addComment("This will unlock some options that would usually be restricted by progress."); if (V.cheatMode === 0) { el.append(options.render()); @@ -1076,7 +1078,10 @@ App.UI.artOptions = function() { const el = new DocumentFragment(); let options = new App.UI.OptionsGroup(); - App.Events.drawEventArt(el, BaseSlave()); + const art = App.UI.DOM.appendNewElement("span", el); + art.style.position = "relative"; + art.style.zIndex = "-1"; + App.Events.drawEventArt(art, BaseSlave()); options.addOption("Images are", "seeImages") .addValue("Enabled", 1).on().addValue("Disabled", 0).off(); diff --git a/src/interaction/main/walkPast.js b/src/interaction/main/walkPast.js index d760154404277d11d1699399c9ea63ef6ddf45f2..554c566d7a38a5c1ddc60a592775b72d7c757de6 100644 --- a/src/interaction/main/walkPast.js +++ b/src/interaction/main/walkPast.js @@ -2079,7 +2079,7 @@ globalThis.walkPast = (function() { t += `dig into the soft flesh as ${he} moves.`; } break; - case "attractive lingerie for a pregnant women": + case "attractive lingerie for a pregnant woman": if (slave.boobs < 300) { t += `The bulge of ${his} ${slave.nipples} nipples can be seen under the taut silk.`; } else { @@ -2863,9 +2863,9 @@ globalThis.walkPast = (function() { if (slave.bellyImplant < 2000) { if (slave.belly >= 600000) { switch (slave.clothes) { - case "a very tight corset": - t += `${His} corset struggles to contain ${his} enormous belly.`; - break; + // case "an extreme corset": // FIXME: corsets are not clothes + // t += `${His} corset struggles to contain ${his} enormous belly.`; + // break; case "chains": t += `${His} enormous belly bulges in between ${his} tight chains.`; break; @@ -2992,9 +2992,9 @@ globalThis.walkPast = (function() { } } else if (slave.belly >= 300000) { switch (slave.clothes) { - case "a very tight corset": - t += `${His} corset struggles to contain ${his} giant belly.`; - break; + // case "an extreme corset": //FIXME: Corsets are not clothes + // t += `${His} corset struggles to contain ${his} giant belly.`; + // break; case "chains": t += `${His} giant belly bulges in between ${his} tight chains.`; break; @@ -3527,7 +3527,7 @@ globalThis.walkPast = (function() { case "battlearmor": t += `${His} giant jiggling gut is barely contained by ${his} armor.`; break; - case "Imperial Armor": + case "Imperial Plate": t += `Even through ${his} massively thick Imperial armor, you can swear you see ${his} obscene gut jiggle somehow.`; break; case "a mounty outfit": @@ -4506,9 +4506,9 @@ globalThis.walkPast = (function() { } else { /* implant descs */ if (slave.bellyImplant >= 32000) { switch (slave.clothes) { - case "a very tight corset": - t += `${His} corset struggles to contain ${his} enormous belly.`; - break; + // case "an extreme corset": //FIXME: Corsets are not clothes + // t += `${His} corset struggles to contain ${his} enormous belly.`; + // break; case "chains": t += `${His} enormous belly bulges in between ${his} tight chains.`; break; @@ -4654,9 +4654,9 @@ globalThis.walkPast = (function() { } } else if (slave.bellyImplant >= 16000) { switch (slave.clothes) { - case "a very tight corset": - t += `${His} corset struggles to contain ${his} giant belly.`; - break; + // case "an extreme corset": // FIXME: Corsets are not clothes + // t += `${His} corset struggles to contain ${his} giant belly.`; + // break; case "chains": t += `${His} giant belly bulges in between ${his} tight chains.`; break; diff --git a/src/interaction/universalRules.js b/src/interaction/universalRules.js index 8cc36e2042f4db1c1dd8a6085f3ad3dbb67fdcbf..96e0f24a0ee525b9466587a40f27b54eefbda860 100644 --- a/src/interaction/universalRules.js +++ b/src/interaction/universalRules.js @@ -78,13 +78,13 @@ App.UI.universalRules = function() { const options = new App.UI.OptionsGroup(); options.addOption("Slaves keep surnames", "surnamesForbidden") - .addValue("Yes", 1).on() - .addValue(`No going forward`, 0).off() + .addValue("Yes", 0).on() + .addValue(`No going forward`, 1).off() .customButton(`No and strip all current surnames`, () => { for (const slave of V.slaves) { slave.slaveSurname = 0; } - V.surnamesForbidden = 0; + V.surnamesForbidden = 1; }, passage()); if (V.surnamesForbidden === 0) { diff --git a/src/js/SlaveState.js b/src/js/SlaveState.js index c3c9ba6d5a2cdd06210541f93f46378c561ba706..f6df3d3389f79ed102f12eea9c092801ea247dd2 100644 --- a/src/js/SlaveState.js +++ b/src/js/SlaveState.js @@ -1862,7 +1862,7 @@ App.Entity.SlaveState = class SlaveState { * * "striped underwear" * * "uncomfortable straps" * * "Western clothing" - */ + * @type {FC.Clothes} */ this.clothes = "no clothing"; /** * may accept strings, use at own risk @@ -1910,6 +1910,10 @@ App.Entity.SlaveState = class SlaveState { * * "extreme heels" * * "boots" * * "flats" + * * "platform heels" + * * "extreme heels" + * * "extreme platform heels" + * * "platform shoes" */ this.shoes = "none"; /** diff --git a/src/js/assignJS.js b/src/js/assignJS.js index f6f5451d6ce25d10572b20bafa6982ac1f774625..2cfb62b088bb30bc36ed4c454163f4a338bcc1f9 100644 --- a/src/js/assignJS.js +++ b/src/js/assignJS.js @@ -82,7 +82,7 @@ globalThis.assignJob = function(slave, job) { case Job.ARCADE.toLowerCase(): case "arcade": slave.assignment = Job.ARCADE; - if (slave.clothes !== "a fuckdoll suit") { + if (slave.clothes !== "a Fuckdoll suit") { slave.clothes = "no clothing"; } slave.shoes = "none"; diff --git a/src/js/eventSelectionJS.js b/src/js/eventSelectionJS.js index c4242bccc77d37461f4ad9351ed6ea5a1581f66c..23c07becdf1e3ba79131e7f03b3387eedcabafa1 100644 --- a/src/js/eventSelectionJS.js +++ b/src/js/eventSelectionJS.js @@ -504,18 +504,6 @@ if(eventSlave.drugs === "breast injections") { V.RESSevent.push("back stretch"); } } - - if (eventSlave.devotion > 20) { - if (eventSlave.trust > 20) { - if (eventSlave.rules.speech !== "restrictive") { - if (eventSlave.choosesOwnClothes !== 1) { - if (getExposure(eventSlave) === 0) { - V.RESSevent.push("modest clothes"); - } - } - } - } - } } if (V.PC.vagina > -1) { if (eventSlave.devotion <= 20) { @@ -785,13 +773,6 @@ if(eventSlave.drugs === "breast injections") { if (eventSlave.rules.release.masturbation === 0 && !App.Utils.hasNonassignmentSex(eventSlave)) { if (eventSlave.need) { - if (eventSlave.devotion <= 95) { - if (eventSlave.trust >= -20) { - if ((eventSlave.chastityPenis !== 1) || (eventSlave.dick === 0)) { - V.RESSevent.push("forbidden masturbation"); - } - } - } if (eventSlave.devotion >= -20) { if (eventSlave.trust >= -50) { V.RESSevent.push("desperately horny"); @@ -1120,14 +1101,6 @@ if(eventSlave.drugs === "breast injections") { } } - if (eventSlave.assignment === Job.WHORE) { - if (canDoAnal(eventSlave) && (eventSlave.vagina < 0 || canDoVaginal(eventSlave))) { - if (eventSlave.devotion < -20 && eventSlave.trust >= -20) { - V.RESSevent.push("whore rebellious"); - } - } - } - if (eventSlave.assignment !== Job.QUARTER) { if (isAmputee(eventSlave)) { if (eventSlave.devotion > 20) { diff --git a/src/js/main.js b/src/js/main.js index accb599874e0ddcaccefa47d2e195874ae600359..66b976f0875448a8da8fb8f81021601b714ba29e 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -3,14 +3,6 @@ * @returns {HTMLDivElement} */ App.MainView.useFucktoy = function(slave) { - const fragment = document.createDocumentFragment(); - - function setEnvironment() { - V.AS = slave.ID; - V.nextButton = "Back"; - V.nextLink = passage(); - } - const {him, his} = getPronouns(slave); const div = document.createElement("div"); @@ -29,37 +21,38 @@ App.MainView.useFucktoy = function(slave) { if (slave.fuckdoll === 0) { div.append(", but for now:"); + const showScene = (passage, ...args) => $(linkDiv).empty().append(App.Interact[passage](slave, ...args)); + const linkArray = []; linkArray.push( - App.UI.DOM.passageLink(`Use ${his} mouth`, "fLips", setEnvironment), - App.UI.DOM.passageLink("Play with " + his + " tits", "fBoobs", setEnvironment) + App.UI.DOM.link(`Use ${his} mouth`, showScene, ["fLips"]), + App.UI.DOM.link(`Play with ${his} tits`, showScene, ["fBoobs"]) ); if (canDoVaginal(slave)) { - linkArray.push(App.UI.DOM.passageLink(`Fuck ${him}`, "fVagina", setEnvironment)); + linkArray.push(App.UI.DOM.link(`Fuck ${him}`, showScene, ["fVagina"])); if (canDoAnal(slave)) { - linkArray.push(App.UI.DOM.passageLink(`Use ${his} holes`, "fButt", setEnvironment)); + linkArray.push(App.UI.DOM.link(`Use ${his} holes`, showScene, ["fButt"])); } } if (canDoAnal(slave)) { - linkArray.push(App.UI.DOM.passageLink(`Fuck ${his} ass`, "fAnus", setEnvironment)); + linkArray.push(App.UI.DOM.link(`Fuck ${his} ass`, showScene, ["fAnus"])); } if (canDoVaginal(slave) || canDoAnal(slave)) { if (slave.belly >= 300000) { - linkArray.push(App.UI.DOM.passageLink(`Fuck ${him} over ${his} belly`, "fBellyFuck", setEnvironment)); + linkArray.push(App.UI.DOM.link(`Fuck ${him} over ${his} belly`, showScene, ["fBellyFuck"])); } } if (canPenetrate(slave)) { - linkArray.push(App.UI.DOM.passageLink(`Ride ${him}`, "fDick", setEnvironment)); + linkArray.push(App.UI.DOM.link(`Ride ${him}`, showScene, ["fDick"])); } - linkArray.push(App.UI.DOM.passageLink(`Abuse ${him}`, "fAbuse", setEnvironment)); + linkArray.push(App.UI.DOM.link(`Abuse ${him}`, showScene, ["fAbuse"])); - App.UI.DOM.appendNewElement("div", div, App.UI.DOM.generateLinksStrip(linkArray), "indent"); + const linkDiv = App.UI.DOM.appendNewElement("div", div, App.UI.DOM.generateLinksStrip(linkArray), "indent"); } else { div.append("."); } - fragment.append(div); return div; }; @@ -78,38 +71,36 @@ App.MainView.useGuard = function() { App.UI.DOM.appendNewElement("span", outerDiv, App.Interact.guardPose(guard), "scene-intro"); - function setEnvironment() { - V.AS = guard.ID; - V.nextButton = "Back"; - V.nextLink = passage(); - } + const showScene = (passage, ...args) => $(linkDiv).empty().append(App.Interact[passage](guard, ...args)); const {him, his} = getPronouns(guard); const linkArray = []; linkArray.push( - App.UI.DOM.passageLink(`Use ${his} mouth`, "fLips", setEnvironment), - App.UI.DOM.passageLink(`Play with ${his} tits`, "fBoobs", setEnvironment) + App.UI.DOM.link(`Use ${his} mouth`, showScene, ["fLips"]), + App.UI.DOM.link(`Play with ${his} tits`, showScene, ["fBoobs"]) ); if (canDoVaginal(guard)) { - linkArray.push(App.UI.DOM.passageLink(`Fuck ${him}`, "fVagina", setEnvironment)); + linkArray.push(App.UI.DOM.link(`Fuck ${him}`, showScene, ["fVagina"])); if (canDoAnal(guard)) { - linkArray.push(App.UI.DOM.passageLink(`Use ${his} holes`, "fButt", setEnvironment)); + linkArray.push(App.UI.DOM.link(`Use ${his} holes`, showScene, ["fButt"])); } + } + if (canDoAnal(guard)) { + linkArray.push(App.UI.DOM.link(`Fuck ${his} ass`, showScene, ["fAnus"])); + } + if (canDoVaginal(guard) || canDoAnal(guard)) { if (guard.belly >= 300000) { - linkArray.push(App.UI.DOM.passageLink(`Fuck ${him} over ${his} belly`, "fBellyFuck", setEnvironment)); + linkArray.push(App.UI.DOM.link(`Fuck ${him} over ${his} belly`, showScene, ["fBellyFuck"])); } } if (canPenetrate(guard)) { - linkArray.push(App.UI.DOM.passageLink(`Ride ${him}`, "fDick", setEnvironment)); - } - if (canDoAnal(guard)) { - linkArray.push(App.UI.DOM.passageLink(`Fuck ${his} ass`, "fAnus", setEnvironment)); + linkArray.push(App.UI.DOM.link(`Ride ${him}`, showScene, ["fDick"])); } linkArray.push(App.UI.DOM.passageLink(`Abuse ${him}`, "Gameover", () => { V.gameover = "idiot ball"; })); - App.UI.DOM.appendNewElement("div", outerDiv, App.UI.DOM.generateLinksStrip(linkArray), "indent"); + const linkDiv = App.UI.DOM.appendNewElement("div", outerDiv, App.UI.DOM.generateLinksStrip(linkArray), "indent"); return outerDiv; }; diff --git a/src/js/rulesAssistantOptions.js b/src/js/rulesAssistantOptions.js index 4b25cc9b20f798f5867c6a854a266f1ff53e3cec..8f8b3753175ea67c8ebd662ef01d7a52776e979b 100644 --- a/src/js/rulesAssistantOptions.js +++ b/src/js/rulesAssistantOptions.js @@ -1972,11 +1972,11 @@ App.RA.options = (function() { ]; super("Collar", items); - const niceCollars = isItemAccessible.array(App.Data.slaveWear.collar, (c) => c.harsh); + const niceCollars = isItemAccessible.array(App.Data.slaveWear.collar, (c) => !c.harsh); niceCollars.sort(function(a, b) { if (a[0] < b[0]) { return -1; } if (a[0] > b[0]) { return 1; } return 0; }); this._nice = new ListSubSection(this, "Nice", niceCollars); - const harshCollars = isItemAccessible.array(App.Data.slaveWear.collar, (c) => !c.harsh); + const harshCollars = isItemAccessible.array(App.Data.slaveWear.collar, (c) => c.harsh); harshCollars.sort(function(a, b) { if (a[0] < b[0]) { return -1; } if (a[0] > b[0]) { return 1; } return 0; }); this._harsh = new ListSubSection(this, "Harsh", harshCollars); diff --git a/src/js/statsChecker/statsChecker.js b/src/js/statsChecker/statsChecker.js index fd9c58062c802844409818e16f4936a31eed1edf..8ca229103b20d9a2c1958fd9c8bddfa62e7a6e39 100644 --- a/src/js/statsChecker/statsChecker.js +++ b/src/js/statsChecker/statsChecker.js @@ -900,6 +900,14 @@ globalThis.isHindered = function(slave) { } else if (slave.muscles < -30) { return true; } + // player exclusives + if (slave.ID === -1) { + if (onBedRest(slave)) { + return true; + } else if (slave.criticalDamage !== 0) { + return true; + } + } return false; }; diff --git a/src/js/utilsPC.js b/src/js/utilsPC.js index 845579e23f79e57db65befdaf0cb518180b905c7..905c6c460f3b62101e772ec62bbea6df2ce17b44 100644 --- a/src/js/utilsPC.js +++ b/src/js/utilsPC.js @@ -627,6 +627,8 @@ globalThis.onBedRest = function(actor) { // consider player health and injury in the future! if (!actor) { return null; + } else if (actor.health.shortDamage > 0) { + return true; } else if (!canMove(actor)) { return true; } else if (actor.preg > actor.pregData.normalBirth / 1.33 && actor.womb.find((ft) => ft.genetics.geneticQuirks.polyhydramnios === 2 && ft.age >= 20)) { diff --git a/src/npc/descriptions/butt/buttplug.js b/src/npc/descriptions/butt/buttplug.js index 9d723c161242ac1fbf5ea231ddd884d95f7c9cc5..b2e6486985b62e6b413d20a0ba209e7e85fe9ca9 100644 --- a/src/npc/descriptions/butt/buttplug.js +++ b/src/npc/descriptions/butt/buttplug.js @@ -533,7 +533,7 @@ App.Desc.buttplug = function(slave, {market, eventDescription} = {}) { break; case "conservative clothing": case "a toga": - case "huipil": + case "a huipil": case "cutoffs and a t-shirt": case "battledress": case "battlearmor": diff --git a/src/npc/descriptions/style/clothing.js b/src/npc/descriptions/style/clothing.js index 7c8b2bdbe611251e4a6065c5748b4a519a09dd67..5e18eab5a97043abb9965c7231cb9f20cb80ff18 100644 --- a/src/npc/descriptions/style/clothing.js +++ b/src/npc/descriptions/style/clothing.js @@ -686,7 +686,6 @@ App.Desc.clothing = function(slave, {market, eventDescription} = {}) { case "a sweater": case "a t-shirt": case "a tank-top": - case "a nice over-sizes shirt": case "a tube top": case "an oversized t-shirt": r.push(`which only covers ${his}`); @@ -957,7 +956,7 @@ App.Desc.clothing = function(slave, {market, eventDescription} = {}) { } r.push(`built-in corset and an elegant, layered skirt that evokes the feeling of a flower ready to blossom.`); if (hasAnyLegs(slave)) { - r.push(`${He} is wearing`); + r.push(`${He} is`); r.push(App.Desc.footwear(slave)); } break; diff --git a/src/npc/descriptions/style/clothingCorset.js b/src/npc/descriptions/style/clothingCorset.js index 8c7c9a38337fce6e50abfa8b3975c6d00fc8bd09..d3d043157fff08f34d268519a26fabefc9202944 100644 --- a/src/npc/descriptions/style/clothingCorset.js +++ b/src/npc/descriptions/style/clothingCorset.js @@ -558,7 +558,7 @@ App.Desc.clothingCorset = function(slave) { break; case "a tube top and thong": case "striped underwear": - case "leather pants and tube top": + case "leather pants and a tube top": case "sport shorts and a sports bra": case "a slutty klan robe": if (slave.bellyAccessory === "a corset") { @@ -581,7 +581,6 @@ App.Desc.clothingCorset = function(slave) { case "jeans": case "sport shorts": case "leather pants": - case "leather pants and a tube top": case "leather pants and pasties": case "panties and pasties": case "pasties": diff --git a/src/npc/descriptions/style/footwear.js b/src/npc/descriptions/style/footwear.js index 619b1405f2b7ded7e529669b47e545eab5158a74..e5bffb89004699197ec2f472b4dd39085034ecf9 100644 --- a/src/npc/descriptions/style/footwear.js +++ b/src/npc/descriptions/style/footwear.js @@ -1972,7 +1972,7 @@ App.Desc.footwear = function(slave) { r.push(`a stylish platform shoe.`); } break; - case "platform hees": + case "platform heels": if (bothFeet) { r.push(`elegant platform heels.`); } else { @@ -4371,66 +4371,62 @@ App.Desc.footwear = function(slave) { switch (slave.shoes) { case "flats": if (bothFeet) { - r.push(`an elegant pair of dancing slippers.`); + r.push(`wearing an elegant pair of dancing slippers.`); } else { - r.push(`an elegant dancing slipper.`); + r.push(`wearing an elegant dancing slipper.`); } break; case "boots": if (bothFeet) { - r.push(`an elegant pair of heeled booties.`); + r.push(`wearing an elegant pair of heeled booties.`); } else { - r.push(`an elegant heeled boot.`); + r.push(`wearing an elegant heeled boot.`); } break; case "heels": if (bothFeet) { - r.push(`an elegant pair of heels.`); + r.push(`wearing an elegant pair of heels.`); } else { - r.push(`an elegant heel.`); + r.push(`wearing an elegant heel.`); } break; case "pumps": if (bothFeet) { - r.push(`an elegant pair of pumps.`); + r.push(`wearing an elegant pair of pumps.`); } else { - r.push(`an elegant heel.`); + r.push(`wearing an elegant heel.`); } break; case "extreme heels": if (bothFeet) { - r.push(`an elegant pair of excruciatingly high heels that test ${his} grace.`); + r.push(`wearing an elegant pair of excruciatingly high heels that test ${his} grace.`); } else { - r.push(`an elegant, excruciatingly high heel that makes it impossible for ${him} to stand.`); + r.push(`wearing an elegant, excruciatingly high heel that makes it impossible for ${him} to stand.`); } break; case "platform shoes": if (bothFeet) { - r.push(`a fragile pair of platform shoes.`); + r.push(`wearing a fragile pair of platform shoes.`); } else { - r.push(`a fragile platform shoe.`); + r.push(`wearing a fragile platform shoe.`); } break; case "platform heels": if (bothFeet) { - r.push(`a fragile pair of platform heels.`); + r.push(`wearing a fragile pair of platform heels.`); } else { - r.push(`a fragile platform heel.`); + r.push(`wearing a fragile platform heel.`); } break; case "extreme platform heels": if (bothFeet) { - r.push(`a fragile pair of excruciatingly high platform heels that test ${his} focus with each step.`); + r.push(`wearing a fragile pair of excruciatingly high platform heels that test ${his} focus with each step.`); } else { - r.push(`a fragile, excruciatingly high platform heel that makes it impossible for ${him} to stand.`); + r.push(`wearing a fragile, excruciatingly high platform heel that makes it impossible for ${him} to stand.`); } break; default: - if (bothFeet) { - r.push(`elegantly bare feet.`); - } else { - r.push(`an elegant bare feet.`); - } + r.push(`elegantly bare footed.`); } break; case "a bimbo outfit": diff --git a/src/npc/descriptions/style/hairClothing.js b/src/npc/descriptions/style/hairClothing.js index abb2b573157580e82502466a04ad98bd63873ded..f0dd72434a564e7a13fd44c474dbe12274caf2f0 100644 --- a/src/npc/descriptions/style/hairClothing.js +++ b/src/npc/descriptions/style/hairClothing.js @@ -622,7 +622,7 @@ App.Desc.hairClothing = function(slave) { case "a string bikini": case "attractive lingerie": case "attractive lingerie for a pregnant woman": - case "long qipao": + case "a long qipao": case "a dirndl": case "lederhosen": case "a biyelgee costume": @@ -1238,7 +1238,7 @@ App.Desc.hairClothing = function(slave) { case "uncomfortable straps": r.push(`is back in huge tails secured by leather ties.`); break; - case "shibari rope": + case "shibari ropes": r.push(`is back in huge tails tied back with rope.`); break; case "restrictive latex": @@ -1400,7 +1400,7 @@ App.Desc.hairClothing = function(slave) { case "uncomfortable straps": r.push(`is back in big tails secured by leather ties.`); break; - case "shibari rope": + case "shibari ropes": r.push(`is back in big tails tied back with rope.`); break; case "restrictive latex": @@ -1562,7 +1562,7 @@ App.Desc.hairClothing = function(slave) { case "uncomfortable straps": r.push(`is back in short tails secured by leather ties.`); break; - case "shibari rope": + case "shibari ropes": r.push(`is back in short tails secured with rope.`); break; case "restrictive latex": @@ -1821,7 +1821,7 @@ App.Desc.hairClothing = function(slave) { case "uncomfortable straps": r.push(`is back in a huge ponytail secured by leather ties.`); break; - case "shibari rope": + case "shibari ropes": r.push(`is back in a huge ponytail tied back with rope.`); break; case "restrictive latex": @@ -1983,7 +1983,7 @@ App.Desc.hairClothing = function(slave) { case "uncomfortable straps": r.push(`is back in a big ponytail secured by leather ties.`); break; - case "shibari rope": + case "shibari ropes": r.push(`is back in a big ponytail tied back with rope.`); break; case "restrictive latex": @@ -2145,7 +2145,7 @@ App.Desc.hairClothing = function(slave) { case "uncomfortable straps": r.push(`is back in short ponytail secured by leather ties.`); break; - case "shibari rope": + case "shibari ropes": r.push(`is back in short ponytail secured with rope.`); break; case "restrictive latex": @@ -2327,7 +2327,7 @@ App.Desc.hairClothing = function(slave) { case "uncomfortable straps": r.push(`is back in huge braids secured by leather ties.`); break; - case "shibari rope": + case "shibari ropes": r.push(`is back in huge braids tied back with rope.`); break; case "restrictive latex": @@ -2483,7 +2483,7 @@ App.Desc.hairClothing = function(slave) { case "uncomfortable straps": r.push(`is back in long braids secured by leather ties.`); break; - case "shibari rope": + case "shibari ropes": r.push(`is back in long braids tied back with rope.`); break; case "restrictive latex": @@ -2638,7 +2638,7 @@ App.Desc.hairClothing = function(slave) { case "uncomfortable straps": r.push(`is back in short braids secured by leather ties.`); break; - case "shibari rope": + case "shibari ropes": r.push(`is back in short braids secured with rope.`); break; case "restrictive latex": @@ -2820,7 +2820,7 @@ App.Desc.hairClothing = function(slave) { case "uncomfortable straps": r.push(`is in long dreadlocks some in simple leather ties.`); break; - case "shibari rope": + case "shibari ropes": r.push(`is in long dreadlocks, some simply tied with string.`); break; case "restrictive latex": @@ -2976,7 +2976,7 @@ App.Desc.hairClothing = function(slave) { case "uncomfortable straps": r.push(`is in dreadlocks, some tied with simple leather ties.`); break; - case "shibari rope": + case "shibari ropes": r.push(`is in dreadlocks, some simply tied with string.`); break; case "restrictive latex": @@ -3136,7 +3136,7 @@ App.Desc.hairClothing = function(slave) { case "uncomfortable straps": r.push(`is in short dreadlocks, some with simple leather ties.`); break; - case "shibari rope": + case "shibari ropes": r.push(`is in dreadlocks, some simply tied with string.`); break; case "restrictive latex": @@ -3318,7 +3318,7 @@ App.Desc.hairClothing = function(slave) { case "uncomfortable straps": r.push(`is curled into long flowing locks secured by leather ties.`); break; - case "shibari rope": + case "shibari ropes": r.push(`is in long dreadlocks, some simply tied with string.`); break; case "restrictive latex": @@ -3474,7 +3474,7 @@ App.Desc.hairClothing = function(slave) { case "uncomfortable straps": r.push(`is curled into long locks, secured by leather ties.`); break; - case "shibari rope": + case "shibari ropes": r.push(`is curled into long locks, tied back with rope.`); break; case "restrictive latex": @@ -3630,7 +3630,7 @@ App.Desc.hairClothing = function(slave) { case "uncomfortable straps": r.push(`is curled into short locks secured by leather ties.`); break; - case "shibari rope": + case "shibari ropes": r.push(`is curled into short locks tied with rope.`); break; case "restrictive latex": @@ -3812,7 +3812,7 @@ App.Desc.hairClothing = function(slave) { case "uncomfortable straps": r.push(`is permed into long flowing curls secured by leather ties.`); break; - case "shibari rope": + case "shibari ropes": r.push(`is in long dreadlocks, some simply tied with string.`); break; case "restrictive latex": @@ -3968,7 +3968,7 @@ App.Desc.hairClothing = function(slave) { case "uncomfortable straps": r.push(`is permed and secured by leather ties.`); break; - case "shibari rope": + case "shibari ropes": r.push(`is permed and tied back with rope.`); break; case "restrictive latex": @@ -4124,7 +4124,7 @@ App.Desc.hairClothing = function(slave) { case "uncomfortable straps": r.push(`is permed into short waves secured by leather ties.`); break; - case "shibari rope": + case "shibari ropes": r.push(`is permed into short waves tied with rope.`); break; case "restrictive latex": @@ -5031,7 +5031,7 @@ App.Desc.hairClothing = function(slave) { r.push(`is shaved into a permed strip which falls down ${his} back.`); break; case "a kimono": - case "long qipao": + case "a long qipao": r.push(`is shaved into a long braided strip with little ivory talismans woven into it.`); break; case "a slutty qipao": @@ -5448,7 +5448,7 @@ App.Desc.hairClothing = function(slave) { r.push(`is shaved into a permed strip which falls down ${his} back.`); break; case "a kimono": - case "long qipao": + case "a long qipao": r.push(`is shaved into a long, flowing undercut with little ivory talismans woven into it.`); break; case "a slutty qipao": @@ -6309,7 +6309,7 @@ App.Desc.hairClothing = function(slave) { case "a string bikini": case "attractive lingerie": case "attractive lingerie for a pregnant woman": - case "long qipao": + case "a long qipao": case "a dirndl": case "lederhosen": case "a biyelgee costume": @@ -6363,7 +6363,7 @@ App.Desc.hairClothing = function(slave) { case "uncomfortable straps": r.push(`is wound into enormous coils restrained by leather ties.`); break; - case "shibari rope": + case "shibari ropes": r.push(`is wound into enormous coils restrained with rope.`); break; case "restrictive latex": @@ -6522,7 +6522,7 @@ App.Desc.hairClothing = function(slave) { case "uncomfortable straps": r.push(`is wound into large coils secured by leather ties.`); break; - case "shibari rope": + case "shibari ropes": r.push(`is wound into large coils tied back with rope.`); break; case "restrictive latex": @@ -6684,7 +6684,7 @@ App.Desc.hairClothing = function(slave) { case "uncomfortable straps": r.push(`is back in short coils secured by leather ties.`); break; - case "shibari rope": + case "shibari ropes": r.push(`is back in short coils secured with rope.`); break; case "restrictive latex": diff --git a/src/npc/generate/newSlaveIntro.js b/src/npc/generate/newSlaveIntro.js index 1b871d618282454fda2dd414a4a9967f08b33f0b..01e098ca988324918d831d3360566d3a423af619 100644 --- a/src/npc/generate/newSlaveIntro.js +++ b/src/npc/generate/newSlaveIntro.js @@ -3114,6 +3114,60 @@ App.UI.newSlaveIntro = function(slave, slave2, {tankBorn = false, momInterest = lineBreak(); } + if (slave.boobs > 300 && slave.lactation > 0) { + choice({ + linkName: `Milk ${him}`, + result(slave) { + const r = []; + r.push(`You`); + if (tankBorn) { + r.push(`pull the curious ${desc}`); + } else { + if (slave.devotion > 20 || slave.trust < -20) { + r.push(`instruct the obedient ${desc}`); + } else { + r.push(`force the reluctant ${desc}`); + } + r.push(`to sit`); + } + r.push(`atop your desk in front of you and present ${his} chest. After a quick look, you extend an idle hand and begin to fondle ${his}`); + if (slave.boobs > 2000) { + r.push(`massive milky tits,`); + } else if (slave.boobs > 400) { + r.push(`healthy milky breasts,`); + } else { + r.push(`cute little milky boobs,`); + } + r.push(`continuing your work with your other hand. You quickly focus your fiddling on ${his} ${slave.nipples} nipples, the stimulation`); + if (slave.nipples === "fuckable") { + if (slave.devotion > 20) { + r.push(`rapidly engorging them around your fingers.`); + } else { + r.push(`slowly engorging them around your fingers despite ${his} feelings.`); + } + } else { + r.push(`bringing them`); + if (slave.devotion > 20) { + r.push(`quickly erect.`); + } else { + r.push(`slowly erect despite ${his} feelings.`); + } + } + r.push(`Once you feel satisfied with the state of those two bumps, you move to tug and squeeze ${his} breasts in a much different way, expertly putting pressure as to draw out the cream held within those swollen bags. You take your time to work as much out as you can, both for your own enjoyment and to judge your slave's character better.`); + if (slave.devotion > 20) { + r.push(`${He} easily accepts your orders and commands, being devoted enough to not make any fuss, especially for something as simple as this.`); + slave.devotion += 4; + } else { + r.push(`${He} expects something worse to happen immediately, and slowly relaxes when ${he} realizes that ${he}'s nothing more than your desktop stress relief toy, at least for now. ${He} experiences the usual effects of nipple play, but seems <span class="trust dec">somewhat frightened</span> to be dehumanized so thoroughly.`); + slave.trust -= 4; + } + return r.join(" "); + } + }); + lineBreak(); + } + + choice({ linkName: `Tease ${his} nipples`, result(slave) { diff --git a/src/npc/interaction/fPCImpreg.js b/src/npc/interaction/fPCImpreg.js index 88d1caa54decb7540485368b697a0d0624048a8a..487d206776c90584f29dc6ffde13c416c6f32740 100644 --- a/src/npc/interaction/fPCImpreg.js +++ b/src/npc/interaction/fPCImpreg.js @@ -272,20 +272,14 @@ App.Interact.fPCImpreg = function(slave) { if (V.arcologies[0].FSGenderRadicalist !== 'unset' && slave.mpreg) { text.push(`Society <span class="reputation inc">approves</span> of your fucking your slaves' asses pregnant; this advances the ideal all a slave needs is ${his} rear.`); - - repX(V.FSSingleSlaveRep * (V.arcologies[0].FSGenderRadicalist / V.FSLockinLevel), 'futureSocieties', slave); - V.arcologies[0].FSGenderRadicalist += 0.05 * V.FSSingleSlaveRep; + FutureSocieties.Change("FSGenderRadicalist", 1); } else if (V.arcologies[0].FSGenderFundamentalist !== 'unset') { if (slave.mpreg) { - text.push(`Society <span class="reputation inc">approves</span> of your putting a new slave in ${him}; this advances the idea that all slaves should bear their masters' babies.`); - - repX(forceNeg(V.FSSingleSlaveRep * (V.arcologies[0].FSGenderFundamentalist / V.FSLockinLevel)), 'futureSocieties', slave); - V.arcologies[0].FSGenderFundamentalist -= 0.05 * V.FSSingleSlaveRep; - } else { text.push(`Society <span class="reputation dec">is disgusted</span> by this degenerate form of reproduction.`); - - repX(V.FSSingleSlaveRep * (V.arcologies[0].FSGenderFundamentalist / V.FSLockinLevel), 'futureSocieties', slave); - V.arcologies[0].FSGenderFundamentalist += 0.05 * V.FSSingleSlaveRep; + FutureSocieties.Change("FSGenderFundamentalist", -1); + } else { + text.push(`Society <span class="reputation inc">approves</span> of your putting a new slave in ${him}; this advances the idea that all slaves should bear their masters' babies.`); + FutureSocieties.Change("FSGenderFundamentalist", 1); } } diff --git a/src/npc/interaction/passage/fSlaveImpreg.js b/src/npc/interaction/passage/fSlaveImpreg.js index 918139e487e8fe69600b8443359b84a547bc7425..b97a0cb57bb025b023677cf4ec5bdfae2b10e29f 100644 --- a/src/npc/interaction/passage/fSlaveImpreg.js +++ b/src/npc/interaction/passage/fSlaveImpreg.js @@ -443,18 +443,18 @@ App.Interact.fSlaveImpreg = function(slave) { r.push(`Rumors spread about you breeding your slaves; the Societal Elite are <span class="red">displeased</span> by these rumors.`); V.failedElite += 1; } - if (V.arcologies[0].FSGenderRadicalist !== "unset" && slave.mpreg === 1) { - r.push(`Society <span class="green">approves</span> of your breeding your slave's ass; this advances the ideal all a slave needs is their rear.`); - repX(V.FSSingleSlaveRep * (V.arcologies[0].FSGenderRadicalist / V.FSLockinLevel), "futureSocieties", slave); - V.arcologies[0].FSGenderRadicalist += 0.05 * V.FSSingleSlaveRep; - } else if (V.arcologies[0].FSGenderFundamentalist !== "unset" && slave.mpreg === 1) { - r.push(`Society <span class="red">is disgusted</span> by this degenerate form of reproduction.`); - repX(forceNeg(V.FSSingleSlaveRep * (V.arcologies[0].FSGenderFundamentalist / V.FSLockinLevel)), "futureSocieties", slave); - V.arcologies[0].FSGenderFundamentalist -= 0.05 * V.FSSingleSlaveRep; - } else if (V.arcologies[0].FSGenderFundamentalist !== "unset") { - r.push(`Society <span class="green">approves</span> of your breeding your slaves; this advances the ideal of a durable, self propagating race of slaves.`); - repX(V.FSSingleSlaveRep * (V.arcologies[0].FSGenderFundamentalist / V.FSLockinLevel), "futureSocieties", slave); - V.arcologies[0].FSGenderFundamentalist += 0.05 * V.FSSingleSlaveRep; + + if (V.arcologies[0].FSGenderRadicalist !== 'unset' && slave.mpreg) { + r.push(`Society <span class="reputation inc">approves</span> of your breeding your slave's ass; this advances the ideal all a slave needs is ${his} rear.`); + FutureSocieties.Change("FSGenderRadicalist", 1); + } else if (V.arcologies[0].FSGenderFundamentalist !== 'unset') { + if (slave.mpreg) { + r.push(`Society <span class="reputation dec">is disgusted</span> by this degenerate form of reproduction.`); + FutureSocieties.Change("FSGenderFundamentalist", -1); + } else { + r.push(`Society <span class="reputation inc">approves</span> of your breeding your slaves; this advances the ideal of a durable, self propagating race of slaves`); + FutureSocieties.Change("FSGenderFundamentalist", 1); + } } App.Events.addParagraph(node, r); diff --git a/src/player/js/PlayerState.js b/src/player/js/PlayerState.js index befb2e66c94e4b8f9bc05aa7ca1b03bc6fecdd58..dd4173e855497fa45df1def71a10920719d7c37c 100644 --- a/src/player/js/PlayerState.js +++ b/src/player/js/PlayerState.js @@ -312,7 +312,7 @@ App.Entity.PlayerState = class PlayerState { * * 90 - : Unnaturally healthy */ condition: 0, - /** your short term health damage */ + /** your short term health damage, used to determine how long you are in recovery */ shortDamage: 0, /** your long term health damage */ longDamage: 0, @@ -609,7 +609,7 @@ App.Entity.PlayerState = class PlayerState { * * 70000-89999 - door-crowding * * 90000-100000 - door-jamming */ - this.boobs = 100; + this.boobs = 200; /** breast engorgement from unmilked tits */ this.boobsMilk = 0; /** @@ -1879,13 +1879,13 @@ App.Entity.PlayerState = class PlayerState { /** Have you gone through female puberty. * @type {FC.Bool} * 0: no; 1: yes */ - this.pubertyXX = 1; + this.pubertyXX = 0; /** Target .physicalAge for male puberty to occur. */ this.pubertyAgeXY = 13; /** Have you slave gone through male puberty. * @type {FC.Bool} * 0: no; 1: yes */ - this.pubertyXY = 1; + this.pubertyXY = 0; /** * scar * Sub-object: diff --git a/src/pregmod/FCTV/FCTV.js b/src/pregmod/FCTV/FCTV.js index 00ad0d706248bfa198f619d0c56829e8b98576f6..ea21b50cee00aed29f1ff71a5642e5e6b08618cc 100644 --- a/src/pregmod/FCTV/FCTV.js +++ b/src/pregmod/FCTV/FCTV.js @@ -97,7 +97,7 @@ globalThis.FctvDisplay = function() { p.append(` to turn on the TV and `); if (!usedRemote) { p.append(`set FCTV to find a random show. Your larger-than-life screen flashes on, and is soon playing content from the popular streaming service. `); - if (V.cheatMode > 0 || V.debugMode > 0 || V.FCTV.remote) { + if (V.cheatMode > 0 || (V.debugMode > 0 && V.debugModeEventSelection > 0) || V.FCTV.remote) { // Create "Use remote" link. Hide once clicked. span = document.createElement("span"); span.id = "use-remote"; @@ -114,7 +114,7 @@ globalThis.FctvDisplay = function() { p.append(span); } p.append(randomShow()); - } else if (usedRemote && (V.cheatMode > 0 || V.debugMode > 0 || V.FCTV.remote)) { + } else if (usedRemote && (V.cheatMode > 0 || (V.debugMode > 0 && V.debugModeEventSelection > 0) || V.FCTV.remote)) { p.append(`bring you the remote so you can choose whatever show you find interesting. `); if (selectedChannel === V.FCTV.channel.last) { App.UI.DOM.appendNewElement("div", p, `You tuned into this channel last week, you may want to choose something else.`); @@ -133,7 +133,7 @@ globalThis.FctvDisplay = function() { p.classList.add("FCTV"); span = document.createElement("span"); span.id = "remote"; - if (usedRemote && (V.cheatMode > 0 || V.debugMode > 0 || V.FCTV.remote)) { + if (usedRemote && (V.cheatMode > 0 || (V.debugMode > 0 && V.debugModeEventSelection > 0) || V.FCTV.remote)) { span.append(createRemote()); } p.append(span); @@ -225,7 +225,7 @@ globalThis.FctvDisplay = function() { ), ["fctv-remote-button"] ); - if (V.cheatMode > 0 || V.debugMode > 0) { + if (V.debugMode > 0 && V.debugModeEventSelection > 0) { App.UI.DOM.appendNewElement( "div", p, diff --git a/src/pregmod/FCTV/FCTVshows.js b/src/pregmod/FCTV/FCTVshows.js index d37f03e6a41d6c42e8dea7f2238f2c4aa68680a5..e079cd39682ac44417bd0027e694ba20d3258aff 100644 --- a/src/pregmod/FCTV/FCTVshows.js +++ b/src/pregmod/FCTV/FCTVshows.js @@ -93,7 +93,7 @@ App.Data.FCTV.actors = { const slave = BaseSlave(); slave.devotion = 0; slave.trust = 0; - slave.muscles = 600; + slave.muscles = 60; slave.boobs = 700; slave.butt = 3; slave.hLength = 50; diff --git a/src/pregmod/managePersonalAffairs.js b/src/pregmod/managePersonalAffairs.js index cc591564431ba01a000cb4de23b3b19fcd1716f1..9c5a9460b3813b3604e79b9d09a0f9b2e7d3eb13 100644 --- a/src/pregmod/managePersonalAffairs.js +++ b/src/pregmod/managePersonalAffairs.js @@ -1129,7 +1129,7 @@ App.UI.managePersonalAffairs = function() { function breederExam() { App.UI.DOM.appendNewElement("h2", breederExamDiv, `Elite Breeder Qualifications`); - App.Events.addNode(breederExamDiv, [eliteBreedingExam()]); + breederExamDiv.append(eliteBreedingExam()); return breederExamDiv; } diff --git a/src/uncategorized/PESS.tw b/src/uncategorized/PESS.tw index b9a614a2f4fae061c3708ecc1bc3fdaa4ceb407b..bf16a27359639fd4676eab13b952a96fb4a5b463 100644 --- a/src/uncategorized/PESS.tw +++ b/src/uncategorized/PESS.tw @@ -24,7 +24,7 @@ <<if Array.isArray($PESSevent)>> <<set $activeSlave = $eventSlave>> - <<if $cheatMode == 1>> + <<if ($debugMode > 0 && $debugModeEventSelection > 0)>> <<set $nextButton = "Back", $nextLink = "Nonrandom Event", $returnTo = "Nonrandom Event">> /* if user just clicks spacebar */ ''A random single slave event would have been selected from the following:'' <br> @@ -635,7 +635,7 @@ $He sees you examining at $him, and looks back at you submissively, too tired to <br>ERROR: bad PESS event $PESSevent <</switch>> -<<if $cheatMode == 1>> +<<if ($debugMode > 0 && $debugModeEventSelection > 0)>> <br><br>DEBUG: [[Go back to Nonrandom Event|Nonrandom Event][$activeSlave = 0, $eventSlave = 0]] <</if>> diff --git a/src/uncategorized/PETS.tw b/src/uncategorized/PETS.tw index 9dea1f679fb981190e059363a442aa945a305a51..21ae86029cd23548bc3d2270e1c9e595057a8f96 100644 --- a/src/uncategorized/PETS.tw +++ b/src/uncategorized/PETS.tw @@ -24,7 +24,7 @@ <<if Array.isArray($PETSevent)>> <<set $activeSlave = $eventSlave>> - <<if $cheatMode == 1>> + <<if ($debugMode > 0 && $debugModeEventSelection > 0)>> <<set $nextButton = "Back", $nextLink = "Nonrandom Event", $returnTo = "Nonrandom Event">> /* if user just clicks spacebar */ ''A random two slave event would have been selected from the following:'' <br> @@ -363,7 +363,7 @@ You decide to knit up care's raveled sleave with a break in the spa. You have yo <br>ERROR: bad PETS event $PETSevent <</switch>> -<<if $cheatMode == 1>> +<<if ($debugMode > 0 && $debugModeEventSelection > 0)>> <br><br>DEBUG: [[Go back to Nonrandom Event|Nonrandom Event][$activeSlave = 0, $eventSlave = 0]] <</if>> diff --git a/src/uncategorized/REFS.tw b/src/uncategorized/REFS.tw index 176d914f34e55baf3ab819bb96d8fe495efa8f38..48e119d2380cd6be003a6cac842fab038516de38 100644 --- a/src/uncategorized/REFS.tw +++ b/src/uncategorized/REFS.tw @@ -23,7 +23,7 @@ /* Some scenes are also stored in useGuard.tw, walkPast.tw, and toychest.tw */ <<if Array.isArray($REFSevent)>> - <<if $cheatMode === 1>> + <<if $debugMode > 0 && $debugModeEventSelection > 0>> <<set $nextButton = "Back", $nextLink = "Nonrandom Event", $returnTo = "Nonrandom Event">> /* if user just clicks spacebar */ ''A random future societies event would have been selected from the following:'' <br> diff --git a/src/uncategorized/RESS.tw b/src/uncategorized/RESS.tw index db0b8d9ab0cbda1337a546d52865ef07bb251ab5..ed563dea00037e3d46c6622d16f17aa2bb47b2a6 100644 --- a/src/uncategorized/RESS.tw +++ b/src/uncategorized/RESS.tw @@ -24,7 +24,7 @@ <<if Array.isArray($RESSevent)>> <<set $activeSlave = $eventSlave>> - <<if $cheatMode == 1>> + <<if $debugMode > 0 && $debugModeEventSelection > 0>> <<set $nextButton = "Back", $nextLink = "Nonrandom Event", $returnTo = "Nonrandom Event">> /* if user just clicks spacebar */ ''A random single slave event would have been selected from the following:'' <br> @@ -44,11 +44,8 @@ <<set _clothesTemp = $activeSlave.clothes>> <<switch $RESSevent>> /*Some events start with the slave naked (any event that starts with the daily inspection, for example). Here we switch their clothing just for the image to load, then switch it back quickly so the player's choice is not messed up.*/ -<<case "age implant" "ara ara" "back stretch" "bad dream" "bonded love" "breast expansion blues" "confident tanning" "devoted exhibition" "devoted lotion" "desperate null" "devoted nympho" "extreme aphrodisiacs" "fearful balls" "fucktoy tribbing" "gaped asshole" "happy dance" "heavy piercing" "huge naturals" "huge tits" "hugely pregnant" "ignorant horny" "implant inspection" "language lesson" "mindbroken morning" "modest clothes" "mods please" "old PC age difference" "orchiectomy please" "PA flirting" "penitent" "permitted masturbation" "plimb help" "rebellious arrogant" "resistant gelding" "resistant shower" "resting amp" "restricted profession" "restricted smart" "sexy succubus" "shaped areolae" "shift masturbation" "shift sleep" "shower slip" "slave dick huge" "sleeping ambivalent" "sore shoulders" "spa boobs" "subjugation blues" "tendon fall" "terrified inspection" "tittymonster inspection" "torpedo squeeze" "transition anxiety" "trusting HG" "unhappy virgin" "used whore" "vocal disobedience" "young PC age difference">> +<<case "age implant" "ara ara" "back stretch" "bad dream" "bonded love" "breast expansion blues" "confident tanning" "devoted exhibition" "devoted lotion" "desperate null" "devoted nympho" "extreme aphrodisiacs" "fearful balls" "fucktoy tribbing" "gaped asshole" "happy dance" "heavy piercing" "huge naturals" "huge tits" "hugely pregnant" "ignorant horny" "implant inspection" "language lesson" "mindbroken morning" "mods please" "old PC age difference" "orchiectomy please" "PA flirting" "penitent" "permitted masturbation" "plimb help" "rebellious arrogant" "resistant gelding" "resistant shower" "resting amp" "restricted profession" "restricted smart" "sexy succubus" "shaped areolae" "shift masturbation" "shift sleep" "shower slip" "slave dick huge" "sleeping ambivalent" "sore shoulders" "spa boobs" "subjugation blues" "tendon fall" "terrified inspection" "tittymonster inspection" "torpedo squeeze" "transition anxiety" "trusting HG" "unhappy virgin" "used whore" "vocal disobedience" "young PC age difference">> <<set $activeSlave.clothes = "no clothing">> -<<case "whore rebellious">> - /* this scene states they are wearing "thick, durable latex with temperature regulation and anchor points for restraint" no matter what they are assigned to wear. */ - <<set $activeSlave.clothes = "restrictive latex">> <<case "inconvenient labia">> /* "pulling down the compression shorts $he was wearing" */ <<if isItemAccessible.entry("sport shorts", "clothes")>> @@ -1665,14 +1662,6 @@ $He constantly passes by your desk as you work, going back and forth between the <</if>> gingerly, supporting $his udders with <<if hasBothArms($activeSlave)>>both hands<<else>>$his hand<</if>><<if $activeSlave.belly >= 10000>> and $his _belly <<if $activeSlave.belly >= 3000>>pregnant<<else>>rounded<</if>> belly<</if>>, <<if $activeSlave.nipples == "inverted">>wincing<<else>>dribbling a little milk<</if>> as $he goes. The other way, $he has a distinctly relieved expression and $his breasts are much saggier. -<<case "whore rebellious">> - -<<= App.UI.slaveDescriptionDialog($activeSlave)>> is kicked out of bed early in the morning. $He's not yet obedient, but $he has to earn $his keep anyway. This means selling $his body, or in $his particular case, having $his unwilling body sold. $He knows the score and allows $himself to be stuffed into a special latex public whore suit. $He's learned the hard way that resisting being suited up just means $he'll be painfully punished before being suited up. -<br><br> -The suit is quite special. It is made of thick, durable latex with temperature regulation and anchor points for restraint. It is specially crafted to be able to accommodate its wearer's tits, belly,<<if $seeDicks != 0>> dick, balls,<</if>> and rear, however large. It has a hole at $his mouth that holds $his jaws well open, with a plug to fill it completely when not in use. $He breathes through a port at $his nose that muffles all noise, in and out.<<if ($activeSlave.dick > 0)>> $His cock is neglected inside the latex, with no means of access.<</if>><<if ($activeSlave.vagina != -1)>> There's a hole over $his pussy, of course.<</if>> Finally, there's a hole over $his anus. -<br><br> -$He will spend the day restrained in public, with your other slaves periodically stopping by to hydrate $him and wash out $his holes. - <<case "millenary">> Late one night, <<= App.UI.slaveDescriptionDialog($activeSlave)>> comes to see you. Strangely, several of your other slaves are stealing glances at $him as $he does. $He seems oddly proud of $himself. Asked why, $he says, "It'<<s>> my millenary, <<Master>>. The arcology has logged me getting fucked <<= num(999)>> time<<s>>." The other slaves obviously view it as significant, too. @@ -2305,82 +2294,6 @@ To go by $his behavior, the likelihood that $he's actually eager to <<if $PC.dic $desc has run through the prescribed motions of a normal inspection, and you've reached the part of the routine where you usually ask the slave a few questions, give $him a few orders, or fuck $him. $His <<if canSee($activeSlave)>><<= App.Desc.eyesColor($activeSlave)>> are watching you closely<<else>>face is centered on you<</if>>, and $he's <<if canHear($activeSlave)>>listening carefully<<else>>waiting patiently<</if>> for direction. This is probably due to linguistic anxiety: $he can understand the most straightforward commands, but giving $him orders is often an exercise in <<if canSee($activeSlave)>>pointing and gesturing, or when that fails, simply<<else>>frustration, ending with you simply<</if>> pushing and pulling $his usually-compliant body into the proper place. -<<case "forbidden masturbation">> - -<<if $assistant.personality > 0>> - There is an alert from $assistant.name, in _hisA deliciously feminine voice: "$activeSlave.slaveName is masturbating, <<= properMaster()>>. Ooh, $he's breaking the rules, <<= properMaster()>>!" _HisA avatar - <<switch $assistant.appearance>> - <<case "monstergirl">> - strokes _hisA dicks suggestively. - <<case "shemale">> - shifts uncomfortably, _hisA cock rock hard. - <<case "amazon">> - struts back and forth indignantly, _hisA bone bangles rattling. - <<case "businesswoman">> - licks _hisA cherry-red lips suggestively. - <<case "fairy" "pregnant fairy">> - giggles uncontrollably. - <<case "hypergoddess" "goddess">> - tutting disapprovingly, despite _hisA blushing. - <<case "loli">> - stares innocently at the scene. - <<case "preggololi">> - stares at the scene, blushing, while a hand caresses _hisA large belly. - <<case "angel">> - is covering _hisA face, occasionally peeping through _hisA fingers. - <<case "cherub">> - is trying _hisA hardest to look away, but keeps glancing back at the scene. - <<case "incubus">> - is openly jacking off to the sight. - <<case "succubus">> - is groping _himselfA to the sight. - <<case "imp">> - is hovering while viciously fingering _hisA cunt. - <<case "witch">> - is pretending to read from _hisA spell book, but is obviously watching over the top of it. - <<case "ERROR_1606_APPEARANCE_FILE_CORRUPT">> - is mimicking _hisA actions nearly perfectly. - <<case "schoolgirl">> - giggles nervously. - <<default>> - spins accusingly. - <</switch>> -<<else>> - There is a gentle alert from $assistant.name: "$activeSlave.slaveName is masturbating in violation of the rules, <<= properMaster()>>." -<</if>> -A video feed appears. -<<if ($activeSlave.chastityVagina)>> - In $his chastity belt, all $he can manage is furious nipple-<<if $activeSlave.nipples != "fuckable">>rubbing<<else>>fisting<</if>> and some furtive fingering of $his asshole. -<<elseif ($activeSlave.chastityPenis == 1)>> - In $his chastity cage, all $he can manage is furious nipple-<<if $activeSlave.nipples != "fuckable">>rubbing<<else>>fisting<</if>> and some furtive fingering of $his asshole. -<<elseif ($activeSlave.dick > 0) && ($activeSlave.hormoneBalance >= 100)>> - Since $he's impotent from hormone treatment, all $he can manage is rubbing $his soft dick and some furtive fingering of $his asshole. -<<elseif ($activeSlave.dick > 0) && ($activeSlave.balls > 0) && ($activeSlave.ballType == "sterile")>> - Since $he's impotent due to $his useless balls, all $he can manage is rubbing $his soft dick and some furtive fingering of $his asshole. -<<elseif ($activeSlave.dick > 0) && ($activeSlave.balls == 0)>> - Since $he's impotent due to $his lack of balls, all $he can manage is rubbing $his soft dick and some furtive fingering of $his asshole. -<<elseif !canAchieveErection($activeSlave) && ($activeSlave.dick > 6)>> - Since $his dick requires far too much blood to get erect, $he's furiously massaging the semi-engorged monster. -<<elseif !canAchieveErection($activeSlave) && ($activeSlave.dick > 0)>> - Since $he's can't get it up, all $he can manage is rubbing $his soft dick and some furtive fingering of $his asshole. -<<elseif ($activeSlave.vagina == -1) && ($activeSlave.dick == 0)>> - $He's rubbing $his perineum desperately with one hand, and $his anus with the other, since $he lacks external genitalia. -<<elseif $activeSlave.vagina == -1>> - $He's furiously jacking off. -<<elseif $activeSlave.clit >= 3>> - $He's furiously jacking off $his clitdick. -<<else>> - $He's furiously polishing $his pearl. -<</if>> -$He's chosen to do it in a dark corner and looks like $he's hurrying; $he clearly knows this is forbidden. -<br><br> -<<= App.UI.slaveDescriptionDialog($activeSlave)>> does not hear your approach <<if canHear($activeSlave)>>until you're very close.<<else>>but soon realizes your presence.<</if>> $He starts and tries to look normal. -<<if !canTalk($activeSlave)>> - $He nervously gestures that $he wasn't doing anything. -<<else>> - "I wa<<s>>n't doing anything, <<if $activeSlave.rudeTitle == 1>><<= PoliteRudeTitle($activeSlave)>><<else>><<Master>><</if>>!" $he lies. -<</if>> - <<case "hates oral">> <<= App.UI.slaveDescriptionDialog($activeSlave)>> has been in your service long enough to know that oral sex is a daily fact of life for most slaves, and that most slaves are not only required to put up with cum, but to love it, too — or at least be able to fake enjoyment convincingly. $He's <<if canSee($activeSlave)>>seen cum spattered on other slaves' faces, pooling in their mouths, and dripping from their asses only to be licked up by other slaves<<elseif canHear($activeSlave)>>heard cum spattering across other slaves' faces, the sound of it in their mouths, dripping from their asses, and more<<else>>felt seminal fluid on $his skin and on $his lips, always coercively or accidentally<</if>>. It's clear from $activeSlave.slaveName's recent reactions to these acts that $he's quite disgusted by oral sex in general and cum in particular. Depending on your point of view, this could be a flaw for $him to overcome or a weakness you can exploit. @@ -3474,41 +3387,6 @@ sighing contentedly at the feeling. <<if canSee($activeSlave)>>$He opens $his ey "Good morning, <<Master>>," $he <<say>>s properly, doing $his best to be good. $He <<if canSee($activeSlave)>>watches you closely<<elseif canHear($activeSlave)>>listens closely<<else>>waits patiently<</if>>, ready to obey any command you might give $him. <</if>> -<<case "modest clothes">> - -<<if SlaveStatsChecker.checkForLisp($activeSlave)>> - <<set _clothes = lispReplace($activeSlave.clothes)>> -<<else>> - <<set _clothes = $activeSlave.clothes>> -<</if>> - -Near the end of $his weekly inspection, <<= App.UI.slaveDescriptionDialog($activeSlave)>> asks you a question. The inspection happens to have been at the start of $his day, and after you're done with $him, $he'll be heading off to get dressed. $He's naked for inspection, of course, -<<if $activeSlave.fetishKnown && $activeSlave.fetish == "humiliation">>which has the humiliation fetishist $desc decently aroused<<else>>but $he's a good $desc, and $he trusts you, so $he has no problem at all with being seen nude<</if>>. In fact, that's what $he asks you about. -<br><br> -"<<Master>>," $he <<say>>s, "may I plea<<s>>e wear <<s>>omething a little more revealing, ju<<s>>t for today?" $He <<if $activeSlave.trust > 95>>trusts you completely, enough to have confidence that you'll understand $he isn't<<else>>bites $his lip, realizing that $he might have come across as<</if>> questioning you. "Wearing -<<switch $activeSlave.clothes>> -<<case "a nice maid outfit">> - a proper maid'<<s>> outfit -<<case "a nice nurse outfit">> - a proper nur<<s>>e'<<s>> outfit -<<case "nice business attire">> - a <<s>>uit -<<case "battledress">> - a _clothes -<<default>> - _clothes -<</switch>> -i<<s>> ni<<c>>e," $he <<if $activeSlave.trust > 95>>allows<<else>>hurries to add<</if>>. -<<if $activeSlave.fetishKnown && $activeSlave.fetish == "humiliation">>"It'<<s>> not really embara<<ss>>ing, though. It would be <<s>>o <<s>>e<<x>>y to be, um, falling out of my clothe<<s>>. -<<elseif $activeSlave.fetishKnown && $activeSlave.fetish == "buttslut">>"But they cover my a<<ss>>hole. -<<elseif $activeSlave.fetishKnown && $activeSlave.fetish == "boobs">>"But they cover my boob<<s>>. -<<elseif $activeSlave.fetishKnown && $activeSlave.fetish == "pregnancy" && $activeSlave.bellyPreg >= 1500>>"But it cover<<s>> up my pregnan<<c>>y. -<<elseif $activeSlave.assignment == "whore">>"But I al<<s>>o like being a pro<<s>>titute, <<Master>>. It'd be fun to try looking like a total whore. -<<elseif $activeSlave.assignment == "serve the public">>"But I al<<s>>o like being a public <<s>>lut, <<Master>>. It'd be fun to really flaunt it. -<<else>>"But it'd be fun and different to wear <<s>>omething really naughty. -<</if>> -May I plea<<s>>e try out <<s>>omething <<s>>kimpier today?" - <<case "hyperpreg stuck">> You are alerted to an issue regarding your @@ -9879,120 +9757,6 @@ $He cranes $his neck, glancing over $his shoulder to give you a pleading look. <</link>><<if ($activeSlave.anus == 0 && canDoAnal($activeSlave)) || ($activeSlave.vagina == 0 && canDoVaginal($activeSlave))>> //This option will take $his virginity//<</if>> <</if>> -<<case "whore rebellious">> - -<<link "Increase $his assignment to 24 hours a day">> - <<replace "#result">> - You give $activeSlave.slaveName no indication that $his public use assignment is about to change. Late in the day, when $his shift would normally end, another of your slaves simply maintains $him as usual and then leaves $him be. $activeSlave.slaveName is so deprived of any way to tell time that $he doesn't realize $he's been left for some time. The first indication $he gets that something's different is when liquid food is squirted down $his throat the next morning. When $he's finally stripped out of the suit at the end of the week, $he's pale and wan and $his holes are puffy and red. @@.health.dec;$His health was damaged.@@ However, $his permanent presence became quite noted. @@.green;Your reputation has increased.@@ And when $he's out of the suit, $he instantly begs you to allow $him to do anything to save $himself from more of that. @@.gold;$His fear of you has increased.@@ - <</replace>> - <<run repX(500, "event", $activeSlave), healthDamage($activeSlave, 10)>> - <<set $activeSlave.trust -= 10>> - <<if canDoVaginal($activeSlave)>> - <<if canDoAnal($activeSlave)>> - <<run seX($activeSlave, "vaginal", "public", "penetrative", 10)>> - <<run seX($activeSlave, "anal", "public", "penetrative", 10)>> - <<run seX($activeSlave, "oral", "public", "penetrative", 10)>> - <<if canGetPregnant($activeSlave) && $activeSlave.eggType == "human">> - <<= knockMeUp($activeSlave, 10, 2, -2)>> - <</if>> - <<else>> - <<run seX($activeSlave, "vaginal", "public", "penetrative", 20)>> - <<run seX($activeSlave, "oral", "public", "penetrative", 10)>> - <<if canGetPregnant($activeSlave) && $activeSlave.eggType == "human">> - <<= knockMeUp($activeSlave, 25, 0, -2)>> - <</if>> - <</if>> - <<else>> - <<run seX($activeSlave, "anal", "public", "penetrative", 20)>> - <<run seX($activeSlave, "oral", "public", "penetrative", 10)>> - <<if canGetPregnant($activeSlave) && $activeSlave.eggType == "human">> - <<= knockMeUp($activeSlave, 20, 1, -2)>> - <</if>> - <</if>> - <<if $activeSlave.vagina == 0 && $activeSlave.anus == 0>> - $His patrons, however, enjoyed claiming @@.lime;both $his virginity and anal cherry.@@ - <<set $activeSlave.anus++, $activeSlave.vagina++>> - <<elseif $activeSlave.vagina == 0>> - $His patrons, however, enjoyed claiming @@.lime;$his virginity.@@ - <<set $activeSlave.vagina++>> - <<elseif $activeSlave.anus == 0>> - $His patrons, however, enjoyed claiming @@.lime;$his anal cherry.@@ - <<set $activeSlave.anus++>> - <</if>> -<</link>><<if ($activeSlave.anus == 0 && canDoAnal($activeSlave)) || ($activeSlave.vagina == 0 && canDoVaginal($activeSlave))>> //This option will take $his virginity//<</if>> -<br><<link "Take the first and last every day">> - <<replace "#result">> - When $activeSlave.slaveName feels a cock entering $his mouth right after $he's suited up, $he knows it's you and wriggles as best $he can in the suit. It doesn't help much, and $his struggles don't prevent you from moving from $his mouth to $his ass, either. At the end of the day, on the other hand, the <<if $girl == "girl">>fe<</if>>male-shaped latex form is completely still and quiescent as you <<if $PC.dick == 0>>use a couple of fingers to brutally molest<<else>>molest<</if>> each of its holes. It takes viciously hard anal penetration to elicit any response at all, and even then, it's just the slightest hint of a moan. @@.gold;$His fear of you has increased.@@ - <</replace>> - <<set $activeSlave.trust -= 5>> - <<if canDoVaginal($activeSlave)>> - <<if canDoAnal($activeSlave)>> - <<run seX($activeSlave, "vaginal", "public", "penetrative", 6)>> - <<run seX($activeSlave, "anal", "public", "penetrative", 6)>> - <<run seX($activeSlave, "oral", "public", "penetrative", 6)>> - <<if canImpreg($activeSlave, $PC)>> - <<= knockMeUp($activeSlave, 5, 2, -1)>> - <</if>> - <<if canGetPregnant($activeSlave) && $activeSlave.eggType == "human">> - <<= knockMeUp($activeSlave, 10, 2, -2)>> - <</if>> - <<else>> - <<run seX($activeSlave, "vaginal", "public", "penetrative", 9)>> - <<run seX($activeSlave, "oral", "public", "penetrative", 9)>> - <<if canImpreg($activeSlave, $PC)>> - <<= knockMeUp($activeSlave, 10, 0, -1)>> - <</if>> - <<if canGetPregnant($activeSlave) && $activeSlave.eggType == "human">> - <<= knockMeUp($activeSlave, 15, 0, -2)>> - <</if>> - <</if>> - <<else>> - <<run seX($activeSlave, "anal", "public", "penetrative", 9)>> - <<run seX($activeSlave, "oral", "public", "penetrative", 9)>> - <<if canImpreg($activeSlave, $PC)>> - <<= knockMeUp($activeSlave, 5, 1, -1)>> - <</if>> - <<if canGetPregnant($activeSlave) && $activeSlave.eggType == "human">> - <<= knockMeUp($activeSlave, 10, 1, -2)>> - <</if>> - <</if>> - <<if $activeSlave.vagina == 0 && $activeSlave.anus == 0>> - You made sure to claim @@.lime;both $his virginity and anal cherry@@ before anyone else could. - <<set $activeSlave.anus++, $activeSlave.vagina++>> - <<elseif $activeSlave.vagina == 0>> - You made sure to claim @@.lime;$his virginity@@ before anyone else could. - <<set $activeSlave.vagina++>> - <<elseif $activeSlave.anus == 0>> - You made sure to claim @@.lime;$his anal cherry@@ before anyone else could. - <<set $activeSlave.anus++>> - <</if>> -<</link>><<if ($activeSlave.anus == 0 && canDoAnal($activeSlave)) || ($activeSlave.vagina == 0 && canDoVaginal($activeSlave))>> //This option will take $his virginity//<</if>> -<<if $arcade > 0>> - <br><<link "Sentence $him to a month in the arcade">> - <<replace "#result">> - $activeSlave.slaveName screams and begs when $he realizes what $his punishment is, but you are obdurate. - <<if ($activeSlave.muscles > 30)>> - $His powerful form has to be sedated for immurement in the arcade. - <<elseif ($activeSlave.weight >= 190)>> - $He is so massively fat that immuring $him in the arcade is a struggle, even when $he isn't trying to. - <<elseif $activeSlave.belly >= 120000>> - $He is so enormously gravid that immuring $him in the arcade is a hassle, even though $his _belly middle limits $his ability to struggle. - <<elseif ($activeSlave.weight >= -10)>> - $His desperate struggles make immuring $him in the arcade difficult. - <<elseif $activeSlave.belly >= 1500>> - $His <<if $activeSlave.bellyPreg >= 3000>>pregnant<<else>>_belly<</if>> body makes it slightly difficult to fit $him properly into the restraints for immurement in the arcade. - <<elseif $activeSlave.muscles < -15>> - $His weak body makes immuring $him in the arcade pathetically easy. - <<else>> - $His thin form makes immuring $him in the arcade pathetically easy. - <</if>> - After $he's properly confined, the only sign of $his discomfiture is a slight movement of $his butt as $he wriggles desperately against $his restraints. - <<= assignJob($activeSlave, "be confined in the arcade")>> - <<set $activeSlave.sentence = 4>> - <</replace>> - <</link>> -<</if>> - <<case "millenary">> <<if canDoAnal($activeSlave) || canDoVaginal($activeSlave)>> @@ -12286,211 +12050,6 @@ $He cranes $his neck, glancing over $his shoulder to give you a pleading look. <</replace>> <</link>> -<<case "forbidden masturbation">> - -<<link "Let $him earn relief">> - <<replace "#result">> - $He's extremely relieved that you're not going to punish $him for the rulebreaking when you tell $him that $he can touch $himself if $he - <<if $activeSlave.belly >= 300000>> - leans over $his _belly belly - <<else>> - gets on $his knees - <</if>> - and sucks you off. $He does a decent job, playing with $himself all the while. $He's learned that $he can get away with infractions if $he's willing to suck dick afterward. $His resistance to your will @@.mediumorchid;has increased.@@ - <<set $activeSlave.devotion -= 5>> - <<run seX($activeSlave, "oral", $PC, "penetrative")>> - <</replace>> -<</link>> -<br>Punish $him, but then let $him get off: -<<if ($activeSlave.fetish != "cumslut") || ($activeSlave.fetishKnown != 1) || ($activeSlave.fetishStrength <= 95)>> - <br> <<link "when $he sucks">> - <<replace "#result">> - You - <<if $PC.belly >= 10000>> - <<if $activeSlave.belly >= 300000>> - tip $him over $his _belly <<if $activeSlave.bellyPreg >= 3000>>pregnancy<<else>>middle<</if>>, do your best to get close beside $him, - <<elseif $activeSlave.belly >= 5000>> - order $him to bend over beside you so your pregnancy doesn't obstruct you as badly - <<else>> - lean back, pull $him over your knee and under your gravid dome of a middle - <</if>> - <<else>> - <<if $activeSlave.belly >= 300000>> - tip $him over $his _belly <<if $activeSlave.bellyPreg >= 3000>>pregnancy<<else>>middle<</if>> - <<elseif $activeSlave.belly >= 5000>> - spread your legs to give $his <<if $activeSlave.bellyPreg >= 3000>>pregnancy<<else>>bloated middle<</if>> room as you pull $him onto your lap - <<else>> - pull $him down over your knee - <</if>> - <</if>> - and spank $his $activeSlave.skin buttocks until they're warm to the touch. It's not a sexual punishment, it's too painful for that; by the end, $activeSlave.slaveName has cried $himself out and is limp in your hands. You pull $him up to face you and give $him your instructions: from now on, $he can come to you and ask to <<if $PC.dick != 0>>blow you<<if $PC.vagina != -1>> and <</if>><</if>><<if $PC.vagina != -1>>perform cunnilingus on you<</if>>, and masturbate while $he does. $He nods through $his tears and flees. In an hour or so, though, $he finds you and asks to <<if $PC.vagina != -1>>give you oral<<else>>suck your cock<</if>>. When you pretend indifference, $he abjectly begs. Soon, $he's down on $his knees, crying a little with shame as $he masturbates furiously. - <<run seX($activeSlave, "oral", $PC, "penetrative", 5)>> - <<if ($activeSlave.fetish == "cumslut") && ($activeSlave.fetishKnown == 1)>> - <<set $activeSlave.fetishStrength += 4>> - @@.lightcoral;$His enjoyment of <<if $PC.dick == 0>>giving head<<else>>sucking cock<</if>> has increased.@@ - <<elseif random(1,100) > 50>> - <<set $activeSlave.fetish = "cumslut", $activeSlave.fetishKnown = 1, $activeSlave.fetishStrength = 65>> - Before $he realizes what's happening, @@.lightcoral;$he's getting aroused at the thought of <<if $PC.dick == 0>>giving head<<else>>sucking cock<</if>>.@@ - <</if>> - <</replace>> - <</link>> -<</if>> -<<if ($activeSlave.fetish != "boobs") || ($activeSlave.fetishKnown != 1) || ($activeSlave.fetishStrength <= 95)>> - <br> <<link "during nipple play">> - <<replace "#result">> - You - <<if $PC.belly >= 10000>> - <<if $activeSlave.belly >= 300000>> - tip $him over $his _belly <<if $activeSlave.bellyPreg >= 3000>>pregnancy<<else>>middle<</if>>, do your best to get close beside $him, and grope $him thoroughly, bringing $him to the painful edge of orgasm. Just when $he's about to tip over the edge, the stimulation stops and you flip $him onto $his back, lower your gravid body down to $his level and start playing with $his nipples. - <<elseif $activeSlave.belly >= 5000>> - order $him to bend over beside you so your pregnancy doesn't obstruct you as badly and grope $him thoroughly, bringing $him to the painful edge of orgasm. Just when $he's about to tip over the edge, the stimulation stops and you haul $him upright and start playing with $his nipples. - <<else>> - lean back, pull $him over your knee and under your gravid dome of a middle and grope $him thoroughly, bringing $him to the painful edge of orgasm. Just when $he's about to tip over the edge, the stimulation stops and you haul $him upright and start playing with $his nipples. - <</if>> - <<else>> - <<if $activeSlave.belly >= 300000>> - tip $him over $his _belly <<if $activeSlave.bellyPreg >= 3000>>pregnancy<<else>>middle<</if>> and grope $him thoroughly, bringing $him to the painful edge of orgasm. Just when $he's about to tip over the edge, the stimulation stops and you haul $him up into your lap, $his stomach spreading your legs, and start playing with $his nipples. - <<elseif $activeSlave.belly >= 5000>> - spread your legs to give $his <<if $activeSlave.bellyPreg >= 3000>>pregnancy<<else>>bloated middle<</if>> room as you pull $him onto your lap and grope $him thoroughly, bringing $him to the painful edge of orgasm. Just when $he's about to tip over the edge, the stimulation stops and you haul $him up into your lap and start playing with $his nipples. - <<else>> - pull $him down over your knee and grope $him thoroughly, bringing $him to the painful edge of orgasm. Just when $he's about to tip over the edge, the stimulation stops and you haul $him up into your lap and start playing with $his nipples. - <</if>> - <</if>> - $He writhes and sobs at the orgasm denial, since the nipple play is just barely enough to keep $him at a high level of arousal without giving relief. You switch back and forth until $he finally goes over into muscle-spasming climax during nipple stimulation alone. - <<run seX($activeSlave, "mammary", $PC, "penetrative")>> - <<if ($activeSlave.fetish == "boobs") && ($activeSlave.fetishKnown == 1)>> - <<set $activeSlave.fetishStrength += 4>> - @@.lightcoral;$His enjoyment of breast play has increased.@@ - <<elseif random(1,100) > 50>> - <<set $activeSlave.fetish = "boobs", $activeSlave.fetishKnown = 1, $activeSlave.fetishStrength = 65>> - Before $he realizes what's happening, @@.lightcoral;$he's getting aroused at every brush against $his breasts.@@ - <</if>> - <</replace>> - <</link>> -<</if>> -<<if (($activeSlave.fetish != "pregnancy") || ($activeSlave.fetishKnown != 1) || ($activeSlave.fetishStrength <= 95)) && $activeSlave.belly >= 5000>> - <br> <<link "while fondling $his belly">> - <<replace "#result">> - You - <<if $activeSlave.belly >= 300000>> - roll $him onto $his back - <<else>> - pull $him into a sitting position on your lap - <</if>> - and grope $his _belly <<if $activeSlave.bellyPreg >= 3000>>pregnancy<<else>>stomach<</if>>thoroughly, allowing $him to reach the painful edge of orgasm. You feel $his belly shudder as $he reaches climax under your ministrations. You tease $his <<if $activeSlave.belly >= 10001>>popped <</if>>navel as $he comes down from $his masturbation session. - <<if ($activeSlave.fetish == "pregnancy") && ($activeSlave.fetishKnown == 1)>> - <<set $activeSlave.fetishStrength += 4>> - @@.lightcoral;$His enjoyment of pregnancy has increased.@@ - <<elseif random(1,100) > 50>> - <<set $activeSlave.fetish = "pregnancy", $activeSlave.fetishKnown = 1, $activeSlave.fetishStrength = 65>> - Before $he realizes what's happening, @@.lightcoral;$he's getting aroused at <<if $activeSlave.pregKnown == 1>>every thought about $his pregnancy<<else>>the very thought of being pregnant<</if>>.@@ - <</if>> - <</replace>> - <</link>> -<</if>> -<<if canDoAnal($activeSlave)>> - <<if ($activeSlave.fetish != "buttslut") || ($activeSlave.fetishKnown != 1) || ($activeSlave.fetishStrength <= 95)>> - <br> <<link "when $he takes it up the ass">> - <<replace "#result">> - You - <<if $PC.belly >= 10000>> - <<if $activeSlave.belly >= 300000>> - tip $him over $his _belly <<if $activeSlave.bellyPreg >= 3000>>pregnancy<<else>>middle<</if>>, do your best to get close beside $him, - <<elseif $activeSlave.belly >= 5000>> - order $him to bend over beside you so your pregnancy doesn't obstruct you as badly - <<else>> - lean back, pull $him over your knee and under your gravid dome of a middle - <</if>> - <<else>> - <<if $activeSlave.belly >= 300000>> - tip $him over $his _belly <<if $activeSlave.bellyPreg >= 3000>>pregnancy<<else>>middle<</if>> - <<elseif $activeSlave.belly >= 5000>> - spread your legs to give $his <<if $activeSlave.bellyPreg >= 3000>>pregnancy<<else>>bloated middle<</if>> room as you pull $him onto your lap - <<else>> - pull $him down over your knee - <</if>> - <</if>> - and spank $his $activeSlave.skin buttocks until they're warm to the touch. It's not a sexual punishment, it's too painful for that; by the end, $activeSlave.slaveName has cried $himself out and is limp in your hands. You pull $him up to face you and give $him your instructions: from now on, $he can come to you and ask you to assrape $him, and masturbate while $he takes <<if $PC.dick == 0>>anal penetration<<else>>cock<</if>>. $He nods through $his tears and flees. In an hour or so, though, $he finds you and haltingly asks you to buttfuck $him. When you pretend indifference, $he offers you $his anus and abjectly begs you to stick <<if $PC.dick == 0>>a strap-on<<else>>your cock<</if>> up $his butt. Soon, $he's down on all fours, crying a little with mixed shame and anal pain as $he masturbates furiously. - <<= VCheck.Anal($activeSlave, 5)>> - <<if ($activeSlave.fetish == "buttslut") && ($activeSlave.fetishKnown == 1)>> - <<set $activeSlave.fetishStrength += 4>> - @@.lightcoral;$His enjoyment of anal has increased.@@ - <<elseif random(1,100) > 50>> - <<set $activeSlave.fetish = "buttslut", $activeSlave.fetishKnown = 1, $activeSlave.fetishStrength = 65>> - Before $he realizes what's happening, @@.lightcoral;$he's getting aroused at the thought of anal sex.@@ - <</if>> - <</replace>> - <</link>><<if ($activeSlave.anus == 0)>> //This option will take $his anal virginity//<</if>> - <</if>> -<</if>> -<<if ($activeSlave.fetish != "humiliation") || ($activeSlave.fetishKnown != 1) || ($activeSlave.fetishStrength <= 95)>> - <br> <<link "in public">> - <<replace "#result">> - You bring $him out <<if $club > 0>>to $clubName<<else>>onto the street<</if>> and secure $him upright with a set of vibrators attached to all of $his erogenous zones. There's a lot of them, and they're extremely powerful; when you test the setup, $he wriggles with the intensity of the stimulation, and is about to climax when you shut it down. Without telling $him, you slave the vibrators to a program originally designed for VIP security details. It uses the cameras scattered through the area to detect when passersby are looking at $him. The more eyes on $him, the stronger the vibrations. - <<if ($activeSlave.fetish == "humiliation") && ($activeSlave.fetishKnown == 1)>> - <<set $activeSlave.fetishStrength += 4>> - @@.lightcoral;$His enjoyment of humiliation has increased.@@ - <<elseif random(1,100) > 50>> - <<set $activeSlave.fetish = "humiliation", $activeSlave.fetishKnown = 1, $activeSlave.fetishStrength = 65>> - Before $he realizes what's happening, @@.lightcoral;$he's starting to long for humiliation.@@ - <</if>> - <</replace>> - <</link>> -<</if>> -<<if ($activeSlave.fetish != "submissive") || ($activeSlave.fetishKnown != 1) || ($activeSlave.fetishStrength <= 95)>> - <br> <<link "while submitting to a spanking">> - <<replace "#result">> - You tell $him that $he can get $himself off while $he's being spanked, and that's it: you don't tell $him to offer $his bottom, much less start spanking $him. $He doesn't understand for a long moment, but before long $he's begging abjectly for a spanking, and has $his buttocks presented, quivering with simultaneous arousal and fear of pain. The pain comes soon enough, with a delicious crack of palm on flesh <<if $activeSlave.voice == 0>>and a hoarse grunt, the most noise $he can make.<<else>>and a shriek of agony.<</if>> $He masturbates furiously, but you're an accomplished spanker, and you repeatedly cause $him just enough pain to prevent climax. Eventually $he gets off in part because of, rather than in spite of, the lengthy beating. - <<if ($activeSlave.fetish == "submissive") && ($activeSlave.fetishKnown == 1)>> - <<set $activeSlave.fetishStrength += 4>> - @@.lightcoral;$His enjoyment of submission has increased.@@ - <<elseif random(1,100) > 50>> - <<set $activeSlave.fetish = "submissive", $activeSlave.fetishKnown = 1, $activeSlave.fetishStrength = 65>> - Before $he realizes what's happening, @@.lightcoral;$he starts to associate submitting to you with getting off.@@ - <</if>> - <</replace>> - <</link>> -<</if>> -<<if ($activeSlave.fetish != "masochist") || ($activeSlave.fetishKnown != 1) || ($activeSlave.fetishStrength <= 95)>> - <br> <<link "while in pain">> - <<replace "#result">> - You order $him to - <<if ($activeSlave.heels == 1) && shoeHeelCategory($activeSlave) == 0>> - kneel - <<elseif shoeHeelCategory($activeSlave) > 1>> - teeter - <<else>> - stand - <</if>> - with $his arm<<if hasBothArms($activeSlave)>>s<</if>> over $his head and $his arm<<if hasBothLegs($activeSlave)>>s<</if>> splayed, and tell $him that if $he moves or resists $his punishment will begin again from the start. - <<if ($activeSlave.chastityVagina) || ($activeSlave.chastityPenis == 1)>> - $He was touching $his nipples and ass, so you flick and torture $his nipples and give $him a severe spanking. - <<elseif !canAchieveErection($activeSlave) && ($activeSlave.dick > 6)>> - $He was playing with $his oversized cock, so you kick and swat at the swollen monster, enjoying the way it spasms. - <<elseif ($activeSlave.dick > 0) && !canAchieveErection($activeSlave)>> - $He was touching $his limp dick and ass, so you slap and torture $his offending dick and give $him a severe spanking. - <<elseif ($activeSlave.vagina == -1) && ($activeSlave.dick == 0)>> - $He was desperately rubbing $his perineum and anus, the most sensitive parts $he has left, so you slap that part of $him repeatedly, enjoying the way it spasms. - <<elseif $activeSlave.vagina == -1 || $activeSlave.clit >= 3>> - $He was jacking it, so you force $him to get $himself hard for punishment and then deliver a series of agonizing slaps and flicks to $his offending member. - <<elseif $activeSlave.labia > 1>> - $His generous pussylips bear a sheen of incriminating moisture, so you slap and flick them, causing $him intense agony. - <<else>> - You deliver a series of agonizing slaps to $his mons. - <</if>> - You have to start over twice. By the end, $he's managed to orgasm to all the stimulation, but $he's crying and desperately promising never to touch $himself again without your permission. $His submission to you @@.hotpink;has increased.@@ - <<set $activeSlave.devotion += 4>> - <<if ($activeSlave.fetish == "masochist") && ($activeSlave.fetishKnown == 1)>> - <<set $activeSlave.fetishStrength += 4>> - @@.lightcoral;$His enjoyment of pain has increased.@@ - <<elseif random(1,100) > 50>> - <<set $activeSlave.fetish = "masochist", $activeSlave.fetishKnown = 1, $activeSlave.fetishStrength = 65>> - Before $he realizes what's happening, @@.lightcoral;$he's getting aroused at the thought of <<= getWrittenTitle($activeSlave)>> beating $him.@@ - <</if>> - <</replace>> - <</link>> -<</if>> - <<case "hates oral">> <<link "Let $him earn a break for $his throat">> @@ -16487,209 +16046,6 @@ $He cranes $his neck, glancing over $his shoulder to give you a pleading look. <</link>> <</if>> -<<case "modest clothes">> - -<<link "No">> - <<replace "#result">> - You tell $him no. $He's a good enough slave that making a simple request and having you return a straightforward negative without punishment @@.mediumaquamarine;makes $him just slightly more trusting.@@ It's nice to be allowed to ask things. - <<set $activeSlave.trust += 2>> - <</replace>> -<</link>> -<br><<link "Show $him how much you like $his usual outfit">> - <<replace "#art-frame">> - /* 000-250-006 */ - <<if $seeImages == 1>> - <<if $imageChoice == 1>> - <div class="imageRef lrgVector"><div class="mask"> </div><<SlaveArt $activeSlave 3 0>></div> - <<else>> - <div class="imageRef lrgRender"><div class="mask"> </div><<SlaveArt $activeSlave 3 0>></div> - <</if>> - <</if>> - /* 000-250-006 */ - <</replace>> - <<replace "#result">> - You tell $him to go get dressed as usual. $His face falls a little, but there was no condemnation in your tone, and $he hurries off, - <<if $activeSlave.dick > 6>> - monstrous cock dangling. - <<elseif $activeSlave.balls > 4>> - big balls dangling. - <<elseif $activeSlave.bellyFluid >= 5000 || $activeSlave.weight > 95>> - big belly jiggling. - <<elseif $activeSlave.belly >= 5000>> - as fast as $his swollen belly will allow. - <<elseif ($activeSlave.boobsImplant/$activeSlave.boobs) >= .60>> - fake tits bouncing. - <<elseif $activeSlave.butt > 4>> - $his big booty jiggling. - <<elseif $activeSlave.boobs > 2000>> - udders jiggling. - <<else>> - giving you a nice view of $his naked rear. - <</if>> - $He returns quickly, in $his proper - <<switch $activeSlave.clothes>> - <<case "a long qipao" "a slutty qipao">> - qipao. - <<case "a penitent nuns habit">> - habit. - <<case "a slave gown" "a ball gown">> - gown. - <<case "a comfortable bodysuit">> - bodysuit. - <<case "a schoolgirl outfit">> - school clothes. - <<case "a nice maid outfit">> - maid outfit. - <<case "a slutty maid outfit">> - skimpy maid outfit. - <<case "a biyelgee costume" "a dirndl" "a halter top dress" "a mini dress" "a maternity dress">> - dress. - <<case "a military uniform" "a mounty outfit" "a red army uniform" "a schutzstaffel uniform" "a slutty schutzstaffel uniform">> - uniform. - <<case "spats and a tank top">> - spats. - <<case "a burkini" "a monokini">> - swimsuit. - <<case "a chattel habit" "a fallen nuns habit">> - slutty habit. - <<case "a succubus outfit">> - succubus getup. - <<case "a hijab and blouse" "conservative clothing">> - conservative clothes. - <<default>> - <<= App.Data.clothes.get($activeSlave.clothes).name.toLowerCase()>> - <</switch>> - You tell $him that you like how $he looks, and that $he's pretty. $He wasn't expecting such a blunt compliment, and <<if canSee($activeSlave)>>$his <<= App.Desc.eyesColor($activeSlave)>> flick down to<<else>>$he faces<</if>> the ground for a moment as $he blushes. "T-thank you, <<Master>>," $he stutters. - <br><br> - You add that $he looks so good that $he had better take $his nice clean - <<switch $activeSlave.clothes>> - <<case "a long qipao" "a slutty qipao">> - qipao - <<case "a penitent nuns habit">> - habit - <<case "a slave gown" "a ball gown">> - gown - <<case "a comfortable bodysuit">> - bodysuit - <<case "a nice nurse outfit">> - nurse outfit - <<case "a schoolgirl outfit">> - school clothes - <<case "a nice maid outfit">> - maid outfit - <<case "a slutty maid outfit">> - skimpy maid outfit - <<case "a biyelgee costume" "a dirndl" "a halter top dress" "a mini dress" "a maternity dress">> - dress - <<case "a military uniform" "a mounty outfit" "a red army uniform" "a schutzstaffel uniform" "a slutty schutzstaffel uniform">> - uniform - <<case "spats and a tank top">> - spats - <<case "a burkini" "a monokini">> - swimsuit - <<case "a chattel habit" "a fallen nuns habit">> - slutty habit - <<case "a succubus outfit">> - succubus getup - <<case "a hijab and blouse" "conservative clothing">> - conservative clothes - <<default>> - <<= App.Data.clothes.get($activeSlave.clothes).name.toLowerCase()>> - <</switch>> - off again, because - <<if canDoVaginal($activeSlave) && $activeSlave.vagina != 0>> - you're going to <<if $PC.dick>>fuck<<else>>trib<</if>> $his senseless. - <<= VCheck.Vaginal($activeSlave, 1)>> - <<elseif canDoAnal($activeSlave) && $activeSlave.anus != 0>> - you're going to fuck $his butt<<if $activeSlave.balls>> until $he cums<</if>>. - <<= VCheck.Anal($activeSlave, 1)>> - <<else>> - $he's going to <<if $PC.dick>>suck your dick until you cover $him in cum<<else>>eat you out until $he's got your pussyjuice running down $his chin<</if>>. - <<run seX($activeSlave, "oral", $PC, "penetrative")>> - <</if>> - $He giggles at the sudden lewdness, and quickly strips naked again, complimented and @@.hotpink;eager to be used.@@ - <<set $activeSlave.devotion += 5>> - <</replace>> -<</link>> -<br><<link "Put $him in a string bikini">> - <<set _clothesTemp = $activeSlave.clothes, $activeSlave.clothes = "a string bikini">> - <<replace "#art-frame">> - /* 000-250-006 */ - <<if $seeImages == 1>> - <<if $imageChoice == 1>> - <div class="imageRef lrgVector"><div class="mask"> </div><<SlaveArt $activeSlave 3 0>></div> - <<else>> - <div class="imageRef lrgRender"><div class="mask"> </div><<SlaveArt $activeSlave 3 0>></div> - <</if>> - <</if>> - /* 000-250-006 */ - <</replace>> - <<set $activeSlave.clothes = _clothesTemp>> - <<replace "#result">> - You tell $him that the wardrobe's sorting system will present $him with a new outfit, just for today. $He's to go try it on and come right back, to see how it fits. "Thank<<s>>, <<Master>>!" $he <<say>>s brightly, and hurries off to see what's in store for $him. $He might be a slave and a $desc but <<= $girl>>s everywhere love trying on new clothes. $He makes an entrance when $he comes back, spinning around to show off. $He's wearing the briefest possible string bikini. The top, rather than having patches of material to cover $his nipples, forms a string triangle around them, framing them but not covering them. The bottom is a single string in front, <<if $activeSlave.dick>>which looks rather sad and alone, pushed aside by $his dick as it is<<elseif $activeSlave.labia>>and it's embraced completely by $his generous pussylips<<else>>and it threatens to disappear inside $his pussylips<</if>>. "Thi<<s>> feel<<s>> <<s>>o hot, <<Master>>," $he <<say>>s, and - <<if $activeSlave.fetishKnown && $activeSlave.fetish == "humiliation">> - blushes cutely. $He looks up at you, <<if canSee($activeSlave)>>sees<<else>>feels<</if>> the way you're staring at $him, and hangs $his head, blushing even harder. - <<elseif $activeSlave.fetishKnown && $activeSlave.fetish == "buttslut">> - turns around again, bending a little and cocking $his hips to show off the way the string between $his buttocks totally fails to conceal $his <<if $activeSlave.anus > 2>>huge soft asspussy<<elseif $activeSlave.anus > 1>>nice butthole<<else>>tight little anus<</if>>. - <<elseif $activeSlave.fetishKnown && $activeSlave.fetish == "boobs">> - bounces $his - <<if $activeSlave.boobsImplant>> - fake tits. - <<elseif $activeSlave.boobs > 8000>> - earth-shattering tits. - <<elseif $activeSlave.boobs > 2000>> - huge boobs. - <<elseif $activeSlave.boobs > 400>> - boobs. - <<else>> - petite chest. - <</if>> - Giggling, $he bounces harder, and $his nipples escape from $his top, such as it is. - <<elseif $activeSlave.fetishKnown && $activeSlave.fetish == "pregnancy" && $activeSlave.bellyPreg >= 1500>> - and attempts to pull the strings over the front of $his belly. Without delay, they slide right back to the sides of the _belly dome, eliciting a giggle from the preggo slut. - <<elseif $activeSlave.assignment == "whore" || $activeSlave.assignment == "serve the public">> - sneaks a hand under the string around $his waist, tugging $his bottom up <<if $activeSlave.vagina != -1>>until the string between $his legs is pulled up into the entrance of $his womanhood<<else>>and turning sideways to suggest $his ass<</if>>. "Guy<<s>>'ll <<if $activeSlave.assignment == "whore">>pay money for<<else>>line up to fuck<</if>> thi<<s>>," $he giggles. - <<else>> - bounces a little, smiling. "I'm ba<<s>>ically naked," $he giggles. "Today i<<s>> going to be fun. The other $girl<<s>>'ll be jealou<<s>> you wanted me to look <<s>>o <<s>>lutty. Love you, <<Master>>." - <</if>> - $He's happy you indulged $him, and @@.mediumaquamarine;satisfied that you think $he's cute@@ enough to have around (practically) nude. - <<set $activeSlave.trust += 5>> - <</replace>> -<</link>> -<br><<link "Force uncomfortable straps on $him">> - <<set _clothesTemp = $activeSlave.clothes, $activeSlave.clothes = "uncomfortable straps">> - <<replace "#art-frame">> - /* 000-250-006 */ - <<if $seeImages == 1>> - <<if $imageChoice == 1>> - <div class="imageRef lrgVector"><div class="mask"> </div><<SlaveArt $activeSlave 3 0>></div> - <<else>> - <div class="imageRef lrgRender"><div class="mask"> </div><<SlaveArt $activeSlave 3 0>></div> - <</if>> - <</if>> - /* 000-250-006 */ - <</replace>> - <<set $activeSlave.clothes = _clothesTemp>> - <<replace "#result">> - You tell $him that the wardrobe's sorting system will present $him with a new outfit, just for today. $He's to go try it on and come right back, to see how it fits. "Thanks, <<Master>>!" $he <<say>>s brightly, and hurries off to see what's in store for $him. $He might be a slave and a $desc but <<= $girl>>s everywhere love trying on new clothes. $He's wrong to be so enthusiastic. $He comes obediently back, wearing a set of cruelly uncomfortable leather straps in the general shape of a bikini, but much tighter and more restrictive. It isn't at all what $he was expecting, but $he did $his best to obey. $He's @@.gold;tightened $his own straps down@@ until they're just short of cutting off circulation, in an obvious effort to please you. You ask $him how $he likes $his outfit. "It'<<s>> ni<<c>>e, <<Master>>," $he <<say>>s, but $he sounds a little sad. - <<if $activeSlave.fetishKnown && $activeSlave.fetish == "humiliation">> - "I'm ju<<s>>t a worthle<<ss>> humiliation <<s>>lut. I love having <<s>>teel ring<<s>> around my hole<<s>> like thi<<s>>," $he adds. - <<elseif $activeSlave.fetishKnown && $activeSlave.fetish == "buttslut">> - $He turns to show you $his asshole, framed by a steel ring that spreads $his buttocks to keep it nice and defenseless. "I know my backpu<<ss>>y'<<s>> the be<<s>>t thing about me," $he adds. - <<elseif $activeSlave.fetishKnown && $activeSlave.fetish == "boobs">> - $He does $his best to thrust out $his chest, making the straps creak. "I know I'm, I'm ju<<s>>t, ju<<s>>t a pair of boob<<s>>," $he adds. - <<elseif $activeSlave.fetishKnown && $activeSlave.fetish == "pregnancy" && $activeSlave.bellyPreg >= 1500>> - $He does $his best to thrust out $his _belly belly, making the straps creak ominously. "I know I'm, I'm ju<<s>>t, ju<<s>>t a baby maker," $he adds. - <<elseif $activeSlave.assignment == "whore" || $activeSlave.assignment == "serve the public">> - $He hangs $his head. "I feel like a worthle<<ss>> <<if $activeSlave.assignment == "whore">>whore<<else>>bitch<</if>>," $he adds. "Gue<<ss>> I am." - <<else>> - $He indicates the steel rings that frame $his holes and keep them defenseless. "I know I'm ju<<s>>t a collection of fuckhole<<s>>," $he adds. - <</if>> - $He sounds like $he's trying to convince $himself, but $his @@.hotpink;abasement us not feigned.@@ - <<set $activeSlave.devotion += 5, $activeSlave.trust -= 5>> - <</replace>> -<</link>> - <<case "hyperpreg stuck">> <<link "Abuse $him">> @@ -16875,7 +16231,7 @@ $He cranes $his neck, glancing over $his shoulder to give you a pleading look. <br>ERROR: bad RESS event $RESSevent <</switch>> -<<if $cheatMode == 1>> +<<if $debugMode > 0 && $debugModeEventSelection > 0>> <br><br>DEBUG: [[Go back to Nonrandom Event|Nonrandom Event][$activeSlave = 0, $eventSlave = 0]] <</if>> diff --git a/src/uncategorized/RESSTR.tw b/src/uncategorized/RESSTR.tw index 7cc46776a8407e6d208a6eed764affc1295373b9..44fb58cf01f85fda3c04f2c107fd734f599e8e5d 100644 --- a/src/uncategorized/RESSTR.tw +++ b/src/uncategorized/RESSTR.tw @@ -24,7 +24,7 @@ <<if Array.isArray($RESSTRevent)>> <<set $activeSlave = $eventSlave>> - <<if $cheatMode == 1>> + <<if $debugMode > 0 && $debugModeEventSelection > 0>> <<set $nextButton = "Back", $nextLink = "Nonrandom Event", $returnTo = "Nonrandom Event">> /* if user just clicks spacebar */ ''A random event would have been selected from the following:'' <br> @@ -68,7 +68,7 @@ <br>ERROR: bad RESSTR event $RESSTRevent <</switch>> - <<if $cheatMode == 1>> + <<if $debugMode > 0 && $debugModeEventSelection > 0>> <br><br>DEBUG: [[Go back to Nonrandom Event|Nonrandom Event][$activeSlave = 0, $eventSlave = 0]] <</if>> diff --git a/src/uncategorized/randomIndividualEvent.tw b/src/uncategorized/randomIndividualEvent.tw index fca571696d41b738d6797fa86c10443aa5f48bae..30c5424c9e4f1751959225506830d6759e377273 100644 --- a/src/uncategorized/randomIndividualEvent.tw +++ b/src/uncategorized/randomIndividualEvent.tw @@ -1,7 +1,7 @@ :: Random Individual Event [nobr] <<if $eventSlave == 0>> - <<if $cheatMode == 1>> + <<if ($debugMode > 0 && $debugModeEventSelection > 0)>> <<set $nextButton = "Refresh", $nextLink = "Random Individual Event", $returnTo = "Random Individual Event", $encyclopedia = "Random Events">> <<link "Skip week-end events" "Next Week">><</link>> @@ -31,7 +31,7 @@ /* EVENT RANDOMIZATION */ <<set $events = populateEventArray().concat(App.Events.getIndividualEventsPassageList($eventSlave))>> - <<if $cheatMode == 1>> + <<if ($debugMode > 0 && $debugModeEventSelection > 0)>> <<goto "random event select">> <<else>> <<goto "random event roll">> diff --git a/src/uncategorized/randomNonindividualEvent.tw b/src/uncategorized/randomNonindividualEvent.tw index dc7ae13b84ab1b5ea909f20ce4757215dae5f6f5..0094702861d83e6a19c8c644e17ccbc4375c7335 100644 --- a/src/uncategorized/randomNonindividualEvent.tw +++ b/src/uncategorized/randomNonindividualEvent.tw @@ -2,7 +2,7 @@ <<if $eventSlave == 0>> <<set $eventSlave = $slaves.random()>> - <<if $cheatMode == 1>> + <<if ($debugMode > 0) && ($debugModeEventSelection > 0)>> <<set $nextButton = "Refresh", $nextLink = "Random Nonindividual Event", $returnTo = "Random Nonindividual Event", $encyclopedia = "Random Events">> <<link "Skip week-end events" "Next Week">><</link>> @@ -19,9 +19,11 @@ <<goto "Random Nonindividual Event">> <</if>> <<else>> - <<silently>> + /* <<silently>> */ /* initialize event lists as arrays [], not objects {} */ <<set $events = [], $RecETSevent = [], $REFIevent = [], $PESSevent = [], $PETSevent = [], $REFSevent = [], $activeSlave = 0, _recruitEvents = []>> + /* FIXME: almost none of the events that use this condition do so correctly. 50 || 25 is 50, not 25. */ + <<set _oneIfDebug = ($debugMode > 0 && $debugModeEventSelection > 0) ? 1 : 0>> <<if $week >= 10>> <<set $events.push("P associates public slut")>> @@ -173,11 +175,6 @@ <<if App.Entity.facilities.arcade.employeesIDs().size > 3>> <<set $events.push("RE busy arcade")>> <</if>> - <<if App.Entity.facilities.masterSuite.employeesIDs().size > 3>> - <<if $ConcubineID != 0>> - <<set $events.push("RE busy master suite")>> - <</if>> - <</if>> /* Position Events */ @@ -313,25 +310,25 @@ <<if $seePreg != 0>> <<if $seeHyperPreg == 1>> - <<if $arcologies[0].FSRestart == "unset" && ((random(1,100) <= 5) || $cheatMode)>> + <<if $arcologies[0].FSRestart == "unset" && ((random(1,100) <= 5) || ($debugMode > 0 && $debugModeEventSelection > 0))>> <<set $RecETSevent.push("desperate broodmother")>> <</if>> <</if>> <</if>> - <<if (($rep/400) > random(1,100)) || $cheatMode>> + <<if (($rep/400) > random(1,100)) || ($debugMode > 0 && $debugModeEventSelection > 0)>> <<set $RecETSevent.push("identical pair")>> <</if>> - <<if (($rep/400) > random(1,100)) || $cheatMode>> + <<if (($rep/400) > random(1,100)) || ($debugMode > 0 && $debugModeEventSelection > 0)>> <<set $RecETSevent.push("posh mother daughter")>> <</if>> <<if $seeIncest != 0>> - <<if (($rep/400) > random(1,100)) || $cheatMode>> + <<if (($rep/400) > random(1,100)) || ($debugMode > 0 && $debugModeEventSelection > 0)>> <<set $RecETSevent.push("incest sister sister")>> <</if>> - <<if (($rep/400) > random(1,100)) || $cheatMode>> + <<if (($rep/400) > random(1,100)) || ($debugMode > 0 && $debugModeEventSelection > 0)>> <<set $RecETSevent.push("incest twin sister")>> <</if>> - <<if (($rep/400) > random(1,100)) || $cheatMode>> + <<if (($rep/400) > random(1,100)) || ($debugMode > 0 && $debugModeEventSelection > 0)>> <<set $RecETSevent.push("incest mother daughter")>> <</if>> <</if>> @@ -346,37 +343,37 @@ <<if (_S.HeadGirl && _S.HeadGirl.devotion > 50)>> <<set $RecETSevent.push("mismatched pair")>> <</if>> - <<if ($rep/400) > (random(1,100) || $cheatMode)>> + <<if ($rep/400) > (random(1,100) || _oneIfDebug)>> <<set $RecETSevent.push("matched pair")>> <</if>> <<if $seeIncest != 0>> <<if $seePreg != 0>> - <<if ($rep/400) > (random(1,100) || $cheatMode) && $arcologies[0].FSRestart == "unset">> + <<if ($rep/400) > (random(1,100) || _oneIfDebug) && $arcologies[0].FSRestart == "unset">> <<set $RecETSevent.push("identical herm pair")>> <</if>> - <<if ($rep/400) > (random(1,100) || $cheatMode) && $arcologies[0].FSRestart == "unset">> + <<if ($rep/400) > (random(1,100) || _oneIfDebug) && $arcologies[0].FSRestart == "unset">> <<set $RecETSevent.push("incest mother son")>> <</if>> - <<if ($rep/400) > (random(1,100) || $cheatMode) && $arcologies[0].FSRestart == "unset">> + <<if ($rep/400) > (random(1,100) || _oneIfDebug) && $arcologies[0].FSRestart == "unset">> <<set $RecETSevent.push("incest father daughter")>> <</if>> - <<if ($rep/400) > (random(1,100) || $cheatMode)>> + <<if ($rep/400) > (random(1,100) || _oneIfDebug)>> <<set $RecETSevent.push("incest brother sister")>> <</if>> <</if>> - <<if ($rep/400) > (random(1,100) || $cheatMode)>> + <<if ($rep/400) > (random(1,100) || _oneIfDebug)>> <<set $RecETSevent.push("incest twins mixed")>> <</if>> <</if>> <</if>> <<if $seeIncest != 0>> - <<if ($rep/400) > (random(1,100) || $cheatMode)>> + <<if ($rep/400) > (random(1,100) || _oneIfDebug)>> <<set $RecETSevent.push("incest brother brother")>> <</if>> - <<if ($rep/400) > (random(1,100) || $cheatMode)>> + <<if ($rep/400) > (random(1,100) || _oneIfDebug)>> <<set $RecETSevent.push("incest twin brother")>> <</if>> - <<if ($rep/400) > (random(1,100) || $cheatMode)>> + <<if ($rep/400) > (random(1,100) || _oneIfDebug)>> <<set $RecETSevent.push("incest father son")>> <</if>> <</if>> @@ -408,224 +405,224 @@ <<set $malefactor.push("passfail")>> <</if>> <<set $malefactor = $malefactor.random()>> - <<if ($rep/150) > (random(1,100) || $cheatMode)>> + <<if ($rep/150) > (random(1,100) || _oneIfDebug)>> <<set _recruitEvents.push("RE malefactor")>> <</if>> <</if>> - <<if ($rep/400) > (random(1,100) || $cheatMode)>> + <<if ($rep/400) > (random(1,100) || _oneIfDebug)>> <<set $RecETSevent.push("addict mother daughter")>> <</if>> <<if $FSAnnounced == 1>> <<set $FSAcquisitionEvents = []>> - <<if $arcologies[0].FSSupremacist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSSupremacist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Supremacist")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSSubjugationist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSSubjugationist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Subjugationist")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSGenderRadicalist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSGenderRadicalist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Gender Radicalist")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSRepopulationFocus > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSRepopulationFocus > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Repopulation Efforts")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSRestart > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSRestart > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Eugenics")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> <<if $seePreg != 0>> - <<if $arcologies[0].FSGenderFundamentalist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSGenderFundamentalist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Gender Fundamentalist")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> <</if>> - <<if $arcologies[0].FSPaternalist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSPaternalist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Paternalist")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSDegradationist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSDegradationist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Degradationist")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSIntellectualDependency > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSIntellectualDependency > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Intellectual Dependency")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSSlaveProfessionalism > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSSlaveProfessionalism > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Slave Professionalism")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSBodyPurist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSBodyPurist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Body Purist")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSTransformationFetishist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSTransformationFetishist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Transformation Fetishist")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSPetiteAdmiration > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSPetiteAdmiration > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Petite Admiration")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSStatuesqueGlorification > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSStatuesqueGlorification > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Statuesque Glorification")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSYouthPreferentialist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSYouthPreferentialist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Youth Preferentialist")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSMaturityPreferentialist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSMaturityPreferentialist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Maturity Preferentialist")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSSlimnessEnthusiast > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSSlimnessEnthusiast > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Slimness Enthusiast")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSAssetExpansionist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSAssetExpansionist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Asset Expansionist")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> <<if $seePreg != 0>> - <<if $arcologies[0].FSPastoralist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSPastoralist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Pastoralist")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> <</if>> - <<if $arcologies[0].FSPhysicalIdealist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSPhysicalIdealist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Physical Idealist")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSHedonisticDecadence > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSHedonisticDecadence > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Hedonistic Decadence")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSChattelReligionist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSChattelReligionist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Chattel Religionist")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSSupremacist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSSupremacist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Supremacist Two")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSSubjugationist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSSubjugationist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Subjugationist Two")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSGenderRadicalist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSGenderRadicalist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Gender Radicalist Two")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> <<if $seePreg != 0>> - <<if $arcologies[0].FSGenderFundamentalist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSGenderFundamentalist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Gender Fundamentalist Two")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> <</if>> - <<if $arcologies[0].FSPaternalist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSPaternalist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Paternalist Two")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSDegradationist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSDegradationist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Degradationist Two")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSIntellectualDependency > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSIntellectualDependency > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Intellectual Dependency Two")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSSlaveProfessionalism > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSSlaveProfessionalism > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Slave Professionalism Two")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSBodyPurist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSBodyPurist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Body Purist Two")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSTransformationFetishist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSTransformationFetishist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Transformation Fetishist Two")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSPetiteAdmiration > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSPetiteAdmiration > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Petite Admiration Two")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSStatuesqueGlorification > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSStatuesqueGlorification > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Statuesque Glorification Two")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSYouthPreferentialist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSYouthPreferentialist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Youth Preferentialist Two")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSMaturityPreferentialist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSMaturityPreferentialist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Maturity Preferentialist Two")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSSlimnessEnthusiast > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSSlimnessEnthusiast > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Slimness Enthusiast Two")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSAssetExpansionist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSAssetExpansionist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Asset Expansionist Two")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSPastoralist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSPastoralist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Pastoralist Two")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSPhysicalIdealist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSPhysicalIdealist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Physical Idealist Two")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSHedonisticDecadence > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSHedonisticDecadence > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Hedonistic Decadence Two")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSChattelReligionist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSChattelReligionist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Chattel Religionist Two")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSRepopulationFocus > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSRepopulationFocus > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Repopulation Efforts Two")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSRestart > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSRestart > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Eugenics Two")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSRomanRevivalist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSRomanRevivalist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Roman Revivalist")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSNeoImperialist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSNeoImperialist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Neo Imperialist")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSAztecRevivalist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSAztecRevivalist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Aztec Revivalist")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSEdoRevivalist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSEdoRevivalist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Edo Revivalist")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSArabianRevivalist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSArabianRevivalist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Arabian Revivalist")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSChineseRevivalist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSChineseRevivalist > (random(1,100) || _oneIfDebug)>> <<set $FSAcquisitionEvents.push("Chinese Revivalist")>> <<set _recruitEvents.push("RE FS acquisition")>> <</if>> - <<if $arcologies[0].FSEgyptianRevivalist > (random(1,100) || $cheatMode)>> + <<if $arcologies[0].FSEgyptianRevivalist > (random(1,100) || _oneIfDebug)>> <<set _recruitEvents.push("RE FSEgyptianRevivalist acquisition")>> <</if>> <<set $FSNonconformistEvents = []>> @@ -1016,7 +1013,7 @@ <</if>> <</if>> - <<if minimumSlaveCost() > 3000 && (random(1,2) == 1 || $cheatMode)>> + <<if minimumSlaveCost() > 3000 && (random(1,2) == 1 || ($debugMode > 0 && $debugModeEventSelection > 0))>> <<set $events.push("RE shipping container")>> <</if>> @@ -1025,14 +1022,14 @@ <</if>> <<if $mercenaries > 0>> - <<if (random(1,2) == 1 || $cheatMode)>> + <<if (random(1,2) == 1 || ($debugMode > 0 && $debugModeEventSelection > 0))>> <<set $events.push("RE AWOL")>> <<else>> <<set $events.push("RE Poker Night")>> <</if>> <</if>> - <<if ($arcologies[0].prosperity >= 100 && ($rep > random(1,30000)) || $cheatMode)>> + <<if ($arcologies[0].prosperity >= 100 && ($rep > random(1,30000)) || _oneIfDebug)>> <<set _milfSlaves = $slaves.filter(function(s) { return s.devotion > 20 && canTalk(s) && canWalk(s) && (s.assignment == "serve the public" || s.assignment == "serve in the club"); })>> <<if _milfSlaves.length > 0>> <<set $events.push("RE milf tourist")>> @@ -1051,7 +1048,7 @@ <<else>> <<set $events.push("RE citizen hookup")>> <</if>> - <<if ($rep-10000 > random(1,10000) || $cheatMode)>> + <<if ($rep-10000 > random(1,10000) || ($debugMode > 0 && $debugModeEventSelection > 0))>> <<if ($PC.vagina > 0 && $PC.boobs >= 300 && $PC.title == 0) && (random(0,99) < $seeDicks)>> <<set $events.push("RE male arcology owner")>> <<else>> @@ -1074,43 +1071,43 @@ /* FUTURE SOCIETY EVENTS */ - <<if $arcologies[0].FSBodyPurist > (random(25,100) || $cheatMode+24)>> + <<if $arcologies[0].FSBodyPurist > (random(25,100) || _oneIfDebug+24)>> <<set $REFSevent.push("body purism encounter")>> <</if>> - <<if $arcologies[0].FSTransformationFetishist > (random(25,100) || $cheatMode+24)>> + <<if $arcologies[0].FSTransformationFetishist > (random(25,100) || _oneIfDebug+24)>> <<set $REFSevent.push("transformation fetishism encounter")>> <</if>> - <<if $arcologies[0].FSYouthPreferentialist > (random(25,100) || $cheatMode+24)>> + <<if $arcologies[0].FSYouthPreferentialist > (random(25,100) || _oneIfDebug+24)>> <<set $REFSevent.push("youth preferentialist encounter")>> <</if>> - <<if $arcologies[0].FSMaturityPreferentialist > (random(25,100) || $cheatMode+24)>> + <<if $arcologies[0].FSMaturityPreferentialist > (random(25,100) || _oneIfDebug+24)>> <<set $REFSevent.push("maturity preferentialist encounter")>> <</if>> - <<if $arcologies[0].FSPastoralist > (random(25,100) || $cheatMode+24)>> + <<if $arcologies[0].FSPastoralist > (random(25,100) || _oneIfDebug+24)>> <<set $REFSevent.push("pastoralist encounter")>> <</if>> - <<if $arcologies[0].FSPhysicalIdealist > (random(25,100) || $cheatMode+24)>> + <<if $arcologies[0].FSPhysicalIdealist > (random(25,100) || _oneIfDebug+24)>> <<set $REFSevent.push("physical idealist encounter")>> <</if>> - <<if $arcologies[0].FSPaternalist > (random(25,100) || $cheatMode+24)>> + <<if $arcologies[0].FSPaternalist > (random(25,100) || _oneIfDebug+24)>> <<set $REFSevent.push("paternalist encounter")>> <</if>> - <<if $arcologies[0].FSDegradationist > (random(25,100) || $cheatMode+24)>> + <<if $arcologies[0].FSDegradationist > (random(25,100) || _oneIfDebug+24)>> <<set $REFSevent.push("degradationist encounter")>> <</if>> - <<if $arcologies[0].FSNeoImperialist > (random(25,100) || $cheatMode+24) && $arcologies[0].FSNeoImperialistLaw1 == 1>> + <<if $arcologies[0].FSNeoImperialist > (random(25,100) || _oneIfDebug+24) && $arcologies[0].FSNeoImperialistLaw1 == 1>> <<set $REFSevent.push("knightly duel")>> <</if>> - <<if $arcologies[0].FSNeoImperialist > (random(25,100) || $cheatMode+24) && $arcologies[0].FSNeoImperialistLaw2 == 1 && $newBaron == 1>> + <<if $arcologies[0].FSNeoImperialist > (random(25,100) || _oneIfDebug+24) && $arcologies[0].FSNeoImperialistLaw2 == 1 && $newBaron == 1>> <<set $REFSevent.push("dead baron")>> <</if>> - <<if $arcologies[0].FSNeoImperialist > (random(25,100) || $cheatMode+24) && $arcologies[0].FSNeoImperialistLaw2 == 1>> + <<if $arcologies[0].FSNeoImperialist > (random(25,100) || _oneIfDebug+24) && $arcologies[0].FSNeoImperialistLaw2 == 1>> <<set $REFSevent.push("baron demand")>> <</if>> - <<if $arcologies[0].FSNeoImperialist > (random(25,100) || $cheatMode+24) && $arcologies[0].FSNeoImperialistLaw2 == 1 && $arcologies[0].FSNeoImperialistLaw1 == 1 && $policies.regularParties == 1>> + <<if $arcologies[0].FSNeoImperialist > (random(25,100) || _oneIfDebug+24) && $arcologies[0].FSNeoImperialistLaw2 == 1 && $arcologies[0].FSNeoImperialistLaw1 == 1 && $policies.regularParties == 1>> <<set $REFSevent.push("feast")>> <</if>> - <<if $arcologies[0].FSNeoImperialist > (random(25,100) || $cheatMode+24)>> + <<if $arcologies[0].FSNeoImperialist > (random(25,100) || _oneIfDebug+24)>> <<set $REFSevent.push("warhound")>> <</if>> @@ -1137,11 +1134,11 @@ <<set _recruitEvents.length = _maxRecruitNumber>> <</if>> <<set $events = $events.concat(_recruitEvents).concat(App.Events.getNonindividualEventsPassageList())>> - <<if $cheatMode == 1>> + <<if $debugMode > 0 && $debugModeEventSelection > 0>> <<goto "random event select">> <<else>> <<goto "random event roll">> <</if>> - <</silently>> + /* <</silently>>*/ <</if>> /* CLOSES SLAVE SELECT */ diff --git a/src/uncategorized/reBusyMasterSuite.tw b/src/uncategorized/reBusyMasterSuite.tw deleted file mode 100644 index 7d91c0160255d6c25ea971e34c6573324226efee..0000000000000000000000000000000000000000 --- a/src/uncategorized/reBusyMasterSuite.tw +++ /dev/null @@ -1,204 +0,0 @@ -:: RE busy master suite [nobr] - -<<set $nextButton = "Continue", $nextLink = "RIE Eligibility Check">> - -/* figure out how each slave will be participating in the train */ -<<set _msSlaves = $slaves.filter((s) => s.fuckdoll === 0 && s.assignment === "serve in the master suite") - .map((s) => { - let options = []; - if (canDoAnal(s) && s.anus > 0) { - options.push("anal"); - } - if (canDoVaginal(s) && s.vagina > 0) { - options.push("vaginal"); - } - if (options.length === 0) { - options.push("none"); - } - return {slave: s, mode: options.pluck()}; - });>> -<<set _bottomSlave = _msSlaves.find((s) => s.mode !== "none").slave>> - -/* insufficient participants */ -<<set _participantCount = _msSlaves.filter((s) => s.mode !== "none").length>> /* SC <<if>> parser is stupid and can't deal with lambdas, so stuff it in a temporary */ -<<if _participantCount < 3>> - <<goto "RIE Eligibility Check">> -<<else>> - -<<setLocalPronouns _S.Concubine>> -<<setLocalPronouns _bottomSlave 2>> - -<p>You have an extended meeting with a prominent citizen planned, from the start of business in the morning until you're done. That's likely to be in the late evening, since he's probably going to get into technical business proposals, and _S.Concubine.slaveName knows it. $He is surprised, therefore, when a minor business emergency calls your would-be interlocutor away, canceling the meeting and sending you home hours earlier than you'd planned. $He <<if canTalk(_S.Concubine)>>giggles helplessly<<else>>signs humorously<</if>> at the surprise when you walk into your suite. Apparently, $he decided to while away the hours until you got back by having some truly grandiose group sex with all the slaves you have in the suite.</p> - -<p>$He had to turn to greet you as you entered, since $he was facing away from the entry, and the reason why is rather obvious. Up near the opposite wall, _bottomSlave.slaveName is on the floor with _his2 face down and _his2 ass up. - -/* build the train from all participating slaves */ -<<print _msSlaves.filter((s) => s.mode !== "none").reduce((acc, cur, i, arr) => { - let r = ``; - const {mode, slave} = cur; - const nextSlave = (i+1 >= arr.length) ? S.Concubine : arr[i+1].slave; - let hole = () => { - if (mode === "vaginal") { - if (slave.vagina > 2) { - return "loose pussy"; - } else if (slave.vagina > 1) { - return "pussy"; - } else { - return "tight pussy"; - } - } else if (mode === "anal") { - if (slave.anus > 2) { - return "asspussy"; - } else if (slave.anus > 1) { - return "asshole"; - } else { - return "tight butt"; - } - } - }; - let penetrator = () => { - let t = ``; - if (canPenetrate(nextSlave)) { - t += nextSlave.slaveName + "'s "; - if (nextSlave.dick > 3) { - t += "painfully big"; - } else { - t = "hard"; - } - t += "dick"; - } else { - t += "a "; - const size = (mode === "vaginal" ? slave.vagina : slave.anus); - if (size > 2) { - t += "huge"; - } else if (size > 1) { - t += "big"; - } else { - t += "moderate"; - } - t += " strap-on worn by " + nextSlave.slaveName; - } - return t; - }; - - if (i === 0) { - return r; /* bottom slave already accounted for */ - } else if (i !== arr.length-1) { - /* middle slaves */ - r += `${slave.slaveName}'s ${hole()} ` + "is" /* FUCK SUGARCUBE */ + ` filled by ${penetrator()}, `; - if (nextSlave.belly >= 150000) { - r += `whose middle is so obscenely distended that ${slave.slaveName} is struggling to support it.`; - } else if (nextSlave.belly >= 10000 || nextSlave.weight >= 160) { - r += `whose middle is resting on ${slave.slaveName}'s ${slave.skin} back.`; - } else if (nextSlave.boobs > 10000) { - r += `whose tits are so unreasonably large they're resting on ${slave.slaveName}'s ${slave.skin} back.`; - } else if (slave.butt > 4) { - r += `well cushioned by ${slave.slaveName}'s huge ass.`; - } else if (nextSlave.nipples === "huge") { - r += `who is bending to rub ${getPronouns(nextSlave).his} enormous hard nipples across ${slave.slaveName}'s ${slave.skin} back.`; - } else if (nextSlave.lips > 40) { - r += `who is bending forward to nibble along ${slave.slaveName}'s ${slave.skin} neck.`; - } else if (hasAnyArms(nextSlave)) { - r += `who is reaching around to grope ${slave.slaveName}'s ${slave.skin} chest.`; - } else { - r += `who is propped up against ${slave.slaveName}'s ${slave.skin} butt.`; - } - } else { - /* top slave */ - r += `Finally, ${slave.slaveName}'s ${hole()} ` + "is" /* FUCK SUGARCUBE */ + ` filled by ${penetrator()}, `; - r += "who has paused $his thrusting to issue a preemptory order to the slaves to stay where they are, before turning to greet you cheerfully."; - } - seX(nextSlave, "penetrative", slave, mode, 1); - return acc + ` ` + r; -}, ``)>></p> - -/* and now describe what the non-participating slaves are doing */ -<<set _nonparticipants = _msSlaves.filter((s) => s.mode === "none").map((s) => s.slave)>> -<<if _nonparticipants.length > 0>> - <p> - <<print _nonparticipants.map((s) => s.slaveName).reduce((res, ch, i, arr) => res + (i === arr.length - 1 ? ' and ' : ', ') + ch)>> can't participate in the train, so _S.Concubine.slaveName has them busy lying under the slaves who are, offering what oral stimulation they can manage. - </p> - <<run _nonparticipants.forEach((s) => actX(s, "oral"))>> -<</if>> - -<<set _top = _msSlaves.slice().reverse().find((s) => s.mode !== "none")>> - -<<set _concubineMode = "none">> -<<if canDoAnal(_S.Concubine) && _S.Concubine.anus > 0>> - <<set _concubineMode = "anal">> - <<if (_S.Concubine.anus > 2)>><<set _concubineHole = "loose anus">><<elseif (_S.Concubine.anus > 1)>><<set _concubineHole = "asshole">><<else>><<set _concubineHole = "tight little asshole">><</if>> -<<elseif canDoVaginal(_S.Concubine) && _S.Concubine.vagina > 0>> - <<set _concubineMode = "vaginal">> - <<if (_S.Concubine.vagina > 2)>><<set _concubineHole = "loose pussy">><<elseif (_S.Concubine.vagina > 1)>><<set _concubineHole = "pussy">><<else>><<set _concubineHole = "tight little pussy">><</if>> -<</if>> -<span id="result"> -<<if _concubineMode !== "none">> - <<link "Slide in behind the concubine for some action">> - <<replace "#result">> - <<setLocalPronouns _top.slave 2>> - _S.Concubine.slaveName anticipates you, and is already sliding $himself partway out of <<=_top.slave.slaveName>> and cocking $his hips to spread $his - <<if _S.Concubine.butt > 15>> - immeasurable - <<elseif _S.Concubine.butt > 10>> - expansive - <<elseif _S.Concubine.butt > 7>> - enormous - <<elseif (_S.Concubine.butt > 5)>> - huge - <<elseif (_S.Concubine.butt > 2)>> - healthy - <<else>> - trim - <</if>> - buttocks as wide as $he can without disentangling $himself from the sex train. Up on the bed $he's at just the right height, and $he winks $his _concubineHole invitingly<<if canTalk(_S.Concubine)>>, laughing at the sheer decadence of it<</if>>. <<if ($PC.dick == 0)>>You pull on a strap-on and push it<<else>>You push yourself<</if>> home with some force, your concubine's extreme state of arousal leaving $his ass very relaxed and welcoming; the thrust shoves $him forward to hilt $himself in <<= _top.slave.slaveName>>, and so on down the line, producing more giggling, some squealing, and much scrabbling for balance. It takes a while to find the rhythm, and while you wait for the inevitable tangles to be fixed you decide to challenge yourself. You reach around and <<if (_S.Concubine.boobs > 10000)>>sink your hands into _S.Concubine.slaveName's massive boobs<<elseif (_S.Concubine.boobs > 1000)>>heft _S.Concubine.slaveName's heavy boobs<<elseif (_S.Concubine.boobs > 300)>>tease _S.Concubine.slaveName's healthy breasts<<else>>massage _S.Concubine.slaveName's flat chest<</if>>, nibbling $his _S.Concubine.skin neck, and generally torturing $him with stimulation until $he climaxes to $his beloved <<= getWrittenTitle(_S.Concubine)>>. When $he does, you extract yourself and pull $him unceremoniously off <<= _top.slave.slaveName>>, replacing $him in <<= _top.slave.slaveName>>'s <<if _top.mode === "anal">>butt<<else>>pussy<</if>>. You work your way down the line, orgasm by orgasm, delaying your own climax until the exhausted _bottomSlave.slaveName manages yet another orgasm by heroic efforts, and you're done. As you roll off _him2, panting, there is scattered applause and much congratulation from your harem of @@.mediumaquamarine;trusting slaves.@@ - <<set _S.Concubine.trust += 5>> - <<run seX($PC, "penetrative", _S.Concubine, _concubineMode)>> - <<run _msSlaves.forEach((s) => { - s.slave.trust += 1; - seX($PC, "penetrative", s.slave, s.mode); - })>> - <<if canImpreg(_bottomSlave, $PC)>> - <<run knockMeUp(_bottomSlave, 10, 1, $PC.ID)>> - <</if>> - <</replace>> - <</link>> -<</if>> -<br><<link "Slide in up at the head of the bed for some oral">> - <<replace "#result">> - <<setLocalPronouns _bottomSlave 2>> - _bottomSlave.slaveName's <<= App.Desc.eyesColor(_bottomSlave)>> widen when you push _him2 upright for a moment and slide in under _him2, but _he2 wraps _his2 - <<if (_bottomSlave.lips > 95)>> - facepussy - <<elseif (_bottomSlave.lips > 70)>> - dick sucking lips - <<elseif (_bottomSlave.lips > 20)>> - pretty lips - <<else>> - lips - <</if>> - around your <<if ($PC.dick == 0)>>clit<<else>>cock<<if $PC.vagina != -1>> and starts stroking your pussy<</if>><</if>> eagerly enough, even as <<=_msSlaves[1].slave.slaveName>> goes back to fucking _him2. The sex train is fairly gentle, since anything too fast would disintegrate the gymnastic arrangement, but _bottomSlave.slaveName is still getting enough stimulation that _he2 whimpers quietly into your <<if ($PC.vagina != -1)>>pussy<<else>>dick<</if>>, a nice feeling. The blowjob is <<if (_bottomSlave.skill.oral >= 100)>>masterful, despite the distraction<<elseif (_bottomSlave.skill.oral > 10)>>serviceable, despite the distraction<<else>>only mediocre, but serviceable enough<</if>>, so you let _him2 work for a while before gently shoving _him2 off the side of the bed and telling _him2 to get to the back of the line. The slaves all shuffle forward awkwardly, and inadvertently block your view so that you hear rather than see _bottomSlave.slaveName start groping your concubine _S.Concubine.slaveName's - <<if _S.Concubine.butt > 15>> - immeasurable - <<elseif _S.Concubine.butt > 10>> - expansive - <<elseif _S.Concubine.butt > 7>> - enormous - <<elseif (_S.Concubine.butt > 5)>> - huge - <<elseif (_S.Concubine.butt > 2)>> - healthy - <<else>> - trim - <</if>> - ass down near the foot of the bed. You climax, on occasion, but are enjoying yourself so immensely that you let the slaves continue the rotation until you're entirely spent, and they're entirely exhausted. You reach for a tablet to get some work done, in the center of a pile of sweaty, tired slaves, all of whom are resting with at least one body part in contact with their @@.hotpink;beloved@@ <<= properMaster()>>. - <<set _S.Concubine.devotion += 5>> - <<run seX($PC, "penetrative", _S.Concubine, "oral")>> - <<run _msSlaves.forEach((s) => { - s.slave.devotion += 1; - seX($PC, "penetrative", s.slave, "oral", 2); - })>> - <</replace>> -<</link>> -</span> - -<</if>> /* closes eligibility check */ diff --git a/src/uncategorized/reFSAcquisition.tw b/src/uncategorized/reFSAcquisition.tw index 622f2b83f4b832e0326d267a86e55b828c1f2b09..2aaac0a9f4ca4ec7da765084dc84f7d1e2c4e567 100644 --- a/src/uncategorized/reFSAcquisition.tw +++ b/src/uncategorized/reFSAcquisition.tw @@ -1,7 +1,7 @@ :: RE FS acquisition [nobr] <<if Array.isArray($FSAcquisitionEvents)>> - <<if $cheatMode == 1>> + <<if $debugMode > 0 && $debugModeEventSelection > 0>> <<set $nextButton = "Back", $nextLink = "Nonrandom Event", $returnTo = "Nonrandom Event">> /* if user just clicks spacebar */ ''A random FS acquisition event would have been selected from the following:'' <br> @@ -1475,7 +1475,7 @@ //You lack the necessary funds to enslave $him.// <</if>> -<<if $cheatMode == 1>> +<<if $debugMode > 0 && $debugModeEventSelection > 0>> <br><br>DEBUG: [[Go back to Nonrandom Event|Nonrandom Event][_slave = 0, $eventSlave = 0]] <</if>> diff --git a/src/uncategorized/recETS.tw b/src/uncategorized/recETS.tw index 7a2dbd4b76776ce9a593547648bec5ee59b4ab04..7420dcd4d6544d32b3b3d0b8fc77d2b474754615 100644 --- a/src/uncategorized/recETS.tw +++ b/src/uncategorized/recETS.tw @@ -2,7 +2,7 @@ <<if Array.isArray($RecETSevent)>> <<set _slave = $eventSlave>> - <<if $cheatMode === 1>> + <<if $debugMode > 0 && $debugModeEventSelection > 0>> <<set $nextButton = "Back", $nextLink = "Nonrandom Event", $returnTo = "Nonrandom Event">> /* if user just clicks spacebar */ <div style="font-weight:bold"> A random two slave recruitment event would have been selected from the following: @@ -12,37 +12,35 @@ <<print "[[$RecETSevent[_i]|RecETS][$RecETSevent = $RecETSevent[" + _i + "]]]">> </div> <</for>> - <<if $debugMode === 1>> - <div> - For debug purposes, the following scenes would not have been selected but can be chosen. - </div> - <<set _allEvents = [ - "addict mother daughter", - "posh mother daughter", - "incest mother son", - "incest father daughter", - "incest brother sister", - "incest sister sister", - "incest brother brother", - "incest twin sister", - "incest twin brother", - "incest twins mixed", - "incest mother daughter", - "incest father son", - "mismatched pair", - "matched pair", - "identical pair", - "identical herm pair", - "desperate broodmother" - ]>> - <<for _i = 0; _i < _allEvents.length; _i++>> - <<if !$RecETSevent.includes(_allEvents[_i])>> - <div> - <<print "[[_allEvents[_i]|RecETS][$RecETSevent = _allEvents[" + _i + "]]]">> - </div> - <</if>> - <</for>> - <</if>> + <div> + For debug purposes, the following scenes would not have been selected but can be chosen. + </div> + <<set _allEvents = [ + "addict mother daughter", + "posh mother daughter", + "incest mother son", + "incest father daughter", + "incest brother sister", + "incest sister sister", + "incest brother brother", + "incest twin sister", + "incest twin brother", + "incest twins mixed", + "incest mother daughter", + "incest father son", + "mismatched pair", + "matched pair", + "identical pair", + "identical herm pair", + "desperate broodmother" + ]>> + <<for _i = 0; _i < _allEvents.length; _i++>> + <<if !$RecETSevent.includes(_allEvents[_i])>> + <div> + <<print "[[_allEvents[_i]|RecETS][$RecETSevent = _allEvents[" + _i + "]]]">> + </div> + <</if>> + <</for>> <p> [[Go Back to Random Nonindividual Event|Random Nonindividual Event][$eventSlave = 0]] @@ -1574,7 +1572,7 @@ </div> <</if>> - <<if $cheatMode === 1>> + <<if $debugMode > 0 && $debugModeEventSelection > 0>> <p> DEBUG: <span class="indent"> diff --git a/src/uncategorized/spa.tw b/src/uncategorized/spa.tw deleted file mode 100644 index 0966d569f6c61e77e23d8db629b3902b2a295697..0000000000000000000000000000000000000000 --- a/src/uncategorized/spa.tw +++ /dev/null @@ -1,161 +0,0 @@ -:: Spa [nobr jump-to-safe jump-from-safe] - -<<set _DL = App.Entity.facilities.spa.employeesIDs().size, $nextButton = "Back to Main", $nextLink = "Main", $returnTo = "Spa", $encyclopedia = "Spa">> - -<<set _spaNameCaps = capFirstChar($spaName)>> -<p class="scene-intro"> - _spaNameCaps - <<switch $spaDecoration>> - <<case "Roman Revivalist">> - is built as a Roman bath. The flooring is pleasantly warm due to a modernized version of hypocaust heating, and is covered in mosaic depicting slaves enjoying sex. - <<case "Neo-Imperialist">> - is built as a modern Imperial garden. Bright green plants mix with the pulsating lights of high technology, and clear, sleek windows fog up with the steam of a central bath heated by the latest hydraulic technology. - <<case "Aztec Revivalist">> - is built as an Aztec bathhouse. Water steams from the middle of the room and the air is heavy with the scent of herbs and essences. The idols by the door glisten with moisture. - <<case "Egyptian Revivalist">> - is decorated like an Egyptian water garden. All but the hottest pools include aquatic plants around their edges, and the atmosphere is heavy with perfume. - <<case "Edo Revivalist">> - is decorated like a traditional onsen. The stone-lined pools are surrounded by meticulously kept gardens, and there are proper provisions for bathing in the old Japanese style. - <<case "Arabian Revivalist">> - looks like a dream of an Arabian palace garden. Every surface is richly tiled in vibrant colors, and the beguiling scents of perfumes from the Levant hang in the air. - <<case "Chinese Revivalist">> - is gloomy and hot, filled with an oppressive steam that immediately dulls the senses. Though relaxation is possible and indeed easy here, it is a stultifying relaxation whose humid warmth seems to suppress independence. - <<case "Chattel Religionist">> - is dedicated to the purification of the body and the spirit. The pools are arranged for the completion of self-purification procedures which include ritual masturbation. - <<case "Degradationist">> - is utilitarian. There are waterproof cameras positioned throughout the spa so that anyone who wants to can watch the nude slaves. One wall has a screen showing the current viewer count to keep the slaves aware of this. - <<case "Asset Expansionist">> - is utilitarian. It is equipped with all sorts of devices to help slaves care for huge assets, including lifts to help them in and out of the water, and all around showers to help clean and moisturize difficult to reach spots. - <<case "Transformation Fetishist">> - is utilitarian. It is equipped with special devices to help speed surgical recovery, including a series of baths designed to prevent scarring. - <<case "Repopulationist">> - is comfortable, with waterproof cushions lining the pools. It is equipped with all sorts of devices to aid pregnant slaves, including lifts to help them in and out of the water, baths just for their feet, and all around showers to help clean and moisturize difficult to reach spots. - <<case "Eugenics">> - is comfortable, albeit split in half. One side for the lower classes' slaves, and the other for the Elite and their pets. - <<case "Gender Radicalist">> - is comfortable, with waterproof cushions lining the pools. There are screens on the walls showing slave girls with all different varieties of genitalia orgasming from penetration, to keep the idea at the forefront of the slaves' minds. - <<case "Gender Fundamentalist">> - is comfortable, with waterproof cushions lining the pools. There are screens on the walls showing light entertainment featuring a lot of beautiful women and handsome men for the slaves' edification. - <<case "Physical Idealist">> - is not the gym, but it does have some workout equipment, mostly low-impact machines designed to speed recovery. There are special hot baths to ease sore muscles. - <<case "Supremacist">> - is comfortable, with waterproof cushions lining the pools. There are screens on the walls showing light entertainment featuring $arcologies[0].FSSupremacistRace main characters. - <<case "Subjugationist">> - is comfortable, with waterproof cushions lining the pools. There are screens on the walls showing light entertainment featuring $arcologies[0].FSSubjugationistRace characters in comic relief roles. - <<case "Paternalist">> - is comfortable, with waterproof cushions lining the pools. There are screens on the walls showing light entertainment written by and intended for smart, loyal slaves. - <<case "Pastoralist">> - is utilitarian. It is equipped with all sorts of devices to help slaves care for huge assets, including lifts to help them in and out of the water, and all around showers to help clean and moisturize difficult to reach spots. - <<case "Maturity Preferentialist">> - is comfortable, but surprisingly businesslike. It's all about beautification here; there's a bewildering array of mud baths, resting pools, and massage setups, all designed to keep mature slaves looking their very best. - <<case "Youth Preferentialist">> - is comfortable and fun. There are hot tubs and massage tables for slaves who feel like relaxing, but there's also a colder pool with pool toys for slaves who want to play. It even has a small waterslide. - <<case "Body Purist">> - is comfortable, with waterproof cushions lining the pools. Everything is designed for the slaves' comfort; there are even special mud baths to perfect skin clarity. - <<case "Slimness Enthusiast">> - is comfortable, with waterproof cushions lining the pools. Everything is designed for the slaves' comfort; there are even special mud baths to perfect skin clarity. - <<case "Hedonistic">> - is comfortable, with waterproof cushions lining the pools. It is equipped with all sorts of devices to aid hefty slaves, including lifts to help them in and out of the water, specialized moisturizers to keep their skin healthy and smooth, and all around showers to help clean difficult to reach spots and between folds. <<if $arcologies[0].FSHedonisticDecadenceResearch == 1>>Platters of food and treats are readily available around the tubs so that relaxing slaves never have to strain to grab a bite to eat<<else>>Feeders connected to the slave food reserves line the pools so that so that relaxing slaves never have to strain to suck down their fill of food<</if>>. - <<case "Intellectual Dependency">> - is comfortable, fun and, most importantly, safe; even the dumbest slave can enjoy the pools without worrying their <<= properTitle()>>. There are screens on the walls showing simple entertainment designed to arouse more than titillate. - <<case "Slave Professionalism">> - is comfortable, with waterproof cushions lining the pools. It is a place where a weary slave can rest their mind after a hards day's work. There are screens on the walls showing documentaries intended for smart, skilled slaves. - <<case "Petite Admiration">> - is comfortable, but designed with short slaves in mind. The pools are shallow and easy to slip in and out of; taller slaves are likely to find them more frustrating than enjoyable. - <<case "Statuesque Glorification">> - is comfortable, but designed with tall slaves in mind. The pools are deep; too deep for a short slave to find relaxing. - <<default>> - is well-appointed, with massage tables, hot tubs, and a cold pool. - <</switch>> - - <<set _spaUtilization = 1 - ($spaSpots / ($spa * 20))>> - <<if _spaUtilization >= 1>> - It's crowded in here. Slaves are relaxing in the warm water, splashing around or just floating. Here and there some of the more sex-starved are in the early stages of intercourse, but most prefer to take time off from it all. Unfortunately there is not enough space for all of your slaves to enjoy the spa. - <<elseif _spaUtilization >= 0.5>> - It's busy in here. Slaves are relaxing in the warm water, splashing around or just floating. Here and there some of the more sex-starved are in the early stages of intercourse, but most prefer to take time off from it all. - <<elseif _spaUtilization > 0>> - It's sparsely populated; though the few slaves here have little company they like having the water to themselves. - <<elseif _DL / $spa > 0.5>> - It's busy in here. Slaves are relaxing in the warm water, splashing around or just floating. Here and there some of the more sex-starved are in the early stages of intercourse, but most prefer to take time off from it all. - <<elseif _DL > 0>> - It's sparsely populated; though the few slaves here have little company they like having the water to themselves. - <<elseif _S.Attendant>> - <<setLocalPronouns _S.Attendant>> - _S.Attendant.slaveName is alone here, and has nothing to do but keep the place (and $his own soft, wet body) spotlessly clean. - <<else>> - It's empty and quiet. - <</if>> - <<if _DL == 0 && !_S.Attendant>> - <div class="choices" style="font-style:normal"> - [[Decommission the Spa|Main][$spa = 0, $spaDecoration = "standard", $spaUpgrade = 0, $spaFix = 0]] - </div> - <</if>> -</p> - -<div> - <<set _Tmult0 = Math.trunc($spa*1000*$upgradeMultiplierArcology)>> - _spaNameCaps can house $spa slaves while they recuperate here. There <<if _DL == 1>>is<<else>>are<</if>> currently _DL slave<<if _DL != 1>>s<</if>> recuperating in $spaName. - <div class="choices"> - [[Expand the spa|Spa][cashX(forceNeg(_Tmult0), "capEx"), $spa += 5]] - <span class="note"> - Costs <<print cashFormat(_Tmult0)>> - </span> - </div> - <div class="choices"> - <<if _DL > 0>> - <<includeDOM removeFacilityWorkers("spa", "rest", "rest")>> - <</if>> - </div> -</div> - -<div> - <<if $spaUpgrade == 1>> - _spaNameCaps has been upgraded with state of the art temperature treatment options, from hot and cold mineral water pools to baking saunas and dense steam rooms. - <<else>> - <<set _Tmult1 = Math.trunc($spa*1000*$upgradeMultiplierArcology)>> - _spaNameCaps is a standard spa. - <div class="choices"> - [[Upgrade the spa with saunas, steam rooms, and mineral water baths|Spa][cashX(forceNeg(_Tmult1), "capEx"), $spaUpgrade = 1]] - <span class="note"> - Costs <<print cashFormat(_Tmult1)>> - </span> - </div> - <</if>> -</div> -<div> - <<if _S.Attendant>> - <<setLocalPronouns _S.Attendant>> - <<if $spaFix == 2>> - _S.Attendant.slaveName is focusing only on the health and wellness of the slaves under $his care, obeying your orders to avoid attempting to right mental flaws. - <div class="choices"> - [["Order " + $him + " to only fix mindbroken slaves"|Spa][$spaFix = 1]] | - [["Let " + $him + " tend as " + $he + " sees fit"|Spa][$spaFix = 0]] - </div> - <<elseif $spaFix == 1>> - _S.Attendant.slaveName is focusing on the health and wellness of the slaves under $his care, as well as trying to bring mindbroken slaves back, while ignoring any mental hang-ups a slave may have. - <div class="choices"> - [["Order " + $him + " to not fix flaws"|Spa][$spaFix = 2]] | - [["Let " + $him + " tend as " + $he + " sees fit"|Spa][$spaFix = 0]] - </div> - <<else>> - _S.Attendant.slaveName is not following any special orders and is tending to your slaves as $he sees fit. - <div class="choices"> - [["Order " + $him + " to not fix any flaws"|Spa][$spaFix = 2]] | - [["Order " + $him + " to only fix mindbroken slaves"|Spa][$spaFix = 1]] - </div> - <</if>> - <</if>> -</div> - -<p> - <<includeDOM App.UI.SlaveList.stdFacilityPage(App.Entity.facilities.spa, true)>> -</p> - -<p> - Rename $spaName: <<textbox "$spaName" $spaName "Spa">> - <span class="note"> - Use a noun or similar short phrase - </span> -</p> - -<<run App.UI.SlaveList.ScrollPosition.restore()>>