mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-19 12:45:45 +01:00
Began implementing Sleeve UI page
This commit is contained in:
parent
7d51182c60
commit
d9b865ef17
9
css/sleeves.scss
Normal file
9
css/sleeves.scss
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/**
|
||||||
|
* Styling for the Sleeves Management page
|
||||||
|
*/
|
||||||
|
@import "theme";
|
||||||
|
|
||||||
|
.sleeve-container {
|
||||||
|
border: 1px solid white;
|
||||||
|
margin: 4px;
|
||||||
|
}
|
@ -508,6 +508,10 @@ export let CONSTANTS: IMap<any> = {
|
|||||||
LatestUpdate:
|
LatestUpdate:
|
||||||
`
|
`
|
||||||
v0.43.0
|
v0.43.0
|
||||||
|
* Stock Market Changes:
|
||||||
|
** Each stock now has a maximum number of shares you can purchase (both Long and Short positions combined)
|
||||||
|
** Added getStockMaxShares() Netscript function to the TIX API
|
||||||
|
|
||||||
* Home Computer RAM is now capped at 2 ^ 30 GB (1073741824 GB)
|
* Home Computer RAM is now capped at 2 ^ 30 GB (1073741824 GB)
|
||||||
`
|
`
|
||||||
|
|
||||||
|
@ -51,14 +51,6 @@ export interface ICrime {
|
|||||||
kills: number;
|
kills: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interface for Faction object
|
|
||||||
// Used because at the time of implementation, the Faction object has not been
|
|
||||||
// converted to TypeScript
|
|
||||||
export interface IFaction {
|
|
||||||
name: string;
|
|
||||||
playerReputation: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Interface that defines a generic object used to track experience/money
|
// Interface that defines a generic object used to track experience/money
|
||||||
// earnings for tasks
|
// earnings for tasks
|
||||||
export interface ITaskTracker {
|
export interface ITaskTracker {
|
||||||
@ -129,6 +121,12 @@ export abstract class Person {
|
|||||||
|
|
||||||
work_money_mult: number;
|
work_money_mult: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Augmentations
|
||||||
|
*/
|
||||||
|
this.augmentations = [];
|
||||||
|
this.queuedAugmentations = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* City that the person is in
|
* City that the person is in
|
||||||
*/
|
*/
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Sleeves are clones of the player that can be used to perform
|
* Sleeves are bodies that contain the player's cloned consciousness.
|
||||||
* different tasks synchronously.
|
* The player can use these bodies to perform different tasks synchronously.
|
||||||
*
|
*
|
||||||
* Each sleeve is its own individual, meaning it has its own stats/exp
|
* Each sleeve is its own individual, meaning it has its own stats/exp
|
||||||
*
|
*
|
||||||
@ -11,7 +11,6 @@ import { SleeveTaskType } from "./SleeveTaskTypesEnum";
|
|||||||
import { Person,
|
import { Person,
|
||||||
IPlayer,
|
IPlayer,
|
||||||
ICrime,
|
ICrime,
|
||||||
IFaction,
|
|
||||||
ITaskTracker,
|
ITaskTracker,
|
||||||
createTaskTracker } from "../Person";
|
createTaskTracker } from "../Person";
|
||||||
|
|
||||||
@ -101,6 +100,8 @@ export class Sleeve extends Person {
|
|||||||
* Sleeve shock. Number between 1 and 100
|
* Sleeve shock. Number between 1 and 100
|
||||||
* Trauma/shock that comes with being in a sleeve. Experience earned
|
* Trauma/shock that comes with being in a sleeve. Experience earned
|
||||||
* is multipled by shock%. This gets applied before synchronization
|
* is multipled by shock%. This gets applied before synchronization
|
||||||
|
*
|
||||||
|
* Reputation earned is also multiplied by shock%
|
||||||
*/
|
*/
|
||||||
shock: number = 1;
|
shock: number = 1;
|
||||||
|
|
||||||
@ -251,6 +252,7 @@ export class Sleeve extends Person {
|
|||||||
* Earn money for player
|
* Earn money for player
|
||||||
*/
|
*/
|
||||||
gainMoney(p: IPlayer, task: ITaskTracker, numCycles: number=1): void {
|
gainMoney(p: IPlayer, task: ITaskTracker, numCycles: number=1): void {
|
||||||
|
this.earningsForPlayer.money += (task.money * numCycles);
|
||||||
p.gainMoney(task.money * numCycles);
|
p.gainMoney(task.money * numCycles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,17 +264,17 @@ export class Sleeve extends Person {
|
|||||||
if (this.currentTask === SleeveTaskType.Faction) {
|
if (this.currentTask === SleeveTaskType.Faction) {
|
||||||
switch (this.factionWorkType) {
|
switch (this.factionWorkType) {
|
||||||
case FactionWorkType.Hacking:
|
case FactionWorkType.Hacking:
|
||||||
return this.getFactionHackingWorkRepGain();
|
return this.getFactionHackingWorkRepGain() * (this.shock / 100);
|
||||||
case FactionWorkType.Field:
|
case FactionWorkType.Field:
|
||||||
return this.getFactionFieldWorkRepGain();
|
return this.getFactionFieldWorkRepGain() * (this.shock / 100);
|
||||||
case FactionWorkType.Security:
|
case FactionWorkType.Security:
|
||||||
return this.getFactionSecurityWorkRepGain();
|
return this.getFactionSecurityWorkRepGain() * (this.shock / 100);
|
||||||
default:
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
} else if (this.currentTask === SleeveTaskType.Company) {
|
} else if (this.currentTask === SleeveTaskType.Company) {
|
||||||
return 0;
|
return 0; // TODO
|
||||||
} else {
|
} 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;
|
return 0;
|
||||||
@ -327,16 +329,21 @@ export class Sleeve extends Person {
|
|||||||
retValue = this.gainExperience(p, this.gainRatesForTask, cyclesUsed);
|
retValue = this.gainExperience(p, this.gainRatesForTask, cyclesUsed);
|
||||||
this.gainMoney(p, this.gainRatesForTask, cyclesUsed);
|
this.gainMoney(p, this.gainRatesForTask, cyclesUsed);
|
||||||
|
|
||||||
// TODO REP for both this and company
|
// Gain faction reputation
|
||||||
const fac = Factions[this.currentTaskLocation];
|
const fac: Faction = Factions[this.currentTaskLocation];
|
||||||
if (!(fac instanceof Faction)) {
|
if (!(fac instanceof Faction)) {
|
||||||
console.error(`Invalid faction for Sleeve task: ${this.currentTaskLocation}`);
|
console.error(`Invalid faction for Sleeve task: ${this.currentTaskLocation}`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const repGainPerCycle: number = this.getRepGain();
|
||||||
|
fac.playerReputation += (repGainPerCycle * cyclesUsed);
|
||||||
break;
|
break;
|
||||||
case SleeveTaskType.Company:
|
case SleeveTaskType.Company:
|
||||||
retValue = this.gainExperience(p, this.gainRatesForTask, cyclesUsed);
|
retValue = this.gainExperience(p, this.gainRatesForTask, cyclesUsed);
|
||||||
this.gainMoney(p, this.gainRatesForTask, cyclesUsed);
|
this.gainMoney(p, this.gainRatesForTask, cyclesUsed);
|
||||||
|
|
||||||
|
// TODO Rep gain for this
|
||||||
break;
|
break;
|
||||||
case SleeveTaskType.Recovery:
|
case SleeveTaskType.Recovery:
|
||||||
this.shock = Math.max(100, this.shock + (0.001 * this.storedCycles));
|
this.shock = Math.max(100, this.shock + (0.001 * this.storedCycles));
|
||||||
|
166
src/PersonObjects/Sleeve/SleeveUI.ts
Normal file
166
src/PersonObjects/Sleeve/SleeveUI.ts
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
/**
|
||||||
|
* Module for handling the Sleeve UI
|
||||||
|
*/
|
||||||
|
import { Sleeve } from "./Sleeve";
|
||||||
|
import { SleeveTaskType } from "./SleeveTaskTypesEnum";
|
||||||
|
|
||||||
|
import { IMap } from "../../types";
|
||||||
|
|
||||||
|
import { Page,
|
||||||
|
routing } from "../../ui/navigationTracking";
|
||||||
|
|
||||||
|
import { exceptionAlert } from "../../../utils/helpers/exceptionAlert";
|
||||||
|
|
||||||
|
import { createElement } from "../../../utils/uiHelpers/createElement";
|
||||||
|
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
|
||||||
|
import { removeElement } from "../../../utils/uiHelpers/removeElement";
|
||||||
|
import { removeElementById } from "../../../utils/uiHelpers/removeElementById";
|
||||||
|
|
||||||
|
// Object that keeps track of all DOM elements for the UI for a single Sleeve
|
||||||
|
interface ISleeveUIElems {
|
||||||
|
container: Element | null,
|
||||||
|
statsPanel: Element | null,
|
||||||
|
stats: Element | null,
|
||||||
|
statsTooltip: Element | null,
|
||||||
|
taskPanel: Element | null,
|
||||||
|
taskSelector: Element | null,
|
||||||
|
taskDetailsSelector: Element | null,
|
||||||
|
taskDescription: Element | null,
|
||||||
|
earningsPanel: Element | null,
|
||||||
|
currentEarningsInfo: Element | null,
|
||||||
|
totalEarningsInfo: Element | null,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Object that keeps track of all DOM elements for the entire Sleeve UI
|
||||||
|
interface IPageUIElems {
|
||||||
|
container: Element | null;
|
||||||
|
info: Element | null,
|
||||||
|
sleeveList: Element | null,
|
||||||
|
sleeves: ISleeveUIElems[] | null,
|
||||||
|
}
|
||||||
|
|
||||||
|
const UIElems: IPageUIElems = {
|
||||||
|
container: null,
|
||||||
|
info: null,
|
||||||
|
sleeveList: null,
|
||||||
|
sleeves: null,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interface for Player object
|
||||||
|
interface IPlayer {
|
||||||
|
sleeves: Sleeve[];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates the UI for the entire Sleeves page
|
||||||
|
export function createSleevesPage(p: IPlayer) {
|
||||||
|
if (!routing.isOn(Page.Sleeves)) { return; }
|
||||||
|
|
||||||
|
try {
|
||||||
|
UIElems.container = createElement("div", {
|
||||||
|
class: "generic-menupage-container",
|
||||||
|
id: "sleeves-container",
|
||||||
|
position: "fixed",
|
||||||
|
});
|
||||||
|
|
||||||
|
UIElems.info = createElement("p", {
|
||||||
|
display: "inline-block",
|
||||||
|
innerText: "Sleeves are MK-V Synthoids (synthetic androids) into which your " +
|
||||||
|
"consciousness has copied. In other words, these Synthoids contain " +
|
||||||
|
"a perfect duplicate of your mind.<br><br>" +
|
||||||
|
"Sleeves can be used to perform different tasks synchronously.",
|
||||||
|
});
|
||||||
|
|
||||||
|
UIElems.sleeveList = createElement("ul");
|
||||||
|
UIElems.sleeves = [];
|
||||||
|
|
||||||
|
for (const sleeve of p.sleeves) {
|
||||||
|
UIElems.sleeves.push(this.createSleeveUi(sleeve, p.sleeves));
|
||||||
|
}
|
||||||
|
|
||||||
|
UIElems.container.appendChild(UIElems.info);
|
||||||
|
UIElems.container.appendChild(UIElems.sleeveList);
|
||||||
|
|
||||||
|
document.getElementById("entire-game-container")!.appendChild(UIElems.container);
|
||||||
|
} catch(e) {
|
||||||
|
exceptionAlert(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updates the UI for the entire Sleeves page
|
||||||
|
export function updateSleevesPage() {
|
||||||
|
if (!routing.isOn(Page.Sleeves)) { return; }
|
||||||
|
}
|
||||||
|
|
||||||
|
export function clearSleevesPage() {
|
||||||
|
removeElement(UIElems.container);
|
||||||
|
for (const prop in UIElems) {
|
||||||
|
UIElems[prop] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates the UI for a single Sleeve
|
||||||
|
// Returns an object containing the DOM elements in the UI (ISleeveUIElems)
|
||||||
|
function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]) {
|
||||||
|
if (!routing.isOn(Page.Sleeves)) { return; }
|
||||||
|
|
||||||
|
const elems: ISleeveUIElems = {
|
||||||
|
container: null,
|
||||||
|
statsPanel: null,
|
||||||
|
stats: null,
|
||||||
|
statsTooltip: null,
|
||||||
|
taskPanel: null,
|
||||||
|
taskSelector: null,
|
||||||
|
taskDetailsSelector: null,
|
||||||
|
taskDescription: null,
|
||||||
|
earningsPanel: null,
|
||||||
|
currentEarningsInfo: null,
|
||||||
|
totalEarningsButton: null,
|
||||||
|
}
|
||||||
|
|
||||||
|
elems.container = createElement("div", {
|
||||||
|
class: "sleeve-container",
|
||||||
|
display: "block",
|
||||||
|
});
|
||||||
|
|
||||||
|
elems.statsPanel = createElement("div", { class: "sleeve-panel" });
|
||||||
|
elems.stats = createElement("p", { class: "sleeve-stats-text tooltip" });
|
||||||
|
elems.statsTooltip = createElement("span", { class: "tooltiptext" });
|
||||||
|
elems.stats.appendChild(elems.statsTooltip);
|
||||||
|
elems.statsPanel.appendChild(elems.stats);
|
||||||
|
|
||||||
|
elems.taskPanel = createElement("div", { class: "sleeve-panel" });
|
||||||
|
elems.taskSelector = createElement("select");
|
||||||
|
elems.taskSelector.add(createOptionElement("------"));
|
||||||
|
elems.taskSelector.add(createOptionElement("Work for Company"));
|
||||||
|
elems.taskSelector.add(createOptionElement("Work for Faction"));
|
||||||
|
elems.taskSelector.add(createOptionElement("Commit Crime"));
|
||||||
|
elems.taskSelector.add(createOptionElement("Take University Course"));
|
||||||
|
elems.taskSelector.add(createOptionElement("Workout at Gym"));
|
||||||
|
elems.taskSelector.add(createOptionElement("Shock Recovery"));
|
||||||
|
elems.taskSelector.add(createOptionElement("Synchronize"));
|
||||||
|
elems.taskSelector.addEventListener("change", () => {
|
||||||
|
updateSleeveTaskSelector(sleeve, elems, allSleeves);
|
||||||
|
});
|
||||||
|
// TODO Set initial value for task selector
|
||||||
|
elems.taskDetailsSelector = createElement("select");
|
||||||
|
elems.taskDescription = createElement("p");
|
||||||
|
elems.taskPanel.appendChild(elems.taskSelector);
|
||||||
|
elems.taskPanel.appendChild(elems.taskDetailsSelector);
|
||||||
|
elems.taskPanel.appendChild(elems.taskDescription);
|
||||||
|
|
||||||
|
elems.earningsPanel = createElement("div", { class: "sleeve-panel" });
|
||||||
|
elems.currentEarningsInfo = createElement("p");
|
||||||
|
elems.totalEarningsButton = createElement("button", { class: "std-button" });
|
||||||
|
|
||||||
|
return elems;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updates the UI for a single Sleeve
|
||||||
|
function updateSleeveUi() {
|
||||||
|
if (!routing.isOn(Page.Sleeves)) { return; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Whenever a new task is selected, the "details" selector must update accordingly
|
||||||
|
function updateSleeveTaskSelector(sleeve: Sleeve, elems: ISleeveUIElems, allSleeves: Sleeve[]) {
|
||||||
|
const value: string =
|
||||||
|
}
|
@ -190,6 +190,9 @@ function PlayerObject() {
|
|||||||
this.bladeburner_analysis_mult = 1; //Field Analysis Only
|
this.bladeburner_analysis_mult = 1; //Field Analysis Only
|
||||||
this.bladeburner_success_chance_mult = 1;
|
this.bladeburner_success_chance_mult = 1;
|
||||||
|
|
||||||
|
// Sleeves
|
||||||
|
this.sleeves = [];
|
||||||
|
|
||||||
//bitnode
|
//bitnode
|
||||||
this.bitNodeN = 1;
|
this.bitNodeN = 1;
|
||||||
|
|
||||||
|
@ -112,6 +112,11 @@ export enum Page {
|
|||||||
* Manage special Bladeburner activities.
|
* Manage special Bladeburner activities.
|
||||||
*/
|
*/
|
||||||
Bladeburner = "Bladeburner",
|
Bladeburner = "Bladeburner",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manage your Sleeves
|
||||||
|
*/
|
||||||
|
Sleeves = "Sleeves",
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import { dialogBoxCreate } from "../DialogBox";
|
import { dialogBoxCreate } from "../DialogBox";
|
||||||
|
|
||||||
function exceptionAlert(e) {
|
interface IError {
|
||||||
|
fileName?: string,
|
||||||
|
lineNumber?: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
export function exceptionAlert(e: IError): void {
|
||||||
dialogBoxCreate("Caught an exception: " + e + "<br><br>" +
|
dialogBoxCreate("Caught an exception: " + e + "<br><br>" +
|
||||||
"Filename: " + (e.fileName || "UNKNOWN FILE NAME") + "<br><br>" +
|
"Filename: " + (e.fileName || "UNKNOWN FILE NAME") + "<br><br>" +
|
||||||
"Line Number: " + (e.lineNumber || "UNKNOWN LINE NUMBER") + "<br><br>" +
|
"Line Number: " + (e.lineNumber || "UNKNOWN LINE NUMBER") + "<br><br>" +
|
||||||
"This is a bug, please report to game developer with this " +
|
"This is a bug, please report to game developer with this " +
|
||||||
"message as well as details about how to reproduce the bug.<br><br>" +
|
"message as well as details about how to reproduce the bug.<br><br>" +
|
||||||
"If you want to be safe, I suggest refreshing the game WITHOUT saving so that your " +
|
"If you want to be safe, I suggest refreshing the game WITHOUT saving so that your " +
|
||||||
"safe doesn't get corrupted");
|
"safe doesn't get corrupted", false);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export {
|
|
||||||
exceptionAlert
|
|
||||||
}
|
}
|
11
utils/uiHelpers/createOptionElement.ts
Normal file
11
utils/uiHelpers/createOptionElement.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { createElement } from "./createElement";
|
||||||
|
|
||||||
|
export function createOptionElement(text: string, value: string="") {
|
||||||
|
const sanitizedValue: string = value;
|
||||||
|
if (sanitizedValue === "") { sanitizedValue = text; }
|
||||||
|
|
||||||
|
return createElement("option", {
|
||||||
|
text: text,
|
||||||
|
value: sanitizedValue,
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user