diff --git a/js/medicine/surgery/prosthetics/backInterface.js b/js/medicine/surgery/prosthetics/backInterface.js new file mode 100644 index 0000000000000000000000000000000000000000..da810396805abba37c5d2b666ca2a17983c16b40 --- /dev/null +++ b/js/medicine/surgery/prosthetics/backInterface.js @@ -0,0 +1,29 @@ +App.Medicine.Surgery.Reactions.BackInterface = class extends App.Medicine.Surgery.SimpleReaction { + reaction(slave, diff) { + const reaction = super.reaction(slave, diff); + const {his} = getPronouns(slave); + const r = []; + + r.push(`Implanting back sockets and interfacing them with ${his} spinal column is a delicate and invasive procedure <span class="health dec">${his} health has been greatly affected.</span>`); + + reaction.longReaction.push(r); + return reaction; + } +}; + +App.Medicine.Surgery.Procedures.BackInterface = class extends App.Medicine.Surgery.Procedure { + get name() { + return "Implant back interface"; + } + + get healthCost() { + return 20; + } + + apply(cheat) { + this._slave.PBack = 1; + this._slave.appendages = "none"; + this._slave.appendagesColor = "none"; + return this._assemble(new App.Medicine.Surgery.Reactions.BackInterface()); + } +}; diff --git a/js/medicine/surgery/prosthetics/pLimbInterface.js b/js/medicine/surgery/prosthetics/pLimbInterface.js new file mode 100644 index 0000000000000000000000000000000000000000..afe7babf98d707bfb9cbf85c905c8377dbd53ba8 --- /dev/null +++ b/js/medicine/surgery/prosthetics/pLimbInterface.js @@ -0,0 +1,96 @@ +App.Medicine.Surgery.Reactions.PLimbInterface = class extends App.Medicine.Surgery.SimpleReaction { + /** + * @param {FC.LimbsState} oldLimbs + */ + constructor(oldLimbs) { + super(); + this.oldLimbs = oldLimbs; + } + + reaction(slave, diff) { + const reaction = super.reaction(slave, diff); + const r = []; + + r.push(App.Medicine.Limbs.prosthetic(slave, this.oldLimbs)); + + reaction.longReaction.push(r); + return reaction; + } +}; + +App.Medicine.Surgery.Procedures.BasicPLimbInterface = class extends App.Medicine.Surgery.Procedure { + get name() { + return "Install basic prosthetic interface"; + } + + get healthCost() { + return 20; + } + + apply(cheat) { + const oldLimbs = App.Medicine.Limbs.currentLimbs(this._slave); + this._slave.PLimb = 1; + return this._assemble(new App.Medicine.Surgery.Reactions.PLimbInterface(oldLimbs)); + } +}; + +App.Medicine.Surgery.Procedures.AdvancedPLimbInterface = class extends App.Medicine.Surgery.Procedure { + get name() { + if (this.originalSlave.PLimb === 0) { + return "Install advanced prosthetic interface"; + } else if (this.originalSlave.PLimb === 1) { + return "Upgrade to advanced prosthetic interface"; + } else { + return "Downgrade to advanced prosthetic interface"; + } + } + + get disabledReasons() { + const r = []; + const {He} = getPronouns(this.originalSlave); + if (this.originalSlave.PLimb === 3 && hasAnyProstheticLimbs(this.originalSlave)) { + r.push(`${He} still has limbs attached. Remove all limbs before downgrading.`); + } + return r; + } + + get healthCost() { + return 20; + } + + apply(cheat) { + const oldLimbs = App.Medicine.Limbs.currentLimbs(this._slave); + this._slave.PLimb = 2; + return this._assemble(new App.Medicine.Surgery.Reactions.PLimbInterface(oldLimbs)); + } +}; + +App.Medicine.Surgery.Procedures.QuadrupedalPLimbInterface = class extends App.Medicine.Surgery.Procedure { + get name() { + if (this.originalSlave.PLimb === 0) { + return "Install quadrupedal prosthetic interface"; + } else { + return "Upgrade to quadrupedal prosthetic interface"; + } + } + + get disabledReasons() { + const r = []; + const {He} = getPronouns(this.originalSlave); + if ((this.originalSlave.PLimb === 1 || this.originalSlave.PLimb === 2) && + hasAnyProstheticLimbs(this.originalSlave)) { + r.push(`${He} still has limbs attached. Remove all limbs before upgrading.`); + } + return r; + } + + get healthCost() { + return 20; + } + + apply(cheat) { + const oldLimbs = App.Medicine.Limbs.currentLimbs(this._slave); + this._slave.PLimb = 3; + return this._assemble(new App.Medicine.Surgery.Reactions.PLimbInterface(oldLimbs)); + } +}; diff --git a/js/medicine/surgery/prosthetics/tailInterface.js b/js/medicine/surgery/prosthetics/tailInterface.js new file mode 100644 index 0000000000000000000000000000000000000000..301b41b9d0a58d242d8e07e9a149e7da807f85e6 --- /dev/null +++ b/js/medicine/surgery/prosthetics/tailInterface.js @@ -0,0 +1,29 @@ +App.Medicine.Surgery.Reactions.TailInterface = class extends App.Medicine.Surgery.SimpleReaction { + reaction(slave, diff) { + const reaction = super.reaction(slave, diff); + const {his} = getPronouns(slave); + const r = []; + + r.push(`Implanting a tail socket and interfacing it with ${his} spinal column is delicate and invasive procedure <span class="health dec">${his} health has been greatly affected.</span>`); + + reaction.longReaction.push(r); + return reaction; + } +}; + +App.Medicine.Surgery.Procedures.TailInterface = class extends App.Medicine.Surgery.Procedure { + get name() { + return "Implant interface"; + } + + get healthCost() { + return 10; + } + + apply(cheat) { + this._slave.PTail = 1; + this._slave.tail = "none"; + this._slave.tailColor = "none"; + return this._assemble(new App.Medicine.Surgery.Reactions.TailInterface()); + } +}; diff --git a/js/medicine/surgery/reaction/backInterface.js b/js/medicine/surgery/reaction/backInterface.js deleted file mode 100644 index 736b3277552a76bbd7e0363462be6d95db3bc519..0000000000000000000000000000000000000000 --- a/js/medicine/surgery/reaction/backInterface.js +++ /dev/null @@ -1,18 +0,0 @@ -{ - class BackInterface extends App.Medicine.Surgery.Reaction { - get key() { return "backInterface"; } - - reaction(slave, diff) { - const reaction = super.reaction(slave, diff); - const {his} = getPronouns(slave); - const r = []; - - r.push(`Implanting back sockets and interfacing them with ${his} spinal column is a delicate and invasive procedure <span class="health dec">${his} health has been greatly affected.</span>`); - - reaction.longReaction.push(r); - return reaction; - } - } - - new BackInterface(); -} diff --git a/js/medicine/surgery/reaction/pLimbInterface.js b/js/medicine/surgery/reaction/pLimbInterface.js deleted file mode 100644 index ab230e2ceff79ce93b3515dc170c583b533cca1d..0000000000000000000000000000000000000000 --- a/js/medicine/surgery/reaction/pLimbInterface.js +++ /dev/null @@ -1,19 +0,0 @@ -{ - class PLimbInterface extends App.Medicine.Surgery.Reaction { - get key() { return "PLimb interface"; } - - reaction(slave, diff) { - const reaction = super.reaction(slave, diff); - const r = []; - - V.nextButton = " "; - r.push(App.Medicine.Limbs.prosthetic(slave, V.oldLimbs, "Remote Surgery")); // FIXME: Property 'oldLimbs' does not exist on type 'GameVariables'. - delete V.oldLimbs; - - reaction.longReaction.push(r); - return reaction; - } - } - - new PLimbInterface(); -} diff --git a/js/medicine/surgery/reaction/tailInterface.js b/js/medicine/surgery/reaction/tailInterface.js deleted file mode 100644 index 591047ec685946624caf4d43f3ad33c79679c9fb..0000000000000000000000000000000000000000 --- a/js/medicine/surgery/reaction/tailInterface.js +++ /dev/null @@ -1,18 +0,0 @@ -{ - class TailInterface extends App.Medicine.Surgery.Reaction { - get key() { return "tailInterface"; } - - reaction(slave, diff) { - const reaction = super.reaction(slave, diff); - const {his} = getPronouns(slave); - const r = []; - - r.push(`Implanting a tail socket and interfacing it with ${his} spinal column is delicate and invasive procedure <span class="health dec">${his} health has been greatly affected.</span>`); - - reaction.longReaction.push(r); - return reaction; - } - } - - new TailInterface(); -} diff --git a/src/facilities/surgery/multiImplant.js b/src/facilities/surgery/multiImplant.js index ab28412c582ab1b1c1fc91e128cf465254b2c923..e85d5a27647d1d072b39fb85eaef4b5da9283b22 100644 --- a/src/facilities/surgery/multiImplant.js +++ b/src/facilities/surgery/multiImplant.js @@ -220,13 +220,7 @@ App.UI.multipleOrganImplant = function() { } break; case "interfaceTail": - slave.PTail = 1; - slave.tail = "none"; - slave.tailColor = "none"; - cashX(forceNeg(V.surgeryCost), "slaveSurgery", slave); - surgeryDamage(slave, 10); - V.surgeryType = "tailInterface"; - node.append(App.UI.SlaveInteract.surgeryDegradation(slave)); + applyProcedure(new App.Medicine.Surgery.Procedures.TailInterface(slave)); break; case "modT": case "sexT": @@ -257,13 +251,7 @@ App.UI.multipleOrganImplant = function() { } break; case "interfaceBack": - slave.PBack = 1; - slave.appendages = "none"; - slave.appendagesColor = "none"; - cashX(forceNeg(V.surgeryCost), "slaveSurgery", slave); - surgeryDamage(slave, 10); - V.surgeryType = "backInterface"; - node.append(App.UI.SlaveInteract.surgeryDegradation(slave)); + applyProcedure(new App.Medicine.Surgery.Procedures.BackInterface(slave)); break; case "modW": case "flightW": @@ -317,6 +305,26 @@ App.UI.multipleOrganImplant = function() { return node; + /** + * @param {App.Medicine.Surgery.Procedure} procedure + */ + function applyProcedure(procedure) { + // TODO: dedupe with organfarm and main surgery + const result = App.Medicine.Surgery.apply(procedure, false); + if (result === null) { + App.UI.DOM.includePassage(node, "Surgery Death"); + return; + } + + const [diff, reaction] = result; + + const f = App.Medicine.Surgery.makeSlaveReaction(procedure.originalSlave, diff, reaction); + + App.Utils.Diff.applyDiff(procedure.originalSlave, diff); + + node.append(f); + } + function intro() { const frag = document.createDocumentFragment(); diff --git a/src/facilities/surgery/surgeryPassageStructural.js b/src/facilities/surgery/surgeryPassageStructural.js index 55168f026a4ff932e04f4572c7f817a57de7d513..72ab09b9f1bc3f59654939b0143df09e26021b4d 100644 --- a/src/facilities/surgery/surgeryPassageStructural.js +++ b/src/facilities/surgery/surgeryPassageStructural.js @@ -361,73 +361,18 @@ App.UI.surgeryPassageStructural = function(slave, refreshParent, cheat = false) const el = new DocumentFragment(); const r = []; const linkArray = []; - if (!hasAllNaturalLimbs(slave) && slave.PLimb === 0) { - if (isProstheticAvailable(slave, "interfaceP1")) { - linkArray.push(makeLink( - "Install basic prosthetic interface", - "PLimb interface", - () => { - V.oldLimbs = App.Medicine.Limbs.currentLimbs(slave); - slave.PLimb = 1; - surgeryDamage(slave, 20); - } - )); + if (!hasAllNaturalLimbs(slave)) { + if (slave.PLimb === 0 && isProstheticAvailable(slave, "interfaceP1")) { + linkArray.push(App.Medicine.Surgery.makeLink( + new App.Medicine.Surgery.Procedures.BasicPLimbInterface(slave), refresh, cheat)); } - if (isProstheticAvailable(slave, "interfaceP2")) { - linkArray.push(makeLink( - "Install advanced prosthetic interface", - "PLimb interface", - () => { - V.oldLimbs = App.Medicine.Limbs.currentLimbs(slave); - slave.PLimb = 2; - surgeryDamage(slave, 20); - } - )); + if (slave.PLimb !== 2 && isProstheticAvailable(slave, "interfaceP2")) { + linkArray.push(App.Medicine.Surgery.makeLink( + new App.Medicine.Surgery.Procedures.AdvancedPLimbInterface(slave), refresh, cheat)); } - if (isProstheticAvailable(slave, "interfaceP3")) { - linkArray.push(makeLink( - "Install quadrupedal prosthetic interface", - "PLimb interface", - () => { - V.oldLimbs = App.Medicine.Limbs.currentLimbs(slave); - slave.PLimb = 3; - surgeryDamage(slave, 20); - } - )); - } - } else if (slave.PLimb === 1 && isProstheticAvailable(slave, "interfaceP2")) { - linkArray.push(makeLink( - "Upgrade to advanced prosthetic interface", - "PLimb interface", - () => { - V.oldLimbs = App.Medicine.Limbs.currentLimbs(slave); - slave.PLimb = 2; - surgeryDamage(slave, 5); - } - )); - } else if (slave.PLimb === 2 && isProstheticAvailable(slave, "interfaceP3")) { - linkArray.push(makeLink( - "Upgrade to quadrupedal prosthetic interface", - "PLimb interface", - () => { - V.oldLimbs = App.Medicine.Limbs.currentLimbs(slave); - slave.PLimb = 3; - surgeryDamage(slave, 5); - } - )); - } else if (slave.PLimb === 3 && isProstheticAvailable(slave, "interfaceP2")) { - if (!hasAnyLimbs(slave)) { - linkArray.push(makeLink( - "Downgrade to advanced prosthetic interface", - "PLimb interface", - () => { - V.oldLimbs = App.Medicine.Limbs.currentLimbs(slave); - slave.PLimb = 2; - surgeryDamage(slave, 5); - } - )); - } else { - r.push(`${He} still has limbs attached. Remove all limbs before downgrading.`); + if (slave.PLimb !== 3 && isProstheticAvailable(slave, "interfaceP3")) { + linkArray.push(App.Medicine.Surgery.makeLink( + new App.Medicine.Surgery.Procedures.QuadrupedalPLimbInterface(slave), refresh, cheat)); } } App.Events.addNode(el, r, "div"); @@ -443,16 +388,9 @@ App.UI.surgeryPassageStructural = function(slave, refreshParent, cheat = false) r.push(`${He} has a neural interface allowing attachment of tails.`); } else if (isProstheticAvailable(slave, "interfaceTail")) { r.push(`${He} lacks a neural interface allowing attachment of tails.`); - linkArray.push(makeLink( - "Implant interface", - "tailInterface", - () => { - slave.PTail = 1; - slave.tail = "none"; - slave.tailColor = "none"; - surgeryDamage(slave, 10); - } - )); + linkArray.push(App.Medicine.Surgery.makeLink( + new App.Medicine.Surgery.Procedures.TailInterface(slave), + refresh, cheat)); } else { r.push(`${He} lacks a neural interface allowing attachment of tails and you have none ready for ${him}.`); } @@ -469,16 +407,9 @@ App.UI.surgeryPassageStructural = function(slave, refreshParent, cheat = false) r.push(`${He} has a neural back interface allowing attachment of dorsal appendages.`); } else if (isProstheticAvailable(slave, "interfaceBack")) { r.push(`${He} lacks a neural back interface allowing attachment of dorsal appendages.`); - linkArray.push(makeLink( - "Implant back interface", - "backInterface", - () => { - slave.PBack = 1; - slave.appendages = "none"; - slave.appendagesColor = "none"; - surgeryDamage(slave, 20); - } - )); + linkArray.push(App.Medicine.Surgery.makeLink( + new App.Medicine.Surgery.Procedures.BackInterface(slave), + refresh, cheat)); } else { r.push(`${He} lacks a neural back interface allowing attachment of dorsal appendages and you have none ready for ${him}.`); } @@ -488,43 +419,6 @@ App.UI.surgeryPassageStructural = function(slave, refreshParent, cheat = false) } } - /** - * - * @param {string} title - * @param {string} surgeryType - * @param {function(void):void} [func] - * @param {number} [costMult=1] - * @param {string} [note] - * @returns {HTMLAnchorElement} - */ - function makeLink(title, surgeryType, func, costMult = 1, note = "") { - const cost = Math.trunc(V.surgeryCost * costMult); - const tooltip = new DocumentFragment(); - App.UI.DOM.appendNewElement("div", tooltip, cost !== 0 ? `Costs ${cashFormat(cost)}` : `Free`); - if (note) { - App.UI.DOM.appendNewElement("div", tooltip, note); - } - return App.UI.DOM.link( - title, - () => { - if (typeof func === "function") { - func(); - } - if (cheat) { - refresh(); - } else { - V.surgeryType = surgeryType; - // TODO: pass if it affected health or not? - cashX(forceNeg(cost), "slaveSurgery", slave); - Engine.play("Surgery Degradation"); - } - }, - [], - "", - tooltip - ); - } - function refresh() { jQuery(container).empty().append(content()); App.Events.refreshEventArt(slave); diff --git a/src/interaction/prostheticConfig.js b/src/interaction/prostheticConfig.js index 1098a588feb0d828d56b103a1e786116ca83eb5a..44147410af15659fb89f0fca0c1fedfcbf71e45b 100644 --- a/src/interaction/prostheticConfig.js +++ b/src/interaction/prostheticConfig.js @@ -605,13 +605,6 @@ App.UI.prostheticsConfigPassage = function(slave) { V.nextLink = "Slave Interact"; node.append(App.UI.prostheticsConfig(slave)); break; - case "limbs": - V.prostheticsConfig = "main"; - V.nextButton = "Continue"; - V.nextLink = "Prosthetics Configuration"; - node.append(App.Medicine.Limbs.reaction(slave, V.oldLimbs)); - delete V.oldLimbs; - break; case "hearing": V.prostheticsConfig = "main"; V.nextButton = "Continue"; diff --git a/src/npc/descriptions/limbs.js b/src/npc/descriptions/limbs.js index 1e559d9a26ccd60cf3b9c5133b602b1a9901e387..885c7f526904e2d353c301e98acc8f434b9772cd 100644 --- a/src/npc/descriptions/limbs.js +++ b/src/npc/descriptions/limbs.js @@ -72,33 +72,38 @@ App.Medicine.Limbs.amputate = function(slave, oldLimbs) { function install(id) { slave.PLimb = id; surgeryDamage(slave, 10); - App.UI.DOM.replace("#amputate", App.Medicine.Limbs.prosthetic(slave, oldLimbs, "")); + App.UI.DOM.replace("#amputate", App.Medicine.Limbs.prosthetic(slave, oldLimbs)); } function noInstall() { - App.UI.DOM.replace("#amputate", App.Medicine.Limbs.reaction(slave, oldLimbs, "")); + App.UI.DOM.replace("#amputate", App.Medicine.Limbs.reaction(slave, oldLimbs)); } // check if there is a limb interface installed already, if there is show limb selection screen if (slave.PLimb > 0) { - return App.Medicine.Limbs.prosthetic(slave, oldLimbs, ""); + return App.Medicine.Limbs.prosthetic(slave, oldLimbs); } - return App.Medicine.Limbs.reaction(slave, oldLimbs, ""); + return App.Medicine.Limbs.reaction(slave, oldLimbs); }; /** * @param {App.Entity.SlaveState} slave * @param {FC.LimbsState} oldLimbs - * @param {string} returnTo * @returns {DocumentFragment|HTMLDivElement} */ -App.Medicine.Limbs.prosthetic = function(slave, oldLimbs, returnTo) { - if (!((isProstheticAvailable(slave, "basicL") && slave.PLimb < 3) || (isProstheticAvailable(slave, "sexL") && slave.PLimb < 3) - || (isProstheticAvailable(slave, "beautyL") && slave.PLimb < 3) || (isProstheticAvailable(slave, "combatL") && slave.PLimb < 3) - || (isProstheticAvailable(slave, "cyberneticL") && slave.PLimb === 2) || (isProstheticAvailable(slave, "felidaeL") && slave.PLimb > 2) - || (isProstheticAvailable(slave, "canidaeL") && slave.PLimb > 2) || (isProstheticAvailable(slave, "felidaeCL") && slave.PLimb > 2) - || (isProstheticAvailable(slave, "canidaeCL") && slave.PLimb > 2))) { - return App.Medicine.Limbs.reaction(slave, oldLimbs, returnTo); +App.Medicine.Limbs.prosthetic = function(slave, oldLimbs) { + if (!( + (isProstheticAvailable(slave, "basicL") && slave.PLimb < 3) || + (isProstheticAvailable(slave, "sexL") && slave.PLimb < 3) || + (isProstheticAvailable(slave, "beautyL") && slave.PLimb < 3) || + (isProstheticAvailable(slave, "combatL") && slave.PLimb < 3) || + (isProstheticAvailable(slave, "cyberneticL") && slave.PLimb === 2) || + (isProstheticAvailable(slave, "felidaeL") && slave.PLimb > 2) || + (isProstheticAvailable(slave, "canidaeL") && slave.PLimb > 2) || + (isProstheticAvailable(slave, "felidaeCL") && slave.PLimb > 2) || + (isProstheticAvailable(slave, "canidaeCL") && slave.PLimb > 2) + )) { + return App.Medicine.Limbs.reaction(slave, oldLimbs); } const {him} = getPronouns(slave); @@ -106,7 +111,7 @@ App.Medicine.Limbs.prosthetic = function(slave, oldLimbs, returnTo) { div.id = "selector"; App.UI.DOM.appendNewElement("div", div, `Since you already have limbs prepared for ${him} you might as well attach them while you are working on ${him}:`); - div.append(App.Medicine.Limbs.selector(slave, oldLimbs, returnTo)); + div.append(App.Medicine.Limbs.selector(slave, oldLimbs)); return div; }; @@ -115,10 +120,9 @@ App.Medicine.Limbs.prosthetic = function(slave, oldLimbs, returnTo) { * Displays a selector for prosthetic limbs of slave * @param {App.Entity.SlaveState} slave * @param {FC.LimbsState} oldLimbs - * @param {string} [returnTo=""] * @returns {HTMLSpanElement|DocumentFragment} */ -App.Medicine.Limbs.selector = function(slave, oldLimbs, returnTo = "") { +App.Medicine.Limbs.selector = function(slave, oldLimbs) { const {her} = getPronouns(slave); if (hasAllNaturalLimbs(slave)) { return App.UI.DOM.makeElement("span", `You must amputate ${her} limbs before you can attach prosthetics.`, "detail"); @@ -154,25 +158,15 @@ App.Medicine.Limbs.selector = function(slave, oldLimbs, returnTo = "") { }); f.append(limbSelector); - f.append(apply()); + f.append( + App.UI.DOM.link("Apply", () => { + applySelector(slave, newState); + App.UI.DOM.replace("#selector", App.Medicine.Limbs.reaction(slave, oldLimbs)); + }) + ); return f; - function apply() { - V.AS = slave.ID; - - return App.UI.DOM.link("Apply", () => { - applySelector(slave, newState); - if (returnTo) { - App.UI.DOM.replace("#selector", App.Medicine.Limbs.reaction(slave, oldLimbs, returnTo)); - } else { - V.prostheticsConfig = "limbs"; - V.oldLimbs = oldLimbs; - Engine.play("Prosthetics Configuration"); - } - }); - } - /** * Generates an array with the current limbs of a slave. * @param {App.Entity.SlaveState} slave