This commit is contained in:
Olivier Gagnon 2021-05-31 17:34:23 -04:00
parent 674ce17834
commit 0f266eaa42
26 changed files with 306 additions and 105 deletions

@ -47,17 +47,16 @@
text-align: right;
}
#character-hack-wrapper td,
#character-agi-wrapper td {
border-bottom: 1px #aaa solid;
padding-bottom: 10px;
}
#character-str-wrapper td,
#character-cha-wrapper td {
padding-top: 10px;
}
.character-divider td {
border-top: 1px #aaa solid;
padding-top: 10px;
}
#character-hp-wrapper { color: $my-stat-hp-color; }
.character-hp-cell { color: $my-stat-hp-color; }
#character-money-wrapper { color: $my-stat-money-color; }
@ -69,6 +68,8 @@
#character-int-wrapper { color: $my-stat-int-color; }
.character-int-cell { color: $my-stat-int-color; }
.character-combat-cell { color: $my-stat-physical; }
#character-work-wrapper { color: $my-stat-hack-color; }
.character-work-cell { color: $my-stat-hack-color; }
.character-overview-btn {
@include borderRadius(12px);

@ -26,7 +26,7 @@
margin: 10px;
}
#work-in-progress-cancel-button {
.work-button {
@include borderRadius(12px);
@include boxShadow(1px 1px 3px #000);
@ -39,8 +39,8 @@
border: 3px solid #fff;
}
#work-in-progress-cancel-button:hover,
#work-in-progress-cancel-button:focus {
.work-button:hover,
.work-button:focus {
color: #fff;
text-decoration: none;
cursor: pointer;

File diff suppressed because one or more lines are too long

@ -1,2 +1,2 @@
!function(n){function t(t){for(var e,i,f=t[0],c=t[1],l=t[2],p=0,s=[];p<f.length;p++)i=f[p],u[i]&&s.push(u[i][0]),u[i]=0;for(e in c)Object.prototype.hasOwnProperty.call(c,e)&&(n[e]=c[e]);for(a&&a(t);s.length;)s.shift()();return r.push.apply(r,l||[]),o()}function o(){for(var n,t=0;t<r.length;t++){for(var o=r[t],e=!0,f=1;f<o.length;f++){var c=o[f];0!==u[c]&&(e=!1)}e&&(r.splice(t--,1),n=i(i.s=o[0]))}return n}var e={},u={1:0},r=[];function i(t){if(e[t])return e[t].exports;var o=e[t]={i:t,l:!1,exports:{}};return n[t].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=n,i.c=e,i.d=function(n,t,o){i.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:o})},i.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,t){if(1&t&&(n=i(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var e in n)i.d(o,e,function(t){return n[t]}.bind(null,e));return o},i.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(t,"a",t),t},i.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},i.p="";var f=window.webpackJsonp=window.webpackJsonp||[],c=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var a=c;r.push([842,0]),o()}({781:function(n,t,o){},783:function(n,t,o){},785:function(n,t,o){},787:function(n,t,o){},789:function(n,t,o){},791:function(n,t,o){},793:function(n,t,o){},795:function(n,t,o){},797:function(n,t,o){},799:function(n,t,o){},801:function(n,t,o){},803:function(n,t,o){},805:function(n,t,o){},807:function(n,t,o){},809:function(n,t,o){},811:function(n,t,o){},813:function(n,t,o){},815:function(n,t,o){},817:function(n,t,o){},819:function(n,t,o){},821:function(n,t,o){},823:function(n,t,o){},825:function(n,t,o){},827:function(n,t,o){},829:function(n,t,o){},831:function(n,t,o){},833:function(n,t,o){},835:function(n,t,o){},837:function(n,t,o){},839:function(n,t,o){},842:function(n,t,o){"use strict";o.r(t);o(841),o(839),o(837),o(835),o(833),o(831),o(829),o(827),o(825),o(823),o(821),o(819),o(817),o(815),o(813),o(811),o(809),o(807),o(805),o(803),o(801),o(799),o(797),o(795),o(793),o(791),o(789),o(787),o(785),o(783),o(781)}});
!function(n){function t(t){for(var e,i,f=t[0],c=t[1],l=t[2],p=0,s=[];p<f.length;p++)i=f[p],u[i]&&s.push(u[i][0]),u[i]=0;for(e in c)Object.prototype.hasOwnProperty.call(c,e)&&(n[e]=c[e]);for(a&&a(t);s.length;)s.shift()();return r.push.apply(r,l||[]),o()}function o(){for(var n,t=0;t<r.length;t++){for(var o=r[t],e=!0,f=1;f<o.length;f++){var c=o[f];0!==u[c]&&(e=!1)}e&&(r.splice(t--,1),n=i(i.s=o[0]))}return n}var e={},u={1:0},r=[];function i(t){if(e[t])return e[t].exports;var o=e[t]={i:t,l:!1,exports:{}};return n[t].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=n,i.c=e,i.d=function(n,t,o){i.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:o})},i.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,t){if(1&t&&(n=i(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var e in n)i.d(o,e,function(t){return n[t]}.bind(null,e));return o},i.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(t,"a",t),t},i.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},i.p="";var f=window.webpackJsonp=window.webpackJsonp||[],c=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var a=c;r.push([845,0]),o()}({784:function(n,t,o){},786:function(n,t,o){},788:function(n,t,o){},790:function(n,t,o){},792:function(n,t,o){},794:function(n,t,o){},796:function(n,t,o){},798:function(n,t,o){},800:function(n,t,o){},802:function(n,t,o){},804:function(n,t,o){},806:function(n,t,o){},808:function(n,t,o){},810:function(n,t,o){},812:function(n,t,o){},814:function(n,t,o){},816:function(n,t,o){},818:function(n,t,o){},820:function(n,t,o){},822:function(n,t,o){},824:function(n,t,o){},826:function(n,t,o){},828:function(n,t,o){},830:function(n,t,o){},832:function(n,t,o){},834:function(n,t,o){},836:function(n,t,o){},838:function(n,t,o){},840:function(n,t,o){},842:function(n,t,o){},845:function(n,t,o){"use strict";o.r(t);o(844),o(842),o(840),o(838),o(836),o(834),o(832),o(830),o(828),o(826),o(824),o(822),o(820),o(818),o(816),o(814),o(812),o(810),o(808),o(806),o(804),o(802),o(800),o(798),o(796),o(794),o(792),o(790),o(788),o(786),o(784)}});
//# sourceMappingURL=engineStyle.bundle.js.map

36
dist/engineStyle.css vendored

@ -366,13 +366,14 @@ a:visited {
.noscrollbar {
-ms-overflow-style: none;
/* IE and Edge */
/* stylelint-disable-next-line property-no-unknown */
scrollbar-width: none;
/* Firefox */ }
/* Firefox https://developer.mozilla.org/en-US/docs/Web/CSS/scrollbar-width */ }
.noscrollbar::-webkit-scrollbar {
display: none; }
input[type=checkbox] {
input[type="checkbox"] {
filter: invert(1) sepia(1) hue-rotate(41deg) brightness(100%) saturate(10); }
.optionCheckbox {
@ -784,15 +785,14 @@ button {
.character-stat-cell {
text-align: right; }
#character-hack-wrapper td,
#character-agi-wrapper td {
border-bottom: 1px #aaa solid;
padding-bottom: 10px; }
#character-str-wrapper td,
#character-cha-wrapper td {
padding-top: 10px; }
.character-divider td {
border-top: 1px #aaa solid;
padding-top: 10px; }
#character-hp-wrapper {
color: #dd3434; }
@ -826,6 +826,12 @@ button {
.character-combat-cell {
color: #faffdf; }
#character-work-wrapper {
color: #adff2f; }
.character-work-cell {
color: #adff2f; }
.character-overview-btn {
-webkit-border-radius: 12px;
-moz-border-radius: 12px;
@ -1521,7 +1527,7 @@ button {
width: 70%;
margin: 10px; }
#work-in-progress-cancel-button {
.work-button {
-webkit-border-radius: 12px;
-moz-border-radius: 12px;
border-radius: 12px;
@ -1536,8 +1542,8 @@ button {
padding: 5px;
border: 3px solid #fff; }
#work-in-progress-cancel-button:hover,
#work-in-progress-cancel-button:focus {
.work-button:hover,
.work-button:focus {
color: #fff;
text-decoration: none;
cursor: pointer; }
@ -2317,10 +2323,10 @@ button {
border-right: none;
opacity: 0;
transform: rotate(-45deg); }
.bbcheckbox input[type=checkbox] {
.bbcheckbox input[type="checkbox"] {
margin: 3px;
visibility: hidden; }
.bbcheckbox input[type=checkbox]:checked + label:after {
.bbcheckbox input[type="checkbox"]:checked + label:after {
opacity: 1; }
/* Bladeburner Console */
@ -2508,6 +2514,7 @@ button {
.Treant > .unlocked:hover {
background-color: #666; }
/* stylelint-disable */
/*!
* Bootstrap Grid v4.1.2 (https://getbootstrap.com/)
* Copyright 2011-2018 The Bootstrap Authors
@ -4986,10 +4993,7 @@ html {
margin-left: 0; }
.exp-input {
margin-right: 0;
margin-left: 0;
margin-top: 5px;
margin-bottom: 5px;
margin: 5px 0 5px 0;
padding: 2px 5px; }
.text-center {

70
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

@ -50,7 +50,7 @@ Duplicate Sleeves. It is a numeral value between 1 and 100, and it affects how m
is earned when the sleeve is performing a task.
Let N be the sleeve's synchronization. When the sleeve earns experience by performing
a task, both the sleeve and the player's original host consciousness of N% of the
a task, both the sleeve and the player's original host consciousness gain N% of the
amount of experience normally earned by the task. All of the player's other sleeves
earn ((N/100)^2 * 100)% of the experience.

@ -124,6 +124,6 @@ Gain experience by:
* Committing certain crimes
* Infiltration
* Working out at a gym
* Studying at a university
* Working a relevant job at a company
* Doing Field work for a Faction

@ -3,6 +3,49 @@
Changelog
=========
v0.51.10 - 2021-05-31 Focus Mark, Focus! (hydroflame)
-----------------------------------------------------
**Focus**
* You can now use the terminal and write scripts while working for factions
but you will gain reputation at a slower rate.
**SF -1**
* Added a new SF -1: Bypass
**Gang**
* "Vigilante justice"/"Ethical hacking" now reduces wanted level by a very
small percentage as well an absolute value.
**Netscript**
* 'tFormat' now has a second argument to display with millisecond precision.
* 'purchaseSleeveAug' can no longer purchase the same aug over and over for
the same sleeve.
* fix typo in logging for 'getServerSecurityLevel'
* Fixed some weird issue where very rarely you would get 0 exp from 'grow'
* 'getActionTime' now returns correct values for Diplomacy and Regeneration.
**Corporations**
* Fixed an exploit where you could get nearly infinite corporation funds by
entering negative numbers in textboxes.
* Fixed an exploit where shares could be sold again by clicking the
"sell share" button via scripts.
**Documentation**
* typo fix in purchaseTor
* typo fix in basicgameplay/stats
**Misc.**
* Very large number will no longer appear as "$NaNt"
* Hash capacity now displays in the "big number" format.
v0.51.9 - 2021-05-17 offline progress and exports! (hydroflame & community)
---------------------------------------------------------------

@ -1,15 +1,17 @@
tFormat() Netscript Function
============================
.. js:function:: tFormat(milliseconds)
.. js:function:: tFormat(milliseconds[, milliPrecision=false])
:RAM cost: 0 GB
:param number milliseconds: Amount of milliseconds to format.
:param number milliPrecision: Display time with millisecond precision.
:returns: milliseconds in the "D M H S" format
Example:
.. code-block:: javascript
tFormat(3000); // returns: "3 seconds"
tFormat(10000000); // returns: "2 hours 46 minutes 40 seconds"
tFormat(3000); // returns: "3 seconds"
tFormat(10000000); // returns: "2 hours 46 minutes 40 seconds"
tFormat(10000023, true); // returns: "2 hours 46 minutes 40.023 seconds"

@ -92,7 +92,7 @@ its type and name. The following are valid values when specifying the action's t
* blackop
* blackops
**General Actions (Training, Field Analysis, Recruitment)**
**General Actions (Training, Field Analysis, etc)**
* general
* general action
* gen

@ -10,6 +10,6 @@ purchaseTor() Netscript Function
This function allows you to automatically purchase a TOR router. The cost for purchasing a TOR router using this
function is the same as if you were to manually purchase one.
This function will return true if it successfully purchase a TOR router and false otherwise.
This function will return true if it successfully purchased a TOR router and false otherwise.
:RAM cost: 2 GB

@ -352,7 +352,8 @@
<div id="work-in-progress-container" class="generic-fullscreen-container">
<p id="work-in-progress-text"> </p>
<button id="work-in-progress-cancel-button"> Cancel Work </button>
<button id="work-in-progress-cancel-button" class="work-button"> Cancel Work </button>
<button id="work-in-progress-something-else-button" class="work-button"> Do something else simultaneously </button>
</div>
<!-- Red Pill Container -->

@ -574,6 +574,10 @@ Bladeburner.prototype.getActionObject = function(actionId) {
return GeneralActions["Field Analysis"];
case ActionTypes["Recruitment"]:
return GeneralActions["Recruitment"];
case ActionTypes["Diplomacy"]:
return GeneralActions["Diplomacy"];
case ActionTypes["Hyperbolic Regeneration Chamber"]:
return GeneralActions["Hyperbolic Regeneration Chamber"];
default:
return null;
}
@ -3037,6 +3041,9 @@ Bladeburner.prototype.getActionTimeNetscriptFn = function(type, name, workerScri
return 30;
case ActionTypes["Recruitment"]:
return this.getRecruitmentTime();
case ActionTypes["Diplomacy"]:
case ActionTypes["Hyperbolic Regeneration Chamber"]:
return 60;
default:
workerScript.log("bladeburner.getActionTime", errorLogText);
return -1;

@ -6,7 +6,7 @@
import { IMap } from "./types";
export const CONSTANTS: IMap<any> = {
Version: "0.51.9",
Version: "0.51.10",
/** 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
@ -228,10 +228,40 @@ export const CONSTANTS: IMap<any> = {
LatestUpdate:
`
v0.51.9 - 2021-05-17 offline progress and exports!
v0.51.10 - 2021-05-31 Focus Mark, Focus! (hydroflame)
-------
Focus
* You can now use the terminal and write scripts while working for factions
but you will gain reputation at a slower rate.
SF -1
* Added a new SF -1: Bypass
Gang
* "Vigilante justice"/"Ethical hacking" now reduces wanted level by a very
small percentage as well an absolute value.
Netscript
* 'tFormat' now has a second argument to display with millisecond precision.
* 'purchaseSleeveAug' can no longer purchase the same aug over and over for
the same sleeve.
* fix typo in logging for 'getServerSecurityLevel'
* Fixed some weird issue where very rarely you would get 0 exp from 'grow'
* 'getActionTime' now returns correct values for Diplomacy and Regeneration.
Corporations
* Fixed an exploit where you could get nearly infinite corporation funds by
entering negative numbers in textboxes.
* Fixed an exploit where shares could be sold again by clicking the
"sell share" button via scripts.
Documentation
* typo fix in purchaseTor
* typo fix in basicgameplay/stats
Misc.
* Very large number will no longer appear as "$NaNt"
* Hash capacity now displays in the "big number" format.
`,
}

@ -63,9 +63,14 @@ export class CorporationEventHandler {
const txt = createElement("p", {
innerText:"You can use Corporation funds or stock shares to bribe Faction Leaders in exchange for faction reputation",
});
const factionSelector = createElement("select", { margin:"3px" });
const factionSelector = createElement("select", { class: "dropdown", margin:"3px" });
for (let i = 0; i < Player.factions.length; ++i) {
const facName = Player.factions[i];
const faction = Factions[facName];
const info = faction.getInfo();
if(!info.offersWork()) continue;
factionSelector.add(createElement("option", {
text: facName, value: facName,
}));
@ -73,6 +78,7 @@ export class CorporationEventHandler {
var repGainText = createElement("p");
var stockSharesInput;
var moneyInput = createElement("input", {
class: "text-input",
type:"number", placeholder:"Corporation funds", margin:"5px",
inputListener:()=>{
var money = moneyInput.value == null || moneyInput.value == "" ? 0 : parseFloat(moneyInput.value);
@ -96,6 +102,7 @@ export class CorporationEventHandler {
},
});
stockSharesInput = createElement("input", {
class: "text-input",
type:"number", placeholder:"Stock Shares", margin: "5px",
inputListener:()=>{
var money = moneyInput.value == null || moneyInput.value == "" ? 0 : parseFloat(moneyInput.value);
@ -595,7 +602,10 @@ export class CorporationEventHandler {
const txt = createElement("p", {
innerHTML: popupText,
});
const designCity = createElement("select", { margin: "5px" });
const designCity = createElement("select", {
class: "dropdown",
margin: "5px",
});
for (const cityName in division.offices) {
if (division.offices[cityName] instanceof OfficeSpace) {
designCity.add(createElement("option", {
@ -613,17 +623,20 @@ export class CorporationEventHandler {
productNamePlaceholder = "Property Name";
}
var productNameInput = createElement("input", {
class: "text-input",
margin: "5px",
placeholder: productNamePlaceholder,
});
var lineBreak1 = createElement("br");
var designInvestInput = createElement("input", {
class: "text-input",
margin: "5px",
placeholder: "Design investment",
type: "number",
});
let confirmBtn;
var marketingInvestInput = createElement("input", {
class: "text-input",
margin: "5px",
placeholder: "Marketing investment",
type: "number",
@ -636,8 +649,8 @@ export class CorporationEventHandler {
class: "std-button",
innerText: "Develop Product",
clickListener: () => {
if (designInvestInput.value == null) { designInvestInput.value = 0; }
if (marketingInvestInput.value == null) { marketingInvestInput.value = 0; }
if (designInvestInput.value == null || designInvestInput.value < 0) { designInvestInput.value = 0; }
if (marketingInvestInput.value == null || marketingInvestInput.value < 0) { marketingInvestInput.value = 0; }
var designInvest = parseFloat(designInvestInput.value),
marketingInvest = parseFloat(marketingInvestInput.value);
if (productNameInput.value == null || productNameInput.value === "") {
@ -1501,6 +1514,7 @@ export class CorporationEventHandler {
});
const profitIndicator = createElement("p");
const input = createElement("input", {
class: "text-input",
type:"number", placeholder:"Shares to sell", margin:"5px",
inputListener: ()=> {
var numShares = Math.round(input.value);

@ -197,7 +197,10 @@ export class Overview extends BaseReactComponent {
const sellSharesBtn = this.createButton({
class: sellSharesClass,
display: "inline-block",
onClick: sellSharesOnClick,
onClick: function(event) {
if(!event.isTrusted) return;
sellSharesOnClick(event);
},
text: "Sell Shares",
tooltip: sellSharesTooltip,
});

@ -548,6 +548,12 @@ class DevMenuComponent extends Component {
}
}
addTonsCorporationFunds() {
if(Player.corporation) {
Player.corporation.funds = Player.corporation.funds.plus(1e99);
}
}
addTonsCorporationCycles() {
if (Player.corporation) {
Player.corporation.storedCycles = tonsP;
@ -1127,6 +1133,9 @@ class DevMenuComponent extends Component {
</div>
<table>
<tbody>
<tr>
<td><button className="std-button" onClick={this.addTonsCorporationFunds}>Tons of funds</button></td>
</tr>
<tr>
<td><span className="text">Cycles:</span></td>
<td><button className="std-button" onClick={this.addTonsCorporationCycles}>Tons</button></td>

@ -18,6 +18,7 @@ import {
} from "../HacknetHelpers";
import { Player } from "../../Player";
import { numeralWrapper } from "../../ui/numeralFormat";
import { Money } from "../../ui/React/Money";
import { Hashes } from "../../ui/React/Hashes";
@ -172,7 +173,7 @@ export class HacknetServer extends React.Component {
</div>
<div className={"row"}>
<p>Hash Capacity:</p>
<span className={"text"}>{node.hashCapacity}</span>
<span className={"text"}>{Hashes(node.hashCapacity)}</span>
</div>
<div className={"row"}>
<p>Level:</p><span className={"text upgradable-info"}>{node.level}</span>

@ -871,9 +871,6 @@ function NetscriptFunctions(workerScript) {
const moneyAfter = server.moneyAvailable;
workerScript.scriptRef.recordGrow(server.ip, threads);
var expGain = calculateHackingExpGain(server, Player) * threads;
if (growthPercentage == 1) {
expGain = 0;
}
const logGrowPercent = (moneyAfter/moneyBefore) - 1;
workerScript.log("grow", `Available money on '${server.hostname}' grown by ${numeralWrapper.formatPercentage(logGrowPercent, 6)}. Gained ${numeralWrapper.formatExp(expGain)} hacking exp (t=${numeralWrapper.formatThreads(threads)}).`);
workerScript.scriptRef.onlineExpGained += expGain;
@ -1581,7 +1578,7 @@ function NetscriptFunctions(workerScript) {
workerScript.log("getServerMoneyAvailable", `returned player's money: ${numeralWrapper.formatMoney(Player.money.toNumber())}`);
return Player.money.toNumber();
}
workerScript.log("getServerMoneyAvailable", `returned ${numeralWrapper.formatMoney(server.moneyAvailable)} for '${server.hostname}`);
workerScript.log("getServerMoneyAvailable", `returned ${numeralWrapper.formatMoney(server.moneyAvailable)} for '${server.hostname}'`);
return server.moneyAvailable;
},
getServerSecurityLevel: function(ip) {
@ -2486,8 +2483,8 @@ function NetscriptFunctions(workerScript) {
return numeralWrapper.format(parseFloat(n), format);
},
tFormat: function(milliseconds) {
return convertTimeMsToTimeElapsedString(milliseconds);
tFormat: function(milliseconds, milliPrecision=false) {
return convertTimeMsToTimeElapsedString(milliseconds, milliPrecision);
},
getTimeSinceLastAug: function() {
updateDynamicRam("getTimeSinceLastAug", getRamCost("getTimeSinceLastAug"));

@ -112,6 +112,7 @@ export function PlayerObject() {
//Flags/variables for working (Company, Faction, Creating Program, Taking Class)
this.isWorking = false;
this.focus = false;
this.workType = "";
this.currentWorkFactionName = "";

@ -512,7 +512,10 @@ export function queryStatFromString(str) {
}
/******* Working functions *******/
export function resetWorkStatus() {
export function resetWorkStatus(generalType, group, workType) {
if(generalType === this.workType && group === this.companyName) return;
if(generalType === this.workType && group === this.currentWorkFactionName && workType === this.factionWorkType) return;
if(this.isWorking) this.singularityStopWork();
this.workHackExpGainRate = 0;
this.workStrExpGainRate = 0;
this.workDefExpGainRate = 0;
@ -544,12 +547,13 @@ export function resetWorkStatus() {
}
export function processWorkEarnings(numCycles=1) {
const hackExpGain = this.workHackExpGainRate * numCycles;
const strExpGain = this.workStrExpGainRate * numCycles;
const defExpGain = this.workDefExpGainRate * numCycles;
const dexExpGain = this.workDexExpGainRate * numCycles;
const agiExpGain = this.workAgiExpGainRate * numCycles;
const chaExpGain = this.workChaExpGainRate * numCycles;
const focusBonus = this.focus? 1 : 0.8;
const hackExpGain = focusBonus * this.workHackExpGainRate * numCycles;
const strExpGain = focusBonus * this.workStrExpGainRate * numCycles;
const defExpGain = focusBonus * this.workDefExpGainRate * numCycles;
const dexExpGain = focusBonus * this.workDexExpGainRate * numCycles;
const agiExpGain = focusBonus * this.workAgiExpGainRate * numCycles;
const chaExpGain = focusBonus * this.workChaExpGainRate * numCycles;
const moneyGain = (this.workMoneyGainRate - this.workMoneyLossRate) * numCycles;
this.gainHackingExp(hackExpGain);
@ -570,15 +574,16 @@ export function processWorkEarnings(numCycles=1) {
this.workDexExpGained += dexExpGain;
this.workAgiExpGained += agiExpGain;
this.workChaExpGained += chaExpGain;
this.workRepGained += this.workRepGainRate * numCycles;
this.workMoneyGained += this.workMoneyGainRate * numCycles;
this.workMoneyGained -= this.workMoneyLossRate * numCycles;
this.workRepGained += focusBonus * this.workRepGainRate * numCycles;
this.workMoneyGained += focusBonus * this.workMoneyGainRate * numCycles;
this.workMoneyGained -= focusBonus * this.workMoneyLossRate * numCycles;
}
/* Working for Company */
export function startWork(companyName) {
this.resetWorkStatus();
this.resetWorkStatus(CONSTANTS.WorkTypeCompany, companyName);
this.isWorking = true;
this.focus = true;
this.companyName = companyName;
this.workType = CONSTANTS.WorkTypeCompany;
@ -601,6 +606,14 @@ export function startWork(companyName) {
return false;
});
const focusButton = clearEventListeners("work-in-progress-something-else-button");
focusButton.style.visibility = "visible";
focusButton.innerHTML = "Do something else simultaneously";
focusButton.addEventListener("click", () => {
this.stopFocusing();
return false;
});
//Display Work In Progress Screen
Engine.loadWorkInProgressContent();
}
@ -722,8 +735,9 @@ export function finishWork(cancelled, sing=false) {
}
export function startWorkPartTime(companyName) {
this.resetWorkStatus();
this.resetWorkStatus(CONSTANTS.WorkTypeCompanyPartTime, companyName);
this.isWorking = true;
this.focus = true;
this.companyName = companyName;
this.workType = CONSTANTS.WorkTypeCompanyPartTime;
@ -834,6 +848,20 @@ export function finishWorkPartTime(sing=false) {
this.resetWorkStatus();
}
export function startFocusing() {
const mainMenu = document.getElementById("mainmenu-container");
mainMenu.style.visibility = "hidden";
this.focus = true;
Engine.loadWorkInProgressContent();
}
export function stopFocusing() {
const mainMenu = document.getElementById("mainmenu-container");
mainMenu.style.visibility = "visible";
this.focus = false;
Engine.loadTerminalContent();
}
/* Working for Faction */
export function startFactionWork(faction) {
//Update reputation gain rate to account for faction favor
@ -843,24 +871,33 @@ export function startFactionWork(faction) {
this.workRepGainRate *= BitNodeMultipliers.FactionWorkRepGain;
this.isWorking = true;
this.focus = true;
this.workType = CONSTANTS.WorkTypeFaction;
this.currentWorkFactionName = faction.name;
this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer20Hours;
var cancelButton = clearEventListeners("work-in-progress-cancel-button");
const cancelButton = clearEventListeners("work-in-progress-cancel-button");
cancelButton.innerHTML = "Stop Faction Work";
cancelButton.addEventListener("click", () => {
this.finishFactionWork(true);
return false;
});
const focusButton = clearEventListeners("work-in-progress-something-else-button");
focusButton.style.visibility = "visible";
focusButton.innerHTML = "Do something else simultaneously";
focusButton.addEventListener("click", () => {
this.stopFocusing();
return false;
});
//Display Work In Progress Screen
Engine.loadWorkInProgressContent();
}
export function startFactionHackWork(faction) {
this.resetWorkStatus();
this.resetWorkStatus(CONSTANTS.WorkTypeFaction, faction.name, CONSTANTS.FactionWorkHacking);
this.workHackExpGainRate = .15 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.workRepGainRate = (this.hacking_skill + this.intelligence) / CONSTANTS.MaxSkillLevel * this.faction_rep_mult * this.getIntelligenceBonus(0.5);
@ -872,7 +909,7 @@ export function startFactionHackWork(faction) {
}
export function startFactionFieldWork(faction) {
this.resetWorkStatus();
this.resetWorkStatus(CONSTANTS.WorkTypeFaction, faction.name, CONSTANTS.FactionWorkField);
this.workHackExpGainRate = .1 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.workStrExpGainRate = .1 * this.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
@ -889,7 +926,7 @@ export function startFactionFieldWork(faction) {
}
export function startFactionSecurityWork(faction) {
this.resetWorkStatus();
this.resetWorkStatus(CONSTANTS.WorkTypeFaction, faction.name, CONSTANTS.FactionWorkSecurity);
this.workHackExpGainRate = 0.05 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.workStrExpGainRate = 0.15 * this.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
@ -1157,6 +1194,7 @@ export function getWorkRepGain() {
export function startCreateProgramWork(programName, time, reqLevel) {
this.resetWorkStatus();
this.isWorking = true;
this.focus = true;
this.workType = CONSTANTS.WorkTypeCreateProgram;
//Time needed to complete work affected by hacking skill (linearly based on
@ -1189,6 +1227,9 @@ export function startCreateProgramWork(programName, time, reqLevel) {
return false;
});
const focusButton = clearEventListeners("work-in-progress-something-else-button");
focusButton.style.visibility = "hidden";
//Display Work In Progress Screen
Engine.loadWorkInProgressContent();
}
@ -1247,6 +1288,7 @@ export function finishCreateProgramWork(cancelled) {
export function startClass(costMult, expMult, className) {
this.resetWorkStatus();
this.isWorking = true;
this.focus = true;
this.workType = CONSTANTS.WorkTypeStudyClass;
this.className = className;
@ -1402,6 +1444,7 @@ export function startCrime(crimeType, hackExp, strExp, defExp, dexExp, agiExp, c
this.resetWorkStatus();
this.isWorking = true;
this.focus = true;
this.workType = CONSTANTS.WorkTypeCrime;
if (singParams && singParams.workerscript) {
@ -1420,13 +1463,16 @@ export function startCrime(crimeType, hackExp, strExp, defExp, dexExp, agiExp, c
this.timeNeededToCompleteWork = time;
//Remove all old event listeners from Cancel button
var newCancelButton = clearEventListeners("work-in-progress-cancel-button")
const newCancelButton = clearEventListeners("work-in-progress-cancel-button")
newCancelButton.innerHTML = "Cancel crime"
newCancelButton.addEventListener("click", () => {
this.finishCrime(true);
return false;
});
const focusButton = clearEventListeners("work-in-progress-something-else-button");
focusButton.style.visibility = "hidden";
//Display Work In Progress Screen
Engine.loadWorkInProgressContent();
}

@ -666,6 +666,11 @@ export class Sleeve extends Person {
return false;
}
// Verify that this sleeve does not already have that augmentation.
if(this.augmentations.some(a => a.name === aug.name)) {
return false;
}
p.loseMoney(aug.startingCost);
this.installAugmentation(aug);
return true;

@ -1097,6 +1097,7 @@ const Engine = {
// Process offline progress
loadAllRunningScripts(); // This also takes care of offline production for those scripts
if (Player.isWorking) {
Player.focus = true;
if (Player.workType == CONSTANTS.WorkTypeFaction) {
Player.workForFaction(numCyclesOffline);
} else if (Player.workType == CONSTANTS.WorkTypeCreateProgram) {
@ -1520,6 +1521,17 @@ const Engine = {
Player.finishWork(true);
}
});
const focusButton = document.getElementById("work-in-progress-something-else-button");
focusButton.style.visibility = "hidden";
const focusable = [CONSTANTS.WorkTypeFaction, CONSTANTS.WorkTypeCompanyPartTime, CONSTANTS.WorkTypeCompany];
if(focusable.includes(Player.workType)) {
focusButton.style.visibility = "visible";
focusButton.addEventListener("click", function() {
Player.stopFocusing();
});
}
Engine.loadWorkInProgressContent();
}

@ -365,7 +365,8 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %>
<div id="work-in-progress-container" class="generic-fullscreen-container">
<p id="work-in-progress-text"> </p>
<button id="work-in-progress-cancel-button"> Cancel Work </button>
<button id="work-in-progress-cancel-button" class="work-button"> Cancel Work </button>
<button id="work-in-progress-something-else-button" class="work-button"> Do something else simultaneously </button>
</div>
<!-- Red Pill Container -->

@ -3,6 +3,7 @@ import React from "react";
import { Player } from "../../Player";
import { numeralWrapper } from "../../ui/numeralFormat";
import { Reputation } from "./Reputation";
const Component = React.Component;
@ -14,7 +15,25 @@ export class CharacterOverviewComponent extends Component {
</tr>
);
/*const work = (
<div>
<p>Work progress:</p>
<p>+{Reputation(Player.workRepGained)} rep</p>
<button onClick={() => Player.startFocusing()} id="character-overview-options-button" className="character-overview-btn">Focus</button>
</div>
);*/
const work = (
<>
<tr className="character-divider"><td colSpan="2">Work progress:</td></tr>
<tr><td colSpan="2">+{Reputation(Player.workRepGained)} rep</td></tr>
<tr><td colSpan="2">
<button onClick={() => Player.startFocusing()} id="character-overview-options-button" className="character-overview-btn">Focus</button>
</td></tr>
</>
);
return (
<>
<table>
<tbody>
<tr id="character-hp-wrapper">
@ -26,7 +45,7 @@ export class CharacterOverviewComponent extends Component {
<tr id="character-hack-wrapper">
<td className="character-hack-cell">Hack:&nbsp;</td><td id="character-hack-text" className="character-hack-cell character-stat-cell">{numeralWrapper.formatSkill(Player.hacking_skill)}</td>
</tr>
<tr id="character-str-wrapper">
<tr id="character-str-wrapper" className="character-divider">
<td className="character-combat-cell">Str:&nbsp;</td><td id="character-str-text" className="character-combat-cell character-stat-cell">{numeralWrapper.formatSkill(Player.strength)}</td>
</tr>
<tr id="character-def-wrapper">
@ -38,15 +57,20 @@ export class CharacterOverviewComponent extends Component {
<tr id="character-agi-wrapper">
<td className="character-combat-cell">Agi:&nbsp;</td><td id="character-agi-text" className="character-combat-cell character-stat-cell">{numeralWrapper.formatSkill(Player.agility)}</td>
</tr>
<tr id="character-cha-wrapper">
<tr id="character-cha-wrapper" className="character-divider">
<td className="character-cha-cell">Cha:&nbsp;</td><td id="character-cha-text" className="character-cha-cell character-stat-cell">{numeralWrapper.formatSkill(Player.charisma)}</td>
</tr>
{
Player.intelligence >= 1 &&
intelligence
}
{
(Player.isWorking && !Player.focus) &&
work
}
</tbody>
</table>
</>
)
}
}