mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-18 05:33:54 +01:00
V 0.34.2 Changes
This commit is contained in:
parent
8d72dd0f4e
commit
5f817c8016
@ -126,7 +126,6 @@
|
||||
margin:4px;
|
||||
padding:12px;
|
||||
border-radius:25px;
|
||||
width:45%;
|
||||
color:var(--my-font-color);
|
||||
}
|
||||
|
||||
|
@ -64,26 +64,6 @@
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
#script-editor-save-and-close-button,
|
||||
#script-editor-netscript-doc-button,
|
||||
#script-editor-status-text {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#script-editor-status-text {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
#script-editor-save-and-close-button {
|
||||
float:left;
|
||||
}
|
||||
|
||||
#script-editor-netscript-doc-button {
|
||||
float: right;
|
||||
padding-right: 0px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
#script-editor-wrapper {
|
||||
height:100%;
|
||||
width: 70%;
|
||||
|
2544
dist/bundle.js
vendored
2544
dist/bundle.js
vendored
File diff suppressed because it is too large
Load Diff
@ -101,11 +101,7 @@
|
||||
|
||||
<div id="javascript-editor"></div>
|
||||
|
||||
<div id="script-editor-buttons-wrapper">
|
||||
<span id="script-editor-save-and-close-button" class="a-link-button">Save & Close (Ctrl + b)</span>
|
||||
<p id="script-editor-status-text"> </p>
|
||||
<a id="script-editor-netscript-doc-button" class="a-link-button" href="https://bitburner.wikia.com/wiki/Netscript" target="_blank"> Netscript Documentation </a>
|
||||
</div>
|
||||
<div id="script-editor-buttons-wrapper"></div> <!-- Buttons below script editor -->
|
||||
</div> <!-- End wrapper -->
|
||||
|
||||
<div id="script-editor-options-panel">
|
||||
|
@ -356,7 +356,7 @@ let CompanyPositions = {
|
||||
CompanyPositions.VicePresident.setPerformanceParameters(70, 0, 0, 0, 0, 30, 1.75);
|
||||
CompanyPositions.VicePresident.setExperienceGains(1.2, 0, 0, 0, 0, .6);
|
||||
CompanyPositions.CTO.setPerformanceParameters(65, 0, 0, 0, 0, 35, 2);
|
||||
CompanyPositions.CTO.setExperienceGains(1.5, 0, 0, 0, 1);
|
||||
CompanyPositions.CTO.setExperienceGains(1.5, 0, 0, 0, 0, 1);
|
||||
|
||||
//Business
|
||||
CompanyPositions.BusinessIntern.setPerformanceParameters(10, 0, 0, 0, 0, 90, 0.9);
|
||||
|
@ -59,12 +59,10 @@ var WarehouseInitialCost = 5e9; //Initial purchase cost of warehouse
|
||||
var WarehouseInitialSize = 100;
|
||||
var WarehouseUpgradeBaseCost = 1e9;
|
||||
|
||||
var OfficeInitialCost = 5e9;
|
||||
var OfficeInitialCost = 4e9;
|
||||
var OfficeInitialSize = 3;
|
||||
var OfficeUpgradeBaseCost = 1e9;
|
||||
|
||||
|
||||
|
||||
function Material(params={}) {
|
||||
this.name = params.name ? params.name : "";
|
||||
this.qty = 0; //Quantity
|
||||
@ -529,6 +527,20 @@ var ProductRatingWeights = {
|
||||
}
|
||||
}
|
||||
|
||||
//Industry upgrades
|
||||
//The structure is:
|
||||
// [index in array, base price, price mult, benefit mult (if applicable), name, desc]
|
||||
var IndustryUpgrades = {
|
||||
"0": [0, 500e3, 1, 1.05,
|
||||
"Coffee", "Provide your employees with coffee, increasing their energy by 5%."],
|
||||
"1": [1, 1e9, 1.02, 1.01,
|
||||
"AdVert.Inc", "Hire AdVert.Inc to advertise your company. Each level of " +
|
||||
"this upgrade grants your company a static increase of 5 and 1 to its awareness and " +
|
||||
"popularity, respectively. It will then increase your company's awareness by 1%, and its popularity " +
|
||||
"by a random percentage between 5% and 15%. These effects are increased by other upgrades " +
|
||||
"that increase the power of your advertising."]
|
||||
}
|
||||
|
||||
var empManualAssignmentModeActive = false;
|
||||
function Industry(params={}) {
|
||||
this.offices = { //Maps locations to offices. 0 if no office at that location
|
||||
@ -594,6 +606,10 @@ function Industry(params={}) {
|
||||
this.thisCycleRevenue = new Decimal(0);
|
||||
this.thisCycleExpenses = new Decimal(0);
|
||||
|
||||
//Upgrades
|
||||
var numUpgrades = Object.keys(IndustryUpgrades).length;
|
||||
this.upgrades = Array(numUpgrades).fill(0);
|
||||
|
||||
this.state = "START";
|
||||
|
||||
this.init();
|
||||
@ -750,6 +766,10 @@ Industry.prototype.init = function() {
|
||||
case Industries.Software:
|
||||
this.sciFac = 0.7;
|
||||
this.advFac = 0.5;
|
||||
this.hwFac = 0.25;
|
||||
this.reFac = 0.1;
|
||||
this.aiFac = 0.1;
|
||||
this.robFac = 0.05;
|
||||
this.reqMats = {
|
||||
"Hardware": 0.5,
|
||||
"Energy": 1,
|
||||
@ -878,6 +898,18 @@ Industry.prototype.process = function(marketCycles=1, state, company) {
|
||||
//Process change in demand/competition of materials/products
|
||||
this.processMaterialMarket(marketCycles);
|
||||
this.processProductMarket(marketCycles);
|
||||
|
||||
//Process loss of popularity
|
||||
this.popularity -= (marketCycles * .0001);
|
||||
this.popularity = Math.max(0, this.popularity);
|
||||
|
||||
//Process Dreamsense gains
|
||||
var popularityGain = company.getDreamSenseGain(), awarenessGain = popularityGain * 4;
|
||||
if (popularityGain > 0) {
|
||||
this.popularity += (popularityGain * marketCycles);
|
||||
this.awareness += (awarenessGain * marketCycles);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1048,9 +1080,6 @@ Industry.prototype.processMaterials = function(marketCycles=1, company) {
|
||||
Math.pow(this.sciResearch.qty, this.sciFac) +
|
||||
Math.pow(warehouse.materials["AICores"].qty, this.aiFac) / 10e3);
|
||||
}
|
||||
} else {
|
||||
console.log("Production of materials failed because producableFrac <= 0 or prod <= 0.");
|
||||
console.log("prod: " + prod);
|
||||
}
|
||||
//Per second
|
||||
var fooProd = prod * producableFrac / (SecsPerMarketCycle * marketCycles);
|
||||
@ -1065,7 +1094,10 @@ Industry.prototype.processMaterials = function(marketCycles=1, company) {
|
||||
for (var matName in warehouse.materials) {
|
||||
if (warehouse.materials.hasOwnProperty(matName)) {
|
||||
var mat = warehouse.materials[matName];
|
||||
if (mat.sCost < 0 || mat.sllman[0] === false) {continue;}
|
||||
if (mat.sCost < 0 || mat.sllman[0] === false) {
|
||||
mat.sll = 0;
|
||||
continue;
|
||||
}
|
||||
var mat = warehouse.materials[matName];
|
||||
|
||||
var sCost;
|
||||
@ -1093,7 +1125,8 @@ Industry.prototype.processMaterials = function(marketCycles=1, company) {
|
||||
}
|
||||
var businessFactor = 1 + (office.employeeProd[EmployeePositions.Business] / office.employeeProd["total"]);
|
||||
var maxSell = (mat.qlt + .001) * mat.dmd * (100 - mat.cmp)/100 * markup * businessFactor *
|
||||
(this.awareness === 0 ? 0.01 : (this.popularity + .001) / this.awareness);
|
||||
Math.pow(this.awareness + 1, 0.05) * Math.pow(this.popularity + 1, 0.07) *
|
||||
(this.awareness === 0 ? 0.01 : Math.max((this.popularity + .001) / this.awareness, 0.01));
|
||||
var sellAmt;
|
||||
if (mat.sllman[1] !== -1) {
|
||||
//Sell amount is manually limited
|
||||
@ -1301,7 +1334,8 @@ Industry.prototype.processProduct = function(marketCycles=1, product, corporatio
|
||||
}
|
||||
}
|
||||
var maxSell = Math.pow(product.rat, 0.95) * product.dmd * (1-(product.cmp/100)) *
|
||||
(this.awareness === 0 ? 0.01 : (this.popularity+0.001) / this.awareness) * markup;
|
||||
markup * businessFactor * Math.pow(this.awareness + 1, 0.05) * Math.pow(this.popularity + 1, 0.07) *
|
||||
(this.awareness === 0 ? 0.01 : Math.max((this.popularity + .001) / this.awareness, 0.01));
|
||||
var sellAmt;
|
||||
if (product.sllman[city][0] && product.sllman[city][1] > 0) {
|
||||
//Sell amount is manually limited
|
||||
@ -1345,6 +1379,33 @@ Industry.prototype.discontinueProduct = function(product, parentRefs) {
|
||||
}
|
||||
}
|
||||
|
||||
Industry.prototype.upgrade = function(upgrade, refs) {
|
||||
var corporation = refs.corporation, division = refs.division,
|
||||
office = refs.office;
|
||||
var upgN = upgrade[0], basePrice = upgrade[1], priceMult = upgrade[2],
|
||||
upgradeBenefit = upgrade[3];
|
||||
while (this.upgrades.length <= upgN) {this.upgrades.push(0);}
|
||||
++this.upgrades[upgN];
|
||||
|
||||
switch (upgN) {
|
||||
case 0: //Coffee, 5% energy per employee
|
||||
for (var i = 0; i < office.employees.length; ++i) {
|
||||
office.employees[i].ene = Math.min(office.employees[i].ene * 1.05, 100);
|
||||
}
|
||||
break;
|
||||
case 1: //AdVert.Inc,
|
||||
var advMult = corporation.getAdvertisingMultiplier();
|
||||
this.awareness += (5 * advMult);
|
||||
this.popularity += (1 * advMult);
|
||||
this.awareness *= (1.01 * advMult);
|
||||
this.popularity *= ((1 + Math.random(5, 15) / 100) * advMult);
|
||||
break;
|
||||
default:
|
||||
console.log("ERROR: Un-implemented function index: " + upgN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Industry.prototype.toJSON = function() {
|
||||
return Generic_toJSON("Industry", this);
|
||||
}
|
||||
@ -1385,7 +1446,7 @@ function Employee(params={}) {
|
||||
this.pro = 0; //Productivity, This is calculated
|
||||
|
||||
this.loc = params.loc ? params.loc : "";
|
||||
this.pos = params.position ? params.position : EmployeePositions.Operations;
|
||||
this.pos = EmployeePositions.Unassigned;
|
||||
}
|
||||
|
||||
//Returns the amount the employee needs to be paid
|
||||
@ -1444,6 +1505,9 @@ Employee.prototype.calculateProductivity = function(corporation) {
|
||||
prodMult = (1.5 * effInt) + (0.8 * this.exp) + (effCre) +
|
||||
(0.5 * effEff);
|
||||
break;
|
||||
case EmployeePositions.Unassigned:
|
||||
prodMult = 0;
|
||||
break;
|
||||
default:
|
||||
console.log("ERROR: Invalid employee position: " + this.pos);
|
||||
break;
|
||||
@ -1612,7 +1676,8 @@ OfficeSpace.prototype.calculateEmployeeProductivity = function(marketCycles=1, c
|
||||
}
|
||||
|
||||
//Takes care of UI as well
|
||||
OfficeSpace.prototype.findEmployees = function(company) {
|
||||
OfficeSpace.prototype.findEmployees = function(parentRefs) {
|
||||
var company = parentRefs.corporation, division = parentRefs.division;
|
||||
if (document.getElementById("cmpy-mgmt-hire-employee-popup") != null) {return;}
|
||||
|
||||
//Generate three random employees (meh, decent, amazing)
|
||||
@ -1667,7 +1732,7 @@ OfficeSpace.prototype.findEmployees = function(company) {
|
||||
"Efficiency: " + formatNumber(employee.eff, 1) + "<br>" +
|
||||
"Salary: " + numeral(employee.sal).format('$0.000a') + " \ s<br>",
|
||||
clickListener:()=>{
|
||||
office.hireEmployee(employee, company);
|
||||
office.hireEmployee(employee, parentRefs);
|
||||
removeElementById("cmpy-mgmt-hire-employee-popup");
|
||||
return false;
|
||||
}
|
||||
@ -1694,7 +1759,8 @@ OfficeSpace.prototype.findEmployees = function(company) {
|
||||
createPopup("cmpy-mgmt-hire-employee-popup", elems);
|
||||
}
|
||||
|
||||
OfficeSpace.prototype.hireEmployee = function(employee, company) {
|
||||
OfficeSpace.prototype.hireEmployee = function(employee, parentRefs) {
|
||||
var company = parentRefs.corporation, division = parentRefs.division;
|
||||
var yesBtn = yesNoTxtInpBoxGetYesButton(),
|
||||
noBtn = yesNoTxtInpBoxGetNoButton();
|
||||
yesBtn.innerHTML = "Hire";
|
||||
@ -1709,7 +1775,7 @@ OfficeSpace.prototype.hireEmployee = function(employee, company) {
|
||||
}
|
||||
employee.name = name;
|
||||
this.employees.push(employee);
|
||||
company.updateUIContent();
|
||||
company.displayDivisionContent(division, currentCityUi);
|
||||
return yesNoTxtInpBoxClose();
|
||||
});
|
||||
noBtn.addEventListener("click", ()=>{
|
||||
@ -1718,6 +1784,28 @@ OfficeSpace.prototype.hireEmployee = function(employee, company) {
|
||||
yesNoTxtInpBoxCreate("Give your employee a nickname!");
|
||||
}
|
||||
|
||||
//Finds the first unassigned employee and assigns its to the specified job
|
||||
OfficeSpace.prototype.assignEmployeeToJob = function(job) {
|
||||
for (var i = 0; i < this.employees.length; ++i) {
|
||||
if (this.employees[i].pos === EmployeePositions.Unassigned) {
|
||||
this.employees[i].pos = job;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//Finds the first employee with the given job and unassigns it
|
||||
OfficeSpace.prototype.unassignEmployeeFromJob = function(job) {
|
||||
for (var i = 0; i < this.employees.length; ++i) {
|
||||
if (this.employees[i].pos === job) {
|
||||
this.employees[i].pos = EmployeePositions.Unassigned;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
OfficeSpace.prototype.toJSON = function() {
|
||||
return Generic_toJSON("OfficeSpace", this);
|
||||
}
|
||||
@ -2099,16 +2187,22 @@ Warehouse.prototype.createMaterialUI = function(mat, matName, parentRefs) {
|
||||
buttonPanel.appendChild(createElement("br", {})); // Force line break
|
||||
|
||||
//Button to set sell amount
|
||||
var innerTextString = (mat.sllman[1] === -1 ? "Sell (" + formatNumber(mat.sll, 3) + "/MAX)" :
|
||||
"Sell (" + formatNumber(mat.sll, 3) + "/" + formatNumber(mat.sllman[1], 3) + ")")
|
||||
if (mat.sCost) {
|
||||
if (isString(mat.sCost)) {
|
||||
var sCost = mat.sCost.replace(/MP/g, mat.bCost);
|
||||
innerTextString += " @ $" + formatNumber(eval(sCost), 2);
|
||||
} else {
|
||||
innerTextString += " @ $" + formatNumber(mat.sCost, 2);
|
||||
var innerTextString;
|
||||
if (mat.sllman[0]) {
|
||||
innerTextString = (mat.sllman[1] === -1 ? "Sell (" + formatNumber(mat.sll, 3) + "/MAX)" :
|
||||
"Sell (" + formatNumber(mat.sll, 3) + "/" + formatNumber(mat.sllman[1], 3) + ")");
|
||||
if (mat.sCost) {
|
||||
if (isString(mat.sCost)) {
|
||||
var sCost = mat.sCost.replace(/MP/g, mat.bCost);
|
||||
innerTextString += " @ $" + formatNumber(eval(sCost), 2);
|
||||
} else {
|
||||
innerTextString += " @ $" + formatNumber(mat.sCost, 2);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
innerTextString = "Sell (0.000/0.000)";
|
||||
}
|
||||
|
||||
buttonPanel.appendChild(createElement("a", {
|
||||
innerText: innerTextString, display:"inline-block", class:"a-link-button",
|
||||
clickListener:()=>{
|
||||
@ -2124,16 +2218,17 @@ Warehouse.prototype.createMaterialUI = function(mat, matName, parentRefs) {
|
||||
"changing price that depends on the market price. For example, if you set the sell price " +
|
||||
"to 'MP+10' then it will always be sold at $10 above the market price.",
|
||||
});
|
||||
var br = createElement("br", {});
|
||||
var inputQty = createElement("input", {
|
||||
type:"text", value: mat.sllman[1] ? mat.sllman[1] : null, placeholder: "Sell amount"
|
||||
type:"text", marginTop:"4px",
|
||||
value: mat.sllman[1] ? mat.sllman[1] : null, placeholder: "Sell amount"
|
||||
});
|
||||
var inputPx = createElement("input", {
|
||||
type:"text", value: mat.sCost ? mat.sCost : null, placeholder: "Sell price"
|
||||
type:"text", marginTop:"4px",
|
||||
value: mat.sCost ? mat.sCost : null, placeholder: "Sell price"
|
||||
});
|
||||
var confirmBtn = createElement("a", {
|
||||
innerText:"Confirm",
|
||||
class:"a-link-button",
|
||||
margin:"6px",
|
||||
innerText:"Confirm", class:"a-link-button", margin:"6px",
|
||||
clickListener:()=>{
|
||||
//Parse price
|
||||
//Sanitize cost
|
||||
@ -2164,6 +2259,7 @@ Warehouse.prototype.createMaterialUI = function(mat, matName, parentRefs) {
|
||||
if (isNaN(qty)) {qty = 0;}
|
||||
if (qty === 0) {
|
||||
mat.sllman[0] = false;
|
||||
mat.sllman[1] = 0;
|
||||
} else {
|
||||
mat.sllman[0] = true;
|
||||
mat.sllman[1] = qty;
|
||||
@ -2176,14 +2272,12 @@ Warehouse.prototype.createMaterialUI = function(mat, matName, parentRefs) {
|
||||
}
|
||||
});
|
||||
var cancelBtn = createElement("a", {
|
||||
innerText:"Cancel",
|
||||
class:"a-link-button",
|
||||
margin: "6px",
|
||||
innerText:"Cancel", class:"a-link-button", margin: "6px",
|
||||
clickListener:()=>{
|
||||
removeElementById(sellPopupid);
|
||||
}
|
||||
});
|
||||
createPopup(sellPopupid, [txt, inputQty, inputPx, confirmBtn, cancelBtn]);
|
||||
createPopup(sellPopupid, [txt, br, inputQty, inputPx, confirmBtn, cancelBtn]);
|
||||
inputQty.focus();
|
||||
}
|
||||
}));
|
||||
@ -2427,46 +2521,48 @@ var CorporationUnlockUpgrades = {
|
||||
// name, desc]
|
||||
var CorporationUpgrades = {
|
||||
//Smart factories, increases production
|
||||
"0": [0, 4e9, 1.07, 0.02,
|
||||
"0": [0, 2e9, 1.07, 0.02,
|
||||
"Smart Factories", "Advanced AI automatically optimizes the operation and productivity " +
|
||||
"of factories. Each level of this upgrade increases your global production by 2% (additive)."],
|
||||
|
||||
//Smart warehouses, increases storage size
|
||||
"1": [1, 4e9, 1.07, .1,
|
||||
"1": [1, 2e9, 1.07, .1,
|
||||
"Smart Storage", "Advanced AI automatically optimizes your warehouse storage methods. " +
|
||||
"Each level of this upgrade increases your global warehouse storage size by 10% (additive)."],
|
||||
|
||||
//Advertise through dreams, passive popularity/ awareness gain
|
||||
"2": [2, 999999e9, 1.08, .001,
|
||||
"DreamSense", "NOT YET IMPLEMENTED! - Use DreamSense LCC Technologies to advertise your corporation " +
|
||||
"2": [2, 8e9, 1.09, .001,
|
||||
"DreamSense", "Use DreamSense LCC Technologies to advertise your corporation " +
|
||||
"to consumers through their dreams. Each level of this upgrade provides a passive " +
|
||||
"increase in awareness of your company by 0.001 / second."],
|
||||
"increase in awareness of all of your companies (divisions) by 0.004 / market cycle," +
|
||||
"and in popularity by 0.001 / market cycle. A market cycle is approximately " +
|
||||
"20 seconds."],
|
||||
|
||||
//Makes advertising more effective
|
||||
"3": [3, 999999e9, 1.11, 0.1,
|
||||
"Wilson Analytics", "NOT YET IMPLEMENTED - Purchase data and analysis from Wilson, a marketing research " +
|
||||
"3": [3, 4e9, 1.11, 0.1,
|
||||
"Wilson Analytics", "Purchase data and analysis from Wilson, a marketing research " +
|
||||
"firm. Each level of this upgrades increases the effectiveness of your " +
|
||||
"advertising by 10% (additive)."],
|
||||
|
||||
//Augmentation for employees, increases cre
|
||||
"4": [4, 2e9, 1.06, 0.1,
|
||||
"4": [4, 1e9, 1.06, 0.1,
|
||||
"Nuoptimal Nootropic Injector Implants", "Purchase the Nuoptimal Nootropic " +
|
||||
"Injector augmentation for your employees. Each level of this upgrade " +
|
||||
"globally increases the creativity of your employees by 10% (additive)."],
|
||||
|
||||
//Augmentation for employees, increases cha
|
||||
"5": [5, 2e9, 1.06, 0.1,
|
||||
"5": [5, 1e9, 1.06, 0.1,
|
||||
"Speech Processor Implants", "Purchase the Speech Processor augmentation for your employees. " +
|
||||
"Each level of this upgrade globally increases the charisma of your employees by 10% (additive)."],
|
||||
|
||||
//Augmentation for employees, increases int
|
||||
"6": [6, 2e9, 1.06, 0.1,
|
||||
"6": [6, 1e9, 1.06, 0.1,
|
||||
"Neural Accelerators", "Purchase the Neural Accelerator augmentation for your employees. " +
|
||||
"Each level of this upgrade globally increases the intelligence of your employees " +
|
||||
"by 10% (additive)."],
|
||||
|
||||
//Augmentation for employees, increases eff
|
||||
"7": [7, 2e9, 1.06, 0.1,
|
||||
"7": [7, 1e9, 1.06, 0.1,
|
||||
"FocusWires", "Purchase the FocusWire augmentation for your employees. Each level " +
|
||||
"of this upgrade globally increases the efficiency of your employees by 10% (additive)."],
|
||||
|
||||
@ -2477,7 +2573,7 @@ var CorporationUpgrades = {
|
||||
"by 1% (additive)."],
|
||||
|
||||
//Improves scientific research rate
|
||||
"9": [9, 5e9, 1.08, 0.05,
|
||||
"9": [9, 5e9, 1.07, 0.05,
|
||||
"Project Insight", "Purchase 'Project Insight', a R&D service provided by the secretive " +
|
||||
"Fulcrum Technologies. Each level of this upgrade globally increases the amount of " +
|
||||
"Scientific Research you produce by 5% (additive)."],
|
||||
@ -2544,7 +2640,7 @@ Corporation.prototype.process = function(numCycles=1) {
|
||||
Corporation.prototype.determineValuation = function() {
|
||||
var val, profit = (this.revenue.minus(this.expenses)).toNumber();
|
||||
if (this.public) {
|
||||
val = 25e9 + this.funds.toNumber() + (profit * 25e3);
|
||||
val = this.funds.toNumber() + (profit * 100e3);
|
||||
val *= (Math.pow(1.1, this.divisions.length));
|
||||
val = Math.max(val, 0);
|
||||
} else {
|
||||
@ -2578,7 +2674,7 @@ Corporation.prototype.getInvestment = function() {
|
||||
case 4:
|
||||
return;
|
||||
}
|
||||
var funding = val * percShares,
|
||||
var funding = val * percShares * 2,
|
||||
investShares = Math.floor(TOTALSHARES * percShares),
|
||||
yesBtn = yesNoBoxGetYesButton(),
|
||||
noBtn = yesNoBoxGetNoButton();
|
||||
@ -2588,6 +2684,7 @@ Corporation.prototype.getInvestment = function() {
|
||||
++this.fundingRound;
|
||||
this.funds = this.funds.plus(funding);
|
||||
this.numShares -= investShares;
|
||||
this.displayCorporationOverviewContent();
|
||||
return yesNoBoxClose();
|
||||
});
|
||||
noBtn.addEventListener("click", ()=>{
|
||||
@ -2609,12 +2706,13 @@ Corporation.prototype.goPublic = function() {
|
||||
numeral(initialSharePrice).format('$0.000a') + " per share.<br><br>" +
|
||||
"Furthermore, issuing more shares now will help drive up " +
|
||||
"your company's stock price in the future.<br><br>" +
|
||||
"You have a total of " + this.numShares + " of shares that you can issue.",
|
||||
"You have a total of " + numeral(this.numShares).format("0.000a") + " of shares that you can issue.",
|
||||
});
|
||||
var input = createElement("input", {
|
||||
type:"number",
|
||||
placeholder: "Shares to issue",
|
||||
});
|
||||
var br = createElement("br", {});
|
||||
var yesBtn = createElement("a", {
|
||||
class:"a-link-button",
|
||||
innerText:"Go Public",
|
||||
@ -2646,7 +2744,7 @@ Corporation.prototype.goPublic = function() {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
createPopup(goPublicPopupId, [txt, input, yesBtn, noBtn]);
|
||||
createPopup(goPublicPopupId, [txt, br, input, yesBtn, noBtn]);
|
||||
}
|
||||
|
||||
Corporation.prototype.updateSharePrice = function() {
|
||||
@ -2715,6 +2813,11 @@ Corporation.prototype.getStorageMultiplier = function() {
|
||||
if (isNaN(mult) || mult < 1) {return 1;} else {return mult;}
|
||||
}
|
||||
|
||||
Corporation.prototype.getDreamSenseGain = function() {
|
||||
var gain = this.upgradeMultipliers[2] - 1;
|
||||
return gain <= 0 ? 0 : gain;
|
||||
}
|
||||
|
||||
Corporation.prototype.getAdvertisingMultiplier = function() {
|
||||
var mult = this.upgradeMultipliers[3];
|
||||
if (isNaN(mult) || mult < 1) {return 1;} else {return mult;}
|
||||
@ -2750,14 +2853,13 @@ Corporation.prototype.getScientificResearchMultiplier = function() {
|
||||
if (isNaN(mult) || mult < 1) {return 1;} else {return mult;}
|
||||
}
|
||||
|
||||
|
||||
//Keep 'global' variables for DOM elements so we don't have to search
|
||||
//through the DOM tree repeatedly when updating UI
|
||||
var companyManagementDiv, companyManagementHeaderTabs, companyManagementPanel,
|
||||
currentCityUi,
|
||||
corporationUnlockUpgrades, corporationUpgrades,
|
||||
industryOverviewPanel, industryOverviewText,
|
||||
industryEmployeePanel, industryEmployeeText, industryEmployeeHireButton, industryEmployeeList,
|
||||
industryEmployeePanel, industryEmployeeText, industryEmployeeHireButton, industryEmployeeManagementUI, industryEmployeeInfo,
|
||||
industryOfficeUpgradeSizeButton,
|
||||
industryWarehousePanel,
|
||||
headerTabs, cityTabs;
|
||||
@ -2980,13 +3082,37 @@ Corporation.prototype.displayCorporationOverviewContent = function() {
|
||||
this.selectHeaderTab(headerTabs[0]);
|
||||
}
|
||||
|
||||
//Check if player has Corporation Handbook
|
||||
var homeComp = Player.getHomeComputer(), hasHandbook = false,
|
||||
handbookFn = "corporation-management-handbook.lit";
|
||||
for (var i = 0; i < homeComp.messages.length; ++i) {
|
||||
if (isString(homeComp.messages[i]) && homeComp.messages[i] === handbookFn) {
|
||||
hasHandbook = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasHandbook) {
|
||||
companyManagementPanel.appendChild(createElement("a", {
|
||||
class:"a-link-button", innerText:"Get Handbook", display:"inline-block",
|
||||
tooltip:"Get a copy of 'The Complete Handbook for Creating a Successful Corporation.'" +
|
||||
"This is a .lit file that provides some tips/pointers for helping you get started with " +
|
||||
"starting and managing a Corporation.",
|
||||
clickListener:()=>{
|
||||
homeComp.messages.push(handbookFn);
|
||||
this.displayCorporationOverviewContent();
|
||||
return false;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
//Investors
|
||||
if (this.public) {
|
||||
//Sell share buttons
|
||||
var sellShares = createElement("a", {
|
||||
class:"a-link-button tooltip",
|
||||
innerText:"Sell Shares",
|
||||
display:"inline-block",
|
||||
class:"a-link-button", innerText:"Sell Shares", display:"inline-block",
|
||||
tooltip:"Sell your shares in the company. This is the only way to " +
|
||||
"profit from your business venture.",
|
||||
clickListener:()=>{
|
||||
var popupId = "cmpy-mgmt-sell-shares-popup";
|
||||
var currentStockPrice = this.sharePrice;
|
||||
@ -2996,8 +3122,7 @@ Corporation.prototype.displayCorporationOverviewContent = function() {
|
||||
});
|
||||
var profitIndicator = createElement("p", {});
|
||||
var input = createElement("input", {
|
||||
type:"number",
|
||||
placeholder:"Shares to sell",
|
||||
type:"number", placeholder:"Shares to sell", margin:"5px",
|
||||
inputListener: ()=> {
|
||||
var numShares = Math.round(input.value);
|
||||
if (isNaN(numShares)) {
|
||||
@ -3011,9 +3136,7 @@ Corporation.prototype.displayCorporationOverviewContent = function() {
|
||||
}
|
||||
});
|
||||
var confirmBtn = createElement("a", {
|
||||
class:"a-link-button",
|
||||
innerText:"Sell shares",
|
||||
display:"inline-block",
|
||||
class:"a-link-button", innerText:"Sell shares", display:"inline-block",
|
||||
clickListener:()=>{
|
||||
var shares = Math.round(input.value);
|
||||
if (isNaN(shares)) {
|
||||
@ -3031,9 +3154,7 @@ Corporation.prototype.displayCorporationOverviewContent = function() {
|
||||
}
|
||||
});
|
||||
var cancelBtn = createElement("a", {
|
||||
class:"a-link-button",
|
||||
innerText:"Cancel",
|
||||
display:"inline-block",
|
||||
class:"a-link-button", innerText:"Cancel", display:"inline-block",
|
||||
clickListener:()=>{
|
||||
removeElementById(popupId);
|
||||
return false;
|
||||
@ -3042,18 +3163,11 @@ Corporation.prototype.displayCorporationOverviewContent = function() {
|
||||
createPopup(popupId, [txt, profitIndicator, input, confirmBtn, cancelBtn]);
|
||||
}
|
||||
});
|
||||
var sellSharesTooltip = createElement("span", {
|
||||
class:"tooltiptext",
|
||||
innerText:"Sell your shares in the company. This is the only way to " +
|
||||
"profit from your business venture.",
|
||||
});
|
||||
sellShares.appendChild(sellSharesTooltip);
|
||||
|
||||
//Buyback shares button
|
||||
var buybackShares = createElement("a", {
|
||||
class:"a-link-button tooltip",
|
||||
innerText:"Buyback shares",
|
||||
display:"inline-block",
|
||||
class:"a-link-button", innerText:"Buyback shares", display:"inline-block",
|
||||
tooltip:"Buy back shares you that previously issued or sold at market price.",
|
||||
clickListener:()=>{
|
||||
var popupId = "cmpy-mgmt-buyback-shares-popup";
|
||||
var currentStockPrice = this.sharePrice;
|
||||
@ -3063,8 +3177,7 @@ Corporation.prototype.displayCorporationOverviewContent = function() {
|
||||
});
|
||||
var costIndicator = createElement("p", {});
|
||||
var input = createElement("input", {
|
||||
type:"number",
|
||||
placeholder:"Shares to sell",
|
||||
type:"number", placeholder:"Shares to buyback", margin:"5px",
|
||||
inputListener: ()=> {
|
||||
var numShares = Math.round(input.value);
|
||||
//TODO add conditional for if player doesn't have enough money
|
||||
@ -3080,9 +3193,7 @@ Corporation.prototype.displayCorporationOverviewContent = function() {
|
||||
}
|
||||
});
|
||||
var confirmBtn = createElement("a", {
|
||||
class:"a-link-button",
|
||||
innerText:"Sell shares",
|
||||
display:"inline-block",
|
||||
class:"a-link-button", innerText:"Buy shares", display:"inline-block",
|
||||
clickListener:()=>{
|
||||
var shares = Math.round(input.value);
|
||||
var tempStockPrice = this.sharePrice;
|
||||
@ -3096,6 +3207,7 @@ Corporation.prototype.displayCorporationOverviewContent = function() {
|
||||
} else {
|
||||
this.numShares += shares;
|
||||
this.issuedShares -= shares;
|
||||
Player.loseMoney(shares * tempStockPrice);
|
||||
//TODO REMOVE from Player money
|
||||
removeElementById(popupId);
|
||||
}
|
||||
@ -3115,12 +3227,6 @@ Corporation.prototype.displayCorporationOverviewContent = function() {
|
||||
createPopup(popupId, [txt, costIndicator, input, confirmBtn, cancelBtn]);
|
||||
}
|
||||
});
|
||||
var buybackSharesTooltip = createElement("span", {
|
||||
class:"tooltiptext",
|
||||
innerText:"Buy back shares you that previously issued or sold at market " +
|
||||
"price."
|
||||
});
|
||||
buybackShares.appendChild(buybackSharesTooltip);
|
||||
|
||||
companyManagementPanel.appendChild(sellShares);
|
||||
companyManagementPanel.appendChild(buybackShares);
|
||||
@ -3133,12 +3239,14 @@ Corporation.prototype.displayCorporationOverviewContent = function() {
|
||||
this.getInvestment();
|
||||
}
|
||||
});
|
||||
var findInvestorsTooltip = createElement("span", {
|
||||
class:"tooltiptext",
|
||||
innerText:"Search for private investors who will give you startup funding in exchange " +
|
||||
"for equity (stock shares) in your company"
|
||||
});
|
||||
findInvestors.appendChild(findInvestorsTooltip);
|
||||
if (this.fundingRound < 4) {
|
||||
var findInvestorsTooltip = createElement("span", {
|
||||
class:"tooltiptext",
|
||||
innerText:"Search for private investors who will give you startup funding in exchange " +
|
||||
"for equity (stock shares) in your company"
|
||||
});
|
||||
findInvestors.appendChild(findInvestorsTooltip);
|
||||
}
|
||||
|
||||
var goPublic = createElement("a", {
|
||||
class:"a-link-button tooltip",
|
||||
@ -3196,7 +3304,7 @@ Corporation.prototype.displayCorporationOverviewContent = function() {
|
||||
}
|
||||
|
||||
upgradeContainer.appendChild(createElement("div", {
|
||||
class:"cmpy-mgmt-upgrade-div",
|
||||
class:"cmpy-mgmt-upgrade-div", width:"45%",
|
||||
innerHTML:upgrade[2] + " - " + numeral(upgrade[1]).format("$0.000a"),
|
||||
tooltip: upgrade[3],
|
||||
clickListener:()=>{
|
||||
@ -3228,7 +3336,7 @@ Corporation.prototype.displayCorporationOverviewContent = function() {
|
||||
var baseCost = upgrade[1], priceMult = upgrade[2];
|
||||
var cost = baseCost * Math.pow(priceMult, corp.upgrades[i]);
|
||||
upgradeContainer.appendChild(createElement("div", {
|
||||
class:"cmpy-mgmt-upgrade-div",
|
||||
class:"cmpy-mgmt-upgrade-div", width:"45%",
|
||||
innerHTML:upgrade[4] + " - " + numeral(cost).format("$0.000a"),
|
||||
tooltip:upgrade[5],
|
||||
clickListener:()=>{
|
||||
@ -3312,7 +3420,7 @@ Corporation.prototype.displayDivisionContent = function(division, city) {
|
||||
innerText: "Would you like to expand into a new city by opening an office? " +
|
||||
"This would cost " + numeral(OfficeInitialCost).format('$0.000a'),
|
||||
});
|
||||
var citySelector = createElement("select", {});
|
||||
var citySelector = createElement("select", {margin:"5px"});
|
||||
for (var cityName in division.offices) {
|
||||
if (division.offices.hasOwnProperty(cityName)) {
|
||||
if (!(division.offices[cityName] instanceof OfficeSpace)) {
|
||||
@ -3356,39 +3464,87 @@ Corporation.prototype.displayDivisionContent = function(division, city) {
|
||||
}));
|
||||
companyManagementPanel.appendChild(createElement("br", {})); // Force line break
|
||||
|
||||
//Get office object
|
||||
var office = division.offices[currentCityUi];
|
||||
if (!(office instanceof OfficeSpace)) {
|
||||
console.log("ERROR: Current city for UI does not have an office space");
|
||||
return;
|
||||
}
|
||||
|
||||
//Left and right panels
|
||||
var leftPanel = createElement("div", {
|
||||
class:"cmpy-mgmt-industry-left-panel"
|
||||
});
|
||||
var rightPanel = createElement("div", {
|
||||
class:"cmpy-mgmt-industry-right-panel"
|
||||
});
|
||||
var leftPanel = createElement("div", {class:"cmpy-mgmt-industry-left-panel"});
|
||||
var rightPanel = createElement("div", {class:"cmpy-mgmt-industry-right-panel"});
|
||||
companyManagementPanel.appendChild(leftPanel);
|
||||
companyManagementPanel.appendChild(rightPanel);
|
||||
|
||||
//Different sections (Overview, Employee/Office, and Warehouse)
|
||||
industryOverviewPanel = createElement("div", {
|
||||
id:"cmpy-mgmt-industry-overview-panel",
|
||||
class:"cmpy-mgmt-industry-overview-panel"
|
||||
id:"cmpy-mgmt-industry-overview-panel", class:"cmpy-mgmt-industry-overview-panel"
|
||||
});
|
||||
leftPanel.appendChild(industryOverviewPanel);
|
||||
|
||||
industryEmployeePanel = createElement("div", {
|
||||
id:"cmpy-mgmt-employee-panel",
|
||||
class:"cmpy-mgmt-employee-panel"
|
||||
id:"cmpy-mgmt-employee-panel", class:"cmpy-mgmt-employee-panel"
|
||||
});
|
||||
leftPanel.appendChild(industryEmployeePanel);
|
||||
|
||||
industryWarehousePanel = createElement("div", {
|
||||
id:"cmpy-mgmt-warehouse-panel",
|
||||
class:"cmpy-mgmt-warehouse-panel"
|
||||
id:"cmpy-mgmt-warehouse-panel", class:"cmpy-mgmt-warehouse-panel"
|
||||
});
|
||||
rightPanel.appendChild(industryWarehousePanel);
|
||||
|
||||
//Industry overview text element
|
||||
//Industry overview text
|
||||
industryOverviewText = createElement("p", {});
|
||||
industryOverviewPanel.appendChild(industryOverviewText);
|
||||
|
||||
//Industry overview Purchases & Upgrades
|
||||
var numUpgrades = Object.keys(IndustryUpgrades).length;
|
||||
while (division.upgrades.length < numUpgrades) {division.upgrades.push(0);} //Backwards compatibility
|
||||
|
||||
var industryOverviewUpgrades = createElement("div", {});
|
||||
industryOverviewUpgrades.appendChild(createElement("h1", {innerText:"Purchases & Upgrades", margin:"4px", padding:"4px"}));
|
||||
for (var i = 0; i < numUpgrades; ++i) {
|
||||
(function(i, corp, division, office) {
|
||||
var upgrade = IndustryUpgrades[i.toString()];
|
||||
if (upgrade == null) {
|
||||
console.log("ERROR: Could not find levelable upgrade index: " + i);
|
||||
return;
|
||||
}
|
||||
|
||||
var baseCost = upgrade[1], priceMult = upgrade[2], cost = 0;
|
||||
switch(i) {
|
||||
case 0: //Coffee, cost is static per employee
|
||||
cost = office.employees.length * baseCost;
|
||||
break;
|
||||
default:
|
||||
cost = baseCost * Math.pow(priceMult, division.upgrades[i]);
|
||||
break;
|
||||
}
|
||||
industryOverviewUpgrades.appendChild(createElement("div", {
|
||||
class:"cmpy-mgmt-upgrade-div", display:"inline-block",
|
||||
innerHTML:upgrade[4] + ' - ' + numeral(cost).format("$0.000a"),
|
||||
tooltip:upgrade[5],
|
||||
clickListener:()=>{
|
||||
if (corp.funds.lt(cost)) {
|
||||
dialogBoxCreate("Insufficient funds");
|
||||
} else {
|
||||
corp.funds = corp.funds.minus(cost);
|
||||
division.upgrade(upgrade, {
|
||||
corporation:corp,
|
||||
office:office,
|
||||
});
|
||||
corp.displayDivisionContent(division, city);
|
||||
}
|
||||
}
|
||||
}));
|
||||
industryOverviewUpgrades.appendChild(createElement("br", {}));
|
||||
|
||||
})(i, this, division, office);
|
||||
}
|
||||
|
||||
|
||||
industryOverviewPanel.appendChild(industryOverviewUpgrades);
|
||||
|
||||
//Industry Overview 'Create Product' button if applicable
|
||||
if (division.makesProducts) {
|
||||
//Get the text on the button based on Industry type
|
||||
@ -3522,11 +3678,6 @@ Corporation.prototype.displayDivisionContent = function(division, city) {
|
||||
}
|
||||
|
||||
//Employee and Office Panel
|
||||
var office = division.offices[currentCityUi];
|
||||
if (!(office instanceof OfficeSpace)) {
|
||||
console.log("ERROR: Current city for UI does not have an office space");
|
||||
return;
|
||||
}
|
||||
industryEmployeeText = createElement("p", {
|
||||
id: "cmpy-mgmt-employee-p",
|
||||
display:"block",
|
||||
@ -3543,7 +3694,7 @@ Corporation.prototype.displayDivisionContent = function(division, city) {
|
||||
innerText:"Hire Employee",
|
||||
display:"inline-block",
|
||||
clickListener:()=>{
|
||||
office.findEmployees(this);
|
||||
office.findEmployees({corporation:this, division:division});
|
||||
return false;
|
||||
}
|
||||
});
|
||||
@ -3554,7 +3705,7 @@ Corporation.prototype.displayDivisionContent = function(division, city) {
|
||||
class:"a-link-button", innerText:"Upgrade Office size", display:"inline-block", margin:"6px",
|
||||
clickListener:()=>{
|
||||
var popupId = "cmpy-mgmt-upgrade-office-size-popup";
|
||||
var upgradeCost = OfficeInitialCost * Math.pow(1.13, Math.round(office.size / OfficeInitialSize));
|
||||
var upgradeCost = OfficeInitialCost * Math.pow(1.07, Math.round(office.size / OfficeInitialSize));
|
||||
var text = createElement("p", {
|
||||
innerHTML:"Increase the size of your office space to fit " + OfficeInitialSize +
|
||||
" more employees. This will cost " + numeral(upgradeCost).format('$0.000a'),
|
||||
@ -3596,9 +3747,7 @@ Corporation.prototype.displayDivisionContent = function(division, city) {
|
||||
//Throw Office Party
|
||||
industryEmployeePanel.appendChild(createElement("br",{}));
|
||||
industryEmployeePanel.appendChild(createElement("a", {
|
||||
class:"a-link-button",
|
||||
display:"inline-block",
|
||||
innerText:"Throw Office Party",
|
||||
class:"a-link-button", display:"inline-block", innerText:"Throw Office Party",
|
||||
tooltip:"Throw an office party to increase your employee's morale and happiness",
|
||||
clickListener:()=>{
|
||||
var popupId = "cmpy-mgmt-throw-office-party-popup";
|
||||
@ -3610,7 +3759,7 @@ Corporation.prototype.displayDivisionContent = function(division, city) {
|
||||
innerText:"Throwing this party will cost a total of $0"
|
||||
});
|
||||
var input = createElement("input", {
|
||||
type:"number",
|
||||
type:"number", margin:"5px", placeholder:"$ / employee",
|
||||
inputListener:()=>{
|
||||
if (isNaN(input.value) || input.value < 0) {
|
||||
totalCostTxt.innerText = "Invalid value entered!"
|
||||
@ -3658,36 +3807,131 @@ Corporation.prototype.displayDivisionContent = function(division, city) {
|
||||
}
|
||||
}));
|
||||
|
||||
/*
|
||||
//Employee list
|
||||
var industryEmployeeList = createElement("ul", {
|
||||
id:"cmpy-mgmt-employee-ul"
|
||||
});
|
||||
industryEmployeePanel.appendChild(industryEmployeeList);
|
||||
for (var i = 0; i < office.employees.length; ++i) {
|
||||
(function(corp) {
|
||||
var emp = office.employees[i];
|
||||
var li = createAccordionElement({
|
||||
id:"cmpy-mgmt-employee-" + emp.name,
|
||||
hdrText:emp.name,
|
||||
});
|
||||
var panel = li.children[1];
|
||||
if (panel == null) {
|
||||
console.log("ERROR: Could not find employee accordion panel");
|
||||
return;
|
||||
}
|
||||
emp.createUI(panel, corp);
|
||||
industryEmployeeList.appendChild(li);
|
||||
})(this);
|
||||
}
|
||||
*/
|
||||
industryEmployeeManagementUI = createElement("div", {});
|
||||
if (empManualAssignmentModeActive) {
|
||||
//Employees manually assigned
|
||||
industryEmployeeManagementUI.appendChild(createElement("a", {
|
||||
class:"a-link-button", display:"inline-block", margin:"4px",
|
||||
innerText:"Switch to Auto Mode",
|
||||
tooltip:"Switch to Automatic Assignment Mode, which will automatically " +
|
||||
"assign employees to your selected jobs. You simply have to select " +
|
||||
"the number of assignments for each job",
|
||||
clickListener:()=>{
|
||||
empManualAssignmentModeActive = false;
|
||||
this.displayDivisionContent(division, city);
|
||||
}
|
||||
}));
|
||||
industryEmployeeManagementUI.appendChild(createElement("br", {}));
|
||||
|
||||
industryEmployeeInfo = createElement("div", {margin:"4px", padding:"4px"});
|
||||
|
||||
var selector = createElement("select", {
|
||||
color: "white", backgroundColor:"black", margin:"4px", padding:"4px",
|
||||
changeListener:()=>{
|
||||
var name = selector.options[selector.selectedIndex].text;
|
||||
for (var i = 0; i < office.employees.length; ++i) {
|
||||
if (office.employees[i].name === name) {
|
||||
removeChildrenFromElement(industryEmployeeInfo);
|
||||
office.employees[i].createUI(industryEmployeeInfo, this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
console.log("ERROR: Employee in selector could not be found");
|
||||
}
|
||||
});
|
||||
|
||||
for (var i = 0; i < office.employees.length; ++i) {
|
||||
selector.add(createElement("option", {text:office.employees[i].name}));
|
||||
}
|
||||
|
||||
selector.selectedIndex = -1;
|
||||
|
||||
industryEmployeeManagementUI.appendChild(selector);
|
||||
industryEmployeeManagementUI.appendChild(industryEmployeeInfo);
|
||||
|
||||
} else {
|
||||
//Player only manages the number of each occupation, not who gets what job
|
||||
industryEmployeeManagementUI.appendChild(createElement("a", {
|
||||
class:"a-link-button", display:"inline-block", margin:"4px",
|
||||
innerText:"Switch to Manual Mode",
|
||||
tooltip:"Switch to Manual Assignment Mode, which allows you to " +
|
||||
"specify which employees should get which jobs",
|
||||
clickListener:()=>{
|
||||
empManualAssignmentModeActive = true;
|
||||
this.displayDivisionContent(division, city);
|
||||
}
|
||||
}));
|
||||
industryEmployeeManagementUI.appendChild(createElement("br", {}));
|
||||
|
||||
var opCount = 0, engCount = 0, busCount = 0,
|
||||
mgmtCount = 0, rndCount = 0, unassignedCount = 0;
|
||||
for (var i = 0; i < office.employees.length; ++i) {
|
||||
switch (office.employees[i].pos) {
|
||||
case EmployeePositions.Operations:
|
||||
++opCount; break;
|
||||
case EmployeePositions.Engineer:
|
||||
++engCount; break;
|
||||
case EmployeePositions.Business:
|
||||
++busCount; break;
|
||||
case EmployeePositions.Management:
|
||||
++mgmtCount; break;
|
||||
case EmployeePositions.RandD:
|
||||
++rndCount; break;
|
||||
case EmployeePositions.Unassigned:
|
||||
++unassignedCount; break;
|
||||
default:
|
||||
console.log("ERROR: Unrecognized employee position: " + office.employees[i].pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Unassigned employee count display
|
||||
industryEmployeeManagementUI.appendChild(createElement("p", {
|
||||
display:"inline-block",
|
||||
innerText:"Unassigned Employees: " + unassignedCount,
|
||||
}));
|
||||
industryEmployeeManagementUI.appendChild(createElement("br", {}));
|
||||
|
||||
//General display of employee information (avg morale, avg energy, etc.)
|
||||
industryEmployeeInfo = createElement("p", {margin:"4px", padding:"4px"});
|
||||
industryEmployeeManagementUI.appendChild(industryEmployeeInfo);
|
||||
industryEmployeeManagementUI.appendChild(createElement("br", {}));
|
||||
|
||||
var positions = [EmployeePositions.Operations, EmployeePositions.Engineer,
|
||||
EmployeePositions.Business, EmployeePositions.Management,
|
||||
EmployeePositions.RandD];
|
||||
var counts = [opCount, engCount, busCount, mgmtCount, rndCount];
|
||||
for (var i = 0; i < positions.length; ++i) {
|
||||
(function(corp, i) {
|
||||
var info = createElement("h2", {
|
||||
display:"inline-block", width:"40%",
|
||||
innerText: positions[i] + "(" + counts[i] + ")"
|
||||
});
|
||||
var plusBtn = createElement("a", {
|
||||
class: unassignedCount > 0 ? "a-link-button" : "a-link-button-inactive",
|
||||
display:"inline-block", innerText:"+",
|
||||
clickListener:()=>{
|
||||
office.assignEmployeeToJob(positions[i]);
|
||||
corp.displayDivisionContent(division, city);
|
||||
}
|
||||
});
|
||||
var minusBtn = createElement("a", {
|
||||
class: counts[i] > 0 ? "a-link-button" : "a-link-button-inactive",
|
||||
display:"inline-block", innerText:"-",
|
||||
clickListener:()=>{
|
||||
office.unassignEmployeeFromJob(positions[i]);
|
||||
corp.displayDivisionContent(division, city);
|
||||
}
|
||||
});
|
||||
var newline = createElement("br", {});
|
||||
industryEmployeeManagementUI.appendChild(info);
|
||||
industryEmployeeManagementUI.appendChild(plusBtn);
|
||||
industryEmployeeManagementUI.appendChild(minusBtn);
|
||||
industryEmployeeManagementUI.appendChild(newline);
|
||||
})(this, i);
|
||||
}
|
||||
}
|
||||
industryEmployeePanel.appendChild(industryEmployeeManagementUI);
|
||||
|
||||
//Warehouse Panel
|
||||
var warehouse = division.warehouses[currentCityUi];
|
||||
@ -3725,8 +3969,8 @@ Corporation.prototype.updateDivisionContent = function(division) {
|
||||
profitStr = profit >= 0 ? numeral(profit).format("$0.000a") : "-" + numeral(-1 * profit).format("$0.000a");
|
||||
industryOverviewText.innerHTML =
|
||||
"Industry: " + division.type + "<br><br>" +
|
||||
"Awareness: " + division.awareness + "<br>" +
|
||||
"Popularity: " + division.popularity + "<br><br>" +
|
||||
"Awareness: " + formatNumber(division.awareness, 3) + "<br>" +
|
||||
"Popularity: " + formatNumber(division.popularity, 3) + "<br><br>" +
|
||||
"Revenue: " + numeral(division.lastCycleRevenue.toNumber()).format("$0.000a") + " / s<br>" +
|
||||
"Expenses: " + numeral(division.lastCycleExpenses.toNumber()).format("$0.000a") + " /s<br>" +
|
||||
"Profit: " + profitStr + " / s<br><br>" +
|
||||
@ -3748,27 +3992,28 @@ Corporation.prototype.updateDivisionContent = function(division) {
|
||||
} else {
|
||||
industryEmployeeHireButton.className = "a-link-button";
|
||||
}
|
||||
var employeeList = document.getElementById("cmpy-mgmt-employee-ul");
|
||||
if (employeeList && office instanceof OfficeSpace) {
|
||||
|
||||
if (!empManualAssignmentModeActive) {
|
||||
//Calculate average morale, happiness, and energy
|
||||
var totalMorale = 0, totalHappiness = 0, totalEnergy = 0,
|
||||
avgMorale = 0, avgHappiness = 0, avgEnergy = 0;
|
||||
for (var i = 0; i < office.employees.length; ++i) {
|
||||
(function(company) {
|
||||
var emp = office.employees[i];
|
||||
var panel = document.getElementById("cmpy-mgmt-employee-" + emp.name + "-panel");
|
||||
if (panel == null) {
|
||||
var li = createAccordionElement({
|
||||
id:"cmpy-mgmt-employee-" + emp.name,
|
||||
hdrText:emp.name,
|
||||
});
|
||||
panel = li.children[1];
|
||||
emp.createUI(panel, company);
|
||||
employeeList.appendChild(li);
|
||||
return;
|
||||
}
|
||||
emp.updateUI(panel, company);
|
||||
})(this);
|
||||
totalMorale += office.employees[i].mor;
|
||||
totalHappiness += office.employees[i].hap;
|
||||
totalEnergy += office.employees[i].ene;
|
||||
}
|
||||
if (office.employees.length > 0) {
|
||||
avgMorale = totalMorale / office.employees.length;
|
||||
avgHappiness = totalHappiness / office.employees.length;
|
||||
avgEnergy = totalEnergy / office.employees.length;
|
||||
}
|
||||
industryEmployeeInfo.innerHTML =
|
||||
"Avg Employee Morale: " + formatNumber(avgMorale, 3) + "<br>" +
|
||||
"Avg Employee Happiness: " + formatNumber(avgHappiness, 3) + "<br>" +
|
||||
"Avg Employee Energy: " + formatNumber(avgEnergy, 3);
|
||||
}
|
||||
|
||||
|
||||
//Warehouse
|
||||
var warehouse = division.warehouses[currentCityUi];
|
||||
if (warehouse instanceof Warehouse) {
|
||||
@ -3816,10 +4061,11 @@ Corporation.prototype.clearUI = function() {
|
||||
industryOverviewPanel = null;
|
||||
industryOverviewText = null;
|
||||
|
||||
industryEmployeePanel = null;
|
||||
industryEmployeeText = null;
|
||||
industryEmployeeHireButton = null;
|
||||
industryEmployeeList = null;
|
||||
industryEmployeePanel = null;
|
||||
industryEmployeeText = null;
|
||||
industryEmployeeHireButton = null;
|
||||
industryEmployeeManagementUI = null;
|
||||
industryEmployeeInfo = null;
|
||||
|
||||
industryOfficeUpgradeSizeButton = null;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
let CONSTANTS = {
|
||||
Version: "0.34.1",
|
||||
Version: "0.34.2",
|
||||
|
||||
//Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience
|
||||
//and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then
|
||||
@ -10,8 +10,8 @@ let CONSTANTS = {
|
||||
CorpFactionRepRequirement: 250000,
|
||||
|
||||
/* Base costs */
|
||||
BaseCostFor1GBOfRamHome: 30000,
|
||||
BaseCostFor1GBOfRamServer: 50000, //1 GB of RAM
|
||||
BaseCostFor1GBOfRamHome: 32000,
|
||||
BaseCostFor1GBOfRamServer: 55000, //1 GB of RAM
|
||||
BaseCostFor1GBOfRamHacknetNode: 30000,
|
||||
|
||||
BaseCostForHacknetNode: 1000,
|
||||
@ -41,29 +41,23 @@ let CONSTANTS = {
|
||||
//RAM Costs for different commands
|
||||
ScriptWhileRamCost: 0.2,
|
||||
ScriptForRamCost: 0.2,
|
||||
ScriptIfRamCost: 0.1,
|
||||
ScriptIfRamCost: 0.15,
|
||||
ScriptHackRamCost: 0.1,
|
||||
ScriptGrowRamCost: 0.15,
|
||||
ScriptWeakenRamCost: 0.15,
|
||||
ScriptScanRamCost: 0.2,
|
||||
ScriptNukeRamCost: 0.05,
|
||||
ScriptBrutesshRamCost: 0.05,
|
||||
ScriptFtpcrackRamCost: 0.05,
|
||||
ScriptRelaysmtpRamCost: 0.05,
|
||||
ScriptHttpwormRamCost: 0.05,
|
||||
ScriptSqlinjectRamCost: 0.05,
|
||||
ScriptRunRamCost: 0.8,
|
||||
ScriptExecRamCost: 1.1,
|
||||
ScriptScpRamCost: 0.5,
|
||||
ScriptPortProgramRamCost: 0.05,
|
||||
ScriptRunRamCost: 1.0,
|
||||
ScriptExecRamCost: 1.3,
|
||||
ScriptScpRamCost: 0.6,
|
||||
ScriptKillRamCost: 0.5, //Kill and killall
|
||||
ScriptHasRootAccessRamCost: 0.05,
|
||||
ScriptGetHostnameRamCost: 0.05, //getHostname() and getIp()
|
||||
ScriptGetHackingLevelRamCost: 0.05, //getHackingLevel()
|
||||
ScriptGetMultipliersRamCost: 4.0, //getHackingMultipliers() and getBitNodeMultipliers()
|
||||
ScriptGetServerCost: 0.1,
|
||||
ScriptGetServerRamCost: 0.1,
|
||||
ScriptFileExistsRamCost: 0.1,
|
||||
ScriptIsRunningRamCost: 0.1,
|
||||
ScriptOperatorRamCost: 0.01,
|
||||
ScriptPurchaseHacknetRamCost: 1.5,
|
||||
ScriptHacknetNodesRamCost: 1.0, //Base cost for accessing hacknet nodes array
|
||||
ScriptHNUpgLevelRamCost: 0.4,
|
||||
@ -71,7 +65,7 @@ let CONSTANTS = {
|
||||
ScriptHNUpgCoreRamCost: 0.8,
|
||||
ScriptGetStockRamCost: 2.0,
|
||||
ScriptBuySellStockRamCost: 2.5,
|
||||
ScriptPurchaseServerRamCost: 2.0,
|
||||
ScriptPurchaseServerRamCost: 2.25,
|
||||
ScriptRoundRamCost: 0.05,
|
||||
ScriptReadWriteRamCost: 1.0,
|
||||
ScriptArbScriptRamCost: 1.0, //Functions that apply to all scripts regardless of args
|
||||
@ -613,8 +607,8 @@ let CONSTANTS = {
|
||||
"<i><u>serverExists(hostname/ip)</u></i><br>Returns a boolean denoting whether or not the specified server exists. The argument " +
|
||||
"must be a string with the hostname or IP of the target server.<br><br>" +
|
||||
"<i><u>fileExists(filename, [hostname/ip])</u></i><br> Returns a boolean (true or false) indicating whether the specified file exists on a server. " +
|
||||
"The first argument must be a string with the name of the file. A file can either be a script, program, or literature file. A script name is case-sensitive, but a " +
|
||||
"program/literature file is not. For example, fileExists('brutessh.exe') will work fine, even though the actual program is named BruteSSH.exe. <br><br> " +
|
||||
"The first argument must be a string with the filename. A file can either be a script, program, literature file, or a text file. The filename for a script is case-sensitive, but " +
|
||||
"for the other files it is not. For example, fileExists('brutessh.exe') will work fine, even though the actual program is named BruteSSH.exe. <br><br> " +
|
||||
"The second argument is a string with the hostname or IP of the server on which to search for the program. This second argument is optional. " +
|
||||
"If it is omitted, then the function will search through the current server (the server running the script that calls this function) for the file. <br> " +
|
||||
"Example: fileExists('foo.script', 'foodnstuff');<br>" +
|
||||
@ -667,6 +661,8 @@ let CONSTANTS = {
|
||||
"<i><u>clear(port/fn)</u></i><br>This function is used to clear a Netscript Port or a text file.<br><br>" +
|
||||
"It takes a single argument. If this argument is a number between 1 and 10, then it specifies a port and will clear it (deleting all data from it). " +
|
||||
"If the argument is a string, then it specifies the name of a text file (.txt) and will clear the text file so that it is empty.<br><br>" +
|
||||
"<i><u>rm(fn)</u></i><br>This function is used to remove a file. It takes a string with the filename as the argument. Returns " +
|
||||
"true if it successfully deletes the given file, and false otherwise. This function works for every file type except message files (.msg).<br><br>" +
|
||||
"<i><u>scriptRunning(scriptname, hostname/ip)</u></i><br>Returns a boolean indicating whether any instance of the specified script is running " +
|
||||
"on a server, regardless of its arguments. This is different than the isRunning() function because it does not " +
|
||||
"try to identify a specific instance of a running script by its arguments.<br><br>" +
|
||||
@ -1118,6 +1114,30 @@ let CONSTANTS = {
|
||||
|
||||
LatestUpdate:
|
||||
"v0.34.2<br>" +
|
||||
"-Corporation Management Changes:<br>" +
|
||||
"---Added advertising mechanics<br>" +
|
||||
"---Added Industry-specific purchases<br>" +
|
||||
"---Re-designed employee management UI<br>" +
|
||||
"---Rebalancing: Made many upgrades/purchases cheaper. Receive more money from investors in early stage. Company valuation is higher after going public<br>" +
|
||||
"---Multiple bug fixes<br>" +
|
||||
"-Added rm() Netscript function<br>" +
|
||||
"-Updated the way script RAM usage is calculated. Now, a function only increases RAM usage the " +
|
||||
"first time it is called. i.e. even if you call hack() multiple times in a script, it only counts " +
|
||||
"against RAM usage once. The same change applies for while/for loops and if conditionals.<br>" +
|
||||
"-The RAM cost of the following were increased:<br>" +
|
||||
"---If statements: increased by 0.05GB<br>" +
|
||||
"---run() and exec(): increased by 0.2GB<br>" +
|
||||
"---scp(): increased by 0.1GB<br>" +
|
||||
"---purchaseServer(): increased by 0.25GB<br>" +
|
||||
"-Note: You may need to re-save all of your scripts in order to re-calculate their RAM usages. Otherwise, " +
|
||||
"it should automatically be re-calculated when you reset/prestige<br>" +
|
||||
"-The cost to upgrade your home computer's RAM has been increased (both the base cost and the exponential upgrade multiplier)<br>" +
|
||||
"-The cost of purchasing a server was increased by 10% (it is now $55k per RAM)<br>" +
|
||||
"-Bug fix: (Hopefully) removed an exploit where you could avoid RAM usage for Netscript function calls " +
|
||||
"by assigning functions to a variable (foo = hack(); foo('helios');)<br>" +
|
||||
"-Bug fix: (Hopefully) removed an exploit where you could run arbitrary Javascript code using the constructor() " +
|
||||
"method<br>" +
|
||||
"-Thanks to Github user mateon1 and Reddit users havoc_mayhem and spaceglace for notifying me of the above exploits<br>" +
|
||||
"-The fileExists() Netscript function now works on text files (.txt). Thanks to Github user devoidfury for this<br>"
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,21 @@ function initLiterature() {
|
||||
"Netscript command to copy your scripts onto these servers and then run them.";
|
||||
Literatures[fn] = new Literature(title, fn, txt);
|
||||
|
||||
title = "The Complete Handbook for Creating a Successful Corporation";
|
||||
fn = "corporation-management-handbook.lit";
|
||||
txt = "This is a brief collection of tips/pointers on how to successfully start and manage a Corporation.<br><br>" +
|
||||
"-Purchasing Hardware, Robots, AI Cores, and Real Estate can potentially increase your production. " +
|
||||
"The effects of these depend on what industry you are in.<br><br>" +
|
||||
"-In order to optimize your production, you will need a good balance of Operators, Managers, and Engineers<br><br>" +
|
||||
"-Different employees excel in different jobs. For example, the highly intelligent employees will probably do best " +
|
||||
"if they are assigned to do Engineering work or Research & Development.<br><br>" +
|
||||
"-If your employees have low morale, energy, or happiness, their production will greatly suffer.<br><br>" +
|
||||
"-Tech is important, but don't neglect sales! Having several Businessmen can boost your sales and your bottom line.<br><br>" +
|
||||
"-Don't forget to advertise your company. You won't have any business if nobody knows you.<br><br>" +
|
||||
"-Having company awareness is great, but what's really important is your company's popularity. Try to keep " +
|
||||
"your popularity as high as possible to see the biggest benefit for your sales<br><br>";
|
||||
Literatures[fn] = new Literature(title, fn, txt);
|
||||
|
||||
title = "A Green Tomorrow";
|
||||
fn = "A-Green-Tomorrow.lit";
|
||||
txt = "Starting a few decades ago, there was a massive global movement towards the generation of renewable energy in an effort to " +
|
||||
|
@ -1768,7 +1768,7 @@ function initLocationButtons() {
|
||||
//Calculate cost
|
||||
//Have cost increase by some percentage each time RAM has been upgraded
|
||||
var cost = currentRam * CONSTANTS.BaseCostFor1GBOfRamHome;
|
||||
var mult = Math.pow(1.55, numUpgrades);
|
||||
var mult = Math.pow(1.58, numUpgrades);
|
||||
cost = cost * mult;
|
||||
|
||||
var yesBtn = yesNoBoxGetYesButton(), noBtn = yesNoBoxGetNoButton();
|
||||
|
@ -58,6 +58,11 @@ function evaluate(exp, workerScript) {
|
||||
return Promise.resolve(exp.value);
|
||||
break;
|
||||
case "Identifier":
|
||||
//Javascript constructor() method can be used as an exploit to run arbitrary code
|
||||
if (exp.name == "constructor") {
|
||||
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Illegal usage of constructor() method. If you have your own function named 'constructor', you must re-name it."));
|
||||
}
|
||||
|
||||
if (!(exp.name in env.vars)){
|
||||
return Promise.reject(makeRuntimeRejectMsg(workerScript, "variable " + exp.name + " not defined"));
|
||||
}
|
||||
@ -177,9 +182,11 @@ function evaluate(exp, workerScript) {
|
||||
} else {
|
||||
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Invalid MemberExpression"));
|
||||
}
|
||||
|
||||
});
|
||||
} else {
|
||||
if (exp.property.name === "constructor") {
|
||||
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Illegal usage of constructor() method. If you have your own function named 'constructor', you must re-name it."));
|
||||
}
|
||||
try {
|
||||
return Promise.resolve(object[exp.property.name])
|
||||
} catch (e) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -25,9 +25,10 @@ function WorkerScript(runningScriptObj) {
|
||||
this.scriptRef = runningScriptObj;
|
||||
this.errorMessage = "";
|
||||
this.args = runningScriptObj.args;
|
||||
//this.killTrigger = function() {}; //CB func used to clear any delays (netscriptDelay())
|
||||
this.delay = null;
|
||||
this.fnWorker = null; //Workerscript for a function call
|
||||
this.checkingRam = false;
|
||||
this.loadedFns = {}; //Stores names of fns that are "loaded" by this script, thus using RAM
|
||||
}
|
||||
|
||||
//Returns the server on which the workerScript is running
|
||||
@ -65,7 +66,6 @@ function runScriptsLoop() {
|
||||
//items fucks up the indexing
|
||||
for (var i = workerScripts.length - 1; i >= 0; i--) {
|
||||
if (workerScripts[i].running == false && workerScripts[i].env.stopFlag == true) {
|
||||
console.log("Deleting script: " + workerScripts[i].name);
|
||||
//Delete script from the runningScripts array on its host serverIp
|
||||
var ip = workerScripts[i].serverIp;
|
||||
var name = workerScripts[i].name;
|
||||
@ -95,7 +95,7 @@ function runScriptsLoop() {
|
||||
if (workerScripts[i].running == false && workerScripts[i].env.stopFlag == false) {
|
||||
try {
|
||||
var ast = parse(workerScripts[i].code);
|
||||
//console.log(ast);
|
||||
console.log(ast);
|
||||
} catch (e) {
|
||||
console.log("Error parsing script: " + workerScripts[i].name);
|
||||
dialogBoxCreate("Syntax ERROR in " + workerScripts[i].name + ":<br>" + e);
|
||||
@ -113,7 +113,6 @@ function runScriptsLoop() {
|
||||
w.env.stopFlag = true;
|
||||
w.scriptRef.log("Script finished running");
|
||||
}).catch(function(w) {
|
||||
console.log(w);
|
||||
if (w instanceof Error) {
|
||||
dialogBoxCreate("Script runtime unknown error. This is a bug please contact game developer");
|
||||
console.log("ERROR: Evaluating workerscript returns an Error. THIS SHOULDN'T HAPPEN: " + w.toString());
|
||||
|
282
src/Script.js
282
src/Script.js
@ -18,16 +18,18 @@ import {Engine} from "./engine.js";
|
||||
import {iTutorialSteps, iTutorialNextStep,
|
||||
iTutorialIsRunning, currITutorialStep} from "./InteractiveTutorial.js";
|
||||
import {NetscriptFunctions} from "./NetscriptFunctions.js";
|
||||
import {addWorkerScript, killWorkerScript} from "./NetscriptWorker.js";
|
||||
import {addWorkerScript, killWorkerScript,
|
||||
WorkerScript} from "./NetscriptWorker.js";
|
||||
import {Player} from "./Player.js";
|
||||
import {AllServers, processSingleServerGrowth} from "./Server.js";
|
||||
import {Settings} from "./Settings.js";
|
||||
import {post} from "./Terminal.js";
|
||||
|
||||
import {parse, Node} from "../utils/acorn.js";
|
||||
import {dialogBoxCreate} from "../utils/DialogBox.js";
|
||||
import {Reviver, Generic_toJSON,
|
||||
Generic_fromJSON} from "../utils/JSONReviver.js";
|
||||
import {compareArrays} from "../utils/HelperFunctions.js";
|
||||
import {compareArrays, createElement} from "../utils/HelperFunctions.js";
|
||||
import {formatNumber, numOccurrences,
|
||||
numNetscriptOperators} from "../utils/StringHelperFunctions.js";
|
||||
|
||||
@ -37,15 +39,53 @@ var keybindings = {
|
||||
emacs: "ace/keyboard/emacs",
|
||||
};
|
||||
|
||||
var scriptEditorRamCheck = null, scriptEditorRamText = null;
|
||||
function scriptEditorInit() {
|
||||
//Initialize save and close button
|
||||
var closeButton = document.getElementById("script-editor-save-and-close-button");
|
||||
|
||||
closeButton.addEventListener("click", function() {
|
||||
saveAndCloseScriptEditor();
|
||||
return false;
|
||||
//Create buttons at the bottom of script editor
|
||||
var wrapper = document.getElementById("script-editor-buttons-wrapper");
|
||||
if (wrapper == null) {
|
||||
console.log("Error finding 'script-editor-buttons-wrapper'");
|
||||
return;
|
||||
}
|
||||
var closeButton = createElement("a", {
|
||||
class:"a-link-button", display:"inline-block",
|
||||
innerText:"Save & Close (Ctrl + b)",
|
||||
clickListener:()=>{
|
||||
saveAndCloseScriptEditor();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
scriptEditorRamText = createElement("p", {
|
||||
display:"inline-block", margin:"10px", id:"script-editor-status-text"
|
||||
});
|
||||
|
||||
var checkboxLabel = createElement("label", {
|
||||
for:"script-editor-ram-check", margin:"4px", marginTop: "8px",
|
||||
innerText:"Dynamic RAM Usage Checker", color:"white",
|
||||
tooltip:"Enable/Disable the dynamic RAM Usage display. You may " +
|
||||
"want to disable it for very long scripts because there may be " +
|
||||
"performance issues"
|
||||
});
|
||||
|
||||
scriptEditorRamCheck = createElement("input", {
|
||||
type:"checkbox", name:"script-editor-ram-check", id:"script-editor-ram-check",
|
||||
margin:"4px", marginTop: "8px",
|
||||
});
|
||||
scriptEditorRamCheck.checked = true;
|
||||
|
||||
var documentationButton = createElement("a", {
|
||||
display:"inline-block", class:"a-link-button", innerText:"Netscript Documentation",
|
||||
href:"https://bitburner.wikia.com/wiki/Netscript",
|
||||
target:"_blank"
|
||||
});
|
||||
|
||||
wrapper.appendChild(closeButton);
|
||||
wrapper.appendChild(scriptEditorRamText);
|
||||
wrapper.appendChild(scriptEditorRamCheck);
|
||||
wrapper.appendChild(checkboxLabel);
|
||||
wrapper.appendChild(documentationButton);
|
||||
|
||||
//Initialize ACE Script editor
|
||||
var editor = ace.edit('javascript-editor');
|
||||
editor.getSession().setMode('ace/mode/netscript');
|
||||
@ -127,14 +167,19 @@ function scriptEditorInit() {
|
||||
}
|
||||
document.addEventListener("DOMContentLoaded", scriptEditorInit, false);
|
||||
|
||||
//Updates line number and RAM usage in script
|
||||
//Updates RAM usage in script
|
||||
function updateScriptEditorContent() {
|
||||
if (scriptEditorRamCheck == null || !scriptEditorRamCheck.checked) {
|
||||
scriptEditorRamText.innerText = "N/A";
|
||||
return;
|
||||
}
|
||||
var editor = ace.edit('javascript-editor');
|
||||
var code = editor.getValue();
|
||||
var codeCopy = code.repeat(1);
|
||||
var ramUsage = calculateRamUsage(codeCopy);
|
||||
document.getElementById("script-editor-status-text").innerText =
|
||||
"RAM: " + formatNumber(ramUsage, 2).toString() + "GB";
|
||||
if (ramUsage !== -1) {
|
||||
scriptEditorRamText.innerText = "RAM: " + formatNumber(ramUsage, 2).toString() + "GB";
|
||||
}
|
||||
}
|
||||
|
||||
//Define key commands in script editor (ctrl o to save + close, etc.)
|
||||
@ -233,154 +278,87 @@ Script.prototype.saveScript = function() {
|
||||
//Updates how much RAM the script uses when it is running.
|
||||
Script.prototype.updateRamUsage = function() {
|
||||
var codeCopy = this.code.repeat(1);
|
||||
this.ramUsage = calculateRamUsage(codeCopy);
|
||||
console.log("ram usage: " + this.ramUsage);
|
||||
if (isNaN(this.ramUsage)) {
|
||||
dialogBoxCreate("ERROR in calculating ram usage. This is a bug, please report to game develoepr");
|
||||
var res = calculateRamUsage(codeCopy);
|
||||
if (res !== -1) {
|
||||
this.ramUsage = res;
|
||||
}
|
||||
}
|
||||
|
||||
function calculateRamUsage(codeCopy) {
|
||||
codeCopy = codeCopy.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, '$1'); //Delete comments
|
||||
codeCopy = codeCopy.replace(/\s/g,''); //Remove all whitespace
|
||||
var baseRam = 1.4;
|
||||
var whileCount = numOccurrences(codeCopy, "while(");
|
||||
var forCount = numOccurrences(codeCopy, "for(");
|
||||
var ifCount = numOccurrences(codeCopy, "if(");
|
||||
var hackCount = numOccurrences(codeCopy, "hack(");
|
||||
var growCount = numOccurrences(codeCopy, "grow(");
|
||||
var weakenCount = numOccurrences(codeCopy, "weaken(");
|
||||
var scanCount = numOccurrences(codeCopy, "scan(");
|
||||
var nukeCount = numOccurrences(codeCopy, "nuke(");
|
||||
var brutesshCount = numOccurrences(codeCopy, "brutessh(");
|
||||
var ftpcrackCount = numOccurrences(codeCopy, "ftpcrack(");
|
||||
var relaysmtpCount = numOccurrences(codeCopy, "relaysmtp(");
|
||||
var httpwormCount = numOccurrences(codeCopy, "httpworm(");
|
||||
var sqlinjectCount = numOccurrences(codeCopy, "sqlinject(");
|
||||
var runCount = numOccurrences(codeCopy, "run(");
|
||||
var execCount = numOccurrences(codeCopy, "exec(");
|
||||
var killCount = numOccurrences(codeCopy, "kill(") + numOccurrences(codeCopy, "killall(") +
|
||||
numOccurrences(codeCopy, "exit(");
|
||||
var scpCount = numOccurrences(codeCopy, "scp(");
|
||||
var hasRootAccessCount = numOccurrences(codeCopy, "hasRootAccess(");
|
||||
var getHostnameCount = numOccurrences(codeCopy, "getHostname(") +
|
||||
numOccurrences(codeCopy, "getIp(");
|
||||
var getHackingLevelCount = numOccurrences(codeCopy, "getHackingLevel(");
|
||||
var getMultipliersCount = numOccurrences(codeCopy, "getHackingMultipliers(") +
|
||||
numOccurrences(codeCopy, "getBitNodeMultipliers(");
|
||||
var getServerCount = numOccurrences(codeCopy, "getServerMoneyAvailable(") +
|
||||
numOccurrences(codeCopy, "getServerMaxMoney(") +
|
||||
numOccurrences(codeCopy, "getServerSecurityLevel(") +
|
||||
numOccurrences(codeCopy, "getServerBaseSecurityLevel(") +
|
||||
numOccurrences(codeCopy, "getServerMinSecurityLevel(") +
|
||||
numOccurrences(codeCopy, "getServerGrowth(") +
|
||||
numOccurrences(codeCopy, "getServerRequiredHackingLevel(") +
|
||||
numOccurrences(codeCopy, "getServerNumPortsRequired(") +
|
||||
numOccurrences(codeCopy, "getServerRam(") +
|
||||
numOccurrences(codeCopy, "serverExists(");
|
||||
var fileExistsCount = numOccurrences(codeCopy, "fileExists(");
|
||||
var isRunningCount = numOccurrences(codeCopy, "isRunning(");
|
||||
var purchaseHacknetCount = numOccurrences(codeCopy, "purchaseHacknetNode(");
|
||||
var hacknetnodesArrayCount = numOccurrences(codeCopy, "hacknetnodes[");
|
||||
var hnUpgLevelCount = numOccurrences(codeCopy, ".upgradeLevel(");
|
||||
var hnUpgRamCount = numOccurrences(codeCopy, ".upgradeRam()");
|
||||
var hnUpgCoreCount = numOccurrences(codeCopy, ".upgradeCore()");
|
||||
var scriptGetStockCount = numOccurrences(codeCopy, "getStockPrice(") +
|
||||
numOccurrences(codeCopy, "getStockPosition(");
|
||||
var scriptBuySellStockCount = numOccurrences(codeCopy, "buyStock(") +
|
||||
numOccurrences(codeCopy, "sellStock(") +
|
||||
numOccurrences(codeCopy, "shortStock(") +
|
||||
numOccurrences(codeCopy, "sellShort(") +
|
||||
numOccurrences(codeCopy, "placeOrder(") +
|
||||
numOccurrences(codeCopy, "cancelOrder(");
|
||||
var scriptPurchaseServerCount = numOccurrences(codeCopy, "purchaseServer(") +
|
||||
numOccurrences(codeCopy, "deleteServer(") +
|
||||
numOccurrences(codeCopy, "getPurchasedServers(");
|
||||
var scriptRoundCount = numOccurrences(codeCopy, "round(");
|
||||
var scriptWriteCount = numOccurrences(codeCopy, "write(") + numOccurrences(codeCopy, "clear(");
|
||||
var scriptReadCount = numOccurrences(codeCopy, "read(");
|
||||
var arbScriptCount = numOccurrences(codeCopy, "scriptRunning(") +
|
||||
numOccurrences(codeCopy, "scriptKill(");
|
||||
var getScriptCount = numOccurrences(codeCopy, "getScriptRam(") +
|
||||
numOccurrences(codeCopy, "getScriptIncome(") +
|
||||
numOccurrences(codeCopy, "getScriptExpGain(");
|
||||
var getHackTimeCount = numOccurrences(codeCopy, "getHackTime(") +
|
||||
numOccurrences(codeCopy, "getGrowTime(") +
|
||||
numOccurrences(codeCopy, "getWeakenTime(") +
|
||||
numOccurrences(codeCopy, "getTimeSinceLastAug(");
|
||||
var singFn1Count = numOccurrences(codeCopy, "universityCourse(") +
|
||||
numOccurrences(codeCopy, "gymWorkout(") +
|
||||
numOccurrences(codeCopy, "travelToCity(") +
|
||||
numOccurrences(codeCopy, "purchaseTor(") +
|
||||
numOccurrences(codeCopy, "purchaseProgram(") +
|
||||
numOccurrences(codeCopy, "getStats(") +
|
||||
numOccurrences(codeCopy, "isBusy(");
|
||||
var singFn2Count = numOccurrences(codeCopy, "upgradeHomeRam(") +
|
||||
numOccurrences(codeCopy, "getUpgradeHomeRamCost(") +
|
||||
numOccurrences(codeCopy, "workForCompany(") +
|
||||
numOccurrences(codeCopy, "applyToCompany(") +
|
||||
numOccurrences(codeCopy, "getCompanyRep(") +
|
||||
numOccurrences(codeCopy, "checkFactionInvitations(") +
|
||||
numOccurrences(codeCopy, "joinFaction(") +
|
||||
numOccurrences(codeCopy, "workForFaction(") +
|
||||
numOccurrences(codeCopy, "getFactionRep(");
|
||||
var singFn3Count = numOccurrences(codeCopy, "createProgram(") +
|
||||
numOccurrences(codeCopy, "commitCrime(") +
|
||||
numOccurrences(codeCopy, "getCrimeChance(") +
|
||||
numOccurrences(codeCopy, "getOwnedAugmentations(") +
|
||||
numOccurrences(codeCopy, "getAugmentationsFromFaction(") +
|
||||
numOccurrences(codeCopy, "getAugmentationCost(") +
|
||||
numOccurrences(codeCopy, "purchaseAugmentation(") +
|
||||
numOccurrences(codeCopy, "installAugmentations(");
|
||||
//Create a temporary/mock WorkerScript and an AST from the code
|
||||
var workerScript = new WorkerScript({
|
||||
filename:"foo",
|
||||
scriptRef: {code:""},
|
||||
args:[]
|
||||
});
|
||||
workerScript.checkingRam = true; //Netscript functions will return RAM usage
|
||||
|
||||
if (Player.bitNodeN != 4) {
|
||||
singFn1Count *= 10;
|
||||
singFn2Count *= 10;
|
||||
singFn3Count *= 10;
|
||||
try {
|
||||
var ast = parse(codeCopy);
|
||||
} catch(e) {
|
||||
console.log("returning -1 bc parsing error: " + e.toString());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return baseRam +
|
||||
((whileCount * CONSTANTS.ScriptWhileRamCost) +
|
||||
(forCount * CONSTANTS.ScriptForRamCost) +
|
||||
(ifCount * CONSTANTS.ScriptIfRamCost) +
|
||||
(hackCount * CONSTANTS.ScriptHackRamCost) +
|
||||
(growCount * CONSTANTS.ScriptGrowRamCost) +
|
||||
(weakenCount * CONSTANTS.ScriptWeakenRamCost) +
|
||||
(scanCount * CONSTANTS.ScriptScanRamCost) +
|
||||
(nukeCount * CONSTANTS.ScriptNukeRamCost) +
|
||||
(brutesshCount * CONSTANTS.ScriptBrutesshRamCost) +
|
||||
(ftpcrackCount * CONSTANTS.ScriptFtpcrackRamCost) +
|
||||
(relaysmtpCount * CONSTANTS.ScriptRelaysmtpRamCost) +
|
||||
(httpwormCount * CONSTANTS.ScriptHttpwormRamCost) +
|
||||
(sqlinjectCount * CONSTANTS.ScriptSqlinjectRamCost) +
|
||||
(runCount * CONSTANTS.ScriptRunRamCost) +
|
||||
(execCount * CONSTANTS.ScriptExecRamCost) +
|
||||
(killCount * CONSTANTS.ScriptKillRamCost) +
|
||||
(scpCount * CONSTANTS.ScriptScpRamCost) +
|
||||
(hasRootAccessCount * CONSTANTS.ScriptHasRootAccessRamCost) +
|
||||
(getHostnameCount * CONSTANTS.ScriptGetHostnameRamCost) +
|
||||
(getHackingLevelCount * CONSTANTS.ScriptGetHackingLevelRamCost) +
|
||||
(getMultipliersCount * CONSTANTS.ScriptGetMultipliersRamCost) +
|
||||
(getServerCount * CONSTANTS.ScriptGetServerCost) +
|
||||
(fileExistsCount * CONSTANTS.ScriptFileExistsRamCost) +
|
||||
(isRunningCount * CONSTANTS.ScriptIsRunningRamCost) +
|
||||
(purchaseHacknetCount * CONSTANTS.ScriptPurchaseHacknetRamCost) +
|
||||
(hacknetnodesArrayCount * CONSTANTS.ScriptHacknetNodesRamCost) +
|
||||
(hnUpgLevelCount * CONSTANTS.ScriptHNUpgLevelRamCost) +
|
||||
(hnUpgRamCount * CONSTANTS.ScriptHNUpgRamRamCost) +
|
||||
(hnUpgCoreCount * CONSTANTS.ScriptHNUpgCoreRamCost) +
|
||||
(scriptGetStockCount * CONSTANTS.ScriptGetStockRamCost) +
|
||||
(scriptBuySellStockCount * CONSTANTS.ScriptBuySellStockRamCost) +
|
||||
(scriptPurchaseServerCount * CONSTANTS.ScriptPurchaseServerRamCost) +
|
||||
(scriptRoundCount * CONSTANTS.ScriptRoundRamCost) +
|
||||
(scriptWriteCount * CONSTANTS.ScriptReadWriteRamCost) +
|
||||
(scriptReadCount * CONSTANTS.ScriptReadWriteRamCost) +
|
||||
(arbScriptCount * CONSTANTS.ScriptArbScriptRamCost) +
|
||||
(getScriptCount * CONSTANTS.ScriptGetScriptRamCost) +
|
||||
(getHackTimeCount * CONSTANTS.ScriptGetHackTimeRamCost) +
|
||||
(singFn1Count * CONSTANTS.ScriptSingularityFn1RamCost) +
|
||||
(singFn2Count * CONSTANTS.ScriptSingularityFn2RamCost) +
|
||||
(singFn3Count * CONSTANTS.ScriptSingularityFn3RamCost));
|
||||
//Search through AST, scanning for any 'Identifier' nodes for functions, or While/For/If nodes
|
||||
var queue = [], ramUsage = 1.4;
|
||||
var whileUsed = false, forUsed = false, ifUsed = false;
|
||||
queue.push(ast);
|
||||
while (queue.length != 0) {
|
||||
var exp = queue.shift();
|
||||
switch (exp.type) {
|
||||
case "BlockStatement":
|
||||
case "Program":
|
||||
for (var i = 0; i < exp.body.length; ++i) {
|
||||
if (exp.body[i] instanceof Node) {
|
||||
queue.push(exp.body[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "WhileStatement":
|
||||
if (!whileUsed) {
|
||||
ramUsage += CONSTANTS.ScriptWhileRamCost;
|
||||
whileUsed = true;
|
||||
}
|
||||
break;
|
||||
case "ForStatement":
|
||||
if (!forUsed) {
|
||||
ramUsage += CONSTANTS.ScriptForRamCost;
|
||||
forUsed = true;
|
||||
}
|
||||
break;
|
||||
case "IfStatement":
|
||||
if (!ifUsed) {
|
||||
ramUsage += CONSTANTS.ScriptIfRamCost;
|
||||
ifUsed = true;
|
||||
}
|
||||
break;
|
||||
case "Identifier":
|
||||
if (exp.name in workerScript.env.vars) {
|
||||
var func = workerScript.env.get(exp.name);
|
||||
if (typeof func === "function") {
|
||||
try {
|
||||
var res = func.apply(null, []);
|
||||
if (!isNaN(res)) {ramUsage += res;}
|
||||
} catch(e) {
|
||||
console.log("ERROR applying function: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (var prop in exp) {
|
||||
if (exp.hasOwnProperty(prop)) {
|
||||
if (exp[prop] instanceof Node) {
|
||||
queue.push(exp[prop]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ramUsage;
|
||||
}
|
||||
|
||||
Script.prototype.toJSON = function() {
|
||||
|
@ -32,15 +32,14 @@ import {containsAllStrings, longestCommonStart,
|
||||
formatNumber, isString} from "../utils/StringHelperFunctions.js";
|
||||
import {addOffset, printArray} from "../utils/HelperFunctions.js";
|
||||
import {logBoxCreate} from "../utils/LogBox.js";
|
||||
import {yesNoBoxCreate,
|
||||
yesNoBoxGetYesButton,
|
||||
yesNoBoxGetNoButton, yesNoBoxClose} from "../utils/YesNoBox.js";
|
||||
|
||||
/* Write text to terminal */
|
||||
//If replace is true then spaces are replaced with " "
|
||||
function post(input, replace=true) {
|
||||
if (replace) {
|
||||
$("#terminal-input").before('<tr class="posted"><td class="terminal-line" style="color: var(--my-font-color); background-color: var(--my-background-color); white-space:pre;">' + input.replace( / /g, " " ) + '</td></tr>');
|
||||
} else {
|
||||
$("#terminal-input").before('<tr class="posted"><td class="terminal-line" style="color: var(--my-font-color); background-color: var(--my-background-color);">' + input + '</td></tr>');
|
||||
}
|
||||
function post(input) {
|
||||
$("#terminal-input").before('<tr class="posted"><td class="terminal-line" style="color: var(--my-font-color); background-color: var(--my-background-color); white-space:pre-wrap;">' + input + '</td></tr>');
|
||||
updateTerminalScroll();
|
||||
}
|
||||
|
||||
@ -744,7 +743,7 @@ let Terminal = {
|
||||
if (SpecialServerIps.hasOwnProperty("Darkweb Server")) {
|
||||
executeDarkwebTerminalCommand(commandArray);
|
||||
} else {
|
||||
post("You need to be connected to the Dark Web to use the buy command");
|
||||
post("You need to be able to connect to the Dark Web to use the buy command. (Maybe there's a TOR router you can buy somewhere)");
|
||||
}
|
||||
break;
|
||||
case "cat":
|
||||
@ -1636,7 +1635,21 @@ let Terminal = {
|
||||
post("Agility: " + Player.agility + " / 1500");
|
||||
break;
|
||||
case Programs.BitFlume:
|
||||
hackWorldDaemon(Player.bitNodeN, true);
|
||||
var yesBtn = yesNoBoxGetYesButton(),
|
||||
noBtn = yesNoBoxGetNoButton();
|
||||
yesBtn.innerHTML = "Travel to BitNode Nexus";
|
||||
noBtn.innerHTML = "Cancel";
|
||||
yesBtn.addEventListener("click", function() {
|
||||
hackWorldDaemon(Player.bitNodeN, true);
|
||||
return yesNoBoxClose();
|
||||
});
|
||||
noBtn.addEventListener("click", function() {
|
||||
return yesNoBoxClose();
|
||||
});
|
||||
yesNoBoxCreate("WARNING: USING THIS PROGRAM WILL CAUSE YOU TO LOSE ALL OF YOUR PROGRESS ON THE CURRENT BITNODE.<br><br>" +
|
||||
"Do you want to travel to the BitNode Nexus? This allows you to reset the current BitNode " +
|
||||
"and select a new one.");
|
||||
|
||||
break;
|
||||
default:
|
||||
post("Invalid executable. Cannot be run");
|
||||
|
@ -75,4 +75,15 @@ function createTextFile(fn, txt, server) {
|
||||
return file;
|
||||
}
|
||||
|
||||
function deleteTextFile(fn, server) {
|
||||
if (!fn.endsWith(".txt")) {fn += ".txt";}
|
||||
for (var i = 0; i < server.textFiles.length; ++i) {
|
||||
if (server.textFiles[i].fn === fn) {
|
||||
server.textFiles.splice(i, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export {TextFile, getTextFile, createTextFile};
|
||||
|
@ -937,7 +937,6 @@ let Engine = {
|
||||
messages: 150,
|
||||
stockTick: 30, //Update stock prices
|
||||
sCr: 1500,
|
||||
updateScriptEditorDisplay: 5,
|
||||
},
|
||||
|
||||
decrementAllCounters: function(numCycles = 1) {
|
||||
@ -997,6 +996,8 @@ let Engine = {
|
||||
if (Engine.Counters.updateDisplaysLong <= 0) {
|
||||
if (Engine.currentPage === Engine.Page.Gang) {
|
||||
updateGangContent();
|
||||
} else if (Engine.currentPage === Engine.Page.ScriptEditor) {
|
||||
updateScriptEditorContent();
|
||||
}
|
||||
Engine.Counters.updateDisplaysLong = 15;
|
||||
}
|
||||
@ -1058,13 +1059,6 @@ let Engine = {
|
||||
}
|
||||
Engine.Counters.sCr = 1500;
|
||||
}
|
||||
|
||||
if (Engine.Counters.updateScriptEditorDisplay <= 0) {
|
||||
if (Engine.currentPage == Engine.Page.ScriptEditor) {
|
||||
updateScriptEditorContent();
|
||||
}
|
||||
Engine.Counters.updateScriptEditorDisplay = 5;
|
||||
}
|
||||
},
|
||||
|
||||
/* Calculates the hack progress for a manual (non-scripted) hack and updates the progress bar/time accordingly */
|
||||
|
@ -71,6 +71,7 @@ function createElement(type, params) {
|
||||
if (params.visibility) {el.style.visibility = params.visibility;}
|
||||
if (params.margin) {el.style.margin = params.margin;}
|
||||
if (params.marginLeft) {el.style.marginLeft = params.marginLeft;}
|
||||
if (params.marginTop) {el.style.marginTop = params.marginTop;}
|
||||
if (params.padding) {el.style.padding = params.padding;}
|
||||
if (params.color) {el.style.color = params.color;}
|
||||
if (params.border) {el.style.border = params.border;}
|
||||
@ -94,6 +95,8 @@ function createElement(type, params) {
|
||||
innerHTML:params.tooltip
|
||||
}));
|
||||
}
|
||||
if (params.href) {el.href = params.href;}
|
||||
if (params.target) {el.target = params.target;}
|
||||
if (params.clickListener) {
|
||||
el.addEventListener("click", params.clickListener);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user