Sleeve UI improvements.

This commit is contained in:
Olivier Gagnon 2021-03-16 05:42:12 -04:00
parent 29ea1281e0
commit c9fe8d9b65
12 changed files with 295 additions and 150 deletions

70
package-lock.json generated

@ -1,11 +1,11 @@
{
"name": "bitburner",
"version": "0.47.3",
"version": "0.49.2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "0.47.3",
"version": "0.49.2",
"hasInstallScript": true,
"license": "SEE LICENSE IN license.txt",
"dependencies": {
@ -38,6 +38,7 @@
"numeral": "2.0.6",
"react": "^16.8.3",
"react-dom": "^16.8.3",
"react-modal": "^3.12.1",
"sprintf-js": "^1.1.1",
"tapable": "^1.0.0",
"uuid": "^3.2.1",
@ -4571,6 +4572,11 @@
"node": ">=0.10.0"
}
},
"node_modules/exenv": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
"integrity": "sha1-KueOhdmJQVhnCwPUe+wfA72Ru50="
},
"node_modules/exit": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
@ -11779,6 +11785,29 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.3.tgz",
"integrity": "sha512-Y4rC1ZJmsxxkkPuMLwvKvlL1Zfpbcu+Bf4ZigkHup3v9EfdYhAlWAaVyA19olXq2o2mGn0w+dFKvk3pVVlYcIA=="
},
"node_modules/react-lifecycles-compat": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
},
"node_modules/react-modal": {
"version": "3.12.1",
"resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.12.1.tgz",
"integrity": "sha512-WGuXn7Fq31PbFJwtWmOk+jFtGC7E9tJVbFX0lts8ZoS5EPi9+WWylUJWLKKVm3H4GlQ7ZxY7R6tLlbSIBQ5oZA==",
"dependencies": {
"exenv": "^1.2.0",
"prop-types": "^15.5.10",
"react-lifecycles-compat": "^3.0.0",
"warning": "^4.0.3"
},
"engines": {
"node": ">=8"
},
"peerDependencies": {
"react": "^0.14.0 || ^15.0.0 || ^16 || ^17",
"react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17"
}
},
"node_modules/readable-stream": {
"version": "2.3.4",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz",
@ -15999,6 +16028,14 @@
"xml-name-validator": "3.0.0"
}
},
"node_modules/warning": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
"dependencies": {
"loose-envify": "^1.0.0"
}
},
"node_modules/watchpack": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",
@ -21422,6 +21459,11 @@
"clone-regexp": "1.0.1"
}
},
"exenv": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
"integrity": "sha1-KueOhdmJQVhnCwPUe+wfA72Ru50="
},
"exit": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
@ -27426,6 +27468,22 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.3.tgz",
"integrity": "sha512-Y4rC1ZJmsxxkkPuMLwvKvlL1Zfpbcu+Bf4ZigkHup3v9EfdYhAlWAaVyA19olXq2o2mGn0w+dFKvk3pVVlYcIA=="
},
"react-lifecycles-compat": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
},
"react-modal": {
"version": "3.12.1",
"resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.12.1.tgz",
"integrity": "sha512-WGuXn7Fq31PbFJwtWmOk+jFtGC7E9tJVbFX0lts8ZoS5EPi9+WWylUJWLKKVm3H4GlQ7ZxY7R6tLlbSIBQ5oZA==",
"requires": {
"exenv": "^1.2.0",
"prop-types": "^15.5.10",
"react-lifecycles-compat": "^3.0.0",
"warning": "^4.0.3"
}
},
"readable-stream": {
"version": "2.3.4",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz",
@ -31040,6 +31098,14 @@
"xml-name-validator": "3.0.0"
}
},
"warning": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
"requires": {
"loose-envify": "^1.0.0"
}
},
"watchpack": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",

@ -35,6 +35,7 @@
"numeral": "2.0.6",
"react": "^16.8.3",
"react-dom": "^16.8.3",
"react-modal": "^3.12.1",
"sprintf-js": "^1.1.1",
"tapable": "^1.0.0",
"uuid": "^3.2.1",

@ -41,6 +41,9 @@ import { removeElementById } from "../../../utils/uiHelpers/removeElementById";
import { EarningsTableElement } from "./ui/EarningsTableElement";
import { StatsElement } from "./ui/StatsElement";
import { MoreStatsContent } from "./ui/MoreStatsContent";
import { MoreEarningsContent } from "./ui/MoreEarningsContent";
import * as React from "react";
import * as ReactDOM from "react-dom";
// Object that keeps track of all DOM elements for the UI for a single Sleeve
@ -100,8 +103,8 @@ export function createSleevesPage(p: IPlayer) {
class: "sleeves-page-info",
innerHTML: "<h1>Sleeves</h1>Duplicate Sleeves are MK-V Synthoids (synthetic androids) into which your " +
"consciousness has been copied. In other words, these Synthoids contain " +
"a perfect duplicate of your mind.<br><br>" +
"Sleeves can be used to perform different tasks synchronously.<br><br>",
"a perfect duplicate of your mind.<br /><br />" +
"Sleeves can be used to perform different tasks synchronously.<br /><br />",
});
UIElems.faqButton = createElement("button", {
@ -163,7 +166,7 @@ export function clearSleevesPage() {
}
for (const prop in UIElems) {
(<any>UIElems)[prop] = null;
(UIElems as any)[prop] = null;
}
playerRef = null;
@ -204,35 +207,7 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
class: "std-button",
innerText: "More Stats",
clickListener: () => {
dialogBoxCreate(
[
"<h2><u>Stats:</u></h2>",
`Hacking: ${sleeve.hacking_skill} (${numeralWrapper.formatBigNumber(sleeve.hacking_exp)} exp)`,
`Strength: ${sleeve.strength} (${numeralWrapper.formatBigNumber(sleeve.strength_exp)} exp)`,
`Defense: ${sleeve.defense} (${numeralWrapper.formatBigNumber(sleeve.defense_exp)} exp)`,
`Dexterity: ${sleeve.dexterity} (${numeralWrapper.formatBigNumber(sleeve.dexterity_exp)} exp)`,
`Agility: ${sleeve.agility} (${numeralWrapper.formatBigNumber(sleeve.agility_exp)} exp)`,
`Charisma: ${sleeve.charisma} (${numeralWrapper.formatBigNumber(sleeve.charisma_exp)} exp)<br>`,
"<h2><u>Multipliers:</u></h2>",
`Hacking Level multiplier: ${numeralWrapper.formatPercentage(sleeve.hacking_mult)}`,
`Hacking Experience multiplier: ${numeralWrapper.formatPercentage(sleeve.hacking_exp_mult)}`,
`Strength Level multiplier: ${numeralWrapper.formatPercentage(sleeve.strength_mult)}`,
`Strength Experience multiplier: ${numeralWrapper.formatPercentage(sleeve.strength_exp_mult)}`,
`Defense Level multiplier: ${numeralWrapper.formatPercentage(sleeve.defense_mult)}`,
`Defense Experience multiplier: ${numeralWrapper.formatPercentage(sleeve.defense_exp_mult)}`,
`Dexterity Level multiplier: ${numeralWrapper.formatPercentage(sleeve.dexterity_mult)}`,
`Dexterity Experience multiplier: ${numeralWrapper.formatPercentage(sleeve.dexterity_exp_mult)}`,
`Agility Level multiplier: ${numeralWrapper.formatPercentage(sleeve.agility_mult)}`,
`Agility Experience multiplier: ${numeralWrapper.formatPercentage(sleeve.agility_exp_mult)}`,
`Charisma Level multiplier: ${numeralWrapper.formatPercentage(sleeve.charisma_mult)}`,
`Charisma Experience multiplier: ${numeralWrapper.formatPercentage(sleeve.charisma_exp_mult)}`,
`Faction Reputation Gain multiplier: ${numeralWrapper.formatPercentage(sleeve.faction_rep_mult)}`,
`Company Reputation Gain multiplier: ${numeralWrapper.formatPercentage(sleeve.company_rep_mult)}`,
`Salary multiplier: ${numeralWrapper.formatPercentage(sleeve.work_money_mult)}`,
`Crime Money multiplier: ${numeralWrapper.formatPercentage(sleeve.crime_money_mult)}`,
`Crime Success multiplier: ${numeralWrapper.formatPercentage(sleeve.crime_success_mult)}`,
].join("<br>"), false
);
dialogBoxCreate(MoreStatsContent(sleeve));
}
});
elems.travelButton = createElement("button", {
@ -261,7 +236,7 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
dialogBoxCreate("You cannot afford to have this sleeve travel to another city", false);
return false;
}
sleeve.city = <CityName>cityName;
sleeve.city = cityName as CityName;
playerRef!.loseMoney(CONSTANTS.TravelCost);
sleeve.resetTaskStatus();
removeElementById(popupId);
@ -332,34 +307,7 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
class: "std-button",
innerText: "More Earnings Info",
clickListener: () => {
dialogBoxCreate(
[
"<h2><u>Earnings for Current Task:</u></h2>",
`Money: ${numeralWrapper.formatMoney(sleeve.earningsForTask.money)}`,
`Hacking Exp: ${numeralWrapper.formatBigNumber(sleeve.earningsForTask.hack)}`,
`Strength Exp: ${numeralWrapper.formatBigNumber(sleeve.earningsForTask.str)}`,
`Defense Exp: ${numeralWrapper.formatBigNumber(sleeve.earningsForTask.def)}`,
`Dexterity Exp: ${numeralWrapper.formatBigNumber(sleeve.earningsForTask.dex)}`,
`Agility Exp: ${numeralWrapper.formatBigNumber(sleeve.earningsForTask.agi)}`,
`Charisma Exp: ${numeralWrapper.formatBigNumber(sleeve.earningsForTask.cha)}<br>`,
"<h2><u>Total Earnings for Host Consciousness:</u></h2>",
`Money: ${numeralWrapper.formatMoney(sleeve.earningsForPlayer.money)}`,
`Hacking Exp: ${numeralWrapper.formatBigNumber(sleeve.earningsForPlayer.hack)}`,
`Strength Exp: ${numeralWrapper.formatBigNumber(sleeve.earningsForPlayer.str)}`,
`Defense Exp: ${numeralWrapper.formatBigNumber(sleeve.earningsForPlayer.def)}`,
`Dexterity Exp: ${numeralWrapper.formatBigNumber(sleeve.earningsForPlayer.dex)}`,
`Agility Exp: ${numeralWrapper.formatBigNumber(sleeve.earningsForPlayer.agi)}`,
`Charisma Exp: ${numeralWrapper.formatBigNumber(sleeve.earningsForPlayer.cha)}<br>`,
"<h2><u>Total Earnings for Other Sleeves:</u></h2>",
`Money: ${numeralWrapper.formatMoney(sleeve.earningsForSleeves.money)}`,
`Hacking Exp: ${numeralWrapper.formatBigNumber(sleeve.earningsForSleeves.hack)}`,
`Strength Exp: ${numeralWrapper.formatBigNumber(sleeve.earningsForSleeves.str)}`,
`Defense Exp: ${numeralWrapper.formatBigNumber(sleeve.earningsForSleeves.def)}`,
`Dexterity Exp: ${numeralWrapper.formatBigNumber(sleeve.earningsForSleeves.dex)}`,
`Agility Exp: ${numeralWrapper.formatBigNumber(sleeve.earningsForSleeves.agi)}`,
`Charisma Exp: ${numeralWrapper.formatBigNumber(sleeve.earningsForSleeves.cha)}`,
].join("<br>"), false
);
dialogBoxCreate(MoreEarningsContent(sleeve));
}
});
@ -383,13 +331,13 @@ function updateSleeveUi(sleeve: Sleeve, elems: ISleeveUIElems) {
if (sleeve.currentTask === SleeveTaskType.Crime) {
const data = [
[`Money`, `${numeralWrapper.formatMoney(parseFloat(sleeve.currentTaskLocation))}`, `(on success)`],
[`Hacking Exp`, `${numeralWrapper.format(sleeve.gainRatesForTask.hack, "0.00")}`, `(2x on success)`],
[`Strength Exp`, `${numeralWrapper.format(sleeve.gainRatesForTask.str, "0.00")}`, `(2x on success)`],
[`Defense Exp`, `${numeralWrapper.format(sleeve.gainRatesForTask.def, "0.00")}`, `(2x on success)`],
[`Dexterity Exp`, `${numeralWrapper.format(sleeve.gainRatesForTask.dex, "0.00")}`, `(2x on success)`],
[`Agility Exp`, `${numeralWrapper.format(sleeve.gainRatesForTask.agi, "0.00")}`, `(2x on success)`],
[`Charisma Exp`, `${numeralWrapper.format(sleeve.gainRatesForTask.cha, "0.00")}`, `(2x on success)`]
[`Money`, numeralWrapper.formatMoney(parseFloat(sleeve.currentTaskLocation)), `(on success)`],
[`Hacking Exp`, numeralWrapper.format(sleeve.gainRatesForTask.hack, "0.00"), `(2x on success)`],
[`Strength Exp`, numeralWrapper.format(sleeve.gainRatesForTask.str, "0.00"), `(2x on success)`],
[`Defense Exp`, numeralWrapper.format(sleeve.gainRatesForTask.def, "0.00"), `(2x on success)`],
[`Dexterity Exp`, numeralWrapper.format(sleeve.gainRatesForTask.dex, "0.00"), `(2x on success)`],
[`Agility Exp`, numeralWrapper.format(sleeve.gainRatesForTask.agi, "0.00"), `(2x on success)`],
[`Charisma Exp`, numeralWrapper.format(sleeve.gainRatesForTask.cha, "0.00"), `(2x on success)`]
];
ReactDOM.render(EarningsTableElement('Earnings (Pre-Synchronization)', data), elems.currentEarningsInfo!)

@ -1,57 +0,0 @@
export const SleeveFaq: string =
[
"<strong><u>How do Duplicate Sleeves work?</strong></u><br>",
"Duplicate Sleeves are essentially clones. You can use them to perform any work type",
"action, such as working for a company/faction or committing a crime.",
"Having sleeves perform these tasks earns you money, experience, and reputation.<br><br>",
"Sleeves are their own individuals, which means they each have their own",
"experience and stats.<br><br>",
"When a sleeve earns experience, it earns experience for itself, the player's",
"original 'consciousness', as well as all of the player's other sleeves.<br><br>",
"<strong><u>What is Synchronization (Sync)?</strong></u><br>",
"Synchronization is a measure of how aligned your consciousness is with",
"that of your Duplicate Sleeves. It is a numerical value between 1 and 100, and",
"it affects how much experience is earned when the sleeve is performing a task.<br><br>",
"Let N be the sleeve's synchronization. When the sleeve earns experience by performing a",
"task, both the sleeve and the player's original host consciousness earn N%",
"of the amount of experience normally earned by the task. All of the player's",
"other sleeves earn ((N/100)^2 * 100)% of the experience.<br><br>",
"Synchronization can be increased by assigning sleeves to the 'Synchronize' task.<br><br>",
"<strong><u>What is Shock?</u></strong><br>",
"Sleeve shock is a measure of how much trauma the sleeve has due to being placed in a new",
"body. It is a numerical value between 0 and 99, where 99 indicates full shock and 0 indicates",
"no shock. Shock affects the amount of experience earned by the sleeve.<br><br>",
"Sleeve shock slowly decreases over time. You can further increase the rate at which",
"it decreases by assigning sleeves to the 'Shock Recovery' task.<br><br>",
"<strong><u>Why can't I work for this company or faction?</u></strong><br>",
"Only one of your sleeves can work for a given company/faction a time.",
"To clarify further, if you have two sleeves they can work for two different",
"companies, but they cannot both work for the same company.<br><br>",
"<strong><u>Why did my Sleeve stop working?</u></strong><br>",
"Sleeves are subject to the same time restrictions as you. This means that",
"they automatically stop working at a company after 8 hours, and stop working",
"for a faction after 20 hours.<br><br>",
"<strong><u>How do I buy Augmentations for my Sleeves?</u></strong><br>",
"Your Sleeve needs to have a Shock of 0 in order for you to buy Augmentations",
"for it.<br><br>",
"<strong><u>Why can't I buy the X Augmentation for my sleeve?</u></strong><br>",
"Certain Augmentations, like Bladeburner-specific ones and NeuroFlux Governor,",
"are not available for sleeves.<br><br>",
"<strong><u>Do sleeves get reset when installing Augmentations or switching BitNodes?</u></strong><br>",
"Sleeves are reset when switching BitNodes, but not when installing Augmentations.<br><br>",
"<strong><u>What is Memory?</u></strong><br>",
"Sleeve memory dictates what a sleeve's synchronization will be",
"when its reset by switching BitNodes. For example, if a sleeve has a memory of 25,",
"then when you switch BitNodes its synchronization will initially be set to 25, rather than 1.<br><br>",
"Memory can only be increased by purchasing upgrades from The Covenant. It is a",
"persistent stat, meaning it never gets resets back to 1. The maximum possible",
"value for a sleeve's memory is 100."
].join(" ");

@ -0,0 +1,80 @@
import * as React from "react";
export const SleeveFaq = (<>
<strong><u>How do Duplicate Sleeves work?</u></strong>
<br />
Duplicate Sleeves are essentially clones. You can use them to perform any work type
action, such as working for a company/faction or committing a crime.
Having sleeves perform these tasks earns you money, experience, and reputation.
<br /><br />
Sleeves are their own individuals, which means they each have their own
experience and stats.
<br /><br />
When a sleeve earns experience, it earns experience for itself, the player's
original 'consciousness', as well as all of the player's other sleeves.
<br /><br />
<strong><u>What is Synchronization (Sync)?</u></strong>
<br />
Synchronization is a measure of how aligned your consciousness is with
that of your Duplicate Sleeves. It is a numerical value between 1 and 100, and
it affects how much experience is earned when the sleeve is performing a task.
<br /><br />
Let N be the sleeve's synchronization. When the sleeve earns experience by performing a
task, both the sleeve and the player's original host consciousness earn N%
of the amount of experience normally earned by the task. All of the player's
other sleeves earn ((N/100)^2 * 100)% of the experience.
<br /><br />
Synchronization can be increased by assigning sleeves to the 'Synchronize' task.
<br /><br />
<strong><u>What is Shock?</u></strong>
<br />
Sleeve shock is a measure of how much trauma the sleeve has due to being placed in a new
body. It is a numerical value between 0 and 99, where 99 indicates full shock and 0 indicates
no shock. Shock affects the amount of experience earned by the sleeve.
<br /><br />
Sleeve shock slowly decreases over time. You can further increase the rate at which
it decreases by assigning sleeves to the 'Shock Recovery' task.
<br /><br />
<strong><u>Why can't I work for this company or faction?</u></strong>
<br />
Only one of your sleeves can work for a given company/faction a time.
To clarify further, if you have two sleeves they can work for two different
companies, but they cannot both work for the same company.
<br /><br />
<strong><u>Why did my Sleeve stop working?</u></strong>
<br />
Sleeves are subject to the same time restrictions as you. This means that
they automatically stop working at a company after 8 hours, and stop working
for a faction after 20 hours.
<br /><br />
<strong><u>How do I buy Augmentations for my Sleeves?</u></strong>
<br />
Your Sleeve needs to have a Shock of 0 in order for you to buy Augmentations
for it.
<br /><br />
<strong><u>Why can't I buy the X Augmentation for my sleeve?</u></strong>
<br />
Certain Augmentations, like Bladeburner-specific ones and NeuroFlux Governor,
are not available for sleeves.
<br /><br />
<strong><u>Do sleeves get reset when installing Augmentations or switching BitNodes?</u></strong><br />
Sleeves are reset when switching BitNodes, but not when installing Augmentations.
<br /><br />
<strong><u>What is Memory?</u></strong>
<br />
Sleeve memory dictates what a sleeve's synchronization will be
when its reset by switching BitNodes. For example, if a sleeve has a memory of 25,
then when you switch BitNodes its synchronization will initially be set to 25, rather than 1.
<br /><br />
Memory can only be increased by purchasing upgrades from The Covenant. It is a
persistent stat, meaning it never gets resets back to 1. The maximum possible
value for a sleeve's memory is 100.
</>);

@ -2,7 +2,7 @@ import * as React from "react";
export function EarningsTableElement(title: string, stats: any[][]): React.ReactElement {
return (<>
{title}
<pre>{title}</pre>
<table>
<tbody>
{stats.map((stat: any[], i: number) => <tr key={i}>

@ -0,0 +1,41 @@
import { Sleeve } from "../Sleeve";
import { numeralWrapper } from "../../../ui/numeralFormat";
import * as React from "react";
import { StatsTable } from "../../../ui/React/StatsTable";
export function MoreEarningsContent(sleeve: Sleeve): React.ReactElement {
let style = {}
style = {textAlign: 'right'};
return (<>
{StatsTable([
['Money ', numeralWrapper.formatMoney(sleeve.earningsForTask.money)],
['Hacking Exp ', numeralWrapper.formatBigNumber(sleeve.earningsForTask.hack)],
['Strength Exp ', numeralWrapper.formatBigNumber(sleeve.earningsForTask.str)],
['Defense Exp ', numeralWrapper.formatBigNumber(sleeve.earningsForTask.def)],
['Dexterity Exp ', numeralWrapper.formatBigNumber(sleeve.earningsForTask.dex)],
['Agility Exp ', numeralWrapper.formatBigNumber(sleeve.earningsForTask.agi)],
['Charisma Exp ', numeralWrapper.formatBigNumber(sleeve.earningsForTask.cha)],
], 'Earnings for Current Task:')}
<br />
{StatsTable([
['Money: ', numeralWrapper.formatMoney(sleeve.earningsForPlayer.money)],
['Hacking Exp: ', numeralWrapper.formatBigNumber(sleeve.earningsForPlayer.hack)],
['Strength Exp: ', numeralWrapper.formatBigNumber(sleeve.earningsForPlayer.str)],
['Defense Exp: ', numeralWrapper.formatBigNumber(sleeve.earningsForPlayer.def)],
['Dexterity Exp: ', numeralWrapper.formatBigNumber(sleeve.earningsForPlayer.dex)],
['Agility Exp: ', numeralWrapper.formatBigNumber(sleeve.earningsForPlayer.agi)],
['Charisma Exp: ', numeralWrapper.formatBigNumber(sleeve.earningsForPlayer.cha)],
], 'Total Earnings for Host Consciousness:')}
<br />
{StatsTable([
['Money: ', numeralWrapper.formatMoney(sleeve.earningsForSleeves.money)],
['Hacking Exp: ', numeralWrapper.formatBigNumber(sleeve.earningsForSleeves.hack)],
['Strength Exp: ', numeralWrapper.formatBigNumber(sleeve.earningsForSleeves.str)],
['Defense Exp: ', numeralWrapper.formatBigNumber(sleeve.earningsForSleeves.def)],
['Dexterity Exp: ', numeralWrapper.formatBigNumber(sleeve.earningsForSleeves.dex)],
['Agility Exp: ', numeralWrapper.formatBigNumber(sleeve.earningsForSleeves.agi)],
['Charisma Exp: ', numeralWrapper.formatBigNumber(sleeve.earningsForSleeves.cha)],
], 'Total Earnings for Other Sleeves:')}
<br />
</>);
}

@ -0,0 +1,39 @@
import { Sleeve } from "../Sleeve";
import { numeralWrapper } from "../../../ui/numeralFormat";
import { StatsTable } from "../../../ui/React/StatsTable";
import * as React from "react";
export function MoreStatsContent(sleeve: Sleeve): React.ReactElement {
let style = {}
style = {textAlign: 'right'};
return (<>
{StatsTable([
['Hacking: ', sleeve.hacking_skill, `(${numeralWrapper.formatBigNumber(sleeve.hacking_exp)} exp)`],
['Strength: ', sleeve.strength, `(${numeralWrapper.formatBigNumber(sleeve.strength_exp)} exp)`],
['Defense: ', sleeve.defense, `(${numeralWrapper.formatBigNumber(sleeve.defense_exp)} exp)`],
['Dexterity: ', sleeve.dexterity, `(${numeralWrapper.formatBigNumber(sleeve.dexterity_exp)} exp)`],
['Agility: ', sleeve.agility, `(${numeralWrapper.formatBigNumber(sleeve.agility_exp)} exp)`],
['Charisma: ', sleeve.charisma, `(${numeralWrapper.formatBigNumber(sleeve.charisma_exp)} exp)`],
], 'Stats:')}
<br />
{StatsTable([
['Hacking Level multiplier: ', numeralWrapper.formatPercentage(sleeve.hacking_mult)],
['Hacking Experience multiplier: ', numeralWrapper.formatPercentage(sleeve.hacking_exp_mult)],
['Strength Level multiplier: ', numeralWrapper.formatPercentage(sleeve.strength_mult)],
['Strength Experience multiplier: ', numeralWrapper.formatPercentage(sleeve.strength_exp_mult)],
['Defense Level multiplier: ', numeralWrapper.formatPercentage(sleeve.defense_mult)],
['Defense Experience multiplier: ', numeralWrapper.formatPercentage(sleeve.defense_exp_mult)],
['Dexterity Level multiplier: ', numeralWrapper.formatPercentage(sleeve.dexterity_mult)],
['Dexterity Experience multiplier: ', numeralWrapper.formatPercentage(sleeve.dexterity_exp_mult)],
['Agility Level multiplier: ', numeralWrapper.formatPercentage(sleeve.agility_mult)],
['Agility Experience multiplier: ', numeralWrapper.formatPercentage(sleeve.agility_exp_mult)],
['Charisma Level multiplier: ', numeralWrapper.formatPercentage(sleeve.charisma_mult)],
['Charisma Experience multiplier: ', numeralWrapper.formatPercentage(sleeve.charisma_exp_mult)],
['Faction Reputation Gain multiplier: ', numeralWrapper.formatPercentage(sleeve.faction_rep_mult)],
['Company Reputation Gain multiplier: ', numeralWrapper.formatPercentage(sleeve.company_rep_mult)],
['Salary multiplier: ', numeralWrapper.formatPercentage(sleeve.work_money_mult)],
['Crime Money multiplier: ', numeralWrapper.formatPercentage(sleeve.crime_money_mult)],
['Crime Success multiplier: ', numeralWrapper.formatPercentage(sleeve.crime_success_mult)],
], 'Multipliers:')}
</>);
}

@ -0,0 +1,24 @@
import * as React from "react";
export function StatsTable(rows: any[][], title: string | null): React.ReactElement {
let titleElem = <></>
if (title) {
titleElem = <><h2><u>{title}</u></h2><br /></>;
}
return (<>
{titleElem}
<table>
<tbody>
{rows.map((row: any[]) => {
return <tr key={row[0]}>
{row.map((elem: any, i: number) => {
let style = {};
if (i !== 0) style = {textAlign: 'right'};
return <td key={i} style={style}>{elem}</td>
})}
</tr>
})}
</tbody>
</table>
</>);
}

@ -1,2 +1,2 @@
export function dialogBoxCreate(txt: string, preformatted?: boolean): void;
export function dialogBoxCreate(txt: string | JSX.Element, preformatted?: boolean): void;
export var dialogBoxOpened: boolean;

@ -1,4 +1,7 @@
import { KEY } from "./helpers/keyCodes";
import { DialogBox } from "./ui/DialogBox";
import React from "react";
import ReactDOM from "react-dom";
/**
* Create and display a pop-up dialog box.
@ -41,32 +44,24 @@ document.addEventListener("keydown", function (event) {
let dialogBoxOpened = false;
function dialogBoxCreate(txt, preformatted=false) {
var container = document.createElement("div");
const container = document.createElement("div");
container.setAttribute("class", "dialog-box-container");
var content = document.createElement("div");
content.setAttribute("class", "dialog-box-content");
var closeButton = document.createElement("span");
closeButton.setAttribute("class", "dialog-box-close-button");
closeButton.innerHTML = "&times;"
var textE;
if (preformatted) {
// For text files as they are often computed data that
// shouldn't be wrapped and should retain tabstops.
textE = document.createElement("pre");
textE.innerHTML = txt;
} else {
textE = document.createElement("p");
textE.innerHTML = txt.replace(/(?:\r\n|\r|\n)/g, '<br>');
let elem = txt;
if (typeof txt === 'string') {
if (preformatted) {
// For text files as they are often computed data that
// shouldn't be wrapped and should retain tabstops.
elem = <pre dangerouslySetInnerHTML={{ __html: txt }} />
} else {
elem = <p dangerouslySetInnerHTML={{ __html: txt.replace(/(?:\r\n|\r|\n)/g, '<br />') }} />
}
}
content.appendChild(closeButton);
content.appendChild(textE);
container.appendChild(content);
ReactDOM.render(DialogBox(elem), container);
document.body.appendChild(container);
if (dialogBoxes.length >= 1) {
container.style.visibility = "hidden";

8
utils/ui/DialogBox.tsx Normal file

@ -0,0 +1,8 @@
import * as React from "react";
export function DialogBox(content: HTMLElement): React.ReactElement {
return (<div className="dialog-box-content text">
<span className="dialog-box-close-button ">&times;</span>
{content}
</div>);
}