diff --git a/src/DevMenu.js b/src/DevMenu.js
index ceadc51cf..03b72f108 100644
--- a/src/DevMenu.js
+++ b/src/DevMenu.js
@@ -51,6 +51,15 @@ export function createDevMenu() {
innerText: "Add $1000t",
});
+ const addMoney2 = createElement("button", {
+ class: "std-button",
+ clickListener: () => {
+ Player.gainMoney(1e12);
+ },
+ display: "block",
+ innerText: "Add $1t",
+ })
+
const addRam = createElement("button", {
class: "std-button",
clickListener: () => {
@@ -588,6 +597,20 @@ export function createDevMenu() {
innerText: "View Stock Price Caps",
});
+ // Sleeves
+ const sleevesHeader = createElement("h2", { innerText: "Sleeves" });
+
+ const sleevesRemoveAllShockRecovery = createElement("button", {
+ class: "std-button",
+ display: "block",
+ innerText: "Set Shock Recovery of All Sleeves to 0",
+ clickListener: () => {
+ for (let i = 0; i < Player.sleeves.length; ++i) {
+ Player.sleeves[i].shock = 100;
+ }
+ }
+ });
+
// Add everything to container, then append to main menu
const devMenuContainer = createElement("div", {
class: "generic-menupage-container",
@@ -597,6 +620,7 @@ export function createDevMenu() {
devMenuContainer.appendChild(devMenuText);
devMenuContainer.appendChild(genericHeader);
devMenuContainer.appendChild(addMoney);
+ devMenuContainer.appendChild(addMoney2);
devMenuContainer.appendChild(addRam);
devMenuContainer.appendChild(triggerBitflume);
devMenuContainer.appendChild(destroyCurrentBitnode);
@@ -674,6 +698,8 @@ export function createDevMenu() {
devMenuContainer.appendChild(stockPriceChangeBtn);
devMenuContainer.appendChild(createElement("br"));
devMenuContainer.appendChild(stockViewPriceCapBtn);
+ devMenuContainer.appendChild(sleevesHeader);
+ devMenuContainer.appendChild(sleevesRemoveAllShockRecovery);
const entireGameContainer = document.getElementById("entire-game-container");
if (entireGameContainer == null) {
diff --git a/src/PersonObjects/Person.ts b/src/PersonObjects/Person.ts
index 6a80dce2f..9bc208a0a 100644
--- a/src/PersonObjects/Person.ts
+++ b/src/PersonObjects/Person.ts
@@ -5,7 +5,6 @@ import { IPlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentatio
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
import { Cities } from "../Locations/Cities";
import { CONSTANTS } from "../Constants";
-import { IMap } from "../types";
// Interface that defines a generic object used to track experience/money
// earnings for tasks
diff --git a/src/PersonObjects/Sleeve/Sleeve.ts b/src/PersonObjects/Sleeve/Sleeve.ts
index a634a8d2f..a02842560 100644
--- a/src/PersonObjects/Sleeve/Sleeve.ts
+++ b/src/PersonObjects/Sleeve/Sleeve.ts
@@ -13,6 +13,8 @@ import { Person,
ITaskTracker,
createTaskTracker } from "../Person";
+import { Augmentation } from "../../Augmentation/Augmentation";
+
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
import { Crime } from "../../Crime/Crime";
@@ -136,8 +138,11 @@ export class Sleeve extends Person {
*/
sync: number = 1;
- constructor() {
+ constructor(p: IPlayer | null = null) {
super();
+ if (p != null) {
+ this.shockRecovery(p);
+ }
}
/**
@@ -381,6 +386,17 @@ export class Sleeve extends Person {
}
}
+ installAugmentation(aug: Augmentation): void {
+ this.hacking_exp = 0;
+ this.strength_exp = 0;
+ this.defense_exp = 0;
+ this.dexterity_exp = 0;
+ this.agility_exp = 0;
+ this.charisma_exp = 0;
+ this.applyAugmentation(aug);
+ this.updateStatLevels();
+ }
+
log(entry: string): void {
const MaxLogSize: number = 50;
this.logs.push(entry);
@@ -452,10 +468,10 @@ export class Sleeve extends Person {
company!.playerReputation += (this.getRepGain(p) * cyclesUsed);
break;
case SleeveTaskType.Recovery:
- this.shock = Math.min(100, this.shock + (0.0001 * cyclesUsed));
+ this.shock = Math.min(100, this.shock + (0.0002 * cyclesUsed));
break;
case SleeveTaskType.Sync:
- this.sync = Math.min(100, this.sync + (0.0001 * cyclesUsed));
+ this.sync = Math.min(100, this.sync + (0.0002 * cyclesUsed));
break;
default:
break;
@@ -492,6 +508,28 @@ export class Sleeve extends Person {
this.gymStatType = "";
}
+ shockRecovery(p: IPlayer): boolean {
+ if (this.currentTask !== SleeveTaskType.Idle) {
+ this.finishTask(p);
+ } else {
+ this.resetTaskStatus();
+ }
+
+ this.currentTask = SleeveTaskType.Recovery;
+ return true;
+ }
+
+ synchronize(p: IPlayer): boolean {
+ if (this.currentTask !== SleeveTaskType.Idle) {
+ this.finishTask(p);
+ } else {
+ this.resetTaskStatus();
+ }
+
+ this.currentTask = SleeveTaskType.Sync;
+ return true;
+ }
+
/**
* Take a course at a university
*/
diff --git a/src/PersonObjects/Sleeve/SleeveAugmentationsUI.ts b/src/PersonObjects/Sleeve/SleeveAugmentationsUI.ts
new file mode 100644
index 000000000..280b8b37b
--- /dev/null
+++ b/src/PersonObjects/Sleeve/SleeveAugmentationsUI.ts
@@ -0,0 +1,91 @@
+/**
+ * Module for handling the UI for purchasing Sleeve Augmentations
+ * This UI is a popup, not a full page
+ */
+import { Sleeve } from "./Sleeve";
+
+import { IPlayer } from "../IPlayer";
+
+import { Augmentation } from "../../Augmentation/Augmentation";
+import { Augmentations } from "../../Augmentation/Augmentations";
+
+import { Faction } from "../../Faction/Faction";
+import { Factions } from "../../Faction/Factions";
+
+import { numeralWrapper } from "../../ui/numeralFormat";
+
+import { dialogBoxCreate } from "../../../utils/DialogBox";
+
+import { clearEventListeners } from "../../../utils/uiHelpers/clearEventListeners";
+import { createElement } from "../../../utils/uiHelpers/createElement";
+import { createPopup } from "../../../utils/uiHelpers/createPopup";
+import { createPopupCloseButton } from "../../../utils/uiHelpers/createPopupCloseButton";
+import { getSelectValue } from "../../../utils/uiHelpers/getSelectData";
+import { removeChildrenFromElement } from "../../../utils/uiHelpers/removeChildrenFromElement";
+import { removeElement } from "../../../utils/uiHelpers/removeElement";
+import { removeElementById } from "../../../utils/uiHelpers/removeElementById";
+
+export function createSleevePurchaseAugsPopup(sleeve: Sleeve, p: IPlayer) {
+ // You can only purchase Augmentations that are actually available from
+ // your factions. I.e. you must be in a faction that has the Augmentation
+ // and you must also have enough rep in that faction in order to purchase it.
+ const availableAugs: Augmentation[] = [];
+
+ for (const facName of p.factions) {
+ const fac: Faction | null = Factions[facName];
+ if (fac == null) { continue; }
+
+ for (const augName of fac.augmentations) {
+ const aug: Augmentation | null = Augmentations[augName];
+
+ if (fac.playerReputation > aug.baseRepRequirement && !availableAugs.includes(aug)) {
+ availableAugs.push(aug);
+ }
+ }
+ }
+
+
+ // General info about buying Augmentations
+ const info = createElement("p", {
+ innerHTML:
+ [
+ `You can purchase Augmentations for your Duplicate Sleeves. These Augmentations`,
+ `have the same effect as they would for you. You can only purchase Augmentations`,
+ `that you have unlocked through Factions.
`,
+ `When purchasing an Augmentation for a Duplicate Sleeve, they are immediately`,
+ `installed. This means that the Duplicate Sleeve will immediately lose all of`,
+ `its stat experience.`
+ ].join(" "),
+ });
+
+ const popupId = "purchase-sleeve-augs-popup";
+ const popupElems: HTMLElement[] = [info];
+
+ for (const aug of availableAugs) {
+ const div = createElement("div", {
+ class: "cmpy-mgmt-upgrade-div", // We'll reuse this CSS class
+ });
+
+ div.appendChild(createElement("p", {
+ innerHTML:
+ [
+ `