mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-23 22:52:29 +01:00
fix decimal
This commit is contained in:
commit
0114c92829
46
dist/vendor.bundle.js
vendored
46
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
@ -10,7 +10,7 @@ getPlayer() Netscript Function
|
||||
Returns an object with the Player's stats. The object has the following properties::
|
||||
|
||||
{
|
||||
hacking_skill: Current Hacking skill level
|
||||
hacking: Current Hacking skill level
|
||||
hp: Current health points
|
||||
max_hp: Maximum health points
|
||||
strength: Current Strength skill level
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
22
package-lock.json
generated
22
package-lock.json
generated
@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "bitburner",
|
||||
"version": "0.58.0",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"version": "0.58.0",
|
||||
"version": "1.0.0",
|
||||
"hasInstallScript": true,
|
||||
"license": "SEE LICENSE IN license.txt",
|
||||
"dependencies": {
|
||||
@ -28,6 +28,7 @@
|
||||
"arg": "^5.0.0",
|
||||
"better-react-mathjax": "^1.0.3",
|
||||
"clsx": "^1.1.1",
|
||||
"date-fns": "^2.25.0",
|
||||
"decimal.js": "7.2.3",
|
||||
"escodegen": "^1.11.0",
|
||||
"file-saver": "^1.3.8",
|
||||
@ -6963,6 +6964,18 @@
|
||||
"whatwg-url": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/date-fns": {
|
||||
"version": "2.25.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.25.0.tgz",
|
||||
"integrity": "sha512-ovYRFnTrbGPD4nqaEqescPEv1mNwvt+UTqI3Ay9SzNtey9NZnYu6E2qCcBBgJ6/2VF1zGGygpyTDITqpQQ5e+w==",
|
||||
"engines": {
|
||||
"node": ">=0.11"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/date-fns"
|
||||
}
|
||||
},
|
||||
"node_modules/date-now": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
|
||||
@ -26992,6 +27005,11 @@
|
||||
"whatwg-url": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"date-fns": {
|
||||
"version": "2.25.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.25.0.tgz",
|
||||
"integrity": "sha512-ovYRFnTrbGPD4nqaEqescPEv1mNwvt+UTqI3Ay9SzNtey9NZnYu6E2qCcBBgJ6/2VF1zGGygpyTDITqpQQ5e+w=="
|
||||
},
|
||||
"date-now": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
|
||||
|
@ -29,7 +29,7 @@
|
||||
"arg": "^5.0.0",
|
||||
"better-react-mathjax": "^1.0.3",
|
||||
"clsx": "^1.1.1",
|
||||
"decimal.js": "7.2.3",
|
||||
"date-fns": "^2.25.0",
|
||||
"escodegen": "^1.11.0",
|
||||
"file-saver": "^1.3.8",
|
||||
"jquery": "^3.5.0",
|
||||
|
@ -27,12 +27,12 @@ export function NewIndustry(corporation: ICorporation, industry: string, name: s
|
||||
if (cost === undefined) {
|
||||
throw new Error(`Invalid industry: '${industry}'`);
|
||||
}
|
||||
if (corporation.funds.lt(cost)) {
|
||||
if (corporation.funds < cost) {
|
||||
throw new Error("Not enough money to create a new division in this industry");
|
||||
} else if (name === "") {
|
||||
throw new Error("New division must have a name!");
|
||||
} else {
|
||||
corporation.funds = corporation.funds.minus(cost);
|
||||
corporation.funds = corporation.funds - cost;
|
||||
corporation.divisions.push(
|
||||
new Industry({
|
||||
corp: corporation,
|
||||
@ -44,10 +44,10 @@ export function NewIndustry(corporation: ICorporation, industry: string, name: s
|
||||
}
|
||||
|
||||
export function NewCity(corporation: ICorporation, division: IIndustry, city: string): void {
|
||||
if (corporation.funds.lt(CorporationConstants.OfficeInitialCost)) {
|
||||
if (corporation.funds < CorporationConstants.OfficeInitialCost) {
|
||||
throw new Error("You don't have enough company funds to open a new office!");
|
||||
} else {
|
||||
corporation.funds = corporation.funds.minus(CorporationConstants.OfficeInitialCost);
|
||||
corporation.funds = corporation.funds - CorporationConstants.OfficeInitialCost;
|
||||
division.offices[city] = new OfficeSpace({
|
||||
loc: city,
|
||||
size: CorporationConstants.OfficeInitialSize,
|
||||
@ -56,7 +56,7 @@ export function NewCity(corporation: ICorporation, division: IIndustry, city: st
|
||||
}
|
||||
|
||||
export function UnlockUpgrade(corporation: ICorporation, upgrade: CorporationUnlockUpgrade): void {
|
||||
if (corporation.funds.lt(upgrade[1])) {
|
||||
if (corporation.funds < upgrade[1]) {
|
||||
throw new Error("Insufficient funds");
|
||||
}
|
||||
corporation.unlock(upgrade);
|
||||
@ -67,7 +67,7 @@ export function LevelUpgrade(corporation: ICorporation, upgrade: CorporationUpgr
|
||||
const priceMult = upgrade[2];
|
||||
const level = corporation.upgrades[upgrade[0]];
|
||||
const cost = baseCost * Math.pow(priceMult, level);
|
||||
if (corporation.funds.lt(cost)) {
|
||||
if (corporation.funds < cost) {
|
||||
throw new Error("Insufficient funds");
|
||||
} else {
|
||||
corporation.upgrade(upgrade);
|
||||
@ -259,15 +259,15 @@ export function UpgradeOfficeSize(corp: ICorporation, office: OfficeSpace, size:
|
||||
mult += Math.pow(costMultiplier, initialPriceMult + i);
|
||||
}
|
||||
const cost = CorporationConstants.OfficeInitialCost * mult;
|
||||
if (corp.funds.lt(cost)) return;
|
||||
if (corp.funds < cost) return;
|
||||
office.size += size;
|
||||
corp.funds = corp.funds.minus(cost);
|
||||
corp.funds = corp.funds - cost;
|
||||
}
|
||||
|
||||
export function ThrowParty(corp: ICorporation, office: OfficeSpace, costPerEmployee: number): number {
|
||||
const totalCost = costPerEmployee * office.employees.length;
|
||||
if (corp.funds.lt(totalCost)) return 0;
|
||||
corp.funds = corp.funds.minus(totalCost);
|
||||
if (corp.funds < totalCost) return 0;
|
||||
corp.funds = corp.funds - totalCost;
|
||||
let mult = 0;
|
||||
for (let i = 0; i < office.employees.length; ++i) {
|
||||
mult = office.employees[i].throwParty(costPerEmployee);
|
||||
@ -277,7 +277,7 @@ export function ThrowParty(corp: ICorporation, office: OfficeSpace, costPerEmplo
|
||||
}
|
||||
|
||||
export function PurchaseWarehouse(corp: ICorporation, division: IIndustry, city: string): void {
|
||||
if (corp.funds.lt(CorporationConstants.WarehouseInitialCost)) return;
|
||||
if (corp.funds < CorporationConstants.WarehouseInitialCost) return;
|
||||
if (division.warehouses[city] instanceof Warehouse) return;
|
||||
division.warehouses[city] = new Warehouse({
|
||||
corp: corp,
|
||||
@ -285,21 +285,21 @@ export function PurchaseWarehouse(corp: ICorporation, division: IIndustry, city:
|
||||
loc: city,
|
||||
size: CorporationConstants.WarehouseInitialSize,
|
||||
});
|
||||
corp.funds = corp.funds.minus(CorporationConstants.WarehouseInitialCost);
|
||||
corp.funds = corp.funds - CorporationConstants.WarehouseInitialCost;
|
||||
}
|
||||
|
||||
export function UpgradeWarehouse(corp: ICorporation, division: IIndustry, warehouse: Warehouse): void {
|
||||
const sizeUpgradeCost = CorporationConstants.WarehouseUpgradeBaseCost * Math.pow(1.07, warehouse.level + 1);
|
||||
++warehouse.level;
|
||||
warehouse.updateSize(corp, division);
|
||||
corp.funds = corp.funds.minus(sizeUpgradeCost);
|
||||
corp.funds = corp.funds - sizeUpgradeCost;
|
||||
}
|
||||
|
||||
export function BuyCoffee(corp: ICorporation, division: IIndustry, office: OfficeSpace): void {
|
||||
const upgrade = IndustryUpgrades[0];
|
||||
const cost = office.employees.length * upgrade[1];
|
||||
if (corp.funds.lt(cost)) return;
|
||||
corp.funds = corp.funds.minus(cost);
|
||||
if (corp.funds < cost) return;
|
||||
corp.funds = corp.funds - cost;
|
||||
division.upgrade(upgrade, {
|
||||
corporation: corp,
|
||||
office: office,
|
||||
@ -309,8 +309,8 @@ export function BuyCoffee(corp: ICorporation, division: IIndustry, office: Offic
|
||||
export function HireAdVert(corp: ICorporation, division: IIndustry, office: OfficeSpace): void {
|
||||
const upgrade = IndustryUpgrades[1];
|
||||
const cost = upgrade[1] * Math.pow(upgrade[2], division.upgrades[1]);
|
||||
if (corp.funds.lt(cost)) return;
|
||||
corp.funds = corp.funds.minus(cost);
|
||||
if (corp.funds < cost) return;
|
||||
corp.funds = corp.funds - cost;
|
||||
division.upgrade(upgrade, {
|
||||
corporation: corp,
|
||||
office: office,
|
||||
@ -340,7 +340,7 @@ export function MakeProduct(
|
||||
if (isNaN(marketingInvest)) {
|
||||
throw new Error("Invalid value for marketing investment");
|
||||
}
|
||||
if (corp.funds.lt(designInvest + marketingInvest)) {
|
||||
if (corp.funds < designInvest + marketingInvest) {
|
||||
throw new Error("You don't have enough company funds to make this large of an investment");
|
||||
}
|
||||
const product = new Product({
|
||||
@ -352,7 +352,7 @@ export function MakeProduct(
|
||||
if (division.products[product.name] instanceof Product) {
|
||||
throw new Error(`You already have a product with this name!`);
|
||||
}
|
||||
corp.funds = corp.funds.minus(designInvest + marketingInvest);
|
||||
corp.funds = corp.funds - (designInvest + marketingInvest);
|
||||
division.products[product.name] = product;
|
||||
}
|
||||
|
||||
|
@ -14,10 +14,6 @@ import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||
import { Reviver, Generic_toJSON, Generic_fromJSON } from "../utils/JSONReviver";
|
||||
import { isString } from "../utils/helpers/isString";
|
||||
|
||||
// UI Related Imports
|
||||
|
||||
import Decimal from "decimal.js";
|
||||
|
||||
interface IParams {
|
||||
name?: string;
|
||||
}
|
||||
@ -29,9 +25,9 @@ export class Corporation {
|
||||
divisions: Industry[] = [];
|
||||
|
||||
//Financial stats
|
||||
funds = new Decimal(150e9);
|
||||
revenue = new Decimal(0);
|
||||
expenses = new Decimal(0);
|
||||
funds = 150e9;
|
||||
revenue = 0;
|
||||
expenses = 0;
|
||||
fundingRound = 0;
|
||||
public = false; //Publicly traded
|
||||
totalShares = CorporationConstants.INITIALSHARES; // Total existing shares
|
||||
@ -65,7 +61,7 @@ export class Corporation {
|
||||
console.error("Trying to add invalid amount of funds. Report to a developper.");
|
||||
return;
|
||||
}
|
||||
this.funds = this.funds.plus(amt);
|
||||
this.funds = this.funds + amt;
|
||||
}
|
||||
|
||||
getState(): string {
|
||||
@ -97,8 +93,8 @@ export class Corporation {
|
||||
|
||||
//At the start of a new cycle, calculate profits from previous cycle
|
||||
if (state === "START") {
|
||||
this.revenue = new Decimal(0);
|
||||
this.expenses = new Decimal(0);
|
||||
this.revenue = 0;
|
||||
this.expenses = 0;
|
||||
this.divisions.forEach((ind) => {
|
||||
if (ind.lastCycleRevenue === -Infinity || ind.lastCycleRevenue === Infinity) {
|
||||
return;
|
||||
@ -106,18 +102,18 @@ export class Corporation {
|
||||
if (ind.lastCycleExpenses === -Infinity || ind.lastCycleExpenses === Infinity) {
|
||||
return;
|
||||
}
|
||||
this.revenue = this.revenue.plus(ind.lastCycleRevenue);
|
||||
this.expenses = this.expenses.plus(ind.lastCycleExpenses);
|
||||
this.revenue = this.revenue + ind.lastCycleRevenue;
|
||||
this.expenses = this.expenses + ind.lastCycleExpenses;
|
||||
});
|
||||
const profit = this.revenue.minus(this.expenses);
|
||||
const cycleProfit = profit.times(marketCycles * CorporationConstants.SecsPerMarketCycle);
|
||||
const profit = this.revenue - this.expenses;
|
||||
const cycleProfit = profit * (marketCycles * CorporationConstants.SecsPerMarketCycle);
|
||||
if (isNaN(this.funds) || this.funds === Infinity || this.funds === -Infinity) {
|
||||
dialogBoxCreate(
|
||||
"There was an error calculating your Corporations funds and they got reset to 0. " +
|
||||
"This is a bug. Please report to game developer.<br><br>" +
|
||||
"(Your funds have been set to $150b for the inconvenience)",
|
||||
);
|
||||
this.funds = new Decimal(150e9);
|
||||
this.funds = 150e9;
|
||||
}
|
||||
|
||||
// Process dividends
|
||||
@ -147,28 +143,36 @@ export class Corporation {
|
||||
}
|
||||
|
||||
getDividends(): number {
|
||||
const profit = this.revenue.minus(this.expenses);
|
||||
const cycleProfit = profit.times(CorporationConstants.SecsPerMarketCycle);
|
||||
const profit = this.revenue - this.expenses;
|
||||
const cycleProfit = profit * CorporationConstants.SecsPerMarketCycle;
|
||||
const totalDividends = (this.dividendPercentage / 100) * cycleProfit;
|
||||
const dividendsPerShare = totalDividends / this.totalShares;
|
||||
const dividends = this.numShares * dividendsPerShare * (1 - this.dividendTaxPercentage / 100);
|
||||
return Math.pow(dividends, BitNodeMultipliers.CorporationSoftCap);
|
||||
let upgrades = -0.15;
|
||||
if (this.unlockUpgrades[5] === 1) {
|
||||
upgrades += 0.05;
|
||||
}
|
||||
if (this.unlockUpgrades[6] === 1) {
|
||||
upgrades += 0.1;
|
||||
}
|
||||
console.log(upgrades);
|
||||
return Math.pow(dividends, BitNodeMultipliers.CorporationSoftCap + upgrades);
|
||||
}
|
||||
|
||||
determineValuation(): number {
|
||||
let val,
|
||||
profit = this.revenue.minus(this.expenses).toNumber();
|
||||
profit = this.revenue - this.expenses;
|
||||
if (this.public) {
|
||||
// Account for dividends
|
||||
if (this.dividendPercentage > 0) {
|
||||
profit *= (100 - this.dividendPercentage) / 100;
|
||||
}
|
||||
|
||||
val = this.funds.toNumber() + profit * 85e3;
|
||||
val = this.funds + profit * 85e3;
|
||||
val *= Math.pow(1.1, this.divisions.length);
|
||||
val = Math.max(val, 0);
|
||||
} else {
|
||||
val = 10e9 + Math.max(this.funds.toNumber(), 0) / 3; //Base valuation
|
||||
val = 10e9 + Math.max(this.funds, 0) / 3; //Base valuation
|
||||
if (profit > 0) {
|
||||
val += profit * 315e3;
|
||||
val *= Math.pow(1.1, this.divisions.length);
|
||||
@ -262,12 +266,12 @@ export class Corporation {
|
||||
while (this.unlockUpgrades.length <= upgN) {
|
||||
this.unlockUpgrades.push(0);
|
||||
}
|
||||
if (this.funds.lt(price)) {
|
||||
if (this.funds < price) {
|
||||
dialogBoxCreate("You don't have enough funds to unlock this!");
|
||||
return;
|
||||
}
|
||||
this.unlockUpgrades[upgN] = 1;
|
||||
this.funds = this.funds.minus(price);
|
||||
this.funds = this.funds - price;
|
||||
|
||||
// Apply effects for one-time upgrades
|
||||
if (upgN === 5) {
|
||||
@ -290,12 +294,12 @@ export class Corporation {
|
||||
this.upgradeMultipliers.push(1);
|
||||
}
|
||||
const totalCost = basePrice * Math.pow(priceMult, this.upgrades[upgN]);
|
||||
if (this.funds.lt(totalCost)) {
|
||||
if (this.funds < totalCost) {
|
||||
dialogBoxCreate("You don't have enough funds to purchase this!");
|
||||
return;
|
||||
}
|
||||
++this.upgrades[upgN];
|
||||
this.funds = this.funds.minus(totalCost);
|
||||
this.funds = this.funds - totalCost;
|
||||
|
||||
//Increase upgrade multiplier
|
||||
this.upgradeMultipliers[upgN] = 1 + this.upgrades[upgN] * upgradeAmt;
|
||||
|
@ -9,9 +9,9 @@ export interface ICorporation {
|
||||
|
||||
divisions: Industry[];
|
||||
|
||||
funds: any;
|
||||
revenue: any;
|
||||
expenses: any;
|
||||
funds: number;
|
||||
revenue: number;
|
||||
expenses: number;
|
||||
fundingRound: number;
|
||||
public: boolean;
|
||||
totalShares: number;
|
||||
|
@ -31,10 +31,10 @@ export interface IIndustry {
|
||||
prodMult: number;
|
||||
|
||||
// Decimal
|
||||
lastCycleRevenue: any;
|
||||
lastCycleExpenses: any;
|
||||
thisCycleRevenue: any;
|
||||
thisCycleExpenses: any;
|
||||
lastCycleRevenue: number;
|
||||
lastCycleExpenses: number;
|
||||
thisCycleRevenue: number;
|
||||
thisCycleExpenses: number;
|
||||
|
||||
upgrades: number[];
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { Reviver, Generic_toJSON, Generic_fromJSON } from "../utils/JSONReviver";
|
||||
import { CityName } from "../Locations/data/CityNames";
|
||||
import Decimal from "decimal.js";
|
||||
import { Industries, IndustryStartingCosts, IndustryResearchTrees } from "./IndustryData";
|
||||
import { CorporationConstants } from "./data/Constants";
|
||||
import { EmployeePositions } from "./EmployeePositions";
|
||||
@ -55,10 +54,10 @@ export class Industry implements IIndustry {
|
||||
prodMult = 0; //Production multiplier
|
||||
|
||||
//Financials
|
||||
lastCycleRevenue: any;
|
||||
lastCycleExpenses: any;
|
||||
thisCycleRevenue: any;
|
||||
thisCycleExpenses: any;
|
||||
lastCycleRevenue: number;
|
||||
lastCycleExpenses: number;
|
||||
thisCycleRevenue: number;
|
||||
thisCycleExpenses: number;
|
||||
|
||||
//Upgrades
|
||||
upgrades: number[] = Array(Object.keys(IndustryUpgrades).length).fill(0);
|
||||
@ -87,10 +86,10 @@ export class Industry implements IIndustry {
|
||||
this.type = params.type ? params.type : Industries.Agriculture;
|
||||
|
||||
//Financials
|
||||
this.lastCycleRevenue = new Decimal(0);
|
||||
this.lastCycleExpenses = new Decimal(0);
|
||||
this.thisCycleRevenue = new Decimal(0);
|
||||
this.thisCycleExpenses = new Decimal(0);
|
||||
this.lastCycleRevenue = 0;
|
||||
this.lastCycleExpenses = 0;
|
||||
this.thisCycleRevenue = 0;
|
||||
this.thisCycleExpenses = 0;
|
||||
|
||||
this.warehouses = {
|
||||
[CityName.Aevum]: 0,
|
||||
@ -399,17 +398,17 @@ export class Industry implements IIndustry {
|
||||
dialogBoxCreate(
|
||||
"Something went wrong when compting Corporation's revenue/expenses. This is a bug. Please report to game developer",
|
||||
);
|
||||
this.thisCycleRevenue = new Decimal(0);
|
||||
this.thisCycleExpenses = new Decimal(0);
|
||||
this.thisCycleRevenue = 0;
|
||||
this.thisCycleExpenses = 0;
|
||||
}
|
||||
this.lastCycleRevenue = this.thisCycleRevenue.dividedBy(marketCycles * CorporationConstants.SecsPerMarketCycle);
|
||||
this.lastCycleExpenses = this.thisCycleExpenses.dividedBy(marketCycles * CorporationConstants.SecsPerMarketCycle);
|
||||
this.thisCycleRevenue = new Decimal(0);
|
||||
this.thisCycleExpenses = new Decimal(0);
|
||||
this.lastCycleRevenue = this.thisCycleRevenue / (marketCycles * CorporationConstants.SecsPerMarketCycle);
|
||||
this.lastCycleExpenses = this.thisCycleExpenses / (marketCycles * CorporationConstants.SecsPerMarketCycle);
|
||||
this.thisCycleRevenue = 0;
|
||||
this.thisCycleExpenses = 0;
|
||||
|
||||
// Once you start making revenue, the player should no longer be
|
||||
// considered new, and therefore no longer needs the 'tutorial' UI elements
|
||||
if (this.lastCycleRevenue.gt(0)) {
|
||||
if (this.lastCycleRevenue > 0) {
|
||||
this.newInd = false;
|
||||
}
|
||||
|
||||
@ -422,7 +421,7 @@ export class Industry implements IIndustry {
|
||||
employeeSalary += office.process(marketCycles, corporation, this);
|
||||
}
|
||||
}
|
||||
this.thisCycleExpenses = this.thisCycleExpenses.plus(employeeSalary);
|
||||
this.thisCycleExpenses = this.thisCycleExpenses + employeeSalary;
|
||||
|
||||
// Process change in demand/competition of materials/products
|
||||
this.processMaterialMarket();
|
||||
@ -446,15 +445,15 @@ export class Industry implements IIndustry {
|
||||
// Process production, purchase, and import/export of materials
|
||||
let res = this.processMaterials(marketCycles, corporation);
|
||||
if (Array.isArray(res)) {
|
||||
this.thisCycleRevenue = this.thisCycleRevenue.plus(res[0]);
|
||||
this.thisCycleExpenses = this.thisCycleExpenses.plus(res[1]);
|
||||
this.thisCycleRevenue = this.thisCycleRevenue + res[0];
|
||||
this.thisCycleExpenses = this.thisCycleExpenses + res[1];
|
||||
}
|
||||
|
||||
// Process creation, production & sale of products
|
||||
res = this.processProducts(marketCycles, corporation);
|
||||
if (Array.isArray(res)) {
|
||||
this.thisCycleRevenue = this.thisCycleRevenue.plus(res[0]);
|
||||
this.thisCycleExpenses = this.thisCycleExpenses.plus(res[1]);
|
||||
this.thisCycleRevenue = this.thisCycleRevenue + res[0];
|
||||
this.thisCycleExpenses = this.thisCycleExpenses + res[1];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1476,10 +1475,10 @@ export class Industry implements IIndustry {
|
||||
division.prodMult = this.prodMult;
|
||||
division.state = this.state;
|
||||
division.newInd = this.newInd;
|
||||
division.lastCycleRevenue = this.lastCycleRevenue.plus(0);
|
||||
division.lastCycleExpenses = this.lastCycleExpenses.plus(0);
|
||||
division.thisCycleRevenue = this.thisCycleRevenue.plus(0);
|
||||
division.thisCycleExpenses = this.thisCycleExpenses.plus(0);
|
||||
division.lastCycleRevenue = this.lastCycleRevenue + 0;
|
||||
division.lastCycleExpenses = this.lastCycleExpenses + 0;
|
||||
division.thisCycleRevenue = this.thisCycleRevenue + 0;
|
||||
division.thisCycleExpenses = this.thisCycleExpenses + 0;
|
||||
division.upgrades = this.upgrades.slice();
|
||||
division.prodMats = this.prodMats.slice();
|
||||
return division;
|
||||
|
@ -53,14 +53,14 @@ export const CorporationUnlockUpgrades: IMap<CorporationUnlockUpgrade> = {
|
||||
],
|
||||
"5": [
|
||||
5,
|
||||
500e9,
|
||||
500e12,
|
||||
"Shady Accounting",
|
||||
"Utilize unscrupulous accounting practices and pay off government officials to save money " +
|
||||
"on taxes. This reduces the dividend tax rate by 5%.",
|
||||
],
|
||||
"6": [
|
||||
6,
|
||||
2e12,
|
||||
2e15,
|
||||
"Government Partnership",
|
||||
"Help national governments further their agendas in exchange for lowered taxes. " +
|
||||
"This reduces the dividend tax rate by 10%",
|
||||
|
@ -38,7 +38,7 @@ export function BribeFactionModal(props: IProps): React.ReactElement {
|
||||
isNaN(stock) ||
|
||||
money < 0 ||
|
||||
stock < 0 ||
|
||||
corp.funds.lt(money) ||
|
||||
corp.funds < money ||
|
||||
stock > corp.numShares;
|
||||
|
||||
function onMoneyChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
@ -61,7 +61,7 @@ export function BribeFactionModal(props: IProps): React.ReactElement {
|
||||
if (money === 0 && stock === 0) return "";
|
||||
if (isNaN(money) || isNaN(stock) || money < 0 || stock < 0) {
|
||||
return "ERROR: Invalid value(s) entered";
|
||||
} else if (corp.funds.lt(money)) {
|
||||
} else if (corp.funds < money) {
|
||||
return "ERROR: You do not have this much money to bribe with";
|
||||
} else if (stock > corp.numShares) {
|
||||
return "ERROR: You do not have this many shares to bribe with";
|
||||
@ -84,7 +84,7 @@ export function BribeFactionModal(props: IProps): React.ReactElement {
|
||||
"You gained " + numeralWrapper.formatReputation(rep) + " reputation with " + fac.name + " by bribing them.",
|
||||
);
|
||||
fac.playerReputation += rep;
|
||||
corp.funds = corp.funds.minus(money);
|
||||
corp.funds = corp.funds - money;
|
||||
corp.numShares -= stock;
|
||||
props.onClose();
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ export function ExpandIndustryTab(props: IProps): React.ReactElement {
|
||||
if (cost === undefined) {
|
||||
throw new Error(`Invalid industry: '${industry}'`);
|
||||
}
|
||||
const disabled = corp.funds.lt(cost) || name === "";
|
||||
const disabled = corp.funds < cost || name === "";
|
||||
|
||||
function newIndustry(): void {
|
||||
if (disabled) return;
|
||||
|
@ -19,7 +19,7 @@ export function ExpandNewCity(props: IProps): React.ReactElement {
|
||||
const possibleCities = Object.keys(division.offices).filter((cityName: string) => division.offices[cityName] === 0);
|
||||
const [city, setCity] = useState(possibleCities[0]);
|
||||
|
||||
const disabled = corp.funds.lt(CorporationConstants.OfficeInitialCost);
|
||||
const disabled = corp.funds < CorporationConstants.OfficeInitialCost;
|
||||
|
||||
function onCityChange(event: SelectChangeEvent<string>): void {
|
||||
setCity(event.target.value);
|
||||
|
@ -440,7 +440,7 @@ export function IndustryOffice(props: IProps): React.ReactElement {
|
||||
<br />
|
||||
<Tooltip title={<Typography>Upgrade the office's size so that it can hold more employees!</Typography>}>
|
||||
<span>
|
||||
<Button disabled={corp.funds.lt(0)} onClick={() => setUpgradeOfficeSizeOpen(true)}>
|
||||
<Button disabled={corp.funds < 0} onClick={() => setUpgradeOfficeSizeOpen(true)}>
|
||||
Upgrade size
|
||||
</Button>
|
||||
</span>
|
||||
@ -458,7 +458,7 @@ export function IndustryOffice(props: IProps): React.ReactElement {
|
||||
title={<Typography>Throw an office party to increase your employee's morale and happiness</Typography>}
|
||||
>
|
||||
<span>
|
||||
<Button disabled={corp.funds.lt(0)} onClick={() => setThrowPartyOpen(true)}>
|
||||
<Button disabled={corp.funds < 0} onClick={() => setThrowPartyOpen(true)}>
|
||||
Throw Party
|
||||
</Button>
|
||||
</span>
|
||||
|
@ -79,11 +79,7 @@ function MakeProductButton(): React.ReactElement {
|
||||
)
|
||||
}
|
||||
>
|
||||
<Button
|
||||
color={shouldFlash() ? "error" : "primary"}
|
||||
onClick={() => setMakeOpen(true)}
|
||||
disabled={corp.funds.lt(0)}
|
||||
>
|
||||
<Button color={shouldFlash() ? "error" : "primary"} onClick={() => setMakeOpen(true)} disabled={corp.funds < 0}>
|
||||
{createProductButtonText}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
@ -97,7 +93,7 @@ function Text(): React.ReactElement {
|
||||
const [helpOpen, setHelpOpen] = useState(false);
|
||||
const [researchOpen, setResearchOpen] = useState(false);
|
||||
const vechain = corp.unlockUpgrades[4] === 1;
|
||||
const profit = division.lastCycleRevenue.minus(division.lastCycleExpenses).toNumber();
|
||||
const profit = division.lastCycleRevenue - division.lastCycleExpenses;
|
||||
|
||||
let advertisingInfo = false;
|
||||
const advertisingFactors = division.getAdvertisingFactors();
|
||||
@ -119,7 +115,7 @@ function Text(): React.ReactElement {
|
||||
return (
|
||||
<>
|
||||
<Typography>
|
||||
Industry: {division.type} (Corp Funds: <Money money={corp.funds.toNumber()} />)
|
||||
Industry: {division.type} (Corp Funds: <Money money={corp.funds} />)
|
||||
</Typography>
|
||||
<br />
|
||||
<StatsTable
|
||||
@ -149,8 +145,8 @@ function Text(): React.ReactElement {
|
||||
<br />
|
||||
<StatsTable
|
||||
rows={[
|
||||
["Revenue:", <MoneyRate money={division.lastCycleRevenue.toNumber()} />],
|
||||
["Expenses:", <MoneyRate money={division.lastCycleExpenses.toNumber()} />],
|
||||
["Revenue:", <MoneyRate money={division.lastCycleRevenue} />],
|
||||
["Expenses:", <MoneyRate money={division.lastCycleExpenses} />],
|
||||
["Profit:", <MoneyRate money={profit} />],
|
||||
]}
|
||||
/>
|
||||
@ -241,8 +237,8 @@ function Upgrades(props: { office: OfficeSpace; rerender: () => void }): React.R
|
||||
}
|
||||
|
||||
function onClick(): void {
|
||||
if (corp.funds.lt(cost)) return;
|
||||
corp.funds = corp.funds.minus(cost);
|
||||
if (corp.funds < cost) return;
|
||||
corp.funds = corp.funds - cost;
|
||||
division.upgrade(upgrade, {
|
||||
corporation: corp,
|
||||
office: props.office,
|
||||
@ -253,7 +249,7 @@ function Upgrades(props: { office: OfficeSpace; rerender: () => void }): React.R
|
||||
upgrades.push(
|
||||
<Tooltip key={index} title={upgrade[5]}>
|
||||
<span>
|
||||
<Button disabled={corp.funds.lt(cost)} onClick={onClick}>
|
||||
<Button disabled={corp.funds < cost} onClick={onClick}>
|
||||
{upgrade[4]} -
|
||||
<MoneyCost money={cost} corp={corp} />
|
||||
</Button>
|
||||
|
@ -45,14 +45,14 @@ function WarehouseRoot(props: IProps): React.ReactElement {
|
||||
|
||||
// Upgrade Warehouse size button
|
||||
const sizeUpgradeCost = CorporationConstants.WarehouseUpgradeBaseCost * Math.pow(1.07, props.warehouse.level + 1);
|
||||
const canAffordUpgrade = corp.funds.gt(sizeUpgradeCost);
|
||||
const canAffordUpgrade = corp.funds > sizeUpgradeCost;
|
||||
function upgradeWarehouseOnClick(): void {
|
||||
if (division === null) return;
|
||||
if (props.warehouse === 0) return;
|
||||
if (!canAffordUpgrade) return;
|
||||
++props.warehouse.level;
|
||||
props.warehouse.updateSize(corp, division);
|
||||
corp.funds = corp.funds.minus(sizeUpgradeCost);
|
||||
corp.funds = corp.funds - sizeUpgradeCost;
|
||||
props.rerender();
|
||||
}
|
||||
|
||||
@ -197,7 +197,7 @@ interface IEmptyProps {
|
||||
function EmptyWarehouse(props: IEmptyProps): React.ReactElement {
|
||||
const corp = useCorporation();
|
||||
const division = useDivision();
|
||||
const disabled = corp.funds.lt(CorporationConstants.WarehouseInitialCost);
|
||||
const disabled = corp.funds < CorporationConstants.WarehouseInitialCost;
|
||||
function purchaseWarehouse(): void {
|
||||
if (disabled) return;
|
||||
PurchaseWarehouse(corp, division, props.city);
|
||||
|
@ -81,7 +81,7 @@ export function IssueNewSharesModal(props: IProps): React.ReactElement {
|
||||
privateShares = Math.round(privateShares / 1e6) * 1e6;
|
||||
|
||||
corp.issuedShares += newShares - privateShares;
|
||||
corp.funds = corp.funds.plus(profit);
|
||||
corp.funds = corp.funds + profit;
|
||||
corp.immediatelyUpdateSharePrice();
|
||||
props.onClose();
|
||||
dialogBoxCreate(
|
||||
|
@ -28,7 +28,7 @@ export function LevelableUpgrade(props: IProps): React.ReactElement {
|
||||
|
||||
const tooltip = data[5];
|
||||
function onClick(): void {
|
||||
if (corp.funds.lt(cost)) return;
|
||||
if (corp.funds < cost) return;
|
||||
try {
|
||||
LevelUpgrade(corp, props.upgrade);
|
||||
} catch (err) {
|
||||
@ -40,11 +40,13 @@ export function LevelableUpgrade(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<Grid item xs={4}>
|
||||
<Box display="flex" alignItems="center" flexDirection="row-reverse">
|
||||
<Button disabled={corp.funds.lt(cost)} sx={{ mx: 1 }} onClick={onClick}>
|
||||
<Button disabled={corp.funds < cost} sx={{ mx: 1 }} onClick={onClick}>
|
||||
<MoneyCost money={cost} corp={corp} />
|
||||
</Button>
|
||||
<Tooltip title={tooltip}>
|
||||
<Typography>{data[4]} - lvl {level}</Typography>
|
||||
<Typography>
|
||||
{data[4]} - lvl {level}
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
</Grid>
|
||||
|
@ -23,7 +23,7 @@ interface IProps {
|
||||
|
||||
export function MoneyCost(props: IProps): React.ReactElement {
|
||||
const classes = useStyles();
|
||||
if (!props.corp.funds.gt(props.money))
|
||||
if (!(props.corp.funds > props.money))
|
||||
return <span className={classes.unbuyable}>{numeralWrapper.formatMoney(props.money)}</span>;
|
||||
|
||||
return <span className={classes.money}>{numeralWrapper.formatMoney(props.money)}</span>;
|
||||
|
@ -36,7 +36,7 @@ interface IProps {
|
||||
export function Overview({ rerender }: IProps): React.ReactElement {
|
||||
const player = use.Player();
|
||||
const corp = useCorporation();
|
||||
const profit: number = corp.revenue.minus(corp.expenses).toNumber();
|
||||
const profit: number = corp.revenue - corp.expenses;
|
||||
|
||||
const multRows: any[][] = [];
|
||||
function appendMult(name: string, value: number): void {
|
||||
@ -57,9 +57,9 @@ export function Overview({ rerender }: IProps): React.ReactElement {
|
||||
<>
|
||||
<StatsTable
|
||||
rows={[
|
||||
["Total Funds:", <Money money={corp.funds.toNumber()} />],
|
||||
["Total Revenue:", <MoneyRate money={corp.revenue.toNumber()} />],
|
||||
["Total Expenses:", <MoneyRate money={corp.expenses.toNumber()} />],
|
||||
["Total Funds:", <Money money={corp.funds} />],
|
||||
["Total Revenue:", <MoneyRate money={corp.revenue} />],
|
||||
["Total Expenses:", <MoneyRate money={corp.expenses} />],
|
||||
["Publicly Traded:", corp.public ? "Yes" : "No"],
|
||||
["Owned Stock Shares:", numeralWrapper.format(corp.numShares, "0.000a")],
|
||||
["Stock Price:", corp.public ? <Money money={corp.sharePrice} /> : "N/A"],
|
||||
|
@ -25,15 +25,25 @@ function BulkPurchaseText(props: IBulkPurchaseTextProps): React.ReactElement {
|
||||
const maxAmount = (props.warehouse.size - props.warehouse.sizeUsed) / matSize;
|
||||
|
||||
if (parsedAmt * matSize > maxAmount) {
|
||||
return <><Typography color={"error"}>Not enough warehouse space to purchase this amount</Typography></>;
|
||||
return (
|
||||
<>
|
||||
<Typography color={"error"}>Not enough warehouse space to purchase this amount</Typography>
|
||||
</>
|
||||
);
|
||||
} else if (isNaN(cost)) {
|
||||
return <><Typography color={"error"}>Invalid put for Bulk Purchase amount</Typography></>;
|
||||
return (
|
||||
<>
|
||||
<Typography color={"error"}>Invalid put for Bulk Purchase amount</Typography>
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<><Typography>
|
||||
Purchasing {numeralWrapper.format(parsedAmt, "0,0.00")} of {props.mat.name} will cost{" "}
|
||||
{numeralWrapper.formatMoney(cost)}</Typography>
|
||||
</>
|
||||
<>
|
||||
<Typography>
|
||||
Purchasing {numeralWrapper.format(parsedAmt, "0,0.00")} of {props.mat.name} will cost{" "}
|
||||
{numeralWrapper.formatMoney(cost)}
|
||||
</Typography>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -62,8 +72,8 @@ function BulkPurchase(props: IBPProps): React.ReactElement {
|
||||
dialogBoxCreate("Invalid input amount");
|
||||
} else {
|
||||
const cost = amount * props.mat.bCost;
|
||||
if (corp.funds.gt(cost)) {
|
||||
corp.funds = corp.funds.minus(cost);
|
||||
if (corp.funds >= cost) {
|
||||
corp.funds = corp.funds - cost;
|
||||
props.mat.qty += amount;
|
||||
} else {
|
||||
dialogBoxCreate(`You cannot afford this purchase.`);
|
||||
|
@ -23,7 +23,7 @@ export function ThrowPartyModal(props: IProps): React.ReactElement {
|
||||
const [cost, setCost] = useState(0);
|
||||
|
||||
const totalCost = cost * props.office.employees.length;
|
||||
const canParty = corp.funds.gte(totalCost);
|
||||
const canParty = corp.funds >= totalCost;
|
||||
function changeCost(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
let x = parseFloat(event.target.value);
|
||||
if (isNaN(x)) x = 0;
|
||||
|
@ -22,7 +22,7 @@ export function UnlockUpgrade(props: IProps): React.ReactElement {
|
||||
const data = props.upgradeData;
|
||||
const tooltip = data[3];
|
||||
function onClick(): void {
|
||||
if (corp.funds.lt(data[1])) return;
|
||||
if (corp.funds < data[1]) return;
|
||||
try {
|
||||
UU(corp, props.upgradeData);
|
||||
} catch (err) {
|
||||
@ -34,7 +34,7 @@ export function UnlockUpgrade(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<Grid item xs={4}>
|
||||
<Box display="flex" alignItems="center" flexDirection="row-reverse">
|
||||
<Button disabled={corp.funds.lt(data[1])} sx={{ mx: 1 }} onClick={onClick}>
|
||||
<Button disabled={corp.funds < data[1]} sx={{ mx: 1 }} onClick={onClick}>
|
||||
<MoneyCost money={data[1]} corp={corp} />
|
||||
</Button>
|
||||
<Tooltip title={tooltip}>
|
||||
|
@ -23,7 +23,7 @@ interface IUpgradeButton {
|
||||
function UpgradeSizeButton(props: IUpgradeButton): React.ReactElement {
|
||||
const corp = useCorporation();
|
||||
function upgradeSize(cost: number, size: number): void {
|
||||
if (corp.funds.lt(cost)) {
|
||||
if (corp.funds < cost) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -34,7 +34,7 @@ function UpgradeSizeButton(props: IUpgradeButton): React.ReactElement {
|
||||
return (
|
||||
<Tooltip title={numeralWrapper.formatMoney(props.cost)}>
|
||||
<span>
|
||||
<Button disabled={corp.funds.lt(props.cost)} onClick={() => upgradeSize(props.cost, props.size)}>
|
||||
<Button disabled={corp.funds < props.cost} onClick={() => upgradeSize(props.cost, props.size)}>
|
||||
+{props.size}
|
||||
</Button>
|
||||
</span>
|
||||
@ -63,7 +63,7 @@ export function UpgradeOfficeSizeModal(props: IProps): React.ReactElement {
|
||||
const upgradeCost15 = CorporationConstants.OfficeInitialCost * mult;
|
||||
|
||||
//Calculate max upgrade size and cost
|
||||
const maxMult = corp.funds.dividedBy(CorporationConstants.OfficeInitialCost).toNumber();
|
||||
const maxMult = corp.funds / CorporationConstants.OfficeInitialCost;
|
||||
let maxNum = 1;
|
||||
mult = Math.pow(costMultiplier, initialPriceMult);
|
||||
while (maxNum < 50) {
|
||||
|
@ -54,7 +54,7 @@ export function buyDarkwebItem(itemName: string): void {
|
||||
}
|
||||
|
||||
// return if the player doesn't have enough money
|
||||
if (Player.money.lt(item.price)) {
|
||||
if (Player.money < item.price) {
|
||||
Terminal.error("Not enough money to purchase " + item.program);
|
||||
return;
|
||||
}
|
||||
|
@ -19,13 +19,13 @@ interface IProps {
|
||||
export function Corporation(props: IProps): React.ReactElement {
|
||||
function addTonsCorporationFunds(): void {
|
||||
if (props.player.corporation) {
|
||||
props.player.corporation.funds = props.player.corporation.funds.plus(1e99);
|
||||
props.player.corporation.funds = props.player.corporation.funds + 1e99;
|
||||
}
|
||||
}
|
||||
|
||||
function resetCorporationFunds(): void {
|
||||
if (props.player.corporation) {
|
||||
props.player.corporation.funds = props.player.corporation.funds.minus(props.player.corporation.funds);
|
||||
props.player.corporation.funds = props.player.corporation.funds - props.player.corporation.funds;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,7 @@ export function purchaseAugmentation(aug: Augmentation, fac: Faction, sing = fal
|
||||
} else {
|
||||
dialogBoxCreate(txt);
|
||||
}
|
||||
} else if (aug.baseCost !== 0 && Player.money.lt(aug.baseCost * factionInfo.augmentationPriceMult)) {
|
||||
} else if (aug.baseCost !== 0 && Player.money < aug.baseCost * factionInfo.augmentationPriceMult) {
|
||||
const txt = "You don't have enough money to purchase " + aug.name;
|
||||
if (sing) {
|
||||
return txt;
|
||||
@ -99,7 +99,7 @@ export function purchaseAugmentation(aug: Augmentation, fac: Faction, sing = fal
|
||||
return txt;
|
||||
}
|
||||
dialogBoxCreate(txt);
|
||||
} else if (aug.baseCost === 0 || Player.money.gte(aug.baseCost * factionInfo.augmentationPriceMult)) {
|
||||
} else if (aug.baseCost === 0 || Player.money >= aug.baseCost * factionInfo.augmentationPriceMult) {
|
||||
const queuedAugmentation = new PlayerOwnedAugmentation(aug.name);
|
||||
if (aug.name == AugmentationNames.NeuroFluxGovernor) {
|
||||
queuedAugmentation.level = getNextNeurofluxLevel();
|
||||
|
@ -93,8 +93,7 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
|
||||
const repCost = aug.baseRepRequirement * props.faction.getInfo().augmentationRepRequirementMult;
|
||||
const hasReq = props.faction.playerReputation >= repCost;
|
||||
const hasRep = hasAugmentationPrereqs(aug);
|
||||
const hasCost =
|
||||
aug.baseCost !== 0 && player.money.gt(aug.baseCost * props.faction.getInfo().augmentationPriceMult);
|
||||
const hasCost = aug.baseCost !== 0 && player.money > aug.baseCost * props.faction.getInfo().augmentationPriceMult;
|
||||
return hasCost && hasReq && hasRep;
|
||||
}
|
||||
const buy = augs.filter(canBuy).sort((augName1, augName2) => {
|
||||
|
@ -37,7 +37,7 @@ export function DonateOption(props: IProps): React.ReactElement {
|
||||
function canDonate(): boolean {
|
||||
if (donateAmt === null) return false;
|
||||
if (isNaN(donateAmt) || donateAmt <= 0) return false;
|
||||
if (props.p.money.lt(donateAmt)) return false;
|
||||
if (props.p.money < donateAmt) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ export function DonateOption(props: IProps): React.ReactElement {
|
||||
function Status(): React.ReactElement {
|
||||
if (donateAmt === null) return <></>;
|
||||
if (!canDonate()) {
|
||||
if (props.p.money.lt(donateAmt)) return <Typography>Insufficient funds</Typography>;
|
||||
if (props.p.money < donateAmt) return <Typography>Insufficient funds</Typography>;
|
||||
return <Typography>Invalid donate amount entered!</Typography>;
|
||||
}
|
||||
return (
|
||||
|
@ -88,7 +88,7 @@ export function PurchaseableAugmentation(props: IProps): React.ReactElement {
|
||||
const repCost = aug.baseRepRequirement * props.faction.getInfo().augmentationRepRequirementMult;
|
||||
const hasReq = hasAugmentationPrereqs(aug);
|
||||
const hasRep = props.faction.playerReputation >= repCost;
|
||||
const hasCost = aug.baseCost === 0 || props.p.money.gt(aug.baseCost * props.faction.getInfo().augmentationPriceMult);
|
||||
const hasCost = aug.baseCost === 0 || props.p.money > aug.baseCost * props.faction.getInfo().augmentationPriceMult;
|
||||
|
||||
// Determine UI properties
|
||||
const color: "error" | "primary" = !hasReq || !hasRep || !hasCost ? "error" : "primary";
|
||||
|
@ -316,7 +316,7 @@ export class GangMember {
|
||||
// Prevent purchasing of already-owned upgrades
|
||||
if (this.augmentations.includes(upg.name) || this.upgrades.includes(upg.name)) return false;
|
||||
|
||||
if (player.money.lt(gang.getUpgradeCost(upg))) return false;
|
||||
if (player.money < gang.getUpgradeCost(upg)) return false;
|
||||
player.loseMoney(gang.getUpgradeCost(upg), "gang");
|
||||
if (upg.type === "g") {
|
||||
this.augmentations.push(upg.name);
|
||||
|
@ -28,7 +28,7 @@ function NextReveal(props: INextRevealProps): React.ReactElement {
|
||||
const upgrades = Object.keys(GangMemberUpgrades)
|
||||
.filter((upgName: string) => {
|
||||
const upg = GangMemberUpgrades[upgName];
|
||||
if (player.money.gt(gang.getUpgradeCost(upg))) return false;
|
||||
if (player.money > gang.getUpgradeCost(upg)) return false;
|
||||
if (upg.type !== props.type) return false;
|
||||
if (props.upgrades.includes(upgName)) return false;
|
||||
return true;
|
||||
@ -96,7 +96,7 @@ function GangMemberUpgradePanel(props: IPanelProps): React.ReactElement {
|
||||
return Object.keys(GangMemberUpgrades)
|
||||
.filter((upgName: string) => {
|
||||
const upg = GangMemberUpgrades[upgName];
|
||||
if (player.money.lt(gang.getUpgradeCost(upg))) return false;
|
||||
if (player.money < gang.getUpgradeCost(upg)) return false;
|
||||
if (upg.type !== type) return false;
|
||||
if (list.includes(upgName)) return false;
|
||||
return true;
|
||||
|
@ -98,14 +98,14 @@ export function getMaxNumberLevelUpgrades(
|
||||
throw new Error(`getMaxNumberLevelUpgrades() called without maxLevel arg`);
|
||||
}
|
||||
|
||||
if (player.money.lt(nodeObj.calculateLevelUpgradeCost(1, player.hacknet_node_level_cost_mult))) {
|
||||
if (player.money < nodeObj.calculateLevelUpgradeCost(1, player.hacknet_node_level_cost_mult)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let min = 1;
|
||||
let max = maxLevel - 1;
|
||||
const levelsToMax = maxLevel - nodeObj.level;
|
||||
if (player.money.gt(nodeObj.calculateLevelUpgradeCost(levelsToMax, player.hacknet_node_level_cost_mult))) {
|
||||
if (player.money > nodeObj.calculateLevelUpgradeCost(levelsToMax, player.hacknet_node_level_cost_mult)) {
|
||||
return levelsToMax;
|
||||
}
|
||||
|
||||
@ -113,13 +113,13 @@ export function getMaxNumberLevelUpgrades(
|
||||
const curr = ((min + max) / 2) | 0;
|
||||
if (
|
||||
curr !== maxLevel &&
|
||||
player.money.gt(nodeObj.calculateLevelUpgradeCost(curr, player.hacknet_node_level_cost_mult)) &&
|
||||
player.money.lt(nodeObj.calculateLevelUpgradeCost(curr + 1, player.hacknet_node_level_cost_mult))
|
||||
player.money > nodeObj.calculateLevelUpgradeCost(curr, player.hacknet_node_level_cost_mult) &&
|
||||
player.money < nodeObj.calculateLevelUpgradeCost(curr + 1, player.hacknet_node_level_cost_mult)
|
||||
) {
|
||||
return Math.min(levelsToMax, curr);
|
||||
} else if (player.money.lt(nodeObj.calculateLevelUpgradeCost(curr, player.hacknet_node_level_cost_mult))) {
|
||||
} else if (player.money < nodeObj.calculateLevelUpgradeCost(curr, player.hacknet_node_level_cost_mult)) {
|
||||
max = curr - 1;
|
||||
} else if (player.money.gt(nodeObj.calculateLevelUpgradeCost(curr, player.hacknet_node_level_cost_mult))) {
|
||||
} else if (player.money > nodeObj.calculateLevelUpgradeCost(curr, player.hacknet_node_level_cost_mult)) {
|
||||
min = curr + 1;
|
||||
} else {
|
||||
return Math.min(levelsToMax, curr);
|
||||
@ -138,7 +138,7 @@ export function getMaxNumberRamUpgrades(
|
||||
throw new Error(`getMaxNumberRamUpgrades() called without maxLevel arg`);
|
||||
}
|
||||
|
||||
if (player.money.lt(nodeObj.calculateRamUpgradeCost(1, player.hacknet_node_ram_cost_mult))) {
|
||||
if (player.money < nodeObj.calculateRamUpgradeCost(1, player.hacknet_node_ram_cost_mult)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -148,13 +148,13 @@ export function getMaxNumberRamUpgrades(
|
||||
} else {
|
||||
levelsToMax = Math.round(Math.log2(maxLevel / nodeObj.ram));
|
||||
}
|
||||
if (player.money.gt(nodeObj.calculateRamUpgradeCost(levelsToMax, player.hacknet_node_ram_cost_mult))) {
|
||||
if (player.money > nodeObj.calculateRamUpgradeCost(levelsToMax, player.hacknet_node_ram_cost_mult)) {
|
||||
return levelsToMax;
|
||||
}
|
||||
|
||||
//We'll just loop until we find the max
|
||||
for (let i = levelsToMax - 1; i >= 0; --i) {
|
||||
if (player.money.gt(nodeObj.calculateRamUpgradeCost(i, player.hacknet_node_ram_cost_mult))) {
|
||||
if (player.money > nodeObj.calculateRamUpgradeCost(i, player.hacknet_node_ram_cost_mult)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@ -171,14 +171,14 @@ export function getMaxNumberCoreUpgrades(
|
||||
throw new Error(`getMaxNumberCoreUpgrades() called without maxLevel arg`);
|
||||
}
|
||||
|
||||
if (player.money.lt(nodeObj.calculateCoreUpgradeCost(1, player.hacknet_node_core_cost_mult))) {
|
||||
if (player.money < nodeObj.calculateCoreUpgradeCost(1, player.hacknet_node_core_cost_mult)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let min = 1;
|
||||
let max = maxLevel - 1;
|
||||
const levelsToMax = maxLevel - nodeObj.cores;
|
||||
if (player.money.gt(nodeObj.calculateCoreUpgradeCost(levelsToMax, player.hacknet_node_core_cost_mult))) {
|
||||
if (player.money > nodeObj.calculateCoreUpgradeCost(levelsToMax, player.hacknet_node_core_cost_mult)) {
|
||||
return levelsToMax;
|
||||
}
|
||||
|
||||
@ -187,13 +187,13 @@ export function getMaxNumberCoreUpgrades(
|
||||
const curr = ((min + max) / 2) | 0;
|
||||
if (
|
||||
curr != maxLevel &&
|
||||
player.money.gt(nodeObj.calculateCoreUpgradeCost(curr, player.hacknet_node_core_cost_mult)) &&
|
||||
player.money.lt(nodeObj.calculateCoreUpgradeCost(curr + 1, player.hacknet_node_core_cost_mult))
|
||||
player.money > nodeObj.calculateCoreUpgradeCost(curr, player.hacknet_node_core_cost_mult) &&
|
||||
player.money < nodeObj.calculateCoreUpgradeCost(curr + 1, player.hacknet_node_core_cost_mult)
|
||||
) {
|
||||
return Math.min(levelsToMax, curr);
|
||||
} else if (player.money.lt(nodeObj.calculateCoreUpgradeCost(curr, player.hacknet_node_core_cost_mult))) {
|
||||
} else if (player.money < nodeObj.calculateCoreUpgradeCost(curr, player.hacknet_node_core_cost_mult)) {
|
||||
max = curr - 1;
|
||||
} else if (player.money.gt(nodeObj.calculateCoreUpgradeCost(curr, player.hacknet_node_core_cost_mult))) {
|
||||
} else if (player.money > nodeObj.calculateCoreUpgradeCost(curr, player.hacknet_node_core_cost_mult)) {
|
||||
min = curr + 1;
|
||||
} else {
|
||||
return Math.min(levelsToMax, curr);
|
||||
@ -480,7 +480,7 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
||||
player.hashManager.refundUpgrade(upgName);
|
||||
return false;
|
||||
}
|
||||
corp.funds = corp.funds.plus(upg.value);
|
||||
corp.funds = corp.funds + upg.value;
|
||||
break;
|
||||
}
|
||||
case "Reduce Minimum Security": {
|
||||
|
@ -20,8 +20,6 @@ import { createRandomIp } from "../utils/IPAddress";
|
||||
|
||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
||||
|
||||
|
||||
|
||||
interface IConstructorParams {
|
||||
adminRights?: boolean;
|
||||
hostname: string;
|
||||
@ -37,7 +35,7 @@ export class HacknetServer extends BaseServer implements IHacknetNode {
|
||||
|
||||
// Number of cores. Improves hash production
|
||||
cores = 1;
|
||||
|
||||
|
||||
// Number of hashes that can be stored by this Hacknet Server
|
||||
hashCapacity = 0;
|
||||
|
||||
@ -53,6 +51,9 @@ export class HacknetServer extends BaseServer implements IHacknetNode {
|
||||
// Total number of hashes earned by this server
|
||||
totalHashesGenerated = 0;
|
||||
|
||||
// Flag indicating wehther this is a purchased server
|
||||
purchasedByPlayer = true;
|
||||
|
||||
constructor(params: IConstructorParams = { hostname: "", ip: createRandomIp() }) {
|
||||
super(params);
|
||||
|
||||
@ -95,7 +96,7 @@ export class HacknetServer extends BaseServer implements IHacknetNode {
|
||||
upgradeCore(levels: number, prodMult: number): void {
|
||||
this.cores = Math.min(HacknetServerConstants.MaxCores, Math.round(this.cores + levels));
|
||||
this.updateHashRate(prodMult);
|
||||
this.cpuCores=this.cores;
|
||||
this.cpuCores = this.cores;
|
||||
}
|
||||
|
||||
upgradeLevel(levels: number, prodMult: number): void {
|
||||
|
@ -155,7 +155,7 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
|
||||
<Money money={upgradeCacheCost} player={props.player} />
|
||||
</>
|
||||
);
|
||||
if (props.player.money.lt(upgradeCacheCost)) {
|
||||
if (props.player.money < upgradeCacheCost) {
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ export function PlayerInfo(props: IProps): React.ReactElement {
|
||||
<>
|
||||
<Typography>
|
||||
Money:
|
||||
<Money money={props.player.money.toNumber()} />
|
||||
<Money money={props.player.money} />
|
||||
</Typography>
|
||||
|
||||
{hasServers && (
|
||||
|
@ -2,18 +2,11 @@ import { CONSTANTS } from "../Constants";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
|
||||
export function getHospitalizationCost(p: IPlayer): number {
|
||||
let money;
|
||||
if (typeof p.money === "number") {
|
||||
money = p.money;
|
||||
} else {
|
||||
money = p.money.toNumber();
|
||||
}
|
||||
|
||||
if (money < 0) {
|
||||
if (p.money < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Math.min(money * 0.1, (p.max_hp - p.hp) * CONSTANTS.HospitalCostPerHp);
|
||||
return Math.min(p.money * 0.1, (p.max_hp - p.hp) * CONSTANTS.HospitalCostPerHp);
|
||||
}
|
||||
|
||||
export function calculateHospitalizationCost(p: IPlayer, damage: number): number {
|
||||
|
@ -1294,9 +1294,9 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
// Return player's money
|
||||
workerScript.log(
|
||||
"getServerMoneyAvailable",
|
||||
`returned player's money: ${numeralWrapper.formatMoney(Player.money.toNumber())}`,
|
||||
`returned player's money: ${numeralWrapper.formatMoney(Player.money)}`,
|
||||
);
|
||||
return Player.money.toNumber();
|
||||
return Player.money;
|
||||
}
|
||||
workerScript.log(
|
||||
"getServerMoneyAvailable",
|
||||
@ -1522,7 +1522,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (Player.money.lt(cost)) {
|
||||
if (Player.money < cost) {
|
||||
workerScript.log(
|
||||
"purchaseServer",
|
||||
`Not enough money to purchase server. Need ${numeralWrapper.formatMoney(cost)}`,
|
||||
@ -2126,7 +2126,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
company_rep_mult: Player.company_rep_mult,
|
||||
faction_rep_mult: Player.faction_rep_mult,
|
||||
numPeopleKilled: Player.numPeopleKilled,
|
||||
money: Player.money.toNumber(),
|
||||
money: Player.money,
|
||||
city: Player.city,
|
||||
location: Player.location,
|
||||
companyName: Player.companyName,
|
||||
|
@ -450,7 +450,7 @@ export function NetscriptSingularity(
|
||||
case CityName.NewTokyo:
|
||||
case CityName.Ishima:
|
||||
case CityName.Volhaven:
|
||||
if (player.money.lt(CONSTANTS.TravelCost)) {
|
||||
if (player.money < CONSTANTS.TravelCost) {
|
||||
throw helper.makeRuntimeErrorMsg("travelToCity", "Not enough money to travel.");
|
||||
}
|
||||
player.loseMoney(CONSTANTS.TravelCost, "other");
|
||||
@ -473,7 +473,7 @@ export function NetscriptSingularity(
|
||||
return false;
|
||||
}
|
||||
|
||||
if (player.money.lt(CONSTANTS.TorRouterCost)) {
|
||||
if (player.money < CONSTANTS.TorRouterCost) {
|
||||
workerScript.log("purchaseTor", "You cannot afford to purchase a Tor router.");
|
||||
return false;
|
||||
}
|
||||
@ -520,7 +520,7 @@ export function NetscriptSingularity(
|
||||
return false;
|
||||
}
|
||||
|
||||
if (player.money.lt(item.price)) {
|
||||
if (player.money < item.price) {
|
||||
workerScript.log(
|
||||
"purchaseProgram",
|
||||
`Not enough money to purchase '${item.program}'. Need ${numeralWrapper.formatMoney(item.price)}`,
|
||||
@ -724,7 +724,7 @@ export function NetscriptSingularity(
|
||||
}
|
||||
|
||||
const cost = player.getUpgradeHomeCoresCost();
|
||||
if (player.money.lt(cost)) {
|
||||
if (player.money < cost) {
|
||||
workerScript.log("upgradeHomeCores", `You don't have enough money. Need ${numeralWrapper.formatMoney(cost)}`);
|
||||
return false;
|
||||
}
|
||||
@ -757,7 +757,7 @@ export function NetscriptSingularity(
|
||||
}
|
||||
|
||||
const cost = player.getUpgradeHomeRamCost();
|
||||
if (player.money.lt(cost)) {
|
||||
if (player.money < cost) {
|
||||
workerScript.log("upgradeHomeRam", `You don't have enough money. Need ${numeralWrapper.formatMoney(cost)}`);
|
||||
return false;
|
||||
}
|
||||
@ -1107,7 +1107,7 @@ export function NetscriptSingularity(
|
||||
workerScript.log("donateToFaction", `Invalid donation amount: '${amt}'.`);
|
||||
return false;
|
||||
}
|
||||
if (player.money.lt(amt)) {
|
||||
if (player.money < amt) {
|
||||
workerScript.log(
|
||||
"donateToFaction",
|
||||
`You do not have enough money to donate ${numeralWrapper.formatMoney(amt)} to '${name}'`,
|
||||
|
@ -319,7 +319,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
return true;
|
||||
}
|
||||
|
||||
if (player.money.lt(getStockMarket4SDataCost())) {
|
||||
if (player.money < getStockMarket4SDataCost()) {
|
||||
workerScript.log("purchase4SMarketData", "Not enough money to purchase 4S Market Data.");
|
||||
return false;
|
||||
}
|
||||
@ -338,7 +338,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
return true;
|
||||
}
|
||||
|
||||
if (player.money.lt(getStockMarket4STixApiCost())) {
|
||||
if (player.money < getStockMarket4STixApiCost()) {
|
||||
workerScript.log("purchase4SMarketDataTixApi", "Not enough money to purchase 4S Market Data TIX API");
|
||||
return false;
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ export interface IPlayer {
|
||||
numPeopleKilled: number;
|
||||
location: LocationName;
|
||||
max_hp: number;
|
||||
readonly money: any;
|
||||
readonly money: number;
|
||||
moneySourceA: MoneySourceTracker;
|
||||
moneySourceB: MoneySourceTracker;
|
||||
playtimeSinceLastAug: number;
|
||||
|
@ -35,8 +35,6 @@ import { CityName } from "../../Locations/data/CityNames";
|
||||
import { MoneySourceTracker } from "../../utils/MoneySourceTracker";
|
||||
import { Reviver, Generic_toJSON, Generic_fromJSON } from "../../utils/JSONReviver";
|
||||
|
||||
import Decimal from "decimal.js";
|
||||
|
||||
export class PlayerObject implements IPlayer {
|
||||
// Class members
|
||||
augmentations: IPlayerOwnedAugmentation[];
|
||||
@ -63,7 +61,7 @@ export class PlayerObject implements IPlayer {
|
||||
numPeopleKilled: number;
|
||||
location: LocationName;
|
||||
max_hp: number;
|
||||
money: any;
|
||||
money: number;
|
||||
moneySourceA: MoneySourceTracker;
|
||||
moneySourceB: MoneySourceTracker;
|
||||
playtimeSinceLastAug: number;
|
||||
@ -336,7 +334,7 @@ export class PlayerObject implements IPlayer {
|
||||
this.faction_rep_mult = 1;
|
||||
|
||||
//Money
|
||||
this.money = new Decimal(1000);
|
||||
this.money = 1000;
|
||||
|
||||
//Location information
|
||||
this.city = CityName.Sector12;
|
||||
|
@ -36,7 +36,7 @@ import {
|
||||
import { GetServer, AddToAllServers, createUniqueRandomIp } from "../../Server/AllServers";
|
||||
import { Server } from "../../Server/Server";
|
||||
import { safetlyCreateUniqueServer } from "../../Server/ServerHelpers";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
|
||||
import { SpecialServers } from "../../Server/data/SpecialServers";
|
||||
import { applySourceFile } from "../../SourceFile/applySourceFile";
|
||||
import { applyExploit } from "../../Exploits/applyExploits";
|
||||
@ -47,8 +47,6 @@ import { getHospitalizationCost } from "../../Hospital/Hospital";
|
||||
import { WorkerScript } from "../../Netscript/WorkerScript";
|
||||
import { HacknetServer } from "../../Hacknet/HacknetServer";
|
||||
|
||||
import Decimal from "decimal.js";
|
||||
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { MoneySourceTracker } from "../../utils/MoneySourceTracker";
|
||||
@ -102,7 +100,7 @@ export function prestigeAugmentation(this: PlayerObject): void {
|
||||
this.agility_exp = 0;
|
||||
this.charisma_exp = 0;
|
||||
|
||||
this.money = new Decimal(1000);
|
||||
this.money = 1000;
|
||||
|
||||
this.city = CityName.Sector12;
|
||||
this.location = LocationName.TravelAgency;
|
||||
@ -325,7 +323,7 @@ export function setMoney(this: PlayerObject, money: number): void {
|
||||
console.error("NaN passed into Player.setMoney()");
|
||||
return;
|
||||
}
|
||||
this.money = new Decimal(money);
|
||||
this.money = money;
|
||||
}
|
||||
|
||||
export function gainMoney(this: PlayerObject, money: number, source: string): void {
|
||||
@ -333,7 +331,8 @@ export function gainMoney(this: PlayerObject, money: number, source: string): vo
|
||||
console.error("NaN passed into Player.gainMoney()");
|
||||
return;
|
||||
}
|
||||
this.money = this.money.plus(money);
|
||||
|
||||
this.money = this.money + money;
|
||||
this.recordMoneySource(money, source);
|
||||
}
|
||||
|
||||
@ -342,8 +341,8 @@ export function loseMoney(this: PlayerObject, money: number, source: string): vo
|
||||
console.error("NaN passed into Player.loseMoney()");
|
||||
return;
|
||||
}
|
||||
if (this.money.eq(Infinity) && money === Infinity) return;
|
||||
this.money = this.money.minus(money);
|
||||
if (this.money === Infinity && money === Infinity) return;
|
||||
this.money = this.money - money;
|
||||
this.recordMoneySource(-1 * money, source);
|
||||
}
|
||||
|
||||
@ -352,7 +351,7 @@ export function canAfford(this: IPlayer, cost: number): boolean {
|
||||
console.error(`NaN passed into Player.canAfford()`);
|
||||
return false;
|
||||
}
|
||||
return this.money.gte(cost);
|
||||
return this.money >= cost;
|
||||
}
|
||||
|
||||
export function recordMoneySource(this: PlayerObject, amt: number, source: string): void {
|
||||
@ -535,7 +534,6 @@ export function processWorkEarnings(this: IPlayer, numCycles = 1): void {
|
||||
const agiExpGain = focusBonus * this.workAgiExpGainRate * numCycles;
|
||||
const chaExpGain = focusBonus * this.workChaExpGainRate * numCycles;
|
||||
const moneyGain = (this.workMoneyGainRate - this.workMoneyLossRate) * numCycles;
|
||||
|
||||
this.gainHackingExp(hackExpGain);
|
||||
this.gainStrengthExp(strExpGain);
|
||||
this.gainDefenseExp(defExpGain);
|
||||
@ -2070,7 +2068,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
!illuminatiFac.isMember &&
|
||||
!illuminatiFac.alreadyInvited &&
|
||||
numAugmentations >= 30 &&
|
||||
this.money.gte(150000000000) &&
|
||||
this.money >= 150000000000 &&
|
||||
this.hacking >= 1500 &&
|
||||
this.strength >= 1200 &&
|
||||
this.defense >= 1200 &&
|
||||
@ -2087,7 +2085,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
!daedalusFac.isMember &&
|
||||
!daedalusFac.alreadyInvited &&
|
||||
numAugmentations >= Math.round(30 * BitNodeMultipliers.DaedalusAugsRequirement) &&
|
||||
this.money.gte(100000000000) &&
|
||||
this.money >= 100000000000 &&
|
||||
(this.hacking >= 2500 ||
|
||||
(this.strength >= 1500 && this.defense >= 1500 && this.dexterity >= 1500 && this.agility >= 1500))
|
||||
) {
|
||||
@ -2101,7 +2099,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
!covenantFac.isMember &&
|
||||
!covenantFac.alreadyInvited &&
|
||||
numAugmentations >= 20 &&
|
||||
this.money.gte(75000000000) &&
|
||||
this.money >= 75000000000 &&
|
||||
this.hacking >= 850 &&
|
||||
this.strength >= 850 &&
|
||||
this.defense >= 850 &&
|
||||
@ -2280,7 +2278,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
!chongqingFac.isBanned &&
|
||||
!chongqingFac.isMember &&
|
||||
!chongqingFac.alreadyInvited &&
|
||||
this.money.gte(20000000) &&
|
||||
this.money >= 20000000 &&
|
||||
this.city == CityName.Chongqing
|
||||
) {
|
||||
invitedFactions.push(chongqingFac);
|
||||
@ -2292,7 +2290,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
!sector12Fac.isBanned &&
|
||||
!sector12Fac.isMember &&
|
||||
!sector12Fac.alreadyInvited &&
|
||||
this.money.gte(15000000) &&
|
||||
this.money >= 15000000 &&
|
||||
this.city == CityName.Sector12
|
||||
) {
|
||||
invitedFactions.push(sector12Fac);
|
||||
@ -2304,7 +2302,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
!newtokyoFac.isBanned &&
|
||||
!newtokyoFac.isMember &&
|
||||
!newtokyoFac.alreadyInvited &&
|
||||
this.money.gte(20000000) &&
|
||||
this.money >= 20000000 &&
|
||||
this.city == CityName.NewTokyo
|
||||
) {
|
||||
invitedFactions.push(newtokyoFac);
|
||||
@ -2316,7 +2314,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
!aevumFac.isBanned &&
|
||||
!aevumFac.isMember &&
|
||||
!aevumFac.alreadyInvited &&
|
||||
this.money.gte(40000000) &&
|
||||
this.money >= 40000000 &&
|
||||
this.city == CityName.Aevum
|
||||
) {
|
||||
invitedFactions.push(aevumFac);
|
||||
@ -2328,7 +2326,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
!ishimaFac.isBanned &&
|
||||
!ishimaFac.isMember &&
|
||||
!ishimaFac.alreadyInvited &&
|
||||
this.money.gte(30000000) &&
|
||||
this.money >= 30000000 &&
|
||||
this.city == CityName.Ishima
|
||||
) {
|
||||
invitedFactions.push(ishimaFac);
|
||||
@ -2340,7 +2338,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
!volhavenFac.isBanned &&
|
||||
!volhavenFac.isMember &&
|
||||
!volhavenFac.alreadyInvited &&
|
||||
this.money.gte(50000000) &&
|
||||
this.money >= 50000000 &&
|
||||
this.city == CityName.Volhaven
|
||||
) {
|
||||
invitedFactions.push(volhavenFac);
|
||||
@ -2397,7 +2395,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
this.dexterity >= 200 &&
|
||||
this.agility >= 200 &&
|
||||
(this.city == CityName.Aevum || this.city == CityName.Sector12) &&
|
||||
this.money.gte(10000000) &&
|
||||
this.money >= 10000000 &&
|
||||
this.karma <= -90 &&
|
||||
!allCompanies.includes(LocationName.Sector12CIA) &&
|
||||
!allCompanies.includes(LocationName.Sector12NSA)
|
||||
@ -2414,7 +2412,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
(allPositions.includes("Chief Technology Officer") ||
|
||||
allPositions.includes("Chief Financial Officer") ||
|
||||
allPositions.includes("Chief Executive Officer")) &&
|
||||
this.money.gte(15000000) &&
|
||||
this.money >= 15000000 &&
|
||||
this.karma <= -22
|
||||
) {
|
||||
invitedFactions.push(silhouetteFac);
|
||||
@ -2447,7 +2445,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
this.dexterity >= 30 &&
|
||||
this.agility >= 30 &&
|
||||
this.karma <= -9 &&
|
||||
this.money.gte(1000000)
|
||||
this.money >= 1000000
|
||||
) {
|
||||
invitedFactions.push(slumsnakesFac);
|
||||
}
|
||||
@ -2490,7 +2488,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
!tiandihuiFac.isBanned &&
|
||||
!tiandihuiFac.isMember &&
|
||||
!tiandihuiFac.alreadyInvited &&
|
||||
this.money.gte(1000000) &&
|
||||
this.money >= 1000000 &&
|
||||
this.hacking >= 50 &&
|
||||
(this.city == CityName.Chongqing || this.city == CityName.NewTokyo || this.city == CityName.Ishima)
|
||||
) {
|
||||
|
@ -18,7 +18,7 @@ export function hasTorRouter(this: IPlayer): boolean {
|
||||
|
||||
export function getCurrentServer(this: IPlayer): BaseServer {
|
||||
const server = GetServer(this.currentServer);
|
||||
if (server === null) throw new Error("somehow connected to a server that does not exist.");
|
||||
if (server === null) throw new Error(`somehow connected to a server that does not exist. ${this.currentServer}`);
|
||||
return server;
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ export function SleeveAugmentationsModal(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<TableRow key={aug.name}>
|
||||
<TableCell>
|
||||
<Button onClick={() => purchaseAugmentation(aug)} disabled={player.money.lt(aug.startingCost)}>
|
||||
<Button onClick={() => purchaseAugmentation(aug)} disabled={player.money < aug.startingCost}>
|
||||
Buy
|
||||
</Button>
|
||||
</TableCell>
|
||||
|
@ -174,9 +174,9 @@ export function SleeveElem(props: IProps): React.ReactElement {
|
||||
<Grid item xs={3}>
|
||||
<StatsElement sleeve={props.sleeve} />
|
||||
<Button onClick={() => setStatsOpen(true)}>More Stats</Button>
|
||||
<Tooltip title={player.money.lt(CONSTANTS.TravelCost) ? <Typography>Insufficient funds</Typography> : ""}>
|
||||
<Tooltip title={player.money < CONSTANTS.TravelCost ? <Typography>Insufficient funds</Typography> : ""}>
|
||||
<span>
|
||||
<Button onClick={() => setTravelOpen(true)} disabled={player.money.lt(CONSTANTS.TravelCost)}>
|
||||
<Button onClick={() => setTravelOpen(true)} disabled={player.money < CONSTANTS.TravelCost}>
|
||||
Travel
|
||||
</Button>
|
||||
</span>
|
||||
|
@ -3,29 +3,11 @@ import { PlayerObject } from "./PersonObjects/Player/PlayerObject";
|
||||
import { sanitizeExploits } from "./Exploits/Exploit";
|
||||
|
||||
import { Reviver } from "./utils/JSONReviver";
|
||||
import Decimal from "decimal.js";
|
||||
|
||||
export let Player = new PlayerObject();
|
||||
|
||||
export function loadPlayer(saveString: string): void {
|
||||
Player = JSON.parse(saveString, Reviver);
|
||||
|
||||
// Parse Decimal.js objects
|
||||
Player.money = new Decimal(Player.money);
|
||||
|
||||
if (Player.corporation instanceof Corporation) {
|
||||
Player.corporation.funds = new Decimal(Player.corporation.funds);
|
||||
Player.corporation.revenue = new Decimal(Player.corporation.revenue);
|
||||
Player.corporation.expenses = new Decimal(Player.corporation.expenses);
|
||||
|
||||
for (let i = 0; i < Player.corporation.divisions.length; ++i) {
|
||||
const ind = Player.corporation.divisions[i];
|
||||
ind.lastCycleRevenue = new Decimal(ind.lastCycleRevenue);
|
||||
ind.lastCycleExpenses = new Decimal(ind.lastCycleExpenses);
|
||||
ind.thisCycleRevenue = new Decimal(ind.thisCycleRevenue);
|
||||
ind.thisCycleExpenses = new Decimal(ind.thisCycleExpenses);
|
||||
}
|
||||
}
|
||||
|
||||
Player.money = parseFloat(Player.money as any);
|
||||
Player.exploits = sanitizeExploits(Player.exploits);
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ import { Terminal } from "./Terminal";
|
||||
|
||||
import { dialogBoxCreate } from "./ui/React/DialogBox";
|
||||
|
||||
import Decimal from "decimal.js";
|
||||
import { ProgramsSeen } from "./Programs/ui/ProgramsRoot";
|
||||
import { InvitationsSeen } from "./Faction/ui/FactionsRoot";
|
||||
|
||||
@ -120,7 +119,7 @@ export function prestigeAugmentation(): void {
|
||||
|
||||
// BitNode 8: Ghost of Wall Street
|
||||
if (Player.bitNodeN === 8) {
|
||||
Player.money = new Decimal(BitNode8StartingMoney);
|
||||
Player.money = BitNode8StartingMoney;
|
||||
}
|
||||
if (Player.bitNodeN === 8 || SourceFileFlags[8] > 0) {
|
||||
Player.hasWseAccount = true;
|
||||
@ -235,7 +234,7 @@ export function prestigeSourceFile(flume: boolean): void {
|
||||
|
||||
// BitNode 8: Ghost of Wall Street
|
||||
if (Player.bitNodeN === 8) {
|
||||
Player.money = new Decimal(BitNode8StartingMoney);
|
||||
Player.money = BitNode8StartingMoney;
|
||||
}
|
||||
if (Player.bitNodeN === 8 || SourceFileFlags[8] > 0) {
|
||||
Player.hasWseAccount = true;
|
||||
|
@ -306,10 +306,10 @@ export const programsMetadata: IProgramCreationParams[] = [
|
||||
create: null,
|
||||
run: (router: IRouter, terminal: ITerminal, player: IPlayer): void => {
|
||||
const numAugReq = Math.round(BitNodeMultipliers.DaedalusAugsRequirement * 30);
|
||||
const fulfilled = player.augmentations.length >= numAugReq && player.money.gt(1e11) && player.hacking >= 2500;
|
||||
const fulfilled = player.augmentations.length >= numAugReq && player.money > 1e11 && player.hacking >= 2500;
|
||||
if (!fulfilled) {
|
||||
terminal.print(`Augmentations: ${player.augmentations.length} / ${numAugReq}`);
|
||||
terminal.print(`Money: ${numeralWrapper.formatMoney(player.money.toNumber())} / $100b`);
|
||||
terminal.print(`Money: ${numeralWrapper.formatMoney(player.money)} / $100b`);
|
||||
terminal.print(`Hacking skill: ${player.hacking} / 2500`);
|
||||
return;
|
||||
}
|
||||
|
@ -354,8 +354,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
.find((l: any) => l.id === "javascript")
|
||||
.loader();
|
||||
l.language.tokenizer.root.unshift(["ns", { token: "ns" }]);
|
||||
for (const symbol of symbols)
|
||||
l.language.tokenizer.root.unshift(["[^a-zA-Z0-9]" + symbol + "[^a-zA-Z0-9]", { token: "netscriptfunction" }]);
|
||||
for (const symbol of symbols) l.language.tokenizer.root.unshift([symbol, { token: "netscriptfunction" }]);
|
||||
const otherKeywords = ["let", "const", "var", "function"];
|
||||
const otherKeyvars = ["true", "false", "null", "undefined"];
|
||||
otherKeywords.forEach((k) => l.language.tokenizer.root.unshift([k, { token: "otherkeywords" }]));
|
||||
|
@ -94,6 +94,9 @@ export class BaseServer {
|
||||
// Text files on this server
|
||||
textFiles: TextFile[] = [];
|
||||
|
||||
// Flag indicating wehther this is a purchased server
|
||||
purchasedByPlayer = false;
|
||||
|
||||
constructor(params: IConstructorParams = { hostname: "", ip: createRandomIp() }) {
|
||||
this.ip = params.ip ? params.ip : createRandomIp();
|
||||
|
||||
|
@ -48,9 +48,6 @@ export class Server extends BaseServer {
|
||||
// How many ports are currently opened on the server
|
||||
openPortCount = 0;
|
||||
|
||||
// Flag indicating wehther this is a purchased server
|
||||
purchasedByPlayer = false;
|
||||
|
||||
// Hacking level required to hack this server
|
||||
requiredHackingSkill = 1;
|
||||
|
||||
|
@ -166,7 +166,7 @@ export const defaultSettings: IDefaultSettings = {
|
||||
DisableHotkeys: false,
|
||||
DisableTextEffects: false,
|
||||
EnableBashHotkeys: false,
|
||||
TimestampsFormat: "YYYY-MM-DD HH:MM:SS",
|
||||
TimestampsFormat: "",
|
||||
Locale: "en",
|
||||
MaxLogCapacity: 50,
|
||||
MaxPortCapacity: 50,
|
||||
|
@ -64,7 +64,7 @@ export function buyStock(
|
||||
if (totalPrice == null) {
|
||||
return false;
|
||||
}
|
||||
if (Player.money.lt(totalPrice)) {
|
||||
if (Player.money < totalPrice) {
|
||||
if (workerScript) {
|
||||
workerScript.log(
|
||||
"buyStock",
|
||||
@ -241,7 +241,7 @@ export function shortStock(
|
||||
if (totalPrice == null) {
|
||||
return false;
|
||||
}
|
||||
if (Player.money.lt(totalPrice)) {
|
||||
if (Player.money < totalPrice) {
|
||||
if (workerScript) {
|
||||
workerScript.log(
|
||||
"shortStock",
|
||||
|
@ -173,7 +173,7 @@ export function StockTicker(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
function handleBuyMaxButtonClick(): void {
|
||||
const playerMoney: number = props.p.money.toNumber();
|
||||
const playerMoney: number = props.p.money;
|
||||
|
||||
const stock = props.stock;
|
||||
let maxShares = calculateBuyMaxAmount(stock, position, playerMoney);
|
||||
|
@ -27,7 +27,11 @@ export function download(
|
||||
const file = new Blob([server.scripts[i].code], {
|
||||
type: "text/plain",
|
||||
});
|
||||
zip.file(server.scripts[i].filename + ".js", file);
|
||||
let name = server.scripts[i].filename;
|
||||
if (name.startsWith("/")) {
|
||||
name = name.slice(1);
|
||||
}
|
||||
zip.file(name + ".js", file);
|
||||
}
|
||||
}
|
||||
if (fn === "*" || fn === "*.txt") {
|
||||
|
1
src/ThirdParty/decimal.js.d.ts
vendored
1
src/ThirdParty/decimal.js.d.ts
vendored
@ -1 +0,0 @@
|
||||
declare module "decimal.js";
|
@ -251,9 +251,25 @@ const Engine: {
|
||||
const timeOffline = Engine._lastUpdate - lastUpdate;
|
||||
const numCyclesOffline = Math.floor(timeOffline / CONSTANTS._idleSpeed);
|
||||
|
||||
// Generate coding contracts
|
||||
// let numContracts = 0;
|
||||
// if (numCyclesOffline < 3000 * 100) {
|
||||
// // if we have less than 100 rolls, just roll them exactly.
|
||||
// for (let i = 0; i < numCyclesOffline / 3000; i++) {
|
||||
// if (Math.random() < 0.25) numContracts++;
|
||||
// }
|
||||
// } else {
|
||||
// // just average it.
|
||||
// numContracts = (numCyclesOffline / 3000) * 0.25;
|
||||
// }
|
||||
// console.log(`${numCyclesOffline} ${numContracts}`);
|
||||
// for (let i = 0; i < numContracts; i++) {
|
||||
// generateRandomContract();
|
||||
// }
|
||||
|
||||
let offlineReputation = 0;
|
||||
const offlineHackingIncome = (Player.moneySourceA.hacking / Player.playtimeSinceLastAug) * timeOffline * 0.75;
|
||||
Player.gainMoney(offlineHackingIncome, "hacknet");
|
||||
Player.gainMoney(offlineHackingIncome, "hacking");
|
||||
// Process offline progress
|
||||
loadAllRunningScripts(); // This also takes care of offline production for those scripts
|
||||
if (Player.isWorking) {
|
||||
|
@ -290,7 +290,7 @@ export function CharacterStats(): React.ReactElement {
|
||||
<Employers />
|
||||
|
||||
<Typography>
|
||||
Money: <Money money={player.money.toNumber()} />
|
||||
Money: <Money money={player.money} />
|
||||
<IconButton onClick={() => setMoneyOpen(true)}>
|
||||
<MoreHorizIcon color="info" />
|
||||
</IconButton>
|
||||
|
@ -176,9 +176,7 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
|
||||
<Typography classes={{ root: classes.money }}>Money </Typography>
|
||||
</TableCell>
|
||||
<TableCell align="right" classes={{ root: classes.cellNone }}>
|
||||
<Typography classes={{ root: classes.money }}>
|
||||
{numeralWrapper.formatMoney(player.money.toNumber())}
|
||||
</Typography>
|
||||
<Typography classes={{ root: classes.money }}>{numeralWrapper.formatMoney(player.money)}</Typography>
|
||||
</TableCell>
|
||||
<TableCell align="right" classes={{ root: classes.cellNone }}>
|
||||
<Typography id="overview-money-hook" classes={{ root: classes.money }}>
|
||||
|
@ -19,6 +19,7 @@ import List from "@mui/material/List";
|
||||
import ListItem from "@mui/material/ListItem";
|
||||
import Link from "@mui/material/Link";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import TextField from "@mui/material/TextField";
|
||||
|
||||
import DownloadIcon from "@mui/icons-material/Download";
|
||||
import UploadIcon from "@mui/icons-material/Upload";
|
||||
@ -30,6 +31,7 @@ import { ThemeEditorModal } from "./ThemeEditorModal";
|
||||
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
import { save, deleteGame } from "../../db";
|
||||
import { formatTime } from "../../utils/helpers/formatTime";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
@ -73,7 +75,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
||||
const [disableASCIIArt, setDisableASCIIArt] = useState(Settings.DisableASCIIArt);
|
||||
const [disableTextEffects, setDisableTextEffects] = useState(Settings.DisableTextEffects);
|
||||
const [enableBashHotkeys, setEnableBashHotkeys] = useState(Settings.EnableBashHotkeys);
|
||||
const [enableTimestamps, setEnableTimestamps] = useState(!!Settings.TimestampsFormat);
|
||||
const [timestampFormat, setTimestampFormat] = useState(Settings.TimestampsFormat);
|
||||
const [saveGameOnFileSave, setSaveGameOnFileSave] = useState(Settings.SaveGameOnFileSave);
|
||||
|
||||
const [locale, setLocale] = useState(Settings.Locale);
|
||||
@ -154,9 +156,9 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
||||
setEnableBashHotkeys(event.target.checked);
|
||||
Settings.EnableBashHotkeys = event.target.checked;
|
||||
}
|
||||
function handleEnableTimestampsChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
setEnableTimestamps(event.target.checked);
|
||||
Settings.TimestampsFormat = event.target.checked ? "YYYY-MM-DD HH:MM:SS" : "";
|
||||
function handleTimestampFormatChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
setTimestampFormat(event.target.value);
|
||||
Settings.TimestampsFormat = event.target.value;
|
||||
}
|
||||
function handleSaveGameOnFile(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
setSaveGameOnFileSave(event.target.checked);
|
||||
@ -466,21 +468,28 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<FormControlLabel
|
||||
control={<Switch checked={enableTimestamps} onChange={handleEnableTimestampsChange} />}
|
||||
label={
|
||||
<Tooltip
|
||||
title={
|
||||
<Typography>
|
||||
Terminal commands and log entries will be timestamped. The timestamp will have the format: M/D
|
||||
h:m
|
||||
</Typography>
|
||||
}
|
||||
>
|
||||
<Typography>Enable timestamps</Typography>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
title={
|
||||
<Typography>
|
||||
Terminal commands and log entries will be timestamped. See
|
||||
https://date-fns.org/docs/Getting-Started/
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
>
|
||||
<span>
|
||||
<TextField
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<Typography color={formatTime(timestampFormat) === "format error" ? "error" : "success"}>
|
||||
Timestamp format:
|
||||
</Typography>
|
||||
),
|
||||
}}
|
||||
value={timestampFormat}
|
||||
onChange={handleTimestampFormatChange}
|
||||
/>
|
||||
</span>
|
||||
</Tooltip>
|
||||
</ListItem>
|
||||
|
||||
<ListItem>
|
||||
|
@ -1,3 +1,10 @@
|
||||
export function formatTime(format: string): string {
|
||||
return "";
|
||||
import { format } from "date-fns";
|
||||
|
||||
export function formatTime(fmt: string): string {
|
||||
try {
|
||||
return format(new Date(), fmt);
|
||||
} catch (err: any) {
|
||||
console.error(err);
|
||||
return "format error";
|
||||
}
|
||||
}
|
||||
|
@ -856,7 +856,7 @@ describe("Stock Market Tests", function () {
|
||||
expect(buyStock(stock, shares, null, suppressDialogOpt)).equal(true);
|
||||
expect(stock.playerShares).equal(shares);
|
||||
expect(stock.playerAvgPx).greaterThan(0);
|
||||
expect(Player.money.toNumber()).equal(0);
|
||||
expect(Player.money).equal(0);
|
||||
});
|
||||
});
|
||||
|
||||
@ -888,7 +888,7 @@ describe("Stock Market Tests", function () {
|
||||
expect(sellStock(stock, shares, null, suppressDialogOpt)).equal(true);
|
||||
expect(stock.playerShares).equal(0);
|
||||
expect(stock.playerAvgPx).equal(0);
|
||||
expect(Player.money.toNumber()).equal(gain);
|
||||
expect(Player.money).equal(gain);
|
||||
});
|
||||
|
||||
it("should cap the number of sharse sold to however many the player owns", function () {
|
||||
@ -902,7 +902,7 @@ describe("Stock Market Tests", function () {
|
||||
expect(sellStock(stock, attemptedShares, null, suppressDialogOpt)).equal(true);
|
||||
expect(stock.playerShares).equal(0);
|
||||
expect(stock.playerAvgPx).equal(0);
|
||||
expect(Player.money.toNumber()).equal(gain);
|
||||
expect(Player.money).equal(gain);
|
||||
});
|
||||
|
||||
it("should properly update stock properties for partial transactions", function () {
|
||||
@ -916,7 +916,7 @@ describe("Stock Market Tests", function () {
|
||||
expect(sellStock(stock, shares, null, suppressDialogOpt)).equal(true);
|
||||
expect(stock.playerShares).equal(shares);
|
||||
expect(stock.playerAvgPx).equal(origPrice);
|
||||
expect(Player.money.toNumber()).equal(gain);
|
||||
expect(Player.money).equal(gain);
|
||||
});
|
||||
});
|
||||
|
||||
@ -950,7 +950,7 @@ describe("Stock Market Tests", function () {
|
||||
expect(shortStock(stock, shares, null, suppressDialogOpt)).equal(true);
|
||||
expect(stock.playerShortShares).equal(shares);
|
||||
expect(stock.playerAvgShortPx).greaterThan(0);
|
||||
expect(Player.money.toNumber()).equal(0);
|
||||
expect(Player.money).equal(0);
|
||||
});
|
||||
});
|
||||
|
||||
@ -982,7 +982,7 @@ describe("Stock Market Tests", function () {
|
||||
expect(sellShort(stock, shares, null, suppressDialogOpt)).equal(true);
|
||||
expect(stock.playerShortShares).equal(0);
|
||||
expect(stock.playerAvgShortPx).equal(0);
|
||||
expect(Player.money.toNumber()).equal(gain);
|
||||
expect(Player.money).equal(gain);
|
||||
});
|
||||
|
||||
it("should cap the number of sharse sold to however many the player owns", function () {
|
||||
@ -996,7 +996,7 @@ describe("Stock Market Tests", function () {
|
||||
expect(sellShort(stock, attemptedShares, null, suppressDialogOpt)).equal(true);
|
||||
expect(stock.playerShortShares).equal(0);
|
||||
expect(stock.playerAvgShortPx).equal(0);
|
||||
expect(Player.money.toNumber()).equal(gain);
|
||||
expect(Player.money).equal(gain);
|
||||
});
|
||||
|
||||
it("should properly update stock properties for partial transactions", function () {
|
||||
@ -1010,7 +1010,7 @@ describe("Stock Market Tests", function () {
|
||||
expect(sellShort(stock, shares, null, suppressDialogOpt)).equal(true);
|
||||
expect(stock.playerShortShares).equal(shares);
|
||||
expect(stock.playerAvgShortPx).equal(origPrice);
|
||||
expect(Player.money.toNumber()).equal(gain);
|
||||
expect(Player.money).equal(gain);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user