From c444ba5256d02fd1cf2a5d19ea152b51dd65fc35 Mon Sep 17 00:00:00 2001 From: Svornost <11434-svornost@users.noreply.gitgud.io> Date: Sun, 1 Aug 2021 13:26:15 -0700 Subject: [PATCH] Art rendering improvements: 1. Use batch rendering for death, expire, retire, burst, and birth. 2. Add `App.UI.DOM.drawOneSlaveRight` to draw a single slave floating to the right of a block of text, since we do that exact thing all over the place. 3. Fix some broken stuff in matchmaking and provide a slave description dialog link in case you've forgotten the slave's fetishes and so on. 4. Fix some inconsistencies in the layout of the HG's slave's penthouse report entry. 5. A few little type fixes --- js/003-data/gameVariableData.js | 1 + src/art/artJS.js | 2 +- src/endWeek/events/death.js | 9 ++++++-- src/endWeek/events/expire.js | 9 ++++++-- src/endWeek/events/retire.js | 11 +++++++--- src/endWeek/reports/penthouseReport.js | 21 +++++++++---------- src/events/scheduled/burst/burst.js | 13 +++++++----- .../dairy/freeRangeDairyAssignmentScene.js | 16 ++++---------- src/js/birth/birth.js | 14 +++++++++---- src/js/utilsDOM.js | 16 ++++++++++++++ src/js/utilsSC.js | 4 ++-- src/npc/interaction/passage/matchmaking.js | 9 +++----- 12 files changed, 77 insertions(+), 48 deletions(-) diff --git a/js/003-data/gameVariableData.js b/js/003-data/gameVariableData.js index ebdae0d3450..c53a37bbaea 100644 --- a/js/003-data/gameVariableData.js +++ b/js/003-data/gameVariableData.js @@ -808,6 +808,7 @@ App.Data.resetOnNGPlus = { milkPipeline: 0, cumPipeline: 0, wcPiping: 0, + /** @type {Map<number, "oldAge"|"overdosed"|"lowHealth">} */ slaveDeath: new Map(), playerBred: 0, playerBredTube: 0, diff --git a/src/art/artJS.js b/src/art/artJS.js index 1ae87f071f5..6c759a84739 100644 --- a/src/art/artJS.js +++ b/src/art/artJS.js @@ -13,7 +13,7 @@ Macro.add("SlaveArt", { App.Art.SlaveArtBatch = class { /** Prepare to render art in the same format for multiple slaves within a single passage context. * Do not persist this object across passage contexts. - * @param {number[]} artSlaveIDs + * @param {Iterable<number>} artSlaveIDs * @param {number} artSize Image size/center: * * 3: Large, right. Example: long slave description. * * 2: Medium, right. Example: random events. diff --git a/src/endWeek/events/death.js b/src/endWeek/events/death.js index 6b3b124ebca..af9ed44407a 100644 --- a/src/endWeek/events/death.js +++ b/src/endWeek/events/death.js @@ -18,6 +18,11 @@ App.Events.SEDeath = class SEDeath extends App.Events.BaseEvent { } execute(node) { + const artRenderer = V.seeImages && V.seeReportImages ? new App.Art.SlaveArtBatch(V.slaveDeath.keys(), 0, 0) : null; + if (artRenderer) { + node.append(artRenderer.writePreamble()); + } + for (const [id, deathType] of V.slaveDeath) { const deceased = getSlave(id); if (deceased) { @@ -47,8 +52,8 @@ App.Events.SEDeath = class SEDeath extends App.Events.BaseEvent { He, His, he, his } = getPronouns(slave); - if (V.seeImages) { - App.UI.DOM.appendNewElement("div", el, App.Art.SlaveArtElement(slave, 0, 0), ["imageRef", "tinyImg"]); + if (artRenderer) { + App.UI.DOM.appendNewElement("div", el, artRenderer.render(slave), ["imageRef", "tinyImg"]); } switch (deathType) { diff --git a/src/endWeek/events/expire.js b/src/endWeek/events/expire.js index ef2c58d67e0..85cb09d24eb 100644 --- a/src/endWeek/events/expire.js +++ b/src/endWeek/events/expire.js @@ -12,6 +12,11 @@ App.Events.SEExpiration = class SEExpiration extends App.Events.BaseEvent { execute(node) { V.encyclopedia = "Indentured Servants"; const _this = this; + const artRenderer = V.seeImages && V.seeReportImages ? new App.Art.SlaveArtBatch(_this.actors, 0, 0) : null; + if (artRenderer) { + node.append(artRenderer.writePreamble()); + } + for (const id of _this.actors) { const slave = getSlave(id); if (slave) { @@ -45,8 +50,8 @@ App.Events.SEExpiration = class SEExpiration extends App.Events.BaseEvent { he, his, him, himself, woman } = getPronouns(slave); const {title: Master} = getEnunciation(slave); - if (V.seeImages) { - App.UI.DOM.appendNewElement("div", el, App.Art.SlaveArtElement(slave, 0, 0), ["imageRef", "tinyImg"]); + if (artRenderer) { + App.UI.DOM.appendNewElement("div", el, artRenderer.render(slave), ["imageRef", "tinyImg"]); } r.push(`${slave.slaveName}'s indentured servitude is ending this week, meaning that your arcology is gaining a citizen.`); diff --git a/src/endWeek/events/retire.js b/src/endWeek/events/retire.js index ccaaf57d8f2..8448bf6549f 100644 --- a/src/endWeek/events/retire.js +++ b/src/endWeek/events/retire.js @@ -10,6 +10,11 @@ App.Events.SERetire = class SERetire extends App.Events.BaseEvent { } execute(node) { + const artRenderer = V.seeImages && V.seeReportImages ? new App.Art.SlaveArtBatch(this.actors, 2, 0) : null; + if (artRenderer) { + node.append(artRenderer.writePreamble()); + } + for (const id of this.actors) { const slave = getSlave(id); if (slave) { @@ -27,10 +32,10 @@ App.Events.SERetire = class SERetire extends App.Events.BaseEvent { }; /** - * * @param {App.Entity.SlaveState} originalSlave + * @param {App.Art.SlaveArtBatch} [artRenderer] */ -globalThis.retireScene = function(originalSlave) { +globalThis.retireScene = function(originalSlave, artRenderer) { const el = new DocumentFragment(); const slave = clone(originalSlave); removeSlave(originalSlave); @@ -49,7 +54,7 @@ globalThis.retireScene = function(originalSlave) { } const {heU, hisU, himU, girlU} = getNonlocalPronouns(V.seeDicks).appendSuffix('U'); - const art = (V.seeImages) ? App.UI.DOM.appendNewElement("div", el, App.Art.SlaveArtElement(slave, 0, 0), ["imageRef", "tinyImg"]) : document.createElement("div"); + const art = (V.seeImages) ? App.UI.DOM.drawOneSlaveRight(el, slave, artRenderer) : document.createElement("div"); const desc = App.UI.DOM.appendNewElement("div", el); const result = App.UI.DOM.appendNewElement("div", el); diff --git a/src/endWeek/reports/penthouseReport.js b/src/endWeek/reports/penthouseReport.js index 2248460d249..1fe638b39fd 100644 --- a/src/endWeek/reports/penthouseReport.js +++ b/src/endWeek/reports/penthouseReport.js @@ -20,7 +20,7 @@ App.EndWeek.penthouseReport = function() { for (const slave of App.SlaveAssignment.reportSlaves(penthouseSlaves)) { const slaveEntry = App.UI.DOM.appendNewElement("div", el, '', "slave-report"); if (penthouseArtRenderer) { - App.UI.DOM.appendNewElement("div", slaveEntry, penthouseArtRenderer.render(slave), ["imageRef", "medImg"]); + App.UI.DOM.drawOneSlaveRight(slaveEntry, slave, penthouseArtRenderer); } App.SlaveAssignment.appendSlaveLinks(slaveEntry, slave); slaveEntry.append(fullReport(slave)); @@ -28,22 +28,21 @@ App.EndWeek.penthouseReport = function() { if (slave.ID === V.HeadGirlID && hgSlave) { /* Output the HG's slave immediately after the hg */ const {He2, he2} = getPronouns(hgSlave).appendSuffix("2"); - const r = []; + const hgSlaveEntry = App.UI.DOM.appendNewElement("div", el, '', "slave-report"); if (hgSlave.assignment !== Job.HEADGIRLSUITE) { - r.push(`<span class="red">${hgSlave.slaveName} had been assigned to live with your Head Girl, but this week ${he2} was assigned to ${hgSlave.assignment}. ${He2} has been released to your penthouse for reassignment.</span>`); + App.UI.DOM.appendNewElement("span", hgSlaveEntry, `${hgSlave.slaveName} had been assigned to live with your Head Girl, but this week ${he2} was assigned to ${hgSlave.assignment}. ${He2} has been released to your penthouse for reassignment.`, "warning"); removeJob(hgSlave, Job.HEADGIRLSUITE); } else { - r.push(App.UI.DOM.makeElement("span", SlaveFullName(hgSlave), "slave-name")); - if (hgSlave.choosesOwnAssignment === 2) { - r.push(App.SlaveAssignment.choosesOwnJob(hgSlave)); - r.push(He2); - } if (penthouseArtRenderer) { - r.push(App.UI.DOM.makeElement("div", penthouseArtRenderer.render(hgSlave), ["imageRef", "medImg"])); + App.UI.DOM.drawOneSlaveRight(hgSlaveEntry, hgSlave, penthouseArtRenderer); + } + App.SlaveAssignment.appendSlaveLinks(hgSlaveEntry, hgSlave); + App.UI.DOM.appendNewElement("span", hgSlaveEntry, SlaveFullName(hgSlave), "slave-name"); + if (hgSlave.choosesOwnAssignment === 2) { + hgSlaveEntry.append(App.SlaveAssignment.choosesOwnJob(hgSlave), ` ${He2}`); } - r.push(App.SlaveAssignment.liveWithHG(hgSlave)); + hgSlaveEntry.append(` `, App.SlaveAssignment.liveWithHG(hgSlave)); } - App.Events.addNode(el, r, "div", "slave-report"); } } diff --git a/src/events/scheduled/burst/burst.js b/src/events/scheduled/burst/burst.js index d5d14df4f79..5bd6efbc5d2 100644 --- a/src/events/scheduled/burst/burst.js +++ b/src/events/scheduled/burst/burst.js @@ -10,9 +10,14 @@ App.Events.SEBurst = class SEBurst extends App.Events.BaseEvent { } execute(node) { + const artRenderer = V.seeImages && V.seeReportImages ? new App.Art.SlaveArtBatch(this.actors, 2, 0) : null; + if (artRenderer) { + node.append(artRenderer.writePreamble()); + } + for (const slave of this.actors.map(id => getSlave(id))) { if (slave.womb.length > 0) { - node.append(birth(slave)); + node.append(birth(slave, {artRenderer})); } else { node.append(pop(slave)); } @@ -32,10 +37,8 @@ App.Events.SEBurst = class SEBurst extends App.Events.BaseEvent { He, His, he, his, him } = getPronouns(slave); - if (V.seeImages && V.seeReportImages) { - r.push( - App.UI.DOM.makeElement("div", App.Art.SlaveArtElement(slave, 2, 0), ["imageRef", "medImg"]) - ); + if (artRenderer) { + App.UI.DOM.drawOneSlaveRight(el, slave, artRenderer); } r.push(`As ${slave.slaveName} is going about ${his} business with ${his} overfilled`); if (slave.inflation !== 0) { diff --git a/src/facilities/dairy/freeRangeDairyAssignmentScene.js b/src/facilities/dairy/freeRangeDairyAssignmentScene.js index c22b6a839e6..21e57308ec4 100644 --- a/src/facilities/dairy/freeRangeDairyAssignmentScene.js +++ b/src/facilities/dairy/freeRangeDairyAssignmentScene.js @@ -10,9 +10,7 @@ App.Facilities.Dairy.freeRangeAssignmentScene = function(slave) { he, him, his, himself } = getPronouns(slave); - if (V.seeImages) { - App.UI.DOM.appendNewElement("div", node, App.Art.SlaveArtElement(slave, 2, 0), ["imageRef", "medImg"]); - } + App.UI.DOM.drawOneSlaveRight(node, slave); r.push(`${slave.slaveName} reports to the dairy.`); if (slave.energy > 90 ) { @@ -65,9 +63,7 @@ App.Facilities.Dairy.freeRangeAssignmentScene = function(slave) { he2, his2, him2, } = getPronouns(cow).appendSuffix("2"); aroused = true; - if (V.seeImages) { - App.UI.DOM.appendNewElement("div", node, App.Art.SlaveArtElement(cow, 2, 0), ["imageRef", "medImg"]); - } + App.UI.DOM.drawOneSlaveRight(node, cow); r.push(`The hyper-endowed cum-cow ${cow.slaveName} is the pride of ${V.dairyName}. ${He2} is limply hanging on ${his2} milking chair, panting heavily because of the constant suction on ${his2} dick. ${He2} is obviously nearing climax. Soon,`); if (hasAnyNaturalEyes(cow)) { r.push(his2); @@ -162,17 +158,13 @@ App.Facilities.Dairy.freeRangeAssignmentScene = function(slave) { const { He2 } = getPronouns(assayedSlave).appendSuffix("2"); - if (V.seeImages === 1) { - App.UI.DOM.appendNewElement("div", node, App.Art.SlaveArtElement(assayedSlave, 2, 0), ["imageRef", "medImg"]); - } + App.UI.DOM.drawOneSlaveRight(node, assayedSlave); r.push(`${His} ${assayType} ${assayedSlave.slaveName} is at the dairy, too. ${He2} is in the adjacent stall. The two of them are going to be milked right next to each other.`); } App.Events.addParagraph(node, r); r = []; - if (S.Milkmaid && V.seeImages === 1) { - App.UI.DOM.appendNewElement("div", node, App.Art.SlaveArtElement(S.Milkmaid, 2, 0), ["imageRef", "medImg"]); - } + App.UI.DOM.drawOneSlaveRight(node, S.Milkmaid); r.push(`The only "furniture" in the stall looks like a dentist's chair. Despite the medical appearance, when ${he}`); if (slave.devotion > 90) { r.push(`eagerly`); diff --git a/src/js/birth/birth.js b/src/js/birth/birth.js index dbd4c00a620..fab3eb3645b 100644 --- a/src/js/birth/birth.js +++ b/src/js/birth/birth.js @@ -10,8 +10,13 @@ App.Events.SEBirth = class SEBirth extends App.Events.BaseEvent { } execute(node) { + const artRenderer = V.seeImages && V.seeReportImages ? new App.Art.SlaveArtBatch(this.actors, 2, 0) : null; + if (artRenderer) { + node.append(artRenderer.writePreamble()); + } + for (const slave of this.actors.map(id => getSlave(id))) { - node.append(birth(slave)); + node.append(birth(slave, {artRenderer})); node.append(sectionBreak()); } V.birthIDs = []; @@ -32,8 +37,9 @@ App.Events.SEBirth = class SEBirth extends App.Events.BaseEvent { * @param {object} [obj] * @param {boolean} [obj.birthStorm] * @param {boolean} [obj.cSection] + * @param {App.Art.SlaveArtBatch} [obj.artRenderer] */ -globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) { +globalThis.birth = function(slave, {birthStorm = false, cSection = false, artRenderer = null} = {}) { const el = document.createElement("p"); el.style.overflow = "hidden"; // Keep image from floating into the next slave. let p; @@ -59,8 +65,8 @@ globalThis.birth = function(slave, {birthStorm = false, cSection = false} = {}) he, his, him, himself, wife, girl } = getPronouns(slave); const hands = (hasBothArms(slave)) ? "hands" : "hand"; - if (V.seeImages && V.seeReportImages) { - App.UI.DOM.appendNewElement("div", el, App.Art.SlaveArtElement(slave, 2), ["imageRef", "medImg"]); + if (artRenderer) { + App.UI.DOM.drawOneSlaveRight(el, slave, artRenderer); } el.append(titleText()); suddenBirthCheck(); diff --git a/src/js/utilsDOM.js b/src/js/utilsDOM.js index c75292dc954..5d0bf432382 100644 --- a/src/js/utilsDOM.js +++ b/src/js/utilsDOM.js @@ -544,3 +544,19 @@ App.UI.DOM.makeCheckbox = function(arg) { }; return checkbox; }; + +/** + * Draw a single medium-sized slave image, floating to the right of a block of text. + * If you're rendering simple scene-wide art where the relationship between text and image location isn't important, @see App.Events.drawEventArt instead. + * @param {ParentNode} node + * @param {App.Entity.SlaveState} slave + * @param {App.Art.SlaveArtBatch} [batchRenderer] an initialized batch renderer with the preamble already output; if omitted, the entire art block will be output inline + * @returns {HTMLDivElement|DocumentFragment} + */ +App.UI.DOM.drawOneSlaveRight = function(node, slave, batchRenderer) { + if (!V.seeImages || !slave) { + return new DocumentFragment(); + } + const artElement = batchRenderer ? batchRenderer.render(slave) : App.Art.SlaveArtElement(slave, 2, 0); + return App.UI.DOM.appendNewElement("div", node, artElement, ["imageRef", "medImg"]); +}; diff --git a/src/js/utilsSC.js b/src/js/utilsSC.js index 260b3d96a22..a2de774ae8c 100644 --- a/src/js/utilsSC.js +++ b/src/js/utilsSC.js @@ -227,8 +227,8 @@ App.UI.tabBar = function() { /** handler function for slaveDescriptionDialog. do not call directly. */ App.UI._showDescriptionDialog = function(slave, options) { Dialog.setup(SlaveFullName(slave)); - const image = V.seeImages ? App.UI.DOM.makeElement("div", App.Art.SlaveArtElement(slave, 2, 0), ["imageRef", "medImg"]) : ''; - Dialog.append(image).append(App.Desc.longSlave(slave, options)); + App.UI.DOM.drawOneSlaveRight(Dialog.body(), slave); + Dialog.append(App.Desc.longSlave(slave, options)); Dialog.open(); }; diff --git a/src/npc/interaction/passage/matchmaking.js b/src/npc/interaction/passage/matchmaking.js index c5987fe2371..d06ae2cd4c3 100644 --- a/src/npc/interaction/passage/matchmaking.js +++ b/src/npc/interaction/passage/matchmaking.js @@ -14,13 +14,9 @@ App.Interact.matchmaking = function(slave) { const desc = SlaveTitle(slave); - if (V.seeImages) { - node.append( - App.UI.DOM.makeElement("div", App.Art.SlaveArtElement(slave, 2, 0), ["imageRef", "medImg"]) - ); - } + App.UI.DOM.drawOneSlaveRight(node, slave); - r.push(`You order ${slave.slaveName} to come to your office. The`); + r.push(`You order`, App.UI.DOM.slaveDescriptionDialog(slave, slave.slaveName, {noArt: true}), `to come to your office. The`); if (slave.relationship === -2) { r.push(`worshipful`); } else { @@ -222,6 +218,7 @@ App.Interact.matchmaking = function(slave) { slave.trust -= 10; subSlave.trust -= 10; } + App.Events.addParagraph(frag, r); return frag; } -- GitLab