mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-20 13:15:48 +01:00
Merge branch 'dev' of https://github.com/danielyxie/bitburner into dev
This commit is contained in:
commit
184a2a22ff
@ -1211,6 +1211,7 @@ Bladeburner.prototype.completeAction = function() {
|
|||||||
if (!isOperation) {
|
if (!isOperation) {
|
||||||
moneyGain = ContractBaseMoneyGain * rewardMultiplier * this.skillMultipliers.money;
|
moneyGain = ContractBaseMoneyGain * rewardMultiplier * this.skillMultipliers.money;
|
||||||
Player.gainMoney(moneyGain);
|
Player.gainMoney(moneyGain);
|
||||||
|
Player.recordMoneySource(moneyGain, "bladeburner");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isOperation) {
|
if (isOperation) {
|
||||||
|
@ -2868,7 +2868,9 @@ Corporation.prototype.process = function() {
|
|||||||
const totalDividends = (this.dividendPercentage / 100) * cycleProfit;
|
const totalDividends = (this.dividendPercentage / 100) * cycleProfit;
|
||||||
const retainedEarnings = cycleProfit - totalDividends;
|
const retainedEarnings = cycleProfit - totalDividends;
|
||||||
const dividendsPerShare = totalDividends / this.totalShares;
|
const dividendsPerShare = totalDividends / this.totalShares;
|
||||||
Player.gainMoney(this.numShares * dividendsPerShare * (1 - (this.dividendTaxPercentage / 100)));
|
const profit = this.numShares * dividendsPerShare * (1 - (this.dividendTaxPercentage / 100));
|
||||||
|
Player.gainMoney(profit);
|
||||||
|
Player.recordMoneySource(profit, "corporation");
|
||||||
this.funds = this.funds.plus(retainedEarnings);
|
this.funds = this.funds.plus(retainedEarnings);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -3533,6 +3535,7 @@ Corporation.prototype.displayCorporationOverviewContent = function() {
|
|||||||
this.shareSalesUntilPriceUpdate = newSharesUntilUpdate;
|
this.shareSalesUntilPriceUpdate = newSharesUntilUpdate;
|
||||||
this.shareSaleCooldown = SellSharesCooldown;
|
this.shareSaleCooldown = SellSharesCooldown;
|
||||||
Player.gainMoney(profit);
|
Player.gainMoney(profit);
|
||||||
|
Player.recordMoneySource(profit, "corporation");
|
||||||
removeElementById(popupId);
|
removeElementById(popupId);
|
||||||
dialogBoxCreate(`Sold ${numeralWrapper.formatMoney(shares, "0.000a")} shares for ` +
|
dialogBoxCreate(`Sold ${numeralWrapper.formatMoney(shares, "0.000a")} shares for ` +
|
||||||
`${numeralWrapper.formatMoney(profit, "$0.000a")}. ` +
|
`${numeralWrapper.formatMoney(profit, "$0.000a")}. ` +
|
||||||
|
@ -1,30 +1,27 @@
|
|||||||
import { Crimes } from "./Crimes";
|
import { Crimes } from "./Crimes";
|
||||||
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { Player } from "../Player";
|
|
||||||
|
|
||||||
import { dialogBoxCreate } from "../../utils/DialogBox";
|
import { dialogBoxCreate } from "../../utils/DialogBox";
|
||||||
|
|
||||||
export function determineCrimeSuccess(type, moneyGained) {
|
export function determineCrimeSuccess(p: IPlayer, type: string) {
|
||||||
var chance = 0;
|
let chance: number = 0;
|
||||||
var found = false;
|
let found: boolean = false;
|
||||||
for(const i in Crimes) {
|
for (const i in Crimes) {
|
||||||
const crime = Crimes[i];
|
let crime = Crimes[i];
|
||||||
if(crime.type == type) {
|
if (crime.type == type) {
|
||||||
chance = crime.successRate(Player);
|
chance = crime.successRate(p);
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!found) {
|
if (!found) {
|
||||||
console.log(crime);
|
dialogBoxCreate(`ERR: Unrecognized crime type: ${type} This is probably a bug please contact the developer`, false);
|
||||||
dialogBoxCreate("ERR: Unrecognized crime type. This is probably a bug please contact the developer");
|
return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Math.random() <= chance) {
|
if (Math.random() <= chance) {
|
||||||
//Success
|
//Success
|
||||||
Player.gainMoney(moneyGained);
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
//Failure
|
//Failure
|
||||||
@ -32,7 +29,7 @@ export function determineCrimeSuccess(type, moneyGained) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function findCrime(roughName) {
|
export function findCrime(roughName: string) {
|
||||||
if (roughName.includes("shoplift")) {
|
if (roughName.includes("shoplift")) {
|
||||||
return Crimes.Shoplift;
|
return Crimes.Shoplift;
|
||||||
} else if (roughName.includes("rob") && roughName.includes("store")) {
|
} else if (roughName.includes("rob") && roughName.includes("store")) {
|
@ -247,6 +247,7 @@ Gang.prototype.processGains = function(numCycles=1, player) {
|
|||||||
}
|
}
|
||||||
if (typeof moneyGains === "number") {
|
if (typeof moneyGains === "number") {
|
||||||
player.gainMoney(moneyGains * numCycles);
|
player.gainMoney(moneyGains * numCycles);
|
||||||
|
player.recordMoneySource(moneyGains * numCycles, "gang");
|
||||||
} else {
|
} else {
|
||||||
console.warn("ERROR: respectGains is NaN");
|
console.warn("ERROR: respectGains is NaN");
|
||||||
}
|
}
|
||||||
|
@ -4,15 +4,19 @@ import { Engine } from "./engine";
|
|||||||
import {iTutorialSteps, iTutorialNextStep,
|
import {iTutorialSteps, iTutorialNextStep,
|
||||||
ITutorial} from "./InteractiveTutorial";
|
ITutorial} from "./InteractiveTutorial";
|
||||||
import {Player} from "./Player";
|
import {Player} from "./Player";
|
||||||
|
import {Page, routing} from "./ui/navigationTracking";
|
||||||
|
import { numeralWrapper } from "./ui/numeralFormat";
|
||||||
|
|
||||||
import {dialogBoxCreate} from "../utils/DialogBox";
|
import {dialogBoxCreate} from "../utils/DialogBox";
|
||||||
import {clearEventListeners} from "../utils/uiHelpers/clearEventListeners";
|
import {clearEventListeners} from "../utils/uiHelpers/clearEventListeners";
|
||||||
import {Reviver, Generic_toJSON,
|
import {Reviver, Generic_toJSON,
|
||||||
Generic_fromJSON} from "../utils/JSONReviver";
|
Generic_fromJSON} from "../utils/JSONReviver";
|
||||||
import {createElement} from "../utils/uiHelpers/createElement";
|
import {createElement} from "../utils/uiHelpers/createElement";
|
||||||
import {Page, routing} from "./ui/navigationTracking";
|
|
||||||
import {formatNumber} from "../utils/StringHelperFunctions";
|
|
||||||
import {getElementById} from "../utils/uiHelpers/getElementById";
|
import {getElementById} from "../utils/uiHelpers/getElementById";
|
||||||
|
|
||||||
|
// Stores total money gain rate from all of the player's Hacknet Nodes
|
||||||
|
let TotalHacknetNodeProduction = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overwrites the inner text of the specified HTML element if it is different from what currently exists.
|
* Overwrites the inner text of the specified HTML element if it is different from what currently exists.
|
||||||
* @param {string} elementId The HTML ID to find the first instance of.
|
* @param {string} elementId The HTML ID to find the first instance of.
|
||||||
@ -299,7 +303,7 @@ function updateTotalHacknetProduction() {
|
|||||||
for (var i = 0; i < Player.hacknetNodes.length; ++i) {
|
for (var i = 0; i < Player.hacknetNodes.length; ++i) {
|
||||||
total += Player.hacknetNodes[i].moneyGainRatePerSecond;
|
total += Player.hacknetNodes[i].moneyGainRatePerSecond;
|
||||||
}
|
}
|
||||||
Player.totalHacknetNodeProduction = total;
|
TotalHacknetNodeProduction = total;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCostOfNextHacknetNode() {
|
function getCostOfNextHacknetNode() {
|
||||||
@ -446,9 +450,9 @@ function updateHacknetNodesContent() {
|
|||||||
//Set purchase button to inactive if not enough money, and update its price display
|
//Set purchase button to inactive if not enough money, and update its price display
|
||||||
var cost = getCostOfNextHacknetNode();
|
var cost = getCostOfNextHacknetNode();
|
||||||
var purchaseButton = getElementById("hacknet-nodes-purchase-button");
|
var purchaseButton = getElementById("hacknet-nodes-purchase-button");
|
||||||
var formattedCost = formatNumber(cost, 2);
|
var formattedCost = numeralWrapper.formatMoney(cost);
|
||||||
|
|
||||||
updateText("hacknet-nodes-purchase-button", "Purchase Hacknet Node - $" + formattedCost);
|
updateText("hacknet-nodes-purchase-button", `Purchase Hacknet Node - ${formattedCost}`);
|
||||||
|
|
||||||
if (Player.money.lt(cost)) {
|
if (Player.money.lt(cost)) {
|
||||||
purchaseButton.setAttribute("class", "a-link-button-inactive");
|
purchaseButton.setAttribute("class", "a-link-button-inactive");
|
||||||
@ -457,8 +461,8 @@ function updateHacknetNodesContent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Update player's money
|
//Update player's money
|
||||||
updateText("hacknet-nodes-player-money", "$" + formatNumber(Player.money.toNumber(), 2));
|
updateText("hacknet-nodes-player-money", numeralWrapper.formatMoney(Player.money.toNumber()));
|
||||||
updateText("hacknet-nodes-total-production", "$" + formatNumber(Player.totalHacknetNodeProduction, 2) + " / sec");
|
updateText("hacknet-nodes-total-production", numeralWrapper.formatMoney(TotalHacknetNodeProduction) + " / sec");
|
||||||
|
|
||||||
//Update information in each owned hacknet node
|
//Update information in each owned hacknet node
|
||||||
for (var i = 0; i < Player.hacknetNodes.length; ++i) {
|
for (var i = 0; i < Player.hacknetNodes.length; ++i) {
|
||||||
@ -559,8 +563,8 @@ function updateHacknetNodeDomElement(nodeObj) {
|
|||||||
var nodeName = nodeObj.name;
|
var nodeName = nodeObj.name;
|
||||||
|
|
||||||
updateText("hacknet-node-name-" + nodeName, nodeName);
|
updateText("hacknet-node-name-" + nodeName, nodeName);
|
||||||
updateText("hacknet-node-total-production-" + nodeName, "$" + formatNumber(nodeObj.totalMoneyGenerated, 2));
|
updateText("hacknet-node-total-production-" + nodeName, numeralWrapper.formatMoney(nodeObj.totalMoneyGenerated));
|
||||||
updateText("hacknet-node-production-rate-" + nodeName, "($" + formatNumber(nodeObj.moneyGainRatePerSecond, 2) + " / sec)");
|
updateText("hacknet-node-production-rate-" + nodeName, "(" + numeralWrapper.formatMoney(nodeObj.moneyGainRatePerSecond) + " / sec)");
|
||||||
updateText("hacknet-node-level-" + nodeName, nodeObj.level);
|
updateText("hacknet-node-level-" + nodeName, nodeObj.level);
|
||||||
updateText("hacknet-node-ram-" + nodeName, nodeObj.ram + "GB");
|
updateText("hacknet-node-ram-" + nodeName, nodeObj.ram + "GB");
|
||||||
updateText("hacknet-node-cores-" + nodeName, nodeObj.cores);
|
updateText("hacknet-node-cores-" + nodeName, nodeObj.cores);
|
||||||
@ -582,7 +586,7 @@ function updateHacknetNodeDomElement(nodeObj) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var upgradeLevelCost = nodeObj.calculateLevelUpgradeCost(multiplier);
|
var upgradeLevelCost = nodeObj.calculateLevelUpgradeCost(multiplier);
|
||||||
updateText("hacknet-node-upgrade-level-" + nodeName, "Upgrade x" + multiplier + " - $" + formatNumber(upgradeLevelCost, 2))
|
updateText("hacknet-node-upgrade-level-" + nodeName, "Upgrade x" + multiplier + " - " + numeralWrapper.formatMoney(upgradeLevelCost))
|
||||||
if (Player.money.lt(upgradeLevelCost)) {
|
if (Player.money.lt(upgradeLevelCost)) {
|
||||||
upgradeLevelButton.setAttribute("class", "a-link-button-inactive");
|
upgradeLevelButton.setAttribute("class", "a-link-button-inactive");
|
||||||
} else {
|
} else {
|
||||||
@ -606,7 +610,7 @@ function updateHacknetNodeDomElement(nodeObj) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var upgradeRamCost = nodeObj.calculateRamUpgradeCost(multiplier);
|
var upgradeRamCost = nodeObj.calculateRamUpgradeCost(multiplier);
|
||||||
updateText("hacknet-node-upgrade-ram-" + nodeName, "Upgrade x" + multiplier + " - $" + formatNumber(upgradeRamCost, 2));
|
updateText("hacknet-node-upgrade-ram-" + nodeName, "Upgrade x" + multiplier + " - " + numeralWrapper.formatMoney(upgradeRamCost));
|
||||||
if (Player.money.lt(upgradeRamCost)) {
|
if (Player.money.lt(upgradeRamCost)) {
|
||||||
upgradeRamButton.setAttribute("class", "a-link-button-inactive");
|
upgradeRamButton.setAttribute("class", "a-link-button-inactive");
|
||||||
} else {
|
} else {
|
||||||
@ -629,7 +633,7 @@ function updateHacknetNodeDomElement(nodeObj) {
|
|||||||
multiplier = Math.min(levelsToMax, hacknetNodePurchaseMultiplier);
|
multiplier = Math.min(levelsToMax, hacknetNodePurchaseMultiplier);
|
||||||
}
|
}
|
||||||
var upgradeCoreCost = nodeObj.calculateCoreUpgradeCost(multiplier);
|
var upgradeCoreCost = nodeObj.calculateCoreUpgradeCost(multiplier);
|
||||||
updateText("hacknet-node-upgrade-core-" + nodeName, "Upgrade x" + multiplier + " - $" + formatNumber(upgradeCoreCost, 2));
|
updateText("hacknet-node-upgrade-core-" + nodeName, "Upgrade x" + multiplier + " - " + numeralWrapper.formatMoney(upgradeCoreCost));
|
||||||
if (Player.money.lt(upgradeCoreCost)) {
|
if (Player.money.lt(upgradeCoreCost)) {
|
||||||
upgradeCoreButton.setAttribute("class", "a-link-button-inactive");
|
upgradeCoreButton.setAttribute("class", "a-link-button-inactive");
|
||||||
} else {
|
} else {
|
||||||
@ -660,6 +664,7 @@ function processSingleHacknetNodeEarnings(numCycles, nodeObj) {
|
|||||||
nodeObj.totalMoneyGenerated += totalEarnings;
|
nodeObj.totalMoneyGenerated += totalEarnings;
|
||||||
nodeObj.onlineTimeSeconds += (numCycles * (Engine._idleSpeed / 1000));
|
nodeObj.onlineTimeSeconds += (numCycles * (Engine._idleSpeed / 1000));
|
||||||
Player.gainMoney(totalEarnings);
|
Player.gainMoney(totalEarnings);
|
||||||
|
Player.recordMoneySource(totalEarnings, "hacknetnode");
|
||||||
return totalEarnings;
|
return totalEarnings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import { augmentationExists,
|
|||||||
installAugmentations } from "./Augmentation/AugmentationHelpers";
|
installAugmentations } from "./Augmentation/AugmentationHelpers";
|
||||||
import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
|
import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
|
||||||
import { BitNodeMultipliers } from "./BitNode/BitNodeMultipliers";
|
import { BitNodeMultipliers } from "./BitNode/BitNodeMultipliers";
|
||||||
import { determineCrimeSuccess, findCrime } from "./Crime/CrimeHelpers";
|
import { findCrime } from "./Crime/CrimeHelpers";
|
||||||
import {Bladeburner} from "./Bladeburner";
|
import {Bladeburner} from "./Bladeburner";
|
||||||
import {Company} from "./Company/Company";
|
import {Company} from "./Company/Company";
|
||||||
import {Companies, companyExists} from "./Company/Companies";
|
import {Companies, companyExists} from "./Company/Companies";
|
||||||
@ -381,6 +381,7 @@ function NetscriptFunctions(workerScript) {
|
|||||||
Player.gainMoney(moneyGained);
|
Player.gainMoney(moneyGained);
|
||||||
workerScript.scriptRef.onlineMoneyMade += moneyGained;
|
workerScript.scriptRef.onlineMoneyMade += moneyGained;
|
||||||
Player.scriptProdSinceLastAug += moneyGained;
|
Player.scriptProdSinceLastAug += moneyGained;
|
||||||
|
Player.recordMoneySource(moneyGained, "hacking");
|
||||||
workerScript.scriptRef.recordHack(server.ip, moneyGained, threads);
|
workerScript.scriptRef.recordHack(server.ip, moneyGained, threads);
|
||||||
Player.gainHackingExp(expGainedOnSuccess);
|
Player.gainHackingExp(expGainedOnSuccess);
|
||||||
workerScript.scriptRef.onlineExpGained += expGainedOnSuccess;
|
workerScript.scriptRef.onlineExpGained += expGainedOnSuccess;
|
||||||
@ -1621,6 +1622,7 @@ function NetscriptFunctions(workerScript) {
|
|||||||
if (isNaN(netProfit)) {netProfit = 0;}
|
if (isNaN(netProfit)) {netProfit = 0;}
|
||||||
workerScript.scriptRef.onlineMoneyMade += netProfit;
|
workerScript.scriptRef.onlineMoneyMade += netProfit;
|
||||||
Player.scriptProdSinceLastAug += netProfit;
|
Player.scriptProdSinceLastAug += netProfit;
|
||||||
|
Player.recordMoneySource(netProfit, "stock");
|
||||||
|
|
||||||
stock.playerShares -= shares;
|
stock.playerShares -= shares;
|
||||||
if (stock.playerShares == 0) {
|
if (stock.playerShares == 0) {
|
||||||
|
@ -10,24 +10,33 @@ import { IMap } from "../types";
|
|||||||
|
|
||||||
import { IPlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentation";
|
import { IPlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentation";
|
||||||
import { IPlayerOwnedSourceFile } from "../SourceFile/PlayerOwnedSourceFile";
|
import { IPlayerOwnedSourceFile } from "../SourceFile/PlayerOwnedSourceFile";
|
||||||
|
import { MoneySourceTracker } from "../utils/MoneySourceTracker";
|
||||||
|
|
||||||
export interface IPlayer {
|
export interface IPlayer {
|
||||||
// Class members
|
// Class members
|
||||||
augmentations: IPlayerOwnedAugmentation[];
|
augmentations: IPlayerOwnedAugmentation[];
|
||||||
bladeburner: any;
|
bladeburner: any;
|
||||||
bitNodeN: number;
|
bitNodeN: number;
|
||||||
|
city: string;
|
||||||
companyName: string;
|
companyName: string;
|
||||||
corporation: any;
|
corporation: any;
|
||||||
factions: string[];
|
factions: string[];
|
||||||
|
hacknetNodes: any[];
|
||||||
hasWseAccount: boolean;
|
hasWseAccount: boolean;
|
||||||
jobs: IMap<string>;
|
jobs: IMap<string>;
|
||||||
karma: number;
|
karma: number;
|
||||||
money: any;
|
money: any;
|
||||||
|
moneySourceA: MoneySourceTracker;
|
||||||
|
moneySourceB: MoneySourceTracker;
|
||||||
|
playtimeSinceLastAug: number;
|
||||||
|
playtimeSinceLastBitnode: number;
|
||||||
|
purchasedServers: any[];
|
||||||
queuedAugmentations: IPlayerOwnedAugmentation[];
|
queuedAugmentations: IPlayerOwnedAugmentation[];
|
||||||
resleeves: Resleeve[];
|
resleeves: Resleeve[];
|
||||||
sleeves: Sleeve[];
|
sleeves: Sleeve[];
|
||||||
sleevesFromCovenant: number;
|
sleevesFromCovenant: number;
|
||||||
sourceFiles: IPlayerOwnedSourceFile[];
|
sourceFiles: IPlayerOwnedSourceFile[];
|
||||||
|
totalPlaytime: number;
|
||||||
|
|
||||||
// Stats
|
// Stats
|
||||||
hacking_skill: number;
|
hacking_skill: number;
|
||||||
@ -47,7 +56,32 @@ export interface IPlayer {
|
|||||||
charisma_exp: number;
|
charisma_exp: number;
|
||||||
|
|
||||||
// Multipliers
|
// Multipliers
|
||||||
|
hacking_chance_mult: number;
|
||||||
|
hacking_speed_mult: number;
|
||||||
|
hacking_money_mult: number;
|
||||||
|
hacking_grow_mult: number;
|
||||||
|
hacking_mult: number;
|
||||||
|
hacking_exp_mult: number;
|
||||||
|
strength_mult: number;
|
||||||
|
strength_exp_mult: number;
|
||||||
|
defense_mult: number;
|
||||||
|
defense_exp_mult: number;
|
||||||
|
dexterity_mult: number;
|
||||||
|
dexterity_exp_mult: number;
|
||||||
|
agility_mult: number;
|
||||||
|
agility_exp_mult: number;
|
||||||
|
charisma_mult: number;
|
||||||
|
charisma_exp_mult: number;
|
||||||
|
hacknet_node_money_mult: number;
|
||||||
|
hacknet_node_purchase_cost_mult: number;
|
||||||
|
hacknet_node_ram_cost_mult: number;
|
||||||
|
hacknet_node_core_cost_mult: number;
|
||||||
|
hacknet_node_level_cost_mult: number;
|
||||||
|
company_rep_mult: number;
|
||||||
|
faction_rep_mult: number;
|
||||||
|
work_money_mult: number;
|
||||||
crime_success_mult: number;
|
crime_success_mult: number;
|
||||||
|
crime_money_mult: number;
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
canAfford(cost: number): boolean;
|
canAfford(cost: number): boolean;
|
||||||
@ -64,6 +98,7 @@ export interface IPlayer {
|
|||||||
loseMoney(money: number): void;
|
loseMoney(money: number): void;
|
||||||
reapplyAllAugmentations(resetMultipliers: boolean): void;
|
reapplyAllAugmentations(resetMultipliers: boolean): void;
|
||||||
reapplyAllSourceFiles(): void;
|
reapplyAllSourceFiles(): void;
|
||||||
|
recordMoneySource(amt: number, source: string): void;
|
||||||
startCrime(crimeType: string,
|
startCrime(crimeType: string,
|
||||||
hackExp: number,
|
hackExp: number,
|
||||||
strExp: number,
|
strExp: number,
|
||||||
|
@ -31,6 +31,7 @@ import {SourceFiles, applySourceFile} from "./SourceFile";
|
|||||||
import { SourceFileFlags } from "./SourceFile/SourceFileFlags";
|
import { SourceFileFlags } from "./SourceFile/SourceFileFlags";
|
||||||
import Decimal from "decimal.js";
|
import Decimal from "decimal.js";
|
||||||
import {numeralWrapper} from "./ui/numeralFormat";
|
import {numeralWrapper} from "./ui/numeralFormat";
|
||||||
|
import { MoneySourceTracker } from "./utils/MoneySourceTracker";
|
||||||
import {dialogBoxCreate} from "../utils/DialogBox";
|
import {dialogBoxCreate} from "../utils/DialogBox";
|
||||||
import {clearEventListeners} from "../utils/uiHelpers/clearEventListeners";
|
import {clearEventListeners} from "../utils/uiHelpers/clearEventListeners";
|
||||||
import {createRandomIp} from "../utils/IPAddress";
|
import {createRandomIp} from "../utils/IPAddress";
|
||||||
@ -92,8 +93,6 @@ function PlayerObject() {
|
|||||||
|
|
||||||
//Money
|
//Money
|
||||||
this.money = new Decimal(1000);
|
this.money = new Decimal(1000);
|
||||||
this.total_money = new Decimal(0); //Total money ever earned in this "simulation"
|
|
||||||
this.lifetime_money = new Decimal(0); //Total money ever earned
|
|
||||||
|
|
||||||
//IP Address of Starting (home) computer
|
//IP Address of Starting (home) computer
|
||||||
this.homeComputer = "";
|
this.homeComputer = "";
|
||||||
@ -114,7 +113,6 @@ function PlayerObject() {
|
|||||||
this.currentServer = ""; //IP address of Server currently being accessed through terminal
|
this.currentServer = ""; //IP address of Server currently being accessed through terminal
|
||||||
this.purchasedServers = []; //IP Addresses of purchased servers
|
this.purchasedServers = []; //IP Addresses of purchased servers
|
||||||
this.hacknetNodes = [];
|
this.hacknetNodes = [];
|
||||||
this.totalHacknetNodeProduction = 0;
|
|
||||||
|
|
||||||
//Factions
|
//Factions
|
||||||
this.factions = []; //Names of all factions player has joined
|
this.factions = []; //Names of all factions player has joined
|
||||||
@ -218,11 +216,12 @@ function PlayerObject() {
|
|||||||
this.playtimeSinceLastAug = 0;
|
this.playtimeSinceLastAug = 0;
|
||||||
this.playtimeSinceLastBitnode = 0;
|
this.playtimeSinceLastBitnode = 0;
|
||||||
|
|
||||||
//Production since last Augmentation installation
|
// Keep track of where money comes from
|
||||||
|
this.moneySourceA = new MoneySourceTracker(); // Where money comes from since last-installed Augmentation
|
||||||
|
this.moneySourceB = new MoneySourceTracker(); // Where money comes from for this entire BitNode run
|
||||||
|
|
||||||
|
// Production since last Augmentation installation
|
||||||
this.scriptProdSinceLastAug = 0;
|
this.scriptProdSinceLastAug = 0;
|
||||||
this.stockProdSinceLastAug = 0;
|
|
||||||
this.crimeProdSinceLastAug = 0;
|
|
||||||
this.jobProdSinceLastAug = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
PlayerObject.prototype.init = function() {
|
PlayerObject.prototype.init = function() {
|
||||||
@ -315,11 +314,12 @@ PlayerObject.prototype.prestigeAugmentation = function() {
|
|||||||
|
|
||||||
this.lastUpdate = new Date().getTime();
|
this.lastUpdate = new Date().getTime();
|
||||||
|
|
||||||
|
// Statistics Trackers
|
||||||
this.playtimeSinceLastAug = 0;
|
this.playtimeSinceLastAug = 0;
|
||||||
this.scriptProdSinceLastAug = 0;
|
this.scriptProdSinceLastAug = 0;
|
||||||
|
this.moneySourceA.reset();
|
||||||
|
|
||||||
this.hacknetNodes.length = 0;
|
this.hacknetNodes.length = 0;
|
||||||
this.totalHacknetNodeProduction = 0;
|
|
||||||
|
|
||||||
//Re-calculate skills and reset HP
|
//Re-calculate skills and reset HP
|
||||||
this.updateSkillLevels();
|
this.updateSkillLevels();
|
||||||
@ -405,7 +405,6 @@ PlayerObject.prototype.prestigeSourceFile = function() {
|
|||||||
this.lastUpdate = new Date().getTime();
|
this.lastUpdate = new Date().getTime();
|
||||||
|
|
||||||
this.hacknetNodes.length = 0;
|
this.hacknetNodes.length = 0;
|
||||||
this.totalHacknetNodeProduction = 0;
|
|
||||||
|
|
||||||
//Gang
|
//Gang
|
||||||
this.gang = null;
|
this.gang = null;
|
||||||
@ -420,9 +419,12 @@ PlayerObject.prototype.prestigeSourceFile = function() {
|
|||||||
//BitNode 3: Corporatocracy
|
//BitNode 3: Corporatocracy
|
||||||
this.corporation = 0;
|
this.corporation = 0;
|
||||||
|
|
||||||
|
// Statistics trackers
|
||||||
this.playtimeSinceLastAug = 0;
|
this.playtimeSinceLastAug = 0;
|
||||||
this.playtimeSinceLastBitnode = 0;
|
this.playtimeSinceLastBitnode = 0;
|
||||||
this.scriptProdSinceLastAug = 0;
|
this.scriptProdSinceLastAug = 0;
|
||||||
|
this.moneySourceA.reset();
|
||||||
|
this.moneySourceB.reset();
|
||||||
|
|
||||||
this.updateSkillLevels();
|
this.updateSkillLevels();
|
||||||
this.hp = this.max_hp;
|
this.hp = this.max_hp;
|
||||||
@ -542,8 +544,6 @@ PlayerObject.prototype.gainMoney = function(money) {
|
|||||||
console.log("ERR: NaN passed into Player.gainMoney()"); return;
|
console.log("ERR: NaN passed into Player.gainMoney()"); return;
|
||||||
}
|
}
|
||||||
this.money = this.money.plus(money);
|
this.money = this.money.plus(money);
|
||||||
this.total_money = this.total_money.plus(money);
|
|
||||||
this.lifetime_money = this.lifetime_money.plus(money);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerObject.prototype.loseMoney = function(money) {
|
PlayerObject.prototype.loseMoney = function(money) {
|
||||||
@ -561,6 +561,11 @@ PlayerObject.prototype.canAfford = function(cost) {
|
|||||||
return this.money.gte(cost);
|
return this.money.gte(cost);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PlayerObject.prototype.recordMoneySource = function(amt, source) {
|
||||||
|
this.moneySourceA.record(amt, source);
|
||||||
|
this.moneySourceB.record(amt, source);
|
||||||
|
}
|
||||||
|
|
||||||
PlayerObject.prototype.gainHackingExp = function(exp) {
|
PlayerObject.prototype.gainHackingExp = function(exp) {
|
||||||
if (isNaN(exp)) {
|
if (isNaN(exp)) {
|
||||||
console.log("ERR: NaN passed into Player.gainHackingExp()"); return;
|
console.log("ERR: NaN passed into Player.gainHackingExp()"); return;
|
||||||
@ -690,6 +695,7 @@ PlayerObject.prototype.processWorkEarnings = function(numCycles=1) {
|
|||||||
this.gainAgilityExp(agiExpGain);
|
this.gainAgilityExp(agiExpGain);
|
||||||
this.gainCharismaExp(chaExpGain);
|
this.gainCharismaExp(chaExpGain);
|
||||||
this.gainMoney(moneyGain);
|
this.gainMoney(moneyGain);
|
||||||
|
this.recordMoneySource(moneyGain, "work");
|
||||||
this.workHackExpGained += hackExpGain;
|
this.workHackExpGained += hackExpGain;
|
||||||
this.workStrExpGained += strExpGain;
|
this.workStrExpGained += strExpGain;
|
||||||
this.workDefExpGained += defExpGain;
|
this.workDefExpGained += defExpGain;
|
||||||
@ -1561,7 +1567,7 @@ PlayerObject.prototype.finishCrime = function(cancelled) {
|
|||||||
//Determine crime success/failure
|
//Determine crime success/failure
|
||||||
if (!cancelled) {
|
if (!cancelled) {
|
||||||
var statusText = ""; //TODO, unique message for each crime when you succeed
|
var statusText = ""; //TODO, unique message for each crime when you succeed
|
||||||
if (determineCrimeSuccess(this.crimeType, this.workMoneyGained)) {
|
if (determineCrimeSuccess(Player, this.crimeType)) {
|
||||||
//Handle Karma and crime statistics
|
//Handle Karma and crime statistics
|
||||||
let crime = null;
|
let crime = null;
|
||||||
for(const i in Crimes) {
|
for(const i in Crimes) {
|
||||||
@ -1574,6 +1580,8 @@ PlayerObject.prototype.finishCrime = function(cancelled) {
|
|||||||
console.log(this.crimeType);
|
console.log(this.crimeType);
|
||||||
dialogBoxCreate("ERR: Unrecognized crime type. This is probably a bug please contact the developer");
|
dialogBoxCreate("ERR: Unrecognized crime type. This is probably a bug please contact the developer");
|
||||||
}
|
}
|
||||||
|
Player.gainMoney(this.workMoneyGained);
|
||||||
|
Player.recordMoneySource(this.workMoneyGained, "crime");
|
||||||
this.karma -= crime.karma;
|
this.karma -= crime.karma;
|
||||||
this.numPeopleKilled += crime.kills;
|
this.numPeopleKilled += crime.kills;
|
||||||
if(crime.intelligence_exp > 0) {
|
if(crime.intelligence_exp > 0) {
|
||||||
@ -2429,6 +2437,7 @@ PlayerObject.prototype.gainCodingContractReward = function(reward, difficulty=1)
|
|||||||
default:
|
default:
|
||||||
var moneyGain = CONSTANTS.CodingContractBaseMoneyGain * difficulty * BitNodeMultipliers.CodingContractMoney;
|
var moneyGain = CONSTANTS.CodingContractBaseMoneyGain * difficulty * BitNodeMultipliers.CodingContractMoney;
|
||||||
this.gainMoney(moneyGain);
|
this.gainMoney(moneyGain);
|
||||||
|
this.recordMoneySource(moneyGain, "codingcontract");
|
||||||
return `Gained ${numeralWrapper.format(moneyGain, '$0.000a')}`;
|
return `Gained ${numeralWrapper.format(moneyGain, '$0.000a')}`;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2441,8 +2450,6 @@ function loadPlayer(saveString) {
|
|||||||
|
|
||||||
//Parse Decimal.js objects
|
//Parse Decimal.js objects
|
||||||
Player.money = new Decimal(Player.money);
|
Player.money = new Decimal(Player.money);
|
||||||
Player.total_money = new Decimal(Player.total_money);
|
|
||||||
Player.lifetime_money = new Decimal(Player.lifetime_money);
|
|
||||||
|
|
||||||
if (Player.corporation instanceof Corporation) {
|
if (Player.corporation instanceof Corporation) {
|
||||||
Player.corporation.funds = new Decimal(Player.corporation.funds);
|
Player.corporation.funds = new Decimal(Player.corporation.funds);
|
||||||
|
@ -293,8 +293,6 @@ function loadImportedGame(saveObj, saveString) {
|
|||||||
|
|
||||||
//Parse Decimal.js objects
|
//Parse Decimal.js objects
|
||||||
tempPlayer.money = new Decimal(tempPlayer.money);
|
tempPlayer.money = new Decimal(tempPlayer.money);
|
||||||
tempPlayer.total_money = new Decimal(tempPlayer.total_money);
|
|
||||||
tempPlayer.lifetime_money = new Decimal(tempPlayer.lifetime_money);
|
|
||||||
|
|
||||||
tempAllServers = JSON.parse(tempSaveObj.AllServersSave, Reviver);
|
tempAllServers = JSON.parse(tempSaveObj.AllServersSave, Reviver);
|
||||||
tempCompanies = JSON.parse(tempSaveObj.CompaniesSave, Reviver);
|
tempCompanies = JSON.parse(tempSaveObj.CompaniesSave, Reviver);
|
||||||
|
@ -854,6 +854,7 @@ function scriptCalculateOfflineProduction(runningScriptObj) {
|
|||||||
}
|
}
|
||||||
totalOfflineProduction += production;
|
totalOfflineProduction += production;
|
||||||
Player.gainMoney(production);
|
Player.gainMoney(production);
|
||||||
|
Player.recordMoneySource(production, "hacking");
|
||||||
console.log(runningScriptObj.filename + " generated $" + production + " while offline by hacking " + serv.hostname);
|
console.log(runningScriptObj.filename + " generated $" + production + " while offline by hacking " + serv.hostname);
|
||||||
runningScriptObj.log(runningScriptObj.filename + " generated $" + production + " while offline by hacking " + serv.hostname);
|
runningScriptObj.log(runningScriptObj.filename + " generated $" + production + " while offline by hacking " + serv.hostname);
|
||||||
serv.moneyAvailable -= production;
|
serv.moneyAvailable -= production;
|
||||||
|
@ -454,6 +454,7 @@ function sellStock(stock, shares) {
|
|||||||
if (shares === 0) {return false;}
|
if (shares === 0) {return false;}
|
||||||
var gains = stock.price * shares - CONSTANTS.StockMarketCommission;
|
var gains = stock.price * shares - CONSTANTS.StockMarketCommission;
|
||||||
Player.gainMoney(gains);
|
Player.gainMoney(gains);
|
||||||
|
Player.recordMoneySource(profit, "stock");
|
||||||
stock.playerShares = Math.round(stock.playerShares - shares);
|
stock.playerShares = Math.round(stock.playerShares - shares);
|
||||||
if (stock.playerShares == 0) {
|
if (stock.playerShares == 0) {
|
||||||
stock.playerAvgPx = 0;
|
stock.playerAvgPx = 0;
|
||||||
@ -550,6 +551,7 @@ function sellShort(stock, shares, workerScript=null) {
|
|||||||
var profit = ((stock.playerAvgShortPx - stock.price) * shares) - CONSTANTS.StockMarketCommission;
|
var profit = ((stock.playerAvgShortPx - stock.price) * shares) - CONSTANTS.StockMarketCommission;
|
||||||
if (isNaN(profit)) {profit = 0;}
|
if (isNaN(profit)) {profit = 0;}
|
||||||
Player.gainMoney(origCost + profit);
|
Player.gainMoney(origCost + profit);
|
||||||
|
Player.recordMoneySource(profit, "stock");
|
||||||
if (tixApi) {
|
if (tixApi) {
|
||||||
workerScript.scriptRef.onlineMoneyMade += profit;
|
workerScript.scriptRef.onlineMoneyMade += profit;
|
||||||
Player.scriptProdSinceLastAug += profit;
|
Player.scriptProdSinceLastAug += profit;
|
||||||
|
@ -729,6 +729,7 @@ let Terminal = {
|
|||||||
|
|
||||||
server.moneyAvailable -= moneyGained;
|
server.moneyAvailable -= moneyGained;
|
||||||
Player.gainMoney(moneyGained);
|
Player.gainMoney(moneyGained);
|
||||||
|
Player.recordMoneySource(moneyGained, "hacking");
|
||||||
Player.gainHackingExp(expGainedOnSuccess)
|
Player.gainHackingExp(expGainedOnSuccess)
|
||||||
Player.gainIntelligenceExp(expGainedOnSuccess / CONSTANTS.IntelligenceTerminalHackBaseExpGain);
|
Player.gainIntelligenceExp(expGainedOnSuccess / CONSTANTS.IntelligenceTerminalHackBaseExpGain);
|
||||||
|
|
||||||
|
101
src/engine.js
101
src/engine.js
@ -76,6 +76,7 @@ import { clearResleevesPage,
|
|||||||
createResleevesPage } from "./PersonObjects/Resleeving/ResleevingUI";
|
createResleevesPage } from "./PersonObjects/Resleeving/ResleevingUI";
|
||||||
|
|
||||||
import { createStatusText } from "./ui/createStatusText";
|
import { createStatusText } from "./ui/createStatusText";
|
||||||
|
import { displayCharacterInfo } from "./ui/displayCharacterInfo";
|
||||||
import {Page, routing} from "./ui/navigationTracking";
|
import {Page, routing} from "./ui/navigationTracking";
|
||||||
import {numeralWrapper} from "./ui/numeralFormat";
|
import {numeralWrapper} from "./ui/numeralFormat";
|
||||||
import {setSettingsLabels} from "./ui/setSettingsLabels";
|
import {setSettingsLabels} from "./ui/setSettingsLabels";
|
||||||
@ -271,7 +272,7 @@ const Engine = {
|
|||||||
loadCharacterContent: function() {
|
loadCharacterContent: function() {
|
||||||
Engine.hideAllContent();
|
Engine.hideAllContent();
|
||||||
Engine.Display.characterContent.style.display = "block";
|
Engine.Display.characterContent.style.display = "block";
|
||||||
Engine.displayCharacterInfo();
|
Engine.updateCharacterInfo();
|
||||||
routing.navigateTo(Page.CharacterInfo);
|
routing.navigateTo(Page.CharacterInfo);
|
||||||
MainMenuLinks.Stats.classList.add("active");
|
MainMenuLinks.Stats.classList.add("active");
|
||||||
},
|
},
|
||||||
@ -593,96 +594,8 @@ const Engine = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/* Display character info */
|
/* Display character info */
|
||||||
displayCharacterInfo: function() {
|
updateCharacterInfo: function() {
|
||||||
removeChildrenFromElement(Engine.Display.characterInfo);
|
displayCharacterInfo(Engine.Display.characterInfo, Player);
|
||||||
|
|
||||||
let companyPosition = "";
|
|
||||||
if (Player.companyName !== "") {
|
|
||||||
companyPosition = Player.jobs[Player.companyName];
|
|
||||||
}
|
|
||||||
|
|
||||||
var intText = "";
|
|
||||||
if (Player.intelligence > 0) {
|
|
||||||
intText = 'Intelligence: ' + (Player.intelligence).toLocaleString() + '<br>';
|
|
||||||
}
|
|
||||||
|
|
||||||
let bitNodeTimeText = "";
|
|
||||||
if(Player.sourceFiles.length > 0) {
|
|
||||||
bitNodeTimeText = 'Time played since last Bitnode destroyed: ' + convertTimeMsToTimeElapsedString(Player.playtimeSinceLastBitnode) + '<br>';
|
|
||||||
}
|
|
||||||
|
|
||||||
Engine.Display.characterInfo.appendChild(createElement("pre", {
|
|
||||||
innerHTML:
|
|
||||||
'<b>General</b><br><br>' +
|
|
||||||
'Current City: ' + Player.city + '<br><br>' +
|
|
||||||
`Employer at which you last worked: ${Player.companyName}<br>` +
|
|
||||||
`Job you last worked: ${companyPosition}<br>` +
|
|
||||||
`All Employers: ${Object.keys(Player.jobs).join(", ")}<br><br>` +
|
|
||||||
'Money: $' + formatNumber(Player.money.toNumber(), 2) + '<br><br><br>' +
|
|
||||||
'<b>Stats</b><br><br>' +
|
|
||||||
'Hacking Level: ' + (Player.hacking_skill).toLocaleString() +
|
|
||||||
' (' + numeralWrapper.format(Player.hacking_exp, '(0.000a)') + ' experience)<br>' +
|
|
||||||
'Strength: ' + (Player.strength).toLocaleString() +
|
|
||||||
' (' + numeralWrapper.format(Player.strength_exp, '(0.000a)') + ' experience)<br>' +
|
|
||||||
'Defense: ' + (Player.defense).toLocaleString() +
|
|
||||||
' (' + numeralWrapper.format(Player.defense_exp, '(0.000a)') + ' experience)<br>' +
|
|
||||||
'Dexterity: ' + (Player.dexterity).toLocaleString() +
|
|
||||||
' (' + numeralWrapper.format(Player.dexterity_exp, '(0.000a)') + ' experience)<br>' +
|
|
||||||
'Agility: ' + (Player.agility).toLocaleString() +
|
|
||||||
' (' + numeralWrapper.format(Player.agility_exp, '(0.000a)') + ' experience)<br>' +
|
|
||||||
'Charisma: ' + (Player.charisma).toLocaleString() +
|
|
||||||
' (' + numeralWrapper.format(Player.charisma_exp, '(0.000a)') + ' experience)<br>' +
|
|
||||||
intText + '<br><br>' +
|
|
||||||
'<b>Multipliers</b><br><br>' +
|
|
||||||
'Hacking Chance multiplier: ' + formatNumber(Player.hacking_chance_mult * 100, 2) + '%<br>' +
|
|
||||||
'Hacking Speed multiplier: ' + formatNumber(Player.hacking_speed_mult * 100, 2) + '%<br>' +
|
|
||||||
'Hacking Money multiplier: ' + formatNumber(Player.hacking_money_mult * 100, 2) + '%<br>' +
|
|
||||||
'Hacking Growth multiplier: ' + formatNumber(Player.hacking_grow_mult * 100, 2) + '%<br><br>' +
|
|
||||||
'Hacking Level multiplier: ' + formatNumber(Player.hacking_mult * 100, 2) + '%<br>' +
|
|
||||||
'Hacking Experience multiplier: ' + formatNumber(Player.hacking_exp_mult * 100, 2) + '%<br><br>' +
|
|
||||||
'Strength Level multiplier: ' + formatNumber(Player.strength_mult * 100, 2) + '%<br>' +
|
|
||||||
'Strength Experience multiplier: ' + formatNumber(Player.strength_exp_mult * 100, 2) + '%<br><br>' +
|
|
||||||
'Defense Level multiplier: ' + formatNumber(Player.defense_mult * 100, 2) + '%<br>' +
|
|
||||||
'Defense Experience multiplier: ' + formatNumber(Player.defense_exp_mult * 100, 2) + '%<br><br>' +
|
|
||||||
'Dexterity Level multiplier: ' + formatNumber(Player.dexterity_mult * 100, 2) + '%<br>' +
|
|
||||||
'Dexterity Experience multiplier: ' + formatNumber(Player.dexterity_exp_mult * 100, 2) + '%<br><br>' +
|
|
||||||
'Agility Level multiplier: ' + formatNumber(Player.agility_mult * 100, 2) + '%<br>' +
|
|
||||||
'Agility Experience multiplier: ' + formatNumber(Player.agility_exp_mult * 100, 2) + '%<br><br>' +
|
|
||||||
'Charisma Level multiplier: ' + formatNumber(Player.charisma_mult * 100, 2) + '%<br>' +
|
|
||||||
'Charisma Experience multiplier: ' + formatNumber(Player.charisma_exp_mult * 100, 2) + '%<br><br>' +
|
|
||||||
'Hacknet Node production multiplier: ' + formatNumber(Player.hacknet_node_money_mult * 100, 2) + '%<br>' +
|
|
||||||
'Hacknet Node purchase cost multiplier: ' + formatNumber(Player.hacknet_node_purchase_cost_mult * 100, 2) + '%<br>' +
|
|
||||||
'Hacknet Node RAM upgrade cost multiplier: ' + formatNumber(Player.hacknet_node_ram_cost_mult * 100, 2) + '%<br>' +
|
|
||||||
'Hacknet Node Core purchase cost multiplier: ' + formatNumber(Player.hacknet_node_core_cost_mult * 100, 2) + '%<br>' +
|
|
||||||
'Hacknet Node level upgrade cost multiplier: ' + formatNumber(Player.hacknet_node_level_cost_mult * 100, 2) + '%<br><br>' +
|
|
||||||
'Company reputation gain multiplier: ' + formatNumber(Player.company_rep_mult * 100, 2) + '%<br>' +
|
|
||||||
'Faction reputation gain multiplier: ' + formatNumber(Player.faction_rep_mult * 100, 2) + '%<br>' +
|
|
||||||
'Salary multiplier: ' + formatNumber(Player.work_money_mult * 100, 2) + '%<br>' +
|
|
||||||
'Crime success multiplier: ' + formatNumber(Player.crime_success_mult * 100, 2) + '%<br>' +
|
|
||||||
'Crime money multiplier: ' + formatNumber(Player.crime_money_mult * 100, 2) + '%<br><br><br>' +
|
|
||||||
'<b>Misc</b><br><br>' +
|
|
||||||
'Servers owned: ' + Player.purchasedServers.length + '<br>' +
|
|
||||||
'Hacknet Nodes owned: ' + Player.hacknetNodes.length + '<br>' +
|
|
||||||
'Augmentations installed: ' + Player.augmentations.length + '<br>' +
|
|
||||||
'Time played since last Augmentation: ' + convertTimeMsToTimeElapsedString(Player.playtimeSinceLastAug) + '<br>' +
|
|
||||||
bitNodeTimeText +
|
|
||||||
'Time played: ' + convertTimeMsToTimeElapsedString(Player.totalPlaytime),
|
|
||||||
}));
|
|
||||||
|
|
||||||
if (Player.sourceFiles.length !== 0) {
|
|
||||||
var index = "BitNode" + Player.bitNodeN;
|
|
||||||
|
|
||||||
Engine.Display.characterInfo.appendChild(createElement("p", {
|
|
||||||
width:"60%",
|
|
||||||
innerHTML:
|
|
||||||
"<br>Current BitNode: " + Player.bitNodeN + " (" + BitNodes[index].name + ")<br><br>",
|
|
||||||
}));
|
|
||||||
|
|
||||||
Engine.Display.characterInfo.appendChild(createElement("p", {
|
|
||||||
width:"60%", fontSize: "13px", marginLeft:"4%",
|
|
||||||
innerHTML:BitNodes[index].info,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/* Display locations in the world*/
|
/* Display locations in the world*/
|
||||||
@ -1060,9 +973,7 @@ const Engine = {
|
|||||||
|
|
||||||
if (Engine.Counters.updateDisplays <= 0) {
|
if (Engine.Counters.updateDisplays <= 0) {
|
||||||
Engine.displayCharacterOverviewInfo();
|
Engine.displayCharacterOverviewInfo();
|
||||||
if (routing.isOn(Page.CharacterInfo)) {
|
if (routing.isOn(Page.HacknetNodes)) {
|
||||||
Engine.displayCharacterInfo();
|
|
||||||
} else if (routing.isOn(Page.HacknetNodes)) {
|
|
||||||
updateHacknetNodesContent();
|
updateHacknetNodesContent();
|
||||||
} else if (routing.isOn(Page.CreateProgram)) {
|
} else if (routing.isOn(Page.CreateProgram)) {
|
||||||
displayCreateProgramContent();
|
displayCreateProgramContent();
|
||||||
@ -1080,6 +991,8 @@ const Engine = {
|
|||||||
if (Engine.Counters.updateDisplaysMed <= 0) {
|
if (Engine.Counters.updateDisplaysMed <= 0) {
|
||||||
if (routing.isOn(Page.Corporation)) {
|
if (routing.isOn(Page.Corporation)) {
|
||||||
Player.corporation.updateUIContent();
|
Player.corporation.updateUIContent();
|
||||||
|
} else if (routing.isOn(Page.CharacterInfo)) {
|
||||||
|
Engine.updateCharacterInfo();
|
||||||
}
|
}
|
||||||
Engine.Counters.updateDisplaysMed = 9;
|
Engine.Counters.updateDisplaysMed = 9;
|
||||||
}
|
}
|
||||||
|
156
src/ui/displayCharacterInfo.ts
Normal file
156
src/ui/displayCharacterInfo.ts
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
// Displays character info on a given element. This is used to create & update
|
||||||
|
// the 'Stats' page from the main menu
|
||||||
|
import { BitNodes } from "../BitNode/BitNode";
|
||||||
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
|
|
||||||
|
import { numeralWrapper } from "../ui/numeralFormat";
|
||||||
|
import { MoneySourceTracker } from "../utils/MoneySourceTracker";
|
||||||
|
|
||||||
|
import { dialogBoxCreate } from "../../utils/DialogBox";
|
||||||
|
import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions";
|
||||||
|
|
||||||
|
import { createElement } from "../../utils/uiHelpers/createElement";
|
||||||
|
import { removeChildrenFromElement } from "../../utils/uiHelpers/removeChildrenFromElement";
|
||||||
|
|
||||||
|
export function displayCharacterInfo(elem: HTMLElement, p: IPlayer) {
|
||||||
|
removeChildrenFromElement(elem);
|
||||||
|
|
||||||
|
let companyPosition = "";
|
||||||
|
if (p.companyName !== "") {
|
||||||
|
companyPosition = p.jobs[p.companyName];
|
||||||
|
}
|
||||||
|
|
||||||
|
var intText = "";
|
||||||
|
if (p.intelligence > 0) {
|
||||||
|
intText = 'Intelligence: ' + (p.intelligence).toLocaleString() + '<br>';
|
||||||
|
}
|
||||||
|
|
||||||
|
let bitNodeTimeText = "";
|
||||||
|
if(p.sourceFiles.length > 0) {
|
||||||
|
bitNodeTimeText = 'Time played since last Bitnode destroyed: ' + convertTimeMsToTimeElapsedString(p.playtimeSinceLastBitnode) + '<br>';
|
||||||
|
}
|
||||||
|
|
||||||
|
const unlockedBitnodes: boolean = p.sourceFiles.length !== 0;
|
||||||
|
|
||||||
|
// General info
|
||||||
|
elem.appendChild(createElement("pre", {
|
||||||
|
display: "block",
|
||||||
|
innerHTML:
|
||||||
|
'<b>General</b><br><br>' +
|
||||||
|
'Current City: ' + p.city + '<br><br>' +
|
||||||
|
`Employer at which you last worked: ${p.companyName}<br>` +
|
||||||
|
`Job you last worked: ${companyPosition}<br>` +
|
||||||
|
`All Employers: ${Object.keys(p.jobs).join(", ")}<br><br>`
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Money, and a button to show money breakdown
|
||||||
|
elem.appendChild(createElement("pre", {
|
||||||
|
display: "inline-block",
|
||||||
|
innerHTML: 'Money: ' + numeralWrapper.formatMoney(p.money.toNumber()) + '<br><br><br>',
|
||||||
|
margin: "6px",
|
||||||
|
}));
|
||||||
|
|
||||||
|
function convertMoneySourceTrackerToString(src: MoneySourceTracker): string {
|
||||||
|
let parts: string[] = [`Total: ${numeralWrapper.formatMoney(src.total)}`];
|
||||||
|
if (src.bladeburner) { parts.push(`Bladeburner: ${numeralWrapper.formatMoney(src.bladeburner)}`) };
|
||||||
|
if (src.codingcontract) { parts.push(`Coding Contracts: ${numeralWrapper.formatMoney(src.codingcontract)}`) };
|
||||||
|
if (src.work) { parts.push(`Company Work: ${numeralWrapper.formatMoney(src.work)}`) };
|
||||||
|
if (src.corporation) { parts.push(`Corporation: ${numeralWrapper.formatMoney(src.corporation)}}`) };
|
||||||
|
if (src.crime) { parts.push(`Crimes: ${numeralWrapper.formatMoney(src.crime)}`) };
|
||||||
|
if (src.gang) { parts.push(`Gang: ${numeralWrapper.formatMoney(src.gang)}`) };
|
||||||
|
if (src.hacking) { parts.push(`Hacking: ${numeralWrapper.formatMoney(src.hacking)}`) };
|
||||||
|
if (src.hacknetnode) { parts.push(`Hacknet Nodes: ${numeralWrapper.formatMoney(src.hacknetnode)}`) };
|
||||||
|
if (src.infiltration) { parts.push(`Infiltration: ${numeralWrapper.formatMoney(src.infiltration)}`) };
|
||||||
|
if (src.stock) { parts.push(`Stock Market: ${numeralWrapper.formatMoney(src.stock)}`) };
|
||||||
|
|
||||||
|
return parts.join("<br>");
|
||||||
|
}
|
||||||
|
|
||||||
|
elem.appendChild(createElement("button", {
|
||||||
|
class: "popup-box-button",
|
||||||
|
display: "inline-block",
|
||||||
|
float: "none",
|
||||||
|
innerText: "Money Statistics & Breakdown",
|
||||||
|
clickListener: () => {
|
||||||
|
let txt: string = "<u>Money earned since you last installed Augmentations:</u><br>" +
|
||||||
|
convertMoneySourceTrackerToString(p.moneySourceA);
|
||||||
|
if (unlockedBitnodes) {
|
||||||
|
txt += "<br><br><u>Money earned in this BitNode:</u><br>" +
|
||||||
|
convertMoneySourceTrackerToString(p.moneySourceB);
|
||||||
|
}
|
||||||
|
|
||||||
|
dialogBoxCreate(txt, false);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Stats and multiplier
|
||||||
|
elem.appendChild(createElement("pre", {
|
||||||
|
display: "block",
|
||||||
|
innerHTML:
|
||||||
|
'<b>Stats</b><br><br>' +
|
||||||
|
'Hacking Level: ' + (p.hacking_skill).toLocaleString() +
|
||||||
|
' (' + numeralWrapper.format(p.hacking_exp, '(0.000a)') + ' experience)<br>' +
|
||||||
|
'Strength: ' + (p.strength).toLocaleString() +
|
||||||
|
' (' + numeralWrapper.format(p.strength_exp, '(0.000a)') + ' experience)<br>' +
|
||||||
|
'Defense: ' + (p.defense).toLocaleString() +
|
||||||
|
' (' + numeralWrapper.format(p.defense_exp, '(0.000a)') + ' experience)<br>' +
|
||||||
|
'Dexterity: ' + (p.dexterity).toLocaleString() +
|
||||||
|
' (' + numeralWrapper.format(p.dexterity_exp, '(0.000a)') + ' experience)<br>' +
|
||||||
|
'Agility: ' + (p.agility).toLocaleString() +
|
||||||
|
' (' + numeralWrapper.format(p.agility_exp, '(0.000a)') + ' experience)<br>' +
|
||||||
|
'Charisma: ' + (p.charisma).toLocaleString() +
|
||||||
|
' (' + numeralWrapper.format(p.charisma_exp, '(0.000a)') + ' experience)<br>' +
|
||||||
|
intText + '<br><br>' +
|
||||||
|
'<b>Multipliers</b><br><br>' +
|
||||||
|
'Hacking Chance multiplier: ' + numeralWrapper.formatPercentage(p.hacking_chance_mult) + '<br>' +
|
||||||
|
'Hacking Speed multiplier: ' + numeralWrapper.formatPercentage(p.hacking_speed_mult) + '<br>' +
|
||||||
|
'Hacking Money multiplier: ' + numeralWrapper.formatPercentage(p.hacking_money_mult) + '<br>' +
|
||||||
|
'Hacking Growth multiplier: ' + numeralWrapper.formatPercentage(p.hacking_grow_mult) + '<br><br>' +
|
||||||
|
'Hacking Level multiplier: ' + numeralWrapper.formatPercentage(p.hacking_mult) + '<br>' +
|
||||||
|
'Hacking Experience multiplier: ' + numeralWrapper.formatPercentage(p.hacking_exp_mult) + '<br><br>' +
|
||||||
|
'Strength Level multiplier: ' + numeralWrapper.formatPercentage(p.strength_mult) + '<br>' +
|
||||||
|
'Strength Experience multiplier: ' + numeralWrapper.formatPercentage(p.strength_exp_mult) + '<br><br>' +
|
||||||
|
'Defense Level multiplier: ' + numeralWrapper.formatPercentage(p.defense_mult) + '<br>' +
|
||||||
|
'Defense Experience multiplier: ' + numeralWrapper.formatPercentage(p.defense_exp_mult) + '<br><br>' +
|
||||||
|
'Dexterity Level multiplier: ' + numeralWrapper.formatPercentage(p.dexterity_mult) + '<br>' +
|
||||||
|
'Dexterity Experience multiplier: ' + numeralWrapper.formatPercentage(p.dexterity_exp_mult) + '<br><br>' +
|
||||||
|
'Agility Level multiplier: ' + numeralWrapper.formatPercentage(p.agility_mult) + '<br>' +
|
||||||
|
'Agility Experience multiplier: ' + numeralWrapper.formatPercentage(p.agility_exp_mult) + '<br><br>' +
|
||||||
|
'Charisma Level multiplier: ' + numeralWrapper.formatPercentage(p.charisma_mult) + '<br>' +
|
||||||
|
'Charisma Experience multiplier: ' + numeralWrapper.formatPercentage(p.charisma_exp_mult) + '<br><br>' +
|
||||||
|
'Hacknet Node production multiplier: ' + numeralWrapper.formatPercentage(p.hacknet_node_money_mult) + '<br>' +
|
||||||
|
'Hacknet Node purchase cost multiplier: ' + numeralWrapper.formatPercentage(p.hacknet_node_purchase_cost_mult) + '<br>' +
|
||||||
|
'Hacknet Node RAM upgrade cost multiplier: ' + numeralWrapper.formatPercentage(p.hacknet_node_ram_cost_mult) + '<br>' +
|
||||||
|
'Hacknet Node Core purchase cost multiplier: ' + numeralWrapper.formatPercentage(p.hacknet_node_core_cost_mult) + '<br>' +
|
||||||
|
'Hacknet Node level upgrade cost multiplier: ' + numeralWrapper.formatPercentage(p.hacknet_node_level_cost_mult) + '<br><br>' +
|
||||||
|
'Company reputation gain multiplier: ' + numeralWrapper.formatPercentage(p.company_rep_mult) + '<br>' +
|
||||||
|
'Faction reputation gain multiplier: ' + numeralWrapper.formatPercentage(p.faction_rep_mult) + '<br>' +
|
||||||
|
'Salary multiplier: ' + numeralWrapper.formatPercentage(p.work_money_mult) + '<br>' +
|
||||||
|
'Crime success multiplier: ' + numeralWrapper.formatPercentage(p.crime_success_mult) + '<br>' +
|
||||||
|
'Crime money multiplier: ' + numeralWrapper.formatPercentage(p.crime_money_mult) + '<br><br><br>' +
|
||||||
|
'<b>Misc</b><br><br>' +
|
||||||
|
'Servers owned: ' + p.purchasedServers.length + '<br>' +
|
||||||
|
'Hacknet Nodes owned: ' + p.hacknetNodes.length + '<br>' +
|
||||||
|
'Augmentations installed: ' + p.augmentations.length + '<br>' +
|
||||||
|
'Time played since last Augmentation: ' + convertTimeMsToTimeElapsedString(p.playtimeSinceLastAug) + '<br>' +
|
||||||
|
bitNodeTimeText +
|
||||||
|
'Time played: ' + convertTimeMsToTimeElapsedString(p.totalPlaytime),
|
||||||
|
}));
|
||||||
|
|
||||||
|
// BitNode information, if player has gotten that far
|
||||||
|
if (unlockedBitnodes) {
|
||||||
|
var index = "BitNode" + p.bitNodeN;
|
||||||
|
|
||||||
|
elem.appendChild(createElement("p", {
|
||||||
|
width:"60%",
|
||||||
|
innerHTML:
|
||||||
|
"<br>Current BitNode: " + p.bitNodeN + " (" + BitNodes[index].name + ")<br><br>",
|
||||||
|
}));
|
||||||
|
|
||||||
|
elem.appendChild(createElement("p", {
|
||||||
|
width:"60%", fontSize: "13px", marginLeft:"4%",
|
||||||
|
innerHTML:BitNodes[index].info,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
56
src/utils/MoneySourceTracker.ts
Normal file
56
src/utils/MoneySourceTracker.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/**
|
||||||
|
* This is an object that is used to keep track of where all of the player's
|
||||||
|
* money is coming from
|
||||||
|
*/
|
||||||
|
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
|
||||||
|
|
||||||
|
export class MoneySourceTracker {
|
||||||
|
// Initiatizes a MoneySourceTracker object from a JSON save state.
|
||||||
|
static fromJSON(value: any): MoneySourceTracker {
|
||||||
|
return Generic_fromJSON(MoneySourceTracker, value.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
bladeburner: number = 0;
|
||||||
|
codingcontract: number = 0;
|
||||||
|
corporation: number = 0;
|
||||||
|
crime: number = 0;
|
||||||
|
gang: number = 0;
|
||||||
|
hacking: number = 0;
|
||||||
|
hacknetnode: number = 0;
|
||||||
|
infiltration: number = 0;
|
||||||
|
stock: number = 0;
|
||||||
|
total: number = 0;
|
||||||
|
work: number = 0;
|
||||||
|
|
||||||
|
[key: string]: number | Function;
|
||||||
|
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
// Record money earned
|
||||||
|
record(amt: number, source: string): void {
|
||||||
|
const sanitizedSource = source.toLowerCase();
|
||||||
|
if (typeof this[sanitizedSource] !== "number") {
|
||||||
|
console.warn(`MoneySourceTracker.record() called with invalid source: ${source}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
(<number> this[sanitizedSource]) += amt;
|
||||||
|
this.total += amt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the money tracker by setting all stats to 0
|
||||||
|
reset(): void {
|
||||||
|
for (const prop in this) {
|
||||||
|
if (typeof this[prop] === "number") {
|
||||||
|
this[prop] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize the current object to a JSON save state.
|
||||||
|
toJSON(): any {
|
||||||
|
return Generic_toJSON("MoneySourceTracker", this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Reviver.constructors.MoneySourceTracker = MoneySourceTracker;
|
@ -88,6 +88,7 @@ function infiltrationBoxCreate(inst) {
|
|||||||
sellButton.addEventListener("click", function(e) {
|
sellButton.addEventListener("click", function(e) {
|
||||||
if (!e.isTrusted) {return false;}
|
if (!e.isTrusted) {return false;}
|
||||||
Player.gainMoney(moneyValue);
|
Player.gainMoney(moneyValue);
|
||||||
|
Player.recordMoneySource(moneyValue, "infiltration");
|
||||||
dialogBoxCreate("You sold the classified information you stole from " + inst.companyName +
|
dialogBoxCreate("You sold the classified information you stole from " + inst.companyName +
|
||||||
" for <span class='money-gold'>$" + formatNumber(moneyValue, 2) + "</span> on the black market!<br><br>" +
|
" for <span class='money-gold'>$" + formatNumber(moneyValue, 2) + "</span> on the black market!<br><br>" +
|
||||||
expGainText);
|
expGainText);
|
||||||
|
Loading…
Reference in New Issue
Block a user