mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-05-05 23:27:55 +02:00
prettify, sorry for the big ass commit
This commit is contained in:
@@ -7,57 +7,68 @@ import { Person } from "../Person";
|
||||
import { Augmentation } from "../../Augmentation/Augmentation";
|
||||
import { Augmentations } from "../../Augmentation/Augmentations";
|
||||
|
||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../../utils/JSONReviver";
|
||||
import {
|
||||
Generic_fromJSON,
|
||||
Generic_toJSON,
|
||||
Reviver,
|
||||
} from "../../../utils/JSONReviver";
|
||||
|
||||
export class Resleeve extends Person {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
getCost(): number {
|
||||
// Each experience point adds this to the cost
|
||||
const CostPerExp = 25e3;
|
||||
|
||||
// Final cost is multiplied by this constant ^ # Augs
|
||||
const NumAugsExponent = 1.2;
|
||||
|
||||
// Get total exp in this re-sleeve
|
||||
const totalExp: number =
|
||||
this.hacking_exp +
|
||||
this.strength_exp +
|
||||
this.defense_exp +
|
||||
this.dexterity_exp +
|
||||
this.agility_exp +
|
||||
this.charisma_exp;
|
||||
|
||||
// Get total base Augmentation cost for this re-sleeve
|
||||
let totalAugmentationCost = 0;
|
||||
for (let i = 0; i < this.augmentations.length; ++i) {
|
||||
const aug: Augmentation | null =
|
||||
Augmentations[this.augmentations[i].name];
|
||||
if (aug == null) {
|
||||
console.error(
|
||||
`Could not find Augmentation ${this.augmentations[i].name}`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
totalAugmentationCost += aug.startingCost;
|
||||
}
|
||||
|
||||
getCost(): number {
|
||||
// Each experience point adds this to the cost
|
||||
const CostPerExp = 25e3;
|
||||
return (
|
||||
totalExp * CostPerExp +
|
||||
totalAugmentationCost *
|
||||
Math.pow(NumAugsExponent, this.augmentations.length)
|
||||
);
|
||||
}
|
||||
|
||||
// Final cost is multiplied by this constant ^ # Augs
|
||||
const NumAugsExponent = 1.2;
|
||||
/**
|
||||
* Serialize the current object to a JSON save state.
|
||||
*/
|
||||
toJSON(): any {
|
||||
return Generic_toJSON("Resleeve", this);
|
||||
}
|
||||
|
||||
// Get total exp in this re-sleeve
|
||||
const totalExp: number = this.hacking_exp +
|
||||
this.strength_exp +
|
||||
this.defense_exp +
|
||||
this.dexterity_exp +
|
||||
this.agility_exp +
|
||||
this.charisma_exp;
|
||||
|
||||
// Get total base Augmentation cost for this re-sleeve
|
||||
let totalAugmentationCost = 0;
|
||||
for (let i = 0; i < this.augmentations.length; ++i) {
|
||||
const aug: Augmentation | null = Augmentations[this.augmentations[i].name];
|
||||
if (aug == null) {
|
||||
console.error(`Could not find Augmentation ${this.augmentations[i].name}`);
|
||||
continue;
|
||||
}
|
||||
totalAugmentationCost += aug.startingCost;
|
||||
}
|
||||
|
||||
return (totalExp * CostPerExp) + (totalAugmentationCost * Math.pow(NumAugsExponent, this.augmentations.length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize the current object to a JSON save state.
|
||||
*/
|
||||
toJSON(): any {
|
||||
return Generic_toJSON("Resleeve", this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiatizes a Resleeve object from a JSON save state.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): Resleeve {
|
||||
return Generic_fromJSON(Resleeve, value.data);
|
||||
}
|
||||
/**
|
||||
* Initiatizes a Resleeve object from a JSON save state.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): Resleeve {
|
||||
return Generic_fromJSON(Resleeve, value.data);
|
||||
}
|
||||
}
|
||||
|
||||
Reviver.constructors.Resleeve = Resleeve;
|
||||
|
||||
@@ -15,110 +15,120 @@ import { IPlayer } from "../IPlayer";
|
||||
|
||||
import { Augmentation } from "../../Augmentation/Augmentation";
|
||||
import { Augmentations } from "../../Augmentation/Augmentations";
|
||||
import { IPlayerOwnedAugmentation,
|
||||
PlayerOwnedAugmentation } from "../../Augmentation/PlayerOwnedAugmentation";
|
||||
import {
|
||||
IPlayerOwnedAugmentation,
|
||||
PlayerOwnedAugmentation,
|
||||
} from "../../Augmentation/PlayerOwnedAugmentation";
|
||||
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
|
||||
|
||||
import { getRandomInt } from "../../../utils/helpers/getRandomInt";
|
||||
|
||||
|
||||
// Executes the actual re-sleeve when one is purchased
|
||||
export function purchaseResleeve(r: Resleeve, p: IPlayer): boolean {
|
||||
const cost: number = r.getCost();
|
||||
if (!p.canAfford(cost)) {
|
||||
return false;
|
||||
const cost: number = r.getCost();
|
||||
if (!p.canAfford(cost)) {
|
||||
return false;
|
||||
}
|
||||
p.loseMoney(cost);
|
||||
|
||||
// Set the player's exp
|
||||
p.hacking_exp = r.hacking_exp;
|
||||
p.strength_exp = r.strength_exp;
|
||||
p.defense_exp = r.defense_exp;
|
||||
p.dexterity_exp = r.dexterity_exp;
|
||||
p.agility_exp = r.agility_exp;
|
||||
p.charisma_exp = r.charisma_exp;
|
||||
|
||||
// Reset Augmentation "owned" data
|
||||
for (const augKey in Augmentations) {
|
||||
Augmentations[augKey].owned = false;
|
||||
}
|
||||
|
||||
// Clear all of the player's augmentations, except the NeuroFlux Governor
|
||||
// which is kept
|
||||
for (let i = p.augmentations.length - 1; i >= 0; --i) {
|
||||
if (p.augmentations[i].name !== AugmentationNames.NeuroFluxGovernor) {
|
||||
p.augmentations.splice(i, 1);
|
||||
} else {
|
||||
// NeuroFlux Governor
|
||||
Augmentations[AugmentationNames.NeuroFluxGovernor].owned = true;
|
||||
}
|
||||
p.loseMoney(cost);
|
||||
}
|
||||
|
||||
// Set the player's exp
|
||||
p.hacking_exp = r.hacking_exp;
|
||||
p.strength_exp = r.strength_exp;
|
||||
p.defense_exp = r.defense_exp;
|
||||
p.dexterity_exp = r.dexterity_exp;
|
||||
p.agility_exp = r.agility_exp;
|
||||
p.charisma_exp = r.charisma_exp;
|
||||
for (let i = 0; i < r.augmentations.length; ++i) {
|
||||
p.augmentations.push(new PlayerOwnedAugmentation(r.augmentations[i].name));
|
||||
Augmentations[r.augmentations[i].name].owned = true;
|
||||
}
|
||||
|
||||
// Reset Augmentation "owned" data
|
||||
for (const augKey in Augmentations) {
|
||||
Augmentations[augKey].owned = false;
|
||||
// The player's purchased Augmentations should remain the same, but any purchased
|
||||
// Augmentations that are given by the resleeve should be removed so there are no duplicates
|
||||
for (let i = p.queuedAugmentations.length - 1; i >= 0; --i) {
|
||||
const name: string = p.queuedAugmentations[i].name;
|
||||
|
||||
if (
|
||||
p.augmentations.filter((e: IPlayerOwnedAugmentation) => {
|
||||
return (
|
||||
e.name !== AugmentationNames.NeuroFluxGovernor && e.name === name
|
||||
);
|
||||
}).length >= 1
|
||||
) {
|
||||
p.queuedAugmentations.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear all of the player's augmentations, except the NeuroFlux Governor
|
||||
// which is kept
|
||||
for (let i = p.augmentations.length - 1; i >= 0; --i) {
|
||||
if (p.augmentations[i].name !== AugmentationNames.NeuroFluxGovernor) {
|
||||
p.augmentations.splice(i, 1);
|
||||
} else {
|
||||
// NeuroFlux Governor
|
||||
Augmentations[AugmentationNames.NeuroFluxGovernor].owned = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < r.augmentations.length; ++i) {
|
||||
p.augmentations.push(new PlayerOwnedAugmentation(r.augmentations[i].name));
|
||||
Augmentations[r.augmentations[i].name].owned = true;
|
||||
}
|
||||
|
||||
// The player's purchased Augmentations should remain the same, but any purchased
|
||||
// Augmentations that are given by the resleeve should be removed so there are no duplicates
|
||||
for (let i = p.queuedAugmentations.length - 1; i >= 0; --i) {
|
||||
const name: string = p.queuedAugmentations[i].name;
|
||||
|
||||
if (p.augmentations.filter((e: IPlayerOwnedAugmentation) => {return e.name !== AugmentationNames.NeuroFluxGovernor && e.name === name}).length >= 1) {
|
||||
p.queuedAugmentations.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
p.reapplyAllAugmentations(true);
|
||||
p.reapplyAllSourceFiles(); //Multipliers get reset, so have to re-process source files too
|
||||
return true;
|
||||
p.reapplyAllAugmentations(true);
|
||||
p.reapplyAllSourceFiles(); //Multipliers get reset, so have to re-process source files too
|
||||
return true;
|
||||
}
|
||||
|
||||
// Creates all of the Re-sleeves that will be available for purchase at VitaLife
|
||||
export function generateResleeves(): Resleeve[] {
|
||||
const NumResleeves = 40; // Total number of Resleeves to generate
|
||||
const NumResleeves = 40; // Total number of Resleeves to generate
|
||||
|
||||
const ret: Resleeve[] = [];
|
||||
for (let i = 0; i < NumResleeves; ++i) {
|
||||
// i will be a number indicating how "powerful" the Re-sleeve should be
|
||||
const r: Resleeve = new Resleeve();
|
||||
const ret: Resleeve[] = [];
|
||||
for (let i = 0; i < NumResleeves; ++i) {
|
||||
// i will be a number indicating how "powerful" the Re-sleeve should be
|
||||
const r: Resleeve = new Resleeve();
|
||||
|
||||
// Generate experience
|
||||
const expMult: number = (5 * i) + 1;
|
||||
r.hacking_exp = expMult * getRandomInt(1000, 5000);
|
||||
r.strength_exp = expMult * getRandomInt(1000, 5000);
|
||||
r.defense_exp = expMult * getRandomInt(1000, 5000);
|
||||
r.dexterity_exp = expMult * getRandomInt(1000, 5000);
|
||||
r.agility_exp = expMult * getRandomInt(1000, 5000);
|
||||
r.charisma_exp = expMult * getRandomInt(1000, 5000);
|
||||
// Generate experience
|
||||
const expMult: number = 5 * i + 1;
|
||||
r.hacking_exp = expMult * getRandomInt(1000, 5000);
|
||||
r.strength_exp = expMult * getRandomInt(1000, 5000);
|
||||
r.defense_exp = expMult * getRandomInt(1000, 5000);
|
||||
r.dexterity_exp = expMult * getRandomInt(1000, 5000);
|
||||
r.agility_exp = expMult * getRandomInt(1000, 5000);
|
||||
r.charisma_exp = expMult * getRandomInt(1000, 5000);
|
||||
|
||||
// Generate Augs
|
||||
// Augmentation prequisites will be ignored for this
|
||||
const baseNumAugs: number = Math.max(2, Math.ceil((i + 3) / 2));
|
||||
const numAugs: number = getRandomInt(baseNumAugs, baseNumAugs + 2);
|
||||
const augKeys: string[] = Object.keys(Augmentations);
|
||||
for (let a = 0; a < numAugs; ++a) {
|
||||
// Get a random aug
|
||||
const randIndex: number = getRandomInt(0, augKeys.length - 1)
|
||||
const randKey: string = augKeys[randIndex];
|
||||
// Generate Augs
|
||||
// Augmentation prequisites will be ignored for this
|
||||
const baseNumAugs: number = Math.max(2, Math.ceil((i + 3) / 2));
|
||||
const numAugs: number = getRandomInt(baseNumAugs, baseNumAugs + 2);
|
||||
const augKeys: string[] = Object.keys(Augmentations);
|
||||
for (let a = 0; a < numAugs; ++a) {
|
||||
// Get a random aug
|
||||
const randIndex: number = getRandomInt(0, augKeys.length - 1);
|
||||
const randKey: string = augKeys[randIndex];
|
||||
|
||||
// Forbidden augmentations
|
||||
if (randKey === AugmentationNames.TheRedPill || randKey === AugmentationNames.NeuroFluxGovernor) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const randAug: Augmentation | null = Augmentations[randKey];
|
||||
if(randAug === null) throw new Error(`null augmentation: ${randKey}`)
|
||||
r.augmentations.push({name: randAug.name, level: 1});
|
||||
r.applyAugmentation(Augmentations[randKey]);
|
||||
r.updateStatLevels();
|
||||
// Forbidden augmentations
|
||||
if (
|
||||
randKey === AugmentationNames.TheRedPill ||
|
||||
randKey === AugmentationNames.NeuroFluxGovernor
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Remove Augmentation so that there are no duplicates
|
||||
augKeys.splice(randIndex, 1);
|
||||
}
|
||||
const randAug: Augmentation | null = Augmentations[randKey];
|
||||
if (randAug === null) throw new Error(`null augmentation: ${randKey}`);
|
||||
r.augmentations.push({ name: randAug.name, level: 1 });
|
||||
r.applyAugmentation(Augmentations[randKey]);
|
||||
r.updateStatLevels();
|
||||
|
||||
ret.push(r);
|
||||
// Remove Augmentation so that there are no duplicates
|
||||
augKeys.splice(randIndex, 1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
ret.push(r);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
* Module for handling the Re-sleeving UI
|
||||
*/
|
||||
import { Resleeve } from "./Resleeve";
|
||||
import { generateResleeves,
|
||||
purchaseResleeve } from "./Resleeving";
|
||||
import { generateResleeves, purchaseResleeve } from "./Resleeving";
|
||||
|
||||
import { IPlayer } from "../IPlayer";
|
||||
|
||||
@@ -12,8 +11,7 @@ import { Augmentations } from "../../Augmentation/Augmentations";
|
||||
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { Page,
|
||||
routing } from "../../ui/navigationTracking";
|
||||
import { Page, routing } from "../../ui/navigationTracking";
|
||||
|
||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||
|
||||
@@ -26,353 +24,509 @@ import { removeChildrenFromElement } from "../../../utils/uiHelpers/removeChildr
|
||||
import { removeElement } from "../../../utils/uiHelpers/removeElement";
|
||||
|
||||
import * as React from "react";
|
||||
import { renderToStaticMarkup } from "react-dom/server"
|
||||
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;
|
||||
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;
|
||||
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,
|
||||
}
|
||||
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; }
|
||||
if (!routing.isOn(Page.Resleeves)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
playerRef = p;
|
||||
try {
|
||||
playerRef = p;
|
||||
|
||||
UIElems.container = createElement("div", {
|
||||
class: "generic-menupage-container",
|
||||
id: "resleeves-container",
|
||||
position: "fixed",
|
||||
});
|
||||
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%",
|
||||
});
|
||||
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);
|
||||
// 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);
|
||||
}
|
||||
if (UIElems.container instanceof HTMLElement) {
|
||||
removeElement(UIElems.container);
|
||||
}
|
||||
|
||||
for (const prop in UIElems) {
|
||||
(UIElems as any)[prop] = null;
|
||||
}
|
||||
for (const prop in UIElems) {
|
||||
(UIElems as any)[prop] = null;
|
||||
}
|
||||
|
||||
playerRef = 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);
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
let innerHTML = aug.info;
|
||||
if (typeof innerHTML !== "string") {
|
||||
innerHTML = renderToStaticMarkup(innerHTML);
|
||||
}
|
||||
|
||||
elems.augDescription.innerHTML = innerHTML;
|
||||
elems.augDescription.innerHTML = innerHTML;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user