mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-26 09:33:49 +01:00
resleeve in react
This commit is contained in:
parent
4e22b880bb
commit
ab8937870c
@ -3,7 +3,12 @@
|
|||||||
*/
|
*/
|
||||||
@import "theme";
|
@import "theme";
|
||||||
|
|
||||||
.resleeve-container {
|
#resleeve-container {
|
||||||
|
position: fixed;
|
||||||
|
padding: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resleeve-elem {
|
||||||
border: 1px solid white;
|
border: 1px solid white;
|
||||||
margin: 4px;
|
margin: 4px;
|
||||||
width: 75%;
|
width: 75%;
|
||||||
|
159
src/PersonObjects/Resleeving/ui/ResleeveElem.tsx
Normal file
159
src/PersonObjects/Resleeving/ui/ResleeveElem.tsx
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import { IPlayer } from "../../IPlayer";
|
||||||
|
import { Resleeve } from "../Resleeve";
|
||||||
|
import { Augmentations } from "../../../Augmentation/Augmentations";
|
||||||
|
import { generateResleeves, purchaseResleeve } from "../Resleeving";
|
||||||
|
import { Money } from "../../../ui/React/Money";
|
||||||
|
|
||||||
|
import { numeralWrapper } from "../../../ui/numeralFormat";
|
||||||
|
import { dialogBoxCreate } from "../../../../utils/DialogBox";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
resleeve: Resleeve;
|
||||||
|
player: IPlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ResleeveElem(props: IProps): React.ReactElement {
|
||||||
|
const [aug, setAug] = useState(props.resleeve.augmentations[0].name);
|
||||||
|
|
||||||
|
function openStats(): void {
|
||||||
|
dialogBoxCreate(
|
||||||
|
<>
|
||||||
|
<h2>
|
||||||
|
<u>Total Multipliers:</u>
|
||||||
|
</h2>
|
||||||
|
Hacking Level multiplier: {numeralWrapper.formatPercentage(props.resleeve.hacking_mult)}
|
||||||
|
<br />
|
||||||
|
Hacking Experience multiplier: {numeralWrapper.formatPercentage(props.resleeve.hacking_exp_mult)}
|
||||||
|
<br />
|
||||||
|
Strength Level multiplier: {numeralWrapper.formatPercentage(props.resleeve.strength_mult)}
|
||||||
|
<br />
|
||||||
|
Strength Experience multiplier: {numeralWrapper.formatPercentage(props.resleeve.strength_exp_mult)}
|
||||||
|
<br />
|
||||||
|
Defense Level multiplier: {numeralWrapper.formatPercentage(props.resleeve.defense_mult)}
|
||||||
|
<br />
|
||||||
|
Defense Experience multiplier: {numeralWrapper.formatPercentage(props.resleeve.defense_exp_mult)}
|
||||||
|
<br />
|
||||||
|
Dexterity Level multiplier: {numeralWrapper.formatPercentage(props.resleeve.dexterity_mult)}
|
||||||
|
<br />
|
||||||
|
Dexterity Experience multiplier: {numeralWrapper.formatPercentage(props.resleeve.dexterity_exp_mult)}
|
||||||
|
<br />
|
||||||
|
Agility Level multiplier: {numeralWrapper.formatPercentage(props.resleeve.agility_mult)}
|
||||||
|
<br />
|
||||||
|
Agility Experience multiplier: {numeralWrapper.formatPercentage(props.resleeve.agility_exp_mult)}
|
||||||
|
<br />
|
||||||
|
Charisma Level multiplier: {numeralWrapper.formatPercentage(props.resleeve.charisma_mult)}
|
||||||
|
<br />
|
||||||
|
Charisma Experience multiplier: {numeralWrapper.formatPercentage(props.resleeve.charisma_exp_mult)}
|
||||||
|
<br />
|
||||||
|
Hacking Chance multiplier: {numeralWrapper.formatPercentage(props.resleeve.hacking_chance_mult)}
|
||||||
|
<br />
|
||||||
|
Hacking Speed multiplier: {numeralWrapper.formatPercentage(props.resleeve.hacking_speed_mult)}
|
||||||
|
<br />
|
||||||
|
Hacking Money multiplier: {numeralWrapper.formatPercentage(props.resleeve.hacking_money_mult)}
|
||||||
|
<br />
|
||||||
|
Hacking Growth multiplier: {numeralWrapper.formatPercentage(props.resleeve.hacking_grow_mult)}
|
||||||
|
<br />
|
||||||
|
Salary multiplier: {numeralWrapper.formatPercentage(props.resleeve.work_money_mult)}
|
||||||
|
<br />
|
||||||
|
Company Reputation Gain multiplier: {numeralWrapper.formatPercentage(props.resleeve.company_rep_mult)}
|
||||||
|
<br />
|
||||||
|
Faction Reputation Gain multiplier: {numeralWrapper.formatPercentage(props.resleeve.faction_rep_mult)}
|
||||||
|
<br />
|
||||||
|
Crime Money multiplier: {numeralWrapper.formatPercentage(props.resleeve.crime_money_mult)}
|
||||||
|
<br />
|
||||||
|
Crime Success multiplier: {numeralWrapper.formatPercentage(props.resleeve.crime_success_mult)}
|
||||||
|
<br />
|
||||||
|
Hacknet Income multiplier: {numeralWrapper.formatPercentage(props.resleeve.hacknet_node_money_mult)}
|
||||||
|
<br />
|
||||||
|
Hacknet Purchase Cost multiplier:
|
||||||
|
{numeralWrapper.formatPercentage(props.resleeve.hacknet_node_purchase_cost_mult)}
|
||||||
|
<br />
|
||||||
|
Hacknet Level Upgrade Cost multiplier:
|
||||||
|
{numeralWrapper.formatPercentage(props.resleeve.hacknet_node_level_cost_mult)}
|
||||||
|
<br />
|
||||||
|
Hacknet Ram Upgrade Cost multiplier:
|
||||||
|
{numeralWrapper.formatPercentage(props.resleeve.hacknet_node_ram_cost_mult)}
|
||||||
|
<br />
|
||||||
|
Hacknet Core Upgrade Cost multiplier:
|
||||||
|
{numeralWrapper.formatPercentage(props.resleeve.hacknet_node_core_cost_mult)}
|
||||||
|
<br />
|
||||||
|
Bladeburner Max Stamina multiplier:
|
||||||
|
{numeralWrapper.formatPercentage(props.resleeve.bladeburner_max_stamina_mult)}
|
||||||
|
<br />
|
||||||
|
Bladeburner Stamina Gain multiplier:
|
||||||
|
{numeralWrapper.formatPercentage(props.resleeve.bladeburner_stamina_gain_mult)}
|
||||||
|
<br />
|
||||||
|
Bladeburner Field Analysis multiplier:
|
||||||
|
{numeralWrapper.formatPercentage(props.resleeve.bladeburner_analysis_mult)}
|
||||||
|
<br />
|
||||||
|
Bladeburner Success Chance multiplier:
|
||||||
|
{numeralWrapper.formatPercentage(props.resleeve.bladeburner_success_chance_mult)}
|
||||||
|
</>,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onAugChange(event: React.ChangeEvent<HTMLSelectElement>): void {
|
||||||
|
setAug(event.target.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentAug = Augmentations[aug];
|
||||||
|
const cost = props.resleeve.getCost();
|
||||||
|
|
||||||
|
function purchase(): void {
|
||||||
|
if (!purchaseResleeve(props.resleeve, props.player)) return;
|
||||||
|
dialogBoxCreate(
|
||||||
|
<>
|
||||||
|
You re-sleeved for <Money money={cost} />!
|
||||||
|
</>,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="resleeve-elem" style={{ display: "block" }}>
|
||||||
|
<div className="resleeve-panel" style={{ width: "30%" }}>
|
||||||
|
<p>
|
||||||
|
Hacking: {numeralWrapper.formatSkill(props.resleeve.hacking_skill)} (
|
||||||
|
{numeralWrapper.formatExp(props.resleeve.hacking_exp)} exp)
|
||||||
|
<br />
|
||||||
|
Strength: {numeralWrapper.formatSkill(props.resleeve.strength)} (
|
||||||
|
{numeralWrapper.formatExp(props.resleeve.strength_exp)} exp)
|
||||||
|
<br />
|
||||||
|
Defense: {numeralWrapper.formatSkill(props.resleeve.defense)} (
|
||||||
|
{numeralWrapper.formatExp(props.resleeve.defense_exp)} exp)
|
||||||
|
<br />
|
||||||
|
Dexterity: {numeralWrapper.formatSkill(props.resleeve.dexterity)} (
|
||||||
|
{numeralWrapper.formatExp(props.resleeve.dexterity_exp)} exp)
|
||||||
|
<br />
|
||||||
|
Agility: {numeralWrapper.formatSkill(props.resleeve.agility)} (
|
||||||
|
{numeralWrapper.formatExp(props.resleeve.agility_exp)} exp)
|
||||||
|
<br />
|
||||||
|
Charisma: {numeralWrapper.formatSkill(props.resleeve.charisma)} (
|
||||||
|
{numeralWrapper.formatExp(props.resleeve.charisma_exp)} exp)
|
||||||
|
<br /># Augmentations: {props.resleeve.augmentations.length}
|
||||||
|
</p>
|
||||||
|
<button className="std-button" onClick={openStats}>
|
||||||
|
Multipliers
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="resleeve-panel" style={{ width: "50%" }}>
|
||||||
|
<select className="resleeve-aug-selector dropdown" onChange={onAugChange}>
|
||||||
|
{props.resleeve.augmentations.map((aug) => (
|
||||||
|
<option key={aug.name} value={aug.name}>
|
||||||
|
{aug.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
<p>{currentAug !== undefined && currentAug.info}</p>
|
||||||
|
</div>
|
||||||
|
<div className="resleeve-panel" style={{ width: "20%" }}>
|
||||||
|
<p>
|
||||||
|
It costs <Money money={cost} player={props.player} /> to purchase this Sleeve.
|
||||||
|
</p>
|
||||||
|
<button className="std-button" onClick={purchase}>
|
||||||
|
Purchase
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
121
src/PersonObjects/Resleeving/ui/ResleeveRoot.tsx
Normal file
121
src/PersonObjects/Resleeving/ui/ResleeveRoot.tsx
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
|
||||||
|
import { IPlayer } from "../../IPlayer";
|
||||||
|
import { generateResleeves, purchaseResleeve } from "../Resleeving";
|
||||||
|
import { Resleeve } from "../Resleeve";
|
||||||
|
import { ResleeveElem } from "./ResleeveElem";
|
||||||
|
|
||||||
|
const SortOption: {
|
||||||
|
[key: string]: string | undefined;
|
||||||
|
Cost: string;
|
||||||
|
Hacking: string;
|
||||||
|
Strength: string;
|
||||||
|
Defense: string;
|
||||||
|
Dexterity: string;
|
||||||
|
Agility: string;
|
||||||
|
Charisma: string;
|
||||||
|
AverageCombatStats: string;
|
||||||
|
AverageAllStats: string;
|
||||||
|
TotalNumAugmentations: string;
|
||||||
|
} = {
|
||||||
|
Cost: "Cost",
|
||||||
|
Hacking: "Hacking Level",
|
||||||
|
Strength: "Strength Level",
|
||||||
|
Defense: "Defense Level",
|
||||||
|
Dexterity: "Dexterity Level",
|
||||||
|
Agility: "Agility Level",
|
||||||
|
Charisma: "Charisma Level",
|
||||||
|
AverageCombatStats: "Average Combat Stats",
|
||||||
|
AverageAllStats: "Average Stats",
|
||||||
|
TotalNumAugmentations: "Number of Augmentations",
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper function for averaging
|
||||||
|
function getAverage(...values: number[]): number {
|
||||||
|
let sum = 0;
|
||||||
|
for (let i = 0; i < values.length; ++i) {
|
||||||
|
sum += values[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum / values.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SortFunctions: {
|
||||||
|
[key: string]: ((a: Resleeve, b: Resleeve) => number) | undefined;
|
||||||
|
Cost: (a: Resleeve, b: Resleeve) => number;
|
||||||
|
Hacking: (a: Resleeve, b: Resleeve) => number;
|
||||||
|
Strength: (a: Resleeve, b: Resleeve) => number;
|
||||||
|
Defense: (a: Resleeve, b: Resleeve) => number;
|
||||||
|
Dexterity: (a: Resleeve, b: Resleeve) => number;
|
||||||
|
Agility: (a: Resleeve, b: Resleeve) => number;
|
||||||
|
Charisma: (a: Resleeve, b: Resleeve) => number;
|
||||||
|
AverageCombatStats: (a: Resleeve, b: Resleeve) => number;
|
||||||
|
AverageAllStats: (a: Resleeve, b: Resleeve) => number;
|
||||||
|
TotalNumAugmentations: (a: Resleeve, b: Resleeve) => number;
|
||||||
|
} = {
|
||||||
|
Cost: (a: Resleeve, b: Resleeve): number => a.getCost() - b.getCost(),
|
||||||
|
Hacking: (a: Resleeve, b: Resleeve): number => a.hacking_skill - b.hacking_skill,
|
||||||
|
Strength: (a: Resleeve, b: Resleeve): number => a.strength - b.strength,
|
||||||
|
Defense: (a: Resleeve, b: Resleeve): number => a.defense - b.defense,
|
||||||
|
Dexterity: (a: Resleeve, b: Resleeve): number => a.dexterity - b.dexterity,
|
||||||
|
Agility: (a: Resleeve, b: Resleeve): number => a.agility - b.agility,
|
||||||
|
Charisma: (a: Resleeve, b: Resleeve): number => a.charisma - b.charisma,
|
||||||
|
AverageCombatStats: (a: Resleeve, b: Resleeve): number =>
|
||||||
|
getAverage(a.strength, a.defense, a.dexterity, a.agility) -
|
||||||
|
getAverage(b.strength, b.defense, b.dexterity, b.agility),
|
||||||
|
AverageAllStats: (a: Resleeve, b: Resleeve): number =>
|
||||||
|
getAverage(a.hacking_skill, a.strength, a.defense, a.dexterity, a.agility, a.charisma) -
|
||||||
|
getAverage(b.hacking_skill, b.strength, b.defense, b.dexterity, b.agility, b.charisma),
|
||||||
|
TotalNumAugmentations: (a: Resleeve, b: Resleeve): number => a.augmentations.length - b.augmentations.length,
|
||||||
|
};
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
player: IPlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ResleeveRoot(props: IProps): React.ReactElement {
|
||||||
|
const [sort, setSort] = useState(SortOption.Cost);
|
||||||
|
// Randomly create all Resleeves if they dont already exist
|
||||||
|
if (props.player.resleeves.length === 0) {
|
||||||
|
props.player.resleeves = generateResleeves();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSortChange(event: React.ChangeEvent<HTMLSelectElement>): void {
|
||||||
|
setSort(event.target.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
const sortFunction = SortFunctions[sort];
|
||||||
|
if (sortFunction === undefined) throw new Error(`sort function '${sort}' is undefined`);
|
||||||
|
props.player.resleeves.sort(sortFunction);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p style={{ display: "block", width: "75%" }}>
|
||||||
|
Re-sleeving is the process of digitizing and transferring your consciousness into a new human body, or 'sleeve'.
|
||||||
|
Here at VitaLife, you can purchase new specially-engineered bodies for the re-sleeve process. Many of these
|
||||||
|
bodies even come with genetic and cybernetic Augmentations!
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Re-sleeving will change your experience for every stat. It will also REMOVE all of your currently-installed
|
||||||
|
Augmentations, and replace them with the ones provided by the purchased sleeve. However, Augmentations that you
|
||||||
|
have purchased but not installed will NOT be removed. If you have purchased an Augmentation and then re-sleeve
|
||||||
|
into a body which already has that Augmentation, it will be removed (since you cannot have duplicate
|
||||||
|
Augmentations).
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
NOTE: The stats and multipliers displayed on this page do NOT include your bonuses from Source-File.
|
||||||
|
</p>
|
||||||
|
<p style={{ display: "inline-block" }}>Sort By: </p>
|
||||||
|
<select className="dropdown" defaultValue={sort} onChange={onSortChange}>
|
||||||
|
{Object.keys(SortOption).map((opt) => (
|
||||||
|
<option key={opt} value={opt}>
|
||||||
|
{SortOption[opt]}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
{props.player.resleeves.map((resleeve, i) => (
|
||||||
|
<ResleeveElem key={i} player={props.player} resleeve={resleeve} />
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -22,6 +22,7 @@ import { FactionList } from "./Faction/ui/FactionList";
|
|||||||
import { Root as BladeburnerRoot } from "./Bladeburner/ui/Root";
|
import { Root as BladeburnerRoot } from "./Bladeburner/ui/Root";
|
||||||
import { Root as GangRoot } from "./Gang/ui/Root";
|
import { Root as GangRoot } from "./Gang/ui/Root";
|
||||||
import { CorporationRoot } from "./Corporation/ui/CorporationRoot";
|
import { CorporationRoot } from "./Corporation/ui/CorporationRoot";
|
||||||
|
import { ResleeveRoot } from "./PersonObjects/Resleeving/ui/ResleeveRoot";
|
||||||
import { displayInfiltrationContent } from "./Infiltration/Helper";
|
import { displayInfiltrationContent } from "./Infiltration/Helper";
|
||||||
import {
|
import {
|
||||||
getHackingWorkRepGain,
|
getHackingWorkRepGain,
|
||||||
@ -189,6 +190,7 @@ const Engine = {
|
|||||||
stockMarketContent: null,
|
stockMarketContent: null,
|
||||||
gangContent: null,
|
gangContent: null,
|
||||||
bladeburnerContent: null,
|
bladeburnerContent: null,
|
||||||
|
resleeveContent: null,
|
||||||
corporationContent: null,
|
corporationContent: null,
|
||||||
locationContent: null,
|
locationContent: null,
|
||||||
workInProgressContent: null,
|
workInProgressContent: null,
|
||||||
@ -439,13 +441,10 @@ const Engine = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
loadResleevingContent: function () {
|
loadResleevingContent: function () {
|
||||||
try {
|
Engine.hideAllContent();
|
||||||
Engine.hideAllContent();
|
routing.navigateTo(Page.Resleeves);
|
||||||
routing.navigateTo(Page.Resleeves);
|
Engine.Display.resleeveContent.style.display = "block";
|
||||||
createResleevesPage(Player);
|
ReactDOM.render(<ResleeveRoot player={Player} />, Engine.Display.resleeveContent);
|
||||||
} catch (e) {
|
|
||||||
exceptionAlert(e);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Helper function that hides all content
|
// Helper function that hides all content
|
||||||
@ -486,16 +485,21 @@ const Engine = {
|
|||||||
Engine.Display.bladeburnerContent.style.display = "none";
|
Engine.Display.bladeburnerContent.style.display = "none";
|
||||||
ReactDOM.unmountComponentAtNode(Engine.Display.bladeburnerContent);
|
ReactDOM.unmountComponentAtNode(Engine.Display.bladeburnerContent);
|
||||||
|
|
||||||
|
Engine.Display.resleeveContent.style.display = "none";
|
||||||
|
ReactDOM.unmountComponentAtNode(Engine.Display.resleeveContent);
|
||||||
|
|
||||||
Engine.Display.corporationContent.style.display = "none";
|
Engine.Display.corporationContent.style.display = "none";
|
||||||
ReactDOM.unmountComponentAtNode(Engine.Display.corporationContent);
|
ReactDOM.unmountComponentAtNode(Engine.Display.corporationContent);
|
||||||
|
|
||||||
|
Engine.Display.resleeveContent.style.display = "none";
|
||||||
|
ReactDOM.unmountComponentAtNode(Engine.Display.resleeveContent);
|
||||||
|
|
||||||
Engine.Display.workInProgressContent.style.display = "none";
|
Engine.Display.workInProgressContent.style.display = "none";
|
||||||
Engine.Display.redPillContent.style.display = "none";
|
Engine.Display.redPillContent.style.display = "none";
|
||||||
Engine.Display.cinematicTextContent.style.display = "none";
|
Engine.Display.cinematicTextContent.style.display = "none";
|
||||||
Engine.Display.stockMarketContent.style.display = "none";
|
Engine.Display.stockMarketContent.style.display = "none";
|
||||||
Engine.Display.missionContent.style.display = "none";
|
Engine.Display.missionContent.style.display = "none";
|
||||||
|
|
||||||
clearResleevesPage();
|
|
||||||
clearSleevesPage();
|
clearSleevesPage();
|
||||||
|
|
||||||
// Make nav menu tabs inactive
|
// Make nav menu tabs inactive
|
||||||
@ -1252,6 +1256,9 @@ const Engine = {
|
|||||||
Engine.Display.bladeburnerContent = document.getElementById("bladeburner-container");
|
Engine.Display.bladeburnerContent = document.getElementById("bladeburner-container");
|
||||||
Engine.Display.bladeburnerContent.style.display = "none";
|
Engine.Display.bladeburnerContent.style.display = "none";
|
||||||
|
|
||||||
|
Engine.Display.resleeveContent = document.getElementById("resleeve-container");
|
||||||
|
Engine.Display.resleeveContent.style.display = "none";
|
||||||
|
|
||||||
Engine.Display.corporationContent = document.getElementById("corporation-container");
|
Engine.Display.corporationContent = document.getElementById("corporation-container");
|
||||||
Engine.Display.corporationContent.style.display = "none";
|
Engine.Display.corporationContent.style.display = "none";
|
||||||
|
|
||||||
|
@ -364,6 +364,7 @@
|
|||||||
<div id="infiltration-container" class="generic-fullscreen-container"></div>
|
<div id="infiltration-container" class="generic-fullscreen-container"></div>
|
||||||
<div id="stock-market-container" class="generic-menupage-container"></div>
|
<div id="stock-market-container" class="generic-menupage-container"></div>
|
||||||
<div id="bladeburner-container" class="generic-menupage-container"></div>
|
<div id="bladeburner-container" class="generic-menupage-container"></div>
|
||||||
|
<div id="resleeve-container" class="generic-menupage-container"></div>
|
||||||
<div id="gang-container" class="generic-menupage-container"></div>
|
<div id="gang-container" class="generic-menupage-container"></div>
|
||||||
<div id="corporation-container" class="generic-menupage-container"></div>
|
<div id="corporation-container" class="generic-menupage-container"></div>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user