prettify, sorry for the big ass commit

This commit is contained in:
Olivier Gagnon
2021-09-04 19:09:30 -04:00
parent 3d7cdb4ef9
commit a18bdd6afc
554 changed files with 91615 additions and 66138 deletions
File diff suppressed because it is too large Load Diff
@@ -2,7 +2,7 @@
* Module for handling the UI for purchasing Sleeve Augmentations
* This UI is a popup, not a full page
*/
import React from 'react';
import React from "react";
import { Sleeve } from "./Sleeve";
import { findSleevePurchasableAugs } from "./SleeveHelpers";
@@ -20,106 +20,118 @@ import { createPopup } from "../../../utils/uiHelpers/createPopup";
import { createPopupCloseButton } from "../../../utils/uiHelpers/createPopupCloseButton";
import { removeElementById } from "../../../utils/uiHelpers/removeElementById";
import { renderToStaticMarkup } from "react-dom/server"
import { renderToStaticMarkup } from "react-dom/server";
export function createSleevePurchaseAugsPopup(sleeve: Sleeve, p: IPlayer): void {
// Array of all owned Augmentations. Names only
const ownedAugNames: string[] = sleeve.augmentations.map((e) => {return e.name});
export function createSleevePurchaseAugsPopup(
sleeve: Sleeve,
p: IPlayer,
): void {
// Array of all owned Augmentations. Names only
const ownedAugNames: string[] = sleeve.augmentations.map((e) => {
return e.name;
});
// You can only purchase Augmentations that are actually available from
// your factions. I.e. you must be in a faction that has the Augmentation
// and you must also have enough rep in that faction in order to purchase it.
const availableAugs = findSleevePurchasableAugs(sleeve, p);
// You can only purchase Augmentations that are actually available from
// your factions. I.e. you must be in a faction that has the Augmentation
// and you must also have enough rep in that faction in order to purchase it.
const availableAugs = findSleevePurchasableAugs(sleeve, p);
// Create popup
const popupId = "purchase-sleeve-augs-popup";
// Create popup
const popupId = "purchase-sleeve-augs-popup";
// Close popup button
const closeBtn = createPopupCloseButton(popupId, { innerText: "Cancel" });
// Close popup button
const closeBtn = createPopupCloseButton(popupId, { innerText: "Cancel" });
// General info about owned Augmentations
const ownedAugsInfo = createElement("p", {
display: "block",
innerHTML: "Owned Augmentations:",
// General info about owned Augmentations
const ownedAugsInfo = createElement("p", {
display: "block",
innerHTML: "Owned Augmentations:",
});
const popupElems: HTMLElement[] = [closeBtn, ownedAugsInfo];
// Show owned augmentations
// First we'll make a div with a reduced width, so the tooltips don't go off
// the edge of the popup
const ownedAugsDiv = createElement("div", { width: "70%" });
for (const ownedAug of ownedAugNames) {
const aug: Augmentation | null = Augmentations[ownedAug];
if (aug == null) {
console.warn(`Invalid Augmentation: ${ownedAug}`);
continue;
}
let tooltip = aug.info;
if (typeof tooltip !== "string") {
tooltip = renderToStaticMarkup(tooltip);
}
tooltip += "<br /><br />";
tooltip += renderToStaticMarkup(aug.stats);
ownedAugsDiv.appendChild(
createElement("div", {
class: "gang-owned-upgrade", // Reusing a class from the Gang UI
innerText: ownedAug,
tooltip: tooltip,
}),
);
}
popupElems.push(ownedAugsDiv);
// General info about buying Augmentations
const info = createElement("p", {
innerHTML: [
`You can purchase Augmentations for your Duplicate Sleeves. These Augmentations`,
`have the same effect as they would for you. You can only purchase Augmentations`,
`that you have unlocked through Factions.<br><br>`,
`When purchasing an Augmentation for a Duplicate Sleeve, they are immediately`,
`installed. This means that the Duplicate Sleeve will immediately lose all of`,
`its stat experience.`,
].join(" "),
});
popupElems.push(info);
for (const aug of availableAugs) {
const div = createElement("div", {
class: "cmpy-mgmt-upgrade-div", // We'll reuse this CSS class
});
const popupElems: HTMLElement[] = [closeBtn, ownedAugsInfo];
// Show owned augmentations
// First we'll make a div with a reduced width, so the tooltips don't go off
// the edge of the popup
const ownedAugsDiv = createElement("div", { width: "70%" });
for (const ownedAug of ownedAugNames) {
const aug: Augmentation | null = Augmentations[ownedAug];
if (aug == null) {
console.warn(`Invalid Augmentation: ${ownedAug}`);
continue;
}
let tooltip = aug.info;
if(typeof tooltip !== 'string') {
tooltip = renderToStaticMarkup(tooltip);
}
tooltip += "<br /><br />";
tooltip += renderToStaticMarkup(aug.stats);
ownedAugsDiv.appendChild(createElement("div", {
class: "gang-owned-upgrade", // Reusing a class from the Gang UI
innerText: ownedAug,
tooltip: tooltip,
}))
let info = aug.info;
if (typeof info !== "string") {
info = renderToStaticMarkup(info);
}
popupElems.push(ownedAugsDiv);
info += "<br /><br />";
info += renderToStaticMarkup(aug.stats);
// General info about buying Augmentations
const info = createElement("p", {
innerHTML:
[
`You can purchase Augmentations for your Duplicate Sleeves. These Augmentations`,
`have the same effect as they would for you. You can only purchase Augmentations`,
`that you have unlocked through Factions.<br><br>`,
`When purchasing an Augmentation for a Duplicate Sleeve, they are immediately`,
`installed. This means that the Duplicate Sleeve will immediately lose all of`,
`its stat experience.`,
div.appendChild(
createElement("p", {
fontSize: "12px",
innerHTML: [
`<h2>${aug.name}</h2><br>`,
`Cost: ${renderToStaticMarkup(
<Money money={aug.startingCost} player={p} />,
)}<br><br>`,
`${info}`,
].join(" "),
});
padding: "2px",
clickListener: () => {
if (sleeve.tryBuyAugmentation(p, aug)) {
dialogBoxCreate(
`Installed ${aug.name} on Duplicate Sleeve!`,
false,
);
removeElementById(popupId);
createSleevePurchaseAugsPopup(sleeve, p);
} else {
dialogBoxCreate(`You cannot afford ${aug.name}`, false);
}
},
}),
);
popupElems.push(info);
popupElems.push(div);
}
for (const aug of availableAugs) {
const div = createElement("div", {
class: "cmpy-mgmt-upgrade-div", // We'll reuse this CSS class
});
let info = aug.info;
if(typeof info !== 'string') {
info = renderToStaticMarkup(info);
}
info += "<br /><br />";
info += renderToStaticMarkup(aug.stats);
div.appendChild(createElement("p", {
fontSize: "12px",
innerHTML:
[
`<h2>${aug.name}</h2><br>`,
`Cost: ${renderToStaticMarkup(<Money money={aug.startingCost} player={p} />)}<br><br>`,
`${info}`,
].join(" "),
padding: "2px",
clickListener: () => {
if (sleeve.tryBuyAugmentation(p, aug)) {
dialogBoxCreate(`Installed ${aug.name} on Duplicate Sleeve!`, false);
removeElementById(popupId);
createSleevePurchaseAugsPopup(sleeve, p);
} else {
dialogBoxCreate(`You cannot afford ${aug.name}`, false);
}
},
}));
popupElems.push(div);
}
createPopup(popupId, popupElems);
createPopup(popupId, popupElems);
}
@@ -5,13 +5,15 @@
import { IPlayer } from "../IPlayer";
import { CovenantPurchasesRoot } from "./ui/CovenantPurchasesRoot";
import { createPopup,
removePopup } from "../../ui/React/createPopup";
import { createPopup, removePopup } from "../../ui/React/createPopup";
export const MaxSleevesFromCovenant = 5;
export const BaseCostPerSleeve = 10e12;
export const PopupId = "covenant-sleeve-purchases-popup";
export function createSleevePurchasesFromCovenantPopup(p: IPlayer): void {
createPopup(PopupId, CovenantPurchasesRoot, { p: p, closeFn: () => removePopup(PopupId) });
createPopup(PopupId, CovenantPurchasesRoot, {
p: p,
closeFn: () => removePopup(PopupId),
});
}
+66 -43
View File
@@ -8,57 +8,80 @@ import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { Faction } from "../../Faction/Faction";
import { Factions } from "../../Faction/Factions";
export function findSleevePurchasableAugs(sleeve: Sleeve, p: IPlayer): Augmentation[] {
// You can only purchase Augmentations that are actually available from
// your factions. I.e. you must be in a faction that has the Augmentation
// and you must also have enough rep in that faction in order to purchase it.
export function findSleevePurchasableAugs(
sleeve: Sleeve,
p: IPlayer,
): Augmentation[] {
// You can only purchase Augmentations that are actually available from
// your factions. I.e. you must be in a faction that has the Augmentation
// and you must also have enough rep in that faction in order to purchase it.
const ownedAugNames: string[] = sleeve.augmentations.map((e) => {return e.name});
const availableAugs: Augmentation[] = [];
const ownedAugNames: string[] = sleeve.augmentations.map((e) => {
return e.name;
});
const availableAugs: Augmentation[] = [];
// Helper function that helps filter out augs that are already owned
// and augs that aren't allowed for sleeves
function isAvailableForSleeve(aug: Augmentation): boolean {
if (aug.name === AugmentationNames.NeuroFluxGovernor) { return false; }
if (ownedAugNames.includes(aug.name)) { return false; }
if (availableAugs.includes(aug)) { return false; }
if (aug.isSpecial) { return false; }
return true;
// Helper function that helps filter out augs that are already owned
// and augs that aren't allowed for sleeves
function isAvailableForSleeve(aug: Augmentation): boolean {
if (aug.name === AugmentationNames.NeuroFluxGovernor) {
return false;
}
if (ownedAugNames.includes(aug.name)) {
return false;
}
if (availableAugs.includes(aug)) {
return false;
}
if (aug.isSpecial) {
return false;
}
// If player is in a gang, then we return all augs that the player
// has enough reputation for (since that gang offers all augs)
if (p.inGang()) {
const fac = p.getGangFaction();
return true;
}
for (const augName in Augmentations) {
const aug = Augmentations[augName];
if (!isAvailableForSleeve(aug)) { continue; }
// If player is in a gang, then we return all augs that the player
// has enough reputation for (since that gang offers all augs)
if (p.inGang()) {
const fac = p.getGangFaction();
if (fac.playerReputation > aug.baseRepRequirement) {
availableAugs.push(aug);
}
}
for (const augName in Augmentations) {
const aug = Augmentations[augName];
if (!isAvailableForSleeve(aug)) {
continue;
}
return availableAugs;
}
for (const facName of p.factions) {
if (facName === "Bladeburners") { continue; }
if (facName === "Netburners") { continue; }
const fac: Faction | null = Factions[facName];
if (fac == null) { continue; }
for (const augName of fac.augmentations) {
const aug: Augmentation = Augmentations[augName];
if (!isAvailableForSleeve(aug)) { continue; }
if (fac.playerReputation > aug.baseRepRequirement) {
availableAugs.push(aug);
}
}
if (fac.playerReputation > aug.baseRepRequirement) {
availableAugs.push(aug);
}
}
return availableAugs;
}
for (const facName of p.factions) {
if (facName === "Bladeburners") {
continue;
}
if (facName === "Netburners") {
continue;
}
const fac: Faction | null = Factions[facName];
if (fac == null) {
continue;
}
for (const augName of fac.augmentations) {
const aug: Augmentation = Augmentations[augName];
if (!isAvailableForSleeve(aug)) {
continue;
}
if (fac.playerReputation > aug.baseRepRequirement) {
availableAugs.push(aug);
}
}
}
return availableAugs;
}
@@ -2,13 +2,13 @@
* Enum for different types of tasks that a Sleeve can perform
*/
export enum SleeveTaskType {
// Same Order as selectable order in UI
Idle,
Company,
Faction,
Crime,
Class,
Gym,
Recovery,
Synchro,
// Same Order as selectable order in UI
Idle,
Company,
Faction,
Crime,
Class,
Gym,
Recovery,
Synchro,
}
File diff suppressed because it is too large Load Diff
+106 -70
View File
@@ -1,80 +1,116 @@
import * as React from "react";
export const SleeveFaq = (<>
<strong><u>How do Duplicate Sleeves work?</u></strong>
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>
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 />
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>
Sleeves are their own individuals, which means they each have their own
experience and stats.
<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>
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 />
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>
<strong>
<u>What is Synchronization (Sync)?</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.
</>);
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,92 +2,110 @@
* Root React component for the popup that lets player purchase Duplicate
* Sleeves and Sleeve-related upgrades from The Covenant
*/
import React, { useState } from 'react';
import React, { useState } from "react";
import { CovenantSleeveUpgrades } from "./CovenantSleeveUpgrades";
import { CovenantSleeveUpgrades } from "./CovenantSleeveUpgrades";
import { Sleeve } from "../Sleeve";
import { BaseCostPerSleeve,
MaxSleevesFromCovenant,
PopupId } from "../SleeveCovenantPurchases";
import { IPlayer } from "../../IPlayer";
import { Sleeve } from "../Sleeve";
import {
BaseCostPerSleeve,
MaxSleevesFromCovenant,
PopupId,
} from "../SleeveCovenantPurchases";
import { IPlayer } from "../../IPlayer";
import { PopupCloseButton } from "../../../ui/React/PopupCloseButton";
import { StdButton } from "../../../ui/React/StdButton";
import { Money } from "../../../ui/React/Money";
import { PopupCloseButton } from "../../../ui/React/PopupCloseButton";
import { StdButton } from "../../../ui/React/StdButton";
import { Money } from "../../../ui/React/Money";
import { dialogBoxCreate } from "../../../../utils/DialogBox";
import { dialogBoxCreate } from "../../../../utils/DialogBox";
interface IProps {
closeFn: () => void;
p: IPlayer;
closeFn: () => void;
p: IPlayer;
}
export function CovenantPurchasesRoot(props: IProps): React.ReactElement {
const [update, setUpdate] = useState(0);
const [update, setUpdate] = useState(0);
/**
* Get the cost to purchase a new Duplicate Sleeve
*/
function purchaseCost(): number {
return (props.p.sleevesFromCovenant + 1) * BaseCostPerSleeve;
}
/**
* Get the cost to purchase a new Duplicate Sleeve
*/
function purchaseCost(): number {
return (props.p.sleevesFromCovenant + 1) * BaseCostPerSleeve;
}
/**
* Force a rerender by just changing an arbitrary state value
*/
function rerender(): void {
setUpdate(update + 1);
}
/**
* Force a rerender by just changing an arbitrary state value
*/
function rerender(): void {
setUpdate(update + 1);
}
// Purchasing a new Duplicate Sleeve
let purchaseDisabled = false;
if (!props.p.canAfford(purchaseCost())) {
purchaseDisabled = true;
}
if (props.p.sleevesFromCovenant >= MaxSleevesFromCovenant) {
purchaseDisabled = true;
}
// Purchasing a new Duplicate Sleeve
let purchaseDisabled = false;
if (!props.p.canAfford(purchaseCost())) {
purchaseDisabled = true;
}
if (props.p.sleevesFromCovenant >= MaxSleevesFromCovenant) {
purchaseDisabled = true;
}
function purchaseOnClick(): void {
if (props.p.sleevesFromCovenant >= MaxSleevesFromCovenant) return;
if (props.p.canAfford(purchaseCost())) {
props.p.loseMoney(purchaseCost());
props.p.sleevesFromCovenant += 1;
props.p.sleeves.push(new Sleeve(props.p));
rerender();
} else {
dialogBoxCreate(`You cannot afford to purchase a Duplicate Sleeve`, false);
}
}
function purchaseOnClick(): void {
if (props.p.sleevesFromCovenant >= MaxSleevesFromCovenant) return;
// Purchasing Upgrades for Sleeves
const upgradePanels = [];
for (let i = 0; i < props.p.sleeves.length; ++i) {
const sleeve = props.p.sleeves[i];
upgradePanels.push(
<CovenantSleeveUpgrades {...props} sleeve={sleeve} index={i} rerender={rerender} key={i} />,
)
if (props.p.canAfford(purchaseCost())) {
props.p.loseMoney(purchaseCost());
props.p.sleevesFromCovenant += 1;
props.p.sleeves.push(new Sleeve(props.p));
rerender();
} else {
dialogBoxCreate(
`You cannot afford to purchase a Duplicate Sleeve`,
false,
);
}
}
return (<div>
<PopupCloseButton popup={PopupId} text={"Close"} />
<p>
Would you like to purchase an additional Duplicate Sleeve from The Covenant
for <Money money={purchaseCost()} player={props.p} />?
</p>
<br />
<p>
These Duplicate Sleeves are permanent (they persist through BitNodes). You can
purchase a total of {MaxSleevesFromCovenant} from The Covenant.
</p>
<StdButton disabled={purchaseDisabled} onClick={purchaseOnClick} text={"Purchase"} />
<br /><br />
<p>
Here, you can also purchase upgrades for your Duplicate Sleeves. These upgrades
are also permanent, meaning they persist across BitNodes.
</p>
{upgradePanels}
</div>);
// Purchasing Upgrades for Sleeves
const upgradePanels = [];
for (let i = 0; i < props.p.sleeves.length; ++i) {
const sleeve = props.p.sleeves[i];
upgradePanels.push(
<CovenantSleeveUpgrades
{...props}
sleeve={sleeve}
index={i}
rerender={rerender}
key={i}
/>,
);
}
return (
<div>
<PopupCloseButton popup={PopupId} text={"Close"} />
<p>
Would you like to purchase an additional Duplicate Sleeve from The
Covenant for <Money money={purchaseCost()} player={props.p} />?
</p>
<br />
<p>
These Duplicate Sleeves are permanent (they persist through BitNodes).
You can purchase a total of {MaxSleevesFromCovenant} from The Covenant.
</p>
<StdButton
disabled={purchaseDisabled}
onClick={purchaseOnClick}
text={"Purchase"}
/>
<br />
<br />
<p>
Here, you can also purchase upgrades for your Duplicate Sleeves. These
upgrades are also permanent, meaning they persist across BitNodes.
</p>
{upgradePanels}
</div>
);
}
@@ -12,91 +12,116 @@ import { StdButton } from "../../../ui/React/StdButton";
import { Money } from "../../../ui/React/Money";
interface IProps {
index: number;
p: IPlayer;
rerender: () => void;
sleeve: Sleeve;
index: number;
p: IPlayer;
rerender: () => void;
sleeve: Sleeve;
}
interface IState {
amt: number;
amt: number;
}
export class CovenantSleeveMemoryUpgrade extends React.Component<IProps, IState> {
constructor(props: IProps) {
super(props);
export class CovenantSleeveMemoryUpgrade extends React.Component<
IProps,
IState
> {
constructor(props: IProps) {
super(props);
this.state = {
amt: 1,
}
this.state = {
amt: 1,
};
this.changePurchaseAmount = this.changePurchaseAmount.bind(this);
this.purchaseMemory = this.purchaseMemory.bind(this);
this.changePurchaseAmount = this.changePurchaseAmount.bind(this);
this.purchaseMemory = this.purchaseMemory.bind(this);
}
changePurchaseAmount(e: React.ChangeEvent<HTMLInputElement>): void {
let n: number = parseInt(e.target.value);
if (isNaN(n)) n = 1;
const maxMemory = 100 - this.props.sleeve.memory;
if (n > maxMemory) n = maxMemory;
this.setState({
amt: n,
});
}
getPurchaseCost(): number {
if (isNaN(this.state.amt)) {
return Infinity;
}
changePurchaseAmount(e: React.ChangeEvent<HTMLInputElement>): void {
let n: number = parseInt(e.target.value);
if(isNaN(n)) n = 1;
const maxMemory = 100 - this.props.sleeve.memory;
if (n > maxMemory) n = maxMemory;
this.setState({
amt: n,
});
const maxMemory = 100 - this.props.sleeve.memory;
if (this.state.amt > maxMemory) {
return Infinity;
}
getPurchaseCost(): number {
if (isNaN(this.state.amt)) { return Infinity; }
return this.props.sleeve.getMemoryUpgradeCost(this.state.amt);
}
const maxMemory = 100 - this.props.sleeve.memory;
if (this.state.amt > maxMemory) { return Infinity; }
purchaseMemory(): void {
const cost = this.getPurchaseCost();
if (this.props.p.canAfford(cost)) {
this.props.sleeve.upgradeMemory(this.state.amt);
this.props.p.loseMoney(cost);
this.props.rerender();
}
}
return this.props.sleeve.getMemoryUpgradeCost(this.state.amt);
render(): React.ReactNode {
const inputId = `sleeve-${this.props.index}-memory-upgrade-input`;
// Memory cannot go above 100
const maxMemory = 100 - this.props.sleeve.memory;
// Purchase button props
const cost = this.getPurchaseCost();
const purchaseBtnDisabled = !this.props.p.canAfford(cost);
let purchaseBtnContent;
if (isNaN(this.state.amt)) {
purchaseBtnContent = <>Invalid value</>;
} else if (this.state.amt > maxMemory) {
purchaseBtnContent = <>Memory cannot exceed 100?</>;
} else {
purchaseBtnContent = (
<>
Purchase {this.state.amt} memory -{" "}
<Money money={cost} player={this.props.p} />?
</>
);
}
purchaseMemory(): void {
const cost = this.getPurchaseCost();
if (this.props.p.canAfford(cost)) {
this.props.sleeve.upgradeMemory(this.state.amt);
this.props.p.loseMoney(cost);
this.props.rerender();
}
}
return (
<div>
<h2>
<u>Upgrade Memory</u>
</h2>
<p>
Purchase a memory upgrade for your sleeve. Note that a sleeve's max
memory is 100 (current:{" "}
{numeralWrapper.formatSleeveMemory(this.props.sleeve.memory)})
</p>
render(): React.ReactNode {
const inputId = `sleeve-${this.props.index}-memory-upgrade-input`;
// Memory cannot go above 100
const maxMemory = 100 - this.props.sleeve.memory;
// Purchase button props
const cost = this.getPurchaseCost();
const purchaseBtnDisabled = !this.props.p.canAfford(cost);
let purchaseBtnContent;
if (isNaN(this.state.amt)) {
purchaseBtnContent = <>Invalid value</>;
} else if (this.state.amt > maxMemory) {
purchaseBtnContent = <>Memory cannot exceed 100?</>;
} else {
purchaseBtnContent = <>Purchase {this.state.amt} memory - <Money money={cost} player={this.props.p} />?</>;
}
return (
<div>
<h2><u>Upgrade Memory</u></h2>
<p>
Purchase a memory upgrade for your sleeve. Note that a sleeve's max memory
is 100 (current: {numeralWrapper.formatSleeveMemory(this.props.sleeve.memory)})
</p>
<label htmlFor={inputId}>
Amount of memory to purchase (must be an integer):
</label>
<input className="text-input" id={inputId} onChange={this.changePurchaseAmount} type={"number"} value={this.state.amt} />
<br />
<StdButton disabled={purchaseBtnDisabled} onClick={this.purchaseMemory} text={purchaseBtnContent} />
</div>
)
}
<label htmlFor={inputId}>
Amount of memory to purchase (must be an integer):
</label>
<input
className="text-input"
id={inputId}
onChange={this.changePurchaseAmount}
type={"number"}
value={this.state.amt}
/>
<br />
<StdButton
disabled={purchaseBtnDisabled}
onClick={this.purchaseMemory}
text={purchaseBtnContent}
/>
</div>
);
}
}
@@ -10,19 +10,19 @@ import { Sleeve } from "../Sleeve";
import { IPlayer } from "../../IPlayer";
interface IProps {
index: number;
p: IPlayer;
rerender: () => void;
sleeve: Sleeve;
index: number;
p: IPlayer;
rerender: () => void;
sleeve: Sleeve;
}
export class CovenantSleeveUpgrades extends React.Component<IProps, any> {
render(): React.ReactNode {
return (
<div className={"bladeburner-action"}>
<h1>Duplicate Sleeve {this.props.index}</h1>
<CovenantSleeveMemoryUpgrade {...this.props} />
</div>
)
}
render(): React.ReactNode {
return (
<div className={"bladeburner-action"}>
<h1>Duplicate Sleeve {this.props.index}</h1>
<CovenantSleeveMemoryUpgrade {...this.props} />
</div>
);
}
}
@@ -1,20 +1,31 @@
import * as React from "react";
export function EarningsTableElement(title: string, stats: any[][]): React.ReactElement {
return (<>
<pre>{title}</pre>
<table>
<tbody>
{stats.map((stat: any[], i: number) => <tr key={i}>
{stat.map((s: any, i: number) => {
let style = {};
if(i !== 0) {
style = {textAlign: "right"};
}
return <td style={style} key={i}>{s}</td>
})}
</tr>)}
</tbody>
</table>
</>)
export function EarningsTableElement(
title: string,
stats: any[][],
): React.ReactElement {
return (
<>
<pre>{title}</pre>
<table>
<tbody>
{stats.map((stat: any[], i: number) => (
<tr key={i}>
{stat.map((s: any, i: number) => {
let style = {};
if (i !== 0) {
style = { textAlign: "right" };
}
return (
<td style={style} key={i}>
{s}
</td>
);
})}
</tr>
))}
</tbody>
</table>
</>
);
}
@@ -5,36 +5,101 @@ import * as React from "react";
import { StatsTable } from "../../../ui/React/StatsTable";
export function MoreEarningsContent(sleeve: Sleeve): React.ReactElement {
return (<>
{StatsTable([
['Money ', <Money money={sleeve.earningsForTask.money} />],
['Hacking Exp ', numeralWrapper.formatExp(sleeve.earningsForTask.hack)],
['Strength Exp ', numeralWrapper.formatExp(sleeve.earningsForTask.str)],
['Defense Exp ', numeralWrapper.formatExp(sleeve.earningsForTask.def)],
['Dexterity Exp ', numeralWrapper.formatExp(sleeve.earningsForTask.dex)],
['Agility Exp ', numeralWrapper.formatExp(sleeve.earningsForTask.agi)],
['Charisma Exp ', numeralWrapper.formatExp(sleeve.earningsForTask.cha)],
], 'Earnings for Current Task:')}
<br />
{StatsTable([
['Money: ', <Money money={sleeve.earningsForPlayer.money} />],
['Hacking Exp: ', numeralWrapper.formatExp(sleeve.earningsForPlayer.hack)],
['Strength Exp: ', numeralWrapper.formatExp(sleeve.earningsForPlayer.str)],
['Defense Exp: ', numeralWrapper.formatExp(sleeve.earningsForPlayer.def)],
['Dexterity Exp: ', numeralWrapper.formatExp(sleeve.earningsForPlayer.dex)],
['Agility Exp: ', numeralWrapper.formatExp(sleeve.earningsForPlayer.agi)],
['Charisma Exp: ', numeralWrapper.formatExp(sleeve.earningsForPlayer.cha)],
], 'Total Earnings for Host Consciousness:')}
<br />
{StatsTable([
['Money: ', <Money money={sleeve.earningsForSleeves.money} />],
['Hacking Exp: ', numeralWrapper.formatExp(sleeve.earningsForSleeves.hack)],
['Strength Exp: ', numeralWrapper.formatExp(sleeve.earningsForSleeves.str)],
['Defense Exp: ', numeralWrapper.formatExp(sleeve.earningsForSleeves.def)],
['Dexterity Exp: ', numeralWrapper.formatExp(sleeve.earningsForSleeves.dex)],
['Agility Exp: ', numeralWrapper.formatExp(sleeve.earningsForSleeves.agi)],
['Charisma Exp: ', numeralWrapper.formatExp(sleeve.earningsForSleeves.cha)],
], 'Total Earnings for Other Sleeves:')}
<br />
</>);
}
return (
<>
{StatsTable(
[
["Money ", <Money money={sleeve.earningsForTask.money} />],
[
"Hacking Exp ",
numeralWrapper.formatExp(sleeve.earningsForTask.hack),
],
[
"Strength Exp ",
numeralWrapper.formatExp(sleeve.earningsForTask.str),
],
[
"Defense Exp ",
numeralWrapper.formatExp(sleeve.earningsForTask.def),
],
[
"Dexterity Exp ",
numeralWrapper.formatExp(sleeve.earningsForTask.dex),
],
[
"Agility Exp ",
numeralWrapper.formatExp(sleeve.earningsForTask.agi),
],
[
"Charisma Exp ",
numeralWrapper.formatExp(sleeve.earningsForTask.cha),
],
],
"Earnings for Current Task:",
)}
<br />
{StatsTable(
[
["Money: ", <Money money={sleeve.earningsForPlayer.money} />],
[
"Hacking Exp: ",
numeralWrapper.formatExp(sleeve.earningsForPlayer.hack),
],
[
"Strength Exp: ",
numeralWrapper.formatExp(sleeve.earningsForPlayer.str),
],
[
"Defense Exp: ",
numeralWrapper.formatExp(sleeve.earningsForPlayer.def),
],
[
"Dexterity Exp: ",
numeralWrapper.formatExp(sleeve.earningsForPlayer.dex),
],
[
"Agility Exp: ",
numeralWrapper.formatExp(sleeve.earningsForPlayer.agi),
],
[
"Charisma Exp: ",
numeralWrapper.formatExp(sleeve.earningsForPlayer.cha),
],
],
"Total Earnings for Host Consciousness:",
)}
<br />
{StatsTable(
[
["Money: ", <Money money={sleeve.earningsForSleeves.money} />],
[
"Hacking Exp: ",
numeralWrapper.formatExp(sleeve.earningsForSleeves.hack),
],
[
"Strength Exp: ",
numeralWrapper.formatExp(sleeve.earningsForSleeves.str),
],
[
"Defense Exp: ",
numeralWrapper.formatExp(sleeve.earningsForSleeves.def),
],
[
"Dexterity Exp: ",
numeralWrapper.formatExp(sleeve.earningsForSleeves.dex),
],
[
"Agility Exp: ",
numeralWrapper.formatExp(sleeve.earningsForSleeves.agi),
],
[
"Charisma Exp: ",
numeralWrapper.formatExp(sleeve.earningsForSleeves.cha),
],
],
"Total Earnings for Other Sleeves:",
)}
<br />
</>
);
}
+114 -31
View File
@@ -4,34 +4,117 @@ import { StatsTable } from "../../../ui/React/StatsTable";
import * as React from "react";
export function MoreStatsContent(sleeve: Sleeve): React.ReactElement {
return (<>
{StatsTable([
['Hacking: ', sleeve.hacking_skill, `(${numeralWrapper.formatExp(sleeve.hacking_exp)} exp)`],
['Strength: ', sleeve.strength, `(${numeralWrapper.formatExp(sleeve.strength_exp)} exp)`],
['Defense: ', sleeve.defense, `(${numeralWrapper.formatExp(sleeve.defense_exp)} exp)`],
['Dexterity: ', sleeve.dexterity, `(${numeralWrapper.formatExp(sleeve.dexterity_exp)} exp)`],
['Agility: ', sleeve.agility, `(${numeralWrapper.formatExp(sleeve.agility_exp)} exp)`],
['Charisma: ', sleeve.charisma, `(${numeralWrapper.formatExp(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:')}
</>);
}
return (
<>
{StatsTable(
[
[
"Hacking: ",
sleeve.hacking_skill,
`(${numeralWrapper.formatExp(sleeve.hacking_exp)} exp)`,
],
[
"Strength: ",
sleeve.strength,
`(${numeralWrapper.formatExp(sleeve.strength_exp)} exp)`,
],
[
"Defense: ",
sleeve.defense,
`(${numeralWrapper.formatExp(sleeve.defense_exp)} exp)`,
],
[
"Dexterity: ",
sleeve.dexterity,
`(${numeralWrapper.formatExp(sleeve.dexterity_exp)} exp)`,
],
[
"Agility: ",
sleeve.agility,
`(${numeralWrapper.formatExp(sleeve.agility_exp)} exp)`,
],
[
"Charisma: ",
sleeve.charisma,
`(${numeralWrapper.formatExp(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:",
)}
</>
);
}
+75 -52
View File
@@ -3,56 +3,79 @@ import { numeralWrapper } from "../../../ui/numeralFormat";
import * as React from "react";
export function StatsElement(sleeve: Sleeve): React.ReactElement {
let style = {};
style = { textAlign: "right" };
return (<>
<table>
<tbody>
<tr>
<td className="character-hp-cell">HP: </td>
<td className="character-hp-cell" style={style}>{numeralWrapper.formatHp(sleeve.hp)} / {numeralWrapper.formatHp(sleeve.max_hp)}</td>
</tr>
<tr>
<td>City: </td>
<td style={style}>{sleeve.city}</td>
</tr>
<tr>
<td className="character-hack-cell">Hacking: </td>
<td className="character-hack-cell" style={style}>{numeralWrapper.formatSkill(sleeve.hacking_skill)}</td>
</tr>
<tr>
<td className="character-combat-cell">Strength: </td>
<td className="character-combat-cell" style={style}>{numeralWrapper.formatSkill(sleeve.strength)}</td>
</tr>
<tr>
<td className="character-combat-cell">Defense: </td>
<td className="character-combat-cell" style={style}>{numeralWrapper.formatSkill(sleeve.defense)}</td>
</tr>
<tr>
<td className="character-combat-cell">Dexterity: </td>
<td className="character-combat-cell" style={style}>{numeralWrapper.formatSkill(sleeve.dexterity)}</td>
</tr>
<tr>
<td className="character-combat-cell">Agility: </td>
<td className="character-combat-cell" style={style}>{numeralWrapper.formatSkill(sleeve.agility)}</td>
</tr>
<tr>
<td className="character-cha-cell">Charisma: </td>
<td className="character-cha-cell" style={style}>{numeralWrapper.formatSkill(sleeve.charisma)}</td>
</tr>
<tr>
<td className="character-int-cell">Shock: </td>
<td className="character-int-cell" style={style}>{numeralWrapper.formatSleeveShock(100 - sleeve.shock)}</td>
</tr>
<tr>
<td className="character-int-cell">Sync: </td>
<td className="character-int-cell" style={style}>{numeralWrapper.formatSleeveSynchro(sleeve.sync)}</td>
</tr>
<tr>
<td className="character-int-cell">Memory: </td>
<td className="character-int-cell" style={style}>{numeralWrapper.formatSleeveMemory(sleeve.memory)}</td>
</tr>
</tbody>
</table>
</>)
let style = {};
style = { textAlign: "right" };
return (
<>
<table>
<tbody>
<tr>
<td className="character-hp-cell">HP: </td>
<td className="character-hp-cell" style={style}>
{numeralWrapper.formatHp(sleeve.hp)} /{" "}
{numeralWrapper.formatHp(sleeve.max_hp)}
</td>
</tr>
<tr>
<td>City: </td>
<td style={style}>{sleeve.city}</td>
</tr>
<tr>
<td className="character-hack-cell">Hacking: </td>
<td className="character-hack-cell" style={style}>
{numeralWrapper.formatSkill(sleeve.hacking_skill)}
</td>
</tr>
<tr>
<td className="character-combat-cell">Strength: </td>
<td className="character-combat-cell" style={style}>
{numeralWrapper.formatSkill(sleeve.strength)}
</td>
</tr>
<tr>
<td className="character-combat-cell">Defense: </td>
<td className="character-combat-cell" style={style}>
{numeralWrapper.formatSkill(sleeve.defense)}
</td>
</tr>
<tr>
<td className="character-combat-cell">Dexterity: </td>
<td className="character-combat-cell" style={style}>
{numeralWrapper.formatSkill(sleeve.dexterity)}
</td>
</tr>
<tr>
<td className="character-combat-cell">Agility: </td>
<td className="character-combat-cell" style={style}>
{numeralWrapper.formatSkill(sleeve.agility)}
</td>
</tr>
<tr>
<td className="character-cha-cell">Charisma: </td>
<td className="character-cha-cell" style={style}>
{numeralWrapper.formatSkill(sleeve.charisma)}
</td>
</tr>
<tr>
<td className="character-int-cell">Shock: </td>
<td className="character-int-cell" style={style}>
{numeralWrapper.formatSleeveShock(100 - sleeve.shock)}
</td>
</tr>
<tr>
<td className="character-int-cell">Sync: </td>
<td className="character-int-cell" style={style}>
{numeralWrapper.formatSleeveSynchro(sleeve.sync)}
</td>
</tr>
<tr>
<td className="character-int-cell">Memory: </td>
<td className="character-int-cell" style={style}>
{numeralWrapper.formatSleeveMemory(sleeve.memory)}
</td>
</tr>
</tbody>
</table>
</>
);
}