From 8eecb1539c67b866693dfc1aeb6e331f5b4ea018 Mon Sep 17 00:00:00 2001 From: danielyxie Date: Wed, 13 Mar 2019 20:10:28 -0700 Subject: [PATCH] Fix bug with recent Corporation UI rewrite. Improve some styling with Corporation UI and the status text messages --- css/companymanagement.scss | 4 +- css/styles.scss | 5 +- src/Corporation/Corporation.jsx | 51 ++++++------------- src/Corporation/Warehouse.ts | 2 +- src/Corporation/data/ResearchMetadata.ts | 3 +- src/Corporation/ui/CityTabs.jsx | 4 +- .../ui/CorporationUIEventHandler.js | 38 ++++++++++---- src/Corporation/ui/IndustryOffice.jsx | 47 +++++++++-------- src/Corporation/ui/IndustryOverview.jsx | 3 +- src/Corporation/ui/IndustryWarehouse.jsx | 14 +++-- src/Corporation/ui/LevelableUpgrade.jsx | 7 +-- src/Corporation/ui/MainPanel.jsx | 10 ++-- src/Corporation/ui/UnlockUpgrade.jsx | 7 +-- src/DevMenu.js | 27 ++++++++++ src/ScriptEditor/CodeMirrorNetscriptMode.js | 1 + src/ui/createStatusText.ts | 4 +- 16 files changed, 140 insertions(+), 87 deletions(-) diff --git a/css/companymanagement.scss b/css/companymanagement.scss index 5fde635a6..bd632773f 100644 --- a/css/companymanagement.scss +++ b/css/companymanagement.scss @@ -60,7 +60,6 @@ overflow-y: auto; overflow-x: auto; overflow: visible; - padding: 2px; top: 10px; width: 45%; } @@ -69,18 +68,21 @@ border: 1px solid #fff; color: var(--my-font-color); display: inline-block; + padding: 3px; width: 100%; } .cmpy-mgmt-employee-panel { border: 1px solid #fff; display: block; + padding: 3px; width: 100%; } .cmpy-mgmt-warehouse-panel { border: 1px solid #fff; display: inline-block; + padding: 3px; width: 100%; } diff --git a/css/styles.scss b/css/styles.scss index fa9870bf9..bfdaeb278 100644 --- a/css/styles.scss +++ b/css/styles.scss @@ -203,7 +203,6 @@ a:visited { .status-text { display: inline-block; - height: 15%; position: fixed; z-index: 2; -webkit-animation: status-text 3s 1; @@ -215,10 +214,12 @@ a:visited { #status-text { background-color: transparent; - font-size: $defaultFontSize * 1.25; bottom: 0; color: #fff; + display: none; + font-size: $defaultFontSize * 1.25; margin-right: 14px; + opacity: 0; padding: 4px; right: 0; top: 0; diff --git a/src/Corporation/Corporation.jsx b/src/Corporation/Corporation.jsx index 3ec1511a4..e8d510de2 100644 --- a/src/Corporation/Corporation.jsx +++ b/src/Corporation/Corporation.jsx @@ -751,16 +751,20 @@ Industry.prototype.processMaterials = function(marketCycles=1, company) { } var mat = warehouse.materials[matName]; + // Calculate sale cost + const markupLimit = mat.getMarkupLimit(); var sCost; - if (isString(mat.sCost)) { + if (mat.marketTa1) { + sCost = mat.bCost + markupLimit; + } else if (isString(mat.sCost)) { sCost = mat.sCost.replace(/MP/g, mat.bCost); sCost = eval(sCost); } else { sCost = mat.sCost; } - //Calculate how much of the material sells (per second) - let markup = 1, markupLimit = mat.getMarkupLimit(); + // Calculate how much of the material sells (per second) + let markup = 1; if (sCost > mat.bCost) { //Penalty if difference between sCost and bCost is greater than markup limit if ((sCost - mat.bCost) > markupLimit) { @@ -1111,7 +1115,6 @@ Industry.prototype.discontinueProduct = function(product, parentRefs) { if (this.products.hasOwnProperty(productName)) { if (product === this.products[productName]) { delete this.products[productName]; - company.updateUIContent(); } } } @@ -1534,31 +1537,6 @@ Employee.prototype.createUI = function(panel, corporation, industry) { panel.appendChild(selector); } -Employee.prototype.updateUI = function(panel, corporation, industry) { - var effCre = this.cre * corporation.getEmployeeCreMultiplier() * industry.getEmployeeCreMultiplier(), - effCha = this.cha * corporation.getEmployeeChaMultiplier() * industry.getEmployeeChaMultiplier(), - effInt = this.int * corporation.getEmployeeIntMultiplier() * industry.getEmployeeIntMultiplier(), - effEff = this.eff * corporation.getEmployeeEffMultiplier() * industry.getEmployeeEffMultiplier(); - if (panel == null) { - console.log("ERROR: Employee.updateUI() called with null panel"); - return; - } - var text = document.getElementById("cmpy-mgmt-employee-" + this.name + "-panel-text"); - if (text == null) { - return this.createUI(panel); - } - text.innerHTML = "Morale: " + formatNumber(this.mor, 3) + "
" + - "Happiness: " + formatNumber(this.hap, 3) + "
" + - "Energy: " + formatNumber(this.ene, 3) + "
" + - "Age: " + formatNumber(this.age, 3) + "
" + - "Intelligence: " + formatNumber(effInt, 3) + "
" + - "Charisma: " + formatNumber(effCha, 3) + "
" + - "Experience: " + formatNumber(this.exp, 3) + "
" + - "Creativity: " + formatNumber(effCre, 3) + "
" + - "Efficiency: " + formatNumber(effEff, 3) + "
" + - "Salary: " + numeralWrapper.format(this.sal, "$0.000a") + "/ s
"; -} - Employee.prototype.toJSON = function() { return Generic_toJSON("Employee", this); } @@ -1606,6 +1584,10 @@ function OfficeSpace(params={}) { }; } +OfficeSpace.prototype.atCapacity = function() { + return (this.employees.length) >= this.size; +} + OfficeSpace.prototype.process = function(marketCycles=1, parentRefs) { var corporation = parentRefs.corporation, industry = parentRefs.industry; @@ -1685,6 +1667,7 @@ OfficeSpace.prototype.calculateEmployeeProductivity = function(marketCycles=1, p //Takes care of UI as well OfficeSpace.prototype.findEmployees = function(parentRefs) { var company = parentRefs.corporation, division = parentRefs.industry; + if (this.atCapacity()) { return; } if (document.getElementById("cmpy-mgmt-hire-employee-popup") != null) {return;} //Generate three random employees (meh, decent, amazing) @@ -1782,7 +1765,7 @@ OfficeSpace.prototype.hireEmployee = function(employee, parentRefs) { } employee.name = name; this.employees.push(employee); - company.displayDivisionContent(division, currentCityUi); + company.rerender(); return yesNoTxtInpBoxClose(); }); noBtn.addEventListener("click", ()=>{ @@ -1793,6 +1776,7 @@ OfficeSpace.prototype.hireEmployee = function(employee, parentRefs) { OfficeSpace.prototype.hireRandomEmployee = function(parentRefs) { var company = parentRefs.corporation, division = parentRefs.industry; + if (this.atCapacity()) { return; } if (document.getElementById("cmpy-mgmt-hire-employee-popup") != null) {return;} //Generate three random employees (meh, decent, amazing) @@ -1822,7 +1806,6 @@ OfficeSpace.prototype.hireRandomEmployee = function(parentRefs) { } emp.name = name; this.employees.push(emp); - company.displayDivisionContent(division, currentCityUi); } //Finds the first unassigned employee and assigns its to the specified job @@ -2021,7 +2004,7 @@ Corporation.prototype.getInvestment = function() { ++this.fundingRound; this.funds = this.funds.plus(funding); this.numShares -= investShares; - this.displayCorporationOverviewContent(); + this.rerender(); return yesNoBoxClose(); }); noBtn.addEventListener("click", ()=>{ @@ -2074,7 +2057,7 @@ Corporation.prototype.goPublic = function() { this.issuedShares = numShares; this.numShares -= numShares; this.funds = this.funds.plus(numShares * initialSharePrice); - this.displayCorporationOverviewContent(); + this.rerender(); removeElementById(goPublicPopupId); dialogBoxCreate(`You took your ${this.name} public and earned ` + `${numeralWrapper.formatMoney(numShares * initialSharePrice)} in your IPO`); @@ -2213,8 +2196,6 @@ Corporation.prototype.upgrade = function(upgrade) { } } } - - this.updateCorporationOverviewContent(); } Corporation.prototype.getProductionMultiplier = function() { diff --git a/src/Corporation/Warehouse.ts b/src/Corporation/Warehouse.ts index a6bf7ce27..6f7a8cdd3 100644 --- a/src/Corporation/Warehouse.ts +++ b/src/Corporation/Warehouse.ts @@ -26,7 +26,7 @@ export class Warehouse { breakdown: string = ""; // Warehouse's level, which affects its maximum size - level: number = 0; + level: number = 1; // City that this Warehouse is in loc: string; diff --git a/src/Corporation/data/ResearchMetadata.ts b/src/Corporation/data/ResearchMetadata.ts index ed61a0a97..57f6f7d5e 100644 --- a/src/Corporation/data/ResearchMetadata.ts +++ b/src/Corporation/data/ResearchMetadata.ts @@ -89,7 +89,8 @@ export const researchMetadata: IConstructorParams[] = [ desc: "Develop advanced AI software that uses technical analysis to " + "help you understand and exploit the market. This research " + "allows you to know what price to sell your Materials/Products " + - "at in order to avoid losing sales due to having too high of a mark-up.", + "at in order to avoid losing sales due to having too high of a mark-up. " + + "It also lets you automatically use that sale price.", }, { name: "Market-TA.II", diff --git a/src/Corporation/ui/CityTabs.jsx b/src/Corporation/ui/CityTabs.jsx index fd99e8323..0172a6802 100644 --- a/src/Corporation/ui/CityTabs.jsx +++ b/src/Corporation/ui/CityTabs.jsx @@ -32,6 +32,8 @@ export class CityTabs extends BaseReactComponent { } render() { + const division = this.routing().currentDivision; + const tabs = []; // Tabs for each city @@ -44,7 +46,7 @@ export class CityTabs extends BaseReactComponent { } // Tab to "Expand into new City" - const newCityOnClick = this.eventHandler().createNewCityPopup.bind(this.eventHandler()); + const newCityOnClick = this.eventHandler().createNewCityPopup.bind(this.eventHandler(), division); tabs.push(this.renderTab({ current: false, key: "Expand into new City", diff --git a/src/Corporation/ui/CorporationUIEventHandler.js b/src/Corporation/ui/CorporationUIEventHandler.js index be7ee277d..edbd70d56 100644 --- a/src/Corporation/ui/CorporationUIEventHandler.js +++ b/src/Corporation/ui/CorporationUIEventHandler.js @@ -239,6 +239,7 @@ export class CorporationEventHandler { clickListener:()=>{ industry.discontinueProduct(product, parentRefs); removeElementById(popupId); + this.corp.rerender(); return false; } }); @@ -669,6 +670,28 @@ export class CorporationEventHandler { ". This means that if you set the sale price higher than this, " + "you will begin to experience a loss in number of sales", }); + + // Enable using Market-TA1 for automatically setting sale price + const useTa1AutoSaleId = "cmpy-mgmt-marketa1-checkbox"; + const useTa1AutoSaleDiv = createElement("div", { display: "block" }); + const useTa1AutoSaleLabel = createElement("label", { + color: "white", + for: useTa1AutoSaleId, + innerText: "Use Market-TA.I for Auto-Sale Price", + tooltip: "If this is enabled, then this Material will automatically " + + "be sold at the price identified by Market-TA.I (i.e. the price shown above)" + }) + const useTa1AutoSaleCheckbox = createElement("input", { + id: useTa1AutoSaleId, + type: "checkbox", + value: mat.marketTa1, + changeListener: (e) => { + mat.marketTa1 = e.target.value; + } + }); + useTa1AutoSaleDiv.appendChild(useTa1AutoSaleCheckbox); + useTa1AutoSaleDiv.appendChild(useTa1AutoSaleCheckbox); + const closeBtn = createPopupCloseButton(popupId, { class: "std-button", display: "block", @@ -713,7 +736,7 @@ export class CorporationEventHandler { createPopup(popupId, [ta1, ta2Text, ta2Input, closeBtn]); } else { // Market-TA.I only - createPopup(popupId, [ta1, closeBtn]); + createPopup(popupId, [ta1, useTa1AutoSaleDiv, closeBtn]); } } @@ -726,13 +749,11 @@ export class CorporationEventHandler { }); const citySelector = createElement("select", { class: "dropdown", margin:"5px" }); for (const cityName in division.offices) { - if (division.offices.hasOwnProperty(cityName)) { - if (!(division.offices[cityName] instanceof OfficeSpace)) { - citySelector.add(createElement("option", { - text: cityName, - value: cityName - })); - } + if (!(division.offices[cityName] instanceof OfficeSpace)) { + citySelector.add(createElement("option", { + text: cityName, + value: cityName + })); } } @@ -740,7 +761,6 @@ export class CorporationEventHandler { class:"std-button", display:"inline-block", innerText: "Confirm", - margin:"3px", clickListener: () => { let city = citySelector.options[citySelector.selectedIndex].value; if (this.corp.funds.lt(OfficeInitialCost)) { diff --git a/src/Corporation/ui/IndustryOffice.jsx b/src/Corporation/ui/IndustryOffice.jsx index 56707f8b5..566d44588 100644 --- a/src/Corporation/ui/IndustryOffice.jsx +++ b/src/Corporation/ui/IndustryOffice.jsx @@ -117,7 +117,7 @@ export class IndustryOffice extends BaseReactComponent { // Helper functions for (re-)assigning employees to different positions const assignEmployee = (to) => { - if (this.state.numUnassigned >= 0) { + if (this.state.numUnassigned <= 0) { console.warn("Cannot assign employee. No unassigned employees available"); return; } @@ -310,7 +310,7 @@ export class IndustryOffice extends BaseReactComponent { }

- {EmployeePositions.Operations} + {EmployeePositions.Operations} ({this.state.numOperations}) Manages supply chain operations. Improves production. @@ -320,7 +320,7 @@ export class IndustryOffice extends BaseReactComponent {

- {EmployeePositions.Engineer} + {EmployeePositions.Engineer} ({this.state.numEngineers}) Develops and maintains products and production systems. Improves production. @@ -330,7 +330,7 @@ export class IndustryOffice extends BaseReactComponent {

- {EmployeePositions.Business} + {EmployeePositions.Business} ({this.state.numBusiness}) Handles sales and finances. Improves sales. @@ -340,7 +340,7 @@ export class IndustryOffice extends BaseReactComponent {

- {EmployeePositions.Management} + {EmployeePositions.Management} ({this.state.numManagement}) Leads and oversees employees and office operations. Improves production. @@ -350,7 +350,7 @@ export class IndustryOffice extends BaseReactComponent {

- {EmployeePositions.RandD} + {EmployeePositions.RandD} ({this.state.numResearch}) Research new innovative ways to improve the company. Generates Scientific Research @@ -360,7 +360,7 @@ export class IndustryOffice extends BaseReactComponent {

- {EmployeePositions.Training} + {EmployeePositions.Training} ({this.state.numTraining}) Set employee to training, which will increase some of their stats. Employees in training do not affect any company operations. @@ -402,13 +402,6 @@ export class IndustryOffice extends BaseReactComponent { } } - const employeeSelectorStyle = { - backgroundColor: "black", - color: "white", - margin: "4px", - padding: "4px", - } - // Employee Positions Selector const employeePositions = []; const positionNames = Object.values(EmployeePositions); @@ -475,7 +468,7 @@ export class IndustryOffice extends BaseReactComponent { } - {employees} @@ -492,16 +485,30 @@ export class IndustryOffice extends BaseReactComponent { } // Hire Employee button - let hireEmployeeButtonClass = "std-button tooltip"; - if (office.employees.length === 0) { - hireEmployeeButtonClass += " flashing-button"; + let hireEmployeeButtonClass = "tooltip"; + if (office.atCapacity()) { + hireEmployeeButtonClass += " a-link-button-inactive"; + } else { + hireEmployeeButtonClass += " std-button"; + if (office.employees.length === 0) { + hireEmployeeButtonClass += " flashing-button"; + } } + + const hireEmployeeButtonOnClick = () => { office.findEmployees({ corporation: corp, industry: division }); } // Autohire employee button + let autohireEmployeeButtonClass = "tooltip"; + if (office.atCapacity()) { + autohireEmployeeButtonClass += " a-link-button-inactive"; + } else { + autohireEmployeeButtonClass += " std-button"; + } const autohireEmployeeButtonOnClick = () => { + if (office.atCapacity()) { return; } office.hireRandomEmployee({ corporation: corp, industry: division }); this.corp().rerender(); } @@ -514,7 +521,7 @@ export class IndustryOffice extends BaseReactComponent { return (
-

Office Space

+

Office Space

Size: {office.employees.length} / {office.size} employees

- -
?
) } diff --git a/src/Corporation/ui/IndustryWarehouse.jsx b/src/Corporation/ui/IndustryWarehouse.jsx index 3c643ed6e..421ff5303 100644 --- a/src/Corporation/ui/IndustryWarehouse.jsx +++ b/src/Corporation/ui/IndustryWarehouse.jsx @@ -157,6 +157,7 @@ function MaterialComponent(props) { const warehouse = props.warehouse; const mat = props.mat; const eventHandler = props.eventHandler; + const markupLimit = mat.getMarkupLimit(); // Numeraljs formatter const nf = "0.000"; @@ -192,11 +193,13 @@ function MaterialComponent(props) { sellButtonText = (mat.sllman[1] === -1 ? "Sell (" + numeralWrapper.format(mat.sll, nf) + "/MAX)" : "Sell (" + numeralWrapper.format(mat.sll, nf) + "/" + numeralWrapper.format(mat.sllman[1], nf) + ")"); if (mat.sCost) { - if (isString(mat.sCost)) { + if (mat.marketTa1) { + sellButtonText += " @ " + numeralWrapper.formatMoney(mat.bCost + markupLimit); + } else if (isString(mat.sCost)) { var sCost = mat.sCost.replace(/MP/g, mat.bCost); - sellButtonText += " @ $" + numeralWrapper.format(eval(sCost), "0.00"); + sellButtonText += " @ " + numeralWrapper.formatMoney(eval(sCost)); } else { - sellButtonText += " @ $" + numeralWrapper.format(mat.sCost, "0.00"); + sellButtonText += " @ " + numeralWrapper.formatMoney(mat.sCost); } } } else { @@ -303,7 +306,7 @@ export class IndustryWarehouse extends BaseReactComponent { ++warehouse.level; warehouse.updateSize(corp, division); corp.funds = corp.funds.minus(sizeUpgradeCost); - warehouse.createUI(parentRefs); + corp.rerender(); return; } @@ -444,12 +447,13 @@ export class IndustryWarehouse extends BaseReactComponent { { corp.unlockUpgrades[1] &&
-
diff --git a/src/Corporation/ui/LevelableUpgrade.jsx b/src/Corporation/ui/LevelableUpgrade.jsx index 1c79c0d37..937652d8f 100644 --- a/src/Corporation/ui/LevelableUpgrade.jsx +++ b/src/Corporation/ui/LevelableUpgrade.jsx @@ -17,11 +17,12 @@ export class LevelableUpgrade extends BaseReactComponent { const text = `${data[4]} - ${numeralWrapper.formatMoney(cost)}` const tooltip = data[5]; const onClick = () => { - if (this.corp().funds.lt(cost)) { + const corp = this.corp(); + if (corp.funds.lt(cost)) { dialogBoxCreate("Insufficient funds"); } else { - this.corp().upgrade(data); - //this.corp().displayCorporationOverviewContent(); + corp.upgrade(data); + corp.rerender(); } } diff --git a/src/Corporation/ui/MainPanel.jsx b/src/Corporation/ui/MainPanel.jsx index d737c8baa..f67827feb 100644 --- a/src/Corporation/ui/MainPanel.jsx +++ b/src/Corporation/ui/MainPanel.jsx @@ -9,6 +9,8 @@ import { Industry } from "./Industry"; import { Overview } from "./Overview"; import { overviewPage } from "./Routing"; +import { OfficeSpace } from "../Corporation"; + import { Cities } from "../../Locations/Cities"; export class MainPanel extends BaseReactComponent { @@ -59,9 +61,11 @@ export class MainPanel extends BaseReactComponent { // City tabs const onClicks = {}; for (const cityName in division.offices) { - onClicks[cityName] = () => { - this.state.city = cityName; - this.corp().rerender(); + if (division.offices[cityName] instanceof OfficeSpace) { + onClicks[cityName] = () => { + this.state.city = cityName; + this.corp().rerender(); + } } } const cityTabs = ( diff --git a/src/Corporation/ui/UnlockUpgrade.jsx b/src/Corporation/ui/UnlockUpgrade.jsx index 1ead8b199..e719c73c7 100644 --- a/src/Corporation/ui/UnlockUpgrade.jsx +++ b/src/Corporation/ui/UnlockUpgrade.jsx @@ -11,11 +11,12 @@ export class UnlockUpgrade extends BaseReactComponent { const text = `${data[2]} - ${numeralWrapper.formatMoney(data[1])}`; const tooltip = data[3]; const onClick = () => { - if (this.corp().funds.lt(data[1])) { + const corp = this.corp(); + if (corp.funds.lt(data[1])) { dialogBoxCreate("Insufficient funds"); } else { - this.corp().unlock(data); - //this.corp().displayCorporationOverviewContent(); + corp.unlock(data); + corp.rerender(); } } diff --git a/src/DevMenu.js b/src/DevMenu.js index 95591491c..48a4cbee1 100644 --- a/src/DevMenu.js +++ b/src/DevMenu.js @@ -494,6 +494,29 @@ export function createDevMenu() { innerText: "Add cycles to Gang mechanic", }); + // Corporation + const corpHeader = createElement("h2", { innerText: "Corporation" }); + + const corpStoredCyclesInput = createElement("input", { + class: "text-input", + margin: "5px", + placeholder: "# Cycles to Add", + type: "number", + }); + + const corpStoredCyclesButton = createElement("button", { + class: "std-button", + clickListener: () => { + try { + const cycles = parseInt(bladeburnerStoredCyclesInput.value); + Player.corporation.storeCycles(cycles); + } catch(e) { + exceptionAlert(`Failed to add cycles to Bladeburner in dev menu: ${e}`); + } + }, + innerText: "Add Cycles to Corporation mechanic", + }); + // Coding Contracts const contractsHeader = createElement("h2", {innerText: "Coding Contracts"}); @@ -686,6 +709,10 @@ export function createDevMenu() { devMenuContainer.appendChild(gangStoredCyclesInput); devMenuContainer.appendChild(gangAddStoredCycles); devMenuContainer.appendChild(createElement("br")); + devMenuContainer.appendChild(corpHeader); + devMenuContainer.appendChild(corpStoredCyclesInput); + devMenuContainer.appendChild(corpStoredCyclesButton); + devMenuContainer.appendChild(createElement("br")); devMenuContainer.appendChild(contractsHeader); devMenuContainer.appendChild(generateRandomContractBtn); devMenuContainer.appendChild(generateRandomContractOnHomeBtn); diff --git a/src/ScriptEditor/CodeMirrorNetscriptMode.js b/src/ScriptEditor/CodeMirrorNetscriptMode.js index ead49e12f..2baf88d91 100644 --- a/src/ScriptEditor/CodeMirrorNetscriptMode.js +++ b/src/ScriptEditor/CodeMirrorNetscriptMode.js @@ -219,6 +219,7 @@ CodeMirror.defineMode("netscript", function(config, parserConfig) { "setActionAutolevel": atom, "setActionLevel": atom, "getRank": atom, + "getBlackOpRank": atom, "getSkillPoints": atom, "getSkillLevel": atom, "getSkillUpgradeCost": atom, diff --git a/src/ui/createStatusText.ts b/src/ui/createStatusText.ts index c0ae47446..161eb047e 100644 --- a/src/ui/createStatusText.ts +++ b/src/ui/createStatusText.ts @@ -17,11 +17,13 @@ export function createStatusText(text: string) { } const statusElement: HTMLElement = getElementById("status-text"); + statusElement.style.display = "block"; statusElement.classList.add("status-text"); statusElement.innerText = text; const handler: Action = () => { - statusElement.classList.remove("status-text"); statusElement.innerText = ""; + statusElement.style.display = "none"; + statusElement.classList.remove("status-text"); }; x = setTimeoutRef(handler, threeSeconds);