From 6f7e344b7a389477812e8f4711bf072d808a5a6d Mon Sep 17 00:00:00 2001 From: Svornost <11434-svornost@users.noreply.gitgud.io> Date: Wed, 22 Feb 2023 00:01:56 -0500 Subject: [PATCH] Bodyswap cleanup 1. `$swappingSlave` is now an ID instead of a cloned object. 2. Eliminate many direct slave index lookups. 3. Clearly comment that `origBodyOwner` and `origBodyOwnerID` actually store exactly opposite data despite having pretty much the same name. 4. Fix various bugs dealing with tracking original bodies. 5. Fix body swap reactions upon regaining one's original body, and don't emit the same spuriously. --- src/js/SlaveState.js | 4 +- src/npc/surgery/bodySwap/bodySwap.js | 4 +- src/npc/surgery/bodySwap/bodySwapReaction.js | 35 +++++--- src/npc/surgery/bodySwap/huskSlaveSwap.js | 74 ++++++++-------- src/npc/surgery/bodySwap/slaveSlaveSwap.js | 89 +++++++++++--------- 5 files changed, 111 insertions(+), 95 deletions(-) diff --git a/src/js/SlaveState.js b/src/js/SlaveState.js index 2f4285e3dc4..4954d4c97a5 100644 --- a/src/js/SlaveState.js +++ b/src/js/SlaveState.js @@ -2611,9 +2611,9 @@ App.Entity.SlaveState = class SlaveState { * * 0: yes; 1+: number of swaps (increases upkeep each time) */ this.bodySwap = 0; - /** Who, if relevant, the body belonged to. */ + /** Who, if relevant, this slave's current body belonged to originally. */ this.origBodyOwner = ""; - /** Who, if relevant, the body belonged to. */ + /** Who, if relevant, this slave's original body currently belongs to (i.e. the exact opposite of the variable above). */ this.origBodyOwnerID = 0; /** * Slave's current hormonal balance, directs saHormones changes diff --git a/src/npc/surgery/bodySwap/bodySwap.js b/src/npc/surgery/bodySwap/bodySwap.js index b532dae1485..5c6cdb2c71a 100644 --- a/src/npc/surgery/bodySwap/bodySwap.js +++ b/src/npc/surgery/bodySwap/bodySwap.js @@ -261,7 +261,7 @@ globalThis.bodySwapSelection = function(soul) { App.UI.DOM.link( body.slaveName, () => { - V.swappingSlave = body; + V.swappingSlave = body.ID; cashX(forceNeg(cost), "slaveSurgery", body); }, [], @@ -335,7 +335,7 @@ globalThis.huskSwapSelection = function(body) { App.UI.DOM.link( soul.slaveName, () => { - V.swappingSlave = soul; + V.swappingSlave = soul.ID; cashX(forceNeg(cost), "slaveSurgery", soul); }, [], diff --git a/src/npc/surgery/bodySwap/bodySwapReaction.js b/src/npc/surgery/bodySwap/bodySwapReaction.js index b18c2db8460..a95555ac5a3 100644 --- a/src/npc/surgery/bodySwap/bodySwapReaction.js +++ b/src/npc/surgery/bodySwap/bodySwapReaction.js @@ -2028,25 +2028,32 @@ globalThis.bodySwapReaction = function(body, soul) { } } + App.Events.addParagraph(el, r); + r = []; if (body.fetish !== Fetish.MINDBROKEN) { + let recognizesBody = false; if (body.origBodyOwnerID === body.ID) { r.push(`This is ${his} body alright.`); + recognizesBody = true; } else if (body.ID === body.cloneID) { r.push(`This feels like ${his} body, in a sense.`); + recognizesBody = true; } - r.push(`Some things might have changed,`); - if (body.devotion > 50) { - r.push(`but ${he} enjoyed the time they spent apart.`); - } else if (body.devotion >= -20) { - r.push(`but <span class="mediumaquamarine">it's good to be home.</span>`); - body.trust += 15; - } else { - r.push(`but <span class="mediumaquamarine">${he}'s where ${he} belongs.</span> Now to get it back the way <span class="mediumorchid">${he} likes it.</span>`); - body.trust += 30; - body.devotion -= 15; - } - if (body.ID === body.cloneID) { - r.push(`Whether or not ${he}'ll figure out it is a clone of ${his} original body remains to be seen.`); + if (recognizesBody) { + r.push(`Some things might have changed,`); + if (body.devotion > 50) { + r.push(`but ${he} enjoyed the time they spent apart.`); + } else if (body.devotion >= -20) { + r.push(`but <span class="mediumaquamarine">it's good to be home.</span>`); + body.trust += 15; + } else { + r.push(`but <span class="mediumaquamarine">${he}'s where ${he} belongs.</span> Now to get it back the way <span class="mediumorchid">${he} likes it.</span>`); + body.trust += 30; + body.devotion -= 15; + } + if (body.ID === body.cloneID) { + r.push(`Whether or not ${he}'ll figure out it is a clone of ${his} original body remains to be seen.`); + } } } } @@ -3782,6 +3789,8 @@ globalThis.bodySwapReaction = function(body, soul) { } } + App.Events.addParagraph(el, r); + r = []; if (body.fetish !== Fetish.MINDBROKEN) { if (body.origBodyOwnerID === body.ID) { r.push(`This is ${his} body alright. Some things might have changed,`); diff --git a/src/npc/surgery/bodySwap/huskSlaveSwap.js b/src/npc/surgery/bodySwap/huskSlaveSwap.js index 599ceb4acfd..56a0b484bfe 100644 --- a/src/npc/surgery/bodySwap/huskSlaveSwap.js +++ b/src/npc/surgery/bodySwap/huskSlaveSwap.js @@ -1,61 +1,61 @@ App.UI.SlaveInteract.huskSlaveSwap = function() { const node = new DocumentFragment(); - const oldSlave = clone(V.swappingSlave); - const m = V.slaveIndices[V.swappingSlave.ID]; + const target = getSlave(V.swappingSlave); + const oldSlave = clone(target); const { he - } = getPronouns(V.swappingSlave); + } = getPronouns(target); - App.UI.DOM.appendNewElement("p", node, `You strap ${V.slaves[m].slaveName}, and the body to which ${he} will be transferred, into the remote surgery and stand back as it goes to work.`); - bodySwap(V.slaves[m], V.activeSlave, false); - const gps = V.genePool.findIndex(function(s) { return s.ID === V.slaves[m].ID; }); - // special exception to swap genePool since the temporary body lacks an entry. Otherwise we could just call the widget using the genePool entries - V.genePool[gps].race = V.slaves[m].race; - V.genePool[gps].origRace = V.slaves[m].origRace; - V.genePool[gps].skin = V.slaves[m].skin; - V.genePool[gps].markings = V.slaves[m].markings; - V.genePool[gps].eye.origColor = V.slaves[m].eye.origColor; - V.genePool[gps].origHColor = V.slaves[m].origHColor; - V.genePool[gps].origSkin = V.slaves[m].origSkin; - V.genePool[gps].face = V.slaves[m].face; - V.genePool[gps].pubicHStyle = V.slaves[m].pubicHStyle; - V.genePool[gps].underArmHStyle = V.slaves[m].underArmHStyle; - V.genePool[gps].eyebrowHStyle = V.slaves[m].eyebrowHStyle; + App.UI.DOM.appendNewElement("p", node, `You strap ${target.slaveName}, and the body to which ${he} will be transferred, into the remote surgery and stand back as it goes to work.`); + bodySwap(target, V.activeSlave, false); + const gps = V.genePool.find(s => s.ID === target.ID); + // special exception to swap genePool since the temporary body lacks an entry. Otherwise we could just call bodySwap using the genePool entries + gps.race = target.race; + gps.origRace = target.origRace; + gps.skin = target.skin; + gps.markings = target.markings; + gps.eye.origColor = target.eye.origColor; + gps.origHColor = target.origHColor; + gps.origSkin = target.origSkin; + gps.face = target.face; + gps.pubicHStyle = target.pubicHStyle; + gps.underArmHStyle = target.underArmHStyle; + gps.eyebrowHStyle = target.eyebrowHStyle; App.Events.addParagraph(node, [ - `After an honestly impressive procedure, ${V.slaves[m].slaveName} is recovering nicely.`, - bodySwapReaction(V.slaves[m], oldSlave) + `After an honestly impressive procedure, ${target.slaveName} is recovering nicely.`, + bodySwapReaction(target, oldSlave) ]); const cost = slaveCost(oldSlave); const payout = Math.trunc(cost/3); let r = []; - r.push(`${V.slaves[m].slaveName}'s old body was bought by the Flesh Heap for ${cashFormat(payout)}.`); - if (V.slaves[m].bodySwap > 0) { - const myBody = V.slaves.findIndex(function(s) { return s.origBodyOwnerID === V.slaves[m].ID; }); - if (myBody !== -1) { - V.slaves[myBody].origBodyOwnerID = 0; + r.push(`${target.slaveName}'s old body was bought by the Flesh Heap for ${cashFormat(payout)}.`); + if (target.bodySwap > 0) { + const origBodyOwner = V.slaves.find(s => s.origBodyOwnerID === target.ID); + if (origBodyOwner) { + origBodyOwner.origBodyOwnerID = 0; const { he2, him2, his2 - } = getPronouns(V.slaves[myBody]).appendSuffix("2"); - if (V.slaves[myBody].fetish !== Fetish.MINDBROKEN && V.slaves[myBody].fuckdoll === 0) { - if (V.slaves[myBody].devotion > 20) { - r.push(`${V.slaves[myBody].slaveName} is somewhat saddened to see ${his2} body leave forever.`); - } else if (V.slaves[myBody].devotion >= -50) { - r.push(`${V.slaves[myBody].slaveName} is <span class="mediumorchid">disturbed</span> to find ${his2} body is gone for good, damaging ${his2} <span class="gold">ability to trust you.</span>`); - V.slaves[myBody].devotion -= 30; - V.slaves[myBody].trust -= 30; + } = getPronouns(origBodyOwner).appendSuffix("2"); + if (origBodyOwner.fetish !== Fetish.MINDBROKEN && origBodyOwner.fuckdoll === 0) { + if (origBodyOwner.devotion > 20) { + r.push(`${origBodyOwner.slaveName} is somewhat saddened to see ${his2} body leave forever.`); + } else if (origBodyOwner.devotion >= -50) { + r.push(`${origBodyOwner.slaveName} is <span class="mediumorchid">disturbed</span> to find ${his2} body is gone for good, damaging ${his2} <span class="gold">ability to trust you.</span>`); + origBodyOwner.devotion -= 30; + origBodyOwner.trust -= 30; } else { - r.push(`${V.slaves[myBody].slaveName} is <span class="mediumorchid">deeply upset</span> that ${he2}'ll never see ${his2} body again. With so little left, ${he2} finds it easy to take vengeance by <span class="orangered">completely rejecting your ownership of ${him2}.</span>`); - V.slaves[myBody].devotion -= 50; - V.slaves[myBody].trust = 100; + r.push(`${origBodyOwner.slaveName} is <span class="mediumorchid">deeply upset</span> that ${he2}'ll never see ${his2} body again. With so little left, ${he2} finds it easy to take vengeance by <span class="orangered">completely rejecting your ownership of ${him2}.</span>`); + origBodyOwner.devotion -= 50; + origBodyOwner.trust = 100; } } } } App.Events.addParagraph(node, r); - V.slaves[m].bodySwap++; + target.bodySwap++; cashX(payout, "slaveTransfer"); V.activeSlave = 0; V.swappingSlave = 0; diff --git a/src/npc/surgery/bodySwap/slaveSlaveSwap.js b/src/npc/surgery/bodySwap/slaveSlaveSwap.js index 285c6cf015f..77097c3d15b 100644 --- a/src/npc/surgery/bodySwap/slaveSlaveSwap.js +++ b/src/npc/surgery/bodySwap/slaveSlaveSwap.js @@ -1,57 +1,55 @@ App.UI.SlaveInteract.slaveSlaveSwap = function() { const node = new DocumentFragment(); - const ss1 = V.slaveIndices[V.AS]; - const ss1Clone = clone(getSlave(V.AS)); + const ss1 = getSlave(V.AS); + const ss1Clone = clone(ss1); - const ss2 = V.slaveIndices[V.swappingSlave.ID]; - const ss2Clone = clone(V.swappingSlave); + const ss2 = getSlave(V.swappingSlave); + const ss2Clone = clone(ss2); - const gps1 = V.genePool.findIndex(s => s.ID === V.slaves[ss1].ID); - const gps1Clone = clone(V.genePool[gps1]); + const gps1 = V.genePool.find(s => s.ID === ss1.ID); + const gps1Clone = clone(gps1); - const gps2 = V.genePool.findIndex(s => s.ID === V.slaves[ss2].ID); - const gps2Clone = clone(V.genePool[gps2]); + const gps2 = V.genePool.find(s => s.ID === ss2.ID); + const gps2Clone = clone(gps2); - App.UI.DOM.appendNewElement("p", node, `You strap ${getSlave(V.AS).slaveName} and ${V.swappingSlave.slaveName} into the remote surgery and stand back as it goes to work.`); + App.UI.DOM.appendNewElement("p", node, `You strap ${ss1.slaveName} and ${ss2.slaveName} into the remote surgery and stand back as it goes to work.`); - bodySwap(V.slaves[ss1], ss2Clone, false); - bodySwap(V.genePool[gps1], gps2Clone, true); + bodySwap(ss1, ss2Clone, false); + bodySwap(gps1, gps2Clone, true); - bodySwap(V.slaves[ss2], ss1Clone, false); - bodySwap(V.genePool[gps2], gps1Clone, true); + bodySwap(ss2, ss1Clone, false); + bodySwap(gps2, gps1Clone, true); + + // figuring out who has whose body now + whoHasWho(ss1, ss2, ss2Clone); + whoHasWho(ss2, ss1, ss1Clone); + + // now to handle whose body it is, name-wise + bodySwapName(ss1, ss2Clone); + bodySwapName(ss2, ss1Clone); App.Events.addParagraph(node, [ - `After an honestly impressive procedure, ${V.slaves[ss1].slaveName} is recovering nicely.`, - bodySwapReaction(V.slaves[ss1], ss1Clone) + `After an honestly impressive procedure, ${ss1.slaveName} is recovering nicely.`, + bodySwapReaction(ss1, ss1Clone) ]); App.UI.DOM.appendNewElement("hr", node); App.Events.addParagraph(node, [ - `In the neighboring bed, ${V.slaves[ss2].slaveName} rests peacefully.`, - bodySwapReaction(V.slaves[ss2], ss2Clone) + `In the neighboring bed, ${ss2.slaveName} rests peacefully.`, + bodySwapReaction(ss2, ss2Clone) ]); - // figuring out whom has whose body now - whoHasWho(ss1, ss2Clone); - whoHasWho(ss2, ss1Clone); - - // now to handle whose body it is, name-wise - bodySwapName(V.slaves[ss1], V.slaves[ss2]); - bodySwapName(V.slaves[ss2], V.slaves[ss1]); - for (const ss of [ss1, ss2]) { - if (ss1Clone.bodySwap > 0) { - if (V.slaves[ss].origBodyOwnerID === V.slaves[ss].ID) { - V.slaves[ss].bodySwap = 0; - V.slaves[ss].origBodyOwnerID = 0; - V.slaves[ss].origBodyOwner = ""; - } else { - V.slaves[ss].bodySwap++; - } + if (ss.origBodyOwnerID === ss.ID) { + // if we got our own original body back, clear our bodyswap records + ss.bodySwap = 0; + ss.origBodyOwnerID = 0; + ss.origBodyOwner = ""; } else { - V.slaves[ss].bodySwap++; + // otherwise, increment the bodyswap counter + ss.bodySwap++; } } @@ -59,13 +57,22 @@ App.UI.SlaveInteract.slaveSlaveSwap = function() { V.swappingSlave = 0; return node; - function whoHasWho(index, opposingClone) { - if (V.slaves[index].bodySwap === 0) { - V.slaves[index].origBodyOwnerID = opposingClone.ID; - } else if (V.slaves[ss2].origBodyOwner !== "") { // now who's going to be looking for you? - const myBody = V.slaves.findIndex(function(s) { return s.origBodyOwnerID === V.slaves[ss2].ID; }); - if (myBody !== -1) { - V.slaves[myBody].origBodyOwnerID = V.slaves[index].ID; + /** Update origBodyOwnerID appropriately. + * @param {App.Entity.SlaveState} target + * @param {App.Entity.SlaveState} opposing + * @param {App.Entity.SlaveState} opposingClone + */ + function whoHasWho(target, opposing, opposingClone) { + if (opposingClone.bodySwap === 0) { + // if my new body came directly from its original owner, give them a reference to me + opposing.origBodyOwnerID = target.ID; + } else { + // if my new body originally belonged to someone else, update the original owner's reference to point to me + // note that the original owner may also be me; we'll take care of that later (after generating the reaction) + // but we never want to find a self-reference, since those are always temporary + const originalOwner = V.slaves.find(s => s.origBodyOwnerID === opposingClone.ID && s.origBodyOwnerID !== s.ID); + if (originalOwner) { + originalOwner.origBodyOwnerID = target.ID; } } } -- GitLab