merge dev

This commit is contained in:
Olivier Gagnon 2021-09-04 15:11:17 -04:00
commit 75d77410ea
64 changed files with 664 additions and 505 deletions

@ -345,6 +345,10 @@ a:visited {
color: $light-yellow; color: $light-yellow;
} }
.unbuyable {
color: #66CFBC;
}
.failure { .failure {
color: $alert-red; color: $alert-red;
text-shadow: 0 0 0 $alert-red; text-shadow: 0 0 0 $alert-red;

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([925,0]),o()}({862:function(n,t,o){},864:function(n,t,o){},866:function(n,t,o){},868:function(n,t,o){},870:function(n,t,o){},872:function(n,t,o){},874:function(n,t,o){},876:function(n,t,o){},878:function(n,t,o){},880:function(n,t,o){},882:function(n,t,o){},884:function(n,t,o){},886:function(n,t,o){},888:function(n,t,o){},890:function(n,t,o){},892:function(n,t,o){},894:function(n,t,o){},896:function(n,t,o){},898:function(n,t,o){},900:function(n,t,o){},902:function(n,t,o){},904:function(n,t,o){},906:function(n,t,o){},908:function(n,t,o){},910:function(n,t,o){},912:function(n,t,o){},914:function(n,t,o){},916:function(n,t,o){},918:function(n,t,o){},920:function(n,t,o){},922:function(n,t,o){},925:function(n,t,o){"use strict";o.r(t);o(924),o(922),o(920),o(918),o(916),o(914),o(912),o(910),o(908),o(906),o(904),o(902),o(900),o(898),o(896),o(894),o(892),o(890),o(888),o(886),o(884),o(882),o(880),o(878),o(876),o(874),o(872),o(870),o(868),o(866),o(864),o(862)}}); !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([926,0]),o()}({863:function(n,t,o){},865:function(n,t,o){},867:function(n,t,o){},869:function(n,t,o){},871:function(n,t,o){},873:function(n,t,o){},875:function(n,t,o){},877:function(n,t,o){},879:function(n,t,o){},881:function(n,t,o){},883:function(n,t,o){},885:function(n,t,o){},887:function(n,t,o){},889:function(n,t,o){},891:function(n,t,o){},893:function(n,t,o){},895:function(n,t,o){},897:function(n,t,o){},899:function(n,t,o){},901:function(n,t,o){},903:function(n,t,o){},905:function(n,t,o){},907:function(n,t,o){},909:function(n,t,o){},911:function(n,t,o){},913:function(n,t,o){},915:function(n,t,o){},917:function(n,t,o){},919:function(n,t,o){},921:function(n,t,o){},923:function(n,t,o){},926:function(n,t,o){"use strict";o.r(t);o(925),o(923),o(921),o(919),o(917),o(915),o(913),o(911),o(909),o(907),o(905),o(903),o(901),o(899),o(897),o(895),o(893),o(891),o(889),o(887),o(885),o(883),o(881),o(879),o(877),o(875),o(873),o(871),o(869),o(867),o(865),o(863)}});
//# sourceMappingURL=engineStyle.bundle.js.map //# sourceMappingURL=engineStyle.bundle.js.map

@ -342,6 +342,9 @@ a:visited {
.light-yellow { .light-yellow {
color: #faffdf; } color: #faffdf; }
.unbuyable {
color: #66CFBC; }
.failure { .failure {
color: #ff2929; color: #ff2929;
text-shadow: 0 0 0 #ff2929; } text-shadow: 0 0 0 #ff2929; }
@ -869,6 +872,9 @@ a:visited {
.light-yellow { .light-yellow {
color: #faffdf; } color: #faffdf; }
.unbuyable {
color: #66CFBC; }
.failure { .failure {
color: #ff2929; color: #ff2929;
text-shadow: 0 0 0 #ff2929; } text-shadow: 0 0 0 #ff2929; }
@ -2271,6 +2277,9 @@ a:visited {
.light-yellow { .light-yellow {
color: #faffdf; } color: #faffdf; }
.unbuyable {
color: #66CFBC; }
.failure { .failure {
color: #ff2929; color: #ff2929;
text-shadow: 0 0 0 #ff2929; } text-shadow: 0 0 0 #ff2929; }

30
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

@ -167,7 +167,7 @@ function generateStatsDescription(mults: IMap<number>, programs?: string[], star
desc = <>{desc}<br />+{f(mults.bladeburner_success_chance_mult-1)} Bladeburner Contracts and Operations success chance</> desc = <>{desc}<br />+{f(mults.bladeburner_success_chance_mult-1)} Bladeburner Contracts and Operations success chance</>
if(startingMoney) if(startingMoney)
desc = <>{desc}<br />Start with {Money(startingMoney)} after installing Augmentations.</> desc = <>{desc}<br />Start with <Money money={startingMoney} /> after installing Augmentations.</>
if(programs) if(programs)
desc = <>{desc}<br />Start with {programs.join(' and ')} after installing Augmentations.</> desc = <>{desc}<br />Start with {programs.join(' and ')} after installing Augmentations.</>

@ -97,7 +97,7 @@ export function Stats(props: IProps): React.ReactElement {
<p>Team Size: {formatNumber(props.bladeburner.teamSize, 0)}</p> <p>Team Size: {formatNumber(props.bladeburner.teamSize, 0)}</p>
<p>Team Members Lost: {formatNumber(props.bladeburner.teamLost, 0)}</p><br /> <p>Team Members Lost: {formatNumber(props.bladeburner.teamLost, 0)}</p><br />
<p>Num Times Hospitalized: {props.bladeburner.numHosp}</p> <p>Num Times Hospitalized: {props.bladeburner.numHosp}</p>
<p>Money Lost From Hospitalizations: {Money(props.bladeburner.moneyLost)}</p><br /> <p>Money Lost From Hospitalizations: <Money money={props.bladeburner.moneyLost} /></p><br />
<p>Current City: {props.bladeburner.city}</p> <p>Current City: {props.bladeburner.city}</p>
<p className="tooltip" style={{display: 'inline-block'}}> <p className="tooltip" style={{display: 'inline-block'}}>
Est. Synthoid Population: {numeralWrapper.formatPopulation(props.bladeburner.getCurrentCity().popEst)} Est. Synthoid Population: {numeralWrapper.formatPopulation(props.bladeburner.getCurrentCity().popEst)}

@ -314,7 +314,7 @@ export class Blackjack extends Game<Props, State> {
label={ label={
<> <>
{"Wager (Max: "} {"Wager (Max: "}
{Money(MAX_BET)} <Money money={MAX_BET} />
{")"} {")"}
</> </>
} }
@ -333,7 +333,7 @@ export class Blackjack extends Game<Props, State> {
<p> <p>
{"Total earnings this session: "} {"Total earnings this session: "}
{Money(gains)} <Money money={gains} />
</p> </p>
</div> </div>
@ -404,13 +404,13 @@ export class Blackjack extends Game<Props, State> {
{this.isPlayerWinResult(result) && ( {this.isPlayerWinResult(result) && (
<> <>
{" You gained "} {" You gained "}
{Money(this.state.bet)} <Money money={this.state.bet} />
</> </>
)} )}
{result === Result.DealerWon && ( {result === Result.DealerWon && (
<> <>
{" You lost "} {" You lost "}
{Money(this.state.bet)} <Money money={this.state.bet} />
</> </>
)} )}
</p> </p>

@ -202,10 +202,10 @@ export class Roulette extends Game<IProps, IState> {
} }
if(playerWin) { if(playerWin) {
gain = this.state.investment*this.state.strategy.payout; gain = this.state.investment*this.state.strategy.payout;
status = <>won {Money(gain)}</>; status = <>won <Money money={gain} /></>;
} else { } else {
gain = -this.state.investment; gain = -this.state.investment;
status = <>lost {Money(-gain)}</>; status = <>lost <Money money={-gain} /></>;
} }
this.win(this.props.p, gain); this.win(this.props.p, gain);
this.setState({ this.setState({

@ -170,7 +170,7 @@ export class SlotMachine extends Game<IProps, IState> {
} }
this.setState({ this.setState({
status: <>{gains>0?"gained":"lost"} {Money(Math.abs(gains))}</>, status: <>{gains>0?"gained":"lost"} <Money money={Math.abs(gains)} /></>,
canPlay: true, canPlay: true,
}) })
if(this.reachedLimit(this.props.p)) return; if(this.reachedLimit(this.props.p)) return;

@ -5,7 +5,124 @@
*/ */
import { IMap } from "./types"; import { IMap } from "./types";
export const CONSTANTS: IMap<any> = { export const CONSTANTS: {
Version: string;
_idleSpeed: number;
MaxSkillLevel: number;
MilliPerCycle: number;
CorpFactionRepRequirement: number;
BaseCostFor1GBOfRamHome: number;
BaseCostFor1GBOfRamServer: number;
TravelCost: number;
BaseFavorToDonate: number;
DonateMoneyToRepDivisor: number;
FactionReputationToFavorBase: number;
FactionReputationToFavorMult: number;
CompanyReputationToFavorBase: number;
CompanyReputationToFavorMult: number;
NeuroFluxGovernorLevelMult: number;
NumNetscriptPorts: number;
HomeComputerMaxRam: number;
ServerBaseGrowthRate: number;
ServerMaxGrowthRate: number;
ServerFortifyAmount: number;
ServerWeakenAmount: number;
PurchasedServerLimit: number;
PurchasedServerMaxRam: number;
MultipleAugMultiplier: number;
TorRouterCost: number;
InfiltrationBribeBaseAmount: number;
InfiltrationMoneyValue: number;
InfiltrationRepValue: number;
InfiltrationExpPow: number;
WSEAccountCost: number;
TIXAPICost: number;
MarketData4SCost: number;
MarketDataTixApi4SCost: number;
StockMarketCommission: number;
HospitalCostPerHp: number;
IntelligenceCrimeWeight: number;
IntelligenceInfiltrationWeight: number;
IntelligenceCrimeBaseExpGain: number;
IntelligenceProgramBaseExpGain: number;
IntelligenceTerminalHackBaseExpGain: number;
IntelligenceSingFnBaseExpGain: number;
IntelligenceClassBaseExpGain: number;
IntelligenceHackingMissionBaseExpGain: number;
HackingMissionRepToDiffConversion: number;
HackingMissionRepToRewardConversion: number;
HackingMissionSpamTimeIncrease: number;
HackingMissionTransferAttackIncrease: number;
HackingMissionMiscDefenseIncrease: number;
HackingMissionDifficultyToHacking: number;
HackingMissionHowToPlay: string;
MillisecondsPer20Hours: number;
GameCyclesPer20Hours: number;
MillisecondsPer10Hours: number;
GameCyclesPer10Hours: number;
MillisecondsPer8Hours: number;
GameCyclesPer8Hours: number;
MillisecondsPer4Hours: number;
GameCyclesPer4Hours: number;
MillisecondsPer2Hours: number;
GameCyclesPer2Hours: number;
MillisecondsPerHour: number;
GameCyclesPerHour: number;
MillisecondsPerHalfHour: number;
GameCyclesPerHalfHour: number;
MillisecondsPerQuarterHour: number;
GameCyclesPerQuarterHour: number;
MillisecondsPerFiveMinutes: number;
GameCyclesPerFiveMinutes: number;
FactionWorkHacking: string;
FactionWorkField: string;
FactionWorkSecurity: string;
WorkTypeCompany: string;
WorkTypeCompanyPartTime: string;
WorkTypeFaction: string;
WorkTypeCreateProgram: string;
WorkTypeStudyClass: string;
WorkTypeCrime: string;
ClassStudyComputerScience: string;
ClassDataStructures: string;
ClassNetworks: string;
ClassAlgorithms: string;
ClassManagement: string;
ClassLeadership: string;
ClassGymStrength: string;
ClassGymDefense: string;
ClassGymDexterity: string;
ClassGymAgility: string;
ClassDataStructuresBaseCost: number;
ClassNetworksBaseCost: number;
ClassAlgorithmsBaseCost: number;
ClassManagementBaseCost: number;
ClassLeadershipBaseCost: number;
ClassGymBaseCost: number;
ClassStudyComputerScienceBaseExp: number;
ClassDataStructuresBaseExp: number;
ClassNetworksBaseExp: number;
ClassAlgorithmsBaseExp: number;
ClassManagementBaseExp: number;
ClassLeadershipBaseExp: number;
CrimeShoplift: string;
CrimeRobStore: string;
CrimeMug: string;
CrimeLarceny: string;
CrimeDrugs: string;
CrimeBondForgery: string;
CrimeTraffickArms: string;
CrimeHomicide: string;
CrimeGrandTheftAuto: string;
CrimeKidnap: string;
CrimeAssassination: string;
CrimeHeist: string;
CodingContractBaseFactionRepGain: number;
CodingContractBaseCompanyRepGain: number;
CodingContractBaseMoneyGain: number;
TotalNumBitNodes: number;
LatestUpdate: string;
} = {
Version: "0.52.9", Version: "0.52.9",
// Speed (in ms) at which the main loop is updated // Speed (in ms) at which the main loop is updated

@ -61,46 +61,46 @@ export const IndustryStartingCosts: IIndustryMap<number> = {
// Map of description for each industry // Map of description for each industry
export const IndustryDescriptions: IIndustryMap<JSX.Element> = { export const IndustryDescriptions: IIndustryMap<JSX.Element> = {
Energy: (<>Engage in the production and distribution of energy.<br /><br /> Energy: (<>Engage in the production and distribution of energy.<br /><br />
Starting cost: {Money(IndustryStartingCosts.Energy)}<br /> Starting cost: <Money money={IndustryStartingCosts.Energy} /><br />
Recommended starting Industry: NO</>), Recommended starting Industry: NO</>),
Utilities: (<>Distribute water and provide wastewater services.<br /><br /> Utilities: (<>Distribute water and provide wastewater services.<br /><br />
Starting cost: {Money(IndustryStartingCosts.Utilities)}<br /> Starting cost: <Money money={IndustryStartingCosts.Utilities} /><br />
Recommended starting Industry: NO</>), Recommended starting Industry: NO</>),
Agriculture: (<>Cultivate crops and breed livestock to produce food.<br /><br /> Agriculture: (<>Cultivate crops and breed livestock to produce food.<br /><br />
Starting cost: {Money(IndustryStartingCosts.Agriculture)}<br /> Starting cost: <Money money={IndustryStartingCosts.Agriculture} /><br />
Recommended starting Industry: YES</>), Recommended starting Industry: YES</>),
Fishing: (<>Produce food through the breeding and processing of fish and fish products.<br /><br /> Fishing: (<>Produce food through the breeding and processing of fish and fish products.<br /><br />
Starting cost: {Money(IndustryStartingCosts.Fishing)}<br /> Starting cost: <Money money={IndustryStartingCosts.Fishing} /><br />
Recommended starting Industry: NO</>), Recommended starting Industry: NO</>),
Mining: (<>Extract and process metals from the earth.<br /><br /> Mining: (<>Extract and process metals from the earth.<br /><br />
Starting cost: {Money(IndustryStartingCosts.Mining)}<br /> Starting cost: <Money money={IndustryStartingCosts.Mining} /><br />
Recommended starting Industry: NO</>), Recommended starting Industry: NO</>),
Food: (<>Create your own restaurants all around the world.<br /><br /> Food: (<>Create your own restaurants all around the world.<br /><br />
Starting cost: {Money(IndustryStartingCosts.Food)}<br /> Starting cost: <Money money={IndustryStartingCosts.Food} /><br />
Recommended starting Industry: YES</>), Recommended starting Industry: YES</>),
Tobacco: (<>Create and distribute tobacco and tobacco-related products.<br /><br /> Tobacco: (<>Create and distribute tobacco and tobacco-related products.<br /><br />
Starting cost: {Money(IndustryStartingCosts.Tobacco)}<br /> Starting cost: <Money money={IndustryStartingCosts.Tobacco} /><br />
Recommended starting Industry: YES</>), Recommended starting Industry: YES</>),
Chemical: (<>Produce industrial chemicals.<br /><br /> Chemical: (<>Produce industrial chemicals.<br /><br />
Starting cost: {Money(IndustryStartingCosts.Chemical)}<br /> Starting cost: <Money money={IndustryStartingCosts.Chemical} /><br />
Recommended starting Industry: NO</>), Recommended starting Industry: NO</>),
Pharmaceutical: (<>Discover, develop, and create new pharmaceutical drugs.<br /><br /> Pharmaceutical: (<>Discover, develop, and create new pharmaceutical drugs.<br /><br />
Starting cost: {Money(IndustryStartingCosts.Pharmaceutical)}<br /> Starting cost: <Money money={IndustryStartingCosts.Pharmaceutical} /><br />
Recommended starting Industry: NO</>), Recommended starting Industry: NO</>),
Computer: (<>Develop and manufacture new computer hardware and networking infrastructures.<br /><br /> Computer: (<>Develop and manufacture new computer hardware and networking infrastructures.<br /><br />
Starting cost: {Money(IndustryStartingCosts.Computer)}<br /> Starting cost: <Money money={IndustryStartingCosts.Computer} /><br />
Recommended starting Industry: NO</>), Recommended starting Industry: NO</>),
Robotics: (<>Develop and create robots.<br /><br /> Robotics: (<>Develop and create robots.<br /><br />
Starting cost: {Money(IndustryStartingCosts.Robotics)}<br /> Starting cost: <Money money={IndustryStartingCosts.Robotics} /><br />
Recommended starting Industry: NO</>), Recommended starting Industry: NO</>),
Software: (<>Develop computer software and create AI Cores.<br /><br /> Software: (<>Develop computer software and create AI Cores.<br /><br />
Starting cost: {Money(IndustryStartingCosts.Software)}<br /> Starting cost: <Money money={IndustryStartingCosts.Software} /><br />
Recommended starting Industry: YES</>), Recommended starting Industry: YES</>),
Healthcare: (<>Create and manage hospitals.<br /><br /> Healthcare: (<>Create and manage hospitals.<br /><br />
Starting cost: {Money(IndustryStartingCosts.Healthcare)}<br /> Starting cost: <Money money={IndustryStartingCosts.Healthcare} /><br />
Recommended starting Industry: NO</>), Recommended starting Industry: NO</>),
RealEstate: (<>Develop and manage real estate properties.<br /><br /> RealEstate: (<>Develop and manage real estate properties.<br /><br />
Starting cost: {Money(IndustryStartingCosts.RealEstate)}<br /> Starting cost: <Money money={IndustryStartingCosts.RealEstate} /><br />
Recommended starting Industry: NO</>), Recommended starting Industry: NO</>),
} }

@ -164,7 +164,7 @@ export function IndustryOverview(props: IProps): React.ReactElement {
return ( return (
<div> <div>
Industry: {division.type} (Corp Funds: {Money(corp.funds.toNumber())}) Industry: {division.type} (Corp Funds: <Money money={corp.funds.toNumber()} />)
<br /> <br /> <br /> <br />
Awareness: {numeralWrapper.format(division.awareness, "0.000")} <br /> Awareness: {numeralWrapper.format(division.awareness, "0.000")} <br />
Popularity: {numeralWrapper.format(division.popularity, "0.000")} <br /> Popularity: {numeralWrapper.format(division.popularity, "0.000")} <br />
@ -184,9 +184,9 @@ export function IndustryOverview(props: IProps): React.ReactElement {
} }
{advertisingInfo} {advertisingInfo}
<br /><br /> <br /><br />
Revenue: {Money(division.lastCycleRevenue.toNumber())} / s <br /> Revenue: <Money money={division.lastCycleRevenue.toNumber()} /> / s <br />
Expenses: {Money(division.lastCycleExpenses.toNumber())} /s <br /> Expenses: <Money money={division.lastCycleExpenses.toNumber()} /> /s <br />
Profit: {Money(profit)} / s Profit: <Money money={profit} /> / s
<br /> <br /> <br /> <br />
<p className={"tooltip"}> <p className={"tooltip"}>
Production Multiplier: {numeralWrapper.format(division.prodMult, "0.00")} Production Multiplier: {numeralWrapper.format(division.prodMult, "0.00")}
@ -259,7 +259,7 @@ export function IndustryOverview(props: IProps): React.ReactElement {
upgrades.push(renderUpgrade({ upgrades.push(renderUpgrade({
key: index, key: index,
onClick: onClick, onClick: onClick,
text: <>{upgrade[4]} - {Money(cost)}</>, text: <>{upgrade[4]} - <Money money={cost} /></>,
tooltip: upgrade[5], tooltip: upgrade[5],
})); }));
} }

@ -23,7 +23,7 @@ export function LevelableUpgrade(props: IProps): React.ReactElement {
const priceMult = data[2]; const priceMult = data[2];
const cost = baseCost * Math.pow(priceMult, level); const cost = baseCost * Math.pow(priceMult, level);
const text = <>{data[4]} - {Money(cost)}</> const text = <>{data[4]} - <Money money={cost} /></>
const tooltip = data[5]; const tooltip = data[5];
function onClick(): void { function onClick(): void {
try { try {

@ -105,12 +105,12 @@ export function Overview(props: IProps): React.ReactElement {
const dividendsPerShare = totalDividends / props.corp.totalShares; const dividendsPerShare = totalDividends / props.corp.totalShares;
const playerEarnings = props.corp.numShares * dividendsPerShare; const playerEarnings = props.corp.numShares * dividendsPerShare;
return (<> return (<>
Retained Profits (after dividends): {Money(retainedEarnings)} / s<br /><br /> Retained Profits (after dividends): <Money money={retainedEarnings} /> / s<br /><br />
Dividend Percentage: {numeralWrapper.format(props.corp.dividendPercentage / 100, "0%")}<br /> Dividend Percentage: {numeralWrapper.format(props.corp.dividendPercentage / 100, "0%")}<br />
Dividends per share: {Money(dividendsPerShare)} / s<br /> Dividends per share: <Money money={dividendsPerShare} /> / s<br />
Your earnings as a shareholder (Pre-Tax): {Money(playerEarnings)} / s<br /> Your earnings as a shareholder (Pre-Tax): <Money money={playerEarnings} /> / s<br />
Dividend Tax Rate: {props.corp.dividendTaxPercentage}%<br /> Dividend Tax Rate: {props.corp.dividendTaxPercentage}%<br />
Your earnings as a shareholder (Post-Tax): {Money(playerEarnings * (1 - (props.corp.dividendTaxPercentage / 100)))} / s<br /><br /> Your earnings as a shareholder (Post-Tax): <Money money={playerEarnings * (1 - (props.corp.dividendTaxPercentage / 100))} /> / s<br /><br />
</>); </>);
} }
@ -316,14 +316,14 @@ export function Overview(props: IProps): React.ReactElement {
return ( return (
<div> <div>
<p> <p>
Total Funds: {Money(props.corp.funds.toNumber())}<br /> Total Funds: <Money money={props.corp.funds.toNumber()} /><br />
Total Revenue: {Money(props.corp.revenue.toNumber())} / s<br /> Total Revenue: <Money money={props.corp.revenue.toNumber()} /> / s<br />
Total Expenses: {Money(props.corp.expenses.toNumber())} / s<br /> Total Expenses: <Money money={props.corp.expenses.toNumber()} /> / s<br />
Total Profits: {Money(profit)} / s<br /> Total Profits: <Money money={profit} /> / s<br />
<DividendsStats /> <DividendsStats />
Publicly Traded: {(props.corp.public ? "Yes" : "No")}<br /> Publicly Traded: {(props.corp.public ? "Yes" : "No")}<br />
Owned Stock Shares: {numeralWrapper.format(props.corp.numShares, '0.000a')}<br /> Owned Stock Shares: {numeralWrapper.format(props.corp.numShares, '0.000a')}<br />
Stock Price: {(props.corp.public ? Money(props.corp.sharePrice) : "N/A")}<br /> Stock Price: {(props.corp.public ? <Money money={props.corp.sharePrice} /> : "N/A")}<br />
</p> </p>
<p className='tooltip'> <p className='tooltip'>
Total Stock Shares: {numeralWrapper.format(props.corp.totalShares, "0.000a")} Total Stock Shares: {numeralWrapper.format(props.corp.totalShares, "0.000a")}

@ -17,7 +17,7 @@ interface IProps {
export function UnlockUpgrade(props: IProps): React.ReactElement { export function UnlockUpgrade(props: IProps): React.ReactElement {
const data = props.upgradeData; const data = props.upgradeData;
const text = <>{data[2]} - {Money(data[1])}</>; const text = <>{data[2]} - <Money money={data[1]} /></>;
const tooltip = data[3]; const tooltip = data[3];
function onClick(): void { function onClick(): void {
try { try {

@ -51,7 +51,7 @@ export function executeDarkwebTerminalCommand(commandArray: string[]): void {
function listAllDarkwebItems(): void { function listAllDarkwebItems(): void {
for(const key in DarkWebItems) { for(const key in DarkWebItems) {
const item = DarkWebItems[key]; const item = DarkWebItems[key];
postElement(<>{item.program} - {Money(item.price)} - {item.description}</>); postElement(<>{item.program} - <Money money={item.price} player={Player} /> - {item.description}</>);
} }
} }

@ -641,7 +641,7 @@ class DevMenuComponent extends Component {
this.processStocks((stock) => { this.processStocks((stock) => {
stocks.push(<tr key={stock.symbol}> stocks.push(<tr key={stock.symbol}>
<td>{stock.symbol}</td> <td>{stock.symbol}</td>
<td style={{'textAlign':'right'}}>{Money(stock.cap)}</td> <td style={{'textAlign':'right'}}><Money money={stock.cap} /></td>
</tr>); </tr>);
}); });
dialogBoxCreate(<table><tbody><tr><th>Stock</th><th>Price cap</th></tr> dialogBoxCreate(<table><tbody><tr><th>Stock</th><th>Price cap</th></tr>
@ -741,11 +741,11 @@ class DevMenuComponent extends Component {
<h2>Generic</h2> <h2>Generic</h2>
</div> </div>
<div className="row"> <div className="row">
<button className="std-button" onClick={this.addMoney(1e6)}>Add $1m</button> <button className="std-button" onClick={this.addMoney(1e6)}>Add <Money money={1e6} /></button>
<button className="std-button" onClick={this.addMoney(1e9)}>Add $1b</button> <button className="std-button" onClick={this.addMoney(1e9)}>Add <Money money={1e9} /></button>
<button className="std-button" onClick={this.addMoney(1e12)}>Add $1t</button> <button className="std-button" onClick={this.addMoney(1e12)}>Add <Money money={1e12} /></button>
<button className="std-button" onClick={this.addMoney(1e15)}>Add $1000t</button> <button className="std-button" onClick={this.addMoney(1e15)}>Add <Money money={1000e12} /></button>
<button className="std-button" onClick={this.addMoney(Infinity)}>Add $Infinity</button> <button className="std-button" onClick={this.addMoney(Infinity)}>Add <Money money={Infinity} /></button>
<button className="std-button" onClick={this.upgradeRam}>Upgrade Home Computer's RAM</button> <button className="std-button" onClick={this.upgradeRam}>Upgrade Home Computer's RAM</button>
</div> </div>
<div className="row"> <div className="row">

@ -124,7 +124,7 @@ export function purchaseAugmentationBoxCreate(aug, fac) {
<h2>{aug.name}</h2><br /> <h2>{aug.name}</h2><br />
{content}<br /><br /> {content}<br /><br />
<br />Would you like to purchase the {aug.name} Augmentation for&nbsp; <br />Would you like to purchase the {aug.name} Augmentation for&nbsp;
{Money(aug.baseCost * factionInfo.augmentationPriceMult)}? <Money money={aug.baseCost * factionInfo.augmentationPriceMult} />?
</>); </>);
} }

@ -0,0 +1,6 @@
import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer";
export function repFromDonation(amt: number, player: IPlayer): number {
return amt / CONSTANTS.DonateMoneyToRepDivisor * player.faction_rep_mult;
}

@ -2,8 +2,15 @@
// These formulas were derived on wolfram alpha. // These formulas were derived on wolfram alpha.
// Wolfram Alpha: sum from 0 to n of 500*1.02^n // Wolfram Alpha: sum from 0 to n of 500*1.02^n
// 500 * ((pow(51, f+1)) / pow(50,f) - 50)
// Then we use https://herbie.uwplse.org/demo/ to simplify it and prevent
// Infinity issues.
export function favorToRep(f: number): number { export function favorToRep(f: number): number {
return 500 * ((Math.pow(51, f+1)) / Math.pow(50,f) - 50); function fma(a: number, b: number, c: number): number {
return a * b + c;
}
const ex = fma(f, (Math.log(51.0) - Math.log(50.0)), Math.log(51.0));
return fma(500.0, Math.exp(ex), -25000.0);
} }
// Wolfram Alpha: 500 (50^(-n) 51^(n + 1) - 50) solve for n // Wolfram Alpha: 500 (50^(-n) 51^(n + 1) - 50) solve for n

@ -1,11 +1,12 @@
/** /**
* React component for a donate option on the Faction UI * React component for a donate option on the Faction UI
*/ */
import * as React from "react"; import React, { useState } from "react";
import { CONSTANTS } from "../../Constants"; import { CONSTANTS } from "../../Constants";
import { Faction } from "../../Faction/Faction"; import { Faction } from "../../Faction/Faction";
import { IPlayer } from "../../PersonObjects/IPlayer"; import { IPlayer } from "../../PersonObjects/IPlayer";
import { repFromDonation } from "../formulas/donation";
import { Money } from "../../ui/React/Money"; import { Money } from "../../ui/React/Money";
import { Reputation } from "../../ui/React/Reputation"; import { Reputation } from "../../ui/React/Reputation";
@ -15,6 +16,7 @@ import { StdButton } from "../../ui/React/StdButton";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { dialogBoxCreate } from "../../../utils/DialogBox"; import { dialogBoxCreate } from "../../../utils/DialogBox";
import { MathComponent } from 'mathjax-react';
type IProps = { type IProps = {
faction: Faction; faction: Faction;
@ -24,93 +26,78 @@ type IProps = {
rerender: () => void; rerender: () => void;
} }
type IState = {
donateAmt: number;
status: JSX.Element;
}
const inputStyleMarkup = { const inputStyleMarkup = {
margin: "5px", margin: "5px",
height: "26px", height: "26px",
} }
export class DonateOption extends React.Component<IProps, IState> { const blockStyle = { display: "block" };
// Style markup for block elements. Stored as property
blockStyle: any = { display: "block" };
constructor(props: IProps) { export function DonateOption(props: IProps): React.ReactElement {
super(props); const [donateAmt, setDonateAmt] = useState<number | null>(null);
const digits = (CONSTANTS.DonateMoneyToRepDivisor+'').length-1;
function canDonate(): boolean {
this.state = { if(donateAmt === null) return false;
donateAmt: 0, if (isNaN(donateAmt) || donateAmt <= 0) return false;
status: props.disabled ? <>Unlocked at {props.favorToDonate} favor with {props.faction.name}</> : <></>, if(props.p.money.lt(donateAmt)) return false;
return true;
} }
this.calculateRepGain = this.calculateRepGain.bind(this); function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
this.donate = this.donate.bind(this); const amt = numeralWrapper.parseMoney(event.target.value);
this.handleChange = this.handleChange.bind(this); if(event.target.value === "" || isNaN(amt)) setDonateAmt(null);
else setDonateAmt(amt);
} }
// Returns rep gain for a given donation amount function donate(): void {
calculateRepGain(amt: number): number { const fac = props.faction;
return amt / CONSTANTS.DonateMoneyToRepDivisor * this.props.p.faction_rep_mult; const amt = donateAmt;
} if(amt === null) return;
if(!canDonate()) return;
donate(): void { props.p.loseMoney(amt);
const fac = this.props.faction; const repGain = repFromDonation(amt, props.p);
const amt = this.state.donateAmt; props.faction.playerReputation += repGain;
if (isNaN(amt) || amt <= 0) {
dialogBoxCreate(`Invalid amount entered!`);
} else if (!this.props.p.canAfford(amt)) {
dialogBoxCreate(`You cannot afford to donate this much money!`);
} else {
this.props.p.loseMoney(amt);
const repGain = this.calculateRepGain(amt);
this.props.faction.playerReputation += repGain;
dialogBoxCreate(<> dialogBoxCreate(<>
You just donated {Money(amt)} to {fac.name} to gain {Reputation(repGain)} reputation You just donated <Money money={amt} /> to {fac.name} to gain {Reputation(repGain)} reputation.
</>); </>);
this.props.rerender(); props.rerender();
}
} }
handleChange(e: React.ChangeEvent<HTMLInputElement>): void { function Status(): React.ReactElement {
const amt = numeralWrapper.parseMoney(e.target.value); if(donateAmt === null) return (<></>);
if(!canDonate()) {
if (isNaN(amt)) { if(props.p.money.lt(donateAmt))
this.setState({ return (<p>Insufficient funds</p>);
donateAmt: 0, return (<p>Invalid donate amount entered!</p>);
status: <>Invalid donate amount entered!</>,
});
} else {
const repGain = this.calculateRepGain(amt);
this.setState({
donateAmt: amt,
status: <>This donation will result in {Reputation(repGain)} reputation gain</>,
});
} }
return (<p>This donation will result in {Reputation(repFromDonation(donateAmt, props.p))} reputation gain</p>);
} }
render(): React.ReactNode {
return ( return (<div className={"faction-work-div"}>
<div className={"faction-work-div"}>
<div className={"faction-work-div-wrapper"}> <div className={"faction-work-div-wrapper"}>
<input <input
className="text-input" className="text-input"
onChange={this.handleChange} onChange={onChange}
placeholder={"Donation amount"} placeholder={"Donation amount"}
style={inputStyleMarkup} style={inputStyleMarkup}
disabled={this.props.disabled} disabled={props.disabled}
/> />
<StdButton <StdButton
onClick={this.donate} onClick={donate}
text={"Donate Money"} text={"Donate Money"}
disabled={this.props.disabled} disabled={props.disabled || !canDonate()}
/> />
<p style={this.blockStyle}>{this.state.status}</p> <Status />
{
props.disabled ?
<p>Unlocked at {props.favorToDonate} favor with {props.faction.name}</p> :
<div className="text">
<MathComponent tex={String.raw`reputation = \frac{\text{donation amount} \times \text{reputation multiplier}}{10^{${digits}}}`} />
</div> </div>
</div>
)
} }
</div>
</div>);
} }

@ -11,7 +11,7 @@ import { AutoupdatingParagraph } from "../../ui/React/AutoupdatingParagraph";
import { ParagraphWithTooltip } from "../../ui/React/ParagraphWithTooltip"; import { ParagraphWithTooltip } from "../../ui/React/ParagraphWithTooltip";
import { Reputation } from "../../ui/React/Reputation"; import { Reputation } from "../../ui/React/Reputation";
import { Favor } from "../../ui/React/Favor"; import { Favor } from "../../ui/React/Favor";
import { MathComponent } from 'mathjax-react' import { MathComponent } from 'mathjax-react';
type IProps = { type IProps = {
faction: Faction; faction: Faction;
@ -41,7 +41,11 @@ export class Info extends React.Component<IProps, any> {
getFavorGainContent(): JSX.Element { getFavorGainContent(): JSX.Element {
const favorGain = this.props.faction.getFavorGain()[0]; const favorGain = this.props.faction.getFavorGain()[0];
return <>You will earn {Favor(favorGain)} faction favor upon resetting after installing an Augmentation</> return (<>
You will have {Favor(this.props.faction.favor+favorGain)} faction favor after installing an Augmentation.
<MathComponent tex={String.raw`\large{r = \text{total faction reputation}}`} />
<MathComponent tex={String.raw`\large{favor=\left\lfloor\log_{1.02}\left(\frac{r+25000}{25500}\right)\right\rfloor}`} />
</>);
} }
getReputationContent(): JSX.Element { getReputationContent(): JSX.Element {
@ -52,12 +56,14 @@ export class Info extends React.Component<IProps, any> {
const favorTooltip = <> const favorTooltip = <>
Faction favor increases the rate at which you earn reputation for Faction favor increases the rate at which you earn reputation for
this faction by 1% per favor. Faction favor is gained whenever you this faction by 1% per favor. Faction favor is gained whenever you
reset after installing an Augmentation. The amount of install an Augmentation. The amount of
favor you gain depends on how much reputation you have with the faction favor you gain depends on the total amount of reputation you earned with this faction.
<MathComponent tex={String.raw`r = \text{total faction reputation}`} /> Across all resets.
<MathComponent tex={String.raw`\text{favor} = \frac{-\ln(\frac{25500}{r + 25000})}{\ln(\frac{51}{50})}`} /> <MathComponent tex={String.raw`\large{r = reputation}`} />
<MathComponent tex={String.raw`\large{\Delta r = \Delta r \times \frac{100+favor}{100}}`} />
</>; </>;
const infoText: IInnerHTMLMarkup = { const infoText: IInnerHTMLMarkup = {
__html: this.props.factionInfo.infoText, __html: this.props.factionInfo.infoText,
} }

@ -119,10 +119,10 @@ export class PurchaseableAugmentation extends React.Component<IProps, any> {
} else if (this.aug.name !== AugmentationNames.NeuroFluxGovernor && (this.aug.owned || this.owned())) { } else if (this.aug.name !== AugmentationNames.NeuroFluxGovernor && (this.aug.owned || this.owned())) {
disabled = true; disabled = true;
} else if (this.hasReputation()) { } else if (this.hasReputation()) {
status = <>UNLOCKED (at {Reputation(repCost)} faction reputation) - {Money(moneyCost)}</>; status = <>UNLOCKED (at {Reputation(repCost)} faction reputation) - <Money money={moneyCost} player={this.props.p} /></>;
} else { } else {
disabled = true; disabled = true;
status = <>LOCKED (Requires {Reputation(repCost)} faction reputation - {Money(moneyCost)})</>; status = <>LOCKED (Requires {Reputation(repCost)} faction reputation - <Money money={moneyCost} player={this.props.p} />)</>;
color = "red"; color = "red";
} }

@ -125,7 +125,6 @@ export class Gang {
this.respectGainRate = respectGains; this.respectGainRate = respectGains;
this.wantedGainRate = wantedLevelGains; this.wantedGainRate = wantedLevelGains;
this.moneyGainRate = moneyGains; this.moneyGainRate = moneyGains;
const gain = respectGains * numCycles; const gain = respectGains * numCycles;
this.respect += gain; this.respect += gain;
// Faction reputation gains is respect gain divided by some constant // Faction reputation gains is respect gain divided by some constant
@ -135,6 +134,7 @@ export class Gang {
throw new Error('Could not find the faction associated with this gang.'); throw new Error('Could not find the faction associated with this gang.');
} }
const favorMult = 1 + (fac.favor / 100); const favorMult = 1 + (fac.favor / 100);
fac.playerReputation += ((player.faction_rep_mult * gain * favorMult) / GangConstants.GangRespectToReputationRatio); fac.playerReputation += ((player.faction_rep_mult * gain * favorMult) / GangConstants.GangRespectToReputationRatio);
// Keep track of respect gained per member // Keep track of respect gained per member

@ -51,7 +51,7 @@ function GangMemberUpgradePanel(props: IPanelProps): React.ReactElement {
setRerender(old => !old); setRerender(old => !old);
} }
return (<a key={upg.name} className="a-link-button tooltip" style={{margin:"2px", padding:"2px", display:"block", fontSize:"11px"}} onClick={onClick}> return (<a key={upg.name} className="a-link-button tooltip" style={{margin:"2px", padding:"2px", display:"block", fontSize:"11px"}} onClick={onClick}>
{upg.name} - {Money(props.gang.getUpgradeCost(upg))} {upg.name} - <Money money={props.gang.getUpgradeCost(upg)} player={props.player} />
<span className={left?"tooltiptextleft":"tooltiptext"} dangerouslySetInnerHTML={{__html: upg.desc}} /> <span className={left?"tooltiptextleft":"tooltiptext"} dangerouslySetInnerHTML={{__html: upg.desc}} />
</a>); </a>);
} }

@ -10,14 +10,14 @@ export const HashUpgradesMetadata: IConstructorParams[] = [
costPerLevel: 4, costPerLevel: 4,
desc: "Sell hashes for $1m", desc: "Sell hashes for $1m",
name: "Sell for Money", name: "Sell for Money",
effectText: (level: number): JSX.Element | null => (<>Sold for {Money(1e6*level)}</>), effectText: (level: number): JSX.Element | null => (<>Sold for <Money money={1e6*level} /></>),
value: 1e6, value: 1e6,
}, },
{ {
costPerLevel: 100, costPerLevel: 100,
desc: "Sell hashes for $1b in Corporation funds", desc: "Sell hashes for $1b in Corporation funds",
name: "Sell for Corporation Funds", name: "Sell for Corporation Funds",
effectText: (level: number): JSX.Element | null => (<>Sold for {Money(1e9*level)} Corporation funds.</>), effectText: (level: number): JSX.Element | null => (<>Sold for <Money money={1e9*level} /> Corporation funds.</>),
value: 1e9, value: 1e9,
}, },
{ {

@ -40,7 +40,7 @@ export class HacknetNode extends React.Component {
} }
const upgradeLevelCost = node.calculateLevelUpgradeCost(multiplier, Player.hacknet_node_level_cost_mult); const upgradeLevelCost = node.calculateLevelUpgradeCost(multiplier, Player.hacknet_node_level_cost_mult);
upgradeLevelContent = <>Upgrade x{multiplier} - {Money(upgradeLevelCost)}</>; upgradeLevelContent = <>Upgrade x{multiplier} - <Money money={upgradeLevelCost} player={Player} /></>;
if (Player.money.lt(upgradeLevelCost)) { if (Player.money.lt(upgradeLevelCost)) {
upgradeLevelClass = "std-button-disabled"; upgradeLevelClass = "std-button-disabled";
} else { } else {
@ -71,7 +71,7 @@ export class HacknetNode extends React.Component {
} }
const upgradeRamCost = node.calculateRamUpgradeCost(multiplier, Player.hacknet_node_ram_cost_mult); const upgradeRamCost = node.calculateRamUpgradeCost(multiplier, Player.hacknet_node_ram_cost_mult);
upgradeRamContent = <>Upgrade x{multiplier} - {Money(upgradeRamCost)}</>; upgradeRamContent = <>Upgrade x{multiplier} - <Money money={upgradeRamCost} player={Player} /></>;
if (Player.money.lt(upgradeRamCost)) { if (Player.money.lt(upgradeRamCost)) {
upgradeRamClass = "std-button-disabled"; upgradeRamClass = "std-button-disabled";
} else { } else {
@ -102,7 +102,7 @@ export class HacknetNode extends React.Component {
} }
const upgradeCoreCost = node.calculateCoreUpgradeCost(multiplier, Player.hacknet_node_core_cost_mult); const upgradeCoreCost = node.calculateCoreUpgradeCost(multiplier, Player.hacknet_node_core_cost_mult);
upgradeCoresContent = <>Upgrade x{multiplier} - {Money(upgradeCoreCost)}</>; upgradeCoresContent = <>Upgrade x{multiplier} - <Money money={upgradeCoreCost} player={Player} /></>;
if (Player.money.lt(upgradeCoreCost)) { if (Player.money.lt(upgradeCoreCost)) {
upgradeCoresClass = "std-button-disabled"; upgradeCoresClass = "std-button-disabled";
} else { } else {
@ -128,7 +128,7 @@ export class HacknetNode extends React.Component {
<div className={"row"}> <div className={"row"}>
<p>Production:</p> <p>Production:</p>
<span className={"text money-gold"}> <span className={"text money-gold"}>
{Money(node.totalMoneyGenerated)} ({MoneyRate(node.moneyGainRatePerSecond)}) <Money money={node.totalMoneyGenerated} player={Player} /> ({MoneyRate(node.moneyGainRatePerSecond)})
</span> </span>
</div> </div>
<div className={"row"}> <div className={"row"}>

@ -44,7 +44,7 @@ export class HacknetServer extends React.Component {
} }
const upgradeLevelCost = node.calculateLevelUpgradeCost(multiplier, Player.hacknet_node_level_cost_mult); const upgradeLevelCost = node.calculateLevelUpgradeCost(multiplier, Player.hacknet_node_level_cost_mult);
upgradeLevelContent = <>Upgrade x{multiplier} - {Money(upgradeLevelCost)}</>; upgradeLevelContent = <>Upgrade x{multiplier} - <Money money={upgradeLevelCost} player={Player} /></>;
if (Player.money.lt(upgradeLevelCost)) { if (Player.money.lt(upgradeLevelCost)) {
upgradeLevelClass = "std-button-disabled"; upgradeLevelClass = "std-button-disabled";
} else { } else {
@ -76,7 +76,7 @@ export class HacknetServer extends React.Component {
} }
const upgradeRamCost = node.calculateRamUpgradeCost(multiplier, Player.hacknet_node_ram_cost_mult); const upgradeRamCost = node.calculateRamUpgradeCost(multiplier, Player.hacknet_node_ram_cost_mult);
upgradeRamContent = <>Upgrade x{multiplier} - {Money(upgradeRamCost)}</>; upgradeRamContent = <>Upgrade x{multiplier} - <Money money={upgradeRamCost} player={Player} /></>;
if (Player.money.lt(upgradeRamCost)) { if (Player.money.lt(upgradeRamCost)) {
upgradeRamClass = "std-button-disabled"; upgradeRamClass = "std-button-disabled";
} else { } else {
@ -108,7 +108,7 @@ export class HacknetServer extends React.Component {
} }
const upgradeCoreCost = node.calculateCoreUpgradeCost(multiplier, Player.hacknet_node_core_cost_mult); const upgradeCoreCost = node.calculateCoreUpgradeCost(multiplier, Player.hacknet_node_core_cost_mult);
upgradeCoresContent = <>Upgrade x{multiplier} - {Money(upgradeCoreCost)}</>; upgradeCoresContent = <>Upgrade x{multiplier} - <Money money={upgradeCoreCost} player={Player} /></>;
if (Player.money.lt(upgradeCoreCost)) { if (Player.money.lt(upgradeCoreCost)) {
upgradeCoresClass = "std-button-disabled"; upgradeCoresClass = "std-button-disabled";
} else { } else {
@ -140,7 +140,7 @@ export class HacknetServer extends React.Component {
} }
const upgradeCacheCost = node.calculateCacheUpgradeCost(multiplier); const upgradeCacheCost = node.calculateCacheUpgradeCost(multiplier);
upgradeCacheContent = <>Upgrade x{multiplier} - {Money(upgradeCacheCost)}</>; upgradeCacheContent = <>Upgrade x{multiplier} - <Money money={upgradeCacheCost} player={Player} /></>;
if (Player.money.lt(upgradeCacheCost)) { if (Player.money.lt(upgradeCacheCost)) {
upgradeCacheClass = "std-button-disabled"; upgradeCacheClass = "std-button-disabled";
} else { } else {

@ -26,7 +26,7 @@ export function PlayerInfo(props) {
return ( return (
<p id={"hacknet-nodes-money"}> <p id={"hacknet-nodes-money"}>
<span>Money: </span> <span>Money: </span>
{Money(Player.money.toNumber())}<br /> <Money money={Player.money.toNumber()} /><br />
{ {
hasServers && <><span>Hashes: {Hashes(Player.hashManager.hashes)} / {Hashes(Player.hashManager.capacity)}</span><br /></> hasServers && <><span>Hashes: {Hashes(Player.hashManager.hashes)} / {Hashes(Player.hashManager.capacity)}</span><br /></>

@ -23,10 +23,10 @@ export function PurchaseButton(props) {
text = <>Hacknet Server limit reached</>; text = <>Hacknet Server limit reached</>;
style = {color: "red"}; style = {color: "red"};
} else { } else {
text = <>Purchase Hacknet Server - {Money(cost)}</>; text = <>Purchase Hacknet Server - <Money money={cost} player={Player} /></>;
} }
} else { } else {
text = <>Purchase Hacknet Node - {Money(cost)}</>; text = <>Purchase Hacknet Node - <Money money={cost} player={Player} /></>;
} }
return ( return (

@ -67,7 +67,7 @@ export function Victory(props: IProps): React.ReactElement {
<StdButton onClick={trade} text={<>{"Trade for "}{Reputation(repGain)}{" reputation"}</>} /> <StdButton onClick={trade} text={<>{"Trade for "}{Reputation(repGain)}{" reputation"}</>} />
</Grid> </Grid>
<Grid item xs={3}> <Grid item xs={3}>
<StdButton onClick={sell} text={<>{"Sell for "}{Money(moneyGain)}</>} /> <StdButton onClick={sell} text={<>{"Sell for "}<Money money={moneyGain} /></>} />
</Grid> </Grid>
<Grid item xs={3}> <Grid item xs={3}>
<StdButton onClick={quitInfiltration} text={"Quit"} /> <StdButton onClick={quitInfiltration} text={"Quit"} />

@ -79,7 +79,7 @@ export function createTravelPopup(destination: CityName, travelFn: TravelFunctio
}); });
yesNoBoxCreate(<span>Would you like to travel to {destination}? The trip will yesNoBoxCreate(<span>Would you like to travel to {destination}? The trip will
cost {Money(cost)}.</span>); cost <Money money={cost} />.</span>);
} }
/** /**
@ -107,7 +107,7 @@ export function createPurchaseServerPopup(ram: number, p: IPlayer): void {
yesNoTxtInpBoxClose(); yesNoTxtInpBoxClose();
}); });
yesNoTxtInpBoxCreate(<>Would you like to purchase a new server with {numeralWrapper.formatRAM(ram)} of RAM for {Money(cost)}? yesNoTxtInpBoxCreate(<>Would you like to purchase a new server with {numeralWrapper.formatRAM(ram)} of RAM for <Money money={cost} player={p} />?
<br /><br />Please enter the server hostname below:<br /> <br /><br />Please enter the server hostname below:<br />
</>); </>);
} }
@ -245,48 +245,9 @@ export function createUpgradeHomeCoresPopup(p: IPlayer): void {
yesNoBoxCreate(<>Would you like to purchase an additional CPU Core for your home computer? Each CPU Core yesNoBoxCreate(<>Would you like to purchase an additional CPU Core for your home computer? Each CPU Core
lets you start with an additional Core Node in Hacking Missions.<br /><br /> lets you start with an additional Core Node in Hacking Missions.<br /><br />
Purchasing an additional core (for a total of {p.getHomeComputer().cpuCores + 1}) will Purchasing an additional core (for a total of {p.getHomeComputer().cpuCores + 1}) will
cost {Money(cost)}</>); cost <Money money={cost} player={p} /></>);
} }
/**
* Create a popup that lets the player upgrade the RAM on his/her home computer
* @param {IPlayer} p - Player object
*/
export function createUpgradeHomeRamPopup(p: IPlayer): void {
const cost: number = p.getUpgradeHomeRamCost();
const ram: number = p.getHomeComputer().maxRam;
const yesBtn = yesNoBoxGetYesButton();
const noBtn = yesNoBoxGetNoButton();
if (yesBtn == null || noBtn == null) { return; }
const homeComputer = p.getHomeComputer();
if (homeComputer.maxRam >= CONSTANTS.HomeComputerMaxRam) {
dialogBoxCreate(<>
You have the maximum amount of RAM on your home computer.
</>);
return;
}
yesBtn.innerText = "Purchase";
yesBtn.addEventListener("click", ()=>{
purchaseRamForHomeComputer(cost, p);
yesNoBoxClose();
});
noBtn.innerText = "Cancel";
noBtn.addEventListener("click", ()=>{
yesNoBoxClose();
});
yesNoBoxCreate(<>
Would you like to purchase additional RAM for your home computer? <br /><br />
This will upgrade your RAM from {numeralWrapper.formatRAM(ram)} to {numeralWrapper.formatRAM(ram*2)}. <br /><br />
This will cost {Money(cost)}
</>);
}
/** /**
* Attempt to purchase a TOR router * Attempt to purchase a TOR router
* @param {IPlayer} p - Player object * @param {IPlayer} p - Player object

@ -0,0 +1,72 @@
import React, { useState } from "react";
import { Location } from "../Location";
import { createPurchaseServerPopup,
createUpgradeHomeCoresPopup,
purchaseTorRouter } from "../LocationsHelpers";
import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { purchaseRamForHomeComputer } from "../../Server/ServerPurchases";
import { StdButtonPurchased } from "../../ui/React/StdButtonPurchased";
import { StdButton } from "../../ui/React/StdButton";
import { Money } from "../../ui/React/Money";
import { MathComponent } from 'mathjax-react';
type IProps = {
p: IPlayer;
}
export function CoresButton(props: IProps): React.ReactElement {
const setRerender = useState(false)[1];
function rerender(): void {
setRerender(old => !old);
}
const btnStyle = { display: "block" };
const homeComputer = props.p.getHomeComputer();
const maxCores = homeComputer.cpuCores >= 8;
if(maxCores) {
return (<StdButtonPurchased
style={btnStyle}
text={"Upgrade 'home' cores - MAX"}
/>);
}
const cost = 1e9*Math.pow(7.5, homeComputer.cpuCores);
function buy(): void {
if(maxCores) return;
if (!props.p.canAfford(cost)) return;
props.p.loseMoney(cost);
homeComputer.cpuCores++;
rerender();
}
const settings = {
CommonHTML: {
scale: 90
},
"HTML-CSS": {
scale: 90
},
NativeMML: {
scale: 90
},
SVG: {
scale: 90
},
PreviewHTML: {
scale: 90
}
}
return (<StdButton
disabled={!props.p.canAfford(cost)}
onClick={buy}
style={btnStyle}
text={<>Upgrade 'home' cores ({homeComputer.cpuCores} -&gt; {homeComputer.cpuCores+1}) - <Money money={cost} player={props.p} /></>}
tooltip={<MathComponent tex={String.raw`\large{cost = 10^9 \times 7.5 ^{\text{cores}}}`} />}
/>);
}

@ -77,22 +77,22 @@ export class GymLocation extends React.Component<IProps, any> {
<StdButton <StdButton
onClick={this.trainStrength} onClick={this.trainStrength}
style={this.btnStyle} style={this.btnStyle}
text={<>Train Strength ({Money(cost)} / sec)</>} text={<>Train Strength (<Money money={cost} player={this.props.p} /> / sec)</>}
/> />
<StdButton <StdButton
onClick={this.trainDefense} onClick={this.trainDefense}
style={this.btnStyle} style={this.btnStyle}
text={<>Train Defense ({Money(cost)} / sec)</>} text={<>Train Defense (<Money money={cost} player={this.props.p} /> / sec)</>}
/> />
<StdButton <StdButton
onClick={this.trainDexterity} onClick={this.trainDexterity}
style={this.btnStyle} style={this.btnStyle}
text={<>Train Dexterity ({Money(cost)} / sec)</>} text={<>Train Dexterity (<Money money={cost} player={this.props.p} /> / sec)</>}
/> />
<StdButton <StdButton
onClick={this.trainAgility} onClick={this.trainAgility}
style={this.btnStyle} style={this.btnStyle}
text={<>Train Agility ({Money(cost)} / sec)</>} text={<>Train Agility (<Money money={cost} player={this.props.p} /> / sec)</>}
/> />
</div> </div>
) )

@ -60,7 +60,7 @@ export class HospitalLocation extends React.Component<IProps, IState> {
currHp: this.props.p.hp, currHp: this.props.p.hp,
}); });
dialogBoxCreate(<>You were healed to full health! The hospital billed you for {Money(cost)}</>); dialogBoxCreate(<>You were healed to full health! The hospital billed you for <Money money={cost} /></>);
} }
render(): React.ReactNode { render(): React.ReactNode {
@ -70,7 +70,7 @@ export class HospitalLocation extends React.Component<IProps, IState> {
<AutoupdatingStdButton <AutoupdatingStdButton
onClick={this.getHealed} onClick={this.getHealed}
style={this.btnStyle} style={this.btnStyle}
text={<>Get treatment for wounds - {Money(cost)}</>} text={<>Get treatment for wounds - <Money money={cost} player={this.props.p} /></>}
/> />
) )
} }

@ -0,0 +1,51 @@
import React, { useState } from "react";
import { Location } from "../Location";
import { createPurchaseServerPopup,
createUpgradeHomeCoresPopup,
purchaseTorRouter } from "../LocationsHelpers";
import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { purchaseRamForHomeComputer } from "../../Server/ServerPurchases";
import { StdButtonPurchased } from "../../ui/React/StdButtonPurchased";
import { StdButton } from "../../ui/React/StdButton";
import { Money } from "../../ui/React/Money";
import { MathComponent } from 'mathjax-react';
type IProps = {
p: IPlayer;
}
export function RamButton(props: IProps): React.ReactElement {
const setRerender = useState(false)[1];
function rerender(): void {
setRerender(old => !old);
}
const btnStyle = { display: "block" };
const homeComputer = props.p.getHomeComputer();
if(homeComputer.maxRam >= CONSTANTS.HomeComputerMaxRam) {
return (<StdButtonPurchased
style={btnStyle}
text={"Upgrade 'home' RAM - MAX"}
/>);
}
const cost = props.p.getUpgradeHomeRamCost();
function buy(): void {
purchaseRamForHomeComputer(props.p);
rerender();
}
return (<StdButton
disabled={!props.p.canAfford(cost)}
onClick={buy}
style={btnStyle}
text={<>Upgrade 'home' RAM ({homeComputer.maxRam}GB -&gt; {homeComputer.maxRam*2}GB) - <Money money={cost} player={props.p} /></>}
tooltip={<MathComponent tex={String.raw`\large{3.2 \times 10^3 \times 1.58^{log_2{(ram)}}}`} />}
/>);
}

@ -8,8 +8,10 @@ import * as React from "react";
import { Location } from "../Location"; import { Location } from "../Location";
import { createPurchaseServerPopup, import { createPurchaseServerPopup,
createUpgradeHomeCoresPopup, createUpgradeHomeCoresPopup,
createUpgradeHomeRamPopup,
purchaseTorRouter } from "../LocationsHelpers"; purchaseTorRouter } from "../LocationsHelpers";
import { RamButton } from "./RamButton";
import { TorButton } from "./TorButton";
import { CoresButton } from "./CoresButton";
import { CONSTANTS } from "../../Constants"; import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer"; import { IPlayer } from "../../PersonObjects/IPlayer";
@ -24,86 +26,30 @@ type IProps = {
p: IPlayer; p: IPlayer;
} }
export class TechVendorLocation extends React.Component<IProps, any> { export function TechVendorLocation(props: IProps): React.ReactElement {
/** const btnStyle = { display: "block" };
* Stores button styling that sets them all to block display
*/
btnStyle: any;
constructor(props: IProps) {
super(props);
this.btnStyle = { display: "block" };
this.state = {
torPurchased: props.p.hasTorRouter(),
}
this.createUpgradeHomeCoresPopup = this.createUpgradeHomeCoresPopup.bind(this);
this.createUpgradeHomeRamPopup = this.createUpgradeHomeRamPopup.bind(this);
this.purchaseTorRouter = this.purchaseTorRouter.bind(this);
}
createUpgradeHomeCoresPopup(): void {
createUpgradeHomeCoresPopup(this.props.p);
}
createUpgradeHomeRamPopup(): void {
createUpgradeHomeRamPopup(this.props.p);
}
purchaseTorRouter(): void {
purchaseTorRouter(this.props.p);
this.setState({
torPurchased: this.props.p.hasTorRouter(),
});
}
render(): React.ReactNode {
const loc: Location = this.props.loc;
const purchaseServerButtons: React.ReactNode[] = []; const purchaseServerButtons: React.ReactNode[] = [];
for (let i = loc.techVendorMinRam; i <= loc.techVendorMaxRam; i *= 2) { for (let i = props.loc.techVendorMinRam; i <= props.loc.techVendorMaxRam; i *= 2) {
const cost = getPurchaseServerCost(i); const cost = getPurchaseServerCost(i);
purchaseServerButtons.push( purchaseServerButtons.push(
<StdButton <StdButton
key={i} key={i}
onClick={() => createPurchaseServerPopup(i, this.props.p)} onClick={() => createPurchaseServerPopup(i, props.p)}
style={this.btnStyle} style={btnStyle}
text={<>Purchase {i}GB Server - {Money(cost)}</>} text={<>Purchase {i}GB Server - <Money money={cost} player={props.p} /></>}
disabled={!props.p.canAfford(cost)}
/>, />,
) )
} }
return ( return (<div>
<div>
{purchaseServerButtons} {purchaseServerButtons}
{ <br />
this.state.torPurchased ? ( <p className="noselect"><i>"You can order bigger servers via scripts. We don't take custom order in person."</i></p>
<StdButtonPurchased <br />
style={this.btnStyle} <TorButton p={props.p} />
text={"TOR Router - Purchased"} <RamButton p={props.p} />
/> <CoresButton p={props.p} />
) : ( </div>);
<StdButton
onClick={this.purchaseTorRouter}
style={this.btnStyle}
text={<>Purchase TOR Router - {Money(CONSTANTS.TorRouterCost)}</>}
/>
)
}
<StdButton
onClick={this.createUpgradeHomeRamPopup}
style={this.btnStyle}
text={`Purchase additional RAM for Home computer`}
/>
<StdButton
onClick={this.createUpgradeHomeCoresPopup}
style={this.btnStyle}
text={`Purchase additional Core for Home computer`}
/>
</div>
)
}
} }

@ -0,0 +1,46 @@
import React, { useState } from "react";
import { Location } from "../Location";
import { createPurchaseServerPopup,
createUpgradeHomeCoresPopup,
purchaseTorRouter } from "../LocationsHelpers";
import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { purchaseRamForHomeComputer } from "../../Server/ServerPurchases";
import { StdButtonPurchased } from "../../ui/React/StdButtonPurchased";
import { StdButton } from "../../ui/React/StdButton";
import { Money } from "../../ui/React/Money";
type IProps = {
p: IPlayer;
}
export function TorButton(props: IProps): React.ReactElement {
const setRerender = useState(false)[1];
function rerender(): void {
setRerender(old => !old);
}
const btnStyle = { display: "block" };
function buy(): void {
purchaseTorRouter(props.p);
rerender();
}
if(props.p.hasTorRouter()) {
return (<StdButtonPurchased
style={btnStyle}
text={"TOR Router - Purchased"}
/>);
}
return (<StdButton
disabled={!props.p.canAfford(CONSTANTS.TorRouterCost)}
onClick={buy}
style={btnStyle}
text={<>Purchase TOR router - <Money money={CONSTANTS.TorRouterCost} player={props.p} /></>}
/>);
}

@ -47,7 +47,7 @@ export class TravelAgencyLocation extends React.Component<IProps, any> {
<div className="noselect"> <div className="noselect">
<p> <p>
From here, you can travel to any other city! A ticket From here, you can travel to any other city! A ticket
costs {Money(CONSTANTS.TravelCost)}. costs <Money money={CONSTANTS.TravelCost} player={this.props.p} />.
</p> </p>
<pre> ,_ . ._. _. .</pre> <pre> ,_ . ._. _. .</pre>
<pre> , _-\','|~\~ ~/ ;-'_ _-' ,;_;_, ~~-</pre> <pre> , _-\','|~\~ ~/ ;-'_ _-' ,;_;_, ~~-</pre>
@ -98,7 +98,7 @@ export class TravelAgencyLocation extends React.Component<IProps, any> {
<div> <div>
<p> <p>
From here, you can travel to any other city! A ticket From here, you can travel to any other city! A ticket
costs {Money(CONSTANTS.TravelCost)}. costs <Money money={CONSTANTS.TravelCost} />.
</p> </p>
{travelBtns} {travelBtns}
</div> </div>

@ -103,31 +103,31 @@ export class UniversityLocation extends React.Component<IProps, any> {
<StdButton <StdButton
onClick={this.dataStructures} onClick={this.dataStructures}
style={this.btnStyle} style={this.btnStyle}
text={<>Take Data Structures course ({Money(dataStructuresCost)} / sec)</>} text={<>Take Data Structures course (<Money money={dataStructuresCost} player={this.props.p} /> / sec)</>}
tooltip={earnHackingExpTooltip} tooltip={earnHackingExpTooltip}
/> />
<StdButton <StdButton
onClick={this.networks} onClick={this.networks}
style={this.btnStyle} style={this.btnStyle}
text={<>Take Networks course ({Money(networksCost)} / sec)</>} text={<>Take Networks course (<Money money={networksCost} player={this.props.p} /> / sec)</>}
tooltip={earnHackingExpTooltip} tooltip={earnHackingExpTooltip}
/> />
<StdButton <StdButton
onClick={this.algorithms} onClick={this.algorithms}
style={this.btnStyle} style={this.btnStyle}
text={<>Take Algorithms course ({Money(algorithmsCost)} / sec)</>} text={<>Take Algorithms course (<Money money={algorithmsCost} player={this.props.p} /> / sec)</>}
tooltip={earnHackingExpTooltip} tooltip={earnHackingExpTooltip}
/> />
<StdButton <StdButton
onClick={this.management} onClick={this.management}
style={this.btnStyle} style={this.btnStyle}
text={<>Take Management course ({Money(managementCost)} / sec)</>} text={<>Take Management course (<Money money={managementCost} player={this.props.p} /> / sec)</>}
tooltip={earnCharismaExpTooltip} tooltip={earnCharismaExpTooltip}
/> />
<StdButton <StdButton
onClick={this.leadership} onClick={this.leadership}
style={this.btnStyle} style={this.btnStyle}
text={<>Take Leadership course ({Money(leadershipCost)} / sec)</>} text={<>Take Leadership course (<Money money={leadershipCost} player={this.props.p} /> / sec)</>}
tooltip={earnCharismaExpTooltip} tooltip={earnCharismaExpTooltip}
/> />
</div> </div>

@ -988,7 +988,7 @@ function NetscriptFunctions(workerScript) {
workerScript.scriptRef.clearLog(); workerScript.scriptRef.clearLog();
}, },
disableLog: function(fn) { disableLog: function(fn) {
if (fn = "ALL") { if (fn === "ALL") {
for (fn in possibleLogs) { for (fn in possibleLogs) {
workerScript.disableLogs[fn] = true; workerScript.disableLogs[fn] = true;
} }
@ -4142,45 +4142,45 @@ function NetscriptFunctions(workerScript) {
}, },
}, // End Bladeburner }, // End Bladeburner
corporation: { // corporation: {
expandIndustry: function(industryName, divisionName) { // expandIndustry: function(industryName, divisionName) {
NewIndustry(Player.corporation, industryName, divisionName); // NewIndustry(Player.corporation, industryName, divisionName);
}, // },
expandCity: function(divisionName, cityName) { // expandCity: function(divisionName, cityName) {
const division = getDivision(divisionName); // const division = getDivision(divisionName);
NewCity(Player.corporation, division, cityName); // NewCity(Player.corporation, division, cityName);
}, // },
unlockUpgrade: function(upgradeName) { // unlockUpgrade: function(upgradeName) {
const upgrade = Object.values(CorporationUnlockUpgrades). // const upgrade = Object.values(CorporationUnlockUpgrades).
find(upgrade => upgrade[2] === upgradeName); // find(upgrade => upgrade[2] === upgradeName);
if(upgrade === undefined) throw new Error("No upgrade named '${upgradeName}'") // if(upgrade === undefined) throw new Error("No upgrade named '${upgradeName}'")
UnlockUpgrade(Player.corporation, upgrade); // UnlockUpgrade(Player.corporation, upgrade);
}, // },
levelUpgrade: function(upgradeName) { // levelUpgrade: function(upgradeName) {
const upgrade = Object.values(CorporationUpgrades). // const upgrade = Object.values(CorporationUpgrades).
find(upgrade => upgrade[4] === upgradeName); // find(upgrade => upgrade[4] === upgradeName);
if(upgrade === undefined) throw new Error("No upgrade named '${upgradeName}'") // if(upgrade === undefined) throw new Error("No upgrade named '${upgradeName}'")
LevelUpgrade(Player.corporation, upgrade); // LevelUpgrade(Player.corporation, upgrade);
}, // },
issueDividends: function(percent) { // issueDividends: function(percent) {
IssueDividends(Player.corporation, percent); // IssueDividends(Player.corporation, percent);
}, // },
sellMaterial: function(divisionName, cityName, materialName, amt, price) { // sellMaterial: function(divisionName, cityName, materialName, amt, price) {
const material = getMaterial(divisionName, cityName, materialName); // const material = getMaterial(divisionName, cityName, materialName);
SellMaterial(material, amt, price); // SellMaterial(material, amt, price);
}, // },
sellProduct: function(divisionName, cityName, productName, amt, price, all) { // sellProduct: function(divisionName, cityName, productName, amt, price, all) {
const product = getProduct(divisionName, productName); // const product = getProduct(divisionName, productName);
SellProduct(product, cityName, amt, price, all); // SellProduct(product, cityName, amt, price, all);
}, // },
setSmartSupply: function(divisionName, cityName, enabled) { // setSmartSupply: function(divisionName, cityName, enabled) {
const warehouse = getWarehouse(divisionName, cityName); // const warehouse = getWarehouse(divisionName, cityName);
SetSmartSupply(warehouse, enabled); // SetSmartSupply(warehouse, enabled);
}, // },
BuyMaterial: function(divisionName, cityName, materialName, amt) { // BuyMaterial: function(divisionName, cityName, materialName, amt) {
}, // },
}, // End Corporation API // }, // End Corporation API
// Coding Contract API // Coding Contract API
codingcontract: { codingcontract: {

@ -125,6 +125,12 @@ export function prestigeAugmentation() {
this.resleeves = []; this.resleeves = [];
let numSleeves = Math.min(3, SourceFileFlags[10] + (this.bitNodeN === 10 ? 1 : 0)) + this.sleevesFromCovenant;
if(this.sleeves.length > numSleeves) this.sleeves.length = numSleeves;
for(let i = this.sleeves.length; i < numSleeves; i++) {
this.sleeves.push(new Sleeve(this));
}
for (let i = 0; i < this.sleeves.length; ++i) { for (let i = 0; i < this.sleeves.length; ++i) {
if (this.sleeves[i] instanceof Sleeve) { if (this.sleeves[i] instanceof Sleeve) {
if (this.sleeves[i].shock >= 100) { if (this.sleeves[i].shock >= 100) {
@ -178,56 +184,17 @@ export function prestigeAugmentation() {
} }
export function prestigeSourceFile() { export function prestigeSourceFile() {
var homeComp = this.getHomeComputer(); this.prestigeAugmentation();
this.currentServer = homeComp.ip;
this.homeComputer = homeComp.ip;
this.numPeopleKilled = 0;
this.karma = 0;
//Reset stats
this.hacking_skill = 1;
this.strength = 1;
this.defense = 1;
this.dexterity = 1;
this.agility = 1;
this.charisma = 1;
this.hacking_exp = 0;
this.strength_exp = 0;
this.defense_exp = 0;
this.dexterity_exp = 0;
this.agility_exp = 0;
this.charisma_exp = 0;
this.money = new Decimal(1000);
this.city = CityName.Sector12;
this.location = "";
this.companyName = "";
this.jobs = {};
this.purchasedServers = [];
this.factions = [];
this.factionInvitations = [];
this.queuedAugmentations = [];
this.augmentations = [];
this.resleeves = [];
// Duplicate sleeves are reset to level 1 every Bit Node (but the number of sleeves you have persists) // Duplicate sleeves are reset to level 1 every Bit Node (but the number of sleeves you have persists)
this.sleeves.length = SourceFileFlags[10] + this.sleevesFromCovenant;
for (let i = 0; i < this.sleeves.length; ++i) { for (let i = 0; i < this.sleeves.length; ++i) {
if (this.sleeves[i] instanceof Sleeve) {
this.sleeves[i].prestige(this);
} else {
this.sleeves[i] = new Sleeve(this); this.sleeves[i] = new Sleeve(this);
} }
if(this.bitNodeN === 10) {
for (let i = 0; i < this.sleeves.length; i++) {
this.sleeves[i].shock = Math.max(25, this.sleeves[i].shock);
this.sleeves[i].sync = Math.max(25, this.sleeves[i].sync);
}
} }
const characterMenuHeader = document.getElementById("character-menu-header"); const characterMenuHeader = document.getElementById("character-menu-header");
@ -235,38 +202,8 @@ export function prestigeSourceFile() {
characterMenuHeader.click(); characterMenuHeader.click(); characterMenuHeader.click(); characterMenuHeader.click();
} }
this.isWorking = false;
this.currentWorkFactionName = "";
this.currentWorkFactionDescription = "";
this.createProgramName = "";
this.className = "";
this.crimeType = "";
this.workHackExpGainRate = 0;
this.workStrExpGainRate = 0;
this.workDefExpGainRate = 0;
this.workDexExpGainRate = 0;
this.workAgiExpGainRate = 0;
this.workChaExpGainRate = 0;
this.workRepGainRate = 0;
this.workMoneyGainRate = 0;
this.workHackExpGained = 0;
this.workStrExpGained = 0;
this.workDefExpGained = 0;
this.workDexExpGained = 0;
this.workAgiExpGained = 0;
this.workChaExpGained = 0;
this.workRepGained = 0;
this.workMoneyGained = 0;
this.timeWorked = 0; this.timeWorked = 0;
this.lastUpdate = new Date().getTime();
this.hacknetNodes.length = 0;
this.hashManager.prestige();
// Gang // Gang
this.gang = null; this.gang = null;
resetGangs(); resetGangs();
@ -280,15 +217,10 @@ export function prestigeSourceFile() {
// BitNode 3: Corporatocracy // BitNode 3: Corporatocracy
this.corporation = 0; this.corporation = 0;
// Statistics trackers
this.playtimeSinceLastAug = 0;
this.playtimeSinceLastBitnode = 0;
this.scriptProdSinceLastAug = 0;
this.moneySourceA.reset();
this.moneySourceB.reset(); this.moneySourceB.reset();
this.playtimeSinceLastBitnode = 0;
this.augmentations = [];
this.updateSkillLevels();
this.hp = this.max_hp;
} }
export function receiveInvite(factionName) { export function receiveInvite(factionName) {
@ -668,7 +600,7 @@ export function work(numCycles) {
You are currently working as a {position} at {this.companyName} (Current Company Reputation: {Reputation(companyRep)})<br /><br /> You are currently working as a {position} at {this.companyName} (Current Company Reputation: {Reputation(companyRep)})<br /><br />
You have been working for {convertTimeMsToTimeElapsedString(this.timeWorked)}<br /><br /> You have been working for {convertTimeMsToTimeElapsedString(this.timeWorked)}<br /><br />
You have earned: <br /><br /> You have earned: <br /><br />
{Money(this.workMoneyGained)} ({MoneyRate(this.workMoneyGainRate * CYCLES_PER_SEC)}) <br /><br /> <Money money={this.workMoneyGained} /> ({MoneyRate(this.workMoneyGainRate * CYCLES_PER_SEC)}) <br /><br />
{Reputation(this.workRepGained)} ({ReputationRate(this.workRepGainRate * CYCLES_PER_SEC)}) reputation for this company <br /><br /> {Reputation(this.workRepGained)} ({ReputationRate(this.workRepGainRate * CYCLES_PER_SEC)}) reputation for this company <br /><br />
{numeralWrapper.formatExp(this.workHackExpGained)} ({`${numeralWrapper.formatExp(this.workHackExpGainRate * CYCLES_PER_SEC)} / sec`}) hacking exp <br /><br /> {numeralWrapper.formatExp(this.workHackExpGained)} ({`${numeralWrapper.formatExp(this.workHackExpGainRate * CYCLES_PER_SEC)} / sec`}) hacking exp <br /><br />
{numeralWrapper.formatExp(this.workStrExpGained)} ({`${numeralWrapper.formatExp(this.workStrExpGainRate * CYCLES_PER_SEC)} / sec`}) strength exp <br /> {numeralWrapper.formatExp(this.workStrExpGained)} ({`${numeralWrapper.formatExp(this.workStrExpGainRate * CYCLES_PER_SEC)} / sec`}) strength exp <br />
@ -694,7 +626,7 @@ export function finishWork(cancelled, sing=false) {
let content = <> let content = <>
You earned a total of: <br /> You earned a total of: <br />
{Money(this.workMoneyGained)}<br /> <Money money={this.workMoneyGained} /><br />
{Reputation(this.workRepGained)} reputation for the company <br /> {Reputation(this.workRepGained)} reputation for the company <br />
{numeralWrapper.formatExp(this.workHackExpGained)} hacking exp <br /> {numeralWrapper.formatExp(this.workHackExpGained)} hacking exp <br />
{numeralWrapper.formatExp(this.workStrExpGained)} strength exp <br /> {numeralWrapper.formatExp(this.workStrExpGained)} strength exp <br />
@ -796,7 +728,7 @@ export function workPartTime(numCycles) {
You are currently working as a {position} at {this.companyName} (Current Company Reputation: {Reputation(companyRep)})<br /><br /> You are currently working as a {position} at {this.companyName} (Current Company Reputation: {Reputation(companyRep)})<br /><br />
You have been working for {convertTimeMsToTimeElapsedString(this.timeWorked)}<br /><br /> You have been working for {convertTimeMsToTimeElapsedString(this.timeWorked)}<br /><br />
You have earned: <br /><br /> You have earned: <br /><br />
{Money(this.workMoneyGained)} ({MoneyRate(this.workMoneyGainRate * CYCLES_PER_SEC)}) <br /><br /> <Money money={this.workMoneyGained} /> ({MoneyRate(this.workMoneyGainRate * CYCLES_PER_SEC)}) <br /><br />
{Reputation(this.workRepGained)} ({Reputation(`${numeralWrapper.formatExp(this.workRepGainRate * CYCLES_PER_SEC)} / sec`)}) reputation for this company <br /><br /> {Reputation(this.workRepGained)} ({Reputation(`${numeralWrapper.formatExp(this.workRepGainRate * CYCLES_PER_SEC)} / sec`)}) reputation for this company <br /><br />
{numeralWrapper.formatExp(this.workHackExpGained)} ({`${numeralWrapper.formatExp(this.workHackExpGainRate * CYCLES_PER_SEC)} / sec`}) hacking exp <br /><br /> {numeralWrapper.formatExp(this.workHackExpGained)} ({`${numeralWrapper.formatExp(this.workHackExpGainRate * CYCLES_PER_SEC)} / sec`}) hacking exp <br /><br />
{numeralWrapper.formatExp(this.workStrExpGained)} ({`${numeralWrapper.formatExp(this.workStrExpGainRate * CYCLES_PER_SEC)} / sec`}) strength exp <br /> {numeralWrapper.formatExp(this.workStrExpGained)} ({`${numeralWrapper.formatExp(this.workStrExpGainRate * CYCLES_PER_SEC)} / sec`}) strength exp <br />
@ -817,7 +749,7 @@ export function finishWorkPartTime(sing=false) {
const content = <> const content = <>
You worked for {convertTimeMsToTimeElapsedString(this.timeWorked)}<br /><br /> You worked for {convertTimeMsToTimeElapsedString(this.timeWorked)}<br /><br />
You earned a total of: <br /> You earned a total of: <br />
{Money(this.workMoneyGained)}<br /> <Money money={this.workMoneyGained} /><br />
{Reputation(this.workRepGained)} reputation for the company <br /> {Reputation(this.workRepGained)} reputation for the company <br />
{numeralWrapper.formatExp(this.workHackExpGained)} hacking exp <br /> {numeralWrapper.formatExp(this.workHackExpGained)} hacking exp <br />
{numeralWrapper.formatExp(this.workStrExpGained)} strength exp <br /> {numeralWrapper.formatExp(this.workStrExpGained)} strength exp <br />
@ -981,7 +913,7 @@ export function workForFaction(numCycles) {
(Current Faction Reputation: {Reputation(faction.playerReputation)}). <br /> (Current Faction Reputation: {Reputation(faction.playerReputation)}). <br />
You have been doing this for {convertTimeMsToTimeElapsedString(this.timeWorked)}<br /><br /> You have been doing this for {convertTimeMsToTimeElapsedString(this.timeWorked)}<br /><br />
You have earned: <br /><br /> You have earned: <br /><br />
{Money(this.workMoneyGained)} ({MoneyRate(this.workMoneyGainRate * CYCLES_PER_SEC)}) <br /><br /> <Money money={this.workMoneyGained} /> ({MoneyRate(this.workMoneyGainRate * CYCLES_PER_SEC)}) <br /><br />
{Reputation(this.workRepGained)} ({ReputationRate(this.workRepGainRate * CYCLES_PER_SEC)}) reputation for this faction <br /><br /> {Reputation(this.workRepGained)} ({ReputationRate(this.workRepGainRate * CYCLES_PER_SEC)}) reputation for this faction <br /><br />
{numeralWrapper.formatExp(this.workHackExpGained)} ({numeralWrapper.formatExp(this.workHackExpGainRate * CYCLES_PER_SEC)} / sec) hacking exp <br /><br /> {numeralWrapper.formatExp(this.workHackExpGained)} ({numeralWrapper.formatExp(this.workHackExpGainRate * CYCLES_PER_SEC)} / sec) hacking exp <br /><br />
{numeralWrapper.formatExp(this.workStrExpGained)} ({numeralWrapper.formatExp(this.workStrExpGainRate * CYCLES_PER_SEC)} / sec) strength exp <br /> {numeralWrapper.formatExp(this.workStrExpGained)} ({numeralWrapper.formatExp(this.workStrExpGainRate * CYCLES_PER_SEC)} / sec) strength exp <br />
@ -1004,7 +936,7 @@ export function finishFactionWork(cancelled, sing=false) {
dialogBoxCreate(<> dialogBoxCreate(<>
You worked for your faction {faction.name} for a total of {convertTimeMsToTimeElapsedString(this.timeWorked)} <br /><br /> You worked for your faction {faction.name} for a total of {convertTimeMsToTimeElapsedString(this.timeWorked)} <br /><br />
You earned a total of: <br /> You earned a total of: <br />
{Money(this.workMoneyGained)}<br /> <Money money={this.workMoneyGained} /><br />
{Reputation(this.workRepGained)} reputation for the faction <br /> {Reputation(this.workRepGained)} reputation for the faction <br />
{numeralWrapper.formatExp(this.workHackExpGained)} hacking exp <br /> {numeralWrapper.formatExp(this.workHackExpGained)} hacking exp <br />
{numeralWrapper.formatExp(this.workStrExpGained)} strength exp <br /> {numeralWrapper.formatExp(this.workStrExpGained)} strength exp <br />
@ -1384,7 +1316,7 @@ export function takeClass(numCycles) {
ReactDOM.render(<> ReactDOM.render(<>
You have been {className} for {convertTimeMsToTimeElapsedString(this.timeWorked)}<br /><br /> You have been {className} for {convertTimeMsToTimeElapsedString(this.timeWorked)}<br /><br />
This has cost you: <br /> This has cost you: <br />
{Money(-this.workMoneyGained)} ({MoneyRate(this.workMoneyLossRate * CYCLES_PER_SEC)}) <br /><br /> <Money money={-this.workMoneyGained} /> ({MoneyRate(this.workMoneyLossRate * CYCLES_PER_SEC)}) <br /><br />
You have gained: <br /> You have gained: <br />
{numeralWrapper.formatExp(this.workHackExpGained)} ({numeralWrapper.formatExp(this.workHackExpGainRate * CYCLES_PER_SEC)} / sec) hacking exp <br /> {numeralWrapper.formatExp(this.workHackExpGained)} ({numeralWrapper.formatExp(this.workHackExpGainRate * CYCLES_PER_SEC)} / sec) hacking exp <br />
{numeralWrapper.formatExp(this.workStrExpGained)} ({numeralWrapper.formatExp(this.workStrExpGainRate * CYCLES_PER_SEC)} / sec) strength exp <br /> {numeralWrapper.formatExp(this.workStrExpGained)} ({numeralWrapper.formatExp(this.workStrExpGainRate * CYCLES_PER_SEC)} / sec) strength exp <br />
@ -1409,7 +1341,7 @@ export function finishClass(sing=false) {
if (!sing) { if (!sing) {
dialogBoxCreate(<> dialogBoxCreate(<>
After {this.className} for {convertTimeMsToTimeElapsedString(this.timeWorked)}, <br /> After {this.className} for {convertTimeMsToTimeElapsedString(this.timeWorked)}, <br />
you spent a total of {Money(this.workMoneyGained * -1)}. <br /><br /> you spent a total of <Money money={-this.workMoneyGained} />. <br /><br />
You earned a total of: <br /> You earned a total of: <br />
{numeralWrapper.formatExp(this.workHackExpGained)} hacking exp <br /> {numeralWrapper.formatExp(this.workHackExpGained)} hacking exp <br />
{numeralWrapper.formatExp(this.workStrExpGained)} strength exp <br /> {numeralWrapper.formatExp(this.workStrExpGained)} strength exp <br />
@ -1543,7 +1475,7 @@ export function finishCrime(cancelled) {
dialogBoxCreate(<> dialogBoxCreate(<>
Crime successful!<br /><br /> Crime successful!<br /><br />
You gained:<br /> You gained:<br />
{Money(this.workMoneyGained)}<br /> <Money money={this.workMoneyGained} /><br />
{numeralWrapper.formatExp(this.workHackExpGained)} hacking experience <br /> {numeralWrapper.formatExp(this.workHackExpGained)} hacking experience <br />
{numeralWrapper.formatExp(this.workStrExpGained)} strength experience<br /> {numeralWrapper.formatExp(this.workStrExpGained)} strength experience<br />
{numeralWrapper.formatExp(this.workDefExpGained)} defense experience<br /> {numeralWrapper.formatExp(this.workDefExpGained)} defense experience<br />
@ -1664,7 +1596,7 @@ export function hospitalize() {
dialogBoxCreate(<> dialogBoxCreate(<>
You were in critical condition! You were taken to the hospital where You were in critical condition! You were taken to the hospital where
luckily they were able to save your life. You were charged&nbsp; luckily they were able to save your life. You were charged&nbsp;
{Money(cost)} <Money money={cost} />
</>); </>);
} }

@ -254,6 +254,7 @@ function createResleeveUi(resleeve: Resleeve): IResleeveUIElems {
costText: null, costText: null,
buyButton: null, buyButton: null,
}; };
if(playerRef === null) return elems;
if (!routing.isOn(Page.Resleeves)) { return elems; } if (!routing.isOn(Page.Resleeves)) { return elems; }
@ -334,7 +335,7 @@ function createResleeveUi(resleeve: Resleeve): IResleeveUIElems {
const cost: number = resleeve.getCost(); const cost: number = resleeve.getCost();
elems.costPanel = createElement("div", { class: "resleeve-panel", width: "20%" }); elems.costPanel = createElement("div", { class: "resleeve-panel", width: "20%" });
elems.costText = createElement("p", { elems.costText = createElement("p", {
innerHTML: `It costs ${renderToStaticMarkup(Money(cost))} ` + innerHTML: `It costs ${renderToStaticMarkup(<Money money={cost} player={playerRef} />)} ` +
`to purchase this Sleeve.`, `to purchase this Sleeve.`,
}); });
elems.buyButton = createElement("button", { elems.buyButton = createElement("button", {
@ -343,7 +344,7 @@ function createResleeveUi(resleeve: Resleeve): IResleeveUIElems {
clickListener: () => { clickListener: () => {
if(playerRef == null) throw new Error("playerRef is null in buyButton.click()"); if(playerRef == null) throw new Error("playerRef is null in buyButton.click()");
if (purchaseResleeve(resleeve, playerRef)) { if (purchaseResleeve(resleeve, playerRef)) {
dialogBoxCreate((<>You re-sleeved for {Money(cost)}!</>), false); dialogBoxCreate((<>You re-sleeved for <Money money={cost} />!</>), false);
} else { } else {
dialogBoxCreate(`You cannot afford to re-sleeve into this body`, false); dialogBoxCreate(`You cannot afford to re-sleeve into this body`, false);
} }

@ -2,6 +2,7 @@
* Module for handling the UI for purchasing Sleeve Augmentations * Module for handling the UI for purchasing Sleeve Augmentations
* This UI is a popup, not a full page * This UI is a popup, not a full page
*/ */
import React from 'react';
import { Sleeve } from "./Sleeve"; import { Sleeve } from "./Sleeve";
import { findSleevePurchasableAugs } from "./SleeveHelpers"; import { findSleevePurchasableAugs } from "./SleeveHelpers";
@ -102,7 +103,7 @@ export function createSleevePurchaseAugsPopup(sleeve: Sleeve, p: IPlayer): void
innerHTML: innerHTML:
[ [
`<h2>${aug.name}</h2><br>`, `<h2>${aug.name}</h2><br>`,
`Cost: ${renderToStaticMarkup(Money(aug.startingCost))}<br><br>`, `Cost: ${renderToStaticMarkup(<Money money={aug.startingCost} player={p} />)}<br><br>`,
`${info}`, `${info}`,
].join(" "), ].join(" "),
padding: "2px", padding: "2px",

@ -1,6 +1,7 @@
/** /**
* Module for handling the Sleeve UI * Module for handling the Sleeve UI
*/ */
import React from 'react';
import { createSleevePurchaseAugsPopup } from "./SleeveAugmentationsUI"; import { createSleevePurchaseAugsPopup } from "./SleeveAugmentationsUI";
import { Sleeve } from "./Sleeve"; import { Sleeve } from "./Sleeve";
import { SleeveTaskType } from "./SleeveTaskTypesEnum"; import { SleeveTaskType } from "./SleeveTaskTypesEnum";
@ -202,6 +203,7 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
currentEarningsInfo: null, currentEarningsInfo: null,
totalEarningsButton: null, totalEarningsButton: null,
} }
if(playerRef === null) return elems;
if (!routing.isOn(Page.Sleeves)) { return elems; } if (!routing.isOn(Page.Sleeves)) { return elems; }
@ -223,13 +225,14 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
class: "std-button", class: "std-button",
innerText: "Travel", innerText: "Travel",
clickListener: () => { clickListener: () => {
if(playerRef === null) return;
const popupId = "sleeve-travel-popup"; const popupId = "sleeve-travel-popup";
const popupArguments: HTMLElement[] = []; const popupArguments: HTMLElement[] = [];
popupArguments.push(createPopupCloseButton(popupId, { class: "std-button" })); popupArguments.push(createPopupCloseButton(popupId, { class: "std-button" }));
popupArguments.push(createElement("p", { popupArguments.push(createElement("p", {
innerHTML: "Have this sleeve travel to a different city. This affects " + innerHTML: "Have this sleeve travel to a different city. This affects " +
"the gyms and universities at which this sleeve can study. " + "the gyms and universities at which this sleeve can study. " +
`Traveling to a different city costs ${renderToStaticMarkup(Money(CONSTANTS.TravelCost))}. ` + `Traveling to a different city costs ${renderToStaticMarkup(<Money money={CONSTANTS.TravelCost} player={playerRef} />)}. ` +
"It will also CANCEL the sleeve's current task (setting it to idle)", "It will also CANCEL the sleeve's current task (setting it to idle)",
})); }));
for (const cityName in Cities) { for (const cityName in Cities) {
@ -346,7 +349,7 @@ function updateSleeveUi(sleeve: Sleeve, elems: ISleeveUIElems): void {
if (sleeve.currentTask === SleeveTaskType.Crime) { if (sleeve.currentTask === SleeveTaskType.Crime) {
const data = [ const data = [
[`Money`, Money(parseFloat(sleeve.currentTaskLocation)), `(on success)`], [`Money`, <Money money={parseFloat(sleeve.currentTaskLocation)} />, `(on success)`],
[`Hacking Exp`, numeralWrapper.formatExp(sleeve.gainRatesForTask.hack), `(2x on success)`], [`Hacking Exp`, numeralWrapper.formatExp(sleeve.gainRatesForTask.hack), `(2x on success)`],
[`Strength Exp`, numeralWrapper.formatExp(sleeve.gainRatesForTask.str), `(2x on success)`], [`Strength Exp`, numeralWrapper.formatExp(sleeve.gainRatesForTask.str), `(2x on success)`],
[`Defense Exp`, numeralWrapper.formatExp(sleeve.gainRatesForTask.def), `(2x on success)`], [`Defense Exp`, numeralWrapper.formatExp(sleeve.gainRatesForTask.def), `(2x on success)`],

@ -75,7 +75,7 @@ export function CovenantPurchasesRoot(props: IProps): React.ReactElement {
<PopupCloseButton popup={PopupId} text={"Close"} /> <PopupCloseButton popup={PopupId} text={"Close"} />
<p> <p>
Would you like to purchase an additional Duplicate Sleeve from The Covenant Would you like to purchase an additional Duplicate Sleeve from The Covenant
for {Money(purchaseCost())}? for <Money money={purchaseCost()} player={props.p} />?
</p> </p>
<br /> <br />
<p> <p>

@ -79,7 +79,7 @@ export class CovenantSleeveMemoryUpgrade extends React.Component<IProps, IState>
} else if (this.state.amt > maxMemory) { } else if (this.state.amt > maxMemory) {
purchaseBtnContent = <>Memory cannot exceed 100?</>; purchaseBtnContent = <>Memory cannot exceed 100?</>;
} else { } else {
purchaseBtnContent = <>Purchase {this.state.amt} memory - {Money(cost)}?</>; purchaseBtnContent = <>Purchase {this.state.amt} memory - <Money money={cost} player={this.props.p} />?</>;
} }
return ( return (

@ -7,7 +7,7 @@ import { StatsTable } from "../../../ui/React/StatsTable";
export function MoreEarningsContent(sleeve: Sleeve): React.ReactElement { export function MoreEarningsContent(sleeve: Sleeve): React.ReactElement {
return (<> return (<>
{StatsTable([ {StatsTable([
['Money ', Money(sleeve.earningsForTask.money)], ['Money ', <Money money={sleeve.earningsForTask.money} />],
['Hacking Exp ', numeralWrapper.formatExp(sleeve.earningsForTask.hack)], ['Hacking Exp ', numeralWrapper.formatExp(sleeve.earningsForTask.hack)],
['Strength Exp ', numeralWrapper.formatExp(sleeve.earningsForTask.str)], ['Strength Exp ', numeralWrapper.formatExp(sleeve.earningsForTask.str)],
['Defense Exp ', numeralWrapper.formatExp(sleeve.earningsForTask.def)], ['Defense Exp ', numeralWrapper.formatExp(sleeve.earningsForTask.def)],
@ -17,7 +17,7 @@ export function MoreEarningsContent(sleeve: Sleeve): React.ReactElement {
], 'Earnings for Current Task:')} ], 'Earnings for Current Task:')}
<br /> <br />
{StatsTable([ {StatsTable([
['Money: ', Money(sleeve.earningsForPlayer.money)], ['Money: ', <Money money={sleeve.earningsForPlayer.money} />],
['Hacking Exp: ', numeralWrapper.formatExp(sleeve.earningsForPlayer.hack)], ['Hacking Exp: ', numeralWrapper.formatExp(sleeve.earningsForPlayer.hack)],
['Strength Exp: ', numeralWrapper.formatExp(sleeve.earningsForPlayer.str)], ['Strength Exp: ', numeralWrapper.formatExp(sleeve.earningsForPlayer.str)],
['Defense Exp: ', numeralWrapper.formatExp(sleeve.earningsForPlayer.def)], ['Defense Exp: ', numeralWrapper.formatExp(sleeve.earningsForPlayer.def)],
@ -27,7 +27,7 @@ export function MoreEarningsContent(sleeve: Sleeve): React.ReactElement {
], 'Total Earnings for Host Consciousness:')} ], 'Total Earnings for Host Consciousness:')}
<br /> <br />
{StatsTable([ {StatsTable([
['Money: ', Money(sleeve.earningsForSleeves.money)], ['Money: ', <Money money={sleeve.earningsForSleeves.money} />],
['Hacking Exp: ', numeralWrapper.formatExp(sleeve.earningsForSleeves.hack)], ['Hacking Exp: ', numeralWrapper.formatExp(sleeve.earningsForSleeves.hack)],
['Strength Exp: ', numeralWrapper.formatExp(sleeve.earningsForSleeves.str)], ['Strength Exp: ', numeralWrapper.formatExp(sleeve.earningsForSleeves.str)],
['Defense Exp: ', numeralWrapper.formatExp(sleeve.earningsForSleeves.def)], ['Defense Exp: ', numeralWrapper.formatExp(sleeve.earningsForSleeves.def)],

@ -96,7 +96,8 @@ export function purchaseServer(ram: number, p: IPlayer): void {
} }
// Manually upgrade RAM on home computer (NOT through Netscript) // Manually upgrade RAM on home computer (NOT through Netscript)
export function purchaseRamForHomeComputer(cost: number, p: IPlayer): void { export function purchaseRamForHomeComputer(p: IPlayer): void {
const cost = p.getUpgradeHomeRamCost();
if (!p.canAfford(cost)) { if (!p.canAfford(cost)) {
dialogBoxCreate("You do not have enough money to purchase additional RAM for your home computer"); dialogBoxCreate("You do not have enough money to purchase additional RAM for your home computer");
return; return;
@ -111,6 +112,4 @@ export function purchaseRamForHomeComputer(cost: number, p: IPlayer): void {
homeComputer.maxRam *= 2; homeComputer.maxRam *= 2;
p.loseMoney(cost); p.loseMoney(cost);
dialogBoxCreate("Purchased additional RAM for home computer! It now has " + homeComputer.maxRam + "GB of RAM.");
} }

@ -60,7 +60,7 @@ export function buyStock(stock: Stock, shares: number, workerScript: WorkerScrip
if (workerScript) { if (workerScript) {
workerScript.log("buyStock", `You do not have enough money to purchase this position. You need ${numeralWrapper.formatMoney(totalPrice)}.`); workerScript.log("buyStock", `You do not have enough money to purchase this position. You need ${numeralWrapper.formatMoney(totalPrice)}.`);
} else if (opts.suppressDialog !== true) { } else if (opts.suppressDialog !== true) {
dialogBoxCreate(<>You do not have enough money to purchase this. You need {Money(totalPrice)}</>); dialogBoxCreate(<>You do not have enough money to purchase this. You need <Money money={totalPrice} /></>);
} }
return false; return false;
@ -92,7 +92,7 @@ export function buyStock(stock: Stock, shares: number, workerScript: WorkerScrip
`Paid ${numeralWrapper.formatMoney(CONSTANTS.StockMarketCommission)} in commission fees.` `Paid ${numeralWrapper.formatMoney(CONSTANTS.StockMarketCommission)} in commission fees.`
workerScript.log("buyStock", resultTxt) workerScript.log("buyStock", resultTxt)
} else if (opts.suppressDialog !== true) { } else if (opts.suppressDialog !== true) {
dialogBoxCreate(<>Bought {numeralWrapper.formatShares(shares)} shares of {stock.symbol} for {Money(totalPrice)}. Paid {Money(CONSTANTS.StockMarketCommission)} in commission fees.</>); dialogBoxCreate(<>Bought {numeralWrapper.formatShares(shares)} shares of {stock.symbol} for <Money money={totalPrice} />. Paid <Money money={CONSTANTS.StockMarketCommission} /> in commission fees.</>);
} }
return true; return true;
@ -150,7 +150,7 @@ export function sellStock(stock: Stock, shares: number, workerScript: WorkerScri
`After commissions, you gained a total of ${numeralWrapper.formatMoney(gains)}.`; `After commissions, you gained a total of ${numeralWrapper.formatMoney(gains)}.`;
workerScript.log("sellStock", resultTxt) workerScript.log("sellStock", resultTxt)
} else if (opts.suppressDialog !== true) { } else if (opts.suppressDialog !== true) {
dialogBoxCreate(<>Sold {numeralWrapper.formatShares(shares)} shares of {stock.symbol}. After commissions, you gained a total of {Money(gains)}.</>); dialogBoxCreate(<>Sold {numeralWrapper.formatShares(shares)} shares of {stock.symbol}. After commissions, you gained a total of <Money money={gains} />.</>);
} }
return true; return true;
@ -188,7 +188,7 @@ export function shortStock(stock: Stock, shares: number, workerScript: WorkerScr
"money to purchase this short position. You need " + "money to purchase this short position. You need " +
numeralWrapper.formatMoney(totalPrice)); numeralWrapper.formatMoney(totalPrice));
} else if (opts.suppressDialog !== true) { } else if (opts.suppressDialog !== true) {
dialogBoxCreate(<>You do not have enough money to purchase this short position. You need {Money(totalPrice)}</>); dialogBoxCreate(<>You do not have enough money to purchase this short position. You need <Money money={totalPrice} /></>);
} }
return false; return false;
@ -222,7 +222,7 @@ export function shortStock(stock: Stock, shares: number, workerScript: WorkerScr
`in commission fees.`; `in commission fees.`;
workerScript.log("shortStock", resultTxt); workerScript.log("shortStock", resultTxt);
} else if (!opts.suppressDialog) { } else if (!opts.suppressDialog) {
dialogBoxCreate(<>Bought a short position of {numeralWrapper.formatShares(shares)} shares of {stock.symbol} for {Money(totalPrice)}. Paid {Money(CONSTANTS.StockMarketCommission)} in commission fees.</>); dialogBoxCreate(<>Bought a short position of {numeralWrapper.formatShares(shares)} shares of {stock.symbol} for <Money money={totalPrice} />. Paid <Money money={CONSTANTS.StockMarketCommission} /> in commission fees.</>);
} }
return true; return true;
@ -287,7 +287,7 @@ export function sellShort(stock: Stock, shares: number, workerScript: WorkerScri
`After commissions, you gained a total of ${numeralWrapper.formatMoney(totalGain)}`; `After commissions, you gained a total of ${numeralWrapper.formatMoney(totalGain)}`;
workerScript.log("sellShort", resultTxt); workerScript.log("sellShort", resultTxt);
} else if (!opts.suppressDialog) { } else if (!opts.suppressDialog) {
dialogBoxCreate(<>Sold your short position of {numeralWrapper.formatShares(shares)} shares of {stock.symbol}. After commissions, you gained a total of {Money(totalGain)}</>); dialogBoxCreate(<>Sold your short position of {numeralWrapper.formatShares(shares)} shares of {stock.symbol}. After commissions, you gained a total of <Money money={totalGain} /></>);
} }
return true; return true;

@ -150,7 +150,7 @@ function executeOrder(order: Order, refs: IProcessOrderRefs): void {
for (let i = 0; i < stockOrders.length; ++i) { for (let i = 0; i < stockOrders.length; ++i) {
if (order == stockOrders[i]) { if (order == stockOrders[i]) {
stockOrders.splice(i, 1); stockOrders.splice(i, 1);
dialogBoxCreate(<>{order.type} for {stock.symbol} @ {Money(order.price)} ({pos}) was filled ({numeralWrapper.formatShares(Math.round(order.shares))} shares)</>); dialogBoxCreate(<>{order.type} for {stock.symbol} @ <Money money={order.price} /> ({pos}) was filled ({numeralWrapper.formatShares(Math.round(order.shares))} shares)</>);
refs.rerenderFn(); refs.rerenderFn();
return; return;
} }
@ -160,7 +160,7 @@ function executeOrder(order: Order, refs: IProcessOrderRefs): void {
console.error(order); console.error(order);
} else { } else {
if (isBuy) { if (isBuy) {
dialogBoxCreate(<>Failed to execute {order.type} for {stock.symbol} @ {Money(order.price)} ({pos}). This is most likely because you do not have enough money or the order would exceed the stock's maximum number of shares</>); dialogBoxCreate(<>Failed to execute {order.type} for {stock.symbol} @ <Money money={order.price} /> ({pos}). This is most likely because you do not have enough money or the order would exceed the stock's maximum number of shares</>);
} }
} }
} }

@ -107,7 +107,7 @@ export class InfoAndPurchases extends React.Component<IProps, any> {
<StdButton <StdButton
disabled={!this.props.p.canAfford(cost)} disabled={!this.props.p.canAfford(cost)}
onClick={this.purchaseWseAccount} onClick={this.purchaseWseAccount}
text={<>Buy WSE Account - {Money(cost)}</>} text={<>Buy WSE Account - <Money money={cost} player={this.props.p} /></>}
/> />
) )
} }
@ -125,7 +125,7 @@ export class InfoAndPurchases extends React.Component<IProps, any> {
disabled={!this.props.p.canAfford(cost) || !this.props.p.hasWseAccount} disabled={!this.props.p.canAfford(cost) || !this.props.p.hasWseAccount}
onClick={this.purchaseTixApiAccess} onClick={this.purchaseTixApiAccess}
style={blockStyleMarkup} style={blockStyleMarkup}
text={<>Buy Trade Information eXchange (TIX) API Access - {Money(cost)}</>} text={<>Buy Trade Information eXchange (TIX) API Access - <Money money={cost} player={this.props.p} /></>}
/> />
) )
} }
@ -145,7 +145,7 @@ export class InfoAndPurchases extends React.Component<IProps, any> {
<StdButton <StdButton
disabled={!this.props.p.canAfford(cost) || !this.props.p.hasWseAccount} disabled={!this.props.p.canAfford(cost) || !this.props.p.hasWseAccount}
onClick={this.purchase4SMarketData} onClick={this.purchase4SMarketData}
text={<>Buy 4S Market Data Access - {Money(cost)}</>} text={<>Buy 4S Market Data Access - <Money money={cost} player={this.props.p} /></>}
tooltip={"Lets you view additional pricing and volatility information about stocks"} tooltip={"Lets you view additional pricing and volatility information about stocks"}
/> />
) )
@ -174,7 +174,7 @@ export class InfoAndPurchases extends React.Component<IProps, any> {
<StdButton <StdButton
disabled={!this.props.p.canAfford(cost)} disabled={!this.props.p.canAfford(cost)}
onClick={this.purchase4SMarketDataTixApiAccess} onClick={this.purchase4SMarketDataTixApiAccess}
text={<>Buy 4S Market Data TIX API Access - {Money(cost)}</>} text={<>Buy 4S Market Data TIX API Access - <Money money={cost} player={this.props.p} /></>}
tooltip={"Let you access 4S Market Data through Netscript"} tooltip={"Let you access 4S Market Data through Netscript"}
/> />
) )
@ -216,7 +216,7 @@ export class InfoAndPurchases extends React.Component<IProps, any> {
{this.renderPurchase4SMarketDataTixApiAccessButton()} {this.renderPurchase4SMarketDataTixApiAccessButton()}
<p> <p>
Commission Fees: Every transaction you make has Commission Fees: Every transaction you make has
a {Money(CONSTANTS.StockMarketCommission)} commission fee. a <Money money={CONSTANTS.StockMarketCommission} player={this.props.p} /> commission fee.
</p><br /> </p><br />
<p> <p>
WARNING: When you reset after installing Augmentations, the Stock WARNING: When you reset after installing Augmentations, the Stock

@ -115,7 +115,7 @@ export class StockTicker extends React.Component<IProps, IState> {
const cost = getBuyTransactionCost(stock, qty, this.state.position); const cost = getBuyTransactionCost(stock, qty, this.state.position);
if (cost == null) { return null; } if (cost == null) { return null; }
return <>Purchasing {numeralWrapper.formatShares(qty)} shares ({this.state.position === PositionTypes.Long ? "Long" : "Short"}) will cost {Money(cost)}.</>; return <>Purchasing {numeralWrapper.formatShares(qty)} shares ({this.state.position === PositionTypes.Long ? "Long" : "Short"}) will cost <Money money={cost} />.</>;
} }
getQuantity(): number { getQuantity(): number {
@ -140,7 +140,7 @@ export class StockTicker extends React.Component<IProps, IState> {
const cost = getSellTransactionGain(stock, qty, this.state.position); const cost = getSellTransactionGain(stock, qty, this.state.position);
if (cost == null) { return null; } if (cost == null) { return null; }
return <>Selling {numeralWrapper.formatShares(qty)} shares ({this.state.position === PositionTypes.Long ? "Long" : "Short"}) will result in a gain of {Money(cost)}.</>; return <>Selling {numeralWrapper.formatShares(qty)} shares ({this.state.position === PositionTypes.Long ? "Long" : "Short"}) will result in a gain of <Money money={cost} />.</>;
} }
handleBuyButtonClick(): void { handleBuyButtonClick(): void {

@ -29,7 +29,7 @@ export class StockTickerOrder extends React.Component<IProps, any> {
const order = this.props.order; const order = this.props.order;
const posTxt = order.pos === PositionTypes.Long ? "Long Position" : "Short Position"; const posTxt = order.pos === PositionTypes.Long ? "Long Position" : "Short Position";
const txt = <>{order.type} - {posTxt} - {numeralWrapper.formatShares(order.shares)} @ {Money(order.price)}</> const txt = <>{order.type} - {posTxt} - {numeralWrapper.formatShares(order.shares)} @ <Money money={order.price} /></>
return ( return (
<li> <li>

@ -43,10 +43,10 @@ export class StockTickerPositionText extends React.Component<IProps, any> {
Shares: {numeralWrapper.formatShares(stock.playerShares)} Shares: {numeralWrapper.formatShares(stock.playerShares)}
</p><br /> </p><br />
<p> <p>
Average Price: {Money(stock.playerAvgPx)} (Total Cost: {Money(totalCost)}) Average Price: <Money money={stock.playerAvgPx} /> (Total Cost: <Money money={totalCost} />
</p><br /> </p><br />
<p> <p>
Profit: {Money(gains)} ({numeralWrapper.formatPercentage(percentageGains)}) Profit: <Money money={gains} /> ({numeralWrapper.formatPercentage(percentageGains)})
</p><br /> </p><br />
</div> </div>
) )
@ -75,10 +75,10 @@ export class StockTickerPositionText extends React.Component<IProps, any> {
Shares: {numeralWrapper.formatShares(stock.playerShortShares)} Shares: {numeralWrapper.formatShares(stock.playerShortShares)}
</p><br /> </p><br />
<p> <p>
Average Price: {Money(stock.playerAvgShortPx)} (Total Cost: {Money(totalCost)}) Average Price: <Money money={stock.playerAvgShortPx} /> (Total Cost: <Money money={totalCost} />)
</p><br /> </p><br />
<p> <p>
Profit: {Money(gains)} ({numeralWrapper.formatPercentage(percentageGains)}) Profit: <Money money={gains} /> ({numeralWrapper.formatPercentage(percentageGains)})
</p><br /> </p><br />
</div> </div>
) )
@ -96,13 +96,13 @@ export class StockTickerPositionText extends React.Component<IProps, any> {
Max Shares: {numeralWrapper.formatShares(stock.maxShares)} Max Shares: {numeralWrapper.formatShares(stock.maxShares)}
</p> </p>
<p className={"tooltip"} > <p className={"tooltip"} >
Ask Price: {Money(stock.getAskPrice())} Ask Price: <Money money={stock.getAskPrice()} />
<span className={"tooltiptext"}> <span className={"tooltiptext"}>
See Investopedia for details on what this is See Investopedia for details on what this is
</span> </span>
</p><br /> </p><br />
<p className={"tooltip"} > <p className={"tooltip"} >
Bid Price: {Money(stock.getBidPrice())} Bid Price: <Money money={stock.getBidPrice()} />
<span className={"tooltiptext"}> <span className={"tooltiptext"}>
See Investopedia for details on what this is See Investopedia for details on what this is
</span> </span>

@ -555,7 +555,7 @@ let Terminal = {
server.fortify(CONSTANTS.ServerFortifyAmount); server.fortify(CONSTANTS.ServerFortifyAmount);
postElement(<>Hack successful! Gained {Money(moneyGained)} and {numeralWrapper.formatExp(expGainedOnSuccess)} hacking exp</>); postElement(<>Hack successful! Gained <Money money={moneyGained} /> and {numeralWrapper.formatExp(expGainedOnSuccess)} hacking exp</>);
} else { // Failure } else { // Failure
// Player only gains 25% exp for failure? TODO Can change this later to balance // Player only gains 25% exp for failure? TODO Can change this later to balance
Player.gainHackingExp(expGainedOnFailure) Player.gainHackingExp(expGainedOnFailure)
@ -600,7 +600,7 @@ let Terminal = {
post("Chance to hack: " + (!isHacknet ? numeralWrapper.formatPercentage(hackingChance) : "N/A")); post("Chance to hack: " + (!isHacknet ? numeralWrapper.formatPercentage(hackingChance) : "N/A"));
const hackingTime = calculateHackingTime(currServ, Player)*1000; const hackingTime = calculateHackingTime(currServ, Player)*1000;
post("Time to hack: " + (!isHacknet ? convertTimeMsToTimeElapsedString(hackingTime, true) : "N/A")); post("Time to hack: " + (!isHacknet ? convertTimeMsToTimeElapsedString(hackingTime, true) : "N/A"));
postElement(<>Total money available on server: {!isHacknet ? Money(currServ.moneyAvailable) : "N/A"}</>); postElement(<>Total money available on server: {!isHacknet ? <Money money={currServ.moneyAvailable} /> : "N/A"}</>);
const numPort = currServ.numOpenPortsRequired; const numPort = currServ.numOpenPortsRequired;
post("Required number of open ports for NUKE: " + (!isHacknet ? numPort : "N/A")); post("Required number of open ports for NUKE: " + (!isHacknet ? numPort : "N/A"));
post("SSH port: "+ (currServ.sshPortOpen ? "Open" : "Closed")) post("SSH port: "+ (currServ.sshPortOpen ? "Open" : "Closed"))
@ -2242,7 +2242,7 @@ let Terminal = {
Player.hacking_skill >= 2500; Player.hacking_skill >= 2500;
if(!fulfilled) { if(!fulfilled) {
post(`Augmentations: ${Player.augmentations.length} / ${numAugReq}`); post(`Augmentations: ${Player.augmentations.length} / ${numAugReq}`);
postElement(<>Money: {Money(Player.money.toNumber())} / {Money(1e11)}</>); postElement(<>Money: <Money money={Player.money.toNumber()} /> / <Money money={1e11} /></>);
post(`Hacking skill: ${Player.hacking_skill} / 2500`); post(`Hacking skill: ${Player.hacking_skill} / 2500`);
return; return;
} }

@ -1059,7 +1059,7 @@ const Engine = {
var offlineProductionFromHacknetNodes = processHacknetEarnings(numCyclesOffline); var offlineProductionFromHacknetNodes = processHacknetEarnings(numCyclesOffline);
const hacknetProdInfo = hasHacknetServers() ? const hacknetProdInfo = hasHacknetServers() ?
<>{Hashes(offlineProductionFromHacknetNodes)} hashes</>: <>{Hashes(offlineProductionFromHacknetNodes)} hashes</>:
Money(offlineProductionFromHacknetNodes); <Money money={offlineProductionFromHacknetNodes} />;
// Passive faction rep gain offline // Passive faction rep gain offline
processPassiveFactionRepGain(numCyclesOffline); processPassiveFactionRepGain(numCyclesOffline);
@ -1113,7 +1113,7 @@ const Engine = {
const timeOfflineString = convertTimeMsToTimeElapsedString(time); const timeOfflineString = convertTimeMsToTimeElapsedString(time);
dialogBoxCreate(<> dialogBoxCreate(<>
Offline for {timeOfflineString}. While you were offline, your scripts Offline for {timeOfflineString}. While you were offline, your scripts
generated {Money(offlineHackingIncome)}, your Hacknet Nodes generated <Money money={offlineHackingIncome} />, your Hacknet Nodes
generated {hacknetProdInfo} and you generated {hacknetProdInfo} and you
gained {Reputation(offlineReputation)} divided amongst your factions. gained {Reputation(offlineReputation)} divided amongst your factions.
</>); </>);

@ -26,18 +26,18 @@ export function ScriptProduction(props: IProps): React.ReactElement {
Total online production of Active scripts:&nbsp; Total online production of Active scripts:&nbsp;
<span className="money-gold"> <span className="money-gold">
<span id="active-scripts-total-production-active"> <span id="active-scripts-total-production-active">
{Money(onlineProduction)} <Money money={onlineProduction} />
</span> / sec </span> / sec
</span><br /> </span><br />
Total online production since last Aug installation:&nbsp; Total online production since last Aug installation:&nbsp;
<span id="active-scripts-total-prod-aug-total" className="money-gold"> <span id="active-scripts-total-prod-aug-total" className="money-gold">
{Money(props.p.scriptProdSinceLastAug)} <Money money={props.p.scriptProdSinceLastAug} />
</span> </span>
&nbsp;(<span className="money-gold"> &nbsp;(<span className="money-gold">
<span id="active-scripts-total-prod-aug-avg" className="money-gold"> <span id="active-scripts-total-prod-aug-avg" className="money-gold">
{Money(prodRateSinceLastAug)} <Money money={prodRateSinceLastAug} />
</span> / sec </span> / sec
</span>) </span>)
</p> </p>

@ -53,13 +53,13 @@ export function WorkerScriptAccordion(props: IProps): React.ReactElement {
<pre>Args: {arrayToString(props.workerScript.args)}</pre> <pre>Args: {arrayToString(props.workerScript.args)}</pre>
<pre>Online Time: {convertTimeMsToTimeElapsedString(scriptRef.onlineRunningTime * 1e3)}</pre> <pre>Online Time: {convertTimeMsToTimeElapsedString(scriptRef.onlineRunningTime * 1e3)}</pre>
<pre>Offline Time: {convertTimeMsToTimeElapsedString(scriptRef.offlineRunningTime * 1e3)}</pre> <pre>Offline Time: {convertTimeMsToTimeElapsedString(scriptRef.offlineRunningTime * 1e3)}</pre>
<pre>Total online production: {Money(scriptRef.onlineMoneyMade)}</pre> <pre>Total online production: <Money money={scriptRef.onlineMoneyMade} /></pre>
<pre>{(Array(26).join(" ") + numeralWrapper.formatExp(scriptRef.onlineExpGained) + " hacking exp")}</pre> <pre>{(Array(26).join(" ") + numeralWrapper.formatExp(scriptRef.onlineExpGained) + " hacking exp")}</pre>
<pre>Online production rate: {Money(onlineMps)} / second</pre> <pre>Online production rate: <Money money={onlineMps} /> / second</pre>
<pre>{(Array(25).join(" ") + numeralWrapper.formatExp(onlineEps) + " hacking exp / second")}</pre> <pre>{(Array(25).join(" ") + numeralWrapper.formatExp(onlineEps) + " hacking exp / second")}</pre>
<pre>Total offline production: {Money(scriptRef.offlineMoneyMade)}</pre> <pre>Total offline production: <Money money={scriptRef.offlineMoneyMade} /></pre>
<pre>{(Array(27).join(" ") + numeralWrapper.formatExp(scriptRef.offlineExpGained) + " hacking exp")}</pre> <pre>{(Array(27).join(" ") + numeralWrapper.formatExp(scriptRef.offlineExpGained) + " hacking exp")}</pre>
<pre>Offline production rate: {Money(offlineMps)} / second</pre> <pre>Offline production rate: <Money money={offlineMps} /> / second</pre>
<pre>{(Array(26).join(" ") + numeralWrapper.formatExp(offlineEps) + " hacking exp / second")}</pre> <pre>{(Array(26).join(" ") + numeralWrapper.formatExp(offlineEps) + " hacking exp / second")}</pre>
<AccordionButton <AccordionButton

@ -47,21 +47,21 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
} }
function convertMoneySourceTrackerToString(src: MoneySourceTracker): React.ReactElement { function convertMoneySourceTrackerToString(src: MoneySourceTracker): React.ReactElement {
const parts: any[][] = [[`Total:`, Money(src.total)]]; const parts: any[][] = [[`Total:`, <Money money={src.total} />]];
if (src.bladeburner) { parts.push([`Bladeburner:`, Money(src.bladeburner)]) } if (src.bladeburner) { parts.push([`Bladeburner:`, <Money money={src.bladeburner} />]) }
if (src.codingcontract) { parts.push([`Coding Contracts:`, Money(src.codingcontract)]) } if (src.codingcontract) { parts.push([`Coding Contracts:`, <Money money={src.codingcontract} />]) }
if (src.work) { parts.push([`Company Work:`, Money(src.work)]) } if (src.work) { parts.push([`Company Work:`, <Money money={src.work} />]) }
if (src.class) { parts.push([`Class:`, Money(src.class)]) } if (src.class) { parts.push([`Class:`, <Money money={src.class} />]) }
if (src.corporation) { parts.push([`Corporation:`, Money(src.corporation)]) } if (src.corporation) { parts.push([`Corporation:`, <Money money={src.corporation} />]) }
if (src.crime) { parts.push([`Crimes:`, Money(src.crime)]) } if (src.crime) { parts.push([`Crimes:`, <Money money={src.crime} />]) }
if (src.gang) { parts.push([`Gang:`, Money(src.gang)]) } if (src.gang) { parts.push([`Gang:`, <Money money={src.gang} />]) }
if (src.hacking) { parts.push([`Hacking:`, Money(src.hacking)]) } if (src.hacking) { parts.push([`Hacking:`, <Money money={src.hacking} />]) }
if (src.hacknetnode) { parts.push([`Hacknet Nodes:`, Money(src.hacknetnode)]) } if (src.hacknetnode) { parts.push([`Hacknet Nodes:`, <Money money={src.hacknetnode} />]) }
if (src.hospitalization) { parts.push([`Hospitalization:`, Money(src.hospitalization)]) } if (src.hospitalization) { parts.push([`Hospitalization:`, <Money money={src.hospitalization} />]) }
if (src.infiltration) { parts.push([`Infiltration:`, Money(src.infiltration)]) } if (src.infiltration) { parts.push([`Infiltration:`, <Money money={src.infiltration} />]) }
if (src.stock) { parts.push([`Stock Market:`, Money(src.stock)]) } if (src.stock) { parts.push([`Stock Market:`, <Money money={src.stock} />]) }
if (src.casino) { parts.push([`Casino:`, Money(src.casino)]) } if (src.casino) { parts.push([`Casino:`, <Money money={src.casino} />]) }
if (src.sleeves) { parts.push([`Sleeves:`, Money(src.sleeves)]) } if (src.sleeves) { parts.push([`Sleeves:`, <Money money={src.sleeves} />]) }
return StatsTable(parts); return StatsTable(parts);
} }
@ -154,7 +154,7 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
<LastEmployer /> <LastEmployer />
<LastJob /> <LastJob />
<Employers /> <Employers />
<span>Money: {Money(p.money.toNumber())}</span> <span>Money: <Money money={p.money.toNumber()} /></span>
<button className="popup-box-button" style={{display: 'inline-block', float: 'none'}} onClick={openMoneyModal}>Money Statistics & Breakdown</button><br /><br /> <button className="popup-box-button" style={{display: 'inline-block', float: 'none'}} onClick={openMoneyModal}>Money Statistics & Breakdown</button><br /><br />
<b>Stats</b> <b>Stats</b>
<table> <table>

@ -58,13 +58,13 @@ export class AutoupdatingParagraph extends React.Component<IProps, IState> {
render(): React.ReactNode { render(): React.ReactNode {
return ( return (
<p className="tooltip" style={this.props.style}> <div className="tooltip" style={this.props.style}>
{this.props.getContent()} <p>{this.props.getContent()}</p>
{ {
this.hasTooltip() && this.hasTooltip() &&
<span className={"tooltiptext"}>{this.tooltip()}</span> <span className={"tooltiptext"}>{this.tooltip()}</span>
} }
</p> </div>
) )
} }
} }

@ -1,6 +1,16 @@
import * as React from "react"; import * as React from "react";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { IPlayer } from "../../PersonObjects/IPlayer";
export function Money(money: number | string): JSX.Element { interface IProps {
return <span className={"money-gold samefont"}>{typeof money === 'number' ? numeralWrapper.formatMoney(money) : money}</span> money: number | string;
player?: IPlayer;
}
export function Money(props: IProps): JSX.Element {
if(props.player !== undefined) {
if(typeof props.money !== 'number') throw new Error('if player if provided, money should be number, contact dev');
if(!props.player.canAfford(props.money))
return <span className={"unbuyable samefont"}>{numeralWrapper.formatMoney(props.money)}</span>
}
return <span className={"money-gold samefont"}>{typeof props.money === 'number' ? numeralWrapper.formatMoney(props.money) : props.money}</span>
} }

@ -1,6 +1,7 @@
import React from 'react';
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { Money } from "../../ui/React/Money"; import { Money } from "../../ui/React/Money";
export function MoneyRate(money: number): JSX.Element { export function MoneyRate(money: number): JSX.Element {
return Money(`${numeralWrapper.formatMoney(money)} / sec`); return <Money money={`${numeralWrapper.formatMoney(money)} / sec`} />;
} }