diff --git a/js/003-data/gameVariableData.js b/js/003-data/gameVariableData.js index b16a5cdd35706ac841270285aeba075fd7a73866..a40856cf4c2809a5051f981dfd2e4877c0c01ead 100644 --- a/js/003-data/gameVariableData.js +++ b/js/003-data/gameVariableData.js @@ -1098,7 +1098,7 @@ App.Data.resetOnNGPlus = { foodConsumption: 0, /* total amount food consumed per week */ revealFoodEffects: 0, rations: 0, - /** @type {App.Arcology.Building | null} */ + /** @type {App.Arcology.Building} */ building: null, menials: 0, diff --git a/src/004-base/arcologyBuilding.js b/src/004-base/arcologyBuilding.js index 72518f5534887576f354236cbd56026db8c957b9..990ab2d94deac013158bc9f52f952efc6da53a1f 100644 --- a/src/004-base/arcologyBuilding.js +++ b/src/004-base/arcologyBuilding.js @@ -40,6 +40,13 @@ App.Arcology.Cell.BaseCell = class extends App.Entity.Serializable { return 1; } + /** + * @returns {string} + */ + get name() { + return "Base Cell"; + } + /** * @returns {boolean} */ @@ -72,9 +79,15 @@ App.Arcology.Cell.BaseCell = class extends App.Entity.Serializable { /** * @param {App.Arcology.Building} containingBuilding - * @returns {Node} + * @returns {DocumentFragment} */ cellPassage(containingBuilding) { + /** + * Thanks JS! + * @type {App.Arcology.Cell.BaseCell} + */ + const _this = this; + const fragment = document.createDocumentFragment(); const scene = document.createElement("p"); @@ -88,7 +101,7 @@ App.Arcology.Cell.BaseCell = class extends App.Entity.Serializable { if (this.owner === 1) { const upgrades = document.createElement("p"); - upgrades.append(this._body()); + upgrades.append(this._body(containingBuilding)); fragment.append(upgrades); @@ -97,15 +110,30 @@ App.Arcology.Cell.BaseCell = class extends App.Entity.Serializable { if (V.rep < 5000) { fragment.append(App.UI.DOM.makeElement("p", "You don't have the reputation required to convert the sector base type.")); } else { + const cost = 50000; + const rep = 5000; for (const ac of this.allowedConversions) { const cellClass = App.Arcology.Cell[ac]; if (!(this instanceof cellClass)) { - p.append(this._makeUpgrade(`Convert sector to ${cellClass.cellName}.`, () => { + p.append(App.UI.DOM.link(`Convert sector to ${cellClass.cellName}.`, () => { + if (Dialog.isOpen()) { + Dialog.close(); + } + + /** @type {App.Arcology.Cell.BaseCell} */ const newCell = new cellClass(1); newCell.allowedConversions = this.allowedConversions; containingBuilding.replaceCell(this, newCell); - repX(-5000, "capEx"); - }, 50000, "and 5000 reputation as many citizens will lose most of what they own.")); + cashX(-cost, "capEx"); + repX(-rep, "capEx"); + + containingBuilding.refresh(); + Dialog.setup(newCell.name); + $(Dialog.body()).empty().append(newCell.cellPassage(containingBuilding)); + Dialog.open(); + })); + + App.UI.DOM.appendNewElement("span", p, ` Costs ${cashFormat(cost)} and ${rep} reputation as many citizens will lose most of what they own.`); } } } @@ -132,7 +160,7 @@ App.Arcology.Cell.BaseCell = class extends App.Entity.Serializable { if (ownedCells > 1) { const span = document.createElement("span"); span.classList.add("clear-formatting"); - span.append(App.UI.DOM.passageLink("Sell", "Main", + span.append(App.Arcology.getCellLink("Sell", _this.name, () => _this.cellPassage(containingBuilding), () => { cashX(price, "capEx"); App.Arcology.updateOwnership(); @@ -147,7 +175,7 @@ App.Arcology.Cell.BaseCell = class extends App.Entity.Serializable { if (availableCells >= 1) { const buySpan = document.createElement("span"); buySpan.classList.add("clear-formatting"); - buySpan.append(App.UI.DOM.passageLink("Buy", "Main", + buySpan.append(App.Arcology.getCellLink("Buy", _this.name, () => _this.cellPassage(containingBuilding), () => { cashX(-(price + 10000), "capEx"); A.demandFactor += 20; @@ -162,7 +190,7 @@ App.Arcology.Cell.BaseCell = class extends App.Entity.Serializable { const repPrice = Math.clamp(price / 2, 0, 18000); repDiv.append("You have so much political capital that you can spend reputation to acquire ownership by spending reputation. ", - App.UI.DOM.passageLink("Use reputation", "Main", + App.Arcology.getCellLink("Use reputation", _this.name, () => _this.cellPassage(containingBuilding), () => { repX(-(repPrice), "capEx"); A.demandFactor += 20; @@ -188,10 +216,11 @@ App.Arcology.Cell.BaseCell = class extends App.Entity.Serializable { } /** + * @param {App.Arcology.Building} containingBuilding * @returns {Node} * @protected */ - _body() { + _body(containingBuilding) { return document.createDocumentFragment(); } @@ -199,20 +228,59 @@ App.Arcology.Cell.BaseCell = class extends App.Entity.Serializable { * @param {string} name * @param {function(): void} action * @param {number} cost + * @param {App.Arcology.Building} containingBuilding * @param {string} [note] * @param {Node} [domNote] * @returns {HTMLDivElement} * @protected */ - _makeUpgrade(name, action, cost, note, domNote) { + _makeInternalUpgrade(name, action, cost, containingBuilding, note, domNote) { const div = document.createElement("div"); - div.append(App.UI.DOM.passageLink(name, "Main", + div.append(App.Arcology.getCellLink(name, this.name, () => this.cellPassage(containingBuilding), () => { cashX(-cost, "capEx"); action(); })); + this._upgradeNote(div, cost, note, domNote); + + return div; + } + + /** + * @param {string} name + * @param {function(): void} action + * @param {number} cost + * @param {string} passage + * @param {string} [note] + * @param {Node} [domNote] + * @returns {HTMLDivElement} + * @protected + */ + _makeExternalUpgrade(name, action, cost, passage, note, domNote) { + const div = document.createElement("div"); + + div.append(App.UI.DOM.passageLink(name, passage, + () => { + cashX(-cost, "capEx"); + action(); + Dialog.close(); + })); + + this._upgradeNote(div, cost, note, domNote); + + return div; + } + + /** + * @param {HTMLDivElement} div + * @param {number} cost + * @param {string} [note] + * @param {Node} [domNote] + * @private + */ + _upgradeNote(div, cost, note, domNote) { if (cost > 0 || note === undefined) { note = ` Costs ${cashFormat(cost)}${note !== undefined ? ` ${note}` : ""}.`; } @@ -221,8 +289,6 @@ App.Arcology.Cell.BaseCell = class extends App.Entity.Serializable { if (domNote !== undefined) { div.append(domNote); // this only exists for the farmyard, remove once that is out of alpha } - - return div; } /** diff --git a/src/005-passages/arcologyBuildingPassages.js b/src/005-passages/arcologyBuildingPassages.js deleted file mode 100644 index cf43a8f8c94f8fe949f96093d7cd9e8f2d71481b..0000000000000000000000000000000000000000 --- a/src/005-passages/arcologyBuildingPassages.js +++ /dev/null @@ -1,8 +0,0 @@ -new App.DomPassage("Cell", - () => { - V.nextButton = "Back"; - V.nextLink = "Main"; - - return V.building.renderCell(V.cellPath); - }, ["jump-from-safe", "no-history"] -); diff --git a/src/arcologyBuilding/apartments.js b/src/arcologyBuilding/apartments.js index 03c088276cb1c4542ad7b85e90baf15faa22552e..22156338a08bb884ba79e2e3e7b42e9d5f49d627 100644 --- a/src/arcologyBuilding/apartments.js +++ b/src/arcologyBuilding/apartments.js @@ -30,23 +30,28 @@ App.Arcology.Cell.Apartment = class extends App.Arcology.Cell.BaseCell { } /** - * @param {Array<number>} path - * @returns {Node} + * @override + * @returns {string} */ - cellContent(path) { - let message = ""; + get name() { switch (this.type) { case 1: - message = "Luxury Apartments"; - break; + return "Luxury Apartments"; case 2: - message = "Apartments"; - break; + return "Apartments"; case 3: - message = "Dense Apartments"; - break; + return"Dense Apartments"; + default: + return super.name; } - return App.Arcology.getCellLink(path, message); + } + + /** + * @param {Array<number>} path + * @returns {Node} + */ + cellContent(path) { + return App.Arcology.getCellLinkFromPath(path, this.name); } /** @@ -81,27 +86,27 @@ App.Arcology.Cell.Apartment = class extends App.Arcology.Cell.BaseCell { * @returns {Node} * @override @protected */ - _body() { + _body(containingBuilding) { const fragment = document.createDocumentFragment(); const cost = 10000 * V.upgradeMultiplierArcology; if (this.type !== 3) { - fragment.append(this._makeUpgrade( + fragment.append(this._makeInternalUpgrade( "Upgrade this sector of apartments for dense occupancy by as many citizens as possible.", - () => { this.type = 3; }, cost)); + () => { this.type = 3; }, cost, containingBuilding)); } if (this.type !== 1) { - fragment.append(this._makeUpgrade( + fragment.append(this._makeInternalUpgrade( "Improve this sector of apartments for occupancy by the Free Cities' wealthiest citizens.", - () => { this.type = 1; }, cost)); + () => { this.type = 1; }, cost, containingBuilding)); } if (this.type !== 2) { - fragment.append(this._makeUpgrade( + fragment.append(this._makeInternalUpgrade( "Return this sector to standard, mixed housing.", - () => { this.type = 2; }, cost)); + () => { this.type = 2; }, cost, containingBuilding)); } return fragment; diff --git a/src/arcologyBuilding/base.js b/src/arcologyBuilding/base.js index 3cfb869b8f01008982d4857eb827bc27aef80f5a..48f031f1058b97e9439021bd5c75f2202c986345 100644 --- a/src/arcologyBuilding/base.js +++ b/src/arcologyBuilding/base.js @@ -3,8 +3,30 @@ * @param {string} message * @returns {Node} */ -App.Arcology.getCellLink = function(path, message) { - return App.UI.DOM.passageLink(message, "Cell", () => { V.cellPath = path; }); +App.Arcology.getCellLinkFromPath = function(path, message) { + return App.Arcology.getCellLink(message, message, () => V.building.renderCell(path)); +}; + +/** + * @param {string} linkText + * @param {string} title + * @param {function():(HTMLDivElement|DocumentFragment)} content + * @param {function():void} [callback] + * @returns {HTMLAnchorElement} + */ +App.Arcology.getCellLink = function(linkText, title, content, callback) { + return App.UI.DOM.link(linkText, () => { + if (Dialog.isOpen()) { + Dialog.close(); + } + if (callback) { + callback(); + V.building.refresh(); + } + Dialog.setup(title); + $(Dialog.body()).empty().append(content()); + Dialog.open(); + }); }; /** @@ -157,7 +179,7 @@ App.Arcology.Section = class extends App.Entity.Serializable { /** * @param {Array<number>} path of the form [i, j] * @param {App.Arcology.Building} containingBuilding - * @returns {Node} + * @returns {DocumentFragment} */ renderCell(path, containingBuilding) { return this.rows[path[0]][path[1]].cellPassage(containingBuilding); @@ -233,9 +255,23 @@ App.Arcology.Building = class extends App.Entity.Serializable { } /** - * @returns {DocumentFragment} + * @returns {HTMLDivElement} */ render() { + const div = document.createElement("div"); + div.id = "arcology-building-container"; + div.append(this.renderInner()); + return div; + } + + refresh() { + App.UI.DOM.replace("#arcology-building-container", this.renderInner()); + } + + /** + * @returns {DocumentFragment} + */ + renderInner() { const fragment = document.createDocumentFragment(); let maxWidth = 0; @@ -266,7 +302,7 @@ App.Arcology.Building = class extends App.Entity.Serializable { /** * @param {Array<*>} path - * @returns {Node} + * @returns {DocumentFragment} */ renderCell(path) { return this.sections[path[0]].renderCell(path.slice(1), this); diff --git a/src/arcologyBuilding/manufacturing.js b/src/arcologyBuilding/manufacturing.js index 3740265670b2020829661a47e814058f63a4c792..ab6cb5d55e3cb6fc643ac3264434e0865d33dd12 100644 --- a/src/arcologyBuilding/manufacturing.js +++ b/src/arcologyBuilding/manufacturing.js @@ -36,6 +36,14 @@ App.Arcology.Cell.Manufacturing = class extends App.Arcology.Cell.BaseCell { } } + /** + * @override + * @returns {string} + */ + get name() { + return this.type; + } + /** * @returns {boolean} */ @@ -48,17 +56,15 @@ App.Arcology.Cell.Manufacturing = class extends App.Arcology.Cell.BaseCell { * @returns {Node} */ cellContent(path) { - if (this.type === "Dairy") { - return App.Arcology.facilityCellContent(App.Entity.facilities.dairy); - } - if (this.type === "Farmyard") { - return App.Arcology.facilityCellContent(App.Entity.facilities.farmyard); - } switch (this.type) { + case "Dairy": + return App.Arcology.facilityCellContent(App.Entity.facilities.dairy); + case"Farmyard": + return App.Arcology.facilityCellContent(App.Entity.facilities.farmyard); case "Manufacturing": case "Pens": case "Sweatshops": - return App.Arcology.getCellLink(path, this.type); + return App.Arcology.getCellLinkFromPath(path, this.type); case "Barracks": return App.UI.DOM.passageLink("Barracks", "Barracks"); case "Weapon Manufacturing": @@ -107,7 +113,7 @@ App.Arcology.Cell.Manufacturing = class extends App.Arcology.Cell.BaseCell { * @returns {Node} * @protected @override */ - _body() { + _body(containingBuilding) { const fragment = document.createDocumentFragment(); const pensDOM = pens(this); @@ -187,73 +193,73 @@ App.Arcology.Cell.Manufacturing = class extends App.Arcology.Cell.BaseCell { const cost = Math.trunc(10000 * V.upgradeMultiplierArcology); if (V.dairy === 0) { - fragment.append(thisCell._makeUpgrade( + fragment.append(thisCell._makeExternalUpgrade( "Construct a dairy to milk slaves on an industrial scale", () => { V.dairy = 5; thisCell.type = "Dairy"; - }, cost, "and will incur upkeep costs" + }, cost, "Dairy", "and will incur upkeep costs" )); } if (V.experimental.food === 1) { if (V.farmyard === 0) { - fragment.append(thisCell._makeUpgrade( + fragment.append(thisCell._makeExternalUpgrade( "Construct a farming facility to grow food for your arcology and house animals", () => { V.farmyard = 5; thisCell.type = "Farmyard"; - }, cost, "and will incur upkeep costs" + }, cost, "Farmyard", "and will incur upkeep costs" )); } } if (V.mercenaries) { if (V.barracks !== 1) { - fragment.append(thisCell._makeUpgrade( + fragment.append(thisCell._makeExternalUpgrade( "Build an armory to properly house your mercenaries", () => { V.barracks = 1; thisCell.type = "Barracks"; - }, cost, "but will reduce mercenary upkeep" + }, cost, "Barracks", "but will reduce mercenary upkeep" )); } } if (V.secExpEnabled > 0 && !V.SecExp.buildings.weapManu) { - fragment.append(thisCell._makeUpgrade( + fragment.append(thisCell._makeExternalUpgrade( "Convert this sector to weapons manufacturing", () => { App.SecExp.weapManu.Init(); thisCell.type = "Weapon Manufacturing"; - }, cost, "but will provide a weekly income and will unlock upgrades for our troops" + }, cost, "Weapon Manufacturing", "but will provide a weekly income and will unlock upgrades for our troops" )); } if (thisCell.type !== "Pens") { - fragment.append(thisCell._makeUpgrade( + fragment.append(thisCell._makeInternalUpgrade( "Convert to pens to increase the number of menial slaves you can house", () => { thisCell.type = "Pens"; - }, cost + }, cost, containingBuilding )); } if (thisCell.type !== "Sweatshops") { - fragment.append(thisCell._makeUpgrade( + fragment.append(thisCell._makeInternalUpgrade( "Convert these facilities to use the labor of menial slaves", () => { thisCell.type = "Sweatshops"; - }, cost + }, cost, containingBuilding )); } if (thisCell.type !== "Manufacturing") { - fragment.append(thisCell._makeUpgrade( + fragment.append(thisCell._makeInternalUpgrade( "Return this sector to standard manufacturing", () => { thisCell.type = "Manufacturing"; - }, cost + }, cost, containingBuilding )); } diff --git a/src/arcologyBuilding/markets.js b/src/arcologyBuilding/markets.js index 4d3caebf3da39a6a352492e0dbe317030317a98c..a42238708b7fd1370f4695466de288b74936910a 100644 --- a/src/arcologyBuilding/markets.js +++ b/src/arcologyBuilding/markets.js @@ -32,6 +32,14 @@ App.Arcology.Cell.Market = class extends App.Arcology.Cell.BaseCell { } } + /** + * @override + * @returns {string} + */ + get name() { + return this.type; + } + isBaseType() { return this.type === "Markets"; } @@ -47,22 +55,14 @@ App.Arcology.Cell.Market = class extends App.Arcology.Cell.BaseCell { case "Pit": return App.Arcology.facilityCellContent(App.Entity.facilities.pit); case "Markets": - return App.Arcology.getCellLink(path, "Markets"); + return App.Arcology.getCellLinkFromPath(path, "Markets"); case "Transport Hub": return App.UI.DOM.passageLink("Transport Hub", "transportHub"); case "Corporate Market": return App.UI.DOM.passageLink( "Corporate Market", "Market", - () => { - V.market = new App.Markets.GlobalVariable(); - V.market.slaveMarket = "corporate"; - V.market.newSlaves = []; - V.market.numArcology = 1; - V.nextButton = "Back to Main"; - V.nextLink = "Main"; - V.returnTo = "Main"; - } + this._prepareCorporateMarket ); default: return App.UI.DOM.makeElement("span", "ERROR: invalid type: " + this.type, "error"); @@ -87,55 +87,69 @@ App.Arcology.Cell.Market = class extends App.Arcology.Cell.BaseCell { * @returns {Node} * @protected @override */ - _body() { + _body(containingBuilding) { const fragment = document.createDocumentFragment(); const cost = Math.trunc(10000 * V.upgradeMultiplierArcology); if (V.arcade === 0) { - fragment.append(this._makeUpgrade( + fragment.append(this._makeExternalUpgrade( "Construct a sex arcade to present slaves' holes for public use", () => { this.type = "Arcade"; V.arcade = 10; - }, cost, "and will incur upkeep costs" + }, cost, "Arcade", "and will incur upkeep costs" )); } if (!V.pit) { - fragment.append(this._makeUpgrade( + fragment.append(this._makeExternalUpgrade( "Build a pit to host proper slave fights", () => { this.type = "Pit"; App.Facilities.Pit.init(); - }, cost + }, cost, "Pit" )); } if (V.secExpEnabled > 0 && !V.SecExp.buildings.transportHub) { - fragment.append(this._makeUpgrade( + fragment.append(this._makeExternalUpgrade( "Centralize and modernize the transport hub", () => { this.type = "Transport Hub"; App.SecExp.transportHub.Init(); - }, cost + }, cost, "transportHub" )); } const corpCost = Math.trunc(10000 * V.upgradeMultiplierArcology); if (V.corp.Market === 0 && V.corp.Incorporated === 1) { - fragment.append(this._makeUpgrade( + fragment.append(this._makeExternalUpgrade( "Create a flagship slave market for your corporation here", () => { this.type = "Corporate Market"; V.corp.Market = 1; V.corp.Cash -= corpCost; - }, 0, ` Costs ${cashFormat(corpCost)} of the corporation's money` + this._prepareCorporateMarket(); + }, 0, "Market", ` Costs ${cashFormat(corpCost)} of the corporation's money` )); } return fragment; } + /** + * @private + */ + _prepareCorporateMarket() { + V.market = new App.Markets.GlobalVariable(); + V.market.slaveMarket = "corporate"; + V.market.newSlaves = []; + V.market.numArcology = 1; + V.nextButton = "Back to Main"; + V.nextLink = "Main"; + V.returnTo = "Main"; + } + /** * @returns {boolean} */ diff --git a/src/arcologyBuilding/shops.js b/src/arcologyBuilding/shops.js index 036e978a95d2b788a568ad8719bb73d3be1bc73c..60e78b1e91c2f6aa829cbd995a44bdf30d822a5b 100644 --- a/src/arcologyBuilding/shops.js +++ b/src/arcologyBuilding/shops.js @@ -28,6 +28,21 @@ App.Arcology.Cell.Shop = class extends App.Arcology.Cell.BaseCell { } } + /** + * @override + * @returns {string} + */ + get name() { + switch (this.type) { + case "Shops": + case "Brothel": + case "Club": + return this.type; + default: + return `${this.type} Shops`; + } + } + isBaseType() { return this.type === "Shops"; } @@ -42,9 +57,9 @@ App.Arcology.Cell.Shop = class extends App.Arcology.Cell.BaseCell { } else if (this.type === "Club") { return App.Arcology.facilityCellContent(App.Entity.facilities.club); } else if (this.type === "Shops") { - return App.Arcology.getCellLink(path, this.type); + return App.Arcology.getCellLinkFromPath(path, this.type); } else { - return App.Arcology.getCellLink(path, `${this.type} Shops`); + return App.Arcology.getCellLinkFromPath(path, `${this.type} Shops`); } } @@ -309,49 +324,49 @@ App.Arcology.Cell.Shop = class extends App.Arcology.Cell.BaseCell { * @returns {Node} * @protected @override */ - _body() { + _body(containingBuilding) { const fragment = document.createDocumentFragment(); const A = V.arcologies[0]; const cost = Math.trunc(10000 * V.upgradeMultiplierArcology); if (V.brothel === 0) { - fragment.append(this._makeUpgrade( + fragment.append(this._makeExternalUpgrade( "Convert this sector of the promenade into a brothel.", () => { V.brothel = 5; this.type = "Brothel"; - }, cost, "and will incur upkeep costs" + }, cost, "Brothel", "and will incur upkeep costs" )); } if (V.club === 0) { - fragment.append(this._makeUpgrade( + fragment.append(this._makeExternalUpgrade( "Build a club to serve as a focal point for public sluts.", () => { V.club = 5; this.type = "Club"; - }, cost, "and will incur upkeep costs" + }, cost, "Club", "and will incur upkeep costs" )); } for (const FS of FutureSocieties.activeFSes(A)) { const decorationName = FutureSocieties.decorationName(FS); if (decorationName && !App.Arcology.hasShopOfType(decorationName)) { - fragment.append(this._makeUpgrade( + fragment.append(this._makeInternalUpgrade( `Upgrade this sector to appeal to ${FutureSocieties.displayAdj(FS)} establishments.`, () => { this.type = decorationName; - }, cost + }, cost, containingBuilding )); } } if (this.type !== "Shops") { - fragment.append(this._makeUpgrade( + fragment.append(this._makeInternalUpgrade( "Return this sector to standard outlets", () => { this.type = "Shops"; - }, cost + }, cost, containingBuilding )); }