mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-21 13:45:44 +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:
|
||||
`
|
||||
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)
|
||||
`
|
||||
|
||||
|
@ -51,14 +51,6 @@ export interface ICrime {
|
||||
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
|
||||
// earnings for tasks
|
||||
export interface ITaskTracker {
|
||||
@ -129,6 +121,12 @@ export abstract class Person {
|
||||
|
||||
work_money_mult: number;
|
||||
|
||||
/**
|
||||
* Augmentations
|
||||
*/
|
||||
this.augmentations = [];
|
||||
this.queuedAugmentations = [];
|
||||
|
||||
/**
|
||||
* City that the person is in
|
||||
*/
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Sleeves are clones of the player that can be used to perform
|
||||
* different tasks synchronously.
|
||||
* Sleeves are bodies that contain the player's cloned consciousness.
|
||||
* The player can use these bodies to perform different tasks synchronously.
|
||||
*
|
||||
* Each sleeve is its own individual, meaning it has its own stats/exp
|
||||
*
|
||||
@ -11,7 +11,6 @@ import { SleeveTaskType } from "./SleeveTaskTypesEnum";
|
||||
import { Person,
|
||||
IPlayer,
|
||||
ICrime,
|
||||
IFaction,
|
||||
ITaskTracker,
|
||||
createTaskTracker } from "../Person";
|
||||
|
||||
@ -101,6 +100,8 @@ export class Sleeve extends Person {
|
||||
* Sleeve shock. Number between 1 and 100
|
||||
* Trauma/shock that comes with being in a sleeve. Experience earned
|
||||
* is multipled by shock%. This gets applied before synchronization
|
||||
*
|
||||
* Reputation earned is also multiplied by shock%
|
||||
*/
|
||||
shock: number = 1;
|
||||
|
||||
@ -251,6 +252,7 @@ export class Sleeve extends Person {
|
||||
* Earn money for player
|
||||
*/
|
||||
gainMoney(p: IPlayer, task: ITaskTracker, numCycles: number=1): void {
|
||||
this.earningsForPlayer.money += (task.money * numCycles);
|
||||
p.gainMoney(task.money * numCycles);
|
||||
}
|
||||
|
||||
@ -262,17 +264,17 @@ export class Sleeve extends Person {
|
||||
if (this.currentTask === SleeveTaskType.Faction) {
|
||||
switch (this.factionWorkType) {
|
||||
case FactionWorkType.Hacking:
|
||||
return this.getFactionHackingWorkRepGain();
|
||||
return this.getFactionHackingWorkRepGain() * (this.shock / 100);
|
||||
case FactionWorkType.Field:
|
||||
return this.getFactionFieldWorkRepGain();
|
||||
return this.getFactionFieldWorkRepGain() * (this.shock / 100);
|
||||
case FactionWorkType.Security:
|
||||
return this.getFactionSecurityWorkRepGain();
|
||||
return this.getFactionSecurityWorkRepGain() * (this.shock / 100);
|
||||
default:
|
||||
console.warn(`Invalid Sleeve.factionWorkType property in Sleeve.getRepGain(): ${this.factionWorkType}`);
|
||||
return 0;
|
||||
}
|
||||
} else if (this.currentTask === SleeveTaskType.Company) {
|
||||
return 0;
|
||||
return 0; // TODO
|
||||
} else {
|
||||
console.warn(`Sleeve.getRepGain() called for invalid task type: ${this.currentTask}`);
|
||||
return 0;
|
||||
@ -327,16 +329,21 @@ export class Sleeve extends Person {
|
||||
retValue = this.gainExperience(p, this.gainRatesForTask, cyclesUsed);
|
||||
this.gainMoney(p, this.gainRatesForTask, cyclesUsed);
|
||||
|
||||
// TODO REP for both this and company
|
||||
const fac = Factions[this.currentTaskLocation];
|
||||
// Gain faction reputation
|
||||
const fac: Faction = Factions[this.currentTaskLocation];
|
||||
if (!(fac instanceof Faction)) {
|
||||
console.error(`Invalid faction for Sleeve task: ${this.currentTaskLocation}`);
|
||||
break;
|
||||
}
|
||||
|
||||
const repGainPerCycle: number = this.getRepGain();
|
||||
fac.playerReputation += (repGainPerCycle * cyclesUsed);
|
||||
break;
|
||||
case SleeveTaskType.Company:
|
||||
retValue = this.gainExperience(p, this.gainRatesForTask, cyclesUsed);
|
||||
this.gainMoney(p, this.gainRatesForTask, cyclesUsed);
|
||||
|
||||
// TODO Rep gain for this
|
||||
break;
|
||||
case SleeveTaskType.Recovery:
|
||||
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_success_chance_mult = 1;
|
||||
|
||||
// Sleeves
|
||||
this.sleeves = [];
|
||||
|
||||
//bitnode
|
||||
this.bitNodeN = 1;
|
||||
|
||||
|
@ -112,6 +112,11 @@ export enum Page {
|
||||
* Manage special Bladeburner activities.
|
||||
*/
|
||||
Bladeburner = "Bladeburner",
|
||||
|
||||
/**
|
||||
* Manage your Sleeves
|
||||
*/
|
||||
Sleeves = "Sleeves",
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,16 +1,16 @@
|
||||
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>" +
|
||||
"Filename: " + (e.fileName || "UNKNOWN FILE NAME") + "<br><br>" +
|
||||
"Line Number: " + (e.lineNumber || "UNKNOWN LINE NUMBER") + "<br><br>" +
|
||||
"This is a bug, please report to game developer with this " +
|
||||
"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 " +
|
||||
"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