unify the way engine loads pages

This commit is contained in:
Olivier Gagnon 2021-09-10 15:08:51 -04:00
parent c9611cc824
commit b45ab657c5
5 changed files with 157 additions and 115 deletions

@ -20,7 +20,8 @@ function ExpandButton(props: IExpandButtonProps): React.ReactElement {
const allIndustries = Object.keys(Industries).sort(); const allIndustries = Object.keys(Industries).sort();
const possibleIndustries = allIndustries const possibleIndustries = allIndustries
.filter( .filter(
(industryType: string) => props.corp.divisions.find((division: IIndustry) => division.type === industryType) === undefined, (industryType: string) =>
props.corp.divisions.find((division: IIndustry) => division.type === industryType) === undefined,
) )
.sort(); .sort();
if (possibleIndustries.length === 0) return <></>; if (possibleIndustries.length === 0) return <></>;
@ -50,7 +51,7 @@ export function CorporationRoot(props: IProps): React.ReactElement {
const [divisionName, setDivisionName] = useState("Overview"); const [divisionName, setDivisionName] = useState("Overview");
useEffect(() => { useEffect(() => {
const id = setInterval(rerender, 150); const id = setInterval(rerender, 20);
return () => clearInterval(id); return () => clearInterval(id);
}, []); }, []);

@ -52,6 +52,7 @@ export function Overview(props: IProps): React.ReactElement {
} }
function openBribeFactionPopup(): void { function openBribeFactionPopup(): void {
console.log("hello click");
const popupId = "corp-bribe-popup"; const popupId = "corp-bribe-popup";
createPopup(popupId, BribeFactionPopup, { createPopup(popupId, BribeFactionPopup, {
player: props.player, player: props.player,

@ -218,7 +218,7 @@ const Engine = {
loadCharacterContent: function () { loadCharacterContent: function () {
Engine.hideAllContent(); Engine.hideAllContent();
Engine.Display.characterContent.style.display = "block"; Engine.Display.characterContent.style.display = "block";
Engine.updateCharacterInfo(); ReactDOM.render(<CharacterInfo player={Player} />, Engine.Display.characterInfo);
routing.navigateTo(Page.CharacterInfo); routing.navigateTo(Page.CharacterInfo);
MainMenuLinks.Stats.classList.add("active"); MainMenuLinks.Stats.classList.add("active");
}, },
@ -447,6 +447,8 @@ const Engine = {
hideAllContent: function () { hideAllContent: function () {
Engine.Display.terminalContent.style.display = "none"; Engine.Display.terminalContent.style.display = "none";
Engine.Display.characterContent.style.display = "none"; Engine.Display.characterContent.style.display = "none";
ReactDOM.unmountComponentAtNode(Engine.Display.characterContent);
Engine.Display.scriptEditorContent.style.display = "none"; Engine.Display.scriptEditorContent.style.display = "none";
ReactDOM.unmountComponentAtNode(Engine.Display.scriptEditorContent); ReactDOM.unmountComponentAtNode(Engine.Display.scriptEditorContent);
@ -540,11 +542,6 @@ const Engine = {
} }
}, },
/// Display character info
updateCharacterInfo: function () {
ReactDOM.render(CharacterInfo(Player), Engine.Display.characterInfo);
},
// Main Game Loop // Main Game Loop
idleTimer: function () { idleTimer: function () {
// Get time difference // Get time difference
@ -676,7 +673,6 @@ const Engine = {
autoSaveCounter: 300, autoSaveCounter: 300,
updateSkillLevelsCounter: 10, updateSkillLevelsCounter: 10,
updateDisplays: 3, updateDisplays: 3,
updateDisplaysMed: 9,
updateDisplaysLong: 15, updateDisplaysLong: 15,
updateActiveScriptsDisplay: 5, updateActiveScriptsDisplay: 5,
createProgramNotifications: 10, createProgramNotifications: 10,
@ -718,17 +714,6 @@ const Engine = {
Engine.Counters.updateSkillLevelsCounter = 10; Engine.Counters.updateSkillLevelsCounter = 10;
} }
if (Engine.Counters.updateActiveScriptsDisplay <= 0) {
if (routing.isOn(Page.ActiveScripts)) {
ReactDOM.render(
<ActiveScriptsRoot p={Player} workerScripts={workerScripts} />,
Engine.Display.activeScriptsContent,
);
}
Engine.Counters.updateActiveScriptsDisplay = 5;
}
if (Engine.Counters.updateDisplays <= 0) { if (Engine.Counters.updateDisplays <= 0) {
Engine.displayCharacterOverviewInfo(); Engine.displayCharacterOverviewInfo();
if (routing.isOn(Page.CreateProgram)) { if (routing.isOn(Page.CreateProgram)) {
@ -738,13 +723,6 @@ const Engine = {
Engine.Counters.updateDisplays = 3; Engine.Counters.updateDisplays = 3;
} }
if (Engine.Counters.updateDisplaysMed <= 0) {
if (routing.isOn(Page.CharacterInfo)) {
Engine.updateCharacterInfo();
}
Engine.Counters.updateDisplaysMed = 9;
}
if (Engine.Counters.createProgramNotifications <= 0) { if (Engine.Counters.createProgramNotifications <= 0) {
var num = getNumAvailableCreateProgram(); var num = getNumAvailableCreateProgram();
var elem = document.getElementById("create-program-notification"); var elem = document.getElementById("create-program-notification");

@ -2,7 +2,7 @@
* Root React Component for the "Active Scripts" UI page. This page displays * Root React Component for the "Active Scripts" UI page. This page displays
* and provides information about all of the player's scripts that are currently running * and provides information about all of the player's scripts that are currently running
*/ */
import * as React from "react"; import React, { useState, useEffect } from "react";
import { ScriptProduction } from "./ScriptProduction"; import { ScriptProduction } from "./ScriptProduction";
import { ServerAccordions } from "./ServerAccordions"; import { ServerAccordions } from "./ServerAccordions";
@ -15,23 +15,28 @@ type IProps = {
workerScripts: Map<number, WorkerScript>; workerScripts: Map<number, WorkerScript>;
}; };
export class ActiveScriptsRoot extends React.Component<IProps> { export function ActiveScriptsRoot(props: IProps): React.ReactElement {
constructor(props: IProps) { const setRerender = useState(false)[1];
super(props); function rerender(): void {
setRerender((old) => !old);
} }
const [divisionName, setDivisionName] = useState("Overview");
useEffect(() => {
const id = setInterval(rerender, 20);
return () => clearInterval(id);
}, []);
render(): React.ReactNode {
return ( return (
<> <>
<p> <p>
This page displays a list of all of your scripts that are currently running across every machine. It also This page displays a list of all of your scripts that are currently running across every machine. It also
provides information about each script's production. The scripts are categorized by the hostname of the provides information about each script's production. The scripts are categorized by the hostname of the servers
servers on which they are running. on which they are running.
</p> </p>
<ScriptProduction {...this.props} /> <ScriptProduction {...props} />
<ServerAccordions {...this.props} /> <ServerAccordions {...props} />
</> </>
); );
} }
}

@ -1,4 +1,4 @@
import * as React from "react"; import React, { useState, useEffect } from "react";
import { numeralWrapper } from "../ui/numeralFormat"; import { numeralWrapper } from "../ui/numeralFormat";
import { BitNodes } from "../BitNode/BitNode"; import { BitNodes } from "../BitNode/BitNode";
@ -13,12 +13,27 @@ import { HacknetServerConstants } from "../Hacknet/data/Constants";
import { StatsTable } from "./React/StatsTable"; import { StatsTable } from "./React/StatsTable";
import { Money } from "./React/Money"; import { Money } from "./React/Money";
export function CharacterInfo(p: IPlayer): React.ReactElement { interface IProps {
player: IPlayer;
}
export function CharacterInfo(props: IProps): React.ReactElement {
const setRerender = useState(false)[1];
function rerender(): void {
setRerender((old) => !old);
}
const [divisionName, setDivisionName] = useState("Overview");
useEffect(() => {
const id = setInterval(rerender, 20);
return () => clearInterval(id);
}, []);
function LastEmployer(): React.ReactElement { function LastEmployer(): React.ReactElement {
if (p.companyName) { if (props.player.companyName) {
return ( return (
<> <>
<span>Employer at which you last worked: {p.companyName}</span> <span>Employer at which you last worked: {props.player.companyName}</span>
<br /> <br />
</> </>
); );
@ -26,10 +41,10 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
return <></>; return <></>;
} }
function LastJob(): React.ReactElement { function LastJob(): React.ReactElement {
if (p.companyName !== "") { if (props.player.companyName !== "") {
return ( return (
<> <>
<span>Job you last worked: {p.jobs[p.companyName]}</span> <span>Job you last worked: {props.player.jobs[props.player.companyName]}</span>
<br /> <br />
</> </>
); );
@ -37,13 +52,13 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
return <></>; return <></>;
} }
function Employers(): React.ReactElement { function Employers(): React.ReactElement {
if (p.jobs && Object.keys(p.jobs).length !== 0) if (props.player.jobs && Object.keys(props.player.jobs).length !== 0)
return ( return (
<> <>
<span>All Employers:</span> <span>All Employers:</span>
<br /> <br />
<ul> <ul>
{Object.keys(p.jobs).map((j) => ( {Object.keys(props.player.jobs).map((j) => (
<li key={j}> * {j}</li> <li key={j}> * {j}</li>
))} ))}
</ul> </ul>
@ -56,17 +71,17 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
function Hacknet(): React.ReactElement { function Hacknet(): React.ReactElement {
// Can't import HacknetHelpers for some reason. // Can't import HacknetHelpers for some reason.
if (!(p.bitNodeN === 9 || SourceFileFlags[9] > 0)) { if (!(props.player.bitNodeN === 9 || SourceFileFlags[9] > 0)) {
return ( return (
<> <>
<span>{`Hacknet Nodes owned: ${p.hacknetNodes.length}`}</span> <span>{`Hacknet Nodes owned: ${props.player.hacknetNodes.length}`}</span>
<br /> <br />
</> </>
); );
} else { } else {
return ( return (
<> <>
<span>{`Hacknet Servers owned: ${p.hacknetNodes.length} / ${HacknetServerConstants.MaxServers}`}</span> <span>{`Hacknet Servers owned: ${props.player.hacknetNodes.length} / ${HacknetServerConstants.MaxServers}`}</span>
<br /> <br />
</> </>
); );
@ -126,10 +141,10 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
<> <>
<u>Money earned since you last installed Augmentations:</u> <u>Money earned since you last installed Augmentations:</u>
<br /> <br />
{convertMoneySourceTrackerToString(p.moneySourceA)} {convertMoneySourceTrackerToString(props.player.moneySourceA)}
</> </>
); );
if (p.sourceFiles.length !== 0) { if (props.player.sourceFiles.length !== 0) {
content = ( content = (
<> <>
{content} {content}
@ -137,7 +152,7 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
<br /> <br />
<u>Money earned in this BitNode:</u> <u>Money earned in this BitNode:</u>
<br /> <br />
{convertMoneySourceTrackerToString(p.moneySourceB)} {convertMoneySourceTrackerToString(props.player.moneySourceB)}
</> </>
); );
} }
@ -146,11 +161,11 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
} }
function Intelligence(): React.ReactElement { function Intelligence(): React.ReactElement {
if (p.intelligence > 0 && (p.bitNodeN === 5 || SourceFileFlags[5] > 0)) { if (props.player.intelligence > 0 && (props.player.bitNodeN === 5 || SourceFileFlags[5] > 0)) {
return ( return (
<tr key="5"> <tr key="5">
<td>Intelligence:</td> <td>Intelligence:</td>
<td style={{ textAlign: "right" }}>{numeralWrapper.formatSkill(p.intelligence)}</td> <td style={{ textAlign: "right" }}>{numeralWrapper.formatSkill(props.player.intelligence)}</td>
</tr> </tr>
); );
} }
@ -189,15 +204,15 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
} }
function BladeburnerMults(): React.ReactElement { function BladeburnerMults(): React.ReactElement {
if (!p.canAccessBladeburner()) return <></>; if (!props.player.canAccessBladeburner()) return <></>;
return ( return (
<> <>
<MultiplierTable <MultiplierTable
rows={[ rows={[
["Bladeburner Success Chance", p.bladeburner_max_stamina_mult], ["Bladeburner Success Chance", props.player.bladeburner_max_stamina_mult],
["Bladeburner Max Stamina", p.bladeburner_stamina_gain_mult], ["Bladeburner Max Stamina", props.player.bladeburner_stamina_gain_mult],
["Bladeburner Stamina Gain", p.bladeburner_analysis_mult], ["Bladeburner Stamina Gain", props.player.bladeburner_analysis_mult],
["Bladeburner Field Analysis", p.bladeburner_success_chance_mult], ["Bladeburner Field Analysis", props.player.bladeburner_success_chance_mult],
]} ]}
/> />
<br /> <br />
@ -206,12 +221,12 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
} }
function CurrentBitNode(): React.ReactElement { function CurrentBitNode(): React.ReactElement {
if (p.sourceFiles.length > 0) { if (props.player.sourceFiles.length > 0) {
const index = "BitNode" + p.bitNodeN; const index = "BitNode" + props.player.bitNodeN;
return ( return (
<> <>
<span> <span>
Current BitNode: {p.bitNodeN} ({BitNodes[index].name}) Current BitNode: {props.player.bitNodeN} ({BitNodes[index].name})
</span> </span>
<br /> <br />
<br /> <br />
@ -230,27 +245,29 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
return <></>; return <></>;
} }
const timeRows = [["Time played since last Augmentation:", convertTimeMsToTimeElapsedString(p.playtimeSinceLastAug)]]; const timeRows = [
if (p.sourceFiles.length > 0) { ["Time played since last Augmentation:", convertTimeMsToTimeElapsedString(props.player.playtimeSinceLastAug)],
];
if (props.player.sourceFiles.length > 0) {
timeRows.push([ timeRows.push([
"Time played since last Bitnode destroyed:", "Time played since last Bitnode destroyed:",
convertTimeMsToTimeElapsedString(p.playtimeSinceLastBitnode), convertTimeMsToTimeElapsedString(props.player.playtimeSinceLastBitnode),
]); ]);
} }
timeRows.push(["Total Time played:", convertTimeMsToTimeElapsedString(p.totalPlaytime)]); timeRows.push(["Total Time played:", convertTimeMsToTimeElapsedString(props.player.totalPlaytime)]);
return ( return (
<pre> <pre>
<b>General</b> <b>General</b>
<br /> <br />
<br /> <br />
<span>Current City: {p.city}</span> <span>Current City: {props.player.city}</span>
<br /> <br />
<LastEmployer /> <LastEmployer />
<LastJob /> <LastJob />
<Employers /> <Employers />
<span> <span>
Money: <Money money={p.money.toNumber()} /> Money: <Money money={props.player.money.toNumber()} />
</span> </span>
<button className="popup-box-button" style={{ display: "inline-block", float: "none" }} onClick={openMoneyModal}> <button className="popup-box-button" style={{ display: "inline-block", float: "none" }} onClick={openMoneyModal}>
Money Statistics & Breakdown Money Statistics & Breakdown
@ -263,55 +280,55 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
<tr key="0"> <tr key="0">
<td key="0">Hacking:</td> <td key="0">Hacking:</td>
<td key="1" style={{ textAlign: "right" }}> <td key="1" style={{ textAlign: "right" }}>
{numeralWrapper.formatSkill(p.hacking_skill)} {numeralWrapper.formatSkill(props.player.hacking_skill)}
</td> </td>
<td key="2" style={{ textAlign: "right" }}> <td key="2" style={{ textAlign: "right" }}>
({numeralWrapper.formatExp(p.hacking_exp)} exp) ({numeralWrapper.formatExp(props.player.hacking_exp)} exp)
</td> </td>
</tr> </tr>
<tr key="1"> <tr key="1">
<td key="0">Strength:</td> <td key="0">Strength:</td>
<td key="1" style={{ textAlign: "right" }}> <td key="1" style={{ textAlign: "right" }}>
{numeralWrapper.formatSkill(p.strength)} {numeralWrapper.formatSkill(props.player.strength)}
</td> </td>
<td key="2" style={{ textAlign: "right" }}> <td key="2" style={{ textAlign: "right" }}>
({numeralWrapper.formatExp(p.strength_exp)} exp) ({numeralWrapper.formatExp(props.player.strength_exp)} exp)
</td> </td>
</tr> </tr>
<tr key="2"> <tr key="2">
<td key="0">Defense:</td> <td key="0">Defense:</td>
<td key="1" style={{ textAlign: "right" }}> <td key="1" style={{ textAlign: "right" }}>
{numeralWrapper.formatSkill(p.defense)} {numeralWrapper.formatSkill(props.player.defense)}
</td> </td>
<td key="2" style={{ textAlign: "right" }}> <td key="2" style={{ textAlign: "right" }}>
({numeralWrapper.formatExp(p.defense_exp)} exp) ({numeralWrapper.formatExp(props.player.defense_exp)} exp)
</td> </td>
</tr> </tr>
<tr key="3"> <tr key="3">
<td key="0">Dexterity:</td> <td key="0">Dexterity:</td>
<td key="1" style={{ textAlign: "right" }}> <td key="1" style={{ textAlign: "right" }}>
{numeralWrapper.formatSkill(p.dexterity)} {numeralWrapper.formatSkill(props.player.dexterity)}
</td> </td>
<td key="2" style={{ textAlign: "right" }}> <td key="2" style={{ textAlign: "right" }}>
({numeralWrapper.formatExp(p.dexterity_exp)} exp) ({numeralWrapper.formatExp(props.player.dexterity_exp)} exp)
</td> </td>
</tr> </tr>
<tr key="4"> <tr key="4">
<td key="0">Agility:</td> <td key="0">Agility:</td>
<td key="1" style={{ textAlign: "right" }}> <td key="1" style={{ textAlign: "right" }}>
{numeralWrapper.formatSkill(p.agility)} {numeralWrapper.formatSkill(props.player.agility)}
</td> </td>
<td key="2" style={{ textAlign: "right" }}> <td key="2" style={{ textAlign: "right" }}>
({numeralWrapper.formatExp(p.agility_exp)} exp) ({numeralWrapper.formatExp(props.player.agility_exp)} exp)
</td> </td>
</tr> </tr>
<tr key="5"> <tr key="5">
<td key="0">Charisma:</td> <td key="0">Charisma:</td>
<td key="1" style={{ textAlign: "right" }}> <td key="1" style={{ textAlign: "right" }}>
{numeralWrapper.formatSkill(p.charisma)} {numeralWrapper.formatSkill(props.player.charisma)}
</td> </td>
<td key="2" style={{ textAlign: "right" }}> <td key="2" style={{ textAlign: "right" }}>
({numeralWrapper.formatExp(p.charisma_exp)} exp) ({numeralWrapper.formatExp(props.player.charisma_exp)} exp)
</td> </td>
</tr> </tr>
<Intelligence /> <Intelligence />
@ -320,57 +337,93 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
<br /> <br />
<MultiplierTable <MultiplierTable
rows={[ rows={[
["Hacking Chance", p.hacking_chance_mult], ["Hacking Chance", props.player.hacking_chance_mult],
["Hacking Speed", p.hacking_speed_mult], ["Hacking Speed", props.player.hacking_speed_mult],
["Hacking Money", p.hacking_money_mult, p.hacking_money_mult * BitNodeMultipliers.ScriptHackMoney], [
["Hacking Growth", p.hacking_grow_mult, p.hacking_grow_mult * BitNodeMultipliers.ServerGrowthRate], "Hacking Money",
props.player.hacking_money_mult,
props.player.hacking_money_mult * BitNodeMultipliers.ScriptHackMoney,
],
[
"Hacking Growth",
props.player.hacking_grow_mult,
props.player.hacking_grow_mult * BitNodeMultipliers.ServerGrowthRate,
],
]} ]}
/> />
<br /> <br />
<MultiplierTable <MultiplierTable
rows={[ rows={[
["Hacking Level", p.hacking_mult, p.hacking_mult * BitNodeMultipliers.HackingLevelMultiplier], [
["Hacking Experience", p.hacking_exp_mult, p.hacking_exp_mult * BitNodeMultipliers.HackExpGain], "Hacking Level",
props.player.hacking_mult,
props.player.hacking_mult * BitNodeMultipliers.HackingLevelMultiplier,
],
[
"Hacking Experience",
props.player.hacking_exp_mult,
props.player.hacking_exp_mult * BitNodeMultipliers.HackExpGain,
],
]} ]}
/> />
<br /> <br />
<MultiplierTable <MultiplierTable
rows={[ rows={[
["Strength Level", p.strength_mult, p.strength_mult * BitNodeMultipliers.StrengthLevelMultiplier], [
["Strength Experience", p.strength_exp_mult], "Strength Level",
props.player.strength_mult,
props.player.strength_mult * BitNodeMultipliers.StrengthLevelMultiplier,
],
["Strength Experience", props.player.strength_exp_mult],
]} ]}
/> />
<br /> <br />
<MultiplierTable <MultiplierTable
rows={[ rows={[
["Defense Level", p.defense_mult, p.defense_mult * BitNodeMultipliers.DefenseLevelMultiplier], [
["Defense Experience", p.defense_exp_mult], "Defense Level",
props.player.defense_mult,
props.player.defense_mult * BitNodeMultipliers.DefenseLevelMultiplier,
],
["Defense Experience", props.player.defense_exp_mult],
]} ]}
/> />
<br /> <br />
<MultiplierTable <MultiplierTable
rows={[ rows={[
["Dexterity Level", p.dexterity_mult, p.dexterity_mult * BitNodeMultipliers.DexterityLevelMultiplier], [
["Dexterity Experience", p.dexterity_exp_mult], "Dexterity Level",
props.player.dexterity_mult,
props.player.dexterity_mult * BitNodeMultipliers.DexterityLevelMultiplier,
],
["Dexterity Experience", props.player.dexterity_exp_mult],
]} ]}
/> />
<br /> <br />
<MultiplierTable <MultiplierTable
rows={[ rows={[
["Agility Level", p.agility_mult, p.agility_mult * BitNodeMultipliers.AgilityLevelMultiplier], [
["Agility Experience", p.agility_exp_mult], "Agility Level",
props.player.agility_mult,
props.player.agility_mult * BitNodeMultipliers.AgilityLevelMultiplier,
],
["Agility Experience", props.player.agility_exp_mult],
]} ]}
/> />
<br /> <br />
<MultiplierTable <MultiplierTable
rows={[ rows={[
["Charisma Level", p.charisma_mult, p.charisma_mult * BitNodeMultipliers.CharismaLevelMultiplier], [
["Charisma Experience", p.charisma_exp_mult], "Charisma Level",
props.player.charisma_mult,
props.player.charisma_mult * BitNodeMultipliers.CharismaLevelMultiplier,
],
["Charisma Experience", props.player.charisma_exp_mult],
]} ]}
/> />
<br /> <br />
@ -379,30 +432,34 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
rows={[ rows={[
[ [
"Hacknet Node production", "Hacknet Node production",
p.hacknet_node_money_mult, props.player.hacknet_node_money_mult,
p.hacknet_node_money_mult * BitNodeMultipliers.HacknetNodeMoney, props.player.hacknet_node_money_mult * BitNodeMultipliers.HacknetNodeMoney,
], ],
["Hacknet Node purchase cost", p.hacknet_node_purchase_cost_mult], ["Hacknet Node purchase cost", props.player.hacknet_node_purchase_cost_mult],
["Hacknet Node RAM upgrade cost", p.hacknet_node_ram_cost_mult], ["Hacknet Node RAM upgrade cost", props.player.hacknet_node_ram_cost_mult],
["Hacknet Node Core purchase cost", p.hacknet_node_core_cost_mult], ["Hacknet Node Core purchase cost", props.player.hacknet_node_core_cost_mult],
["Hacknet Node level upgrade cost", p.hacknet_node_level_cost_mult], ["Hacknet Node level upgrade cost", props.player.hacknet_node_level_cost_mult],
]} ]}
/> />
<br /> <br />
<MultiplierTable <MultiplierTable
rows={[ rows={[
["Company reputation gain", p.company_rep_mult], ["Company reputation gain", props.player.company_rep_mult],
["Faction reputation gain", p.faction_rep_mult, p.faction_rep_mult * BitNodeMultipliers.FactionWorkRepGain], [
["Salary", p.work_money_mult, p.work_money_mult * BitNodeMultipliers.CompanyWorkMoney], "Faction reputation gain",
props.player.faction_rep_mult,
props.player.faction_rep_mult * BitNodeMultipliers.FactionWorkRepGain,
],
["Salary", props.player.work_money_mult, props.player.work_money_mult * BitNodeMultipliers.CompanyWorkMoney],
]} ]}
/> />
<br /> <br />
<MultiplierTable <MultiplierTable
rows={[ rows={[
["Crime success", p.crime_success_mult], ["Crime success", props.player.crime_success_mult],
["Crime money", p.crime_money_mult, p.crime_money_mult * BitNodeMultipliers.CrimeMoney], ["Crime money", props.player.crime_money_mult, props.player.crime_money_mult * BitNodeMultipliers.CrimeMoney],
]} ]}
/> />
<br /> <br />
@ -413,10 +470,10 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
<b>Misc.</b> <b>Misc.</b>
<br /> <br />
<br /> <br />
<span>{`Servers owned: ${p.purchasedServers.length} / ${getPurchaseServerLimit()}`}</span> <span>{`Servers owned: ${props.player.purchasedServers.length} / ${getPurchaseServerLimit()}`}</span>
<br /> <br />
<Hacknet /> <Hacknet />
<span>{`Augmentations installed: ${p.augmentations.length}`}</span> <span>{`Augmentations installed: ${props.player.augmentations.length}`}</span>
<br /> <br />
<br /> <br />
{StatsTable(timeRows)} {StatsTable(timeRows)}