resleeve in react

This commit is contained in:
Olivier Gagnon 2021-09-09 15:19:11 -04:00
parent 4e22b880bb
commit ab8937870c
5 changed files with 302 additions and 9 deletions

@ -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%;

@ -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>
);
}

@ -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);
createResleevesPage(Player); Engine.Display.resleeveContent.style.display = "block";
} catch (e) { ReactDOM.render(<ResleeveRoot player={Player} />, Engine.Display.resleeveContent);
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>