track money more precisely.

This commit is contained in:
Olivier Gagnon 2021-10-27 14:18:33 -04:00
parent 9f6767062b
commit 48988e228e
38 changed files with 90 additions and 100 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1235,8 +1235,7 @@ export class Bladeburner implements IBladeburner {
let moneyGain = 0;
if (!isOperation) {
moneyGain = BladeburnerConstants.ContractBaseMoneyGain * rewardMultiplier * this.skillMultipliers.money;
player.gainMoney(moneyGain);
player.recordMoneySource(moneyGain, "bladeburner");
player.gainMoney(moneyGain, "bladeburner");
}
if (isOperation) {

@ -76,7 +76,7 @@ export class Blackjack extends Game<Props, State> {
// Take money from player right away so that player's dont just "leave" to avoid the loss (I mean they could
// always reload without saving but w.e)
this.props.p.loseMoney(this.state.bet);
this.props.p.loseMoney(this.state.bet, "casino");
const playerHand = new Hand([this.deck.safeDrawCard(), this.deck.safeDrawCard()]);
const dealerHand = new Hand([this.deck.safeDrawCard(), this.deck.safeDrawCard()]);

@ -5,8 +5,7 @@ import { dialogBoxCreate } from "../ui/React/DialogBox";
const gainLimit = 10e9;
export function win(p: IPlayer, n: number): void {
p.gainMoney(n);
p.recordMoneySource(n, "casino");
p.gainMoney(n, "casino");
}
export function reachedLimit(p: IPlayer): boolean {
@ -19,8 +18,7 @@ export function reachedLimit(p: IPlayer): boolean {
export class Game<T, U> extends React.Component<T, U> {
win(p: IPlayer, n: number): void {
p.gainMoney(n);
p.recordMoneySource(n, "casino");
p.gainMoney(n, "casino");
}
reachedLimit(p: IPlayer): boolean {

@ -134,8 +134,7 @@ export class Corporation {
const retainedEarnings = cycleProfit - totalDividends;
const dividendsPerShare = totalDividends / this.totalShares;
const profit = this.numShares * dividendsPerShare * (1 - this.dividendTaxPercentage / 100);
player.gainMoney(profit);
player.recordMoneySource(profit, "corporation");
player.gainMoney(profit, "corporation");
this.addFunds(retainedEarnings);
}
} else {

@ -48,7 +48,7 @@ export function BuybackSharesModal(props: IProps): React.ReactElement {
}
}
corp.issuedShares -= shares;
player.loseMoney(shares * buybackPrice);
player.loseMoney(shares * buybackPrice, "corporation");
props.onClose();
props.rerender();
}

@ -36,7 +36,7 @@ export function CreateCorporationModal(props: IProps): React.ReactElement {
}
player.startCorporation(name);
player.loseMoney(150e9);
player.loseMoney(150e9, "corporation");
props.onClose();
router.toCorporation();

@ -69,8 +69,7 @@ export function SellSharesModal(props: IProps): React.ReactElement {
corp.sharePrice = newSharePrice;
corp.shareSalesUntilPriceUpdate = newSharesUntilUpdate;
corp.shareSaleCooldown = CorporationConstants.SellSharesCooldown;
player.gainMoney(profit);
player.recordMoneySource(profit, "corporation");
player.gainMoney(profit, "corporation");
props.onClose();
dialogBoxCreate(
<>

@ -60,7 +60,7 @@ export function buyDarkwebItem(itemName: string): void {
}
// buy and push
Player.loseMoney(item.price);
Player.loseMoney(item.price, "other");
Player.getHomeComputer().programs.push(item.program);
Terminal.print(
"You have purchased the " + item.program + " program. The new program can be found on your home computer.",

@ -19,7 +19,7 @@ interface IProps {
export function General(props: IProps): React.ReactElement {
function addMoney(n: number) {
return function () {
props.player.gainMoney(n);
props.player.gainMoney(n, "other");
};
}

@ -106,7 +106,7 @@ export function purchaseAugmentation(aug: Augmentation, fac: Faction, sing = fal
}
Player.queuedAugmentations.push(queuedAugmentation);
Player.loseMoney(aug.baseCost * factionInfo.augmentationPriceMult);
Player.loseMoney(aug.baseCost * factionInfo.augmentationPriceMult, "augmentations");
// If you just purchased Neuroflux Governor, recalculate the cost
if (aug.name == AugmentationNames.NeuroFluxGovernor) {

@ -52,7 +52,7 @@ export function DonateOption(props: IProps): React.ReactElement {
const amt = donateAmt;
if (amt === null) return;
if (!canDonate()) return;
props.p.loseMoney(amt);
props.p.loseMoney(amt, "other");
const repGain = repFromDonation(amt, props.p);
props.faction.playerReputation += repGain;
dialogBoxCreate(

@ -147,8 +147,7 @@ export class Gang {
this.wanted = newWanted;
if (this.wanted < 1) this.wanted = 1;
}
player.gainMoney(moneyGains * numCycles);
player.recordMoneySource(moneyGains * numCycles, "gang");
player.gainMoney(moneyGains * numCycles, "gang");
}
processTerritoryAndPowerGains(numCycles = 1): void {

@ -317,7 +317,7 @@ export class GangMember {
if (this.augmentations.includes(upg.name) || this.upgrades.includes(upg.name)) return false;
if (player.money.lt(gang.getUpgradeCost(upg))) return false;
player.loseMoney(gang.getUpgradeCost(upg));
player.loseMoney(gang.getUpgradeCost(upg), "gang");
if (upg.type === "g") {
this.augmentations.push(upg.name);
} else {

@ -50,7 +50,7 @@ export function purchaseHacknet(player: IPlayer): number {
if (!player.canAfford(cost)) {
return -1;
}
player.loseMoney(cost);
player.loseMoney(cost, "hacknet");
player.createHacknetServer();
updateHashManagerCapacity(player);
@ -69,7 +69,7 @@ export function purchaseHacknet(player: IPlayer): number {
const name = "hacknet-node-" + numOwned;
const node = new HacknetNode(name, player.hacknet_node_money_mult);
player.loseMoney(cost);
player.loseMoney(cost, "hacknet");
player.hacknetNodes.push(node);
return numOwned;
@ -266,7 +266,7 @@ export function purchaseLevelUpgrade(player: IPlayer, node: HacknetNode | Hackne
return false;
}
player.loseMoney(cost);
player.loseMoney(cost, "hacknet");
node.upgradeLevel(sanitizedLevels, player.hacknet_node_money_mult);
return true;
@ -305,7 +305,7 @@ export function purchaseRamUpgrade(player: IPlayer, node: HacknetNode | HacknetS
return false;
}
player.loseMoney(cost);
player.loseMoney(cost, "hacknet");
node.upgradeRam(sanitizedLevels, player.hacknet_node_money_mult);
return true;
@ -336,7 +336,7 @@ export function purchaseCoreUpgrade(player: IPlayer, node: HacknetNode | Hacknet
return false;
}
player.loseMoney(cost);
player.loseMoney(cost, "hacknet");
node.upgradeCore(sanitizedLevels, player.hacknet_node_money_mult);
return true;
@ -364,7 +364,7 @@ export function purchaseCacheUpgrade(player: IPlayer, node: HacknetServer, level
return false;
}
player.loseMoney(cost);
player.loseMoney(cost, "hacknet");
node.upgradeCache(sanitizedLevels);
return true;
@ -398,8 +398,7 @@ function processAllHacknetNodeEarnings(player: IPlayer, numCycles: number): numb
function processSingleHacknetNodeEarnings(player: IPlayer, numCycles: number, nodeObj: HacknetNode): number {
const totalEarnings = nodeObj.process(numCycles);
player.gainMoney(totalEarnings);
player.recordMoneySource(totalEarnings, "hacknetnode");
player.gainMoney(totalEarnings, "hacknet");
return totalEarnings;
}
@ -472,8 +471,7 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
switch (upgName) {
case "Sell for Money": {
player.gainMoney(upg.value);
player.recordMoneySource(upg.value, "hacknetnode");
player.gainMoney(upg.value, "hacknet");
break;
}
case "Sell for Corporation Funds": {

@ -42,8 +42,7 @@ export function Victory(props: IProps): React.ReactElement {
BitNodeMultipliers.InfiltrationMoney;
function sell(): void {
player.gainMoney(moneyGain);
player.recordMoneySource(moneyGain, "infiltration");
player.gainMoney(moneyGain, "infiltration");
quitInfiltration();
}

@ -23,7 +23,7 @@ export function purchaseTorRouter(p: IPlayer): void {
dialogBoxCreate("You cannot afford to purchase the TOR router!");
return;
}
p.loseMoney(CONSTANTS.TorRouterCost);
p.loseMoney(CONSTANTS.TorRouterCost, "other");
const darkweb = safetlyCreateUniqueServer({
ip: createUniqueRandomIp(),

@ -24,7 +24,7 @@ export function CoresButton(props: IProps): React.ReactElement {
function buy(): void {
if (maxCores) return;
if (!props.p.canAfford(cost)) return;
props.p.loseMoney(cost);
props.p.loseMoney(cost, "servers");
homeComputer.cpuCores++;
props.rerender();
}

@ -57,9 +57,8 @@ export class HospitalLocation extends React.Component<IProps, IState> {
}
const cost = this.getCost();
this.props.p.loseMoney(cost);
this.props.p.loseMoney(cost, "hospitalization");
this.props.p.hp = this.props.p.max_hp;
this.props.p.recordMoneySource(-1 * cost, "hospitalization");
// This just forces a re-render to update the cost
this.setState({

@ -33,7 +33,7 @@ function travel(p: IPlayer, router: IRouter, to: CityName): void {
return;
}
p.loseMoney(cost);
p.loseMoney(cost, "other");
p.travel(to);
dialogBoxCreate(<>You are now in {to}!</>);
router.toCity();

@ -395,10 +395,9 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
const moneyGained = moneyDrained * BitNodeMultipliers.ScriptHackMoneyGain;
Player.gainMoney(moneyGained);
Player.gainMoney(moneyGained, "hacking");
workerScript.scriptRef.onlineMoneyMade += moneyGained;
Player.scriptProdSinceLastAug += moneyGained;
Player.recordMoneySource(moneyGained, "hacking");
workerScript.scriptRef.recordHack(server.hostname, moneyGained, threads);
Player.gainHackingExp(expGainedOnSuccess);
workerScript.scriptRef.onlineExpGained += expGainedOnSuccess;
@ -1550,7 +1549,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
const homeComputer = Player.getHomeComputer();
homeComputer.serversOnNetwork.push(newServ.hostname);
newServ.serversOnNetwork.push(homeComputer.hostname);
Player.loseMoney(cost);
Player.loseMoney(cost, "servers");
workerScript.log(
"purchaseServer",
`Purchased new server with hostname '${newServ.hostname}' for ${numeralWrapper.formatMoney(cost)}`,
@ -2297,7 +2296,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
if (Player.money.lt(CONSTANTS.TravelCost)) {
throw makeRuntimeErrorMsg("travelToCity", "Not enough money to travel.");
}
Player.loseMoney(CONSTANTS.TravelCost);
Player.loseMoney(CONSTANTS.TravelCost, "other");
Player.city = cityname;
workerScript.log("travelToCity", `Traveled to ${cityname}`);
return true;
@ -2320,7 +2319,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
workerScript.log("purchaseTor", "You cannot afford to purchase a Tor router.");
return false;
}
Player.loseMoney(CONSTANTS.TorRouterCost);
Player.loseMoney(CONSTANTS.TorRouterCost, "other");
const darkweb = safetlyCreateUniqueServer({
ip: createUniqueRandomIp(),
@ -2376,7 +2375,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
return true;
}
Player.loseMoney(item.price);
Player.loseMoney(item.price, "other");
Player.getHomeComputer().programs.push(item.program);
workerScript.log(
"purchaseProgram",
@ -2667,7 +2666,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
}
homeComputer.cpuCores += 1;
Player.loseMoney(cost);
Player.loseMoney(cost, "servers");
Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain);
workerScript.log(
@ -2700,7 +2699,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
}
homeComputer.maxRam *= 2;
Player.loseMoney(cost);
Player.loseMoney(cost, "servers");
Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain);
workerScript.log(
@ -3061,7 +3060,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
}
const repGain = (amt / CONSTANTS.DonateMoneyToRepDivisor) * Player.faction_rep_mult;
faction.playerReputation += repGain;
Player.loseMoney(amt);
Player.loseMoney(amt, "other");
workerScript.log(
"donateToFaction",
`${numeralWrapper.formatMoney(amt)} donated to '${name}' for ${numeralWrapper.formatReputation(

@ -350,7 +350,7 @@ export function NetscriptStockMarket(
}
player.has4SData = true;
player.loseMoney(getStockMarket4SDataCost());
player.loseMoney(getStockMarket4SDataCost(), "stock");
workerScript.log("purchase4SMarketData", "Purchased 4S Market Data");
return true;
},
@ -369,7 +369,7 @@ export function NetscriptStockMarket(
}
player.has4SDataTixApi = true;
player.loseMoney(getStockMarket4STixApiCost());
player.loseMoney(getStockMarket4STixApiCost(), "stock");
workerScript.log("purchase4SMarketDataTixApi", "Purchased 4S Market Data TIX API");
return true;
},

@ -184,7 +184,7 @@ export interface IPlayer {
gainAgilityExp(exp: number): void;
gainCharismaExp(exp: number): void;
gainIntelligenceExp(exp: number): void;
gainMoney(money: number): void;
gainMoney(money: number, source: string): void;
getCurrentServer(): BaseServer;
getGangFaction(): Faction;
getGangName(): string;
@ -201,12 +201,11 @@ export interface IPlayer {
inBladeburner(): boolean;
inGang(): boolean;
isQualified(company: Company, position: CompanyPosition): boolean;
loseMoney(money: number): void;
loseMoney(money: number, source: string): void;
process(router: IRouter, numCycles?: number): void;
reapplyAllAugmentations(resetMultipliers?: boolean): void;
reapplyAllSourceFiles(): void;
regenerateHp(amt: number): void;
recordMoneySource(amt: number, source: string): void;
setMoney(amt: number): void;
singularityStopWork(): string;
startBladeburner(p: any): void;

@ -191,7 +191,7 @@ export class PlayerObject implements IPlayer {
gainAgilityExp: (exp: number) => void;
gainCharismaExp: (exp: number) => void;
gainIntelligenceExp: (exp: number) => void;
gainMoney: (money: number) => void;
gainMoney: (money: number, source: string) => void;
getCurrentServer: () => BaseServer;
getGangFaction: () => Faction;
getGangName: () => string;
@ -208,7 +208,7 @@ export class PlayerObject implements IPlayer {
inBladeburner: () => boolean;
inGang: () => boolean;
isQualified: (company: Company, position: CompanyPosition) => boolean;
loseMoney: (money: number) => void;
loseMoney: (money: number, source: string) => void;
reapplyAllAugmentations: (resetMultipliers?: boolean) => void;
reapplyAllSourceFiles: () => void;
regenerateHp: (amt: number) => void;

@ -328,21 +328,23 @@ export function setMoney(this: PlayerObject, money: number): void {
this.money = new Decimal(money);
}
export function gainMoney(this: PlayerObject, money: number): void {
export function gainMoney(this: PlayerObject, money: number, source: string): void {
if (isNaN(money)) {
console.error("NaN passed into Player.gainMoney()");
return;
}
this.money = this.money.plus(money);
this.recordMoneySource(money, source);
}
export function loseMoney(this: PlayerObject, money: number): void {
export function loseMoney(this: PlayerObject, money: number, source: string): void {
if (isNaN(money)) {
console.error("NaN passed into Player.loseMoney()");
return;
}
if (this.money.eq(Infinity) && money === Infinity) return;
this.money = this.money.minus(money);
this.recordMoneySource(-1 * money, source);
}
export function canAfford(this: IPlayer, cost: number): boolean {
@ -353,7 +355,7 @@ export function canAfford(this: IPlayer, cost: number): boolean {
return this.money.gte(cost);
}
export function recordMoneySource(this: IPlayer, amt: number, source: string): void {
export function recordMoneySource(this: PlayerObject, amt: number, source: string): void {
if (!(this.moneySourceA instanceof MoneySourceTracker)) {
console.warn(`Player.moneySourceA was not properly initialized. Resetting`);
this.moneySourceA = new MoneySourceTracker();
@ -540,12 +542,7 @@ export function processWorkEarnings(this: IPlayer, numCycles = 1): void {
this.gainDexterityExp(dexExpGain);
this.gainAgilityExp(agiExpGain);
this.gainCharismaExp(chaExpGain);
this.gainMoney(moneyGain);
if (this.className) {
this.recordMoneySource(moneyGain, "class");
} else {
this.recordMoneySource(moneyGain, "work");
}
this.gainMoney(moneyGain, this.className ? "class" : "work");
this.workHackExpGained += hackExpGain;
this.workStrExpGained += strExpGain;
this.workDefExpGained += defExpGain;
@ -1513,8 +1510,7 @@ export function finishCrime(this: IPlayer, cancelled: boolean): string {
);
return "";
}
this.gainMoney(this.workMoneyGained);
this.recordMoneySource(this.workMoneyGained, "crime");
this.gainMoney(this.workMoneyGained, "crime");
this.karma -= crime.karma;
this.numPeopleKilled += crime.kills;
if (crime.intelligence_exp > 0) {
@ -1703,8 +1699,7 @@ export function hospitalize(this: IPlayer): number {
SnackbarEvents.emit(`You've been Hospitalized for ${numeralWrapper.formatMoney(cost)}`, "warning");
}
this.loseMoney(cost);
this.recordMoneySource(-1 * cost, "hospitalization");
this.loseMoney(cost, "hospitalization");
this.hp = this.max_hp;
return cost;
}
@ -2601,8 +2596,7 @@ export function gainCodingContractReward(this: IPlayer, reward: ICodingContractR
case CodingContractRewardType.Money:
default: {
const moneyGain = CONSTANTS.CodingContractBaseMoneyGain * difficulty * BitNodeMultipliers.CodingContractMoney;
this.gainMoney(moneyGain);
this.recordMoneySource(moneyGain, "codingcontract");
this.gainMoney(moneyGain, "codingcontract");
return `Gained ${numeralWrapper.formatMoney(moneyGain)}`;
}
}

@ -26,7 +26,7 @@ export function purchaseResleeve(r: Resleeve, p: IPlayer): boolean {
if (!p.canAfford(cost)) {
return false;
}
p.loseMoney(cost);
p.loseMoney(cost, "other");
// Set the player's exp
p.hacking_exp = r.hacking_exp;

@ -331,8 +331,7 @@ export class Sleeve extends Person {
const gain: number = task.money * numCycles;
this.earningsForTask.money += gain;
this.earningsForPlayer.money += gain;
p.gainMoney(gain);
p.recordMoneySource(gain, "sleeves");
p.gainMoney(gain, "sleeves");
}
/**
@ -668,7 +667,7 @@ export class Sleeve extends Person {
* Travel to another City. Costs money from player
*/
travel(p: IPlayer, newCity: CityName): boolean {
p.loseMoney(CONSTANTS.TravelCost);
p.loseMoney(CONSTANTS.TravelCost, "sleeves");
this.city = newCity;
return true;
@ -684,7 +683,7 @@ export class Sleeve extends Person {
return false;
}
p.loseMoney(aug.startingCost);
p.loseMoney(aug.startingCost, "sleeves");
this.installAugmentation(aug);
return true;
}

@ -53,7 +53,7 @@ export function CovenantPurchasesRoot(props: IProps): React.ReactElement {
if (player.sleevesFromCovenant >= MaxSleevesFromCovenant) return;
if (player.canAfford(purchaseCost())) {
player.loseMoney(purchaseCost());
player.loseMoney(purchaseCost(), "sleeves");
player.sleevesFromCovenant += 1;
player.sleeves.push(new Sleeve(player));
rerender();

@ -53,7 +53,7 @@ export function CovenantSleeveMemoryUpgrade(props: IProps): React.ReactElement {
const cost = getPurchaseCost();
if (props.p.canAfford(cost)) {
props.sleeve.upgradeMemory(amt);
props.p.loseMoney(cost);
props.p.loseMoney(cost, "sleeves");
props.rerender();
}
}

@ -25,7 +25,7 @@ export function TravelModal(props: IProps): React.ReactElement {
dialogBoxCreate("You cannot afford to have this sleeve travel to another city");
}
props.sleeve.city = city as CityName;
player.loseMoney(CONSTANTS.TravelCost);
player.loseMoney(CONSTANTS.TravelCost, "sleeve");
props.sleeve.resetTaskStatus();
props.rerender();
props.onClose();

@ -94,7 +94,7 @@ export function purchaseServer(hostname: string, ram: number, cost: number, p: I
homeComputer.serversOnNetwork.push(newServ.hostname);
newServ.serversOnNetwork.push(homeComputer.hostname);
p.loseMoney(cost);
p.loseMoney(cost, "servers");
dialogBoxCreate("Server successfully purchased with hostname " + hostname);
}
@ -114,5 +114,5 @@ export function purchaseRamForHomeComputer(p: IPlayer): void {
}
homeComputer.maxRam *= 2;
p.loseMoney(cost);
p.loseMoney(cost, "servers");
}

@ -102,7 +102,7 @@ export function buyStock(
}
const origTotal = stock.playerShares * stock.playerAvgPx;
Player.loseMoney(totalPrice);
Player.loseMoney(totalPrice, "stock");
const newTotal = origTotal + totalPrice - CONSTANTS.StockMarketCommission;
stock.playerShares = Math.round(stock.playerShares + shares);
stock.playerAvgPx = newTotal / stock.playerShares;
@ -171,8 +171,7 @@ export function sellStock(
if (isNaN(netProfit)) {
netProfit = 0;
}
Player.gainMoney(gains);
Player.recordMoneySource(netProfit, "stock");
Player.gainMoney(gains, "stock");
if (workerScript) {
workerScript.scriptRef.onlineMoneyMade += netProfit;
Player.scriptProdSinceLastAug += netProfit;
@ -280,7 +279,7 @@ export function shortStock(
}
const origTotal = stock.playerShortShares * stock.playerAvgShortPx;
Player.loseMoney(totalPrice);
Player.loseMoney(totalPrice, "stock");
const newTotal = origTotal + totalPrice - CONSTANTS.StockMarketCommission;
stock.playerShortShares = Math.round(stock.playerShortShares + shares);
stock.playerAvgShortPx = newTotal / stock.playerShortShares;
@ -364,8 +363,7 @@ export function sellShort(
if (isNaN(profit)) {
profit = 0;
}
Player.gainMoney(totalGain);
Player.recordMoneySource(profit, "stock");
Player.gainMoney(totalGain, "stock");
if (workerScript) {
workerScript.scriptRef.onlineMoneyMade += profit;
Player.scriptProdSinceLastAug += profit;

@ -35,7 +35,7 @@ function Purchase4SMarketDataTixApiAccessButton(props: IProps): React.ReactEleme
return;
}
props.p.has4SDataTixApi = true;
props.p.loseMoney(getStockMarket4STixApiCost());
props.p.loseMoney(getStockMarket4STixApiCost(), "stock");
props.rerender();
}
@ -88,7 +88,7 @@ function PurchaseWseAccountButton(props: IProps): React.ReactElement {
}
props.p.hasWseAccount = true;
props.initStockMarket();
props.p.loseMoney(CONSTANTS.WSEAccountCost);
props.p.loseMoney(CONSTANTS.WSEAccountCost, "stock");
props.rerender();
}
@ -113,7 +113,7 @@ function PurchaseTixApiAccessButton(props: IProps): React.ReactElement {
return;
}
props.p.hasTixApiAccess = true;
props.p.loseMoney(CONSTANTS.TIXAPICost);
props.p.loseMoney(CONSTANTS.TIXAPICost, "stock");
props.rerender();
}
@ -143,7 +143,7 @@ function Purchase4SMarketDataButton(props: IProps): React.ReactElement {
return;
}
props.p.has4SData = true;
props.p.loseMoney(getStockMarket4SDataCost());
props.p.loseMoney(getStockMarket4SDataCost(), "stock");
props.rerender();
}
if (props.p.has4SData) {

@ -196,8 +196,7 @@ export class Terminal implements ITerminal {
} // Safety check
server.moneyAvailable -= moneyGained;
player.gainMoney(moneyGained);
player.recordMoneySource(moneyGained, "hacking");
player.gainMoney(moneyGained, "hacking");
player.gainHackingExp(expGainedOnSuccess);
player.gainIntelligenceExp(expGainedOnSuccess / CONSTANTS.IntelligenceTerminalHackBaseExpGain);

@ -253,7 +253,7 @@ const Engine: {
let offlineReputation = 0;
const offlineHackingIncome = (Player.moneySourceA.hacking / Player.playtimeSinceLastAug) * timeOffline * 0.75;
Player.gainMoney(offlineHackingIncome);
Player.gainMoney(offlineHackingIncome, "hacknet");
// Process offline progress
loadAllRunningScripts(); // This also takes care of offline production for those scripts
if (Player.isWorking) {

@ -167,9 +167,15 @@ function MoneyModal({ open, onClose }: IMoneyModalProps): React.ReactElement {
const player = use.Player();
function convertMoneySourceTrackerToString(src: MoneySourceTracker): React.ReactElement {
const parts: any[][] = [[`Total:`, <Money money={src.total} />]];
if (src.augmentations) {
parts.push([`Augmentations:`, <Money money={src.augmentations} />]);
}
if (src.bladeburner) {
parts.push([`Bladeburner:`, <Money money={src.bladeburner} />]);
}
if (src.casino) {
parts.push([`Casino:`, <Money money={src.casino} />]);
}
if (src.codingcontract) {
parts.push([`Coding Contracts:`, <Money money={src.codingcontract} />]);
}
@ -191,8 +197,8 @@ function MoneyModal({ open, onClose }: IMoneyModalProps): React.ReactElement {
if (src.hacking) {
parts.push([`Hacking:`, <Money money={src.hacking} />]);
}
if (src.hacknetnode) {
parts.push([`Hacknet Nodes:`, <Money money={src.hacknetnode} />]);
if (src.hacknet) {
parts.push([`Hacknet Nodes:`, <Money money={src.hacknet} />]);
}
if (src.hospitalization) {
parts.push([`Hospitalization:`, <Money money={src.hospitalization} />]);
@ -200,15 +206,18 @@ function MoneyModal({ open, onClose }: IMoneyModalProps): React.ReactElement {
if (src.infiltration) {
parts.push([`Infiltration:`, <Money money={src.infiltration} />]);
}
if (src.servers) {
parts.push([`Servers:`, <Money money={src.servers} />]);
}
if (src.stock) {
parts.push([`Stock Market:`, <Money money={src.stock} />]);
}
if (src.casino) {
parts.push([`Casino:`, <Money money={src.casino} />]);
}
if (src.sleeves) {
parts.push([`Sleeves:`, <Money money={src.sleeves} />]);
}
if (src.other) {
parts.push([`Other:`, <Money money={src.other} />]);
}
return <StatsTable rows={parts} wide />;
}

@ -16,13 +16,16 @@ export class MoneySourceTracker {
crime = 0;
gang = 0;
hacking = 0;
hacknetnode = 0;
hacknet = 0;
hospitalization = 0;
infiltration = 0;
sleeves = 0;
stock = 0;
total = 0;
work = 0;
servers = 0;
other = 0;
augmentations = 0;
// Record money earned
record(amt: number, source: string): void {