fix sleeve memory bug

This commit is contained in:
Olivier Gagnon
2021-09-08 23:47:34 -04:00
parent bada8a5f39
commit 2a13db39c7
360 changed files with 5424 additions and 15764 deletions
+1 -4
View File
@@ -146,10 +146,7 @@ export interface IPlayer {
getGangFaction(): Faction;
getGangName(): string;
getHomeComputer(): Server;
getNextCompanyPosition(
company: Company,
entryPosType: CompanyPosition,
): CompanyPosition;
getNextCompanyPosition(company: Company, entryPosType: CompanyPosition): CompanyPosition;
getUpgradeHomeRamCost(): number;
gotoLocation(to: LocationName): boolean;
hasCorporation(): boolean;
+8 -36
View File
@@ -114,9 +114,7 @@ export abstract class Person {
applyAugmentation(aug: Augmentation): void {
for (const mult in aug.mults) {
if ((this as any)[mult] == null) {
console.warn(
`Augmentation has unrecognized multiplier property: ${mult}`,
);
console.warn(`Augmentation has unrecognized multiplier property: ${mult}`);
} else {
(this as any)[mult] *= aug.mults[mult];
}
@@ -153,9 +151,7 @@ export abstract class Person {
* when doing Hacking Work for a faction
*/
getFactionHackingWorkRepGain(): number {
return (
(this.hacking_skill / CONSTANTS.MaxSkillLevel) * this.faction_rep_mult
);
return (this.hacking_skill / CONSTANTS.MaxSkillLevel) * this.faction_rep_mult;
}
/**
@@ -207,56 +203,32 @@ export abstract class Person {
updateStatLevels(): void {
this.hacking_skill = Math.max(
1,
Math.floor(
this.calculateStat(
this.hacking_exp,
this.hacking_mult * BitNodeMultipliers.HackingLevelMultiplier,
),
),
Math.floor(this.calculateStat(this.hacking_exp, this.hacking_mult * BitNodeMultipliers.HackingLevelMultiplier)),
);
this.strength = Math.max(
1,
Math.floor(
this.calculateStat(
this.strength_exp,
this.strength_mult * BitNodeMultipliers.StrengthLevelMultiplier,
),
this.calculateStat(this.strength_exp, this.strength_mult * BitNodeMultipliers.StrengthLevelMultiplier),
),
);
this.defense = Math.max(
1,
Math.floor(
this.calculateStat(
this.defense_exp,
this.defense_mult * BitNodeMultipliers.DefenseLevelMultiplier,
),
),
Math.floor(this.calculateStat(this.defense_exp, this.defense_mult * BitNodeMultipliers.DefenseLevelMultiplier)),
);
this.dexterity = Math.max(
1,
Math.floor(
this.calculateStat(
this.dexterity_exp,
this.dexterity_mult * BitNodeMultipliers.DexterityLevelMultiplier,
),
this.calculateStat(this.dexterity_exp, this.dexterity_mult * BitNodeMultipliers.DexterityLevelMultiplier),
),
);
this.agility = Math.max(
1,
Math.floor(
this.calculateStat(
this.agility_exp,
this.agility_mult * BitNodeMultipliers.AgilityLevelMultiplier,
),
),
Math.floor(this.calculateStat(this.agility_exp, this.agility_mult * BitNodeMultipliers.AgilityLevelMultiplier)),
);
this.charisma = Math.max(
1,
Math.floor(
this.calculateStat(
this.charisma_exp,
this.charisma_mult * BitNodeMultipliers.CharismaLevelMultiplier,
),
this.calculateStat(this.charisma_exp, this.charisma_mult * BitNodeMultipliers.CharismaLevelMultiplier),
),
);
+1 -5
View File
@@ -9,11 +9,7 @@ import { HashManager } from "../../Hacknet/HashManager";
import { CityName } from "../../Locations/data/CityNames";
import { MoneySourceTracker } from "../../utils/MoneySourceTracker";
import {
Reviver,
Generic_toJSON,
Generic_fromJSON,
} from "../../../utils/JSONReviver";
import { Reviver, Generic_toJSON, Generic_fromJSON } from "../../../utils/JSONReviver";
import Decimal from "decimal.js";
@@ -5,10 +5,7 @@ import { IPlayer } from "../IPlayer";
import { Augmentation } from "../../Augmentation/Augmentation";
export function hasAugmentation(
this: IPlayer,
aug: string | Augmentation,
): boolean {
export function hasAugmentation(this: IPlayer, aug: string | Augmentation): boolean {
const augName: string = aug instanceof Augmentation ? aug.name : aug;
for (const owned of this.augmentations) {
@@ -6,12 +6,7 @@ export function canAccessBladeburner() {
return false;
}
return (
this.bitNodeN === 6 ||
this.bitNodeN === 7 ||
SourceFileFlags[6] > 0 ||
SourceFileFlags[7] > 0
);
return this.bitNodeN === 6 || this.bitNodeN === 7 || SourceFileFlags[6] > 0 || SourceFileFlags[7] > 0;
}
export function inBladeburner() {
@@ -14,9 +14,7 @@ export function canAccessGang() {
return false;
}
return (
this.karma <= BitNodeMultipliers.GangKarmaRequirement * GangKarmaRequirement
);
return this.karma <= BitNodeMultipliers.GangKarmaRequirement * GangKarmaRequirement;
}
export function getGangFaction() {
File diff suppressed because it is too large Load Diff
@@ -8,11 +8,7 @@ import { CONSTANTS } from "../../Constants";
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
import { Server } from "../../Server/Server";
import { HacknetServer } from "../../Hacknet/HacknetServer";
import {
AddToAllServers,
AllServers,
createUniqueRandomIp,
} from "../../Server/AllServers";
import { AddToAllServers, AllServers, createUniqueRandomIp } from "../../Server/AllServers";
import { SpecialServerIps } from "../../Server/SpecialServerIps";
export function hasTorRouter(this: IPlayer): boolean {
@@ -35,11 +31,7 @@ export function getUpgradeHomeRamCost(this: IPlayer): number {
//Calculate cost
//Have cost increase by some percentage each time RAM has been upgraded
const mult = Math.pow(1.58, numUpgrades);
const cost =
currentRam *
CONSTANTS.BaseCostFor1GBOfRamHome *
mult *
BitNodeMultipliers.HomeComputerRamCost;
const cost = currentRam * CONSTANTS.BaseCostFor1GBOfRamHome * mult * BitNodeMultipliers.HomeComputerRamCost;
return cost;
}
+4 -15
View File
@@ -7,11 +7,7 @@ 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() {
@@ -37,22 +33,15 @@ export class Resleeve extends Person {
// 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];
const aug: Augmentation | null = Augmentations[this.augmentations[i].name];
if (aug == null) {
console.error(
`Could not find Augmentation ${this.augmentations[i].name}`,
);
console.error(`Could not find Augmentation ${this.augmentations[i].name}`);
continue;
}
totalAugmentationCost += aug.startingCost;
}
return (
totalExp * CostPerExp +
totalAugmentationCost *
Math.pow(NumAugsExponent, this.augmentations.length)
);
return totalExp * CostPerExp + totalAugmentationCost * Math.pow(NumAugsExponent, this.augmentations.length);
}
/**
+3 -11
View File
@@ -15,10 +15,7 @@ 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";
@@ -67,9 +64,7 @@ export function purchaseResleeve(r: Resleeve, p: IPlayer): boolean {
if (
p.augmentations.filter((e: IPlayerOwnedAugmentation) => {
return (
e.name !== AugmentationNames.NeuroFluxGovernor && e.name === name
);
return e.name !== AugmentationNames.NeuroFluxGovernor && e.name === name;
}).length >= 1
) {
p.queuedAugmentations.splice(i, 1);
@@ -110,10 +105,7 @@ export function generateResleeves(): Resleeve[] {
const randKey: string = augKeys[randIndex];
// Forbidden augmentations
if (
randKey === AugmentationNames.TheRedPill ||
randKey === AugmentationNames.NeuroFluxGovernor
) {
if (randKey === AugmentationNames.TheRedPill || randKey === AugmentationNames.NeuroFluxGovernor) {
continue;
}
+60 -164
View File
@@ -119,39 +119,15 @@ export function createResleevesPage(p: IPlayer): void {
}
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.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 = () => {
@@ -202,40 +178,16 @@ export function createResleevesPage(p: IPlayer): void {
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,
);
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,
);
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;
});
@@ -253,18 +205,13 @@ export function createResleevesPage(p: IPlayer): void {
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()");
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()",
);
if (resleeveUi.container == null) throw new Error("resleeveUi.container is null in sortSelector.click()");
UIElems.resleeveList.appendChild(resleeveUi.container);
UIElems.resleeves.push(resleeveUi);
}
@@ -278,10 +225,7 @@ export function createResleevesPage(p: IPlayer): void {
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()",
);
if (container == null) throw new Error("Could not find entire-game-container in createResleevesPage()");
container.appendChild(UIElems.container);
} catch (e) {
exceptionAlert(e);
@@ -331,24 +275,24 @@ function createResleeveUi(resleeve: Resleeve): IResleeveUIElems {
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 />` +
`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", {
@@ -358,72 +302,28 @@ function createResleeveUi(resleeve: Resleeve): IResleeveUIElems {
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,
)}`,
`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,
)}`,
@@ -481,16 +381,13 @@ function createResleeveUi(resleeve: Resleeve): IResleeveUIElems {
});
elems.costText = createElement("p", {
innerHTML:
`It costs ${renderToStaticMarkup(
<Money money={cost} player={playerRef} />,
)} ` + `to purchase this Sleeve.`,
`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 (playerRef == null) throw new Error("playerRef is null in buyButton.click()");
if (purchaseResleeve(resleeve, playerRef)) {
dialogBoxCreate(
<>
@@ -514,8 +411,7 @@ function createResleeveUi(resleeve: Resleeve): IResleeveUIElems {
}
function updateAugDescription(elems: IResleeveUIElems): void {
if (elems.augDescription == null)
throw new Error("elems.augDescription is null in updateAugDescription()");
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) {
+56 -169
View File
@@ -32,11 +32,7 @@ import { FactionWorkType } from "../../Faction/FactionWorkTypeEnum";
import { CityName } from "../../Locations/data/CityNames";
import { LocationName } from "../../Locations/data/LocationNames";
import {
Generic_fromJSON,
Generic_toJSON,
Reviver,
} from "../../../utils/JSONReviver";
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../../utils/JSONReviver";
export class Sleeve extends Person {
/**
@@ -158,32 +154,13 @@ export class Sleeve extends Person {
this.resetTaskStatus();
}
this.gainRatesForTask.hack =
crime.hacking_exp *
this.hacking_exp_mult *
BitNodeMultipliers.CrimeExpGain;
this.gainRatesForTask.str =
crime.strength_exp *
this.strength_exp_mult *
BitNodeMultipliers.CrimeExpGain;
this.gainRatesForTask.def =
crime.defense_exp *
this.defense_exp_mult *
BitNodeMultipliers.CrimeExpGain;
this.gainRatesForTask.dex =
crime.dexterity_exp *
this.dexterity_exp_mult *
BitNodeMultipliers.CrimeExpGain;
this.gainRatesForTask.agi =
crime.agility_exp *
this.agility_exp_mult *
BitNodeMultipliers.CrimeExpGain;
this.gainRatesForTask.cha =
crime.charisma_exp *
this.charisma_exp_mult *
BitNodeMultipliers.CrimeExpGain;
this.gainRatesForTask.money =
crime.money * this.crime_money_mult * BitNodeMultipliers.CrimeMoney;
this.gainRatesForTask.hack = crime.hacking_exp * this.hacking_exp_mult * BitNodeMultipliers.CrimeExpGain;
this.gainRatesForTask.str = crime.strength_exp * this.strength_exp_mult * BitNodeMultipliers.CrimeExpGain;
this.gainRatesForTask.def = crime.defense_exp * this.defense_exp_mult * BitNodeMultipliers.CrimeExpGain;
this.gainRatesForTask.dex = crime.dexterity_exp * this.dexterity_exp_mult * BitNodeMultipliers.CrimeExpGain;
this.gainRatesForTask.agi = crime.agility_exp * this.agility_exp_mult * BitNodeMultipliers.CrimeExpGain;
this.gainRatesForTask.cha = crime.charisma_exp * this.charisma_exp_mult * BitNodeMultipliers.CrimeExpGain;
this.gainRatesForTask.money = crime.money * this.crime_money_mult * BitNodeMultipliers.CrimeMoney;
this.currentTaskLocation = String(this.gainRatesForTask.money);
@@ -204,9 +181,7 @@ export class Sleeve extends Person {
if (this.currentTaskTime >= this.currentTaskMaxTime) {
const crime: Crime | null = Crimes[this.crimeType];
if (!(crime instanceof Crime)) {
console.error(
`Invalid data stored in sleeve.crimeType: ${this.crimeType}`,
);
console.error(`Invalid data stored in sleeve.crimeType: ${this.crimeType}`);
this.resetTaskStatus();
return retValue;
}
@@ -214,9 +189,7 @@ export class Sleeve extends Person {
// Success
const successGainRates: ITaskTracker = createTaskTracker();
const keysForIteration: (keyof ITaskTracker)[] = Object.keys(
successGainRates,
) as (keyof ITaskTracker)[];
const keysForIteration: (keyof ITaskTracker)[] = Object.keys(successGainRates) as (keyof ITaskTracker)[];
for (let i = 0; i < keysForIteration.length; ++i) {
const key = keysForIteration[i];
successGainRates[key] = this.gainRatesForTask[key] * 2;
@@ -246,12 +219,7 @@ export class Sleeve extends Person {
* Earn experience for any stats (supports multiple)
* This function also handles experience propogating to Player and other sleeves
*/
gainExperience(
p: IPlayer,
exp: ITaskTracker,
numCycles = 1,
fromOtherSleeve = false,
): ITaskTracker {
gainExperience(p: IPlayer, exp: ITaskTracker, numCycles = 1, fromOtherSleeve = false): ITaskTracker {
// If the experience is coming from another sleeve, it is not multiplied by anything.
// Also the player does not earn anything
if (fromOtherSleeve) {
@@ -405,41 +373,26 @@ export class Sleeve extends Person {
switch (this.factionWorkType) {
case FactionWorkType.Hacking:
return (
this.getFactionHackingWorkRepGain() * (this.shock / 100) * favorMult
);
return this.getFactionHackingWorkRepGain() * (this.shock / 100) * favorMult;
case FactionWorkType.Field:
return (
this.getFactionFieldWorkRepGain() * (this.shock / 100) * favorMult
);
return this.getFactionFieldWorkRepGain() * (this.shock / 100) * favorMult;
case FactionWorkType.Security:
return (
this.getFactionSecurityWorkRepGain() *
(this.shock / 100) *
favorMult
);
return this.getFactionSecurityWorkRepGain() * (this.shock / 100) * favorMult;
default:
console.warn(
`Invalid Sleeve.factionWorkType property in Sleeve.getRepGain(): ${this.factionWorkType}`,
);
console.warn(`Invalid Sleeve.factionWorkType property in Sleeve.getRepGain(): ${this.factionWorkType}`);
return 0;
}
} else if (this.currentTask === SleeveTaskType.Company) {
const companyName: string = this.currentTaskLocation;
const company: Company | null = Companies[companyName];
if (company == null) {
console.error(
`Invalid company found when trying to calculate rep gain: ${companyName}`,
);
console.error(`Invalid company found when trying to calculate rep gain: ${companyName}`);
return 0;
}
const companyPosition: CompanyPosition | null =
CompanyPositions[p.jobs[companyName]];
const companyPosition: CompanyPosition | null = CompanyPositions[p.jobs[companyName]];
if (companyPosition == null) {
console.error(
`Invalid company position name found when trying to calculate rep gain: ${p.jobs[companyName]}`,
);
console.error(`Invalid company position name found when trying to calculate rep gain: ${p.jobs[companyName]}`);
return 0;
}
@@ -455,9 +408,7 @@ export class Sleeve extends Person {
return jobPerformance * this.company_rep_mult * favorMult;
} else {
console.warn(
`Sleeve.getRepGain() called for invalid task type: ${this.currentTask}`,
);
console.warn(`Sleeve.getRepGain() called for invalid task type: ${this.currentTask}`);
return 0;
}
}
@@ -527,10 +478,7 @@ export class Sleeve extends Person {
let time = this.storedCycles * CONSTANTS.MilliPerCycle;
let cyclesUsed = this.storedCycles;
if (
this.currentTaskMaxTime !== 0 &&
this.currentTaskTime + time > this.currentTaskMaxTime
) {
if (this.currentTaskMaxTime !== 0 && this.currentTaskTime + time > this.currentTaskMaxTime) {
time = this.currentTaskMaxTime - this.currentTaskTime;
cyclesUsed = Math.floor(time / CONSTANTS.MilliPerCycle);
@@ -562,9 +510,7 @@ export class Sleeve extends Person {
// Gain faction reputation
const fac: Faction = Factions[this.currentTaskLocation];
if (!(fac instanceof Faction)) {
console.error(
`Invalid faction for Sleeve task: ${this.currentTaskLocation}`,
);
console.error(`Invalid faction for Sleeve task: ${this.currentTaskLocation}`);
break;
}
@@ -577,9 +523,7 @@ export class Sleeve extends Person {
const company: Company = Companies[this.currentTaskLocation];
if (!(company instanceof Company)) {
console.error(
`Invalid company for Sleeve task: ${this.currentTaskLocation}`,
);
console.error(`Invalid company for Sleeve task: ${this.currentTaskLocation}`);
break;
}
@@ -590,19 +534,13 @@ export class Sleeve extends Person {
this.shock = Math.min(100, this.shock + 0.0002 * cyclesUsed);
break;
case SleeveTaskType.Synchro:
this.sync = Math.min(
100,
this.sync + p.getIntelligenceBonus(0.5) * 0.0002 * cyclesUsed,
);
this.sync = Math.min(100, this.sync + p.getIntelligenceBonus(0.5) * 0.0002 * cyclesUsed);
break;
default:
break;
}
if (
this.currentTaskMaxTime !== 0 &&
this.currentTaskTime >= this.currentTaskMaxTime
) {
if (this.currentTaskMaxTime !== 0 && this.currentTaskTime >= this.currentTaskMaxTime) {
if (this.currentTask === SleeveTaskType.Crime) {
retValue = this.finishTask(p);
} else {
@@ -658,11 +596,7 @@ export class Sleeve extends Person {
/**
* Take a course at a university
*/
takeUniversityCourse(
p: IPlayer,
universityName: string,
className: string,
): boolean {
takeUniversityCourse(p: IPlayer, universityName: string, className: string): boolean {
if (this.currentTask !== SleeveTaskType.Idle) {
this.finishTask(p);
} else {
@@ -703,24 +637,19 @@ export class Sleeve extends Person {
case "study computer science":
break;
case "data structures":
this.gainRatesForTask.money =
-1 * (CONSTANTS.ClassDataStructuresBaseCost * costMult);
this.gainRatesForTask.money = -1 * (CONSTANTS.ClassDataStructuresBaseCost * costMult);
break;
case "networks":
this.gainRatesForTask.money =
-1 * (CONSTANTS.ClassNetworksBaseCost * costMult);
this.gainRatesForTask.money = -1 * (CONSTANTS.ClassNetworksBaseCost * costMult);
break;
case "algorithms":
this.gainRatesForTask.money =
-1 * (CONSTANTS.ClassAlgorithmsBaseCost * costMult);
this.gainRatesForTask.money = -1 * (CONSTANTS.ClassAlgorithmsBaseCost * costMult);
break;
case "management":
this.gainRatesForTask.money =
-1 * (CONSTANTS.ClassManagementBaseCost * costMult);
this.gainRatesForTask.money = -1 * (CONSTANTS.ClassManagementBaseCost * costMult);
break;
case "leadership":
this.gainRatesForTask.money =
-1 * (CONSTANTS.ClassLeadershipBaseCost * costMult);
this.gainRatesForTask.money = -1 * (CONSTANTS.ClassLeadershipBaseCost * costMult);
break;
default:
return false;
@@ -777,39 +706,22 @@ export class Sleeve extends Person {
switch (this.className.toLowerCase()) {
case "study computer science":
this.gainRatesForTask.hack =
CONSTANTS.ClassStudyComputerScienceBaseExp *
totalExpMult *
this.hacking_exp_mult;
CONSTANTS.ClassStudyComputerScienceBaseExp * totalExpMult * this.hacking_exp_mult;
break;
case "data structures":
this.gainRatesForTask.hack =
CONSTANTS.ClassDataStructuresBaseExp *
totalExpMult *
this.hacking_exp_mult;
this.gainRatesForTask.hack = CONSTANTS.ClassDataStructuresBaseExp * totalExpMult * this.hacking_exp_mult;
break;
case "networks":
this.gainRatesForTask.hack =
CONSTANTS.ClassNetworksBaseExp *
totalExpMult *
this.hacking_exp_mult;
this.gainRatesForTask.hack = CONSTANTS.ClassNetworksBaseExp * totalExpMult * this.hacking_exp_mult;
break;
case "algorithms":
this.gainRatesForTask.hack =
CONSTANTS.ClassAlgorithmsBaseExp *
totalExpMult *
this.hacking_exp_mult;
this.gainRatesForTask.hack = CONSTANTS.ClassAlgorithmsBaseExp * totalExpMult * this.hacking_exp_mult;
break;
case "management":
this.gainRatesForTask.cha =
CONSTANTS.ClassManagementBaseExp *
totalExpMult *
this.charisma_exp_mult;
this.gainRatesForTask.cha = CONSTANTS.ClassManagementBaseExp * totalExpMult * this.charisma_exp_mult;
break;
case "leadership":
this.gainRatesForTask.cha =
CONSTANTS.ClassLeadershipBaseExp *
totalExpMult *
this.charisma_exp_mult;
this.gainRatesForTask.cha = CONSTANTS.ClassLeadershipBaseExp * totalExpMult * this.charisma_exp_mult;
break;
default:
break;
@@ -846,25 +758,19 @@ export class Sleeve extends Person {
const totalExpMultiplier = p.hashManager.getTrainingMult() * expMult;
const sanitizedStat: string = this.gymStatType.toLowerCase();
if (sanitizedStat.includes("str")) {
this.gainRatesForTask.str =
baseGymExp * totalExpMultiplier * this.strength_exp_mult;
this.gainRatesForTask.str = baseGymExp * totalExpMultiplier * this.strength_exp_mult;
} else if (sanitizedStat.includes("def")) {
this.gainRatesForTask.def =
baseGymExp * totalExpMultiplier * this.defense_exp_mult;
this.gainRatesForTask.def = baseGymExp * totalExpMultiplier * this.defense_exp_mult;
} else if (sanitizedStat.includes("dex")) {
this.gainRatesForTask.dex =
baseGymExp * totalExpMultiplier * this.dexterity_exp_mult;
this.gainRatesForTask.dex = baseGymExp * totalExpMultiplier * this.dexterity_exp_mult;
} else if (sanitizedStat.includes("agi")) {
this.gainRatesForTask.agi =
baseGymExp * totalExpMultiplier * this.agility_exp_mult;
this.gainRatesForTask.agi = baseGymExp * totalExpMultiplier * this.agility_exp_mult;
}
return;
}
console.warn(
`Sleeve.updateTaskGainRates() called for unexpected task type ${this.currentTask}`,
);
console.warn(`Sleeve.updateTaskGainRates() called for unexpected task type ${this.currentTask}`);
}
upgradeMemory(n: number): void {
@@ -881,10 +787,7 @@ export class Sleeve extends Person {
* Returns boolean indicating success
*/
workForCompany(p: IPlayer, companyName: string): boolean {
if (
!(Companies[companyName] instanceof Company) ||
p.jobs[companyName] == null
) {
if (!(Companies[companyName] instanceof Company) || p.jobs[companyName] == null) {
return false;
}
@@ -895,8 +798,7 @@ export class Sleeve extends Person {
}
const company: Company | null = Companies[companyName];
const companyPosition: CompanyPosition | null =
CompanyPositions[p.jobs[companyName]];
const companyPosition: CompanyPosition | null = CompanyPositions[p.jobs[companyName]];
if (company == null) {
return false;
}
@@ -954,10 +856,7 @@ export class Sleeve extends Person {
if (factionName === "") {
return false;
}
if (
!(Factions[factionName] instanceof Faction) ||
!p.factions.includes(factionName)
) {
if (!(Factions[factionName] instanceof Faction) || !p.factions.includes(factionName)) {
return false;
}
@@ -976,40 +875,28 @@ export class Sleeve extends Person {
return false;
}
this.factionWorkType = FactionWorkType.Hacking;
this.gainRatesForTask.hack =
0.15 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.hack = 0.15 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
} else if (sanitizedWorkType.includes("field")) {
if (!factionInfo.offerFieldWork) {
return false;
}
this.factionWorkType = FactionWorkType.Field;
this.gainRatesForTask.hack =
0.1 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.str =
0.1 * this.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.def =
0.1 * this.defense_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.dex =
0.1 * this.dexterity_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.agi =
0.1 * this.agility_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.cha =
0.1 * this.charisma_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.hack = 0.1 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.str = 0.1 * this.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.def = 0.1 * this.defense_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.dex = 0.1 * this.dexterity_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.agi = 0.1 * this.agility_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.cha = 0.1 * this.charisma_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
} else if (sanitizedWorkType.includes("security")) {
if (!factionInfo.offerSecurityWork) {
return false;
}
this.factionWorkType = FactionWorkType.Security;
this.gainRatesForTask.hack =
0.1 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.str =
0.15 * this.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.def =
0.15 * this.defense_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.dex =
0.15 * this.dexterity_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.agi =
0.15 * this.agility_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.hack = 0.1 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.str = 0.15 * this.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.def = 0.15 * this.defense_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.dex = 0.15 * this.dexterity_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.agi = 0.15 * this.agility_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
} else {
return false;
}
@@ -22,10 +22,7 @@ import { removeElementById } from "../../../utils/uiHelpers/removeElementById";
import { renderToStaticMarkup } from "react-dom/server";
export function createSleevePurchaseAugsPopup(
sleeve: Sleeve,
p: IPlayer,
): void {
export function createSleevePurchaseAugsPopup(sleeve: Sleeve, p: IPlayer): void {
// Array of all owned Augmentations. Names only
const ownedAugNames: string[] = sleeve.augmentations.map((e) => {
return e.name;
@@ -109,18 +106,13 @@ export function createSleevePurchaseAugsPopup(
fontSize: "12px",
innerHTML: [
`<h2>${aug.name}</h2><br>`,
`Cost: ${renderToStaticMarkup(
<Money money={aug.startingCost} player={p} />,
)}<br><br>`,
`Cost: ${renderToStaticMarkup(<Money money={aug.startingCost} player={p} />)}<br><br>`,
`${info}`,
].join(" "),
padding: "2px",
clickListener: () => {
if (sleeve.tryBuyAugmentation(p, aug)) {
dialogBoxCreate(
`Installed ${aug.name} on Duplicate Sleeve!`,
false,
);
dialogBoxCreate(`Installed ${aug.name} on Duplicate Sleeve!`, false);
removeElementById(popupId);
createSleevePurchaseAugsPopup(sleeve, p);
} else {
+1 -4
View File
@@ -8,10 +8,7 @@ import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { Faction } from "../../Faction/Faction";
import { Factions } from "../../Faction/Factions";
export function findSleevePurchasableAugs(
sleeve: Sleeve,
p: IPlayer,
): Augmentation[] {
export function findSleevePurchasableAugs(sleeve: Sleeve, p: IPlayer): Augmentation[] {
// 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.
+56 -188
View File
@@ -136,8 +136,7 @@ export function createSleevesPage(p: IPlayer): void {
// Create UI modules for all Sleeve
for (const sleeve of p.sleeves) {
const sleeveUi = createSleeveUi(sleeve, p.sleeves);
if (sleeveUi.container == null)
throw new Error("sleeveUi.container is null in createSleevesPage()");
if (sleeveUi.container == null) throw new Error("sleeveUi.container is null in createSleevesPage()");
UIElems.sleeveList.appendChild(sleeveUi.container);
UIElems.sleeves.push(sleeveUi);
}
@@ -148,8 +147,7 @@ export function createSleevesPage(p: IPlayer): void {
UIElems.container.appendChild(UIElems.sleeveList);
const container = document.getElementById("entire-game-container");
if (container === null)
throw new Error("entire-game-container not found in createSleevesPage()");
if (container === null) throw new Error("entire-game-container not found in createSleevesPage()");
container.appendChild(UIElems.container);
} catch (e) {
exceptionAlert(e);
@@ -161,10 +159,8 @@ export function updateSleevesPage(): void {
if (!routing.isOn(Page.Sleeves)) {
return;
}
if (playerRef === null)
throw new Error("playerRef is null in updateSleevesPage()");
if (UIElems.sleeves === null)
throw new Error("UIElems.sleeves is null in updateSleevesPage()");
if (playerRef === null) throw new Error("playerRef is null in updateSleevesPage()");
if (UIElems.sleeves === null) throw new Error("UIElems.sleeves is null in updateSleevesPage()");
try {
for (let i = 0; i < playerRef.sleeves.length; ++i) {
@@ -240,9 +236,7 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
if (playerRef === null) return;
const popupId = "sleeve-travel-popup";
const popupArguments: HTMLElement[] = [];
popupArguments.push(
createPopupCloseButton(popupId, { class: "std-button" }),
);
popupArguments.push(createPopupCloseButton(popupId, { class: "std-button" }));
popupArguments.push(
createElement("p", {
innerHTML:
@@ -266,15 +260,9 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
class: "cmpy-mgmt-find-employee-option",
innerText: cityName,
clickListener: () => {
if (playerRef == null)
throw new Error(
"playerRef is null in popupArguments.click()",
);
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,
);
dialogBoxCreate("You cannot afford to have this sleeve travel to another city", false);
return false;
}
sleeve.city = cityName as CityName;
@@ -298,8 +286,7 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
display: "block",
innerText: "Manage Augmentations",
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);
},
});
@@ -384,58 +371,24 @@ function updateSleeveUi(sleeve: Sleeve, elems: ISleeveUIElems): void {
if (!routing.isOn(Page.Sleeves)) {
return;
}
if (playerRef == null)
throw new Error("playerRef is null in updateSleeveUi()");
if (elems.taskProgressBar == null)
throw new Error("elems.taskProgressBar is null");
if (playerRef == null) throw new Error("playerRef is null in updateSleeveUi()");
if (elems.taskProgressBar == null) throw new Error("elems.taskProgressBar is null");
if (elems.stats == null) throw new Error("elems.stats is null");
if (elems.currentEarningsInfo == null)
throw new Error("elems.currentEarningsInfo is null");
if (elems.currentEarningsInfo == null) throw new Error("elems.currentEarningsInfo is null");
ReactDOM.render(StatsElement(sleeve), elems.stats);
if (sleeve.currentTask === SleeveTaskType.Crime) {
const data = [
[
`Money`,
<Money money={parseFloat(sleeve.currentTaskLocation)} />,
`(on success)`,
],
[
`Hacking Exp`,
numeralWrapper.formatExp(sleeve.gainRatesForTask.hack),
`(2x on success)`,
],
[
`Strength Exp`,
numeralWrapper.formatExp(sleeve.gainRatesForTask.str),
`(2x on success)`,
],
[
`Defense Exp`,
numeralWrapper.formatExp(sleeve.gainRatesForTask.def),
`(2x on success)`,
],
[
`Dexterity Exp`,
numeralWrapper.formatExp(sleeve.gainRatesForTask.dex),
`(2x on success)`,
],
[
`Agility Exp`,
numeralWrapper.formatExp(sleeve.gainRatesForTask.agi),
`(2x on success)`,
],
[
`Charisma Exp`,
numeralWrapper.formatExp(sleeve.gainRatesForTask.cha),
`(2x on success)`,
],
[`Money`, <Money money={parseFloat(sleeve.currentTaskLocation)} />, `(on success)`],
[`Hacking Exp`, numeralWrapper.formatExp(sleeve.gainRatesForTask.hack), `(2x on success)`],
[`Strength Exp`, numeralWrapper.formatExp(sleeve.gainRatesForTask.str), `(2x on success)`],
[`Defense Exp`, numeralWrapper.formatExp(sleeve.gainRatesForTask.def), `(2x on success)`],
[`Dexterity Exp`, numeralWrapper.formatExp(sleeve.gainRatesForTask.dex), `(2x on success)`],
[`Agility Exp`, numeralWrapper.formatExp(sleeve.gainRatesForTask.agi), `(2x on success)`],
[`Charisma Exp`, numeralWrapper.formatExp(sleeve.gainRatesForTask.cha), `(2x on success)`],
];
ReactDOM.render(
EarningsTableElement("Earnings (Pre-Synchronization)", data),
elems.currentEarningsInfo,
);
ReactDOM.render(EarningsTableElement("Earnings (Pre-Synchronization)", data), elems.currentEarningsInfo);
elems.taskProgressBar.innerText = createProgressBarText({
progress: sleeve.currentTaskTime / sleeve.currentTaskMaxTime,
@@ -444,42 +397,18 @@ function updateSleeveUi(sleeve: Sleeve, elems: ISleeveUIElems): void {
} else {
const data = [
[`Money:`, MoneyRate(5 * sleeve.gainRatesForTask.money)],
[
`Hacking Exp:`,
`${numeralWrapper.formatExp(5 * sleeve.gainRatesForTask.hack)} / s`,
],
[
`Strength Exp:`,
`${numeralWrapper.formatExp(5 * sleeve.gainRatesForTask.str)} / s`,
],
[
`Defense Exp:`,
`${numeralWrapper.formatExp(5 * sleeve.gainRatesForTask.def)} / s`,
],
[
`Dexterity Exp:`,
`${numeralWrapper.formatExp(5 * sleeve.gainRatesForTask.dex)} / s`,
],
[
`Agility Exp:`,
`${numeralWrapper.formatExp(5 * sleeve.gainRatesForTask.agi)} / s`,
],
[
`Charisma Exp:`,
`${numeralWrapper.formatExp(5 * sleeve.gainRatesForTask.cha)} / s`,
],
[`Hacking Exp:`, `${numeralWrapper.formatExp(5 * sleeve.gainRatesForTask.hack)} / s`],
[`Strength Exp:`, `${numeralWrapper.formatExp(5 * sleeve.gainRatesForTask.str)} / s`],
[`Defense Exp:`, `${numeralWrapper.formatExp(5 * sleeve.gainRatesForTask.def)} / s`],
[`Dexterity Exp:`, `${numeralWrapper.formatExp(5 * sleeve.gainRatesForTask.dex)} / s`],
[`Agility Exp:`, `${numeralWrapper.formatExp(5 * sleeve.gainRatesForTask.agi)} / s`],
[`Charisma Exp:`, `${numeralWrapper.formatExp(5 * sleeve.gainRatesForTask.cha)} / s`],
];
if (
sleeve.currentTask === SleeveTaskType.Company ||
sleeve.currentTask === SleeveTaskType.Faction
) {
if (sleeve.currentTask === SleeveTaskType.Company || sleeve.currentTask === SleeveTaskType.Faction) {
const repGain: number = sleeve.getRepGain(playerRef);
data.push([`Reputation:`, ReputationRate(5 * repGain)]);
}
ReactDOM.render(
EarningsTableElement("Earnings (Pre-Synchronization)", data),
elems.currentEarningsInfo,
);
ReactDOM.render(EarningsTableElement("Earnings (Pre-Synchronization)", data), elems.currentEarningsInfo);
elems.taskProgressBar.innerText = "";
}
@@ -494,19 +423,10 @@ const universitySelectorOptions: string[] = [
"Leadership",
];
const gymSelectorOptions: string[] = [
"Train Strength",
"Train Defense",
"Train Dexterity",
"Train Agility",
];
const gymSelectorOptions: string[] = ["Train Strength", "Train Defense", "Train Dexterity", "Train Agility"];
// Whenever a new task is selected, the "details" selector must update accordingly
function updateSleeveTaskSelector(
sleeve: Sleeve,
elems: ISleeveUIElems,
allSleeves: Sleeve[],
): void {
function updateSleeveTaskSelector(sleeve: Sleeve, elems: ISleeveUIElems, allSleeves: Sleeve[]): void {
if (playerRef == null) {
throw new Error(`playerRef is null in updateSleeveTaskSelector()`);
}
@@ -543,9 +463,7 @@ function updateSleeveTaskSelector(
// Reset Selectors
removeChildrenFromElement(elems.taskDetailsSelector);
removeChildrenFromElement(elems.taskDetailsSelector2);
elems.taskDetailsSelector2 = clearEventListeners(
elems.taskDetailsSelector2,
) as HTMLSelectElement;
elems.taskDetailsSelector2 = clearEventListeners(elems.taskDetailsSelector2) as HTMLSelectElement;
const value: string = getSelectValue(elems.taskSelector);
switch (value) {
@@ -585,23 +503,18 @@ function updateSleeveTaskSelector(
// The available faction work types depends on the faction
elems.taskDetailsSelector.addEventListener("change", () => {
if (elems.taskDetailsSelector2 === null)
throw new Error("elems.taskDetailsSelector2 is null");
if (elems.taskDetailsSelector2 === null) throw new Error("elems.taskDetailsSelector2 is null");
const facName = getSelectValue(elems.taskDetailsSelector);
const faction: Faction | null = Factions[facName];
if (faction == null) {
console.warn(
`Invalid faction name when trying to update Sleeve Task Selector: ${facName}`,
);
console.warn(`Invalid faction name when trying to update Sleeve Task Selector: ${facName}`);
return;
}
const facInfo = faction.getInfo();
removeChildrenFromElement(elems.taskDetailsSelector2);
let numOptionsAdded = 0;
if (facInfo.offerHackingWork) {
elems.taskDetailsSelector2.add(
createOptionElement("Hacking Contracts"),
);
elems.taskDetailsSelector2.add(createOptionElement("Hacking Contracts"));
if (sleeve.factionWorkType === FactionWorkType.Hacking) {
elems.taskDetailsSelector2.selectedIndex = numOptionsAdded;
}
@@ -652,9 +565,7 @@ function updateSleeveTaskSelector(
case "Take University Course":
// First selector has class type
for (let i = 0; i < universitySelectorOptions.length; ++i) {
elems.taskDetailsSelector.add(
createOptionElement(universitySelectorOptions[i]),
);
elems.taskDetailsSelector.add(createOptionElement(universitySelectorOptions[i]));
// Set initial value
if (sleeve.className === universitySelectorOptions[i]) {
@@ -665,39 +576,26 @@ function updateSleeveTaskSelector(
// Second selector has which university
switch (sleeve.city) {
case CityName.Aevum:
elems.taskDetailsSelector2.add(
createOptionElement(LocationName.AevumSummitUniversity),
);
elems.taskDetailsSelector2.add(createOptionElement(LocationName.AevumSummitUniversity));
break;
case CityName.Sector12:
elems.taskDetailsSelector2.add(
createOptionElement(LocationName.Sector12RothmanUniversity),
);
elems.taskDetailsSelector2.add(createOptionElement(LocationName.Sector12RothmanUniversity));
break;
case CityName.Volhaven:
elems.taskDetailsSelector2.add(
createOptionElement(LocationName.VolhavenZBInstituteOfTechnology),
);
elems.taskDetailsSelector2.add(createOptionElement(LocationName.VolhavenZBInstituteOfTechnology));
break;
default:
elems.taskDetailsSelector2.add(
createOptionElement("No university available in city!"),
);
elems.taskDetailsSelector2.add(createOptionElement("No university available in city!"));
break;
}
break;
case "Workout at Gym":
// First selector has what stat is being trained
for (let i = 0; i < gymSelectorOptions.length; ++i) {
elems.taskDetailsSelector.add(
createOptionElement(gymSelectorOptions[i]),
);
elems.taskDetailsSelector.add(createOptionElement(gymSelectorOptions[i]));
// Set initial value
if (
sleeve.gymStatType ===
gymSelectorOptions[i].substring(6, 9).toLowerCase()
) {
if (sleeve.gymStatType === gymSelectorOptions[i].substring(6, 9).toLowerCase()) {
elems.taskDetailsSelector.selectedIndex = i;
}
}
@@ -706,50 +604,32 @@ function updateSleeveTaskSelector(
// In this switch statement we also set the initial value of the second selector
switch (sleeve.city) {
case CityName.Aevum:
elems.taskDetailsSelector2.add(
createOptionElement(LocationName.AevumCrushFitnessGym),
);
elems.taskDetailsSelector2.add(
createOptionElement(LocationName.AevumSnapFitnessGym),
);
elems.taskDetailsSelector2.add(createOptionElement(LocationName.AevumCrushFitnessGym));
elems.taskDetailsSelector2.add(createOptionElement(LocationName.AevumSnapFitnessGym));
// Set initial value
if (
sleeve.currentTaskLocation === LocationName.AevumCrushFitnessGym
) {
if (sleeve.currentTaskLocation === LocationName.AevumCrushFitnessGym) {
elems.taskDetailsSelector2.selectedIndex = 0;
} else if (
sleeve.currentTaskLocation === LocationName.AevumSnapFitnessGym
) {
} else if (sleeve.currentTaskLocation === LocationName.AevumSnapFitnessGym) {
elems.taskDetailsSelector2.selectedIndex = 1;
}
break;
case CityName.Sector12:
elems.taskDetailsSelector2.add(
createOptionElement(LocationName.Sector12IronGym),
);
elems.taskDetailsSelector2.add(
createOptionElement(LocationName.Sector12PowerhouseGym),
);
elems.taskDetailsSelector2.add(createOptionElement(LocationName.Sector12IronGym));
elems.taskDetailsSelector2.add(createOptionElement(LocationName.Sector12PowerhouseGym));
// Set initial value
if (sleeve.currentTaskLocation === LocationName.Sector12IronGym) {
elems.taskDetailsSelector2.selectedIndex = 0;
} else if (
sleeve.currentTaskLocation === LocationName.Sector12PowerhouseGym
) {
} else if (sleeve.currentTaskLocation === LocationName.Sector12PowerhouseGym) {
elems.taskDetailsSelector2.selectedIndex = 1;
}
break;
case CityName.Volhaven:
elems.taskDetailsSelector2.add(
createOptionElement(LocationName.VolhavenMilleniumFitnessGym),
);
elems.taskDetailsSelector2.add(createOptionElement(LocationName.VolhavenMilleniumFitnessGym));
break;
default:
elems.taskDetailsSelector2.add(
createOptionElement("No gym available in city!"),
);
elems.taskDetailsSelector2.add(createOptionElement("No gym available in city!"));
break;
}
@@ -771,8 +651,7 @@ function setSleeveTask(sleeve: Sleeve, elems: ISleeveUIElems): boolean {
if (playerRef == null) {
throw new Error("playerRef is null in Sleeve UI's setSleeveTask()");
}
if (elems.taskDescription == null)
throw new Error("elems.taskDescription is null");
if (elems.taskDescription == null) throw new Error("elems.taskDescription is null");
const taskValue: string = getSelectValue(elems.taskSelector);
const detailValue: string = getSelectValue(elems.taskDetailsSelector);
@@ -806,9 +685,7 @@ function setSleeveTask(sleeve: Sleeve, elems: ISleeveUIElems): boolean {
res = sleeve.synchronize(playerRef);
break;
default:
console.error(
`Invalid/Unrecognized taskValue in setSleeveTask(): ${taskValue}`,
);
console.error(`Invalid/Unrecognized taskValue in setSleeveTask(): ${taskValue}`);
}
if (res) {
@@ -820,8 +697,7 @@ function setSleeveTask(sleeve: Sleeve, elems: ISleeveUIElems): boolean {
"Failed to assign sleeve to task. This is most likely because the selected faction does not offer the selected work type.";
break;
default:
elems.taskDescription.innerText =
"Failed to assign sleeve to task. Invalid choice(s).";
elems.taskDescription.innerText = "Failed to assign sleeve to task. Invalid choice(s).";
break;
}
}
@@ -845,10 +721,7 @@ function setSleeveTask(sleeve: Sleeve, elems: ISleeveUIElems): boolean {
}
}
function updateSleeveTaskDescription(
sleeve: Sleeve,
elems: ISleeveUIElems,
): void {
function updateSleeveTaskDescription(sleeve: Sleeve, elems: ISleeveUIElems): void {
try {
if (playerRef == null) {
throw new Error("playerRef is null in Sleeve UI's setSleeveTask()");
@@ -857,8 +730,7 @@ function updateSleeveTaskDescription(
const taskValue: string = getSelectValue(elems.taskSelector);
const detailValue: string = getSelectValue(elems.taskDetailsSelector);
const detailValue2: string = getSelectValue(elems.taskDetailsSelector2);
if (elems.taskDescription == null)
throw new Error("elems.taskDescription should not be null");
if (elems.taskDescription == null) throw new Error("elems.taskDescription should not be null");
switch (taskValue) {
case "------":
@@ -873,9 +745,7 @@ function updateSleeveTaskDescription(
case "Commit Crime":
elems.taskDescription.innerText = `This sleeve is currently attempting to ${
Crimes[detailValue].type
} (Success Rate: ${numeralWrapper.formatPercentage(
Crimes[detailValue].successRate(sleeve),
)}).`;
} (Success Rate: ${numeralWrapper.formatPercentage(Crimes[detailValue].successRate(sleeve))}).`;
break;
case "Take University Course":
elems.taskDescription.innerText = `This sleeve is currently studying/taking a course at ${sleeve.currentTaskLocation}.`;
@@ -894,9 +764,7 @@ function updateSleeveTaskDescription(
"This causes the Sleeve's synchronization to increase.";
break;
default:
console.error(
`Invalid/Unrecognized taskValue in updateSleeveTaskDescription(): ${taskValue}`,
);
console.error(`Invalid/Unrecognized taskValue in updateSleeveTaskDescription(): ${taskValue}`);
}
} catch (e) {
console.error(`Exception caught in updateSleeveTaskDescription(): ${e}`);
+32 -48
View File
@@ -6,111 +6,95 @@ export const SleeveFaq = (
<u>How do Duplicate Sleeves work?</u>
</strong>
<br />
Duplicate Sleeves are essentially clones. You can use them to perform any
work type action, such as working for a company/faction or committing a
crime. Having sleeves perform these tasks earns you money, experience, and
Duplicate Sleeves are essentially clones. You can use them to perform any work type action, such as working for a
company/faction or committing a crime. Having sleeves perform these tasks earns you money, experience, and
reputation.
<br />
<br />
Sleeves are their own individuals, which means they each have their own
experience and stats.
Sleeves are their own individuals, which means they each have their own experience and stats.
<br />
<br />
When a sleeve earns experience, it earns experience for itself, the player's
original 'consciousness', as well as all of the player's other sleeves.
When a sleeve earns experience, it earns experience for itself, the player's original 'consciousness', as well as
all of the player's other sleeves.
<br />
<br />
<strong>
<u>What is Synchronization (Sync)?</u>
</strong>
<br />
Synchronization is a measure of how aligned your consciousness is with that
of your Duplicate Sleeves. It is a numerical value between 1 and 100, and it
affects how much experience is earned when the sleeve is performing a task.
<br />
<br />
Let N be the sleeve's synchronization. When the sleeve earns experience by
performing a task, both the sleeve and the player's original host
consciousness earn N% of the amount of experience normally earned by the
task. All of the player's other sleeves earn ((N/100)^2 * 100)% of the
experience.
<br />
<br />
Synchronization can be increased by assigning sleeves to the 'Synchronize'
Synchronization is a measure of how aligned your consciousness is with that of your Duplicate Sleeves. It is a
numerical value between 1 and 100, and it affects how much experience is earned when the sleeve is performing a
task.
<br />
<br />
Let N be the sleeve's synchronization. When the sleeve earns experience by performing a task, both the sleeve and
the player's original host consciousness earn N% of the amount of experience normally earned by the task. All of the
player's other sleeves earn ((N/100)^2 * 100)% of the experience.
<br />
<br />
Synchronization can be increased by assigning sleeves to the 'Synchronize' task.
<br />
<br />
<strong>
<u>What is Shock?</u>
</strong>
<br />
Sleeve shock is a measure of how much trauma the sleeve has due to being
placed in a new body. It is a numerical value between 0 and 99, where 99
indicates full shock and 0 indicates no shock. Shock affects the amount of
Sleeve shock is a measure of how much trauma the sleeve has due to being placed in a new body. It is a numerical
value between 0 and 99, where 99 indicates full shock and 0 indicates no shock. Shock affects the amount of
experience earned by the sleeve.
<br />
<br />
Sleeve shock slowly decreases over time. You can further increase the rate
at which it decreases by assigning sleeves to the 'Shock Recovery' task.
Sleeve shock slowly decreases over time. You can further increase the rate at which it decreases by assigning
sleeves to the 'Shock Recovery' task.
<br />
<br />
<strong>
<u>Why can't I work for this company or faction?</u>
</strong>
<br />
Only one of your sleeves can work for a given company/faction a time. To
clarify further, if you have two sleeves they can work for two different
companies, but they cannot both work for the same company.
Only one of your sleeves can work for a given company/faction a time. To clarify further, if you have two sleeves
they can work for two different companies, but they cannot both work for the same company.
<br />
<br />
<strong>
<u>Why did my Sleeve stop working?</u>
</strong>
<br />
Sleeves are subject to the same time restrictions as you. This means that
they automatically stop working at a company after 8 hours, and stop working
for a faction after 20 hours.
Sleeves are subject to the same time restrictions as you. This means that they automatically stop working at a
company after 8 hours, and stop working for a faction after 20 hours.
<br />
<br />
<strong>
<u>How do I buy Augmentations for my Sleeves?</u>
</strong>
<br />
Your Sleeve needs to have a Shock of 0 in order for you to buy Augmentations
for it.
Your Sleeve needs to have a Shock of 0 in order for you to buy Augmentations for it.
<br />
<br />
<strong>
<u>Why can't I buy the X Augmentation for my sleeve?</u>
</strong>
<br />
Certain Augmentations, like Bladeburner-specific ones and NeuroFlux
Governor, are not available for sleeves.
Certain Augmentations, like Bladeburner-specific ones and NeuroFlux Governor, are not available for sleeves.
<br />
<br />
<strong>
<u>
Do sleeves get reset when installing Augmentations or switching
BitNodes?
</u>
<u>Do sleeves get reset when installing Augmentations or switching BitNodes?</u>
</strong>
<br />
Sleeves are reset when switching BitNodes, but not when installing
Augmentations.
Sleeves are reset when switching BitNodes, but not when installing Augmentations.
<br />
<br />
<strong>
<u>What is Memory?</u>
</strong>
<br />
Sleeve memory dictates what a sleeve's synchronization will be when its
reset by switching BitNodes. For example, if a sleeve has a memory of 25,
then when you switch BitNodes its synchronization will initially be set to
25, rather than 1.
Sleeve memory dictates what a sleeve's synchronization will be when its reset by switching BitNodes. For example, if
a sleeve has a memory of 25, then when you switch BitNodes its synchronization will initially be set to 25, rather
than 1.
<br />
<br />
Memory can only be increased by purchasing upgrades from The Covenant. It is
a persistent stat, meaning it never gets resets back to 1. The maximum
possible value for a sleeve's memory is 100.
Memory can only be increased by purchasing upgrades from The Covenant. It is a persistent stat, meaning it never
gets resets back to 1. The maximum possible value for a sleeve's memory is 100.
</>
);
@@ -7,11 +7,7 @@ import React, { useState } from "react";
import { CovenantSleeveUpgrades } from "./CovenantSleeveUpgrades";
import { Sleeve } from "../Sleeve";
import {
BaseCostPerSleeve,
MaxSleevesFromCovenant,
PopupId,
} from "../SleeveCovenantPurchases";
import { BaseCostPerSleeve, MaxSleevesFromCovenant, PopupId } from "../SleeveCovenantPurchases";
import { IPlayer } from "../../IPlayer";
import { PopupCloseButton } from "../../../ui/React/PopupCloseButton";
@@ -60,10 +56,7 @@ export function CovenantPurchasesRoot(props: IProps): React.ReactElement {
props.p.sleeves.push(new Sleeve(props.p));
rerender();
} else {
dialogBoxCreate(
`You cannot afford to purchase a Duplicate Sleeve`,
false,
);
dialogBoxCreate(`You cannot afford to purchase a Duplicate Sleeve`, false);
}
}
@@ -71,39 +64,27 @@ export function CovenantPurchasesRoot(props: IProps): React.ReactElement {
const upgradePanels = [];
for (let i = 0; i < props.p.sleeves.length; ++i) {
const sleeve = props.p.sleeves[i];
upgradePanels.push(
<CovenantSleeveUpgrades
{...props}
sleeve={sleeve}
index={i}
rerender={rerender}
key={i}
/>,
);
upgradePanels.push(<CovenantSleeveUpgrades {...props} sleeve={sleeve} index={i} rerender={rerender} key={i} />);
}
return (
<div>
<PopupCloseButton popup={PopupId} text={"Close"} />
<p>
Would you like to purchase an additional Duplicate Sleeve from The
Covenant for <Money money={purchaseCost()} player={props.p} />?
Would you like to purchase an additional Duplicate Sleeve from The Covenant for{" "}
<Money money={purchaseCost()} player={props.p} />?
</p>
<br />
<p>
These Duplicate Sleeves are permanent (they persist through BitNodes).
You can purchase a total of {MaxSleevesFromCovenant} from The Covenant.
These Duplicate Sleeves are permanent (they persist through BitNodes). You can purchase a total of{" "}
{MaxSleevesFromCovenant} from The Covenant.
</p>
<StdButton
disabled={purchaseDisabled}
onClick={purchaseOnClick}
text={"Purchase"}
/>
<StdButton disabled={purchaseDisabled} onClick={purchaseOnClick} text={"Purchase"} />
<br />
<br />
<p>
Here, you can also purchase upgrades for your Duplicate Sleeves. These
upgrades are also permanent, meaning they persist across BitNodes.
Here, you can also purchase upgrades for your Duplicate Sleeves. These upgrades are also permanent, meaning they
persist across BitNodes.
</p>
{upgradePanels}
</div>
@@ -22,10 +22,7 @@ interface IState {
amt: number;
}
export class CovenantSleeveMemoryUpgrade extends React.Component<
IProps,
IState
> {
export class CovenantSleeveMemoryUpgrade extends React.Component<IProps, IState> {
constructor(props: IProps) {
super(props);
@@ -88,8 +85,7 @@ export class CovenantSleeveMemoryUpgrade extends React.Component<
} else {
purchaseBtnContent = (
<>
Purchase {this.state.amt} memory -{" "}
<Money money={cost} player={this.props.p} />?
Purchase {this.state.amt} memory - <Money money={cost} player={this.props.p} />?
</>
);
}
@@ -100,14 +96,11 @@ export class CovenantSleeveMemoryUpgrade extends React.Component<
<u>Upgrade Memory</u>
</h2>
<p>
Purchase a memory upgrade for your sleeve. Note that a sleeve's max
memory is 100 (current:{" "}
Purchase a memory upgrade for your sleeve. Note that a sleeve's max memory is 100 (current:{" "}
{numeralWrapper.formatSleeveMemory(this.props.sleeve.memory)})
</p>
<label htmlFor={inputId}>
Amount of memory to purchase (must be an integer):
</label>
<label htmlFor={inputId}>Amount of memory to purchase (must be an integer):</label>
<input
className="text-input"
id={inputId}
@@ -116,11 +109,7 @@ export class CovenantSleeveMemoryUpgrade extends React.Component<
value={this.state.amt}
/>
<br />
<StdButton
disabled={purchaseBtnDisabled}
onClick={this.purchaseMemory}
text={purchaseBtnContent}
/>
<StdButton disabled={purchaseBtnDisabled} onClick={this.purchaseMemory} text={purchaseBtnContent} />
</div>
);
}
@@ -1,9 +1,6 @@
import * as React from "react";
export function EarningsTableElement(
title: string,
stats: any[][],
): React.ReactElement {
export function EarningsTableElement(title: string, stats: any[][]): React.ReactElement {
return (
<>
<pre>{title}</pre>
@@ -10,30 +10,12 @@ export function MoreEarningsContent(sleeve: Sleeve): React.ReactElement {
{StatsTable(
[
["Money ", <Money money={sleeve.earningsForTask.money} />],
[
"Hacking Exp ",
numeralWrapper.formatExp(sleeve.earningsForTask.hack),
],
[
"Strength Exp ",
numeralWrapper.formatExp(sleeve.earningsForTask.str),
],
[
"Defense Exp ",
numeralWrapper.formatExp(sleeve.earningsForTask.def),
],
[
"Dexterity Exp ",
numeralWrapper.formatExp(sleeve.earningsForTask.dex),
],
[
"Agility Exp ",
numeralWrapper.formatExp(sleeve.earningsForTask.agi),
],
[
"Charisma Exp ",
numeralWrapper.formatExp(sleeve.earningsForTask.cha),
],
["Hacking Exp ", numeralWrapper.formatExp(sleeve.earningsForTask.hack)],
["Strength Exp ", numeralWrapper.formatExp(sleeve.earningsForTask.str)],
["Defense Exp ", numeralWrapper.formatExp(sleeve.earningsForTask.def)],
["Dexterity Exp ", numeralWrapper.formatExp(sleeve.earningsForTask.dex)],
["Agility Exp ", numeralWrapper.formatExp(sleeve.earningsForTask.agi)],
["Charisma Exp ", numeralWrapper.formatExp(sleeve.earningsForTask.cha)],
],
"Earnings for Current Task:",
)}
@@ -41,30 +23,12 @@ export function MoreEarningsContent(sleeve: Sleeve): React.ReactElement {
{StatsTable(
[
["Money: ", <Money money={sleeve.earningsForPlayer.money} />],
[
"Hacking Exp: ",
numeralWrapper.formatExp(sleeve.earningsForPlayer.hack),
],
[
"Strength Exp: ",
numeralWrapper.formatExp(sleeve.earningsForPlayer.str),
],
[
"Defense Exp: ",
numeralWrapper.formatExp(sleeve.earningsForPlayer.def),
],
[
"Dexterity Exp: ",
numeralWrapper.formatExp(sleeve.earningsForPlayer.dex),
],
[
"Agility Exp: ",
numeralWrapper.formatExp(sleeve.earningsForPlayer.agi),
],
[
"Charisma Exp: ",
numeralWrapper.formatExp(sleeve.earningsForPlayer.cha),
],
["Hacking Exp: ", numeralWrapper.formatExp(sleeve.earningsForPlayer.hack)],
["Strength Exp: ", numeralWrapper.formatExp(sleeve.earningsForPlayer.str)],
["Defense Exp: ", numeralWrapper.formatExp(sleeve.earningsForPlayer.def)],
["Dexterity Exp: ", numeralWrapper.formatExp(sleeve.earningsForPlayer.dex)],
["Agility Exp: ", numeralWrapper.formatExp(sleeve.earningsForPlayer.agi)],
["Charisma Exp: ", numeralWrapper.formatExp(sleeve.earningsForPlayer.cha)],
],
"Total Earnings for Host Consciousness:",
)}
@@ -72,30 +36,12 @@ export function MoreEarningsContent(sleeve: Sleeve): React.ReactElement {
{StatsTable(
[
["Money: ", <Money money={sleeve.earningsForSleeves.money} />],
[
"Hacking Exp: ",
numeralWrapper.formatExp(sleeve.earningsForSleeves.hack),
],
[
"Strength Exp: ",
numeralWrapper.formatExp(sleeve.earningsForSleeves.str),
],
[
"Defense Exp: ",
numeralWrapper.formatExp(sleeve.earningsForSleeves.def),
],
[
"Dexterity Exp: ",
numeralWrapper.formatExp(sleeve.earningsForSleeves.dex),
],
[
"Agility Exp: ",
numeralWrapper.formatExp(sleeve.earningsForSleeves.agi),
],
[
"Charisma Exp: ",
numeralWrapper.formatExp(sleeve.earningsForSleeves.cha),
],
["Hacking Exp: ", numeralWrapper.formatExp(sleeve.earningsForSleeves.hack)],
["Strength Exp: ", numeralWrapper.formatExp(sleeve.earningsForSleeves.str)],
["Defense Exp: ", numeralWrapper.formatExp(sleeve.earningsForSleeves.def)],
["Dexterity Exp: ", numeralWrapper.formatExp(sleeve.earningsForSleeves.dex)],
["Agility Exp: ", numeralWrapper.formatExp(sleeve.earningsForSleeves.agi)],
["Charisma Exp: ", numeralWrapper.formatExp(sleeve.earningsForSleeves.cha)],
],
"Total Earnings for Other Sleeves:",
)}
@@ -8,110 +8,35 @@ export function MoreStatsContent(sleeve: Sleeve): React.ReactElement {
<>
{StatsTable(
[
[
"Hacking: ",
sleeve.hacking_skill,
`(${numeralWrapper.formatExp(sleeve.hacking_exp)} exp)`,
],
[
"Strength: ",
sleeve.strength,
`(${numeralWrapper.formatExp(sleeve.strength_exp)} exp)`,
],
[
"Defense: ",
sleeve.defense,
`(${numeralWrapper.formatExp(sleeve.defense_exp)} exp)`,
],
[
"Dexterity: ",
sleeve.dexterity,
`(${numeralWrapper.formatExp(sleeve.dexterity_exp)} exp)`,
],
[
"Agility: ",
sleeve.agility,
`(${numeralWrapper.formatExp(sleeve.agility_exp)} exp)`,
],
[
"Charisma: ",
sleeve.charisma,
`(${numeralWrapper.formatExp(sleeve.charisma_exp)} exp)`,
],
["Hacking: ", sleeve.hacking_skill, `(${numeralWrapper.formatExp(sleeve.hacking_exp)} exp)`],
["Strength: ", sleeve.strength, `(${numeralWrapper.formatExp(sleeve.strength_exp)} exp)`],
["Defense: ", sleeve.defense, `(${numeralWrapper.formatExp(sleeve.defense_exp)} exp)`],
["Dexterity: ", sleeve.dexterity, `(${numeralWrapper.formatExp(sleeve.dexterity_exp)} exp)`],
["Agility: ", sleeve.agility, `(${numeralWrapper.formatExp(sleeve.agility_exp)} exp)`],
["Charisma: ", sleeve.charisma, `(${numeralWrapper.formatExp(sleeve.charisma_exp)} exp)`],
],
"Stats:",
)}
<br />
{StatsTable(
[
[
"Hacking Level multiplier: ",
numeralWrapper.formatPercentage(sleeve.hacking_mult),
],
[
"Hacking Experience multiplier: ",
numeralWrapper.formatPercentage(sleeve.hacking_exp_mult),
],
[
"Strength Level multiplier: ",
numeralWrapper.formatPercentage(sleeve.strength_mult),
],
[
"Strength Experience multiplier: ",
numeralWrapper.formatPercentage(sleeve.strength_exp_mult),
],
[
"Defense Level multiplier: ",
numeralWrapper.formatPercentage(sleeve.defense_mult),
],
[
"Defense Experience multiplier: ",
numeralWrapper.formatPercentage(sleeve.defense_exp_mult),
],
[
"Dexterity Level multiplier: ",
numeralWrapper.formatPercentage(sleeve.dexterity_mult),
],
[
"Dexterity Experience multiplier: ",
numeralWrapper.formatPercentage(sleeve.dexterity_exp_mult),
],
[
"Agility Level multiplier: ",
numeralWrapper.formatPercentage(sleeve.agility_mult),
],
[
"Agility Experience multiplier: ",
numeralWrapper.formatPercentage(sleeve.agility_exp_mult),
],
[
"Charisma Level multiplier: ",
numeralWrapper.formatPercentage(sleeve.charisma_mult),
],
[
"Charisma Experience multiplier: ",
numeralWrapper.formatPercentage(sleeve.charisma_exp_mult),
],
[
"Faction Reputation Gain multiplier: ",
numeralWrapper.formatPercentage(sleeve.faction_rep_mult),
],
[
"Company Reputation Gain multiplier: ",
numeralWrapper.formatPercentage(sleeve.company_rep_mult),
],
[
"Salary multiplier: ",
numeralWrapper.formatPercentage(sleeve.work_money_mult),
],
[
"Crime Money multiplier: ",
numeralWrapper.formatPercentage(sleeve.crime_money_mult),
],
[
"Crime Success multiplier: ",
numeralWrapper.formatPercentage(sleeve.crime_success_mult),
],
["Hacking Level multiplier: ", numeralWrapper.formatPercentage(sleeve.hacking_mult)],
["Hacking Experience multiplier: ", numeralWrapper.formatPercentage(sleeve.hacking_exp_mult)],
["Strength Level multiplier: ", numeralWrapper.formatPercentage(sleeve.strength_mult)],
["Strength Experience multiplier: ", numeralWrapper.formatPercentage(sleeve.strength_exp_mult)],
["Defense Level multiplier: ", numeralWrapper.formatPercentage(sleeve.defense_mult)],
["Defense Experience multiplier: ", numeralWrapper.formatPercentage(sleeve.defense_exp_mult)],
["Dexterity Level multiplier: ", numeralWrapper.formatPercentage(sleeve.dexterity_mult)],
["Dexterity Experience multiplier: ", numeralWrapper.formatPercentage(sleeve.dexterity_exp_mult)],
["Agility Level multiplier: ", numeralWrapper.formatPercentage(sleeve.agility_mult)],
["Agility Experience multiplier: ", numeralWrapper.formatPercentage(sleeve.agility_exp_mult)],
["Charisma Level multiplier: ", numeralWrapper.formatPercentage(sleeve.charisma_mult)],
["Charisma Experience multiplier: ", numeralWrapper.formatPercentage(sleeve.charisma_exp_mult)],
["Faction Reputation Gain multiplier: ", numeralWrapper.formatPercentage(sleeve.faction_rep_mult)],
["Company Reputation Gain multiplier: ", numeralWrapper.formatPercentage(sleeve.company_rep_mult)],
["Salary multiplier: ", numeralWrapper.formatPercentage(sleeve.work_money_mult)],
["Crime Money multiplier: ", numeralWrapper.formatPercentage(sleeve.crime_money_mult)],
["Crime Success multiplier: ", numeralWrapper.formatPercentage(sleeve.crime_success_mult)],
],
"Multipliers:",
)}
+1 -2
View File
@@ -12,8 +12,7 @@ export function StatsElement(sleeve: Sleeve): React.ReactElement {
<tr>
<td className="character-hp-cell">HP: </td>
<td className="character-hp-cell" style={style}>
{numeralWrapper.formatHp(sleeve.hp)} /{" "}
{numeralWrapper.formatHp(sleeve.max_hp)}
{numeralWrapper.formatHp(sleeve.hp)} / {numeralWrapper.formatHp(sleeve.max_hp)}
</td>
</tr>
<tr>
+1 -4
View File
@@ -1,6 +1,3 @@
export function calculateIntelligenceBonus(
intelligence: number,
weight = 1,
): number {
export function calculateIntelligenceBonus(intelligence: number, weight = 1): number {
return 1 + (weight * Math.pow(intelligence, 0.8)) / 600;
}