diff --git a/js/artInfrastructure.js b/js/artInfrastructure.js index c709c72c0349619ae38fe5af057bf1af9e8c43b4..6b3bf218b0ee97abe148bdbcc0b9dd4abeaa33f4 100644 --- a/js/artInfrastructure.js +++ b/js/artInfrastructure.js @@ -98,24 +98,31 @@ App.Art.SvgQueue = class { * @param {NamedNodeMap} right */ function equalAttributes(left, right) { - /** get all the attribute names from an attribute list and sort them + /** get all the attribute names from an attribute list * @param {NamedNodeMap} attrs * @returns {string[]} */ - function sortedAttrNames(attrs) { + function attrNames(attrs) { let names = []; for (let index = 0; index < attrs.length; ++index) { names.push(attrs[index].nodeName); } - names.sort(); return names; } - if (typeof(left) !== typeof(right)) { - return false; + if (!left && !right) { + return true; // both are nullish, treat as equal + } else if (!left || !right) { + return false; // only one is nullish, not equal } - const allNames = _.union(sortedAttrNames(left), sortedAttrNames(right)); - return allNames.every((attr) => left[attr].nodeValue === right[attr].nodeValue); + + const leftNames = attrNames(left), rightNames = attrNames(right); + const intersectionLength = _.intersection(leftNames, rightNames).length; + if (leftNames.length !== intersectionLength || rightNames.length !== intersectionLength) { + return false; // contain different attributes, not equal + } + // are all values equal? + return leftNames.every((attr) => left.getNamedItem(attr).nodeValue === right.getNamedItem(attr).nodeValue); } let frag = document.createDocumentFragment(); diff --git a/src/004-base/facility.js b/src/004-base/facility.js index be67be3c9701de0b13ca434cd07eb2028bb3d4c3..719fdf7781fc3b08d351315f1707fd60bc3312cc 100644 --- a/src/004-base/facility.js +++ b/src/004-base/facility.js @@ -82,12 +82,6 @@ App.Entity.Facilities.Job = class { return this.hasEmployeeWithId(slave.ID); } - /** - * @callback linkCallback - * @param {string} assignment new assignment - * @returns {string} code to include into the <<link>><</link>> - */ - /** * @callback assignmentCallback * @param {App.Entity.SlaveState} slave the slave whose assignment changes @@ -95,20 +89,6 @@ App.Entity.Facilities.Job = class { * @returns {void} */ - /** - * Returns link text for the penthouse assignment - * @param {number} ID slave ID - * @param {string} [passage] passage to go to - * @param {linkCallback} [callback] - * @param {string} [linkText] - * @returns {string} - */ - assignmentLink(ID, passage, callback, linkText) { - linkText = linkText || this.desc.position; - const linkAction = callback !== undefined ? callback(this.desc.assignment) : ''; - return `<<link "${linkText}"${passage !== undefined ? ' "' + passage + '"' : ''}>><<= assignJob(slaveStateById(${ID}), "${this.desc.assignment}")>>${linkAction}<</link>>`; - } - /** * Returns link text for the penthouse assignment * @param {number} ID slave ID @@ -420,32 +400,6 @@ App.Entity.Facilities.Facility = class { return this.jobs.some(job => job.isEmployed(slave)); } - /** - * Returns link text for the job assignments - * @param {number} ID slave ID - * @param {string} [job] generate link only for this job - * @param {string} [passage] - * @param {linkCallback} callback - * @returns {string[]} - */ - assignmentLinks(ID, job, passage, callback) { - /** @type {App.Entity.SlaveState} */ - const slave = slaveStateById(ID); - const jobs = job === undefined ? this._jobs : {job: this._jobs[job]}; - - let res = []; - for (const jn in jobs) { - const j = jobs[jn]; - let rejects = j.canEmploy(slave); - if (rejects.length === 0) { - res.push(j.assignmentLink(ID, passage, callback)); - } else { - res.push(App.UI.disabledLink(j.desc.position, rejects)); - } - } - return res; - } - /** * Returns link text for the job assignments * @param {number} ID slave ID @@ -472,19 +426,6 @@ App.Entity.Facilities.Facility = class { return res; } - /** - * Returns link text for the facility transfer - * @param {number} ID slave ID - * @param {string} [job] transfer to this job (uses default job if this is undefined) - * @param {string} [passage] - * @param {linkCallback} [callback] - * @returns {string} - */ - transferLink(ID, job, passage, callback) { - job = job || this.desc.defaultJob; - return this._jobs[job].assignmentLink(ID, passage, callback, this.genericName); - } - /** * Returns link text for the facility transfer * @param {number} ID slave ID @@ -558,20 +499,6 @@ App.Entity.Facilities.Facility = class { * Job for a facility with a single job option */ App.Entity.Facilities.FacilitySingleJob = class extends App.Entity.Facilities.Job { - /** - * Returns link text for the penthouse assignment - * @param {number} ID slave ID - * @param {string} [targetPassage] passage to go to - * @param {linkCallback} [callback] - * @param {string} [linkText] - * @returns {string} - */ - assignmentLink(ID, targetPassage, callback, linkText) { - linkText = linkText || this.facility.genericName; - const linkAction = callback !== undefined ? callback(this.desc.assignment) : ''; - return `<<link "${linkText}">>${linkAction}<<run assignmentTransition(slaveStateById(${ID}), "${this.facility.genericName}", "${targetPassage || passage()}")>><</link>>`; - } - /** * @param {number} ID slave ID * @param {string} [targetPassage] passage to go to diff --git a/src/data/backwardsCompatibility/backwardsCompatibility.js b/src/data/backwardsCompatibility/backwardsCompatibility.js index f48faf2a5e71884ca03987708a37fa579d90f668..7c87d009f1e3d08ced0be68c58b3d595c97910c4 100644 --- a/src/data/backwardsCompatibility/backwardsCompatibility.js +++ b/src/data/backwardsCompatibility/backwardsCompatibility.js @@ -93,7 +93,7 @@ App.Update.backwardsCompatibility = function() { jQuery('#backwardsCompatibility').append(div); App.SecExp.Check.general(); if (V.secExpEnabled === 1) { - jQuery(div).wiki(`<<include "SecExpBackwardCompatibility">>`); + div.append(App.UI.DOM.renderPassage("SecExpBackwardCompatibility")); } div = document.createElement('div'); diff --git a/src/endWeek/slaveAssignmentReport.js b/src/endWeek/slaveAssignmentReport.js index ac7203838a93640c491c8c6fa805e34958954c18..d68248c0d9cf1da4bf8fada411ee88b6c9d852b4 100644 --- a/src/endWeek/slaveAssignmentReport.js +++ b/src/endWeek/slaveAssignmentReport.js @@ -399,13 +399,6 @@ App.EndWeek.slaveAssignmentReport = function() { } } - /* IMPORTANT FOR REASONS!!! */ - // <<unset _ii>> - /** /Accordion */ - - /* release loading screen as soon as the event loop can run */ - //App.UI.EndWeekAnim.end(); - return res; function _countPenthousePopulation() { diff --git a/src/events/reRelativeRecruiter.js b/src/events/reRelativeRecruiter.js index a478be3f8b8cdd4d8b2f31e6cb0aa8eaa3531478..05e53a0498205fb2764f6cc39233bbbf8b351776 100644 --- a/src/events/reRelativeRecruiter.js +++ b/src/events/reRelativeRecruiter.js @@ -455,7 +455,8 @@ App.Events.RERelativeRecruiter = class RERelativeRecruiter extends App.Events.Ba slave.hStyle = either("bun", "luxurious", "neat", "up"); slave.voice = 2; slave.counter.birthsTotal = 5; - slave.bellySag = 4, slave.bellySagPreg = 4; + slave.bellySag = 4; + slave.bellySagPreg = 4; slave.energy = 65; slave.bellyTat = "a heart"; } @@ -637,10 +638,8 @@ App.Events.RERelativeRecruiter = class RERelativeRecruiter extends App.Events.Ba let elements = []; elements.push(`You complete the legalities and biometric scanning quickly and without fuss. ${V.activeSlave.slaveName} arrives shortly. The two slaves remember each other only dimly — they parted a long time ago — but they embrace. The devoted ${SlaveTitle(eventSlave)} explains the situation and encourages ${his} ${_this.params.relative} to be a good slave to you. ${V.activeSlave.slaveName} looks a little fearful but clearly realizes that ${he2}'s lucky to be here.`); - let desc = document.createDocumentFragment(); V.eventSlave = eventSlave; // New Slave Intro uses global $eventSlave, so set it here - $(desc).wiki(`<<include "New Slave Intro">>`); - elements.push(desc); + elements.push(App.UI.DOM.renderPassage("New Slave Intro")); return elements; } diff --git a/src/facilities/nursery/widgets/utils/nurseryUtils.js b/src/facilities/nursery/widgets/utils/nurseryUtils.js index c2a3f739bb9adf163311276764cd56dcda9c21bb..cacacfa15973ab09e90b0781a3b9cd842b22dd93 100644 --- a/src/facilities/nursery/widgets/utils/nurseryUtils.js +++ b/src/facilities/nursery/widgets/utils/nurseryUtils.js @@ -721,7 +721,8 @@ App.Facilities.Nursery.nurserySort = function nurserySort() { const PC = V.PC, SL = V.slaves.length, - arcology = V.arcologies[0]; + arcology = V.arcologies[0], + freeCribs = (V.nursery - V.cribs.length); let r = ``, @@ -811,7 +812,7 @@ App.Facilities.Nursery.nurserySort = function nurserySort() { r += `All ${reservedNursery} of ${his} children will be placed in ${V.nurseryName}. `; } - if ((reservedIncubator + reservedNursery < WL) && (reservedChildrenNursery < V.freeCribs)) { + if ((reservedIncubator + reservedNursery < WL) && (reservedChildrenNursery < freeCribs)) { r += `<br> `; r += App.UI.passageLink("Keep another child", "Nursery", `${WombAddToGenericReserve(slave, "nursery", 1)}`); if (reservedNursery > 0) { @@ -820,30 +821,30 @@ App.Facilities.Nursery.nurserySort = function nurserySort() { if (reservedNursery > 1) { r += ` | ${App.UI.passageLink(`Keep none of ${his} children`, "Nursery", `${WombCleanGenericReserve(slave, "nursery", 9999)}`)}`; } - if (reservedChildrenNursery + WL - reservedNursery <= V.freeCribs) { + if (reservedChildrenNursery + WL - reservedNursery <= freeCribs) { r += ` | ${App.UI.passageLink(`Keep the rest of ${his} children`, "Nursery", `${WombAddToGenericReserve(slave, "nursery", 9999)}`)}`; } - } else if (reservedNursery === WL || reservedChildrenNursery === V.freeCribs || reservedIncubator + reservedNursery === WL) { + } else if (reservedNursery === WL || reservedChildrenNursery === freeCribs || reservedIncubator + reservedNursery === WL) { r += `<br> `; r += App.UI.passageLink("Keep one less child", "Nursery", `${WombCleanGenericReserve(slave, "nursery", 1)}`); if (reservedNursery > 1) { r += ` | ${App.UI.passageLink(`Keep none of ${his} children`, "Nursery", `${WombCleanGenericReserve(slave, "nursery", 9999)}`)}`; } } - } else if (reservedChildrenNursery < V.freeCribs && V.freeCribs > WL) { + } else if (reservedChildrenNursery < freeCribs && freeCribs > WL) { if (WL - reservedIncubator === 0) { r += `<i>${His} children are already reserved for ${V.incubatorName}</i>`; r += `<br> `; r += App.UI.passageLink(`Keep ${his} child${WL > 1 ? `ren` : ``} here instead`, "Nursery", `${WombAddToGenericReserve(slave, "nursery", 1)}`); } else { - r += `You have ${V.freeCribs === 1 ? `an ` : ``}<span class="lime">available room${V.freeCribs > 1 ? `s` : ``}.</span> `; + r += `You have ${freeCribs === 1 ? `an ` : ``}<span class="lime">available room${freeCribs > 1 ? `s` : ``}.</span> `; r += `<br> `; r += App.UI.passageLink(`Keep ${WL > 1 ? `a` : `the`} child`, "Nursery", `${WombAddToGenericReserve(slave, "nursery", 1)}`); - if (WL > 1 && (reservedChildrenNursery + WL - reservedNursery <= V.freeCribs)) { + if (WL > 1 && (reservedChildrenNursery + WL - reservedNursery <= freeCribs)) { r += ` | ${App.UI.passageLink(`Keep all of ${his} children`, "Nursery", `${WombAddToGenericReserve(slave, "nursery", 9999)}`)}`; } } - } else if (reservedChildrenNursery === V.freeCribs) { + } else if (reservedChildrenNursery === freeCribs) { r += `<br> `; r += `You have <span class="red">no room for ${his} offspring.</span> `; } @@ -885,7 +886,7 @@ App.Facilities.Nursery.nurserySort = function nurserySort() { r += `All ${reservedNursery} of your children will be placed in ${V.nurseryName}.`; } - if (reservedNursery < WL && reservedChildrenNursery < V.freeCribs && reservedNursery - reservedIncubator > 0) { + if (reservedNursery < WL && reservedChildrenNursery < freeCribs && reservedNursery - reservedIncubator > 0) { r += `<br> `; r += App.UI.passageLink("Keep another child", "Nursery", `${reservedNursery += 1}, ${reservedChildrenNursery += 1}`); if (reservedNursery > 0) { @@ -896,29 +897,29 @@ App.Facilities.Nursery.nurserySort = function nurserySort() { r += ` | ${App.UI.passageLink("Keep none of your children", "Nursery", `${reservedChildrenNursery -= reservedNursery}, ${reservedChildrenNursery = 0}`)}`; } - if (reservedChildrenNursery + WL - reservedNursery <= V.freeCribs) { + if (reservedChildrenNursery + WL - reservedNursery <= freeCribs) { r += ` | ${App.UI.passageLink("Keep the rest of your children", "Nursery", `${reservedChildrenNursery += (WL - reservedNursery)}, ${reservedNursery += (WL - reservedNursery)}`)}`; } - } else if (reservedNursery === WL || reservedChildrenNursery === V.freeCribs || reservedNursery - reservedIncubator >= 0) { + } else if (reservedNursery === WL || reservedChildrenNursery === freeCribs || reservedNursery - reservedIncubator >= 0) { r += `<br> `; r += App.UI.passageLink("Keep one less child", "Nursery", `${reservedNursery -= 1}, ${reservedChildrenNursery -= 1}`); if (reservedNursery > 1) { r += App.UI.passageLink("Keep none of your children", "Nursery", `${reservedChildrenNursery -= reservedNursery}, ${reservedNursery = 0}`); } } - } else if (reservedChildrenNursery < V.freeCribs) { + } else if (reservedChildrenNursery < freeCribs) { if (WL - reservedIncubator === 0) { r += `<i>Your child${WL > 1 ? `ren are` : ` is`} already reserved for ${V.incubatorName}</i>`; r += App.UI.passageLink(`Keep your child${WL > 1 ? `ren` : ``} here instead`, "Nursery", `${reservedNursery += WL}, ${reservedIncubator = 0}`); } else { - r += `You have ${V.freeCribs === 1 ? `an ` : ``}<span class="lime">available room${V.freeCribs > 1 ? `s` : ``}. `; + r += `You have ${freeCribs === 1 ? `an ` : ``}<span class="lime">available room${freeCribs > 1 ? `s` : ``}. `; r += `<br> `; r += App.UI.passageLink(`Keep ${WL > 1 ? `a` : `your`} child`, "Nursery", `${reservedNursery += 1}, ${reservedChildrenNursery += 1}`); - if (WL > 1 && (reservedChildrenNursery + WL - reservedNursery <= V.freeCribs)) { + if (WL > 1 && (reservedChildrenNursery + WL - reservedNursery <= freeCribs)) { r += ` | ${App.UI.passageLink("Keep all of your children", "Nursery", `${reservedChildrenNursery += WL}, ${reservedNursery += WL}`)}`; } } - } else if (reservedChildrenNursery === V.freeCribs) { + } else if (reservedChildrenNursery === freeCribs) { r += `<br> `; r += `You have <span class="red">no room for your offspring.</span> `; } diff --git a/src/facilities/penthouse/penthouseFramework.js b/src/facilities/penthouse/penthouseFramework.js index 818d2057f7c5ce50c885a62bd011b69fcc1c1156..5531c55fcd93d7caf3b59dbc315cba56f6cabd49 100644 --- a/src/facilities/penthouse/penthouseFramework.js +++ b/src/facilities/penthouse/penthouseFramework.js @@ -140,13 +140,6 @@ App.Entity.Facilities.PenthouseJobs = { return r; } - assignmentLink(ID, passage, callback, linkText) { - return super.assignmentLink(ID, "Subordinate Targeting", - (assignment) => { - return `<<set $activeSlave = slaveStateById(${ID})>>` + (callback !== undefined ? callback(assignment) : ''); - }, linkText); - } - assignmentLinkElement(ID, passage, callback, linkText) { linkText = linkText || this.desc.position; return App.UI.DOM.assignmentLink(slaveStateById(ID), this.desc.assignment, "Subordinate Targeting", diff --git a/src/gui/multipleInspect.js b/src/gui/multipleInspect.js index c46c8d3b712da7fb6619caf355ec8825db6e4e73..508a63e29e7e59a6092f6ffd6c91c92408e5c092 100644 --- a/src/gui/multipleInspect.js +++ b/src/gui/multipleInspect.js @@ -4,11 +4,9 @@ App.UI.MultipleInspect = (function() { V.saleDescription = (saleDescription ? 1 : 0); V.applyLaw = (applyLaw ? 1 : 0); - // embedded sugarcube sucks but that's just how LSD works right now const oldAS = V.activeSlave; V.activeSlave = slave; - const frag = document.createDocumentFragment(); - $(frag).wiki(`<<include "Long Slave Description">>`); + const frag = App.UI.DOM.renderPassage("Long Slave Description"); V.activeSlave = oldAS; return frag; } @@ -47,22 +45,5 @@ App.UI.MultipleInspect = (function() { return frag; } - /** - * Provide a mechanism to inspect multiple slaves at once (for example, for Household Liquidators and recETS). - * Usable directly from SugarCube passages. - * @param {Array<App.Entity.SlaveState>} slaves - * @param {boolean} showFamilyTree - * @param {boolean} saleDescription - * @param {boolean} applyLaw - * @returns {string} - */ - function MultipleInspectSugarcube(slaves, showFamilyTree, saleDescription, applyLaw) { - const frag = MultipleInspectDOM(slaves, showFamilyTree, saleDescription, applyLaw); - return App.UI.DOM.includeDOM(frag, "MultipleInspect", "div"); - } - - return { - DOM: MultipleInspectDOM, - SC: MultipleInspectSugarcube - }; + return MultipleInspectDOM; })(); diff --git a/src/interaction/slaveInteract.js b/src/interaction/slaveInteract.js index 320fc4c93aac9bf2c105bc91959fdb0567db6c15..c3727380d2880993148a76b949a457e760e95f43 100644 --- a/src/interaction/slaveInteract.js +++ b/src/interaction/slaveInteract.js @@ -1308,8 +1308,7 @@ App.UI.SlaveInteract.useSlaveDisplay = function(slave) { Engine.play(sexOption.goto); } else if (sexOption.scene) { // Run scene and store render results temporarily - let frag = document.createDocumentFragment(); - $(frag).wiki(`<<include "${sexOption.scene}">>`); + let frag = App.UI.DOM.renderPassage(sexOption.scene); // Refresh (clears scene display) App.UI.SlaveInteract.refreshAll(V.slaves[V.slaveIndices[V.activeSlave.ID]]); @@ -1727,7 +1726,7 @@ App.UI.SlaveInteract.incubator = function(slave) { title.textContent = `${His} children are already reserved for ${V.nurseryName}`; title.style.fontStyle = "italic"; } else { - V.freeTanks = (V.incubator - V.tanks.length); + const freeTanks = (V.incubator - V.tanks.length); if (_reservedIncubator > 0) { if (_WL === 1) { title.textContent = `${His} child will be placed in ${V.incubatorName}. `; @@ -1738,7 +1737,7 @@ App.UI.SlaveInteract.incubator = function(slave) { } else { title.textContent = `All ${_reservedIncubator} of ${his} children will be placed in ${V.incubatorName}. `; } - if ((_reservedIncubator + _reservedNursery < _WL) && (V.reservedChildren < V.freeTanks)) { + if ((_reservedIncubator + _reservedNursery < _WL) && (V.reservedChildren < freeTanks)) { link.appendChild( App.UI.DOM.link( `Keep another child`, @@ -1778,7 +1777,7 @@ App.UI.SlaveInteract.incubator = function(slave) { ) ); } - if ((V.reservedChildren + _WL - _reservedIncubator) <= V.freeTanks) { + if ((V.reservedChildren + _WL - _reservedIncubator) <= freeTanks) { link.append(` | `); link.appendChild( App.UI.DOM.link( @@ -1792,7 +1791,7 @@ App.UI.SlaveInteract.incubator = function(slave) { ) ); } - } else if ((_reservedIncubator === _WL) || (V.reservedChildren === V.freeTanks) || (_reservedIncubator - _reservedNursery >= 0)) { + } else if ((_reservedIncubator === _WL) || (V.reservedChildren === freeTanks) || (_reservedIncubator - _reservedNursery >= 0)) { link.appendChild( App.UI.DOM.link( `Keep one less child`, @@ -1819,15 +1818,15 @@ App.UI.SlaveInteract.incubator = function(slave) { ); } } - } else if (V.reservedChildren < V.freeTanks) { + } else if (V.reservedChildren < freeTanks) { title.textContent = `${He} is pregnant and you have `; - if (V.freeTanks === 1) { + if (freeTanks === 1) { title.textContent += `an `; } let tank = document.createElement('span'); tank.className = "lime"; tank.textContent = `available aging tank`; - if (V.freeTanks > 1) { + if (freeTanks > 1) { tank.textContent += `s`; } tank.textContent += `.`; @@ -1844,7 +1843,7 @@ App.UI.SlaveInteract.incubator = function(slave) { ) ); title.appendChild(tank); - if ((_WL > 1) && (V.reservedChildren + _WL) <= V.freeTanks) { + if ((_WL > 1) && (V.reservedChildren + _WL) <= freeTanks) { link.append(` | `); link.appendChild( App.UI.DOM.link( @@ -1858,7 +1857,7 @@ App.UI.SlaveInteract.incubator = function(slave) { ) ); } - } else if (V.reservedChildren === V.freeTanks) { + } else if (V.reservedChildren === freeTanks) { title.textContent = `You have no available tanks for ${his} children. `; } } @@ -1898,7 +1897,7 @@ App.UI.SlaveInteract.nursery = function(slave) { title.textContent = `${His} children are already reserved for ${V.incubatorName}`; title.style.fontStyle = "italic"; } else { - V.freeCribs = (V.nursery - V.cribs.length); + const freeCribs = (V.nursery - V.cribs.length); if (_reservedNursery > 0) { if (_WL === 1) { title.textContent = `${His} child will be placed in ${V.nurseryName}. `; @@ -1909,7 +1908,7 @@ App.UI.SlaveInteract.nursery = function(slave) { } else { title.textContent = `All ${_reservedNursery} of ${his} children will be placed in ${V.nurseryName}. `; } - if ((_reservedIncubator + _reservedNursery < _WL) && (V.reservedChildrenNursery < V.freeCribs)) { + if ((_reservedIncubator + _reservedNursery < _WL) && (V.reservedChildrenNursery < freeCribs)) { link.appendChild( App.UI.DOM.link( `Keep another child`, @@ -1949,7 +1948,7 @@ App.UI.SlaveInteract.nursery = function(slave) { ) ); } - if ((V.reservedChildrenNursery + _WL - _reservedNursery) <= V.freeCribs) { + if ((V.reservedChildrenNursery + _WL - _reservedNursery) <= freeCribs) { link.append(` | `); link.appendChild( App.UI.DOM.link( @@ -1962,7 +1961,7 @@ App.UI.SlaveInteract.nursery = function(slave) { ) ); } - } else if ((_reservedNursery === _WL) || (V.reservedChildrenNursery === V.freeCribs) || (_reservedNursery - _reservedIncubator >= 0)) { + } else if ((_reservedNursery === _WL) || (V.reservedChildrenNursery === freeCribs) || (_reservedNursery - _reservedIncubator >= 0)) { link.appendChild( App.UI.DOM.link( `Keep one less child`, @@ -1990,15 +1989,15 @@ App.UI.SlaveInteract.nursery = function(slave) { ); } } - } else if (V.reservedChildrenNursery < V.freeCribs) { + } else if (V.reservedChildrenNursery < freeCribs) { title.textContent = `${He} is pregnant and you have `; - if (V.freeCribs === 1) { + if (freeCribs === 1) { title.textContent += `an `; } let crib = document.createElement('span'); crib.className = "lime"; crib.textContent = `available room`; - if (V.freeCribs > 1) { + if (freeCribs > 1) { crib.textContent += `s`; } crib.textContent += `.`; @@ -2015,7 +2014,7 @@ App.UI.SlaveInteract.nursery = function(slave) { ) ); title.appendChild(crib); - if ((_WL > 1) && (V.reservedChildrenNursery + _WL) <= V.freeCribs) { + if ((_WL > 1) && (V.reservedChildrenNursery + _WL) <= freeCribs) { link.append(` | `); link.appendChild( App.UI.DOM.link( @@ -2029,7 +2028,7 @@ App.UI.SlaveInteract.nursery = function(slave) { ) ); } - } else if (V.reservedChildrenNursery === V.freeCribs) { + } else if (V.reservedChildrenNursery === freeCribs) { title.textContent = `You have no available rooms for ${his} children. `; } } diff --git a/src/js/assignJS.js b/src/js/assignJS.js index d04f9b90c0ffe33e6ccbdc986e2f34fc6e6659b9..e40f3e6136ffa32b284a9bf385a4c6c46b1dd307 100644 --- a/src/js/assignJS.js +++ b/src/js/assignJS.js @@ -761,62 +761,12 @@ App.UI.jobLinks = function() { ]; return { - assignments: assignmentLinks, - transfers: transferLinks, assignmentsFragment: assignmentsFragment, transfersFragment: transfersFragment }; /** - * Generates assignment links (as Sugarcube markup) - * @param {number} ID slave ID - * @param {string} [passage] optional next passage to go to - * @param {linkCallback} [callback] - * @returns {string} - */ - function assignmentLinks(ID, passage, callback) { - let penthouseJobs = App.Entity.facilities.penthouse.assignmentLinks(ID, undefined, passage, callback); - const slave = slaveStateById(ID); - const sp = getPronouns(slave); - - if (slave.fuckdoll === 0) { - const assignment = Job.CHOICE; - if (slave.assignment !== assignment) { - const linkAction = callback !== undefined ? callback(assignment) : ''; - penthouseJobs.push(`<<link "Let ${sp.object} choose" ${passage !== undefined ? `"${passage}"` : ''}>><<= assignJob(slaveStateById(${ID}), "${assignment}")>>${linkAction}<</link>>`); - } - } else { - penthouseJobs.push(App.UI.disabledLink(`Let ${sp.object} choose`, ["Fuckdolls can't choose their job"])); - } - - return penthouseJobs.join(" | "); - } - - /** - * Generates transfer links (as Sugarcube markup) - * @param {number} ID slave ID - * @returns {string} - */ - function transferLinks(ID) { - /** @type {string[]} */ - const transfers = []; - const slave = slaveStateById(ID); - - for (const f of facilitiesOrder) { - if (!f.established || f.jobs.length === 0) { continue; } - const rejects = f.canHostSlave(slave); - if (rejects.length === 0) { - transfers.push(f.transferLink(ID, undefined, passage())); - } else { - transfers.push(App.UI.disabledLink(f.genericName, rejects)); - } - } - - return transfers.join(' | '); - } - - /** - * Generates assigment links (as a DocumentFragment) + * Generates assigment links * @param {number} ID * @param {string} passage * @param {assignmentCallback} [callback] @@ -846,7 +796,7 @@ App.UI.jobLinks = function() { } /** - * Generates transfer links (as a DocumentFragment) + * Generates transfer links * @param {number} ID * @param {assignmentCallback} [callback] * @returns {DocumentFragment} @@ -956,11 +906,11 @@ globalThis.assignmentTransition = function(slave, assignTo, passage) { V.activeSlave = slave; // might be needed by the passage we're transitioning to (TODO: get rid of this) assignJob(slave, assignTo); if (V.showAssignToScenes === 1 && slave.fetish !== "mindbroken") { - if (assignTo === "Dairy" && ((V.dairyStimulatorsSetting >= 2) || (V.dairyFeedersSetting >= 2) || (V.dairyPregSetting >= 2))) { + if (assignTo === Job.DAIRY && ((V.dairyStimulatorsSetting >= 2) || (V.dairyFeedersSetting >= 2) || (V.dairyPregSetting >= 2))) { detourThroughScene("Industrial Dairy Assignment Scene"); - } else if (assignTo === "Dairy" && (V.dairyRestraintsSetting === 0 && V.activeSlave.devotion > 0)) { + } else if (assignTo === Job.DAIRY && (V.dairyRestraintsSetting === 0 && V.activeSlave.devotion > 0)) { detourThroughScene("Free Range Dairy Assignment Scene"); - } else if (assignTo === "Brothel") { + } else if (assignTo === Job.BROTHEL) { detourThroughScene("Brothel Assignment Scene"); } else { Engine.play(passage); diff --git a/src/js/describePiercings.js b/src/js/describePiercings.js deleted file mode 100644 index e57c2f2e59847524a544f38eb12b3c31d4131b61..0000000000000000000000000000000000000000 --- a/src/js/describePiercings.js +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @param {App.Entity.SlaveState} slave - * @returns {string} Relevant slave tattoo, if present - */ -App.Desc.piercing = function(slave, surface) { - "use strict"; - let r = ``; - /* eslint-disable no-unused-vars*/ - const { - he, him, his, hers, himself, boy, He, His - } = getPronouns(slave); - /* eslint-enable */ - if (V.showBodyMods !== 1) { - return; - } - switch (surface) { - case "ear": { - r += `<<earPiercingDescription>>`; - break; - } - case "nose": { - r += `<<nosePiercingDescription>>`; - break; - } - case "eyebrow": { - r += `<<eyebrowPiercingDescription>>`; - break; - } - case "lips": { - r += `<<lipsPiercingDescription>>`; - break; - } - case "tongue": { - r += `<<tonguePiercingDescription>>`; - break; - } - case "nipple": { - r += `<<nipplesPiercingDescription>>`; - break; - } - case "areolae": { - r += `<<areolaePiercingDescription>>`; - break; - } - case "navel": { - r += `<<navelPiercingDescription>>`; - break; - } - case "clit": { - r += `<<clitPiercingDescription>>`; - break; - } - case "vagina": { - r += `<<vaginaPiercingDescription>>`; - break; - } - case "dick": { - r += `<<dickPiercingDescription>>`; - break; - } - case "anus": { - r += `<<anusPiercingDescription>>`; - break; - } - case "corset": { // non anatomical - r += `<<CorsetPiercingDescription>>`; - break; - } - case "chastity": { // non anatomical - r += `<<chastityPiercingDescription>>`; - break; - } - } - return r; -}; diff --git a/src/js/main.js b/src/js/main.js index e65ab93f01e88162c8087e8b24104f8c0d9e0978..1854c4e6343b57ee130cb45a5faad2fcb66b0a0e 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -162,11 +162,11 @@ App.MainView.useFucktoy = function(slave) { * @returns {HTMLDivElement} */ App.MainView.useGuard = function() { - const guard = V.slaves[V.slaveIndices[V.Bodyguard.ID]]; + const guard = S.Bodyguard; const outerDiv = document.createElement("div"); - if (guard === undefined || guard.assignment !== "guard you") { + if (!guard || guard.assignment !== "guard you") { return outerDiv; } @@ -273,5 +273,5 @@ App.MainView.full = function() { fragment.append(App.MainView.useGuard()); } - return App.UI.DOM.includeDOM(fragment, "mainFullDOM"); + return fragment; }; diff --git a/src/js/rulesAssistantOptions.js b/src/js/rulesAssistantOptions.js index efcb5b411d6c9ed78e2120a1353619fe6b93633a..c16dd5d33808bf0d56e4d505652c24b3a48ef97b 100644 --- a/src/js/rulesAssistantOptions.js +++ b/src/js/rulesAssistantOptions.js @@ -1317,7 +1317,7 @@ globalThis.rulesAssistantOptions = (function() { } const explanation = document.createElement("div"); - explanation.innerHTML = "Insert a valid <a target='_blank' class='link-external' href='https://www.w3schools.com/js/js_comparisons.asp'>JavaScript comparison and/or logical operation</a>."; + explanation.innerHTML = `Insert <kbd>(slave) =></kbd> followed by a valid <a target='_blank' class='link-external' href='https://www.w3schools.com/js/js_comparisons.asp'>JavaScript comparison and/or logical operation</a>.`; elem.appendChild(explanation); return elem; } diff --git a/src/js/utilsDOM.js b/src/js/utilsDOM.js index 030d439d05b4ce89a7f167a956f3278c737e9283..25cbe24234b9c02415a77302d294d5c3c9d62de8 100644 --- a/src/js/utilsDOM.js +++ b/src/js/utilsDOM.js @@ -251,21 +251,6 @@ App.UI.DOM.colorInput = function(defaultValue, onEnter) { return input; }; -/** - * @param {Node} node - * @param {string} [uniqueID] - should be unique in the whole passage - * @param {string} [tag] - * @returns {string} - */ -App.UI.DOM.includeDOM = function(node, uniqueID, tag = "span") { - if (uniqueID === undefined) { - uniqueID = Math.random().toString(36).substring(2, 10); // TODO not perfect, but works for now - } - $(document).one(':passagedisplay', () => { $(`#inclDOM${uniqueID}`).append(node); }); - - return `<${tag} id='inclDOM${uniqueID}'></${tag}>`; -}; - /** * Concats an array of DOM nodes or strings into a human readable list. * diff --git a/src/js/utilsSC.js b/src/js/utilsSC.js index af511e4ad9b774c250bdd8ce8896c46250da1c2f..7220553e7049efef3aa861447665c84a6d3b6bad 100644 --- a/src/js/utilsSC.js +++ b/src/js/utilsSC.js @@ -278,8 +278,9 @@ App.UI._showDescriptionDialog = function(slave) { const oldActiveSlave = V.activeSlave; V.activeSlave = slave; Dialog.setup(SlaveFullName(slave)); - const image = V.seeImages ? `<div class="imageRef medImg"><<= SlaveArt($activeSlave, 2, 0)>></div>` : ``; - Dialog.wiki(`${image}<<include "Long Slave Description">>`); + const image = App.UI.DOM.makeElement("div", App.Art.SlaveArtElement(slave, 2, 0), ["imageRef", "medImg"]); + const lsd = App.UI.DOM.renderPassage("Long Slave Description"); + Dialog.append(image).append(lsd); Dialog.open(); V.activeSlave = oldActiveSlave; V.eventDescription = oldEventDescription; diff --git a/src/npc/descriptions/describeBrands.js b/src/npc/descriptions/describeBrands.js new file mode 100644 index 0000000000000000000000000000000000000000..19250234f7101169ef52da0a0ba3eb7bc09ab00b --- /dev/null +++ b/src/npc/descriptions/describeBrands.js @@ -0,0 +1,115 @@ +/** + * @param {App.Entity.SlaveState} slave + * @returns {string} Slave's brand. Slave is the slave in question, but call the body part without modifiers. Rather than using "left breast" and "right breast" just use "breast". The function will then describe any brands on the breasts, if present, in natural language. + */ +App.Desc.brand = function(slave, surface) { + "use strict"; + let r = ``; + const bellyAccessory = slave.bellyAccessory; + /* eslint-disable no-unused-vars*/ + const { + he, him, his, hers, himself, boy, He, His + } = getPronouns(slave); + /* eslint-enable */ + if (V.showBodyMods === 1) { + if (surface === "extra") { // Make a sentence that describes all body parts that aren't explicitly described elsewhere in longSlave. If you brand a slave on her thumb, for instance. But why. + let extraMarks = App.Desc.extraMarks(slave, "brand"); + extraMarks = Object.keys(extraMarks); + let length = extraMarks.length; + if (length === 0) { + return r; + } else if (length === 1) { + r += `${He} also has a single unusual brand: `; + } else { + r += `${He} also has several unusual brands: `; + } + + // If L/R parts of this object match, they will be described in the same phrase. Length is used only to calculate punctuation, so we prepare to skip. + for (const bodyPart of extraMarks) { + if (bodyPart.startsWith("left ")) { + let right = "right " + bodyPart.replace("left ", ""); + if (slave.brand[bodyPart] && slave.brand[right]) { + length--; + } + } + } + let counter = 0; + for (const bodyPart of extraMarks) { + counter++; + surface = App.Desc.oppositeSides(bodyPart); + if (slave.brand[surface.center]) { // center defined, body part has no mirror. + r += `${slave.brand[surface.center]} branded into the flesh of ${his} ${surface.center}`; + } else { // Center not defined, body part has a mirror. + if (!slave.brand[surface.left] && !slave.brand[surface.right]) { + // no marks + } else if (bodyPart.startsWith("right ") && slave.brand[surface.left]) { + // we already described it on the left + } else if (slave.brand[surface.left] === slave.brand[surface.right]) { + // matching places and marks + // note that the slave.brand object won't have slave.brand["upper armS"] with an S defined, just the left and right, so we just use the left since we know they match. + r += `${slave.brand[surface.left]} branded into the flesh of both ${his} ${surface.both}`; + } else if (slave.brand[surface.left] && slave.brand[surface.right]) { + // matching places but different marks + r += `both ${slave.brand[surface.left]} branded into the flesh of ${his} ${surface.left}, and ${slave.brand[surface.right]} branded into ${his} ${surface.right}`; + } else if (slave.brand[surface.left]) { + // left + r += `${slave.brand[surface.left]} branded into the flesh of ${his} ${surface.left}`; + } else if (slave.brand[surface.right]) { + // right + r += `${slave.brand[surface.right]} branded into the flesh of ${his} ${surface.right}`; + } + } + if (counter === length) { + r += `. `; + } else if (counter === length - 1) { + r += `, and `; + } else if (counter < length) { + r += `, `; + } + } + } else if (surface) { /* describes a single branded body part */ + if (surface === "belly" && setup.fakeBellies.includes(bellyAccessory) && slave.brand.belly) { + r += `${His} fake belly has the same brand, ${slave.brand.belly}, as ${his} real one. `; + } else { + surface = App.Desc.oppositeSides(surface); + if (slave.brand[surface.center]) { // center defined, body part has no mirror. + r += `${He} has ${slave.brand[surface.center]} branded into the flesh of ${his} ${surface.center}. `; + } else { // Center not defined, body part has a mirror. + if (!slave.brand[surface.left] && !slave.brand[surface.right]) { + // no marks + } else if (slave.brand[surface.left] === slave.brand[surface.right]) { + // matching places and marks + // note that the slave.brand object won't have slave.brand["upper armS"] with an S defined, just the left and right, so we just use the left since we know they match. + r += `${He} has ${slave.brand[surface.left]} branded into the flesh of both ${his} ${surface.both}. `; + } else if (slave.brand[surface.left] && slave.brand[surface.right]) { + // matching places but different marks + r += `${He} has both ${slave.brand[surface.left]} branded into the flesh of ${his} ${surface.left}, and ${slave.brand[surface.right]} branded into ${his} ${surface.right}. `; + } else if (slave.brand[surface.left]) { + // left + r += `${He} has ${slave.brand[surface.left]} branded into the flesh of ${his} ${surface.left}. `; + } else if (slave.brand[surface.right]) { + // right + r += `${He} has ${slave.brand[surface.right]} branded into the flesh of ${his} ${surface.right}. `; + } + } + } + } else { /* describes all branded body parts */ + for (let [key, value] of Object.entries(slave.brand)) { + if (r === ``) { + r += `${He} has `; + } + if (key === "belly" && setup.fakeBellies.includes(bellyAccessory) && slave.brand.belly) { + r += `${value} branded on both ${his} real belly and ${his} fake one, `; + } else { + r += `${value} branded into the flesh of ${his} ${key}, `; + } + } + if (r !== ``) { + r += `marking ${him} as yours. `; + } else { + r += `${His} body is unmarked by brands. `; + } + } + } + return r; +}; diff --git a/src/npc/descriptions/describePiercings.js b/src/npc/descriptions/describePiercings.js new file mode 100644 index 0000000000000000000000000000000000000000..5b3a0f4ab424f020dd8fcfda047fbf112369a685 --- /dev/null +++ b/src/npc/descriptions/describePiercings.js @@ -0,0 +1,822 @@ +/** + * @param {App.Entity.SlaveState} slave + * @returns {string} Relevant slave tattoo, if present + */ +App.Desc.piercing = function(slave, surface) { + "use strict"; + let r = []; + /* eslint-disable no-unused-vars*/ + const { + he, him, his, hers, himself, boy, He, His + } = getPronouns(slave); + /* eslint-enable */ + if (V.showBodyMods !== 1) { + return; + } + switch (surface) { + case "ear": { + if (slave.earPiercing > 0) { + if (slave.earPiercing === 1) { + r.push(`${His} earlobes are conventionally pierced.`); + } else { + r.push(`${His} ears are heavily pierced, with multiple lobe piercings and a row of helix piercings.`); + } + if (slave.assignment === "get milked" || slave.assignment === "work in the dairy") { + r.push(`${He} has a plastic livestock tag in one ear to help identify ${him} for milking.`); + } else { + switch (slave.clothes) { + case "attractive lingerie": + case "attractive lingerie for a pregnant woman": + r.push(`${He}'s wearing pretty, womanly earrings.`); + break; + case "a bra": + case "a button-up shirt": + case "a button-up shirt and panties": + case "a sweater": + case "a sweater and panties": + case "a t-shirt": + case "a t-shirt and jeans": + case "a t-shirt and thong": + case "a tank-top": + case "a tank-top and panties": + case "a thong": + case "a tube top and thong": + case "an oversized t-shirt": + case "an oversized t-shirt and boyshorts": + case "boyshorts": + case "cutoffs": + case "panties": + r.push(`${He}'s wearing plain but pretty earrings.`); + break; + case "a nice pony outfit": + case "a slutty pony outfit": + r.push(`${He}'s wearing horseshoe shaped earrings.`); + break; + case "leather pants and pasties": + case "leather pants": + case "leather pants and a tube top": + case "a tube top": + r.push(`${He}'s wearing large hoop earrings.`); + break; + case "a gothic lolita dress": + r.push(`${He}'s wearing black earrings.`); + break; + case "a sports bra": + case "a one-piece swimsuit": + case "sport shorts and a t-shirt": + case "sport shorts and a sports bra": + case "sport shorts": + r.push(`${He}'s wearing cute, simple earrings.`); + break; + case "a skimpy loincloth": + r.push(`${He}'s wearing a pair of bone earrings.`); + break; + case "a police uniform": + r.push(`${He}'s wearing nightstick-shaped earrings.`); + break; + case "a succubus outfit": + r.push(`${He}'s wearing pentagram earrings.`); + break; + case "a fallen nuns habit": + case "a penitent nuns habit": + r.push(`${His} earrings mimic tiny crowns of thorns.`); + break; + case "a chattel habit": + r.push(`${He}'s wearing golden earrings in the shape of saintly nudes.`); + break; + case "a hijab and abaya": + case "a niqab and abaya": + r.push(`${He}'s wearing bronze earrings shaped like crescent moons.`); + break; + case "a klan robe": + case "a slutty klan robe": + r.push(`${He}'s wearing bronze earrings shaped like crucifixes.`); + break; + case "a long qipao": + case "a slutty qipao": + r.push(`${His} golden earrings resemble Eastern-style dragons.`); + break; + case "a string bikini": + case "cutoffs and a t-shirt": + case "a t-shirt and panties": + case "panties and pasties": + case "pasties": + case "jeans": + case "a sweater and cutoffs": + r.push(`${He}'s wearing girly earrings.`); + break; + case "a schoolgirl outfit": + r.push(`${He}'s wearing small girlish earrings.`); + break; + case "striped panties": + case "a striped bra": + case "striped underwear": + r.push(`${He}'s wearing big girlish earrings.`); + break; + case "a burkini": + case "a monokini": + r.push(`${He}'s wearing unobtrusive little stud earrings.`); + break; + case "a Santa dress": + r.push(`${His} earrings resemble little green pine trees.`); + break; + case "a mini dress": + case "an apron": + case "a hanbok": + r.push(`${He}'s wearing shiny pearl earrings.`); + break; + case "a hijab and blouse": + case "conservative clothing": + r.push(`${He}'s wearing small unobtrusive hoop earrings.`); + break; + case "a cybersuit": + case "a scalemail bikini": + r.push(`${He}'s wearing sharp and brutal-looking earrings.`); + break; + case "a kimono": + r.push(`${He}'s wearing gorgeous enameled earrings made to look like tiny koi.`); + break; + case "a burqa": + r.push(`${He}'s wearing cheap metal earrings with fake gems.`); + break; + case "a slave gown": + case "a halter top dress": + case "a ball gown": + case "a maternity dress": + r.push(`${He}'s wearing lovely diamond earrings; the stones are cut in an alluring, feminine style.`); + break; + case "slutty business attire": + r.push(`${He}'s wearing lovely diamond earrings; the stones are cut in a gaudy, nouveau riche style.`); + break; + case "nice business attire": + r.push(`${He}'s wearing lovely diamond earrings; the stones are cut in an assertive, unsubtle style.`); + break; + case "a slutty maid outfit": + r.push(`${He}'s wearing big hoop earrings inappropriate for a real maid.`); + break; + case "a nice maid outfit": + r.push(`${He}'s wearing conservative earrings like those a free maid could afford.`); + break; + case "harem gauze": + r.push(`${He}'s wearing broad gold earrings in faux-Arabian style.`); + break; + case "overalls": + case "Western clothing": + r.push(`${He}'s wearing earrings in the shape of a sheriff's star.`); + break; + case "a huipil": + r.push(`${He}'s wearing earrings in the shape of a stylized jaguar's head.`); + break; + case "a bunny outfit": + r.push(`${He}'s wearing earrings in the shape of a stylized rabbit's head.`); + break; + case "kitty lingerie": + r.push(`${He}'s wearing earrings in the shape of a stylized cat's head.`); + break; + case "a bimbo outfit": + r.push(`${He}'s wearing large, heart-shaped earrings.`); + break; + case "a courtesan dress": + r.push(`${He}'s wearing hanging earrings that accentuate each movement of ${his} head.`); + break; + case "slutty jewelry": + r.push(`${He}'s wearing gold earrings in the shape of a pair of`); + if (slave.dick > 0 && slave.balls === 0) { + r.push(`limp dicks.`); + } else if ((slave.dick > 0)) { + r.push(`erect cocks.`); + } else if ((slave.skill.oral >= 100)) { + r.push(`tongues.`); + } else if ((slave.boobs > 1000)) { + r.push(`heavy breasts.`); + } else { + r.push(`female bottoms.`); + } + break; + } + } + } + break; + } + case "nose": { + if (slave.nosePiercing === 1) { + r.push(`${He} has simple studs in $his nose.`); + } else if (slave.nosePiercing === 2) { + r.push(`${He} has nasal studs and a large septum ring.`); + if (slave.clothes === "slutty jewelry" && slave.earPiercing > 0) { + r.push(`${His} bangles include a light chain from ${his} nose ring to ${his} ear piercings on one side.`); + } + } + break; + } + case "eyebrow": { + if (slave.eyebrowPiercing === 1) { + r.push(`${He} has a simple stud in one eyebrow.`); + } else if (slave.eyebrowPiercing === 2) { + r.push(`${He} has multiple eyebrow rings.`); + } + break; + } + case "lips": { + if (slave.lipsPiercing === 1) { + r.push(`${He} has a simple lip piercing.`); + } else if (slave.lipsPiercing === 2) { + r.push(`${His} lips are heavily pierced.`); + } + break; + } + case "tongue": { + if (slave.tonguePiercing === 1) { + r.push(`${His} tongue bears a single stud, so oral sex with ${him} is a bit more fun.`); + } else if (slave.tonguePiercing === 2) { + r.push(`${His} tongue bears a row of studs, offering thorough stimulation to anyone ${he} blows.`); + } + if (canTalk(slave)) { + if (slave.lips >= 70 || slave.lipsPiercing === 2) { + r.push(`${He} can barely enunciate`); + if (slave.lipsPiercing === 2) { + r.push(`past ${his} piercings;`); + } else { + r.push(`with ${his} fat lips;`); + } + Enunciate(slave); + if (V.writtenTitle === V.enunciate.title) { + if (setup.badNames.includes(capFirstChar(V.writtenTitle))) { + r.push(`unfortunately`); + } else { + r.push(`fortunately`); + } + r.push(`'V.enunciate.title' is easy to pronounce.`); + } else { + r.push(`'V.writtenTitle' comes out as 'V.enunciate.title.'`); + } + } + } + break; + } + case "nipple": { + if (slave.fuckdoll > 0) { + if (slave.nipplesPiercing > 0) { + r.push(`${His} nipple piercings help secure the suit material to ${his} breasts.`); + } + } else { + if (slave.nipplesPiercing === 1) { + r.push(`${His} ${nippleColor(slave)} nipples have a simple piercing, which keeps them a little harder than they would normally be.`); + } else if (slave.nipplesPiercing === 2) { + r.push(`${His} ${nippleColor(slave)} nipples are heavily pierced with several rings and studs, and there is a chain between them.`); + if (slave.boobShape === "saggy" && slave.boobs > 2500) { + r.push(`It's been shortened to take advantage of the way ${his} tits sag, and holds ${his} ${nippleColor(slave)} nipples almost together, producing cleavage that runs from ${his} ${nippleColor(slave)} nipples all the way up to ${his} sternum.`); + } else { + r.push(`The constant tugging keeps ${his} ${nippleColor(slave)} nipples erect.`); + } + } + if (slave.nipplesPiercing > 0) { + switch (slave.clothes) { + case "kitty lingerie": + r.push(`The piercings slightly distort the shape of ${his} lacy bra's cleavage window.`); + break; + case "attractive lingerie": + r.push(`The piercings are a girly color, to complement ${his} lingerie.`); + break; + case "a succubus outfit": + r.push(`The piercings are severe steel, as befits a sex demon.`); + break; + case "uncomfortable straps": + r.push(`Each nipple bears a horizontal bar that is held forward of the steel ring that's part of ${his} outfit, constantly tugging them outward.`); + break; + case "restrictive latex": + r.push(`The piercings are tantalizingly visible under the latex.`); + break; + case "a fallen nuns habit": + r.push(`A tiny ebon cross on a short chain dangles from each piercing.`); + break; + case "a chattel habit": + r.push(`A tiny golden cock and balls dangles from each piercing.`); + break; + case "a monokini": + r.push(`Due to ${his} toplessness, the piercings are plainly visible.`); + break; + case "a cybersuit": + r.push(`The piercings are tantalizingly visible under the bodysuit.`); + break; + case "a string bikini": + r.push(`The piercings are a pastel color, to complement ${his} bikini.`); + break; + case "striped panties": + r.push(`The piercings are a pastel color, to complement ${his} panties.`); + break; + case "a scalemail bikini": + r.push(`The piercings are severe steel, as befits a hardened warrior.`); + break; + case "a schoolgirl outfit": + if (slave.boobs <= 2000) { + r.push(`The piercings are tantalizingly visible under the thin material.`); + } + break; + case "battledress": + r.push(`The piercings are tantalizingly visible under ${his} tank top.`); + break; + case "nice business attire": + r.push(`One side of each piercing peeks over the edge of ${his} blouse.`); + break; + case "a comfortable bodysuit": + r.push(`The piercings are tantalizingly visible under the tight bodysuit.`); + break; + case "a latex catsuit": + r.push(`The piercings are tantalizingly visible under the tight latex catsuit.`); + break; + case "a mini dress": + r.push(`The piercings are tantalizingly visible under the tight mini dress.`); + break; + case "a courtesan dress": + r.push(`The piercings are tantalizingly visible through ${his} thin dress.`); + break; + case "a bimbo outfit": + r.push(`They can't be seen, but one can clearly feel the piercings are in the shape of hearts.`); + break; + case "a slutty maid outfit": + r.push(`One side of each piercing peeks over the edge of ${his} lacy top.`); + break; + case "harem gauze": + r.push(`The piercings are tantalizingly visible under the gauze.`); + break; + case "attractive lingerie for a pregnant woman": + r.push(`The piercings are tantalizingly visible under the thin silk.`); + break; + case "a maternity dress": + r.push(`The piercings are tantalizingly visible under the dress's tight top.`); + break; + case "stretch pants and a crop-top": + r.push(`The piercings are tantalizingly visible under ${his} crop-top.`); + break; + } + } + } + + break; + } + case "areolae": { + r.push(App.Desc.areolaePiercing(slave)); + break; + } + case "navel": { + if (slave.fuckdoll === 0) { + if (setup.fakeBellies.includes(slave.bellyAccessory)) { + if (slave.navelPiercing === 1) { + r.push(`${His} fake navel bears a simple stud.`); + } else if (slave.navelPiercing === 2) { + r.push(`${His} fake navel is pierced with a big ring.`); + if (slave.clothes === "slutty jewelry") { + r.push(`It has a length of gilded chain dangling from it.`); + } else { + r.push(`It has a short length of chain dangling from it.`); + } + } + } else { + if (slave.navelPiercing === 1) { + r.push(`${His} navel bears a simple stud.`); + } else if (slave.navelPiercing === 2) { + r.push(`${His} navel is pierced with a big ring.`); + if (slave.clothes === "slutty jewelry") { + r.push(`It has a length of gilded chain dangling from it.`); + } else { + r.push(`It has a short length of chain dangling from it.`); + } + } + } + } else { + if (slave.navelPiercing > 0) { + if (slave.belly >= 10000) { + if (slave.navelPiercing === 1) { + r.push(`${His} popped navel bears a simple stud.`); + } else if (slave.navelPiercing === 2) { + r.push(`${His} popped navel is pierced with a big ring.`); + } + r.push(`It's eye-catching, since most of ${his} piercings are hidden by the suit.`); + } else { + r.push(`${His} navel piercing runs through the suit's material.`); + } + } + } + break; + } + case "clit": { + if (slave.clitPiercing === 1 && slave.vagina !== -1) { + r.push(`${He} has a simple clitoral stud.`); + } else if (slave.clitPiercing === 2 && slave.vagina !== -1) { + r.push(`${He} has a big ring in ${his} clit.`); + if (slave.clothes === "slutty jewelry") { + r.push(`Since ${he}'s wearing slutty bangles ${he} has a short length of light chain dangling from ${his} clit ring; it constantly stimulates ${his} pussylips.`); + } + } else if (slave.clitPiercing === 3 && slave.vagina !== -1 && slave.dick === 0) { + r.push(`${He} has a smart piercing in ${his} clit.`); + } else if (slave.clitPiercing === 1) { + r.push(`${He} has a simple dickhead stud.`); + } else if (slave.clitPiercing === 2) { + r.push(`${He} has a big ring in ${his} dickhead.`); + if (slave.clothes === "slutty jewelry") { + r.push(`Since ${he}'s wearing slutty bangles ${he} has a short length of light chain dangling from ${his} dickhead piercing; as ${he} moves it tugs lightly at ${his} cock.`); + } + } else if ((slave.clitPiercing === 3)) { + r.push(`${He} has a smart frenulum piercing.`); + } + if (slave.fuckdoll > 0) { + r.push(`It anchors the suit's material.`); + } + break; + } + case "vagina": { + if (slave.vagina !== -1) { + if (slave.vaginaPiercing > 0) { + r.push(`${He} has a`); + if (slave.vaginaPiercing === 1) { + r.push(`simple row of studs`); + } else { + r.push(`row of big rings`); + } + r.push(`down ${his}`); + if (slave.fuckdoll > 0) { + r.push(`labia, which are looped into the edge of the suit's material as it stops around ${his} vulva.`); + } else { + r.push(`labia.`); + } + } + } + break; + } + case "dick": { + if (slave.dick !== 0) { + if (slave.dickPiercing === 1) { + r.push(`${He} has a row of studs down ${his} shaft.`); + } else if ((slave.dickPiercing === 2)) { + r.push(`${He} has a row of heavy rings down ${his} shaft.`); + } + if (slave.scrotum !== 0) { + if (slave.dickPiercing === 1) { + r.push(`${He} has a couple of studs in ${his} ballsack.`); + } else if ((slave.dickPiercing === 2)) { + r.push(`${He} has a row of rings down the center of ${his} ballsack, all the way from the base of ${his} shaft to ${his} perineum.`); + } + } else { + if (slave.dickPiercing === 1) { + r.push(`${He} has a couple of studs beneath the base of ${his} dick.`); + } else if ((slave.dickPiercing === 2)) { + r.push(`${He} has a row of rings all the way from the base of ${his} shaft to ${his} perineum.`); + } + } + } + if (slave.fuckdoll > 0) { + if (slave.dickPiercing > 0) { + r.push(`Every one of them runs through the suit's material, securing it to the Fuckdoll's member.`); + } + } + break; + } + case "anus": { + if (slave.vagina > -1) { + if (slave.anusPiercing === 1) { + r.push(`${He} has a simple piercing between ${his} pussy and ${his}`); + if (slave.fuckdoll > 0) { + r.push(`asshole which helps keep the strip of material`); + if (slave.vagina > -1) { + r.push(`between ${his} holes`); + } else { + r.push(`below ${his} rear hole`); + } + r.push(`in place.`); + } else { + r.push(`asshole.`); + } + } else if ((slave.anusPiercing === 2)) { + r.push(`${He} has a big ring between ${his} pussy and ${his} asshole`); + if (slave.fuckdoll > 0) { + r.push(`, which helps keep the strip of material`); + if (slave.vagina > -1) { + r.push(`between ${his} holes`); + } else { + r.push(`below ${his} rear hole`); + } + r.push(`in place,`); + } + r.push(`and studs in all around ${his} anus.`); + } + } else { + if (slave.anusPiercing === 1) { + r.push(`${He} has a simple perianal piercing between the base of ${his} dick and ${his} girly`); + if (slave.fuckdoll > 0) { + r.push(`butthole which helps keep the strip of material`); + if (slave.vagina > -1) { + r.push(`between ${his} holes`); + } else { + r.push(`below ${his} rear hole`); + } + r.push(`in place.`); + } else { + r.push(`butthole.`); + } + } else if ((slave.anusPiercing === 2)) { + r.push(`${He} has a big ring between the base of ${his} dick and ${his} girly butthole, which has studs all around it.`); + } + } + break; + } + case "corset": { // non anatomical + if (slave.corsetPiercing > 0) { + if (slave.fuckdoll === 0) { + r.push(`${He} has a corset piercing, a ladder of steel rings running up each side of ${his} back:`); + if (slave.bellyAccessory === "a corset" || slave.bellyAccessory === "an extreme corset") { + r.push(`these are looped through special lugs in the back of ${his} actual corset, making it almost a part of ${his} body.`); + if (slave.devotion > 50) { + r.push(`${He} couldn't remove it, even if ${he} wanted to.`); + } else if (slave.devotion >= -20) { + r.push(`${He} couldn't remove it, even if ${he} were inclined to try.`); + } else { + r.push(`Any attempt to remove it will cause intense pain.`); + } + } else { + switch (slave.clothes) { + case "a hijab and blouse": + case "a schoolgirl outfit": + case "conservative clothing": + case "nice business attire": + case "slutty business attire": + r.push(`${his} blouse hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "chains": + r.push(`they're laced together with steel cable, tightly enough that they're tugging at ${his} skin.`); + break; + case "Western clothing": + r.push(`${his} shirt hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "a toga": + r.push(`${his} toga hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "a huipil": + r.push(`${his} huipil hides them partially, so the leather straps that pull on ${his} skin are clearly evident.`); + break; + case "a long qipao": + case "a slutty qipao": + r.push(`${his} qipao hides them completely, but they're laced tightly with silk cord, so ${he}'s aware they're there.`); + break; + case "uncomfortable straps": + r.push(`they're laced together with a leather cord, tightly enough that they're tugging at ${his} skin.`); + break; + case "shibari ropes": + r.push(`they're laced together as part of ${his} bindings.`); + break; + case "a latex catsuit": + case "restrictive latex": + r.push(`these are clipped into the latex covering them, making it almost a part of ${his} body.`); + if (slave.devotion > 50) { + r.push(`${He} couldn't remove it, even if ${he} wanted to.`); + } else if (slave.devotion >= -20) { + r.push(`${He} couldn't remove it, even if ${he} were inclined to try.`); + } else { + r.push(`Any attempt to remove it will cause intense pain.`); + } + break; + case "a military uniform": + r.push(`${his} tunic hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "a schutzstaffel uniform": + r.push(`${his} tunic hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "a slutty schutzstaffel uniform": + r.push(`${his} tunic hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "a red army uniform": + r.push(`${his} tunic hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "battlearmor": + r.push(`${his} armor hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "a dirndl": + r.push(`${his} dress hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "lederhosen": + r.push(`${his} tunic hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "a mounty outfit": + r.push(`${his} tunic hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "a biyelgee costume": + r.push(`${his} dress hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "a nice nurse outfit": + r.push(`${his} scrubs hide them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "a mini dress": + r.push(`these are clipped into the mini dress covering them, making it almost a part of ${his} body.`); + if (slave.devotion > 50) { + r.push(`${He} couldn't remove it, even if ${he} wanted to.`); + } else if (slave.devotion >= -20) { + r.push(`${He} couldn't remove it, even if ${he} were inclined to try.`); + } else { + r.push(`Any attempt to remove it will cause intense pain.`); + } + break; + case "attractive lingerie": + case "attractive lingerie for a pregnant woman": + case "kitty lingerie": + r.push(`they're laced together with a lacy ribbon finished off with a bow.`); + break; + case "a succubus outfit": + r.push(`they're laced into ${his} succubus corset, making it a part of ${him}.`); + break; + case "a fallen nuns habit": + r.push(`they're laced together with cord, tightly enough that ${he} is forced to arch ${his} back or suffer. ${He} spends most of ${his} time involuntarily presenting ${his} bottom to relieve the tugging.`); + break; + case "a chattel habit": + r.push(`${his} white habit hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "a penitent nuns habit": + r.push(`${his} habit hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "a gothic lolita dress": + case "a hanbok": + case "a Santa dress": + r.push(`${his} dress hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "a burkini": + case "a one-piece swimsuit": + r.push(`${his} swimsuit hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "a monokini": + r.push(`the straps of ${his} swimsuit run on each side of these loops.`); + break; + case "an apron": + r.push(`the straps of ${his} apron run on each side of these loops.`); + break; + case "overalls": + r.push(`the straps of ${his} overalls run on each side of these loops.`); + break; + case "a bra": + case "a skimpy loincloth": + case "a striped bra": + case "a thong": + case "boyshorts": + case "cutoffs": + case "jeans": + case "leather pants": + case "leather pants and pasties": + case "panties": + case "panties and pasties": + case "pasties": + case "sport shorts": + case "striped panties": + case "striped underwear": + r.push(`the piercings are plainly visible on ${his} bare back.`); + break; + case "a slutty klan robe": + case "a slutty pony outfit": + case "a sports bra": + case "a tank-top and panties": + case "a tube top": + case "a tube top and thong": + case "leather pants and a tube top": + r.push(`the piercings are only partly visible on ${his} back.`); + break; + case "a button-up shirt": + case "a button-up shirt and panties": + case "a police uniform": + case "a t-shirt and jeans": + case "a t-shirt and panties": + case "a t-shirt and thong": + case "a t-shirt": + case "a tank-top": + case "an oversized t-shirt and boyshorts": + case "an oversized t-shirt": + case "sport shorts and a sports bra": + case "sport shorts and a t-shirt": + r.push(`${his} shirt hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "a sweater": + case "a sweater and cutoffs": + case "a sweater and panties": + r.push(`${his} sweater hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "a nice pony outfit": + r.push(`${his} outfit hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "a string bikini": + r.push(`the back of ${his} string top loops into them and runs down through them to become ${his} bottom, such as it is.`); + break; + case "a scalemail bikini": + r.push(`they're laced together with a steel chain.`); + break; + case "a cheerleader outfit": + r.push(`they're laced together with a simple ribbon, but the effect makes it clear that this is one kinky cheerleader.`); + break; + case "clubslut netting": + r.push(`these are clipped into the netting covering them, making it almost a part of ${his} body.`); + if (slave.devotion > 50) { + r.push(`${He} couldn't remove it, even if ${he} wanted to.`); + } else if (slave.devotion >= -20) { + r.push(`${He} couldn't remove it, even if ${he} were inclined to try.`); + } else { + r.push(`Any attempt to remove it will cause intense pain.`); + } + break; + case "cutoffs and a t-shirt": + r.push(`they're laced together with a simple ribbon, but the effect makes it clear that this is one kinky ${girl}.`); + break; + case "a slutty outfit": + r.push(`they're laced together with a simple ribbon, tightly enough that ${he}'s aware they're there.`); + break; + case "a slave gown": + r.push(`they're revealed by the swooping back of ${his} gown and laced up with matching silk ribbon.`); + break; + case "a comfortable bodysuit": + r.push(`these are clipped into the bodysuit covering them, making it almost a part of ${his} body.`); + if (slave.devotion > 50) { + r.push(`${He} couldn't remove it, even if ${he} wanted to.`); + } else if (slave.devotion >= -20) { + r.push(`${He} couldn't remove it, even if ${he} were inclined to try.`); + } else { + r.push(`Any attempt to remove it will cause intense pain.`); + } + break; + case "a leotard": + r.push(`these are clipped into the leotard covering them, making it almost a part of ${his} body.`); + if (slave.devotion > 50) { + r.push(`${He} couldn't remove it, even if ${he} wanted to.`); + } else if (slave.devotion >= -20) { + r.push(`${He} couldn't remove it, even if ${he} were inclined to try.`); + } else { + r.push(`Any attempt to remove it will cause intense pain.`); + } + break; + case "a bunny outfit": + r.push(`${his} teddy hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "a slutty maid outfit": + r.push(`${his} dress has an open back to reveal them and the black ribbon that laces them tightly together.`); + break; + case "a nice maid outfit": + r.push(`${his} dress hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "a slutty nurse outfit": + r.push(`${his} jacket hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "a kimono": + r.push(`${his} kimono hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "a hijab and abaya": + case "a niqab and abaya": + r.push(`${his} abaya hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "a klan robe": + r.push(`${his} robe hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "a burqa": + r.push(`${his} burqa hides them completely, but they're laced tightly, so ${he}'s aware they're there.`); + break; + case "battledress": + r.push(`they're laced together with paracord.`); + break; + case "harem gauze": + r.push(`they're laced up with a light golden chain that glints through ${his} filmy clothing.`); + break; + case "slutty jewelry": + r.push(`they're laced up with a light golden chain that begins and ends in other parts of ${his} glinting bonds.`); + break; + case "a courtesan dress": + r.push(`they're laced into ${his} dress's corset, binding the material even closer to ${him}.`); + break; + case "a bimbo outfit": + r.push(`they're laced together with a bright pink ribbon.`); + break; + default: + r.push(`they're laced up with a ribbon, tightly enough to keep ${him} aware they're there.`); + } + } + } + } + break; + } + case "chastity": { // non anatomical + if (slave.clitPiercing > 0) { + if (slave.nipplesPiercing > 0) { + if (!(slave.chastityPenis)) { + if (slave.dick > 4) { + if (slave.boobs > 1000) { + if (canAchieveErection(slave.balls > 0)) { + if (slave.devotion > 20) { + if (slave.energy > 90) { + r.push(`${His} very special body allows ${him} to wear an incredibly lewd piece of jewelry: a thin golden chain that runs from nipple to nipple, through ${his} pierced cockhead. The chain is short, and any motion at all tugs at ${his} nipples and penis.`); + if (canWalk(slave)) { + r.push(`The stimulation is almost unbearable, and the mere act of walking sometimes causes ${him} to cum.`); + } + } + } + } + } + } + } + } + } + break; + } + } + return r.join(" "); +}; diff --git a/src/npc/descriptions/describeScars.js b/src/npc/descriptions/describeScars.js new file mode 100644 index 0000000000000000000000000000000000000000..2c8faa1ab3a09b73f68d1aa1d4173f5a5a58b7db --- /dev/null +++ b/src/npc/descriptions/describeScars.js @@ -0,0 +1,288 @@ +/** + * @param {App.Entity.SlaveState} slave + * @returns {string} Slave's scar. Slave is the slave in question, but call the body part without modifiers. Rather than using "left breast" and "right breast" just use "breast". The function will then describe any scars on the breasts, if present, in natural language. + */ +App.Desc.scar = function(slave, surface) { + "use strict"; + let r = ``; + const bellyAccessory = slave.bellyAccessory; + /* eslint-disable no-unused-vars*/ + const { + he, him, his, hers, himself, boy, He, His + } = getPronouns(slave); + /* eslint-enable */ + if (V.showBodyMods === 1) { + if (surface === "extra") { // Make a sentence that describes all body parts that aren't explicitly described elsewhere in longSlave. If you scar a slave on her thumb, for instance. But why. + let extraMarks = App.Desc.extraMarks(slave, "scar"); + extraMarks = Object.keys(extraMarks); + let length = extraMarks.length; + if (length === 0) { + return r; + } else if (length === 1) { + r += `${He} also has a single unusual scar: `; + } else { + r += `${He} also has several unusual scars: `; + } + + // If L/R parts of this object match, they will be described in the same phrase. Length is used only to calculate punctuation, so we prepare to skip. + for (const bodyPart of extraMarks) { + if (bodyPart.startsWith("left ")) { + let right = "right " + bodyPart.replace("left ", ""); + if (slave.scar[bodyPart] && slave.scar[right]) { + length--; + } + } + } + let counter = 0; + for (const bodyPart of extraMarks) { + counter++; + surface = App.Desc.oppositeSides(bodyPart); + if (slave.scar[surface.center]) { // center defined, body part has no mirror. + r += `${App.Desc.expandScarString(slave, surface.center)} on ${his} ${surface.center}`; + } else { // Center not defined, body part has a mirror. + let left = App.Desc.expandScarString(slave, surface.left); + let right = App.Desc.expandScarString(slave, surface.right); + if (!slave.scar[surface.left] && !slave.scar[surface.right]) { + // no marks + } else if (bodyPart.startsWith("right ") && slave.scar[surface.left]) { + // we already described it on the left + } else if (left === right) { + // matching places and marks + // note that the slave.scar object won't have slave.scar["upper armS"] with an S defined, just the left and right, so we just use the left since we know they match. + r += `${left} on both ${his} ${surface.both}`; + } else if (slave.scar[surface.left] && slave.scar[surface.right]) { + // matching places but different marks + r += `both ${left} on ${his} ${surface.left}, and ${right} scared into ${his} ${surface.right}`; + } else if (slave.scar[surface.left]) { + // left + r += `${left} on ${his} ${surface.left}`; + } else if (slave.scar[surface.right]) { + // right + r += `${right} on ${his} ${surface.right}`; + } + } + if (counter === length) { + r += `. `; + } else if (counter === length - 1) { + r += `, and `; + } else if (counter < length) { + r += `, `; + } + } + } else if (surface) { /* describes a single scarred body part */ + surface = App.Desc.oppositeSides(surface); + if (surface.center === "belly" && setup.fakeBellies.includes(bellyAccessory) && slave.scar.hasOwnProperty("belly")) { + r += `${His} fake belly has the same scar, ${App.Desc.expandScarString(slave, surface.center)}, as ${his} real one. `; + } else { + if (slave.scar[surface.center]) { // center defined, body part has no mirror. + r += `${He} has ${App.Desc.expandScarString(slave, surface.center)} on ${his} ${surface.center}. `; + } else { // Center not defined, body part has a mirror. + let left = App.Desc.expandScarString(slave, surface.left); + let right = App.Desc.expandScarString(slave, surface.right); + if (!slave.scar[surface.left] && !slave.scar[surface.right]) { + // no marks + } else if (left === right) { + // matching places and marks + // note that the slave.scar object won't have slave.scar["upper armS"] with an S defined, just the left and right, so we just use the left since we know they match. + r += `${He} has ${left} on both ${his} ${surface.both}. `; + } else if (slave.scar[surface.left] && slave.scar[surface.right]) { + // matching places but different marks + r += `${He} has both ${left} on ${his} ${surface.left}, and ${right} scared into ${his} ${surface.right}. `; + } else if (slave.scar[surface.left]) { + // left + r += `${He} has ${left} on ${his} ${surface.left}. `; + } else if (right) { + // right + r += `${He} has ${right} on ${his} ${surface.right}. `; + } + } + } + } else { /* describes all scarred body parts */ + for (let [key, value] of Object.entries(slave.scar)) { + if (r === ``) { + r += `${He} has `; + } + if (key === "belly" && setup.fakeBellies.includes(bellyAccessory) && slave.scar.hasOwnProperty("belly")) { + r += `${value} scared on both ${his} real belly and ${his} fake one, `; + } else { + r += `${value} on ${his} ${key}, `; + } + } + if (r !== ``) { + r += `marking ${him} as yours. `; + } else { + r += `${His} body is unmarked by scars. `; + } + } + } + return r; +}; + +/** + * @param {App.Entity.SlaveState} slave + * @returns {string} Slave's scar. Slave is the slave in question, but call the body part without modifiers. Rather than using "left breast" and "right breast" just use "breast". The function will then describe any scars on the breasts, if present, in natural language. + */ +App.Desc.expandScarString = function(slave, surface) { // scars can sometimes be an int. This function generates a reasonable description. It can later be expanded to apply to different body parts, or include features of the slave such as skin tone or weight + let r = ""; + if (!slave.scar[surface]) { + return r; + } + const bodypart = Object.keys(slave.scar[surface]); + for (const kind of bodypart) { + let scar = slave.scar[surface][kind]; + if (scar === 0) { + continue; + } + if (r !== "") { + r += ", "; + } + switch (kind) { + case "generic": + r += "a generic scar"; + break; + case "whip": + if (["back"].includes(surface)) { + r += "a "; + if (scar > 2) { + r += "deeply scored "; + } + if (scar > 1) { + r += "network of welts like a map of hell"; + } else { + r += "record of being beaten"; + } + } else if (["left breast", "right breast", "left buttock", "right buttock"].includes(surface)) { + if (scar > 2) { + r += "thick "; + } else { + r += "thin "; + } + r += "raised lines from a whip tracing the curves"; + } else if (["left upper arm", "right upper arm"].includes(surface)) { + r += "rough edges where a whip abused $his skin"; + } else { + if (scar > 2) { + r += "frightening "; + } else if (scar > 1) { + r += "serious "; + } + r += "whip scars"; + } + break; + case "chain": + if (["left wrist", "right wrist", "left ankle", "right ankle"].includes(surface)) { + if (scar > 1) { + r += "scars from heavy manacles"; + } else { + r += "scars from manacles"; + } + } else { + if (scar > 1) { + r += "scars from heavy chains"; + } else { + r += "scars from chains"; + } + } + break; + case "burn": + if (scar > 2) { + r += "frightening "; + } else if (scar > 1) { + r += "serious "; + } + r += "burn scars"; + break; + case "menacing": + r += "a menacing scar"; + break; + case "exotic": + r += "an exotic scar"; + break; + case "surgical": + if (surface === "left breast" || surface === "right breast") { + if (slave.boobsImplant > 0) { + r += "scars from "; + if (scar > 3) { + r += "horribly botched "; + } else if (scar > 2) { + r += "sloppily inserted "; + } else if (scar > 1) { + r += "carelessly inserted "; + } + r += "implants"; + } else { + r += "scars from "; + if (scar > 3) { + r += "horribly botched "; + } else if (scar > 2) { + r += "sloppily done "; + } else if (scar > 1) { + r += "carelessly done "; + } + r += "surgery to remove implants"; + } + } else if (surface === "left buttock" || surface === "right buttock") { + if (slave.buttImplant > 0) { + r += "scars from "; + if (scar > 3) { + r += "horribly botched "; + } else if (scar > 2) { + r += "sloppily inserted "; + } else if (scar > 1) { + r += "carelessly inserted "; + } + r += "implants"; + } else { + r += "scars from "; + if (scar > 3) { + r += "horribly botched "; + } else if (scar > 2) { + r += "sloppily done "; + } else if (scar > 1) { + r += "carelessly done "; + } + r += "surgery to remove implants"; + } + } else if (surface === "belly" ) { + r += "scars from "; + if (scar > 1) { + r += "a crazy network of scars, as though a hack had tried internal surgery"; + } else { + r += "some faint scarring as though from internal surgery"; + } + } else { + r += "a "; + if (scar > 1) { + r += "pronounced "; + } else { + r += "faint "; + } + r += "surgical scar"; + } + break; + case "c-section": + r += "an "; + if (scar > 1) { + r += "especially "; + } + r += "unsightly c-section scar"; + break; + case "cutting": + if (["left wrist", "right wrist", "neck"].includes(surface)) { + r += "some scars as though $he attempted self harm"; + } else { + r += "some cuts as though from a razor"; + } + break; + default: + if (scar > 2) { + r += "serious "; + } else if (scar) { + r += kind; + } + break; + } + } + r = r.replace(/,(?=[^,]*$)/, ' and'); /* replace the last comma with the word "and" so we can use this in a sentence.*/ + return r; +}; diff --git a/src/js/describeTattoos.js b/src/npc/descriptions/describeTattoos.js similarity index 100% rename from src/js/describeTattoos.js rename to src/npc/descriptions/describeTattoos.js diff --git a/src/js/descriptionWidgets.js b/src/npc/descriptions/descriptionWidgets.js similarity index 77% rename from src/js/descriptionWidgets.js rename to src/npc/descriptions/descriptionWidgets.js index 19ca5bfffd15fcd32a0fe3e6b85e08ed8f99f244..1baf15bd228a975f75149ccf633b44f8c2bf8baf 100644 --- a/src/js/descriptionWidgets.js +++ b/src/npc/descriptions/descriptionWidgets.js @@ -806,412 +806,6 @@ App.Desc.mods = function(slave, surface) { ); }; -/** - * @param {App.Entity.SlaveState} slave - * @returns {string} Slave's brand. Slave is the slave in question, but call the body part without modifiers. Rather than using "left breast" and "right breast" just use "breast". The function will then describe any brands on the breasts, if present, in natural language. - */ -App.Desc.brand = function(slave, surface) { - "use strict"; - let r = ``; - const bellyAccessory = slave.bellyAccessory; - /* eslint-disable no-unused-vars*/ - const { - he, him, his, hers, himself, boy, He, His - } = getPronouns(slave); - /* eslint-enable */ - if (V.showBodyMods === 1) { - if (surface === "extra") { // Make a sentence that describes all body parts that aren't explicitly described elsewhere in longSlave. If you brand a slave on her thumb, for instance. But why. - let extraMarks = App.Desc.extraMarks(slave, "brand"); - extraMarks = Object.keys(extraMarks); - let length = extraMarks.length; - if (length === 0) { - return r; - } else if (length === 1) { - r += `${He} also has a single unusual brand: `; - } else { - r += `${He} also has several unusual brands: `; - } - - // If L/R parts of this object match, they will be described in the same phrase. Length is used only to calculate punctuation, so we prepare to skip. - for (const bodyPart of extraMarks) { - if (bodyPart.startsWith("left ")) { - let right = "right " + bodyPart.replace("left ", ""); - if (slave.brand[bodyPart] && slave.brand[right]) { - length--; - } - } - } - let counter = 0; - for (const bodyPart of extraMarks) { - counter++; - surface = App.Desc.oppositeSides(bodyPart); - if (slave.brand[surface.center]) { // center defined, body part has no mirror. - r += `${slave.brand[surface.center]} branded into the flesh of ${his} ${surface.center}`; - } else { // Center not defined, body part has a mirror. - if (!slave.brand[surface.left] && !slave.brand[surface.right]) { - // no marks - } else if (bodyPart.startsWith("right ") && slave.brand[surface.left]) { - // we already described it on the left - } else if (slave.brand[surface.left] === slave.brand[surface.right]) { - // matching places and marks - // note that the slave.brand object won't have slave.brand["upper armS"] with an S defined, just the left and right, so we just use the left since we know they match. - r += `${slave.brand[surface.left]} branded into the flesh of both ${his} ${surface.both}`; - } else if (slave.brand[surface.left] && slave.brand[surface.right]) { - // matching places but different marks - r += `both ${slave.brand[surface.left]} branded into the flesh of ${his} ${surface.left}, and ${slave.brand[surface.right]} branded into ${his} ${surface.right}`; - } else if (slave.brand[surface.left]) { - // left - r += `${slave.brand[surface.left]} branded into the flesh of ${his} ${surface.left}`; - } else if (slave.brand[surface.right]) { - // right - r += `${slave.brand[surface.right]} branded into the flesh of ${his} ${surface.right}`; - } - } - if (counter === length) { - r += `. `; - } else if (counter === length - 1) { - r += `, and `; - } else if (counter < length) { - r += `, `; - } - } - } else if (surface) { /* describes a single branded body part */ - if (surface === "belly" && setup.fakeBellies.includes(bellyAccessory) && slave.brand.belly) { - r += `${His} fake belly has the same brand, ${slave.brand.belly}, as ${his} real one. `; - } else { - surface = App.Desc.oppositeSides(surface); - if (slave.brand[surface.center]) { // center defined, body part has no mirror. - r += `${He} has ${slave.brand[surface.center]} branded into the flesh of ${his} ${surface.center}. `; - } else { // Center not defined, body part has a mirror. - if (!slave.brand[surface.left] && !slave.brand[surface.right]) { - // no marks - } else if (slave.brand[surface.left] === slave.brand[surface.right]) { - // matching places and marks - // note that the slave.brand object won't have slave.brand["upper armS"] with an S defined, just the left and right, so we just use the left since we know they match. - r += `${He} has ${slave.brand[surface.left]} branded into the flesh of both ${his} ${surface.both}. `; - } else if (slave.brand[surface.left] && slave.brand[surface.right]) { - // matching places but different marks - r += `${He} has both ${slave.brand[surface.left]} branded into the flesh of ${his} ${surface.left}, and ${slave.brand[surface.right]} branded into ${his} ${surface.right}. `; - } else if (slave.brand[surface.left]) { - // left - r += `${He} has ${slave.brand[surface.left]} branded into the flesh of ${his} ${surface.left}. `; - } else if (slave.brand[surface.right]) { - // right - r += `${He} has ${slave.brand[surface.right]} branded into the flesh of ${his} ${surface.right}. `; - } - } - } - } else { /* describes all branded body parts */ - for (let [key, value] of Object.entries(slave.brand)) { - if (r === ``) { - r += `${He} has `; - } - if (key === "belly" && setup.fakeBellies.includes(bellyAccessory) && slave.brand.belly) { - r += `${value} branded on both ${his} real belly and ${his} fake one, `; - } else { - r += `${value} branded into the flesh of ${his} ${key}, `; - } - } - if (r !== ``) { - r += `marking ${him} as yours. `; - } else { - r += `${His} body is unmarked by brands. `; - } - } - } - return r; -}; - -/** - * @param {App.Entity.SlaveState} slave - * @returns {string} Slave's scar. Slave is the slave in question, but call the body part without modifiers. Rather than using "left breast" and "right breast" just use "breast". The function will then describe any scars on the breasts, if present, in natural language. - */ -App.Desc.scar = function(slave, surface) { - "use strict"; - let r = ``; - const bellyAccessory = slave.bellyAccessory; - /* eslint-disable no-unused-vars*/ - const { - he, him, his, hers, himself, boy, He, His - } = getPronouns(slave); - /* eslint-enable */ - if (V.showBodyMods === 1) { - if (surface === "extra") { // Make a sentence that describes all body parts that aren't explicitly described elsewhere in longSlave. If you scar a slave on her thumb, for instance. But why. - let extraMarks = App.Desc.extraMarks(slave, "scar"); - extraMarks = Object.keys(extraMarks); - let length = extraMarks.length; - if (length === 0) { - return r; - } else if (length === 1) { - r += `${He} also has a single unusual scar: `; - } else { - r += `${He} also has several unusual scars: `; - } - - // If L/R parts of this object match, they will be described in the same phrase. Length is used only to calculate punctuation, so we prepare to skip. - for (const bodyPart of extraMarks) { - if (bodyPart.startsWith("left ")) { - let right = "right " + bodyPart.replace("left ", ""); - if (slave.scar[bodyPart] && slave.scar[right]) { - length--; - } - } - } - let counter = 0; - for (const bodyPart of extraMarks) { - counter++; - surface = App.Desc.oppositeSides(bodyPart); - if (slave.scar[surface.center]) { // center defined, body part has no mirror. - r += `${App.Desc.expandScarString(slave, surface.center)} on ${his} ${surface.center}`; - } else { // Center not defined, body part has a mirror. - let left = App.Desc.expandScarString(slave, surface.left); - let right = App.Desc.expandScarString(slave, surface.right); - if (!slave.scar[surface.left] && !slave.scar[surface.right]) { - // no marks - } else if (bodyPart.startsWith("right ") && slave.scar[surface.left]) { - // we already described it on the left - } else if (left === right) { - // matching places and marks - // note that the slave.scar object won't have slave.scar["upper armS"] with an S defined, just the left and right, so we just use the left since we know they match. - r += `${left} on both ${his} ${surface.both}`; - } else if (slave.scar[surface.left] && slave.scar[surface.right]) { - // matching places but different marks - r += `both ${left} on ${his} ${surface.left}, and ${right} scared into ${his} ${surface.right}`; - } else if (slave.scar[surface.left]) { - // left - r += `${left} on ${his} ${surface.left}`; - } else if (slave.scar[surface.right]) { - // right - r += `${right} on ${his} ${surface.right}`; - } - } - if (counter === length) { - r += `. `; - } else if (counter === length - 1) { - r += `, and `; - } else if (counter < length) { - r += `, `; - } - } - } else if (surface) { /* describes a single scarred body part */ - surface = App.Desc.oppositeSides(surface); - if (surface.center === "belly" && setup.fakeBellies.includes(bellyAccessory) && slave.scar.hasOwnProperty("belly")) { - r += `${His} fake belly has the same scar, ${App.Desc.expandScarString(slave, surface.center)}, as ${his} real one. `; - } else { - if (slave.scar[surface.center]) { // center defined, body part has no mirror. - r += `${He} has ${App.Desc.expandScarString(slave, surface.center)} on ${his} ${surface.center}. `; - } else { // Center not defined, body part has a mirror. - let left = App.Desc.expandScarString(slave, surface.left); - let right = App.Desc.expandScarString(slave, surface.right); - if (!slave.scar[surface.left] && !slave.scar[surface.right]) { - // no marks - } else if (left === right) { - // matching places and marks - // note that the slave.scar object won't have slave.scar["upper armS"] with an S defined, just the left and right, so we just use the left since we know they match. - r += `${He} has ${left} on both ${his} ${surface.both}. `; - } else if (slave.scar[surface.left] && slave.scar[surface.right]) { - // matching places but different marks - r += `${He} has both ${left} on ${his} ${surface.left}, and ${right} scared into ${his} ${surface.right}. `; - } else if (slave.scar[surface.left]) { - // left - r += `${He} has ${left} on ${his} ${surface.left}. `; - } else if (right) { - // right - r += `${He} has ${right} on ${his} ${surface.right}. `; - } - } - } - } else { /* describes all scarred body parts */ - for (let [key, value] of Object.entries(slave.scar)) { - if (r === ``) { - r += `${He} has `; - } - if (key === "belly" && setup.fakeBellies.includes(bellyAccessory) && slave.scar.hasOwnProperty("belly")) { - r += `${value} scared on both ${his} real belly and ${his} fake one, `; - } else { - r += `${value} on ${his} ${key}, `; - } - } - if (r !== ``) { - r += `marking ${him} as yours. `; - } else { - r += `${His} body is unmarked by scars. `; - } - } - } - return r; -}; - -/** - * @param {App.Entity.SlaveState} slave - * @returns {string} Slave's scar. Slave is the slave in question, but call the body part without modifiers. Rather than using "left breast" and "right breast" just use "breast". The function will then describe any scars on the breasts, if present, in natural language. - */ -App.Desc.expandScarString = function(slave, surface) { // scars can sometimes be an int. This function generates a reasonable description. It can later be expanded to apply to different body parts, or include features of the slave such as skin tone or weight - let r = ""; - if (!slave.scar[surface]) { - return r; - } - const bodypart = Object.keys(slave.scar[surface]); - for (const kind of bodypart) { - let scar = slave.scar[surface][kind]; - if (scar === 0) { - continue; - } - if (r !== "") { - r += ", "; - } - switch (kind) { - case "generic": - r += "a generic scar"; - break; - case "whip": - if (["back"].includes(surface)) { - r += "a "; - if (scar > 2) { - r += "deeply scored "; - } - if (scar > 1) { - r += "network of welts like a map of hell"; - } else { - r += "record of being beaten"; - } - } else if (["left breast", "right breast", "left buttock", "right buttock"].includes(surface)) { - if (scar > 2) { - r += "thick "; - } else { - r += "thin "; - } - r += "raised lines from a whip tracing the curves"; - } else if (["left upper arm", "right upper arm"].includes(surface)) { - r += "rough edges where a whip abused $his skin"; - } else { - if (scar > 2) { - r += "frightening "; - } else if (scar > 1) { - r += "serious "; - } - r += "whip scars"; - } - break; - case "chain": - if (["left wrist", "right wrist", "left ankle", "right ankle"].includes(surface)) { - if (scar > 1) { - r += "scars from heavy manacles"; - } else { - r += "scars from manacles"; - } - } else { - if (scar > 1) { - r += "scars from heavy chains"; - } else { - r += "scars from chains"; - } - } - break; - case "burn": - if (scar > 2) { - r += "frightening "; - } else if (scar > 1) { - r += "serious "; - } - r += "burn scars"; - break; - case "menacing": - r += "a menacing scar"; - break; - case "exotic": - r += "an exotic scar"; - break; - case "surgical": - if (surface === "left breast" || surface === "right breast") { - if (slave.boobsImplant > 0) { - r += "scars from "; - if (scar > 3) { - r += "horribly botched "; - } else if (scar > 2) { - r += "sloppily inserted "; - } else if (scar > 1) { - r += "carelessly inserted "; - } - r += "implants"; - } else { - r += "scars from "; - if (scar > 3) { - r += "horribly botched "; - } else if (scar > 2) { - r += "sloppily done "; - } else if (scar > 1) { - r += "carelessly done "; - } - r += "surgery to remove implants"; - } - } else if (surface === "left buttock" || surface === "right buttock") { - if (slave.buttImplant > 0) { - r += "scars from "; - if (scar > 3) { - r += "horribly botched "; - } else if (scar > 2) { - r += "sloppily inserted "; - } else if (scar > 1) { - r += "carelessly inserted "; - } - r += "implants"; - } else { - r += "scars from "; - if (scar > 3) { - r += "horribly botched "; - } else if (scar > 2) { - r += "sloppily done "; - } else if (scar > 1) { - r += "carelessly done "; - } - r += "surgery to remove implants"; - } - } else if (surface === "belly" ) { - r += "scars from "; - if (scar > 1) { - r += "a crazy network of scars, as though a hack had tried internal surgery"; - } else { - r += "some faint scarring as though from internal surgery"; - } - } else { - r += "a "; - if (scar > 1) { - r += "pronounced "; - } else { - r += "faint "; - } - r += "surgical scar"; - } - break; - case "c-section": - r += "an "; - if (scar > 1) { - r += "especially "; - } - r += "unsightly c-section scar"; - break; - case "cutting": - if (["left wrist", "right wrist", "neck"].includes(surface)) { - r += "some scars as though $he attempted self harm"; - } else { - r += "some cuts as though from a razor"; - } - break; - default: - if (scar > 2) { - r += "serious "; - } else if (scar) { - r += kind; - } - break; - } - } - r = r.replace(/,(?=[^,]*$)/, ' and'); /* replace the last comma with the word "and" so we can use this in a sentence.*/ - return r; -}; - - /** * @param {App.Entity.SlaveState} slave * @returns {string} Description of slave's limbs diff --git a/src/pregmod/analyzePlayerPregnancy.tw b/src/pregmod/analyzePlayerPregnancy.tw index fb8a2b2a0b46d8cb79ecbf2195c0888e295c39a7..0bbf82a0a03658f89b1de0269fde8f7097beb72c 100644 --- a/src/pregmod/analyzePlayerPregnancy.tw +++ b/src/pregmod/analyzePlayerPregnancy.tw @@ -7,7 +7,7 @@ <</if>> <<set $nextButton = "Continue", $nextLink = $storedLink>> -<<set _WL = $PC.womb.length, _incubatorReservations = WombReserveCount($PC, "incubator"), _nurseryReservations = WombReserveCount($PC, "nursery")>> +<<set _WL = $PC.womb.length, _incubatorReservations = WombReserveCount($PC, "incubator"), _nurseryReservations = WombReserveCount($PC, "nursery"), _freeTanks = $incubator - $incubatorSlaves, _freeCribs = $nursery - $cribs.length>> <<if _WL == 0>> <<goto "Manage Personal Affairs">> @@ -32,7 +32,7 @@ <<set $reservedChildren -= _incubatorReservations>> <</link>> | <</if>> - <<if _incubatorReservations < _WL && ($reservedChildren + _WL - _incubatorReservations <= $freeTanks)>> + <<if _incubatorReservations < _WL && ($reservedChildren + _WL - _incubatorReservations <= _freeTanks)>> <<link "Keep all of your children in $incubatorName" "Analyze PC Pregnancy">> <<run WombChangeReserveType($PC, "nursery", "incubator")>> <<run WombChangeReserveType($PC, "", "incubator")>> @@ -53,7 +53,7 @@ <<set $reservedChildrenNursery -= _nurseryReservations>> <</link>> | <</if>> - <<if _nurseryReservations < _WL && ($reservedChildrenNursery + _WL - _nurseryReservations <= $freeCribs)>> + <<if _nurseryReservations < _WL && ($reservedChildrenNursery + _WL - _nurseryReservations <= _freeCribs)>> <<link "Keep all of your children in $nurseryName" "Analyze PC Pregnancy">> <<run WombChangeReserveType($PC, "incubator", "nursery")>> <<run WombChangeReserveType($PC, "", "nursery")>> @@ -281,7 +281,7 @@ <<set $PC.womb[_ap].reserve = "">> <<set $reservedChildren-->> <</link>> - <<elseif $freeTanks - $reservedChildren > 0>> + <<elseif _freeTanks - $reservedChildren > 0>> <<link "Keep this child in $incubatorName" "Analyze PC Pregnancy">> <<if $PC.womb[_ap].reserve === "nursery">> <<set $reservedChildrenNursery-->> @@ -301,7 +301,7 @@ <<set $PC.womb[_ap].reserve = "">> <<set $reservedChildrenNursery-->> <</link>> - <<elseif $freeCribs - $reservedChildrenNursery > 0>> + <<elseif _freeCribs - $reservedChildrenNursery > 0>> <<link "Keep this child in $nurseryName" "Analyze PC Pregnancy">> <<if $PC.womb[_ap].reserve === "incubator">> <<set $reservedChildren-->> diff --git a/src/pregmod/analyzePregnancy.tw b/src/pregmod/analyzePregnancy.tw index cbfb058f6bc77d865483a792e09faa8fec14a901..1dc5257291becb085469cb539450a2bf1b166dc7 100644 --- a/src/pregmod/analyzePregnancy.tw +++ b/src/pregmod/analyzePregnancy.tw @@ -8,7 +8,7 @@ <<set $nextButton = "Continue", $nextLink = $storedLink>> <<run App.Utils.setLocalPronouns(getSlave($activeSlave.ID))>> -<<set _WL = getSlave($activeSlave.ID).womb.length, _incubatorReservations = WombReserveCount(getSlave($activeSlave.ID), "incubator"), _nurseryReservations = WombReserveCount(getSlave($activeSlave.ID), "nursery")>> +<<set _WL = getSlave($activeSlave.ID).womb.length, _incubatorReservations = WombReserveCount(getSlave($activeSlave.ID), "incubator"), _nurseryReservations = WombReserveCount(getSlave($activeSlave.ID), "nursery"), _freeTanks = $incubator - $incubatorSlaves, _freeCribs = $nursery - $cribs.length>> <p class="scene-intro"> <<= getSlave($activeSlave.ID).slaveName>> is <<if getSlave($activeSlave.ID).devotion < 20>>restrained<<else>>comfortably reclined<</if>> with $his stomach prepped for examination. $He shudders slightly at the cold touch of the sensor against $his skin. @@ -68,7 +68,7 @@ <<set $reservedChildren -= _incubatorReservations>> <</link>> | <</if>> - <<if _incubatorReservations < _WL && ($reservedChildren + _WL - _incubatorReservations <= $freeTanks)>> + <<if _incubatorReservations < _WL && ($reservedChildren + _WL - _incubatorReservations <= _freeTanks)>> <<link "Keep all of $his children in $incubatorName" "Analyze Pregnancy">> <<run WombChangeReserveType(getSlave($activeSlave.ID), "nursery", "incubator")>> <<run WombChangeReserveType(getSlave($activeSlave.ID), "", "incubator")>> @@ -89,7 +89,7 @@ <<set $reservedChildrenNursery -= _nurseryReservations>> <</link>> | <</if>> - <<if _nurseryReservations < _WL && ($reservedChildrenNursery + _WL - _nurseryReservations <= $freeCribs)>> + <<if _nurseryReservations < _WL && ($reservedChildrenNursery + _WL - _nurseryReservations <= _freeCribs)>> <<link "Keep all of $his children in $nurseryName" "Analyze Pregnancy">> <<run WombChangeReserveType(getSlave($activeSlave.ID), "incubator", "nursery")>> <<run WombChangeReserveType(getSlave($activeSlave.ID), "", "nursery")>> @@ -316,7 +316,7 @@ <<set getSlave($activeSlave.ID).womb[_ap].reserve = "">> <<set $reservedChildren-->> <</link>> - <<elseif $freeTanks - $reservedChildren > 0>> + <<elseif _freeTanks - $reservedChildren > 0>> <<link "Keep this child in $incubatorName" "Analyze Pregnancy">> <<if getSlave($activeSlave.ID).womb[_ap].reserve === "nursery">> <<set $reservedChildrenNursery-->> @@ -336,7 +336,7 @@ <<set getSlave($activeSlave.ID).womb[_ap].reserve = "">> <<set $reservedChildrenNursery-->> <</link>> - <<elseif $freeCribs - $reservedChildrenNursery > 0>> + <<elseif _freeCribs - $reservedChildrenNursery > 0>> <<link "Keep this child in $nurseryName" "Analyze Pregnancy">> <<if getSlave($activeSlave.ID).womb[_ap].reserve === "incubator">> <<set $reservedChildren-->> diff --git a/src/pregmod/incubator.tw b/src/pregmod/incubator.tw index 3b04c078da90a3e67ecea272d27b8f4460f43c74..c55f0fcccab0610563a335c5103ed679fb71278f 100644 --- a/src/pregmod/incubator.tw +++ b/src/pregmod/incubator.tw @@ -9,7 +9,7 @@ <</if>> <<if $incubatorImprintSetting == 0>><<set $incubatorImprintSetting = "trust">><</if>> -<<set $readySlaves = 0, $readySlave = 0, $incubatorSlaves = $tanks.length, $freeTanks = $incubator - $incubatorSlaves, _SL = $slaves.length, _eligibility = 0, $reservedChildren = FetusGlobalReserveCount("incubator"), $reservedChildrenNursery = FetusGlobalReserveCount("nursery")>> +<<set $readySlaves = 0, $readySlave = 0, $incubatorSlaves = $tanks.length, _freeTanks = $incubator - $incubatorSlaves, _SL = $slaves.length, _eligibility = 0, $reservedChildren = FetusGlobalReserveCount("incubator"), $reservedChildrenNursery = FetusGlobalReserveCount("nursery")>> <br><br> $incubatorNameCaps is a clean, cold hall designed to be lined with tanks and their connected monitoring systems. @@ -27,14 +27,14 @@ $incubatorNameCaps is a clean, cold hall designed to be lined with tanks and the <br>It can support $incubator child<<if $incubator != 1>>ren<</if>>. There <<if $incubatorSlaves == 1>>is<<else>>are<</if>> currently $incubatorSlaves tank<<if $incubatorSlaves != 1>>s<</if>> in use in $incubatorName. [[Add another incubation tank|Incubator][cashX(forceNeg(Math.trunc(60000*$upgradeMultiplierArcology)), "capEx"), $incubator += 1]] //Costs <<print cashFormat(Math.trunc(60000*$upgradeMultiplierArcology))>> and will increase upkeep costs// -<<if $freeTanks == 0>> +<<if _freeTanks == 0>> All of the tanks are currently occupied by growing children. -<<elseif $incubator > 1 && $reservedChildren < $freeTanks>> +<<elseif $incubator > 1 && $reservedChildren < _freeTanks>> [[Remove an incubation tank|Incubator][cashX(forceNeg(Math.trunc(10000*$upgradeMultiplierArcology)), "capEx"), $incubator -= 1]] //Costs <<print cashFormat(Math.trunc(10000*$upgradeMultiplierArcology))>> and will reduce upkeep costs// <</if>> <br><br> -Reserve an eligible mother-to-be's child to be placed in a tank upon birth. Of $incubator tanks, <<print $freeTanks>> <<if $freeTanks == 1>>is<<else>>are<</if>> unoccupied. Of those, $reservedChildren <<if $reservedChildren == 1>>tank is<<else>>tanks are<</if>> reserved. +Reserve an eligible mother-to-be's child to be placed in a tank upon birth. Of $incubator tanks, <<print _freeTanks>> <<if _freeTanks == 1>>is<<else>>are<</if>> unoccupied. Of those, $reservedChildren <<if $reservedChildren == 1>>tank is<<else>>tanks are<</if>> reserved. /* ** With hundreds of slaves, navigating the Incubator room was giving me as much of a headache as other lists. ** So, I borrowed the sorting list and dropped a few options here. @@ -113,7 +113,7 @@ Reserve an eligible mother-to-be's child to be placed in a tank upon birth. Of $ <<else>> All _reservedIncubator of $his children will be placed in $incubatorName. <</if>> - <<if (_reservedIncubator + _reservedNursery < _WL) && ($reservedChildren < $freeTanks)>> + <<if (_reservedIncubator + _reservedNursery < _WL) && ($reservedChildren < _freeTanks)>> <br> <<if $pregnancyMonitoringUpgrade == 1>> <<print "[[Inspect pregnancy|Analyze Pregnancy][$i = " + _u + "; $activeSlave = $slaves[$i]]] | ">> @@ -125,10 +125,10 @@ Reserve an eligible mother-to-be's child to be placed in a tank upon birth. Of $ <<if _reservedIncubator > 1>> | <<print "[[Keep none of " + $his + " children|Incubator][WombCleanGenericReserve($slaves[" + _u + "], 'incubator', 9999)]]">> <</if>> - <<if ($reservedChildren + _WL - _reservedIncubator) <= $freeTanks>> + <<if ($reservedChildren + _WL - _reservedIncubator) <= _freeTanks>> | <<print "[[Keep the rest of " + $his + " children|Incubator][WombAddToGenericReserve($slaves[" + _u + "], 'incubator', 9999)]]">> <</if>> - <<elseif (_reservedIncubator == _WL) || ($reservedChildren == $freeTanks) || (_reservedIncubator + _reservedNursery == _WL)>> + <<elseif (_reservedIncubator == _WL) || ($reservedChildren == _freeTanks) || (_reservedIncubator + _reservedNursery == _WL)>> <br> <<if $pregnancyMonitoringUpgrade == 1>> <<print "[[Inspect pregnancy|Analyze Pregnancy][$i = " + _u + "; $activeSlave = $slaves[$i]]] | ">> @@ -138,7 +138,7 @@ Reserve an eligible mother-to-be's child to be placed in a tank upon birth. Of $ | <<print "[[Keep none of " + $his + " children|Incubator][WombCleanGenericReserve($slaves[" + _u + "], 'incubator', 9999)]]">> <</if>> <</if>> - <<elseif ($reservedChildren < $freeTanks)>> + <<elseif ($reservedChildren < _freeTanks)>> <<if _WL - _reservedNursery == 0>> //$His children are already reserved for $nurseryName// <br> @@ -147,17 +147,17 @@ Reserve an eligible mother-to-be's child to be placed in a tank upon birth. Of $ <</if>> <<print "[[Keep " + $his + " " + ((_WL > 1) ? "children" : "child") + " here instead|Incubator][WombChangeReserveType($slaves[" + _u + "], 'nursery', 'incubator')]]">> <<else>> - You have <<if $freeTanks == 1>>an<</if>> @@.lime;available aging tank<<if $freeTanks > 1>>s<</if>>.@@ + You have <<if _freeTanks == 1>>an<</if>> @@.lime;available aging tank<<if _freeTanks > 1>>s<</if>>.@@ <br> <<if $pregnancyMonitoringUpgrade == 1>> <<print "[[Inspect pregnancy|Analyze Pregnancy][$i = " + _u + "; $activeSlave = $slaves[$i]]] | ">> <</if>> <<print "[[Keep "+ ((_WL > 1) ? "a" : "the") +" child|Incubator][WombAddToGenericReserve($slaves[" + _u + "], 'incubator', 1)]]">> - <<if (_WL > 1) && ($reservedChildren + _WL - _reservedIncubator) <= $freeTanks>> + <<if (_WL > 1) && ($reservedChildren + _WL - _reservedIncubator) <= _freeTanks>> | <<print "[[Keep all of " + $his + " children|Incubator][WombAddToGenericReserve($slaves[" + _u + "], 'incubator', 9999)]]">> <</if>> <</if>> - <<elseif $reservedChildren == $freeTanks>> + <<elseif $reservedChildren == _freeTanks>> <br> <<if $pregnancyMonitoringUpgrade == 1>> <<print "[[Inspect pregnancy|Analyze Pregnancy][$i = " + _u + "; $activeSlave = $slaves[$i]]] | ">> @@ -198,7 +198,7 @@ Reserve an eligible mother-to-be's child to be placed in a tank upon birth. Of $ <<else>> All _reservedIncubator of your children will be placed in $incubatorName. <</if>> - <<if (_reservedIncubator < _WL) && ($reservedChildren < $freeTanks) && (_reservedIncubator - _reservedNursery > 0)>> + <<if (_reservedIncubator < _WL) && ($reservedChildren < _freeTanks) && (_reservedIncubator - _reservedNursery > 0)>> <br> <<if $pregnancyMonitoringUpgrade == 1>> <<print "[[Inspect pregnancy|Analyze PC Pregnancy]] | ">> @@ -210,10 +210,10 @@ Reserve an eligible mother-to-be's child to be placed in a tank upon birth. Of $ <<if _reservedIncubator > 1>> | <<print "[[Keep none of your children|Incubator][WombCleanGenericReserve($PC, 'incubator', 9999)]]">> <</if>> - <<if ($reservedChildren + _WL - _reservedIncubator) <= $freeTanks>> + <<if ($reservedChildren + _WL - _reservedIncubator) <= _freeTanks>> | <<print "[[Keep the rest of your children|Incubator][WombAddToGenericReserve($PC, 'incubator', 9999)]]">> <</if>> - <<elseif (_reservedIncubator == _WL) || ($reservedChildren == $freeTanks) || (_reservedIncubator - _reservedNursery >= 0)>> + <<elseif (_reservedIncubator == _WL) || ($reservedChildren == _freeTanks) || (_reservedIncubator - _reservedNursery >= 0)>> <br> <<if $pregnancyMonitoringUpgrade == 1>> <<print "[[Inspect pregnancy|Analyze PC Pregnancy]] | ">> @@ -223,22 +223,22 @@ Reserve an eligible mother-to-be's child to be placed in a tank upon birth. Of $ | <<print "[[Keep none of your children|Incubator][WombCleanGenericReserve($PC, 'incubator', 9999)]]">> <</if>> <</if>> - <<elseif $reservedChildren < $freeTanks>> + <<elseif $reservedChildren < _freeTanks>> <<if _WL - _reservedNursery == 0>> //Your child<<if _WL > 0>>ren are<<else>>is<</if>> already reserved for $nurseryName// <<print "[[Keep your" + ((_WL > 1) ? "children" : "child") + " here instead|Incubator][WombChangeReserveType($PC, 'nursery', 'incubator')]]">> <<else>> - You have <<if $freeTanks == 1>>an<</if>> @@.lime;available aging tank<<if $freeTanks > 1>>s<</if>>.@@ + You have <<if _freeTanks == 1>>an<</if>> @@.lime;available aging tank<<if _freeTanks > 1>>s<</if>>.@@ <br> <<if $pregnancyMonitoringUpgrade == 1>> <<print "[[Inspect pregnancy|Analyze PC Pregnancy]] | ">> <</if>> <<print "[[Keep " + ((_WL > 1) ? "a" : "your") +" child|Incubator][WombAddToGenericReserve($PC, 'incubator', 1)]]">> - <<if (_WL > 1) && ($reservedChildren + _WL - _reservedIncubator) <= $freeTanks>> + <<if (_WL > 1) && ($reservedChildren + _WL - _reservedIncubator) <= _freeTanks>> | [[Keep all of your children|Incubator][WombAddToGenericReserve($PC, 'incubator', 9999)]] <</if>> <</if>> - <<elseif $reservedChildren == $freeTanks>> + <<elseif $reservedChildren == _freeTanks>> <br> <<if $pregnancyMonitoringUpgrade == 1>> <<print "[[Inspect pregnancy|Analyze PC Pregnancy]] | ">> diff --git a/src/uncategorized/bodyModification.tw b/src/uncategorized/bodyModification.tw index 4f73105a03b97a5522ba22b73e0b9b2f8d025213..e159920fa7f4d0fce4c2a9ba243a815b1745363b 100644 --- a/src/uncategorized/bodyModification.tw +++ b/src/uncategorized/bodyModification.tw @@ -148,19 +148,19 @@ <<if _piercingCount == 0>> $His smooth <<= getSlave($AS).skin>> skin is completely unpierced. <</if>> - <<if getSlave($AS).earPiercing > 0 >><div><<= App.Desc.piercing(getSlave($AS), "ear")>></div><</if>> - <<if getSlave($AS).nosePiercing > 0 >><div><<= App.Desc.piercing(getSlave($AS), "nose")>></div><</if>> - <<if getSlave($AS).eyebrowPiercing > 0 >><div><<= App.Desc.piercing(getSlave($AS), "eyebrow")>></div><</if>> - <<if getSlave($AS).lipsPiercing > 0 >><div><<= App.Desc.piercing(getSlave($AS), "lips")>></div><</if>> - <<if getSlave($AS).tonguePiercing > 0 >><div><<= App.Desc.piercing(getSlave($AS), "tongue")>></div><</if>> - <<if getSlave($AS).nipplesPiercing > 0 >><div><<= App.Desc.piercing(getSlave($AS), "nipple")>></div><</if>> - <<if getSlave($AS).areolaePiercing > 0 >><div><<= App.Desc.piercing(getSlave($AS), "areolae")>></div><</if>> - <<if getSlave($AS).navelPiercing > 0 >><div><<= App.Desc.piercing(getSlave($AS), "navel")>></div><</if>> - <<if getSlave($AS).corsetPiercing > 0 >><div><<= App.Desc.piercing(getSlave($AS), "corset")>></div><</if>> - <<if getSlave($AS).clitPiercing > 0 >><div><<= App.Desc.piercing(getSlave($AS), "clit")>></div><</if>> - <<if getSlave($AS).vaginaPiercing > 0 >><div><<= App.Desc.piercing(getSlave($AS), "vagina")>></div><</if>> - <<if getSlave($AS).dickPiercing > 0 >><div><<= App.Desc.piercing(getSlave($AS), "dick")>></div><</if>> - <<if getSlave($AS).anusPiercing > 0 >><div><<= App.Desc.piercing(getSlave($AS), "anus")>></div><</if>> + <div><<= App.Desc.piercing(getSlave($AS), "ear")>></div> + <div><<= App.Desc.piercing(getSlave($AS), "nose")>></div> + <div><<= App.Desc.piercing(getSlave($AS), "eyebrow")>></div> + <div><<= App.Desc.piercing(getSlave($AS), "lips")>></div> + <div><<= App.Desc.piercing(getSlave($AS), "tongue")>></div> + <div><<= App.Desc.piercing(getSlave($AS), "nipple")>></div> + <div><<= App.Desc.piercing(getSlave($AS), "areolae")>></div> + <div><<= App.Desc.piercing(getSlave($AS), "navel")>></div> + <div><<= App.Desc.piercing(getSlave($AS), "corset")>></div> + <div><<= App.Desc.piercing(getSlave($AS), "clit")>></div> + <div><<= App.Desc.piercing(getSlave($AS), "vagina")>></div> + <div><<= App.Desc.piercing(getSlave($AS), "dick")>></div> + <div><<= App.Desc.piercing(getSlave($AS), "anus")>></div> <div><<= App.Desc.piercing(getSlave($AS), "chastity")>></div> </div> diff --git a/src/uncategorized/householdLiquidator.tw b/src/uncategorized/householdLiquidator.tw index b2cd1488b4b18d1cbb7697e18036a0252b4acbf5..5d6b023b379ec8aeadb52d483cf8d5a2dfbb8794 100644 --- a/src/uncategorized/householdLiquidator.tw +++ b/src/uncategorized/householdLiquidator.tw @@ -107,4 +107,4 @@ The price is <<print cashFormatColor(_totalCost)>>. <<if $slavesSeen > $slaveMar <br>[[Decline to purchase them and check out another set of slaves|Household Liquidator][$slavesSeen += 2]] <br><br> -<<= App.UI.MultipleInspect.SC(_newSlaves, true, true, true)>> +<<includeDOM App.UI.MultipleInspect(_newSlaves, true, true, true)>> diff --git a/src/uncategorized/main.tw b/src/uncategorized/main.tw index 7df482f44febb0ff06a6ef8ff6f8579e28a618bd..d505c8d2d6ef097fb4fdcca244332c4a69ddbd7f 100644 --- a/src/uncategorized/main.tw +++ b/src/uncategorized/main.tw @@ -50,7 +50,7 @@ [[Hide|Main][$seeDesk = 0]] <</if>> -<<print App.MainView.full()>> +<<includeDOM App.MainView.full()>> <<set $activeSlave = $slaves.random()>> <<if $activeSlave && ($activeSlave.assignment != "please you") && ($activeSlave.assignment != "guard you")>> diff --git a/src/uncategorized/penthouseReport.tw b/src/uncategorized/penthouseReport.tw index 218371beeda33f70d9d41e3901d13a09e657775a..ecbf0225270a7333bf7c1efde3bb9f90058faa40 100644 --- a/src/uncategorized/penthouseReport.tw +++ b/src/uncategorized/penthouseReport.tw @@ -44,4 +44,4 @@ <</for>> /* count open spots in facilities after all assignments have been decided for the week */ -<<set $brothelSpots = App.Entity.facilities.brothel.freeSpacee, $clubSpots = App.Entity.facilities.club.freeSpace, $dairySpots = App.Entity.facilities.dairy.freeSpace, $servantsQuartersSpots = App.Entity.facilities.servantsQuarters.freeSpace>> +<<set $brothelSpots = App.Entity.facilities.brothel.freeSpace, $clubSpots = App.Entity.facilities.club.freeSpace, $dairySpots = App.Entity.facilities.dairy.freeSpace, $servantsQuartersSpots = App.Entity.facilities.servantsQuarters.freeSpace>> diff --git a/src/uncategorized/reFSEgyptianRevivalistAcquisition.tw b/src/uncategorized/reFSEgyptianRevivalistAcquisition.tw index 4287f086cc26fc6039e332c9c515dd49b2b1a4a1..b9a3c46185a6c9beac85358c177f8ec00f823b52 100644 --- a/src/uncategorized/reFSEgyptianRevivalistAcquisition.tw +++ b/src/uncategorized/reFSEgyptianRevivalistAcquisition.tw @@ -68,7 +68,7 @@ This call is coming from a public kiosk, which is usually an indication that the <<set _totalValue = slaveCost($activeSlave) + slaveCost(_secondSlave)>> //Enslaving them will cost <<print cashFormat(_contractCost)>>. Selling them immediately will bring in approximately <<print cashFormat(_totalValue-_contractCost)>>.// <br><br> -<<= App.UI.MultipleInspect.SC(_newSlaves, true, false, false)>> +<<includeDOM App.UI.MultipleInspect(_newSlaves, true, false, false)>> <br><br> <span id="result"> <<if $cash >= _contractCost>> diff --git a/src/uncategorized/recETS.tw b/src/uncategorized/recETS.tw index 95113206f3f2004033c26f60d32706ba6423ab5b..628bf12cd0f121087e39ea7873b7217fc9f8325f 100644 --- a/src/uncategorized/recETS.tw +++ b/src/uncategorized/recETS.tw @@ -1404,7 +1404,7 @@ <<elseif ["addict mother daughter", "posh mother daughter", "mismatched pair"].includes($RecETSevent)>> <<set _newSlaves = [$relative]>> /* caller doesn't want relative involved, so you don't get to inspect her even if you can force a sale */ <</if>> - <<= App.UI.MultipleInspect.SC(_newSlaves, true, true, false)>> + <<includeDOM App.UI.MultipleInspect(_newSlaves, true, true, false)>> </span> <span id="result"> diff --git a/src/uncategorized/slaveAssignmentsReport.tw b/src/uncategorized/slaveAssignmentsReport.tw index c020c8ce15fa00d24d8a6c5f2f7e385fd5dfe737..d1145b3b4f0851d4c11ae9a236f128f5d3261090 100644 --- a/src/uncategorized/slaveAssignmentsReport.tw +++ b/src/uncategorized/slaveAssignmentsReport.tw @@ -4,6 +4,5 @@ <h1> $arcologies[0].name Weekly Slave Report - Week $week</h1> -<<print App.UI.DOM.includeDOM(App.EndWeek.slaveAssignmentReport(), "weeklyReport", "div")>> -/* release loading screen as soon as the event loop can run */ +<<includeDOM App.EndWeek.slaveAssignmentReport()>> <<run App.UI.EndWeekAnim.end()>> diff --git a/src/utility/descriptionWidgetsPiercings.tw b/src/utility/descriptionWidgetsPiercings.tw deleted file mode 100644 index 94505d260dd9c34c36a01be76f67da8299abdad9..0000000000000000000000000000000000000000 --- a/src/utility/descriptionWidgetsPiercings.tw +++ /dev/null @@ -1,618 +0,0 @@ -:: piercing description widgets [widget nobr] - -<<widget "earPiercingDescription">> - <<if $activeSlave.earPiercing > 0>> - <<if $activeSlave.earPiercing == 1>> - $His earlobes are conventionally pierced. - <<else>> - $His ears are heavily pierced, with multiple lobe piercings and a row of helix piercings. - <</if>> - <<if ($activeSlave.assignment == "get milked") || ($activeSlave.assignment == "work in the dairy")>> - $He has a plastic livestock tag in one ear to help identify $him for milking. - <<else>> - <<switch $activeSlave.clothes>> - <<case "attractive lingerie" "attractive lingerie for a pregnant woman">> - $He's wearing pretty, womanly earrings. - <<case "a bra" "a button-up shirt" "a button-up shirt and panties" "a sweater" "a sweater and panties" "a t-shirt" "a t-shirt and jeans" "a t-shirt and thong" "a tank-top" "a tank-top and panties" "a thong" "a tube top and thong" "an oversized t-shirt" "an oversized t-shirt and boyshorts" "boyshorts" "cutoffs" "panties">> - $He's wearing plain but pretty earrings. - <<case "a nice pony outfit" "a slutty pony outfit">> - $He's wearing horseshoe shaped earrings. - <<case "leather pants and pasties" "leather pants" "leather pants and a tube top" "a tube top">> - $He's wearing large hoop earrings. - <<case "a gothic lolita dress">> - $He's wearing black earrings. - <<case "a sports bra" "a one-piece swimsuit" "sport shorts and a t-shirt" "sport shorts and a sports bra" "sport shorts">> - $He's wearing cute, simple earrings. - <<case "a skimpy loincloth">> - $He's wearing a pair of bone earrings. - <<case "a police uniform">> - $He's wearing nightstick-shaped earrings. - <<case "a succubus outfit">> - $He's wearing pentagram earrings. - <<case "a fallen nuns habit" "a penitent nuns habit">> - $His earrings mimic tiny crowns of thorns. - <<case "a chattel habit">> - $He's wearing golden earrings in the shape of saintly nudes. - <<case "a hijab and abaya" "a niqab and abaya">> - $He's wearing bronze earrings shaped like crescent moons. - <<case "a klan robe" "a slutty klan robe">> - $He's wearing bronze earrings shaped like crucifixes. - <<case "a long qipao" "a slutty qipao">> - $His golden earrings resemble Eastern-style dragons. - <<case "a string bikini" "cutoffs and a t-shirt" "a t-shirt and panties" "panties and pasties" "pasties" "jeans" "a sweater and cutoffs">> - $He's wearing girly earrings. - <<case "a schoolgirl outfit">> - $He's wearing small girlish earrings. - <<case "striped panties" "a striped bra" "striped underwear">> - $He's wearing big girlish earrings. - <<case "a burkini" "a monokini">> - $He's wearing unobtrusive little stud earrings. - <<case "a Santa dress">> - $His earrings resemble little green pine trees. - <<case "a mini dress" "an apron" "a hanbok">> - $He's wearing shiny pearl earrings. - <<case "a hijab and blouse" "conservative clothing">> - $He's wearing small unobtrusive hoop earrings. - <<case "a cybersuit" "a scalemail bikini">> - $He's wearing sharp and brutal-looking earrings. - <<case "a kimono">> - $He's wearing gorgeous enameled earrings made to look like tiny koi. - <<case "a burqa">> - $He's wearing cheap metal earrings with fake gems. - <<case "a slave gown" "a halter top dress" "a ball gown" "a maternity dress">> - $He's wearing lovely diamond earrings; the stones are cut in an alluring, feminine style. - <<case "slutty business attire">> - $He's wearing lovely diamond earrings; the stones are cut in a gaudy, nouveau riche style. - <<case "nice business attire">> - $He's wearing lovely diamond earrings; the stones are cut in an assertive, unsubtle style. - <<case "a slutty maid outfit">> - $He's wearing big hoop earrings inappropriate for a real maid. - <<case "a nice maid outfit">> - $He's wearing conservative earrings like those a free maid could afford. - <<case "harem gauze">> - $He's wearing broad gold earrings in faux-Arabian style. - <<case "overalls" "Western clothing">> - $He's wearing earrings in the shape of a sheriff's star. - <<case "a huipil">> - $He's wearing earrings in the shape of a stylized jaguar's head. - <<case "a bunny outfit">> - $He's wearing earrings in the shape of a stylized rabbit's head. - <<case "kitty lingerie">> - $He's wearing earrings in the shape of a stylized cat's head. - <<case "a bimbo outfit">> - $He's wearing large, heart-shaped earrings. - <<case "a courtesan dress">> - $He's wearing hanging earrings that accentuate each movement of $his head. - <<case "slutty jewelry">> - $He's wearing gold earrings in the shape of a pair of - <<if ($activeSlave.dick > 0) && ($activeSlave.balls == 0)>> - limp dicks. - <<elseif ($activeSlave.dick > 0)>> - erect cocks. - <<elseif ($activeSlave.skill.oral >= 100)>> - tongues. - <<elseif ($activeSlave.boobs > 1000)>> - heavy breasts. - <<else>> - female bottoms. - <</if>> - <</switch>> - <</if>> - <</if>> -<</widget>> - -<<widget "nosePiercingDescription">> - <<if $activeSlave.nosePiercing == 1>> - $He has simple studs in $his nose. - <<elseif $activeSlave.nosePiercing == 2>> - $He has nasal studs and a large septum ring. - <<if ($activeSlave.clothes == "slutty jewelry") && ($activeSlave.earPiercing > 0)>> - $His bangles include a light chain from $his nose ring to $his ear piercings on one side. - <</if>> - <</if>> -<</widget>> - -<<widget "eyebrowPiercingDescription">> - <<if $activeSlave.eyebrowPiercing == 1>> - $He has a simple stud in one eyebrow. - <<elseif $activeSlave.eyebrowPiercing == 2>> - $He has multiple eyebrow rings. - <</if>> -<</widget>> - -<<widget "lipsPiercingDescription">> - <<if $activeSlave.lipsPiercing == 1>> - $He has a simple lip piercing. - <<elseif $activeSlave.lipsPiercing == 2>> - $His lips are heavily pierced. - <</if>> -<</widget>> - -<<widget "tonguePiercingDescription">> - <<if $activeSlave.tonguePiercing == 1>> - $His tongue bears a single stud, so oral sex with $him is a bit more fun. - <<elseif $activeSlave.tonguePiercing == 2>> - $His tongue bears a row of studs, offering thorough stimulation to anyone $he blows. - <</if>> - <<if canTalk($activeSlave)>> - <<if $activeSlave.lips >= 70 || $activeSlave.lipsPiercing == 2>> - $He can barely enunciate - <<if $activeSlave.lipsPiercing == 2>> - past $his piercings; - <<else>> - with $his fat lips; - <</if>> - <<run Enunciate($activeSlave)>> - <<if $writtenTitle === $enunciate.title>> - <<if (setup.badNames.includes(capFirstChar($writtenTitle)))>> - unfortunately - <<else>> - fortunately - <</if>> - '$enunciate.title' is easy to pronounce. - <<else>> - '$writtenTitle' comes out as '$enunciate.title.' - <</if>> - <</if>> - <</if>> -<</widget>> - -<<widget "nipplesPiercingDescription">> -<<set _nippleColor = nippleColor($activeSlave)>> -<<if $activeSlave.fuckdoll > 0>> - <<if $activeSlave.nipplesPiercing > 0>> - $His nipple piercings help secure the suit material to $his breasts. - <</if>> -<<else>> - <<if $activeSlave.nipplesPiercing == 1>> - $His _nippleColor nipples have a simple piercing, which keeps them a little harder than they would normally be. - <<elseif $activeSlave.nipplesPiercing == 2>> - $His _nippleColor nipples are heavily pierced with several rings and studs, and there is a chain between them. - <<if ($activeSlave.boobShape == "saggy") && ($activeSlave.boobs > 2500)>> - It's been shortened to take advantage of the way $his tits sag, and holds $his _nippleColor nipples almost together, producing cleavage that runs from $his _nippleColor nipples all the way up to $his sternum. - <<else>> - The constant tugging keeps $his _nippleColor nipples erect. - <</if>> - <</if>> - <<if $activeSlave.nipplesPiercing > 0>> - <<switch $activeSlave.clothes>> - <<case "kitty lingerie">> - The piercings slightly distort the shape of $his lacy bra's cleavage window. - <<case "attractive lingerie">> - The piercings are a girly color, to complement $his lingerie. - <<case "a succubus outfit">> - The piercings are severe steel, as befits a sex demon. - <<case "uncomfortable straps">> - Each nipple bears a horizontal bar that is held forward of the steel ring that's part of $his outfit, constantly tugging them outward. - <<case "restrictive latex">> - The piercings are tantalizingly visible under the latex. - <<case "a fallen nuns habit">> - A tiny ebon cross on a short chain dangles from each piercing. - <<case "a chattel habit">> - A tiny golden cock and balls dangles from each piercing. - <<case "a monokini">> - Due to $his toplessness, the piercings are plainly visible. - <<case "a cybersuit">> - The piercings are tantalizingly visible under the bodysuit. - <<case "a string bikini">> - The piercings are a pastel color, to complement $his bikini. - <<case "striped panties">> - The piercings are a pastel color, to complement $his panties. - <<case "a scalemail bikini">> - The piercings are severe steel, as befits a hardened warrior. - <<case "a schoolgirl outfit">> - <<if ($activeSlave.boobs <= 2000)>> - The piercings are tantalizingly visible under the thin material. - <</if>> - <<case "battledress">> - The piercings are tantalizingly visible under $his tank top. - <<case "nice business attire">> - One side of each piercing peeks over the edge of $his blouse. - <<case "a comfortable bodysuit">> - The piercings are tantalizingly visible under the tight bodysuit. - <<case "a latex catsuit">> - The piercings are tantalizingly visible under the tight latex catsuit. - <<case "a mini dress">> - The piercings are tantalizingly visible under the tight mini dress. - <<case "a courtesan dress">> - The piercings are tantalizingly visible through $his thin dress. - <<case "a bimbo outfit">> - They can't be seen, but one can clearly feel the piercings are in the shape of hearts. - <<case "a slutty maid outfit">> - One side of each piercing peeks over the edge of $his lacy top. - <<case "harem gauze">> - The piercings are tantalizingly visible under the gauze. - <<case "attractive lingerie for a pregnant woman">> - The piercings are tantalizingly visible under the thin silk. - <<case "a maternity dress">> - The piercings are tantalizingly visible under the dress's tight top. - <<case "stretch pants and a crop-top">> - The piercings are tantalizingly visible under $his crop-top. - <</switch>> - <</if>> -<</if>> -<</widget>> - -<<widget "areolaePiercingDescription">> - <<print App.Desc.areolaePiercing($activeSlave)>> -<</widget>> - -<<widget "navelPiercingDescription">> - <<if $activeSlave.fuckdoll == 0>> - <<if setup.fakeBellies.includes($activeSlave.bellyAccessory)>> - <<if $activeSlave.navelPiercing == 1>> - $His fake navel bears a simple stud. - <<elseif $activeSlave.navelPiercing == 2>> - $His fake navel is pierced with a big ring. - <<if ($activeSlave.clothes == "slutty jewelry")>> - It has a length of gilded chain dangling from it. - <<else>> - It has a short length of chain dangling from it. - <</if>> - <</if>> - <<else>> - <<if $activeSlave.navelPiercing == 1>> - $His navel bears a simple stud. - <<elseif $activeSlave.navelPiercing == 2>> - $His navel is pierced with a big ring. - <<if ($activeSlave.clothes == "slutty jewelry")>> - It has a length of gilded chain dangling from it. - <<else>> - It has a short length of chain dangling from it. - <</if>> - <</if>> - <</if>> - <<else>> - <<if $activeSlave.navelPiercing > 0>> - <<if $activeSlave.belly >= 10000>> - <<if $activeSlave.navelPiercing == 1>> - $His popped navel bears a simple stud. - <<elseif $activeSlave.navelPiercing == 2>> - $His popped navel is pierced with a big ring. - <</if>> - It's eye-catching, since most of $his piercings are hidden by the suit. - <<else>> - $His navel piercing runs through the suit's material. - <</if>> - <</if>> - <</if>> -<</widget>> - -<<widget "clitPiercingDescription">> - <<if ($activeSlave.clitPiercing == 1) && ($activeSlave.vagina != -1)>> - $He has a simple clitoral stud. - <<elseif ($activeSlave.clitPiercing == 2) && ($activeSlave.vagina != -1)>> - $He has a big ring in $his clit. - <<if ($activeSlave.clothes == "slutty jewelry")>> - Since $he's wearing slutty bangles $he has a short length of light chain dangling from $his clit ring; it constantly stimulates $his pussylips. - <</if>> - <<elseif ($activeSlave.clitPiercing == 3) && ($activeSlave.vagina != -1) && ($activeSlave.dick == 0)>> - $He has a smart piercing in $his clit. - <<elseif ($activeSlave.clitPiercing == 1)>> - $He has a simple dickhead stud. - <<elseif ($activeSlave.clitPiercing == 2)>> - $He has a big ring in $his dickhead. - <<if ($activeSlave.clothes == "slutty jewelry")>> - Since $he's wearing slutty bangles $he has a short length of light chain dangling from $his dickhead piercing; as $he moves it tugs lightly at $his cock. - <</if>> - <<elseif ($activeSlave.clitPiercing == 3)>> - $He has a smart frenulum piercing. - <</if>> - <<if $activeSlave.fuckdoll > 0>>It anchors the suit's material.<</if>> -<</widget>> - -<<widget "vaginaPiercingDescription">> - <<if ($activeSlave.vagina != -1)>> - <<if $activeSlave.vaginaPiercing > 0>> - $He has a - <<if ($activeSlave.vaginaPiercing == 1)>> - simple row of studs - <<else>> - row of big rings - <</if>> - down $his labia<<if $activeSlave.fuckdoll > 0>>, which are looped into the edge of the suit's material as it stops around $his vulva<</if>>. - <</if>> - <</if>> -<</widget>> - -<<widget "dickPiercingDescription">> - <<if ($activeSlave.dick != 0)>> - <<if ($activeSlave.dickPiercing == 1)>> - $He has a row of studs down $his shaft. - <<elseif ($activeSlave.dickPiercing == 2)>> - $He has a row of heavy rings down $his shaft. - <</if>> - <<if ($activeSlave.scrotum != 0)>> - <<if ($activeSlave.dickPiercing == 1)>> - $He has a couple of studs in $his ballsack. - <<elseif ($activeSlave.dickPiercing == 2)>> - $He has a row of rings down the center of $his ballsack, all the way from the base of $his shaft to $his perineum. - <</if>> - <<else>> - <<if ($activeSlave.dickPiercing == 1)>> - $He has a couple of studs beneath the base of $his dick. - <<elseif ($activeSlave.dickPiercing == 2)>> - $He has a row of rings all the way from the base of $his shaft to $his perineum. - <</if>> - <</if>> - <</if>> - <<if $activeSlave.fuckdoll > 0>> - <<if $activeSlave.dickPiercing > 0>> - Every one of them runs through the suit's material, securing it to the Fuckdoll's member. - <</if>> - <</if>> -<</widget>> - -<<widget "anusPiercingDescription">> - <<if ($activeSlave.vagina > -1)>> - <<if ($activeSlave.anusPiercing == 1)>> - $He has a simple piercing between $his pussy and $his asshole<<if $activeSlave.fuckdoll > 0>> which helps keep the strip of material <<if $activeSlave.vagina > -1>>between $his holes<<else>>below $his rear hole<</if>> in place<</if>>. - <<elseif ($activeSlave.anusPiercing == 2)>> - $He has a big ring between $his pussy and $his asshole<<if $activeSlave.fuckdoll > 0>>, which helps keep the strip of material <<if $activeSlave.vagina > -1>>between $his holes<<else>>below $his rear hole<</if>> in place,<</if>> and studs in all around $his anus. - <</if>> - <<else>> - <<if ($activeSlave.anusPiercing == 1)>> - $He has a simple perianal piercing between the base of $his dick and $his girly butthole<<if $activeSlave.fuckdoll > 0>> which helps keep the strip of material <<if $activeSlave.vagina > -1>>between $his holes<<else>>below $his rear hole<</if>> in place<</if>>. - <<elseif ($activeSlave.anusPiercing == 2)>> - $He has a big ring between the base of $his dick and $his girly butthole, which has studs all around it. - <</if>> - <</if>> -<</widget>> - -<<widget "CorsetPiercingDescription">> - - <<if $activeSlave.corsetPiercing > 0>> - <<if $activeSlave.fuckdoll == 0>> - - $He has a corset piercing, a ladder of steel rings running up each side of $his back: - <<if ($activeSlave.bellyAccessory == "a corset") || ($activeSlave.bellyAccessory == "an extreme corset")>> - these are looped through special lugs in the back of $his actual corset, making it almost a part of $his body. - <<if $activeSlave.devotion > 50>> - $He couldn't remove it, even if $he wanted to. - <<elseif $activeSlave.devotion >= -20>> - $He couldn't remove it, even if $he were inclined to try. - <<else>> - Any attempt to remove it will cause intense pain. - <</if>> - <<else>> - <<switch $activeSlave.clothes>> - - <<case "a hijab and blouse" "a schoolgirl outfit" "conservative clothing" "nice business attire" "slutty business attire">> - $his blouse hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "chains">> - they're laced together with steel cable, tightly enough that they're tugging at $his skin. - - <<case "Western clothing">> - $his shirt hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "a toga">> - $his toga hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "a huipil">> - $his huipil hides them partially, so the leather straps that pull on $his skin are clearly evident. - - <<case "a long qipao" "a slutty qipao">> - $his qipao hides them completely, but they're laced tightly with silk cord, so $he's aware they're there. - - <<case "uncomfortable straps">> - they're laced together with a leather cord, tightly enough that they're tugging at $his skin. - - <<case "shibari ropes">> - they're laced together as part of $his bindings. - - <<case "a latex catsuit" "restrictive latex">> - these are clipped into the latex covering them, making it almost a part of $his body. - <<if $activeSlave.devotion > 50>> - $He couldn't remove it, even if $he wanted to. - <<elseif $activeSlave.devotion >= -20>> - $He couldn't remove it, even if $he were inclined to try. - <<else>> - Any attempt to remove it will cause intense pain. - <</if>> - - <<case "a military uniform">> - $his tunic hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "a schutzstaffel uniform">> - $his tunic hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "a slutty schutzstaffel uniform">> - $his tunic hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "a red army uniform">> - $his tunic hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "battlearmor">> - $his armor hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "a dirndl">> - $his dress hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "lederhosen">> - $his tunic hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "a mounty outfit">> - $his tunic hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "a biyelgee costume">> - $his dress hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "a nice nurse outfit">> - $his scrubs hide them completely, but they're laced tightly, so $he's aware they're there. - - <<case "a mini dress">> - these are clipped into the mini dress covering them, making it almost a part of $his body. - <<if $activeSlave.devotion > 50>> - $He couldn't remove it, even if $he wanted to. - <<elseif $activeSlave.devotion >= -20>> - $He couldn't remove it, even if $he were inclined to try. - <<else>> - Any attempt to remove it will cause intense pain. - <</if>> - - <<case "attractive lingerie" "attractive lingerie for a pregnant woman" "kitty lingerie">> - they're laced together with a lacy ribbon finished off with a bow. - - <<case "a succubus outfit">> - they're laced into $his succubus corset, making it a part of $him. - - <<case "a fallen nuns habit">> - they're laced together with cord, tightly enough that $he is forced to arch $his back or suffer. $He spends most of $his time involuntarily presenting $his bottom to relieve the tugging. - - <<case "a chattel habit">> - $his white habit hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "a penitent nuns habit">> - $his habit hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "a gothic lolita dress" "a hanbok" "a Santa dress">> - $his dress hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "a burkini" "a one-piece swimsuit">> - $his swimsuit hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "a monokini">> - the straps of $his swimsuit run on each side of these loops. - - <<case "an apron">> - the straps of $his apron run on each side of these loops. - - <<case "overalls">> - the straps of $his overalls run on each side of these loops. - - <<case "a bra" "a skimpy loincloth" "a striped bra" "a thong" "boyshorts" "cutoffs" "jeans" "leather pants" "leather pants and pasties" "panties" "panties and pasties" "pasties" "sport shorts" "striped panties" "striped underwear">> - the piercings are plainly visible on $his bare back. - - <<case "a slutty klan robe" "a slutty pony outfit" "a sports bra" "a tank-top and panties" "a tube top" "a tube top and thong" "leather pants and a tube top">> - the piercings are only partly visible on $his back. - - <<case "a button-up shirt" "a button-up shirt and panties" "a police uniform" "a t-shirt and jeans" "a t-shirt and panties" "a t-shirt and thong" "a t-shirt" "a tank-top" "an oversized t-shirt and boyshorts" "an oversized t-shirt" "sport shorts and a sports bra" "sport shorts and a t-shirt">> - $his shirt hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "a sweater" "a sweater and cutoffs" "a sweater and panties">> - $his sweater hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "a nice pony outfit">> - $his outfit hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "a string bikini">> - the back of $his string top loops into them and runs down through them to become $his bottom, such as it is. - - <<case "a scalemail bikini">> - they're laced together with a steel chain. - - <<case "a cheerleader outfit">> - they're laced together with a simple ribbon, but the effect makes it clear that this is one kinky cheerleader. - - <<case "clubslut netting">> - these are clipped into the netting covering them, making it almost a part of $his body. - <<if $activeSlave.devotion > 50>> - $He couldn't remove it, even if $he wanted to. - <<elseif $activeSlave.devotion >= -20>> - $He couldn't remove it, even if $he were inclined to try. - <<else>> - Any attempt to remove it will cause intense pain. - <</if>> - - <<case "cutoffs and a t-shirt">> - they're laced together with a simple ribbon, but the effect makes it clear that this is one kinky $girl. - - <<case "a slutty outfit">> - they're laced together with a simple ribbon, tightly enough that $he's aware they're there. - - <<case "a slave gown">> - they're revealed by the swooping back of $his gown and laced up with matching silk ribbon. - - <<case "a comfortable bodysuit">> - these are clipped into the bodysuit covering them, making it almost a part of $his body. - <<if $activeSlave.devotion > 50>> - $He couldn't remove it, even if $he wanted to. - <<elseif $activeSlave.devotion >= -20>> - $He couldn't remove it, even if $he were inclined to try. - <<else>> - Any attempt to remove it will cause intense pain. - <</if>> - - <<case "a leotard">> - these are clipped into the leotard covering them, making it almost a part of $his body. - <<if $activeSlave.devotion > 50>> - $He couldn't remove it, even if $he wanted to. - <<elseif $activeSlave.devotion >= -20>> - $He couldn't remove it, even if $he were inclined to try. - <<else>> - Any attempt to remove it will cause intense pain. - <</if>> - - <<case "a bunny outfit">> - $his teddy hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "a slutty maid outfit">> - $his dress has an open back to reveal them and the black ribbon that laces them tightly together. - - <<case "a nice maid outfit">> - $his dress hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "a slutty nurse outfit">> - $his jacket hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "a kimono">> - $his kimono hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "a hijab and abaya" "a niqab and abaya">> - $his abaya hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "a klan robe">> - $his robe hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "a burqa">> - $his burqa hides them completely, but they're laced tightly, so $he's aware they're there. - - <<case "battledress">> - they're laced together with paracord. - - <<case "harem gauze">> - they're laced up with a light golden chain that glints through $his filmy clothing. - - <<case "slutty jewelry">> - they're laced up with a light golden chain that begins and ends in other parts of $his glinting bonds. - - <<case "a courtesan dress">> - they're laced into $his dress's corset, binding the material even closer to $him. - - <<case "a bimbo outfit">> - they're laced together with a bright pink ribbon. - - <<default>> - they're laced up with a ribbon, tightly enough to keep $him aware they're there. - - <</switch>> - <</if>> - - <</if>> - <</if>> - -<</widget>> - -<<widget "chastityPiercingDescription">> - <<if ($activeSlave.clitPiercing > 0)>> - <<if ($activeSlave.nipplesPiercing > 0)>> - <<if !($activeSlave.chastityPenis)>> - <<if ($activeSlave.dick > 4)>> - <<if ($activeSlave.boobs > 1000)>> - <<if canAchieveErection($activeSlave.balls > 0)>> - <<if ($activeSlave.devotion > 20)>> - <<if ($activeSlave.energy > 90)>> - $His very special body allows $him to wear an incredibly lewd piece of jewelry: a thin golden chain that runs from nipple to nipple, through $his pierced cockhead. The chain is short, and any motion at all tugs at $his nipples and penis. - <<if canWalk($activeSlave)>> - The stimulation is almost unbearable, and the mere act of walking sometimes causes $him to cum. - <</if>> - <</if>> - <</if>> - <</if>> - <</if>> - <</if>> - <</if>> - <</if>> - <</if>> -<</widget>>