mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-22 23:53:48 +01:00
some sleeve conversion
This commit is contained in:
parent
ab8937870c
commit
b0fcdb8363
@ -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!<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.",
|
|
||||||
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)<br />` +
|
|
||||||
`Strength: ${numeralWrapper.formatSkill(resleeve.strength)} (${numeralWrapper.formatExp(
|
|
||||||
resleeve.strength_exp,
|
|
||||||
)} exp)<br />` +
|
|
||||||
`Defense: ${numeralWrapper.formatSkill(resleeve.defense)} (${numeralWrapper.formatExp(
|
|
||||||
resleeve.defense_exp,
|
|
||||||
)} exp)<br />` +
|
|
||||||
`Dexterity: ${numeralWrapper.formatSkill(resleeve.dexterity)} (${numeralWrapper.formatExp(
|
|
||||||
resleeve.dexterity_exp,
|
|
||||||
)} exp)<br />` +
|
|
||||||
`Agility: ${numeralWrapper.formatSkill(resleeve.agility)} (${numeralWrapper.formatExp(
|
|
||||||
resleeve.agility_exp,
|
|
||||||
)} exp)<br />` +
|
|
||||||
`Charisma: ${numeralWrapper.formatSkill(resleeve.charisma)} (${numeralWrapper.formatExp(
|
|
||||||
resleeve.charisma_exp,
|
|
||||||
)} exp)<br />` +
|
|
||||||
`# Augmentations: ${resleeve.augmentations.length}`,
|
|
||||||
});
|
|
||||||
elems.multipliersButton = createElement("button", {
|
|
||||||
class: "std-button",
|
|
||||||
innerText: "Multipliers",
|
|
||||||
clickListener: () => {
|
|
||||||
dialogBoxCreate(
|
|
||||||
[
|
|
||||||
"<h2><u>Total Multipliers:</u></h2>",
|
|
||||||
`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("<br />"),
|
|
||||||
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(<Money money={cost} player={playerRef} />)} ` + `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 <Money money={cost} />!
|
|
||||||
</>,
|
|
||||||
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;
|
|
||||||
}
|
|
@ -2,7 +2,7 @@ import React, { useState } from "react";
|
|||||||
import { IPlayer } from "../../IPlayer";
|
import { IPlayer } from "../../IPlayer";
|
||||||
import { Resleeve } from "../Resleeve";
|
import { Resleeve } from "../Resleeve";
|
||||||
import { Augmentations } from "../../../Augmentation/Augmentations";
|
import { Augmentations } from "../../../Augmentation/Augmentations";
|
||||||
import { generateResleeves, purchaseResleeve } from "../Resleeving";
|
import { purchaseResleeve } from "../Resleeving";
|
||||||
import { Money } from "../../../ui/React/Money";
|
import { Money } from "../../../ui/React/Money";
|
||||||
|
|
||||||
import { numeralWrapper } from "../../../ui/numeralFormat";
|
import { numeralWrapper } from "../../../ui/numeralFormat";
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
|
||||||
import { IPlayer } from "../../IPlayer";
|
import { IPlayer } from "../../IPlayer";
|
||||||
import { generateResleeves, purchaseResleeve } from "../Resleeving";
|
import { generateResleeves } from "../Resleeving";
|
||||||
import { Resleeve } from "../Resleeve";
|
import { Resleeve } from "../Resleeve";
|
||||||
import { ResleeveElem } from "./ResleeveElem";
|
import { ResleeveElem } from "./ResleeveElem";
|
||||||
|
|
||||||
@ -60,11 +60,9 @@ const SortFunctions: {
|
|||||||
Dexterity: (a: Resleeve, b: Resleeve): number => a.dexterity - b.dexterity,
|
Dexterity: (a: Resleeve, b: Resleeve): number => a.dexterity - b.dexterity,
|
||||||
Agility: (a: Resleeve, b: Resleeve): number => a.agility - b.agility,
|
Agility: (a: Resleeve, b: Resleeve): number => a.agility - b.agility,
|
||||||
Charisma: (a: Resleeve, b: Resleeve): number => a.charisma - b.charisma,
|
Charisma: (a: Resleeve, b: Resleeve): number => a.charisma - b.charisma,
|
||||||
AverageCombatStats: (a: Resleeve, b: Resleeve): number =>
|
AverageCombatStats: (a: Resleeve, b: Resleeve): number => getAverage(a.strength, a.defense, a.dexterity, a.agility) -
|
||||||
getAverage(a.strength, a.defense, a.dexterity, a.agility) -
|
|
||||||
getAverage(b.strength, b.defense, b.dexterity, b.agility),
|
getAverage(b.strength, b.defense, b.dexterity, b.agility),
|
||||||
AverageAllStats: (a: Resleeve, b: Resleeve): number =>
|
AverageAllStats: (a: Resleeve, b: Resleeve): number => getAverage(a.hacking_skill, a.strength, a.defense, a.dexterity, a.agility, a.charisma) -
|
||||||
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),
|
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,
|
TotalNumAugmentations: (a: Resleeve, b: Resleeve): number => a.augmentations.length - b.augmentations.length,
|
||||||
};
|
};
|
||||||
|
@ -2,22 +2,18 @@
|
|||||||
* Module for handling the Sleeve UI
|
* Module for handling the Sleeve UI
|
||||||
*/
|
*/
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { createSleevePurchaseAugsPopup } from "./SleeveAugmentationsUI";
|
|
||||||
import { Sleeve } from "./Sleeve";
|
import { Sleeve } from "./Sleeve";
|
||||||
import { SleeveTaskType } from "./SleeveTaskTypesEnum";
|
import { SleeveTaskType } from "./SleeveTaskTypesEnum";
|
||||||
import { SleeveFaq } from "./data/SleeveFaq";
|
import { SleeveFaq } from "./data/SleeveFaq";
|
||||||
|
|
||||||
import { IPlayer } from "../IPlayer";
|
import { IPlayer } from "../IPlayer";
|
||||||
|
|
||||||
import { CONSTANTS } from "../../Constants";
|
|
||||||
|
|
||||||
import { Faction } from "../../Faction/Faction";
|
import { Faction } from "../../Faction/Faction";
|
||||||
import { Factions } from "../../Faction/Factions";
|
import { Factions } from "../../Faction/Factions";
|
||||||
import { FactionWorkType } from "../../Faction/FactionWorkTypeEnum";
|
import { FactionWorkType } from "../../Faction/FactionWorkTypeEnum";
|
||||||
|
|
||||||
import { Crime } from "../../Crime/Crime";
|
import { Crime } from "../../Crime/Crime";
|
||||||
import { Crimes } from "../../Crime/Crimes";
|
import { Crimes } from "../../Crime/Crimes";
|
||||||
import { Cities } from "../../Locations/Cities";
|
|
||||||
import { CityName } from "../../Locations/data/CityNames";
|
import { CityName } from "../../Locations/data/CityNames";
|
||||||
import { LocationName } from "../../Locations/data/LocationNames";
|
import { LocationName } from "../../Locations/data/LocationNames";
|
||||||
|
|
||||||
@ -32,13 +28,13 @@ import { exceptionAlert } from "../../../utils/helpers/exceptionAlert";
|
|||||||
import { clearEventListeners } from "../../../utils/uiHelpers/clearEventListeners";
|
import { clearEventListeners } from "../../../utils/uiHelpers/clearEventListeners";
|
||||||
import { createElement } from "../../../utils/uiHelpers/createElement";
|
import { createElement } from "../../../utils/uiHelpers/createElement";
|
||||||
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
|
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
|
||||||
import { createPopup } from "../../../utils/uiHelpers/createPopup";
|
import { createPopup } from "../../ui/React/createPopup";
|
||||||
import { createPopupCloseButton } from "../../../utils/uiHelpers/createPopupCloseButton";
|
|
||||||
import { getSelectValue } from "../../../utils/uiHelpers/getSelectData";
|
import { getSelectValue } from "../../../utils/uiHelpers/getSelectData";
|
||||||
import { removeChildrenFromElement } from "../../../utils/uiHelpers/removeChildrenFromElement";
|
import { removeChildrenFromElement } from "../../../utils/uiHelpers/removeChildrenFromElement";
|
||||||
import { removeElement } from "../../../utils/uiHelpers/removeElement";
|
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 { EarningsTableElement } from "./ui/EarningsTableElement";
|
||||||
import { Money } from "../../ui/React/Money";
|
import { Money } from "../../ui/React/Money";
|
||||||
import { MoneyRate } from "../../ui/React/MoneyRate";
|
import { MoneyRate } from "../../ui/React/MoneyRate";
|
||||||
@ -47,7 +43,6 @@ import { StatsElement } from "./ui/StatsElement";
|
|||||||
import { MoreStatsContent } from "./ui/MoreStatsContent";
|
import { MoreStatsContent } from "./ui/MoreStatsContent";
|
||||||
import { MoreEarningsContent } from "./ui/MoreEarningsContent";
|
import { MoreEarningsContent } from "./ui/MoreEarningsContent";
|
||||||
import * as ReactDOM from "react-dom";
|
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
|
// Object that keeps track of all DOM elements for the UI for a single Sleeve
|
||||||
interface ISleeveUIElems {
|
interface ISleeveUIElems {
|
||||||
@ -226,59 +221,20 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
|
|||||||
class: "std-button",
|
class: "std-button",
|
||||||
innerText: "More Stats",
|
innerText: "More Stats",
|
||||||
clickListener: () => {
|
clickListener: () => {
|
||||||
dialogBoxCreate(MoreStatsContent(sleeve));
|
dialogBoxCreate(<MoreStatsContent sleeve={sleeve} />);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
elems.travelButton = createElement("button", {
|
elems.travelButton = createElement("button", {
|
||||||
class: "std-button",
|
class: "std-button",
|
||||||
innerText: "Travel",
|
innerText: "Travel",
|
||||||
clickListener: () => {
|
clickListener: () => {
|
||||||
if (playerRef === null) return;
|
if (playerRef == null) throw new Error("playerRef is null in purchaseAugsButton.click()");
|
||||||
const popupId = "sleeve-travel-popup";
|
const popupId = "sleeve-travel-popup";
|
||||||
const popupArguments: HTMLElement[] = [];
|
createPopup(popupId, TravelPopup, {
|
||||||
popupArguments.push(createPopupCloseButton(popupId, { class: "std-button" }));
|
popupId: popupId,
|
||||||
popupArguments.push(
|
sleeve: sleeve,
|
||||||
createElement("p", {
|
player: playerRef,
|
||||||
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(
|
|
||||||
<Money money={CONSTANTS.TravelCost} player={playerRef} />,
|
|
||||||
)}. ` +
|
|
||||||
"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);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
elems.purchaseAugsButton = createElement("button", {
|
elems.purchaseAugsButton = createElement("button", {
|
||||||
@ -287,7 +243,11 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
|
|||||||
innerText: "Manage Augmentations",
|
innerText: "Manage Augmentations",
|
||||||
clickListener: () => {
|
clickListener: () => {
|
||||||
if (playerRef == null) throw new Error("playerRef is null in purchaseAugsButton.click()");
|
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);
|
elems.statsPanel.appendChild(elems.stats);
|
||||||
@ -350,7 +310,7 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
|
|||||||
class: "std-button",
|
class: "std-button",
|
||||||
innerText: "More Earnings Info",
|
innerText: "More Earnings Info",
|
||||||
clickListener: () => {
|
clickListener: () => {
|
||||||
dialogBoxCreate(MoreEarningsContent(sleeve));
|
dialogBoxCreate(<MoreEarningsContent sleeve={sleeve} />);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -4,44 +4,48 @@ import { Money } from "../../../ui/React/Money";
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { StatsTable } from "../../../ui/React/StatsTable";
|
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 (
|
return (
|
||||||
<>
|
<>
|
||||||
{StatsTable(
|
{StatsTable(
|
||||||
[
|
[
|
||||||
["Money ", <Money money={sleeve.earningsForTask.money} />],
|
["Money ", <Money money={props.sleeve.earningsForTask.money} />],
|
||||||
["Hacking Exp ", numeralWrapper.formatExp(sleeve.earningsForTask.hack)],
|
["Hacking Exp ", numeralWrapper.formatExp(props.sleeve.earningsForTask.hack)],
|
||||||
["Strength Exp ", numeralWrapper.formatExp(sleeve.earningsForTask.str)],
|
["Strength Exp ", numeralWrapper.formatExp(props.sleeve.earningsForTask.str)],
|
||||||
["Defense Exp ", numeralWrapper.formatExp(sleeve.earningsForTask.def)],
|
["Defense Exp ", numeralWrapper.formatExp(props.sleeve.earningsForTask.def)],
|
||||||
["Dexterity Exp ", numeralWrapper.formatExp(sleeve.earningsForTask.dex)],
|
["Dexterity Exp ", numeralWrapper.formatExp(props.sleeve.earningsForTask.dex)],
|
||||||
["Agility Exp ", numeralWrapper.formatExp(sleeve.earningsForTask.agi)],
|
["Agility Exp ", numeralWrapper.formatExp(props.sleeve.earningsForTask.agi)],
|
||||||
["Charisma Exp ", numeralWrapper.formatExp(sleeve.earningsForTask.cha)],
|
["Charisma Exp ", numeralWrapper.formatExp(props.sleeve.earningsForTask.cha)],
|
||||||
],
|
],
|
||||||
"Earnings for Current Task:",
|
"Earnings for Current Task:",
|
||||||
)}
|
)}
|
||||||
<br />
|
<br />
|
||||||
{StatsTable(
|
{StatsTable(
|
||||||
[
|
[
|
||||||
["Money: ", <Money money={sleeve.earningsForPlayer.money} />],
|
["Money: ", <Money money={props.sleeve.earningsForPlayer.money} />],
|
||||||
["Hacking Exp: ", numeralWrapper.formatExp(sleeve.earningsForPlayer.hack)],
|
["Hacking Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForPlayer.hack)],
|
||||||
["Strength Exp: ", numeralWrapper.formatExp(sleeve.earningsForPlayer.str)],
|
["Strength Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForPlayer.str)],
|
||||||
["Defense Exp: ", numeralWrapper.formatExp(sleeve.earningsForPlayer.def)],
|
["Defense Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForPlayer.def)],
|
||||||
["Dexterity Exp: ", numeralWrapper.formatExp(sleeve.earningsForPlayer.dex)],
|
["Dexterity Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForPlayer.dex)],
|
||||||
["Agility Exp: ", numeralWrapper.formatExp(sleeve.earningsForPlayer.agi)],
|
["Agility Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForPlayer.agi)],
|
||||||
["Charisma Exp: ", numeralWrapper.formatExp(sleeve.earningsForPlayer.cha)],
|
["Charisma Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForPlayer.cha)],
|
||||||
],
|
],
|
||||||
"Total Earnings for Host Consciousness:",
|
"Total Earnings for Host Consciousness:",
|
||||||
)}
|
)}
|
||||||
<br />
|
<br />
|
||||||
{StatsTable(
|
{StatsTable(
|
||||||
[
|
[
|
||||||
["Money: ", <Money money={sleeve.earningsForSleeves.money} />],
|
["Money: ", <Money money={props.sleeve.earningsForSleeves.money} />],
|
||||||
["Hacking Exp: ", numeralWrapper.formatExp(sleeve.earningsForSleeves.hack)],
|
["Hacking Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForSleeves.hack)],
|
||||||
["Strength Exp: ", numeralWrapper.formatExp(sleeve.earningsForSleeves.str)],
|
["Strength Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForSleeves.str)],
|
||||||
["Defense Exp: ", numeralWrapper.formatExp(sleeve.earningsForSleeves.def)],
|
["Defense Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForSleeves.def)],
|
||||||
["Dexterity Exp: ", numeralWrapper.formatExp(sleeve.earningsForSleeves.dex)],
|
["Dexterity Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForSleeves.dex)],
|
||||||
["Agility Exp: ", numeralWrapper.formatExp(sleeve.earningsForSleeves.agi)],
|
["Agility Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForSleeves.agi)],
|
||||||
["Charisma Exp: ", numeralWrapper.formatExp(sleeve.earningsForSleeves.cha)],
|
["Charisma Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForSleeves.cha)],
|
||||||
],
|
],
|
||||||
"Total Earnings for Other Sleeves:",
|
"Total Earnings for Other Sleeves:",
|
||||||
)}
|
)}
|
||||||
|
@ -3,40 +3,44 @@ import { numeralWrapper } from "../../../ui/numeralFormat";
|
|||||||
import { StatsTable } from "../../../ui/React/StatsTable";
|
import { StatsTable } from "../../../ui/React/StatsTable";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
export function MoreStatsContent(sleeve: Sleeve): React.ReactElement {
|
interface IProps {
|
||||||
|
sleeve: Sleeve;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MoreStatsContent(props: IProps): React.ReactElement {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{StatsTable(
|
{StatsTable(
|
||||||
[
|
[
|
||||||
["Hacking: ", sleeve.hacking_skill, `(${numeralWrapper.formatExp(sleeve.hacking_exp)} exp)`],
|
["Hacking: ", props.sleeve.hacking_skill, `(${numeralWrapper.formatExp(props.sleeve.hacking_exp)} exp)`],
|
||||||
["Strength: ", sleeve.strength, `(${numeralWrapper.formatExp(sleeve.strength_exp)} exp)`],
|
["Strength: ", props.sleeve.strength, `(${numeralWrapper.formatExp(props.sleeve.strength_exp)} exp)`],
|
||||||
["Defense: ", sleeve.defense, `(${numeralWrapper.formatExp(sleeve.defense_exp)} exp)`],
|
["Defense: ", props.sleeve.defense, `(${numeralWrapper.formatExp(props.sleeve.defense_exp)} exp)`],
|
||||||
["Dexterity: ", sleeve.dexterity, `(${numeralWrapper.formatExp(sleeve.dexterity_exp)} exp)`],
|
["Dexterity: ", props.sleeve.dexterity, `(${numeralWrapper.formatExp(props.sleeve.dexterity_exp)} exp)`],
|
||||||
["Agility: ", sleeve.agility, `(${numeralWrapper.formatExp(sleeve.agility_exp)} exp)`],
|
["Agility: ", props.sleeve.agility, `(${numeralWrapper.formatExp(props.sleeve.agility_exp)} exp)`],
|
||||||
["Charisma: ", sleeve.charisma, `(${numeralWrapper.formatExp(sleeve.charisma_exp)} exp)`],
|
["Charisma: ", props.sleeve.charisma, `(${numeralWrapper.formatExp(props.sleeve.charisma_exp)} exp)`],
|
||||||
],
|
],
|
||||||
"Stats:",
|
"Stats:",
|
||||||
)}
|
)}
|
||||||
<br />
|
<br />
|
||||||
{StatsTable(
|
{StatsTable(
|
||||||
[
|
[
|
||||||
["Hacking Level multiplier: ", numeralWrapper.formatPercentage(sleeve.hacking_mult)],
|
["Hacking Level multiplier: ", numeralWrapper.formatPercentage(props.sleeve.hacking_mult)],
|
||||||
["Hacking Experience multiplier: ", numeralWrapper.formatPercentage(sleeve.hacking_exp_mult)],
|
["Hacking Experience multiplier: ", numeralWrapper.formatPercentage(props.sleeve.hacking_exp_mult)],
|
||||||
["Strength Level multiplier: ", numeralWrapper.formatPercentage(sleeve.strength_mult)],
|
["Strength Level multiplier: ", numeralWrapper.formatPercentage(props.sleeve.strength_mult)],
|
||||||
["Strength Experience multiplier: ", numeralWrapper.formatPercentage(sleeve.strength_exp_mult)],
|
["Strength Experience multiplier: ", numeralWrapper.formatPercentage(props.sleeve.strength_exp_mult)],
|
||||||
["Defense Level multiplier: ", numeralWrapper.formatPercentage(sleeve.defense_mult)],
|
["Defense Level multiplier: ", numeralWrapper.formatPercentage(props.sleeve.defense_mult)],
|
||||||
["Defense Experience multiplier: ", numeralWrapper.formatPercentage(sleeve.defense_exp_mult)],
|
["Defense Experience multiplier: ", numeralWrapper.formatPercentage(props.sleeve.defense_exp_mult)],
|
||||||
["Dexterity Level multiplier: ", numeralWrapper.formatPercentage(sleeve.dexterity_mult)],
|
["Dexterity Level multiplier: ", numeralWrapper.formatPercentage(props.sleeve.dexterity_mult)],
|
||||||
["Dexterity Experience multiplier: ", numeralWrapper.formatPercentage(sleeve.dexterity_exp_mult)],
|
["Dexterity Experience multiplier: ", numeralWrapper.formatPercentage(props.sleeve.dexterity_exp_mult)],
|
||||||
["Agility Level multiplier: ", numeralWrapper.formatPercentage(sleeve.agility_mult)],
|
["Agility Level multiplier: ", numeralWrapper.formatPercentage(props.sleeve.agility_mult)],
|
||||||
["Agility Experience multiplier: ", numeralWrapper.formatPercentage(sleeve.agility_exp_mult)],
|
["Agility Experience multiplier: ", numeralWrapper.formatPercentage(props.sleeve.agility_exp_mult)],
|
||||||
["Charisma Level multiplier: ", numeralWrapper.formatPercentage(sleeve.charisma_mult)],
|
["Charisma Level multiplier: ", numeralWrapper.formatPercentage(props.sleeve.charisma_mult)],
|
||||||
["Charisma Experience multiplier: ", numeralWrapper.formatPercentage(sleeve.charisma_exp_mult)],
|
["Charisma Experience multiplier: ", numeralWrapper.formatPercentage(props.sleeve.charisma_exp_mult)],
|
||||||
["Faction Reputation Gain multiplier: ", numeralWrapper.formatPercentage(sleeve.faction_rep_mult)],
|
["Faction Reputation Gain multiplier: ", numeralWrapper.formatPercentage(props.sleeve.faction_rep_mult)],
|
||||||
["Company Reputation Gain multiplier: ", numeralWrapper.formatPercentage(sleeve.company_rep_mult)],
|
["Company Reputation Gain multiplier: ", numeralWrapper.formatPercentage(props.sleeve.company_rep_mult)],
|
||||||
["Salary multiplier: ", numeralWrapper.formatPercentage(sleeve.work_money_mult)],
|
["Salary multiplier: ", numeralWrapper.formatPercentage(props.sleeve.work_money_mult)],
|
||||||
["Crime Money multiplier: ", numeralWrapper.formatPercentage(sleeve.crime_money_mult)],
|
["Crime Money multiplier: ", numeralWrapper.formatPercentage(props.sleeve.crime_money_mult)],
|
||||||
["Crime Success multiplier: ", numeralWrapper.formatPercentage(sleeve.crime_success_mult)],
|
["Crime Success multiplier: ", numeralWrapper.formatPercentage(props.sleeve.crime_success_mult)],
|
||||||
],
|
],
|
||||||
"Multipliers:",
|
"Multipliers:",
|
||||||
)}
|
)}
|
||||||
|
90
src/PersonObjects/Sleeve/ui/SleeveAugmentationsPopup.tsx
Normal file
90
src/PersonObjects/Sleeve/ui/SleeveAugmentationsPopup.tsx
Normal file
@ -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 (
|
||||||
|
<div className="noselect">
|
||||||
|
<p style={{ display: "block" }}>Owned Augmentations:</p>
|
||||||
|
<div style={{ width: "70%" }}>
|
||||||
|
{ownedAugNames.map((augName) => {
|
||||||
|
const aug = Augmentations[augName];
|
||||||
|
let tooltip = aug.info;
|
||||||
|
if (typeof tooltip !== "string") {
|
||||||
|
tooltip = renderToStaticMarkup(tooltip);
|
||||||
|
}
|
||||||
|
tooltip += "<br /><br />";
|
||||||
|
tooltip += renderToStaticMarkup(aug.stats);
|
||||||
|
return (
|
||||||
|
<div key={augName} className="gang-owned-upgrade tooltip">
|
||||||
|
{augName}
|
||||||
|
<span className="tooltiptext" dangerouslySetInnerHTML={{ __html: tooltip }}></span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
{availableAugs.map((aug) => {
|
||||||
|
let info = aug.info;
|
||||||
|
if (typeof info !== "string") {
|
||||||
|
info = renderToStaticMarkup(info);
|
||||||
|
}
|
||||||
|
info += "<br /><br />";
|
||||||
|
info += renderToStaticMarkup(aug.stats);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div key={aug.name} className="cmpy-mgmt-upgrade-div" onClick={() => purchaseAugmentation(aug)}>
|
||||||
|
<div style={{ fontSize: "12px", padding: "2px" }}>
|
||||||
|
<h2>{aug.name}</h2>
|
||||||
|
<br />
|
||||||
|
Cost: <Money money={aug.startingCost} player={props.player} />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<span dangerouslySetInnerHTML={{ __html: info }}></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
44
src/PersonObjects/Sleeve/ui/TravelPopup.tsx
Normal file
44
src/PersonObjects/Sleeve/ui/TravelPopup.tsx
Normal file
@ -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 (
|
||||||
|
<>
|
||||||
|
<p>
|
||||||
|
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 <Money money={CONSTANTS.TravelCost} player={props.player} />. It will
|
||||||
|
also set your current sleeve task to idle.
|
||||||
|
</p>
|
||||||
|
{Object.keys(Cities)
|
||||||
|
.filter((city: string) => props.sleeve.city !== city)
|
||||||
|
.map((city: string) => (
|
||||||
|
<div className="cmpy-mgmt-find-employee-option" onClick={() => travel(city)}>
|
||||||
|
{city}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -58,7 +58,6 @@ import { displayMilestonesContent } from "./Milestones/MilestoneHelpers";
|
|||||||
import { Terminal, postNetburnerText } from "./Terminal";
|
import { Terminal, postNetburnerText } from "./Terminal";
|
||||||
import { Sleeve } from "./PersonObjects/Sleeve/Sleeve";
|
import { Sleeve } from "./PersonObjects/Sleeve/Sleeve";
|
||||||
import { clearSleevesPage, createSleevesPage, updateSleevesPage } from "./PersonObjects/Sleeve/SleeveUI";
|
import { clearSleevesPage, createSleevesPage, updateSleevesPage } from "./PersonObjects/Sleeve/SleeveUI";
|
||||||
import { clearResleevesPage, createResleevesPage } from "./PersonObjects/Resleeving/ResleevingUI";
|
|
||||||
|
|
||||||
import { createStatusText } from "./ui/createStatusText";
|
import { createStatusText } from "./ui/createStatusText";
|
||||||
import { CharacterInfo } from "./ui/CharacterInfo";
|
import { CharacterInfo } from "./ui/CharacterInfo";
|
||||||
|
Loading…
Reference in New Issue
Block a user