diff --git a/src/PersonObjects/Resleeving/ResleevingUI.tsx b/src/PersonObjects/Resleeving/ResleevingUI.tsx
deleted file mode 100644
index 64ac8e0b1..000000000
--- a/src/PersonObjects/Resleeving/ResleevingUI.tsx
+++ /dev/null
@@ -1,428 +0,0 @@
-/**
- * Module for handling the Re-sleeving UI
- */
-import { Resleeve } from "./Resleeve";
-import { generateResleeves, purchaseResleeve } from "./Resleeving";
-
-import { IPlayer } from "../IPlayer";
-
-import { Augmentation } from "../../Augmentation/Augmentation";
-import { Augmentations } from "../../Augmentation/Augmentations";
-
-import { numeralWrapper } from "../../ui/numeralFormat";
-import { Money } from "../../ui/React/Money";
-import { Page, routing } from "../../ui/navigationTracking";
-
-import { dialogBoxCreate } from "../../../utils/DialogBox";
-
-import { exceptionAlert } from "../../../utils/helpers/exceptionAlert";
-
-import { createElement } from "../../../utils/uiHelpers/createElement";
-import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
-import { getSelectValue } from "../../../utils/uiHelpers/getSelectData";
-import { removeChildrenFromElement } from "../../../utils/uiHelpers/removeChildrenFromElement";
-import { removeElement } from "../../../utils/uiHelpers/removeElement";
-
-import * as React from "react";
-import { renderToStaticMarkup } from "react-dom/server";
-
-interface IResleeveUIElems {
- container: HTMLElement | null;
- statsPanel: HTMLElement | null;
- stats: HTMLElement | null;
- multipliersButton: HTMLElement | null;
- augPanel: HTMLElement | null;
- augSelector: HTMLSelectElement | null;
- augDescription: HTMLElement | null;
- costPanel: HTMLElement | null;
- costText: HTMLElement | null;
- buyButton: HTMLElement | null;
-}
-
-interface IPageUIElems {
- container: HTMLElement | null;
- info: HTMLElement | null;
- sortTag: HTMLElement | null;
- sortSelector: HTMLSelectElement | null;
- resleeveList: HTMLElement | null;
- resleeves: IResleeveUIElems[] | null;
-}
-
-const UIElems: IPageUIElems = {
- container: null,
- info: null,
- sortTag: null,
- sortSelector: null,
- resleeveList: null,
- resleeves: null,
-};
-
-let playerRef: IPlayer | null;
-
-export function createResleevesPage(p: IPlayer): void {
- if (!routing.isOn(Page.Resleeves)) {
- return;
- }
-
- try {
- playerRef = p;
-
- UIElems.container = createElement("div", {
- class: "generic-menupage-container",
- id: "resleeves-container",
- position: "fixed",
- });
-
- UIElems.info = createElement("p", {
- display: "block",
- innerHTML:
- "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!
" +
- "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).
" +
- "NOTE: The stats and multipliers displayed on this page do NOT include your bonuses from " +
- "Source-File.",
- width: "75%",
- });
-
- // Randomly create all Resleeves if they dont already exist
- if (p.resleeves.length === 0) {
- p.resleeves = generateResleeves();
- }
-
- // Create a selector for sorting the list of Resleeves
- UIElems.sortTag = createElement("p", {
- display: "inline-block",
- innerText: "Sort By: ",
- });
- UIElems.sortSelector = createElement("select", {
- class: "dropdown",
- }) as HTMLSelectElement;
-
- enum SortOption {
- Cost = "Cost",
- Hacking = "Hacking",
- Strength = "Strength",
- Defense = "Defense",
- Dexterity = "Dexterity",
- Agility = "Agility",
- Charisma = "Charisma",
- AverageCombatStats = "AverageCombat",
- AverageAllStats = "AverageAllStats",
- TotalNumAugmentations = "TotalNumAugmentations",
- }
-
- UIElems.sortSelector.add(createOptionElement("Cost", SortOption.Cost));
- UIElems.sortSelector.add(createOptionElement("Hacking Level", SortOption.Hacking));
- UIElems.sortSelector.add(createOptionElement("Strength Level", SortOption.Strength));
- UIElems.sortSelector.add(createOptionElement("Defense Level", SortOption.Defense));
- UIElems.sortSelector.add(createOptionElement("Dexterity Level", SortOption.Dexterity));
- UIElems.sortSelector.add(createOptionElement("Agility Level", SortOption.Agility));
- UIElems.sortSelector.add(createOptionElement("Charisma Level", SortOption.Charisma));
- UIElems.sortSelector.add(createOptionElement("Average Combat Stats", SortOption.AverageCombatStats));
- UIElems.sortSelector.add(createOptionElement("Average Stats", SortOption.AverageAllStats));
- UIElems.sortSelector.add(createOptionElement("Number of Augmentations", SortOption.TotalNumAugmentations));
-
- UIElems.resleeveList = createElement("ul");
- UIElems.sortSelector.onchange = () => {
- removeChildrenFromElement(UIElems.resleeveList);
- UIElems.resleeves = [];
-
- // 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 sortOpt = getSelectValue(UIElems.sortSelector);
- switch (sortOpt) {
- case SortOption.Hacking:
- p.resleeves.sort((a, b) => {
- return a.hacking_skill - b.hacking_skill;
- });
- break;
- case SortOption.Strength:
- p.resleeves.sort((a, b) => {
- return a.strength - b.strength;
- });
- break;
- case SortOption.Defense:
- p.resleeves.sort((a, b) => {
- return a.defense - b.defense;
- });
- break;
- case SortOption.Dexterity:
- p.resleeves.sort((a, b) => {
- return a.dexterity - b.dexterity;
- });
- break;
- case SortOption.Agility:
- p.resleeves.sort((a, b) => {
- return a.agility - b.agility;
- });
- break;
- case SortOption.Charisma:
- p.resleeves.sort((a, b) => {
- return a.charisma - b.charisma;
- });
- break;
- case SortOption.AverageCombatStats:
- p.resleeves.sort((a, b) => {
- const aAvg = getAverage(a.strength, a.defense, a.dexterity, a.agility);
- const bAvg = getAverage(b.strength, b.defense, b.dexterity, b.agility);
-
- return aAvg - bAvg;
- });
- break;
- case SortOption.AverageAllStats:
- p.resleeves.sort((a, b) => {
- const aAvg = getAverage(a.hacking_skill, a.strength, a.defense, a.dexterity, a.agility, a.charisma);
- const bAvg = getAverage(b.hacking_skill, b.strength, b.defense, b.dexterity, b.agility, b.charisma);
-
- return aAvg - bAvg;
- });
- break;
- case SortOption.TotalNumAugmentations:
- p.resleeves.sort((a, b) => {
- return a.augmentations.length - b.augmentations.length;
- });
- break;
- case SortOption.Cost:
- default:
- p.resleeves.sort((a, b) => {
- return a.getCost() - b.getCost();
- });
- break;
- }
-
- if (UIElems.resleeveList == null) throw new Error("UIElems.resleeveList is null in sortSelector.click()");
- if (UIElems.resleeves == null) throw new Error("UIElems.resleeves is null in sortSelector.click()");
-
- // Create UI for all Resleeves
- for (const resleeve of p.resleeves) {
- const resleeveUi = createResleeveUi(resleeve);
- if (resleeveUi.container == null) throw new Error("resleeveUi.container is null in sortSelector.click()");
- UIElems.resleeveList.appendChild(resleeveUi.container);
- UIElems.resleeves.push(resleeveUi);
- }
- };
- UIElems.sortSelector.dispatchEvent(new Event("change")); // Force onchange event
-
- UIElems.container.appendChild(UIElems.info);
- UIElems.container.appendChild(createElement("br"));
- UIElems.container.appendChild(UIElems.sortTag);
- UIElems.container.appendChild(UIElems.sortSelector);
- UIElems.container.appendChild(UIElems.resleeveList);
-
- const container = document.getElementById("entire-game-container");
- if (container == null) throw new Error("Could not find entire-game-container in createResleevesPage()");
- container.appendChild(UIElems.container);
- } catch (e) {
- exceptionAlert(e);
- }
-}
-
-export function clearResleevesPage(): void {
- if (UIElems.container instanceof HTMLElement) {
- removeElement(UIElems.container);
- }
-
- for (const prop in UIElems) {
- (UIElems as any)[prop] = null;
- }
-
- playerRef = null;
-}
-
-function createResleeveUi(resleeve: Resleeve): IResleeveUIElems {
- const elems: IResleeveUIElems = {
- container: null,
- statsPanel: null,
- stats: null,
- multipliersButton: null,
- augPanel: null,
- augSelector: null,
- augDescription: null,
- costPanel: null,
- costText: null,
- buyButton: null,
- };
- if (playerRef === null) return elems;
-
- if (!routing.isOn(Page.Resleeves)) {
- return elems;
- }
-
- elems.container = createElement("div", {
- class: "resleeve-container",
- display: "block",
- });
-
- elems.statsPanel = createElement("div", {
- class: "resleeve-panel",
- width: "30%",
- });
- elems.stats = createElement("p", {
- class: "resleeve-stats-text",
- innerHTML:
- `Hacking: ${numeralWrapper.formatSkill(resleeve.hacking_skill)} (${numeralWrapper.formatExp(
- resleeve.hacking_exp,
- )} exp)
` +
- `Strength: ${numeralWrapper.formatSkill(resleeve.strength)} (${numeralWrapper.formatExp(
- resleeve.strength_exp,
- )} exp)
` +
- `Defense: ${numeralWrapper.formatSkill(resleeve.defense)} (${numeralWrapper.formatExp(
- resleeve.defense_exp,
- )} exp)
` +
- `Dexterity: ${numeralWrapper.formatSkill(resleeve.dexterity)} (${numeralWrapper.formatExp(
- resleeve.dexterity_exp,
- )} exp)
` +
- `Agility: ${numeralWrapper.formatSkill(resleeve.agility)} (${numeralWrapper.formatExp(
- resleeve.agility_exp,
- )} exp)
` +
- `Charisma: ${numeralWrapper.formatSkill(resleeve.charisma)} (${numeralWrapper.formatExp(
- resleeve.charisma_exp,
- )} exp)
` +
- `# Augmentations: ${resleeve.augmentations.length}`,
- });
- elems.multipliersButton = createElement("button", {
- class: "std-button",
- innerText: "Multipliers",
- clickListener: () => {
- dialogBoxCreate(
- [
- "
Total Multipliers:
",
- `Hacking Level multiplier: ${numeralWrapper.formatPercentage(resleeve.hacking_mult)}`,
- `Hacking Experience multiplier: ${numeralWrapper.formatPercentage(resleeve.hacking_exp_mult)}`,
- `Strength Level multiplier: ${numeralWrapper.formatPercentage(resleeve.strength_mult)}`,
- `Strength Experience multiplier: ${numeralWrapper.formatPercentage(resleeve.strength_exp_mult)}`,
- `Defense Level multiplier: ${numeralWrapper.formatPercentage(resleeve.defense_mult)}`,
- `Defense Experience multiplier: ${numeralWrapper.formatPercentage(resleeve.defense_exp_mult)}`,
- `Dexterity Level multiplier: ${numeralWrapper.formatPercentage(resleeve.dexterity_mult)}`,
- `Dexterity Experience multiplier: ${numeralWrapper.formatPercentage(resleeve.dexterity_exp_mult)}`,
- `Agility Level multiplier: ${numeralWrapper.formatPercentage(resleeve.agility_mult)}`,
- `Agility Experience multiplier: ${numeralWrapper.formatPercentage(resleeve.agility_exp_mult)}`,
- `Charisma Level multiplier: ${numeralWrapper.formatPercentage(resleeve.charisma_mult)}`,
- `Charisma Experience multiplier: ${numeralWrapper.formatPercentage(resleeve.charisma_exp_mult)}`,
- `Hacking Chance multiplier: ${numeralWrapper.formatPercentage(resleeve.hacking_chance_mult)}`,
- `Hacking Speed multiplier: ${numeralWrapper.formatPercentage(resleeve.hacking_speed_mult)}`,
- `Hacking Money multiplier: ${numeralWrapper.formatPercentage(resleeve.hacking_money_mult)}`,
- `Hacking Growth multiplier: ${numeralWrapper.formatPercentage(resleeve.hacking_grow_mult)}`,
- `Salary multiplier: ${numeralWrapper.formatPercentage(resleeve.work_money_mult)}`,
- `Company Reputation Gain multiplier: ${numeralWrapper.formatPercentage(resleeve.company_rep_mult)}`,
- `Faction Reputation Gain multiplier: ${numeralWrapper.formatPercentage(resleeve.faction_rep_mult)}`,
- `Crime Money multiplier: ${numeralWrapper.formatPercentage(resleeve.crime_money_mult)}`,
- `Crime Success multiplier: ${numeralWrapper.formatPercentage(resleeve.crime_success_mult)}`,
- `Hacknet Income multiplier: ${numeralWrapper.formatPercentage(resleeve.hacknet_node_money_mult)}`,
- `Hacknet Purchase Cost multiplier: ${numeralWrapper.formatPercentage(
- resleeve.hacknet_node_purchase_cost_mult,
- )}`,
- `Hacknet Level Upgrade Cost multiplier: ${numeralWrapper.formatPercentage(
- resleeve.hacknet_node_level_cost_mult,
- )}`,
- `Hacknet Ram Upgrade Cost multiplier: ${numeralWrapper.formatPercentage(
- resleeve.hacknet_node_ram_cost_mult,
- )}`,
- `Hacknet Core Upgrade Cost multiplier: ${numeralWrapper.formatPercentage(
- resleeve.hacknet_node_core_cost_mult,
- )}`,
- `Bladeburner Max Stamina multiplier: ${numeralWrapper.formatPercentage(
- resleeve.bladeburner_max_stamina_mult,
- )}`,
- `Bladeburner Stamina Gain multiplier: ${numeralWrapper.formatPercentage(
- resleeve.bladeburner_stamina_gain_mult,
- )}`,
- `Bladeburner Field Analysis multiplier: ${numeralWrapper.formatPercentage(
- resleeve.bladeburner_analysis_mult,
- )}`,
- `Bladeburner Success Chance multiplier: ${numeralWrapper.formatPercentage(
- resleeve.bladeburner_success_chance_mult,
- )}`,
- ].join("
"),
- false,
- );
- },
- });
- elems.statsPanel.appendChild(elems.stats);
- elems.statsPanel.appendChild(elems.multipliersButton);
-
- elems.augPanel = createElement("div", {
- class: "resleeve-panel",
- width: "50%",
- });
- elems.augSelector = createElement("select", {
- class: "resleeve-aug-selector dropdown",
- }) as HTMLSelectElement;
- elems.augDescription = createElement("p");
- for (let i = 0; i < resleeve.augmentations.length; ++i) {
- elems.augSelector.add(createOptionElement(resleeve.augmentations[i].name));
- }
- elems.augSelector.addEventListener("change", () => {
- updateAugDescription(elems);
- });
- elems.augSelector.dispatchEvent(new Event("change")); // Set inital description by manually triggering change event
- elems.augPanel.appendChild(elems.augSelector);
- elems.augPanel.appendChild(elems.augDescription);
-
- const cost: number = resleeve.getCost();
- elems.costPanel = createElement("div", {
- class: "resleeve-panel",
- width: "20%",
- });
- elems.costText = createElement("p", {
- innerHTML:
- `It costs ${renderToStaticMarkup()} ` + `to purchase this Sleeve.`,
- });
- elems.buyButton = createElement("button", {
- class: "std-button",
- innerText: "Purchase",
- clickListener: () => {
- if (playerRef == null) throw new Error("playerRef is null in buyButton.click()");
- if (purchaseResleeve(resleeve, playerRef)) {
- dialogBoxCreate(
- <>
- You re-sleeved for !
- >,
- false,
- );
- } else {
- dialogBoxCreate(`You cannot afford to re-sleeve into this body`, false);
- }
- },
- });
- elems.costPanel.appendChild(elems.costText);
- elems.costPanel.appendChild(elems.buyButton);
-
- elems.container.appendChild(elems.statsPanel);
- elems.container.appendChild(elems.augPanel);
- elems.container.appendChild(elems.costPanel);
-
- return elems;
-}
-
-function updateAugDescription(elems: IResleeveUIElems): void {
- if (elems.augDescription == null) throw new Error("elems.augDescription is null in updateAugDescription()");
- const augName: string = getSelectValue(elems.augSelector);
- const aug: Augmentation | null = Augmentations[augName];
- if (aug == null) {
- console.warn(`Could not find Augmentation with name ${augName}`);
- return;
- }
-
- let innerHTML = aug.info;
- if (typeof innerHTML !== "string") {
- innerHTML = renderToStaticMarkup(innerHTML);
- }
-
- elems.augDescription.innerHTML = innerHTML;
-}
diff --git a/src/PersonObjects/Resleeving/ui/ResleeveElem.tsx b/src/PersonObjects/Resleeving/ui/ResleeveElem.tsx
index 4ae70ce01..e651af12f 100644
--- a/src/PersonObjects/Resleeving/ui/ResleeveElem.tsx
+++ b/src/PersonObjects/Resleeving/ui/ResleeveElem.tsx
@@ -2,7 +2,7 @@ import React, { useState } from "react";
import { IPlayer } from "../../IPlayer";
import { Resleeve } from "../Resleeve";
import { Augmentations } from "../../../Augmentation/Augmentations";
-import { generateResleeves, purchaseResleeve } from "../Resleeving";
+import { purchaseResleeve } from "../Resleeving";
import { Money } from "../../../ui/React/Money";
import { numeralWrapper } from "../../../ui/numeralFormat";
diff --git a/src/PersonObjects/Resleeving/ui/ResleeveRoot.tsx b/src/PersonObjects/Resleeving/ui/ResleeveRoot.tsx
index 5a7a753bf..404f7bf29 100644
--- a/src/PersonObjects/Resleeving/ui/ResleeveRoot.tsx
+++ b/src/PersonObjects/Resleeving/ui/ResleeveRoot.tsx
@@ -1,7 +1,7 @@
import React, { useState } from "react";
import { IPlayer } from "../../IPlayer";
-import { generateResleeves, purchaseResleeve } from "../Resleeving";
+import { generateResleeves } from "../Resleeving";
import { Resleeve } from "../Resleeve";
import { ResleeveElem } from "./ResleeveElem";
@@ -60,11 +60,9 @@ const SortFunctions: {
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) -
+ 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) -
+ 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,
};
diff --git a/src/PersonObjects/Sleeve/SleeveUI.tsx b/src/PersonObjects/Sleeve/SleeveUI.tsx
index 85d5af344..70ed0b2f5 100644
--- a/src/PersonObjects/Sleeve/SleeveUI.tsx
+++ b/src/PersonObjects/Sleeve/SleeveUI.tsx
@@ -2,22 +2,18 @@
* Module for handling the Sleeve UI
*/
import React from "react";
-import { createSleevePurchaseAugsPopup } from "./SleeveAugmentationsUI";
import { Sleeve } from "./Sleeve";
import { SleeveTaskType } from "./SleeveTaskTypesEnum";
import { SleeveFaq } from "./data/SleeveFaq";
import { IPlayer } from "../IPlayer";
-import { CONSTANTS } from "../../Constants";
-
import { Faction } from "../../Faction/Faction";
import { Factions } from "../../Faction/Factions";
import { FactionWorkType } from "../../Faction/FactionWorkTypeEnum";
import { Crime } from "../../Crime/Crime";
import { Crimes } from "../../Crime/Crimes";
-import { Cities } from "../../Locations/Cities";
import { CityName } from "../../Locations/data/CityNames";
import { LocationName } from "../../Locations/data/LocationNames";
@@ -32,13 +28,13 @@ import { exceptionAlert } from "../../../utils/helpers/exceptionAlert";
import { clearEventListeners } from "../../../utils/uiHelpers/clearEventListeners";
import { createElement } from "../../../utils/uiHelpers/createElement";
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
-import { createPopup } from "../../../utils/uiHelpers/createPopup";
-import { createPopupCloseButton } from "../../../utils/uiHelpers/createPopupCloseButton";
+import { createPopup } from "../../ui/React/createPopup";
import { getSelectValue } from "../../../utils/uiHelpers/getSelectData";
import { removeChildrenFromElement } from "../../../utils/uiHelpers/removeChildrenFromElement";
import { removeElement } from "../../../utils/uiHelpers/removeElement";
-import { removeElementById } from "../../../utils/uiHelpers/removeElementById";
+import { SleeveAugmentationsPopup } from "./ui/SleeveAugmentationsPopup";
+import { TravelPopup } from "./ui/TravelPopup";
import { EarningsTableElement } from "./ui/EarningsTableElement";
import { Money } from "../../ui/React/Money";
import { MoneyRate } from "../../ui/React/MoneyRate";
@@ -47,7 +43,6 @@ import { StatsElement } from "./ui/StatsElement";
import { MoreStatsContent } from "./ui/MoreStatsContent";
import { MoreEarningsContent } from "./ui/MoreEarningsContent";
import * as ReactDOM from "react-dom";
-import { renderToStaticMarkup } from "react-dom/server";
// Object that keeps track of all DOM elements for the UI for a single Sleeve
interface ISleeveUIElems {
@@ -226,59 +221,20 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
class: "std-button",
innerText: "More Stats",
clickListener: () => {
- dialogBoxCreate(MoreStatsContent(sleeve));
+ dialogBoxCreate();
},
});
elems.travelButton = createElement("button", {
class: "std-button",
innerText: "Travel",
clickListener: () => {
- if (playerRef === null) return;
+ if (playerRef == null) throw new Error("playerRef is null in purchaseAugsButton.click()");
const popupId = "sleeve-travel-popup";
- const popupArguments: HTMLElement[] = [];
- popupArguments.push(createPopupCloseButton(popupId, { class: "std-button" }));
- popupArguments.push(
- createElement("p", {
- innerHTML:
- "Have this sleeve travel to a different city. This affects " +
- "the gyms and universities at which this sleeve can study. " +
- `Traveling to a different city costs ${renderToStaticMarkup(
- ,
- )}. ` +
- "It will also CANCEL the sleeve's current task (setting it to idle)",
- }),
- );
- for (const cityName in Cities) {
- if (sleeve.city === cityName) {
- continue;
- }
- (function (sleeve, cityName) {
- popupArguments.push(
- createElement("div", {
- // Reusing this css class. It adds a border and makes it so that
- // the background color changes when you hover
- class: "cmpy-mgmt-find-employee-option",
- innerText: cityName,
- clickListener: () => {
- if (playerRef == null) throw new Error("playerRef is null in popupArguments.click()");
- if (!playerRef.canAfford(CONSTANTS.TravelCost)) {
- dialogBoxCreate("You cannot afford to have this sleeve travel to another city", false);
- return false;
- }
- sleeve.city = cityName as CityName;
- playerRef.loseMoney(CONSTANTS.TravelCost);
- sleeve.resetTaskStatus();
- removeElementById(popupId);
- updateSleeveUi(sleeve, elems);
- updateSleeveTaskSelector(sleeve, elems, allSleeves);
- return false;
- },
- }),
- );
- })(sleeve, cityName);
- }
-
- createPopup(popupId, popupArguments);
+ createPopup(popupId, TravelPopup, {
+ popupId: popupId,
+ sleeve: sleeve,
+ player: playerRef,
+ });
},
});
elems.purchaseAugsButton = createElement("button", {
@@ -287,7 +243,11 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
innerText: "Manage Augmentations",
clickListener: () => {
if (playerRef == null) throw new Error("playerRef is null in purchaseAugsButton.click()");
- createSleevePurchaseAugsPopup(sleeve, playerRef);
+ const popupId = "sleeve-augmentation-popup";
+ createPopup(popupId, SleeveAugmentationsPopup, {
+ sleeve: sleeve,
+ player: playerRef,
+ });
},
});
elems.statsPanel.appendChild(elems.stats);
@@ -350,7 +310,7 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
class: "std-button",
innerText: "More Earnings Info",
clickListener: () => {
- dialogBoxCreate(MoreEarningsContent(sleeve));
+ dialogBoxCreate();
},
});
diff --git a/src/PersonObjects/Sleeve/ui/MoreEarningsContent.tsx b/src/PersonObjects/Sleeve/ui/MoreEarningsContent.tsx
index 7f1d62572..87f8a73b5 100644
--- a/src/PersonObjects/Sleeve/ui/MoreEarningsContent.tsx
+++ b/src/PersonObjects/Sleeve/ui/MoreEarningsContent.tsx
@@ -4,44 +4,48 @@ import { Money } from "../../../ui/React/Money";
import * as React from "react";
import { StatsTable } from "../../../ui/React/StatsTable";
-export function MoreEarningsContent(sleeve: Sleeve): React.ReactElement {
+interface IProps {
+ sleeve: Sleeve;
+}
+
+export function MoreEarningsContent(props: IProps): React.ReactElement {
return (
<>
{StatsTable(
[
- ["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)],
+ ["Money ", ],
+ ["Hacking Exp ", numeralWrapper.formatExp(props.sleeve.earningsForTask.hack)],
+ ["Strength Exp ", numeralWrapper.formatExp(props.sleeve.earningsForTask.str)],
+ ["Defense Exp ", numeralWrapper.formatExp(props.sleeve.earningsForTask.def)],
+ ["Dexterity Exp ", numeralWrapper.formatExp(props.sleeve.earningsForTask.dex)],
+ ["Agility Exp ", numeralWrapper.formatExp(props.sleeve.earningsForTask.agi)],
+ ["Charisma Exp ", numeralWrapper.formatExp(props.sleeve.earningsForTask.cha)],
],
"Earnings for Current Task:",
)}
{StatsTable(
[
- ["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)],
+ ["Money: ", ],
+ ["Hacking Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForPlayer.hack)],
+ ["Strength Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForPlayer.str)],
+ ["Defense Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForPlayer.def)],
+ ["Dexterity Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForPlayer.dex)],
+ ["Agility Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForPlayer.agi)],
+ ["Charisma Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForPlayer.cha)],
],
"Total Earnings for Host Consciousness:",
)}
{StatsTable(
[
- ["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)],
+ ["Money: ", ],
+ ["Hacking Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForSleeves.hack)],
+ ["Strength Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForSleeves.str)],
+ ["Defense Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForSleeves.def)],
+ ["Dexterity Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForSleeves.dex)],
+ ["Agility Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForSleeves.agi)],
+ ["Charisma Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForSleeves.cha)],
],
"Total Earnings for Other Sleeves:",
)}
diff --git a/src/PersonObjects/Sleeve/ui/MoreStatsContent.tsx b/src/PersonObjects/Sleeve/ui/MoreStatsContent.tsx
index d0aeedab3..0ed3f8248 100644
--- a/src/PersonObjects/Sleeve/ui/MoreStatsContent.tsx
+++ b/src/PersonObjects/Sleeve/ui/MoreStatsContent.tsx
@@ -3,40 +3,44 @@ import { numeralWrapper } from "../../../ui/numeralFormat";
import { StatsTable } from "../../../ui/React/StatsTable";
import * as React from "react";
-export function MoreStatsContent(sleeve: Sleeve): React.ReactElement {
+interface IProps {
+ sleeve: Sleeve;
+}
+
+export function MoreStatsContent(props: IProps): 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)`],
+ ["Hacking: ", props.sleeve.hacking_skill, `(${numeralWrapper.formatExp(props.sleeve.hacking_exp)} exp)`],
+ ["Strength: ", props.sleeve.strength, `(${numeralWrapper.formatExp(props.sleeve.strength_exp)} exp)`],
+ ["Defense: ", props.sleeve.defense, `(${numeralWrapper.formatExp(props.sleeve.defense_exp)} exp)`],
+ ["Dexterity: ", props.sleeve.dexterity, `(${numeralWrapper.formatExp(props.sleeve.dexterity_exp)} exp)`],
+ ["Agility: ", props.sleeve.agility, `(${numeralWrapper.formatExp(props.sleeve.agility_exp)} exp)`],
+ ["Charisma: ", props.sleeve.charisma, `(${numeralWrapper.formatExp(props.sleeve.charisma_exp)} exp)`],
],
"Stats:",
)}
{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)],
+ ["Hacking Level multiplier: ", numeralWrapper.formatPercentage(props.sleeve.hacking_mult)],
+ ["Hacking Experience multiplier: ", numeralWrapper.formatPercentage(props.sleeve.hacking_exp_mult)],
+ ["Strength Level multiplier: ", numeralWrapper.formatPercentage(props.sleeve.strength_mult)],
+ ["Strength Experience multiplier: ", numeralWrapper.formatPercentage(props.sleeve.strength_exp_mult)],
+ ["Defense Level multiplier: ", numeralWrapper.formatPercentage(props.sleeve.defense_mult)],
+ ["Defense Experience multiplier: ", numeralWrapper.formatPercentage(props.sleeve.defense_exp_mult)],
+ ["Dexterity Level multiplier: ", numeralWrapper.formatPercentage(props.sleeve.dexterity_mult)],
+ ["Dexterity Experience multiplier: ", numeralWrapper.formatPercentage(props.sleeve.dexterity_exp_mult)],
+ ["Agility Level multiplier: ", numeralWrapper.formatPercentage(props.sleeve.agility_mult)],
+ ["Agility Experience multiplier: ", numeralWrapper.formatPercentage(props.sleeve.agility_exp_mult)],
+ ["Charisma Level multiplier: ", numeralWrapper.formatPercentage(props.sleeve.charisma_mult)],
+ ["Charisma Experience multiplier: ", numeralWrapper.formatPercentage(props.sleeve.charisma_exp_mult)],
+ ["Faction Reputation Gain multiplier: ", numeralWrapper.formatPercentage(props.sleeve.faction_rep_mult)],
+ ["Company Reputation Gain multiplier: ", numeralWrapper.formatPercentage(props.sleeve.company_rep_mult)],
+ ["Salary multiplier: ", numeralWrapper.formatPercentage(props.sleeve.work_money_mult)],
+ ["Crime Money multiplier: ", numeralWrapper.formatPercentage(props.sleeve.crime_money_mult)],
+ ["Crime Success multiplier: ", numeralWrapper.formatPercentage(props.sleeve.crime_success_mult)],
],
"Multipliers:",
)}
diff --git a/src/PersonObjects/Sleeve/ui/SleeveAugmentationsPopup.tsx b/src/PersonObjects/Sleeve/ui/SleeveAugmentationsPopup.tsx
new file mode 100644
index 000000000..c5e6cd4e9
--- /dev/null
+++ b/src/PersonObjects/Sleeve/ui/SleeveAugmentationsPopup.tsx
@@ -0,0 +1,90 @@
+import React, { useState, useEffect } from "react";
+import { Sleeve } from "../Sleeve";
+import { findSleevePurchasableAugs } from "../SleeveHelpers";
+import { Augmentations } from "../../../Augmentation/Augmentations";
+import { Augmentation } from "../../../Augmentation/Augmentation";
+import { IPlayer } from "../../IPlayer";
+import { Money } from "../../../ui/React/Money";
+import { renderToStaticMarkup } from "react-dom/server";
+
+interface IProps {
+ sleeve: Sleeve;
+ player: IPlayer;
+}
+
+export function SleeveAugmentationsPopup(props: IProps): React.ReactElement {
+ const setRerender = useState(false)[1];
+ function rerender(): void {
+ setRerender((old) => !old);
+ }
+
+ useEffect(() => {
+ const id = setInterval(rerender, 150);
+ return () => clearInterval(id);
+ }, []);
+
+ // Array of all owned Augmentations. Names only
+ const ownedAugNames = props.sleeve.augmentations.map((e) => 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(props.sleeve, props.player);
+
+ function purchaseAugmentation(aug: Augmentation): void {
+ props.sleeve.tryBuyAugmentation(props.player, aug);
+ rerender();
+ }
+
+ return (
+
+
Owned Augmentations:
+
+ {ownedAugNames.map((augName) => {
+ const aug = Augmentations[augName];
+ let tooltip = aug.info;
+ if (typeof tooltip !== "string") {
+ tooltip = renderToStaticMarkup(tooltip);
+ }
+ tooltip += "
";
+ tooltip += renderToStaticMarkup(aug.stats);
+ return (
+
+ {augName}
+
+
+ );
+ })}
+
+
+ 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.
+
+
+ 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.
+
+ {availableAugs.map((aug) => {
+ let info = aug.info;
+ if (typeof info !== "string") {
+ info = renderToStaticMarkup(info);
+ }
+ info += "
";
+ info += renderToStaticMarkup(aug.stats);
+
+ return (
+
purchaseAugmentation(aug)}>
+
+
{aug.name}
+
+ Cost:
+
+
+
+
+
+ );
+ })}
+
+ );
+}
diff --git a/src/PersonObjects/Sleeve/ui/TravelPopup.tsx b/src/PersonObjects/Sleeve/ui/TravelPopup.tsx
new file mode 100644
index 000000000..22620104b
--- /dev/null
+++ b/src/PersonObjects/Sleeve/ui/TravelPopup.tsx
@@ -0,0 +1,44 @@
+import React from "react";
+import { Sleeve } from "../Sleeve";
+import { IPlayer } from "../../IPlayer";
+import { CONSTANTS } from "../../../Constants";
+import { Cities } from "../../../Locations/Cities";
+import { removePopup } from "../../../ui/React/createPopup";
+import { Money } from "../../../ui/React/Money";
+import { CityName } from "../../../Locations/data/CityNames";
+import { dialogBoxCreate } from "../../../../utils/DialogBox";
+
+interface IProps {
+ popupId: string;
+ sleeve: Sleeve;
+ player: IPlayer;
+}
+
+export function TravelPopup(props: IProps): React.ReactElement {
+ function travel(city: string): void {
+ if (!props.player.canAfford(CONSTANTS.TravelCost)) {
+ dialogBoxCreate("You cannot afford to have this sleeve travel to another city");
+ }
+ props.sleeve.city = city as CityName;
+ props.player.loseMoney(CONSTANTS.TravelCost);
+ props.sleeve.resetTaskStatus();
+ removePopup(props.popupId);
+ }
+
+ return (
+ <>
+
+ Have this sleeve travel to a different city. This affects the gyms and universities at which this sleeve can
+ study. Traveling to a different city costs . It will
+ also set your current sleeve task to idle.
+
+ {Object.keys(Cities)
+ .filter((city: string) => props.sleeve.city !== city)
+ .map((city: string) => (
+ travel(city)}>
+ {city}
+
+ ))}
+ >
+ );
+}
diff --git a/src/engine.jsx b/src/engine.jsx
index c28fc9dfa..904853c15 100644
--- a/src/engine.jsx
+++ b/src/engine.jsx
@@ -58,7 +58,6 @@ import { displayMilestonesContent } from "./Milestones/MilestoneHelpers";
import { Terminal, postNetburnerText } from "./Terminal";
import { Sleeve } from "./PersonObjects/Sleeve/Sleeve";
import { clearSleevesPage, createSleevesPage, updateSleevesPage } from "./PersonObjects/Sleeve/SleeveUI";
-import { clearResleevesPage, createResleevesPage } from "./PersonObjects/Resleeving/ResleevingUI";
import { createStatusText } from "./ui/createStatusText";
import { CharacterInfo } from "./ui/CharacterInfo";