mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-22 23:53:48 +01:00
resleeve in react
This commit is contained in:
parent
4e22b880bb
commit
ab8937870c
@ -3,7 +3,12 @@
|
||||
*/
|
||||
@import "theme";
|
||||
|
||||
.resleeve-container {
|
||||
#resleeve-container {
|
||||
position: fixed;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.resleeve-elem {
|
||||
border: 1px solid white;
|
||||
margin: 4px;
|
||||
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 GangRoot } from "./Gang/ui/Root";
|
||||
import { CorporationRoot } from "./Corporation/ui/CorporationRoot";
|
||||
import { ResleeveRoot } from "./PersonObjects/Resleeving/ui/ResleeveRoot";
|
||||
import { displayInfiltrationContent } from "./Infiltration/Helper";
|
||||
import {
|
||||
getHackingWorkRepGain,
|
||||
@ -189,6 +190,7 @@ const Engine = {
|
||||
stockMarketContent: null,
|
||||
gangContent: null,
|
||||
bladeburnerContent: null,
|
||||
resleeveContent: null,
|
||||
corporationContent: null,
|
||||
locationContent: null,
|
||||
workInProgressContent: null,
|
||||
@ -439,13 +441,10 @@ const Engine = {
|
||||
},
|
||||
|
||||
loadResleevingContent: function () {
|
||||
try {
|
||||
Engine.hideAllContent();
|
||||
routing.navigateTo(Page.Resleeves);
|
||||
createResleevesPage(Player);
|
||||
} catch (e) {
|
||||
exceptionAlert(e);
|
||||
}
|
||||
Engine.hideAllContent();
|
||||
routing.navigateTo(Page.Resleeves);
|
||||
Engine.Display.resleeveContent.style.display = "block";
|
||||
ReactDOM.render(<ResleeveRoot player={Player} />, Engine.Display.resleeveContent);
|
||||
},
|
||||
|
||||
// Helper function that hides all content
|
||||
@ -486,16 +485,21 @@ const Engine = {
|
||||
Engine.Display.bladeburnerContent.style.display = "none";
|
||||
ReactDOM.unmountComponentAtNode(Engine.Display.bladeburnerContent);
|
||||
|
||||
Engine.Display.resleeveContent.style.display = "none";
|
||||
ReactDOM.unmountComponentAtNode(Engine.Display.resleeveContent);
|
||||
|
||||
Engine.Display.corporationContent.style.display = "none";
|
||||
ReactDOM.unmountComponentAtNode(Engine.Display.corporationContent);
|
||||
|
||||
Engine.Display.resleeveContent.style.display = "none";
|
||||
ReactDOM.unmountComponentAtNode(Engine.Display.resleeveContent);
|
||||
|
||||
Engine.Display.workInProgressContent.style.display = "none";
|
||||
Engine.Display.redPillContent.style.display = "none";
|
||||
Engine.Display.cinematicTextContent.style.display = "none";
|
||||
Engine.Display.stockMarketContent.style.display = "none";
|
||||
Engine.Display.missionContent.style.display = "none";
|
||||
|
||||
clearResleevesPage();
|
||||
clearSleevesPage();
|
||||
|
||||
// Make nav menu tabs inactive
|
||||
@ -1252,6 +1256,9 @@ const Engine = {
|
||||
Engine.Display.bladeburnerContent = document.getElementById("bladeburner-container");
|
||||
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.style.display = "none";
|
||||
|
||||
|
@ -364,6 +364,7 @@
|
||||
<div id="infiltration-container" class="generic-fullscreen-container"></div>
|
||||
<div id="stock-market-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="corporation-container" class="generic-menupage-container"></div>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user